@slock-ai/daemon 0.55.7-play.20260602150229 → 0.56.0

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.
@@ -939,10 +939,12 @@ var actionCardActionSchema = z.discriminatedUnion("type", [
939
939
  ]);
940
940
 
941
941
  // ../shared/src/agentInbox.ts
942
- function formatAgentInboxDelta(rows) {
943
- if (rows.length === 0) return "Inbox update: no pending targets";
942
+ function formatAgentInboxDelta(rows, options = {}) {
943
+ const totalPendingMessages = options.totalPendingMessages;
944
+ const header = typeof totalPendingMessages === "number" ? `Inbox update: ${totalPendingMessages} unread message${totalPendingMessages === 1 ? "" : "s"} total; ${rows.length === 0 ? "no" : rows.length} changed target${rows.length === 1 ? "" : "s"}` : `Inbox update: ${rows.length} changed target${rows.length === 1 ? "" : "s"}`;
945
+ if (rows.length === 0) return typeof totalPendingMessages === "number" ? header : "Inbox update: no pending targets";
944
946
  return [
945
- `Inbox update: ${rows.length} changed target${rows.length === 1 ? "" : "s"}`,
947
+ header,
946
948
  ...rows.map((row) => `${row.target} ${formatAgentInboxRowDetails(row)}`)
947
949
  ].join("\n");
948
950
  }
@@ -1305,6 +1307,7 @@ function buildPrompt(config, variant, opts) {
1305
1307
  const sendCmd = isCli ? "`slock message send`" : `\`${t("send_message")}\``;
1306
1308
  const readCmd = isCli ? "`slock message read`" : `\`${t("read_history")}\``;
1307
1309
  const checkCmd = isCli ? "`slock message check`" : `\`${t("check_messages")}\``;
1310
+ const inboxCheckCmd = isCli ? "`slock inbox check`" : checkCmd;
1308
1311
  const taskClaimCmd = isCli ? "`slock task claim`" : `\`${t("claim_tasks")}\``;
1309
1312
  const taskCreateCmd = isCli ? "`slock task create`" : `\`${t("create_tasks")}\``;
1310
1313
  const taskUpdateCmd = isCli ? "`slock task update`" : `\`${t("update_task_status")}\``;
@@ -1785,14 +1788,14 @@ You may develop a specialized role over time through your interactions. Embrace
1785
1788
 
1786
1789
  ## Message Notifications
1787
1790
 
1788
- While you are working, the daemon may write a batched inbox-count notification into your current turn.
1791
+ While you are working, the daemon may write a batched, content-free inbox update into your current turn.
1789
1792
 
1790
1793
  How to handle these:
1791
- - Treat the notification as a signal that new Slock messages are waiting; it does not include the message content.
1792
- - Call ${checkCmd} at the next safe breakpoint to materialize the pending messages before taking side-effect actions that depend on current context.
1793
- - If the new message is higher priority, pivot after reading it. If not, continue your current work.`;
1794
+ - Treat the notification as a non-urgent signal that new Slock messages are waiting; it does not include the message content and does not require an immediate interruption.
1795
+ - Keep working until a natural breakpoint. If you then choose to inspect pending targets, call ${inboxCheckCmd}; use ${checkCmd} / ${readCmd} when you choose to inspect message content.
1796
+ - If a message you explicitly read is higher priority, pivot to it. If not, continue your current work.`;
1794
1797
  } else {
1795
- const notifyExample = isCli ? `\`[Slock inbox notice: You have N pending inbox message(s). Call slock message check to read them when you're ready.]\`` : `\`[Slock inbox notice: You have N pending inbox message(s). Call ${t("check_messages")} to read them when you're ready.]\``;
1798
+ const notifyExample = isCli ? `\`[Slock inbox notice:\\nInbox update: N unread messages total; M changed targets\\n#channel pending: K messages ...]\`` : `\`[Slock inbox notice:\\nInbox update: N unread messages total; M changed targets\\n#channel pending: K messages ...]\``;
1796
1799
  prompt += `
1797
1800
 
1798
1801
  ## Message Notifications
@@ -1802,9 +1805,9 @@ While you are busy (executing tools, thinking, etc.), new messages may arrive. W
1802
1805
  ${notifyExample}
1803
1806
 
1804
1807
  How to handle these:
1805
- - Call ${checkCmd} to check for new messages. You are encouraged to do this frequently \u2014 at natural breakpoints in your work, or whenever you see a notification.
1806
- - If the new message is higher priority, you may pivot to it. If not, continue your current work.
1807
- - ${checkCmd} returns instantly with any pending messages (or "no new messages"). It is always safe to call.`;
1808
+ - The notice is target-scoped and content-free. Its header may show total unread/pending count, while detail rows list the targets changed by this update; it never includes message bodies.
1809
+ - Do not interrupt the current step just because a notice arrived. At a natural breakpoint, call ${inboxCheckCmd} if you choose to inspect pending targets, or use ${checkCmd} / ${readCmd} when you choose to inspect message content.
1810
+ - If a message you explicitly read is higher priority, you may pivot to it. If not, continue your current work.`;
1808
1811
  }
1809
1812
  }
1810
1813
  if (config.description) {
@@ -1858,19 +1861,6 @@ function listLegacySlockStatePaths(slockHome = resolveSlockHome(), homeDir = os.
1858
1861
  return candidates.filter((candidate) => existsSync(candidate.path));
1859
1862
  }
1860
1863
 
1861
- // src/authEnv.ts
1862
- var DAEMON_API_KEY_ENV = "SLOCK_MACHINE_API_KEY";
1863
- var SLOCK_AGENT_TOKEN_ENV = "SLOCK_AGENT_TOKEN";
1864
- function scrubDaemonAuthEnv(env) {
1865
- delete env[DAEMON_API_KEY_ENV];
1866
- return env;
1867
- }
1868
- function scrubDaemonChildEnv(env) {
1869
- delete env[DAEMON_API_KEY_ENV];
1870
- delete env[SLOCK_AGENT_TOKEN_ENV];
1871
- return env;
1872
- }
1873
-
1874
1864
  // src/agentCredentialProxy.ts
1875
1865
  import { randomBytes } from "crypto";
1876
1866
  import http from "http";
@@ -3026,9 +3016,7 @@ var LOOPBACK_NO_PROXY = "127.0.0.1,localhost";
3026
3016
  var CLI_TRANSPORT_TRACE_DIR_ENV = "SLOCK_CLI_TRANSPORT_TRACE_DIR";
3027
3017
  var safePathPart = (value) => value.replace(/[^a-zA-Z0-9_.-]/g, "_");
3028
3018
  var RAW_CREDENTIAL_ENV_DENYLIST = [
3029
- "SLOCK_AGENT_TOKEN",
3030
- "SLOCK_AGENT_CREDENTIAL_KEY",
3031
- "SLOCK_AGENT_CREDENTIAL_KEY_FILE"
3019
+ "SLOCK_AGENT_CREDENTIAL_KEY"
3032
3020
  ];
3033
3021
  var cachedOpencliBinPath;
3034
3022
  function resolveOpencliBinPath() {
@@ -3243,7 +3231,7 @@ exec ${shellSingleQuote(process.execPath)} ${shellSingleQuote(opencliBinPath)} "
3243
3231
  ...agentCredentialProxy ? {} : { SLOCK_AGENT_TOKEN_FILE: tokenFile },
3244
3232
  PATH: `${slockDir}${path2.delimiter}${process.env.PATH ?? ""}`
3245
3233
  };
3246
- scrubDaemonChildEnv(spawnEnv);
3234
+ delete spawnEnv.SLOCK_AGENT_TOKEN;
3247
3235
  for (const key of RAW_CREDENTIAL_ENV_DENYLIST) {
3248
3236
  delete spawnEnv[key];
3249
3237
  }
@@ -3672,7 +3660,7 @@ function resolveCommandOnWindows(command, env, execFileSyncFn, existsSyncFn) {
3672
3660
  }
3673
3661
  function resolveCommandOnPath(command, deps = {}) {
3674
3662
  const platform = deps.platform ?? process.platform;
3675
- const env = scrubDaemonChildEnv({ ...withWindowsUserEnvironment(deps.env ?? process.env, deps) });
3663
+ const env = withWindowsUserEnvironment(deps.env ?? process.env, deps);
3676
3664
  const execFileSyncFn = deps.execFileSyncFn ?? execFileSync;
3677
3665
  const existsSyncFn = deps.existsSyncFn ?? existsSync2;
3678
3666
  if (platform === "win32") {
@@ -3698,7 +3686,7 @@ function firstExistingPath(candidates, deps = {}) {
3698
3686
  return null;
3699
3687
  }
3700
3688
  function readCommandVersion(command, args = [], deps = {}) {
3701
- const env = scrubDaemonChildEnv({ ...withWindowsUserEnvironment(deps.env ?? process.env, deps) });
3689
+ const env = withWindowsUserEnvironment(deps.env ?? process.env, deps);
3702
3690
  const execFileSyncFn = deps.execFileSyncFn ?? execFileSync;
3703
3691
  try {
3704
3692
  const output = normalizeExecOutput(execFileSyncFn(command, [...args, "--version"], {
@@ -5161,11 +5149,11 @@ function detectCursorModels(runCommand = runCursorModelsCommand) {
5161
5149
  return parseCursorModelsOutput(String(result.stdout || ""));
5162
5150
  }
5163
5151
  function buildCursorModelProbeEnv(deps = {}) {
5164
- return scrubDaemonChildEnv(withWindowsUserEnvironment({
5152
+ return withWindowsUserEnvironment({
5165
5153
  ...deps.env ?? process.env,
5166
5154
  FORCE_COLOR: "0",
5167
5155
  NO_COLOR: "1"
5168
- }, deps));
5156
+ }, deps);
5169
5157
  }
5170
5158
  function runCursorModelsCommand() {
5171
5159
  return spawnSync("cursor-agent", ["models"], {
@@ -5221,7 +5209,7 @@ function resolveGeminiSpawn(commandArgs, deps = {}) {
5221
5209
  }
5222
5210
  const execFileSyncFn = deps.execFileSyncFn ?? execFileSync3;
5223
5211
  const existsSyncFn = deps.existsSyncFn ?? existsSync5;
5224
- const env = scrubDaemonChildEnv({ ...deps.env ?? process.env });
5212
+ const env = deps.env ?? process.env;
5225
5213
  const winPath = path8.win32;
5226
5214
  let geminiEntry = null;
5227
5215
  try {
@@ -5393,16 +5381,13 @@ var GeminiDriver = class {
5393
5381
  // src/drivers/kimi.ts
5394
5382
  import { randomUUID as randomUUID2 } from "crypto";
5395
5383
  import { spawn as spawn7 } from "child_process";
5396
- import { chmodSync, existsSync as existsSync6, readFileSync as readFileSync3, writeFileSync as writeFileSync6 } from "fs";
5384
+ import { existsSync as existsSync6, readFileSync as readFileSync3, writeFileSync as writeFileSync6 } from "fs";
5397
5385
  import os3 from "os";
5398
5386
  import path9 from "path";
5399
5387
  var KIMI_WIRE_PROTOCOL_VERSION = "1.3";
5400
5388
  var KIMI_SYSTEM_PROMPT_FILE = ".slock-kimi-system.md";
5401
5389
  var KIMI_AGENT_FILE = ".slock-kimi-agent.yaml";
5402
5390
  var KIMI_MCP_FILE = ".slock-kimi-mcp.json";
5403
- var KIMI_GENERATED_CONFIG_FILE = ".slock-kimi-config.toml";
5404
- var SLOCK_KIMI_CONFIG_CONTENT_ENV = "SLOCK_KIMI_CONFIG_CONTENT";
5405
- var SLOCK_KIMI_CONFIG_FILE_ENV = "SLOCK_KIMI_CONFIG_FILE";
5406
5391
  function parseToolArguments(raw) {
5407
5392
  if (typeof raw !== "string") return raw;
5408
5393
  try {
@@ -5411,73 +5396,6 @@ function parseToolArguments(raw) {
5411
5396
  return raw;
5412
5397
  }
5413
5398
  }
5414
- function readKimiConfigSource(home = os3.homedir(), env = process.env) {
5415
- const inlineConfig = env[SLOCK_KIMI_CONFIG_CONTENT_ENV];
5416
- if (inlineConfig && inlineConfig.trim()) {
5417
- return {
5418
- raw: inlineConfig,
5419
- explicitPath: null,
5420
- sourcePath: SLOCK_KIMI_CONFIG_CONTENT_ENV
5421
- };
5422
- }
5423
- const explicitPath = env[SLOCK_KIMI_CONFIG_FILE_ENV];
5424
- const configPath = explicitPath && explicitPath.trim() ? explicitPath : path9.join(home, ".kimi", "config.toml");
5425
- try {
5426
- return {
5427
- raw: readFileSync3(configPath, "utf8"),
5428
- explicitPath: explicitPath && explicitPath.trim() ? explicitPath : null,
5429
- sourcePath: configPath
5430
- };
5431
- } catch {
5432
- return {
5433
- raw: null,
5434
- explicitPath: explicitPath && explicitPath.trim() ? explicitPath : null,
5435
- sourcePath: configPath
5436
- };
5437
- }
5438
- }
5439
- function buildKimiSpawnEnv(env = process.env) {
5440
- const spawnEnv = { ...env, FORCE_COLOR: "0", NO_COLOR: "1" };
5441
- delete spawnEnv[SLOCK_KIMI_CONFIG_CONTENT_ENV];
5442
- delete spawnEnv[SLOCK_KIMI_CONFIG_FILE_ENV];
5443
- return scrubDaemonChildEnv(spawnEnv);
5444
- }
5445
- function buildKimiEffectiveEnv(ctx, overrideEnv) {
5446
- return {
5447
- ...process.env,
5448
- ...ctx.config.envVars || {},
5449
- ...overrideEnv || {}
5450
- };
5451
- }
5452
- function buildKimiLaunchOptions(ctx, opts = {}) {
5453
- const env = buildKimiEffectiveEnv(ctx, opts.env);
5454
- const source = readKimiConfigSource(opts.home ?? os3.homedir(), env);
5455
- const args = [];
5456
- let configFilePath = null;
5457
- let configContent = null;
5458
- if (source.explicitPath) {
5459
- configFilePath = source.explicitPath;
5460
- } else if (source.raw !== null && source.sourcePath === SLOCK_KIMI_CONFIG_CONTENT_ENV) {
5461
- configFilePath = path9.join(ctx.workingDirectory, KIMI_GENERATED_CONFIG_FILE);
5462
- configContent = source.raw;
5463
- if (opts.writeGeneratedConfig !== false) {
5464
- writeFileSync6(configFilePath, source.raw, { encoding: "utf8", mode: 384 });
5465
- chmodSync(configFilePath, 384);
5466
- }
5467
- }
5468
- if (configFilePath) {
5469
- args.push("--config-file", configFilePath);
5470
- }
5471
- if (ctx.config.model && ctx.config.model !== "default") {
5472
- args.push("--model", ctx.config.model);
5473
- }
5474
- return {
5475
- args,
5476
- env: buildKimiSpawnEnv(env),
5477
- configFilePath,
5478
- configContent
5479
- };
5480
- }
5481
5399
  function resolveKimiSpawn(commandArgs, deps = {}) {
5482
5400
  return {
5483
5401
  command: resolveCommandOnPath("kimi", deps) ?? "kimi",
@@ -5501,25 +5419,7 @@ var KimiDriver = class {
5501
5419
  };
5502
5420
  model = {
5503
5421
  detectedModelsVerifiedAs: "launchable",
5504
- toLaunchSpec: (modelId, ctx, opts) => {
5505
- if (!ctx) return { args: ["--model", modelId] };
5506
- const launchCtx = {
5507
- ...ctx,
5508
- config: {
5509
- ...ctx.config,
5510
- model: modelId
5511
- }
5512
- };
5513
- const launch = buildKimiLaunchOptions(launchCtx, {
5514
- home: opts?.home,
5515
- writeGeneratedConfig: false
5516
- });
5517
- return {
5518
- args: launch.args,
5519
- env: launch.env,
5520
- configFiles: launch.configFilePath ? [launch.configFilePath] : void 0
5521
- };
5522
- }
5422
+ toLaunchSpec: (modelId) => ({ args: ["--model", modelId] })
5523
5423
  };
5524
5424
  supportsStdinNotification = true;
5525
5425
  mcpToolPrefix = "";
@@ -5573,7 +5473,6 @@ var KimiDriver = class {
5573
5473
  }
5574
5474
  }
5575
5475
  }), "utf8");
5576
- const launch = buildKimiLaunchOptions(ctx);
5577
5476
  const args = [
5578
5477
  "--wire",
5579
5478
  "--yolo",
@@ -5582,16 +5481,15 @@ var KimiDriver = class {
5582
5481
  "--mcp-config-file",
5583
5482
  mcpConfigPath,
5584
5483
  "--session",
5585
- this.sessionId,
5586
- ...launch.args
5484
+ this.sessionId
5587
5485
  ];
5588
5486
  const launchRuntimeFields = runtimeConfigToLaunchFields(ctx.config);
5589
5487
  if (launchRuntimeFields.model && launchRuntimeFields.model !== "default") {
5590
5488
  args.push("--model", launchRuntimeFields.model);
5591
5489
  }
5592
5490
  const spawnEnv = (await prepareCliTransport(ctx, { NO_COLOR: "1" })).spawnEnv;
5593
- const spawnTarget = resolveKimiSpawn(args);
5594
- const proc = spawn7(spawnTarget.command, spawnTarget.args, {
5491
+ const launch = resolveKimiSpawn(args);
5492
+ const proc = spawn7(launch.command, launch.args, {
5595
5493
  cwd: ctx.workingDirectory,
5596
5494
  stdio: ["pipe", "pipe", "pipe"],
5597
5495
  env: spawnEnv,
@@ -5599,7 +5497,7 @@ var KimiDriver = class {
5599
5497
  // and has an 8191-character command-line limit. Kimi's official
5600
5498
  // installer/uv entrypoint is an executable, so launch it directly and
5601
5499
  // keep prompts on stdin / files instead of routing through cmd.exe.
5602
- shell: spawnTarget.shell
5500
+ shell: launch.shell
5603
5501
  });
5604
5502
  proc.stdin?.write(JSON.stringify({
5605
5503
  jsonrpc: "2.0",
@@ -5713,9 +5611,14 @@ var KimiDriver = class {
5713
5611
  return detectKimiModels();
5714
5612
  }
5715
5613
  };
5716
- function detectKimiModels(home = os3.homedir(), opts = {}) {
5717
- const raw = readKimiConfigSource(home, opts.env).raw;
5718
- if (raw === null) return null;
5614
+ function detectKimiModels(home = os3.homedir()) {
5615
+ const configPath = path9.join(home, ".kimi", "config.toml");
5616
+ let raw;
5617
+ try {
5618
+ raw = readFileSync3(configPath, "utf8");
5619
+ } catch {
5620
+ return null;
5621
+ }
5719
5622
  const models = [];
5720
5623
  const sectionRe = /^\s*\[models(?:\.([^\]]+)|"\.[^"]+"|\."[^"]+")\s*\]\s*$/gm;
5721
5624
  const lineRe = /^\s*\[models\.(.+?)\s*\]\s*$/gm;
@@ -5979,7 +5882,7 @@ function runOpenCodeModelsCommand(home, deps = {}) {
5979
5882
  const platform = deps.platform ?? process.platform;
5980
5883
  const spawnSyncFn = deps.spawnSyncFn ?? spawnSync2;
5981
5884
  const result = spawnSyncFn("opencode", ["models"], {
5982
- env: scrubDaemonChildEnv({ ...process.env, HOME: home, FORCE_COLOR: "0", NO_COLOR: "1" }),
5885
+ env: { ...process.env, HOME: home, FORCE_COLOR: "0", NO_COLOR: "1" },
5983
5886
  encoding: "utf8",
5984
5887
  timeout: 5e3,
5985
5888
  shell: platform === "win32"
@@ -6786,7 +6689,9 @@ import { createHash as createHash2 } from "crypto";
6786
6689
  var MAX_RUNTIME_ERROR_MESSAGE_EXCERPT_CHARS = 4096;
6787
6690
  var RUNTIME_AUTH_ACTION_REQUIRED_PATTERNS = [
6788
6691
  /access token could not be refreshed/i,
6692
+ /\btoken_(?:revoked|invalidated)\b/i,
6789
6693
  /refresh token was already used/i,
6694
+ /access token.*invalidated/i,
6790
6695
  /authentication token has been invalidated/i,
6791
6696
  /logged out or signed in to another account/i,
6792
6697
  /not logged in/i,
@@ -6868,6 +6773,9 @@ function classifyRuntimeError(message, httpStatus) {
6868
6773
  return "ProviderApiError";
6869
6774
  }
6870
6775
  if (isRuntimeAuthActionRequiredText(message)) return "AuthError";
6776
+ if (/\bmodel\b.*\bnot supported\b/i.test(message) || /\bunsupported\b.*\bmodel\b/i.test(message) || /\bmodel\b.*\bnot available\b/i.test(message)) {
6777
+ return "ModelConfigError";
6778
+ }
6871
6779
  if (/\b(?:ETIMEDOUT|timeout|timed out)\b/i.test(message)) return "TimeoutError";
6872
6780
  if (/\b(?:ECONNRESET|EPIPE|ECONNREFUSED|ENOTFOUND|EAI_AGAIN)\b/i.test(message) || /\bUnable to connect to API\b/i.test(message)) {
6873
6781
  return "ProviderConnectionError";
@@ -6900,6 +6808,8 @@ function classifyRuntimeErrorReason(runtimeErrorClass) {
6900
6808
  return "auth_failed";
6901
6809
  case "NotFoundError":
6902
6810
  return "not_found";
6811
+ case "ModelConfigError":
6812
+ return "model_config_error";
6903
6813
  case "ProviderServerError":
6904
6814
  return "provider_server_error";
6905
6815
  case "ProviderApiError":
@@ -7901,7 +7811,7 @@ function classifyTerminalFailure(ap) {
7901
7811
  for (const text of candidates) {
7902
7812
  const diagnostics = buildRuntimeErrorDiagnosticEnvelope(text);
7903
7813
  const lower = text.toLowerCase();
7904
- 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)) {
7814
+ 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") || lower.includes("model is not supported") || lower.includes("unsupported model") || /\bmodel\b.*\bnot supported\b/i.test(text) || diagnostics.spanAttrs.runtime_error_action_required === true || isProviderStreamFailureText(text) || isRuntimeStartTimeoutText(text)) {
7905
7815
  const actionRequired = diagnostics.spanAttrs.runtime_error_action_required === true;
7906
7816
  return {
7907
7817
  detail: actionRequired ? formatRuntimeLoginRequiredMessage(ap.driver.id) : text,
@@ -7911,6 +7821,16 @@ function classifyTerminalFailure(ap) {
7911
7821
  }
7912
7822
  return null;
7913
7823
  }
7824
+ function classifyStickyTerminalFailure(ap) {
7825
+ const terminalFailure = classifyTerminalFailure(ap);
7826
+ if (!terminalFailure) return null;
7827
+ if (terminalFailure.actionRequired) return terminalFailure;
7828
+ if (/\bmodel\b.*\bnot supported\b/i.test(terminalFailure.detail)) return terminalFailure;
7829
+ if (/\bunsupported\b.*\bmodel\b/i.test(terminalFailure.detail)) return terminalFailure;
7830
+ if (isProviderStreamFailureText(terminalFailure.detail)) return null;
7831
+ if (isRuntimeStartTimeoutText(terminalFailure.detail)) return null;
7832
+ return null;
7833
+ }
7914
7834
  function isProviderStreamFailureText(text) {
7915
7835
  return /stream closed before response\.completed|error decoding response body/i.test(text);
7916
7836
  }
@@ -8170,17 +8090,17 @@ function sanitizeRuntimeTelemetryPayloadAttrs(attrs) {
8170
8090
  return sanitized;
8171
8091
  }
8172
8092
  function getMessageDeliveryText(driver) {
8173
- return driver.supportsStdinNotification ? "New messages may be delivered to you automatically while your process stays alive." : "The daemon will automatically restart you when new messages arrive.";
8093
+ return driver.supportsStdinNotification ? "New inbox updates may be delivered to you automatically while your process stays alive." : "The daemon will automatically restart you with an inbox update when new messages arrive.";
8174
8094
  }
8175
8095
  function getBusyDeliveryNote(driver) {
8176
8096
  if (!driver.supportsStdinNotification) return "";
8177
8097
  if (driver.busyDeliveryMode === "direct") {
8178
- return "\n\nNote: While you are busy, the daemon may write batched inbox-count notifications into your active turn. Call check_messages to read the pending messages before context-sensitive side effects.";
8098
+ return "\n\nNote: While you are busy, the daemon may write batched content-free inbox updates into your active turn. Finish your current step, then check the inbox or read messages at a natural breakpoint.";
8179
8099
  }
8180
8100
  if (driver.busyDeliveryMode === "gated") {
8181
- return "\n\nNote: While you are busy, the daemon may write batched inbox-count notifications into your active turn at runtime-observed safe boundaries. Call check_messages to read the pending messages before context-sensitive side effects.";
8101
+ return "\n\nNote: While you are busy, the daemon may write batched content-free inbox updates into your active turn at runtime-observed safe boundaries. Finish your current step, then check the inbox or read messages at a natural breakpoint.";
8182
8102
  }
8183
- return "\n\nNote: While you are busy, you may receive [Slock inbox notice: ...] messages. Finish your current step, then call check_messages to check for messages.";
8103
+ return "\n\nNote: While you are busy, you may receive [Slock inbox notice: ...] messages. Finish your current step, then check the inbox or read messages at a natural breakpoint.";
8184
8104
  }
8185
8105
  var NATIVE_STANDING_PROMPT_STARTUP_INPUT = (
8186
8106
  // Claude Code 2.1.114 treats "follow your system prompt" style user turns as
@@ -8735,6 +8655,8 @@ var AgentProcessManager = class _AgentProcessManager {
8735
8655
  const standingPrompt = driver.buildSystemPrompt(runtimeConfig, agentId);
8736
8656
  let prompt;
8737
8657
  let promptSource;
8658
+ let wakeMessageDeliveredAsInboxUpdate = false;
8659
+ const startingInboxMessages = this.startingInboxes.get(agentId) || [];
8738
8660
  if (runtimeConfig.runtimeProfileControl && !wakeMessage) {
8739
8661
  prompt = driver.supportsNativeStandingPrompt ? NATIVE_STANDING_PROMPT_STARTUP_INPUT : formatRuntimeProfileControlStartupInput(runtimeConfig.runtimeProfileControl, driver);
8740
8662
  promptSource = "runtime_profile_control";
@@ -8744,13 +8666,15 @@ var AgentProcessManager = class _AgentProcessManager {
8744
8666
  promptSource = "resume_prompt";
8745
8667
  } else if (wakeMessage) {
8746
8668
  const runtimeProfileControlPrompt = formatRuntimeProfileControlPrompt([wakeMessage]);
8747
- const channelLabel = formatChannelLabel(wakeMessage);
8748
- prompt = runtimeProfileControlPrompt ?? `New message received:
8749
-
8750
- ${formatIncomingMessage(wakeMessage, driver)}`;
8751
- promptSource = runtimeProfileControlPrompt ? "runtime_profile_control_message" : "wake_message";
8669
+ if (runtimeProfileControlPrompt) {
8670
+ prompt = runtimeProfileControlPrompt;
8671
+ } else {
8672
+ wakeMessageDeliveredAsInboxUpdate = true;
8673
+ prompt = this.formatInboxUpdateRuntimeInput([wakeMessage, ...startingInboxMessages], driver);
8674
+ }
8675
+ promptSource = runtimeProfileControlPrompt ? "runtime_profile_control_message" : "wake_inbox_update";
8752
8676
  if (!runtimeProfileControlPrompt && unreadSummary && Object.keys(unreadSummary).length > 0) {
8753
- const otherUnread = Object.entries(unreadSummary).filter(([key]) => key !== channelLabel);
8677
+ const otherUnread = Object.entries(unreadSummary);
8754
8678
  if (otherUnread.length > 0) {
8755
8679
  prompt += `
8756
8680
 
@@ -8761,18 +8685,9 @@ You also have unread messages in other channels:`;
8761
8685
  }
8762
8686
  prompt += `
8763
8687
 
8764
- Use ${communicationCommand(driver, "read_history")} to catch up, or respond to the message above first.`;
8688
+ Use the inbox/read commands at a natural breakpoint if you choose to inspect those targets.`;
8765
8689
  }
8766
8690
  }
8767
- if (!runtimeProfileControlPrompt) {
8768
- prompt += `
8769
-
8770
- Respond as appropriate \u2014 ${dynamicReplyInstruction(driver)}, or take action as needed. Complete ALL your work before stopping.
8771
- ${RESPONSE_TARGET_HINT}
8772
-
8773
- IMPORTANT: If the message requires multi-step work (e.g. research, code changes, testing), complete ALL steps before stopping. Sending a progress update does NOT mean your task is done \u2014 only stop when you have NO more work to do. ${getMessageDeliveryText(driver)}`;
8774
- prompt += getBusyDeliveryNote(driver);
8775
- }
8776
8691
  } else if (isResume && unreadSummary && Object.keys(unreadSummary).length > 0) {
8777
8692
  prompt = `You have unread messages from while you were offline:`;
8778
8693
  for (const [ch, count] of Object.entries(unreadSummary)) {
@@ -8847,7 +8762,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
8847
8762
  const agentProcess = {
8848
8763
  process: proc,
8849
8764
  driver,
8850
- inbox: this.startingInboxes.get(agentId) || [],
8765
+ inbox: wakeMessageDeliveredAsInboxUpdate && wakeMessage ? [wakeMessage, ...startingInboxMessages] : startingInboxMessages,
8851
8766
  config: runtimeConfig,
8852
8767
  sessionId: runtimeConfig.sessionId || null,
8853
8768
  launchId: launchId || null,
@@ -8890,7 +8805,9 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
8890
8805
  if (runtimeConfig.runtimeProfileControl) {
8891
8806
  this.ackInjectedRuntimeProfileControl(agentId, runtimeConfig.runtimeProfileControl, agentProcess.launchId);
8892
8807
  }
8893
- if (wakeMessage) {
8808
+ if (wakeMessageDeliveredAsInboxUpdate) {
8809
+ this.recordInboxUpdateProjection(agentId, agentProcess, agentProcess.inbox, "spawn_wake_inbox_update", "wake", prompt);
8810
+ } else if (wakeMessage) {
8894
8811
  this.consumeVisibleMessages(agentId, { messages: [wakeMessage], source: "spawn_wake_message" });
8895
8812
  this.ackInjectedRuntimeProfileMessages(agentId, [wakeMessage], agentProcess.launchId);
8896
8813
  }
@@ -8991,8 +8908,9 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
8991
8908
  const finalSignal = ap.exitSignal ?? signal;
8992
8909
  const startupTimeoutTermination = ap.expectedTerminationReason === "startup_timeout";
8993
8910
  const expectedTermination = Boolean(ap.expectedTerminationReason);
8994
- const processEndedCleanly = finalCode === 0 || expectedTermination && !ap.lastRuntimeError;
8995
- const terminalFailureDetail = processEndedCleanly ? null : classifyTerminalFailure(ap);
8911
+ const stickyTerminalFailureDetail = classifyStickyTerminalFailure(ap);
8912
+ const processEndedCleanly = !stickyTerminalFailureDetail && (finalCode === 0 || expectedTermination && !ap.lastRuntimeError);
8913
+ const terminalFailureDetail = processEndedCleanly ? null : stickyTerminalFailureDetail ?? classifyTerminalFailure(ap);
8996
8914
  const resumeRecoveryReason = resumeSessionRecoveryReason(ap);
8997
8915
  const shouldColdStartResumeSession = resumeRecoveryReason !== null;
8998
8916
  const summary = summarizeCrash(finalCode, finalSignal);
@@ -9475,13 +9393,36 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
9475
9393
  }));
9476
9394
  return true;
9477
9395
  }
9396
+ const stickyTerminalFailure = classifyStickyTerminalFailure(ap);
9397
+ if (stickyTerminalFailure) {
9398
+ ap.inbox.push(message);
9399
+ this.recordDaemonTrace("daemon.agent.delivery.routed", this.deliveryTraceAttrs(agentId, message, {
9400
+ outcome: "queued_terminal_runtime_error",
9401
+ accepted: true,
9402
+ process_present: true,
9403
+ runtime: ap.config.runtime,
9404
+ session_id_present: Boolean(ap.sessionId),
9405
+ launchId: ap.launchId || void 0,
9406
+ is_idle: ap.isIdle,
9407
+ inbox_count: ap.inbox.length
9408
+ }));
9409
+ this.sendAgentStatus(agentId, "inactive", ap.launchId);
9410
+ this.broadcastActivity(agentId, "error", stickyTerminalFailure.detail);
9411
+ return true;
9412
+ }
9478
9413
  if (ap.isIdle && ap.driver.supportsStdinNotification && ap.sessionId) {
9479
- const nextMessages = ap.inbox.splice(0, ap.inbox.length);
9480
- nextMessages.push(message);
9414
+ ap.inbox.push(message);
9415
+ const nextMessages = [...ap.inbox];
9481
9416
  this.commitApmIdleState(agentId, ap, false);
9482
- this.startRuntimeTrace(agentId, ap, "stdin-idle-delivery", nextMessages);
9417
+ this.startRuntimeTrace(agentId, ap, "stdin-idle-delivery", [message]);
9483
9418
  this.broadcastActivity(agentId, "working", "Message received");
9484
- const stdinAccepted = this.deliverMessagesViaStdin(agentId, ap, nextMessages, "idle");
9419
+ const stdinAccepted = this.deliverInboxUpdateViaStdin(
9420
+ agentId,
9421
+ ap,
9422
+ [message],
9423
+ "idle",
9424
+ "stdin_idle_delivery"
9425
+ );
9485
9426
  this.recordDaemonTrace("daemon.agent.delivery.routed", this.deliveryTraceAttrs(agentId, message, {
9486
9427
  outcome: "stdin_idle_delivery",
9487
9428
  accepted: true,
@@ -10496,7 +10437,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
10496
10437
  return written;
10497
10438
  }
10498
10439
  case "deliver_stdin": {
10499
- const messages = ap.inbox.splice(0, ap.inbox.length);
10440
+ const messages = [...ap.inbox];
10500
10441
  ap.notifications.clear();
10501
10442
  if (messages.length === 0) {
10502
10443
  this.recordApmGatedSteeringEffectTrace(agentId, ap, effect, {
@@ -10514,7 +10455,22 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
10514
10455
  });
10515
10456
  }
10516
10457
  this.broadcastActivity(agentId, "working", "Message received");
10517
- const accepted = this.deliverMessagesViaStdin(agentId, ap, messages, effect.stdinMode);
10458
+ const runtimeProfileMessages = messages.filter((message) => runtimeProfileNotificationFromMessage(message));
10459
+ const ordinaryMessages = messages.filter((message) => !runtimeProfileNotificationFromMessage(message));
10460
+ let accepted = true;
10461
+ if (runtimeProfileMessages.length > 0) {
10462
+ ap.inbox.splice(0, ap.inbox.length, ...ordinaryMessages);
10463
+ accepted = this.deliverMessagesViaStdin(agentId, ap, runtimeProfileMessages, effect.stdinMode);
10464
+ }
10465
+ if (ordinaryMessages.length > 0) {
10466
+ accepted = this.deliverInboxUpdateViaStdin(
10467
+ agentId,
10468
+ ap,
10469
+ ordinaryMessages,
10470
+ effect.stdinMode,
10471
+ `stdin_${effect.stdinMode}_delivery`
10472
+ ) && accepted;
10473
+ }
10518
10474
  this.recordApmGatedSteeringEffectTrace(agentId, ap, effect, {
10519
10475
  outcome: accepted ? "written" : "not_written",
10520
10476
  delivered_messages_count: messages.length
@@ -10826,30 +10782,41 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
10826
10782
  this.flushPendingTrajectory(agentId);
10827
10783
  if (ap) {
10828
10784
  if (event.sessionId) ap.sessionId = event.sessionId;
10785
+ const stickyTerminalFailure = classifyStickyTerminalFailure(ap);
10829
10786
  const reduction = reduceApmGatedTurnEnd(ap.gatedSteering, {
10830
- inboxLength: ap.inbox.length,
10787
+ inboxLength: stickyTerminalFailure ? 0 : ap.inbox.length,
10831
10788
  supportsStdinNotification: ap.driver.supportsStdinNotification,
10832
10789
  hasSession: Boolean(ap.sessionId),
10833
10790
  terminateProcessOnTurnEnd: ap.driver.terminateProcessOnTurnEnd === true
10834
10791
  });
10835
10792
  this.commitGatedSteeringDecisionState(agentId, ap, reduction.nextState, { event: "turn_end" });
10836
10793
  const deliverStdinEffect = reduction.effects.find((effect) => effect.kind === "deliver_stdin");
10794
+ if (stickyTerminalFailure) {
10795
+ this.sendAgentStatus(agentId, "inactive", ap.launchId);
10796
+ }
10837
10797
  if (deliverStdinEffect) {
10838
10798
  if (!this.executeApmGatedSteeringEffect(agentId, ap, deliverStdinEffect)) {
10839
10799
  this.commitApmIdleState(agentId, ap, true);
10840
- this.broadcastActivity(agentId, "online", "Idle");
10800
+ if (stickyTerminalFailure) {
10801
+ this.broadcastActivity(agentId, "error", stickyTerminalFailure.detail);
10802
+ } else {
10803
+ this.broadcastActivity(agentId, "online", "Idle");
10804
+ }
10841
10805
  }
10842
10806
  } else {
10843
- if (ap.lastRuntimeError) {
10807
+ if (stickyTerminalFailure) {
10808
+ this.broadcastActivity(agentId, "error", stickyTerminalFailure.detail);
10809
+ } else if (ap.lastRuntimeError) {
10844
10810
  this.broadcastActivity(agentId, "error", ap.lastRuntimeError);
10845
10811
  } else {
10846
10812
  this.broadcastActivity(agentId, "online", "Idle");
10847
10813
  }
10848
10814
  }
10849
- this.endRuntimeTrace(ap, "ok", {
10850
- outcome: "turn-completed",
10815
+ this.endRuntimeTrace(ap, stickyTerminalFailure ? "error" : "ok", {
10816
+ outcome: stickyTerminalFailure ? "runtime-error-with-turn-end" : "turn-completed",
10817
+ ...stickyTerminalFailure ? { terminalRuntimeError: true } : {},
10851
10818
  ...runtimeTraceCounterAttrs(ap),
10852
- ...this.finalizeRuntimeProfileTurnControl(agentId, ap, "turn_end")
10819
+ ...this.finalizeRuntimeProfileTurnControl(agentId, ap, stickyTerminalFailure ? "runtime_error" : "turn_end")
10853
10820
  });
10854
10821
  if (ap.driver.terminateProcessOnTurnEnd) {
10855
10822
  logger.info(`[Agent ${agentId}] Turn completed; terminating ${ap.driver.id} process`);
@@ -10907,6 +10874,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
10907
10874
  ...this.finalizeRuntimeProfileTurnControl(agentId, ap, "runtime_error")
10908
10875
  });
10909
10876
  if (ap.driver.supportsStdinNotification && terminalFailure) {
10877
+ const stickyTerminalFailure = classifyStickyTerminalFailure(ap);
10910
10878
  if (terminalFailure.actionRequired) {
10911
10879
  logger.warn(`[Agent ${agentId}] ${ap.driver.id} auth requires user action; terminating runtime process`);
10912
10880
  try {
@@ -10919,6 +10887,10 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
10919
10887
  const reason = err instanceof Error ? err.message : String(err);
10920
10888
  logger.warn(`[Agent ${agentId}] Failed to terminate ${ap.driver.id} after auth error: ${reason}`);
10921
10889
  }
10890
+ } else if (stickyTerminalFailure) {
10891
+ ap.notifications.clear();
10892
+ this.sendAgentStatus(agentId, "inactive", ap.launchId);
10893
+ logger.warn(`[Agent ${agentId}] ${ap.driver.id} terminal runtime error requires explicit recovery`);
10922
10894
  } else {
10923
10895
  ap.notifications.clear();
10924
10896
  logger.info(`[Agent ${agentId}] Marked ${ap.driver.id} wakeable after terminal runtime error`);
@@ -11025,9 +10997,10 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
11025
10997
  }
11026
10998
  const inboxCount = ap.inbox.length;
11027
10999
  if (inboxCount === 0) return false;
11028
- const inboxRows = projectAgentInboxSnapshot(ap.inbox);
11000
+ const changedMessages = ap.inbox.slice(Math.max(0, ap.inbox.length - count));
11001
+ const inboxRows = projectAgentInboxSnapshot(changedMessages);
11029
11002
  const notification = `[Slock inbox notice:
11030
- ${formatAgentInboxDelta(inboxRows)}]`;
11003
+ ${formatAgentInboxDelta(inboxRows, { totalPendingMessages: inboxCount })}]`;
11031
11004
  const notificationByteCount = Buffer.byteLength(notification, "utf8");
11032
11005
  const projectionAttrs = this.inboxProjectionTraceAttrs(inboxRows, inboxCount);
11033
11006
  this.recordDaemonTrace("daemon.agent.inbox_projection.delta", {
@@ -11081,6 +11054,104 @@ ${formatAgentInboxDelta(inboxRows)}]`;
11081
11054
  return false;
11082
11055
  }
11083
11056
  }
11057
+ formatInboxUpdateRuntimeInput(messages, driver, totalPendingMessages = messages.length) {
11058
+ const rows = projectAgentInboxSnapshot(messages);
11059
+ return [
11060
+ "[Slock inbox notice:",
11061
+ formatAgentInboxDelta(rows, { totalPendingMessages }),
11062
+ "]"
11063
+ ].join("\n");
11064
+ }
11065
+ recordInboxUpdateProjection(agentId, ap, messages, source, mode, renderedInput, totalPendingMessages = messages.length) {
11066
+ const rows = projectAgentInboxSnapshot(messages);
11067
+ const projectionAttrs = this.inboxProjectionTraceAttrs(rows, totalPendingMessages);
11068
+ this.recordDaemonTrace("daemon.agent.inbox_projection.delta", {
11069
+ agentId,
11070
+ source,
11071
+ ...projectionAttrs
11072
+ });
11073
+ this.recordDaemonTrace("daemon.agent.inbox_update.pushed", {
11074
+ agentId,
11075
+ runtime: ap.config.runtime,
11076
+ model: ap.config.model,
11077
+ launchId: ap.launchId || void 0,
11078
+ mode,
11079
+ notification_byte_count: Buffer.byteLength(renderedInput, "utf8"),
11080
+ cursors_advanced: "none",
11081
+ ...projectionAttrs
11082
+ });
11083
+ return projectionAttrs;
11084
+ }
11085
+ deliverInboxUpdateViaStdin(agentId, ap, messages, mode, source) {
11086
+ if (messages.length === 0) return true;
11087
+ const prompt = this.formatInboxUpdateRuntimeInput(messages, ap.driver, ap.inbox.length);
11088
+ const projectionAttrs = this.recordInboxUpdateProjection(agentId, ap, messages, source, mode, prompt, ap.inbox.length);
11089
+ const inputTraceAttrs = buildRuntimeInputTraceAttrs({
11090
+ source,
11091
+ prompt,
11092
+ messages,
11093
+ sessionIdPresent: Boolean(ap.sessionId),
11094
+ nativeStandingPrompt: Boolean(ap.driver.supportsNativeStandingPrompt)
11095
+ });
11096
+ this.recordRuntimeTraceEvent(agentId, ap, "runtime.input.prepared", inputTraceAttrs);
11097
+ const encoded = ap.driver.encodeStdinMessage(prompt, ap.sessionId, { mode });
11098
+ if (!encoded) {
11099
+ if (mode === "idle") {
11100
+ this.commitApmIdleState(agentId, ap, true);
11101
+ }
11102
+ logger.warn(
11103
+ `[Agent ${agentId}] Failed to encode ${mode} inbox update; ${messages.length === 1 ? "message remains" : "messages remain"} pending`
11104
+ );
11105
+ this.recordDaemonTrace("daemon.agent.stdin_delivery", {
11106
+ agentId,
11107
+ launchId: ap.launchId || void 0,
11108
+ runtime: ap.config.runtime,
11109
+ model: ap.config.model,
11110
+ mode,
11111
+ messages_count: messages.length,
11112
+ session_id_present: Boolean(ap.sessionId),
11113
+ inbox_count: ap.inbox.length,
11114
+ pending_notification_count: ap.notifications.pendingCount,
11115
+ busy_delivery_mode: ap.driver.busyDeliveryMode,
11116
+ supports_stdin_notification: ap.driver.supportsStdinNotification,
11117
+ ...this.messagesTraceAttrs(messages),
11118
+ ...inputTraceAttrs,
11119
+ ...projectionAttrs,
11120
+ outcome: "encode_failed",
11121
+ requeued_messages_count: 0,
11122
+ cursors_advanced: "none"
11123
+ }, "error");
11124
+ return false;
11125
+ }
11126
+ const senders = [...new Set(messages.map((message) => `@${message.sender_name}`))].join(", ");
11127
+ logger.info(
11128
+ `[Agent ${agentId}] Delivering ${mode} inbox update for ${messages.length === 1 ? "message" : `${messages.length} messages`} from ${senders}`
11129
+ );
11130
+ if (this.containsOrdinaryInboxMessage(messages)) {
11131
+ ap.lastRuntimeError = null;
11132
+ }
11133
+ ap.process.stdin?.write(encoded + "\n");
11134
+ this.recordDaemonTrace("daemon.agent.stdin_delivery", {
11135
+ agentId,
11136
+ launchId: ap.launchId || void 0,
11137
+ runtime: ap.config.runtime,
11138
+ model: ap.config.model,
11139
+ mode,
11140
+ messages_count: messages.length,
11141
+ session_id_present: Boolean(ap.sessionId),
11142
+ inbox_count: ap.inbox.length,
11143
+ pending_notification_count: ap.notifications.pendingCount,
11144
+ busy_delivery_mode: ap.driver.busyDeliveryMode,
11145
+ supports_stdin_notification: ap.driver.supportsStdinNotification,
11146
+ ...this.messagesTraceAttrs(messages),
11147
+ ...inputTraceAttrs,
11148
+ ...projectionAttrs,
11149
+ outcome: "written",
11150
+ stdin_write_attempted: true,
11151
+ cursors_advanced: "none"
11152
+ });
11153
+ return true;
11154
+ }
11084
11155
  /** Deliver a message to an agent via stdin, formatting it the same way as the MCP bridge */
11085
11156
  deliverMessagesViaStdin(agentId, ap, messages, mode) {
11086
11157
  if (messages.length === 0) return true;
@@ -12134,7 +12205,7 @@ var DEFAULT_TRACE_UPLOAD_URL = "https://slock-trace-upload.botiverse.dev";
12134
12205
  var RUNNER_CREDENTIAL_SCOPES = ["send", "read", "mentions", "tasks", "reactions", "server", "channels", "knowledge"];
12135
12206
  var RUNNER_CREDENTIAL_MINT_MAX_ATTEMPTS2 = 3;
12136
12207
  var RUNNER_CREDENTIAL_MINT_RETRY_DELAY_MS2 = 250;
12137
- var DAEMON_CLI_USAGE = `Usage: slock-daemon --server-url <url> (--api-key <key> or ${DAEMON_API_KEY_ENV}=<key>)`;
12208
+ var DAEMON_CLI_USAGE = "Usage: slock-daemon --server-url <url> --api-key <key>";
12138
12209
  var RunnerCredentialMintError2 = class extends Error {
12139
12210
  code;
12140
12211
  retryable;
@@ -12170,9 +12241,9 @@ function runnerCredentialErrorDetail2(error) {
12170
12241
  async function waitForRunnerCredentialRetry2() {
12171
12242
  await new Promise((resolve) => setTimeout(resolve, RUNNER_CREDENTIAL_MINT_RETRY_DELAY_MS2));
12172
12243
  }
12173
- function parseDaemonCliArgs(args, env = {}) {
12244
+ function parseDaemonCliArgs(args) {
12174
12245
  let serverUrl = "";
12175
- let apiKey = env[DAEMON_API_KEY_ENV] ?? "";
12246
+ let apiKey = "";
12176
12247
  for (let i = 0; i < args.length; i++) {
12177
12248
  if (args[i] === "--server-url" && args[i + 1]) serverUrl = args[++i];
12178
12249
  if (args[i] === "--api-key" && args[i + 1]) apiKey = args[++i];
@@ -12939,8 +13010,6 @@ var DaemonCore = class {
12939
13010
  };
12940
13011
 
12941
13012
  export {
12942
- DAEMON_API_KEY_ENV,
12943
- scrubDaemonAuthEnv,
12944
13013
  resolveWorkspaceDirectoryPath,
12945
13014
  scanWorkspaceDirectories,
12946
13015
  deleteWorkspaceDirectory,
package/dist/core.js CHANGED
@@ -1,5 +1,4 @@
1
1
  import {
2
- DAEMON_API_KEY_ENV,
3
2
  DAEMON_CLI_USAGE,
4
3
  DaemonCore,
5
4
  deleteWorkspaceDirectory,
@@ -9,14 +8,12 @@ import {
9
8
  resolveChatBridgePath,
10
9
  resolveSlockCliPath,
11
10
  resolveWorkspaceDirectoryPath,
12
- scanWorkspaceDirectories,
13
- scrubDaemonAuthEnv
14
- } from "./chunk-OV4XD66N.js";
11
+ scanWorkspaceDirectories
12
+ } from "./chunk-4H5XFLYA.js";
15
13
  import {
16
14
  subscribeDaemonLogs
17
15
  } from "./chunk-M2KQBJR3.js";
18
16
  export {
19
- DAEMON_API_KEY_ENV,
20
17
  DAEMON_CLI_USAGE,
21
18
  DaemonCore,
22
19
  deleteWorkspaceDirectory,
@@ -27,6 +24,5 @@ export {
27
24
  resolveSlockCliPath,
28
25
  resolveWorkspaceDirectoryPath,
29
26
  scanWorkspaceDirectories,
30
- scrubDaemonAuthEnv,
31
27
  subscribeDaemonLogs
32
28
  };
package/dist/index.js CHANGED
@@ -2,14 +2,12 @@
2
2
  import {
3
3
  DAEMON_CLI_USAGE,
4
4
  DaemonCore,
5
- parseDaemonCliArgs,
6
- scrubDaemonAuthEnv
7
- } from "./chunk-OV4XD66N.js";
5
+ parseDaemonCliArgs
6
+ } from "./chunk-4H5XFLYA.js";
8
7
  import "./chunk-M2KQBJR3.js";
9
8
 
10
9
  // src/index.ts
11
- var parsedArgs = parseDaemonCliArgs(process.argv.slice(2), process.env);
12
- scrubDaemonAuthEnv(process.env);
10
+ var parsedArgs = parseDaemonCliArgs(process.argv.slice(2));
13
11
  if (!parsedArgs) {
14
12
  console.error(DAEMON_CLI_USAGE);
15
13
  process.exit(1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@slock-ai/daemon",
3
- "version": "0.55.7-play.20260602150229",
3
+ "version": "0.56.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "slock-daemon": "dist/index.js"
@@ -1,96 +0,0 @@
1
- // src/drivers/piSdkRunner.ts
2
- import { readFile } from "fs/promises";
3
- import path from "path";
4
- import {
5
- AuthStorage,
6
- createAgentSessionFromServices,
7
- createAgentSessionServices,
8
- SessionManager
9
- } from "@earendil-works/pi-coding-agent";
10
- function writeJson(value) {
11
- process.stdout.write(`${JSON.stringify(value)}
12
- `);
13
- }
14
- function parseArgs(argv) {
15
- const index = argv.indexOf("--config");
16
- const configPath = index >= 0 ? argv[index + 1] : void 0;
17
- if (!configPath) throw new Error("Missing --config <path>");
18
- return { configPath };
19
- }
20
- function resolveConfiguredModel(modelId, modelRegistry) {
21
- if (!modelId) return void 0;
22
- const [provider, ...rest] = modelId.split("/");
23
- const providerScopedId = rest.join("/");
24
- if (provider && providerScopedId) {
25
- const exact = modelRegistry.find(provider, providerScopedId);
26
- if (exact) return exact;
27
- }
28
- return modelRegistry.getAll().find(
29
- (model) => model.id === modelId || `${model.provider}/${model.id}` === modelId || (providerScopedId ? model.id === providerScopedId : false)
30
- );
31
- }
32
- async function createSessionManager(config) {
33
- if (!config.sessionId) return SessionManager.create(config.cwd, config.sessionDir);
34
- const localSessions = await SessionManager.list(config.cwd, config.sessionDir);
35
- const match = localSessions.find((session) => session.id.startsWith(config.sessionId));
36
- if (match) return SessionManager.open(match.path, config.sessionDir);
37
- return SessionManager.create(config.cwd, config.sessionDir);
38
- }
39
- async function run() {
40
- const { configPath } = parseArgs(process.argv.slice(2));
41
- const config = JSON.parse(await readFile(configPath, "utf8"));
42
- const authStorage = AuthStorage.create(path.join(config.agentDir, "auth.json"));
43
- const services = await createAgentSessionServices({
44
- cwd: config.cwd,
45
- agentDir: config.agentDir,
46
- authStorage,
47
- resourceLoaderOptions: {
48
- appendSystemPrompt: [config.standingPrompt],
49
- noContextFiles: true,
50
- noExtensions: true,
51
- noPromptTemplates: true,
52
- noSkills: true,
53
- noThemes: true
54
- }
55
- });
56
- for (const diagnostic of services.diagnostics) {
57
- const line = `[Pi SDK] ${diagnostic.type}: ${diagnostic.message}`;
58
- if (diagnostic.type === "error") throw new Error(line);
59
- process.stderr.write(`${line}
60
- `);
61
- }
62
- const sessionManager = await createSessionManager(config);
63
- const model = resolveConfiguredModel(config.model, services.modelRegistry);
64
- if (config.model && !model) {
65
- throw new Error(`Configured Pi model '${config.model}' was not found in Pi model registry.`);
66
- }
67
- const { session } = await createAgentSessionFromServices({
68
- services,
69
- sessionManager,
70
- model
71
- });
72
- const header = session.sessionManager.getHeader();
73
- if (header) writeJson(header);
74
- const unsubscribe = session.subscribe((event) => writeJson(event));
75
- try {
76
- await session.prompt(config.prompt);
77
- } finally {
78
- unsubscribe();
79
- session.dispose();
80
- await services.settingsManager.flush();
81
- }
82
- }
83
- run().catch((error) => {
84
- const message = error instanceof Error ? error.message : String(error);
85
- writeJson({
86
- type: "message_end",
87
- message: {
88
- role: "assistant",
89
- content: [],
90
- stopReason: "error",
91
- errorMessage: message
92
- }
93
- });
94
- writeJson({ type: "turn_end" });
95
- process.exitCode = 1;
96
- });