@botiverse/raft-daemon 0.68.0 → 0.69.0-play.20260705140609
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-RXK2KSYW.js → chunk-HFYOYYZI.js} +334 -71
- package/dist/cli/index.js +521 -235
- package/dist/core.js +5 -1
- package/dist/{dist-Y3VRAU5E.js → dist-RD3WLJSB.js} +511 -231
- package/dist/index.js +5 -3
- package/package.json +1 -1
|
@@ -2225,7 +2225,12 @@ var agentApiIntegrationLoginResponseSchema = passthroughObject({
|
|
|
2225
2225
|
status: z2.enum(["logged_in", "already_logged_in", "approval_required"]),
|
|
2226
2226
|
service: agentApiIntegrationServiceSchema,
|
|
2227
2227
|
scopes: z2.array(z2.string()),
|
|
2228
|
-
requestId: z2.string(),
|
|
2228
|
+
requestId: z2.string().optional(),
|
|
2229
|
+
session: passthroughObject({
|
|
2230
|
+
status: z2.literal("stored"),
|
|
2231
|
+
source: z2.enum(["cache", "fresh"]),
|
|
2232
|
+
path: nullableStringSchema
|
|
2233
|
+
}).optional(),
|
|
2229
2234
|
approval: passthroughObject({
|
|
2230
2235
|
requestId: z2.string(),
|
|
2231
2236
|
target: nullableStringSchema,
|
|
@@ -3288,6 +3293,7 @@ var AGENT_ACTIVITY_DETAIL_KINDS = [
|
|
|
3288
3293
|
"compaction_stale",
|
|
3289
3294
|
"reviewing_changes",
|
|
3290
3295
|
"review_finished",
|
|
3296
|
+
"review_stale",
|
|
3291
3297
|
"runtime_reconnecting",
|
|
3292
3298
|
"runtime_error",
|
|
3293
3299
|
"runtime_crashed",
|
|
@@ -3738,6 +3744,8 @@ var DISPLAY_PLAN_CONFIG = {
|
|
|
3738
3744
|
}
|
|
3739
3745
|
};
|
|
3740
3746
|
var FREE_MONTHLY_FILE_UPLOAD_LIMIT_BYTES = 100 * 1024 * 1024;
|
|
3747
|
+
var FREE_SINGLE_FILE_UPLOAD_LIMIT_BYTES = 50 * 1024 * 1024;
|
|
3748
|
+
var PRO_SINGLE_FILE_UPLOAD_LIMIT_BYTES = 200 * 1024 * 1024;
|
|
3741
3749
|
var TRIAL_START_DATE = /* @__PURE__ */ new Date("2026-04-18T00:00:00Z");
|
|
3742
3750
|
var TRIAL_END_DATE = /* @__PURE__ */ new Date("2026-06-23T12:00:00Z");
|
|
3743
3751
|
var TRIAL_DURATION_DAYS = (TRIAL_END_DATE.getTime() - TRIAL_START_DATE.getTime()) / (24 * 60 * 60 * 1e3);
|
|
@@ -4520,7 +4528,7 @@ function buildPrompt(config, opts) {
|
|
|
4520
4528
|
const channelAwarenessSection = cliGuideSections.channelAwareness;
|
|
4521
4529
|
const thirdPartyIntegrationsSection = `### Third-party integrations
|
|
4522
4530
|
|
|
4523
|
-
If a built-in Slock app or 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 or built-in Slock app, first run \`raft integration list\` and match the app to a listed service before browsing the app. Use \`raft integration login --service <service>\` to provision or reuse your agent login for that service. If the service exposes manifest-backed HTTP API actions, prefer \`raft integration invoke --service <service> --list-actions\` and then \`raft integration invoke --service <service> --action <name>\`; the CLI
|
|
4531
|
+
If a built-in Slock app or 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 or built-in Slock app, first run \`raft integration list\` and match the app to a listed service before browsing the app. Use \`raft integration login --service <service>\` to provision or reuse your agent login for that service; the CLI consumes the one-time Agent Login handoff internally and stores the service-owned session for this agent, so the successful output should be \`Agent login ready\` / \`Already logged in\`, not a raw request code you need to keep. If the service exposes manifest-backed HTTP API actions, prefer \`raft integration invoke --service <service> --list-actions\` and then \`raft integration invoke --service <service> --action <name>\`; the CLI uses the stored service session or refreshes it internally. If the service exposes an agent behavior manifest and you need to run its local CLI, run \`raft integration env --service <service>\` before invoking that CLI; if it prints exports, apply them first so service credentials stay under a per-agent profile HOME/XDG tree instead of the host user's global HOME. If it reports that no local env is required, do not invent HOME/XDG overrides; for HTTP API action services, use \`raft integration invoke\` instead. If it fails, do not run that local CLI with the host user's HOME; report that the service manifest is unsupported. Slock does not execute local commands from remote manifests automatically. 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. Do not store or reuse raw \`oauth_access_request\` request codes; those are one-time compatibility handoffs for services to exchange once for their own session/token. Prefer \`raft integration invoke\` over manually opening or curling callback URLs. 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 outside the documented CLI flow, 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 \`raft profile show\`. Third-party pages may show \`Login with Slock\`; for agent-facing access, prefer the listed service / Slock Agent Login path.`;
|
|
4524
4532
|
const readingHistorySection = cliGuideSections.readingHistory;
|
|
4525
4533
|
const historicalReferenceSection = cliGuideSections.historicalReferences;
|
|
4526
4534
|
const tasksSection = cliGuideSections.tasks;
|
|
@@ -4708,6 +4716,19 @@ function listLegacySlockStatePaths(slockHome = resolveSlockHome(), homeDir = os.
|
|
|
4708
4716
|
return candidates.filter((candidate) => existsSync(candidate.path));
|
|
4709
4717
|
}
|
|
4710
4718
|
|
|
4719
|
+
// src/authEnv.ts
|
|
4720
|
+
var DAEMON_API_KEY_ENV = "SLOCK_MACHINE_API_KEY";
|
|
4721
|
+
var SLOCK_AGENT_TOKEN_ENV = "SLOCK_AGENT_TOKEN";
|
|
4722
|
+
function scrubDaemonAuthEnv(env) {
|
|
4723
|
+
delete env[DAEMON_API_KEY_ENV];
|
|
4724
|
+
return env;
|
|
4725
|
+
}
|
|
4726
|
+
function scrubDaemonChildEnv(env) {
|
|
4727
|
+
delete env[DAEMON_API_KEY_ENV];
|
|
4728
|
+
delete env[SLOCK_AGENT_TOKEN_ENV];
|
|
4729
|
+
return env;
|
|
4730
|
+
}
|
|
4731
|
+
|
|
4711
4732
|
// src/agentCredentialProxy.ts
|
|
4712
4733
|
import { randomBytes } from "crypto";
|
|
4713
4734
|
import http from "http";
|
|
@@ -6282,7 +6303,9 @@ var LOOPBACK_NO_PROXY = "127.0.0.1,localhost";
|
|
|
6282
6303
|
var CLI_TRANSPORT_TRACE_DIR_ENV = "SLOCK_CLI_TRANSPORT_TRACE_DIR";
|
|
6283
6304
|
var safePathPart = (value) => value.replace(/[^a-zA-Z0-9_.-]/g, "_");
|
|
6284
6305
|
var RAW_CREDENTIAL_ENV_DENYLIST = [
|
|
6285
|
-
"
|
|
6306
|
+
"SLOCK_AGENT_TOKEN",
|
|
6307
|
+
"SLOCK_AGENT_CREDENTIAL_KEY",
|
|
6308
|
+
"SLOCK_AGENT_CREDENTIAL_KEY_FILE"
|
|
6286
6309
|
];
|
|
6287
6310
|
var WORKSPACE_CLI_TRANSPORT_FILENAMES = [
|
|
6288
6311
|
"agent-token",
|
|
@@ -6637,7 +6660,7 @@ set "SLOCK_AGENT_ACTIVE_CAPABILITIES=${DEFAULT_ACTIVE_CAPABILITIES}"\r
|
|
|
6637
6660
|
SLOCK_SERVER_URL: ctx.config.serverUrl,
|
|
6638
6661
|
PATH: `${slockDir}${path2.delimiter}${process.env.PATH ?? ""}`
|
|
6639
6662
|
};
|
|
6640
|
-
|
|
6663
|
+
scrubDaemonChildEnv(spawnEnv);
|
|
6641
6664
|
for (const key of RAW_CREDENTIAL_ENV_DENYLIST) {
|
|
6642
6665
|
delete spawnEnv[key];
|
|
6643
6666
|
}
|
|
@@ -7205,7 +7228,7 @@ function requiresWindowsShell(command, platform = process.platform) {
|
|
|
7205
7228
|
}
|
|
7206
7229
|
function resolveCommandOnPath(command, deps = {}) {
|
|
7207
7230
|
const platform = deps.platform ?? process.platform;
|
|
7208
|
-
const env = withWindowsUserEnvironment(deps.env ?? process.env, deps);
|
|
7231
|
+
const env = scrubDaemonChildEnv({ ...withWindowsUserEnvironment(deps.env ?? process.env, deps) });
|
|
7209
7232
|
const execFileSyncFn = deps.execFileSyncFn ?? execFileSync;
|
|
7210
7233
|
const existsSyncFn = deps.existsSyncFn ?? existsSync3;
|
|
7211
7234
|
if (platform === "win32") {
|
|
@@ -7231,7 +7254,7 @@ function firstExistingPath(candidates, deps = {}) {
|
|
|
7231
7254
|
return null;
|
|
7232
7255
|
}
|
|
7233
7256
|
function readCommandVersion(command, args = [], deps = {}) {
|
|
7234
|
-
const env = withWindowsUserEnvironment(deps.env ?? process.env, deps);
|
|
7257
|
+
const env = scrubDaemonChildEnv({ ...withWindowsUserEnvironment(deps.env ?? process.env, deps) });
|
|
7235
7258
|
const execFileSyncFn = deps.execFileSyncFn ?? execFileSync;
|
|
7236
7259
|
try {
|
|
7237
7260
|
const output = normalizeExecOutput(execFileSyncFn(command, [...args, "--version"], {
|
|
@@ -9315,11 +9338,11 @@ function detectCursorModels(runCommand = runCursorModelsCommand) {
|
|
|
9315
9338
|
return parseCursorModelsOutput(String(result.stdout || ""));
|
|
9316
9339
|
}
|
|
9317
9340
|
function buildCursorModelProbeEnv(deps = {}) {
|
|
9318
|
-
return withWindowsUserEnvironment({
|
|
9341
|
+
return scrubDaemonChildEnv(withWindowsUserEnvironment({
|
|
9319
9342
|
...deps.env ?? process.env,
|
|
9320
9343
|
FORCE_COLOR: "0",
|
|
9321
9344
|
NO_COLOR: "1"
|
|
9322
|
-
}, deps);
|
|
9345
|
+
}, deps));
|
|
9323
9346
|
}
|
|
9324
9347
|
function runCursorModelsCommand() {
|
|
9325
9348
|
return spawnSync("cursor-agent", ["models"], {
|
|
@@ -9375,7 +9398,7 @@ function resolveGeminiSpawn(commandArgs, deps = {}) {
|
|
|
9375
9398
|
}
|
|
9376
9399
|
const execFileSyncFn = deps.execFileSyncFn ?? execFileSync3;
|
|
9377
9400
|
const existsSyncFn = deps.existsSyncFn ?? existsSync5;
|
|
9378
|
-
const env = deps.env ?? process.env;
|
|
9401
|
+
const env = scrubDaemonChildEnv({ ...deps.env ?? process.env });
|
|
9379
9402
|
const winPath = path8.win32;
|
|
9380
9403
|
let geminiEntry = null;
|
|
9381
9404
|
try {
|
|
@@ -9512,12 +9535,15 @@ var GeminiDriver = class {
|
|
|
9512
9535
|
// src/drivers/kimi.ts
|
|
9513
9536
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
9514
9537
|
import { spawn as spawn7 } from "child_process";
|
|
9515
|
-
import { existsSync as existsSync6, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
9538
|
+
import { chmodSync, existsSync as existsSync6, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
9516
9539
|
import os4 from "os";
|
|
9517
9540
|
import path9 from "path";
|
|
9518
9541
|
var KIMI_WIRE_PROTOCOL_VERSION = "1.3";
|
|
9519
9542
|
var KIMI_SYSTEM_PROMPT_FILE = ".slock-kimi-system.md";
|
|
9520
9543
|
var KIMI_AGENT_FILE = ".slock-kimi-agent.yaml";
|
|
9544
|
+
var KIMI_GENERATED_CONFIG_FILE = ".slock-kimi-config.toml";
|
|
9545
|
+
var SLOCK_KIMI_CONFIG_CONTENT_ENV = "SLOCK_KIMI_CONFIG_CONTENT";
|
|
9546
|
+
var SLOCK_KIMI_CONFIG_FILE_ENV = "SLOCK_KIMI_CONFIG_FILE";
|
|
9521
9547
|
function parseToolArguments(raw) {
|
|
9522
9548
|
if (typeof raw !== "string") return raw;
|
|
9523
9549
|
try {
|
|
@@ -9526,6 +9552,73 @@ function parseToolArguments(raw) {
|
|
|
9526
9552
|
return raw;
|
|
9527
9553
|
}
|
|
9528
9554
|
}
|
|
9555
|
+
function readKimiConfigSource(home = os4.homedir(), env = process.env) {
|
|
9556
|
+
const inlineConfig = env[SLOCK_KIMI_CONFIG_CONTENT_ENV];
|
|
9557
|
+
if (inlineConfig && inlineConfig.trim()) {
|
|
9558
|
+
return {
|
|
9559
|
+
raw: inlineConfig,
|
|
9560
|
+
explicitPath: null,
|
|
9561
|
+
sourcePath: SLOCK_KIMI_CONFIG_CONTENT_ENV
|
|
9562
|
+
};
|
|
9563
|
+
}
|
|
9564
|
+
const explicitPath = env[SLOCK_KIMI_CONFIG_FILE_ENV];
|
|
9565
|
+
const configPath = explicitPath && explicitPath.trim() ? explicitPath : path9.join(home, ".kimi", "config.toml");
|
|
9566
|
+
try {
|
|
9567
|
+
return {
|
|
9568
|
+
raw: readFileSync3(configPath, "utf8"),
|
|
9569
|
+
explicitPath: explicitPath && explicitPath.trim() ? explicitPath : null,
|
|
9570
|
+
sourcePath: configPath
|
|
9571
|
+
};
|
|
9572
|
+
} catch {
|
|
9573
|
+
return {
|
|
9574
|
+
raw: null,
|
|
9575
|
+
explicitPath: explicitPath && explicitPath.trim() ? explicitPath : null,
|
|
9576
|
+
sourcePath: configPath
|
|
9577
|
+
};
|
|
9578
|
+
}
|
|
9579
|
+
}
|
|
9580
|
+
function buildKimiSpawnEnv(env = process.env) {
|
|
9581
|
+
const spawnEnv = { ...env, FORCE_COLOR: "0", NO_COLOR: "1" };
|
|
9582
|
+
delete spawnEnv[SLOCK_KIMI_CONFIG_CONTENT_ENV];
|
|
9583
|
+
delete spawnEnv[SLOCK_KIMI_CONFIG_FILE_ENV];
|
|
9584
|
+
return scrubDaemonChildEnv(spawnEnv);
|
|
9585
|
+
}
|
|
9586
|
+
function buildKimiEffectiveEnv(ctx, overrideEnv) {
|
|
9587
|
+
return {
|
|
9588
|
+
...process.env,
|
|
9589
|
+
...ctx.config.envVars || {},
|
|
9590
|
+
...overrideEnv || {}
|
|
9591
|
+
};
|
|
9592
|
+
}
|
|
9593
|
+
function buildKimiLaunchOptions(ctx, opts = {}) {
|
|
9594
|
+
const env = buildKimiEffectiveEnv(ctx, opts.env);
|
|
9595
|
+
const source = readKimiConfigSource(opts.home ?? os4.homedir(), env);
|
|
9596
|
+
const args = [];
|
|
9597
|
+
let configFilePath = null;
|
|
9598
|
+
let configContent = null;
|
|
9599
|
+
if (source.explicitPath) {
|
|
9600
|
+
configFilePath = source.explicitPath;
|
|
9601
|
+
} else if (source.raw !== null && source.sourcePath === SLOCK_KIMI_CONFIG_CONTENT_ENV) {
|
|
9602
|
+
configFilePath = path9.join(ctx.workingDirectory, KIMI_GENERATED_CONFIG_FILE);
|
|
9603
|
+
configContent = source.raw;
|
|
9604
|
+
if (opts.writeGeneratedConfig !== false) {
|
|
9605
|
+
writeFileSync3(configFilePath, source.raw, { encoding: "utf8", mode: 384 });
|
|
9606
|
+
chmodSync(configFilePath, 384);
|
|
9607
|
+
}
|
|
9608
|
+
}
|
|
9609
|
+
if (configFilePath) {
|
|
9610
|
+
args.push("--config-file", configFilePath);
|
|
9611
|
+
}
|
|
9612
|
+
if (ctx.config.model && ctx.config.model !== "default") {
|
|
9613
|
+
args.push("--model", ctx.config.model);
|
|
9614
|
+
}
|
|
9615
|
+
return {
|
|
9616
|
+
args,
|
|
9617
|
+
env: buildKimiSpawnEnv(env),
|
|
9618
|
+
configFilePath,
|
|
9619
|
+
configContent
|
|
9620
|
+
};
|
|
9621
|
+
}
|
|
9529
9622
|
function resolveKimiSpawn(commandArgs, deps = {}) {
|
|
9530
9623
|
return {
|
|
9531
9624
|
command: resolveCommandOnPath("kimi", deps) ?? "kimi",
|
|
@@ -9549,7 +9642,25 @@ var KimiDriver = class {
|
|
|
9549
9642
|
};
|
|
9550
9643
|
model = {
|
|
9551
9644
|
detectedModelsVerifiedAs: "launchable",
|
|
9552
|
-
toLaunchSpec: (modelId) =>
|
|
9645
|
+
toLaunchSpec: (modelId, ctx, opts) => {
|
|
9646
|
+
if (!ctx) return { args: ["--model", modelId] };
|
|
9647
|
+
const launchCtx = {
|
|
9648
|
+
...ctx,
|
|
9649
|
+
config: {
|
|
9650
|
+
...ctx.config,
|
|
9651
|
+
model: modelId
|
|
9652
|
+
}
|
|
9653
|
+
};
|
|
9654
|
+
const launch = buildKimiLaunchOptions(launchCtx, {
|
|
9655
|
+
home: opts?.home,
|
|
9656
|
+
writeGeneratedConfig: false
|
|
9657
|
+
});
|
|
9658
|
+
return {
|
|
9659
|
+
args: launch.args,
|
|
9660
|
+
env: launch.env,
|
|
9661
|
+
configFiles: launch.configFilePath ? [launch.configFilePath] : void 0
|
|
9662
|
+
};
|
|
9663
|
+
}
|
|
9553
9664
|
};
|
|
9554
9665
|
supportsStdinNotification = true;
|
|
9555
9666
|
busyDeliveryMode = "direct";
|
|
@@ -9573,21 +9684,23 @@ var KimiDriver = class {
|
|
|
9573
9684
|
` system_prompt_path: ./${KIMI_SYSTEM_PROMPT_FILE}`,
|
|
9574
9685
|
""
|
|
9575
9686
|
].join("\n"), "utf8");
|
|
9687
|
+
const launch = buildKimiLaunchOptions(ctx);
|
|
9576
9688
|
const args = [
|
|
9577
9689
|
"--wire",
|
|
9578
9690
|
"--yolo",
|
|
9579
9691
|
"--agent-file",
|
|
9580
9692
|
agentFilePath,
|
|
9581
9693
|
"--session",
|
|
9582
|
-
this.sessionId
|
|
9694
|
+
this.sessionId,
|
|
9695
|
+
...launch.args
|
|
9583
9696
|
];
|
|
9584
9697
|
const launchRuntimeFields = runtimeConfigToLaunchFields(hydrateRuntimeConfig(ctx.config));
|
|
9585
9698
|
if (launchRuntimeFields.model && launchRuntimeFields.model !== "default") {
|
|
9586
9699
|
args.push("--model", launchRuntimeFields.model);
|
|
9587
9700
|
}
|
|
9588
9701
|
const spawnEnv = (await prepareCliTransport(ctx, { NO_COLOR: "1" })).spawnEnv;
|
|
9589
|
-
const
|
|
9590
|
-
const proc = spawn7(
|
|
9702
|
+
const spawnTarget = resolveKimiSpawn(args);
|
|
9703
|
+
const proc = spawn7(spawnTarget.command, spawnTarget.args, {
|
|
9591
9704
|
cwd: ctx.workingDirectory,
|
|
9592
9705
|
stdio: ["pipe", "pipe", "pipe"],
|
|
9593
9706
|
env: spawnEnv,
|
|
@@ -9595,7 +9708,7 @@ var KimiDriver = class {
|
|
|
9595
9708
|
// and has an 8191-character command-line limit. Kimi's official
|
|
9596
9709
|
// installer/uv entrypoint is an executable, so launch it directly and
|
|
9597
9710
|
// keep prompts on stdin / files instead of routing through cmd.exe.
|
|
9598
|
-
shell:
|
|
9711
|
+
shell: spawnTarget.shell
|
|
9599
9712
|
});
|
|
9600
9713
|
proc.stdin?.write(JSON.stringify({
|
|
9601
9714
|
jsonrpc: "2.0",
|
|
@@ -9708,14 +9821,9 @@ var KimiDriver = class {
|
|
|
9708
9821
|
return detectKimiModels();
|
|
9709
9822
|
}
|
|
9710
9823
|
};
|
|
9711
|
-
function detectKimiModels(home = os4.homedir()) {
|
|
9712
|
-
const
|
|
9713
|
-
|
|
9714
|
-
try {
|
|
9715
|
-
raw = readFileSync3(configPath, "utf8");
|
|
9716
|
-
} catch {
|
|
9717
|
-
return null;
|
|
9718
|
-
}
|
|
9824
|
+
function detectKimiModels(home = os4.homedir(), opts = {}) {
|
|
9825
|
+
const raw = readKimiConfigSource(home, opts.env).raw;
|
|
9826
|
+
if (raw === null) return null;
|
|
9719
9827
|
const models = [];
|
|
9720
9828
|
const sectionRe = /^\s*\[models(?:\.([^\]]+)|"\.[^"]+"|\."[^"]+")\s*\]\s*$/gm;
|
|
9721
9829
|
const lineRe = /^\s*\[models\.(.+?)\s*\]\s*$/gm;
|
|
@@ -10381,7 +10489,7 @@ function runOpenCodeModelsCommand(home, deps = {}) {
|
|
|
10381
10489
|
const platform = deps.platform ?? process.platform;
|
|
10382
10490
|
const spawnSyncFn = deps.spawnSyncFn ?? spawnSync2;
|
|
10383
10491
|
const result = spawnSyncFn("opencode", ["models"], {
|
|
10384
|
-
env: { ...process.env, HOME: home, FORCE_COLOR: "0", NO_COLOR: "1" },
|
|
10492
|
+
env: scrubDaemonChildEnv({ ...process.env, HOME: home, FORCE_COLOR: "0", NO_COLOR: "1" }),
|
|
10385
10493
|
encoding: "utf8",
|
|
10386
10494
|
timeout: 5e3,
|
|
10387
10495
|
shell: platform === "win32"
|
|
@@ -13370,24 +13478,38 @@ function safeSessionFilename(value) {
|
|
|
13370
13478
|
const normalized = value.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
13371
13479
|
return normalized || "unknown-session";
|
|
13372
13480
|
}
|
|
13373
|
-
function writeRuntimeSessionHandoff(runtime, sessionId, fallbackDir) {
|
|
13481
|
+
function writeRuntimeSessionHandoff(runtime, sessionId, fallbackDir, join, resolve) {
|
|
13374
13482
|
try {
|
|
13375
13483
|
const dir = path14.join(fallbackDir, ".slock", "runtime-sessions");
|
|
13376
13484
|
mkdirSync4(dir, { recursive: true });
|
|
13377
13485
|
const filePath = path14.join(dir, `${runtime}-${safeSessionFilename(sessionId)}.jsonl`);
|
|
13486
|
+
const searchedPaths = resolve?.searchedPaths ?? [];
|
|
13378
13487
|
writeFileSync4(filePath, JSON.stringify({
|
|
13379
13488
|
type: "runtime_session_handoff",
|
|
13380
13489
|
runtime,
|
|
13381
13490
|
sessionId,
|
|
13491
|
+
// Persisted L1<->L2 join keys (#460 V3): without these the
|
|
13492
|
+
// session->launch mapping lives only in daemon memory and old L1
|
|
13493
|
+
// transcripts can never re-join their launch after restart/adopt.
|
|
13494
|
+
// ids-only, closed fields (no content payload).
|
|
13495
|
+
launchId: join?.launchId ?? null,
|
|
13496
|
+
processInstanceId: join?.processInstanceId ?? null,
|
|
13497
|
+
// Negative-space (fruit#0 pt2): a resolve-miss is explicit evidence, not a
|
|
13498
|
+
// silent "not found". Recording the lookup method + the directories checked
|
|
13499
|
+
// makes "looked in the wrong place" distinguishable from "looked in the right
|
|
13500
|
+
// place and it is genuinely absent". ids/paths only — no transcript content.
|
|
13501
|
+
resolveStatus: "transcript_resolve_missing",
|
|
13502
|
+
lookupMethod: resolve?.lookupMethod ?? "none",
|
|
13503
|
+
searchedPaths,
|
|
13382
13504
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
13383
|
-
note: "The native runtime transcript file was not found on this machine; this daemon-created handoff records the runtime session identity for diagnostics."
|
|
13505
|
+
note: "The native runtime transcript file was not found on this machine; this daemon-created handoff records the runtime session identity + the directories checked for diagnostics."
|
|
13384
13506
|
}) + "\n", { mode: 384 });
|
|
13385
13507
|
return {
|
|
13386
13508
|
label: sessionId,
|
|
13387
13509
|
path: filePath,
|
|
13388
13510
|
runtime,
|
|
13389
13511
|
reachable: true,
|
|
13390
|
-
reason:
|
|
13512
|
+
reason: `native session file path not found; using daemon handoff file; searched=[${searchedPaths.join(", ")}]`
|
|
13391
13513
|
};
|
|
13392
13514
|
} catch {
|
|
13393
13515
|
return null;
|
|
@@ -13412,12 +13534,16 @@ function ensureRuntimeHomeDir(config, defaultHomeDir, workspacePath, opts = {})
|
|
|
13412
13534
|
function resolveRuntimeSessionRef(runtime, sessionId, homeDir = os6.homedir(), fallbackDir, opts) {
|
|
13413
13535
|
let resolvedPath = null;
|
|
13414
13536
|
let lookupMethod = "none";
|
|
13537
|
+
const searchedPaths = [];
|
|
13415
13538
|
if (runtime === "claude") {
|
|
13416
13539
|
lookupMethod = "claude_jsonl";
|
|
13417
|
-
|
|
13540
|
+
const claudeRoot = path14.join(homeDir, ".claude", "projects");
|
|
13541
|
+
searchedPaths.push(claudeRoot);
|
|
13542
|
+
resolvedPath = findSessionJsonl(claudeRoot, (filename) => filename === `${sessionId}.jsonl`);
|
|
13418
13543
|
} else if (runtime === "codex") {
|
|
13419
13544
|
lookupMethod = "codex_jsonl";
|
|
13420
13545
|
for (const root of codexSessionRootCandidates(homeDir)) {
|
|
13546
|
+
searchedPaths.push(root);
|
|
13421
13547
|
resolvedPath = findSessionJsonl(root, (filename) => filename.endsWith(".jsonl") && filename.includes(sessionId));
|
|
13422
13548
|
if (resolvedPath) break;
|
|
13423
13549
|
}
|
|
@@ -13429,7 +13555,13 @@ function resolveRuntimeSessionRef(runtime, sessionId, homeDir = os6.homedir(), f
|
|
|
13429
13555
|
resolvedPath = findPiSessionFile2(sessionId, opts?.workingDirectory, homeDir);
|
|
13430
13556
|
}
|
|
13431
13557
|
if (!resolvedPath && fallbackDir) {
|
|
13432
|
-
const fallback = writeRuntimeSessionHandoff(
|
|
13558
|
+
const fallback = writeRuntimeSessionHandoff(
|
|
13559
|
+
runtime,
|
|
13560
|
+
sessionId,
|
|
13561
|
+
fallbackDir,
|
|
13562
|
+
{ launchId: opts?.launchId, processInstanceId: opts?.processInstanceId },
|
|
13563
|
+
{ lookupMethod, searchedPaths }
|
|
13564
|
+
);
|
|
13433
13565
|
if (fallback) {
|
|
13434
13566
|
return {
|
|
13435
13567
|
...fallback,
|
|
@@ -13444,7 +13576,7 @@ function resolveRuntimeSessionRef(runtime, sessionId, homeDir = os6.homedir(), f
|
|
|
13444
13576
|
reachable: Boolean(resolvedPath)
|
|
13445
13577
|
};
|
|
13446
13578
|
if (!resolvedPath) {
|
|
13447
|
-
ref.reason = `session file path not found; attempted_lookup=${lookupMethod}`;
|
|
13579
|
+
ref.reason = `session file path not found; attempted_lookup=${lookupMethod}; searched=[${searchedPaths.join(", ")}]`;
|
|
13448
13580
|
}
|
|
13449
13581
|
return ref;
|
|
13450
13582
|
}
|
|
@@ -13560,11 +13692,12 @@ var RUNTIME_ERROR_DELIVERY_BACKOFF_MAX_MS = 5 * 6e4;
|
|
|
13560
13692
|
var RUNTIME_ERROR_FINGERPRINT_FENCE_THRESHOLD = 3;
|
|
13561
13693
|
var SPAWN_FAIL_BACKOFF_BASE_MS = 1e3;
|
|
13562
13694
|
var SPAWN_FAIL_BACKOFF_MAX_MS = 3e4;
|
|
13563
|
-
var SPAWN_FAIL_BACKOFF_THRESHOLD =
|
|
13695
|
+
var SPAWN_FAIL_BACKOFF_THRESHOLD = 0;
|
|
13564
13696
|
var RUNNER_CREDENTIAL_MINT_BACKOFF_BASE_MS = 6e4;
|
|
13565
13697
|
var RUNNER_CREDENTIAL_MINT_BACKOFF_MAX_MS = 10 * 6e4;
|
|
13566
13698
|
var RUNNER_CREDENTIAL_MINT_BACKOFF_THRESHOLD = 0;
|
|
13567
13699
|
var COMPACTION_STALE_MS = 5 * 6e4;
|
|
13700
|
+
var REVIEW_STALE_MS = 10 * 6e4;
|
|
13568
13701
|
var RUNTIME_PROGRESS_STALE_MS = 15 * 6e4;
|
|
13569
13702
|
var DEFAULT_RUNTIME_START_TIMEOUT_MS = 2 * 6e4;
|
|
13570
13703
|
var DEFAULT_STALLED_RECOVERY_SIGTERM_TIMEOUT_MS = 1e4;
|
|
@@ -14653,10 +14786,10 @@ var AgentProcessManager = class _AgentProcessManager {
|
|
|
14653
14786
|
}
|
|
14654
14787
|
// ----- SPAWN-FAIL BACKOFF (per-agent) ----------------------------------
|
|
14655
14788
|
// Anchored at auto_restart_from_idle (apm:3596) + runtime_profile_auto_restart (apm:4137).
|
|
14656
|
-
//
|
|
14657
|
-
//
|
|
14658
|
-
// inner credential-mint loop exhausted
|
|
14659
|
-
//
|
|
14789
|
+
// One outer spawn failure enters cooldown immediately so repeated wakes cannot burn one
|
|
14790
|
+
// full spawn attempt per delivery. Runner credential mint failures keep a longer cooldown
|
|
14791
|
+
// because one outer failure already means the inner credential-mint loop exhausted
|
|
14792
|
+
// RUNNER_CREDENTIAL_MINT_MAX_ATTEMPTS.
|
|
14660
14793
|
// Successful spawn resets state. State lives outside AgentProcess because spawn fails BEFORE
|
|
14661
14794
|
// ap exists and the rate-window must persist across stop/respawn (else stop/start churn
|
|
14662
14795
|
// bypasses the cap — CC1 lifecycle pattern). Never advances any consume cursor or model-seen
|
|
@@ -14809,14 +14942,22 @@ var AgentProcessManager = class _AgentProcessManager {
|
|
|
14809
14942
|
this.sendStdinNotification(agentId);
|
|
14810
14943
|
}, delayMs);
|
|
14811
14944
|
}
|
|
14812
|
-
|
|
14945
|
+
scheduleIdleInboxDeliveryRetry(agentId, ap, notificationCount, source, traceName) {
|
|
14946
|
+
if (notificationCount <= 0 || !ap.driver.supportsStdinNotification || !ap.sessionId) return false;
|
|
14947
|
+
ap.notifications.add(notificationCount);
|
|
14948
|
+
ap.notifications.clearTimer();
|
|
14949
|
+
return ap.notifications.schedule(() => {
|
|
14950
|
+
this.flushIdleInboxDeliveryRetry(agentId, source, traceName);
|
|
14951
|
+
}, this.stdinNotificationRetryMs);
|
|
14952
|
+
}
|
|
14953
|
+
flushIdleInboxDeliveryRetry(agentId, source, traceName) {
|
|
14813
14954
|
const ap = this.agents.get(agentId);
|
|
14814
14955
|
if (!ap) return false;
|
|
14815
14956
|
const count = ap.notifications.takePendingAndClearTimer();
|
|
14816
14957
|
if (count === 0) return false;
|
|
14817
14958
|
if (!ap.driver.supportsStdinNotification || !ap.sessionId || ap.inbox.length === 0) {
|
|
14818
14959
|
ap.notifications.add(count);
|
|
14819
|
-
this.recordDaemonTrace(
|
|
14960
|
+
this.recordDaemonTrace(traceName, {
|
|
14820
14961
|
agentId,
|
|
14821
14962
|
runtime: ap.config.runtime,
|
|
14822
14963
|
model: ap.config.model,
|
|
@@ -14837,7 +14978,7 @@ var AgentProcessManager = class _AgentProcessManager {
|
|
|
14837
14978
|
ap.notifications.pruneContributedToPending(ap.inbox, ap.sessionId);
|
|
14838
14979
|
const messages = ap.notifications.filterUncontributedMessages(ap.inbox, ap.sessionId);
|
|
14839
14980
|
if (messages.length === 0) {
|
|
14840
|
-
this.recordDaemonTrace(
|
|
14981
|
+
this.recordDaemonTrace(traceName, {
|
|
14841
14982
|
agentId,
|
|
14842
14983
|
runtime: ap.config.runtime,
|
|
14843
14984
|
model: ap.config.model,
|
|
@@ -14851,16 +14992,16 @@ var AgentProcessManager = class _AgentProcessManager {
|
|
|
14851
14992
|
return false;
|
|
14852
14993
|
}
|
|
14853
14994
|
this.commitApmIdleState(agentId, ap, false);
|
|
14854
|
-
this.startRuntimeTrace(agentId, ap, "
|
|
14995
|
+
this.startRuntimeTrace(agentId, ap, source.replaceAll("_", "-"), messages);
|
|
14855
14996
|
this.broadcastMessageReceivedActivity(agentId);
|
|
14856
14997
|
const accepted = this.deliverInboxUpdateViaStdin(
|
|
14857
14998
|
agentId,
|
|
14858
14999
|
ap,
|
|
14859
15000
|
messages,
|
|
14860
15001
|
"idle",
|
|
14861
|
-
|
|
15002
|
+
source
|
|
14862
15003
|
);
|
|
14863
|
-
this.recordDaemonTrace(
|
|
15004
|
+
this.recordDaemonTrace(traceName, {
|
|
14864
15005
|
agentId,
|
|
14865
15006
|
runtime: ap.config.runtime,
|
|
14866
15007
|
model: ap.config.model,
|
|
@@ -14873,6 +15014,13 @@ var AgentProcessManager = class _AgentProcessManager {
|
|
|
14873
15014
|
});
|
|
14874
15015
|
return accepted;
|
|
14875
15016
|
}
|
|
15017
|
+
flushAsyncRejectedIdleDelivery(agentId) {
|
|
15018
|
+
return this.flushIdleInboxDeliveryRetry(
|
|
15019
|
+
agentId,
|
|
15020
|
+
"async_rejected_idle_delivery_retry",
|
|
15021
|
+
"daemon.agent.stdin_delivery.async_rejected.retry"
|
|
15022
|
+
);
|
|
15023
|
+
}
|
|
14876
15024
|
isApmIdle(ap) {
|
|
14877
15025
|
return ap.gatedSteering.isIdle;
|
|
14878
15026
|
}
|
|
@@ -14936,6 +15084,7 @@ var AgentProcessManager = class _AgentProcessManager {
|
|
|
14936
15084
|
if (options.includeCompactionWatchdog ?? true) {
|
|
14937
15085
|
this.clearCompactionWatchdog(ap);
|
|
14938
15086
|
}
|
|
15087
|
+
this.clearReviewWatchdog(ap);
|
|
14939
15088
|
this.clearStalledRecoverySigtermWatchdog(ap);
|
|
14940
15089
|
}
|
|
14941
15090
|
clearRuntimeErrorDeliveryBackoffWithTrace(agentId, ap, resetSource) {
|
|
@@ -15311,7 +15460,8 @@ var AgentProcessManager = class _AgentProcessManager {
|
|
|
15311
15460
|
detailKind: activity.statusEntry.detailKind ?? "daemon_activity",
|
|
15312
15461
|
entries: activity.entries,
|
|
15313
15462
|
launchId: ap?.launchId || void 0,
|
|
15314
|
-
clientSeq: ap ? this.nextActivityClientSeq(agentId) : void 0
|
|
15463
|
+
clientSeq: ap ? this.nextActivityClientSeq(agentId) : void 0,
|
|
15464
|
+
isHeartbeat: false
|
|
15315
15465
|
});
|
|
15316
15466
|
}
|
|
15317
15467
|
recordRuntimeDiagnosticActivity(agentId, ap, event) {
|
|
@@ -15324,7 +15474,8 @@ var AgentProcessManager = class _AgentProcessManager {
|
|
|
15324
15474
|
detailKind: ap.lastActivityDetailKind || "none",
|
|
15325
15475
|
entries: [runtimeDiagnosticTrajectoryEntry(event)],
|
|
15326
15476
|
launchId: ap.launchId || void 0,
|
|
15327
|
-
clientSeq: this.nextActivityClientSeq(agentId)
|
|
15477
|
+
clientSeq: this.nextActivityClientSeq(agentId),
|
|
15478
|
+
isHeartbeat: false
|
|
15328
15479
|
});
|
|
15329
15480
|
this.recordDaemonTrace("daemon.runtime.diagnostic", {
|
|
15330
15481
|
agentId,
|
|
@@ -15375,7 +15526,8 @@ var AgentProcessManager = class _AgentProcessManager {
|
|
|
15375
15526
|
detailKind: ap.lastActivityDetailKind || "none",
|
|
15376
15527
|
entries: [runtimeRecoveryTrajectoryEntry(event)],
|
|
15377
15528
|
launchId: ap.launchId || void 0,
|
|
15378
|
-
clientSeq: this.nextActivityClientSeq(agentId)
|
|
15529
|
+
clientSeq: this.nextActivityClientSeq(agentId),
|
|
15530
|
+
isHeartbeat: false
|
|
15379
15531
|
});
|
|
15380
15532
|
this.recordDaemonTrace("daemon.runtime.recovery.visible", {
|
|
15381
15533
|
agentId,
|
|
@@ -15623,7 +15775,8 @@ var AgentProcessManager = class _AgentProcessManager {
|
|
|
15623
15775
|
this.lifecycleRecords.setRestartSnapshot(agentId, {
|
|
15624
15776
|
config: this.buildRestartSafeConfig(ap.config, nextConfigSessionId),
|
|
15625
15777
|
sessionId: nextConfigSessionId,
|
|
15626
|
-
launchId: nextLaunchId
|
|
15778
|
+
launchId: nextLaunchId,
|
|
15779
|
+
processInstanceId: ap.processInstanceId
|
|
15627
15780
|
});
|
|
15628
15781
|
this.recordStartRebind(agentId, start, reason, previousLaunchId, nextLaunchId, nextSessionId);
|
|
15629
15782
|
this.sendAgentStatus(agentId, "active", nextLaunchId);
|
|
@@ -16054,6 +16207,8 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
|
|
|
16054
16207
|
config: this.buildRestartSafeConfig(runtimeConfig, runtimeConfig.sessionId || null),
|
|
16055
16208
|
sessionId: runtimeConfig.sessionId || null,
|
|
16056
16209
|
launchId: effectiveLaunchId
|
|
16210
|
+
// No live AgentProcess in this adoption branch — omit rather than
|
|
16211
|
+
// fabricate; the marker's processInstanceId is nullable by contract.
|
|
16057
16212
|
});
|
|
16058
16213
|
this.sendAgentStatus(agentId, "active", effectiveLaunchId);
|
|
16059
16214
|
this.broadcastActivity(agentId, "online", "Process idle", [], void 0, "idle");
|
|
@@ -16112,6 +16267,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
|
|
|
16112
16267
|
readinessTransition: null,
|
|
16113
16268
|
activation: { kind: "idle" },
|
|
16114
16269
|
compaction: { kind: "none" },
|
|
16270
|
+
review: { kind: "none" },
|
|
16115
16271
|
runtimeProgress: new RuntimeProgressState(Date.now()),
|
|
16116
16272
|
runtimeTraceSpan: null,
|
|
16117
16273
|
runtimeTraceCounters: createRuntimeTraceCounters(),
|
|
@@ -16142,7 +16298,8 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
|
|
|
16142
16298
|
this.lifecycleRecords.setRestartSnapshot(agentId, {
|
|
16143
16299
|
config: this.buildRestartSafeConfig(runtimeConfig, restartSessionId),
|
|
16144
16300
|
sessionId: restartSessionId,
|
|
16145
|
-
launchId: effectiveLaunchId
|
|
16301
|
+
launchId: effectiveLaunchId,
|
|
16302
|
+
processInstanceId: agentProcess.processInstanceId
|
|
16146
16303
|
});
|
|
16147
16304
|
if (pendingStartRebind) {
|
|
16148
16305
|
this.recordStartRebind(agentId, pendingStartRebind, "startup_registered", originalLaunchId, effectiveLaunchId, agentProcess.sessionId);
|
|
@@ -16344,7 +16501,8 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
|
|
|
16344
16501
|
this.lifecycleRecords.setRestartSnapshot(agentId, {
|
|
16345
16502
|
config: nextConfig,
|
|
16346
16503
|
sessionId: ap.sessionId,
|
|
16347
|
-
launchId: ap.launchId
|
|
16504
|
+
launchId: ap.launchId,
|
|
16505
|
+
processInstanceId: ap.processInstanceId
|
|
16348
16506
|
});
|
|
16349
16507
|
this.broadcastMessageReceivedActivity(agentId);
|
|
16350
16508
|
this.lifecycleRecords.deleteRestartSnapshot(agentId);
|
|
@@ -16362,7 +16520,8 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
|
|
|
16362
16520
|
this.lifecycleRecords.setRestartSnapshot(agentId, {
|
|
16363
16521
|
config: nextConfig,
|
|
16364
16522
|
sessionId: ap.sessionId,
|
|
16365
|
-
launchId: ap.launchId
|
|
16523
|
+
launchId: ap.launchId,
|
|
16524
|
+
processInstanceId: ap.processInstanceId
|
|
16366
16525
|
});
|
|
16367
16526
|
const report = this.recordSpawnFailure(agentId, "runner_credential_mint");
|
|
16368
16527
|
this.assertStartPendingDeliveryInvariants("queued-continuation-runner-credential-mint-failure");
|
|
@@ -16382,7 +16541,8 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
|
|
|
16382
16541
|
this.lifecycleRecords.setRestartSnapshot(agentId, {
|
|
16383
16542
|
config: nextConfig,
|
|
16384
16543
|
sessionId: ap.sessionId,
|
|
16385
|
-
launchId: ap.launchId
|
|
16544
|
+
launchId: ap.launchId,
|
|
16545
|
+
processInstanceId: ap.processInstanceId
|
|
16386
16546
|
});
|
|
16387
16547
|
this.broadcastActivity(agentId, "online", "Process idle", [], void 0, "idle");
|
|
16388
16548
|
});
|
|
@@ -16391,7 +16551,8 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
|
|
|
16391
16551
|
this.lifecycleRecords.setRestartSnapshot(agentId, {
|
|
16392
16552
|
config: this.buildRestartSafeConfig(ap.config, ap.sessionId),
|
|
16393
16553
|
sessionId: ap.sessionId,
|
|
16394
|
-
launchId: ap.launchId
|
|
16554
|
+
launchId: ap.launchId,
|
|
16555
|
+
processInstanceId: ap.processInstanceId
|
|
16395
16556
|
});
|
|
16396
16557
|
if (!ap.driver.supportsStdinNotification) {
|
|
16397
16558
|
logger.info(`[Agent ${agentId}] Turn completed; cached idle state for future restart`);
|
|
@@ -16403,7 +16564,8 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
|
|
|
16403
16564
|
this.lifecycleRecords.setRestartSnapshot(agentId, {
|
|
16404
16565
|
config: this.buildRestartSafeConfig(ap.config, ap.sessionId),
|
|
16405
16566
|
sessionId: ap.sessionId,
|
|
16406
|
-
launchId: ap.launchId
|
|
16567
|
+
launchId: ap.launchId,
|
|
16568
|
+
processInstanceId: ap.processInstanceId
|
|
16407
16569
|
});
|
|
16408
16570
|
logger.warn(`[Agent ${agentId}] Recoverable provider stream failure (${reason}) \u2014 keeping agent wakeable`);
|
|
16409
16571
|
this.sendAgentStatus(agentId, "active", ap.launchId);
|
|
@@ -16619,7 +16781,8 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
|
|
|
16619
16781
|
this.lifecycleRecords.setRestartSnapshot(agentId, {
|
|
16620
16782
|
config: retryConfig,
|
|
16621
16783
|
sessionId: retrySessionId,
|
|
16622
|
-
launchId: ap.launchId
|
|
16784
|
+
launchId: ap.launchId,
|
|
16785
|
+
processInstanceId: ap.processInstanceId
|
|
16623
16786
|
});
|
|
16624
16787
|
this.recordDaemonTrace("daemon.agent.startup_timeout.retry_config_cached", {
|
|
16625
16788
|
agentId,
|
|
@@ -17533,7 +17696,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
|
|
|
17533
17696
|
}
|
|
17534
17697
|
return result;
|
|
17535
17698
|
}
|
|
17536
|
-
buildRuntimeProfileReport(agentId, config, sessionId, launchId, observedRuntimeHomeDir) {
|
|
17699
|
+
buildRuntimeProfileReport(agentId, config, sessionId, launchId, observedRuntimeHomeDir, processInstanceId) {
|
|
17537
17700
|
const workspacePath = path14.join(this.dataDir, agentId);
|
|
17538
17701
|
const runtimeHomeDir = observedRuntimeHomeDir || resolveRuntimeHomeDir(config, this.runtimeSessionHomeDir, workspacePath, { agentId, slockHome: this.slockHome });
|
|
17539
17702
|
return {
|
|
@@ -17549,7 +17712,16 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
|
|
|
17549
17712
|
path: workspacePath,
|
|
17550
17713
|
reachable: true
|
|
17551
17714
|
},
|
|
17552
|
-
sessionRef: sessionId ? resolveRuntimeSessionRef(config.runtime, sessionId, runtimeHomeDir, workspacePath, {
|
|
17715
|
+
sessionRef: sessionId ? resolveRuntimeSessionRef(config.runtime, sessionId, runtimeHomeDir, workspacePath, {
|
|
17716
|
+
agentId,
|
|
17717
|
+
workingDirectory: workspacePath,
|
|
17718
|
+
// Join keys come from the CALLER's context (running agent OR idle
|
|
17719
|
+
// restart snapshot) — reading only live state here left the
|
|
17720
|
+
// restart/adopt path writing launchId:null markers, exactly the
|
|
17721
|
+
// V3 class this exists to close (Leiysky review on #3863).
|
|
17722
|
+
launchId: launchId || void 0,
|
|
17723
|
+
processInstanceId: processInstanceId ?? this.agents.get(agentId)?.processInstanceId
|
|
17724
|
+
}) : null
|
|
17553
17725
|
}
|
|
17554
17726
|
};
|
|
17555
17727
|
}
|
|
@@ -17561,12 +17733,13 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
|
|
|
17561
17733
|
running.config,
|
|
17562
17734
|
running.sessionId,
|
|
17563
17735
|
running.launchId,
|
|
17564
|
-
running.runtime.currentRuntimeHomeDir
|
|
17736
|
+
running.runtime.currentRuntimeHomeDir,
|
|
17737
|
+
running.processInstanceId
|
|
17565
17738
|
);
|
|
17566
17739
|
}
|
|
17567
17740
|
const idle = this.lifecycleRecords.getRestartSnapshot(agentId);
|
|
17568
17741
|
if (idle) {
|
|
17569
|
-
return this.buildRuntimeProfileReport(agentId, idle.config, idle.sessionId, idle.launchId);
|
|
17742
|
+
return this.buildRuntimeProfileReport(agentId, idle.config, idle.sessionId, idle.launchId, null, idle.processInstanceId);
|
|
17570
17743
|
}
|
|
17571
17744
|
return null;
|
|
17572
17745
|
}
|
|
@@ -17964,7 +18137,9 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
|
|
|
17964
18137
|
}
|
|
17965
18138
|
const ref = resolveRuntimeSessionRef(runtime, actualSessionId, homeDir, workspaceDir, {
|
|
17966
18139
|
agentId,
|
|
17967
|
-
workingDirectory: workspaceDir
|
|
18140
|
+
workingDirectory: workspaceDir,
|
|
18141
|
+
launchId: this.agents.get(agentId)?.launchId || void 0,
|
|
18142
|
+
processInstanceId: this.agents.get(agentId)?.processInstanceId
|
|
17968
18143
|
});
|
|
17969
18144
|
const tier = runtimeTier(runtime);
|
|
17970
18145
|
const span = this.tracer.startSpan("daemon.session_transcript.read", {
|
|
@@ -18232,9 +18407,10 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
|
|
|
18232
18407
|
entries,
|
|
18233
18408
|
launchId,
|
|
18234
18409
|
clientSeq,
|
|
18235
|
-
producerFactId
|
|
18410
|
+
producerFactId,
|
|
18411
|
+
isHeartbeat: false
|
|
18236
18412
|
});
|
|
18237
|
-
this.recordActivityProducedTrace(agentId, activityKind, detail, detailKind, entries, ap, launchId, clientSeq, producerFactId);
|
|
18413
|
+
this.recordActivityProducedTrace(agentId, activityKind, detail, detailKind, entries, ap, launchId, clientSeq, producerFactId, false);
|
|
18238
18414
|
if (ap) {
|
|
18239
18415
|
ap.lastActivityKind = activityKind;
|
|
18240
18416
|
ap.lastActivity = activityDisplay;
|
|
@@ -18260,9 +18436,12 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
|
|
|
18260
18436
|
detailKind: ap.lastActivityDetailKind,
|
|
18261
18437
|
launchId: heartbeatLaunchId,
|
|
18262
18438
|
clientSeq: heartbeatClientSeq,
|
|
18263
|
-
producerFactId: heartbeatProducerFactId
|
|
18439
|
+
producerFactId: heartbeatProducerFactId,
|
|
18440
|
+
// The one knowing site: this timer re-broadcasts stale
|
|
18441
|
+
// lastActivity, so it declares its replay provenance.
|
|
18442
|
+
isHeartbeat: true
|
|
18264
18443
|
});
|
|
18265
|
-
this.recordActivityProducedTrace(agentId, ap.lastActivityKind, ap.lastActivityDetail, ap.lastActivityDetailKind, [], ap, heartbeatLaunchId, heartbeatClientSeq, heartbeatProducerFactId);
|
|
18444
|
+
this.recordActivityProducedTrace(agentId, ap.lastActivityKind, ap.lastActivityDetail, ap.lastActivityDetailKind, [], ap, heartbeatLaunchId, heartbeatClientSeq, heartbeatProducerFactId, true);
|
|
18266
18445
|
}, ACTIVITY_HEARTBEAT_MS);
|
|
18267
18446
|
ap.activityHeartbeat = { kind: "active", timer };
|
|
18268
18447
|
}
|
|
@@ -18271,7 +18450,7 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
|
|
|
18271
18450
|
}
|
|
18272
18451
|
}
|
|
18273
18452
|
}
|
|
18274
|
-
recordActivityProducedTrace(agentId, activityKind, detail, detailKind, entries, ap, launchId, clientSeq, producerFactId) {
|
|
18453
|
+
recordActivityProducedTrace(agentId, activityKind, detail, detailKind, entries, ap, launchId, clientSeq, producerFactId, isHeartbeat) {
|
|
18275
18454
|
const runtimeContext = ap?.config.runtimeContext;
|
|
18276
18455
|
this.recordDaemonTrace("daemon.agent.activity.produced", {
|
|
18277
18456
|
agentId,
|
|
@@ -18293,6 +18472,11 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
|
|
|
18293
18472
|
client_seq_present: typeof clientSeq === "number",
|
|
18294
18473
|
producerFactId,
|
|
18295
18474
|
producer_fact_id: producerFactId,
|
|
18475
|
+
// #460 V1: the wire's producer-declared replay-provenance bit must be
|
|
18476
|
+
// independently verifiable from daemon-side evidence (L2<->L3 seam);
|
|
18477
|
+
// closed boolean, mirrors the agent:activity isHeartbeat field exactly.
|
|
18478
|
+
isHeartbeat,
|
|
18479
|
+
is_heartbeat: isHeartbeat,
|
|
18296
18480
|
correlation_id: `agent:${agentId}:daemonActivity:${launchId ?? "legacy"}:${clientSeq ?? "unsequenced"}`,
|
|
18297
18481
|
session_id_present: Boolean(ap?.sessionId),
|
|
18298
18482
|
runtime: ap?.config.runtime
|
|
@@ -18341,9 +18525,10 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
|
|
|
18341
18525
|
launchId,
|
|
18342
18526
|
probeId,
|
|
18343
18527
|
clientSeq,
|
|
18344
|
-
producerFactId
|
|
18528
|
+
producerFactId,
|
|
18529
|
+
isHeartbeat: false
|
|
18345
18530
|
});
|
|
18346
|
-
this.recordActivityProducedTrace(agentId, activityKind, detail, detailKind, [], ap, launchId, clientSeq, producerFactId);
|
|
18531
|
+
this.recordActivityProducedTrace(agentId, activityKind, detail, detailKind, [], ap, launchId, clientSeq, producerFactId, false);
|
|
18347
18532
|
}
|
|
18348
18533
|
flushPendingTrajectory(agentId) {
|
|
18349
18534
|
const ap = this.agents.get(agentId);
|
|
@@ -18489,6 +18674,29 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
|
|
|
18489
18674
|
ap.compaction = { ...ap.compaction, watchdog: null };
|
|
18490
18675
|
this.broadcastActivity(agentId, "working", "Context compaction still running; no finish event observed", [], void 0, "compaction_stale");
|
|
18491
18676
|
}
|
|
18677
|
+
startReviewWatchdog(agentId, ap) {
|
|
18678
|
+
this.clearReviewWatchdog(ap);
|
|
18679
|
+
const startedAt = Date.now();
|
|
18680
|
+
const watchdog = setTimeout(() => {
|
|
18681
|
+
this.markReviewStale(agentId, startedAt);
|
|
18682
|
+
}, REVIEW_STALE_MS);
|
|
18683
|
+
ap.review = { kind: "active", startedAt, watchdog };
|
|
18684
|
+
}
|
|
18685
|
+
clearReviewWatchdog(ap) {
|
|
18686
|
+
if (ap.review.kind === "active" && ap.review.watchdog) {
|
|
18687
|
+
clearTimeout(ap.review.watchdog);
|
|
18688
|
+
}
|
|
18689
|
+
ap.review = { kind: "none" };
|
|
18690
|
+
}
|
|
18691
|
+
markReviewStale(agentId, startedAt) {
|
|
18692
|
+
const ap = this.agents.get(agentId);
|
|
18693
|
+
if (!ap || ap.review.kind !== "active" || ap.review.startedAt !== startedAt) return;
|
|
18694
|
+
ap.review = { ...ap.review, watchdog: null };
|
|
18695
|
+
this.broadcastActivity(agentId, "working", "Review mode still active; no finish event observed", [], void 0, "review_stale");
|
|
18696
|
+
const reduction = reduceApmGatedReview(ap.gatedSteering, { kind: "review_finished" });
|
|
18697
|
+
this.commitGatedSteeringDecisionState(agentId, ap, reduction.nextState, { event: "review_finished", inferred: true });
|
|
18698
|
+
this.flushReviewBoundaryMessages(agentId, ap);
|
|
18699
|
+
}
|
|
18492
18700
|
completeCompactionIfActive(agentId, detail = "Context compaction finished", options = {}) {
|
|
18493
18701
|
const ap = this.agents.get(agentId);
|
|
18494
18702
|
if (!ap || ap.compaction.kind !== "active") return;
|
|
@@ -19428,11 +19636,15 @@ Use \`raft message read\` to catch up on the channels listed above, then stop. R
|
|
|
19428
19636
|
if (ap) {
|
|
19429
19637
|
const reduction = reduceApmGatedReview(ap.gatedSteering, { kind: "review_started" });
|
|
19430
19638
|
this.commitGatedSteeringDecisionState(agentId, ap, reduction.nextState, { event: "review_started" });
|
|
19639
|
+
this.startReviewWatchdog(agentId, ap);
|
|
19431
19640
|
}
|
|
19432
19641
|
break;
|
|
19433
19642
|
case "review_finished":
|
|
19434
19643
|
this.flushPendingTrajectory(agentId);
|
|
19435
|
-
if (ap)
|
|
19644
|
+
if (ap) {
|
|
19645
|
+
this.clearReviewWatchdog(ap);
|
|
19646
|
+
this.recordRuntimeTraceEvent(agentId, ap, "runtime.review_mode.finished");
|
|
19647
|
+
}
|
|
19436
19648
|
this.broadcastActivity(agentId, "working", "Review finished", [], void 0, "review_finished");
|
|
19437
19649
|
if (ap) {
|
|
19438
19650
|
const reduction = reduceApmGatedReview(ap.gatedSteering, { kind: "review_finished" });
|
|
@@ -19953,6 +20165,15 @@ ${RESPONSE_TARGET_HINT}`;
|
|
|
19953
20165
|
`${mode} inbox update`
|
|
19954
20166
|
);
|
|
19955
20167
|
if (!sendResult.ok) {
|
|
20168
|
+
const retryNotificationCount = mode === "idle" && ap.driver.supportsStdinNotification && ap.sessionId ? messages.length : 0;
|
|
20169
|
+
const retrySource = source.endsWith("_retry") ? source : `${source}_retry`;
|
|
20170
|
+
const retryScheduled = mode === "idle" ? this.scheduleIdleInboxDeliveryRetry(
|
|
20171
|
+
agentId,
|
|
20172
|
+
ap,
|
|
20173
|
+
retryNotificationCount,
|
|
20174
|
+
retrySource,
|
|
20175
|
+
"daemon.agent.stdin_delivery.idle_retry"
|
|
20176
|
+
) : false;
|
|
19956
20177
|
if (mode === "idle") {
|
|
19957
20178
|
this.commitApmIdleState(agentId, ap, true);
|
|
19958
20179
|
}
|
|
@@ -19977,7 +20198,9 @@ ${RESPONSE_TARGET_HINT}`;
|
|
|
19977
20198
|
outcome: runtimeSendFailureOutcome(sendResult),
|
|
19978
20199
|
failure_reason: sendResult.reason,
|
|
19979
20200
|
failure_error: sendResult.error,
|
|
19980
|
-
requeued_messages_count:
|
|
20201
|
+
requeued_messages_count: retryNotificationCount,
|
|
20202
|
+
retry_scheduled: retryScheduled,
|
|
20203
|
+
notification_timer_present: ap.notifications.hasTimer,
|
|
19981
20204
|
cursors_advanced: "none"
|
|
19982
20205
|
}, "error");
|
|
19983
20206
|
return false;
|
|
@@ -20162,6 +20385,14 @@ var systemClock = {
|
|
|
20162
20385
|
clearTimeout: (timer) => clearTimeout(timer)
|
|
20163
20386
|
};
|
|
20164
20387
|
var INBOUND_WATCHDOG_MS = 7e4;
|
|
20388
|
+
function normalizeHandshakeReason(value) {
|
|
20389
|
+
const raw = Array.isArray(value) ? value[0] : value;
|
|
20390
|
+
if (typeof raw !== "string") return null;
|
|
20391
|
+
const trimmed = raw.trim();
|
|
20392
|
+
if (!trimmed) return null;
|
|
20393
|
+
if (!/^[a-z0-9_:-]{1,80}$/i.test(trimmed)) return "invalid_header";
|
|
20394
|
+
return trimmed;
|
|
20395
|
+
}
|
|
20165
20396
|
function durationMsBucket(ms) {
|
|
20166
20397
|
if (ms == null || !Number.isFinite(ms) || ms < 0) return "unknown";
|
|
20167
20398
|
if (ms === 0) return "0";
|
|
@@ -20254,6 +20485,7 @@ var DaemonConnection = class {
|
|
|
20254
20485
|
});
|
|
20255
20486
|
const ws = this.options.wsFactory ? this.options.wsFactory(wsUrl, wsOptions) : new WebSocket(wsUrl, wsOptions);
|
|
20256
20487
|
this.ws = ws;
|
|
20488
|
+
let handshakeRejected = false;
|
|
20257
20489
|
ws.on("open", () => {
|
|
20258
20490
|
if (this.ws !== ws) return;
|
|
20259
20491
|
if (!this.shouldConnect) return;
|
|
@@ -20314,8 +20546,27 @@ var DaemonConnection = class {
|
|
|
20314
20546
|
this.options.onDisconnect();
|
|
20315
20547
|
this.scheduleReconnect();
|
|
20316
20548
|
});
|
|
20549
|
+
ws.on("unexpected-response", (_request, response) => {
|
|
20550
|
+
if (this.ws !== ws) return;
|
|
20551
|
+
handshakeRejected = true;
|
|
20552
|
+
const reason = normalizeHandshakeReason(response.headers["slock-reason"]);
|
|
20553
|
+
const statusCode = response.statusCode ?? 0;
|
|
20554
|
+
const reasonText = reason ? `, slock_reason=${reason}` : "";
|
|
20555
|
+
logger.error(`[Daemon] WebSocket handshake rejected (status=${statusCode}${reasonText})`);
|
|
20556
|
+
this.trace("daemon.connection.handshake_rejected", {
|
|
20557
|
+
status_code: statusCode,
|
|
20558
|
+
slock_reason_present: Boolean(reason),
|
|
20559
|
+
slock_reason: reason
|
|
20560
|
+
}, "error");
|
|
20561
|
+
response.resume();
|
|
20562
|
+
try {
|
|
20563
|
+
ws.terminate();
|
|
20564
|
+
} catch {
|
|
20565
|
+
}
|
|
20566
|
+
});
|
|
20317
20567
|
ws.on("error", (err) => {
|
|
20318
20568
|
if (this.ws !== ws) return;
|
|
20569
|
+
if (handshakeRejected) return;
|
|
20319
20570
|
logger.error(`[Daemon] WebSocket error: ${err.message}`);
|
|
20320
20571
|
this.trace("daemon.connection.error", {
|
|
20321
20572
|
error_class: err.name || "Error"
|
|
@@ -21324,7 +21575,17 @@ var DAEMON_CORE_TRACE_ATTR_CONTRACTS = {
|
|
|
21324
21575
|
spanAttrs: ["running_agents_count", "idle_agents_count"]
|
|
21325
21576
|
},
|
|
21326
21577
|
"daemon.agent.activity.produced": {
|
|
21327
|
-
|
|
21578
|
+
// isHeartbeat/is_heartbeat (#460 V1) and process_instance_id (#460 V3)
|
|
21579
|
+
// were emitted by agentProcessManager but scrubbed here (pilot violation
|
|
21580
|
+
// V4): this list is a RUNTIME allowlist (SpanAttrContractTracer), so an
|
|
21581
|
+
// emission-site key that is not added here silently dies before disk.
|
|
21582
|
+
// Witness for the pair lives in agentProcessManager.builtin.e2e.test.ts
|
|
21583
|
+
// behind a contract-wrapped tracer (production-isomorphic oracle).
|
|
21584
|
+
// producerFactId/producer_fact_id and activity_kind/detail_kind are ALSO
|
|
21585
|
+
// emitted-and-scrubbed today; deliberately NOT added here — banned-join-
|
|
21586
|
+
// key discipline for the fact id (#460 classification ruling) means
|
|
21587
|
+
// widening needs its own ruling, not a drive-by.
|
|
21588
|
+
spanAttrs: ["agentId", "agent_id", "server_id", "machine_id", "activity", "detail_present", "entry_kinds", "ap_present", "launchId", "launch_id", "launch_id_present", "clientSeq", "client_seq", "client_seq_present", "correlation_id", "session_id_present", "runtime", "isHeartbeat", "is_heartbeat", "process_instance_id"]
|
|
21328
21589
|
},
|
|
21329
21590
|
"daemon.agent.activity.skipped": {
|
|
21330
21591
|
spanAttrs: ["agentId", "event_kind", "reason", "text_length"]
|
|
@@ -21333,7 +21594,7 @@ var DAEMON_CORE_TRACE_ATTR_CONTRACTS = {
|
|
|
21333
21594
|
spanAttrs: ["agentId", "event_kind", "runtime"]
|
|
21334
21595
|
}
|
|
21335
21596
|
};
|
|
21336
|
-
var DAEMON_CLI_USAGE =
|
|
21597
|
+
var DAEMON_CLI_USAGE = `Usage: slock-daemon --server-url <url> (--api-key <key> or ${DAEMON_API_KEY_ENV}=<key>)`;
|
|
21337
21598
|
var RunnerCredentialMintError2 = class extends Error {
|
|
21338
21599
|
code;
|
|
21339
21600
|
retryable;
|
|
@@ -21369,9 +21630,9 @@ function runnerCredentialErrorDetail2(error) {
|
|
|
21369
21630
|
async function waitForRunnerCredentialRetry2() {
|
|
21370
21631
|
await new Promise((resolve) => setTimeout(resolve, RUNNER_CREDENTIAL_MINT_RETRY_DELAY_MS2));
|
|
21371
21632
|
}
|
|
21372
|
-
function parseDaemonCliArgs(args) {
|
|
21633
|
+
function parseDaemonCliArgs(args, env = {}) {
|
|
21373
21634
|
let serverUrl = "";
|
|
21374
|
-
let apiKey = "";
|
|
21635
|
+
let apiKey = env[DAEMON_API_KEY_ENV] ?? "";
|
|
21375
21636
|
for (let i = 0; i < args.length; i++) {
|
|
21376
21637
|
if (args[i] === "--server-url" && args[i + 1]) serverUrl = args[++i];
|
|
21377
21638
|
if (args[i] === "--api-key" && args[i + 1]) apiKey = args[++i];
|
|
@@ -21408,7 +21669,7 @@ function resolveSlockCliPathOrEmpty(moduleUrl = import.meta.url) {
|
|
|
21408
21669
|
}
|
|
21409
21670
|
async function runBundledSlockCli(argv) {
|
|
21410
21671
|
process.argv = [process.execPath, "slock", ...argv];
|
|
21411
|
-
await import("./dist-
|
|
21672
|
+
await import("./dist-RD3WLJSB.js");
|
|
21412
21673
|
}
|
|
21413
21674
|
function detectRuntimes(tracer = noopTracer) {
|
|
21414
21675
|
const ids = [];
|
|
@@ -22350,6 +22611,8 @@ var DaemonCore = class {
|
|
|
22350
22611
|
|
|
22351
22612
|
export {
|
|
22352
22613
|
subscribeDaemonLogs,
|
|
22614
|
+
DAEMON_API_KEY_ENV,
|
|
22615
|
+
scrubDaemonAuthEnv,
|
|
22353
22616
|
resolveWorkspaceDirectoryPath,
|
|
22354
22617
|
scanWorkspaceDirectories,
|
|
22355
22618
|
deleteWorkspaceDirectory,
|