@atel-ai/runtime-core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/claude-code.d.ts +3 -0
- package/dist/adapters/claude-code.d.ts.map +1 -0
- package/dist/adapters/claude-code.js +65 -0
- package/dist/adapters/claude-code.js.map +1 -0
- package/dist/adapters/codex.d.ts +3 -0
- package/dist/adapters/codex.d.ts.map +1 -0
- package/dist/adapters/codex.js +49 -0
- package/dist/adapters/codex.js.map +1 -0
- package/dist/adapters/gemini-cli.d.ts +3 -0
- package/dist/adapters/gemini-cli.d.ts.map +1 -0
- package/dist/adapters/gemini-cli.js +43 -0
- package/dist/adapters/gemini-cli.js.map +1 -0
- package/dist/adapters/hermes.d.ts +3 -0
- package/dist/adapters/hermes.d.ts.map +1 -0
- package/dist/adapters/hermes.js +58 -0
- package/dist/adapters/hermes.js.map +1 -0
- package/dist/adapters/openclaw.d.ts +13 -0
- package/dist/adapters/openclaw.d.ts.map +1 -0
- package/dist/adapters/openclaw.js +36 -0
- package/dist/adapters/openclaw.js.map +1 -0
- package/dist/adapters/qwen-agent.d.ts +3 -0
- package/dist/adapters/qwen-agent.d.ts.map +1 -0
- package/dist/adapters/qwen-agent.js +128 -0
- package/dist/adapters/qwen-agent.js.map +1 -0
- package/dist/adapters/registry.d.ts +20 -0
- package/dist/adapters/registry.d.ts.map +1 -0
- package/dist/adapters/registry.js +42 -0
- package/dist/adapters/registry.js.map +1 -0
- package/dist/adapters/types.d.ts +46 -0
- package/dist/adapters/types.d.ts.map +1 -0
- package/dist/adapters/types.js +2 -0
- package/dist/adapters/types.js.map +1 -0
- package/dist/adapters/util.d.ts +10 -0
- package/dist/adapters/util.d.ts.map +1 -0
- package/dist/adapters/util.js +86 -0
- package/dist/adapters/util.js.map +1 -0
- package/dist/auth.d.ts +42 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +91 -0
- package/dist/auth.js.map +1 -0
- package/dist/client.d.ts +55 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +139 -0
- package/dist/client.js.map +1 -0
- package/dist/companion.d.ts +45 -0
- package/dist/companion.d.ts.map +1 -0
- package/dist/companion.js +224 -0
- package/dist/companion.js.map +1 -0
- package/dist/config.d.ts +35 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +29 -0
- package/dist/config.js.map +1 -0
- package/dist/deadletter.d.ts +31 -0
- package/dist/deadletter.d.ts.map +1 -0
- package/dist/deadletter.js +67 -0
- package/dist/deadletter.js.map +1 -0
- package/dist/envelope.d.ts +21 -0
- package/dist/envelope.d.ts.map +1 -0
- package/dist/envelope.js +20 -0
- package/dist/envelope.js.map +1 -0
- package/dist/events/channel-relay.d.ts +35 -0
- package/dist/events/channel-relay.d.ts.map +1 -0
- package/dist/events/channel-relay.js +97 -0
- package/dist/events/channel-relay.js.map +1 -0
- package/dist/events/channel-spine.d.ts +41 -0
- package/dist/events/channel-spine.d.ts.map +1 -0
- package/dist/events/channel-spine.js +139 -0
- package/dist/events/channel-spine.js.map +1 -0
- package/dist/events/dedup.d.ts +25 -0
- package/dist/events/dedup.d.ts.map +1 -0
- package/dist/events/dedup.js +56 -0
- package/dist/events/dedup.js.map +1 -0
- package/dist/events/mapping.d.ts +37 -0
- package/dist/events/mapping.d.ts.map +1 -0
- package/dist/events/mapping.js +212 -0
- package/dist/events/mapping.js.map +1 -0
- package/dist/events/roles.d.ts +21 -0
- package/dist/events/roles.d.ts.map +1 -0
- package/dist/events/roles.js +80 -0
- package/dist/events/roles.js.map +1 -0
- package/dist/events/types.d.ts +51 -0
- package/dist/events/types.d.ts.map +1 -0
- package/dist/events/types.js +96 -0
- package/dist/events/types.js.map +1 -0
- package/dist/identity.d.ts +48 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/identity.js +123 -0
- package/dist/identity.js.map +1 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +40 -0
- package/dist/index.js.map +1 -0
- package/dist/queue.d.ts +12 -0
- package/dist/queue.d.ts.map +1 -0
- package/dist/queue.js +25 -0
- package/dist/queue.js.map +1 -0
- package/dist/tracker.d.ts +27 -0
- package/dist/tracker.d.ts.map +1 -0
- package/dist/tracker.js +80 -0
- package/dist/tracker.js.map +1 -0
- package/dist/wakers/cli.d.ts +36 -0
- package/dist/wakers/cli.d.ts.map +1 -0
- package/dist/wakers/cli.js +116 -0
- package/dist/wakers/cli.js.map +1 -0
- package/dist/wakers/daemon.d.ts +26 -0
- package/dist/wakers/daemon.d.ts.map +1 -0
- package/dist/wakers/daemon.js +51 -0
- package/dist/wakers/daemon.js.map +1 -0
- package/dist/wakers/embedded.d.ts +23 -0
- package/dist/wakers/embedded.d.ts.map +1 -0
- package/dist/wakers/embedded.js +26 -0
- package/dist/wakers/embedded.js.map +1 -0
- package/dist/wakers/types.d.ts +29 -0
- package/dist/wakers/types.d.ts.map +1 -0
- package/dist/wakers/types.js +2 -0
- package/dist/wakers/types.js.map +1 -0
- package/package.json +44 -0
- package/src/skill/SKILL.md +80 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-code.d.ts","sourceRoot":"","sources":["../../src/adapters/claude-code.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,OAAO,EAAuC,MAAM,YAAY,CAAC;AAS/E,eAAO,MAAM,iBAAiB,EAAE,OAuD/B,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Code 适配器(口子 ① CLI 无头)。
|
|
3
|
+
* 主动侧已真机验证:`claude -p` 自主调 atel_whoami、DID 一致(6.4)。
|
|
4
|
+
*
|
|
5
|
+
* MCP 配置:写 dataDir/claude-mcp.json(http transport + Bearer JWT),唤醒时用
|
|
6
|
+
* `--mcp-config <file> --strict-mcp-config` 隔离加载 —— 不污染用户全局 ~/.claude.json,
|
|
7
|
+
* 每个 ATEL agent 一份独立 MCP 配置。JWT 续期时重写该文件即可。
|
|
8
|
+
* 唤醒:`claude -p <prompt> --dangerously-skip-permissions`(auto-approve 全自动);
|
|
9
|
+
* 同一订单用确定性 UUID --session-id 续会话(热会话,避免冷启)。
|
|
10
|
+
*/
|
|
11
|
+
import fs from 'node:fs';
|
|
12
|
+
import path from 'node:path';
|
|
13
|
+
import { CliWaker } from '../wakers/cli.js';
|
|
14
|
+
import { which, runText } from './util.js';
|
|
15
|
+
function mcpConfigPath(dataDir) {
|
|
16
|
+
return path.join(dataDir, 'claude-mcp.json');
|
|
17
|
+
}
|
|
18
|
+
export const claudeCodeAdapter = {
|
|
19
|
+
id: 'claude-code',
|
|
20
|
+
displayName: 'Claude Code',
|
|
21
|
+
kind: 'cli',
|
|
22
|
+
async detect() {
|
|
23
|
+
const bin = await which('claude');
|
|
24
|
+
if (!bin)
|
|
25
|
+
return { present: false };
|
|
26
|
+
const version = (await runText('claude', ['--version'])) || undefined;
|
|
27
|
+
return { present: true, binPath: bin, version };
|
|
28
|
+
},
|
|
29
|
+
async writeMcpConfig(ctx) {
|
|
30
|
+
const f = mcpConfigPath(ctx.config.dataDir);
|
|
31
|
+
fs.mkdirSync(path.dirname(f), { recursive: true });
|
|
32
|
+
fs.writeFileSync(f, JSON.stringify({
|
|
33
|
+
mcpServers: {
|
|
34
|
+
atel: {
|
|
35
|
+
type: 'http',
|
|
36
|
+
url: ctx.mcpUrl,
|
|
37
|
+
headers: { Authorization: `Bearer ${ctx.token}` },
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
}, null, 2));
|
|
41
|
+
},
|
|
42
|
+
createWaker(ctx) {
|
|
43
|
+
const mcpCfg = mcpConfigPath(ctx.config.dataDir);
|
|
44
|
+
return new CliWaker({
|
|
45
|
+
bin: 'claude',
|
|
46
|
+
defaultTimeoutMs: 300_000,
|
|
47
|
+
sessionStatePath: path.join(ctx.config.dataDir, 'claude-sessions.json'),
|
|
48
|
+
log: ctx.log,
|
|
49
|
+
buildArgs: ({ prompt, sessionId, isResume }) => {
|
|
50
|
+
const base = [
|
|
51
|
+
'-p',
|
|
52
|
+
prompt,
|
|
53
|
+
'--output-format',
|
|
54
|
+
'text',
|
|
55
|
+
'--mcp-config',
|
|
56
|
+
mcpCfg,
|
|
57
|
+
'--strict-mcp-config',
|
|
58
|
+
'--dangerously-skip-permissions',
|
|
59
|
+
];
|
|
60
|
+
return isResume ? ['--resume', sessionId, ...base] : ['--session-id', sessionId, ...base];
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
//# sourceMappingURL=claude-code.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-code.js","sourceRoot":"","sources":["../../src/adapters/claude-code.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE3C,SAAS,aAAa,CAAC,OAAe;IACpC,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAY;IACxC,EAAE,EAAE,aAAa;IACjB,WAAW,EAAE,aAAa;IAC1B,IAAI,EAAE,KAAK;IAEX,KAAK,CAAC,MAAM;QACV,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,CAAC;QAClC,IAAI,CAAC,GAAG;YAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QACpC,MAAM,OAAO,GAAG,CAAC,MAAM,OAAO,CAAC,QAAQ,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC;QACtE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC;IAClD,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,GAAgB;QACnC,MAAM,CAAC,GAAG,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC5C,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACnD,EAAE,CAAC,aAAa,CACd,CAAC,EACD,IAAI,CAAC,SAAS,CACZ;YACE,UAAU,EAAE;gBACV,IAAI,EAAE;oBACJ,IAAI,EAAE,MAAM;oBACZ,GAAG,EAAE,GAAG,CAAC,MAAM;oBACf,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,GAAG,CAAC,KAAK,EAAE,EAAE;iBAClD;aACF;SACF,EACD,IAAI,EACJ,CAAC,CACF,CACF,CAAC;IACJ,CAAC;IAED,WAAW,CAAC,GAAa;QACvB,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACjD,OAAO,IAAI,QAAQ,CAAC;YAClB,GAAG,EAAE,QAAQ;YACb,gBAAgB,EAAE,OAAO;YACzB,gBAAgB,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,EAAE,sBAAsB,CAAC;YACvE,GAAG,EAAE,GAAG,CAAC,GAAG;YACZ,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE;gBAC7C,MAAM,IAAI,GAAG;oBACX,IAAI;oBACJ,MAAM;oBACN,iBAAiB;oBACjB,MAAM;oBACN,cAAc;oBACd,MAAM;oBACN,qBAAqB;oBACrB,gCAAgC;iBACjC,CAAC;gBACF,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC,CAAC;YAC5F,CAAC;SACF,CAAC,CAAC;IACL,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex.d.ts","sourceRoot":"","sources":["../../src/adapters/codex.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,OAAO,EAAuC,MAAM,YAAY,CAAC;AAK/E,eAAO,MAAM,YAAY,EAAE,OAoC1B,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Codex 适配器(口子 ① CLI 无头)。
|
|
3
|
+
* 主动侧已真机验证:`codex exec` 自主调 atel_whoami、DID 一致(6.4)。
|
|
4
|
+
*
|
|
5
|
+
* MCP 配置:写 ~/.codex/config.toml 的 [mcp_servers.atel](url + Bearer header)。
|
|
6
|
+
* 唤醒:`codex exec <prompt>` + 全自动免审批。
|
|
7
|
+
* ⚠️ codex 的 remote-http MCP toml 字段与 exec 免审批 flag 各版本有差异,
|
|
8
|
+
* 真机以 `codex --help` / `codex exec --help` 为准(install 时 doctor 会校验连通)。
|
|
9
|
+
*/
|
|
10
|
+
import os from 'node:os';
|
|
11
|
+
import path from 'node:path';
|
|
12
|
+
import { CliWaker } from '../wakers/cli.js';
|
|
13
|
+
import { which, runText, writeTomlSection } from './util.js';
|
|
14
|
+
export const codexAdapter = {
|
|
15
|
+
id: 'codex',
|
|
16
|
+
displayName: 'Codex',
|
|
17
|
+
kind: 'cli',
|
|
18
|
+
async detect() {
|
|
19
|
+
const bin = await which('codex');
|
|
20
|
+
if (!bin)
|
|
21
|
+
return { present: false };
|
|
22
|
+
const version = (await runText('codex', ['--version'])) || undefined;
|
|
23
|
+
return { present: true, binPath: bin, version };
|
|
24
|
+
},
|
|
25
|
+
async writeMcpConfig(ctx) {
|
|
26
|
+
const file = path.join(os.homedir(), '.codex', 'config.toml');
|
|
27
|
+
const body = [
|
|
28
|
+
`url = "${ctx.mcpUrl}"`,
|
|
29
|
+
`# ATEL JWT(companion 续期时会自动重写本段)`,
|
|
30
|
+
`[mcp_servers.atel.headers]`,
|
|
31
|
+
`Authorization = "Bearer ${ctx.token}"`,
|
|
32
|
+
].join('\n');
|
|
33
|
+
writeTomlSection(file, 'mcp_servers.atel', body);
|
|
34
|
+
},
|
|
35
|
+
createWaker(ctx) {
|
|
36
|
+
return new CliWaker({
|
|
37
|
+
bin: 'codex',
|
|
38
|
+
defaultTimeoutMs: 300_000,
|
|
39
|
+
log: ctx.log,
|
|
40
|
+
buildArgs: ({ prompt }) => [
|
|
41
|
+
'exec',
|
|
42
|
+
'--dangerously-bypass-approvals-and-sandbox',
|
|
43
|
+
'--skip-git-repo-check',
|
|
44
|
+
prompt,
|
|
45
|
+
],
|
|
46
|
+
});
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
//# sourceMappingURL=codex.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex.js","sourceRoot":"","sources":["../../src/adapters/codex.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE7D,MAAM,CAAC,MAAM,YAAY,GAAY;IACnC,EAAE,EAAE,OAAO;IACX,WAAW,EAAE,OAAO;IACpB,IAAI,EAAE,KAAK;IAEX,KAAK,CAAC,MAAM;QACV,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,CAAC;QACjC,IAAI,CAAC,GAAG;YAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QACpC,MAAM,OAAO,GAAG,CAAC,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC;QACrE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC;IAClD,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,GAAgB;QACnC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;QAC9D,MAAM,IAAI,GAAG;YACX,UAAU,GAAG,CAAC,MAAM,GAAG;YACvB,kCAAkC;YAClC,4BAA4B;YAC5B,2BAA2B,GAAG,CAAC,KAAK,GAAG;SACxC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACb,gBAAgB,CAAC,IAAI,EAAE,kBAAkB,EAAE,IAAI,CAAC,CAAC;IACnD,CAAC;IAED,WAAW,CAAC,GAAa;QACvB,OAAO,IAAI,QAAQ,CAAC;YAClB,GAAG,EAAE,OAAO;YACZ,gBAAgB,EAAE,OAAO;YACzB,GAAG,EAAE,GAAG,CAAC,GAAG;YACZ,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;gBACzB,MAAM;gBACN,4CAA4C;gBAC5C,uBAAuB;gBACvB,MAAM;aACP;SACF,CAAC,CAAC;IACL,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gemini-cli.d.ts","sourceRoot":"","sources":["../../src/adapters/gemini-cli.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,OAAO,EAAuC,MAAM,YAAY,CAAC;AAK/E,eAAO,MAAM,gBAAgB,EAAE,OAgC9B,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gemini CLI 适配器(口子 ① CLI 无头)。
|
|
3
|
+
* 主动侧已真机验证:`gemini -p` 自主调 atel_whoami、DID 一致、auth/兼容已解(6.4)。
|
|
4
|
+
*
|
|
5
|
+
* MCP 配置:写 ~/.gemini/settings.json 的 mcpServers.atel(httpUrl + Bearer header)。
|
|
6
|
+
* 唤醒:`gemini -p <prompt> --yolo`(--yolo = auto-approve 全自动)。
|
|
7
|
+
*/
|
|
8
|
+
import os from 'node:os';
|
|
9
|
+
import path from 'node:path';
|
|
10
|
+
import { CliWaker } from '../wakers/cli.js';
|
|
11
|
+
import { which, runText, mergeJson } from './util.js';
|
|
12
|
+
export const geminiCliAdapter = {
|
|
13
|
+
id: 'gemini-cli',
|
|
14
|
+
displayName: 'Gemini CLI',
|
|
15
|
+
kind: 'cli',
|
|
16
|
+
async detect() {
|
|
17
|
+
const bin = await which('gemini');
|
|
18
|
+
if (!bin)
|
|
19
|
+
return { present: false };
|
|
20
|
+
const version = (await runText('gemini', ['--version'])) || undefined;
|
|
21
|
+
return { present: true, binPath: bin, version };
|
|
22
|
+
},
|
|
23
|
+
async writeMcpConfig(ctx) {
|
|
24
|
+
const file = path.join(os.homedir(), '.gemini', 'settings.json');
|
|
25
|
+
mergeJson(file, {
|
|
26
|
+
mcpServers: {
|
|
27
|
+
atel: {
|
|
28
|
+
httpUrl: ctx.mcpUrl,
|
|
29
|
+
headers: { Authorization: `Bearer ${ctx.token}` },
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
},
|
|
34
|
+
createWaker(ctx) {
|
|
35
|
+
return new CliWaker({
|
|
36
|
+
bin: 'gemini',
|
|
37
|
+
defaultTimeoutMs: 300_000,
|
|
38
|
+
log: ctx.log,
|
|
39
|
+
buildArgs: ({ prompt }) => ['-p', prompt, '--yolo'],
|
|
40
|
+
});
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=gemini-cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gemini-cli.js","sourceRoot":"","sources":["../../src/adapters/gemini-cli.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtD,MAAM,CAAC,MAAM,gBAAgB,GAAY;IACvC,EAAE,EAAE,YAAY;IAChB,WAAW,EAAE,YAAY;IACzB,IAAI,EAAE,KAAK;IAEX,KAAK,CAAC,MAAM;QACV,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,CAAC;QAClC,IAAI,CAAC,GAAG;YAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QACpC,MAAM,OAAO,GAAG,CAAC,MAAM,OAAO,CAAC,QAAQ,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC;QACtE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC;IAClD,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,GAAgB;QACnC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,eAAe,CAAC,CAAC;QACjE,SAAS,CAAC,IAAI,EAAE;YACd,UAAU,EAAE;gBACV,IAAI,EAAE;oBACJ,OAAO,EAAE,GAAG,CAAC,MAAM;oBACnB,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,GAAG,CAAC,KAAK,EAAE,EAAE;iBAClD;aACF;SACF,CAAC,CAAC;IACL,CAAC;IAED,WAAW,CAAC,GAAa;QACvB,OAAO,IAAI,QAAQ,CAAC;YAClB,GAAG,EAAE,QAAQ;YACb,gBAAgB,EAAE,OAAO;YACzB,GAAG,EAAE,GAAG,CAAC,GAAG;YACZ,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC;SACpD,CAAC,CAAC;IACL,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hermes.d.ts","sourceRoot":"","sources":["../../src/adapters/hermes.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,OAAO,EAAuC,MAAM,YAAY,CAAC;AAS/E,eAAO,MAAM,aAAa,EAAE,OA6B3B,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hermes 适配器(口子 ① CLI 无头,NousResearch/hermes-agent)。
|
|
3
|
+
* 主动侧已真机验证:`hermes chat -q "..." --yolo` 自主调 atel_whoami、DID 一致(6.4 核-7)。
|
|
4
|
+
*
|
|
5
|
+
* MCP 配置:Hermes 把 token 存成环境变量 MCP_ATEL_API_KEY(6.4 核-7),且 token 须纯 JWT。
|
|
6
|
+
* `hermes mcp add atel --url <url> --auth header` 是交互式(一次性手动 add),
|
|
7
|
+
* 续期只需更新 MCP_ATEL_API_KEY。这里把当前 JWT 落到 dataDir/hermes.env,
|
|
8
|
+
* 唤醒时注入该 env;并写一份 token 文件供 install 脚本/手动 add 时取用。
|
|
9
|
+
* 唤醒:`hermes chat -q <prompt> --yolo`(-q 一次性 + 拉 MCP;-z 模式按设计不拉 MCP,勿用)。
|
|
10
|
+
* 首跑冷连接可能慢(实测首次可达 220s),timeout 给足。
|
|
11
|
+
*/
|
|
12
|
+
import fs from 'node:fs';
|
|
13
|
+
import path from 'node:path';
|
|
14
|
+
import { CliWaker } from '../wakers/cli.js';
|
|
15
|
+
import { which, runText } from './util.js';
|
|
16
|
+
function tokenFile(dataDir) {
|
|
17
|
+
return path.join(dataDir, 'hermes-mcp-token.txt');
|
|
18
|
+
}
|
|
19
|
+
export const hermesAdapter = {
|
|
20
|
+
id: 'hermes',
|
|
21
|
+
displayName: 'Hermes (NousResearch)',
|
|
22
|
+
kind: 'cli',
|
|
23
|
+
async detect() {
|
|
24
|
+
const bin = await which('hermes');
|
|
25
|
+
if (!bin)
|
|
26
|
+
return { present: false };
|
|
27
|
+
const version = (await runText('hermes', ['--version'])) || undefined;
|
|
28
|
+
return { present: true, binPath: bin, version };
|
|
29
|
+
},
|
|
30
|
+
async writeMcpConfig(ctx) {
|
|
31
|
+
// Hermes 经 env MCP_ATEL_API_KEY 注入纯 JWT;落盘供唤醒器读取注入。
|
|
32
|
+
const f = tokenFile(ctx.config.dataDir);
|
|
33
|
+
fs.mkdirSync(path.dirname(f), { recursive: true });
|
|
34
|
+
fs.writeFileSync(f, ctx.token);
|
|
35
|
+
},
|
|
36
|
+
createWaker(ctx) {
|
|
37
|
+
return new CliWaker({
|
|
38
|
+
bin: 'hermes',
|
|
39
|
+
defaultTimeoutMs: 360_000, // 冷启首次可达 220s,留足
|
|
40
|
+
log: ctx.log,
|
|
41
|
+
buildArgs: ({ prompt }) => ['chat', '-q', prompt, '--yolo'],
|
|
42
|
+
// 每次唤醒前读最新 JWT 注入 env(JWT 续期后即时生效;token 由 writeMcpConfig 落盘)
|
|
43
|
+
env: () => readHermesEnv(ctx.config.dataDir),
|
|
44
|
+
});
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
function readHermesEnv(dataDir) {
|
|
48
|
+
try {
|
|
49
|
+
const token = fs.readFileSync(tokenFile(dataDir), 'utf8').trim();
|
|
50
|
+
if (token)
|
|
51
|
+
return { MCP_ATEL_API_KEY: token };
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
/* token 尚未写入(首次 install 前) */
|
|
55
|
+
}
|
|
56
|
+
return {};
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=hermes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hermes.js","sourceRoot":"","sources":["../../src/adapters/hermes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE3C,SAAS,SAAS,CAAC,OAAe;IAChC,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,sBAAsB,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAAY;IACpC,EAAE,EAAE,QAAQ;IACZ,WAAW,EAAE,uBAAuB;IACpC,IAAI,EAAE,KAAK;IAEX,KAAK,CAAC,MAAM;QACV,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,CAAC;QAClC,IAAI,CAAC,GAAG;YAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QACpC,MAAM,OAAO,GAAG,CAAC,MAAM,OAAO,CAAC,QAAQ,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC;QACtE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC;IAClD,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,GAAgB;QACnC,oDAAoD;QACpD,MAAM,CAAC,GAAG,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACxC,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACnD,EAAE,CAAC,aAAa,CAAC,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC;IACjC,CAAC;IAED,WAAW,CAAC,GAAa;QACvB,OAAO,IAAI,QAAQ,CAAC;YAClB,GAAG,EAAE,QAAQ;YACb,gBAAgB,EAAE,OAAO,EAAE,iBAAiB;YAC5C,GAAG,EAAE,GAAG,CAAC,GAAG;YACZ,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC;YAC3D,6DAA6D;YAC7D,GAAG,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC;SAC7C,CAAC,CAAC;IACL,CAAC;CACF,CAAC;AAEF,SAAS,aAAa,CAAC,OAAe;IACpC,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;QACjE,IAAI,KAAK;YAAE,OAAO,EAAE,gBAAgB,EAAE,KAAK,EAAE,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,8BAA8B;IAChC,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenClaw(龙虾)适配器(口子 ② 常驻 daemon / 也可 CLI 唤醒)。
|
|
3
|
+
* 生产在跑;现有 atel-mcp-openclaw 插件自带 listener + poll-loop + DID-Sig MCP。
|
|
4
|
+
*
|
|
5
|
+
* 定位:OpenClaw 已有完整自管(自己的 MCP DID-Sig、自己的 listener),本适配器
|
|
6
|
+
* 不接管它的 MCP 配置(writeMcpConfig 为 no-op,避免与插件打架),只在需要由内核
|
|
7
|
+
* 统一唤醒时,用 `openclaw agent --session-id <uuid> --local -m <prompt>`(listener.js 实证)。
|
|
8
|
+
*
|
|
9
|
+
* 即:把 OpenClaw 纳入"同一套内核唤醒/映射",但尊重它已有的 MCP 通路。
|
|
10
|
+
*/
|
|
11
|
+
import type { Adapter } from './types.js';
|
|
12
|
+
export declare const openclawAdapter: Adapter;
|
|
13
|
+
//# sourceMappingURL=openclaw.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openclaw.d.ts","sourceRoot":"","sources":["../../src/adapters/openclaw.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,OAAO,EAAuC,MAAM,YAAY,CAAC;AAK/E,eAAO,MAAM,eAAe,EAAE,OAkC7B,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { CliWaker } from '../wakers/cli.js';
|
|
2
|
+
import { which, runText } from './util.js';
|
|
3
|
+
export const openclawAdapter = {
|
|
4
|
+
id: 'openclaw',
|
|
5
|
+
displayName: 'OpenClaw (龙虾)',
|
|
6
|
+
kind: 'daemon',
|
|
7
|
+
async detect() {
|
|
8
|
+
const bin = await which('openclaw');
|
|
9
|
+
if (!bin)
|
|
10
|
+
return { present: false };
|
|
11
|
+
const version = (await runText('openclaw', ['--version'])) || undefined;
|
|
12
|
+
return { present: true, binPath: bin, version, detail: 'MCP 由 atel-mcp-openclaw 插件自管' };
|
|
13
|
+
},
|
|
14
|
+
async writeMcpConfig(_ctx) {
|
|
15
|
+
// no-op:OpenClaw 经 atel-mcp-openclaw 插件用 DID-Sig 连 MCP,不写 JWT。
|
|
16
|
+
},
|
|
17
|
+
createWaker(ctx) {
|
|
18
|
+
return new CliWaker({
|
|
19
|
+
bin: 'openclaw',
|
|
20
|
+
defaultTimeoutMs: 300_000,
|
|
21
|
+
log: ctx.log,
|
|
22
|
+
// 每次 fresh session 防 lane 污染(listener.js 0.6.39 教训);prompt 自包含
|
|
23
|
+
buildArgs: ({ prompt, sessionId }) => [
|
|
24
|
+
'agent',
|
|
25
|
+
'--agent',
|
|
26
|
+
'main',
|
|
27
|
+
'--session-id',
|
|
28
|
+
sessionId,
|
|
29
|
+
'--local',
|
|
30
|
+
'-m',
|
|
31
|
+
prompt,
|
|
32
|
+
],
|
|
33
|
+
});
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=openclaw.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openclaw.js","sourceRoot":"","sources":["../../src/adapters/openclaw.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE3C,MAAM,CAAC,MAAM,eAAe,GAAY;IACtC,EAAE,EAAE,UAAU;IACd,WAAW,EAAE,eAAe;IAC5B,IAAI,EAAE,QAAQ;IAEd,KAAK,CAAC,MAAM;QACV,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,UAAU,CAAC,CAAC;QACpC,IAAI,CAAC,GAAG;YAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QACpC,MAAM,OAAO,GAAG,CAAC,MAAM,OAAO,CAAC,UAAU,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC;QACxE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,8BAA8B,EAAE,CAAC;IAC1F,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,IAAiB;QACpC,+DAA+D;IACjE,CAAC;IAED,WAAW,CAAC,GAAa;QACvB,OAAO,IAAI,QAAQ,CAAC;YAClB,GAAG,EAAE,UAAU;YACf,gBAAgB,EAAE,OAAO;YACzB,GAAG,EAAE,GAAG,CAAC,GAAG;YACZ,+DAA+D;YAC/D,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;gBACpC,OAAO;gBACP,SAAS;gBACT,MAAM;gBACN,cAAc;gBACd,SAAS;gBACT,SAAS;gBACT,IAAI;gBACJ,MAAM;aACP;SACF,CAAC,CAAC;IACL,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qwen-agent.d.ts","sourceRoot":"","sources":["../../src/adapters/qwen-agent.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,OAAO,EAAuC,MAAM,YAAY,CAAC;AAc/E,eAAO,MAAM,gBAAgB,EAAE,OAqE9B,CAAC"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Qwen-Agent 适配器(口子 ③ 嵌入式库,阿里 python 框架)。
|
|
3
|
+
* 主动侧已真机验证:Python 框架自主调 atel_whoami、DID 一致(6.4)。
|
|
4
|
+
*
|
|
5
|
+
* Qwen-Agent 是 python 库,没有现成无头 CLI,所以内核起一个宿主壳进程
|
|
6
|
+
* (scripts/qwen_host.py)import qwen_agent,按 prompt 跑一轮、把结果打到 stdout。
|
|
7
|
+
* MCP 配置:写 dataDir/qwen-mcp.json(streamable-http + Bearer),host 脚本读它装 MCP。
|
|
8
|
+
* 唤醒:EmbeddedWaker 通过 spawn python host 实现。
|
|
9
|
+
*/
|
|
10
|
+
import fs from 'node:fs';
|
|
11
|
+
import path from 'node:path';
|
|
12
|
+
import { spawn } from 'node:child_process';
|
|
13
|
+
import { EmbeddedWaker } from '../wakers/embedded.js';
|
|
14
|
+
import { which, runText } from './util.js';
|
|
15
|
+
function mcpConfigPath(dataDir) {
|
|
16
|
+
return path.join(dataDir, 'qwen-mcp.json');
|
|
17
|
+
}
|
|
18
|
+
/** 宿主壳脚本路径(随包发布在 dist 同级 scripts/,或 dataDir 落一份)。 */
|
|
19
|
+
function hostScriptPath(dataDir) {
|
|
20
|
+
return path.join(dataDir, 'qwen_host.py');
|
|
21
|
+
}
|
|
22
|
+
export const qwenAgentAdapter = {
|
|
23
|
+
id: 'qwen-agent',
|
|
24
|
+
displayName: 'Qwen-Agent (阿里)',
|
|
25
|
+
kind: 'embedded',
|
|
26
|
+
async detect() {
|
|
27
|
+
const py = (await which('python3')) || (await which('python'));
|
|
28
|
+
if (!py)
|
|
29
|
+
return { present: false, detail: 'no python' };
|
|
30
|
+
// 用 sentinel 区分 import 成功 vs 失败(runText 会把 stderr traceback 也返回,不能直接当版本)
|
|
31
|
+
const probe = await runText(py, [
|
|
32
|
+
'-c',
|
|
33
|
+
'import qwen_agent;print("ATEL_OK:"+getattr(qwen_agent,"__version__","?"))',
|
|
34
|
+
]);
|
|
35
|
+
if (!probe || !probe.includes('ATEL_OK:')) {
|
|
36
|
+
return { present: false, detail: 'qwen_agent module not importable' };
|
|
37
|
+
}
|
|
38
|
+
const version = probe.split('ATEL_OK:')[1]?.trim() || '?';
|
|
39
|
+
return { present: true, binPath: py, version };
|
|
40
|
+
},
|
|
41
|
+
async writeMcpConfig(ctx) {
|
|
42
|
+
const f = mcpConfigPath(ctx.config.dataDir);
|
|
43
|
+
fs.mkdirSync(path.dirname(f), { recursive: true });
|
|
44
|
+
fs.writeFileSync(f, JSON.stringify({
|
|
45
|
+
mcpServers: {
|
|
46
|
+
atel: {
|
|
47
|
+
type: 'streamable-http',
|
|
48
|
+
url: ctx.mcpUrl,
|
|
49
|
+
headers: { Authorization: `Bearer ${ctx.token}` },
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
}, null, 2));
|
|
53
|
+
// 落一份宿主壳脚本(若随包没带)
|
|
54
|
+
ensureHostScript(ctx.config.dataDir);
|
|
55
|
+
},
|
|
56
|
+
createWaker(ctx) {
|
|
57
|
+
const dataDir = ctx.config.dataDir;
|
|
58
|
+
ensureHostScript(dataDir);
|
|
59
|
+
return new EmbeddedWaker({
|
|
60
|
+
defaultTimeoutMs: 360_000,
|
|
61
|
+
invoke: ({ prompt, timeoutMs }) => new Promise((resolve, reject) => {
|
|
62
|
+
const py = process.env.ATEL_PYTHON || 'python3';
|
|
63
|
+
const child = spawn(py, [hostScriptPath(dataDir), '--mcp-config', mcpConfigPath(dataDir)], {
|
|
64
|
+
timeout: timeoutMs,
|
|
65
|
+
env: process.env,
|
|
66
|
+
});
|
|
67
|
+
let out = '';
|
|
68
|
+
let err = '';
|
|
69
|
+
child.stdout.on('data', (d) => (out += d.toString()));
|
|
70
|
+
child.stderr.on('data', (d) => (err += d.toString()));
|
|
71
|
+
child.on('error', reject);
|
|
72
|
+
child.on('close', (code) => {
|
|
73
|
+
if (code === 0)
|
|
74
|
+
resolve(out);
|
|
75
|
+
else
|
|
76
|
+
reject(new Error(`qwen_host exit ${code}: ${err.slice(0, 300)}`));
|
|
77
|
+
});
|
|
78
|
+
child.stdin.write(prompt);
|
|
79
|
+
child.stdin.end();
|
|
80
|
+
}),
|
|
81
|
+
});
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
const HOST_SCRIPT = `#!/usr/bin/env python3
|
|
85
|
+
# ATEL Qwen-Agent 宿主壳 —— 读 stdin 的 prompt,经 qwen_agent + ATEL MCP 跑一轮,stdout 输出结果。
|
|
86
|
+
# 由 @atel-ai/runtime-core qwen-agent 适配器 spawn。LLM provider/key 走环境变量(自带账号,不用中转站)。
|
|
87
|
+
import sys, json, argparse, os
|
|
88
|
+
|
|
89
|
+
def main():
|
|
90
|
+
ap = argparse.ArgumentParser()
|
|
91
|
+
ap.add_argument('--mcp-config', required=True)
|
|
92
|
+
args = ap.parse_args()
|
|
93
|
+
prompt = sys.stdin.read().strip()
|
|
94
|
+
with open(args.mcp_config) as f:
|
|
95
|
+
mcp = json.load(f)
|
|
96
|
+
from qwen_agent.agents import Assistant
|
|
97
|
+
llm_cfg = {
|
|
98
|
+
'model': os.environ.get('ATEL_QWEN_MODEL', 'qwen-max'),
|
|
99
|
+
'model_server': os.environ.get('ATEL_QWEN_BASE_URL', os.environ.get('DASHSCOPE_BASE_URL', '')),
|
|
100
|
+
'api_key': os.environ.get('ATEL_QWEN_API_KEY', os.environ.get('DASHSCOPE_API_KEY', '')),
|
|
101
|
+
}
|
|
102
|
+
tools = [{'mcpServers': mcp['mcpServers']}]
|
|
103
|
+
bot = Assistant(llm=llm_cfg, function_list=tools)
|
|
104
|
+
messages = [{'role': 'user', 'content': prompt}]
|
|
105
|
+
final = ''
|
|
106
|
+
for resp in bot.run(messages=messages):
|
|
107
|
+
final = resp
|
|
108
|
+
if isinstance(final, list):
|
|
109
|
+
texts = [m.get('content', '') for m in final if isinstance(m, dict)]
|
|
110
|
+
print('\\n'.join(t for t in texts if t))
|
|
111
|
+
else:
|
|
112
|
+
print(final)
|
|
113
|
+
|
|
114
|
+
if __name__ == '__main__':
|
|
115
|
+
main()
|
|
116
|
+
`;
|
|
117
|
+
function ensureHostScript(dataDir) {
|
|
118
|
+
try {
|
|
119
|
+
const f = hostScriptPath(dataDir);
|
|
120
|
+
fs.mkdirSync(path.dirname(f), { recursive: true });
|
|
121
|
+
if (!fs.existsSync(f))
|
|
122
|
+
fs.writeFileSync(f, HOST_SCRIPT, { mode: 0o755 });
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
/* best-effort */
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=qwen-agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qwen-agent.js","sourceRoot":"","sources":["../../src/adapters/qwen-agent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 适配器注册表 + detect —— 运行时自动识别本机是哪家 agent(6.5 §A detect)。
|
|
3
|
+
*
|
|
4
|
+
* "自动适配"准确含义(6.5 §2):新无头 agent 若归入已知口子类(①CLI/②daemon)
|
|
5
|
+
* 且 MCP 配置格式是已支持格式之一 → 接近"填声明"。F 验收即测此点:挑一个清单外、
|
|
6
|
+
* 属①/②的无头 agent,只用配置式适配过 A 项。
|
|
7
|
+
*/
|
|
8
|
+
import type { Adapter, DetectResult } from './types.js';
|
|
9
|
+
/** 本轮承诺的 6 个适配器。 */
|
|
10
|
+
export declare const ADAPTERS: Adapter[];
|
|
11
|
+
export declare function getAdapter(id: string): Adapter | undefined;
|
|
12
|
+
export interface DetectedRuntime {
|
|
13
|
+
adapter: Adapter;
|
|
14
|
+
result: DetectResult;
|
|
15
|
+
}
|
|
16
|
+
/** 探测本机所有在场的 runtime(并发探,各自超时隔离)。 */
|
|
17
|
+
export declare function detectAll(): Promise<DetectedRuntime[]>;
|
|
18
|
+
/** 选一个 runtime:优先用户指定 id,否则取探到的第一个;都没有返回 null。 */
|
|
19
|
+
export declare function detectPrimary(preferId?: string): Promise<DetectedRuntime | null>;
|
|
20
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/adapters/registry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAQxD,oBAAoB;AACpB,eAAO,MAAM,QAAQ,EAAE,OAAO,EAO7B,CAAC;AAEF,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAE1D;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,YAAY,CAAC;CACtB;AAED,qCAAqC;AACrC,wBAAsB,SAAS,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC,CAY5D;AAED,kDAAkD;AAClD,wBAAsB,aAAa,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAOtF"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { openclawAdapter } from './openclaw.js';
|
|
2
|
+
import { claudeCodeAdapter } from './claude-code.js';
|
|
3
|
+
import { codexAdapter } from './codex.js';
|
|
4
|
+
import { hermesAdapter } from './hermes.js';
|
|
5
|
+
import { geminiCliAdapter } from './gemini-cli.js';
|
|
6
|
+
import { qwenAgentAdapter } from './qwen-agent.js';
|
|
7
|
+
/** 本轮承诺的 6 个适配器。 */
|
|
8
|
+
export const ADAPTERS = [
|
|
9
|
+
openclawAdapter,
|
|
10
|
+
claudeCodeAdapter,
|
|
11
|
+
codexAdapter,
|
|
12
|
+
hermesAdapter,
|
|
13
|
+
geminiCliAdapter,
|
|
14
|
+
qwenAgentAdapter,
|
|
15
|
+
];
|
|
16
|
+
export function getAdapter(id) {
|
|
17
|
+
return ADAPTERS.find((a) => a.id === id);
|
|
18
|
+
}
|
|
19
|
+
/** 探测本机所有在场的 runtime(并发探,各自超时隔离)。 */
|
|
20
|
+
export async function detectAll() {
|
|
21
|
+
const results = await Promise.all(ADAPTERS.map(async (adapter) => {
|
|
22
|
+
try {
|
|
23
|
+
const result = await adapter.detect();
|
|
24
|
+
return { adapter, result };
|
|
25
|
+
}
|
|
26
|
+
catch (e) {
|
|
27
|
+
return { adapter, result: { present: false, detail: e.message } };
|
|
28
|
+
}
|
|
29
|
+
}));
|
|
30
|
+
return results.filter((r) => r.result.present);
|
|
31
|
+
}
|
|
32
|
+
/** 选一个 runtime:优先用户指定 id,否则取探到的第一个;都没有返回 null。 */
|
|
33
|
+
export async function detectPrimary(preferId) {
|
|
34
|
+
const present = await detectAll();
|
|
35
|
+
if (preferId) {
|
|
36
|
+
const hit = present.find((r) => r.adapter.id === preferId);
|
|
37
|
+
if (hit)
|
|
38
|
+
return hit;
|
|
39
|
+
}
|
|
40
|
+
return present[0] || null;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/adapters/registry.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnD,oBAAoB;AACpB,MAAM,CAAC,MAAM,QAAQ,GAAc;IACjC,eAAe;IACf,iBAAiB;IACjB,YAAY;IACZ,aAAa;IACb,gBAAgB;IAChB,gBAAgB;CACjB,CAAC;AAEF,MAAM,UAAU,UAAU,CAAC,EAAU;IACnC,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;AAC3C,CAAC;AAOD,qCAAqC;AACrC,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAC/B,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;QAC7B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC;YACtC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;QAC7B,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAG,CAAW,CAAC,OAAO,EAAkB,EAAE,CAAC;QAC/F,CAAC;IACH,CAAC,CAAC,CACH,CAAC;IACF,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AACjD,CAAC;AAED,kDAAkD;AAClD,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,QAAiB;IACnD,MAAM,OAAO,GAAG,MAAM,SAAS,EAAE,CAAC;IAClC,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;QAC3D,IAAI,GAAG;YAAE,OAAO,GAAG,CAAC;IACtB,CAAC;IACD,OAAO,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;AAC5B,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 适配器接口 —— 每个 runtime 一块薄适配(专属 20%,6.5 §C)。
|
|
3
|
+
*
|
|
4
|
+
* 适配器 = detect 识别 + writeMcpConfig(写它的 MCP 配置格式)+ createWaker(用对应驱动)。
|
|
5
|
+
* "薄但不是纯一条配置"——各家 MCP 配置格式不同(Claude JSON / Codex toml /
|
|
6
|
+
* Hermes mcp add / Gemini settings.json / Qwen python dict),writeMcpConfig 是真代码。
|
|
7
|
+
* "自动适配"准确含义:新无头 agent 若归入已知口子类 + MCP 配置格式已支持 → 近"填声明"。
|
|
8
|
+
*/
|
|
9
|
+
import type { Identity } from '../identity.js';
|
|
10
|
+
import type { RuntimeConfig } from '../config.js';
|
|
11
|
+
import type { Waker } from '../wakers/types.js';
|
|
12
|
+
export interface DetectResult {
|
|
13
|
+
present: boolean;
|
|
14
|
+
version?: string;
|
|
15
|
+
binPath?: string;
|
|
16
|
+
detail?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface WriteMcpCtx {
|
|
19
|
+
mcpUrl: string;
|
|
20
|
+
/** 最新 JWT(AuthManager 续期后会再次调用 writeMcpConfig) */
|
|
21
|
+
token: string;
|
|
22
|
+
identity: Identity;
|
|
23
|
+
config: RuntimeConfig;
|
|
24
|
+
}
|
|
25
|
+
export interface WakerCtx {
|
|
26
|
+
config: RuntimeConfig;
|
|
27
|
+
identity: Identity;
|
|
28
|
+
log?: (msg: string) => void;
|
|
29
|
+
}
|
|
30
|
+
export interface Adapter {
|
|
31
|
+
/** 稳定 id,= RuntimeConfig.runtime */
|
|
32
|
+
id: string;
|
|
33
|
+
displayName: string;
|
|
34
|
+
/** 口子类型 */
|
|
35
|
+
kind: 'cli' | 'daemon' | 'embedded';
|
|
36
|
+
/** 本机是否装了该 runtime */
|
|
37
|
+
detect(): Promise<DetectResult>;
|
|
38
|
+
/**
|
|
39
|
+
* 写该 runtime 的 MCP 配置,让 agent 连 ATEL MCP 并带上 JWT。
|
|
40
|
+
* JWT 续期时会被再次调用以热更新。
|
|
41
|
+
*/
|
|
42
|
+
writeMcpConfig(ctx: WriteMcpCtx): Promise<void>;
|
|
43
|
+
/** 构造该 runtime 的唤醒器 */
|
|
44
|
+
createWaker(ctx: WakerCtx): Waker;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/adapters/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAEhD,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,kDAAkD;IAClD,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,aAAa,CAAC;CACvB;AAED,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,aAAa,CAAC;IACtB,QAAQ,EAAE,QAAQ,CAAC;IACnB,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7B;AAED,MAAM,WAAW,OAAO;IACtB,oCAAoC;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW;IACX,IAAI,EAAE,KAAK,GAAG,QAAQ,GAAG,UAAU,CAAC;IACpC,sBAAsB;IACtB,MAAM,IAAI,OAAO,CAAC,YAAY,CAAC,CAAC;IAChC;;;OAGG;IACH,cAAc,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,uBAAuB;IACvB,WAAW,CAAC,GAAG,EAAE,QAAQ,GAAG,KAAK,CAAC;CACnC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/adapters/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** which/where 解析 bin 绝对路径;找不到返回 null。 */
|
|
2
|
+
export declare function which(bin: string): Promise<string | null>;
|
|
3
|
+
/** 跑 `bin <args>` 取首行(探版本用);失败返回 null。 */
|
|
4
|
+
export declare function runText(bin: string, args: string[], timeoutMs?: number): Promise<string | null>;
|
|
5
|
+
export declare function readJson<T = Record<string, unknown>>(file: string): T | null;
|
|
6
|
+
/** 浅合并写回 JSON,保留文件已有的其他键。 */
|
|
7
|
+
export declare function mergeJson(file: string, patch: Record<string, unknown>): void;
|
|
8
|
+
/** 极简 TOML 段写入:替换/追加 [section] 下的 key=value 块(够 codex mcp_servers 用)。 */
|
|
9
|
+
export declare function writeTomlSection(file: string, section: string, body: string): void;
|
|
10
|
+
//# sourceMappingURL=util.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../src/adapters/util.ts"],"names":[],"mappings":"AAOA,0CAA0C;AAC1C,wBAAgB,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CASzD;AAED,0CAA0C;AAC1C,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,SAAS,SAAO,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAQ7F;AAED,wBAAgB,QAAQ,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI,CAM5E;AAED,6BAA6B;AAC7B,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAK5E;AAiBD,yEAAyE;AACzE,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAwBlF"}
|