@slock-ai/daemon 0.57.2-play.20260608142014 → 0.57.3
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-JVPMCKSF.js → chunk-H2QU4LAU.js} +202 -145
- package/dist/core.js +1 -5
- package/dist/index.js +3 -5
- package/package.json +2 -2
- package/dist/drivers/piSdkRunner.js +0 -96
|
@@ -1438,9 +1438,9 @@ Error code prefixes tell you the layer:
|
|
|
1438
1438
|
function buildCredentialHygieneSection() {
|
|
1439
1439
|
return `### Credential hygiene
|
|
1440
1440
|
|
|
1441
|
-
**Never paste credentials into Slock
|
|
1441
|
+
**Never paste credentials into public Slock channels, public-channel threads, or public-channel task/attachment fields.** Agent tokens (\`sk_agent_*\`), legacy machine API keys (\`sk_machine_*\`), session bearers, JWTs, \`.env\` files, or \`credential.json\` contents must not appear in public channel chat. DMs and private channels are allowed for authorized secret handoff, but verify the audience first. If you accidentally paste one into a public channel, immediately tell the credential owner so they can rotate it.
|
|
1442
1442
|
|
|
1443
|
-
If a tool or error output contains credential-shaped strings, redact them to \`sk_agent_<redacted>\` / \`sk_machine_<redacted>\` shape before
|
|
1443
|
+
If a tool or error output contains credential-shaped strings, redact them to \`sk_agent_<redacted>\` / \`sk_machine_<redacted>\` shape before posting to a public channel.
|
|
1444
1444
|
|
|
1445
1445
|
**Profile credential resolution is strict.** When invoked as \`slock --profile <slug>\` or with \`SLOCK_PROFILE=<slug>\`, the CLI resolves credentials from \`$SLOCK_PROFILE_DIR\` \u2192 \`$SLOCK_HOME/profiles/<slug>\` \u2192 \`$HOME/.slock/profiles/<slug>\` in that order. It does **not** fall back to a different profile's credential, to an ambient user-level token, or to environment-leaked secrets \u2014 if your designated profile credential is missing or unreadable, the CLI fails closed rather than authenticating as someone else.`;
|
|
1446
1446
|
}
|
|
@@ -1808,9 +1808,9 @@ You have MCP tools from the "chat" server. Use ONLY these for communication:
|
|
|
1808
1808
|
17. **${cancelReminderCmd}** \u2014 Cancel one of your reminders by ID.`;
|
|
1809
1809
|
const credentialHygieneSection = isCli ? cliGuideSections.credentialHygiene : `### Credential hygiene
|
|
1810
1810
|
|
|
1811
|
-
**Never paste credentials into Slock
|
|
1811
|
+
**Never paste credentials into public Slock channels, public-channel threads, or public-channel task/attachment fields.** Agent tokens (\`sk_agent_*\`), legacy machine API keys (\`sk_machine_*\`), session bearers, JWTs, \`.env\` files, or \`credential.json\` contents must not appear in public channel chat. DMs and private channels are allowed for authorized secret handoff, but verify the audience first. If you accidentally paste one into a public channel, immediately tell the credential owner so they can rotate it.
|
|
1812
1812
|
|
|
1813
|
-
If a tool or error output contains credential-shaped strings, redact them to \`sk_agent_<redacted>\` / \`sk_machine_<redacted>\` shape before
|
|
1813
|
+
If a tool or error output contains credential-shaped strings, redact them to \`sk_agent_<redacted>\` / \`sk_machine_<redacted>\` shape before posting to a public channel.`;
|
|
1814
1814
|
const reminderSection = isCli ? cliGuideSections.reminders : `### Reminders
|
|
1815
1815
|
|
|
1816
1816
|
Use reminders for follow-up that depends on future state you cannot resolve now, whether user-requested or self-driven. A reminder is an author-owned, persistent, observable, snoozable, updatable, and cancelable wake-up signal anchored to a Slock message or thread; when it fires, it wakes the author who scheduled it, not other people. If anchored to a message or thread, the receipt/fire system message is visible in that surface, but wake ownership does not transfer. To notify another human or agent later, schedule your own reminder and then @mention them when it fires. Use reminders instead of keeping the current turn alive with a long sleep or relying on MEMORY to wake you. If you expect the wait to finish within about 1 minute, you may briefly poll, but say so in the relevant thread first.
|
|
@@ -2081,19 +2081,6 @@ function listLegacySlockStatePaths(slockHome = resolveSlockHome(), homeDir = os.
|
|
|
2081
2081
|
return candidates.filter((candidate) => existsSync(candidate.path));
|
|
2082
2082
|
}
|
|
2083
2083
|
|
|
2084
|
-
// src/authEnv.ts
|
|
2085
|
-
var DAEMON_API_KEY_ENV = "SLOCK_MACHINE_API_KEY";
|
|
2086
|
-
var SLOCK_AGENT_TOKEN_ENV = "SLOCK_AGENT_TOKEN";
|
|
2087
|
-
function scrubDaemonAuthEnv(env) {
|
|
2088
|
-
delete env[DAEMON_API_KEY_ENV];
|
|
2089
|
-
return env;
|
|
2090
|
-
}
|
|
2091
|
-
function scrubDaemonChildEnv(env) {
|
|
2092
|
-
delete env[DAEMON_API_KEY_ENV];
|
|
2093
|
-
delete env[SLOCK_AGENT_TOKEN_ENV];
|
|
2094
|
-
return env;
|
|
2095
|
-
}
|
|
2096
|
-
|
|
2097
2084
|
// src/agentCredentialProxy.ts
|
|
2098
2085
|
import { randomBytes } from "crypto";
|
|
2099
2086
|
import http from "http";
|
|
@@ -3580,9 +3567,7 @@ var LOOPBACK_NO_PROXY = "127.0.0.1,localhost";
|
|
|
3580
3567
|
var CLI_TRANSPORT_TRACE_DIR_ENV = "SLOCK_CLI_TRANSPORT_TRACE_DIR";
|
|
3581
3568
|
var safePathPart = (value) => value.replace(/[^a-zA-Z0-9_.-]/g, "_");
|
|
3582
3569
|
var RAW_CREDENTIAL_ENV_DENYLIST = [
|
|
3583
|
-
"
|
|
3584
|
-
"SLOCK_AGENT_CREDENTIAL_KEY",
|
|
3585
|
-
"SLOCK_AGENT_CREDENTIAL_KEY_FILE"
|
|
3570
|
+
"SLOCK_AGENT_CREDENTIAL_KEY"
|
|
3586
3571
|
];
|
|
3587
3572
|
var cachedOpencliBinPath;
|
|
3588
3573
|
function resolveOpencliBinPath() {
|
|
@@ -3797,7 +3782,7 @@ exec ${shellSingleQuote(process.execPath)} ${shellSingleQuote(opencliBinPath)} "
|
|
|
3797
3782
|
...agentCredentialProxy ? {} : { SLOCK_AGENT_TOKEN_FILE: tokenFile },
|
|
3798
3783
|
PATH: `${slockDir}${path2.delimiter}${process.env.PATH ?? ""}`
|
|
3799
3784
|
};
|
|
3800
|
-
|
|
3785
|
+
delete spawnEnv.SLOCK_AGENT_TOKEN;
|
|
3801
3786
|
for (const key of RAW_CREDENTIAL_ENV_DENYLIST) {
|
|
3802
3787
|
delete spawnEnv[key];
|
|
3803
3788
|
}
|
|
@@ -4226,7 +4211,7 @@ function resolveCommandOnWindows(command, env, execFileSyncFn, existsSyncFn) {
|
|
|
4226
4211
|
}
|
|
4227
4212
|
function resolveCommandOnPath(command, deps = {}) {
|
|
4228
4213
|
const platform = deps.platform ?? process.platform;
|
|
4229
|
-
const env =
|
|
4214
|
+
const env = withWindowsUserEnvironment(deps.env ?? process.env, deps);
|
|
4230
4215
|
const execFileSyncFn = deps.execFileSyncFn ?? execFileSync;
|
|
4231
4216
|
const existsSyncFn = deps.existsSyncFn ?? existsSync2;
|
|
4232
4217
|
if (platform === "win32") {
|
|
@@ -4252,7 +4237,7 @@ function firstExistingPath(candidates, deps = {}) {
|
|
|
4252
4237
|
return null;
|
|
4253
4238
|
}
|
|
4254
4239
|
function readCommandVersion(command, args = [], deps = {}) {
|
|
4255
|
-
const env =
|
|
4240
|
+
const env = withWindowsUserEnvironment(deps.env ?? process.env, deps);
|
|
4256
4241
|
const execFileSyncFn = deps.execFileSyncFn ?? execFileSync;
|
|
4257
4242
|
try {
|
|
4258
4243
|
const output = normalizeExecOutput(execFileSyncFn(command, [...args, "--version"], {
|
|
@@ -5606,11 +5591,11 @@ function detectCursorModels(runCommand = runCursorModelsCommand) {
|
|
|
5606
5591
|
return parseCursorModelsOutput(String(result.stdout || ""));
|
|
5607
5592
|
}
|
|
5608
5593
|
function buildCursorModelProbeEnv(deps = {}) {
|
|
5609
|
-
return
|
|
5594
|
+
return withWindowsUserEnvironment({
|
|
5610
5595
|
...deps.env ?? process.env,
|
|
5611
5596
|
FORCE_COLOR: "0",
|
|
5612
5597
|
NO_COLOR: "1"
|
|
5613
|
-
}, deps)
|
|
5598
|
+
}, deps);
|
|
5614
5599
|
}
|
|
5615
5600
|
function runCursorModelsCommand() {
|
|
5616
5601
|
return spawnSync("cursor-agent", ["models"], {
|
|
@@ -5666,7 +5651,7 @@ function resolveGeminiSpawn(commandArgs, deps = {}) {
|
|
|
5666
5651
|
}
|
|
5667
5652
|
const execFileSyncFn = deps.execFileSyncFn ?? execFileSync3;
|
|
5668
5653
|
const existsSyncFn = deps.existsSyncFn ?? existsSync4;
|
|
5669
|
-
const env =
|
|
5654
|
+
const env = deps.env ?? process.env;
|
|
5670
5655
|
const winPath = path6.win32;
|
|
5671
5656
|
let geminiEntry = null;
|
|
5672
5657
|
try {
|
|
@@ -5806,15 +5791,12 @@ var GeminiDriver = class {
|
|
|
5806
5791
|
// src/drivers/kimi.ts
|
|
5807
5792
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
5808
5793
|
import { spawn as spawn7 } from "child_process";
|
|
5809
|
-
import {
|
|
5794
|
+
import { existsSync as existsSync5, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
5810
5795
|
import os3 from "os";
|
|
5811
5796
|
import path7 from "path";
|
|
5812
5797
|
var KIMI_WIRE_PROTOCOL_VERSION = "1.3";
|
|
5813
5798
|
var KIMI_SYSTEM_PROMPT_FILE = ".slock-kimi-system.md";
|
|
5814
5799
|
var KIMI_AGENT_FILE = ".slock-kimi-agent.yaml";
|
|
5815
|
-
var KIMI_GENERATED_CONFIG_FILE = ".slock-kimi-config.toml";
|
|
5816
|
-
var SLOCK_KIMI_CONFIG_CONTENT_ENV = "SLOCK_KIMI_CONFIG_CONTENT";
|
|
5817
|
-
var SLOCK_KIMI_CONFIG_FILE_ENV = "SLOCK_KIMI_CONFIG_FILE";
|
|
5818
5800
|
function parseToolArguments(raw) {
|
|
5819
5801
|
if (typeof raw !== "string") return raw;
|
|
5820
5802
|
try {
|
|
@@ -5823,73 +5805,6 @@ function parseToolArguments(raw) {
|
|
|
5823
5805
|
return raw;
|
|
5824
5806
|
}
|
|
5825
5807
|
}
|
|
5826
|
-
function readKimiConfigSource(home = os3.homedir(), env = process.env) {
|
|
5827
|
-
const inlineConfig = env[SLOCK_KIMI_CONFIG_CONTENT_ENV];
|
|
5828
|
-
if (inlineConfig && inlineConfig.trim()) {
|
|
5829
|
-
return {
|
|
5830
|
-
raw: inlineConfig,
|
|
5831
|
-
explicitPath: null,
|
|
5832
|
-
sourcePath: SLOCK_KIMI_CONFIG_CONTENT_ENV
|
|
5833
|
-
};
|
|
5834
|
-
}
|
|
5835
|
-
const explicitPath = env[SLOCK_KIMI_CONFIG_FILE_ENV];
|
|
5836
|
-
const configPath = explicitPath && explicitPath.trim() ? explicitPath : path7.join(home, ".kimi", "config.toml");
|
|
5837
|
-
try {
|
|
5838
|
-
return {
|
|
5839
|
-
raw: readFileSync3(configPath, "utf8"),
|
|
5840
|
-
explicitPath: explicitPath && explicitPath.trim() ? explicitPath : null,
|
|
5841
|
-
sourcePath: configPath
|
|
5842
|
-
};
|
|
5843
|
-
} catch {
|
|
5844
|
-
return {
|
|
5845
|
-
raw: null,
|
|
5846
|
-
explicitPath: explicitPath && explicitPath.trim() ? explicitPath : null,
|
|
5847
|
-
sourcePath: configPath
|
|
5848
|
-
};
|
|
5849
|
-
}
|
|
5850
|
-
}
|
|
5851
|
-
function buildKimiSpawnEnv(env = process.env) {
|
|
5852
|
-
const spawnEnv = { ...env, FORCE_COLOR: "0", NO_COLOR: "1" };
|
|
5853
|
-
delete spawnEnv[SLOCK_KIMI_CONFIG_CONTENT_ENV];
|
|
5854
|
-
delete spawnEnv[SLOCK_KIMI_CONFIG_FILE_ENV];
|
|
5855
|
-
return scrubDaemonChildEnv(spawnEnv);
|
|
5856
|
-
}
|
|
5857
|
-
function buildKimiEffectiveEnv(ctx, overrideEnv) {
|
|
5858
|
-
return {
|
|
5859
|
-
...process.env,
|
|
5860
|
-
...ctx.config.envVars || {},
|
|
5861
|
-
...overrideEnv || {}
|
|
5862
|
-
};
|
|
5863
|
-
}
|
|
5864
|
-
function buildKimiLaunchOptions(ctx, opts = {}) {
|
|
5865
|
-
const env = buildKimiEffectiveEnv(ctx, opts.env);
|
|
5866
|
-
const source = readKimiConfigSource(opts.home ?? os3.homedir(), env);
|
|
5867
|
-
const args = [];
|
|
5868
|
-
let configFilePath = null;
|
|
5869
|
-
let configContent = null;
|
|
5870
|
-
if (source.explicitPath) {
|
|
5871
|
-
configFilePath = source.explicitPath;
|
|
5872
|
-
} else if (source.raw !== null && source.sourcePath === SLOCK_KIMI_CONFIG_CONTENT_ENV) {
|
|
5873
|
-
configFilePath = path7.join(ctx.workingDirectory, KIMI_GENERATED_CONFIG_FILE);
|
|
5874
|
-
configContent = source.raw;
|
|
5875
|
-
if (opts.writeGeneratedConfig !== false) {
|
|
5876
|
-
writeFileSync3(configFilePath, source.raw, { encoding: "utf8", mode: 384 });
|
|
5877
|
-
chmodSync(configFilePath, 384);
|
|
5878
|
-
}
|
|
5879
|
-
}
|
|
5880
|
-
if (configFilePath) {
|
|
5881
|
-
args.push("--config-file", configFilePath);
|
|
5882
|
-
}
|
|
5883
|
-
if (ctx.config.model && ctx.config.model !== "default") {
|
|
5884
|
-
args.push("--model", ctx.config.model);
|
|
5885
|
-
}
|
|
5886
|
-
return {
|
|
5887
|
-
args,
|
|
5888
|
-
env: buildKimiSpawnEnv(env),
|
|
5889
|
-
configFilePath,
|
|
5890
|
-
configContent
|
|
5891
|
-
};
|
|
5892
|
-
}
|
|
5893
5808
|
function resolveKimiSpawn(commandArgs, deps = {}) {
|
|
5894
5809
|
return {
|
|
5895
5810
|
command: resolveCommandOnPath("kimi", deps) ?? "kimi",
|
|
@@ -5913,25 +5828,7 @@ var KimiDriver = class {
|
|
|
5913
5828
|
};
|
|
5914
5829
|
model = {
|
|
5915
5830
|
detectedModelsVerifiedAs: "launchable",
|
|
5916
|
-
toLaunchSpec: (modelId
|
|
5917
|
-
if (!ctx) return { args: ["--model", modelId] };
|
|
5918
|
-
const launchCtx = {
|
|
5919
|
-
...ctx,
|
|
5920
|
-
config: {
|
|
5921
|
-
...ctx.config,
|
|
5922
|
-
model: modelId
|
|
5923
|
-
}
|
|
5924
|
-
};
|
|
5925
|
-
const launch = buildKimiLaunchOptions(launchCtx, {
|
|
5926
|
-
home: opts?.home,
|
|
5927
|
-
writeGeneratedConfig: false
|
|
5928
|
-
});
|
|
5929
|
-
return {
|
|
5930
|
-
args: launch.args,
|
|
5931
|
-
env: launch.env,
|
|
5932
|
-
configFiles: launch.configFilePath ? [launch.configFilePath] : void 0
|
|
5933
|
-
};
|
|
5934
|
-
}
|
|
5831
|
+
toLaunchSpec: (modelId) => ({ args: ["--model", modelId] })
|
|
5935
5832
|
};
|
|
5936
5833
|
supportsStdinNotification = true;
|
|
5937
5834
|
mcpToolPrefix = "";
|
|
@@ -5957,23 +5854,21 @@ var KimiDriver = class {
|
|
|
5957
5854
|
` system_prompt_path: ./${KIMI_SYSTEM_PROMPT_FILE}`,
|
|
5958
5855
|
""
|
|
5959
5856
|
].join("\n"), "utf8");
|
|
5960
|
-
const launch = buildKimiLaunchOptions(ctx);
|
|
5961
5857
|
const args = [
|
|
5962
5858
|
"--wire",
|
|
5963
5859
|
"--yolo",
|
|
5964
5860
|
"--agent-file",
|
|
5965
5861
|
agentFilePath,
|
|
5966
5862
|
"--session",
|
|
5967
|
-
this.sessionId
|
|
5968
|
-
...launch.args
|
|
5863
|
+
this.sessionId
|
|
5969
5864
|
];
|
|
5970
5865
|
const launchRuntimeFields = runtimeConfigToLaunchFields(ctx.config);
|
|
5971
5866
|
if (launchRuntimeFields.model && launchRuntimeFields.model !== "default") {
|
|
5972
5867
|
args.push("--model", launchRuntimeFields.model);
|
|
5973
5868
|
}
|
|
5974
5869
|
const spawnEnv = (await prepareCliTransport(ctx, { NO_COLOR: "1" })).spawnEnv;
|
|
5975
|
-
const
|
|
5976
|
-
const proc = spawn7(
|
|
5870
|
+
const launch = resolveKimiSpawn(args);
|
|
5871
|
+
const proc = spawn7(launch.command, launch.args, {
|
|
5977
5872
|
cwd: ctx.workingDirectory,
|
|
5978
5873
|
stdio: ["pipe", "pipe", "pipe"],
|
|
5979
5874
|
env: spawnEnv,
|
|
@@ -5981,7 +5876,7 @@ var KimiDriver = class {
|
|
|
5981
5876
|
// and has an 8191-character command-line limit. Kimi's official
|
|
5982
5877
|
// installer/uv entrypoint is an executable, so launch it directly and
|
|
5983
5878
|
// keep prompts on stdin / files instead of routing through cmd.exe.
|
|
5984
|
-
shell:
|
|
5879
|
+
shell: launch.shell
|
|
5985
5880
|
});
|
|
5986
5881
|
proc.stdin?.write(JSON.stringify({
|
|
5987
5882
|
jsonrpc: "2.0",
|
|
@@ -6095,9 +5990,14 @@ var KimiDriver = class {
|
|
|
6095
5990
|
return detectKimiModels();
|
|
6096
5991
|
}
|
|
6097
5992
|
};
|
|
6098
|
-
function detectKimiModels(home = os3.homedir()
|
|
6099
|
-
const
|
|
6100
|
-
|
|
5993
|
+
function detectKimiModels(home = os3.homedir()) {
|
|
5994
|
+
const configPath = path7.join(home, ".kimi", "config.toml");
|
|
5995
|
+
let raw;
|
|
5996
|
+
try {
|
|
5997
|
+
raw = readFileSync3(configPath, "utf8");
|
|
5998
|
+
} catch {
|
|
5999
|
+
return null;
|
|
6000
|
+
}
|
|
6101
6001
|
const models = [];
|
|
6102
6002
|
const sectionRe = /^\s*\[models(?:\.([^\]]+)|"\.[^"]+"|\."[^"]+")\s*\]\s*$/gm;
|
|
6103
6003
|
const lineRe = /^\s*\[models\.(.+?)\s*\]\s*$/gm;
|
|
@@ -6337,7 +6237,7 @@ function runOpenCodeModelsCommand(home, deps = {}) {
|
|
|
6337
6237
|
const platform = deps.platform ?? process.platform;
|
|
6338
6238
|
const spawnSyncFn = deps.spawnSyncFn ?? spawnSync2;
|
|
6339
6239
|
const result = spawnSyncFn("opencode", ["models"], {
|
|
6340
|
-
env:
|
|
6240
|
+
env: { ...process.env, HOME: home, FORCE_COLOR: "0", NO_COLOR: "1" },
|
|
6341
6241
|
encoding: "utf8",
|
|
6342
6242
|
timeout: 5e3,
|
|
6343
6243
|
shell: platform === "win32"
|
|
@@ -8085,6 +7985,9 @@ var STDIN_NOTIFICATION_INITIAL_DELAY_MS = 3e3;
|
|
|
8085
7985
|
var STDIN_NOTIFICATION_RETRY_DELAY_MS = 15e3;
|
|
8086
7986
|
var RUNTIME_ERROR_DELIVERY_BACKOFF_BASE_MS = 1e4;
|
|
8087
7987
|
var RUNTIME_ERROR_DELIVERY_BACKOFF_MAX_MS = 5 * 6e4;
|
|
7988
|
+
var SPAWN_FAIL_BACKOFF_BASE_MS = 1e3;
|
|
7989
|
+
var SPAWN_FAIL_BACKOFF_MAX_MS = 3e4;
|
|
7990
|
+
var SPAWN_FAIL_BACKOFF_THRESHOLD = 3;
|
|
8088
7991
|
var COMPACTION_STALE_MS = 5 * 6e4;
|
|
8089
7992
|
var RUNTIME_PROGRESS_STALE_MS = 15 * 6e4;
|
|
8090
7993
|
var DEFAULT_RUNTIME_START_TIMEOUT_MS = 2 * 6e4;
|
|
@@ -8592,6 +8495,12 @@ function summarizeCrash(code, signal) {
|
|
|
8592
8495
|
if (typeof code === "number") return `exit code ${code}`;
|
|
8593
8496
|
return "unknown exit";
|
|
8594
8497
|
}
|
|
8498
|
+
function currentErrorCandidates(ap) {
|
|
8499
|
+
return [
|
|
8500
|
+
ap.runtimeErrorSinceProgress ? ap.lastRuntimeError : null,
|
|
8501
|
+
...ap.recentDecisionStderr
|
|
8502
|
+
].filter((value) => !!value);
|
|
8503
|
+
}
|
|
8595
8504
|
function classifyTerminalFailure(ap) {
|
|
8596
8505
|
const candidates = [
|
|
8597
8506
|
ap.lastRuntimeError,
|
|
@@ -8635,21 +8544,16 @@ function isCodexProviderReconnectLog(text) {
|
|
|
8635
8544
|
function isCodexBenignTransportLog(text) {
|
|
8636
8545
|
return /Falling back from WebSockets/i.test(text);
|
|
8637
8546
|
}
|
|
8547
|
+
function isStdinClassRecoveryLine(text) {
|
|
8548
|
+
return /write_stdin failed|stdin is closed|closed for this session|session.*closed/i.test(text);
|
|
8549
|
+
}
|
|
8638
8550
|
function hasDirectStdinRecoveryEvidence(ap) {
|
|
8639
|
-
const candidates =
|
|
8640
|
-
|
|
8641
|
-
...ap.recentStderr
|
|
8642
|
-
].filter((value) => !!value);
|
|
8643
|
-
return candidates.some(
|
|
8644
|
-
(text) => /write_stdin failed|stdin is closed|closed for this session|session.*closed/i.test(text)
|
|
8645
|
-
);
|
|
8551
|
+
const candidates = currentErrorCandidates(ap);
|
|
8552
|
+
return candidates.some((text) => isStdinClassRecoveryLine(text));
|
|
8646
8553
|
}
|
|
8647
8554
|
function resumeSessionRecoveryReason(ap) {
|
|
8648
8555
|
if (!ap.sessionId) return null;
|
|
8649
|
-
const candidates =
|
|
8650
|
-
ap.lastRuntimeError,
|
|
8651
|
-
...ap.recentStderr
|
|
8652
|
-
].filter((value) => !!value);
|
|
8556
|
+
const candidates = currentErrorCandidates(ap);
|
|
8653
8557
|
if (ap.driver.id === "claude") {
|
|
8654
8558
|
return candidates.some((text) => /No conversation found with session ID/i.test(text)) ? "missing" : null;
|
|
8655
8559
|
}
|
|
@@ -8960,6 +8864,11 @@ var AgentProcessManager = class _AgentProcessManager {
|
|
|
8960
8864
|
runtimeExitTraceAttrs = /* @__PURE__ */ new WeakMap();
|
|
8961
8865
|
agentVisibleBoundaries = /* @__PURE__ */ new Map();
|
|
8962
8866
|
agentVisibleMessageIds = /* @__PURE__ */ new Map();
|
|
8867
|
+
// Spawn-fail backoff state per-agent (lifted outside AgentProcess because spawn fails
|
|
8868
|
+
// BEFORE ap exists; rate-state must persist across stop/respawn so churn can't bypass).
|
|
8869
|
+
// Explicit stop clears (fresh launch resets dedup clock — CC1 lifecycle pattern); silent
|
|
8870
|
+
// stop preserves (same-launch respawn must keep counter or churn bypasses the cap).
|
|
8871
|
+
agentSpawnFailBackoff = /* @__PURE__ */ new Map();
|
|
8963
8872
|
daemonVersion;
|
|
8964
8873
|
computerVersion;
|
|
8965
8874
|
constructor(sendToServer, daemonApiKey, opts) {
|
|
@@ -9039,6 +8948,57 @@ var AgentProcessManager = class _AgentProcessManager {
|
|
|
9039
8948
|
const id = typeof message.message_id === "string" ? message.message_id : typeof message.id === "string" ? message.id : "";
|
|
9040
8949
|
return id.length > 0 && this.getVisibleMessageIdSet(agentId, target)?.has(id) === true;
|
|
9041
8950
|
}
|
|
8951
|
+
// ----- SPAWN-FAIL BACKOFF (per-agent) ----------------------------------
|
|
8952
|
+
// Anchored at auto_restart_from_idle (apm:3596) + runtime_profile_auto_restart (apm:4137).
|
|
8953
|
+
// Threshold > 1 → first SPAWN_FAIL_BACKOFF_THRESHOLD failures behave as today (preserves
|
|
8954
|
+
// single-transient-hiccup); subsequent failure schedules a per-agent cooldown gating new
|
|
8955
|
+
// spawn attempts. Successful spawn resets state. State lives outside AgentProcess because
|
|
8956
|
+
// spawn fails BEFORE ap exists and the rate-window must persist across stop/respawn
|
|
8957
|
+
// (else stop/start churn bypasses the cap — CC1 lifecycle pattern). Never advances any
|
|
8958
|
+
// consume cursor or model-seen state (3-cursor orthogonality with CC1/CC2).
|
|
8959
|
+
getOrCreateSpawnFailBackoff(agentId) {
|
|
8960
|
+
let state = this.agentSpawnFailBackoff.get(agentId);
|
|
8961
|
+
if (!state) {
|
|
8962
|
+
state = createRuntimeErrorDeliveryBackoffState();
|
|
8963
|
+
this.agentSpawnFailBackoff.set(agentId, state);
|
|
8964
|
+
}
|
|
8965
|
+
return state;
|
|
8966
|
+
}
|
|
8967
|
+
isSpawnFailBackoffActive(agentId) {
|
|
8968
|
+
const state = this.agentSpawnFailBackoff.get(agentId);
|
|
8969
|
+
if (!state) return false;
|
|
8970
|
+
return state.untilMs > 0 && this.clockNow() < state.untilMs;
|
|
8971
|
+
}
|
|
8972
|
+
clockNow() {
|
|
8973
|
+
return Date.now();
|
|
8974
|
+
}
|
|
8975
|
+
recordSpawnFailure(agentId, reason) {
|
|
8976
|
+
const state = this.getOrCreateSpawnFailBackoff(agentId);
|
|
8977
|
+
state.attempts += 1;
|
|
8978
|
+
state.reason = reason;
|
|
8979
|
+
if (state.attempts <= SPAWN_FAIL_BACKOFF_THRESHOLD) {
|
|
8980
|
+
state.untilMs = 0;
|
|
8981
|
+
return { backoffActive: false, attempts: state.attempts, untilMs: 0 };
|
|
8982
|
+
}
|
|
8983
|
+
const exponent = Math.min(state.attempts - SPAWN_FAIL_BACKOFF_THRESHOLD, 10);
|
|
8984
|
+
const baseDelay = Math.min(SPAWN_FAIL_BACKOFF_MAX_MS, SPAWN_FAIL_BACKOFF_BASE_MS * Math.pow(2, exponent));
|
|
8985
|
+
state.untilMs = this.clockNow() + Math.floor(baseDelay);
|
|
8986
|
+
if (state.timer) clearTimeout(state.timer);
|
|
8987
|
+
state.timer = setTimeout(() => {
|
|
8988
|
+
const s = this.agentSpawnFailBackoff.get(agentId);
|
|
8989
|
+
if (s) {
|
|
8990
|
+
s.timer = null;
|
|
8991
|
+
s.untilMs = 0;
|
|
8992
|
+
}
|
|
8993
|
+
}, Math.max(1, state.untilMs - this.clockNow()));
|
|
8994
|
+
return { backoffActive: true, attempts: state.attempts, untilMs: state.untilMs };
|
|
8995
|
+
}
|
|
8996
|
+
resetSpawnFailBackoff(agentId) {
|
|
8997
|
+
const state = this.agentSpawnFailBackoff.get(agentId);
|
|
8998
|
+
if (!state) return;
|
|
8999
|
+
if (state.timer) clearTimeout(state.timer);
|
|
9000
|
+
this.agentSpawnFailBackoff.delete(agentId);
|
|
9001
|
+
}
|
|
9042
9002
|
scheduleStdinNotification(agentId, ap, delayMs) {
|
|
9043
9003
|
return ap.notifications.schedule(() => {
|
|
9044
9004
|
this.sendStdinNotification(agentId);
|
|
@@ -9893,6 +9853,8 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
9893
9853
|
recentStdout: [],
|
|
9894
9854
|
recentStderr: [],
|
|
9895
9855
|
lastRuntimeError: null,
|
|
9856
|
+
recentDecisionStderr: [],
|
|
9857
|
+
runtimeErrorSinceProgress: false,
|
|
9896
9858
|
runtimeErrorDeliveryBackoff: createRuntimeErrorDeliveryBackoffState(),
|
|
9897
9859
|
spawnError: null,
|
|
9898
9860
|
exitCode: null,
|
|
@@ -9936,6 +9898,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
9936
9898
|
if (driver.id === "codex" && isCodexProviderReconnectLog(text)) {
|
|
9937
9899
|
if (current) {
|
|
9938
9900
|
current.recentStderr = pushRecentStderr(current.recentStderr, text);
|
|
9901
|
+
current.recentDecisionStderr = pushRecentStderr(current.recentDecisionStderr, text);
|
|
9939
9902
|
}
|
|
9940
9903
|
this.recordDaemonTrace("daemon.agent.provider_reconnect", {
|
|
9941
9904
|
agentId,
|
|
@@ -9952,6 +9915,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
9952
9915
|
if (driver.id === "codex" && isCodexBenignTransportLog(text)) return;
|
|
9953
9916
|
if (current) {
|
|
9954
9917
|
current.recentStderr = pushRecentStderr(current.recentStderr, text);
|
|
9918
|
+
current.recentDecisionStderr = pushRecentStderr(current.recentDecisionStderr, text);
|
|
9955
9919
|
}
|
|
9956
9920
|
logger.error(`[Agent ${agentId} stderr]: ${text}`);
|
|
9957
9921
|
});
|
|
@@ -10442,6 +10406,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
10442
10406
|
this.activityClientSeqByAgent.delete(agentId);
|
|
10443
10407
|
this.agentVisibleBoundaries.delete(agentId);
|
|
10444
10408
|
this.agentVisibleMessageIds.delete(agentId);
|
|
10409
|
+
this.resetSpawnFailBackoff(agentId);
|
|
10445
10410
|
}
|
|
10446
10411
|
this.runtimeExitTraceAttrs.set(ap.runtime, {
|
|
10447
10412
|
stop_source: silent ? "daemon_internal" : "explicit_request",
|
|
@@ -10538,6 +10503,25 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
10538
10503
|
return true;
|
|
10539
10504
|
}
|
|
10540
10505
|
logger.info(`[Agent ${agentId}] Starting from idle state for new message`);
|
|
10506
|
+
if (this.isSpawnFailBackoffActive(agentId)) {
|
|
10507
|
+
const state = this.agentSpawnFailBackoff.get(agentId);
|
|
10508
|
+
const pending = this.startingInboxes.get(agentId) || [];
|
|
10509
|
+
pending.push(message);
|
|
10510
|
+
this.startingInboxes.set(agentId, pending);
|
|
10511
|
+
this.recordDaemonTrace("daemon.agent.delivery.routed", this.deliveryTraceAttrs(agentId, message, {
|
|
10512
|
+
outcome: "spawn_fail_cooldown_active",
|
|
10513
|
+
accepted: true,
|
|
10514
|
+
process_present: false,
|
|
10515
|
+
cached_idle_config_present: true,
|
|
10516
|
+
runtime: cached.config.runtime,
|
|
10517
|
+
session_id_present: Boolean(cached.sessionId),
|
|
10518
|
+
launchId: cached.launchId || void 0,
|
|
10519
|
+
spawn_fail_attempts: state.attempts,
|
|
10520
|
+
spawn_fail_until_ms: state.untilMs,
|
|
10521
|
+
starting_inbox_count: pending.length
|
|
10522
|
+
}));
|
|
10523
|
+
return true;
|
|
10524
|
+
}
|
|
10541
10525
|
this.idleAgentConfigs.delete(agentId);
|
|
10542
10526
|
this.recordDaemonTrace("daemon.agent.delivery.routed", this.deliveryTraceAttrs(agentId, message, {
|
|
10543
10527
|
outcome: "auto_restart_from_idle",
|
|
@@ -10548,12 +10532,33 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
10548
10532
|
session_id_present: Boolean(cached.sessionId),
|
|
10549
10533
|
launchId: cached.launchId || void 0
|
|
10550
10534
|
}));
|
|
10551
|
-
return this.startAgent(agentId, cached.config, message, void 0, void 0, cached.launchId || void 0, transientDelivery).then(() =>
|
|
10535
|
+
return this.startAgent(agentId, cached.config, message, void 0, void 0, cached.launchId || void 0, transientDelivery).then(() => {
|
|
10536
|
+
this.resetSpawnFailBackoff(agentId);
|
|
10537
|
+
return true;
|
|
10538
|
+
}, (err) => {
|
|
10552
10539
|
logger.error(`[Agent ${agentId}] Failed to auto-restart`, err);
|
|
10553
10540
|
if (this.reportRunnerCredentialMintFailure(agentId, err, cached.launchId, "idle_auto_restart")) {
|
|
10541
|
+
const report2 = this.recordSpawnFailure(agentId, "runner_credential_mint");
|
|
10542
|
+
this.recordDaemonTrace("daemon.agent.spawn.fail_backoff", {
|
|
10543
|
+
agentId,
|
|
10544
|
+
source: "idle_auto_restart",
|
|
10545
|
+
reason: "runner_credential_mint",
|
|
10546
|
+
attempts: report2.attempts,
|
|
10547
|
+
cooldown_active: report2.backoffActive,
|
|
10548
|
+
until_ms: report2.untilMs
|
|
10549
|
+
});
|
|
10554
10550
|
return false;
|
|
10555
10551
|
}
|
|
10556
10552
|
this.idleAgentConfigs.set(agentId, cached);
|
|
10553
|
+
const report = this.recordSpawnFailure(agentId, "spawn_error");
|
|
10554
|
+
this.recordDaemonTrace("daemon.agent.spawn.fail_backoff", {
|
|
10555
|
+
agentId,
|
|
10556
|
+
source: "idle_auto_restart",
|
|
10557
|
+
reason: "spawn_error",
|
|
10558
|
+
attempts: report.attempts,
|
|
10559
|
+
cooldown_active: report.backoffActive,
|
|
10560
|
+
until_ms: report.untilMs
|
|
10561
|
+
});
|
|
10557
10562
|
return false;
|
|
10558
10563
|
});
|
|
10559
10564
|
}
|
|
@@ -11028,10 +11033,35 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
11028
11033
|
const cached = this.idleAgentConfigs.get(agentId);
|
|
11029
11034
|
if (cached) {
|
|
11030
11035
|
logger.info(`[Agent ${agentId}] Starting from idle state for runtime profile ${kind} ${key}`);
|
|
11036
|
+
if (this.isSpawnFailBackoffActive(agentId)) {
|
|
11037
|
+
const state = this.agentSpawnFailBackoff.get(agentId);
|
|
11038
|
+
span.end("ok", {
|
|
11039
|
+
attrs: {
|
|
11040
|
+
outcome: "spawn_fail_cooldown_active",
|
|
11041
|
+
runtime: cached.config.runtime,
|
|
11042
|
+
launchId: cached.launchId || void 0,
|
|
11043
|
+
spawn_fail_attempts: state.attempts,
|
|
11044
|
+
spawn_fail_until_ms: state.untilMs
|
|
11045
|
+
}
|
|
11046
|
+
});
|
|
11047
|
+
return true;
|
|
11048
|
+
}
|
|
11031
11049
|
this.idleAgentConfigs.delete(agentId);
|
|
11032
|
-
return this.startAgent(agentId, cached.config, message, void 0, void 0, cached.launchId || void 0).then(() =>
|
|
11050
|
+
return this.startAgent(agentId, cached.config, message, void 0, void 0, cached.launchId || void 0).then(() => {
|
|
11051
|
+
this.resetSpawnFailBackoff(agentId);
|
|
11052
|
+
return true;
|
|
11053
|
+
}, (err) => {
|
|
11033
11054
|
logger.error(`[Agent ${agentId}] Failed to auto-restart for runtime profile notification`, err);
|
|
11034
11055
|
if (this.reportRunnerCredentialMintFailure(agentId, err, cached.launchId, "runtime_profile_auto_restart")) {
|
|
11056
|
+
const report2 = this.recordSpawnFailure(agentId, "runner_credential_mint");
|
|
11057
|
+
this.recordDaemonTrace("daemon.agent.spawn.fail_backoff", {
|
|
11058
|
+
agentId,
|
|
11059
|
+
source: "runtime_profile_auto_restart",
|
|
11060
|
+
reason: "runner_credential_mint",
|
|
11061
|
+
attempts: report2.attempts,
|
|
11062
|
+
cooldown_active: report2.backoffActive,
|
|
11063
|
+
until_ms: report2.untilMs
|
|
11064
|
+
});
|
|
11035
11065
|
span.end("error", {
|
|
11036
11066
|
attrs: {
|
|
11037
11067
|
outcome: "runner_credential_mint_failed",
|
|
@@ -11042,6 +11072,15 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
11042
11072
|
return false;
|
|
11043
11073
|
}
|
|
11044
11074
|
this.idleAgentConfigs.set(agentId, cached);
|
|
11075
|
+
const report = this.recordSpawnFailure(agentId, "spawn_error");
|
|
11076
|
+
this.recordDaemonTrace("daemon.agent.spawn.fail_backoff", {
|
|
11077
|
+
agentId,
|
|
11078
|
+
source: "runtime_profile_auto_restart",
|
|
11079
|
+
reason: "spawn_error",
|
|
11080
|
+
attempts: report.attempts,
|
|
11081
|
+
cooldown_active: report.backoffActive,
|
|
11082
|
+
until_ms: report.untilMs
|
|
11083
|
+
});
|
|
11045
11084
|
span.end("error", {
|
|
11046
11085
|
attrs: {
|
|
11047
11086
|
outcome: "restart_failed",
|
|
@@ -11635,6 +11674,21 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
11635
11674
|
}
|
|
11636
11675
|
noteRuntimeProgress(ap, eventKind) {
|
|
11637
11676
|
ap.runtimeProgress.noteRuntimeEvent(eventKind);
|
|
11677
|
+
this.invalidateRecoveryErrorView(ap);
|
|
11678
|
+
}
|
|
11679
|
+
/**
|
|
11680
|
+
* Invalidate the decision-only error view on a liveness signal. The process is
|
|
11681
|
+
* alive and has moved past any error it logged earlier in the turn, so a stale
|
|
11682
|
+
* error must not keep restarting/re-routing a recovered agent. Error-class
|
|
11683
|
+
* agnostic; a genuinely current failure re-populates the view after this point.
|
|
11684
|
+
* Called on BOTH progress paths — ordinary runtime events and
|
|
11685
|
+
* `internal_progress` (raw runtime activity that stale-recovery already treats
|
|
11686
|
+
* as liveness). `recentStderr`/`lastRuntimeError` are untouched and stay full
|
|
11687
|
+
* for diagnostics, user-facing reporting, and sticky terminal-failure gating.
|
|
11688
|
+
*/
|
|
11689
|
+
invalidateRecoveryErrorView(ap) {
|
|
11690
|
+
ap.recentDecisionStderr = [];
|
|
11691
|
+
ap.runtimeErrorSinceProgress = false;
|
|
11638
11692
|
}
|
|
11639
11693
|
recordGatedSteeringEvent(agentId, ap, event, attrs = {}) {
|
|
11640
11694
|
if (ap.runtime.descriptor.busyDelivery !== "gated") return;
|
|
@@ -11825,6 +11879,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
11825
11879
|
const terminalFailureDetail = classifyTerminalFailure(ap);
|
|
11826
11880
|
const detail = terminalFailureDetail?.detail ?? formatRuntimeStartTimeoutMessage(ap.driver.id);
|
|
11827
11881
|
ap.lastRuntimeError = detail;
|
|
11882
|
+
ap.runtimeErrorSinceProgress = true;
|
|
11828
11883
|
ap.runtimeProgress.markStale();
|
|
11829
11884
|
const staleForMs = Math.max(timeoutMs, ap.runtimeProgress.ageMs());
|
|
11830
11885
|
const diagnostic = buildRuntimeStallDiagnostic(ap, staleForMs, Math.max(1, Math.floor(staleForMs / 6e4)));
|
|
@@ -11979,6 +12034,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
11979
12034
|
}
|
|
11980
12035
|
if (event.kind === "internal_progress") {
|
|
11981
12036
|
ap.runtimeProgress.noteInternalProgress();
|
|
12037
|
+
this.invalidateRecoveryErrorView(ap);
|
|
11982
12038
|
this.clearRuntimeErrorDeliveryBackoffAfterProgress(agentId, ap, event.kind);
|
|
11983
12039
|
this.recordRuntimeTraceEvent(agentId, ap, "runtime.progress.internal_observed", {
|
|
11984
12040
|
turn_outcome: "held",
|
|
@@ -12153,7 +12209,10 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
12153
12209
|
case "error": {
|
|
12154
12210
|
this.interruptCompactionIfActive(agentId);
|
|
12155
12211
|
this.flushPendingTrajectory(agentId);
|
|
12156
|
-
if (ap)
|
|
12212
|
+
if (ap) {
|
|
12213
|
+
ap.lastRuntimeError = event.message;
|
|
12214
|
+
ap.runtimeErrorSinceProgress = true;
|
|
12215
|
+
}
|
|
12157
12216
|
let visibleErrorMessage = event.message;
|
|
12158
12217
|
if (ap) {
|
|
12159
12218
|
const runtimeErrorDiagnostics = buildRuntimeErrorDiagnosticEnvelope(event.message);
|
|
@@ -13863,7 +13922,7 @@ var DAEMON_CORE_TRACE_ATTR_CONTRACTS = {
|
|
|
13863
13922
|
spanAttrs: ["running_agents_count", "idle_agents_count"]
|
|
13864
13923
|
}
|
|
13865
13924
|
};
|
|
13866
|
-
var DAEMON_CLI_USAGE =
|
|
13925
|
+
var DAEMON_CLI_USAGE = "Usage: slock-daemon --server-url <url> --api-key <key>";
|
|
13867
13926
|
var RunnerCredentialMintError2 = class extends Error {
|
|
13868
13927
|
code;
|
|
13869
13928
|
retryable;
|
|
@@ -13899,9 +13958,9 @@ function runnerCredentialErrorDetail2(error) {
|
|
|
13899
13958
|
async function waitForRunnerCredentialRetry2() {
|
|
13900
13959
|
await new Promise((resolve) => setTimeout(resolve, RUNNER_CREDENTIAL_MINT_RETRY_DELAY_MS2));
|
|
13901
13960
|
}
|
|
13902
|
-
function parseDaemonCliArgs(args
|
|
13961
|
+
function parseDaemonCliArgs(args) {
|
|
13903
13962
|
let serverUrl = "";
|
|
13904
|
-
let apiKey =
|
|
13963
|
+
let apiKey = "";
|
|
13905
13964
|
for (let i = 0; i < args.length; i++) {
|
|
13906
13965
|
if (args[i] === "--server-url" && args[i + 1]) serverUrl = args[++i];
|
|
13907
13966
|
if (args[i] === "--api-key" && args[i + 1]) apiKey = args[++i];
|
|
@@ -14682,8 +14741,6 @@ var DaemonCore = class {
|
|
|
14682
14741
|
};
|
|
14683
14742
|
|
|
14684
14743
|
export {
|
|
14685
|
-
DAEMON_API_KEY_ENV,
|
|
14686
|
-
scrubDaemonAuthEnv,
|
|
14687
14744
|
subscribeDaemonLogs,
|
|
14688
14745
|
resolveWorkspaceDirectoryPath,
|
|
14689
14746
|
scanWorkspaceDirectories,
|
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,11 +8,9 @@ import {
|
|
|
9
8
|
resolveSlockCliPath,
|
|
10
9
|
resolveWorkspaceDirectoryPath,
|
|
11
10
|
scanWorkspaceDirectories,
|
|
12
|
-
scrubDaemonAuthEnv,
|
|
13
11
|
subscribeDaemonLogs
|
|
14
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-H2QU4LAU.js";
|
|
15
13
|
export {
|
|
16
|
-
DAEMON_API_KEY_ENV,
|
|
17
14
|
DAEMON_CLI_USAGE,
|
|
18
15
|
DaemonCore,
|
|
19
16
|
deleteWorkspaceDirectory,
|
|
@@ -23,6 +20,5 @@ export {
|
|
|
23
20
|
resolveSlockCliPath,
|
|
24
21
|
resolveWorkspaceDirectoryPath,
|
|
25
22
|
scanWorkspaceDirectories,
|
|
26
|
-
scrubDaemonAuthEnv,
|
|
27
23
|
subscribeDaemonLogs
|
|
28
24
|
};
|
package/dist/index.js
CHANGED
|
@@ -2,13 +2,11 @@
|
|
|
2
2
|
import {
|
|
3
3
|
DAEMON_CLI_USAGE,
|
|
4
4
|
DaemonCore,
|
|
5
|
-
parseDaemonCliArgs
|
|
6
|
-
|
|
7
|
-
} from "./chunk-JVPMCKSF.js";
|
|
5
|
+
parseDaemonCliArgs
|
|
6
|
+
} from "./chunk-H2QU4LAU.js";
|
|
8
7
|
|
|
9
8
|
// src/index.ts
|
|
10
|
-
var parsedArgs = parseDaemonCliArgs(process.argv.slice(2)
|
|
11
|
-
scrubDaemonAuthEnv(process.env);
|
|
9
|
+
var parsedArgs = parseDaemonCliArgs(process.argv.slice(2));
|
|
12
10
|
if (!parsedArgs) {
|
|
13
11
|
console.error(DAEMON_CLI_USAGE);
|
|
14
12
|
process.exit(1);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@slock-ai/daemon",
|
|
3
|
-
"version": "0.57.
|
|
3
|
+
"version": "0.57.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"slock-daemon": "dist/index.js"
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"prepublishOnly": "pnpm run build",
|
|
32
32
|
"typecheck": "tsc --noEmit",
|
|
33
33
|
"generate:slock-cli-guide": "tsx scripts/generate-slock-cli-guide.ts",
|
|
34
|
-
"check:slock-cli-guide-fresh": "pnpm generate:slock-cli-guide && git diff --exit-code ../../
|
|
34
|
+
"check:slock-cli-guide-fresh": "pnpm generate:slock-cli-guide && git diff --exit-code ../../manual/agent-knowledge/slock-cli-overview.md",
|
|
35
35
|
"release:patch": "npm version patch --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",
|
|
36
36
|
"release:minor": "npm version minor --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
|
"release:major": "npm version major --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",
|
|
@@ -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
|
-
});
|