@slock-ai/daemon 0.49.0-play.20260516144406 → 0.50.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.
@@ -7,11 +7,11 @@ import {
7
7
  } from "./chunk-KNMCE6WB.js";
8
8
 
9
9
  // src/core.ts
10
- import path17 from "path";
10
+ import path16 from "path";
11
11
  import os8 from "os";
12
12
  import { createRequire } from "module";
13
13
  import { accessSync } from "fs";
14
- import { fileURLToPath as fileURLToPath2 } from "url";
14
+ import { fileURLToPath } from "url";
15
15
 
16
16
  // ../shared/src/tracing/index.ts
17
17
  var DEFAULT_TRACE_FLAGS = "00";
@@ -723,7 +723,6 @@ var SERVER_CAPABILITY_MATRIX = {
723
723
  var RUNTIMES = [
724
724
  { id: "claude", displayName: "Claude Code", binary: "claude", supported: true },
725
725
  { id: "codex", displayName: "Codex CLI", binary: "codex", supported: true },
726
- { id: "pi", displayName: "Pi", binary: "pi", supported: true },
727
726
  { id: "kimi", displayName: "Kimi CLI", binary: "kimi", supported: true },
728
727
  { id: "copilot", displayName: "Copilot CLI", binary: "copilot", supported: true },
729
728
  { id: "cursor", displayName: "Cursor CLI", binary: "cursor-agent", supported: true },
@@ -765,10 +764,10 @@ var DISPLAY_PLAN_CONFIG = {
765
764
  };
766
765
 
767
766
  // src/agentProcessManager.ts
768
- import { mkdirSync as mkdirSync5, readdirSync as readdirSync2, statSync as statSync2, writeFileSync as writeFileSync8 } from "fs";
767
+ import { mkdirSync as mkdirSync4, readdirSync as readdirSync2, statSync as statSync2, writeFileSync as writeFileSync7 } from "fs";
769
768
  import { mkdir, writeFile, access, readdir as readdir2, stat as stat2, readFile, rm as rm2 } from "fs/promises";
770
769
  import { createHash as createHash2 } from "crypto";
771
- import path13 from "path";
770
+ import path12 from "path";
772
771
  import os6 from "os";
773
772
 
774
773
  // src/drivers/claude.ts
@@ -872,15 +871,13 @@ Use the \`slock\` CLI for chat / task / attachment operations. The daemon inject
872
871
  17. **\`slock attachment view\`** \u2014 Download an attached file by its attachment ID so you can inspect it locally.
873
872
  18. **\`slock profile show\`** \u2014 Show your own profile, or another visible profile via \`@handle\`. Mirrors the canonical Slock profile view.
874
873
  19. **\`slock profile update\`** \u2014 Update your own profile. Supports \`--avatar-file <path>\`, \`--display-name <name>\`, and \`--description <text>\`. Values must be non-empty. Provide at least one flag per call; multiple flags can be combined.
875
- 20. **\`slock integration list\`** \u2014 List registered third-party services and this agent's active Slock Agent Logins.
876
- 21. **\`slock integration login\`** \u2014 Provision or reuse this agent's login for a registered third-party service.
877
- 22. **\`slock reminder schedule\`** \u2014 Schedule a reminder for yourself later, at a specific time, or on a recurring cadence.
878
- 23. **\`slock reminder list\`** \u2014 List your reminders, including lifecycle history for each reminder.
879
- 24. **\`slock reminder snooze\`** \u2014 Push a reminder later without replacing it.
880
- 25. **\`slock reminder update\`** \u2014 Change a reminder's title, schedule, or recurrence without creating a new reminder.
881
- 26. **\`slock reminder cancel\`** \u2014 Cancel one of your reminders by ID.
882
- 27. **\`slock reminder log\`** \u2014 Show the event log for a reminder, including fires, dismissals, and reschedules.
883
- 28. **\`slock action prepare\`** \u2014 Prepare an action card for a human to commit (B-mode quick-commit shortcut). Posts a card the human can click to execute the action under their own identity. Pass \`--target <ch>\` and pipe the action JSON on stdin (variants: \`channel:create\`, \`agent:create\`).
874
+ 20. **\`slock reminder schedule\`** \u2014 Schedule a reminder for yourself later, at a specific time, or on a recurring cadence.
875
+ 21. **\`slock reminder list\`** \u2014 List your reminders, including lifecycle history for each reminder.
876
+ 22. **\`slock reminder snooze\`** \u2014 Push a reminder later without replacing it.
877
+ 23. **\`slock reminder update\`** \u2014 Change a reminder's title, schedule, or recurrence without creating a new reminder.
878
+ 24. **\`slock reminder cancel\`** \u2014 Cancel one of your reminders by ID.
879
+ 25. **\`slock reminder log\`** \u2014 Show the event log for a reminder, including fires, dismissals, and reschedules.
880
+ 26. **\`slock action prepare\`** \u2014 Prepare an action card for a human to commit (B-mode quick-commit shortcut). Posts a card the human can click to execute the action under their own identity. Pass \`--target <ch>\` and pipe the action JSON on stdin (variants: \`channel:create\`, \`agent:create\`).
884
881
 
885
882
  The CLI prints human-readable canonical text on success (matching the format you see in received messages and history). On failure it prints JSON to stderr:
886
883
  - failure \u2192 stderr \`{"ok":false,"code":"...","message":"..."}\` with non-zero exit
@@ -981,11 +978,6 @@ Each channel has a **name** and optionally a **description** that define its pur
981
978
  - **Reply in context** \u2014 always respond in the channel/thread the message came from.
982
979
  - **Stay on topic** \u2014 when proactively sharing results or updates, post in the channel most relevant to the work. Don't scatter messages across unrelated channels.
983
980
  - If unsure where something belongs, call ${serverInfoCmd} to review channel descriptions.`;
984
- const thirdPartyIntegrationsSection = isCli ? `### Third-party integrations
985
-
986
- If a registered third-party service requires login, use Slock Agent Login through the CLI instead of asking the human to copy tokens or complete human OAuth for you. If a human asks you to sign into, open, use, or fetch identity from a third-party app, first run \`slock integration list\` and match the app to a registered service before browsing the app. Use \`slock integration login --service <service>\` to provision or reuse your agent login for that service. When the command returns \`Agent login ready\` or \`Already logged in\`, the agent-side login is ready. If the output includes an app URL, open that URL as the service-provided third-party app surface; it should look like the service's normal Login with Slock callback and not require you to understand Slock's internal grant/request protocol. Do not crawl third-party routes looking for a session before trying the registered-service login path. Do not open the human \`Login with Slock\` browser flow, use internal request IDs as OAuth callback codes, or call third-party exchange endpoints unless a human explicitly asks you to debug that server-to-server protocol. If the service or human asks for your Slock Agent identity card, use \`slock profile show\`. Third-party pages may show \`Login with Slock\`; for agent-facing access, prefer the registered service / Slock Agent Login path.` : `### Third-party integrations
987
-
988
- If a registered third-party service requires login, use Slock Agent Login through the available registered-service interface instead of asking the human to copy tokens or complete human OAuth for you. If a human asks you to sign into, open, use, or fetch identity from a third-party app, first inspect the registered-service interface and match the app to a registered service before browsing the app. Once the registered-service interface reports the agent login is ready, the agent-side login is ready. If that interface provides an app URL, use it as the service-provided third-party app surface; it should look like the service's normal Login with Slock callback and not require you to understand Slock's internal grant/request protocol. Do not crawl third-party routes looking for a session before trying the registered-service login path. Do not open the human \`Login with Slock\` browser flow or treat internal request IDs as OAuth callback codes unless a human explicitly asks you to debug that server-to-server protocol. If the service or human asks for your Slock Agent identity card, use your Slock profile view. Third-party pages may show \`Login with Slock\`; for agent-facing access, prefer the registered service / Slock Agent Login path.`;
989
981
  const readingHistorySection = isCli ? `### Reading history
990
982
 
991
983
  \`slock message read --channel "#channel-name"\` or \`slock message read --channel dm:@peer-name\` or \`slock message read --channel "#channel:shortid"\`
@@ -1157,8 +1149,6 @@ ${discoverySection}
1157
1149
 
1158
1150
  ${channelAwarenessSection}
1159
1151
 
1160
- ${thirdPartyIntegrationsSection}
1161
-
1162
1152
  ${readingHistorySection}
1163
1153
 
1164
1154
  ${historicalReferenceSection}
@@ -1190,17 +1180,6 @@ Keep the user informed. They cannot see your internal reasoning, so:
1190
1180
  - For multi-step work, send short progress updates (e.g. "Working on step 2/3\u2026").
1191
1181
  - When done, summarize the result.
1192
1182
  - Keep updates concise \u2014 one or two sentences. Don't flood the chat.
1193
- - For long answers where users need the conclusion first but details still matter, put the conclusion and next action outside any collapse, then use sanitized HTML details blocks for optional depth:
1194
-
1195
- \`\`\`html
1196
- <details>
1197
- <summary>Evidence, logs, or edge cases</summary>
1198
-
1199
- Detailed notes go here.
1200
- </details>
1201
- \`\`\`
1202
-
1203
- Do not hide the main recommendation, blocker, or required action inside \`<details>\`; only fold supporting evidence, logs, alternatives, or extended rationale.
1204
1183
 
1205
1184
  ### Conversation etiquette
1206
1185
 
@@ -1370,19 +1349,6 @@ function listLegacySlockStatePaths(slockHome = resolveSlockHome(), homeDir = os.
1370
1349
  return candidates.filter((candidate) => existsSync(candidate.path));
1371
1350
  }
1372
1351
 
1373
- // src/authEnv.ts
1374
- var DAEMON_API_KEY_ENV = "SLOCK_MACHINE_API_KEY";
1375
- var SLOCK_AGENT_TOKEN_ENV = "SLOCK_AGENT_TOKEN";
1376
- function scrubDaemonAuthEnv(env) {
1377
- delete env[DAEMON_API_KEY_ENV];
1378
- return env;
1379
- }
1380
- function scrubDaemonChildEnv(env) {
1381
- delete env[DAEMON_API_KEY_ENV];
1382
- delete env[SLOCK_AGENT_TOKEN_ENV];
1383
- return env;
1384
- }
1385
-
1386
1352
  // src/drivers/cliTransport.ts
1387
1353
  var shellSingleQuote = (value) => `'${value.replace(/'/g, `'\\''`)}'`;
1388
1354
  function runtimeContextEnv(config) {
@@ -1410,12 +1376,6 @@ function prepareCliTransport(ctx, extraEnv = {}, platform = process.platform) {
1410
1376
  mkdirSync(slockDir, { recursive: true });
1411
1377
  const tokenFile = path2.join(slockDir, "agent-token");
1412
1378
  writeFileSync(tokenFile, ctx.config.authToken || ctx.daemonApiKey, { mode: 384 });
1413
- const agentCredentialKey = ctx.config.agentCredentialKey;
1414
- let agentCredentialKeyFile = null;
1415
- if (typeof agentCredentialKey === "string" && agentCredentialKey.length > 0) {
1416
- agentCredentialKeyFile = path2.join(slockDir, "agent-credential-key");
1417
- writeFileSync(agentCredentialKeyFile, agentCredentialKey, { mode: 384 });
1418
- }
1419
1379
  const posixWrapper = path2.join(slockDir, "slock");
1420
1380
  const posixBody = `#!/usr/bin/env bash
1421
1381
  exec ${shellSingleQuote(process.execPath)} ${shellSingleQuote(ctx.slockCliPath)} "$@"
@@ -1440,15 +1400,12 @@ exec ${shellSingleQuote(process.execPath)} ${shellSingleQuote(ctx.slockCliPath)}
1440
1400
  ...ctx.launchId ? { SLOCK_AGENT_LAUNCH_ID: ctx.launchId } : {},
1441
1401
  SLOCK_SERVER_URL: ctx.config.serverUrl,
1442
1402
  SLOCK_AGENT_TOKEN_FILE: tokenFile,
1443
- ...agentCredentialKeyFile ? { SLOCK_AGENT_CREDENTIAL_KEY_FILE: agentCredentialKeyFile } : {},
1444
1403
  PATH: `${slockDir}${path2.delimiter}${process.env.PATH ?? ""}`
1445
1404
  };
1446
- scrubDaemonChildEnv(spawnEnv);
1447
- delete spawnEnv.SLOCK_AGENT_CREDENTIAL_KEY;
1405
+ delete spawnEnv.SLOCK_AGENT_TOKEN;
1448
1406
  return {
1449
1407
  slockDir,
1450
1408
  tokenFile,
1451
- agentCredentialKeyFile,
1452
1409
  wrapperPath,
1453
1410
  spawnEnv
1454
1411
  };
@@ -1482,7 +1439,7 @@ function resolveCommandOnWindows(command, env, execFileSyncFn) {
1482
1439
  }
1483
1440
  function resolveCommandOnPath(command, deps = {}) {
1484
1441
  const platform = deps.platform ?? process.platform;
1485
- const env = scrubDaemonChildEnv({ ...deps.env ?? process.env });
1442
+ const env = deps.env ?? process.env;
1486
1443
  const execFileSyncFn = deps.execFileSyncFn ?? execFileSync;
1487
1444
  if (platform === "win32") {
1488
1445
  return resolveCommandOnWindows(command, env, execFileSyncFn);
@@ -1507,7 +1464,7 @@ function firstExistingPath(candidates, deps = {}) {
1507
1464
  return null;
1508
1465
  }
1509
1466
  function readCommandVersion(command, args = [], deps = {}) {
1510
- const env = scrubDaemonChildEnv({ ...deps.env ?? process.env });
1467
+ const env = deps.env ?? process.env;
1511
1468
  const execFileSyncFn = deps.execFileSyncFn ?? execFileSync;
1512
1469
  try {
1513
1470
  const output = normalizeExecOutput(execFileSyncFn(command, [...args, "--version"], {
@@ -2784,7 +2741,7 @@ function detectCursorModels(runCommand = runCursorModelsCommand) {
2784
2741
  }
2785
2742
  function runCursorModelsCommand() {
2786
2743
  return spawnSync("cursor-agent", ["models"], {
2787
- env: scrubDaemonChildEnv({ ...process.env, FORCE_COLOR: "0", NO_COLOR: "1" }),
2744
+ env: { ...process.env, FORCE_COLOR: "0", NO_COLOR: "1" },
2788
2745
  encoding: "utf8",
2789
2746
  timeout: 5e3
2790
2747
  });
@@ -2831,7 +2788,7 @@ function resolveGeminiSpawn(commandArgs, deps = {}) {
2831
2788
  }
2832
2789
  const execFileSyncFn = deps.execFileSyncFn ?? execFileSync3;
2833
2790
  const existsSyncFn = deps.existsSyncFn ?? existsSync6;
2834
- const env = scrubDaemonChildEnv({ ...deps.env ?? process.env });
2791
+ const env = deps.env ?? process.env;
2835
2792
  const winPath = path8.win32;
2836
2793
  let geminiEntry = null;
2837
2794
  try {
@@ -3005,16 +2962,13 @@ var GeminiDriver = class {
3005
2962
  // src/drivers/kimi.ts
3006
2963
  import { randomUUID } from "crypto";
3007
2964
  import { spawn as spawn6 } from "child_process";
3008
- import { chmodSync, existsSync as existsSync7, readFileSync as readFileSync3, writeFileSync as writeFileSync6 } from "fs";
2965
+ import { existsSync as existsSync7, readFileSync as readFileSync3, writeFileSync as writeFileSync6 } from "fs";
3009
2966
  import os4 from "os";
3010
2967
  import path9 from "path";
3011
2968
  var KIMI_WIRE_PROTOCOL_VERSION = "1.3";
3012
2969
  var KIMI_SYSTEM_PROMPT_FILE = ".slock-kimi-system.md";
3013
2970
  var KIMI_AGENT_FILE = ".slock-kimi-agent.yaml";
3014
2971
  var KIMI_MCP_FILE = ".slock-kimi-mcp.json";
3015
- var KIMI_GENERATED_CONFIG_FILE = ".slock-kimi-config.toml";
3016
- var SLOCK_KIMI_CONFIG_CONTENT_ENV = "SLOCK_KIMI_CONFIG_CONTENT";
3017
- var SLOCK_KIMI_CONFIG_FILE_ENV = "SLOCK_KIMI_CONFIG_FILE";
3018
2972
  function parseToolArguments(raw) {
3019
2973
  if (typeof raw !== "string") return raw;
3020
2974
  try {
@@ -3023,73 +2977,6 @@ function parseToolArguments(raw) {
3023
2977
  return raw;
3024
2978
  }
3025
2979
  }
3026
- function readKimiConfigSource(home = os4.homedir(), env = process.env) {
3027
- const inlineConfig = env[SLOCK_KIMI_CONFIG_CONTENT_ENV];
3028
- if (inlineConfig && inlineConfig.trim()) {
3029
- return {
3030
- raw: inlineConfig,
3031
- explicitPath: null,
3032
- sourcePath: SLOCK_KIMI_CONFIG_CONTENT_ENV
3033
- };
3034
- }
3035
- const explicitPath = env[SLOCK_KIMI_CONFIG_FILE_ENV];
3036
- const configPath = explicitPath && explicitPath.trim() ? explicitPath : path9.join(home, ".kimi", "config.toml");
3037
- try {
3038
- return {
3039
- raw: readFileSync3(configPath, "utf8"),
3040
- explicitPath: explicitPath && explicitPath.trim() ? explicitPath : null,
3041
- sourcePath: configPath
3042
- };
3043
- } catch {
3044
- return {
3045
- raw: null,
3046
- explicitPath: explicitPath && explicitPath.trim() ? explicitPath : null,
3047
- sourcePath: configPath
3048
- };
3049
- }
3050
- }
3051
- function buildKimiSpawnEnv(env = process.env) {
3052
- const spawnEnv = { ...env, FORCE_COLOR: "0", NO_COLOR: "1" };
3053
- delete spawnEnv[SLOCK_KIMI_CONFIG_CONTENT_ENV];
3054
- delete spawnEnv[SLOCK_KIMI_CONFIG_FILE_ENV];
3055
- return scrubDaemonChildEnv(spawnEnv);
3056
- }
3057
- function buildKimiEffectiveEnv(ctx, overrideEnv) {
3058
- return {
3059
- ...process.env,
3060
- ...ctx.config.envVars || {},
3061
- ...overrideEnv || {}
3062
- };
3063
- }
3064
- function buildKimiLaunchOptions(ctx, opts = {}) {
3065
- const env = buildKimiEffectiveEnv(ctx, opts.env);
3066
- const source = readKimiConfigSource(opts.home ?? os4.homedir(), env);
3067
- const args = [];
3068
- let configFilePath = null;
3069
- let configContent = null;
3070
- if (source.explicitPath) {
3071
- configFilePath = source.explicitPath;
3072
- } else if (source.raw !== null && source.sourcePath === SLOCK_KIMI_CONFIG_CONTENT_ENV) {
3073
- configFilePath = path9.join(ctx.workingDirectory, KIMI_GENERATED_CONFIG_FILE);
3074
- configContent = source.raw;
3075
- if (opts.writeGeneratedConfig !== false) {
3076
- writeFileSync6(configFilePath, source.raw, { encoding: "utf8", mode: 384 });
3077
- chmodSync(configFilePath, 384);
3078
- }
3079
- }
3080
- if (configFilePath) {
3081
- args.push("--config-file", configFilePath);
3082
- }
3083
- if (ctx.config.model && ctx.config.model !== "default") {
3084
- args.push("--model", ctx.config.model);
3085
- }
3086
- return {
3087
- args,
3088
- env: buildKimiSpawnEnv(env),
3089
- configFilePath,
3090
- configContent
3091
- };
3092
- }
3093
2980
  function resolveKimiSpawn(commandArgs, deps = {}) {
3094
2981
  return {
3095
2982
  command: resolveCommandOnPath("kimi", deps) ?? "kimi",
@@ -3113,25 +3000,7 @@ var KimiDriver = class {
3113
3000
  };
3114
3001
  model = {
3115
3002
  detectedModelsVerifiedAs: "launchable",
3116
- toLaunchSpec: (modelId, ctx, opts) => {
3117
- if (!ctx) return { args: ["--model", modelId] };
3118
- const launchCtx = {
3119
- ...ctx,
3120
- config: {
3121
- ...ctx.config,
3122
- model: modelId
3123
- }
3124
- };
3125
- const launch = buildKimiLaunchOptions(launchCtx, {
3126
- home: opts?.home,
3127
- writeGeneratedConfig: false
3128
- });
3129
- return {
3130
- args: launch.args,
3131
- env: launch.env,
3132
- configFiles: launch.configFilePath ? [launch.configFilePath] : void 0
3133
- };
3134
- }
3003
+ toLaunchSpec: (modelId) => ({ args: ["--model", modelId] })
3135
3004
  };
3136
3005
  supportsStdinNotification = true;
3137
3006
  mcpToolPrefix = "";
@@ -3185,7 +3054,6 @@ var KimiDriver = class {
3185
3054
  }
3186
3055
  }
3187
3056
  }), "utf8");
3188
- const launch = buildKimiLaunchOptions(ctx);
3189
3057
  const args = [
3190
3058
  "--wire",
3191
3059
  "--yolo",
@@ -3194,15 +3062,14 @@ var KimiDriver = class {
3194
3062
  "--mcp-config-file",
3195
3063
  mcpConfigPath,
3196
3064
  "--session",
3197
- this.sessionId,
3198
- ...launch.args
3065
+ this.sessionId
3199
3066
  ];
3200
3067
  if (ctx.config.model && ctx.config.model !== "default") {
3201
3068
  args.push("--model", ctx.config.model);
3202
3069
  }
3203
3070
  const spawnEnv = prepareCliTransport(ctx, { NO_COLOR: "1" }).spawnEnv;
3204
- const spawnTarget = resolveKimiSpawn(args);
3205
- const proc = spawn6(spawnTarget.command, spawnTarget.args, {
3071
+ const launch = resolveKimiSpawn(args);
3072
+ const proc = spawn6(launch.command, launch.args, {
3206
3073
  cwd: ctx.workingDirectory,
3207
3074
  stdio: ["pipe", "pipe", "pipe"],
3208
3075
  env: spawnEnv,
@@ -3210,7 +3077,7 @@ var KimiDriver = class {
3210
3077
  // and has an 8191-character command-line limit. Kimi's official
3211
3078
  // installer/uv entrypoint is an executable, so launch it directly and
3212
3079
  // keep prompts on stdin / files instead of routing through cmd.exe.
3213
- shell: spawnTarget.shell
3080
+ shell: launch.shell
3214
3081
  });
3215
3082
  proc.stdin?.write(JSON.stringify({
3216
3083
  jsonrpc: "2.0",
@@ -3326,9 +3193,14 @@ var KimiDriver = class {
3326
3193
  return detectKimiModels();
3327
3194
  }
3328
3195
  };
3329
- function detectKimiModels(home = os4.homedir(), opts = {}) {
3330
- const raw = readKimiConfigSource(home, opts.env).raw;
3331
- if (raw === null) return null;
3196
+ function detectKimiModels(home = os4.homedir()) {
3197
+ const configPath = path9.join(home, ".kimi", "config.toml");
3198
+ let raw;
3199
+ try {
3200
+ raw = readFileSync3(configPath, "utf8");
3201
+ } catch {
3202
+ return null;
3203
+ }
3332
3204
  const models = [];
3333
3205
  const sectionRe = /^\s*\[models(?:\.([^\]]+)|"\.[^"]+"|\."[^"]+")\s*\]\s*$/gm;
3334
3206
  const lineRe = /^\s*\[models\.(.+?)\s*\]\s*$/gm;
@@ -3575,7 +3447,7 @@ function detectOpenCodeModels(home = os5.homedir(), runCommand = runOpenCodeMode
3575
3447
  }
3576
3448
  function runOpenCodeModelsCommand(home) {
3577
3449
  const result = spawnSync2("opencode", ["models"], {
3578
- env: scrubDaemonChildEnv({ ...process.env, HOME: home, FORCE_COLOR: "0", NO_COLOR: "1" }),
3450
+ env: { ...process.env, HOME: home, FORCE_COLOR: "0", NO_COLOR: "1" },
3579
3451
  encoding: "utf8",
3580
3452
  timeout: 5e3
3581
3453
  });
@@ -3731,297 +3603,6 @@ var OpenCodeDriver = class {
3731
3603
  }
3732
3604
  };
3733
3605
 
3734
- // src/drivers/pi.ts
3735
- import { spawn as spawn8 } from "child_process";
3736
- import { existsSync as existsSync8, mkdirSync as mkdirSync4, writeFileSync as writeFileSync7 } from "fs";
3737
- import path11 from "path";
3738
- import { fileURLToPath } from "url";
3739
- import { getAgentDir, VERSION as PI_SDK_VERSION } from "@earendil-works/pi-coding-agent";
3740
- var CHAT_MCP_TOOL_PREFIX2 = "chat_";
3741
- var NO_MESSAGE_PROMPT2 = "No new messages are pending. Stop now.";
3742
- var FIRST_MESSAGE_TASK_PREFIX2 = "First message task (system-triggered):";
3743
- var MIN_SUPPORTED_PI_VERSION = "0.74.0";
3744
- function parseSemver2(version) {
3745
- const match = version.match(/(\d+)\.(\d+)\.(\d+)/);
3746
- if (!match) return null;
3747
- return [Number(match[1]), Number(match[2]), Number(match[3])];
3748
- }
3749
- function isSupportedPiVersion(version) {
3750
- if (!version) return true;
3751
- const actual = parseSemver2(version);
3752
- const minimum = parseSemver2(MIN_SUPPORTED_PI_VERSION);
3753
- if (!actual || !minimum) return true;
3754
- for (let i = 0; i < 3; i += 1) {
3755
- if (actual[i] > minimum[i]) return true;
3756
- if (actual[i] < minimum[i]) return false;
3757
- }
3758
- return true;
3759
- }
3760
- function unsupportedPiVersionMessage(version) {
3761
- if (!version || isSupportedPiVersion(version)) return null;
3762
- return `Pi SDK ${version} is unsupported; requires @earendil-works/pi-coding-agent >= ${MIN_SUPPORTED_PI_VERSION}. Upgrade the daemon Pi dependency before starting this runtime.`;
3763
- }
3764
- function probePi(version = PI_SDK_VERSION) {
3765
- const unsupportedMessage = unsupportedPiVersionMessage(version);
3766
- if (unsupportedMessage) {
3767
- return {
3768
- available: false,
3769
- version: `${version} (requires @earendil-works/pi-coding-agent >= ${MIN_SUPPORTED_PI_VERSION})`
3770
- };
3771
- }
3772
- return { available: true, version };
3773
- }
3774
- function resolvePiSdkRunnerPath(moduleUrl = import.meta.url) {
3775
- const moduleDir = path11.dirname(fileURLToPath(moduleUrl));
3776
- const sourceSibling = path11.join(moduleDir, "piSdkRunner.ts");
3777
- if (existsSync8(sourceSibling)) return sourceSibling;
3778
- const bundledEntry = path11.join(moduleDir, "drivers", "piSdkRunner.js");
3779
- if (existsSync8(bundledEntry)) return bundledEntry;
3780
- return path11.join(moduleDir, "piSdkRunner.js");
3781
- }
3782
- function buildPiSdkNodeArgs(runnerPath = resolvePiSdkRunnerPath()) {
3783
- if (runnerPath.endsWith(".ts")) {
3784
- return [...process.execArgv, runnerPath];
3785
- }
3786
- return [runnerPath];
3787
- }
3788
- function buildPiLaunchOptions(ctx, opts = {}) {
3789
- const command = opts.command ?? process.execPath;
3790
- const piDir = path11.join(ctx.workingDirectory, ".slock", "pi");
3791
- const sessionDir = path11.join(piDir, "sessions");
3792
- mkdirSync4(sessionDir, { recursive: true });
3793
- const slock = prepareCliTransport(ctx, { NO_COLOR: "1" });
3794
- const runnerPath = opts.runnerPath ?? resolvePiSdkRunnerPath();
3795
- const agentDir = opts.agentDir ?? getAgentDir();
3796
- const runnerConfigPath = path11.join(
3797
- piDir,
3798
- `sdk-run-${(ctx.launchId || "launch").replace(/[^a-zA-Z0-9_.-]/g, "_")}.json`
3799
- );
3800
- const turnPrompt = ctx.prompt === ctx.standingPrompt ? NO_MESSAGE_PROMPT2 : ctx.prompt;
3801
- const runnerConfig = {
3802
- cwd: ctx.workingDirectory,
3803
- agentDir,
3804
- sessionDir,
3805
- sessionId: ctx.config.sessionId || null,
3806
- standingPrompt: ctx.standingPrompt,
3807
- prompt: turnPrompt,
3808
- model: ctx.config.model && ctx.config.model !== "default" ? ctx.config.model : null
3809
- };
3810
- writeFileSync7(runnerConfigPath, `${JSON.stringify(runnerConfig)}
3811
- `, { encoding: "utf8", mode: 384 });
3812
- const args = [
3813
- ...buildPiSdkNodeArgs(runnerPath),
3814
- "--config",
3815
- runnerConfigPath
3816
- ];
3817
- return {
3818
- command,
3819
- args,
3820
- env: slock.spawnEnv,
3821
- sessionDir,
3822
- agentDir,
3823
- runnerConfigPath,
3824
- sdkVersion: PI_SDK_VERSION
3825
- };
3826
- }
3827
- function isSystemFirstMessageTask2(message) {
3828
- return message.sender_id === "system" && message.channel_type === "channel" && message.channel_name === "all" && message.content.trimStart().startsWith(FIRST_MESSAGE_TASK_PREFIX2);
3829
- }
3830
- function buildPiSystemPrompt(config) {
3831
- return buildCliTransportSystemPrompt(config, {
3832
- toolPrefix: CHAT_MCP_TOOL_PREFIX2,
3833
- extraCriticalRules: [
3834
- "- Runtime Profile migration controls are not available in the Pi runtime yet. If asked to acknowledge a runtime migration, explain the blocker instead of inventing a command."
3835
- ],
3836
- postStartupNotes: [
3837
- "**Pi runtime note:** Slock launches you as a per-turn process. Complete the current wake using `slock` CLI commands, then stop; the daemon will restart you when new messages arrive."
3838
- ],
3839
- includeStdinNotificationSection: false,
3840
- messageNotificationStyle: "poll"
3841
- });
3842
- }
3843
- function contentText(content) {
3844
- if (!content) return "";
3845
- const chunks = [];
3846
- for (const item of content) {
3847
- if (item.type === "text" && typeof item.text === "string") {
3848
- chunks.push(item.text);
3849
- }
3850
- }
3851
- return chunks.join("");
3852
- }
3853
- function apiKeyErrorMessage(line) {
3854
- const trimmed = line.trim();
3855
- if (!trimmed) return null;
3856
- if (/no api key found/i.test(trimmed)) return trimmed;
3857
- if (/api key.+required/i.test(trimmed)) return trimmed;
3858
- if (/no models available/i.test(trimmed)) return trimmed;
3859
- return null;
3860
- }
3861
- var PiDriver = class {
3862
- id = "pi";
3863
- lifecycle = {
3864
- kind: "per_turn",
3865
- start: "defer_until_concrete_message",
3866
- exit: "terminate_on_turn_end",
3867
- inFlightWake: "coalesce_into_pending"
3868
- };
3869
- communication = {
3870
- chat: "slock_cli",
3871
- runtimeControl: "none"
3872
- };
3873
- session = {
3874
- recovery: "resume_or_fresh"
3875
- };
3876
- model = {
3877
- detectedModelsVerifiedAs: "launchable",
3878
- toLaunchSpec: (modelId, ctx) => {
3879
- if (!ctx) return modelId && modelId !== "default" ? { args: ["--model", modelId] } : { args: [] };
3880
- const launchCtx = {
3881
- ...ctx,
3882
- config: {
3883
- ...ctx.config,
3884
- model: modelId
3885
- }
3886
- };
3887
- const launch = buildPiLaunchOptions(launchCtx);
3888
- return {
3889
- args: launch.args,
3890
- env: launch.env,
3891
- configFiles: [launch.runnerConfigPath],
3892
- params: {
3893
- agentDir: launch.agentDir,
3894
- sessionDir: launch.sessionDir,
3895
- sdkVersion: launch.sdkVersion,
3896
- resources: "extensions/skills/prompt-templates/themes/context-files disabled by Slock policy"
3897
- }
3898
- };
3899
- }
3900
- };
3901
- supportsStdinNotification = false;
3902
- mcpToolPrefix = CHAT_MCP_TOOL_PREFIX2;
3903
- busyDeliveryMode = "none";
3904
- terminateProcessOnTurnEnd = true;
3905
- deferSpawnUntilMessage = true;
3906
- usesSlockCliForCommunication = true;
3907
- sessionId = null;
3908
- sessionAnnounced = false;
3909
- apiKeyErrorAnnounced = false;
3910
- turnEnded = false;
3911
- assistantTextByMessageId = /* @__PURE__ */ new Map();
3912
- shouldDeferWakeMessage(message) {
3913
- return isSystemFirstMessageTask2(message);
3914
- }
3915
- probe() {
3916
- return probePi();
3917
- }
3918
- async detectModels() {
3919
- return null;
3920
- }
3921
- spawn(ctx) {
3922
- this.sessionId = ctx.config.sessionId || null;
3923
- this.sessionAnnounced = false;
3924
- this.apiKeyErrorAnnounced = false;
3925
- this.turnEnded = false;
3926
- this.assistantTextByMessageId.clear();
3927
- const unsupportedMessage = unsupportedPiVersionMessage(PI_SDK_VERSION);
3928
- if (unsupportedMessage) throw new Error(unsupportedMessage);
3929
- const launch = buildPiLaunchOptions(ctx);
3930
- const proc = spawn8(launch.command, launch.args, {
3931
- cwd: ctx.workingDirectory,
3932
- stdio: ["pipe", "pipe", "pipe"],
3933
- env: launch.env,
3934
- shell: false
3935
- });
3936
- proc.stdin?.end();
3937
- return { process: proc };
3938
- }
3939
- parseLine(line) {
3940
- let event;
3941
- try {
3942
- event = JSON.parse(line);
3943
- } catch {
3944
- if (this.apiKeyErrorAnnounced) return [];
3945
- const message = apiKeyErrorMessage(line);
3946
- if (!message) return [];
3947
- this.apiKeyErrorAnnounced = true;
3948
- this.turnEnded = true;
3949
- return [
3950
- { kind: "error", message },
3951
- { kind: "turn_end", sessionId: this.sessionId || void 0 }
3952
- ];
3953
- }
3954
- const events = [];
3955
- if (event.type === "session" && event.id) {
3956
- this.sessionId = event.id;
3957
- }
3958
- if (!this.sessionAnnounced && this.sessionId) {
3959
- events.push({ kind: "session_init", sessionId: this.sessionId });
3960
- this.sessionAnnounced = true;
3961
- }
3962
- switch (event.type) {
3963
- case "agent_start":
3964
- case "turn_start":
3965
- events.push({ kind: "thinking", text: "" });
3966
- break;
3967
- case "message_update":
3968
- case "message_end":
3969
- if (event.message?.role === "assistant") {
3970
- const key = event.message.id || "current";
3971
- const currentText = contentText(event.message.content);
3972
- const previousText = this.assistantTextByMessageId.get(key) ?? "";
3973
- if (currentText.length > previousText.length && currentText.startsWith(previousText)) {
3974
- events.push({ kind: "text", text: currentText.slice(previousText.length) });
3975
- } else if (currentText && currentText !== previousText) {
3976
- events.push({ kind: "text", text: currentText });
3977
- }
3978
- this.assistantTextByMessageId.set(key, currentText);
3979
- if (event.message.stopReason === "error" || event.message.stopReason === "aborted") {
3980
- events.push({ kind: "error", message: event.message.errorMessage || `Request ${event.message.stopReason}` });
3981
- }
3982
- }
3983
- break;
3984
- case "tool_execution_start":
3985
- events.push({
3986
- kind: "tool_call",
3987
- name: event.toolName || "unknown_tool",
3988
- input: event.args
3989
- });
3990
- break;
3991
- case "tool_execution_end":
3992
- events.push({
3993
- kind: "tool_output",
3994
- name: event.toolName || "unknown_tool"
3995
- });
3996
- if (event.isError) {
3997
- events.push({ kind: "error", message: `Pi tool ${event.toolName || "unknown_tool"} failed` });
3998
- }
3999
- break;
4000
- case "compaction_start":
4001
- events.push({ kind: "compaction_started" });
4002
- break;
4003
- case "compaction_end":
4004
- events.push({ kind: "compaction_finished" });
4005
- if (event.errorMessage) events.push({ kind: "error", message: event.errorMessage });
4006
- break;
4007
- case "turn_end":
4008
- case "agent_end":
4009
- if (!this.turnEnded) {
4010
- events.push({ kind: "turn_end", sessionId: this.sessionId || void 0 });
4011
- this.turnEnded = true;
4012
- }
4013
- break;
4014
- }
4015
- return events;
4016
- }
4017
- encodeStdinMessage(_text, _sessionId, _opts) {
4018
- return null;
4019
- }
4020
- buildSystemPrompt(config, _agentId) {
4021
- return buildPiSystemPrompt(config);
4022
- }
4023
- };
4024
-
4025
3606
  // src/drivers/index.ts
4026
3607
  var driverFactories = {
4027
3608
  claude: () => new ClaudeDriver(),
@@ -4030,8 +3611,7 @@ var driverFactories = {
4030
3611
  cursor: () => new CursorDriver(),
4031
3612
  gemini: () => new GeminiDriver(),
4032
3613
  kimi: () => new KimiDriver(),
4033
- opencode: () => new OpenCodeDriver(),
4034
- pi: () => new PiDriver()
3614
+ opencode: () => new OpenCodeDriver()
4035
3615
  };
4036
3616
  function getDriver(runtimeId) {
4037
3617
  const createDriver = driverFactories[runtimeId];
@@ -4044,7 +3624,7 @@ function getDriver(runtimeId) {
4044
3624
 
4045
3625
  // src/workspaces.ts
4046
3626
  import { readdir, rm, stat } from "fs/promises";
4047
- import path12 from "path";
3627
+ import path11 from "path";
4048
3628
  function isValidWorkspaceDirectoryName(directoryName) {
4049
3629
  return !directoryName.includes("/") && !directoryName.includes("\\") && !directoryName.includes("..");
4050
3630
  }
@@ -4052,7 +3632,7 @@ function resolveWorkspaceDirectoryPath(dataDir, directoryName) {
4052
3632
  if (!isValidWorkspaceDirectoryName(directoryName)) {
4053
3633
  return null;
4054
3634
  }
4055
- return path12.join(dataDir, directoryName);
3635
+ return path11.join(dataDir, directoryName);
4056
3636
  }
4057
3637
  function emptyWorkspaceDirectorySummary(latestMtime = /* @__PURE__ */ new Date(0)) {
4058
3638
  return {
@@ -4101,7 +3681,7 @@ async function summarizeWorkspaceDirectory(dirPath) {
4101
3681
  return summary;
4102
3682
  }
4103
3683
  const childSummaries = await Promise.all(
4104
- entries.map((entry) => summarizeWorkspaceEntry(path12.join(dirPath, entry.name), entry))
3684
+ entries.map((entry) => summarizeWorkspaceEntry(path11.join(dirPath, entry.name), entry))
4105
3685
  );
4106
3686
  for (const childSummary of childSummaries) {
4107
3687
  summary = mergeWorkspaceDirectorySummaries(summary, childSummary);
@@ -4120,7 +3700,7 @@ async function scanWorkspaceDirectories(dataDir) {
4120
3700
  if (!entry.isDirectory()) {
4121
3701
  return null;
4122
3702
  }
4123
- const dirPath = path12.join(dataDir, entry.name);
3703
+ const dirPath = path11.join(dataDir, entry.name);
4124
3704
  try {
4125
3705
  const summary = await summarizeWorkspaceDirectory(dirPath);
4126
3706
  return {
@@ -4324,12 +3904,12 @@ function findSessionJsonl(root, predicate) {
4324
3904
  for (const entry of entries) {
4325
3905
  if (++visited > maxEntries) return null;
4326
3906
  if (!entry.isFile() || !predicate(entry.name)) continue;
4327
- return path13.join(dir, entry.name);
3907
+ return path12.join(dir, entry.name);
4328
3908
  }
4329
3909
  for (const entry of entries) {
4330
3910
  if (++visited > maxEntries) return null;
4331
3911
  if (!entry.isDirectory()) continue;
4332
- const found = visit(path13.join(dir, entry.name), depth - 1);
3912
+ const found = visit(path12.join(dir, entry.name), depth - 1);
4333
3913
  if (found) return found;
4334
3914
  }
4335
3915
  return null;
@@ -4342,10 +3922,10 @@ function safeSessionFilename(value) {
4342
3922
  }
4343
3923
  function writeRuntimeSessionHandoff(runtime, sessionId, fallbackDir) {
4344
3924
  try {
4345
- const dir = path13.join(fallbackDir, ".slock", "runtime-sessions");
4346
- mkdirSync5(dir, { recursive: true });
4347
- const filePath = path13.join(dir, `${runtime}-${safeSessionFilename(sessionId)}.jsonl`);
4348
- writeFileSync8(filePath, JSON.stringify({
3925
+ const dir = path12.join(fallbackDir, ".slock", "runtime-sessions");
3926
+ mkdirSync4(dir, { recursive: true });
3927
+ const filePath = path12.join(dir, `${runtime}-${safeSessionFilename(sessionId)}.jsonl`);
3928
+ writeFileSync7(filePath, JSON.stringify({
4349
3929
  type: "runtime_session_handoff",
4350
3930
  runtime,
4351
3931
  sessionId,
@@ -4364,7 +3944,7 @@ function writeRuntimeSessionHandoff(runtime, sessionId, fallbackDir) {
4364
3944
  }
4365
3945
  }
4366
3946
  function resolveRuntimeSessionRef(runtime, sessionId, homeDir = os6.homedir(), fallbackDir) {
4367
- const directPath = path13.isAbsolute(sessionId) ? sessionId : null;
3947
+ const directPath = path12.isAbsolute(sessionId) ? sessionId : null;
4368
3948
  if (directPath) {
4369
3949
  try {
4370
3950
  if (statSync2(directPath).isFile()) {
@@ -4373,7 +3953,7 @@ function resolveRuntimeSessionRef(runtime, sessionId, homeDir = os6.homedir(), f
4373
3953
  } catch {
4374
3954
  }
4375
3955
  }
4376
- const resolvedPath = runtime === "claude" ? findSessionJsonl(path13.join(homeDir, ".claude", "projects"), (filename) => filename === `${sessionId}.jsonl`) : runtime === "codex" ? findSessionJsonl(path13.join(homeDir, ".codex", "sessions"), (filename) => filename.endsWith(".jsonl") && filename.includes(sessionId)) : null;
3956
+ const resolvedPath = runtime === "claude" ? findSessionJsonl(path12.join(homeDir, ".claude", "projects"), (filename) => filename === `${sessionId}.jsonl`) : runtime === "codex" ? findSessionJsonl(path12.join(homeDir, ".codex", "sessions"), (filename) => filename.endsWith(".jsonl") && filename.includes(sessionId)) : null;
4377
3957
  if (!resolvedPath && fallbackDir) {
4378
3958
  const fallback = writeRuntimeSessionHandoff(runtime, sessionId, fallbackDir);
4379
3959
  if (fallback) return fallback;
@@ -5507,26 +5087,26 @@ var AgentProcessManager = class _AgentProcessManager {
5507
5087
  this.recordDaemonTrace("daemon.agent.spawn.started", this.startQueueTraceAttrs(agentId, config, wakeMessage, unreadSummary, resumePrompt, launchId));
5508
5088
  try {
5509
5089
  const driver = this.driverResolver(config.runtime || "claude");
5510
- const agentDataDir = path13.join(this.dataDir, agentId);
5090
+ const agentDataDir = path12.join(this.dataDir, agentId);
5511
5091
  await mkdir(agentDataDir, { recursive: true });
5512
5092
  const runtimeConfig = withLocalRuntimeContext(config, agentId, agentDataDir);
5513
- const memoryMdPath = path13.join(agentDataDir, "MEMORY.md");
5093
+ const memoryMdPath = path12.join(agentDataDir, "MEMORY.md");
5514
5094
  try {
5515
5095
  await access(memoryMdPath);
5516
5096
  } catch {
5517
5097
  const initialMemoryMd = buildInitialMemoryMd(runtimeConfig);
5518
5098
  await writeFile(memoryMdPath, initialMemoryMd);
5519
5099
  }
5520
- const notesDir = path13.join(agentDataDir, "notes");
5100
+ const notesDir = path12.join(agentDataDir, "notes");
5521
5101
  await mkdir(notesDir, { recursive: true });
5522
5102
  if (getOnboardingSeedMode(config) === FIRST_CINDY_SEED_MODE) {
5523
5103
  const seedFiles = buildOnboardingSeedFiles();
5524
5104
  for (const { relativePath, content } of seedFiles) {
5525
- const fullPath = path13.join(agentDataDir, relativePath);
5105
+ const fullPath = path12.join(agentDataDir, relativePath);
5526
5106
  try {
5527
5107
  await access(fullPath);
5528
5108
  } catch {
5529
- await mkdir(path13.dirname(fullPath), { recursive: true });
5109
+ await mkdir(path12.dirname(fullPath), { recursive: true });
5530
5110
  await writeFile(fullPath, content);
5531
5111
  }
5532
5112
  }
@@ -6208,7 +5788,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
6208
5788
  return true;
6209
5789
  }
6210
5790
  async resetWorkspace(agentId) {
6211
- const agentDataDir = path13.join(this.dataDir, agentId);
5791
+ const agentDataDir = path12.join(this.dataDir, agentId);
6212
5792
  try {
6213
5793
  await rm2(agentDataDir, { recursive: true, force: true });
6214
5794
  logger.info(`[Agent ${agentId}] Workspace reset complete (${agentDataDir})`);
@@ -6245,7 +5825,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
6245
5825
  return result;
6246
5826
  }
6247
5827
  buildRuntimeProfileReport(agentId, config, sessionId, launchId) {
6248
- const workspacePath = path13.join(this.dataDir, agentId);
5828
+ const workspacePath = path12.join(this.dataDir, agentId);
6249
5829
  return {
6250
5830
  agentId,
6251
5831
  launchId,
@@ -6493,7 +6073,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
6493
6073
  }
6494
6074
  // Workspace file browsing
6495
6075
  async getFileTree(agentId, dirPath) {
6496
- const agentDir = path13.join(this.dataDir, agentId);
6076
+ const agentDir = path12.join(this.dataDir, agentId);
6497
6077
  try {
6498
6078
  await stat2(agentDir);
6499
6079
  } catch {
@@ -6501,8 +6081,8 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
6501
6081
  }
6502
6082
  let targetDir = agentDir;
6503
6083
  if (dirPath) {
6504
- const resolved = path13.resolve(agentDir, dirPath);
6505
- if (!resolved.startsWith(agentDir + path13.sep) && resolved !== agentDir) {
6084
+ const resolved = path12.resolve(agentDir, dirPath);
6085
+ if (!resolved.startsWith(agentDir + path12.sep) && resolved !== agentDir) {
6506
6086
  return [];
6507
6087
  }
6508
6088
  targetDir = resolved;
@@ -6510,14 +6090,14 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
6510
6090
  return this.listDirectoryChildren(targetDir, agentDir);
6511
6091
  }
6512
6092
  async readFile(agentId, filePath) {
6513
- const agentDir = path13.join(this.dataDir, agentId);
6514
- const resolved = path13.resolve(agentDir, filePath);
6515
- if (!resolved.startsWith(agentDir + path13.sep) && resolved !== agentDir) {
6093
+ const agentDir = path12.join(this.dataDir, agentId);
6094
+ const resolved = path12.resolve(agentDir, filePath);
6095
+ if (!resolved.startsWith(agentDir + path12.sep) && resolved !== agentDir) {
6516
6096
  throw new Error("Access denied");
6517
6097
  }
6518
6098
  const info = await stat2(resolved);
6519
6099
  if (info.isDirectory()) throw new Error("Cannot read a directory");
6520
- const ext = path13.extname(resolved).toLowerCase();
6100
+ const ext = path12.extname(resolved).toLowerCase();
6521
6101
  if (WORKSPACE_TEXT_EXTENSIONS.has(ext) || ext === "") {
6522
6102
  if (info.size > WORKSPACE_TEXT_FILE_MAX_BYTES) throw new Error("File too large");
6523
6103
  const content = await readFile(resolved, "utf-8");
@@ -6552,13 +6132,13 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
6552
6132
  const agent = this.agents.get(agentId);
6553
6133
  const runtime = runtimeHint || agent?.config.runtime || "claude";
6554
6134
  const home = os6.homedir();
6555
- const workspaceDir = path13.join(this.dataDir, agentId);
6135
+ const workspaceDir = path12.join(this.dataDir, agentId);
6556
6136
  const paths = _AgentProcessManager.SKILL_PATHS[runtime] || _AgentProcessManager.SKILL_PATHS.claude;
6557
6137
  const globalResults = await Promise.all(
6558
- paths.global.map((p) => this.scanSkillsDir(path13.join(home, p)))
6138
+ paths.global.map((p) => this.scanSkillsDir(path12.join(home, p)))
6559
6139
  );
6560
6140
  const workspaceResults = await Promise.all(
6561
- paths.workspace.map((p) => this.scanSkillsDir(path13.join(workspaceDir, p)))
6141
+ paths.workspace.map((p) => this.scanSkillsDir(path12.join(workspaceDir, p)))
6562
6142
  );
6563
6143
  const dedup = (skills) => {
6564
6144
  const seen = /* @__PURE__ */ new Set();
@@ -6587,7 +6167,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
6587
6167
  const skills = [];
6588
6168
  for (const entry of entries) {
6589
6169
  if (entry.isDirectory() || entry.isSymbolicLink()) {
6590
- const skillMd = path13.join(dir, entry.name, "SKILL.md");
6170
+ const skillMd = path12.join(dir, entry.name, "SKILL.md");
6591
6171
  try {
6592
6172
  const content = await readFile(skillMd, "utf-8");
6593
6173
  const skill = this.parseSkillMd(entry.name, content);
@@ -6598,7 +6178,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
6598
6178
  } else if (entry.name.endsWith(".md")) {
6599
6179
  const cmdName = entry.name.replace(/\.md$/, "");
6600
6180
  try {
6601
- const content = await readFile(path13.join(dir, entry.name), "utf-8");
6181
+ const content = await readFile(path12.join(dir, entry.name), "utf-8");
6602
6182
  const skill = this.parseSkillMd(cmdName, content);
6603
6183
  skill.sourcePath = dir;
6604
6184
  skills.push(skill);
@@ -7548,8 +7128,8 @@ ${RESPONSE_TARGET_HINT}`);
7548
7128
  const nodes = [];
7549
7129
  for (const entry of entries) {
7550
7130
  if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
7551
- const fullPath = path13.join(dir, entry.name);
7552
- const relativePath = path13.relative(rootDir, fullPath);
7131
+ const fullPath = path12.join(dir, entry.name);
7132
+ const relativePath = path12.relative(rootDir, fullPath);
7553
7133
  let info;
7554
7134
  try {
7555
7135
  info = await stat2(fullPath);
@@ -7852,9 +7432,9 @@ var ReminderCache = class {
7852
7432
 
7853
7433
  // src/machineLock.ts
7854
7434
  import { createHash as createHash3, randomUUID as randomUUID2 } from "crypto";
7855
- import { mkdirSync as mkdirSync6, readFileSync as readFileSync5, rmSync as rmSync2, statSync as statSync3, writeFileSync as writeFileSync9 } from "fs";
7435
+ import { mkdirSync as mkdirSync5, readFileSync as readFileSync5, rmSync as rmSync2, statSync as statSync3, writeFileSync as writeFileSync8 } from "fs";
7856
7436
  import os7 from "os";
7857
- import path14 from "path";
7437
+ import path13 from "path";
7858
7438
  var INCOMPLETE_LOCK_STALE_MS = 3e4;
7859
7439
  var DaemonMachineLockConflictError = class extends Error {
7860
7440
  code = "DAEMON_MACHINE_LOCK_HELD";
@@ -7876,7 +7456,7 @@ function resolveDefaultMachineStateRoot() {
7876
7456
  return resolveSlockHomePath("machines");
7877
7457
  }
7878
7458
  function ownerPath(lockDir) {
7879
- return path14.join(lockDir, "owner.json");
7459
+ return path13.join(lockDir, "owner.json");
7880
7460
  }
7881
7461
  function readOwner(lockDir) {
7882
7462
  try {
@@ -7906,13 +7486,13 @@ function acquireDaemonMachineLock(options) {
7906
7486
  const rootDir = options.rootDir ?? resolveDefaultMachineStateRoot();
7907
7487
  const fingerprint = apiKeyFingerprint(options.apiKey);
7908
7488
  const lockId = getDaemonMachineLockId(options.apiKey);
7909
- const machineDir = path14.join(rootDir, lockId);
7910
- const lockDir = path14.join(machineDir, "daemon.lock");
7489
+ const machineDir = path13.join(rootDir, lockId);
7490
+ const lockDir = path13.join(machineDir, "daemon.lock");
7911
7491
  const token = randomUUID2();
7912
- mkdirSync6(machineDir, { recursive: true });
7492
+ mkdirSync5(machineDir, { recursive: true });
7913
7493
  for (let attempt = 0; attempt < 2; attempt += 1) {
7914
7494
  try {
7915
- mkdirSync6(lockDir);
7495
+ mkdirSync5(lockDir);
7916
7496
  const owner = {
7917
7497
  pid: process.pid,
7918
7498
  token,
@@ -7922,7 +7502,7 @@ function acquireDaemonMachineLock(options) {
7922
7502
  apiKeyFingerprint: fingerprint.slice(0, 16)
7923
7503
  };
7924
7504
  try {
7925
- writeFileSync9(ownerPath(lockDir), `${JSON.stringify(owner, null, 2)}
7505
+ writeFileSync8(ownerPath(lockDir), `${JSON.stringify(owner, null, 2)}
7926
7506
  `, { mode: 384 });
7927
7507
  } catch (err) {
7928
7508
  rmSync2(lockDir, { recursive: true, force: true });
@@ -7959,8 +7539,8 @@ function acquireDaemonMachineLock(options) {
7959
7539
  }
7960
7540
 
7961
7541
  // src/localTraceSink.ts
7962
- import { appendFileSync, mkdirSync as mkdirSync7, readdirSync as readdirSync3, rmSync as rmSync3, statSync as statSync4, writeFileSync as writeFileSync10 } from "fs";
7963
- import path15 from "path";
7542
+ import { appendFileSync, mkdirSync as mkdirSync6, readdirSync as readdirSync3, rmSync as rmSync3, statSync as statSync4, writeFileSync as writeFileSync9 } from "fs";
7543
+ import path14 from "path";
7964
7544
  var DEFAULT_MAX_FILE_BYTES = 5 * 1024 * 1024;
7965
7545
  var DEFAULT_MAX_FILE_AGE_MS = 5 * 60 * 1e3;
7966
7546
  var DEFAULT_MAX_FILES = 8;
@@ -7996,7 +7576,7 @@ var LocalRotatingTraceSink = class {
7996
7576
  currentSize = 0;
7997
7577
  sequence = 0;
7998
7578
  constructor(options) {
7999
- this.traceDir = path15.join(options.machineDir, "traces");
7579
+ this.traceDir = path14.join(options.machineDir, "traces");
8000
7580
  this.maxFileBytes = Math.max(1024, Math.floor(options.maxFileBytes ?? DEFAULT_MAX_FILE_BYTES));
8001
7581
  const baseAgeMs = Math.max(1e3, Math.floor(options.maxFileAgeMs ?? DEFAULT_MAX_FILE_AGE_MS));
8002
7582
  const ageJitterMs = Math.max(0, Math.floor(options.maxFileAgeJitterMs ?? 0));
@@ -8022,15 +7602,15 @@ var LocalRotatingTraceSink = class {
8022
7602
  return this.currentFile;
8023
7603
  }
8024
7604
  ensureFile(nextBytes) {
8025
- mkdirSync7(this.traceDir, { recursive: true, mode: 448 });
7605
+ mkdirSync6(this.traceDir, { recursive: true, mode: 448 });
8026
7606
  const nowMs = this.nowMsProvider();
8027
7607
  const shouldRotateForAge = this.currentFileOpenedAtMs !== null && nowMs - this.currentFileOpenedAtMs >= this.maxFileAgeMs;
8028
7608
  if (!this.currentFile || this.currentSize + nextBytes > this.maxFileBytes || shouldRotateForAge) {
8029
- this.currentFile = path15.join(
7609
+ this.currentFile = path14.join(
8030
7610
  this.traceDir,
8031
7611
  `daemon-trace-${safeTimestamp(nowMs)}-${process.pid}-${String(this.sequence++).padStart(4, "0")}.jsonl`
8032
7612
  );
8033
- writeFileSync10(this.currentFile, "", { flag: "a", mode: 384 });
7613
+ writeFileSync9(this.currentFile, "", { flag: "a", mode: 384 });
8034
7614
  this.currentSize = statSync4(this.currentFile).size;
8035
7615
  this.currentFileOpenedAtMs = nowMs;
8036
7616
  this.pruneOldFiles();
@@ -8041,7 +7621,7 @@ var LocalRotatingTraceSink = class {
8041
7621
  const excess = files.length - this.maxFiles;
8042
7622
  if (excess <= 0) return;
8043
7623
  for (const file of files.slice(0, excess)) {
8044
- rmSync3(path15.join(this.traceDir, file), { force: true });
7624
+ rmSync3(path14.join(this.traceDir, file), { force: true });
8045
7625
  }
8046
7626
  }
8047
7627
  };
@@ -8128,11 +7708,11 @@ function isDiagnosticErrorAttr(key) {
8128
7708
  import { createHash as createHash5, randomUUID as randomUUID3 } from "crypto";
8129
7709
  import { gzipSync } from "zlib";
8130
7710
  import { mkdir as mkdir2, readFile as readFile2, readdir as readdir3, stat as stat3, writeFile as writeFile2 } from "fs/promises";
8131
- import path16 from "path";
7711
+ import path15 from "path";
8132
7712
 
8133
7713
  // src/directUploadCapability.ts
8134
- function joinUrl(base, path18) {
8135
- return `${base.replace(/\/+$/, "")}${path18}`;
7714
+ function joinUrl(base, path17) {
7715
+ return `${base.replace(/\/+$/, "")}${path17}`;
8136
7716
  }
8137
7717
  function jsonHeaders(apiKey) {
8138
7718
  return {
@@ -8351,7 +7931,7 @@ var DaemonTraceBundleUploader = class {
8351
7931
  }, nextMs);
8352
7932
  }
8353
7933
  async findUploadCandidates() {
8354
- const traceDir = path16.join(this.options.machineDir, "traces");
7934
+ const traceDir = path15.join(this.options.machineDir, "traces");
8355
7935
  let names;
8356
7936
  try {
8357
7937
  names = await readdir3(traceDir);
@@ -8363,8 +7943,8 @@ var DaemonTraceBundleUploader = class {
8363
7943
  const currentFile = this.options.currentFileProvider?.();
8364
7944
  const candidates = [];
8365
7945
  for (const name of names.filter((entry) => entry.startsWith("daemon-trace-") && entry.endsWith(".jsonl")).sort()) {
8366
- const file = path16.join(traceDir, name);
8367
- if (currentFile && path16.resolve(file) === path16.resolve(currentFile)) continue;
7946
+ const file = path15.join(traceDir, name);
7947
+ if (currentFile && path15.resolve(file) === path15.resolve(currentFile)) continue;
8368
7948
  if (await this.isUploaded(file)) continue;
8369
7949
  try {
8370
7950
  const info = await stat3(file);
@@ -8438,8 +8018,8 @@ var DaemonTraceBundleUploader = class {
8438
8018
  }
8439
8019
  }
8440
8020
  uploadStatePath(file) {
8441
- const stateDir = path16.join(this.options.machineDir, "trace-uploads");
8442
- return path16.join(stateDir, `${path16.basename(file)}.uploaded.json`);
8021
+ const stateDir = path15.join(this.options.machineDir, "trace-uploads");
8022
+ return path15.join(stateDir, `${path15.basename(file)}.uploaded.json`);
8443
8023
  }
8444
8024
  async isUploaded(file) {
8445
8025
  try {
@@ -8451,9 +8031,9 @@ var DaemonTraceBundleUploader = class {
8451
8031
  }
8452
8032
  async markUploaded(file, metadata) {
8453
8033
  const stateFile = this.uploadStatePath(file);
8454
- await mkdir2(path16.dirname(stateFile), { recursive: true, mode: 448 });
8034
+ await mkdir2(path15.dirname(stateFile), { recursive: true, mode: 448 });
8455
8035
  await writeFile2(stateFile, `${JSON.stringify({
8456
- file: path16.basename(file),
8036
+ file: path15.basename(file),
8457
8037
  uploadedAt: (/* @__PURE__ */ new Date()).toISOString(),
8458
8038
  ...metadata
8459
8039
  }, null, 2)}
@@ -8472,10 +8052,10 @@ function readPositiveIntegerEnv2(name, fallback) {
8472
8052
 
8473
8053
  // src/core.ts
8474
8054
  var DEFAULT_TRACE_UPLOAD_URL = "https://slock-trace-upload.botiverse.dev";
8475
- var DAEMON_CLI_USAGE = `Usage: slock-daemon --server-url <url> (--api-key <key> or ${DAEMON_API_KEY_ENV}=<key>)`;
8476
- function parseDaemonCliArgs(args, env = {}) {
8055
+ var DAEMON_CLI_USAGE = "Usage: slock-daemon --server-url <url> --api-key <key>";
8056
+ function parseDaemonCliArgs(args) {
8477
8057
  let serverUrl = "";
8478
- let apiKey = env[DAEMON_API_KEY_ENV] ?? "";
8058
+ let apiKey = "";
8479
8059
  for (let i = 0; i < args.length; i++) {
8480
8060
  if (args[i] === "--server-url" && args[i + 1]) serverUrl = args[++i];
8481
8061
  if (args[i] === "--api-key" && args[i + 1]) apiKey = args[++i];
@@ -8492,23 +8072,23 @@ function readDaemonVersion(moduleUrl = import.meta.url) {
8492
8072
  }
8493
8073
  }
8494
8074
  function resolveChatBridgePath(moduleUrl = import.meta.url) {
8495
- const dirname = path17.dirname(fileURLToPath2(moduleUrl));
8496
- const jsPath = path17.resolve(dirname, "chat-bridge.js");
8075
+ const dirname = path16.dirname(fileURLToPath(moduleUrl));
8076
+ const jsPath = path16.resolve(dirname, "chat-bridge.js");
8497
8077
  try {
8498
8078
  accessSync(jsPath);
8499
8079
  return jsPath;
8500
8080
  } catch {
8501
- return path17.resolve(dirname, "chat-bridge.ts");
8081
+ return path16.resolve(dirname, "chat-bridge.ts");
8502
8082
  }
8503
8083
  }
8504
8084
  function resolveSlockCliPath(moduleUrl = import.meta.url) {
8505
- const thisDir = path17.dirname(fileURLToPath2(moduleUrl));
8506
- const bundledDistPath = path17.resolve(thisDir, "cli", "index.js");
8085
+ const thisDir = path16.dirname(fileURLToPath(moduleUrl));
8086
+ const bundledDistPath = path16.resolve(thisDir, "cli", "index.js");
8507
8087
  try {
8508
8088
  accessSync(bundledDistPath);
8509
8089
  return bundledDistPath;
8510
8090
  } catch {
8511
- const workspaceDistPath = path17.resolve(thisDir, "..", "..", "cli", "dist", "index.js");
8091
+ const workspaceDistPath = path16.resolve(thisDir, "..", "..", "cli", "dist", "index.js");
8512
8092
  accessSync(workspaceDistPath);
8513
8093
  return workspaceDistPath;
8514
8094
  }
@@ -8687,7 +8267,7 @@ var DaemonCore = class {
8687
8267
  }
8688
8268
  resolveMachineStateRoot() {
8689
8269
  if (this.options.machineStateDir) return this.options.machineStateDir;
8690
- if (this.options.dataDir) return path17.join(path17.dirname(this.options.dataDir), "machines");
8270
+ if (this.options.dataDir) return path16.join(path16.dirname(this.options.dataDir), "machines");
8691
8271
  return resolveDefaultMachineStateRoot();
8692
8272
  }
8693
8273
  shouldEnableLocalTrace() {
@@ -9070,8 +8650,6 @@ var DaemonCore = class {
9070
8650
  };
9071
8651
 
9072
8652
  export {
9073
- DAEMON_API_KEY_ENV,
9074
- scrubDaemonAuthEnv,
9075
8653
  resolveWorkspaceDirectoryPath,
9076
8654
  scanWorkspaceDirectories,
9077
8655
  deleteWorkspaceDirectory,