@slock-ai/daemon 0.57.1 → 0.57.2-play.20260608142014

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.
@@ -351,40 +351,127 @@ var NoopActiveSpan = class {
351
351
  }
352
352
  };
353
353
  var noopTracer = new NoopTracer();
354
- function createScopedTracer(tracer, scopeAttrs) {
354
+ function projectTraceScopeAttrs(scope) {
355
+ const attrs = {};
356
+ addOptionalStringAttr(attrs, "daemon_version", scope.resource?.daemonVersion);
357
+ addPresenceAttr(attrs, "daemon_version_present", scope.resource?.daemonVersion);
358
+ addOptionalStringAttr(attrs, "computer_version", scope.resource?.computerVersion);
359
+ addPresenceAttr(attrs, "computer_version_present", scope.resource?.computerVersion);
360
+ addOptionalStringAttr(attrs, "deployment_environment", scope.resource?.deploymentEnvironment);
361
+ addOptionalStringAttr(attrs, "service_revision", scope.resource?.serviceRevision);
362
+ addOptionalStringAttr(attrs, "request_id", scope.request?.requestId);
363
+ addPresenceAttr(attrs, "request_id_present", scope.request?.requestId);
364
+ addOptionalStringAttr(attrs, "route_pattern", scope.request?.routePattern);
365
+ addOptionalStringAttr(attrs, "method", scope.request?.method);
366
+ addOptionalStringAttr(attrs, "caller_kind", scope.request?.callerKind);
367
+ if (typeof scope.request?.userIdPresent === "boolean") {
368
+ attrs.user_id_present = scope.request.userIdPresent;
369
+ }
370
+ addOptionalStringAttr(attrs, "server_id", scope.actor?.serverId);
371
+ addPresenceAttr(attrs, "server_id_present", scope.actor?.serverId, scope.actor?.serverIdPresent);
372
+ addOptionalStringAttr(attrs, "machine_id", scope.actor?.machineId);
373
+ addPresenceAttr(attrs, "machine_id_present", scope.actor?.machineId, scope.actor?.machineIdPresent);
374
+ addOptionalStringAttr(attrs, "agent_id", scope.actor?.agentId);
375
+ addPresenceAttr(attrs, "agent_id_present", scope.actor?.agentId, scope.actor?.agentIdPresent);
376
+ addOptionalStringAttr(attrs, "launch_id", scope.actor?.launchId);
377
+ addPresenceAttr(attrs, "launch_id_present", scope.actor?.launchId, scope.actor?.launchIdPresent);
378
+ addOptionalStringAttr(attrs, "session_id", scope.actor?.sessionId);
379
+ addPresenceAttr(attrs, "session_id_present", scope.actor?.sessionId, scope.actor?.sessionIdPresent);
380
+ return attrs;
381
+ }
382
+ function createTraceScopeTracer(tracer, scope, options = {}) {
383
+ const scopedTracer = createScopedTracer(tracer, projectTraceScopeAttrs(scope), {
384
+ attrPrecedence: options.scopeAttrPrecedence
385
+ });
386
+ return options.spanAttrContracts ? createSpanAttrContractTracer(scopedTracer, options.spanAttrContracts) : scopedTracer;
387
+ }
388
+ function createScopedTracer(tracer, scopeAttrs, options = {}) {
355
389
  if (!Object.keys(scopeAttrs).length) return tracer;
356
- return new ScopedTracer(tracer, scopeAttrs);
390
+ return new ScopedTracer(tracer, scopeAttrs, options.attrPrecedence ?? "scope");
357
391
  }
358
392
  var ScopedTracer = class {
359
- constructor(tracer, scopeAttrs) {
393
+ constructor(tracer, scopeAttrs, attrPrecedence) {
360
394
  this.tracer = tracer;
361
395
  this.scopeAttrs = scopeAttrs;
396
+ this.attrPrecedence = attrPrecedence;
362
397
  }
363
398
  startSpan(name, options) {
364
399
  const span = this.tracer.startSpan(name, {
365
400
  ...options,
366
- attrs: mergeAttrs(options.attrs, this.scopeAttrs)
401
+ attrs: this.mergeScopeAttrs(options.attrs)
367
402
  });
368
- return new ScopedActiveSpan(span, this.scopeAttrs);
403
+ return new ScopedActiveSpan(span, this.scopeAttrs, this.attrPrecedence);
404
+ }
405
+ mergeScopeAttrs(attrs) {
406
+ return this.attrPrecedence === "caller" ? mergeAttrs(this.scopeAttrs, attrs) : mergeAttrs(attrs, this.scopeAttrs);
369
407
  }
370
408
  };
371
409
  var ScopedActiveSpan = class {
372
- constructor(span, scopeAttrs) {
410
+ constructor(span, scopeAttrs, attrPrecedence) {
373
411
  this.span = span;
374
412
  this.scopeAttrs = scopeAttrs;
413
+ this.attrPrecedence = attrPrecedence;
375
414
  this.context = span.context;
376
415
  }
377
416
  context;
378
417
  addEvent(name, attrs) {
379
- this.span.addEvent(name, mergeAttrs(attrs, this.scopeAttrs));
418
+ this.span.addEvent(name, this.mergeScopeAttrs(attrs));
380
419
  }
381
420
  end(status, options) {
382
421
  this.span.end(status, options ? {
383
422
  ...options,
384
- attrs: mergeAttrs(options.attrs, this.scopeAttrs)
423
+ attrs: this.mergeScopeAttrs(options.attrs)
385
424
  } : void 0);
386
425
  }
426
+ mergeScopeAttrs(attrs) {
427
+ return this.attrPrecedence === "caller" ? mergeAttrs(this.scopeAttrs, attrs) : mergeAttrs(attrs, this.scopeAttrs);
428
+ }
429
+ };
430
+ function createSpanAttrContractTracer(tracer, contracts) {
431
+ if (!Object.keys(contracts).length) return tracer;
432
+ return new SpanAttrContractTracer(tracer, contracts);
433
+ }
434
+ var SpanAttrContractTracer = class {
435
+ constructor(tracer, contracts) {
436
+ this.tracer = tracer;
437
+ this.contracts = contracts;
438
+ }
439
+ startSpan(name, options) {
440
+ const contract = this.contracts[name];
441
+ if (!contract) return this.tracer.startSpan(name, options);
442
+ const span = this.tracer.startSpan(name, {
443
+ ...options,
444
+ attrs: filterTraceAttrs(options.attrs, contract.spanAttrs)
445
+ });
446
+ return new SpanAttrContractActiveSpan(span, contract);
447
+ }
387
448
  };
449
+ var SpanAttrContractActiveSpan = class {
450
+ constructor(span, contract) {
451
+ this.span = span;
452
+ this.contract = contract;
453
+ this.context = span.context;
454
+ }
455
+ context;
456
+ addEvent(name, attrs) {
457
+ this.span.addEvent(name, filterTraceAttrs(attrs, this.contract.eventAttrs?.[name]));
458
+ }
459
+ end(status, options) {
460
+ this.span.end(status, options ? {
461
+ ...options,
462
+ attrs: filterTraceAttrs(options.attrs, this.contract.endAttrs)
463
+ } : void 0);
464
+ }
465
+ };
466
+ function filterTraceAttrs(attrs, allowedKeys) {
467
+ if (!attrs || !allowedKeys) return attrs;
468
+ const allowed = new Set(allowedKeys);
469
+ const filtered = {};
470
+ for (const [key, value] of Object.entries(attrs)) {
471
+ if (allowed.has(key)) filtered[key] = value;
472
+ }
473
+ return Object.keys(filtered).length ? filtered : void 0;
474
+ }
388
475
  var BasicTracer = class {
389
476
  sink;
390
477
  clock;
@@ -482,6 +569,14 @@ function mergeAttrs(base, extra) {
482
569
  if (!extra) return base;
483
570
  return { ...base, ...extra };
484
571
  }
572
+ function addOptionalStringAttr(attrs, key, value) {
573
+ const normalized = value?.trim();
574
+ if (!normalized) return;
575
+ attrs[key] = normalized;
576
+ }
577
+ function addPresenceAttr(attrs, key, value, explicitPresent) {
578
+ attrs[key] = typeof explicitPresent === "boolean" ? explicitPresent : Boolean(value?.trim());
579
+ }
485
580
  function generateTraceId() {
486
581
  return randomNonZeroHex(TRACE_ID_HEX_LENGTH);
487
582
  }
@@ -1046,6 +1141,9 @@ var SERVER_CAPABILITY_MATRIX = {
1046
1141
 
1047
1142
  // ../shared/src/index.ts
1048
1143
  var RUNTIME_CONFIG_VERSION = 1;
1144
+ var EXTERNAL_AGENT_RUNTIME_ID = "external";
1145
+ var EXTERNAL_AGENT_RUNTIME_MODEL = "external";
1146
+ var EXTERNAL_AGENT_RUNTIME_DISPLAY_NAME = "External agent";
1049
1147
  var RUNTIMES = [
1050
1148
  { id: "claude", displayName: "Claude Code", binary: "claude", supported: true },
1051
1149
  { id: "codex", displayName: "Codex CLI", binary: "codex", supported: true },
@@ -1058,6 +1156,9 @@ var RUNTIMES = [
1058
1156
  { id: "pi", displayName: "Pi", binary: "pi", supported: true }
1059
1157
  ];
1060
1158
  var RUNTIME_MODELS = {
1159
+ [EXTERNAL_AGENT_RUNTIME_ID]: [
1160
+ { id: EXTERNAL_AGENT_RUNTIME_MODEL, label: EXTERNAL_AGENT_RUNTIME_DISPLAY_NAME }
1161
+ ],
1061
1162
  claude: [
1062
1163
  { id: "opus", label: "Claude Opus" },
1063
1164
  { id: "claude-opus-4-8", label: "Claude Opus 4.8" },
@@ -1980,6 +2081,19 @@ function listLegacySlockStatePaths(slockHome = resolveSlockHome(), homeDir = os.
1980
2081
  return candidates.filter((candidate) => existsSync(candidate.path));
1981
2082
  }
1982
2083
 
2084
+ // src/authEnv.ts
2085
+ var DAEMON_API_KEY_ENV = "SLOCK_MACHINE_API_KEY";
2086
+ var SLOCK_AGENT_TOKEN_ENV = "SLOCK_AGENT_TOKEN";
2087
+ function scrubDaemonAuthEnv(env) {
2088
+ delete env[DAEMON_API_KEY_ENV];
2089
+ return env;
2090
+ }
2091
+ function scrubDaemonChildEnv(env) {
2092
+ delete env[DAEMON_API_KEY_ENV];
2093
+ delete env[SLOCK_AGENT_TOKEN_ENV];
2094
+ return env;
2095
+ }
2096
+
1983
2097
  // src/agentCredentialProxy.ts
1984
2098
  import { randomBytes } from "crypto";
1985
2099
  import http from "http";
@@ -3466,7 +3580,9 @@ var LOOPBACK_NO_PROXY = "127.0.0.1,localhost";
3466
3580
  var CLI_TRANSPORT_TRACE_DIR_ENV = "SLOCK_CLI_TRANSPORT_TRACE_DIR";
3467
3581
  var safePathPart = (value) => value.replace(/[^a-zA-Z0-9_.-]/g, "_");
3468
3582
  var RAW_CREDENTIAL_ENV_DENYLIST = [
3469
- "SLOCK_AGENT_CREDENTIAL_KEY"
3583
+ "SLOCK_AGENT_TOKEN",
3584
+ "SLOCK_AGENT_CREDENTIAL_KEY",
3585
+ "SLOCK_AGENT_CREDENTIAL_KEY_FILE"
3470
3586
  ];
3471
3587
  var cachedOpencliBinPath;
3472
3588
  function resolveOpencliBinPath() {
@@ -3681,7 +3797,7 @@ exec ${shellSingleQuote(process.execPath)} ${shellSingleQuote(opencliBinPath)} "
3681
3797
  ...agentCredentialProxy ? {} : { SLOCK_AGENT_TOKEN_FILE: tokenFile },
3682
3798
  PATH: `${slockDir}${path2.delimiter}${process.env.PATH ?? ""}`
3683
3799
  };
3684
- delete spawnEnv.SLOCK_AGENT_TOKEN;
3800
+ scrubDaemonChildEnv(spawnEnv);
3685
3801
  for (const key of RAW_CREDENTIAL_ENV_DENYLIST) {
3686
3802
  delete spawnEnv[key];
3687
3803
  }
@@ -4110,7 +4226,7 @@ function resolveCommandOnWindows(command, env, execFileSyncFn, existsSyncFn) {
4110
4226
  }
4111
4227
  function resolveCommandOnPath(command, deps = {}) {
4112
4228
  const platform = deps.platform ?? process.platform;
4113
- const env = withWindowsUserEnvironment(deps.env ?? process.env, deps);
4229
+ const env = scrubDaemonChildEnv({ ...withWindowsUserEnvironment(deps.env ?? process.env, deps) });
4114
4230
  const execFileSyncFn = deps.execFileSyncFn ?? execFileSync;
4115
4231
  const existsSyncFn = deps.existsSyncFn ?? existsSync2;
4116
4232
  if (platform === "win32") {
@@ -4136,7 +4252,7 @@ function firstExistingPath(candidates, deps = {}) {
4136
4252
  return null;
4137
4253
  }
4138
4254
  function readCommandVersion(command, args = [], deps = {}) {
4139
- const env = withWindowsUserEnvironment(deps.env ?? process.env, deps);
4255
+ const env = scrubDaemonChildEnv({ ...withWindowsUserEnvironment(deps.env ?? process.env, deps) });
4140
4256
  const execFileSyncFn = deps.execFileSyncFn ?? execFileSync;
4141
4257
  try {
4142
4258
  const output = normalizeExecOutput(execFileSyncFn(command, [...args, "--version"], {
@@ -5490,11 +5606,11 @@ function detectCursorModels(runCommand = runCursorModelsCommand) {
5490
5606
  return parseCursorModelsOutput(String(result.stdout || ""));
5491
5607
  }
5492
5608
  function buildCursorModelProbeEnv(deps = {}) {
5493
- return withWindowsUserEnvironment({
5609
+ return scrubDaemonChildEnv(withWindowsUserEnvironment({
5494
5610
  ...deps.env ?? process.env,
5495
5611
  FORCE_COLOR: "0",
5496
5612
  NO_COLOR: "1"
5497
- }, deps);
5613
+ }, deps));
5498
5614
  }
5499
5615
  function runCursorModelsCommand() {
5500
5616
  return spawnSync("cursor-agent", ["models"], {
@@ -5550,7 +5666,7 @@ function resolveGeminiSpawn(commandArgs, deps = {}) {
5550
5666
  }
5551
5667
  const execFileSyncFn = deps.execFileSyncFn ?? execFileSync3;
5552
5668
  const existsSyncFn = deps.existsSyncFn ?? existsSync4;
5553
- const env = deps.env ?? process.env;
5669
+ const env = scrubDaemonChildEnv({ ...deps.env ?? process.env });
5554
5670
  const winPath = path6.win32;
5555
5671
  let geminiEntry = null;
5556
5672
  try {
@@ -5690,12 +5806,15 @@ var GeminiDriver = class {
5690
5806
  // src/drivers/kimi.ts
5691
5807
  import { randomUUID as randomUUID2 } from "crypto";
5692
5808
  import { spawn as spawn7 } from "child_process";
5693
- import { existsSync as existsSync5, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
5809
+ import { chmodSync, existsSync as existsSync5, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
5694
5810
  import os3 from "os";
5695
5811
  import path7 from "path";
5696
5812
  var KIMI_WIRE_PROTOCOL_VERSION = "1.3";
5697
5813
  var KIMI_SYSTEM_PROMPT_FILE = ".slock-kimi-system.md";
5698
5814
  var KIMI_AGENT_FILE = ".slock-kimi-agent.yaml";
5815
+ var KIMI_GENERATED_CONFIG_FILE = ".slock-kimi-config.toml";
5816
+ var SLOCK_KIMI_CONFIG_CONTENT_ENV = "SLOCK_KIMI_CONFIG_CONTENT";
5817
+ var SLOCK_KIMI_CONFIG_FILE_ENV = "SLOCK_KIMI_CONFIG_FILE";
5699
5818
  function parseToolArguments(raw) {
5700
5819
  if (typeof raw !== "string") return raw;
5701
5820
  try {
@@ -5704,6 +5823,73 @@ function parseToolArguments(raw) {
5704
5823
  return raw;
5705
5824
  }
5706
5825
  }
5826
+ function readKimiConfigSource(home = os3.homedir(), env = process.env) {
5827
+ const inlineConfig = env[SLOCK_KIMI_CONFIG_CONTENT_ENV];
5828
+ if (inlineConfig && inlineConfig.trim()) {
5829
+ return {
5830
+ raw: inlineConfig,
5831
+ explicitPath: null,
5832
+ sourcePath: SLOCK_KIMI_CONFIG_CONTENT_ENV
5833
+ };
5834
+ }
5835
+ const explicitPath = env[SLOCK_KIMI_CONFIG_FILE_ENV];
5836
+ const configPath = explicitPath && explicitPath.trim() ? explicitPath : path7.join(home, ".kimi", "config.toml");
5837
+ try {
5838
+ return {
5839
+ raw: readFileSync3(configPath, "utf8"),
5840
+ explicitPath: explicitPath && explicitPath.trim() ? explicitPath : null,
5841
+ sourcePath: configPath
5842
+ };
5843
+ } catch {
5844
+ return {
5845
+ raw: null,
5846
+ explicitPath: explicitPath && explicitPath.trim() ? explicitPath : null,
5847
+ sourcePath: configPath
5848
+ };
5849
+ }
5850
+ }
5851
+ function buildKimiSpawnEnv(env = process.env) {
5852
+ const spawnEnv = { ...env, FORCE_COLOR: "0", NO_COLOR: "1" };
5853
+ delete spawnEnv[SLOCK_KIMI_CONFIG_CONTENT_ENV];
5854
+ delete spawnEnv[SLOCK_KIMI_CONFIG_FILE_ENV];
5855
+ return scrubDaemonChildEnv(spawnEnv);
5856
+ }
5857
+ function buildKimiEffectiveEnv(ctx, overrideEnv) {
5858
+ return {
5859
+ ...process.env,
5860
+ ...ctx.config.envVars || {},
5861
+ ...overrideEnv || {}
5862
+ };
5863
+ }
5864
+ function buildKimiLaunchOptions(ctx, opts = {}) {
5865
+ const env = buildKimiEffectiveEnv(ctx, opts.env);
5866
+ const source = readKimiConfigSource(opts.home ?? os3.homedir(), env);
5867
+ const args = [];
5868
+ let configFilePath = null;
5869
+ let configContent = null;
5870
+ if (source.explicitPath) {
5871
+ configFilePath = source.explicitPath;
5872
+ } else if (source.raw !== null && source.sourcePath === SLOCK_KIMI_CONFIG_CONTENT_ENV) {
5873
+ configFilePath = path7.join(ctx.workingDirectory, KIMI_GENERATED_CONFIG_FILE);
5874
+ configContent = source.raw;
5875
+ if (opts.writeGeneratedConfig !== false) {
5876
+ writeFileSync3(configFilePath, source.raw, { encoding: "utf8", mode: 384 });
5877
+ chmodSync(configFilePath, 384);
5878
+ }
5879
+ }
5880
+ if (configFilePath) {
5881
+ args.push("--config-file", configFilePath);
5882
+ }
5883
+ if (ctx.config.model && ctx.config.model !== "default") {
5884
+ args.push("--model", ctx.config.model);
5885
+ }
5886
+ return {
5887
+ args,
5888
+ env: buildKimiSpawnEnv(env),
5889
+ configFilePath,
5890
+ configContent
5891
+ };
5892
+ }
5707
5893
  function resolveKimiSpawn(commandArgs, deps = {}) {
5708
5894
  return {
5709
5895
  command: resolveCommandOnPath("kimi", deps) ?? "kimi",
@@ -5727,7 +5913,25 @@ var KimiDriver = class {
5727
5913
  };
5728
5914
  model = {
5729
5915
  detectedModelsVerifiedAs: "launchable",
5730
- toLaunchSpec: (modelId) => ({ args: ["--model", modelId] })
5916
+ toLaunchSpec: (modelId, ctx, opts) => {
5917
+ if (!ctx) return { args: ["--model", modelId] };
5918
+ const launchCtx = {
5919
+ ...ctx,
5920
+ config: {
5921
+ ...ctx.config,
5922
+ model: modelId
5923
+ }
5924
+ };
5925
+ const launch = buildKimiLaunchOptions(launchCtx, {
5926
+ home: opts?.home,
5927
+ writeGeneratedConfig: false
5928
+ });
5929
+ return {
5930
+ args: launch.args,
5931
+ env: launch.env,
5932
+ configFiles: launch.configFilePath ? [launch.configFilePath] : void 0
5933
+ };
5934
+ }
5731
5935
  };
5732
5936
  supportsStdinNotification = true;
5733
5937
  mcpToolPrefix = "";
@@ -5753,21 +5957,23 @@ var KimiDriver = class {
5753
5957
  ` system_prompt_path: ./${KIMI_SYSTEM_PROMPT_FILE}`,
5754
5958
  ""
5755
5959
  ].join("\n"), "utf8");
5960
+ const launch = buildKimiLaunchOptions(ctx);
5756
5961
  const args = [
5757
5962
  "--wire",
5758
5963
  "--yolo",
5759
5964
  "--agent-file",
5760
5965
  agentFilePath,
5761
5966
  "--session",
5762
- this.sessionId
5967
+ this.sessionId,
5968
+ ...launch.args
5763
5969
  ];
5764
5970
  const launchRuntimeFields = runtimeConfigToLaunchFields(ctx.config);
5765
5971
  if (launchRuntimeFields.model && launchRuntimeFields.model !== "default") {
5766
5972
  args.push("--model", launchRuntimeFields.model);
5767
5973
  }
5768
5974
  const spawnEnv = (await prepareCliTransport(ctx, { NO_COLOR: "1" })).spawnEnv;
5769
- const launch = resolveKimiSpawn(args);
5770
- const proc = spawn7(launch.command, launch.args, {
5975
+ const spawnTarget = resolveKimiSpawn(args);
5976
+ const proc = spawn7(spawnTarget.command, spawnTarget.args, {
5771
5977
  cwd: ctx.workingDirectory,
5772
5978
  stdio: ["pipe", "pipe", "pipe"],
5773
5979
  env: spawnEnv,
@@ -5775,7 +5981,7 @@ var KimiDriver = class {
5775
5981
  // and has an 8191-character command-line limit. Kimi's official
5776
5982
  // installer/uv entrypoint is an executable, so launch it directly and
5777
5983
  // keep prompts on stdin / files instead of routing through cmd.exe.
5778
- shell: launch.shell
5984
+ shell: spawnTarget.shell
5779
5985
  });
5780
5986
  proc.stdin?.write(JSON.stringify({
5781
5987
  jsonrpc: "2.0",
@@ -5889,14 +6095,9 @@ var KimiDriver = class {
5889
6095
  return detectKimiModels();
5890
6096
  }
5891
6097
  };
5892
- function detectKimiModels(home = os3.homedir()) {
5893
- const configPath = path7.join(home, ".kimi", "config.toml");
5894
- let raw;
5895
- try {
5896
- raw = readFileSync3(configPath, "utf8");
5897
- } catch {
5898
- return null;
5899
- }
6098
+ function detectKimiModels(home = os3.homedir(), opts = {}) {
6099
+ const raw = readKimiConfigSource(home, opts.env).raw;
6100
+ if (raw === null) return null;
5900
6101
  const models = [];
5901
6102
  const sectionRe = /^\s*\[models(?:\.([^\]]+)|"\.[^"]+"|\."[^"]+")\s*\]\s*$/gm;
5902
6103
  const lineRe = /^\s*\[models\.(.+?)\s*\]\s*$/gm;
@@ -6136,7 +6337,7 @@ function runOpenCodeModelsCommand(home, deps = {}) {
6136
6337
  const platform = deps.platform ?? process.platform;
6137
6338
  const spawnSyncFn = deps.spawnSyncFn ?? spawnSync2;
6138
6339
  const result = spawnSyncFn("opencode", ["models"], {
6139
- env: { ...process.env, HOME: home, FORCE_COLOR: "0", NO_COLOR: "1" },
6340
+ env: scrubDaemonChildEnv({ ...process.env, HOME: home, FORCE_COLOR: "0", NO_COLOR: "1" }),
6140
6341
  encoding: "utf8",
6141
6342
  timeout: 5e3,
6142
6343
  shell: platform === "win32"
@@ -7381,16 +7582,19 @@ var RuntimeProgressState = class {
7381
7582
  };
7382
7583
 
7383
7584
  // src/runtimeNotificationState.ts
7585
+ function inboxNoticeMessageIdentity(message) {
7586
+ const seq = typeof message.seq === "number" && Number.isFinite(message.seq) && message.seq > 0 ? Math.floor(message.seq) : null;
7587
+ if (seq !== null) {
7588
+ return `s:${seq}`;
7589
+ }
7590
+ const id = typeof message.message_id === "string" && message.message_id.length > 0 ? message.message_id : typeof message.id === "string" && message.id.length > 0 ? message.id : "";
7591
+ return id.length > 0 ? `m:${id}` : "";
7592
+ }
7384
7593
  function computeInboxNoticeFingerprint(messages) {
7385
7594
  const keys = [];
7386
7595
  for (const m of messages) {
7387
- const seq = typeof m.seq === "number" && Number.isFinite(m.seq) && m.seq > 0 ? Math.floor(m.seq) : null;
7388
- if (seq !== null) {
7389
- keys.push(`s:${seq}`);
7390
- continue;
7391
- }
7392
- const id = typeof m.message_id === "string" && m.message_id.length > 0 ? m.message_id : typeof m.id === "string" && m.id.length > 0 ? m.id : "";
7393
- if (id.length > 0) keys.push(`m:${id}`);
7596
+ const key = inboxNoticeMessageIdentity(m);
7597
+ if (key.length > 0) keys.push(key);
7394
7598
  }
7395
7599
  if (keys.length === 0) return "";
7396
7600
  keys.sort();
@@ -7401,6 +7605,10 @@ var RuntimeNotificationState = class {
7401
7605
  pendingCountValue = 0;
7402
7606
  lastNoticeFingerprint = null;
7403
7607
  lastNoticeSessionId = null;
7608
+ lastEncodeFailedFingerprint = null;
7609
+ lastEncodeFailedSessionId = null;
7610
+ contributedSessionId = null;
7611
+ contributedIdentities = /* @__PURE__ */ new Set();
7404
7612
  get pendingCount() {
7405
7613
  return this.pendingCountValue;
7406
7614
  }
@@ -7443,13 +7651,63 @@ var RuntimeNotificationState = class {
7443
7651
  return this.lastNoticeFingerprint === fingerprint && this.lastNoticeSessionId === sessionId;
7444
7652
  }
7445
7653
  /** Register a fingerprint as written — call ONLY after a successful stdin write. */
7446
- recordNoticeWritten(fingerprint, sessionId) {
7654
+ recordNoticeWritten(fingerprint, sessionId, messages = []) {
7447
7655
  this.lastNoticeFingerprint = fingerprint;
7448
7656
  this.lastNoticeSessionId = sessionId;
7657
+ this.lastEncodeFailedFingerprint = null;
7658
+ this.lastEncodeFailedSessionId = null;
7659
+ this.ensureContributionSession(sessionId);
7660
+ for (const message of messages) {
7661
+ const identity = inboxNoticeMessageIdentity(message);
7662
+ if (identity.length > 0) {
7663
+ this.contributedIdentities.add(identity);
7664
+ }
7665
+ }
7666
+ }
7667
+ hasContributedMessage(message, sessionId) {
7668
+ if (this.contributedSessionId !== sessionId) return false;
7669
+ const identity = inboxNoticeMessageIdentity(message);
7670
+ return identity.length > 0 && this.contributedIdentities.has(identity);
7671
+ }
7672
+ filterUncontributedMessages(messages, sessionId) {
7673
+ if (this.contributedSessionId !== sessionId || this.contributedIdentities.size === 0) {
7674
+ return [...messages];
7675
+ }
7676
+ return messages.filter((message) => {
7677
+ const identity = inboxNoticeMessageIdentity(message);
7678
+ return identity.length === 0 || !this.contributedIdentities.has(identity);
7679
+ });
7680
+ }
7681
+ pruneContributedToPending(messages, sessionId) {
7682
+ this.ensureContributionSession(sessionId);
7683
+ if (this.contributedIdentities.size === 0) return;
7684
+ const pending = /* @__PURE__ */ new Set();
7685
+ for (const message of messages) {
7686
+ const identity = inboxNoticeMessageIdentity(message);
7687
+ if (identity.length > 0) pending.add(identity);
7688
+ }
7689
+ for (const identity of this.contributedIdentities) {
7690
+ if (!pending.has(identity)) {
7691
+ this.contributedIdentities.delete(identity);
7692
+ }
7693
+ }
7694
+ }
7695
+ isDuplicateEncodeFailedNotice(fingerprint, sessionId) {
7696
+ if (fingerprint.length === 0) return false;
7697
+ return this.lastEncodeFailedFingerprint === fingerprint && this.lastEncodeFailedSessionId === sessionId;
7698
+ }
7699
+ recordNoticeEncodeFailed(fingerprint, sessionId) {
7700
+ if (fingerprint.length === 0) return;
7701
+ this.lastEncodeFailedFingerprint = fingerprint;
7702
+ this.lastEncodeFailedSessionId = sessionId;
7449
7703
  }
7450
7704
  clearNoticeFingerprint() {
7451
7705
  this.lastNoticeFingerprint = null;
7452
7706
  this.lastNoticeSessionId = null;
7707
+ this.lastEncodeFailedFingerprint = null;
7708
+ this.lastEncodeFailedSessionId = null;
7709
+ this.contributedSessionId = null;
7710
+ this.contributedIdentities.clear();
7453
7711
  }
7454
7712
  schedule(callback, delayMs) {
7455
7713
  if (this.timerValue) return false;
@@ -7462,6 +7720,11 @@ var RuntimeNotificationState = class {
7462
7720
  this.clearTimer();
7463
7721
  return count;
7464
7722
  }
7723
+ ensureContributionSession(sessionId) {
7724
+ if (this.contributedSessionId === sessionId) return;
7725
+ this.contributedSessionId = sessionId;
7726
+ this.contributedIdentities.clear();
7727
+ }
7465
7728
  };
7466
7729
 
7467
7730
  // src/agentProcessManager.ts
@@ -8605,6 +8868,7 @@ var RUNTIME_TELEMETRY_RESERVED_ATTR_KEYS = /* @__PURE__ */ new Set([
8605
8868
  "sessionId",
8606
8869
  "turnId",
8607
8870
  "runtimeResultId",
8871
+ "runtimeResultIdSource",
8608
8872
  "daemonVersion",
8609
8873
  "daemon_version",
8610
8874
  "daemon_version_present",
@@ -8780,13 +9044,33 @@ var AgentProcessManager = class _AgentProcessManager {
8780
9044
  this.sendStdinNotification(agentId);
8781
9045
  }, delayMs);
8782
9046
  }
9047
+ flushPendingDirectStdinNotificationOnRuntimeProgress(agentId, ap, source) {
9048
+ if (ap.notifications.pendingCount === 0) return false;
9049
+ if (ap.isIdle) return false;
9050
+ if (!ap.sessionId) return false;
9051
+ if (!ap.driver.supportsStdinNotification) return false;
9052
+ if (ap.runtime.descriptor.busyDelivery !== "direct") return false;
9053
+ if (ap.gatedSteering.compacting) return false;
9054
+ this.recordDaemonTrace("daemon.agent.stdin_notification.retry_signal", {
9055
+ agentId,
9056
+ runtime: ap.config.runtime,
9057
+ model: ap.config.model,
9058
+ launchId: ap.launchId || void 0,
9059
+ source,
9060
+ mode: "busy",
9061
+ pending_notification_count: ap.notifications.pendingCount,
9062
+ inbox_count: ap.inbox.length,
9063
+ session_id_present: true
9064
+ });
9065
+ return this.sendStdinNotification(agentId, { forceUnsupportedRetry: true });
9066
+ }
8783
9067
  clearRuntimeErrorDeliveryBackoff(ap) {
8784
9068
  if (ap.runtimeErrorDeliveryBackoff.timer) {
8785
9069
  clearTimeout(ap.runtimeErrorDeliveryBackoff.timer);
8786
9070
  }
8787
9071
  ap.runtimeErrorDeliveryBackoff = createRuntimeErrorDeliveryBackoffState();
8788
9072
  }
8789
- clearRuntimeErrorDeliveryBackoffAfterProgress(agentId, ap, eventKind) {
9073
+ clearRuntimeErrorDeliveryBackoffWithTrace(agentId, ap, resetSource) {
8790
9074
  if (ap.runtimeErrorDeliveryBackoff.attempts === 0 && ap.runtimeErrorDeliveryBackoff.untilMs === 0) return;
8791
9075
  const attempts = ap.runtimeErrorDeliveryBackoff.attempts;
8792
9076
  const reason = ap.runtimeErrorDeliveryBackoff.reason;
@@ -8798,9 +9082,12 @@ var AgentProcessManager = class _AgentProcessManager {
8798
9082
  launchId: ap.launchId || void 0,
8799
9083
  reason: reason || void 0,
8800
9084
  attempts,
8801
- reset_source: eventKind
9085
+ reset_source: resetSource
8802
9086
  });
8803
9087
  }
9088
+ clearRuntimeErrorDeliveryBackoffAfterProgress(agentId, ap, eventKind) {
9089
+ this.clearRuntimeErrorDeliveryBackoffWithTrace(agentId, ap, eventKind);
9090
+ }
8804
9091
  runtimeErrorDeliveryBackoffRemainingMs(ap) {
8805
9092
  return Math.max(0, ap.runtimeErrorDeliveryBackoff.untilMs - Date.now());
8806
9093
  }
@@ -8828,8 +9115,10 @@ var AgentProcessManager = class _AgentProcessManager {
8828
9115
  return "provider_connection_error";
8829
9116
  case "ProviderStreamError":
8830
9117
  return "provider_stream_error";
8831
- default:
9118
+ case "TimeoutError":
8832
9119
  return null;
9120
+ default:
9121
+ return "runtime_error";
8833
9122
  }
8834
9123
  }
8835
9124
  noteRuntimeErrorDeliveryBackoff(agentId, ap, message, terminalFailure, stickyTerminalFailure, reasonOverride) {
@@ -8900,9 +9189,24 @@ var AgentProcessManager = class _AgentProcessManager {
8900
9189
  if (ap.inbox.length === 0) return false;
8901
9190
  const reason = ap.runtimeErrorDeliveryBackoff.reason || "runtime_error_backoff";
8902
9191
  if (ap.isIdle && ap.driver.supportsStdinNotification && ap.sessionId) {
8903
- const messages = [...ap.inbox];
9192
+ ap.notifications.pruneContributedToPending(ap.inbox, ap.sessionId);
9193
+ const messages = ap.notifications.filterUncontributedMessages(ap.inbox, ap.sessionId);
8904
9194
  ap.notifications.clearPending();
8905
9195
  ap.notifications.clearTimer();
9196
+ if (messages.length === 0) {
9197
+ this.recordDaemonTrace("daemon.agent.runtime_error_delivery_backoff.flush", {
9198
+ agentId,
9199
+ runtime: ap.config.runtime,
9200
+ model: ap.config.model,
9201
+ launchId: ap.launchId || void 0,
9202
+ reason,
9203
+ mode: "idle",
9204
+ outcome: "suppressed_already_contributed",
9205
+ inbox_count: ap.inbox.length,
9206
+ messages_count: 0
9207
+ });
9208
+ return false;
9209
+ }
8906
9210
  this.commitApmIdleState(agentId, ap, false);
8907
9211
  this.startRuntimeTrace(agentId, ap, "runtime-error-backoff-idle-delivery", messages);
8908
9212
  this.broadcastActivity(agentId, "working", "Message received");
@@ -9583,6 +9887,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
9583
9887
  runtimeProgress: new RuntimeProgressState(Date.now()),
9584
9888
  runtimeTraceSpan: null,
9585
9889
  runtimeTraceCounters: createRuntimeTraceCounters(),
9890
+ runtimeTelemetryResultSeq: 0,
9586
9891
  lastActivity: "",
9587
9892
  lastActivityDetail: "",
9588
9893
  recentStdout: [],
@@ -10135,6 +10440,8 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
10135
10440
  this.agents.delete(agentId);
10136
10441
  if (!silent) {
10137
10442
  this.activityClientSeqByAgent.delete(agentId);
10443
+ this.agentVisibleBoundaries.delete(agentId);
10444
+ this.agentVisibleMessageIds.delete(agentId);
10138
10445
  }
10139
10446
  this.runtimeExitTraceAttrs.set(ap.runtime, {
10140
10447
  stop_source: silent ? "daemon_internal" : "explicit_request",
@@ -10358,6 +10665,25 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
10358
10665
  }));
10359
10666
  return true;
10360
10667
  }
10668
+ ap.notifications.pruneContributedToPending(ap.inbox, ap.sessionId);
10669
+ const noticeFingerprint = computeInboxNoticeFingerprint([message]);
10670
+ const messageAlreadyPending = noticeFingerprint.length > 0 && ap.inbox.some((pending) => computeInboxNoticeFingerprint([pending]) === noticeFingerprint);
10671
+ const messageAlreadyContributed = ap.notifications.hasContributedMessage(message, ap.sessionId);
10672
+ if (messageAlreadyPending && (messageAlreadyContributed || ap.notifications.isDuplicateNotice(noticeFingerprint, ap.sessionId))) {
10673
+ this.recordDaemonTrace("daemon.agent.delivery.routed", this.deliveryTraceAttrs(agentId, message, {
10674
+ outcome: "suppressed_duplicate_stdin_idle_delivery",
10675
+ accepted: true,
10676
+ process_present: true,
10677
+ runtime: ap.config.runtime,
10678
+ session_id_present: true,
10679
+ launchId: ap.launchId || void 0,
10680
+ is_idle: ap.isIdle,
10681
+ inbox_count: ap.inbox.length,
10682
+ pending_notification_count: ap.notifications.pendingCount
10683
+ }));
10684
+ logger.info(`[Agent ${agentId}] Suppressing duplicate idle stdin inbox update (unread-set unchanged since last write); pending=${ap.inbox.length}`);
10685
+ return true;
10686
+ }
10361
10687
  ap.inbox.push(message);
10362
10688
  const nextMessages = [...ap.inbox];
10363
10689
  this.commitApmIdleState(agentId, ap, false);
@@ -11226,6 +11552,8 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
11226
11552
  if (row.flags.includes("task")) taskTargetCount += 1;
11227
11553
  }
11228
11554
  return {
11555
+ target_count: rows.length,
11556
+ changed_target_count: rows.length,
11229
11557
  inbox_target_count: rows.length,
11230
11558
  pending_message_count: pendingMessageCount,
11231
11559
  max_pending_per_target: maxPendingCount,
@@ -11399,7 +11727,9 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
11399
11727
  return false;
11400
11728
  }
11401
11729
  const messages = [...ap.inbox];
11402
- ap.notifications.clear();
11730
+ ap.notifications.pruneContributedToPending(ap.inbox, ap.sessionId);
11731
+ ap.notifications.clearPending();
11732
+ ap.notifications.clearTimer();
11403
11733
  if (messages.length === 0) {
11404
11734
  this.recordApmGatedSteeringEffectTrace(agentId, ap, effect, {
11405
11735
  outcome: "empty",
@@ -11415,12 +11745,23 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
11415
11745
  messageCount: messages.length
11416
11746
  });
11417
11747
  }
11418
- this.broadcastActivity(agentId, "working", "Message received");
11419
11748
  const runtimeProfileMessages = messages.filter((message) => runtimeProfileNotificationFromMessage(message));
11420
- const ordinaryMessages = messages.filter((message) => !runtimeProfileNotificationFromMessage(message));
11749
+ const ordinaryMessageCandidates = messages.filter((message) => !runtimeProfileNotificationFromMessage(message));
11750
+ const ordinaryMessages = ap.notifications.filterUncontributedMessages(
11751
+ ordinaryMessageCandidates,
11752
+ ap.sessionId
11753
+ );
11754
+ if (runtimeProfileMessages.length === 0 && ordinaryMessages.length === 0) {
11755
+ this.recordApmGatedSteeringEffectTrace(agentId, ap, effect, {
11756
+ outcome: "suppressed_already_contributed",
11757
+ delivered_messages_count: 0
11758
+ });
11759
+ return false;
11760
+ }
11761
+ this.broadcastActivity(agentId, "working", "Message received");
11421
11762
  let accepted = true;
11422
11763
  if (runtimeProfileMessages.length > 0) {
11423
- ap.inbox.splice(0, ap.inbox.length, ...ordinaryMessages);
11764
+ ap.inbox.splice(0, ap.inbox.length, ...ordinaryMessageCandidates);
11424
11765
  accepted = this.deliverMessagesViaStdin(agentId, ap, runtimeProfileMessages, effect.stdinMode);
11425
11766
  }
11426
11767
  if (ordinaryMessages.length > 0) {
@@ -11434,7 +11775,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
11434
11775
  }
11435
11776
  this.recordApmGatedSteeringEffectTrace(agentId, ap, effect, {
11436
11777
  outcome: accepted ? "written" : "not_written",
11437
- delivered_messages_count: messages.length
11778
+ delivered_messages_count: runtimeProfileMessages.length + ordinaryMessages.length
11438
11779
  });
11439
11780
  return accepted;
11440
11781
  }
@@ -11666,6 +12007,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
11666
12007
  this.clearRuntimeErrorDeliveryBackoffAfterProgress(agentId, ap, event.kind);
11667
12008
  const reduction = reduceApmGatedAssistantContinuation(ap.gatedSteering);
11668
12009
  this.commitGatedSteeringDecisionState(agentId, ap, reduction.nextState, { event: "thinking" });
12010
+ this.flushPendingDirectStdinNotificationOnRuntimeProgress(agentId, ap, event.kind);
11669
12011
  }
11670
12012
  break;
11671
12013
  }
@@ -11676,6 +12018,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
11676
12018
  this.clearRuntimeErrorDeliveryBackoffAfterProgress(agentId, ap, event.kind);
11677
12019
  const reduction = reduceApmGatedAssistantContinuation(ap.gatedSteering);
11678
12020
  this.commitGatedSteeringDecisionState(agentId, ap, reduction.nextState, { event: "text" });
12021
+ this.flushPendingDirectStdinNotificationOnRuntimeProgress(agentId, ap, event.kind);
11679
12022
  }
11680
12023
  break;
11681
12024
  }
@@ -11748,6 +12091,9 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
11748
12091
  if (ap) {
11749
12092
  if (event.sessionId) ap.sessionId = event.sessionId;
11750
12093
  const stickyTerminalFailure = classifyStickyTerminalFailure(ap);
12094
+ if (!stickyTerminalFailure && ap.runtimeErrorDeliveryBackoff.reason === "runtime_error") {
12095
+ this.clearRuntimeErrorDeliveryBackoffWithTrace(agentId, ap, "turn_end_unclassified_runtime_error");
12096
+ }
11751
12097
  const reduction = reduceApmGatedTurnEnd(ap.gatedSteering, {
11752
12098
  inboxLength: stickyTerminalFailure ? 0 : ap.inbox.length,
11753
12099
  supportsStdinNotification: ap.driver.supportsStdinNotification,
@@ -11879,7 +12225,8 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
11879
12225
  }
11880
12226
  }
11881
12227
  recordRuntimeTelemetry(agentId, ap, event) {
11882
- const sessionId = ap.driver.currentSessionId ?? event.sessionId;
12228
+ const sessionId = ap.driver.currentSessionId ?? event.sessionId ?? ap.sessionId ?? ap.config.sessionId;
12229
+ const resultIdentity = this.runtimeTelemetryResultIdentity(agentId, ap, event);
11883
12230
  const payloadAttrs = sanitizeRuntimeTelemetryPayloadAttrs(event.attrs);
11884
12231
  const versionAttrs = this.runtimeTelemetryVersionAttrs();
11885
12232
  const telemetryAttrs = {
@@ -11889,7 +12236,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
11889
12236
  ...event.usageKind ? { usageKind: event.usageKind } : {},
11890
12237
  ...sessionId ? { sessionId } : {},
11891
12238
  ...event.turnId ? { turnId: event.turnId } : {},
11892
- ...event.runtimeResultId ? { runtimeResultId: event.runtimeResultId } : {}
12239
+ ...resultIdentity
11893
12240
  };
11894
12241
  const attrs = {
11895
12242
  agentId,
@@ -11902,6 +12249,16 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
11902
12249
  ap.runtimeTraceSpan?.addEvent(`runtime.telemetry.${event.name}`, telemetryAttrs);
11903
12250
  this.recordDaemonTrace(`daemon.runtime.telemetry.${event.name}`, attrs);
11904
12251
  }
12252
+ runtimeTelemetryResultIdentity(agentId, ap, event) {
12253
+ if (event.runtimeResultId) return { runtimeResultId: event.runtimeResultId };
12254
+ if (event.name !== "token_usage" || event.source !== "claude_result_usage") return {};
12255
+ const sequence = ++ap.runtimeTelemetryResultSeq;
12256
+ const scope = ap.launchId || agentId;
12257
+ return {
12258
+ runtimeResultId: `${scope}:claude_result_usage:${sequence}`,
12259
+ runtimeResultIdSource: "daemon_sequence"
12260
+ };
12261
+ }
11905
12262
  runtimeTelemetryVersionAttrs() {
11906
12263
  return {
11907
12264
  ...this.daemonVersion ? {
@@ -11970,7 +12327,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
11970
12327
  }
11971
12328
  }
11972
12329
  /** Send a batched notification to the agent via stdin about pending messages */
11973
- sendStdinNotification(agentId) {
12330
+ sendStdinNotification(agentId, options = {}) {
11974
12331
  const ap = this.agents.get(agentId);
11975
12332
  if (!ap) return false;
11976
12333
  const count = ap.notifications.takePendingAndClearTimer();
@@ -12012,7 +12369,24 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
12012
12369
  }
12013
12370
  const inboxCount = ap.inbox.length;
12014
12371
  if (inboxCount === 0) return false;
12015
- const changedMessages = ap.inbox.slice(Math.max(0, ap.inbox.length - count));
12372
+ ap.notifications.pruneContributedToPending(ap.inbox, ap.sessionId);
12373
+ const changedMessageCandidates = ap.inbox.slice(Math.max(0, ap.inbox.length - count));
12374
+ const changedMessages = ap.notifications.filterUncontributedMessages(changedMessageCandidates, ap.sessionId);
12375
+ if (changedMessages.length === 0) {
12376
+ this.recordDaemonTrace("daemon.agent.stdin_notification", {
12377
+ agentId,
12378
+ runtime: ap.config.runtime,
12379
+ model: ap.config.model,
12380
+ launchId: ap.launchId || void 0,
12381
+ outcome: "suppressed_already_contributed",
12382
+ mode: "busy",
12383
+ pending_notification_count: count,
12384
+ inbox_count: ap.inbox.length,
12385
+ session_id_present: true
12386
+ });
12387
+ logger.info(`[Agent ${agentId}] Suppressing stdin inbox notice because all candidate messages already contributed; pending=${ap.inbox.length}`);
12388
+ return false;
12389
+ }
12016
12390
  const noticeFingerprint = computeInboxNoticeFingerprint(changedMessages);
12017
12391
  if (ap.notifications.isDuplicateNotice(noticeFingerprint, ap.sessionId)) {
12018
12392
  this.recordDaemonTrace("daemon.agent.stdin_notification", {
@@ -12029,6 +12403,22 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
12029
12403
  logger.info(`[Agent ${agentId}] Suppressing duplicate stdin inbox notice (unread-set unchanged since last write); pending=${ap.inbox.length}`);
12030
12404
  return false;
12031
12405
  }
12406
+ if (!options.forceUnsupportedRetry && ap.notifications.isDuplicateEncodeFailedNotice(noticeFingerprint, ap.sessionId)) {
12407
+ ap.notifications.add(count);
12408
+ this.recordDaemonTrace("daemon.agent.stdin_notification", {
12409
+ agentId,
12410
+ runtime: ap.config.runtime,
12411
+ model: ap.config.model,
12412
+ launchId: ap.launchId || void 0,
12413
+ outcome: "suppressed_duplicate_encode_failed",
12414
+ mode: "busy",
12415
+ pending_notification_count: count,
12416
+ inbox_count: ap.inbox.length,
12417
+ session_id_present: true
12418
+ });
12419
+ logger.info(`[Agent ${agentId}] Suppressing duplicate unsupported stdin inbox notice (unread-set unchanged since last encode failure); pending=${ap.inbox.length}`);
12420
+ return false;
12421
+ }
12032
12422
  const inboxRows = projectAgentInboxSnapshot(changedMessages);
12033
12423
  const notification = `[Slock inbox notice:
12034
12424
  ${formatAgentInboxDelta(inboxRows, { totalPendingMessages: inboxCount })}]`;
@@ -12051,6 +12441,7 @@ ${formatAgentInboxDelta(inboxRows, { totalPendingMessages: inboxCount })}]`;
12051
12441
  model: ap.config.model,
12052
12442
  launchId: ap.launchId || void 0,
12053
12443
  mode: "busy",
12444
+ source: "busy_stdin_notification",
12054
12445
  notification_byte_count: notificationByteCount,
12055
12446
  ...projectionAttrs
12056
12447
  });
@@ -12066,12 +12457,15 @@ ${formatAgentInboxDelta(inboxRows, { totalPendingMessages: inboxCount })}]`;
12066
12457
  inbox_target_count: inboxRows.length,
12067
12458
  session_id_present: true
12068
12459
  });
12069
- ap.notifications.recordNoticeWritten(noticeFingerprint, ap.sessionId);
12460
+ ap.notifications.recordNoticeWritten(noticeFingerprint, ap.sessionId, changedMessages);
12070
12461
  return true;
12071
12462
  } else {
12072
12463
  ap.notifications.add(count);
12073
- const retryScheduled = ap.runtime.descriptor.busyDelivery === "direct" ? this.scheduleStdinNotification(agentId, ap, this.stdinNotificationRetryMs) : false;
12464
+ const retryScheduled = ap.runtime.descriptor.busyDelivery === "direct" && sendResult.reason !== "unsupported" ? this.scheduleStdinNotification(agentId, ap, this.stdinNotificationRetryMs) : false;
12074
12465
  const outcome = runtimeSendFailureOutcome(sendResult);
12466
+ if (outcome === "encode_failed") {
12467
+ ap.notifications.recordNoticeEncodeFailed(noticeFingerprint, ap.sessionId);
12468
+ }
12075
12469
  this.recordDaemonTrace("daemon.agent.stdin_notification", {
12076
12470
  agentId,
12077
12471
  runtime: ap.config.runtime,
@@ -12113,6 +12507,7 @@ ${formatAgentInboxDelta(inboxRows, { totalPendingMessages: inboxCount })}]`;
12113
12507
  model: ap.config.model,
12114
12508
  launchId: ap.launchId || void 0,
12115
12509
  mode,
12510
+ source,
12116
12511
  notification_byte_count: Buffer.byteLength(renderedInput, "utf8"),
12117
12512
  cursors_advanced: "none",
12118
12513
  ...projectionAttrs
@@ -12191,6 +12586,7 @@ ${formatAgentInboxDelta(inboxRows, { totalPendingMessages: inboxCount })}]`;
12191
12586
  stdin_write_attempted: true,
12192
12587
  cursors_advanced: "none"
12193
12588
  });
12589
+ ap.notifications.recordNoticeWritten(computeInboxNoticeFingerprint(messages), ap.sessionId, messages);
12194
12590
  return true;
12195
12591
  }
12196
12592
  /** Deliver a message to an agent via stdin, formatting it the same way as the MCP bridge */
@@ -12407,7 +12803,7 @@ var DaemonConnection = class {
12407
12803
  logger.warn(`[Daemon] Dropping outbound message while disconnected: ${msg.type}`);
12408
12804
  }
12409
12805
  this.trace("daemon.connection.outbound_dropped", {
12410
- message_type: msg.type,
12806
+ outbound_message_kind: msg.type,
12411
12807
  ws_ready_state: this.ws?.readyState ?? null
12412
12808
  });
12413
12809
  }
@@ -12456,7 +12852,7 @@ var DaemonConnection = class {
12456
12852
  this.resetWatchdog();
12457
12853
  if (messageKind !== "ping") {
12458
12854
  this.trace("daemon.connection.inbound_received", {
12459
- message_type: messageKind,
12855
+ inbound_message_kind: messageKind,
12460
12856
  last_inbound_age_ms_bucket: "0"
12461
12857
  });
12462
12858
  }
@@ -12547,7 +12943,7 @@ var DaemonConnection = class {
12547
12943
  if (msg.launchId && latestLaunchId && msg.launchId !== latestLaunchId) {
12548
12944
  this.trace("daemon.connection.pending_activity_invalidated", {
12549
12945
  reason: "launch_changed",
12550
- message_type: msg.type,
12946
+ outbound_message_kind: msg.type,
12551
12947
  agentId: msg.agentId,
12552
12948
  stale_launch_id_present: true,
12553
12949
  next_launch_id_present: true
@@ -12567,7 +12963,7 @@ var DaemonConnection = class {
12567
12963
  this.pendingActivityByAgent.delete(identity.agentId);
12568
12964
  this.trace("daemon.connection.pending_activity_invalidated", {
12569
12965
  reason: "launch_changed",
12570
- message_type: msg.type,
12966
+ outbound_message_kind: msg.type,
12571
12967
  agentId: identity.agentId,
12572
12968
  stale_launch_id_present: Boolean(pending.launchId),
12573
12969
  next_launch_id_present: true
@@ -12596,7 +12992,7 @@ var DaemonConnection = class {
12596
12992
  ws.send(JSON.stringify(msg));
12597
12993
  }
12598
12994
  this.trace("daemon.connection.outbound_replayed", {
12599
- message_type: "agent:activity",
12995
+ outbound_message_kind: "agent:activity",
12600
12996
  message_count: pending.length
12601
12997
  });
12602
12998
  }
@@ -13422,7 +13818,52 @@ var DEFAULT_TRACE_UPLOAD_URL = "https://slock-trace-upload.botiverse.dev";
13422
13818
  var RUNNER_CREDENTIAL_SCOPES = ["send", "read", "mentions", "tasks", "reactions", "server", "channels", "knowledge"];
13423
13819
  var RUNNER_CREDENTIAL_MINT_MAX_ATTEMPTS2 = 3;
13424
13820
  var RUNNER_CREDENTIAL_MINT_RETRY_DELAY_MS2 = 250;
13425
- var DAEMON_CLI_USAGE = "Usage: slock-daemon --server-url <url> --api-key <key>";
13821
+ var DAEMON_CORE_TRACE_ATTR_CONTRACTS = {
13822
+ "daemon.lifecycle.start": {
13823
+ spanAttrs: ["machine_dir_present", "local_trace_enabled"],
13824
+ eventAttrs: {
13825
+ "daemon.machine_lock.acquired": ["machine_dir_present"]
13826
+ }
13827
+ },
13828
+ "daemon.lifecycle.stop": {
13829
+ spanAttrs: ["machine_lock_present"]
13830
+ },
13831
+ "daemon.runner_credential_mint.retry": {
13832
+ spanAttrs: ["agentId", "runtime", "attempt", "max_attempts", "status", "code", "reason", "retryable"]
13833
+ },
13834
+ "daemon.runner_credential_mint.failed": {
13835
+ spanAttrs: ["agentId", "runtime", "status", "code", "reason", "retryable", "max_attempts"]
13836
+ },
13837
+ "daemon.agent.spawn.failed": {
13838
+ spanAttrs: ["agentId", "launchId", "runtime", "model", "failure_reason", "failure_detail", "session_id_present"]
13839
+ },
13840
+ "daemon.agent.delivery": {
13841
+ spanAttrs: ["agentId", "deliveryId", "delivery_correlation_id", "messageId", "message_id_present", "seq"],
13842
+ eventAttrs: {
13843
+ "daemon.receive": ["seq", "deliveryId"],
13844
+ "daemon.deliver_to_agent_manager": ["accepted"],
13845
+ "daemon.ack.sent": ["seq"]
13846
+ },
13847
+ endAttrs: ["outcome", "ackSeq", "deliveryId", "error_class"]
13848
+ },
13849
+ "daemon.runtime_profile.control.received": {
13850
+ spanAttrs: ["agentId", "control_kind", "key_present", "launchId"],
13851
+ endAttrs: ["outcome", "error_class"]
13852
+ },
13853
+ "daemon.computer_control.received": {
13854
+ spanAttrs: ["action", "handled"]
13855
+ },
13856
+ "daemon.ready.sent": {
13857
+ spanAttrs: ["runtimes_count", "running_agents_count", "idle_agents_count", "runtime_profile_reports_count"]
13858
+ },
13859
+ "daemon.runtime_profile.report.sent": {
13860
+ spanAttrs: ["agentId", "launchId", "runtime", "report_source", "model_present", "session_ref_present", "workspace_ref_present"]
13861
+ },
13862
+ "daemon.connection.local_disconnect_observed": {
13863
+ spanAttrs: ["running_agents_count", "idle_agents_count"]
13864
+ }
13865
+ };
13866
+ var DAEMON_CLI_USAGE = `Usage: slock-daemon --server-url <url> (--api-key <key> or ${DAEMON_API_KEY_ENV}=<key>)`;
13426
13867
  var RunnerCredentialMintError2 = class extends Error {
13427
13868
  code;
13428
13869
  retryable;
@@ -13458,9 +13899,9 @@ function runnerCredentialErrorDetail2(error) {
13458
13899
  async function waitForRunnerCredentialRetry2() {
13459
13900
  await new Promise((resolve) => setTimeout(resolve, RUNNER_CREDENTIAL_MINT_RETRY_DELAY_MS2));
13460
13901
  }
13461
- function parseDaemonCliArgs(args) {
13902
+ function parseDaemonCliArgs(args, env = {}) {
13462
13903
  let serverUrl = "";
13463
- let apiKey = "";
13904
+ let apiKey = env[DAEMON_API_KEY_ENV] ?? "";
13464
13905
  for (let i = 0; i < args.length; i++) {
13465
13906
  if (args[i] === "--server-url" && args[i + 1]) serverUrl = args[++i];
13466
13907
  if (args[i] === "--api-key" && args[i + 1]) apiKey = args[++i];
@@ -13629,6 +14070,8 @@ var DaemonCore = class {
13629
14070
  tracer;
13630
14071
  injectedTracer;
13631
14072
  machineLock = null;
14073
+ observedServerId = null;
14074
+ observedMachineId = null;
13632
14075
  localTraceSink = null;
13633
14076
  traceBundleUploader = null;
13634
14077
  constructor(options) {
@@ -13679,6 +14122,7 @@ var DaemonCore = class {
13679
14122
  return process.env.SLOCK_DAEMON_LOCAL_TRACE !== "0";
13680
14123
  }
13681
14124
  resolveTraceJitter() {
14125
+ if (process.env.SLOCK_DAEMON_TRACE_JITTER_DISABLED === "1") return NO_JITTER;
13682
14126
  const lockId = this.machineLock?.lockId;
13683
14127
  return lockId ? computeTraceJitter(lockId) : NO_JITTER;
13684
14128
  }
@@ -13710,7 +14154,7 @@ var DaemonCore = class {
13710
14154
  workerUrl,
13711
14155
  tracer: this.tracer,
13712
14156
  currentFileProvider: () => this.localTraceSink?.getCurrentFile() ?? null,
13713
- lockId: this.machineLock?.lockId
14157
+ jitter: this.resolveTraceJitter()
13714
14158
  });
13715
14159
  this.traceBundleUploader.start();
13716
14160
  }
@@ -13789,22 +14233,29 @@ var DaemonCore = class {
13789
14233
  span.end(status);
13790
14234
  }
13791
14235
  withDaemonTraceScope(tracer) {
13792
- return createScopedTracer(tracer, this.daemonTraceScopeAttrs());
14236
+ return {
14237
+ startSpan: (name, options) => createTraceScopeTracer(tracer, this.daemonTraceScope(), {
14238
+ spanAttrContracts: DAEMON_CORE_TRACE_ATTR_CONTRACTS
14239
+ }).startSpan(name, options)
14240
+ };
13793
14241
  }
13794
- daemonTraceScopeAttrs() {
14242
+ daemonTraceScope() {
13795
14243
  return {
13796
- daemonVersion: this.daemonVersion,
13797
- daemon_version: this.daemonVersion,
13798
- daemon_version_present: Boolean(this.daemonVersion),
13799
- ...this.computerVersion ? {
13800
- computerVersion: this.computerVersion,
13801
- computer_version: this.computerVersion,
13802
- computer_version_present: true
13803
- } : {
13804
- computer_version_present: false
14244
+ resource: {
14245
+ daemonVersion: this.daemonVersion,
14246
+ computerVersion: this.computerVersion
14247
+ },
14248
+ actor: {
14249
+ serverId: this.observedServerId,
14250
+ machineId: this.observedMachineId
13805
14251
  }
13806
14252
  };
13807
14253
  }
14254
+ observeRuntimeContext(config) {
14255
+ const ctx = config.runtimeContext;
14256
+ if (ctx?.serverId) this.observedServerId = ctx.serverId;
14257
+ if (ctx?.machineId) this.observedMachineId = ctx.machineId;
14258
+ }
13808
14259
  async requestRunnerCredentialOnce(agentId, config) {
13809
14260
  const url = new URL(`/internal/computer/runners/${encodeURIComponent(agentId)}/credentials`, this.options.serverUrl);
13810
14261
  const res = await daemonFetch(url, {
@@ -13896,6 +14347,7 @@ var DaemonCore = class {
13896
14347
  );
13897
14348
  }
13898
14349
  async startAgentFromMessage(msg) {
14350
+ this.observeRuntimeContext(msg.config);
13899
14351
  const agentCredential = await this.mintRunnerCredential(msg.agentId, msg.config);
13900
14352
  const config = { ...msg.config, agentCredentialKey: agentCredential.apiKey, agentCredentialId: agentCredential.credentialId };
13901
14353
  await this.agentManager.startAgent(
@@ -13913,6 +14365,7 @@ var DaemonCore = class {
13913
14365
  logger.info(`[Daemon] Received ${msg.type}${summary ? ` ${summary}` : ""}`);
13914
14366
  switch (msg.type) {
13915
14367
  case "agent:start":
14368
+ this.observeRuntimeContext(msg.config);
13916
14369
  logger.info(`[Agent ${msg.agentId}] Start requested (runtime=${msg.config.runtime}, model=${msg.config.model}, session=${msg.config.sessionId || "new"}${msg.wakeMessage ? ", wake=true" : ""})`);
13917
14370
  this.startAgentFromMessage(msg).catch((err) => {
13918
14371
  const classification = classifySpawnFailure(err);
@@ -14229,6 +14682,8 @@ var DaemonCore = class {
14229
14682
  };
14230
14683
 
14231
14684
  export {
14685
+ DAEMON_API_KEY_ENV,
14686
+ scrubDaemonAuthEnv,
14232
14687
  subscribeDaemonLogs,
14233
14688
  resolveWorkspaceDirectoryPath,
14234
14689
  scanWorkspaceDirectories,
package/dist/cli/index.js CHANGED
@@ -860,11 +860,17 @@ async function runDeviceCodeLogin(options) {
860
860
  const pollIntervalMs = options.pollIntervalOverrideMs ?? serverIntervalMs;
861
861
  const deadlineMs = Date.now() + Math.max(1, authorizeBody.expiresIn ?? 600) * 1e3;
862
862
  while (Date.now() < deadlineMs) {
863
- const tokenRes = await httpFetch(`${base}/api/auth/device/token`, {
864
- method: "POST",
865
- headers: { "content-type": "application/json" },
866
- body: JSON.stringify({ deviceCode: authorizeBody.deviceCode })
867
- });
863
+ let tokenRes;
864
+ try {
865
+ tokenRes = await httpFetch(`${base}/api/auth/device/token`, {
866
+ method: "POST",
867
+ headers: { "content-type": "application/json" },
868
+ body: JSON.stringify({ deviceCode: authorizeBody.deviceCode })
869
+ });
870
+ } catch {
871
+ await delay(pollIntervalMs);
872
+ continue;
873
+ }
868
874
  if (tokenRes.ok) {
869
875
  const tokenBody = await tokenRes.json();
870
876
  if (!tokenBody.accessToken || !tokenBody.refreshToken || !tokenBody.userId) {
@@ -15249,6 +15255,12 @@ var SERVER_CAPABILITY_MATRIX = {
15249
15255
  };
15250
15256
 
15251
15257
  // ../shared/src/index.ts
15258
+ var EXTERNAL_AGENT_RUNTIME_ID = "external";
15259
+ var EXTERNAL_AGENT_RUNTIME_MODEL = "external";
15260
+ var EXTERNAL_AGENT_RUNTIME_DISPLAY_NAME = "External agent";
15261
+ function isExternalAgentRuntime(runtime) {
15262
+ return runtime === EXTERNAL_AGENT_RUNTIME_ID;
15263
+ }
15252
15264
  var RUNTIMES = [
15253
15265
  { id: "claude", displayName: "Claude Code", binary: "claude", supported: true },
15254
15266
  { id: "codex", displayName: "Codex CLI", binary: "codex", supported: true },
@@ -15261,8 +15273,71 @@ var RUNTIMES = [
15261
15273
  { id: "pi", displayName: "Pi", binary: "pi", supported: true }
15262
15274
  ];
15263
15275
  function getRuntimeDisplayName(id) {
15276
+ if (isExternalAgentRuntime(id)) return EXTERNAL_AGENT_RUNTIME_DISPLAY_NAME;
15264
15277
  return RUNTIMES.find((r) => r.id === id)?.displayName ?? id;
15265
15278
  }
15279
+ var RUNTIME_MODELS = {
15280
+ [EXTERNAL_AGENT_RUNTIME_ID]: [
15281
+ { id: EXTERNAL_AGENT_RUNTIME_MODEL, label: EXTERNAL_AGENT_RUNTIME_DISPLAY_NAME }
15282
+ ],
15283
+ claude: [
15284
+ { id: "opus", label: "Claude Opus" },
15285
+ { id: "claude-opus-4-8", label: "Claude Opus 4.8" },
15286
+ { id: "claude-opus-4-7", label: "Claude Opus 4.7" },
15287
+ { id: "claude-opus-4-6", label: "Claude Opus 4.6" },
15288
+ { id: "sonnet", label: "Claude Sonnet" },
15289
+ { id: "claude-sonnet-4-6", label: "Claude Sonnet 4.6" },
15290
+ { id: "haiku", label: "Claude Haiku" },
15291
+ { id: "claude-haiku-4-5", label: "Claude Haiku 4.5" }
15292
+ ],
15293
+ codex: [
15294
+ { id: "gpt-5.5", label: "GPT-5.5" },
15295
+ { id: "gpt-5.4", label: "GPT-5.4" },
15296
+ { id: "gpt-5.3-codex", label: "GPT-5.3 Codex" },
15297
+ { id: "gpt-5.3-codex-spark", label: "GPT-5.3 Codex Spark" },
15298
+ { id: "gpt-5.2-codex", label: "GPT-5.2 Codex" },
15299
+ { id: "gpt-5.2", label: "GPT-5.2" },
15300
+ { id: "gpt-5.1-codex-max", label: "GPT-5.1 Codex Max" },
15301
+ { id: "gpt-5.1-codex", label: "GPT-5.1 Codex" },
15302
+ { id: "gpt-5-codex", label: "GPT-5 Codex" },
15303
+ { id: "gpt-5", label: "GPT-5" }
15304
+ ],
15305
+ antigravity: [
15306
+ { id: "default", label: "AGY configured default", verified: "suggestion_only" }
15307
+ ],
15308
+ copilot: [
15309
+ { id: "gpt-5.4", label: "GPT-5.4" },
15310
+ { id: "gpt-5.2", label: "GPT-5.2" },
15311
+ { id: "claude-4-sonnet", label: "Claude 4 Sonnet" },
15312
+ { id: "claude-4.5-sonnet", label: "Claude 4.5 Sonnet" }
15313
+ ],
15314
+ cursor: [
15315
+ { id: "composer-2-fast", label: "Composer 2 Fast" },
15316
+ { id: "composer-2", label: "Composer 2" },
15317
+ { id: "auto", label: "Auto" }
15318
+ ],
15319
+ gemini: [
15320
+ { id: "default", label: "Configured Default / Auto", verified: "suggestion_only" },
15321
+ { id: "gemini-3.1-pro-preview", label: "Gemini 3.1 Pro (Preview)" },
15322
+ { id: "gemini-3-flash-preview", label: "Gemini 3 Flash (Preview)" },
15323
+ { id: "gemini-2.5-pro", label: "Gemini 2.5 Pro" },
15324
+ { id: "gemini-2.5-flash", label: "Gemini 2.5 Flash" }
15325
+ ],
15326
+ opencode: [
15327
+ { id: "default", label: "Configured Default / Auto", verified: "suggestion_only" },
15328
+ { id: "deepseek/deepseek-v4-pro", label: "DeepSeek V4 Pro (OpenCode)", verified: "suggestion_only" },
15329
+ { id: "openrouter/anthropic/claude-opus-4.5", label: "Claude Opus 4.5 via OpenRouter", verified: "suggestion_only" },
15330
+ { id: "fusecode/opus[1m]", label: "Opus 1M via FuseCode", verified: "suggestion_only" }
15331
+ ],
15332
+ pi: [
15333
+ { id: "default", label: "Configured Default / Auto", verified: "suggestion_only" }
15334
+ ],
15335
+ // Kimi CLI resolves model keys from each user's local config, so the safest
15336
+ // built-in option is to defer to whatever default model the CLI already uses.
15337
+ kimi: [
15338
+ { id: "default", label: "Configured Default" }
15339
+ ]
15340
+ };
15266
15341
  var PLAN_CONFIG = {
15267
15342
  free: {
15268
15343
  displayName: "Hobby",
package/dist/core.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import {
2
+ DAEMON_API_KEY_ENV,
2
3
  DAEMON_CLI_USAGE,
3
4
  DaemonCore,
4
5
  deleteWorkspaceDirectory,
@@ -8,9 +9,11 @@ import {
8
9
  resolveSlockCliPath,
9
10
  resolveWorkspaceDirectoryPath,
10
11
  scanWorkspaceDirectories,
12
+ scrubDaemonAuthEnv,
11
13
  subscribeDaemonLogs
12
- } from "./chunk-6RZCYFJP.js";
14
+ } from "./chunk-JVPMCKSF.js";
13
15
  export {
16
+ DAEMON_API_KEY_ENV,
14
17
  DAEMON_CLI_USAGE,
15
18
  DaemonCore,
16
19
  deleteWorkspaceDirectory,
@@ -20,5 +23,6 @@ export {
20
23
  resolveSlockCliPath,
21
24
  resolveWorkspaceDirectoryPath,
22
25
  scanWorkspaceDirectories,
26
+ scrubDaemonAuthEnv,
23
27
  subscribeDaemonLogs
24
28
  };
@@ -0,0 +1,96 @@
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
+ });
package/dist/index.js CHANGED
@@ -2,11 +2,13 @@
2
2
  import {
3
3
  DAEMON_CLI_USAGE,
4
4
  DaemonCore,
5
- parseDaemonCliArgs
6
- } from "./chunk-6RZCYFJP.js";
5
+ parseDaemonCliArgs,
6
+ scrubDaemonAuthEnv
7
+ } from "./chunk-JVPMCKSF.js";
7
8
 
8
9
  // src/index.ts
9
- var parsedArgs = parseDaemonCliArgs(process.argv.slice(2));
10
+ var parsedArgs = parseDaemonCliArgs(process.argv.slice(2), process.env);
11
+ scrubDaemonAuthEnv(process.env);
10
12
  if (!parsedArgs) {
11
13
  console.error(DAEMON_CLI_USAGE);
12
14
  process.exit(1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@slock-ai/daemon",
3
- "version": "0.57.1",
3
+ "version": "0.57.2-play.20260608142014",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "slock-daemon": "dist/index.js"