@slock-ai/daemon 0.53.1-alpha.3 → 0.53.1-alpha.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.
@@ -723,6 +723,7 @@ var SERVER_CAPABILITY_MATRIX = {
723
723
  var RUNTIMES = [
724
724
  { id: "claude", displayName: "Claude Code", binary: "claude", supported: true },
725
725
  { id: "codex", displayName: "Codex CLI", binary: "codex", supported: true },
726
+ { id: "antigravity", displayName: "Antigravity CLI", binary: "agy", supported: true },
726
727
  { id: "kimi", displayName: "Kimi CLI", binary: "kimi", supported: true },
727
728
  { id: "copilot", displayName: "Copilot CLI", binary: "copilot", supported: true },
728
729
  { id: "cursor", displayName: "Cursor CLI", binary: "cursor-agent", supported: true },
@@ -832,8 +833,9 @@ function buildPrompt(config, variant, opts) {
832
833
  "- Use only the provided MCP tools for messaging \u2014 they are already available and ready.",
833
834
  `- Always claim a task via ${taskClaimCmd} before starting work on it. If the claim fails, move on to a different task.`
834
835
  ];
835
- const runtimeProfileControlStartupStep = config.runtimeProfileControl ? [
836
- "0. If this system prompt contains a **Runtime Profile Control** section, complete that runtime-control instruction first. Do not read MEMORY.md, check messages, or respond to inbox messages until the required runtime control action has succeeded."
836
+ const runtimeProfileControl = config.runtimeProfileControl?.kind === "daemon_release_notice" ? config.runtimeProfileControl : null;
837
+ const runtimeProfileControlStartupStep = runtimeProfileControl ? [
838
+ "0. If this system prompt contains a **Runtime Profile Control** section, read that notice first. It is informational only; no runtime control action or chat reply is required. Do not read MEMORY.md, check messages, or respond to inbox messages before reading it."
837
839
  ] : [];
838
840
  const startupSteps = isCli ? [
839
841
  ...runtimeProfileControlStartupStep,
@@ -1105,28 +1107,19 @@ ${startupSteps.join("\n")}`;
1105
1107
 
1106
1108
  ${opts.postStartupNotes.join("\n")}`;
1107
1109
  }
1108
- if (config.runtimeProfileControl) {
1109
- const control = config.runtimeProfileControl;
1110
+ if (runtimeProfileControl) {
1111
+ const control = runtimeProfileControl;
1110
1112
  prompt += `
1111
1113
 
1112
1114
  ## Runtime Profile Control
1113
1115
 
1114
1116
  `;
1115
- prompt += `This section is a trusted daemon runtime-control instruction. It overrides the normal startup sequence: complete this section before reading MEMORY.md, checking messages, or responding to inbox messages.
1117
+ prompt += `This section is a trusted daemon release notice. Read it before normal startup work; it does not require a runtime control action, chat reply, or migration acknowledgment.
1116
1118
 
1117
1119
  `;
1118
- if (control.kind === "migration") {
1119
- prompt += `You are currently in Runtime Profile migration. Before handling normal inbox messages, re-ground yourself in the new runtime context and then invoke the runtime control action \`${t("runtime_profile_migration_done")}\` with exactly this migration_key: \`${control.key}\`.
1120
-
1121
- `;
1122
- prompt += `Do not use ${sendCmd}, ${checkCmd}, or any chat reply as the migration acknowledgment. Normal inbox delivery is gated until the runtime control action succeeds.
1120
+ prompt += `Read the daemon release notice below before handling normal inbox messages. No chat reply is required for this notice.
1123
1121
 
1124
1122
  `;
1125
- } else {
1126
- prompt += `Read the daemon release notice below before handling normal inbox messages. No chat reply is required for this notice.
1127
-
1128
- `;
1129
- }
1130
1123
  prompt += control.message;
1131
1124
  }
1132
1125
  prompt += `
@@ -1367,30 +1360,85 @@ import { randomBytes } from "crypto";
1367
1360
  import http from "http";
1368
1361
  import { URL as URL2 } from "url";
1369
1362
  var registrations = /* @__PURE__ */ new Map();
1370
- var servers = /* @__PURE__ */ new Map();
1363
+ var proxyServerState = null;
1364
+ var proxyServerStartPromise = null;
1365
+ var proxyServerFactory = createProxyServer;
1371
1366
  var DECODED_RESPONSE_HEADERS = /* @__PURE__ */ new Set(["content-encoding", "content-length", "transfer-encoding"]);
1372
1367
  var LOCAL_HELD_CONTEXT_LIMIT = 3;
1373
- function allocatePort() {
1374
- return 43e3 + randomBytes(2).readUInt16BE(0) % 1e4;
1375
- }
1376
- function ensureServer(port) {
1377
- if (servers.has(port)) return;
1378
- const server = http.createServer((req, res) => {
1379
- void handleProxyRequest(req, res).catch((err) => {
1380
- logger.error(`[Agent Credential Proxy] unhandled local proxy error: ${err.message}`);
1381
- writeProxyFailureResponse(res, {
1382
- error: "failed to proxy local agent request",
1383
- code: "agent_proxy_failed",
1384
- detail: truncateProxyErrorMessage(err.message)
1368
+ var AGENT_CREDENTIAL_PROXY_HOST = "127.0.0.1";
1369
+ var AGENT_CREDENTIAL_PROXY_BIND_MAX_ATTEMPTS = 3;
1370
+ function createProxyRequestHandler() {
1371
+ return (req, res) => {
1372
+ void handleProxyRequest(req, res);
1373
+ };
1374
+ }
1375
+ function createProxyServer(handler) {
1376
+ return http.createServer(handler);
1377
+ }
1378
+ function listenOnLoopback(server) {
1379
+ return new Promise((resolve, reject) => {
1380
+ const onError = (err) => {
1381
+ server.off("listening", onListening);
1382
+ reject(err);
1383
+ };
1384
+ const onListening = () => {
1385
+ server.off("error", onError);
1386
+ const address = server.address();
1387
+ if (!address || typeof address.port !== "number") {
1388
+ reject(new Error("local proxy listen succeeded without a TCP port"));
1389
+ return;
1390
+ }
1391
+ resolve({
1392
+ server,
1393
+ proxyUrl: `http://${AGENT_CREDENTIAL_PROXY_HOST}:${address.port}`
1385
1394
  });
1386
- });
1387
- });
1388
- server.on("error", (err) => {
1389
- logger.warn(`[Agent Credential Proxy] local proxy on port ${port} failed: ${err.message}`);
1395
+ };
1396
+ server.once("error", onError);
1397
+ server.once("listening", onListening);
1398
+ server.listen(0, AGENT_CREDENTIAL_PROXY_HOST);
1390
1399
  });
1391
- server.listen(port, "127.0.0.1");
1392
- server.unref();
1393
- servers.set(port, server);
1400
+ }
1401
+ function closeServerBestEffort(server) {
1402
+ try {
1403
+ server.close();
1404
+ } catch {
1405
+ }
1406
+ }
1407
+ async function startProxyServer() {
1408
+ let lastError;
1409
+ for (let attempt = 1; attempt <= AGENT_CREDENTIAL_PROXY_BIND_MAX_ATTEMPTS; attempt += 1) {
1410
+ const server = proxyServerFactory(createProxyRequestHandler());
1411
+ try {
1412
+ const state = await listenOnLoopback(server);
1413
+ state.server.on("error", (err) => {
1414
+ logger.warn(`[Agent Credential Proxy] local proxy failed after bind: ${err.message}`);
1415
+ });
1416
+ state.server.unref();
1417
+ return state;
1418
+ } catch (err) {
1419
+ lastError = err;
1420
+ closeServerBestEffort(server);
1421
+ logger.warn(
1422
+ `[Agent Credential Proxy] local proxy bind attempt ${attempt}/${AGENT_CREDENTIAL_PROXY_BIND_MAX_ATTEMPTS} failed: ${err instanceof Error ? err.message : String(err)}`
1423
+ );
1424
+ }
1425
+ }
1426
+ const detail = lastError instanceof Error ? lastError.message : String(lastError ?? "unknown error");
1427
+ throw new Error(
1428
+ `Agent Credential Proxy local proxy failed to bind ${AGENT_CREDENTIAL_PROXY_HOST} after ${AGENT_CREDENTIAL_PROXY_BIND_MAX_ATTEMPTS} attempts: ${detail}`
1429
+ );
1430
+ }
1431
+ async function ensureServer() {
1432
+ if (proxyServerState) return proxyServerState;
1433
+ if (!proxyServerStartPromise) {
1434
+ proxyServerStartPromise = startProxyServer();
1435
+ }
1436
+ try {
1437
+ proxyServerState = await proxyServerStartPromise;
1438
+ return proxyServerState;
1439
+ } finally {
1440
+ proxyServerStartPromise = null;
1441
+ }
1394
1442
  }
1395
1443
  function responseHeadersForLocalProxy(upstream) {
1396
1444
  const headers = {};
@@ -1411,7 +1459,6 @@ async function handleProxyRequest(req, res) {
1411
1459
  }
1412
1460
  const method = req.method ?? "GET";
1413
1461
  let target;
1414
- let upstreamStatus = null;
1415
1462
  try {
1416
1463
  target = new URL2(req.url ?? "/", registration.serverUrl);
1417
1464
  const headers = new Headers();
@@ -1461,7 +1508,6 @@ async function handleProxyRequest(req, res) {
1461
1508
  // Required by undici when forwarding a Node stream.
1462
1509
  duplex: body ? "half" : void 0
1463
1510
  });
1464
- upstreamStatus = upstream.status;
1465
1511
  if (shouldBufferJsonResponse(upstream, target.pathname, registration)) {
1466
1512
  const responseText = await upstream.text();
1467
1513
  consumeVisibleResponse(registration, target, sendTarget, responseText);
@@ -1485,45 +1531,26 @@ async function handleProxyRequest(req, res) {
1485
1531
  res.end();
1486
1532
  }
1487
1533
  } catch (err) {
1488
- const failure = proxyFailureForError(method, target, res, upstreamStatus, err);
1534
+ const failure = proxyFailureForError(method, target, err);
1489
1535
  logger.warn(
1490
- `[Agent Credential Proxy] request failed (agent=${registration.agentId}, launch=${registration.launchId ?? "none"}, method=${failure.method}, path=${failure.pathname}, query_keys=${failure.queryKeys.join(",") || "none"}): ${failure.errorClass}: ${failure.errorMessage}`
1536
+ `[Agent Credential Proxy] request failed (agent=${registration.agentId}, launch=${registration.launchId ?? "none"}, method=${failure.method}, path=${failure.pathname}, query_keys=${failure.queryKeys.join(",") || "none"}): ${failure.errorName}: ${failure.errorMessage}`
1491
1537
  );
1492
1538
  registration.inboxCoordinator?.recordProxyFailure?.(failure);
1493
- writeProxyFailureResponse(res, {
1539
+ res.writeHead(502, { "content-type": "application/json" });
1540
+ res.end(JSON.stringify({
1494
1541
  error: "failed to proxy local agent request",
1495
1542
  code: "agent_proxy_failed",
1496
1543
  detail: failure.errorMessage
1497
- });
1498
- }
1499
- }
1500
- function writeProxyFailureResponse(res, body) {
1501
- if (res.destroyed || res.writableEnded) return;
1502
- if (proxyResponseStarted(res)) {
1503
- try {
1504
- res.end();
1505
- } catch {
1506
- }
1507
- return;
1508
- }
1509
- try {
1510
- res.writeHead(502, { "content-type": "application/json" });
1511
- res.end(JSON.stringify(body));
1512
- } catch {
1544
+ }));
1513
1545
  }
1514
1546
  }
1515
- function proxyResponseStarted(res) {
1516
- return res.headersSent || res.writableEnded;
1517
- }
1518
- function proxyFailureForError(method, target, res, upstreamStatus, err) {
1547
+ function proxyFailureForError(method, target, err) {
1519
1548
  const queryKeys = target ? [.../* @__PURE__ */ new Set([...target.searchParams.keys()])].sort() : [];
1520
1549
  return {
1521
1550
  method,
1522
1551
  pathname: target?.pathname ?? "unknown",
1523
1552
  queryKeys,
1524
- responseStarted: proxyResponseStarted(res),
1525
- upstreamStatus,
1526
- errorClass: err instanceof Error ? err.name : typeof err,
1553
+ errorName: err instanceof Error ? err.name : typeof err,
1527
1554
  errorMessage: truncateProxyErrorMessage(err instanceof Error ? err.message : String(err))
1528
1555
  };
1529
1556
  }
@@ -1882,9 +1909,8 @@ function consumeVisibleResponse(registration, targetUrl, sendTarget, responseTex
1882
1909
  coordinator.consumeVisibleMessages({ target, messages, boundarySeq: maxMessageSeq(messages), source: "agent_api_history" });
1883
1910
  }
1884
1911
  }
1885
- function registerAgentCredentialProxy(input) {
1886
- const port = allocatePort();
1887
- ensureServer(port);
1912
+ async function registerAgentCredentialProxy(input) {
1913
+ const server = await ensureServer();
1888
1914
  const proxyToken = `sap_${randomBytes(32).toString("base64url")}`;
1889
1915
  registrations.set(proxyToken, {
1890
1916
  serverUrl: input.serverUrl,
@@ -1895,7 +1921,7 @@ function registerAgentCredentialProxy(input) {
1895
1921
  inboxCoordinator: input.inboxCoordinator
1896
1922
  });
1897
1923
  return {
1898
- proxyUrl: `http://127.0.0.1:${port}`,
1924
+ proxyUrl: server.proxyUrl,
1899
1925
  proxyToken
1900
1926
  };
1901
1927
  }
@@ -1975,7 +2001,7 @@ function runtimeContextEnv(config) {
1975
2001
  function buildCliTransportSystemPrompt(config, opts) {
1976
2002
  return buildCliSystemPrompt(config, opts);
1977
2003
  }
1978
- function prepareCliTransport(ctx, extraEnv = {}, platform = process.platform) {
2004
+ async function prepareCliTransport(ctx, extraEnv = {}, platform = process.platform) {
1979
2005
  if (!ctx.slockCliPath) {
1980
2006
  throw new Error(`${ctx.config.runtime} driver: slockCliPath is required (daemon must inject it)`);
1981
2007
  }
@@ -1988,7 +2014,7 @@ function prepareCliTransport(ctx, extraEnv = {}, platform = process.platform) {
1988
2014
  let agentCredentialProxyTokenFile = null;
1989
2015
  if (typeof agentCredentialKey === "string" && agentCredentialKey.length > 0) {
1990
2016
  rmSync(tokenFile, { force: true });
1991
- agentCredentialProxy = registerAgentCredentialProxy({
2017
+ agentCredentialProxy = await registerAgentCredentialProxy({
1992
2018
  agentId: ctx.agentId,
1993
2019
  launchId: ctx.launchId,
1994
2020
  serverUrl: ctx.config.serverUrl,
@@ -2122,12 +2148,6 @@ import path3 from "path";
2122
2148
  function normalizeExecOutput(raw) {
2123
2149
  return Buffer.isBuffer(raw) ? raw.toString("utf8") : String(raw ?? "");
2124
2150
  }
2125
- function preferWindowsCmdShim(resolved, existsSyncFn) {
2126
- const parsed = path3.win32.parse(resolved);
2127
- if (parsed.ext.toLowerCase() !== ".ps1") return resolved;
2128
- const cmdShim = path3.win32.join(parsed.dir, `${parsed.name}.cmd`);
2129
- return existsSyncFn(cmdShim) ? cmdShim : resolved;
2130
- }
2131
2151
  function resolveCommandOnWindows(command, env, execFileSyncFn, existsSyncFn) {
2132
2152
  const script = "& {$cmd = Get-Command -Name $args[0] -ErrorAction Stop | Select-Object -First 1; if ($cmd.Path) { $cmd.Path } elseif ($cmd.Source) { $cmd.Source } elseif ($cmd.Definition) { $cmd.Definition } }";
2133
2153
  try {
@@ -2142,7 +2162,23 @@ function resolveCommandOnWindows(command, env, execFileSyncFn, existsSyncFn) {
2142
2162
  env
2143
2163
  }));
2144
2164
  const resolved = output.trim().split(/\r?\n/)[0];
2145
- return resolved ? preferWindowsCmdShim(resolved, existsSyncFn) : command;
2165
+ if (!resolved) return null;
2166
+ const lowerResolved = resolved.toLowerCase();
2167
+ if (lowerResolved.endsWith(".ps1")) {
2168
+ const dir = path3.dirname(resolved);
2169
+ const base = path3.basename(resolved, ".ps1");
2170
+ const alternatives = [
2171
+ path3.join(dir, `${base}.cmd`),
2172
+ path3.join(dir, `${base}.bat`),
2173
+ path3.join(dir, `${base}.exe`),
2174
+ path3.join(dir, base)
2175
+ ];
2176
+ for (const alt of alternatives) {
2177
+ if (existsSyncFn(alt)) return alt;
2178
+ }
2179
+ return null;
2180
+ }
2181
+ return resolved;
2146
2182
  } catch {
2147
2183
  return null;
2148
2184
  }
@@ -2230,7 +2266,8 @@ function isRecord(value) {
2230
2266
  function expandClaudeMcpConfigVariables(raw, vars) {
2231
2267
  let expanded = raw;
2232
2268
  for (const [name, value] of Object.entries(vars)) {
2233
- expanded = expanded.replaceAll(`\${${name}}`, value);
2269
+ const escapedValue = process.platform === "win32" ? value.replace(/\\/g, "\\\\") : value;
2270
+ expanded = expanded.replaceAll(`\${${name}}`, escapedValue);
2234
2271
  }
2235
2272
  return expanded;
2236
2273
  }
@@ -2284,7 +2321,7 @@ function collectClaudeMcpConfigFiles(ctx, home) {
2284
2321
  return files;
2285
2322
  }
2286
2323
  function buildClaudeUserMcpServers(ctx, home) {
2287
- const servers2 = /* @__PURE__ */ Object.create(null);
2324
+ const servers = /* @__PURE__ */ Object.create(null);
2288
2325
  for (const configFile of collectClaudeMcpConfigFiles(ctx, home)) {
2289
2326
  const mcpServers = readClaudeMcpServers(configFile.path, configFile.vars);
2290
2327
  if (!mcpServers) continue;
@@ -2293,10 +2330,10 @@ function buildClaudeUserMcpServers(ctx, home) {
2293
2330
  logger.warn(`[Claude] ignoring invalid MCP server "${name}" in ${configFile.path}`);
2294
2331
  continue;
2295
2332
  }
2296
- servers2[name] = server;
2333
+ servers[name] = server;
2297
2334
  }
2298
2335
  }
2299
- return servers2;
2336
+ return servers;
2300
2337
  }
2301
2338
  var ClaudeDriver = class {
2302
2339
  id = "claude";
@@ -2395,8 +2432,8 @@ var ClaudeDriver = class {
2395
2432
  writeFileSync2(mcpConfigPath, this.buildRuntimeActionsMcpConfig(ctx, home), { mode: 384 });
2396
2433
  return { systemPromptPath, mcpConfigPath };
2397
2434
  }
2398
- spawn(ctx) {
2399
- const { slockDir, tokenFile, spawnEnv } = prepareCliTransport(ctx);
2435
+ async spawn(ctx) {
2436
+ const { slockDir, tokenFile, spawnEnv } = await prepareCliTransport(ctx);
2400
2437
  const { systemPromptPath, mcpConfigPath } = this.writeClaudeLaunchFiles(ctx, slockDir);
2401
2438
  const args = this.buildClaudeArgs(ctx.config, ctx.standingPrompt, {
2402
2439
  standingPromptFilePath: systemPromptPath
@@ -2406,11 +2443,18 @@ var ClaudeDriver = class {
2406
2443
  logger.info(
2407
2444
  `[Agent ${ctx.agentId}] transport=cli cli=${ctx.slockCliPath} token_file=${tokenFile}`
2408
2445
  );
2409
- const proc = spawn(resolveClaudeCommand() ?? "claude", args, {
2446
+ const claudeCommand = resolveClaudeCommand();
2447
+ const isWindows = process.platform === "win32";
2448
+ const lowerClaudeCommand = claudeCommand?.toLowerCase();
2449
+ const isBatchFile = Boolean(
2450
+ isWindows && lowerClaudeCommand && (lowerClaudeCommand.endsWith(".cmd") || lowerClaudeCommand.endsWith(".bat"))
2451
+ );
2452
+ const useShell = isWindows && (!claudeCommand || isBatchFile);
2453
+ const proc = spawn(claudeCommand ?? "claude", args, {
2410
2454
  cwd: ctx.workingDirectory,
2411
2455
  stdio: ["pipe", "pipe", "pipe"],
2412
2456
  env: spawnEnv,
2413
- shell: process.platform === "win32"
2457
+ shell: useShell
2414
2458
  });
2415
2459
  const stdinMsg = JSON.stringify({
2416
2460
  type: "user",
@@ -2525,9 +2569,7 @@ var ClaudeDriver = class {
2525
2569
  buildSystemPrompt(config, _agentId) {
2526
2570
  return buildCliTransportSystemPrompt(config, {
2527
2571
  toolPrefix: "mcp__chat__",
2528
- extraCriticalRules: [
2529
- "- Runtime Profile migration completion is the only exception to CLI-only operation: when a migration notice tells you to acknowledge with `runtime_profile_migration_done`, call the `mcp__chat__runtime_profile_migration_done` tool with the exact `migration_key`; do not use `slock` CLI or reply in chat as the acknowledgment."
2530
- ],
2572
+ extraCriticalRules: [],
2531
2573
  postStartupNotes: [
2532
2574
  "**Claude runtime note:** While you are busy, Slock batches inbox-count notifications instead of injecting message content. Use `slock message check` at natural breakpoints to pull the pending messages before side-effect actions that depend on current context."
2533
2575
  ],
@@ -2779,9 +2821,9 @@ var CodexDriver = class {
2779
2821
  sessionAnnounced = false;
2780
2822
  streamedAgentMessageIds = /* @__PURE__ */ new Set();
2781
2823
  streamedReasoningIds = /* @__PURE__ */ new Set();
2782
- spawn(ctx) {
2824
+ async spawn(ctx) {
2783
2825
  ensureGitRepoForCodex(ctx.workingDirectory);
2784
- const { spawnEnv } = prepareCliTransport(ctx, { NO_COLOR: "1" });
2826
+ const { spawnEnv } = await prepareCliTransport(ctx, { NO_COLOR: "1" });
2785
2827
  this.process = null;
2786
2828
  this.requestId = 0;
2787
2829
  this.threadId = ctx.config.sessionId || null;
@@ -3102,12 +3144,142 @@ function detectCodexModels(home = os3.homedir()) {
3102
3144
  return { models, default: defaultModel };
3103
3145
  }
3104
3146
 
3105
- // src/drivers/copilot.ts
3147
+ // src/drivers/antigravity.ts
3148
+ import { randomUUID } from "crypto";
3106
3149
  import { spawn as spawn3 } from "child_process";
3150
+ var DEFAULT_PRINT_TIMEOUT = "30m";
3151
+ var ANTIGRAVITY_ENV_OVERRIDES = {
3152
+ // `agy` switches to a separate file-based token store when it detects an SSH
3153
+ // session. Daemon agents commonly run under SSH-managed hosts, while the
3154
+ // human login lives in the normal local Antigravity credential store.
3155
+ SSH_CLIENT: void 0,
3156
+ SSH_CONNECTION: void 0,
3157
+ SSH_TTY: void 0
3158
+ };
3159
+ function resolveAntigravitySpawn(commandArgs, deps = {}) {
3160
+ return {
3161
+ command: resolveCommandOnPath("agy", deps) ?? "agy",
3162
+ args: commandArgs,
3163
+ shell: false
3164
+ };
3165
+ }
3166
+ function buildAntigravityArgs(ctx) {
3167
+ const args = [
3168
+ "--print",
3169
+ "--print-timeout",
3170
+ ctx.config.envVars?.ANTIGRAVITY_PRINT_TIMEOUT || DEFAULT_PRINT_TIMEOUT,
3171
+ "--dangerously-skip-permissions"
3172
+ ];
3173
+ if (ctx.config.sessionId) {
3174
+ args.push("--continue");
3175
+ }
3176
+ return args;
3177
+ }
3178
+ var ERROR_LINE_PREFIX_RE = /^(?:(?:error|fatal|exception|failure):\s*|failed(?:\b|:))/i;
3179
+ var ERROR_LINE_PATTERNS = [
3180
+ /authentication timed out/i,
3181
+ /\bpermission denied\b/i,
3182
+ /\bunauthorized\b/i,
3183
+ /\brate limit(?:ed)?\b/i,
3184
+ /\bserver error\b/i,
3185
+ /\bnetwork error\b/i,
3186
+ /\brequest timed out\b/i,
3187
+ /\btimed out waiting\b/i,
3188
+ /\b(?:http|status)\s+(?:401|403|429|500|502|503|504)\b/i
3189
+ ];
3190
+ function isErrorLine(line) {
3191
+ return ERROR_LINE_PREFIX_RE.test(line) || ERROR_LINE_PATTERNS.some((pattern) => pattern.test(line));
3192
+ }
3193
+ var AntigravityDriver = class {
3194
+ id = "antigravity";
3195
+ lifecycle = {
3196
+ kind: "per_turn",
3197
+ start: "immediate",
3198
+ exit: "natural",
3199
+ inFlightWake: "spawn_new"
3200
+ };
3201
+ communication = {
3202
+ chat: "slock_cli",
3203
+ runtimeControl: "none"
3204
+ };
3205
+ session = {
3206
+ recovery: "resume_or_fresh"
3207
+ };
3208
+ model = {
3209
+ detectedModelsVerifiedAs: "suggestion_only",
3210
+ toLaunchSpec: (_modelId) => ({ args: [] })
3211
+ };
3212
+ supportsStdinNotification = false;
3213
+ mcpToolPrefix = "";
3214
+ busyDeliveryMode = "none";
3215
+ usesSlockCliForCommunication = true;
3216
+ sessionId = null;
3217
+ sessionAnnounced = false;
3218
+ probe() {
3219
+ const command = resolveCommandOnPath("agy");
3220
+ if (!command) return { available: false };
3221
+ return {
3222
+ available: true,
3223
+ version: readCommandVersion(command) ?? void 0
3224
+ };
3225
+ }
3226
+ async spawn(ctx) {
3227
+ this.sessionId = ctx.config.sessionId || randomUUID();
3228
+ this.sessionAnnounced = false;
3229
+ const { command, args, shell } = resolveAntigravitySpawn(buildAntigravityArgs(ctx));
3230
+ const { spawnEnv } = await prepareCliTransport(ctx, {
3231
+ NO_COLOR: "1",
3232
+ ...ANTIGRAVITY_ENV_OVERRIDES
3233
+ });
3234
+ const proc = spawn3(command, args, {
3235
+ cwd: ctx.workingDirectory,
3236
+ stdio: ["pipe", "pipe", "pipe"],
3237
+ env: spawnEnv,
3238
+ shell
3239
+ });
3240
+ proc.stdin?.end(ctx.prompt);
3241
+ return { process: proc };
3242
+ }
3243
+ parseLine(line) {
3244
+ const trimmed = line.trim();
3245
+ if (!trimmed) return [];
3246
+ const events = [];
3247
+ if (!this.sessionAnnounced && this.sessionId) {
3248
+ events.push({ kind: "session_init", sessionId: this.sessionId });
3249
+ this.sessionAnnounced = true;
3250
+ }
3251
+ if (isErrorLine(trimmed)) {
3252
+ events.push({ kind: "error", message: trimmed });
3253
+ return events;
3254
+ }
3255
+ events.push({ kind: "text", text: line });
3256
+ return events;
3257
+ }
3258
+ encodeStdinMessage(_text, _sessionId, _opts) {
3259
+ return null;
3260
+ }
3261
+ buildSystemPrompt(config, _agentId) {
3262
+ return buildCliTransportSystemPrompt(config, {
3263
+ toolPrefix: "",
3264
+ extraCriticalRules: [],
3265
+ postStartupNotes: [
3266
+ "**Antigravity runtime note:** Slock launches you as a per-turn process. Complete the current wake using `slock` CLI commands, then stop; the daemon will restart you when new messages arrive."
3267
+ ],
3268
+ includeStdinNotificationSection: false,
3269
+ messageNotificationStyle: "poll"
3270
+ });
3271
+ }
3272
+ async detectModels() {
3273
+ return null;
3274
+ }
3275
+ };
3276
+
3277
+ // src/drivers/copilot.ts
3278
+ import { spawn as spawn4 } from "child_process";
3107
3279
  import path6 from "path";
3108
3280
  import { writeFileSync as writeFileSync3 } from "fs";
3109
- function buildCopilotSpawnEnv(ctx) {
3110
- return prepareCliTransport(ctx, { NO_COLOR: "1" }).spawnEnv;
3281
+ async function buildCopilotSpawnEnv(ctx) {
3282
+ return (await prepareCliTransport(ctx, { NO_COLOR: "1" })).spawnEnv;
3111
3283
  }
3112
3284
  var CopilotDriver = class {
3113
3285
  id = "copilot";
@@ -3159,7 +3331,7 @@ var CopilotDriver = class {
3159
3331
  }
3160
3332
  });
3161
3333
  }
3162
- spawn(ctx) {
3334
+ async spawn(ctx) {
3163
3335
  this.sessionId = ctx.config.sessionId || null;
3164
3336
  this.sessionAnnounced = false;
3165
3337
  const mcpConfigPath = path6.join(ctx.workingDirectory, ".slock-copilot-mcp.json");
@@ -3183,8 +3355,8 @@ var CopilotDriver = class {
3183
3355
  if (ctx.config.sessionId) {
3184
3356
  args.push(`--resume=${ctx.config.sessionId}`);
3185
3357
  }
3186
- const spawnEnv = buildCopilotSpawnEnv(ctx);
3187
- const proc = spawn3("copilot", args, {
3358
+ const spawnEnv = await buildCopilotSpawnEnv(ctx);
3359
+ const proc = spawn4("copilot", args, {
3188
3360
  cwd: ctx.workingDirectory,
3189
3361
  stdio: ["pipe", "pipe", "pipe"],
3190
3362
  env: spawnEnv,
@@ -3266,9 +3438,7 @@ var CopilotDriver = class {
3266
3438
  buildSystemPrompt(config, _agentId) {
3267
3439
  return buildCliTransportSystemPrompt(config, {
3268
3440
  toolPrefix: "",
3269
- extraCriticalRules: [
3270
- "- Runtime Profile migration completion is the only exception to CLI-only operation: when a migration notice tells you to acknowledge with `runtime_profile_migration_done`, call the `runtime_profile_migration_done` tool with the exact `migration_key`; do not use `slock` CLI or reply in chat as the acknowledgment."
3271
- ],
3441
+ extraCriticalRules: [],
3272
3442
  postStartupNotes: [
3273
3443
  "**Copilot runtime note:** Slock launches you as a per-turn process. Complete the current wake using `slock` CLI commands, then stop; the daemon will restart you when new messages arrive."
3274
3444
  ],
@@ -3279,11 +3449,11 @@ var CopilotDriver = class {
3279
3449
  };
3280
3450
 
3281
3451
  // src/drivers/cursor.ts
3282
- import { spawn as spawn4, spawnSync } from "child_process";
3452
+ import { spawn as spawn5, spawnSync } from "child_process";
3283
3453
  import { writeFileSync as writeFileSync4, mkdirSync as mkdirSync2, existsSync as existsSync5 } from "fs";
3284
3454
  import path7 from "path";
3285
- function buildCursorSpawnEnv(ctx) {
3286
- return prepareCliTransport(ctx, { NO_COLOR: "1" }).spawnEnv;
3455
+ async function buildCursorSpawnEnv(ctx) {
3456
+ return (await prepareCliTransport(ctx, { NO_COLOR: "1" })).spawnEnv;
3287
3457
  }
3288
3458
  var CursorDriver = class {
3289
3459
  id = "cursor";
@@ -3333,7 +3503,7 @@ var CursorDriver = class {
3333
3503
  }
3334
3504
  });
3335
3505
  }
3336
- spawn(ctx) {
3506
+ async spawn(ctx) {
3337
3507
  const cursorDir = path7.join(ctx.workingDirectory, ".cursor");
3338
3508
  if (!existsSync5(cursorDir)) {
3339
3509
  mkdirSync2(cursorDir, { recursive: true });
@@ -3355,8 +3525,8 @@ var CursorDriver = class {
3355
3525
  args.push("--resume", ctx.config.sessionId);
3356
3526
  }
3357
3527
  args.push(ctx.prompt);
3358
- const spawnEnv = buildCursorSpawnEnv(ctx);
3359
- const proc = spawn4("cursor-agent", args, {
3528
+ const spawnEnv = await buildCursorSpawnEnv(ctx);
3529
+ const proc = spawn5("cursor-agent", args, {
3360
3530
  cwd: ctx.workingDirectory,
3361
3531
  stdio: ["pipe", "pipe", "pipe"],
3362
3532
  env: spawnEnv,
@@ -3424,9 +3594,7 @@ var CursorDriver = class {
3424
3594
  buildSystemPrompt(config, _agentId) {
3425
3595
  return buildCliTransportSystemPrompt(config, {
3426
3596
  toolPrefix: "mcp__chat__",
3427
- extraCriticalRules: [
3428
- "- Runtime Profile migration completion is the only exception to CLI-only operation: when a migration notice tells you to acknowledge with `runtime_profile_migration_done`, call the `runtime_profile_migration_done` tool with the exact `migration_key`; do not use `slock` CLI or reply in chat as the acknowledgment."
3429
- ],
3597
+ extraCriticalRules: [],
3430
3598
  postStartupNotes: [
3431
3599
  "**Cursor runtime note:** Slock launches you as a per-turn process. Complete the current wake using `slock` CLI commands, then stop; the daemon will restart you when new messages arrive."
3432
3600
  ],
@@ -3478,17 +3646,14 @@ function runCursorModelsCommand() {
3478
3646
  }
3479
3647
 
3480
3648
  // src/drivers/gemini.ts
3481
- import { execFileSync as execFileSync3, spawn as spawn5 } from "child_process";
3649
+ import { execFileSync as execFileSync3, spawn as spawn6 } from "child_process";
3482
3650
  import { existsSync as existsSync6, mkdirSync as mkdirSync3, writeFileSync as writeFileSync5 } from "fs";
3483
3651
  import path8 from "path";
3484
- function buildGeminiSpawnEnv(ctx, platform = process.platform) {
3485
- const { spawnEnv } = prepareCliTransport(ctx, { NO_COLOR: "1" }, platform);
3652
+ async function buildGeminiSpawnEnv(ctx, platform = process.platform) {
3653
+ const { spawnEnv } = await prepareCliTransport(ctx, { NO_COLOR: "1" }, platform);
3486
3654
  if (!Object.prototype.hasOwnProperty.call(ctx.config.envVars ?? {}, "GEMINI_CLI_TRUST_WORKSPACE")) {
3487
3655
  spawnEnv.GEMINI_CLI_TRUST_WORKSPACE = "true";
3488
3656
  }
3489
- if (platform === "win32" && !Object.prototype.hasOwnProperty.call(ctx.config.envVars ?? {}, "GEMINI_PTY_INFO")) {
3490
- spawnEnv.GEMINI_PTY_INFO = "child_process";
3491
- }
3492
3657
  return spawnEnv;
3493
3658
  }
3494
3659
  function normalizeExecOutput2(raw) {
@@ -3581,13 +3746,13 @@ var GeminiDriver = class {
3581
3746
  usesSlockCliForCommunication = true;
3582
3747
  sessionId = null;
3583
3748
  sessionAnnounced = false;
3584
- spawn(ctx) {
3749
+ async spawn(ctx) {
3585
3750
  this.sessionId = ctx.config.sessionId || null;
3586
3751
  this.sessionAnnounced = false;
3587
3752
  this.writeGeminiSettings(ctx);
3588
3753
  const { command, args } = resolveGeminiSpawn(buildGeminiArgs(ctx.config));
3589
- const spawnEnv = buildGeminiSpawnEnv(ctx);
3590
- const proc = spawn5(command, args, {
3754
+ const spawnEnv = await buildGeminiSpawnEnv(ctx);
3755
+ const proc = spawn6(command, args, {
3591
3756
  cwd: ctx.workingDirectory,
3592
3757
  stdio: ["pipe", "pipe", "pipe"],
3593
3758
  env: spawnEnv,
@@ -3649,9 +3814,7 @@ var GeminiDriver = class {
3649
3814
  buildSystemPrompt(config, _agentId) {
3650
3815
  return buildCliTransportSystemPrompt(config, {
3651
3816
  toolPrefix: "",
3652
- extraCriticalRules: [
3653
- "- Runtime Profile migration completion is the only exception to CLI-only operation: when a migration notice tells you to acknowledge with `runtime_profile_migration_done`, call the `runtime_profile_migration_done` tool with the exact `migration_key`; do not use `slock` CLI or reply in chat as the acknowledgment."
3654
- ],
3817
+ extraCriticalRules: [],
3655
3818
  postStartupNotes: [
3656
3819
  "**Gemini runtime note:** Slock launches you as a per-turn process. Complete the current wake using `slock` CLI commands, then stop; the daemon will restart you when new messages arrive."
3657
3820
  ],
@@ -3693,8 +3856,8 @@ var GeminiDriver = class {
3693
3856
  };
3694
3857
 
3695
3858
  // src/drivers/kimi.ts
3696
- import { randomUUID } from "crypto";
3697
- import { spawn as spawn6 } from "child_process";
3859
+ import { randomUUID as randomUUID2 } from "crypto";
3860
+ import { spawn as spawn7 } from "child_process";
3698
3861
  import { existsSync as existsSync7, readFileSync as readFileSync4, writeFileSync as writeFileSync6 } from "fs";
3699
3862
  import os4 from "os";
3700
3863
  import path9 from "path";
@@ -3758,11 +3921,11 @@ var KimiDriver = class {
3758
3921
  "--runtime-actions-only"
3759
3922
  ];
3760
3923
  }
3761
- spawn(ctx) {
3924
+ async spawn(ctx) {
3762
3925
  const isResume = !!ctx.config.sessionId;
3763
- this.sessionId = ctx.config.sessionId || randomUUID();
3926
+ this.sessionId = ctx.config.sessionId || randomUUID2();
3764
3927
  this.sessionAnnounced = false;
3765
- this.promptRequestId = randomUUID();
3928
+ this.promptRequestId = randomUUID2();
3766
3929
  const isTsSource = ctx.chatBridgePath.endsWith(".ts");
3767
3930
  const command = isTsSource ? "npx" : "node";
3768
3931
  const bridgeArgs = this.buildChatBridgeArgs(ctx);
@@ -3800,9 +3963,9 @@ var KimiDriver = class {
3800
3963
  if (ctx.config.model && ctx.config.model !== "default") {
3801
3964
  args.push("--model", ctx.config.model);
3802
3965
  }
3803
- const spawnEnv = prepareCliTransport(ctx, { NO_COLOR: "1" }).spawnEnv;
3966
+ const spawnEnv = (await prepareCliTransport(ctx, { NO_COLOR: "1" })).spawnEnv;
3804
3967
  const launch = resolveKimiSpawn(args);
3805
- const proc = spawn6(launch.command, launch.args, {
3968
+ const proc = spawn7(launch.command, launch.args, {
3806
3969
  cwd: ctx.workingDirectory,
3807
3970
  stdio: ["pipe", "pipe", "pipe"],
3808
3971
  env: spawnEnv,
@@ -3814,7 +3977,7 @@ var KimiDriver = class {
3814
3977
  });
3815
3978
  proc.stdin?.write(JSON.stringify({
3816
3979
  jsonrpc: "2.0",
3817
- id: randomUUID(),
3980
+ id: randomUUID2(),
3818
3981
  method: "initialize",
3819
3982
  params: {
3820
3983
  protocol_version: KIMI_WIRE_PROTOCOL_VERSION,
@@ -3895,7 +4058,7 @@ var KimiDriver = class {
3895
4058
  if (mode === "idle") {
3896
4059
  return JSON.stringify({
3897
4060
  jsonrpc: "2.0",
3898
- id: randomUUID(),
4061
+ id: randomUUID2(),
3899
4062
  method: "prompt",
3900
4063
  params: {
3901
4064
  user_input: _text
@@ -3904,7 +4067,7 @@ var KimiDriver = class {
3904
4067
  }
3905
4068
  return JSON.stringify({
3906
4069
  jsonrpc: "2.0",
3907
- id: randomUUID(),
4070
+ id: randomUUID2(),
3908
4071
  method: "steer",
3909
4072
  params: {
3910
4073
  user_input: _text
@@ -3914,9 +4077,7 @@ var KimiDriver = class {
3914
4077
  buildSystemPrompt(config, _agentId) {
3915
4078
  return buildCliTransportSystemPrompt(config, {
3916
4079
  toolPrefix: "",
3917
- extraCriticalRules: [
3918
- "- Runtime Profile migration completion is the only exception to CLI-only operation: when a migration notice tells you to acknowledge with `runtime_profile_migration_done`, call the `runtime_profile_migration_done` tool with the exact `migration_key`; do not use `slock` CLI or reply in chat as the acknowledgment."
3919
- ],
4080
+ extraCriticalRules: [],
3920
4081
  postStartupNotes: [],
3921
4082
  includeStdinNotificationSection: true,
3922
4083
  messageNotificationStyle: "direct"
@@ -3953,7 +4114,7 @@ function detectKimiModels(home = os4.homedir()) {
3953
4114
  }
3954
4115
 
3955
4116
  // src/drivers/opencode.ts
3956
- import { spawn as spawn7, spawnSync as spawnSync2 } from "child_process";
4117
+ import { spawn as spawn8, spawnSync as spawnSync2 } from "child_process";
3957
4118
  import { existsSync as existsSync8, readFileSync as readFileSync5 } from "fs";
3958
4119
  import os5 from "os";
3959
4120
  import path10 from "path";
@@ -4089,8 +4250,8 @@ function buildOpenCodeConfig(ctx, home = os5.homedir()) {
4089
4250
  }
4090
4251
  };
4091
4252
  }
4092
- function buildOpenCodeLaunchOptions(ctx, home = os5.homedir(), version = null) {
4093
- const slock = prepareCliTransport(ctx, { NO_COLOR: "1" });
4253
+ async function buildOpenCodeLaunchOptions(ctx, home = os5.homedir(), version = null) {
4254
+ const slock = await prepareCliTransport(ctx, { NO_COLOR: "1" });
4094
4255
  const config = buildOpenCodeConfig(ctx, home);
4095
4256
  const env = {
4096
4257
  ...slock.spawnEnv,
@@ -4309,9 +4470,7 @@ function isSystemFirstMessageTask(message) {
4309
4470
  function buildOpenCodeSystemPrompt(config) {
4310
4471
  return buildCliTransportSystemPrompt(config, {
4311
4472
  toolPrefix: CHAT_MCP_TOOL_PREFIX,
4312
- extraCriticalRules: [
4313
- "- Runtime Profile migration completion is the only exception to CLI-only operation: when a migration notice tells you to acknowledge with `runtime_profile_migration_done`, call the `chat_runtime_profile_migration_done` tool with the exact `migration_key`; do not use `slock` CLI or reply in chat as the acknowledgment."
4314
- ],
4473
+ extraCriticalRules: [],
4315
4474
  postStartupNotes: [
4316
4475
  "**OpenCode runtime note:** Slock launches you as a per-turn process. Complete the current wake using `slock` CLI commands, then stop; the daemon will restart you when new messages arrive."
4317
4476
  ],
@@ -4336,7 +4495,7 @@ var OpenCodeDriver = class {
4336
4495
  };
4337
4496
  model = {
4338
4497
  detectedModelsVerifiedAs: "launchable",
4339
- toLaunchSpec: (modelId, ctx, opts) => {
4498
+ toLaunchSpec: async (modelId, ctx, opts) => {
4340
4499
  if (!ctx) return { args: ["--model", modelId] };
4341
4500
  const launchCtx = {
4342
4501
  ...ctx,
@@ -4346,7 +4505,7 @@ var OpenCodeDriver = class {
4346
4505
  }
4347
4506
  };
4348
4507
  const version = readOpenCodeVersion();
4349
- const launch = buildOpenCodeLaunchOptions(launchCtx, opts?.home, version);
4508
+ const launch = await buildOpenCodeLaunchOptions(launchCtx, opts?.home, version);
4350
4509
  return {
4351
4510
  args: launch.args,
4352
4511
  env: launch.env,
@@ -4385,7 +4544,7 @@ var OpenCodeDriver = class {
4385
4544
  async detectModels() {
4386
4545
  return detectOpenCodeModels();
4387
4546
  }
4388
- spawn(ctx) {
4547
+ async spawn(ctx) {
4389
4548
  this.sessionId = ctx.config.sessionId || null;
4390
4549
  this.sessionAnnounced = false;
4391
4550
  const version = readOpenCodeVersion();
@@ -4393,9 +4552,9 @@ var OpenCodeDriver = class {
4393
4552
  if (unsupportedMessage) {
4394
4553
  throw new Error(unsupportedMessage);
4395
4554
  }
4396
- const launch = buildOpenCodeLaunchOptions(ctx, os5.homedir(), version);
4555
+ const launch = await buildOpenCodeLaunchOptions(ctx, os5.homedir(), version);
4397
4556
  const spawnSpec = resolveOpenCodeSpawn(launch.args);
4398
- const proc = spawn7(spawnSpec.command, spawnSpec.args, {
4557
+ const proc = spawn8(spawnSpec.command, spawnSpec.args, {
4399
4558
  cwd: ctx.workingDirectory,
4400
4559
  stdio: ["pipe", "pipe", "pipe"],
4401
4560
  env: launch.env,
@@ -4461,6 +4620,7 @@ var OpenCodeDriver = class {
4461
4620
  var driverFactories = {
4462
4621
  claude: () => new ClaudeDriver(),
4463
4622
  codex: () => new CodexDriver(),
4623
+ antigravity: () => new AntigravityDriver(),
4464
4624
  copilot: () => new CopilotDriver(),
4465
4625
  cursor: () => new CursorDriver(),
4466
4626
  gemini: () => new GeminiDriver(),
@@ -4588,15 +4748,38 @@ async function deleteWorkspaceDirectory(dataDir, directoryName) {
4588
4748
  // src/runtimeErrorDiagnostics.ts
4589
4749
  import { createHash } from "crypto";
4590
4750
  var MAX_RUNTIME_ERROR_MESSAGE_EXCERPT_CHARS = 4096;
4751
+ var RUNTIME_AUTH_ACTION_REQUIRED_PATTERNS = [
4752
+ /access token could not be refreshed/i,
4753
+ /refresh token was already used/i,
4754
+ /authentication token has been invalidated/i,
4755
+ /logged out or signed in to another account/i,
4756
+ /not logged in/i,
4757
+ /not signed in/i,
4758
+ /login required/i,
4759
+ /log in first/i,
4760
+ /please log in/i,
4761
+ /authentication failed/i,
4762
+ /auth(?:entication)? failed/i,
4763
+ /authentication timed out/i,
4764
+ /missing (?:api )?token/i,
4765
+ /no (?:api )?token/i,
4766
+ /missing credentials/i,
4767
+ /credentials? not found/i,
4768
+ /invalid api key/i,
4769
+ /api key (?:is )?not set/i
4770
+ ];
4591
4771
  function buildRuntimeErrorDiagnosticEnvelope(message) {
4592
4772
  const rawMessage = String(message || "");
4593
4773
  const scrubbed = scrubRuntimeErrorDiagnosticText(rawMessage);
4594
4774
  const { value: excerpt, truncated } = truncateDiagnosticText(scrubbed, MAX_RUNTIME_ERROR_MESSAGE_EXCERPT_CHARS);
4595
4775
  const httpStatus = extractHttpStatus(rawMessage);
4596
4776
  const runtimeErrorClass = classifyRuntimeError(rawMessage, httpStatus);
4777
+ const runtimeErrorAction = classifyRuntimeErrorAction(rawMessage, runtimeErrorClass);
4597
4778
  const fingerprint = fingerprintRuntimeError(scrubbed);
4598
4779
  const spanAttrs = {
4599
4780
  runtime_error_class: runtimeErrorClass,
4781
+ runtime_error_action: runtimeErrorAction,
4782
+ runtime_error_action_required: runtimeErrorAction !== "none",
4600
4783
  runtime_error_fingerprint: fingerprint,
4601
4784
  runtime_error_message_present: rawMessage.length > 0,
4602
4785
  runtime_error_message_length_bucket: bucketLength(rawMessage.length),
@@ -4613,6 +4796,14 @@ function buildRuntimeErrorDiagnosticEnvelope(message) {
4613
4796
  }
4614
4797
  };
4615
4798
  }
4799
+ function formatRuntimeLoginRequiredMessage(runtimeId) {
4800
+ const runtimeLabel = runtimeDisplayName(runtimeId);
4801
+ return `${runtimeLabel} is not logged in on this machine. Please log in to ${runtimeLabel} locally, then retry starting this agent.`;
4802
+ }
4803
+ function formatRuntimeStartTimeoutMessage(runtimeId) {
4804
+ const runtimeLabel = runtimeDisplayName(runtimeId);
4805
+ return `${runtimeLabel} did not finish starting on this machine. Check that ${runtimeLabel} is installed, logged in, and can run non-interactively, then retry starting this agent.`;
4806
+ }
4616
4807
  function scrubRuntimeErrorDiagnosticText(value) {
4617
4808
  return value.replace(/\bBearer\s+[A-Za-z0-9._~+/=-]{8,}/gi, "Bearer [REDACTED_TOKEN]").replace(/\b(?:sk|sk-ant|sk-proj|xox[baprs]?)-[A-Za-z0-9_-]{8,}\b/g, "[REDACTED_TOKEN]").replace(/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g, "[REDACTED_EMAIL]").replace(/https?:\/\/[^\s"'<>]+/gi, (url) => redactUrlQuery(url)).replace(/\/Users\/[^\s"'<>:]+(?:\/[^\s"'<>:]+)*/g, "[REDACTED_PATH]").replace(/\/home\/[^\s"'<>:]+(?:\/[^\s"'<>:]+)*/g, "[REDACTED_PATH]").replace(/[A-Za-z]:\\Users\\[^\s"'<>:]+(?:\\[^\s"'<>:]+)*/g, "[REDACTED_PATH]");
4618
4809
  }
@@ -4636,12 +4827,44 @@ function classifyRuntimeError(message, httpStatus) {
4636
4827
  if (httpStatus >= 500) return "ProviderServerError";
4637
4828
  return "ProviderApiError";
4638
4829
  }
4830
+ if (isRuntimeAuthActionRequiredText(message)) return "AuthError";
4639
4831
  if (/\btimeout|timed out\b/i.test(message)) return "TimeoutError";
4640
4832
  if (/stream closed before response\.completed|error decoding response body/i.test(message)) return "ProviderStreamError";
4641
4833
  if (/\brate.?limit|too many requests\b/i.test(message)) return "RateLimitError";
4642
4834
  if (/\bnot found\b/i.test(message)) return "NotFoundError";
4643
4835
  return "RuntimeError";
4644
4836
  }
4837
+ function classifyRuntimeErrorAction(message, runtimeErrorClass) {
4838
+ if (runtimeErrorClass === "AuthError" && isRuntimeAuthActionRequiredText(message)) {
4839
+ return "user_reauth";
4840
+ }
4841
+ return "none";
4842
+ }
4843
+ function isRuntimeAuthActionRequiredText(text) {
4844
+ return RUNTIME_AUTH_ACTION_REQUIRED_PATTERNS.some((pattern) => pattern.test(text));
4845
+ }
4846
+ function runtimeDisplayName(runtimeId) {
4847
+ switch (runtimeId) {
4848
+ case "antigravity":
4849
+ return "Antigravity CLI";
4850
+ case "claude":
4851
+ return "Claude Code";
4852
+ case "codex":
4853
+ return "Codex";
4854
+ case "copilot":
4855
+ return "GitHub Copilot CLI";
4856
+ case "cursor":
4857
+ return "Cursor CLI";
4858
+ case "gemini":
4859
+ return "Gemini CLI";
4860
+ case "kimi":
4861
+ return "Kimi CLI";
4862
+ case "opencode":
4863
+ return "OpenCode";
4864
+ default:
4865
+ return runtimeId || "This runtime";
4866
+ }
4867
+ }
4645
4868
  function fingerprintRuntimeError(value) {
4646
4869
  const normalized = value.toLowerCase().replace(/[0-9a-f]{12,}/g, "<hex>").replace(/\b\d+\b/g, "<num>").replace(/\s+/g, " ").trim();
4647
4870
  return createHash("sha256").update(normalized).digest("hex").slice(0, 16);
@@ -4755,6 +4978,12 @@ function stalledRecoverySigtermTimeoutMs() {
4755
4978
  DEFAULT_STALLED_RECOVERY_SIGTERM_TIMEOUT_MS
4756
4979
  );
4757
4980
  }
4981
+ function runtimeStartTimeoutMs() {
4982
+ return readNonNegativeIntegerEnv(
4983
+ "SLOCK_DAEMON_RUNTIME_START_TIMEOUT_MS",
4984
+ DEFAULT_RUNTIME_START_TIMEOUT_MS
4985
+ );
4986
+ }
4758
4987
  function toLocalTime(iso) {
4759
4988
  const d = new Date(iso);
4760
4989
  if (isNaN(d.getTime())) return iso;
@@ -4838,7 +5067,7 @@ function writeRuntimeSessionHandoff(runtime, sessionId, fallbackDir) {
4838
5067
  runtime,
4839
5068
  sessionId,
4840
5069
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
4841
- note: "The native runtime transcript file was not found on this machine; this daemon-created handoff records the previous session identity for Runtime Profile migration."
5070
+ note: "The native runtime transcript file was not found on this machine; this daemon-created handoff records the runtime session identity for diagnostics."
4842
5071
  }) + "\n", { mode: 384 });
4843
5072
  return {
4844
5073
  label: sessionId,
@@ -4947,43 +5176,23 @@ function formatRuntimeProfileControlPrompt(messages) {
4947
5176
  message,
4948
5177
  notification: runtimeProfileNotificationFromMessage(message)
4949
5178
  }));
4950
- if (controls.length === 0 || controls.some(({ notification }) => !notification)) {
5179
+ if (controls.length === 0 || controls.some(({ notification }) => !notification || notification.kind !== "daemon_release_notice")) {
4951
5180
  return null;
4952
5181
  }
4953
5182
  const body = controls.map(({ message }) => message.content).join("\n\n---\n\n");
4954
- const hasMigration = controls.some(({ notification }) => notification?.kind === "migration");
4955
- if (!hasMigration) {
4956
- return [
4957
- "Runtime Profile daemon release notice.",
4958
- "",
4959
- "Read the notice below before continuing. No chat reply or runtime control action is required for this notice \u2014 resume normal inbox processing afterward.",
4960
- "",
4961
- body
4962
- ].join("\n");
4963
- }
4964
5183
  return [
4965
- "Runtime Profile control notice.",
4966
- "",
4967
- "Complete the required runtime control action before reading or responding to normal inbox messages.",
5184
+ "Runtime Profile notice.",
4968
5185
  "",
4969
- body,
5186
+ "Read the daemon release notice below before continuing. No chat reply or runtime control action is required \u2014 resume normal inbox processing afterward.",
4970
5187
  "",
4971
- "Do not answer this notice in prose as the acknowledgment."
5188
+ body
4972
5189
  ].join("\n");
4973
5190
  }
4974
5191
  function formatRuntimeProfileControlStartupInput(control, driver) {
4975
- if (control.kind !== "migration") {
4976
- return [
4977
- "Read the Runtime Profile daemon release notice from your system prompt before normal work.",
4978
- "No chat reply is required for this notice. Stop after reading it; queued inbox messages will be delivered separately."
4979
- ].join("\n");
4980
- }
4981
- const actionName = `${driver.mcpToolPrefix}runtime_profile_migration_done`;
5192
+ void driver;
4982
5193
  return [
4983
- "Runtime Profile migration is required before normal work.",
4984
- `Invoke the available runtime control action \`${actionName}\` with exactly this migration_key: \`${control.key}\`.`,
4985
- "Do not read MEMORY.md, check messages, or send a chat reply before this tool call.",
4986
- "After the runtime control action succeeds, stop. Queued inbox messages will be delivered separately.",
5194
+ "Read the Runtime Profile daemon release notice from your system prompt before normal work.",
5195
+ "No chat reply or runtime control action is required for this notice. Stop after reading it; queued inbox messages will be delivered separately.",
4987
5196
  "",
4988
5197
  control.message
4989
5198
  ].join("\n");
@@ -5002,6 +5211,7 @@ var TRAJECTORY_COALESCE_MS = 350;
5002
5211
  var ACTIVITY_HEARTBEAT_MS = 6e4;
5003
5212
  var COMPACTION_STALE_MS = 5 * 6e4;
5004
5213
  var RUNTIME_PROGRESS_STALE_MS = 15 * 6e4;
5214
+ var DEFAULT_RUNTIME_START_TIMEOUT_MS = 2 * 6e4;
5005
5215
  var DEFAULT_STALLED_RECOVERY_SIGTERM_TIMEOUT_MS = 1e4;
5006
5216
  var MAX_STDOUT_LINES = 8;
5007
5217
  var MAX_STDOUT_LINE_LENGTH = 240;
@@ -5444,7 +5654,7 @@ function runtimeProfileNotificationFromMessage(message) {
5444
5654
  return null;
5445
5655
  }
5446
5656
  function runtimeProfileNotificationTitle(kind) {
5447
- return kind === "migration" ? "Runtime Profile migration" : "Runtime Profile notice";
5657
+ return kind === "migration" ? "Runtime Profile reset" : "Runtime Profile notice";
5448
5658
  }
5449
5659
  function hashRuntimeProfileKey(key) {
5450
5660
  if (!key) return void 0;
@@ -5511,9 +5721,14 @@ function classifyTerminalFailure(ap) {
5511
5721
  ...ap.recentStderr
5512
5722
  ].filter((value) => !!value);
5513
5723
  for (const text of candidates) {
5724
+ const diagnostics = buildRuntimeErrorDiagnosticEnvelope(text);
5514
5725
  const lower = text.toLowerCase();
5515
- if (lower.includes("usage limit") || lower.includes("quota exceeded") || lower.includes("quota limit") || lower.includes("budget limit exceeded") || lower.includes("usage not included in your plan") || lower.includes("modelnotfounderror") || lower.includes("requested entity was not found") || lower.includes("model deprecated") || lower.includes("model not found") || isProviderStreamFailureText(text)) {
5516
- return text;
5726
+ if (lower.includes("usage limit") || lower.includes("quota exceeded") || lower.includes("quota limit") || lower.includes("budget limit exceeded") || lower.includes("usage not included in your plan") || lower.includes("modelnotfounderror") || lower.includes("requested entity was not found") || lower.includes("model deprecated") || lower.includes("model not found") || diagnostics.spanAttrs.runtime_error_action_required === true || isProviderStreamFailureText(text) || isRuntimeStartTimeoutText(text)) {
5727
+ const actionRequired = diagnostics.spanAttrs.runtime_error_action_required === true;
5728
+ return {
5729
+ detail: actionRequired ? formatRuntimeLoginRequiredMessage(ap.driver.id) : text,
5730
+ actionRequired
5731
+ };
5517
5732
  }
5518
5733
  }
5519
5734
  return null;
@@ -5521,6 +5736,9 @@ function classifyTerminalFailure(ap) {
5521
5736
  function isProviderStreamFailureText(text) {
5522
5737
  return /stream closed before response\.completed|error decoding response body/i.test(text);
5523
5738
  }
5739
+ function isRuntimeStartTimeoutText(text) {
5740
+ return /did not finish starting on this machine/i.test(text);
5741
+ }
5524
5742
  function isCodexProviderReconnectLog(text) {
5525
5743
  return /Reconnecting\.\.\.\s*\d+\s*\/\s*\d+/i.test(text);
5526
5744
  }
@@ -5607,6 +5825,8 @@ function buildRuntimeStallDiagnostic(ap, staleForMs, staleForMinutes) {
5607
5825
  lastActivityDetailKind: classifyActivityDetailForTrace(ap.lastActivityDetail),
5608
5826
  runtime: ap.config.runtime,
5609
5827
  model: ap.config.model,
5828
+ platform: process.platform,
5829
+ arch: process.arch,
5610
5830
  launchId: ap.launchId || void 0,
5611
5831
  sessionIdPresent: Boolean(ap.sessionId),
5612
5832
  inboxCount: ap.inbox.length,
@@ -5623,6 +5843,12 @@ function buildRuntimeStallDiagnostic(ap, staleForMs, staleForMinutes) {
5623
5843
  }
5624
5844
  };
5625
5845
  }
5846
+ function classifyRuntimeStallReason(ap) {
5847
+ if (ap.lastRuntimeEventKind === "tool_output" && ap.gatedSteering.outstandingToolUses === 0) {
5848
+ return "harness_post_tool_silent_wedge";
5849
+ }
5850
+ return "no_runtime_events";
5851
+ }
5626
5852
  function bucketBytes(value) {
5627
5853
  const bytes = typeof value === "string" ? Buffer.byteLength(value, "utf8") : Math.max(0, Math.floor(value ?? 0));
5628
5854
  if (bytes === 0) return "0";
@@ -5927,9 +6153,7 @@ var AgentProcessManager = class _AgentProcessManager {
5927
6153
  method: input.method,
5928
6154
  path: input.pathname,
5929
6155
  query_keys: input.queryKeys,
5930
- response_started: input.responseStarted,
5931
- upstream_status: input.upstreamStatus,
5932
- error_class: input.errorClass,
6156
+ error_name: input.errorName,
5933
6157
  error_message: input.errorMessage
5934
6158
  }, "error");
5935
6159
  }
@@ -6182,9 +6406,31 @@ var AgentProcessManager = class _AgentProcessManager {
6182
6406
  this.recordDaemonTrace("daemon.agent.spawn.started", this.startQueueTraceAttrs(agentId, config, wakeMessage, unreadSummary, resumePrompt, launchId));
6183
6407
  try {
6184
6408
  const driver = this.driverResolver(config.runtime || "claude");
6409
+ const legacyWakeRuntimeProfile = wakeMessage ? runtimeProfileNotificationFromMessage(wakeMessage) : null;
6410
+ if (legacyWakeRuntimeProfile?.kind === "migration") {
6411
+ this.completeDeprecatedRuntimeProfileMigration(
6412
+ agentId,
6413
+ legacyWakeRuntimeProfile.key,
6414
+ launchId || null,
6415
+ wakeMessage?.traceparent,
6416
+ "wake_message"
6417
+ );
6418
+ wakeMessage = void 0;
6419
+ }
6185
6420
  const agentDataDir = path12.join(this.dataDir, agentId);
6186
6421
  await mkdir(agentDataDir, { recursive: true });
6187
- const runtimeConfig = withLocalRuntimeContext(config, agentId, agentDataDir);
6422
+ let runtimeConfig = withLocalRuntimeContext(config, agentId, agentDataDir);
6423
+ const legacyRuntimeProfileControl = runtimeConfig.runtimeProfileControl?.kind === "migration" ? runtimeConfig.runtimeProfileControl : null;
6424
+ if (legacyRuntimeProfileControl) {
6425
+ this.completeDeprecatedRuntimeProfileMigration(
6426
+ agentId,
6427
+ legacyRuntimeProfileControl.key,
6428
+ launchId || null,
6429
+ void 0,
6430
+ "agent_config"
6431
+ );
6432
+ runtimeConfig = { ...runtimeConfig, runtimeProfileControl: null };
6433
+ }
6188
6434
  const memoryMdPath = path12.join(agentDataDir, "MEMORY.md");
6189
6435
  try {
6190
6436
  await access(memoryMdPath);
@@ -6300,7 +6546,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
6300
6546
  }
6301
6547
  return;
6302
6548
  }
6303
- const { process: proc } = driver.spawn({
6549
+ const { process: proc } = await driver.spawn({
6304
6550
  agentId,
6305
6551
  config: effectiveConfig,
6306
6552
  standingPrompt,
@@ -6332,9 +6578,12 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
6332
6578
  notificationTimer: null,
6333
6579
  pendingNotificationCount: 0,
6334
6580
  activityHeartbeat: null,
6581
+ startupTimeoutTimer: null,
6582
+ startupTimedOut: false,
6335
6583
  compactionWatchdog: null,
6336
6584
  compactionStartedAt: null,
6337
6585
  lastRuntimeEventAt: Date.now(),
6586
+ lastRuntimeEventKind: null,
6338
6587
  runtimeProgressStaleSince: null,
6339
6588
  runtimeTraceSpan: null,
6340
6589
  runtimeTraceCounters: createRuntimeTraceCounters(),
@@ -6362,8 +6611,8 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
6362
6611
  });
6363
6612
  this.startRuntimeTrace(agentId, agentProcess, "spawn", wakeMessage ? [wakeMessage] : void 0, runtimeInputTraceAttrs);
6364
6613
  this.agentsStarting.delete(agentId);
6365
- if (config.runtimeProfileControl) {
6366
- this.ackInjectedRuntimeProfileControl(agentId, config.runtimeProfileControl, agentProcess.launchId);
6614
+ if (runtimeConfig.runtimeProfileControl) {
6615
+ this.ackInjectedRuntimeProfileControl(agentId, runtimeConfig.runtimeProfileControl, agentProcess.launchId);
6367
6616
  }
6368
6617
  if (wakeMessage) {
6369
6618
  this.consumeVisibleMessages(agentId, { messages: [wakeMessage], source: "spawn_wake_message" });
@@ -6415,7 +6664,10 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
6415
6664
  });
6416
6665
  proc.on("error", (err) => {
6417
6666
  const current = this.agents.get(agentId);
6418
- if (current) current.spawnError = err.message;
6667
+ if (current) {
6668
+ current.spawnError = err.message;
6669
+ this.clearRuntimeStartupTimeout(current);
6670
+ }
6419
6671
  this.recordDaemonTrace("daemon.agent.process.error", {
6420
6672
  agentId,
6421
6673
  launchId: current?.launchId || void 0,
@@ -6459,10 +6711,11 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
6459
6711
  if (ap.activityHeartbeat) {
6460
6712
  clearInterval(ap.activityHeartbeat);
6461
6713
  }
6714
+ this.clearRuntimeStartupTimeout(ap);
6462
6715
  this.clearStalledRecoverySigtermWatchdog(ap);
6463
6716
  const finalCode = ap.exitCode ?? code;
6464
6717
  const finalSignal = ap.exitSignal ?? signal;
6465
- const expectedTermination = Boolean(ap.expectedTerminationReason);
6718
+ const expectedTermination = Boolean(ap.expectedTerminationReason) || ap.startupTimedOut;
6466
6719
  const processEndedCleanly = finalCode === 0 || expectedTermination && !ap.lastRuntimeError;
6467
6720
  const terminalFailureDetail = processEndedCleanly ? null : classifyTerminalFailure(ap);
6468
6721
  const missingResumeSession = isMissingResumeSession(ap);
@@ -6555,7 +6808,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
6555
6808
  this.broadcastActivity(agentId, "online", "Process idle");
6556
6809
  } else {
6557
6810
  const reason = formatCrashReason(finalCode, finalSignal, ap);
6558
- if (terminalFailureDetail && isProviderStreamFailureText(terminalFailureDetail)) {
6811
+ if (terminalFailureDetail && isProviderStreamFailureText(terminalFailureDetail.detail)) {
6559
6812
  this.idleAgentConfigs.set(agentId, {
6560
6813
  config: { ...ap.config, sessionId: ap.sessionId },
6561
6814
  sessionId: ap.sessionId,
@@ -6563,19 +6816,23 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
6563
6816
  });
6564
6817
  logger.warn(`[Agent ${agentId}] Recoverable provider stream failure (${reason}) \u2014 keeping agent wakeable`);
6565
6818
  this.sendAgentStatus(agentId, "active", ap.launchId);
6819
+ } else if (ap.startupTimedOut) {
6820
+ logger.warn(`[Agent ${agentId}] Startup timeout cleanup completed (${reason})`);
6566
6821
  } else {
6567
6822
  this.idleAgentConfigs.delete(agentId);
6568
6823
  logger.error(`[Agent ${agentId}] Process crashed (${reason}) \u2014 marking inactive`);
6569
6824
  this.sendAgentStatus(agentId, "inactive", ap.launchId);
6570
6825
  }
6571
6826
  if (terminalFailureDetail) {
6572
- this.broadcastActivity(
6573
- agentId,
6574
- "error",
6575
- terminalFailureDetail,
6576
- [{ kind: "text", text: `Error: ${terminalFailureDetail}` }],
6577
- ap.launchId
6578
- );
6827
+ if (!ap.startupTimedOut) {
6828
+ this.broadcastActivity(
6829
+ agentId,
6830
+ "error",
6831
+ terminalFailureDetail.detail,
6832
+ [{ kind: "text", text: `Error: ${terminalFailureDetail.detail}` }],
6833
+ ap.launchId
6834
+ );
6835
+ }
6579
6836
  } else {
6580
6837
  this.broadcastActivity(agentId, "offline", `Crashed (${summary})`, [], ap.launchId);
6581
6838
  }
@@ -6584,6 +6841,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
6584
6841
  });
6585
6842
  this.sendAgentStatus(agentId, "active", launchId || null);
6586
6843
  this.broadcastActivity(agentId, "working", "Starting\u2026");
6844
+ this.startRuntimeStartupTimeout(agentId, agentProcess);
6587
6845
  } catch (err) {
6588
6846
  this.agentsStarting.delete(agentId);
6589
6847
  throw err;
@@ -7103,6 +7361,30 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
7103
7361
  logger.info(`[Agent ${agentId}] Deferred non-concrete wake message for ${driver.id}`);
7104
7362
  return true;
7105
7363
  }
7364
+ completeDeprecatedRuntimeProfileMigration(agentId, migrationKey, launchId, traceparent, source) {
7365
+ this.sendToServer({
7366
+ type: "agent:runtime_profile:migration:ack",
7367
+ agentId,
7368
+ migrationKey,
7369
+ launchId: launchId || void 0,
7370
+ traceparent
7371
+ });
7372
+ this.sendToServer({
7373
+ type: "agent:runtime_profile:migration_done",
7374
+ agentId,
7375
+ migrationKey,
7376
+ launchId: launchId || void 0,
7377
+ traceparent
7378
+ });
7379
+ this.recordDaemonTrace("daemon.runtime_profile.migration.deprecated_noop", {
7380
+ agentId,
7381
+ key_present: Boolean(migrationKey),
7382
+ key_hash: hashRuntimeProfileKey(migrationKey),
7383
+ launchId: launchId || void 0,
7384
+ source
7385
+ });
7386
+ logger.info(`[Agent ${agentId}] Completed deprecated Runtime Profile migration ${migrationKey} as reset-session no-op`);
7387
+ }
7106
7388
  getAgentSessionId(agentId) {
7107
7389
  return this.agents.get(agentId)?.sessionId ?? null;
7108
7390
  }
@@ -7164,7 +7446,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
7164
7446
  }
7165
7447
  return reports;
7166
7448
  }
7167
- deliverRuntimeProfileNotification(agentId, key, kind, content, traceparent) {
7449
+ deliverRuntimeProfileNotification(agentId, key, kind, content, traceparent, launchId) {
7168
7450
  const span = this.tracer.startSpan("daemon.runtime_profile.control.inject", {
7169
7451
  parent: parseTraceparent(traceparent),
7170
7452
  surface: "daemon",
@@ -7176,6 +7458,17 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
7176
7458
  key_hash: hashRuntimeProfileKey(key)
7177
7459
  }
7178
7460
  });
7461
+ if (kind === "migration") {
7462
+ this.completeDeprecatedRuntimeProfileMigration(
7463
+ agentId,
7464
+ key,
7465
+ launchId || null,
7466
+ formatTraceparent(span.context),
7467
+ "runtime_profile_message"
7468
+ );
7469
+ span.end("ok", { attrs: { outcome: "deprecated_noop_completed", launchId: launchId || void 0 } });
7470
+ return true;
7471
+ }
7179
7472
  const now = (/* @__PURE__ */ new Date()).toISOString();
7180
7473
  const message = {
7181
7474
  channel_id: "system",
@@ -7186,7 +7479,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
7186
7479
  sender_type: "system",
7187
7480
  content,
7188
7481
  timestamp: now,
7189
- message_id: `${kind === "migration" ? RUNTIME_PROFILE_MIGRATION_MESSAGE_PREFIX : RUNTIME_PROFILE_DAEMON_NOTICE_MESSAGE_PREFIX}${key}`,
7482
+ message_id: `${RUNTIME_PROFILE_DAEMON_NOTICE_MESSAGE_PREFIX}${key}`,
7190
7483
  traceparent: formatTraceparent(span.context)
7191
7484
  };
7192
7485
  const ap = this.agents.get(agentId);
@@ -7281,25 +7574,19 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
7281
7574
  for (const message of messages) {
7282
7575
  const notification = runtimeProfileNotificationFromMessage(message);
7283
7576
  if (!notification) continue;
7284
- const title = runtimeProfileNotificationTitle(notification.kind);
7285
- this.broadcastActivity(agentId, "working", title, [{ kind: "system", title, text: message.content }], launchId);
7286
7577
  if (notification.kind === "migration") {
7287
- this.sendToServer({
7288
- type: "agent:runtime_profile:migration:ack",
7289
- agentId,
7290
- migrationKey: notification.key,
7291
- launchId: launchId || void 0,
7292
- traceparent: message.traceparent
7293
- });
7294
- } else {
7295
- this.sendToServer({
7296
- type: "agent:runtime_profile:daemon_release_notice:ack",
7297
- agentId,
7298
- noticeKey: notification.key,
7299
- launchId: launchId || void 0,
7300
- traceparent: message.traceparent
7301
- });
7578
+ this.completeDeprecatedRuntimeProfileMigration(agentId, notification.key, launchId, message.traceparent, "runtime_profile_message");
7579
+ continue;
7302
7580
  }
7581
+ const title = runtimeProfileNotificationTitle(notification.kind);
7582
+ this.broadcastActivity(agentId, "working", title, [{ kind: "system", title, text: message.content }], launchId);
7583
+ this.sendToServer({
7584
+ type: "agent:runtime_profile:daemon_release_notice:ack",
7585
+ agentId,
7586
+ noticeKey: notification.key,
7587
+ launchId: launchId || void 0,
7588
+ traceparent: message.traceparent
7589
+ });
7303
7590
  }
7304
7591
  }
7305
7592
  ackInjectedRuntimeProfileControl(agentId, control, launchId) {
@@ -7316,24 +7603,19 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
7316
7603
  }
7317
7604
  });
7318
7605
  const title = runtimeProfileNotificationTitle(control.kind);
7319
- this.broadcastActivity(agentId, "working", title, [{ kind: "system", title, text: control.message }], launchId);
7320
7606
  if (control.kind === "migration") {
7321
- this.sendToServer({
7322
- type: "agent:runtime_profile:migration:ack",
7323
- agentId,
7324
- migrationKey: control.key,
7325
- launchId: launchId || void 0,
7326
- traceparent: formatTraceparent(span.context)
7327
- });
7328
- } else {
7329
- this.sendToServer({
7330
- type: "agent:runtime_profile:daemon_release_notice:ack",
7331
- agentId,
7332
- noticeKey: control.key,
7333
- launchId: launchId || void 0,
7334
- traceparent: formatTraceparent(span.context)
7335
- });
7607
+ this.completeDeprecatedRuntimeProfileMigration(agentId, control.key, launchId, formatTraceparent(span.context), "agent_config");
7608
+ span.end("ok", { attrs: { outcome: "deprecated_noop_completed" } });
7609
+ return;
7336
7610
  }
7611
+ this.broadcastActivity(agentId, "working", title, [{ kind: "system", title, text: control.message }], launchId);
7612
+ this.sendToServer({
7613
+ type: "agent:runtime_profile:daemon_release_notice:ack",
7614
+ agentId,
7615
+ noticeKey: control.key,
7616
+ launchId: launchId || void 0,
7617
+ traceparent: formatTraceparent(span.context)
7618
+ });
7337
7619
  span.end("ok", { attrs: { outcome: "agent_config_ack_sent" } });
7338
7620
  }
7339
7621
  sendRuntimeProfileWireReport(report) {
@@ -7774,7 +8056,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
7774
8056
  runtime_profile_key_hash: control.keyHash || void 0,
7775
8057
  runtime_profile_key_present: control.keyPresent,
7776
8058
  runtime_profile_pending_age_ms: pendingAgeMs,
7777
- runtime_profile_requires_ack: control.kind === "migration",
8059
+ runtime_profile_requires_ack: false,
7778
8060
  runtime_profile_migration_done_observed: control.kind === "migration" ? control.migrationDoneToolObserved : void 0
7779
8061
  };
7780
8062
  }
@@ -7801,19 +8083,11 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
7801
8083
  const control = ap.runtimeProfileTurnControl;
7802
8084
  if (!control) return {};
7803
8085
  const attrs = this.runtimeProfileTurnControlTraceAttrs(control);
7804
- if (control.kind === "migration" && !control.migrationDoneToolObserved) {
7805
- this.recordRuntimeTraceEvent(agentId, ap, "runtime_profile.migration.turn_without_ack", {
7806
- ...attrs,
7807
- terminal,
7808
- inbox_count: ap.inbox.length,
7809
- pending_notification_count: ap.pendingNotificationCount
7810
- });
7811
- }
7812
8086
  ap.runtimeProfileTurnControl = null;
7813
8087
  return {
7814
8088
  ...attrs,
7815
8089
  runtime_profile_turn_terminal: terminal,
7816
- runtime_profile_turn_outcome: control.kind === "migration" ? control.migrationDoneToolObserved ? "migration_done_observed" : "missing_migration_done" : "notice_only"
8090
+ runtime_profile_turn_outcome: control.kind === "migration" ? control.migrationDoneToolObserved ? "deprecated_migration_done_observed" : "reset_session_notice" : "notice_only"
7817
8091
  };
7818
8092
  }
7819
8093
  startRuntimeTrace(agentId, ap, reason, messages, inputTraceAttrs = {}) {
@@ -7854,10 +8128,42 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
7854
8128
  recordRuntimeTraceEvent(agentId, ap, name, attrs) {
7855
8129
  this.startRuntimeTrace(agentId, ap, "runtime-progress").addEvent(name, attrs);
7856
8130
  }
7857
- noteRuntimeProgress(ap) {
8131
+ noteRuntimeProgress(ap, eventKind) {
7858
8132
  ap.lastRuntimeEventAt = Date.now();
8133
+ ap.lastRuntimeEventKind = eventKind ?? null;
7859
8134
  ap.runtimeProgressStaleSince = null;
7860
8135
  }
8136
+ observeRuntimeTranscriptProgress(agentId, ap, staleForMs, source) {
8137
+ if (ap.config.runtime !== "codex" || !ap.sessionId) return false;
8138
+ const ref = resolveRuntimeSessionRef(ap.config.runtime, ap.sessionId, this.runtimeSessionHomeDir);
8139
+ if (!ref.reachable || !ref.path) return false;
8140
+ let mtimeMs;
8141
+ try {
8142
+ const stats = statSync2(ref.path);
8143
+ if (!stats.isFile()) return false;
8144
+ mtimeMs = stats.mtimeMs;
8145
+ } catch {
8146
+ return false;
8147
+ }
8148
+ if (mtimeMs <= ap.lastRuntimeEventAt) return false;
8149
+ const now = Date.now();
8150
+ const transcriptAgeMs = Math.max(0, now - mtimeMs);
8151
+ if (transcriptAgeMs >= RUNTIME_PROGRESS_STALE_MS) return false;
8152
+ ap.lastRuntimeEventAt = mtimeMs;
8153
+ ap.runtimeProgressStaleSince = null;
8154
+ this.recordRuntimeTraceEvent(agentId, ap, "runtime.progress.internal_observed", {
8155
+ turn_outcome: "held",
8156
+ turn_subtype: "runtime_progress",
8157
+ turn_reason: "internal_activity_observed",
8158
+ signal: "runtime_transcript_mtime",
8159
+ source,
8160
+ runtime: ap.config.runtime,
8161
+ sessionRefReachable: true,
8162
+ transcriptAgeMs,
8163
+ previousStaleForMs: staleForMs
8164
+ });
8165
+ return true;
8166
+ }
7861
8167
  recordGatedSteeringEvent(agentId, ap, event, attrs = {}) {
7862
8168
  if (ap.driver.busyDeliveryMode !== "gated") return;
7863
8169
  const summary = `${event}:${ap.gatedSteering.phase}:tools=${ap.gatedSteering.outstandingToolUses}:compact=${ap.gatedSteering.compacting}`;
@@ -7937,6 +8243,66 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
7937
8243
  ap.gatedSteering.inFlightBatch = null;
7938
8244
  this.recordGatedSteeringEvent(agentId, ap, "ack", { reason, messageCount });
7939
8245
  }
8246
+ startRuntimeStartupTimeout(agentId, ap) {
8247
+ const timeoutMs = runtimeStartTimeoutMs();
8248
+ if (timeoutMs <= 0) return;
8249
+ ap.startupTimeoutTimer = setTimeout(() => {
8250
+ this.handleRuntimeStartupTimeout(agentId, ap, timeoutMs);
8251
+ }, timeoutMs);
8252
+ ap.startupTimeoutTimer.unref?.();
8253
+ }
8254
+ clearRuntimeStartupTimeout(ap) {
8255
+ if (!ap.startupTimeoutTimer) return;
8256
+ clearTimeout(ap.startupTimeoutTimer);
8257
+ ap.startupTimeoutTimer = null;
8258
+ }
8259
+ handleRuntimeStartupTimeout(agentId, ap, timeoutMs) {
8260
+ const current = this.agents.get(agentId);
8261
+ if (current !== ap) return;
8262
+ if (ap.lastRuntimeEventKind) {
8263
+ this.clearRuntimeStartupTimeout(ap);
8264
+ return;
8265
+ }
8266
+ this.clearRuntimeStartupTimeout(ap);
8267
+ const terminalFailureDetail = classifyTerminalFailure(ap);
8268
+ const detail = terminalFailureDetail?.detail ?? formatRuntimeStartTimeoutMessage(ap.driver.id);
8269
+ ap.startupTimedOut = true;
8270
+ ap.lastRuntimeError = detail;
8271
+ ap.runtimeProgressStaleSince = Date.now();
8272
+ const staleForMs = Math.max(timeoutMs, Date.now() - ap.lastRuntimeEventAt);
8273
+ const diagnostic = buildRuntimeStallDiagnostic(ap, staleForMs, Math.max(1, Math.floor(staleForMs / 6e4)));
8274
+ this.recordRuntimeTraceEvent(agentId, ap, "runtime.start.timeout", {
8275
+ turn_outcome: "failed",
8276
+ turn_subtype: "runtime_stalled",
8277
+ turn_reason: "no_runtime_events",
8278
+ runtime_start_failure_kind: "runtime_start_timeout",
8279
+ timeout_ms: timeoutMs,
8280
+ ...diagnostic.traceAttrs
8281
+ });
8282
+ this.endRuntimeTrace(ap, "error", {
8283
+ turn_outcome: "failed",
8284
+ turn_subtype: "runtime_stalled",
8285
+ turn_reason: "no_runtime_events",
8286
+ runtime_start_failure_kind: "runtime_start_timeout",
8287
+ timeout_ms: timeoutMs,
8288
+ ...runtimeTraceCounterAttrs(ap),
8289
+ ...this.finalizeRuntimeProfileTurnControl(agentId, ap, "runtime_stalled")
8290
+ });
8291
+ logger.warn(`[Agent ${agentId}] ${ap.driver.id} did not emit a startup runtime event within ${timeoutMs}ms; terminating process`);
8292
+ this.broadcastActivity(agentId, "error", detail, [{ kind: "text", text: `Error: ${detail}` }], ap.launchId);
8293
+ this.sendAgentStatus(agentId, "inactive", ap.launchId);
8294
+ this.idleAgentConfigs.delete(agentId);
8295
+ try {
8296
+ this.processExitTraceAttrs.set(ap.process, {
8297
+ stop_source: "startup_timeout",
8298
+ timeout_ms: timeoutMs
8299
+ });
8300
+ ap.process.kill("SIGTERM");
8301
+ } catch (err) {
8302
+ const reason = err instanceof Error ? err.message : String(err);
8303
+ logger.warn(`[Agent ${agentId}] Failed to terminate startup-timed-out ${ap.driver.id} process: ${reason}`);
8304
+ }
8305
+ }
7940
8306
  requeueGatedInFlightBatch(agentId, ap, reason) {
7941
8307
  if (ap.driver.busyDeliveryMode !== "gated" || !ap.gatedSteering.inFlightBatch) return;
7942
8308
  const batch = ap.gatedSteering.inFlightBatch;
@@ -7957,12 +8323,21 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
7957
8323
  if (ap.runtimeProgressStaleSince) return true;
7958
8324
  const staleForMs = Date.now() - ap.lastRuntimeEventAt;
7959
8325
  if (staleForMs < RUNTIME_PROGRESS_STALE_MS) return false;
8326
+ if (this.observeRuntimeTranscriptProgress(agentId, ap, staleForMs, "activity_heartbeat")) return false;
7960
8327
  ap.runtimeProgressStaleSince = Date.now();
7961
8328
  const staleForMinutes = Math.max(1, Math.floor(staleForMs / 6e4));
7962
8329
  const diagnostic = buildRuntimeStallDiagnostic(ap, staleForMs, staleForMinutes);
7963
- this.recordRuntimeTraceEvent(agentId, ap, "runtime.progress.stalled", diagnostic.traceAttrs);
8330
+ const turnReason = classifyRuntimeStallReason(ap);
8331
+ this.recordRuntimeTraceEvent(agentId, ap, "runtime.progress.stalled", {
8332
+ turn_outcome: "failed",
8333
+ turn_subtype: "runtime_stalled",
8334
+ turn_reason: turnReason,
8335
+ ...diagnostic.traceAttrs
8336
+ });
7964
8337
  this.endRuntimeTrace(ap, "error", {
7965
- outcome: "runtime-stalled",
8338
+ turn_outcome: "failed",
8339
+ turn_subtype: "runtime_stalled",
8340
+ turn_reason: turnReason,
7966
8341
  ageMs: staleForMs,
7967
8342
  lastActivity: ap.lastActivity,
7968
8343
  lastActivityDetailPresent: Boolean(ap.lastActivityDetail),
@@ -7984,16 +8359,23 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
7984
8359
  if (!canRestartStalledProcess) return false;
7985
8360
  const staleForMs = Date.now() - ap.lastRuntimeEventAt;
7986
8361
  if (staleForMs < RUNTIME_PROGRESS_STALE_MS && !ap.runtimeProgressStaleSince) return false;
8362
+ if (this.observeRuntimeTranscriptProgress(agentId, ap, staleForMs, "queued_recovery")) return false;
7987
8363
  const staleForMinutes = Math.max(1, Math.floor(staleForMs / 6e4));
7988
8364
  ap.runtimeProgressStaleSince ??= Date.now();
7989
8365
  const diagnostic = buildRuntimeStallDiagnostic(ap, staleForMs, staleForMinutes);
8366
+ const turnReason = classifyRuntimeStallReason(ap);
7990
8367
  this.recordRuntimeTraceEvent(agentId, ap, "runtime.progress.stalled", {
8368
+ turn_outcome: "failed",
8369
+ turn_subtype: "runtime_stalled",
8370
+ turn_reason: turnReason,
7991
8371
  ...diagnostic.traceAttrs,
7992
8372
  pendingMessages: ap.inbox.length,
7993
8373
  recovery: "terminate_for_queued_message"
7994
8374
  });
7995
8375
  this.endRuntimeTrace(ap, "error", {
7996
- outcome: "runtime-stalled",
8376
+ turn_outcome: "failed",
8377
+ turn_subtype: "runtime_stalled",
8378
+ turn_reason: turnReason,
7997
8379
  ageMs: staleForMs,
7998
8380
  lastActivity: ap.lastActivity,
7999
8381
  lastActivityDetailPresent: Boolean(ap.lastActivityDetail),
@@ -8030,12 +8412,13 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
8030
8412
  const ap = this.agents.get(agentId);
8031
8413
  if (ap) {
8032
8414
  const wasStalled = Boolean(ap.runtimeProgressStaleSince);
8415
+ this.clearRuntimeStartupTimeout(ap);
8033
8416
  this.noteRuntimeTraceCounter(ap, event);
8034
8417
  this.recordRuntimeTraceEvent(agentId, ap, "runtime.event.received", { kind: event.kind });
8035
8418
  if (wasStalled) {
8036
8419
  this.recordRuntimeTraceEvent(agentId, ap, "runtime.progress.observed", { afterStall: true });
8037
8420
  }
8038
- this.noteRuntimeProgress(ap);
8421
+ this.noteRuntimeProgress(ap, event.kind);
8039
8422
  }
8040
8423
  switch (event.kind) {
8041
8424
  case "session_init":
@@ -8192,8 +8575,12 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
8192
8575
  this.interruptCompactionIfActive(agentId);
8193
8576
  this.flushPendingTrajectory(agentId);
8194
8577
  if (ap) ap.lastRuntimeError = event.message;
8578
+ let visibleErrorMessage = event.message;
8195
8579
  if (ap) {
8196
8580
  const runtimeErrorDiagnostics = buildRuntimeErrorDiagnosticEnvelope(event.message);
8581
+ if (runtimeErrorDiagnostics.spanAttrs.runtime_error_action_required === true) {
8582
+ visibleErrorMessage = formatRuntimeLoginRequiredMessage(ap.driver.id);
8583
+ }
8197
8584
  this.setGatedSteeringPhase(agentId, ap, "error", { event: "error" });
8198
8585
  if (ap.driver.busyDeliveryMode === "gated" && this.isThinkingBlockMutationError(event.message)) {
8199
8586
  this.requeueGatedInFlightBatch(agentId, ap, "thinking_block_mutation_error");
@@ -8217,18 +8604,33 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
8217
8604
  ...runtimeTraceCounterAttrs(ap),
8218
8605
  ...this.finalizeRuntimeProfileTurnControl(agentId, ap, "runtime_error")
8219
8606
  });
8220
- if (ap.driver.supportsStdinNotification && classifyTerminalFailure(ap)) {
8221
- ap.isIdle = true;
8222
- ap.pendingNotificationCount = 0;
8223
- if (ap.notificationTimer) {
8224
- clearTimeout(ap.notificationTimer);
8225
- ap.notificationTimer = null;
8607
+ const terminalFailure = classifyTerminalFailure(ap);
8608
+ if (ap.driver.supportsStdinNotification && terminalFailure) {
8609
+ if (terminalFailure.actionRequired) {
8610
+ logger.warn(`[Agent ${agentId}] ${ap.driver.id} auth requires user action; terminating runtime process`);
8611
+ try {
8612
+ this.processExitTraceAttrs.set(ap.process, {
8613
+ stop_source: "runtime_auth_error",
8614
+ runtime_error_class: "AuthError"
8615
+ });
8616
+ ap.process.kill("SIGTERM");
8617
+ } catch (err) {
8618
+ const reason = err instanceof Error ? err.message : String(err);
8619
+ logger.warn(`[Agent ${agentId}] Failed to terminate ${ap.driver.id} after auth error: ${reason}`);
8620
+ }
8621
+ } else {
8622
+ ap.isIdle = true;
8623
+ ap.pendingNotificationCount = 0;
8624
+ if (ap.notificationTimer) {
8625
+ clearTimeout(ap.notificationTimer);
8626
+ ap.notificationTimer = null;
8627
+ }
8628
+ logger.info(`[Agent ${agentId}] Marked ${ap.driver.id} wakeable after terminal runtime error`);
8226
8629
  }
8227
- logger.info(`[Agent ${agentId}] Marked ${ap.driver.id} wakeable after terminal runtime error`);
8228
8630
  }
8229
8631
  }
8230
- this.broadcastActivity(agentId, "error", event.message, [
8231
- { kind: "text", text: `Error: ${event.message}` }
8632
+ this.broadcastActivity(agentId, "error", visibleErrorMessage, [
8633
+ { kind: "text", text: `Error: ${visibleErrorMessage}` }
8232
8634
  ]);
8233
8635
  break;
8234
8636
  }
@@ -8346,6 +8748,30 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
8346
8748
  /** Deliver a message to an agent via stdin, formatting it the same way as the MCP bridge */
8347
8749
  deliverMessagesViaStdin(agentId, ap, messages, mode) {
8348
8750
  if (messages.length === 0) return true;
8751
+ const runtimeProfileMigrationMessages = messages.filter((message) => runtimeProfileNotificationFromMessage(message)?.kind === "migration");
8752
+ if (runtimeProfileMigrationMessages.length > 0) {
8753
+ for (const message of runtimeProfileMigrationMessages) {
8754
+ const notification = runtimeProfileNotificationFromMessage(message);
8755
+ if (notification?.kind === "migration") {
8756
+ this.completeDeprecatedRuntimeProfileMigration(agentId, notification.key, ap.launchId, message.traceparent, "runtime_profile_message");
8757
+ }
8758
+ }
8759
+ messages = messages.filter((message) => runtimeProfileNotificationFromMessage(message)?.kind !== "migration");
8760
+ this.recordDaemonTrace("daemon.agent.runtime_profile.deprecated_migration_filtered", {
8761
+ agentId,
8762
+ launchId: ap.launchId || void 0,
8763
+ runtime: ap.config.runtime,
8764
+ mode,
8765
+ filtered_messages_count: runtimeProfileMigrationMessages.length,
8766
+ remaining_messages_count: messages.length
8767
+ });
8768
+ if (messages.length === 0) {
8769
+ if (mode === "idle") {
8770
+ ap.isIdle = true;
8771
+ }
8772
+ return true;
8773
+ }
8774
+ }
8349
8775
  const split = this.splitRuntimeProfileControlBatch(messages);
8350
8776
  if (split.deferredMessages.length > 0) {
8351
8777
  ap.inbox.unshift(...split.deferredMessages);
@@ -8751,7 +9177,7 @@ var ReminderCache = class {
8751
9177
  };
8752
9178
 
8753
9179
  // src/machineLock.ts
8754
- import { createHash as createHash3, randomUUID as randomUUID2 } from "crypto";
9180
+ import { createHash as createHash3, randomUUID as randomUUID3 } from "crypto";
8755
9181
  import { mkdirSync as mkdirSync5, readFileSync as readFileSync6, rmSync as rmSync3, statSync as statSync3, writeFileSync as writeFileSync8 } from "fs";
8756
9182
  import os7 from "os";
8757
9183
  import path13 from "path";
@@ -8808,7 +9234,7 @@ function acquireDaemonMachineLock(options) {
8808
9234
  const lockId = getDaemonMachineLockId(options.apiKey);
8809
9235
  const machineDir = path13.join(rootDir, lockId);
8810
9236
  const lockDir = path13.join(machineDir, "daemon.lock");
8811
- const token = randomUUID2();
9237
+ const token = randomUUID3();
8812
9238
  mkdirSync5(machineDir, { recursive: true });
8813
9239
  for (let attempt = 0; attempt < 2; attempt += 1) {
8814
9240
  try {
@@ -9025,7 +9451,7 @@ function isDiagnosticErrorAttr(key) {
9025
9451
  }
9026
9452
 
9027
9453
  // src/traceBundleUpload.ts
9028
- import { createHash as createHash5, randomUUID as randomUUID3 } from "crypto";
9454
+ import { createHash as createHash5, randomUUID as randomUUID4 } from "crypto";
9029
9455
  import { gzipSync } from "zlib";
9030
9456
  import { mkdir as mkdir2, readFile as readFile2, readdir as readdir3, stat as stat3, writeFile as writeFile2 } from "fs/promises";
9031
9457
  import path15 from "path";
@@ -9296,7 +9722,7 @@ var DaemonTraceBundleUploader = class {
9296
9722
  }
9297
9723
  const gzipped = gzipSync(raw);
9298
9724
  const bundleSha256 = sha256Hex(gzipped);
9299
- const bundleId = randomUUID3();
9725
+ const bundleId = randomUUID4();
9300
9726
  await uploadWithSignedCapability({
9301
9727
  serverUrl: this.options.serverUrl,
9302
9728
  apiKey: this.options.apiKey,
@@ -9924,7 +10350,7 @@ var DaemonCore = class {
9924
10350
  });
9925
10351
  logger.info(`[Agent ${msg.agentId}] Runtime profile migration received (${msg.migrationKey})`);
9926
10352
  Promise.resolve(
9927
- this.agentManager.deliverRuntimeProfileNotification(msg.agentId, msg.migrationKey, "migration", msg.message, formatTraceparent(span.context))
10353
+ this.agentManager.deliverRuntimeProfileNotification(msg.agentId, msg.migrationKey, "migration", msg.message, formatTraceparent(span.context), msg.launchId || null)
9928
10354
  ).then((accepted) => {
9929
10355
  span.end("ok", { attrs: { outcome: accepted ? "accepted" : "no_injection_path" } });
9930
10356
  }, (err) => {
@@ -9947,7 +10373,7 @@ var DaemonCore = class {
9947
10373
  });
9948
10374
  logger.info(`[Agent ${msg.agentId}] Runtime profile daemon release notice received (${msg.noticeKey})`);
9949
10375
  Promise.resolve(
9950
- this.agentManager.deliverRuntimeProfileNotification(msg.agentId, msg.noticeKey, "daemon_release_notice", msg.message, formatTraceparent(span.context))
10376
+ this.agentManager.deliverRuntimeProfileNotification(msg.agentId, msg.noticeKey, "daemon_release_notice", msg.message, formatTraceparent(span.context), msg.launchId || null)
9951
10377
  ).then((accepted) => {
9952
10378
  span.end("ok", { attrs: { outcome: accepted ? "accepted" : "no_injection_path" } });
9953
10379
  }, (err) => {