mosse-agent-bridge 0.1.4 → 0.1.6
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/acp/client.d.ts +47 -0
- package/dist/acp/client.js +94 -0
- package/dist/acp/client.js.map +1 -0
- package/dist/acp/index.d.ts +5 -0
- package/dist/acp/index.js +6 -0
- package/dist/acp/index.js.map +1 -0
- package/dist/acp/jsonrpc.d.ts +37 -0
- package/dist/acp/jsonrpc.js +120 -0
- package/dist/acp/jsonrpc.js.map +1 -0
- package/dist/acp/mock-server.d.ts +15 -0
- package/dist/acp/mock-server.js +100 -0
- package/dist/acp/mock-server.js.map +1 -0
- package/dist/acp/types.d.ts +138 -0
- package/dist/acp/types.js +20 -0
- package/dist/acp/types.js.map +1 -0
- package/dist/drivers/hermes-map.d.ts +34 -0
- package/dist/drivers/hermes-map.js +126 -0
- package/dist/drivers/hermes-map.js.map +1 -0
- package/dist/drivers/hermes.d.ts +66 -0
- package/dist/drivers/hermes.js +232 -0
- package/dist/drivers/hermes.js.map +1 -0
- package/dist/drivers/index.js +2 -0
- package/dist/drivers/index.js.map +1 -1
- package/dist/drivers/resolve.d.ts +3 -0
- package/dist/drivers/resolve.js +8 -0
- package/dist/drivers/resolve.js.map +1 -1
- package/dist/drivers/types.d.ts +13 -3
- package/dist/hermes-config.d.ts +33 -0
- package/dist/hermes-config.js +164 -0
- package/dist/hermes-config.js.map +1 -0
- package/dist/hermes-detect.d.ts +41 -0
- package/dist/hermes-detect.js +165 -0
- package/dist/hermes-detect.js.map +1 -0
- package/dist/hermes-read.d.ts +24 -0
- package/dist/hermes-read.js +76 -0
- package/dist/hermes-read.js.map +1 -0
- package/dist/hermes-test.d.ts +60 -0
- package/dist/hermes-test.js +176 -0
- package/dist/hermes-test.js.map +1 -0
- package/dist/index.js +156 -11
- package/dist/index.js.map +1 -1
- package/dist/memory.d.ts +9 -0
- package/dist/memory.js +12 -1
- package/dist/memory.js.map +1 -1
- package/package.json +20 -14
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
function str(v) {
|
|
2
|
+
return typeof v === "string" ? v : "";
|
|
3
|
+
}
|
|
4
|
+
/** 从 ACP content(可能是 string 或 {type:"text",text} 或 ContentBlock)里取文本。 */
|
|
5
|
+
function readText(content) {
|
|
6
|
+
if (typeof content === "string")
|
|
7
|
+
return content;
|
|
8
|
+
if (content && typeof content === "object") {
|
|
9
|
+
const t = content.text;
|
|
10
|
+
if (typeof t === "string")
|
|
11
|
+
return t;
|
|
12
|
+
}
|
|
13
|
+
return "";
|
|
14
|
+
}
|
|
15
|
+
function truncate(s, n) {
|
|
16
|
+
return s.length > n ? `${s.slice(0, n)}…` : s;
|
|
17
|
+
}
|
|
18
|
+
/** 计划摘要:有 entries/plan 数组就报步数,否则报标题/泛称。 */
|
|
19
|
+
function summarizePlan(update) {
|
|
20
|
+
const entries = update.entries ?? update.plan;
|
|
21
|
+
if (Array.isArray(entries))
|
|
22
|
+
return `${entries.length} step(s)`;
|
|
23
|
+
return str(update.title) || "plan";
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* ACP `session_update` → CcEvent(或 null=忽略)。映射表(§9.2):
|
|
27
|
+
* - agent_message_chunk → {type:"text", delta} (driver 累积成最终文本)
|
|
28
|
+
* - agent_thought_chunk → {type:"activity", tool:"thinking"} (思考摘要)
|
|
29
|
+
* - tool_call / tool_call_update / tool_start / tool_complete
|
|
30
|
+
* → {type:"activity", tool, summary} (工具摘要)
|
|
31
|
+
* - plan / plan_update → {type:"activity", tool:"plan"} (计划摘要)
|
|
32
|
+
* - usage_update → null(忽略;用量并入 result 由 driver 处理)
|
|
33
|
+
* - user_message_chunk → null(resume 时历史重放,非本轮 agent 产出)
|
|
34
|
+
* - 其它/未知 → null
|
|
35
|
+
*/
|
|
36
|
+
export function mapSessionUpdate(update) {
|
|
37
|
+
switch (update.sessionUpdate) {
|
|
38
|
+
case "agent_message_chunk": {
|
|
39
|
+
const delta = readText(update.content);
|
|
40
|
+
return delta ? { type: "text", delta } : null;
|
|
41
|
+
}
|
|
42
|
+
case "agent_thought_chunk": {
|
|
43
|
+
const text = readText(update.content);
|
|
44
|
+
return { type: "activity", tool: "thinking", summary: truncate(text, 200) };
|
|
45
|
+
}
|
|
46
|
+
case "tool_call":
|
|
47
|
+
case "tool_call_update":
|
|
48
|
+
case "tool_start":
|
|
49
|
+
case "tool_complete": {
|
|
50
|
+
const tool = str(update.title) || str(update.kind) || str(update.toolName) || "tool";
|
|
51
|
+
const status = str(update.status);
|
|
52
|
+
const summary = [str(update.title) || tool, status].filter(Boolean).join(" · ");
|
|
53
|
+
return { type: "activity", tool, summary };
|
|
54
|
+
}
|
|
55
|
+
case "plan":
|
|
56
|
+
case "plan_update":
|
|
57
|
+
return { type: "activity", tool: "plan", summary: summarizePlan(update) };
|
|
58
|
+
case "usage_update":
|
|
59
|
+
case "user_message_chunk":
|
|
60
|
+
return null;
|
|
61
|
+
default:
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function toPairs(obj) {
|
|
66
|
+
if (!obj || typeof obj !== "object")
|
|
67
|
+
return undefined;
|
|
68
|
+
const out = Object.entries(obj).map(([name, value]) => ({
|
|
69
|
+
name,
|
|
70
|
+
value: String(value),
|
|
71
|
+
}));
|
|
72
|
+
return out.length ? out : undefined;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* daemon 的 `mcpConfig`(claude `--mcp-config` 形状:`{mcpServers:{name:{type,url,headers}|{command,args,env}}}`)
|
|
76
|
+
* → ACP `session/new` 的 `mcpServers` 数组(F2.6)。
|
|
77
|
+
*
|
|
78
|
+
* **knowledge token 透传与 claude 对齐**:daemon 给 claude 和 hermes 两个 driver 的是**同一个** mcpConfig JSON
|
|
79
|
+
* (见 agent-bridge/src/index.ts cc_turn:知识 MCP = `{type:"http", url, headers:{Authorization:"Bearer <turnToken>"}}`)。
|
|
80
|
+
* claude 经 `--mcp-config` 注入;hermes 在此转成 ACP `mcpServers`,token 原样落到 ACP http server 的 `headers`
|
|
81
|
+
* (或 stdio server 的 `env`)。Mosse 不在此处生成/改写 token —— 只搬运 daemon 已组好的形状。
|
|
82
|
+
*
|
|
83
|
+
* 形状判别:
|
|
84
|
+
* - http / sse transport:有 `type:"http"|"sse"` 或仅有 `url`(claude http 配置必带 url);headers → ACP `{name,value}[]`。
|
|
85
|
+
* - stdio transport:有 `command`;`args` 透传、`env`(可携带 token,如 `*_API_KEY`/`MOSSE_KNOWLEDGE_TOKEN`)→ `{name,value}[]`。
|
|
86
|
+
* - 既无 url 也无 command 的坏项跳过(不注入坏 server)。
|
|
87
|
+
*/
|
|
88
|
+
export function mcpConfigToAcpServers(mcpConfig) {
|
|
89
|
+
if (!mcpConfig)
|
|
90
|
+
return undefined;
|
|
91
|
+
let parsed;
|
|
92
|
+
try {
|
|
93
|
+
parsed = JSON.parse(mcpConfig);
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
const servers = parsed?.mcpServers;
|
|
99
|
+
if (!servers || typeof servers !== "object")
|
|
100
|
+
return undefined;
|
|
101
|
+
const out = [];
|
|
102
|
+
for (const [name, raw] of Object.entries(servers)) {
|
|
103
|
+
const c = (raw ?? {});
|
|
104
|
+
const url = str(c.url);
|
|
105
|
+
const command = typeof c.command === "string" ? c.command : "";
|
|
106
|
+
// http / sse:显式 type,或缺 type 但有 url(且非 stdio)→ 按 http 处理。
|
|
107
|
+
if (c.type === "http" || c.type === "sse" || (url && !command)) {
|
|
108
|
+
if (!url)
|
|
109
|
+
continue; // http/sse 必带 url,否则是坏配置 → 跳过。
|
|
110
|
+
const type = c.type === "sse" ? "sse" : "http";
|
|
111
|
+
out.push({ type, name, url, headers: toPairs(c.headers) });
|
|
112
|
+
}
|
|
113
|
+
else if (command) {
|
|
114
|
+
// stdio:command + args + env(env 可带 token)。
|
|
115
|
+
out.push({
|
|
116
|
+
name,
|
|
117
|
+
command,
|
|
118
|
+
args: Array.isArray(c.args) ? c.args : undefined,
|
|
119
|
+
env: toPairs(c.env),
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
// 既无 url 也无 command:跳过。
|
|
123
|
+
}
|
|
124
|
+
return out.length ? out : undefined;
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=hermes-map.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hermes-map.js","sourceRoot":"","sources":["../../src/drivers/hermes-map.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { Readable, Writable } from "node:stream";
|
|
2
|
+
import type { AgentTurn, CliDriver } from "./types.js";
|
|
3
|
+
/** spawn 出的子进程最小形状(node ChildProcess 满足此结构 → 默认实现直接用)。 */
|
|
4
|
+
export interface HermesChild {
|
|
5
|
+
stdin: Writable | null;
|
|
6
|
+
stdout: Readable | null;
|
|
7
|
+
stderr: Readable | null;
|
|
8
|
+
killed: boolean;
|
|
9
|
+
kill(signal?: NodeJS.Signals | number): boolean;
|
|
10
|
+
on(event: string, listener: (...args: unknown[]) => void): unknown;
|
|
11
|
+
}
|
|
12
|
+
export type SpawnHermes = (bin: string, args: string[], opts: {
|
|
13
|
+
cwd: string;
|
|
14
|
+
env: NodeJS.ProcessEnv;
|
|
15
|
+
}) => HermesChild;
|
|
16
|
+
/** 写隔离目录所需的 fs 操作(可注入,便于单测不碰真盘)。 */
|
|
17
|
+
export interface HermesHomeFs {
|
|
18
|
+
mkdirSync(p: string, opts: {
|
|
19
|
+
recursive: boolean;
|
|
20
|
+
}): void;
|
|
21
|
+
existsSync(p: string): boolean;
|
|
22
|
+
symlinkSync(target: string, path: string): void;
|
|
23
|
+
copyFileSync(src: string, dst: string): void;
|
|
24
|
+
writeFileSync(p: string, data: string, opts?: {
|
|
25
|
+
mode?: number;
|
|
26
|
+
}): void;
|
|
27
|
+
rmSync(p: string, opts?: {
|
|
28
|
+
force?: boolean;
|
|
29
|
+
}): void;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* 准备 per-agent 的隔离 HERMES_HOME:
|
|
33
|
+
* 1. 建目录。
|
|
34
|
+
* 2. **配置继承**:把用户真实 `~/.hermes/config.yaml` + `.env`(M1 写的 LLM 配置)**symlink** 进隔离目录
|
|
35
|
+
* —— LLM 配置保持单一真相源(用户重配即时反映、无双写漂移),而 state.db / session 留隔离目录独立(消除多 agent 串味)。
|
|
36
|
+
* symlink 不可用(如某些 FS / Windows)时退回 copy。
|
|
37
|
+
* 3. F2.3 system prompt:把 systemPromptAppend 写进隔离目录的 `AGENTS.md`(Hermes 启动读 rules),幂等覆盖。
|
|
38
|
+
*/
|
|
39
|
+
export declare function prepareHermesHome(opts: {
|
|
40
|
+
homeDir: string;
|
|
41
|
+
userHermesDir: string;
|
|
42
|
+
systemPromptAppend?: string;
|
|
43
|
+
fs?: HermesHomeFs;
|
|
44
|
+
}): void;
|
|
45
|
+
export interface HermesDeps {
|
|
46
|
+
spawn: SpawnHermes;
|
|
47
|
+
/** 解析 hermes 绝对路径(找不到返回 null)。 */
|
|
48
|
+
resolveBin(): string | null;
|
|
49
|
+
/** 构造子进程 env(剥 daemon 机密 + 合并 inject 白名单 + 补 PATH)。 */
|
|
50
|
+
buildEnv(inject?: Record<string, string>): NodeJS.ProcessEnv;
|
|
51
|
+
/** 准备隔离 HERMES_HOME + 写 AGENTS.md。 */
|
|
52
|
+
prepareHome(opts: {
|
|
53
|
+
homeDir: string;
|
|
54
|
+
userHermesDir: string;
|
|
55
|
+
systemPromptAppend?: string;
|
|
56
|
+
}): void;
|
|
57
|
+
/** 解析该 turn 的隔离目录。 */
|
|
58
|
+
resolveHome(turn: AgentTurn): string;
|
|
59
|
+
/** 用户真实 hermes 配置目录(继承 LLM 配置的源)。 */
|
|
60
|
+
userHermesDir: string;
|
|
61
|
+
/** 无事件多久判 idle 取消(F2.8)。 */
|
|
62
|
+
idleTimeoutMs: number;
|
|
63
|
+
}
|
|
64
|
+
/** 用注入依赖造一个 hermes driver(生产用 defaultDeps;测试传 mock spawn/fs)。 */
|
|
65
|
+
export declare function createHermesDriver(deps: HermesDeps): CliDriver;
|
|
66
|
+
export declare const hermesDriver: CliDriver;
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
// Hermes CLI driver:通过 ACP(`hermes acp` = `python -m acp_adapter`)驱动 Hermes 跑一轮 agent 回合。
|
|
2
|
+
// 实现 CliDriver(F2.2 + F2.2a + F2.3 + F2.4 + F2.8)。设计见 docs/hermes-engine-adaptation.md §5.3/§9。
|
|
3
|
+
//
|
|
4
|
+
// 与 claude driver 的异同:
|
|
5
|
+
// - 同:per-turn spawn 子进程、stdin/stdout 协议、stderr 仅日志、流式 onEvent、返回 {text,sessionId}。
|
|
6
|
+
// - 异:协议是 ACP JSON-RPC(非 stream-json);system prompt 无协议字段 → 写隔离目录 AGENTS.md(F2.3);
|
|
7
|
+
// per-agent HERMES_HOME 隔离(F2.3/D5)+ symlink 用户 LLM 配置继承;支持 abort/idle 取消(F2.8)。
|
|
8
|
+
import { spawn as spawnNode } from "node:child_process";
|
|
9
|
+
import { createHash } from "node:crypto";
|
|
10
|
+
import { copyFileSync, existsSync, mkdirSync, rmSync, symlinkSync, writeFileSync } from "node:fs";
|
|
11
|
+
import { homedir } from "node:os";
|
|
12
|
+
import { dirname, join } from "node:path";
|
|
13
|
+
import { AcpClient } from "../acp/client.js";
|
|
14
|
+
import { buildSpawnEnv } from "./env.js";
|
|
15
|
+
import { mapSessionUpdate, mcpConfigToAcpServers } from "./hermes-map.js";
|
|
16
|
+
import { defaultResolveDeps, resolveBin } from "./resolve.js";
|
|
17
|
+
const HERMES_BIN = process.env.MOSSE_HERMES_BIN ?? "hermes";
|
|
18
|
+
const NODE_DIR = dirname(process.execPath);
|
|
19
|
+
const DEFAULT_IDLE_MS = Number(process.env.MOSSE_HERMES_IDLE_MS) || 120_000;
|
|
20
|
+
const realFs = {
|
|
21
|
+
mkdirSync,
|
|
22
|
+
existsSync,
|
|
23
|
+
symlinkSync,
|
|
24
|
+
copyFileSync,
|
|
25
|
+
writeFileSync,
|
|
26
|
+
rmSync,
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* 准备 per-agent 的隔离 HERMES_HOME:
|
|
30
|
+
* 1. 建目录。
|
|
31
|
+
* 2. **配置继承**:把用户真实 `~/.hermes/config.yaml` + `.env`(M1 写的 LLM 配置)**symlink** 进隔离目录
|
|
32
|
+
* —— LLM 配置保持单一真相源(用户重配即时反映、无双写漂移),而 state.db / session 留隔离目录独立(消除多 agent 串味)。
|
|
33
|
+
* symlink 不可用(如某些 FS / Windows)时退回 copy。
|
|
34
|
+
* 3. F2.3 system prompt:把 systemPromptAppend 写进隔离目录的 `AGENTS.md`(Hermes 启动读 rules),幂等覆盖。
|
|
35
|
+
*/
|
|
36
|
+
export function prepareHermesHome(opts) {
|
|
37
|
+
const fs = opts.fs ?? realFs;
|
|
38
|
+
fs.mkdirSync(opts.homeDir, { recursive: true });
|
|
39
|
+
for (const name of ["config.yaml", ".env"]) {
|
|
40
|
+
const src = join(opts.userHermesDir, name);
|
|
41
|
+
const dst = join(opts.homeDir, name);
|
|
42
|
+
if (!fs.existsSync(src))
|
|
43
|
+
continue;
|
|
44
|
+
try {
|
|
45
|
+
fs.rmSync(dst, { force: true }); // 刷新:删旧链接/拷贝,保证指向当前用户配置。
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
// 不存在即可忽略。
|
|
49
|
+
}
|
|
50
|
+
try {
|
|
51
|
+
fs.symlinkSync(src, dst);
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
fs.copyFileSync(src, dst); // symlink 失败兜底拷贝。
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// 隔离目录的 AGENTS.md 完全由我们托管:有则写、无则清空(避免上一轮 system prompt 残留串味)。
|
|
58
|
+
fs.writeFileSync(join(opts.homeDir, "AGENTS.md"), opts.systemPromptAppend ?? "", { mode: 0o600 });
|
|
59
|
+
}
|
|
60
|
+
/** per-agent HERMES_HOME 默认路径:优先 turn.agentHome(理想来源=daemon 传);否则由 cwd 稳定派生。 */
|
|
61
|
+
function defaultResolveHome(turn) {
|
|
62
|
+
const explicit = turn.agentHome?.trim();
|
|
63
|
+
if (explicit)
|
|
64
|
+
return explicit;
|
|
65
|
+
const base = process.env.MOSSE_HERMES_HOMES_DIR?.trim() || join(homedir(), ".mosse", "hermes-homes");
|
|
66
|
+
const key = createHash("sha256").update(turn.cwd).digest("hex").slice(0, 16);
|
|
67
|
+
return join(base, key);
|
|
68
|
+
}
|
|
69
|
+
function defaultDeps() {
|
|
70
|
+
return {
|
|
71
|
+
spawn: (bin, args, opts) => spawnNode(bin, args, { cwd: opts.cwd, env: opts.env, stdio: ["pipe", "pipe", "pipe"] }),
|
|
72
|
+
resolveBin: () => resolveBin(HERMES_BIN, defaultResolveDeps(buildSpawnEnv({ base: process.env, nodeDir: NODE_DIR }))),
|
|
73
|
+
buildEnv: (inject) => buildSpawnEnv({ base: process.env, inject, nodeDir: NODE_DIR }),
|
|
74
|
+
prepareHome: (o) => prepareHermesHome(o),
|
|
75
|
+
resolveHome: defaultResolveHome,
|
|
76
|
+
// HERMES_HOME 在子进程里被我们覆盖为隔离目录;用户真实配置仍在原 HERMES_HOME 或 ~/.hermes。
|
|
77
|
+
userHermesDir: process.env.HERMES_HOME?.trim() || join(homedir(), ".hermes"),
|
|
78
|
+
idleTimeoutMs: DEFAULT_IDLE_MS,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
/** 杀子进程并保证不留僵尸:SIGTERM → 2s 内未退则 SIGKILL(node 自动 reap 已退进程)。 */
|
|
82
|
+
function makeKiller(child) {
|
|
83
|
+
let exited = false;
|
|
84
|
+
child.on("exit", () => {
|
|
85
|
+
exited = true;
|
|
86
|
+
});
|
|
87
|
+
child.on("close", () => {
|
|
88
|
+
exited = true;
|
|
89
|
+
});
|
|
90
|
+
return () => {
|
|
91
|
+
if (exited || child.killed)
|
|
92
|
+
return;
|
|
93
|
+
try {
|
|
94
|
+
child.kill("SIGTERM");
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
// 进程已不存在即可忽略。
|
|
98
|
+
}
|
|
99
|
+
const t = setTimeout(() => {
|
|
100
|
+
if (!exited) {
|
|
101
|
+
try {
|
|
102
|
+
child.kill("SIGKILL");
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
// 同上。
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}, 2000);
|
|
109
|
+
t.unref?.();
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
/** 用注入依赖造一个 hermes driver(生产用 defaultDeps;测试传 mock spawn/fs)。 */
|
|
113
|
+
export function createHermesDriver(deps) {
|
|
114
|
+
return {
|
|
115
|
+
id: "hermes",
|
|
116
|
+
async detect() {
|
|
117
|
+
const bin = deps.resolveBin();
|
|
118
|
+
return bin ? { id: "hermes", bin } : null;
|
|
119
|
+
},
|
|
120
|
+
async run(turn, onEvent, signal) {
|
|
121
|
+
// F2.3/D5:先备好隔离 HERMES_HOME(含 LLM 配置继承 + AGENTS.md),Hermes 启动才读得到。
|
|
122
|
+
const homeDir = deps.resolveHome(turn);
|
|
123
|
+
deps.prepareHome({
|
|
124
|
+
homeDir,
|
|
125
|
+
userHermesDir: deps.userHermesDir,
|
|
126
|
+
systemPromptAppend: turn.systemPromptAppend,
|
|
127
|
+
});
|
|
128
|
+
const bin = deps.resolveBin() ?? HERMES_BIN;
|
|
129
|
+
const env = deps.buildEnv(turn.env);
|
|
130
|
+
env.HERMES_HOME = homeDir; // 隔离:state.db / session / rules 全落这里。
|
|
131
|
+
const child = deps.spawn(bin, ["acp"], { cwd: turn.cwd, env });
|
|
132
|
+
if (!child.stdin || !child.stdout) {
|
|
133
|
+
throw new Error("hermes acp: missing stdio pipes");
|
|
134
|
+
}
|
|
135
|
+
// stderr 仅日志,绝不混入协议帧。
|
|
136
|
+
child.stderr?.on("data", (d) => process.stderr.write(`[hermes stderr] ${String(d)}`));
|
|
137
|
+
const client = new AcpClient(child.stdout, child.stdin);
|
|
138
|
+
const killChild = makeKiller(child);
|
|
139
|
+
const mcpServers = mcpConfigToAcpServers(turn.mcpConfig);
|
|
140
|
+
const state = { text: "" };
|
|
141
|
+
let currentSessionId = turn.sessionId ?? null;
|
|
142
|
+
// ── F2.8 取消/超时:任一触发 → ACP cancel + kill,受控结束 race ──
|
|
143
|
+
let stopped = false;
|
|
144
|
+
let resolveStopped;
|
|
145
|
+
const stoppedPromise = new Promise((r) => {
|
|
146
|
+
resolveStopped = () => r("stopped");
|
|
147
|
+
});
|
|
148
|
+
let idleTimer;
|
|
149
|
+
function triggerStop() {
|
|
150
|
+
if (stopped)
|
|
151
|
+
return;
|
|
152
|
+
stopped = true;
|
|
153
|
+
try {
|
|
154
|
+
if (currentSessionId)
|
|
155
|
+
client.cancel(currentSessionId); // 通知 agent 取消进行中的回合。
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
// 子进程已挂即可忽略。
|
|
159
|
+
}
|
|
160
|
+
killChild();
|
|
161
|
+
resolveStopped();
|
|
162
|
+
}
|
|
163
|
+
function resetIdle() {
|
|
164
|
+
if (idleTimer)
|
|
165
|
+
clearTimeout(idleTimer);
|
|
166
|
+
idleTimer = setTimeout(triggerStop, deps.idleTimeoutMs);
|
|
167
|
+
idleTimer.unref?.();
|
|
168
|
+
}
|
|
169
|
+
resetIdle();
|
|
170
|
+
// ── F2.2a:session_update → CcEvent;text 累积成最终文本 ──
|
|
171
|
+
client.onSessionUpdate((n) => {
|
|
172
|
+
resetIdle(); // 有活动就续命,避免误判 idle。
|
|
173
|
+
const ev = mapSessionUpdate(n.update);
|
|
174
|
+
if (!ev)
|
|
175
|
+
return;
|
|
176
|
+
if (ev.type === "text")
|
|
177
|
+
state.text += ev.delta;
|
|
178
|
+
onEvent(ev);
|
|
179
|
+
});
|
|
180
|
+
const onAbort = () => triggerStop();
|
|
181
|
+
if (signal) {
|
|
182
|
+
if (signal.aborted)
|
|
183
|
+
triggerStop();
|
|
184
|
+
else
|
|
185
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
186
|
+
}
|
|
187
|
+
// ── ACP 主流程 ──
|
|
188
|
+
async function mainFlow() {
|
|
189
|
+
await client.initialize();
|
|
190
|
+
if (turn.sessionId) {
|
|
191
|
+
// F2.4 会话恢复:有 sessionId 走 resume,延续历史;失败则丢旧会话新开一个(对齐 claude driver)。
|
|
192
|
+
try {
|
|
193
|
+
await client.resumeSession({ sessionId: turn.sessionId, cwd: turn.cwd, mcpServers });
|
|
194
|
+
currentSessionId = turn.sessionId;
|
|
195
|
+
}
|
|
196
|
+
catch {
|
|
197
|
+
const r = await client.newSession({ cwd: turn.cwd, mcpServers });
|
|
198
|
+
currentSessionId = r.sessionId;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
const r = await client.newSession({ cwd: turn.cwd, mcpServers });
|
|
203
|
+
currentSessionId = r.sessionId;
|
|
204
|
+
}
|
|
205
|
+
if (!currentSessionId)
|
|
206
|
+
throw new Error("hermes acp: no session id");
|
|
207
|
+
// D6:Mosse 指定 model 则覆盖会话模型;否则用 Hermes 本地配置默认。
|
|
208
|
+
if (turn.model)
|
|
209
|
+
await client.setSessionModel(currentSessionId, turn.model);
|
|
210
|
+
await client.prompt({
|
|
211
|
+
sessionId: currentSessionId,
|
|
212
|
+
content: [{ type: "text", text: turn.prompt }],
|
|
213
|
+
});
|
|
214
|
+
return "done";
|
|
215
|
+
}
|
|
216
|
+
try {
|
|
217
|
+
// 自然完成 vs 取消/超时,谁先到都受控返回累积文本 + sessionId。
|
|
218
|
+
await Promise.race([mainFlow(), stoppedPromise]);
|
|
219
|
+
return { text: state.text.trim(), sessionId: currentSessionId };
|
|
220
|
+
}
|
|
221
|
+
finally {
|
|
222
|
+
if (idleTimer)
|
|
223
|
+
clearTimeout(idleTimer);
|
|
224
|
+
if (signal)
|
|
225
|
+
signal.removeEventListener("abort", onAbort);
|
|
226
|
+
killChild(); // 每轮 spawn / 每轮收;无僵尸。
|
|
227
|
+
}
|
|
228
|
+
},
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
export const hermesDriver = createHermesDriver(defaultDeps());
|
|
232
|
+
//# sourceMappingURL=hermes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hermes.js","sourceRoot":"","sources":["../../src/drivers/hermes.ts"],"names":[],"mappings":"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"}
|
package/dist/drivers/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
// 运行时分发:按 runtime id 选 driver。codex/gemini 之后在此注册(预留位)。
|
|
2
2
|
import { claudeDriver } from "./claude.js";
|
|
3
|
+
import { hermesDriver } from "./hermes.js";
|
|
3
4
|
const DRIVERS = {
|
|
4
5
|
[claudeDriver.id]: claudeDriver,
|
|
6
|
+
[hermesDriver.id]: hermesDriver, // Hermes(ACP driver,M2)
|
|
5
7
|
// "local:codex": codexDriver, // 未来
|
|
6
8
|
// "local:gemini": geminiDriver, // 未来
|
|
7
9
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/drivers/index.ts"],"names":[],"mappings":"AAAA,wDAAwD;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,MAAM,OAAO,GAA8B;IACzC,CAAC,YAAY,CAAC,EAAE,CAAC,EAAE,YAAY;IAC/B,uCAAuC;IACvC,uCAAuC;CACxC,CAAC;AAEF,sCAAsC;AACtC,MAAM,UAAU,SAAS,CAAC,EAAU;IAClC,OAAO,OAAO,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC;AAC7B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/drivers/index.ts"],"names":[],"mappings":"AAAA,wDAAwD;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,MAAM,OAAO,GAA8B;IACzC,CAAC,YAAY,CAAC,EAAE,CAAC,EAAE,YAAY;IAC/B,CAAC,YAAY,CAAC,EAAE,CAAC,EAAE,YAAY,EAAE,wBAAwB;IACzD,uCAAuC;IACvC,uCAAuC;CACxC,CAAC;AAEF,sCAAsC;AACtC,MAAM,UAAU,SAAS,CAAC,EAAU;IAClC,OAAO,OAAO,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC;AAC7B,CAAC"}
|
|
@@ -11,6 +11,9 @@ export interface ResolveDeps {
|
|
|
11
11
|
export declare function whichWith(env: NodeJS.ProcessEnv): (cmd: string) => string | null;
|
|
12
12
|
/** 登录 shell 兜底:`$SHELL -lc 'command -v <cmd>'`(固定命令名,白名单防注入,带超时)。 */
|
|
13
13
|
export declare function loginShellWhich(): (cmd: string) => string | null;
|
|
14
|
+
/** 通用 bin 解析:PATH → 已知绝对路径 → 登录 shell 兜底(无 Claude Desktop 特例)。找不到返回 null。
|
|
15
|
+
* 非 claude 的 CLI(如 hermes)用这个;claude 在其上再加 Desktop 兜底(resolveClaudeBin)。 */
|
|
16
|
+
export declare function resolveBin(cmd: string, deps: ResolveDeps): string | null;
|
|
14
17
|
/** 解析 claude 绝对路径:PATH → 已知路径 → 登录 shell → macOS Claude Desktop。找不到返回 null。 */
|
|
15
18
|
export declare function resolveClaudeBin(cmd: string, deps: ResolveDeps): string | null;
|
|
16
19
|
/** 生产默认 deps(用补全过 PATH 的 env 跑 which + 登录 shell 兜底)。 */
|
package/dist/drivers/resolve.js
CHANGED
|
@@ -50,6 +50,14 @@ function knownPaths(cmd, home) {
|
|
|
50
50
|
join(home, ".bun/bin", cmd),
|
|
51
51
|
];
|
|
52
52
|
}
|
|
53
|
+
/** 通用 bin 解析:PATH → 已知绝对路径 → 登录 shell 兜底(无 Claude Desktop 特例)。找不到返回 null。
|
|
54
|
+
* 非 claude 的 CLI(如 hermes)用这个;claude 在其上再加 Desktop 兜底(resolveClaudeBin)。 */
|
|
55
|
+
export function resolveBin(cmd, deps) {
|
|
56
|
+
return (deps.which(cmd) ??
|
|
57
|
+
knownPaths(cmd, deps.home).find((p) => deps.existsSync(p)) ??
|
|
58
|
+
deps.loginShellWhich?.(cmd) ??
|
|
59
|
+
null);
|
|
60
|
+
}
|
|
53
61
|
/** 解析 claude 绝对路径:PATH → 已知路径 → 登录 shell → macOS Claude Desktop。找不到返回 null。 */
|
|
54
62
|
export function resolveClaudeBin(cmd, deps) {
|
|
55
63
|
const onPath = deps.which(cmd);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/drivers/resolve.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/drivers/resolve.ts"],"names":[],"mappings":"AAAA,iDAAiD;AACjD,qCAAqC;AACrC,2EAA2E;AAC3E,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,uBAAuB,GAAG,gEAAgE,CAAC;AACjG,MAAM,qBAAqB,GAAG,iEAAiE,CAAC;AAYhG,+CAA+C;AAC/C,MAAM,UAAU,SAAS,CAAC,GAAsB;IAC9C,OAAO,CAAC,GAAG,EAAE,EAAE;QACb,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,YAAY,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1F,OAAO,GAAG,IAAI,IAAI,CAAC;QACrB,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,eAAe;IAC7B,OAAO,CAAC,GAAG,EAAE,EAAE;QACb,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;QAC/C,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,UAAU,CAAC;QAC9C,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,YAAY,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,cAAc,GAAG,EAAE,CAAC,EAAE;gBAC5D,QAAQ,EAAE,MAAM;gBAChB,OAAO,EAAE,IAAI;aACd,CAAC;iBACC,IAAI,EAAE;iBACN,KAAK,CAAC,IAAI,CAAC;iBACX,GAAG,EAAE,CAAC;YACT,OAAO,GAAG,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;QAC3C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED,oCAAoC;AACpC,SAAS,UAAU,CAAC,GAAW,EAAE,IAAY;IAC3C,OAAO;QACL,IAAI,CAAC,IAAI,EAAE,YAAY,EAAE,GAAG,CAAC;QAC7B,IAAI,CAAC,IAAI,EAAE,eAAe,EAAE,GAAG,CAAC;QAChC,qBAAqB,GAAG,EAAE;QAC1B,kBAAkB,GAAG,EAAE;QACvB,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,CAAC;KAC5B,CAAC;AACJ,CAAC;AAED;6EAC6E;AAC7E,MAAM,UAAU,UAAU,CAAC,GAAW,EAAE,IAAiB;IACvD,OAAO,CACL,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC;QACf,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAC1D,IAAI,CAAC,eAAe,EAAE,CAAC,GAAG,CAAC;QAC3B,IAAI,CACL,CAAC;AACJ,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,gBAAgB,CAAC,GAAW,EAAE,IAAiB;IAC7D,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAE1B,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IACzE,IAAI,KAAK;QAAE,OAAO,KAAK,CAAC;IAExB,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC,GAAG,CAAC,CAAC;IAC7C,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAE9B,IAAI,IAAI,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC/B,MAAM,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,uBAAuB,CAAC,EAAE,qBAAqB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAC3F,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CACnB,CAAC;QACF,IAAI,OAAO;YAAE,OAAO,OAAO,CAAC;IAC9B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,wDAAwD;AACxD,MAAM,UAAU,kBAAkB,CAAC,GAAsB;IACvD,OAAO;QACL,KAAK,EAAE,SAAS,CAAC,GAAG,CAAC;QACrB,UAAU;QACV,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,IAAI,EAAE,OAAO,EAAE;QACf,eAAe,EAAE,eAAe,EAAE;KACnC,CAAC;AACJ,CAAC"}
|
package/dist/drivers/types.d.ts
CHANGED
|
@@ -12,6 +12,12 @@ export interface AgentTurn {
|
|
|
12
12
|
env?: Record<string, string>;
|
|
13
13
|
/** MCP 配置 JSON 字符串(如知识服务);传则加 `--mcp-config <json>`。 */
|
|
14
14
|
mcpConfig?: string;
|
|
15
|
+
/**
|
|
16
|
+
* per-agent 的隔离配置根(Hermes 用作 `HERMES_HOME`,见 hermes.ts / docs §9.1 D5)。
|
|
17
|
+
* **理想来源**:daemon 传 `<DATA_DIR>/agents/<agentId>/.hermes-home`(与 agent 私有目录同源、跨重启稳定);
|
|
18
|
+
* 不传时 driver 用 cwd 派生稳定默认(不强依赖上游改动)。对 claude driver 无意义(忽略)。
|
|
19
|
+
*/
|
|
20
|
+
agentHome?: string;
|
|
15
21
|
}
|
|
16
22
|
/** 流式事件:文本增量 / 工具活动。 */
|
|
17
23
|
export type CcEvent = {
|
|
@@ -28,7 +34,7 @@ export interface TurnResult {
|
|
|
28
34
|
sessionId: string | null;
|
|
29
35
|
}
|
|
30
36
|
export interface DriverInfo {
|
|
31
|
-
/**
|
|
37
|
+
/** mosse runtime id,如 "local:claude-code"。 */
|
|
32
38
|
id: string;
|
|
33
39
|
/** 解析出的绝对可执行路径(M2 起带绝对路径)。 */
|
|
34
40
|
bin: string;
|
|
@@ -38,6 +44,10 @@ export interface CliDriver {
|
|
|
38
44
|
id: string;
|
|
39
45
|
/** 本机是否可用 + 解析路径;不可用返回 null(供 detectRuntimes 与 run 共用)。 */
|
|
40
46
|
detect(): Promise<DriverInfo | null>;
|
|
41
|
-
/**
|
|
42
|
-
|
|
47
|
+
/**
|
|
48
|
+
* 跑一轮,流式回调事件,最终返回全文 + sessionId。
|
|
49
|
+
* @param signal 可选取消信号(F2.8):abort → driver 取消进行中的回合并 kill 子进程,受控返回。
|
|
50
|
+
* 旧 driver(如 claude)实现可只接 `(turn, onEvent)`——结构化类型下省略尾参仍兼容本接口。
|
|
51
|
+
*/
|
|
52
|
+
run(turn: AgentTurn, onEvent: (ev: CcEvent) => void, signal?: AbortSignal): Promise<TurnResult>;
|
|
43
53
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 纯函数:合并写 config.yaml 的 `model:` 段。对标 Rust `merge_config_yaml`(逐行等价)。
|
|
3
|
+
* - 设置/更新 `model.default`、`model.provider`,有 base_url 则设 `model.base_url`。
|
|
4
|
+
* - 保留文件里其它所有内容(其它顶层段、model 段下未触及的子键、缩进、注释)。
|
|
5
|
+
* - 文件无 `model:` 段则在末尾创建最小段。
|
|
6
|
+
*/
|
|
7
|
+
export declare function mergeConfigYaml(existing: string, model: string, provider: string, baseUrl?: string): string;
|
|
8
|
+
/**
|
|
9
|
+
* 纯函数:合并写 .env。对标 Rust `merge_env`。
|
|
10
|
+
* - 每个 {name,value}:文件已有同名 KEY(含 `export ` 前缀)→ 覆盖其值(保留 `export `);否则追加。
|
|
11
|
+
* - 其它行(不相关 key、注释、空行)原样保留。
|
|
12
|
+
*/
|
|
13
|
+
export declare function mergeEnv(existing: string, pairs: {
|
|
14
|
+
name: string;
|
|
15
|
+
value: string;
|
|
16
|
+
}[]): string;
|
|
17
|
+
/** 写入结果:只回 ok + authReady(读回磁盘真相);绝不回显 key / 文件内容。 */
|
|
18
|
+
export interface WriteHermesConfigResult {
|
|
19
|
+
ok: boolean;
|
|
20
|
+
authReady: boolean;
|
|
21
|
+
error?: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* IO:合并写指定 HERMES_HOME 的 config.yaml + .env,.env chmod 0600,写后复用 hermes-detect 判 authReady。
|
|
25
|
+
* 对标 Rust `write_hermes_config`(但目录由调用方传入,本机/远程统一走此一份)。
|
|
26
|
+
* **绝不日志/返回 key**;失败返回 {ok:false,error}(不抛)。
|
|
27
|
+
*/
|
|
28
|
+
export declare function writeHermesConfigToDisk(hermesDir: string, opts: {
|
|
29
|
+
provider: string;
|
|
30
|
+
model: string;
|
|
31
|
+
apiKey?: string;
|
|
32
|
+
baseUrl?: string;
|
|
33
|
+
}): Promise<WriteHermesConfigResult>;
|