@nowcrew/daemon 0.6.89 → 0.6.91-beta.1

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.
Files changed (116) hide show
  1. package/README.md +64 -3
  2. package/dist/agent-ability/materializer.js +21 -10
  3. package/dist/agent-environment-contract.js +55 -0
  4. package/dist/agent-environment-control.js +24 -0
  5. package/dist/agent-environment-execution.js +98 -0
  6. package/dist/agent-environments.js +275 -0
  7. package/dist/automatic-daemon-installer.js +49 -1
  8. package/dist/computer-main.js +18 -0
  9. package/dist/computer-profile.js +17 -4
  10. package/dist/computer-setup-client.js +318 -0
  11. package/dist/computer-setup-orchestration.js +203 -0
  12. package/dist/computer-setup.js +244 -0
  13. package/dist/config.js +30 -12
  14. package/dist/console-formatter.js +3 -3
  15. package/dist/console.js +15 -2
  16. package/dist/daemon-update-eligibility.js +1 -1
  17. package/dist/daemon-updater.js +2 -12
  18. package/dist/execution-journal.js +9 -6
  19. package/dist/execution-protocol.js +1 -0
  20. package/dist/execution-runner.js +13 -8
  21. package/dist/i18n.js +19 -0
  22. package/dist/list-models.js +12 -12
  23. package/dist/local-execution-lease.js +22 -0
  24. package/dist/local-executor.js +57 -84
  25. package/dist/local-memory/candidate.js +43 -0
  26. package/dist/local-memory/index-budget.js +8 -0
  27. package/dist/local-memory/inventory-cli.js +61 -0
  28. package/dist/local-memory/inventory-preview.js +159 -0
  29. package/dist/local-memory/inventory-source.js +159 -0
  30. package/dist/local-memory/pending-match.js +29 -0
  31. package/dist/local-memory/pending-query.js +100 -0
  32. package/dist/local-memory/pending-schema.js +29 -0
  33. package/dist/local-memory/pending-source.js +126 -0
  34. package/dist/local-memory/pending.js +34 -84
  35. package/dist/local-memory/prompt.js +19 -12
  36. package/dist/local-memory/read-cli.js +97 -12
  37. package/dist/local-memory/rollout.js +82 -0
  38. package/dist/local-memory/runtime.js +23 -17
  39. package/dist/local-memory/work-log-execution.js +31 -0
  40. package/dist/local-memory/work-log.js +58 -0
  41. package/dist/local-memory/write.js +27 -58
  42. package/dist/local-runtime-environment.js +50 -0
  43. package/dist/machine-environment-cache.js +147 -0
  44. package/dist/machine-environment-contract.js +10 -0
  45. package/dist/machine-environment-control.js +27 -0
  46. package/dist/machine-environment-policy.js +75 -0
  47. package/dist/machine-environment-process.js +110 -0
  48. package/dist/machine-info.js +70 -25
  49. package/dist/machine-runtime-environment.js +189 -0
  50. package/dist/machine-shell-environment-capture.js +135 -0
  51. package/dist/machine-windows-environment-capture.js +215 -0
  52. package/dist/machine-windows-environment-script.js +158 -0
  53. package/dist/main.js +4 -69
  54. package/dist/marketplace-command.js +21 -0
  55. package/dist/marketplace-controller.js +80 -0
  56. package/dist/marketplace-protocol.js +38 -0
  57. package/dist/marketplace-remote.js +48 -0
  58. package/dist/marketplace-runner.js +235 -0
  59. package/dist/marketplace-serve.js +41 -0
  60. package/dist/marketplace-source.js +103 -0
  61. package/dist/message-file-preview.js +246 -0
  62. package/dist/pre-admission-rejection.js +64 -0
  63. package/dist/project-skills/execution-adapter.js +3 -2
  64. package/dist/project-skills/runtime-launch.js +14 -0
  65. package/dist/provider-env.js +26 -15
  66. package/dist/runner.js +17 -4
  67. package/dist/runtime-environment-merge.js +16 -0
  68. package/dist/runtime-health-handler.js +10 -0
  69. package/dist/runtime-health.js +3 -1
  70. package/dist/runtime-path.js +22 -12
  71. package/dist/runtime-probe.js +35 -6
  72. package/dist/runtimes/acp-probe-transport.js +69 -0
  73. package/dist/runtimes/claude-models.js +20 -9
  74. package/dist/runtimes/deepseek-harness-launch.js +10 -0
  75. package/dist/runtimes/deepseek-harness-profile.js +92 -0
  76. package/dist/runtimes/deepseek-harness-runner.js +226 -0
  77. package/dist/runtimes/deepseek-harness.js +76 -15
  78. package/dist/runtimes/harness-probe-retry.js +42 -0
  79. package/dist/runtimes/hermes-models.js +2 -1
  80. package/dist/runtimes/kimi-acp-runner.js +78 -13
  81. package/dist/runtimes/opencode.js +2 -2
  82. package/dist/serve.js +88 -178
  83. package/dist/storage-identity.js +0 -3
  84. package/dist/storage-serve-adapter.js +6 -72
  85. package/dist/supervised-runtime.js +17 -2
  86. package/dist/token.js +0 -1
  87. package/dist/workspace-control-handler.js +27 -0
  88. package/dist/workspace-fs.js +66 -15
  89. package/dist/workspace.js +1 -1
  90. package/package.json +13 -12
  91. package/dist/codex-home-launch.js +0 -7
  92. package/dist/codex-home-mode-controller.js +0 -68
  93. package/dist/daemon-migration-controller.js +0 -211
  94. package/dist/daemon-migration-wiring.js +0 -22
  95. package/dist/runtimes/codex-home-migration-cli.js +0 -26
  96. package/dist/runtimes/codex-home-migration.js +0 -112
  97. package/dist/runtimes/codex-home.js +0 -236
  98. package/dist/storage-control.js +0 -212
  99. package/dist/storage-copy.js +0 -628
  100. package/dist/storage-credential-guard.js +0 -21
  101. package/dist/storage-doctor.js +0 -228
  102. package/dist/storage-manifest.js +0 -1027
  103. package/dist/storage-migration-controller.js +0 -440
  104. package/dist/storage-migration-manifest.js +0 -105
  105. package/dist/storage-migration-policy.js +0 -100
  106. package/dist/storage-runtime-controller.js +0 -381
  107. package/dist/storage-runtime-readiness.js +0 -241
  108. package/dist/storage-safe-fs.js +0 -302
  109. package/dist/storage-status-delivery.js +0 -224
  110. package/dist/storage-status-replay.js +0 -140
  111. package/dist/storage-target-confirmation.js +0 -129
  112. package/dist/storage-worker-command.js +0 -37
  113. package/dist/storage-worker-executor.js +0 -447
  114. package/dist/storage-worker-handoff.js +0 -151
  115. package/dist/storage-worker-operation.js +0 -294
  116. package/dist/storage-worker-status.js +0 -259
@@ -71,9 +71,10 @@ async function stopChild(child) {
71
71
  }
72
72
  export async function listHermesModels(options = {}) {
73
73
  const spawnProcess = options.spawnProcess ?? spawn;
74
+ const env = options.env ?? { ...process.env, PATH: augmentedPath() };
74
75
  const child = spawnProcess("hermes", ["acp"], {
75
76
  cwd: process.cwd(),
76
- env: { ...process.env, PATH: augmentedPath() },
77
+ env,
77
78
  stdio: ["pipe", "pipe", "pipe"],
78
79
  });
79
80
  if (child.stdin === null || child.stdout === null || child.stderr === null)
@@ -1,3 +1,6 @@
1
+ import { AcpProbeTransport } from "./acp-probe-transport.js";
2
+ import { randomUUID } from "node:crypto";
3
+ import { dslog } from "../slog.js";
1
4
  import { once } from "node:events";
2
5
  import { isAbsolute } from "node:path";
3
6
  import { parseArgs } from "node:util";
@@ -10,7 +13,12 @@ import { prepareThreadDelivery } from "../thread-input-delivery.js";
10
13
  import { startFirstProgressWatchdog } from "./progress-watchdog.js";
11
14
  import { assertKimiLegacyPromptFits, buildKimiArgs } from "./kimi.js";
12
15
  const ERROR_MESSAGE_CAP = 2_000;
13
- const PROBE_TIMEOUT_MS = 5_000;
16
+ // macOS launchd cold-starts ACP runtimes materially slower than an interactive
17
+ // shell. DeepSeek Harness was measured at ~4.4s before returning initialize
18
+ // under launchd, while the daemon also creates an isolated profile. Keep this
19
+ // bounded below the control-plane request budget, with the existing 1s/2s
20
+ // Harness retries providing the outer bound.
21
+ export const ACP_PROBE_TIMEOUT_MS = 10_000;
14
22
  function jsonLine(event) {
15
23
  if (process.stdout.write(`${JSON.stringify(event)}\n`))
16
24
  return Promise.resolve();
@@ -128,10 +136,10 @@ function deepSeekPermissionMode(permission) {
128
136
  return "workspace-write";
129
137
  return "danger-full-access";
130
138
  }
131
- function providerEnv(provider, permission) {
139
+ function providerEnv(provider, permission, env = process.env) {
132
140
  return provider === "deepseek-harness"
133
- ? { ...process.env, DSH_PERMISSION_MODE: deepSeekPermissionMode(permission) }
134
- : process.env;
141
+ ? { ...env, DSH_PERMISSION_MODE: deepSeekPermissionMode(permission) }
142
+ : env;
135
143
  }
136
144
  function providerDisplayName(provider) {
137
145
  if (provider === "deepseek-harness")
@@ -194,18 +202,48 @@ async function stopChild(child) {
194
202
  await closed;
195
203
  }
196
204
  }
205
+ export class AcpProbeCleanupError extends Error {
206
+ constructor() { super("ACP probe process cleanup unconfirmed"); this.name = "AcpProbeCleanupError"; }
207
+ }
197
208
  /** Probe the ACP transport without starting a session or forcing an optional interactive login flow. */
198
209
  export async function probeKimiAcp(options, spawnProcess = spawn) {
199
210
  const provider = options.provider ?? "kimi";
200
211
  const permission = options.effectivePermission ?? "sandboxed";
201
- const child = spawnProcess(options.bin, providerArgs(provider, options.configPath), {
202
- cwd: process.cwd(),
203
- // probe 在 daemon 自身 PATH 下运行,补上用户级 CLI 目录,与 which 探测保持一致。
204
- env: { ...providerEnv(provider, permission), PATH: augmentedPath() },
212
+ const probeId = options.probeId ?? randomUUID();
213
+ const started = performance.now();
214
+ const elapsed = () => Math.round(performance.now() - started);
215
+ const transport = new AcpProbeTransport(elapsed);
216
+ let spawnConfirmedMs;
217
+ let reason = "initializing", protocolVersion;
218
+ let stderrSeen = false;
219
+ const fields = () => ({ probe_id: probeId, runtime: provider, duration_ms: elapsed(),
220
+ ...transport.fields(), spawn_confirmed_ms: spawnConfirmedMs, child_pid: child.pid,
221
+ reason, protocol_version: protocolVersion, stderr_seen: stderrSeen, aborted: options.signal?.aborted ?? false });
222
+ dslog("execution.acp_probe_started", "ACP 探测开始", { probe_id: probeId, runtime: provider, node_version: process.version });
223
+ const sourceEnv = options.env ?? { ...process.env, PATH: augmentedPath() };
224
+ const launchEnv = options.launchEnv ?? providerEnv(provider, permission, sourceEnv);
225
+ const child = spawnProcess(options.bin, options.launchArgs ?? providerArgs(provider, options.configPath), {
226
+ cwd: options.launchCwd ?? process.cwd(),
227
+ // 显式 launchEnv 已准备好 PATH/HOME,不能二次补 PATH 或混入父进程环境。
228
+ env: launchEnv,
205
229
  stdio: ["pipe", "pipe", "pipe"],
206
230
  });
231
+ // spawn errors are emitted by ChildProcess, not its stdio streams. A missing
232
+ // launcher must fail admission, not become an uncaught daemon exception.
233
+ const spawnFailed = new Promise((resolve) => {
234
+ child.once("error", () => {
235
+ if (reason === "initializing")
236
+ reason = "spawn_error";
237
+ resolve(false);
238
+ });
239
+ });
240
+ child.once("spawn", () => {
241
+ spawnConfirmedMs = elapsed();
242
+ dslog("execution.acp_probe_spawned", "ACP 探测子进程已启动", fields());
243
+ });
207
244
  if (child.stdin === null || child.stdout === null || child.stderr === null)
208
245
  return false;
246
+ child.stderr.on("data", () => { stderrSeen = true; });
209
247
  child.stderr.resume();
210
248
  const app = client({ name: `nowcrew-daemon-${provider}-probe` })
211
249
  .onRequest(methods.client.session.requestPermission, () => ({
@@ -215,25 +253,37 @@ export async function probeKimiAcp(options, spawnProcess = spawn) {
215
253
  let timeout;
216
254
  let onAbort;
217
255
  try {
218
- const stream = ndJsonStream(Writable.toWeb(child.stdin), Readable.toWeb(child.stdout));
256
+ const stream = ndJsonStream(transport.writable(child.stdin), transport.readable(child.stdout));
219
257
  const connected = app.connectWith(stream, async (context) => {
220
- await context.request(methods.agent.initialize, {
258
+ transport.initializeRequested();
259
+ const initialized = await context.request(methods.agent.initialize, {
221
260
  protocolVersion: PROTOCOL_VERSION,
222
261
  clientCapabilities: {},
223
262
  clientInfo: { name: "nowcrew-daemon", version: "1" },
224
263
  });
225
- return true;
264
+ transport.initializeResponse();
265
+ protocolVersion = initialized.protocolVersion;
266
+ const ready = protocolVersion === PROTOCOL_VERSION;
267
+ if (reason === "initializing")
268
+ reason = ready ? "ready" : "protocol_mismatch";
269
+ dslog("execution.acp_probe_handshake", "ACP 握手结果", { ...fields(), ready });
270
+ return ready;
226
271
  });
227
272
  const result = await Promise.race([
228
273
  connected,
274
+ spawnFailed,
229
275
  new Promise((resolve) => {
230
276
  timeout = setTimeout(() => {
277
+ if (reason === "initializing")
278
+ reason = "timeout";
231
279
  void stopChild(child);
232
280
  resolve(false);
233
- }, PROBE_TIMEOUT_MS);
281
+ }, ACP_PROBE_TIMEOUT_MS);
234
282
  }),
235
283
  new Promise((resolve) => {
236
284
  onAbort = () => {
285
+ if (reason === "initializing")
286
+ reason = "aborted";
237
287
  void stopChild(child);
238
288
  resolve(false);
239
289
  };
@@ -246,6 +296,8 @@ export async function probeKimiAcp(options, spawnProcess = spawn) {
246
296
  return result;
247
297
  }
248
298
  catch {
299
+ if (reason === "initializing")
300
+ reason = options.signal?.aborted ? "aborted" : "transport_error";
249
301
  return false;
250
302
  }
251
303
  finally {
@@ -253,7 +305,20 @@ export async function probeKimiAcp(options, spawnProcess = spawn) {
253
305
  clearTimeout(timeout);
254
306
  if (onAbort !== undefined)
255
307
  options.signal?.removeEventListener("abort", onAbort);
256
- await stopChild(child);
308
+ dslog("execution.acp_probe_cleanup_started", "ACP 探测清理开始", fields());
309
+ let cleanupFinished = false;
310
+ try {
311
+ await stopChild(child);
312
+ cleanupFinished = true;
313
+ }
314
+ catch {
315
+ throw new AcpProbeCleanupError();
316
+ }
317
+ finally {
318
+ dslog("execution.acp_probe_finished", "ACP 探测结束", { ...fields(),
319
+ cleanup_finished: cleanupFinished, exit_code: child.exitCode, exit_signal: child.signalCode,
320
+ level: reason === "ready" && cleanupFinished ? "INFO" : "WARN" });
321
+ }
257
322
  }
258
323
  }
259
324
  export async function runKimiAcp(requestedOptions) {
@@ -11,7 +11,7 @@ const REQUIRED_RUN_FLAGS = [
11
11
  "--variant",
12
12
  "--session",
13
13
  ];
14
- export async function probeOpenCodeRun(signal) {
14
+ export async function probeOpenCodeRun(signal, env = { ...process.env, PATH: augmentedPath() }) {
15
15
  try {
16
16
  const { stdout, stderr } = await execFileP("opencode", ["run", "--help"], {
17
17
  shell: isWin(),
@@ -19,7 +19,7 @@ export async function probeOpenCodeRun(signal) {
19
19
  killSignal: "SIGKILL",
20
20
  maxBuffer: 1024 * 1024,
21
21
  signal,
22
- env: { ...process.env, PATH: augmentedPath() },
22
+ env,
23
23
  });
24
24
  const help = `${stdout}\n${stderr}`;
25
25
  return REQUIRED_RUN_FLAGS.every((flag) => help.includes(flag));