@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.
- package/dist/{chunk-AGSYS44K.js → chunk-LPRTPDGH.js} +94 -498
- package/dist/cli/index.js +1 -1
- package/dist/core.js +2 -6
- package/dist/index.js +3 -5
- package/package.json +1 -2
- package/dist/drivers/piSdkRunner.js +0 -96
|
@@ -7,11 +7,11 @@ import {
|
|
|
7
7
|
} from "./chunk-KNMCE6WB.js";
|
|
8
8
|
|
|
9
9
|
// src/core.ts
|
|
10
|
-
import
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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:
|
|
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 =
|
|
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 {
|
|
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
|
|
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
|
|
3882
|
-
const proc = spawn6(
|
|
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:
|
|
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()
|
|
4007
|
-
const
|
|
4008
|
-
|
|
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:
|
|
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
|
|
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
|
|
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(
|
|
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 =
|
|
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
|
|
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(
|
|
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 =
|
|
5198
|
-
|
|
5199
|
-
const filePath =
|
|
5200
|
-
|
|
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 =
|
|
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(
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
6150
|
+
const fullPath = path12.join(agentDataDir, relativePath);
|
|
6553
6151
|
try {
|
|
6554
6152
|
await access(fullPath);
|
|
6555
6153
|
} catch {
|
|
6556
|
-
await mkdir(
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
7736
|
-
if (!resolved.startsWith(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 =
|
|
7745
|
-
const resolved =
|
|
7746
|
-
if (!resolved.startsWith(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 =
|
|
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 =
|
|
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(
|
|
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(
|
|
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 =
|
|
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(
|
|
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 =
|
|
8799
|
-
const relativePath =
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
9159
|
-
const lockDir =
|
|
8756
|
+
const machineDir = path13.join(rootDir, lockId);
|
|
8757
|
+
const lockDir = path13.join(machineDir, "daemon.lock");
|
|
9160
8758
|
const token = randomUUID2();
|
|
9161
|
-
|
|
8759
|
+
mkdirSync5(machineDir, { recursive: true });
|
|
9162
8760
|
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
9163
8761
|
try {
|
|
9164
|
-
|
|
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
|
-
|
|
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
|
|
9212
|
-
import
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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(
|
|
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
|
|
8978
|
+
import path15 from "path";
|
|
9381
8979
|
|
|
9382
8980
|
// src/directUploadCapability.ts
|
|
9383
|
-
function joinUrl(base,
|
|
9384
|
-
return `${base.replace(/\/+$/, "")}${
|
|
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 =
|
|
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 =
|
|
9616
|
-
if (currentFile &&
|
|
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 =
|
|
9691
|
-
return
|
|
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(
|
|
9301
|
+
await mkdir2(path15.dirname(stateFile), { recursive: true, mode: 448 });
|
|
9704
9302
|
await writeFile2(stateFile, `${JSON.stringify({
|
|
9705
|
-
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 =
|
|
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
|
|
9361
|
+
function parseDaemonCliArgs(args) {
|
|
9764
9362
|
let serverUrl = "";
|
|
9765
|
-
let apiKey =
|
|
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 =
|
|
9783
|
-
const jsPath =
|
|
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
|
|
9386
|
+
return path16.resolve(dirname, "chat-bridge.ts");
|
|
9789
9387
|
}
|
|
9790
9388
|
}
|
|
9791
9389
|
function resolveSlockCliPath(moduleUrl = import.meta.url) {
|
|
9792
|
-
const thisDir =
|
|
9793
|
-
const bundledDistPath =
|
|
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 =
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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)
|
|
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.
|
|
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
|
-
});
|