mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-11-01 23:07:30 +00:00
## ① 全面改名 HomeAgent → HologramAgent
仓库已改名,但代码与文档里仍有大量旧名。本次按"用户能看到的优先"全量替换:
- 用户可见:登录页标题/页脚、默认人格第一句、CLI 状态输出、启动日志、
plugin_install 的工具描述、AI 图片插件的 User-Agent
- 文档与脚本:README、assets/docs、docs/zh、deploy/*.sh、.github/workflows
- 鸿蒙工程:cmd/ohos/HomeAgent → cmd/ohos/HologramAgent(git mv)
目录内的 module/app 描述同步;**证书路径原样保留**
(default_HomeAgent_xxx.cer/p7b/p12 是签名材料的实际文件名,改了会找不到证书)
- 插件元数据:plugin.json 的 author
★ 必须保持原样的两处(改了会坏):
· legacySeededPromptSignature = "你是 HomeAgent 的看板娘「小宅」…"
—— 那是识别历史播种人格卡的**原文锚点**,改了就识别不出旧数据
· 公开 SDK 的 ProxyAuthHomeAgent = "homeagent"
—— 那是 SDK 契约里的值,属独立仓库,本仓不改
## ② 修 21 处乱码(U+FFFD)
这些是历史编辑留下的编码破坏,全在注释里,例如:
「赌注重下���遍」→「赌注重下一遍」
「「不��滤」」 →「「不过滤」」
「**待��退场**」→「**待退场**」
★ 保留 providers/chineseclip/tokenizer.go 里的 2 处:那是**故意**用
U+FFFD 演示"非法 UTF-8 字节被归一成 U+FFFD",不是乱码。
## ③ 提示词技术内容下沉(用户:技术性内容应该收敛到 skill 与 -help 中)
实测系统提示词 2309 字,其中两段几乎全是**模型无法据以行动的实现细节**:
【工具执行顺序】1272 字(ParallelSafe 声明、批内降级、batchRunnable 判据…)
【三层记忆】 1069 字(L1/L2/L3 编号、消费式删除、向量空间、指纹…)
收敛后 **2309 → 1723 字(-25%)**,保留的全是"模型据此做什么不同的事":
工具顺序:默认并行 / 不要依赖先后 / 同通道保序 / 写类工具可能串行
三层记忆:时序里能看最近 / doc_query 把历史事件按原始时间戳插回时序 /
关系用 memory_recall / 成文知识用 knowledge_search
判断口径写进判据:新加一段提示词前先问"模型会据此做什么不同的事",
答不上来就该进 skill 或工具描述。
## 判据
prompt_memory_test.go 新增 2 条:
- TestSystemPromptHasNoImplementationJargon
黑名单:ParallelSafe / batchRunnable / 消费式 / DenseCosine / fingerprint /
向量空间 / 批内降级 / 自激
- TestSystemPromptStaysCompact:上限 2000 字(当前 1723)
变异:把 "ParallelSafe 声明、批内降级" 加回工具顺序段 ⇒ 第一条立刻红。
## 验证
- go build ./... / go vet ./... 干净
- go test ./... -count=1:58 包 0 失败
- make check-client-versions:客户端与内核版本一致
217 lines
6.7 KiB
JavaScript
217 lines
6.7 KiB
JavaScript
#!/usr/bin/env node
|
|
const path = require('path');
|
|
const fs = require('fs');
|
|
const { fork, execSync } = require('child_process');
|
|
|
|
const binDir = __dirname;
|
|
const simDir = path.resolve(binDir, '..');
|
|
|
|
function readJSON(file) {
|
|
try { return JSON.parse(fs.readFileSync(file, 'utf8')); } catch { return null; }
|
|
}
|
|
|
|
// ---- Resolve skills directory ----
|
|
function resolveSkillsDir() {
|
|
const skillsdirPath = path.join(simDir, '.skillsdir');
|
|
if (fs.existsSync(skillsdirPath)) {
|
|
return fs.readFileSync(skillsdirPath, 'utf8').trim();
|
|
}
|
|
const envDir = process.env.OPENCLAW_SKILLS_DIR;
|
|
if (envDir) return path.resolve(envDir);
|
|
const defaultDir = path.resolve(simDir, '..', 'skills');
|
|
if (fs.existsSync(defaultDir)) return defaultDir;
|
|
return null;
|
|
}
|
|
|
|
const skillsDir = resolveSkillsDir();
|
|
|
|
// ---- Detect system openclaw conflict ----
|
|
if (process.env.OPENCLAW_CLI !== '1') {
|
|
const PATH = process.env.PATH || '';
|
|
const pathEntries = PATH.split(path.delimiter);
|
|
for (const entry of pathEntries) {
|
|
if (entry === binDir) continue;
|
|
const otherPath = path.join(entry, 'openclaw');
|
|
try {
|
|
if (fs.statSync(otherPath).isFile() && fs.realpathSync(otherPath) !== __filename) {
|
|
process.stderr.write(`[openclaw] warning: found another openclaw at ${otherPath}\n`);
|
|
process.stderr.write(`[openclaw] using: ${__filename}\n`);
|
|
}
|
|
} catch {}
|
|
}
|
|
}
|
|
|
|
// ---- Settings helpers ----
|
|
function getSettings() {
|
|
return readJSON(path.join(simDir, '.settings.json')) || {};
|
|
}
|
|
|
|
function writePendingSetting(key, value) {
|
|
const pendingPath = path.join(simDir, '.settings-pending.json');
|
|
let pending = readJSON(pendingPath) || {};
|
|
pending[key] = value;
|
|
fs.writeFileSync(pendingPath, JSON.stringify(pending, null, 2));
|
|
}
|
|
|
|
// ---- Permission check for plugin commands ----
|
|
function requireSkillsDir() {
|
|
if (!skillsDir) {
|
|
process.stderr.write('Error: cannot determine skills directory. Start the manager first or set OPENCLAW_SKILLS_DIR.\n');
|
|
process.exit(1);
|
|
}
|
|
if (!fs.existsSync(skillsDir)) {
|
|
fs.mkdirSync(skillsDir, { recursive: true });
|
|
}
|
|
}
|
|
|
|
// ---- Main ----
|
|
const cmd = process.argv[2];
|
|
|
|
if (!cmd || cmd === 'help' || cmd === '--help') {
|
|
console.log(`HologramAgent OpenClaw Adapter 1.0.0 (openclaw-compatible)
|
|
Usage: openclaw <command> [args]
|
|
|
|
Commands:
|
|
plugin:install <spec> Install a plugin (npm:xxx, clawhub:xxx, or path)
|
|
plugin:uninstall <name> Uninstall a plugin
|
|
plugin:list List installed plugins
|
|
auth:login [url] Show QR code for login
|
|
auth:status Check auth status
|
|
config:get <key> Get config value
|
|
config:set <key> <val> Set config value
|
|
config:list List all config
|
|
doctor Run diagnostics
|
|
update Check for updates
|
|
env Show runtime info
|
|
--version Show version
|
|
help Show this help`);
|
|
process.exit(0);
|
|
}
|
|
|
|
if (cmd === '--version' || cmd === 'version') {
|
|
console.log('HologramAgent OpenClaw Adapter 1.0.0 (openclaw-compatible)');
|
|
process.exit(0);
|
|
}
|
|
|
|
if (cmd === 'env') {
|
|
requireSkillsDir();
|
|
const info = {
|
|
homeAgent: true,
|
|
openclawVersion: 'compatible',
|
|
platform: process.platform,
|
|
nodeVersion: process.version,
|
|
skillsDir: skillsDir,
|
|
simulatorDir: simDir,
|
|
openclawCli: __filename,
|
|
};
|
|
console.log(JSON.stringify(info, null, 2));
|
|
process.exit(0);
|
|
}
|
|
|
|
if (cmd === 'doctor') {
|
|
console.log('OpenClaw Adapter diagnostics:');
|
|
console.log(` Simulator dir: ${simDir}`);
|
|
console.log(` Skills dir: ${skillsDir || '(not set)'}`);
|
|
console.log(` Node: ${process.version}`);
|
|
console.log(` Platform: ${process.platform}`);
|
|
if (skillsDir) {
|
|
const entries = fs.readdirSync(skillsDir).filter(e => !e.startsWith('.'));
|
|
console.log(` Installed plugins: ${entries.length}`);
|
|
}
|
|
console.log(' Status: OK');
|
|
process.exit(0);
|
|
}
|
|
|
|
if (cmd === 'update') {
|
|
console.log('Update check: HologramAgent OpenClaw Adapter is bundled with HologramAgent.');
|
|
console.log('To update, update HologramAgent itself.');
|
|
process.exit(0);
|
|
}
|
|
|
|
if (cmd === 'config:get') {
|
|
const key = process.argv[3];
|
|
if (!key) { process.stderr.write('Usage: openclaw config:get <key>\n'); process.exit(1); }
|
|
const settings = getSettings();
|
|
if (key in settings) {
|
|
console.log(settings[key]);
|
|
} else {
|
|
process.stderr.write(`(not set: ${key})\n`);
|
|
process.exit(1);
|
|
}
|
|
process.exit(0);
|
|
}
|
|
|
|
if (cmd === 'config:set') {
|
|
const key = process.argv[3];
|
|
const value = process.argv[4];
|
|
if (!key || value === undefined) { process.stderr.write('Usage: openclaw config:set <key> <value>\n'); process.exit(1); }
|
|
writePendingSetting(key, value);
|
|
console.log(`Set: ${key}=${value} (will apply on next sync)`);
|
|
process.exit(0);
|
|
}
|
|
|
|
if (cmd === 'config:list') {
|
|
const settings = getSettings();
|
|
const keys = Object.keys(settings);
|
|
if (keys.length === 0) {
|
|
console.log('(no settings)');
|
|
} else {
|
|
for (const k of keys) {
|
|
console.log(` ${k}=${settings[k]}`);
|
|
}
|
|
}
|
|
process.exit(0);
|
|
}
|
|
|
|
if (cmd === 'auth:login' || cmd === 'auth:qrcode') {
|
|
const url = process.argv[3] || 'openclaw://auth';
|
|
try {
|
|
const qrcode = require('qrcode');
|
|
qrcode.generate(url, { small: true }, (qr) => process.stdout.write(qr + '\n'));
|
|
} catch {
|
|
console.log('QR not available (install qrcode package). URL:');
|
|
}
|
|
console.log(` ${url}`);
|
|
process.exit(0);
|
|
}
|
|
|
|
if (cmd === 'auth:status') {
|
|
console.log('Auth status: running in HologramAgent mode (not applicable)');
|
|
process.exit(0);
|
|
}
|
|
|
|
// ---- Plugin lifecycle commands - needs manager.js fork ----
|
|
if (cmd === 'plugin:install' || cmd === 'plugin:uninstall' || cmd === 'plugin:list') {
|
|
requireSkillsDir();
|
|
const managerPath = path.join(simDir, 'manager.js');
|
|
if (!fs.existsSync(managerPath)) {
|
|
process.stderr.write('Error: manager.js not found at ' + managerPath + '\n');
|
|
process.exit(1);
|
|
}
|
|
const proc = fork(managerPath, [skillsDir, ...process.argv.slice(2)], {
|
|
stdio: 'inherit',
|
|
env: { ...process.env, OPENCLAW_CLI: '1' },
|
|
});
|
|
proc.on('exit', (code) => {
|
|
// After plugin:install, notify Go side via .reload-request
|
|
if (cmd === 'plugin:install' && code === 0) {
|
|
const spec = process.argv[3] || '';
|
|
const installLog = path.join(simDir, '.install-result');
|
|
if (fs.existsSync(installLog)) {
|
|
const result = readJSON(installLog);
|
|
if (result && result.name) {
|
|
fs.writeFileSync(path.join(simDir, '.reload-request'), result.name);
|
|
console.log(`[openclaw] queued reload for plugin: ${result.name}`);
|
|
}
|
|
fs.rmSync(installLog, { force: true });
|
|
}
|
|
}
|
|
process.exit(code);
|
|
});
|
|
return;
|
|
}
|
|
|
|
process.stderr.write(`Unknown command: ${cmd}\n`);
|
|
process.stderr.write("Run 'openclaw help' for usage.\n");
|
|
process.exit(1);
|