@nowcrew/daemon 0.5.13 → 0.5.15
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/README.md +57 -3
- package/dist/computer-cli.js +214 -0
- package/dist/computer-profile.js +195 -0
- package/dist/computer-service.js +358 -0
- package/dist/config.js +2 -1
- package/dist/console.js +10 -0
- package/dist/execution-backend.js +11 -0
- package/dist/execution-protocol.js +8 -0
- package/dist/execution-runner.js +17 -10
- package/dist/execution-supervisor.js +48 -5
- package/dist/execution-telemetry-journal.js +71 -0
- package/dist/i18n.js +25 -0
- package/dist/local-executor.js +5 -2
- package/dist/machine-info.js +25 -4
- package/dist/main.js +15 -0
- package/dist/normalize.js +11 -0
- package/dist/prompt.js +21 -9
- package/dist/runner.js +1 -0
- package/dist/runtime-capabilities.js +5 -0
- package/dist/runtimes/kimi-acp-runner.js +264 -0
- package/dist/runtimes/kimi.js +10 -0
- package/dist/serve.js +45 -8
- package/package.json +3 -2
package/dist/serve.js
CHANGED
|
@@ -8,7 +8,7 @@ import { randomUUID } from "node:crypto";
|
|
|
8
8
|
import { initSlog, dslog, setSlogDefaults, drainSpool, flushSlog } from "./slog.js";
|
|
9
9
|
import { mergeRunAgentResults, reportScheduledStartFailure, runAgent } from "./runner.js";
|
|
10
10
|
import { buildOriginDecisionRetryPrompt, buildScheduledPrompt } from "./prompt.js";
|
|
11
|
-
import { collectMachineHello, DAEMON_CAPABILITIES, EXECUTION_PROTOCOL } from "./machine-info.js";
|
|
11
|
+
import { collectMachineHello, DAEMON_CAPABILITIES, EXECUTION_PROTOCOL, } from "./machine-info.js";
|
|
12
12
|
import { listWorkspace, readWorkspaceFile } from "./workspace-fs.js";
|
|
13
13
|
import { listSkills } from "./skills.js";
|
|
14
14
|
import { inspectRaftWorkspace, importRaftWorkspace } from "./workspace-import.js";
|
|
@@ -18,8 +18,10 @@ import { formatDaemonLogLine } from "./log-format.js";
|
|
|
18
18
|
import { reportAgentRunComplete } from "./scheduled-run-report.js";
|
|
19
19
|
import { runWithOriginDecisionGuard } from "./origin-decision.js";
|
|
20
20
|
import { createExecutionJournal } from "./execution-journal.js";
|
|
21
|
+
import { createExecutionTelemetryJournal } from "./execution-telemetry-journal.js";
|
|
21
22
|
import { ExecutionRejectedSchema, ExecutionSnapshotSchema, LegacyAgentStartSchema, ServerToDaemonExecutionFrameSchema, } from "./execution-protocol.js";
|
|
22
23
|
import { hashExecutionSpec, runExecution, } from "./execution-runner.js";
|
|
24
|
+
import { executionBackendCapability } from "./execution-backend.js";
|
|
23
25
|
// normalize.ts 的活动种类 → activity 枚举
|
|
24
26
|
const ACTIVITY_MAP = {
|
|
25
27
|
init: "working", text: "thinking", reading: "reading", sending: "sending",
|
|
@@ -28,7 +30,7 @@ const ACTIVITY_MAP = {
|
|
|
28
30
|
};
|
|
29
31
|
export function buildControlPlaneUrl(serverUrl, machineToken, runtimePlatform = process.platform) {
|
|
30
32
|
const query = new URLSearchParams({ key: machineToken });
|
|
31
|
-
if (runtimePlatform
|
|
33
|
+
if (executionBackendCapability(runtimePlatform).supported) {
|
|
32
34
|
query.set("execution_min", String(EXECUTION_PROTOCOL.min));
|
|
33
35
|
query.set("execution_max", String(EXECUTION_PROTOCOL.max));
|
|
34
36
|
}
|
|
@@ -43,8 +45,9 @@ export function serve(config, opts = {}) {
|
|
|
43
45
|
let backoff = 1000;
|
|
44
46
|
const maxBackoff = opts.maxBackoffMs ?? 30_000;
|
|
45
47
|
const executionJournal = opts.execution?.journal ?? createExecutionJournal(config.agentsRoot);
|
|
48
|
+
const executionTelemetry = createExecutionTelemetryJournal(config.agentsRoot);
|
|
46
49
|
const executeProtocol = opts.execution?.runExecution ?? runExecution;
|
|
47
|
-
let
|
|
50
|
+
let detectedExecutionRuntimes = [];
|
|
48
51
|
let runtimeFacts = null;
|
|
49
52
|
const executionReady = executionJournal.reconcileAfterRestart().then(() => true, (error) => {
|
|
50
53
|
dslog("execution.recovery_failed", "execution journal 恢复失败", {
|
|
@@ -66,6 +69,26 @@ export function serve(config, opts = {}) {
|
|
|
66
69
|
}
|
|
67
70
|
catch { /* reconnect/sync replays durable lifecycle */ }
|
|
68
71
|
};
|
|
72
|
+
const reportExecutionFrame = async (frame) => {
|
|
73
|
+
if (frame.type === "execution:activity" || frame.type === "execution:console") {
|
|
74
|
+
try {
|
|
75
|
+
await executionTelemetry.append(frame);
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
dslog("execution.telemetry_journal_failed", "execution telemetry 持久化失败", {
|
|
79
|
+
level: "ERROR", execution_id: frame.executionId,
|
|
80
|
+
error_message: error.message,
|
|
81
|
+
});
|
|
82
|
+
throw error;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
safeExecutionSend(frame);
|
|
86
|
+
};
|
|
87
|
+
const replayExecutionTelemetry = async () => {
|
|
88
|
+
const frames = await executionTelemetry.replay();
|
|
89
|
+
for (const frame of frames)
|
|
90
|
+
safeExecutionSend(frame);
|
|
91
|
+
};
|
|
69
92
|
const snapshotEntry = (entry) => {
|
|
70
93
|
if ((entry.state === "completed" || entry.state === "interrupted") && entry.completion !== null) {
|
|
71
94
|
return { executionId: entry.executionId, state: entry.state, completion: entry.completion, updatedAt: entry.updatedAt };
|
|
@@ -238,7 +261,7 @@ export function serve(config, opts = {}) {
|
|
|
238
261
|
void drainSpool();
|
|
239
262
|
// 上报本机信息 (hostname/os/daemon 版本/已装 runtimes)
|
|
240
263
|
const helloPromise = collectMachineHello(config.agentsRoot, config.executionLimits);
|
|
241
|
-
runtimeFacts = helloPromise.then((hello) => hello.
|
|
264
|
+
runtimeFacts = helloPromise.then((hello) => hello.executionRuntimes, (error) => {
|
|
242
265
|
dslog("execution.runtime_detection_failed", "runtime 探测失败", {
|
|
243
266
|
level: "ERROR", error_message: error.message,
|
|
244
267
|
});
|
|
@@ -246,16 +269,21 @@ export function serve(config, opts = {}) {
|
|
|
246
269
|
});
|
|
247
270
|
void helloPromise
|
|
248
271
|
.then((hello) => {
|
|
249
|
-
|
|
272
|
+
detectedExecutionRuntimes = hello.executionRuntimes;
|
|
250
273
|
try {
|
|
251
274
|
ws?.send(JSON.stringify(hello));
|
|
252
|
-
log(`📤 已上报机器信息: ${hello.hostname} · ${hello.os} ·
|
|
275
|
+
log(`📤 已上报机器信息: ${hello.hostname} · ${hello.os} · installed=[${hello.runtimes.join(",")}] · executable=[${hello.executionRuntimes.join(",")}] · agents=[${hello.agentHandles.join(",")}]`);
|
|
253
276
|
}
|
|
254
277
|
catch { /* 非 OPEN,忽略 */ }
|
|
255
278
|
})
|
|
256
279
|
.catch(() => { });
|
|
257
280
|
opts.onOpen?.(ws);
|
|
258
281
|
void executionReady.then((ready) => ready ? sendSnapshot(`reconnect-${randomUUID()}`) : undefined);
|
|
282
|
+
void replayExecutionTelemetry().catch((error) => {
|
|
283
|
+
dslog("execution.telemetry_replay_failed", "execution telemetry 重放失败", {
|
|
284
|
+
level: "ERROR", error_message: error.message,
|
|
285
|
+
});
|
|
286
|
+
});
|
|
259
287
|
});
|
|
260
288
|
ws.on("message", async (data) => {
|
|
261
289
|
let decoded;
|
|
@@ -292,6 +320,15 @@ export function serve(config, opts = {}) {
|
|
|
292
320
|
await executionJournal.acknowledgeCompletion(frame.executionId).catch(() => { });
|
|
293
321
|
return;
|
|
294
322
|
}
|
|
323
|
+
if (frame.type === "execution:event-ack") {
|
|
324
|
+
await executionTelemetry.acknowledge(frame.executionId, frame.kind, frame.seq).catch((error) => {
|
|
325
|
+
dslog("execution.telemetry_ack_failed", "execution telemetry ACK 处理失败", {
|
|
326
|
+
level: "ERROR", execution_id: frame.executionId,
|
|
327
|
+
error_message: error.message,
|
|
328
|
+
});
|
|
329
|
+
});
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
295
332
|
if (frame.type === "execution:cancel") {
|
|
296
333
|
if (!knownExecutionHashes.has(frame.executionId)
|
|
297
334
|
&& !executionRuns.has(frame.executionId)
|
|
@@ -352,7 +389,7 @@ export function serve(config, opts = {}) {
|
|
|
352
389
|
let availableRuntimes;
|
|
353
390
|
try {
|
|
354
391
|
availableRuntimes = opts.execution?.availableRuntimes?.()
|
|
355
|
-
?? await (runtimeFacts ?? Promise.resolve(
|
|
392
|
+
?? await (runtimeFacts ?? Promise.resolve(detectedExecutionRuntimes));
|
|
356
393
|
}
|
|
357
394
|
catch (error) {
|
|
358
395
|
reservation.release();
|
|
@@ -373,7 +410,7 @@ export function serve(config, opts = {}) {
|
|
|
373
410
|
availableRuntimes,
|
|
374
411
|
...reservation.facts,
|
|
375
412
|
},
|
|
376
|
-
report:
|
|
413
|
+
report: reportExecutionFrame,
|
|
377
414
|
...(reservation.state === undefined ? {} : {
|
|
378
415
|
slot: { state: reservation.state, ready: reservation.ready },
|
|
379
416
|
}),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nowcrew/daemon",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.15",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "crew daemon — 运行在用户机器:拉起/管理 agent 进程,注入 crew CLI,归一化 runtime 事件",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -17,10 +17,11 @@
|
|
|
17
17
|
"access": "public"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
+
"@agentclientprotocol/sdk": "1.2.1",
|
|
20
21
|
"cross-spawn": "^7.0.6",
|
|
21
22
|
"ws": "^8",
|
|
22
23
|
"zod": "^3.23.0",
|
|
23
|
-
"@nowcrew/cli": "^0.4.
|
|
24
|
+
"@nowcrew/cli": "^0.4.7"
|
|
24
25
|
},
|
|
25
26
|
"devDependencies": {
|
|
26
27
|
"@types/cross-spawn": "^6.0.6",
|