@slock-ai/daemon 0.52.2-play.20260522165849 → 0.53.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 as createRequire2 } 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
@@ -988,7 +987,7 @@ Each channel has a **name** and optionally a **description** that define its pur
988
987
  - If unsure where something belongs, call ${serverInfoCmd} to review channel descriptions.`;
989
988
  const thirdPartyIntegrationsSection = isCli ? `### Third-party integrations
990
989
 
991
- 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
990
+ 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. If the CLI reports that the \`integration\` command is unknown, the local daemon/CLI is too old for Slock Agent Login; report that the machine must be upgraded/restarted instead of calling internal HTTP endpoints yourself. 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, call internal Slock integration endpoints directly, 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
992
991
 
993
992
  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.`;
994
993
  const readingHistorySection = isCli ? `### Reading history
@@ -1195,17 +1194,6 @@ Keep the user informed. They cannot see your internal reasoning, so:
1195
1194
  - For multi-step work, send short progress updates (e.g. "Working on step 2/3\u2026").
1196
1195
  - When done, summarize the result.
1197
1196
  - Keep updates concise \u2014 one or two sentences. Don't flood the chat.
1198
- - 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:
1199
-
1200
- \`\`\`html
1201
- <details>
1202
- <summary>Evidence, logs, or edge cases</summary>
1203
-
1204
- Detailed notes go here.
1205
- </details>
1206
- \`\`\`
1207
-
1208
- Do not hide the main recommendation, blocker, or required action inside \`<details>\`; only fold supporting evidence, logs, alternatives, or extended rationale.
1209
1197
 
1210
1198
  ### Conversation etiquette
1211
1199
 
@@ -1374,19 +1362,6 @@ function listLegacySlockStatePaths(slockHome = resolveSlockHome(), homeDir = os.
1374
1362
  return candidates.filter((candidate) => existsSync(candidate.path));
1375
1363
  }
1376
1364
 
1377
- // src/authEnv.ts
1378
- var DAEMON_API_KEY_ENV = "SLOCK_MACHINE_API_KEY";
1379
- var SLOCK_AGENT_TOKEN_ENV = "SLOCK_AGENT_TOKEN";
1380
- function scrubDaemonAuthEnv(env) {
1381
- delete env[DAEMON_API_KEY_ENV];
1382
- return env;
1383
- }
1384
- function scrubDaemonChildEnv(env) {
1385
- delete env[DAEMON_API_KEY_ENV];
1386
- delete env[SLOCK_AGENT_TOKEN_ENV];
1387
- return env;
1388
- }
1389
-
1390
1365
  // src/agentCredentialProxy.ts
1391
1366
  import { randomBytes } from "crypto";
1392
1367
  import http from "http";
@@ -2093,7 +2068,7 @@ exec ${shellSingleQuote(process.execPath)} ${shellSingleQuote(opencliBinPath)} "
2093
2068
  ...agentCredentialProxy ? {} : { SLOCK_AGENT_TOKEN_FILE: tokenFile },
2094
2069
  PATH: `${slockDir}${path2.delimiter}${process.env.PATH ?? ""}`
2095
2070
  };
2096
- scrubDaemonChildEnv(spawnEnv);
2071
+ delete spawnEnv.SLOCK_AGENT_TOKEN;
2097
2072
  delete spawnEnv.SLOCK_AGENT_CREDENTIAL_KEY;
2098
2073
  delete spawnEnv.SLOCK_AGENT_CREDENTIAL_KEY_FILE;
2099
2074
  delete spawnEnv.SLOCK_AGENT_PROXY_URL;
@@ -2140,7 +2115,7 @@ function resolveCommandOnWindows(command, env, execFileSyncFn) {
2140
2115
  }
2141
2116
  function resolveCommandOnPath(command, deps = {}) {
2142
2117
  const platform = deps.platform ?? process.platform;
2143
- const env = scrubDaemonChildEnv({ ...deps.env ?? process.env });
2118
+ const env = deps.env ?? process.env;
2144
2119
  const execFileSyncFn = deps.execFileSyncFn ?? execFileSync;
2145
2120
  if (platform === "win32") {
2146
2121
  return resolveCommandOnWindows(command, env, execFileSyncFn);
@@ -2165,7 +2140,7 @@ function firstExistingPath(candidates, deps = {}) {
2165
2140
  return null;
2166
2141
  }
2167
2142
  function readCommandVersion(command, args = [], deps = {}) {
2168
- const env = scrubDaemonChildEnv({ ...deps.env ?? process.env });
2143
+ const env = deps.env ?? process.env;
2169
2144
  const execFileSyncFn = deps.execFileSyncFn ?? execFileSync;
2170
2145
  try {
2171
2146
  const output = normalizeExecOutput(execFileSyncFn(command, [...args, "--version"], {
@@ -3461,7 +3436,7 @@ function detectCursorModels(runCommand = runCursorModelsCommand) {
3461
3436
  }
3462
3437
  function runCursorModelsCommand() {
3463
3438
  return spawnSync("cursor-agent", ["models"], {
3464
- env: scrubDaemonChildEnv({ ...process.env, FORCE_COLOR: "0", NO_COLOR: "1" }),
3439
+ env: { ...process.env, FORCE_COLOR: "0", NO_COLOR: "1" },
3465
3440
  encoding: "utf8",
3466
3441
  timeout: 5e3
3467
3442
  });
@@ -3508,7 +3483,7 @@ function resolveGeminiSpawn(commandArgs, deps = {}) {
3508
3483
  }
3509
3484
  const execFileSyncFn = deps.execFileSyncFn ?? execFileSync3;
3510
3485
  const existsSyncFn = deps.existsSyncFn ?? existsSync6;
3511
- const env = scrubDaemonChildEnv({ ...deps.env ?? process.env });
3486
+ const env = deps.env ?? process.env;
3512
3487
  const winPath = path8.win32;
3513
3488
  let geminiEntry = null;
3514
3489
  try {
@@ -3682,16 +3657,13 @@ var GeminiDriver = class {
3682
3657
  // src/drivers/kimi.ts
3683
3658
  import { randomUUID } from "crypto";
3684
3659
  import { spawn as spawn6 } from "child_process";
3685
- import { chmodSync, existsSync as existsSync7, readFileSync as readFileSync4, writeFileSync as writeFileSync6 } from "fs";
3660
+ import { existsSync as existsSync7, readFileSync as readFileSync4, writeFileSync as writeFileSync6 } from "fs";
3686
3661
  import os4 from "os";
3687
3662
  import path9 from "path";
3688
3663
  var KIMI_WIRE_PROTOCOL_VERSION = "1.3";
3689
3664
  var KIMI_SYSTEM_PROMPT_FILE = ".slock-kimi-system.md";
3690
3665
  var KIMI_AGENT_FILE = ".slock-kimi-agent.yaml";
3691
3666
  var KIMI_MCP_FILE = ".slock-kimi-mcp.json";
3692
- var KIMI_GENERATED_CONFIG_FILE = ".slock-kimi-config.toml";
3693
- var SLOCK_KIMI_CONFIG_CONTENT_ENV = "SLOCK_KIMI_CONFIG_CONTENT";
3694
- var SLOCK_KIMI_CONFIG_FILE_ENV = "SLOCK_KIMI_CONFIG_FILE";
3695
3667
  function parseToolArguments(raw) {
3696
3668
  if (typeof raw !== "string") return raw;
3697
3669
  try {
@@ -3700,73 +3672,6 @@ function parseToolArguments(raw) {
3700
3672
  return raw;
3701
3673
  }
3702
3674
  }
3703
- function readKimiConfigSource(home = os4.homedir(), env = process.env) {
3704
- const inlineConfig = env[SLOCK_KIMI_CONFIG_CONTENT_ENV];
3705
- if (inlineConfig && inlineConfig.trim()) {
3706
- return {
3707
- raw: inlineConfig,
3708
- explicitPath: null,
3709
- sourcePath: SLOCK_KIMI_CONFIG_CONTENT_ENV
3710
- };
3711
- }
3712
- const explicitPath = env[SLOCK_KIMI_CONFIG_FILE_ENV];
3713
- const configPath = explicitPath && explicitPath.trim() ? explicitPath : path9.join(home, ".kimi", "config.toml");
3714
- try {
3715
- return {
3716
- raw: readFileSync4(configPath, "utf8"),
3717
- explicitPath: explicitPath && explicitPath.trim() ? explicitPath : null,
3718
- sourcePath: configPath
3719
- };
3720
- } catch {
3721
- return {
3722
- raw: null,
3723
- explicitPath: explicitPath && explicitPath.trim() ? explicitPath : null,
3724
- sourcePath: configPath
3725
- };
3726
- }
3727
- }
3728
- function buildKimiSpawnEnv(env = process.env) {
3729
- const spawnEnv = { ...env, FORCE_COLOR: "0", NO_COLOR: "1" };
3730
- delete spawnEnv[SLOCK_KIMI_CONFIG_CONTENT_ENV];
3731
- delete spawnEnv[SLOCK_KIMI_CONFIG_FILE_ENV];
3732
- return scrubDaemonChildEnv(spawnEnv);
3733
- }
3734
- function buildKimiEffectiveEnv(ctx, overrideEnv) {
3735
- return {
3736
- ...process.env,
3737
- ...ctx.config.envVars || {},
3738
- ...overrideEnv || {}
3739
- };
3740
- }
3741
- function buildKimiLaunchOptions(ctx, opts = {}) {
3742
- const env = buildKimiEffectiveEnv(ctx, opts.env);
3743
- const source = readKimiConfigSource(opts.home ?? os4.homedir(), env);
3744
- const args = [];
3745
- let configFilePath = null;
3746
- let configContent = null;
3747
- if (source.explicitPath) {
3748
- configFilePath = source.explicitPath;
3749
- } else if (source.raw !== null && source.sourcePath === SLOCK_KIMI_CONFIG_CONTENT_ENV) {
3750
- configFilePath = path9.join(ctx.workingDirectory, KIMI_GENERATED_CONFIG_FILE);
3751
- configContent = source.raw;
3752
- if (opts.writeGeneratedConfig !== false) {
3753
- writeFileSync6(configFilePath, source.raw, { encoding: "utf8", mode: 384 });
3754
- chmodSync(configFilePath, 384);
3755
- }
3756
- }
3757
- if (configFilePath) {
3758
- args.push("--config-file", configFilePath);
3759
- }
3760
- if (ctx.config.model && ctx.config.model !== "default") {
3761
- args.push("--model", ctx.config.model);
3762
- }
3763
- return {
3764
- args,
3765
- env: buildKimiSpawnEnv(env),
3766
- configFilePath,
3767
- configContent
3768
- };
3769
- }
3770
3675
  function resolveKimiSpawn(commandArgs, deps = {}) {
3771
3676
  return {
3772
3677
  command: resolveCommandOnPath("kimi", deps) ?? "kimi",
@@ -3790,25 +3695,7 @@ var KimiDriver = class {
3790
3695
  };
3791
3696
  model = {
3792
3697
  detectedModelsVerifiedAs: "launchable",
3793
- toLaunchSpec: (modelId, ctx, opts) => {
3794
- if (!ctx) return { args: ["--model", modelId] };
3795
- const launchCtx = {
3796
- ...ctx,
3797
- config: {
3798
- ...ctx.config,
3799
- model: modelId
3800
- }
3801
- };
3802
- const launch = buildKimiLaunchOptions(launchCtx, {
3803
- home: opts?.home,
3804
- writeGeneratedConfig: false
3805
- });
3806
- return {
3807
- args: launch.args,
3808
- env: launch.env,
3809
- configFiles: launch.configFilePath ? [launch.configFilePath] : void 0
3810
- };
3811
- }
3698
+ toLaunchSpec: (modelId) => ({ args: ["--model", modelId] })
3812
3699
  };
3813
3700
  supportsStdinNotification = true;
3814
3701
  mcpToolPrefix = "";
@@ -3862,7 +3749,6 @@ var KimiDriver = class {
3862
3749
  }
3863
3750
  }
3864
3751
  }), "utf8");
3865
- const launch = buildKimiLaunchOptions(ctx);
3866
3752
  const args = [
3867
3753
  "--wire",
3868
3754
  "--yolo",
@@ -3871,15 +3757,14 @@ var KimiDriver = class {
3871
3757
  "--mcp-config-file",
3872
3758
  mcpConfigPath,
3873
3759
  "--session",
3874
- this.sessionId,
3875
- ...launch.args
3760
+ this.sessionId
3876
3761
  ];
3877
3762
  if (ctx.config.model && ctx.config.model !== "default") {
3878
3763
  args.push("--model", ctx.config.model);
3879
3764
  }
3880
3765
  const spawnEnv = prepareCliTransport(ctx, { NO_COLOR: "1" }).spawnEnv;
3881
- const spawnTarget = resolveKimiSpawn(args);
3882
- const proc = spawn6(spawnTarget.command, spawnTarget.args, {
3766
+ const launch = resolveKimiSpawn(args);
3767
+ const proc = spawn6(launch.command, launch.args, {
3883
3768
  cwd: ctx.workingDirectory,
3884
3769
  stdio: ["pipe", "pipe", "pipe"],
3885
3770
  env: spawnEnv,
@@ -3887,7 +3772,7 @@ var KimiDriver = class {
3887
3772
  // and has an 8191-character command-line limit. Kimi's official
3888
3773
  // installer/uv entrypoint is an executable, so launch it directly and
3889
3774
  // keep prompts on stdin / files instead of routing through cmd.exe.
3890
- shell: spawnTarget.shell
3775
+ shell: launch.shell
3891
3776
  });
3892
3777
  proc.stdin?.write(JSON.stringify({
3893
3778
  jsonrpc: "2.0",
@@ -4003,9 +3888,14 @@ var KimiDriver = class {
4003
3888
  return detectKimiModels();
4004
3889
  }
4005
3890
  };
4006
- function detectKimiModels(home = os4.homedir(), opts = {}) {
4007
- const raw = readKimiConfigSource(home, opts.env).raw;
4008
- if (raw === null) return null;
3891
+ function detectKimiModels(home = os4.homedir()) {
3892
+ const configPath = path9.join(home, ".kimi", "config.toml");
3893
+ let raw;
3894
+ try {
3895
+ raw = readFileSync4(configPath, "utf8");
3896
+ } catch {
3897
+ return null;
3898
+ }
4009
3899
  const models = [];
4010
3900
  const sectionRe = /^\s*\[models(?:\.([^\]]+)|"\.[^"]+"|\."[^"]+")\s*\]\s*$/gm;
4011
3901
  const lineRe = /^\s*\[models\.(.+?)\s*\]\s*$/gm;
@@ -4268,7 +4158,7 @@ function runOpenCodeModelsCommand(home, deps = {}) {
4268
4158
  const platform = deps.platform ?? process.platform;
4269
4159
  const spawnSyncFn = deps.spawnSyncFn ?? spawnSync2;
4270
4160
  const result = spawnSyncFn("opencode", ["models"], {
4271
- env: scrubDaemonChildEnv({ ...process.env, HOME: home, FORCE_COLOR: "0", NO_COLOR: "1" }),
4161
+ env: { ...process.env, HOME: home, FORCE_COLOR: "0", NO_COLOR: "1" },
4272
4162
  encoding: "utf8",
4273
4163
  timeout: 5e3,
4274
4164
  shell: platform === "win32"
@@ -4529,297 +4419,6 @@ var OpenCodeDriver = class {
4529
4419
  }
4530
4420
  };
4531
4421
 
4532
- // src/drivers/pi.ts
4533
- import { spawn as spawn8 } from "child_process";
4534
- import { existsSync as existsSync9, mkdirSync as mkdirSync4, writeFileSync as writeFileSync7 } from "fs";
4535
- import path11 from "path";
4536
- import { fileURLToPath } from "url";
4537
- import { getAgentDir, VERSION as PI_SDK_VERSION } from "@earendil-works/pi-coding-agent";
4538
- var CHAT_MCP_TOOL_PREFIX2 = "chat_";
4539
- var NO_MESSAGE_PROMPT2 = "No new messages are pending. Stop now.";
4540
- var FIRST_MESSAGE_TASK_PREFIX2 = "First message task (system-triggered):";
4541
- var MIN_SUPPORTED_PI_VERSION = "0.74.0";
4542
- function parseSemver2(version) {
4543
- const match = version.match(/(\d+)\.(\d+)\.(\d+)/);
4544
- if (!match) return null;
4545
- return [Number(match[1]), Number(match[2]), Number(match[3])];
4546
- }
4547
- function isSupportedPiVersion(version) {
4548
- if (!version) return true;
4549
- const actual = parseSemver2(version);
4550
- const minimum = parseSemver2(MIN_SUPPORTED_PI_VERSION);
4551
- if (!actual || !minimum) return true;
4552
- for (let i = 0; i < 3; i += 1) {
4553
- if (actual[i] > minimum[i]) return true;
4554
- if (actual[i] < minimum[i]) return false;
4555
- }
4556
- return true;
4557
- }
4558
- function unsupportedPiVersionMessage(version) {
4559
- if (!version || isSupportedPiVersion(version)) return null;
4560
- 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.`;
4561
- }
4562
- function probePi(version = PI_SDK_VERSION) {
4563
- const unsupportedMessage = unsupportedPiVersionMessage(version);
4564
- if (unsupportedMessage) {
4565
- return {
4566
- available: false,
4567
- version: `${version} (requires @earendil-works/pi-coding-agent >= ${MIN_SUPPORTED_PI_VERSION})`
4568
- };
4569
- }
4570
- return { available: true, version };
4571
- }
4572
- function resolvePiSdkRunnerPath(moduleUrl = import.meta.url) {
4573
- const moduleDir = path11.dirname(fileURLToPath(moduleUrl));
4574
- const sourceSibling = path11.join(moduleDir, "piSdkRunner.ts");
4575
- if (existsSync9(sourceSibling)) return sourceSibling;
4576
- const bundledEntry = path11.join(moduleDir, "drivers", "piSdkRunner.js");
4577
- if (existsSync9(bundledEntry)) return bundledEntry;
4578
- return path11.join(moduleDir, "piSdkRunner.js");
4579
- }
4580
- function buildPiSdkNodeArgs(runnerPath = resolvePiSdkRunnerPath()) {
4581
- if (runnerPath.endsWith(".ts")) {
4582
- return [...process.execArgv, runnerPath];
4583
- }
4584
- return [runnerPath];
4585
- }
4586
- function buildPiLaunchOptions(ctx, opts = {}) {
4587
- const command = opts.command ?? process.execPath;
4588
- const piDir = path11.join(ctx.workingDirectory, ".slock", "pi");
4589
- const sessionDir = path11.join(piDir, "sessions");
4590
- mkdirSync4(sessionDir, { recursive: true });
4591
- const slock = prepareCliTransport(ctx, { NO_COLOR: "1" });
4592
- const runnerPath = opts.runnerPath ?? resolvePiSdkRunnerPath();
4593
- const agentDir = opts.agentDir ?? getAgentDir();
4594
- const runnerConfigPath = path11.join(
4595
- piDir,
4596
- `sdk-run-${(ctx.launchId || "launch").replace(/[^a-zA-Z0-9_.-]/g, "_")}.json`
4597
- );
4598
- const turnPrompt = ctx.prompt === ctx.standingPrompt ? NO_MESSAGE_PROMPT2 : ctx.prompt;
4599
- const runnerConfig = {
4600
- cwd: ctx.workingDirectory,
4601
- agentDir,
4602
- sessionDir,
4603
- sessionId: ctx.config.sessionId || null,
4604
- standingPrompt: ctx.standingPrompt,
4605
- prompt: turnPrompt,
4606
- model: ctx.config.model && ctx.config.model !== "default" ? ctx.config.model : null
4607
- };
4608
- writeFileSync7(runnerConfigPath, `${JSON.stringify(runnerConfig)}
4609
- `, { encoding: "utf8", mode: 384 });
4610
- const args = [
4611
- ...buildPiSdkNodeArgs(runnerPath),
4612
- "--config",
4613
- runnerConfigPath
4614
- ];
4615
- return {
4616
- command,
4617
- args,
4618
- env: slock.spawnEnv,
4619
- sessionDir,
4620
- agentDir,
4621
- runnerConfigPath,
4622
- sdkVersion: PI_SDK_VERSION
4623
- };
4624
- }
4625
- function isSystemFirstMessageTask2(message) {
4626
- return message.sender_id === "system" && message.channel_type === "channel" && message.channel_name === "all" && message.content.trimStart().startsWith(FIRST_MESSAGE_TASK_PREFIX2);
4627
- }
4628
- function buildPiSystemPrompt(config) {
4629
- return buildCliTransportSystemPrompt(config, {
4630
- toolPrefix: CHAT_MCP_TOOL_PREFIX2,
4631
- extraCriticalRules: [
4632
- "- 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."
4633
- ],
4634
- postStartupNotes: [
4635
- "**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."
4636
- ],
4637
- includeStdinNotificationSection: false,
4638
- messageNotificationStyle: "poll"
4639
- });
4640
- }
4641
- function contentText(content) {
4642
- if (!content) return "";
4643
- const chunks = [];
4644
- for (const item of content) {
4645
- if (item.type === "text" && typeof item.text === "string") {
4646
- chunks.push(item.text);
4647
- }
4648
- }
4649
- return chunks.join("");
4650
- }
4651
- function apiKeyErrorMessage(line) {
4652
- const trimmed = line.trim();
4653
- if (!trimmed) return null;
4654
- if (/no api key found/i.test(trimmed)) return trimmed;
4655
- if (/api key.+required/i.test(trimmed)) return trimmed;
4656
- if (/no models available/i.test(trimmed)) return trimmed;
4657
- return null;
4658
- }
4659
- var PiDriver = class {
4660
- id = "pi";
4661
- lifecycle = {
4662
- kind: "per_turn",
4663
- start: "defer_until_concrete_message",
4664
- exit: "terminate_on_turn_end",
4665
- inFlightWake: "coalesce_into_pending"
4666
- };
4667
- communication = {
4668
- chat: "slock_cli",
4669
- runtimeControl: "none"
4670
- };
4671
- session = {
4672
- recovery: "resume_or_fresh"
4673
- };
4674
- model = {
4675
- detectedModelsVerifiedAs: "launchable",
4676
- toLaunchSpec: (modelId, ctx) => {
4677
- if (!ctx) return modelId && modelId !== "default" ? { args: ["--model", modelId] } : { args: [] };
4678
- const launchCtx = {
4679
- ...ctx,
4680
- config: {
4681
- ...ctx.config,
4682
- model: modelId
4683
- }
4684
- };
4685
- const launch = buildPiLaunchOptions(launchCtx);
4686
- return {
4687
- args: launch.args,
4688
- env: launch.env,
4689
- configFiles: [launch.runnerConfigPath],
4690
- params: {
4691
- agentDir: launch.agentDir,
4692
- sessionDir: launch.sessionDir,
4693
- sdkVersion: launch.sdkVersion,
4694
- resources: "extensions/skills/prompt-templates/themes/context-files disabled by Slock policy"
4695
- }
4696
- };
4697
- }
4698
- };
4699
- supportsStdinNotification = false;
4700
- mcpToolPrefix = CHAT_MCP_TOOL_PREFIX2;
4701
- busyDeliveryMode = "none";
4702
- terminateProcessOnTurnEnd = true;
4703
- deferSpawnUntilMessage = true;
4704
- usesSlockCliForCommunication = true;
4705
- sessionId = null;
4706
- sessionAnnounced = false;
4707
- apiKeyErrorAnnounced = false;
4708
- turnEnded = false;
4709
- assistantTextByMessageId = /* @__PURE__ */ new Map();
4710
- shouldDeferWakeMessage(message) {
4711
- return isSystemFirstMessageTask2(message);
4712
- }
4713
- probe() {
4714
- return probePi();
4715
- }
4716
- async detectModels() {
4717
- return null;
4718
- }
4719
- spawn(ctx) {
4720
- this.sessionId = ctx.config.sessionId || null;
4721
- this.sessionAnnounced = false;
4722
- this.apiKeyErrorAnnounced = false;
4723
- this.turnEnded = false;
4724
- this.assistantTextByMessageId.clear();
4725
- const unsupportedMessage = unsupportedPiVersionMessage(PI_SDK_VERSION);
4726
- if (unsupportedMessage) throw new Error(unsupportedMessage);
4727
- const launch = buildPiLaunchOptions(ctx);
4728
- const proc = spawn8(launch.command, launch.args, {
4729
- cwd: ctx.workingDirectory,
4730
- stdio: ["pipe", "pipe", "pipe"],
4731
- env: launch.env,
4732
- shell: false
4733
- });
4734
- proc.stdin?.end();
4735
- return { process: proc };
4736
- }
4737
- parseLine(line) {
4738
- let event;
4739
- try {
4740
- event = JSON.parse(line);
4741
- } catch {
4742
- if (this.apiKeyErrorAnnounced) return [];
4743
- const message = apiKeyErrorMessage(line);
4744
- if (!message) return [];
4745
- this.apiKeyErrorAnnounced = true;
4746
- this.turnEnded = true;
4747
- return [
4748
- { kind: "error", message },
4749
- { kind: "turn_end", sessionId: this.sessionId || void 0 }
4750
- ];
4751
- }
4752
- const events = [];
4753
- if (event.type === "session" && event.id) {
4754
- this.sessionId = event.id;
4755
- }
4756
- if (!this.sessionAnnounced && this.sessionId) {
4757
- events.push({ kind: "session_init", sessionId: this.sessionId });
4758
- this.sessionAnnounced = true;
4759
- }
4760
- switch (event.type) {
4761
- case "agent_start":
4762
- case "turn_start":
4763
- events.push({ kind: "thinking", text: "" });
4764
- break;
4765
- case "message_update":
4766
- case "message_end":
4767
- if (event.message?.role === "assistant") {
4768
- const key = event.message.id || "current";
4769
- const currentText = contentText(event.message.content);
4770
- const previousText = this.assistantTextByMessageId.get(key) ?? "";
4771
- if (currentText.length > previousText.length && currentText.startsWith(previousText)) {
4772
- events.push({ kind: "text", text: currentText.slice(previousText.length) });
4773
- } else if (currentText && currentText !== previousText) {
4774
- events.push({ kind: "text", text: currentText });
4775
- }
4776
- this.assistantTextByMessageId.set(key, currentText);
4777
- if (event.message.stopReason === "error" || event.message.stopReason === "aborted") {
4778
- events.push({ kind: "error", message: event.message.errorMessage || `Request ${event.message.stopReason}` });
4779
- }
4780
- }
4781
- break;
4782
- case "tool_execution_start":
4783
- events.push({
4784
- kind: "tool_call",
4785
- name: event.toolName || "unknown_tool",
4786
- input: event.args
4787
- });
4788
- break;
4789
- case "tool_execution_end":
4790
- events.push({
4791
- kind: "tool_output",
4792
- name: event.toolName || "unknown_tool"
4793
- });
4794
- if (event.isError) {
4795
- events.push({ kind: "error", message: `Pi tool ${event.toolName || "unknown_tool"} failed` });
4796
- }
4797
- break;
4798
- case "compaction_start":
4799
- events.push({ kind: "compaction_started" });
4800
- break;
4801
- case "compaction_end":
4802
- events.push({ kind: "compaction_finished" });
4803
- if (event.errorMessage) events.push({ kind: "error", message: event.errorMessage });
4804
- break;
4805
- case "turn_end":
4806
- case "agent_end":
4807
- if (!this.turnEnded) {
4808
- events.push({ kind: "turn_end", sessionId: this.sessionId || void 0 });
4809
- this.turnEnded = true;
4810
- }
4811
- break;
4812
- }
4813
- return events;
4814
- }
4815
- encodeStdinMessage(_text, _sessionId, _opts) {
4816
- return null;
4817
- }
4818
- buildSystemPrompt(config, _agentId) {
4819
- return buildPiSystemPrompt(config);
4820
- }
4821
- };
4822
-
4823
4422
  // src/drivers/index.ts
4824
4423
  var driverFactories = {
4825
4424
  claude: () => new ClaudeDriver(),
@@ -4828,8 +4427,7 @@ var driverFactories = {
4828
4427
  cursor: () => new CursorDriver(),
4829
4428
  gemini: () => new GeminiDriver(),
4830
4429
  kimi: () => new KimiDriver(),
4831
- opencode: () => new OpenCodeDriver(),
4832
- pi: () => new PiDriver()
4430
+ opencode: () => new OpenCodeDriver()
4833
4431
  };
4834
4432
  function getDriver(runtimeId) {
4835
4433
  const createDriver = driverFactories[runtimeId];
@@ -4842,7 +4440,7 @@ function getDriver(runtimeId) {
4842
4440
 
4843
4441
  // src/workspaces.ts
4844
4442
  import { readdir, rm, stat } from "fs/promises";
4845
- import path12 from "path";
4443
+ import path11 from "path";
4846
4444
  function isValidWorkspaceDirectoryName(directoryName) {
4847
4445
  return !directoryName.includes("/") && !directoryName.includes("\\") && !directoryName.includes("..");
4848
4446
  }
@@ -4850,7 +4448,7 @@ function resolveWorkspaceDirectoryPath(dataDir, directoryName) {
4850
4448
  if (!isValidWorkspaceDirectoryName(directoryName)) {
4851
4449
  return null;
4852
4450
  }
4853
- return path12.join(dataDir, directoryName);
4451
+ return path11.join(dataDir, directoryName);
4854
4452
  }
4855
4453
  function emptyWorkspaceDirectorySummary(latestMtime = /* @__PURE__ */ new Date(0)) {
4856
4454
  return {
@@ -4899,7 +4497,7 @@ async function summarizeWorkspaceDirectory(dirPath) {
4899
4497
  return summary;
4900
4498
  }
4901
4499
  const childSummaries = await Promise.all(
4902
- entries.map((entry) => summarizeWorkspaceEntry(path12.join(dirPath, entry.name), entry))
4500
+ entries.map((entry) => summarizeWorkspaceEntry(path11.join(dirPath, entry.name), entry))
4903
4501
  );
4904
4502
  for (const childSummary of childSummaries) {
4905
4503
  summary = mergeWorkspaceDirectorySummaries(summary, childSummary);
@@ -4918,7 +4516,7 @@ async function scanWorkspaceDirectories(dataDir) {
4918
4516
  if (!entry.isDirectory()) {
4919
4517
  return null;
4920
4518
  }
4921
- const dirPath = path12.join(dataDir, entry.name);
4519
+ const dirPath = path11.join(dataDir, entry.name);
4922
4520
  try {
4923
4521
  const summary = await summarizeWorkspaceDirectory(dirPath);
4924
4522
  return {
@@ -5176,12 +4774,12 @@ function findSessionJsonl(root, predicate) {
5176
4774
  for (const entry of entries) {
5177
4775
  if (++visited > maxEntries) return null;
5178
4776
  if (!entry.isFile() || !predicate(entry.name)) continue;
5179
- return path13.join(dir, entry.name);
4777
+ return path12.join(dir, entry.name);
5180
4778
  }
5181
4779
  for (const entry of entries) {
5182
4780
  if (++visited > maxEntries) return null;
5183
4781
  if (!entry.isDirectory()) continue;
5184
- const found = visit(path13.join(dir, entry.name), depth - 1);
4782
+ const found = visit(path12.join(dir, entry.name), depth - 1);
5185
4783
  if (found) return found;
5186
4784
  }
5187
4785
  return null;
@@ -5194,10 +4792,10 @@ function safeSessionFilename(value) {
5194
4792
  }
5195
4793
  function writeRuntimeSessionHandoff(runtime, sessionId, fallbackDir) {
5196
4794
  try {
5197
- const dir = path13.join(fallbackDir, ".slock", "runtime-sessions");
5198
- mkdirSync5(dir, { recursive: true });
5199
- const filePath = path13.join(dir, `${runtime}-${safeSessionFilename(sessionId)}.jsonl`);
5200
- writeFileSync8(filePath, JSON.stringify({
4795
+ const dir = path12.join(fallbackDir, ".slock", "runtime-sessions");
4796
+ mkdirSync4(dir, { recursive: true });
4797
+ const filePath = path12.join(dir, `${runtime}-${safeSessionFilename(sessionId)}.jsonl`);
4798
+ writeFileSync7(filePath, JSON.stringify({
5201
4799
  type: "runtime_session_handoff",
5202
4800
  runtime,
5203
4801
  sessionId,
@@ -5216,7 +4814,7 @@ function writeRuntimeSessionHandoff(runtime, sessionId, fallbackDir) {
5216
4814
  }
5217
4815
  }
5218
4816
  function resolveRuntimeSessionRef(runtime, sessionId, homeDir = os6.homedir(), fallbackDir) {
5219
- const directPath = path13.isAbsolute(sessionId) ? sessionId : null;
4817
+ const directPath = path12.isAbsolute(sessionId) ? sessionId : null;
5220
4818
  if (directPath) {
5221
4819
  try {
5222
4820
  if (statSync2(directPath).isFile()) {
@@ -5225,7 +4823,7 @@ function resolveRuntimeSessionRef(runtime, sessionId, homeDir = os6.homedir(), f
5225
4823
  } catch {
5226
4824
  }
5227
4825
  }
5228
- 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;
4826
+ 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;
5229
4827
  if (!resolvedPath && fallbackDir) {
5230
4828
  const fallback = writeRuntimeSessionHandoff(runtime, sessionId, fallbackDir);
5231
4829
  if (fallback) return fallback;
@@ -6534,26 +6132,26 @@ var AgentProcessManager = class _AgentProcessManager {
6534
6132
  this.recordDaemonTrace("daemon.agent.spawn.started", this.startQueueTraceAttrs(agentId, config, wakeMessage, unreadSummary, resumePrompt, launchId));
6535
6133
  try {
6536
6134
  const driver = this.driverResolver(config.runtime || "claude");
6537
- const agentDataDir = path13.join(this.dataDir, agentId);
6135
+ const agentDataDir = path12.join(this.dataDir, agentId);
6538
6136
  await mkdir(agentDataDir, { recursive: true });
6539
6137
  const runtimeConfig = withLocalRuntimeContext(config, agentId, agentDataDir);
6540
- const memoryMdPath = path13.join(agentDataDir, "MEMORY.md");
6138
+ const memoryMdPath = path12.join(agentDataDir, "MEMORY.md");
6541
6139
  try {
6542
6140
  await access(memoryMdPath);
6543
6141
  } catch {
6544
6142
  const initialMemoryMd = buildInitialMemoryMd(runtimeConfig);
6545
6143
  await writeFile(memoryMdPath, initialMemoryMd);
6546
6144
  }
6547
- const notesDir = path13.join(agentDataDir, "notes");
6145
+ const notesDir = path12.join(agentDataDir, "notes");
6548
6146
  await mkdir(notesDir, { recursive: true });
6549
6147
  if (getOnboardingSeedMode(config) === FIRST_CINDY_SEED_MODE) {
6550
6148
  const seedFiles = buildOnboardingSeedFiles();
6551
6149
  for (const { relativePath, content } of seedFiles) {
6552
- const fullPath = path13.join(agentDataDir, relativePath);
6150
+ const fullPath = path12.join(agentDataDir, relativePath);
6553
6151
  try {
6554
6152
  await access(fullPath);
6555
6153
  } catch {
6556
- await mkdir(path13.dirname(fullPath), { recursive: true });
6154
+ await mkdir(path12.dirname(fullPath), { recursive: true });
6557
6155
  await writeFile(fullPath, content);
6558
6156
  }
6559
6157
  }
@@ -7430,7 +7028,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
7430
7028
  return true;
7431
7029
  }
7432
7030
  async resetWorkspace(agentId) {
7433
- const agentDataDir = path13.join(this.dataDir, agentId);
7031
+ const agentDataDir = path12.join(this.dataDir, agentId);
7434
7032
  try {
7435
7033
  await rm2(agentDataDir, { recursive: true, force: true });
7436
7034
  logger.info(`[Agent ${agentId}] Workspace reset complete (${agentDataDir})`);
@@ -7467,7 +7065,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
7467
7065
  return result;
7468
7066
  }
7469
7067
  buildRuntimeProfileReport(agentId, config, sessionId, launchId) {
7470
- const workspacePath = path13.join(this.dataDir, agentId);
7068
+ const workspacePath = path12.join(this.dataDir, agentId);
7471
7069
  return {
7472
7070
  agentId,
7473
7071
  launchId,
@@ -7724,7 +7322,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
7724
7322
  }
7725
7323
  // Workspace file browsing
7726
7324
  async getFileTree(agentId, dirPath) {
7727
- const agentDir = path13.join(this.dataDir, agentId);
7325
+ const agentDir = path12.join(this.dataDir, agentId);
7728
7326
  try {
7729
7327
  await stat2(agentDir);
7730
7328
  } catch {
@@ -7732,8 +7330,8 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
7732
7330
  }
7733
7331
  let targetDir = agentDir;
7734
7332
  if (dirPath) {
7735
- const resolved = path13.resolve(agentDir, dirPath);
7736
- if (!resolved.startsWith(agentDir + path13.sep) && resolved !== agentDir) {
7333
+ const resolved = path12.resolve(agentDir, dirPath);
7334
+ if (!resolved.startsWith(agentDir + path12.sep) && resolved !== agentDir) {
7737
7335
  return [];
7738
7336
  }
7739
7337
  targetDir = resolved;
@@ -7741,14 +7339,14 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
7741
7339
  return this.listDirectoryChildren(targetDir, agentDir);
7742
7340
  }
7743
7341
  async readFile(agentId, filePath) {
7744
- const agentDir = path13.join(this.dataDir, agentId);
7745
- const resolved = path13.resolve(agentDir, filePath);
7746
- if (!resolved.startsWith(agentDir + path13.sep) && resolved !== agentDir) {
7342
+ const agentDir = path12.join(this.dataDir, agentId);
7343
+ const resolved = path12.resolve(agentDir, filePath);
7344
+ if (!resolved.startsWith(agentDir + path12.sep) && resolved !== agentDir) {
7747
7345
  throw new Error("Access denied");
7748
7346
  }
7749
7347
  const info = await stat2(resolved);
7750
7348
  if (info.isDirectory()) throw new Error("Cannot read a directory");
7751
- const ext = path13.extname(resolved).toLowerCase();
7349
+ const ext = path12.extname(resolved).toLowerCase();
7752
7350
  if (WORKSPACE_TEXT_EXTENSIONS.has(ext) || ext === "") {
7753
7351
  if (info.size > WORKSPACE_TEXT_FILE_MAX_BYTES) throw new Error("File too large");
7754
7352
  const content = await readFile(resolved, "utf-8");
@@ -7783,13 +7381,13 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
7783
7381
  const agent = this.agents.get(agentId);
7784
7382
  const runtime = runtimeHint || agent?.config.runtime || "claude";
7785
7383
  const home = os6.homedir();
7786
- const workspaceDir = path13.join(this.dataDir, agentId);
7384
+ const workspaceDir = path12.join(this.dataDir, agentId);
7787
7385
  const paths = _AgentProcessManager.SKILL_PATHS[runtime] || _AgentProcessManager.SKILL_PATHS.claude;
7788
7386
  const globalResults = await Promise.all(
7789
- paths.global.map((p) => this.scanSkillsDir(path13.join(home, p)))
7387
+ paths.global.map((p) => this.scanSkillsDir(path12.join(home, p)))
7790
7388
  );
7791
7389
  const workspaceResults = await Promise.all(
7792
- paths.workspace.map((p) => this.scanSkillsDir(path13.join(workspaceDir, p)))
7390
+ paths.workspace.map((p) => this.scanSkillsDir(path12.join(workspaceDir, p)))
7793
7391
  );
7794
7392
  const dedup = (skills) => {
7795
7393
  const seen = /* @__PURE__ */ new Set();
@@ -7818,7 +7416,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
7818
7416
  const skills = [];
7819
7417
  for (const entry of entries) {
7820
7418
  if (entry.isDirectory() || entry.isSymbolicLink()) {
7821
- const skillMd = path13.join(dir, entry.name, "SKILL.md");
7419
+ const skillMd = path12.join(dir, entry.name, "SKILL.md");
7822
7420
  try {
7823
7421
  const content = await readFile(skillMd, "utf-8");
7824
7422
  const skill = this.parseSkillMd(entry.name, content);
@@ -7829,7 +7427,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
7829
7427
  } else if (entry.name.endsWith(".md")) {
7830
7428
  const cmdName = entry.name.replace(/\.md$/, "");
7831
7429
  try {
7832
- const content = await readFile(path13.join(dir, entry.name), "utf-8");
7430
+ const content = await readFile(path12.join(dir, entry.name), "utf-8");
7833
7431
  const skill = this.parseSkillMd(cmdName, content);
7834
7432
  skill.sourcePath = dir;
7835
7433
  skills.push(skill);
@@ -8795,8 +8393,8 @@ ${RESPONSE_TARGET_HINT}`);
8795
8393
  const nodes = [];
8796
8394
  for (const entry of entries) {
8797
8395
  if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
8798
- const fullPath = path13.join(dir, entry.name);
8799
- const relativePath = path13.relative(rootDir, fullPath);
8396
+ const fullPath = path12.join(dir, entry.name);
8397
+ const relativePath = path12.relative(rootDir, fullPath);
8800
8398
  let info;
8801
8399
  try {
8802
8400
  info = await stat2(fullPath);
@@ -9101,9 +8699,9 @@ var ReminderCache = class {
9101
8699
 
9102
8700
  // src/machineLock.ts
9103
8701
  import { createHash as createHash3, randomUUID as randomUUID2 } from "crypto";
9104
- import { mkdirSync as mkdirSync6, readFileSync as readFileSync6, rmSync as rmSync3, statSync as statSync3, writeFileSync as writeFileSync9 } from "fs";
8702
+ import { mkdirSync as mkdirSync5, readFileSync as readFileSync6, rmSync as rmSync3, statSync as statSync3, writeFileSync as writeFileSync8 } from "fs";
9105
8703
  import os7 from "os";
9106
- import path14 from "path";
8704
+ import path13 from "path";
9107
8705
  var INCOMPLETE_LOCK_STALE_MS = 3e4;
9108
8706
  var DaemonMachineLockConflictError = class extends Error {
9109
8707
  code = "DAEMON_MACHINE_LOCK_HELD";
@@ -9125,7 +8723,7 @@ function resolveDefaultMachineStateRoot() {
9125
8723
  return resolveSlockHomePath("machines");
9126
8724
  }
9127
8725
  function ownerPath(lockDir) {
9128
- return path14.join(lockDir, "owner.json");
8726
+ return path13.join(lockDir, "owner.json");
9129
8727
  }
9130
8728
  function readOwner(lockDir) {
9131
8729
  try {
@@ -9155,13 +8753,13 @@ function acquireDaemonMachineLock(options) {
9155
8753
  const rootDir = options.rootDir ?? resolveDefaultMachineStateRoot();
9156
8754
  const fingerprint = apiKeyFingerprint(options.apiKey);
9157
8755
  const lockId = getDaemonMachineLockId(options.apiKey);
9158
- const machineDir = path14.join(rootDir, lockId);
9159
- const lockDir = path14.join(machineDir, "daemon.lock");
8756
+ const machineDir = path13.join(rootDir, lockId);
8757
+ const lockDir = path13.join(machineDir, "daemon.lock");
9160
8758
  const token = randomUUID2();
9161
- mkdirSync6(machineDir, { recursive: true });
8759
+ mkdirSync5(machineDir, { recursive: true });
9162
8760
  for (let attempt = 0; attempt < 2; attempt += 1) {
9163
8761
  try {
9164
- mkdirSync6(lockDir);
8762
+ mkdirSync5(lockDir);
9165
8763
  const owner = {
9166
8764
  pid: process.pid,
9167
8765
  token,
@@ -9171,7 +8769,7 @@ function acquireDaemonMachineLock(options) {
9171
8769
  apiKeyFingerprint: fingerprint.slice(0, 16)
9172
8770
  };
9173
8771
  try {
9174
- writeFileSync9(ownerPath(lockDir), `${JSON.stringify(owner, null, 2)}
8772
+ writeFileSync8(ownerPath(lockDir), `${JSON.stringify(owner, null, 2)}
9175
8773
  `, { mode: 384 });
9176
8774
  } catch (err) {
9177
8775
  rmSync3(lockDir, { recursive: true, force: true });
@@ -9208,8 +8806,8 @@ function acquireDaemonMachineLock(options) {
9208
8806
  }
9209
8807
 
9210
8808
  // src/localTraceSink.ts
9211
- import { appendFileSync, mkdirSync as mkdirSync7, readdirSync as readdirSync3, rmSync as rmSync4, statSync as statSync4, writeFileSync as writeFileSync10 } from "fs";
9212
- import path15 from "path";
8809
+ import { appendFileSync, mkdirSync as mkdirSync6, readdirSync as readdirSync3, rmSync as rmSync4, statSync as statSync4, writeFileSync as writeFileSync9 } from "fs";
8810
+ import path14 from "path";
9213
8811
  var DEFAULT_MAX_FILE_BYTES = 5 * 1024 * 1024;
9214
8812
  var DEFAULT_MAX_FILE_AGE_MS = 5 * 60 * 1e3;
9215
8813
  var DEFAULT_MAX_FILES = 8;
@@ -9245,7 +8843,7 @@ var LocalRotatingTraceSink = class {
9245
8843
  currentSize = 0;
9246
8844
  sequence = 0;
9247
8845
  constructor(options) {
9248
- this.traceDir = path15.join(options.machineDir, "traces");
8846
+ this.traceDir = path14.join(options.machineDir, "traces");
9249
8847
  this.maxFileBytes = Math.max(1024, Math.floor(options.maxFileBytes ?? DEFAULT_MAX_FILE_BYTES));
9250
8848
  const baseAgeMs = Math.max(1e3, Math.floor(options.maxFileAgeMs ?? DEFAULT_MAX_FILE_AGE_MS));
9251
8849
  const ageJitterMs = Math.max(0, Math.floor(options.maxFileAgeJitterMs ?? 0));
@@ -9271,15 +8869,15 @@ var LocalRotatingTraceSink = class {
9271
8869
  return this.currentFile;
9272
8870
  }
9273
8871
  ensureFile(nextBytes) {
9274
- mkdirSync7(this.traceDir, { recursive: true, mode: 448 });
8872
+ mkdirSync6(this.traceDir, { recursive: true, mode: 448 });
9275
8873
  const nowMs = this.nowMsProvider();
9276
8874
  const shouldRotateForAge = this.currentFileOpenedAtMs !== null && nowMs - this.currentFileOpenedAtMs >= this.maxFileAgeMs;
9277
8875
  if (!this.currentFile || this.currentSize + nextBytes > this.maxFileBytes || shouldRotateForAge) {
9278
- this.currentFile = path15.join(
8876
+ this.currentFile = path14.join(
9279
8877
  this.traceDir,
9280
8878
  `daemon-trace-${safeTimestamp(nowMs)}-${process.pid}-${String(this.sequence++).padStart(4, "0")}.jsonl`
9281
8879
  );
9282
- writeFileSync10(this.currentFile, "", { flag: "a", mode: 384 });
8880
+ writeFileSync9(this.currentFile, "", { flag: "a", mode: 384 });
9283
8881
  this.currentSize = statSync4(this.currentFile).size;
9284
8882
  this.currentFileOpenedAtMs = nowMs;
9285
8883
  this.pruneOldFiles();
@@ -9290,7 +8888,7 @@ var LocalRotatingTraceSink = class {
9290
8888
  const excess = files.length - this.maxFiles;
9291
8889
  if (excess <= 0) return;
9292
8890
  for (const file of files.slice(0, excess)) {
9293
- rmSync4(path15.join(this.traceDir, file), { force: true });
8891
+ rmSync4(path14.join(this.traceDir, file), { force: true });
9294
8892
  }
9295
8893
  }
9296
8894
  };
@@ -9377,11 +8975,11 @@ function isDiagnosticErrorAttr(key) {
9377
8975
  import { createHash as createHash5, randomUUID as randomUUID3 } from "crypto";
9378
8976
  import { gzipSync } from "zlib";
9379
8977
  import { mkdir as mkdir2, readFile as readFile2, readdir as readdir3, stat as stat3, writeFile as writeFile2 } from "fs/promises";
9380
- import path16 from "path";
8978
+ import path15 from "path";
9381
8979
 
9382
8980
  // src/directUploadCapability.ts
9383
- function joinUrl(base, path18) {
9384
- return `${base.replace(/\/+$/, "")}${path18}`;
8981
+ function joinUrl(base, path17) {
8982
+ return `${base.replace(/\/+$/, "")}${path17}`;
9385
8983
  }
9386
8984
  function jsonHeaders(apiKey) {
9387
8985
  return {
@@ -9600,7 +9198,7 @@ var DaemonTraceBundleUploader = class {
9600
9198
  }, nextMs);
9601
9199
  }
9602
9200
  async findUploadCandidates() {
9603
- const traceDir = path16.join(this.options.machineDir, "traces");
9201
+ const traceDir = path15.join(this.options.machineDir, "traces");
9604
9202
  let names;
9605
9203
  try {
9606
9204
  names = await readdir3(traceDir);
@@ -9612,8 +9210,8 @@ var DaemonTraceBundleUploader = class {
9612
9210
  const currentFile = this.options.currentFileProvider?.();
9613
9211
  const candidates = [];
9614
9212
  for (const name of names.filter((entry) => entry.startsWith("daemon-trace-") && entry.endsWith(".jsonl")).sort()) {
9615
- const file = path16.join(traceDir, name);
9616
- if (currentFile && path16.resolve(file) === path16.resolve(currentFile)) continue;
9213
+ const file = path15.join(traceDir, name);
9214
+ if (currentFile && path15.resolve(file) === path15.resolve(currentFile)) continue;
9617
9215
  if (await this.isUploaded(file)) continue;
9618
9216
  try {
9619
9217
  const info = await stat3(file);
@@ -9687,8 +9285,8 @@ var DaemonTraceBundleUploader = class {
9687
9285
  }
9688
9286
  }
9689
9287
  uploadStatePath(file) {
9690
- const stateDir = path16.join(this.options.machineDir, "trace-uploads");
9691
- return path16.join(stateDir, `${path16.basename(file)}.uploaded.json`);
9288
+ const stateDir = path15.join(this.options.machineDir, "trace-uploads");
9289
+ return path15.join(stateDir, `${path15.basename(file)}.uploaded.json`);
9692
9290
  }
9693
9291
  async isUploaded(file) {
9694
9292
  try {
@@ -9700,9 +9298,9 @@ var DaemonTraceBundleUploader = class {
9700
9298
  }
9701
9299
  async markUploaded(file, metadata) {
9702
9300
  const stateFile = this.uploadStatePath(file);
9703
- await mkdir2(path16.dirname(stateFile), { recursive: true, mode: 448 });
9301
+ await mkdir2(path15.dirname(stateFile), { recursive: true, mode: 448 });
9704
9302
  await writeFile2(stateFile, `${JSON.stringify({
9705
- file: path16.basename(file),
9303
+ file: path15.basename(file),
9706
9304
  uploadedAt: (/* @__PURE__ */ new Date()).toISOString(),
9707
9305
  ...metadata
9708
9306
  }, null, 2)}
@@ -9724,7 +9322,7 @@ var DEFAULT_TRACE_UPLOAD_URL = "https://slock-trace-upload.botiverse.dev";
9724
9322
  var RUNNER_CREDENTIAL_SCOPES = ["send", "read", "mentions", "tasks", "reactions", "server", "channels"];
9725
9323
  var RUNNER_CREDENTIAL_MINT_MAX_ATTEMPTS2 = 3;
9726
9324
  var RUNNER_CREDENTIAL_MINT_RETRY_DELAY_MS2 = 250;
9727
- var DAEMON_CLI_USAGE = `Usage: slock-daemon --server-url <url> (--api-key <key> or ${DAEMON_API_KEY_ENV}=<key>)`;
9325
+ var DAEMON_CLI_USAGE = "Usage: slock-daemon --server-url <url> --api-key <key>";
9728
9326
  var RunnerCredentialMintError2 = class extends Error {
9729
9327
  code;
9730
9328
  retryable;
@@ -9760,9 +9358,9 @@ function runnerCredentialErrorDetail2(error) {
9760
9358
  async function waitForRunnerCredentialRetry2() {
9761
9359
  await new Promise((resolve) => setTimeout(resolve, RUNNER_CREDENTIAL_MINT_RETRY_DELAY_MS2));
9762
9360
  }
9763
- function parseDaemonCliArgs(args, env = {}) {
9361
+ function parseDaemonCliArgs(args) {
9764
9362
  let serverUrl = "";
9765
- let apiKey = env[DAEMON_API_KEY_ENV] ?? "";
9363
+ let apiKey = "";
9766
9364
  for (let i = 0; i < args.length; i++) {
9767
9365
  if (args[i] === "--server-url" && args[i + 1]) serverUrl = args[++i];
9768
9366
  if (args[i] === "--api-key" && args[i + 1]) apiKey = args[++i];
@@ -9779,23 +9377,23 @@ function readDaemonVersion(moduleUrl = import.meta.url) {
9779
9377
  }
9780
9378
  }
9781
9379
  function resolveChatBridgePath(moduleUrl = import.meta.url) {
9782
- const dirname = path17.dirname(fileURLToPath2(moduleUrl));
9783
- const jsPath = path17.resolve(dirname, "chat-bridge.js");
9380
+ const dirname = path16.dirname(fileURLToPath(moduleUrl));
9381
+ const jsPath = path16.resolve(dirname, "chat-bridge.js");
9784
9382
  try {
9785
9383
  accessSync(jsPath);
9786
9384
  return jsPath;
9787
9385
  } catch {
9788
- return path17.resolve(dirname, "chat-bridge.ts");
9386
+ return path16.resolve(dirname, "chat-bridge.ts");
9789
9387
  }
9790
9388
  }
9791
9389
  function resolveSlockCliPath(moduleUrl = import.meta.url) {
9792
- const thisDir = path17.dirname(fileURLToPath2(moduleUrl));
9793
- const bundledDistPath = path17.resolve(thisDir, "cli", "index.js");
9390
+ const thisDir = path16.dirname(fileURLToPath(moduleUrl));
9391
+ const bundledDistPath = path16.resolve(thisDir, "cli", "index.js");
9794
9392
  try {
9795
9393
  accessSync(bundledDistPath);
9796
9394
  return bundledDistPath;
9797
9395
  } catch {
9798
- const workspaceDistPath = path17.resolve(thisDir, "..", "..", "cli", "dist", "index.js");
9396
+ const workspaceDistPath = path16.resolve(thisDir, "..", "..", "cli", "dist", "index.js");
9799
9397
  accessSync(workspaceDistPath);
9800
9398
  return workspaceDistPath;
9801
9399
  }
@@ -9974,7 +9572,7 @@ var DaemonCore = class {
9974
9572
  }
9975
9573
  resolveMachineStateRoot() {
9976
9574
  if (this.options.machineStateDir) return this.options.machineStateDir;
9977
- if (this.options.dataDir) return path17.join(path17.dirname(this.options.dataDir), "machines");
9575
+ if (this.options.dataDir) return path16.join(path16.dirname(this.options.dataDir), "machines");
9978
9576
  return resolveDefaultMachineStateRoot();
9979
9577
  }
9980
9578
  shouldEnableLocalTrace() {
@@ -10476,8 +10074,6 @@ var DaemonCore = class {
10476
10074
  };
10477
10075
 
10478
10076
  export {
10479
- DAEMON_API_KEY_ENV,
10480
- scrubDaemonAuthEnv,
10481
10077
  resolveWorkspaceDirectoryPath,
10482
10078
  scanWorkspaceDirectories,
10483
10079
  deleteWorkspaceDirectory,
package/dist/cli/index.js CHANGED
@@ -14161,7 +14161,6 @@ var SERVER_CAPABILITY_MATRIX = {
14161
14161
  var RUNTIMES = [
14162
14162
  { id: "claude", displayName: "Claude Code", binary: "claude", supported: true },
14163
14163
  { id: "codex", displayName: "Codex CLI", binary: "codex", supported: true },
14164
- { id: "pi", displayName: "Pi", binary: "pi", supported: true },
14165
14164
  { id: "kimi", displayName: "Kimi CLI", binary: "kimi", supported: true },
14166
14165
  { id: "copilot", displayName: "Copilot CLI", binary: "copilot", supported: true },
14167
14166
  { id: "cursor", displayName: "Cursor CLI", binary: "cursor-agent", supported: true },
@@ -14282,6 +14281,7 @@ var ApiClient = class {
14282
14281
  if (suffix.startsWith("/search")) return `/internal/agent-api/search${suffix.slice("/search".length)}`;
14283
14282
  if (suffix.startsWith("/channel-members")) return `/internal/agent-api/channel-members${suffix.slice("/channel-members".length)}`;
14284
14283
  if (suffix === "/profile" || suffix.startsWith("/profile/")) return `/internal/agent-api${suffix}`;
14284
+ if (suffix === "/integrations" || suffix.startsWith("/integrations/")) return `/internal/agent-api${suffix}`;
14285
14285
  if (suffix === "/upload") return "/internal/agent-api/upload";
14286
14286
  if (suffix === "/resolve-channel") return "/internal/agent-api/resolve-channel";
14287
14287
  if (suffix === "/threads/unfollow") return "/internal/agent-api/threads/unfollow";
package/dist/core.js CHANGED
@@ -1,5 +1,4 @@
1
1
  import {
2
- DAEMON_API_KEY_ENV,
3
2
  DAEMON_CLI_USAGE,
4
3
  DaemonCore,
5
4
  deleteWorkspaceDirectory,
@@ -9,14 +8,12 @@ import {
9
8
  resolveChatBridgePath,
10
9
  resolveSlockCliPath,
11
10
  resolveWorkspaceDirectoryPath,
12
- scanWorkspaceDirectories,
13
- scrubDaemonAuthEnv
14
- } from "./chunk-AGSYS44K.js";
11
+ scanWorkspaceDirectories
12
+ } from "./chunk-LPRTPDGH.js";
15
13
  import {
16
14
  subscribeDaemonLogs
17
15
  } from "./chunk-KNMCE6WB.js";
18
16
  export {
19
- DAEMON_API_KEY_ENV,
20
17
  DAEMON_CLI_USAGE,
21
18
  DaemonCore,
22
19
  deleteWorkspaceDirectory,
@@ -27,6 +24,5 @@ export {
27
24
  resolveSlockCliPath,
28
25
  resolveWorkspaceDirectoryPath,
29
26
  scanWorkspaceDirectories,
30
- scrubDaemonAuthEnv,
31
27
  subscribeDaemonLogs
32
28
  };
package/dist/index.js CHANGED
@@ -2,14 +2,12 @@
2
2
  import {
3
3
  DAEMON_CLI_USAGE,
4
4
  DaemonCore,
5
- parseDaemonCliArgs,
6
- scrubDaemonAuthEnv
7
- } from "./chunk-AGSYS44K.js";
5
+ parseDaemonCliArgs
6
+ } from "./chunk-LPRTPDGH.js";
8
7
  import "./chunk-KNMCE6WB.js";
9
8
 
10
9
  // src/index.ts
11
- var parsedArgs = parseDaemonCliArgs(process.argv.slice(2), process.env);
12
- scrubDaemonAuthEnv(process.env);
10
+ var parsedArgs = parseDaemonCliArgs(process.argv.slice(2));
13
11
  if (!parsedArgs) {
14
12
  console.error(DAEMON_CLI_USAGE);
15
13
  process.exit(1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@slock-ai/daemon",
3
- "version": "0.52.2-play.20260522165849",
3
+ "version": "0.53.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "slock-daemon": "dist/index.js"
@@ -36,7 +36,6 @@
36
36
  "release:alpha": "npm version prerelease --preid=alpha --no-git-tag-version && cd ../.. && pnpm install --lockfile-only && git add packages/daemon/package.json pnpm-lock.yaml && git commit -m \"chore: bump @slock-ai/daemon to v$(node -p \"require('./packages/daemon/package.json').version\")\" && git tag daemon-v$(node -p \"require('./packages/daemon/package.json').version\") && git push && git push --tags"
37
37
  },
38
38
  "dependencies": {
39
- "@earendil-works/pi-coding-agent": "0.74.0",
40
39
  "@jackwener/opencli": "^1.8.0",
41
40
  "@modelcontextprotocol/sdk": "^1.29.0",
42
41
  "commander": "^12.1.0",
@@ -1,96 +0,0 @@
1
- // src/drivers/piSdkRunner.ts
2
- import { readFile } from "fs/promises";
3
- import path from "path";
4
- import {
5
- AuthStorage,
6
- createAgentSessionFromServices,
7
- createAgentSessionServices,
8
- SessionManager
9
- } from "@earendil-works/pi-coding-agent";
10
- function writeJson(value) {
11
- process.stdout.write(`${JSON.stringify(value)}
12
- `);
13
- }
14
- function parseArgs(argv) {
15
- const index = argv.indexOf("--config");
16
- const configPath = index >= 0 ? argv[index + 1] : void 0;
17
- if (!configPath) throw new Error("Missing --config <path>");
18
- return { configPath };
19
- }
20
- function resolveConfiguredModel(modelId, modelRegistry) {
21
- if (!modelId) return void 0;
22
- const [provider, ...rest] = modelId.split("/");
23
- const providerScopedId = rest.join("/");
24
- if (provider && providerScopedId) {
25
- const exact = modelRegistry.find(provider, providerScopedId);
26
- if (exact) return exact;
27
- }
28
- return modelRegistry.getAll().find(
29
- (model) => model.id === modelId || `${model.provider}/${model.id}` === modelId || (providerScopedId ? model.id === providerScopedId : false)
30
- );
31
- }
32
- async function createSessionManager(config) {
33
- if (!config.sessionId) return SessionManager.create(config.cwd, config.sessionDir);
34
- const localSessions = await SessionManager.list(config.cwd, config.sessionDir);
35
- const match = localSessions.find((session) => session.id.startsWith(config.sessionId));
36
- if (match) return SessionManager.open(match.path, config.sessionDir);
37
- return SessionManager.create(config.cwd, config.sessionDir);
38
- }
39
- async function run() {
40
- const { configPath } = parseArgs(process.argv.slice(2));
41
- const config = JSON.parse(await readFile(configPath, "utf8"));
42
- const authStorage = AuthStorage.create(path.join(config.agentDir, "auth.json"));
43
- const services = await createAgentSessionServices({
44
- cwd: config.cwd,
45
- agentDir: config.agentDir,
46
- authStorage,
47
- resourceLoaderOptions: {
48
- appendSystemPrompt: [config.standingPrompt],
49
- noContextFiles: true,
50
- noExtensions: true,
51
- noPromptTemplates: true,
52
- noSkills: true,
53
- noThemes: true
54
- }
55
- });
56
- for (const diagnostic of services.diagnostics) {
57
- const line = `[Pi SDK] ${diagnostic.type}: ${diagnostic.message}`;
58
- if (diagnostic.type === "error") throw new Error(line);
59
- process.stderr.write(`${line}
60
- `);
61
- }
62
- const sessionManager = await createSessionManager(config);
63
- const model = resolveConfiguredModel(config.model, services.modelRegistry);
64
- if (config.model && !model) {
65
- throw new Error(`Configured Pi model '${config.model}' was not found in Pi model registry.`);
66
- }
67
- const { session } = await createAgentSessionFromServices({
68
- services,
69
- sessionManager,
70
- model
71
- });
72
- const header = session.sessionManager.getHeader();
73
- if (header) writeJson(header);
74
- const unsubscribe = session.subscribe((event) => writeJson(event));
75
- try {
76
- await session.prompt(config.prompt);
77
- } finally {
78
- unsubscribe();
79
- session.dispose();
80
- await services.settingsManager.flush();
81
- }
82
- }
83
- run().catch((error) => {
84
- const message = error instanceof Error ? error.message : String(error);
85
- writeJson({
86
- type: "message_end",
87
- message: {
88
- role: "assistant",
89
- content: [],
90
- stopReason: "error",
91
- errorMessage: message
92
- }
93
- });
94
- writeJson({ type: "turn_end" });
95
- process.exitCode = 1;
96
- });