mosse-agent-bridge 0.1.4
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/attachments.d.ts +11 -0
- package/dist/attachments.js +30 -0
- package/dist/attachments.js.map +1 -0
- package/dist/claude.d.ts +9 -0
- package/dist/claude.js +42 -0
- package/dist/claude.js.map +1 -0
- package/dist/credentials.d.ts +24 -0
- package/dist/credentials.js +123 -0
- package/dist/credentials.js.map +1 -0
- package/dist/drivers/claude.d.ts +2 -0
- package/dist/drivers/claude.js +120 -0
- package/dist/drivers/claude.js.map +1 -0
- package/dist/drivers/env.d.ts +11 -0
- package/dist/drivers/env.js +34 -0
- package/dist/drivers/env.js.map +1 -0
- package/dist/drivers/index.d.ts +4 -0
- package/dist/drivers/index.js +12 -0
- package/dist/drivers/index.js.map +1 -0
- package/dist/drivers/resolve.d.ts +17 -0
- package/dist/drivers/resolve.js +81 -0
- package/dist/drivers/resolve.js.map +1 -0
- package/dist/drivers/stream-json.d.ts +18 -0
- package/dist/drivers/stream-json.js +61 -0
- package/dist/drivers/stream-json.js.map +1 -0
- package/dist/drivers/types.d.ts +43 -0
- package/dist/drivers/types.js +4 -0
- package/dist/drivers/types.js.map +1 -0
- package/dist/fs-exec.d.ts +15 -0
- package/dist/fs-exec.js +161 -0
- package/dist/fs-exec.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +395 -0
- package/dist/index.js.map +1 -0
- package/dist/memory.d.ts +16 -0
- package/dist/memory.js +47 -0
- package/dist/memory.js.map +1 -0
- package/dist/prompt.d.ts +5 -0
- package/dist/prompt.js +5 -0
- package/dist/prompt.js.map +1 -0
- package/package.json +36 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// moss daemon:出站连 server 的 /daemon,代表"这台主机"。一台主机可承载多个 agent。
|
|
3
|
+
// 上线时上报本机检测到的运行时(claude-code / codex…);领任务时按 task.runtime 调对应本地 CLI,用你的 plan。
|
|
4
|
+
// 用法:
|
|
5
|
+
// moss-daemon --server ws://localhost:3001/daemon --token <connect-token>
|
|
6
|
+
// (开发期:pnpm --filter mosse-agent-bridge start -- --server … --token …)
|
|
7
|
+
import { execFile } from "node:child_process";
|
|
8
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
9
|
+
import { homedir, hostname } from "node:os";
|
|
10
|
+
import { join } from "node:path";
|
|
11
|
+
import { promisify } from "node:util";
|
|
12
|
+
import { WebSocket } from "ws";
|
|
13
|
+
import { materializeAttachments } from "./attachments.js";
|
|
14
|
+
import { runClaude } from "./claude.js";
|
|
15
|
+
import { addToken, httpBaseFromWs, loadTokens, removeToken } from "./credentials.js";
|
|
16
|
+
import { getDriver } from "./drivers/index.js";
|
|
17
|
+
import { executeFsOp } from "./fs-exec.js";
|
|
18
|
+
import { agentSystemPrompt, ensureAgentDir } from "./memory.js";
|
|
19
|
+
const execFileAsync = promisify(execFile);
|
|
20
|
+
const DAEMON_VERSION = "0.1.0";
|
|
21
|
+
// 数据目录:这台机器上**所有 agent** 的私有目录(= cwd = 记忆区)+ 会话映射。固定不配置(参考 slock)。
|
|
22
|
+
// 每个 agent 的 cwd = <DATA_DIR>/agents/<agentId>/,按 agentId 默认分配、互不共享、跨会话持久。
|
|
23
|
+
// 不是沙箱:bypassPermissions 下 agent 用绝对路径仍能访问整机;真正隔离靠机器/VM。
|
|
24
|
+
const DATA_DIR = process.env.MOSSE_DATA_DIR ?? join(homedir(), ".mosse");
|
|
25
|
+
// 带时间戳的日志(本地时区,`2026-06-11 20:23:57` 格式),方便和 server 日志对时排查。
|
|
26
|
+
function ts() {
|
|
27
|
+
const d = new Date();
|
|
28
|
+
const p = (n) => String(n).padStart(2, "0");
|
|
29
|
+
return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())} ${p(d.getHours())}:${p(d.getMinutes())}:${p(d.getSeconds())}`;
|
|
30
|
+
}
|
|
31
|
+
function log(msg) {
|
|
32
|
+
console.log(`${ts()} [Daemon] ${msg}`);
|
|
33
|
+
}
|
|
34
|
+
function logErr(msg) {
|
|
35
|
+
console.error(`${ts()} [Daemon] ${msg}`);
|
|
36
|
+
}
|
|
37
|
+
/** WS 心跳:每 30s ping 一次,连续两次没 pong 视为掉线、主动断开触发重连(参考 Slock)。 */
|
|
38
|
+
const PING_INTERVAL_MS = 30_000;
|
|
39
|
+
// 每个 agent 的常驻 Claude Code 会话 id(agentId → sessionId)。
|
|
40
|
+
// **持久化**到数据目录 cc-sessions.json:daemon 重启也能恢复 resume 入口 → 不丢近场对话流。
|
|
41
|
+
const SESSIONS_FILE = join(DATA_DIR, "cc-sessions.json");
|
|
42
|
+
const ccSessions = new Map();
|
|
43
|
+
function loadSessions() {
|
|
44
|
+
try {
|
|
45
|
+
const raw = readFileSync(SESSIONS_FILE, "utf8");
|
|
46
|
+
for (const [k, v] of Object.entries(JSON.parse(raw))) {
|
|
47
|
+
ccSessions.set(k, v);
|
|
48
|
+
}
|
|
49
|
+
if (ccSessions.size > 0)
|
|
50
|
+
log(`Restored ${ccSessions.size} agent session mappings (memory resumable).`);
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
// 首次运行 / 文件不存在:忽略。
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function saveSessions() {
|
|
57
|
+
try {
|
|
58
|
+
mkdirSync(DATA_DIR, { recursive: true });
|
|
59
|
+
writeFileSync(SESSIONS_FILE, JSON.stringify(Object.fromEntries(ccSessions), null, 2));
|
|
60
|
+
}
|
|
61
|
+
catch (e) {
|
|
62
|
+
logErr(`Failed to persist session mappings: ${e instanceof Error ? e.message : e}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function parseArgs(argv) {
|
|
66
|
+
let server = process.env.MOSSE_DAEMON_SERVER ?? process.env.MOSSE_BRIDGE_SERVER ?? "";
|
|
67
|
+
// MOSSE_CONNECT_TOKEN 是「连接命令」(server connectCommand)下发的权威 env 名;
|
|
68
|
+
// MOSSE_DAEMON_TOKEN/MOSSE_BRIDGE_TOKEN 保留兼容旧脚本/桌面 --token 之外的入口。
|
|
69
|
+
let token = process.env.MOSSE_CONNECT_TOKEN ??
|
|
70
|
+
process.env.MOSSE_DAEMON_TOKEN ??
|
|
71
|
+
process.env.MOSSE_BRIDGE_TOKEN ??
|
|
72
|
+
"";
|
|
73
|
+
for (let i = 0; i < argv.length; i++) {
|
|
74
|
+
const a = argv[i];
|
|
75
|
+
const v = argv[i + 1];
|
|
76
|
+
if (a === "--server" && v) {
|
|
77
|
+
server = v;
|
|
78
|
+
i++;
|
|
79
|
+
}
|
|
80
|
+
else if (a === "--token" && v) {
|
|
81
|
+
token = v;
|
|
82
|
+
i++;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return { server, token };
|
|
86
|
+
}
|
|
87
|
+
/** 探测某个 CLI 是否可用(能跑 --version 不报 ENOENT)。 */
|
|
88
|
+
async function hasBin(bin) {
|
|
89
|
+
try {
|
|
90
|
+
await execFileAsync(bin, ["--version"], { timeout: 5000 });
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
catch (e) {
|
|
94
|
+
return e.code !== "ENOENT";
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/** claude-code 登录态:~/.claude/.credentials.json 或 ~/.claude.json(OAuth)存在即视为已登录。 */
|
|
98
|
+
function claudeAuthReady() {
|
|
99
|
+
const home = homedir();
|
|
100
|
+
return (existsSync(join(home, ".claude", ".credentials.json")) || existsSync(join(home, ".claude.json")));
|
|
101
|
+
}
|
|
102
|
+
/** M3.1:检测本机各引擎三态 {id, installed, driverReady, authReady}。driverReady=本 daemon 是否有该 driver。 */
|
|
103
|
+
async function detectRuntimes() {
|
|
104
|
+
const out = [];
|
|
105
|
+
// claude 走 driver 的健壮解析(which + Claude Desktop 兜底);codex 暂用简单探测(driver 未实现)。
|
|
106
|
+
// 裸 harness id(见 @mosse/shared harness-catalog);旧 "local:*" 前缀已退役。
|
|
107
|
+
if (await getDriver("claude-code")?.detect()) {
|
|
108
|
+
out.push({
|
|
109
|
+
id: "claude-code",
|
|
110
|
+
installed: true,
|
|
111
|
+
driverReady: true,
|
|
112
|
+
authReady: claudeAuthReady(),
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
if (await hasBin(process.env.MOSSE_CODEX_BIN ?? "codex")) {
|
|
116
|
+
// codex driver 未实现 → driverReady:false;登录态暂无法探测 → authReady:false。
|
|
117
|
+
out.push({ id: "codex", installed: true, driverReady: !!getDriver("codex"), authReady: false });
|
|
118
|
+
}
|
|
119
|
+
return out;
|
|
120
|
+
}
|
|
121
|
+
const USAGE = `mosse-agent-bridge — connect this computer to a moss workspace.
|
|
122
|
+
|
|
123
|
+
Get the connect command from the Mosse desktop app (Connect a machine → Another machine),
|
|
124
|
+
or from a fleet key's enroll snippet. Run it here.
|
|
125
|
+
|
|
126
|
+
Usage:
|
|
127
|
+
mosse-agent-bridge --server <wss-url>/daemon --token <connect-token>
|
|
128
|
+
|
|
129
|
+
Options:
|
|
130
|
+
--server <url> moss server daemon endpoint (e.g. wss://your-moss.example.com/daemon)
|
|
131
|
+
--token <t> connect token (mct_ bootstrap or msk_ per-attachment). Without it,
|
|
132
|
+
a saved token from ~/.mosse is used; if none, the bridge exits.
|
|
133
|
+
-h, --help show this help
|
|
134
|
+
|
|
135
|
+
Env: MOSSE_CONNECT_TOKEN (= --token), MOSSE_DAEMON_SERVER (= --server), MOSSE_DATA_DIR (default ~/.mosse)`;
|
|
136
|
+
// bun --compile 独立二进制:argv[0]=可执行文件、argv[1]=第一个参数(无 script 项);
|
|
137
|
+
// node/bun 跑源码:argv[0]=runtime、argv[1]=script、argv[2..]=参数。
|
|
138
|
+
// 统一 slice(1)(只去掉 runtime/可执行本身);parseArgs 是 flag 扫描,多一个非-flag 前缀(script 路径)无害。
|
|
139
|
+
const cliArgs = process.argv.slice(1);
|
|
140
|
+
if (cliArgs.includes("--help") || cliArgs.includes("-h")) {
|
|
141
|
+
console.log(USAGE);
|
|
142
|
+
process.exit(0);
|
|
143
|
+
}
|
|
144
|
+
const { server, token: explicitToken } = parseArgs(cliArgs);
|
|
145
|
+
if (!server) {
|
|
146
|
+
console.error(USAGE);
|
|
147
|
+
process.exit(2);
|
|
148
|
+
}
|
|
149
|
+
log(`Data dir (agent private dirs / memory / sessions): ${DATA_DIR}`);
|
|
150
|
+
loadSessions();
|
|
151
|
+
// 活跃连接数(永久停一条减一);归零=全被拒 → 进程非零退出。瞬断重连不减。
|
|
152
|
+
let activeConns = 0;
|
|
153
|
+
function connect(st) {
|
|
154
|
+
// token 走子协议 bearer(不进 URL → 不落服务端 access/APM/反代日志);对齐用户 WS。服务端读 Sec-WebSocket-Protocol。
|
|
155
|
+
const ws = st.token ? new WebSocket(server, ["bearer", st.token]) : new WebSocket(server);
|
|
156
|
+
let alive = true;
|
|
157
|
+
let heartbeat;
|
|
158
|
+
ws.on("open", async () => {
|
|
159
|
+
st.backoff = 500;
|
|
160
|
+
const runtimes = await detectRuntimes();
|
|
161
|
+
ws.send(JSON.stringify({
|
|
162
|
+
type: "hello",
|
|
163
|
+
os: `${process.platform} ${process.arch}`,
|
|
164
|
+
hostname: hostname(),
|
|
165
|
+
version: DAEMON_VERSION,
|
|
166
|
+
runtimes,
|
|
167
|
+
}));
|
|
168
|
+
log(`🔌 Connected. Harnesses: ${runtimes.map((r) => `${r.id}${r.authReady ? "✓" : ""}`).join(", ") || "(no claude/codex detected)"}`);
|
|
169
|
+
// 心跳:ping → 等 pong;连续 2 个周期没 pong 才判死(容忍偶发抖动/延迟),主动断开重连。
|
|
170
|
+
alive = true;
|
|
171
|
+
let missed = 0;
|
|
172
|
+
heartbeat = setInterval(() => {
|
|
173
|
+
if (alive) {
|
|
174
|
+
missed = 0;
|
|
175
|
+
}
|
|
176
|
+
else if (++missed >= 2) {
|
|
177
|
+
logErr("Heartbeat timeout (no pong x2); reconnecting…");
|
|
178
|
+
ws.terminate();
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
alive = false;
|
|
182
|
+
ws.ping();
|
|
183
|
+
}, PING_INTERVAL_MS);
|
|
184
|
+
});
|
|
185
|
+
ws.on("pong", () => {
|
|
186
|
+
alive = true;
|
|
187
|
+
if (process.env.MOSSE_WS_DEBUG)
|
|
188
|
+
log("← pong from server");
|
|
189
|
+
});
|
|
190
|
+
ws.on("message", async (raw) => {
|
|
191
|
+
let msg;
|
|
192
|
+
try {
|
|
193
|
+
msg = JSON.parse(raw.toString());
|
|
194
|
+
}
|
|
195
|
+
catch {
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
// 鉴权失败(app 层信号,优先于 close code):凭证对这个 server 无效。**仅停本连接**,其它挂载连接继续。
|
|
199
|
+
if (msg.type === "auth_error") {
|
|
200
|
+
const reason = msg.reason ?? "invalid";
|
|
201
|
+
if (st.isBootstrap) {
|
|
202
|
+
// bootstrap mct_ 被拒:过期 / 已用过(一次性)/ 此机已在别处连上 —— 都是预期内。不删凭证、不退进程。
|
|
203
|
+
logErr(`Bootstrap connect token rejected (${reason}). If this machine isn't connected yet, generate a fresh connect command. Other connections keep running.`);
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
// per-attachment token 被吊销:移除该条挂载凭证(其它连接不受影响)。
|
|
207
|
+
logErr(`Attachment credential rejected (${reason}); removed it. Other connections keep running.`);
|
|
208
|
+
removeToken(DATA_DIR, server, st.origToken);
|
|
209
|
+
}
|
|
210
|
+
st.reAuth = true; // close 时停掉本连接,不重连
|
|
211
|
+
ws.close();
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
if (msg.type === "registered") {
|
|
215
|
+
const c = msg.computer;
|
|
216
|
+
// 远程 lazy 连机:首连用的是 bootstrap connect token(mct_),服务端换发一把 per-attachment token(msk_)。
|
|
217
|
+
// 存盘 + 切换 → 后续重连/重启都用它(走 hash 鉴权),bootstrap 过期也不影响。
|
|
218
|
+
const issued = msg.token;
|
|
219
|
+
if (issued && issued !== st.token) {
|
|
220
|
+
addToken(DATA_DIR, server, issued);
|
|
221
|
+
st.token = issued;
|
|
222
|
+
st.origToken = issued;
|
|
223
|
+
st.isBootstrap = false; // 已换得 per-attachment token;后续重连/auth_error 按持久 token 处理(可删)
|
|
224
|
+
}
|
|
225
|
+
log(`✅ Bound to computer “${c.name}”. Waiting for tasks…`);
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
// 完整版 Claude Code(Agent SDK,常驻会话):最新一条消息 → 该 agent 的会话(resume)。
|
|
229
|
+
if (msg.type === "cc_turn") {
|
|
230
|
+
const t = msg;
|
|
231
|
+
log(`▶ cc_turn ${t.taskId} (agent=${t.agentId}): running Claude Code… ` +
|
|
232
|
+
`[knowledge=${t.knowledgeToken ? "on(mcp)" : "off"}, role=${t.systemAppend ? "yes" : "no"}]`);
|
|
233
|
+
try {
|
|
234
|
+
// 记忆目录始终建好(MEMORY.md/notes 的家);cwd = 用户设的工作目录(项目)或回退到记忆目录。
|
|
235
|
+
const memoryDir = ensureAgentDir(DATA_DIR, t.agentId);
|
|
236
|
+
const cwd = t.cwd?.trim() || memoryDir;
|
|
237
|
+
// M-V5 多模态:附件物化到 cwd/attachments/,prompt 末尾附本地路径供 CLI 读。
|
|
238
|
+
const prompt = t.prompt + materializeAttachments(cwd, t.attachments);
|
|
239
|
+
const driver = getDriver("claude-code");
|
|
240
|
+
if (!driver)
|
|
241
|
+
throw new Error("Harness claude-code unavailable (claude not detected)");
|
|
242
|
+
// 知识 MCP:用本轮 token + 自己的 server http base 配一个 HTTP MCP server(bearer)。
|
|
243
|
+
const mcpConfig = t.knowledgeToken
|
|
244
|
+
? JSON.stringify({
|
|
245
|
+
mcpServers: {
|
|
246
|
+
moss_knowledge: {
|
|
247
|
+
type: "http",
|
|
248
|
+
url: `${httpBaseFromWs(server)}/api/mcp/knowledge`,
|
|
249
|
+
headers: { Authorization: `Bearer ${t.knowledgeToken}` },
|
|
250
|
+
},
|
|
251
|
+
},
|
|
252
|
+
})
|
|
253
|
+
: undefined;
|
|
254
|
+
const baseAppend = agentSystemPrompt({
|
|
255
|
+
agentId: t.agentId,
|
|
256
|
+
hostname: hostname(),
|
|
257
|
+
os: `${process.platform} ${process.arch}`,
|
|
258
|
+
daemonVersion: DAEMON_VERSION,
|
|
259
|
+
cwd,
|
|
260
|
+
memoryDir,
|
|
261
|
+
});
|
|
262
|
+
const { text, sessionId } = await driver.run({
|
|
263
|
+
prompt,
|
|
264
|
+
sessionId: ccSessions.get(t.agentId),
|
|
265
|
+
cwd,
|
|
266
|
+
model: t.model ?? null,
|
|
267
|
+
systemPromptAppend: t.systemAppend ? `${baseAppend}\n\n${t.systemAppend}` : baseAppend,
|
|
268
|
+
mcpConfig,
|
|
269
|
+
},
|
|
270
|
+
// P2 流式:边跑边把文本增量 / 工具活动推回 server。
|
|
271
|
+
(ev) => {
|
|
272
|
+
if (ev.type === "text") {
|
|
273
|
+
ws.send(JSON.stringify({ type: "delta", taskId: t.taskId, text: ev.delta }));
|
|
274
|
+
}
|
|
275
|
+
else {
|
|
276
|
+
ws.send(JSON.stringify({
|
|
277
|
+
type: "activity",
|
|
278
|
+
taskId: t.taskId,
|
|
279
|
+
tool: ev.tool,
|
|
280
|
+
summary: ev.summary,
|
|
281
|
+
}));
|
|
282
|
+
}
|
|
283
|
+
});
|
|
284
|
+
if (sessionId && ccSessions.get(t.agentId) !== sessionId) {
|
|
285
|
+
ccSessions.set(t.agentId, sessionId);
|
|
286
|
+
saveSessions(); // resume 每轮会 fork 出新 session id → 落盘最新链头。
|
|
287
|
+
}
|
|
288
|
+
ws.send(JSON.stringify({ type: "done", taskId: t.taskId, text }));
|
|
289
|
+
log(`✓ cc_turn ${t.taskId} done (${text.length} chars, session=${sessionId ?? "?"})`);
|
|
290
|
+
}
|
|
291
|
+
catch (e) {
|
|
292
|
+
const error = e instanceof Error ? e.message : String(e);
|
|
293
|
+
ws.send(JSON.stringify({ type: "error", taskId: t.taskId, error }));
|
|
294
|
+
logErr(`✗ cc_turn ${t.taskId} failed: ${error}`);
|
|
295
|
+
}
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
// fs_op(M4):api:* agent 的工具循环在服务端,单次工具调用下发到这里在本机执行,回 fs_result。
|
|
299
|
+
// cwd 默认 = agent 私有目录;服务端可传 cwd 覆盖(指向真实工作目录,不框死,见 M4)。
|
|
300
|
+
if (msg.type === "fs_op") {
|
|
301
|
+
const t = msg;
|
|
302
|
+
try {
|
|
303
|
+
const cwd = t.cwd?.trim() || ensureAgentDir(DATA_DIR, t.agentId);
|
|
304
|
+
const output = await executeFsOp(cwd, t.op, t.args ?? {});
|
|
305
|
+
ws.send(JSON.stringify({ type: "fs_result", callId: t.callId, ok: true, output }));
|
|
306
|
+
if (process.env.MOSSE_WS_DEBUG)
|
|
307
|
+
log(`✓ fs_op ${t.op} (call=${t.callId})`);
|
|
308
|
+
}
|
|
309
|
+
catch (e) {
|
|
310
|
+
const error = e instanceof Error ? e.message : String(e);
|
|
311
|
+
ws.send(JSON.stringify({ type: "fs_result", callId: t.callId, ok: false, error }));
|
|
312
|
+
logErr(`✗ fs_op ${t.op} (call=${t.callId}) failed: ${error}`);
|
|
313
|
+
}
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
if (msg.type === "task") {
|
|
317
|
+
const task = msg;
|
|
318
|
+
log(`▶ task ${task.taskId} (${task.runtime}): calling local CLI…`);
|
|
319
|
+
try {
|
|
320
|
+
let text;
|
|
321
|
+
// task.runtime 是线协议字段(保留字段名兼容已发布 daemon);值已是裸 harness id。
|
|
322
|
+
if (task.runtime === "claude-code") {
|
|
323
|
+
text = await runClaude({
|
|
324
|
+
systemPrompt: task.systemPrompt,
|
|
325
|
+
messages: task.messages,
|
|
326
|
+
model: task.model,
|
|
327
|
+
env: task.env,
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
else {
|
|
331
|
+
throw new Error(`Unsupported runtime: ${task.runtime}`);
|
|
332
|
+
}
|
|
333
|
+
ws.send(JSON.stringify({ type: "done", taskId: task.taskId, text }));
|
|
334
|
+
log(`✓ task ${task.taskId} done (${text.length} chars)`);
|
|
335
|
+
}
|
|
336
|
+
catch (e) {
|
|
337
|
+
const error = e instanceof Error ? e.message : String(e);
|
|
338
|
+
ws.send(JSON.stringify({ type: "error", taskId: task.taskId, error }));
|
|
339
|
+
logErr(`✗ task ${task.taskId} failed: ${error}`);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
ws.on("close", (code) => {
|
|
344
|
+
if (heartbeat)
|
|
345
|
+
clearInterval(heartbeat);
|
|
346
|
+
// **只有确认的 app 层 auth_error(st.reAuth)才永久停本连接**(那里已按 bootstrap/msk_ 区分、必要时 removeToken)。
|
|
347
|
+
// 裸 4401 **不**永久停 —— 反代/瞬断也可能发 4401,当瞬时错误退避重连(误删/误退会害了有效连接);真无效 token 服务端会发 auth_error。
|
|
348
|
+
if (st.reAuth) {
|
|
349
|
+
activeConns--;
|
|
350
|
+
logErr("This connection was rejected (auth_error); stopped. Other connections continue.");
|
|
351
|
+
// 所有连接都永久停了(全被拒/吊销)→ 进程没活可干,非零退出(CLI/服务可感知失败)。
|
|
352
|
+
if (activeConns <= 0) {
|
|
353
|
+
logErr("All connections were rejected; nothing left to do.");
|
|
354
|
+
process.exit(1);
|
|
355
|
+
}
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
if (code === 4401)
|
|
359
|
+
logErr("Closed with 4401 (no auth_error); treating as transient, will retry.");
|
|
360
|
+
log(`Disconnected; reconnecting in ${st.backoff}ms…`);
|
|
361
|
+
setTimeout(() => connect(st), st.backoff);
|
|
362
|
+
st.backoff = Math.min(st.backoff * 2, 10_000);
|
|
363
|
+
});
|
|
364
|
+
ws.on("error", (e) => {
|
|
365
|
+
logErr(`ws error: ${e.message}`);
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
async function main() {
|
|
369
|
+
// 连机靠一次性 key:在 moss 桌面应用「连接电脑 → Another machine」拿连接命令到这台机器上跑。
|
|
370
|
+
const explicit = explicitToken?.trim() ?? "";
|
|
371
|
+
const saved = loadTokens(DATA_DIR, server);
|
|
372
|
+
// 连**所有**:持久 per-attachment token(重启韧性,走 hash)+ 本次显式给的(首连 / 连新 workspace 的 mct_)。去重。
|
|
373
|
+
// 关键:同机连第二个 workspace = 再跑一条带新 mct_ 的命令 → 新 mct_ 与已有持久 token **并存各连一条**,互不吞没。
|
|
374
|
+
// 显式 mct_ 若已消费/过期 → 那条 auth_error 自停(isBootstrap 分支),不删凭证、不影响其它连接。
|
|
375
|
+
const all = [...new Set([...saved, ...(explicit ? [explicit] : [])])];
|
|
376
|
+
if (all.length === 0) {
|
|
377
|
+
logErr("No connect token. Get a one-time connect command from the Mosse desktop app " +
|
|
378
|
+
"(Connect a machine → Another machine) and run it here, " +
|
|
379
|
+
"or pass MOSSE_CONNECT_TOKEN / --token.");
|
|
380
|
+
process.exit(1);
|
|
381
|
+
}
|
|
382
|
+
// 一台机一个桥进程 → 对每条 token 各开一条连接,独立重连、互不影响(M1 F1.8a)。
|
|
383
|
+
activeConns = all.length;
|
|
384
|
+
log(`Starting ${all.length} attachment connection(s) to ${server}.`);
|
|
385
|
+
for (const t of all)
|
|
386
|
+
connect({
|
|
387
|
+
token: t,
|
|
388
|
+
origToken: t,
|
|
389
|
+
backoff: 500,
|
|
390
|
+
reAuth: false,
|
|
391
|
+
isBootstrap: t.startsWith("mct_"),
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
void main();
|
|
395
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/memory.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** agent 的私有目录(= cwd = 记忆区):<dataDir>/agents/<agentId>/ */
|
|
2
|
+
export declare function agentDir(dataDir: string, agentId: string): string;
|
|
3
|
+
/** 首次建好私有目录骨架(目录 + notes/ + 空 MEMORY.md 索引)。返回该目录(用作 cwd)。 */
|
|
4
|
+
export declare function ensureAgentDir(dataDir: string, agentId: string): string;
|
|
5
|
+
export interface RuntimeContext {
|
|
6
|
+
agentId: string;
|
|
7
|
+
hostname: string;
|
|
8
|
+
os: string;
|
|
9
|
+
daemonVersion: string;
|
|
10
|
+
/** 本轮工作目录(cwd):用户为 agent 指定了工作目录就是那个项目,否则 = 私有记忆目录。 */
|
|
11
|
+
cwd: string;
|
|
12
|
+
/** 私有长期记忆目录(MEMORY.md / notes 所在,绝对路径)。可能 != cwd。 */
|
|
13
|
+
memoryDir: string;
|
|
14
|
+
}
|
|
15
|
+
/** 追加到 Claude Code 原生系统提示后:权威 Runtime Context + 工作目录/记忆规约。 */
|
|
16
|
+
export declare function agentSystemPrompt(ctx: RuntimeContext): string;
|
package/dist/memory.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// 每个 agent 一个**私有目录**(= 它的 cwd,也是长期记忆区),按 agentId 默认分配、互不共享、跨会话持久。
|
|
2
|
+
// 参考 slock:cwd = ~/.mosse/agents/<agentId>/;MEMORY.md 在 cwd 根 + notes/ 放细节,agent 直接相对路径读写。
|
|
3
|
+
// 不是沙箱:agent 用绝对路径仍能访问整机,项目路径记进记忆来定位(不靠"工作区"找项目)。
|
|
4
|
+
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
5
|
+
import { join } from "node:path";
|
|
6
|
+
const INDEX = "MEMORY.md";
|
|
7
|
+
/** agent 的私有目录(= cwd = 记忆区):<dataDir>/agents/<agentId>/ */
|
|
8
|
+
export function agentDir(dataDir, agentId) {
|
|
9
|
+
return join(dataDir, "agents", agentId);
|
|
10
|
+
}
|
|
11
|
+
/** 首次建好私有目录骨架(目录 + notes/ + 空 MEMORY.md 索引)。返回该目录(用作 cwd)。 */
|
|
12
|
+
export function ensureAgentDir(dataDir, agentId) {
|
|
13
|
+
const dir = agentDir(dataDir, agentId);
|
|
14
|
+
mkdirSync(join(dir, "notes"), { recursive: true });
|
|
15
|
+
const index = join(dir, INDEX);
|
|
16
|
+
if (!existsSync(index)) {
|
|
17
|
+
writeFileSync(index, "# 记忆索引\n\n(还没有记忆。把值得长期记住的事实写进 notes/,每条在这加一行:`- [标题](notes/文件.md) — 一句话`。)\n");
|
|
18
|
+
}
|
|
19
|
+
return dir;
|
|
20
|
+
}
|
|
21
|
+
/** 追加到 Claude Code 原生系统提示后:权威 Runtime Context + 工作目录/记忆规约。 */
|
|
22
|
+
export function agentSystemPrompt(ctx) {
|
|
23
|
+
const sep = ctx.cwd !== ctx.memoryDir; // 用户指定了独立的工作目录
|
|
24
|
+
const indexPath = sep ? `${ctx.memoryDir}/${INDEX}` : INDEX;
|
|
25
|
+
return `# Runtime Context(Moss 注入的权威信息,别从 hostname/cwd 推断身份)
|
|
26
|
+
- Agent ID: ${ctx.agentId}
|
|
27
|
+
- Hostname: ${ctx.hostname}
|
|
28
|
+
- OS: ${ctx.os}
|
|
29
|
+
- Daemon: v${ctx.daemonVersion}
|
|
30
|
+
- 工作目录(cwd): ${ctx.cwd}
|
|
31
|
+
- 私有记忆目录: ${ctx.memoryDir}
|
|
32
|
+
|
|
33
|
+
# 工作目录与长期记忆
|
|
34
|
+
${sep
|
|
35
|
+
? `你这轮的**工作目录(cwd)是用户为你指定的目录**:${ctx.cwd} —— 文件/命令默认在这里操作(用户问"工作目录"就是它)。
|
|
36
|
+
你的**长期记忆**在另一个私有目录:${ctx.memoryDir} —— 用这个**绝对路径**读写 \`MEMORY.md\` 与 \`notes/\`。`
|
|
37
|
+
: `用户没单独指定工作目录,所以你的当前目录(cwd)就是你的**私有记忆目录**:${ctx.cwd}。`}
|
|
38
|
+
这**不是沙箱**:你能用绝对路径访问这台机器上的其他文件(项目代码、~/ 下的配置等),需要时尽管去。
|
|
39
|
+
|
|
40
|
+
## 记忆怎么用(渐进式,别一次全读)
|
|
41
|
+
- **每轮开始**先读 \`${indexPath}\`(索引)回忆已知的事;**只有索引里某条相关**,才去读它指向的文件。绝不一次性把记忆全读进来。
|
|
42
|
+
- 值得长期记住的事(你负责的项目**及其绝对路径**、关键结论、对方的偏好与约定、踩过的坑),写成 markdown 存进记忆目录的 \`notes/\`,并在索引加一行指针。
|
|
43
|
+
- **项目不靠工作区找,靠记忆找**:第一次接触某项目,把它的绝对路径和概况记进 \`notes/project-<名>.md\`;之后再提到它,从记忆调出路径直接访问。
|
|
44
|
+
- 一条事实一个文件;写前先查索引避免重复,旧记忆错了就改正;索引太长就按主题拆。
|
|
45
|
+
- 这些读写自己用文件工具完成,不必征求许可,也不用在回复里报告"我记下了"——自然地记就好。`;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=memory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.js","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,2FAA2F;AAC3F,kDAAkD;AAClD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,KAAK,GAAG,WAAW,CAAC;AAE1B,2DAA2D;AAC3D,MAAM,UAAU,QAAQ,CAAC,OAAe,EAAE,OAAe;IACvD,OAAO,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;AAC1C,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,cAAc,CAAC,OAAe,EAAE,OAAe;IAC7D,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACvC,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACnD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC/B,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QACvB,aAAa,CACX,KAAK,EACL,8EAA8E,CAC/E,CAAC;IACJ,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAaD,8DAA8D;AAC9D,MAAM,UAAU,iBAAiB,CAAC,GAAmB;IACnD,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,KAAK,GAAG,CAAC,SAAS,CAAC,CAAC,eAAe;IACtD,MAAM,SAAS,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,SAAS,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;IAC5D,OAAO;cACK,GAAG,CAAC,OAAO;cACX,GAAG,CAAC,QAAQ;QAClB,GAAG,CAAC,EAAE;aACD,GAAG,CAAC,aAAa;eACf,GAAG,CAAC,GAAG;YACV,GAAG,CAAC,SAAS;;;EAIvB,GAAG;QACD,CAAC,CAAC,+BAA+B,GAAG,CAAC,GAAG;qBACvB,GAAG,CAAC,SAAS,+CAA+C;QAC7E,CAAC,CAAC,2CAA2C,GAAG,CAAC,GAAG,GACxD;;;;iBAIiB,SAAS;;;;gDAIsB,CAAC;AACjD,CAAC"}
|
package/dist/prompt.d.ts
ADDED
package/dist/prompt.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt.js","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"AAOA,MAAM,UAAU,WAAW,CAAC,QAA6B;IACvD,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAC/B,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAC/D,CAAC;IACF,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC;AAC7C,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mosse-agent-bridge",
|
|
3
|
+
"version": "0.1.4",
|
|
4
|
+
"description": "Mosse daemon — connect your computer to a Mosse workspace so agents can read/write files and run commands on it.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"mosse-agent-bridge": "dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"files": ["dist"],
|
|
10
|
+
"engines": {
|
|
11
|
+
"node": ">=20"
|
|
12
|
+
},
|
|
13
|
+
"publishConfig": {
|
|
14
|
+
"access": "public"
|
|
15
|
+
},
|
|
16
|
+
"keywords": ["mosse", "agent", "daemon", "ai"],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc -p tsconfig.build.json",
|
|
19
|
+
"start": "tsx src/index.ts",
|
|
20
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
21
|
+
"test": "node --import tsx --test 'src/**/*.test.ts'",
|
|
22
|
+
"smoke": "tsx scripts/smoke.ts",
|
|
23
|
+
"build:bin": "bun build ./src/index.ts --compile --target=bun-darwin-arm64 --outfile dist/mosse-host-aarch64-apple-darwin",
|
|
24
|
+
"build:bin:x64": "bun build ./src/index.ts --compile --target=bun-darwin-x64 --outfile dist/mosse-host-x86_64-apple-darwin",
|
|
25
|
+
"prepublishOnly": "rm -rf dist && pnpm build"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"ws": "^8.18.0"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@types/node": "^22.10.5",
|
|
32
|
+
"@types/ws": "^8.5.13",
|
|
33
|
+
"tsx": "^4.19.2",
|
|
34
|
+
"typescript": "^5.7.3"
|
|
35
|
+
}
|
|
36
|
+
}
|