@botiverse/raft-daemon 0.62.0 → 0.63.1-play.20260619141001
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.
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/core.ts
|
|
2
|
-
import
|
|
3
|
-
import
|
|
2
|
+
import path18 from "path";
|
|
3
|
+
import os9 from "os";
|
|
4
4
|
import { createRequire as createRequire3 } from "module";
|
|
5
5
|
import { accessSync } from "fs";
|
|
6
6
|
import { fileURLToPath } from "url";
|
|
@@ -1602,9 +1602,9 @@ var FREE_MONTHLY_FILE_UPLOAD_LIMIT_BYTES = 100 * 1024 * 1024;
|
|
|
1602
1602
|
import { existsSync as existsSync9, mkdirSync as mkdirSync5, readFileSync as readFileSync6, readdirSync as readdirSync3, statSync, writeFileSync as writeFileSync4 } from "fs";
|
|
1603
1603
|
import { mkdir, writeFile, access, readdir as readdir2, stat as stat2, readFile, rm as rm2, lstat, realpath, open } from "fs/promises";
|
|
1604
1604
|
import { createHash as createHash3, randomUUID as randomUUID5 } from "crypto";
|
|
1605
|
-
import
|
|
1605
|
+
import path14 from "path";
|
|
1606
1606
|
import { gzipSync } from "zlib";
|
|
1607
|
-
import
|
|
1607
|
+
import os7 from "os";
|
|
1608
1608
|
|
|
1609
1609
|
// src/proxy.ts
|
|
1610
1610
|
import { HttpsProxyAgent } from "https-proxy-agent";
|
|
@@ -1873,8 +1873,8 @@ async function executeResponseRequest(url, init, {
|
|
|
1873
1873
|
}
|
|
1874
1874
|
|
|
1875
1875
|
// src/directUploadCapability.ts
|
|
1876
|
-
function joinUrl(base,
|
|
1877
|
-
return `${base.replace(/\/+$/, "")}${
|
|
1876
|
+
function joinUrl(base, path19) {
|
|
1877
|
+
return `${base.replace(/\/+$/, "")}${path19}`;
|
|
1878
1878
|
}
|
|
1879
1879
|
function jsonHeaders(apiKey) {
|
|
1880
1880
|
return {
|
|
@@ -2582,6 +2582,19 @@ function listLegacySlockStatePaths(slockHome = resolveSlockHome(), homeDir = os.
|
|
|
2582
2582
|
return candidates.filter((candidate) => existsSync(candidate.path));
|
|
2583
2583
|
}
|
|
2584
2584
|
|
|
2585
|
+
// src/authEnv.ts
|
|
2586
|
+
var DAEMON_API_KEY_ENV = "SLOCK_MACHINE_API_KEY";
|
|
2587
|
+
var SLOCK_AGENT_TOKEN_ENV = "SLOCK_AGENT_TOKEN";
|
|
2588
|
+
function scrubDaemonAuthEnv(env) {
|
|
2589
|
+
delete env[DAEMON_API_KEY_ENV];
|
|
2590
|
+
return env;
|
|
2591
|
+
}
|
|
2592
|
+
function scrubDaemonChildEnv(env) {
|
|
2593
|
+
delete env[DAEMON_API_KEY_ENV];
|
|
2594
|
+
delete env[SLOCK_AGENT_TOKEN_ENV];
|
|
2595
|
+
return env;
|
|
2596
|
+
}
|
|
2597
|
+
|
|
2585
2598
|
// src/agentCredentialProxy.ts
|
|
2586
2599
|
import { randomBytes } from "crypto";
|
|
2587
2600
|
import http from "http";
|
|
@@ -3024,7 +3037,7 @@ function projectApmRuntimeStallDiagnostic(input) {
|
|
|
3024
3037
|
gatedPhase: input.runtimeDescriptorBusyDelivery === "gated" ? input.gatedPhase : void 0,
|
|
3025
3038
|
outstandingToolUses: input.outstandingToolUses,
|
|
3026
3039
|
compacting: input.compacting,
|
|
3027
|
-
|
|
3040
|
+
...input.reviewing === true ? { reviewing: true } : {},
|
|
3028
3041
|
recentStderrCount: input.recentStderrCount,
|
|
3029
3042
|
recentStdoutCount: input.recentStdoutCount,
|
|
3030
3043
|
...input.runtimeTraceCounterAttrs ?? {}
|
|
@@ -4148,7 +4161,20 @@ var LOOPBACK_NO_PROXY = "127.0.0.1,localhost";
|
|
|
4148
4161
|
var CLI_TRANSPORT_TRACE_DIR_ENV = "SLOCK_CLI_TRANSPORT_TRACE_DIR";
|
|
4149
4162
|
var safePathPart = (value) => value.replace(/[^a-zA-Z0-9_.-]/g, "_");
|
|
4150
4163
|
var RAW_CREDENTIAL_ENV_DENYLIST = [
|
|
4151
|
-
"
|
|
4164
|
+
"SLOCK_AGENT_TOKEN",
|
|
4165
|
+
"SLOCK_AGENT_CREDENTIAL_KEY",
|
|
4166
|
+
"SLOCK_AGENT_CREDENTIAL_KEY_FILE"
|
|
4167
|
+
];
|
|
4168
|
+
var WORKSPACE_CLI_TRANSPORT_FILENAMES = [
|
|
4169
|
+
"agent-token",
|
|
4170
|
+
"slock",
|
|
4171
|
+
"slock.cmd",
|
|
4172
|
+
"slock.ps1",
|
|
4173
|
+
"raft",
|
|
4174
|
+
"raft.cmd",
|
|
4175
|
+
"raft.ps1",
|
|
4176
|
+
"opencli",
|
|
4177
|
+
"opencli.cmd"
|
|
4152
4178
|
];
|
|
4153
4179
|
function deriveCliFallbackCandidates(cliPath) {
|
|
4154
4180
|
if (!cliPath || cliPath === "__cli") return [];
|
|
@@ -4210,6 +4236,18 @@ function resolveOpencliBinPath() {
|
|
|
4210
4236
|
return null;
|
|
4211
4237
|
}
|
|
4212
4238
|
}
|
|
4239
|
+
function buildCliTransportDir(slockHome, agentId, launchId) {
|
|
4240
|
+
return path2.join(slockHome, "cli-transport", safePathPart(agentId), buildCliTransportLaunchPart(launchId));
|
|
4241
|
+
}
|
|
4242
|
+
function buildCliTransportLaunchPart(launchId) {
|
|
4243
|
+
return safePathPart(launchId || `pid-${process.pid}`);
|
|
4244
|
+
}
|
|
4245
|
+
function cleanupWorkspaceCliTransportFiles(workingDirectory) {
|
|
4246
|
+
const legacySlockDir = path2.join(workingDirectory, ".slock");
|
|
4247
|
+
for (const filename of WORKSPACE_CLI_TRANSPORT_FILENAMES) {
|
|
4248
|
+
rmSync(path2.join(legacySlockDir, filename), { force: true });
|
|
4249
|
+
}
|
|
4250
|
+
}
|
|
4213
4251
|
function writeOpencliWrapper(slockDir, opencliBinPath, platform = process.platform) {
|
|
4214
4252
|
const fallbacks = deriveOpencliFallbackCandidates(opencliBinPath);
|
|
4215
4253
|
let binPath = opencliBinPath;
|
|
@@ -4340,9 +4378,10 @@ async function prepareCliTransport(ctx, extraEnv = {}, platform = process.platfo
|
|
|
4340
4378
|
);
|
|
4341
4379
|
}
|
|
4342
4380
|
}
|
|
4343
|
-
const
|
|
4381
|
+
const slockHome = ctx.slockHome ? path2.resolve(ctx.slockHome) : resolveSlockHome();
|
|
4382
|
+
cleanupWorkspaceCliTransportFiles(ctx.workingDirectory);
|
|
4383
|
+
const slockDir = buildCliTransportDir(slockHome, ctx.agentId, ctx.launchId);
|
|
4344
4384
|
mkdirSync(slockDir, { recursive: true });
|
|
4345
|
-
const slockHome = resolveSlockHome();
|
|
4346
4385
|
const tokenFile = path2.join(slockDir, "agent-token");
|
|
4347
4386
|
const agentCredentialKey = ctx.config.agentCredentialKey;
|
|
4348
4387
|
let agentCredentialProxy = null;
|
|
@@ -4357,7 +4396,7 @@ async function prepareCliTransport(ctx, extraEnv = {}, platform = process.platfo
|
|
|
4357
4396
|
activeCapabilities: DEFAULT_ACTIVE_CAPABILITIES,
|
|
4358
4397
|
inboxCoordinator: ctx.agentCredentialProxyInboxCoordinator
|
|
4359
4398
|
});
|
|
4360
|
-
const launchPart =
|
|
4399
|
+
const launchPart = buildCliTransportLaunchPart(ctx.launchId);
|
|
4361
4400
|
const proxyTokenDir = path2.join(slockHome, "agent-proxy-tokens", safePathPart(ctx.agentId));
|
|
4362
4401
|
mkdirSync(proxyTokenDir, { recursive: true, mode: 448 });
|
|
4363
4402
|
agentCredentialProxyTokenFile = path2.join(proxyTokenDir, `${launchPart}.token`);
|
|
@@ -4474,10 +4513,9 @@ set "SLOCK_AGENT_ACTIVE_CAPABILITIES=${DEFAULT_ACTIVE_CAPABILITIES}"\r
|
|
|
4474
4513
|
...ctx.launchId ? { SLOCK_AGENT_LAUNCH_ID: ctx.launchId } : {},
|
|
4475
4514
|
...ctx.cliTransportTraceDir ? { [CLI_TRANSPORT_TRACE_DIR_ENV]: ctx.cliTransportTraceDir } : {},
|
|
4476
4515
|
SLOCK_SERVER_URL: ctx.config.serverUrl,
|
|
4477
|
-
...agentCredentialProxy ? {} : { SLOCK_AGENT_TOKEN_FILE: tokenFile },
|
|
4478
4516
|
PATH: `${slockDir}${path2.delimiter}${process.env.PATH ?? ""}`
|
|
4479
4517
|
};
|
|
4480
|
-
|
|
4518
|
+
scrubDaemonChildEnv(spawnEnv);
|
|
4481
4519
|
for (const key of RAW_CREDENTIAL_ENV_DENYLIST) {
|
|
4482
4520
|
delete spawnEnv[key];
|
|
4483
4521
|
}
|
|
@@ -4485,9 +4523,7 @@ set "SLOCK_AGENT_ACTIVE_CAPABILITIES=${DEFAULT_ACTIVE_CAPABILITIES}"\r
|
|
|
4485
4523
|
delete spawnEnv.SLOCK_AGENT_PROXY_TOKEN;
|
|
4486
4524
|
delete spawnEnv.SLOCK_AGENT_PROXY_TOKEN_FILE;
|
|
4487
4525
|
delete spawnEnv.SLOCK_AGENT_ACTIVE_CAPABILITIES;
|
|
4488
|
-
|
|
4489
|
-
delete spawnEnv.SLOCK_AGENT_TOKEN_FILE;
|
|
4490
|
-
}
|
|
4526
|
+
delete spawnEnv.SLOCK_AGENT_TOKEN_FILE;
|
|
4491
4527
|
return {
|
|
4492
4528
|
slockDir,
|
|
4493
4529
|
tokenFile,
|
|
@@ -4912,7 +4948,7 @@ function requiresWindowsShell(command, platform = process.platform) {
|
|
|
4912
4948
|
}
|
|
4913
4949
|
function resolveCommandOnPath(command, deps = {}) {
|
|
4914
4950
|
const platform = deps.platform ?? process.platform;
|
|
4915
|
-
const env = withWindowsUserEnvironment(deps.env ?? process.env, deps);
|
|
4951
|
+
const env = scrubDaemonChildEnv({ ...withWindowsUserEnvironment(deps.env ?? process.env, deps) });
|
|
4916
4952
|
const execFileSyncFn = deps.execFileSyncFn ?? execFileSync;
|
|
4917
4953
|
const existsSyncFn = deps.existsSyncFn ?? existsSync3;
|
|
4918
4954
|
if (platform === "win32") {
|
|
@@ -4938,7 +4974,7 @@ function firstExistingPath(candidates, deps = {}) {
|
|
|
4938
4974
|
return null;
|
|
4939
4975
|
}
|
|
4940
4976
|
function readCommandVersion(command, args = [], deps = {}) {
|
|
4941
|
-
const env = withWindowsUserEnvironment(deps.env ?? process.env, deps);
|
|
4977
|
+
const env = scrubDaemonChildEnv({ ...withWindowsUserEnvironment(deps.env ?? process.env, deps) });
|
|
4942
4978
|
const execFileSyncFn = deps.execFileSyncFn ?? execFileSync;
|
|
4943
4979
|
try {
|
|
4944
4980
|
const output = normalizeExecOutput(execFileSyncFn(command, [...args, "--version"], {
|
|
@@ -5177,8 +5213,47 @@ var ClaudeDriver = class {
|
|
|
5177
5213
|
// src/drivers/codex.ts
|
|
5178
5214
|
import { spawn as spawn2, execFileSync as execFileSync2 } from "child_process";
|
|
5179
5215
|
import { existsSync as existsSync5, readFileSync as readFileSync2 } from "fs";
|
|
5216
|
+
import os4 from "os";
|
|
5217
|
+
import path7 from "path";
|
|
5218
|
+
|
|
5219
|
+
// src/drivers/codexHome.ts
|
|
5180
5220
|
import os3 from "os";
|
|
5181
5221
|
import path6 from "path";
|
|
5222
|
+
function readConfiguredCodexHome(env) {
|
|
5223
|
+
const raw = env.CODEX_HOME;
|
|
5224
|
+
return typeof raw === "string" && raw.trim().length > 0 ? raw : null;
|
|
5225
|
+
}
|
|
5226
|
+
function resolveCodexHomeRootFromEnv(env = process.env, opts = {}) {
|
|
5227
|
+
const raw = readConfiguredCodexHome(env);
|
|
5228
|
+
if (raw) {
|
|
5229
|
+
return path6.resolve(opts.cwd ?? process.cwd(), raw);
|
|
5230
|
+
}
|
|
5231
|
+
return path6.join(opts.defaultHomeDir ?? os3.homedir(), ".codex");
|
|
5232
|
+
}
|
|
5233
|
+
function hasConfiguredCodexHome(config, baseEnv = process.env) {
|
|
5234
|
+
const launchRuntimeFields = config ? runtimeConfigToLaunchFields(config) : null;
|
|
5235
|
+
return Boolean(readConfiguredCodexHome({
|
|
5236
|
+
...baseEnv,
|
|
5237
|
+
...launchRuntimeFields?.envVars || {}
|
|
5238
|
+
}));
|
|
5239
|
+
}
|
|
5240
|
+
function resolveCodexHomeRootFromConfig(config, defaultHomeDir, cwd, baseEnv = process.env, _opts = {}) {
|
|
5241
|
+
const launchRuntimeFields = runtimeConfigToLaunchFields(config);
|
|
5242
|
+
const env = {
|
|
5243
|
+
...baseEnv,
|
|
5244
|
+
...launchRuntimeFields.envVars || {}
|
|
5245
|
+
};
|
|
5246
|
+
return resolveCodexHomeRootFromEnv(env, { defaultHomeDir, cwd });
|
|
5247
|
+
}
|
|
5248
|
+
function codexStateRootCandidates(homeDirOrCodexRoot) {
|
|
5249
|
+
return [
|
|
5250
|
+
homeDirOrCodexRoot,
|
|
5251
|
+
path6.join(homeDirOrCodexRoot, ".codex")
|
|
5252
|
+
];
|
|
5253
|
+
}
|
|
5254
|
+
function codexSessionRootCandidates(homeDirOrCodexRoot) {
|
|
5255
|
+
return codexStateRootCandidates(homeDirOrCodexRoot).map((root) => path6.join(root, "sessions"));
|
|
5256
|
+
}
|
|
5182
5257
|
|
|
5183
5258
|
// src/runtimeTurnState.ts
|
|
5184
5259
|
var RuntimeTurnState = class {
|
|
@@ -5359,7 +5434,7 @@ function codexNotificationDiagnosticEvent(message) {
|
|
|
5359
5434
|
return null;
|
|
5360
5435
|
}
|
|
5361
5436
|
const sessionId = codexMessageThreadId(message);
|
|
5362
|
-
const
|
|
5437
|
+
const path19 = boundedString(params.path);
|
|
5363
5438
|
return {
|
|
5364
5439
|
kind: "runtime_diagnostic",
|
|
5365
5440
|
severity: "warning",
|
|
@@ -5367,12 +5442,42 @@ function codexNotificationDiagnosticEvent(message) {
|
|
|
5367
5442
|
itemType: message.method,
|
|
5368
5443
|
message: diagnosticMessage,
|
|
5369
5444
|
...details ? { details } : {},
|
|
5370
|
-
...
|
|
5445
|
+
...path19 ? { path: path19 } : {},
|
|
5371
5446
|
...params.range !== void 0 ? { range: params.range } : {},
|
|
5372
5447
|
payloadBytes: payloadBytes(params),
|
|
5373
5448
|
...sessionId ? { sessionId } : {}
|
|
5374
5449
|
};
|
|
5375
5450
|
}
|
|
5451
|
+
function codexThreadStatusChangedEvent(message) {
|
|
5452
|
+
if (message.method !== "thread/status/changed") return null;
|
|
5453
|
+
const params = message.params ?? {};
|
|
5454
|
+
const status = params.status ?? params.thread?.status;
|
|
5455
|
+
if (!status || typeof status !== "object") return null;
|
|
5456
|
+
const statusType = nonEmptyString2(status.type);
|
|
5457
|
+
const sessionId = codexMessageThreadId(message);
|
|
5458
|
+
if (statusType === "systemError") {
|
|
5459
|
+
const statusMessage = boundedString(status.message) ?? boundedString(status.error?.message) ?? getCodexNotificationErrorMessage(params) ?? "Codex thread entered system error state";
|
|
5460
|
+
return {
|
|
5461
|
+
kind: "error",
|
|
5462
|
+
message: statusMessage
|
|
5463
|
+
};
|
|
5464
|
+
}
|
|
5465
|
+
if (statusType !== "active" || !Array.isArray(status.activeFlags)) return null;
|
|
5466
|
+
const activeFlags = status.activeFlags.filter((flag) => typeof flag === "string");
|
|
5467
|
+
const waitFlags = activeFlags.filter((flag) => flag === "waitingOnApproval" || flag === "waitingOnUserInput");
|
|
5468
|
+
if (waitFlags.length === 0) return null;
|
|
5469
|
+
const waitLabel = waitFlags.includes("waitingOnApproval") && waitFlags.includes("waitingOnUserInput") ? "approval and user input" : waitFlags.includes("waitingOnApproval") ? "approval" : "user input";
|
|
5470
|
+
return {
|
|
5471
|
+
kind: "runtime_diagnostic",
|
|
5472
|
+
severity: "warning",
|
|
5473
|
+
source: "codex_app_server_notification",
|
|
5474
|
+
itemType: "thread/status/changed",
|
|
5475
|
+
message: `Codex thread is waiting on ${waitLabel}`,
|
|
5476
|
+
details: `Active flags: ${waitFlags.join(", ")}`,
|
|
5477
|
+
payloadBytes: payloadBytes(params),
|
|
5478
|
+
...sessionId ? { sessionId } : {}
|
|
5479
|
+
};
|
|
5480
|
+
}
|
|
5376
5481
|
function joinReasoningSummaryText(item) {
|
|
5377
5482
|
const summary = Array.isArray(item.summary) ? item.summary.filter((entry) => typeof entry === "string") : [];
|
|
5378
5483
|
return summary.join("\n").trim();
|
|
@@ -5400,10 +5505,27 @@ function codexMcpToolName(item) {
|
|
|
5400
5505
|
function codexMessageThreadId(message) {
|
|
5401
5506
|
return nonEmptyString2(message.params?.threadId) ?? nonEmptyString2(message.params?.thread?.id) ?? nonEmptyString2(message.params?.sessionId);
|
|
5402
5507
|
}
|
|
5508
|
+
function codexAgentMessagePhase(value) {
|
|
5509
|
+
return typeof value === "string" && value.length > 0 ? value : null;
|
|
5510
|
+
}
|
|
5511
|
+
function codexAgentMessageDeltaPhase(message) {
|
|
5512
|
+
return codexAgentMessagePhase(message.params?.phase) ?? codexAgentMessagePhase(message.params?.item?.phase);
|
|
5513
|
+
}
|
|
5514
|
+
function isUserVisibleAgentMessagePhase(phase) {
|
|
5515
|
+
return phase === null || phase === "final_answer";
|
|
5516
|
+
}
|
|
5517
|
+
function codexSuppressedAgentMessageEvent(itemType, phase, text, itemId) {
|
|
5518
|
+
return codexNotificationProgressEvent(itemType, {
|
|
5519
|
+
...typeof itemId === "string" ? { itemId } : {},
|
|
5520
|
+
...phase ? { phase } : {},
|
|
5521
|
+
bytes: Buffer.byteLength(text, "utf8")
|
|
5522
|
+
});
|
|
5523
|
+
}
|
|
5403
5524
|
var CodexEventNormalizer = class {
|
|
5404
5525
|
currentThreadId = null;
|
|
5405
5526
|
sessionAnnounced = false;
|
|
5406
5527
|
streamedAgentMessageIds = /* @__PURE__ */ new Set();
|
|
5528
|
+
agentMessagePhases = /* @__PURE__ */ new Map();
|
|
5407
5529
|
streamedReasoningIds = /* @__PURE__ */ new Set();
|
|
5408
5530
|
fileChangeToolCallCounts = /* @__PURE__ */ new Map();
|
|
5409
5531
|
turnState = new RuntimeTurnState();
|
|
@@ -5412,6 +5534,7 @@ var CodexEventNormalizer = class {
|
|
|
5412
5534
|
this.turnState.reset();
|
|
5413
5535
|
this.sessionAnnounced = false;
|
|
5414
5536
|
this.streamedAgentMessageIds.clear();
|
|
5537
|
+
this.agentMessagePhases.clear();
|
|
5415
5538
|
this.streamedReasoningIds.clear();
|
|
5416
5539
|
this.fileChangeToolCallCounts.clear();
|
|
5417
5540
|
}
|
|
@@ -5489,12 +5612,17 @@ var CodexEventNormalizer = class {
|
|
|
5489
5612
|
case "item/agentMessage/delta": {
|
|
5490
5613
|
const delta = message.params?.delta;
|
|
5491
5614
|
const itemId = message.params?.itemId;
|
|
5615
|
+
const phase = codexAgentMessageDeltaPhase(message) ?? (typeof itemId === "string" ? this.agentMessagePhases.get(itemId) ?? null : null);
|
|
5492
5616
|
if (typeof itemId === "string") {
|
|
5493
5617
|
this.streamedAgentMessageIds.add(itemId);
|
|
5494
5618
|
}
|
|
5495
5619
|
if (typeof delta === "string" && delta.length > 0) {
|
|
5496
5620
|
this.turnState.markProgress();
|
|
5497
|
-
|
|
5621
|
+
if (isUserVisibleAgentMessagePhase(phase)) {
|
|
5622
|
+
events.push({ kind: "text", text: delta });
|
|
5623
|
+
} else {
|
|
5624
|
+
events.push(codexSuppressedAgentMessageEvent("agent_message_non_final_delta", phase, delta, itemId));
|
|
5625
|
+
}
|
|
5498
5626
|
}
|
|
5499
5627
|
break;
|
|
5500
5628
|
}
|
|
@@ -5545,6 +5673,13 @@ var CodexEventNormalizer = class {
|
|
|
5545
5673
|
}
|
|
5546
5674
|
break;
|
|
5547
5675
|
}
|
|
5676
|
+
case "thread/status/changed": {
|
|
5677
|
+
const event = codexThreadStatusChangedEvent(message);
|
|
5678
|
+
if (event) {
|
|
5679
|
+
events.push(event);
|
|
5680
|
+
}
|
|
5681
|
+
break;
|
|
5682
|
+
}
|
|
5548
5683
|
case "item/started":
|
|
5549
5684
|
case "item/completed": {
|
|
5550
5685
|
const item = message.params?.item;
|
|
@@ -5566,12 +5701,21 @@ var CodexEventNormalizer = class {
|
|
|
5566
5701
|
}
|
|
5567
5702
|
break;
|
|
5568
5703
|
case "agentMessage":
|
|
5704
|
+
if ((isStarted || isCompleted) && typeof item.id === "string") {
|
|
5705
|
+
this.agentMessagePhases.set(item.id, codexAgentMessagePhase(item.phase));
|
|
5706
|
+
}
|
|
5569
5707
|
if (isCompleted && typeof item.id === "string" && !this.streamedAgentMessageIds.has(item.id) && typeof item.text === "string" && item.text.length > 0) {
|
|
5708
|
+
const phase = codexAgentMessagePhase(item.phase);
|
|
5570
5709
|
this.turnState.markProgress();
|
|
5571
|
-
|
|
5710
|
+
if (isUserVisibleAgentMessagePhase(phase)) {
|
|
5711
|
+
events.push({ kind: "text", text: item.text });
|
|
5712
|
+
} else {
|
|
5713
|
+
events.push(codexSuppressedAgentMessageEvent("agent_message_non_final_completed", phase, item.text, item.id));
|
|
5714
|
+
}
|
|
5572
5715
|
}
|
|
5573
5716
|
if (isCompleted && typeof item.id === "string") {
|
|
5574
5717
|
this.streamedAgentMessageIds.delete(item.id);
|
|
5718
|
+
this.agentMessagePhases.delete(item.id);
|
|
5575
5719
|
}
|
|
5576
5720
|
break;
|
|
5577
5721
|
case "commandExecution":
|
|
@@ -5710,14 +5854,15 @@ var CodexEventNormalizer = class {
|
|
|
5710
5854
|
|
|
5711
5855
|
// src/drivers/codex.ts
|
|
5712
5856
|
var CODEX_DESKTOP_BUNDLE_PATH = "/Applications/Codex.app/Contents/Resources/codex";
|
|
5857
|
+
var CODEX_APP_SERVER_PROBE_ARGS = ["app-server", "--help"];
|
|
5713
5858
|
function isWindowsSandboxRunner(commandPath) {
|
|
5714
|
-
return
|
|
5859
|
+
return path7.basename(commandPath).toLowerCase().startsWith("codex-command-runner");
|
|
5715
5860
|
}
|
|
5716
5861
|
function resolveWindowsNpmCodexEntry(deps = {}) {
|
|
5717
5862
|
const existsSyncFn = deps.existsSyncFn ?? existsSync5;
|
|
5718
5863
|
const execFileSyncFn = deps.execFileSyncFn ?? execFileSync2;
|
|
5719
5864
|
const env = deps.env ?? process.env;
|
|
5720
|
-
const winPath =
|
|
5865
|
+
const winPath = path7.win32;
|
|
5721
5866
|
try {
|
|
5722
5867
|
const globalRoot = String(execFileSyncFn("npm", ["root", "-g"], {
|
|
5723
5868
|
encoding: "utf8",
|
|
@@ -5739,7 +5884,7 @@ function resolveWindowsCodexDesktopEntry(deps = {}) {
|
|
|
5739
5884
|
const existsSyncFn = deps.existsSyncFn ?? existsSync5;
|
|
5740
5885
|
const env = deps.env ?? process.env;
|
|
5741
5886
|
const homeDir = deps.homeDir;
|
|
5742
|
-
const winPath =
|
|
5887
|
+
const winPath = path7.win32;
|
|
5743
5888
|
const candidates = [
|
|
5744
5889
|
env.LOCALAPPDATA ? winPath.join(env.LOCALAPPDATA, "OpenAI", "Codex", "bin", "codex.exe") : null,
|
|
5745
5890
|
env.USERPROFILE ? winPath.join(env.USERPROFILE, "AppData", "Local", "OpenAI", "Codex", "bin", "codex.exe") : null,
|
|
@@ -5750,69 +5895,158 @@ function resolveWindowsCodexDesktopEntry(deps = {}) {
|
|
|
5750
5895
|
}
|
|
5751
5896
|
return null;
|
|
5752
5897
|
}
|
|
5753
|
-
function
|
|
5898
|
+
function codexSpawnCandidates(deps = {}) {
|
|
5754
5899
|
const platform = deps.platform ?? process.platform;
|
|
5755
5900
|
if (platform === "win32") {
|
|
5901
|
+
const candidates2 = [];
|
|
5756
5902
|
const npmEntry = resolveWindowsNpmCodexEntry(deps);
|
|
5757
|
-
if (npmEntry)
|
|
5903
|
+
if (npmEntry) {
|
|
5904
|
+
candidates2.push({
|
|
5905
|
+
source: "npm_global",
|
|
5906
|
+
command: process.execPath,
|
|
5907
|
+
argsPrefix: [npmEntry],
|
|
5908
|
+
shell: false
|
|
5909
|
+
});
|
|
5910
|
+
}
|
|
5758
5911
|
const command = resolveCommandOnPath("codex", deps);
|
|
5759
|
-
if (command && !isWindowsSandboxRunner(command))
|
|
5760
|
-
|
|
5912
|
+
if (command && !isWindowsSandboxRunner(command)) {
|
|
5913
|
+
candidates2.push({
|
|
5914
|
+
source: "path",
|
|
5915
|
+
command,
|
|
5916
|
+
argsPrefix: [],
|
|
5917
|
+
shell: requiresWindowsShell(command, platform)
|
|
5918
|
+
});
|
|
5919
|
+
}
|
|
5920
|
+
const desktopEntry = resolveWindowsCodexDesktopEntry(deps);
|
|
5921
|
+
if (desktopEntry && !candidates2.some((candidate) => candidate.command === desktopEntry)) {
|
|
5922
|
+
candidates2.push({
|
|
5923
|
+
source: "desktop_install",
|
|
5924
|
+
command: desktopEntry,
|
|
5925
|
+
argsPrefix: [],
|
|
5926
|
+
shell: false
|
|
5927
|
+
});
|
|
5928
|
+
}
|
|
5929
|
+
return candidates2;
|
|
5761
5930
|
}
|
|
5931
|
+
const candidates = [];
|
|
5762
5932
|
const pathCommand = resolveCommandOnPath("codex", deps);
|
|
5763
|
-
if (pathCommand)
|
|
5933
|
+
if (pathCommand) {
|
|
5934
|
+
candidates.push({
|
|
5935
|
+
source: "path",
|
|
5936
|
+
command: pathCommand,
|
|
5937
|
+
argsPrefix: [],
|
|
5938
|
+
shell: false
|
|
5939
|
+
});
|
|
5940
|
+
}
|
|
5764
5941
|
if (platform === "darwin") {
|
|
5765
|
-
|
|
5942
|
+
const bundleCommand = firstExistingPath([CODEX_DESKTOP_BUNDLE_PATH], deps);
|
|
5943
|
+
if (bundleCommand && !candidates.some((candidate) => candidate.command === bundleCommand)) {
|
|
5944
|
+
candidates.push({
|
|
5945
|
+
source: "desktop_bundle",
|
|
5946
|
+
command: bundleCommand,
|
|
5947
|
+
argsPrefix: [],
|
|
5948
|
+
shell: false
|
|
5949
|
+
});
|
|
5950
|
+
}
|
|
5766
5951
|
}
|
|
5767
|
-
return
|
|
5952
|
+
return candidates;
|
|
5953
|
+
}
|
|
5954
|
+
function formatCodexCandidate(candidate) {
|
|
5955
|
+
return [candidate.command, ...candidate.argsPrefix].join(" ");
|
|
5956
|
+
}
|
|
5957
|
+
function describeCodexProbeFailure(error) {
|
|
5958
|
+
if (error && typeof error === "object") {
|
|
5959
|
+
const candidate = error;
|
|
5960
|
+
if (typeof candidate.status === "number") return `exit status ${candidate.status}`;
|
|
5961
|
+
if (typeof candidate.signal === "string") return `terminated by ${candidate.signal}`;
|
|
5962
|
+
if (typeof candidate.code === "string") return candidate.code;
|
|
5963
|
+
}
|
|
5964
|
+
return "probe failed";
|
|
5965
|
+
}
|
|
5966
|
+
function validateCodexAppServer(candidate, deps = {}) {
|
|
5967
|
+
const execFileSyncFn = deps.execFileSyncFn ?? execFileSync2;
|
|
5968
|
+
const env = withWindowsUserEnvironment(deps.env ?? process.env, deps);
|
|
5969
|
+
try {
|
|
5970
|
+
execFileSyncFn(candidate.command, [...candidate.argsPrefix, ...CODEX_APP_SERVER_PROBE_ARGS], {
|
|
5971
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
5972
|
+
env,
|
|
5973
|
+
timeout: 5e3,
|
|
5974
|
+
shell: candidate.shell
|
|
5975
|
+
});
|
|
5976
|
+
return null;
|
|
5977
|
+
} catch (error) {
|
|
5978
|
+
return describeCodexProbeFailure(error);
|
|
5979
|
+
}
|
|
5980
|
+
}
|
|
5981
|
+
function readCodexCandidateVersion(candidate, deps = {}) {
|
|
5982
|
+
const execFileSyncFn = deps.execFileSyncFn ?? execFileSync2;
|
|
5983
|
+
const env = withWindowsUserEnvironment(deps.env ?? process.env, deps);
|
|
5984
|
+
try {
|
|
5985
|
+
const output = execFileSyncFn(candidate.command, [...candidate.argsPrefix, "--version"], {
|
|
5986
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
5987
|
+
env,
|
|
5988
|
+
timeout: 5e3,
|
|
5989
|
+
shell: candidate.shell
|
|
5990
|
+
});
|
|
5991
|
+
return (Buffer.isBuffer(output) ? output.toString("utf8") : String(output ?? "")).trim().split(/\r?\n/)[0] || null;
|
|
5992
|
+
} catch {
|
|
5993
|
+
return null;
|
|
5994
|
+
}
|
|
5995
|
+
}
|
|
5996
|
+
function resolveCompatibleCodexCandidate(deps = {}) {
|
|
5997
|
+
const rejected = [];
|
|
5998
|
+
for (const candidate of codexSpawnCandidates(deps)) {
|
|
5999
|
+
const failure = validateCodexAppServer(candidate, deps);
|
|
6000
|
+
if (!failure) return { candidate, rejected };
|
|
6001
|
+
rejected.push(`${candidate.source} ${formatCodexCandidate(candidate)} rejected: app-server probe ${failure}`);
|
|
6002
|
+
}
|
|
6003
|
+
return { candidate: null, rejected };
|
|
5768
6004
|
}
|
|
5769
6005
|
function probeCodex(deps = {}) {
|
|
5770
|
-
|
|
5771
|
-
|
|
5772
|
-
|
|
5773
|
-
|
|
5774
|
-
|
|
5775
|
-
|
|
5776
|
-
|
|
5777
|
-
} catch {
|
|
5778
|
-
return { available: false };
|
|
5779
|
-
}
|
|
6006
|
+
const { candidate, rejected } = resolveCompatibleCodexCandidate(deps);
|
|
6007
|
+
const diagnostic = rejected.length > 0 ? rejected.join("; ") : void 0;
|
|
6008
|
+
if (!candidate) {
|
|
6009
|
+
return {
|
|
6010
|
+
available: false,
|
|
6011
|
+
diagnostic: diagnostic ?? "No Codex CLI app-server candidate was found."
|
|
6012
|
+
};
|
|
5780
6013
|
}
|
|
5781
|
-
const command = resolveCodexCommand(deps);
|
|
5782
|
-
if (!command) return { available: false };
|
|
5783
6014
|
return {
|
|
5784
6015
|
available: true,
|
|
5785
|
-
version:
|
|
6016
|
+
version: readCodexCandidateVersion(candidate, deps) ?? void 0,
|
|
6017
|
+
...diagnostic ? { diagnostic } : {}
|
|
5786
6018
|
};
|
|
5787
6019
|
}
|
|
5788
6020
|
function resolveCodexSpawn(commandArgs, deps = {}) {
|
|
5789
|
-
|
|
5790
|
-
|
|
5791
|
-
|
|
5792
|
-
const codexEntry = resolveWindowsNpmCodexEntry(deps);
|
|
5793
|
-
if (codexEntry) {
|
|
5794
|
-
return {
|
|
5795
|
-
command: process.execPath,
|
|
5796
|
-
args: [codexEntry, ...commandArgs],
|
|
5797
|
-
shell: false
|
|
5798
|
-
};
|
|
5799
|
-
}
|
|
5800
|
-
const command = resolveCommandOnPath("codex", deps);
|
|
5801
|
-
if (command && !isWindowsSandboxRunner(command)) {
|
|
5802
|
-
return { command, args: commandArgs, shell: requiresWindowsShell(command, deps.platform) };
|
|
6021
|
+
const { candidate, rejected } = resolveCompatibleCodexCandidate(deps);
|
|
6022
|
+
if (candidate) {
|
|
6023
|
+
return { command: candidate.command, args: [...candidate.argsPrefix, ...commandArgs], shell: candidate.shell };
|
|
5803
6024
|
}
|
|
5804
|
-
const
|
|
5805
|
-
if (
|
|
5806
|
-
|
|
6025
|
+
const diagnostic = rejected.length > 0 ? ` Rejected candidates: ${rejected.join("; ")}.` : "";
|
|
6026
|
+
if ((deps.platform ?? process.platform) === "win32") {
|
|
6027
|
+
throw new Error(
|
|
6028
|
+
"Cannot resolve a compatible Codex CLI app-server entry point on Windows. Install Codex Desktop or install @openai/codex globally via npm (npm i -g @openai/codex). Ignoring .codex/.sandbox-bin/codex-command-runner because it is a sandbox helper, not the Codex CLI." + diagnostic
|
|
6029
|
+
);
|
|
5807
6030
|
}
|
|
5808
|
-
throw new Error(
|
|
5809
|
-
"Cannot resolve Codex CLI entry point on Windows. Install Codex Desktop or install @openai/codex globally via npm (npm i -g @openai/codex). Ignoring .codex/.sandbox-bin/codex-command-runner because it is a sandbox helper, not the Codex CLI."
|
|
5810
|
-
);
|
|
6031
|
+
throw new Error(`Cannot resolve a compatible Codex CLI app-server entry point.${diagnostic}`);
|
|
5811
6032
|
}
|
|
5812
6033
|
function isCodexMissingRolloutError(message) {
|
|
5813
6034
|
return /\bno\s+rollout\s+found\b/i.test(message) || /\bmissing\s+rollout\b/i.test(message) || /\brollout\b.*\b(not found|missing)\b/i.test(message) || /\bthread\b.*\b(not found|missing)\b/i.test(message) || /\bmissing\s+thread\b/i.test(message);
|
|
5814
6035
|
}
|
|
5815
|
-
function
|
|
6036
|
+
function codexMissingRolloutRecoveryMessage() {
|
|
6037
|
+
return "Codex could not resume its previous thread; Slock started a fresh Codex thread.";
|
|
6038
|
+
}
|
|
6039
|
+
function codexMissingRolloutRecoveryDetails() {
|
|
6040
|
+
return "Use Slock conversation history and local MEMORY.md/notes as the recovery point; do not assume prior Codex thread context is loaded.";
|
|
6041
|
+
}
|
|
6042
|
+
function prependCodexRecoveryNotice(prompt, recovery) {
|
|
6043
|
+
return `${recovery.message}
|
|
6044
|
+
|
|
6045
|
+
${recovery.details}
|
|
6046
|
+
|
|
6047
|
+
${prompt}`;
|
|
6048
|
+
}
|
|
6049
|
+
function classifyCodexResumeError(message, requestedSessionId) {
|
|
5816
6050
|
if (isCodexMissingRolloutError(message)) {
|
|
5817
6051
|
return {
|
|
5818
6052
|
kind: "missing_rollout",
|
|
@@ -5826,6 +6060,15 @@ function classifyCodexResumeError(message) {
|
|
|
5826
6060
|
resume_error_class: "missing_rollout",
|
|
5827
6061
|
recovery_action: "fallback_fresh_thread"
|
|
5828
6062
|
}
|
|
6063
|
+
},
|
|
6064
|
+
recovery: {
|
|
6065
|
+
kind: "runtime_recovery",
|
|
6066
|
+
source: "codex_resume_missing_rollout",
|
|
6067
|
+
resumeErrorClass: "missing_rollout",
|
|
6068
|
+
recoveryAction: "fallback_fresh_thread",
|
|
6069
|
+
message: codexMissingRolloutRecoveryMessage(),
|
|
6070
|
+
details: codexMissingRolloutRecoveryDetails(),
|
|
6071
|
+
...requestedSessionId ? { requestedSessionId } : {}
|
|
5829
6072
|
}
|
|
5830
6073
|
};
|
|
5831
6074
|
}
|
|
@@ -5849,6 +6092,26 @@ function isJsonRpcResponse(message) {
|
|
|
5849
6092
|
function isCodexServerRequest(message) {
|
|
5850
6093
|
return message.id !== void 0 && typeof message.method === "string" && !isJsonRpcResponse(message);
|
|
5851
6094
|
}
|
|
6095
|
+
function payloadBytes2(value) {
|
|
6096
|
+
try {
|
|
6097
|
+
return Buffer.byteLength(JSON.stringify(value), "utf8");
|
|
6098
|
+
} catch {
|
|
6099
|
+
return void 0;
|
|
6100
|
+
}
|
|
6101
|
+
}
|
|
6102
|
+
function extractCodexHome(result) {
|
|
6103
|
+
if (!result || typeof result !== "object") return null;
|
|
6104
|
+
const candidate = result.codexHome;
|
|
6105
|
+
return typeof candidate === "string" && candidate.trim().length > 0 ? candidate : null;
|
|
6106
|
+
}
|
|
6107
|
+
function isCompatibleInitializeResult(result) {
|
|
6108
|
+
if (!result || typeof result !== "object" || Array.isArray(result)) return false;
|
|
6109
|
+
const userAgent = result.userAgent;
|
|
6110
|
+
return typeof userAgent === "string" && userAgent.trim().length > 0;
|
|
6111
|
+
}
|
|
6112
|
+
function unsupportedInitializeResultMessage() {
|
|
6113
|
+
return "Codex app-server initialize response is missing the expected userAgent handshake field; upgrade Codex CLI to a compatible app-server build.";
|
|
6114
|
+
}
|
|
5852
6115
|
var CodexDriver = class {
|
|
5853
6116
|
id = "codex";
|
|
5854
6117
|
lifecycle = {
|
|
@@ -5919,9 +6182,16 @@ var CodexDriver = class {
|
|
|
5919
6182
|
pendingThreadRequestId = null;
|
|
5920
6183
|
pendingThreadRequestMethod = null;
|
|
5921
6184
|
pendingResumeFallbackParams = null;
|
|
6185
|
+
pendingResumeThreadId = null;
|
|
5922
6186
|
pendingInitialTurnRequestId = null;
|
|
6187
|
+
pendingDeliveryRequests = /* @__PURE__ */ new Map();
|
|
5923
6188
|
initialTurnStarted = false;
|
|
5924
6189
|
normalizer = new CodexEventNormalizer();
|
|
6190
|
+
codexHomeRoot = null;
|
|
6191
|
+
spawnWorkingDirectory = null;
|
|
6192
|
+
get currentRuntimeHomeDir() {
|
|
6193
|
+
return this.codexHomeRoot;
|
|
6194
|
+
}
|
|
5925
6195
|
async spawn(ctx) {
|
|
5926
6196
|
const { spawnEnv } = await prepareCliTransport(ctx, { NO_COLOR: "1" });
|
|
5927
6197
|
this.process = null;
|
|
@@ -5932,9 +6202,16 @@ var CodexDriver = class {
|
|
|
5932
6202
|
this.pendingThreadRequestId = null;
|
|
5933
6203
|
this.pendingThreadRequestMethod = null;
|
|
5934
6204
|
this.pendingResumeFallbackParams = null;
|
|
6205
|
+
this.pendingResumeThreadId = null;
|
|
5935
6206
|
this.pendingInitialTurnRequestId = null;
|
|
6207
|
+
this.pendingDeliveryRequests.clear();
|
|
5936
6208
|
this.initialTurnStarted = false;
|
|
5937
6209
|
this.normalizer.reset();
|
|
6210
|
+
this.spawnWorkingDirectory = ctx.workingDirectory;
|
|
6211
|
+
this.codexHomeRoot = resolveCodexHomeRootFromEnv(spawnEnv, {
|
|
6212
|
+
defaultHomeDir: os4.homedir(),
|
|
6213
|
+
cwd: ctx.workingDirectory
|
|
6214
|
+
});
|
|
5938
6215
|
const args = ["app-server", "--listen", "stdio://"];
|
|
5939
6216
|
const { command, args: spawnArgs, shell } = resolveCodexSpawn(args);
|
|
5940
6217
|
const proc = spawn2(command, spawnArgs, {
|
|
@@ -5969,6 +6246,24 @@ var CodexDriver = class {
|
|
|
5969
6246
|
const isResponse = isJsonRpcResponse(message);
|
|
5970
6247
|
if (isResponse && hasJsonRpcField(message, "result")) {
|
|
5971
6248
|
if (message.id === this.initializeRequestId) {
|
|
6249
|
+
if (!isCompatibleInitializeResult(message.result)) {
|
|
6250
|
+
this.initializeRequestId = null;
|
|
6251
|
+
this.pendingThreadRequest = null;
|
|
6252
|
+
this.pendingThreadRequestId = null;
|
|
6253
|
+
this.pendingThreadRequestMethod = null;
|
|
6254
|
+
this.pendingResumeFallbackParams = null;
|
|
6255
|
+
this.pendingResumeThreadId = null;
|
|
6256
|
+
events.push({
|
|
6257
|
+
kind: "error",
|
|
6258
|
+
message: unsupportedInitializeResultMessage(),
|
|
6259
|
+
startupRequestMethod: "initialize"
|
|
6260
|
+
});
|
|
6261
|
+
return events;
|
|
6262
|
+
}
|
|
6263
|
+
const codexHome = extractCodexHome(message.result);
|
|
6264
|
+
if (codexHome) {
|
|
6265
|
+
this.codexHomeRoot = path7.resolve(this.spawnWorkingDirectory ?? process.cwd(), codexHome);
|
|
6266
|
+
}
|
|
5972
6267
|
this.initializeRequestId = null;
|
|
5973
6268
|
this.sendNotification("initialized", {});
|
|
5974
6269
|
if (this.pendingThreadRequest) {
|
|
@@ -5984,6 +6279,7 @@ var CodexDriver = class {
|
|
|
5984
6279
|
this.pendingThreadRequestId = null;
|
|
5985
6280
|
this.pendingThreadRequestMethod = null;
|
|
5986
6281
|
this.pendingResumeFallbackParams = null;
|
|
6282
|
+
this.pendingResumeThreadId = null;
|
|
5987
6283
|
events.push({
|
|
5988
6284
|
kind: "error",
|
|
5989
6285
|
message: message.error?.message || "Codex app-server request failed",
|
|
@@ -5995,9 +6291,16 @@ var CodexDriver = class {
|
|
|
5995
6291
|
if (hasJsonRpcField(message, "error")) {
|
|
5996
6292
|
const errorMessage = message.error?.message || "Codex app-server request failed";
|
|
5997
6293
|
const requestMethod = this.pendingThreadRequestMethod;
|
|
5998
|
-
const resumeErrorClassification = requestMethod === "thread/resume" ? classifyCodexResumeError(errorMessage) : null;
|
|
6294
|
+
const resumeErrorClassification = requestMethod === "thread/resume" ? classifyCodexResumeError(errorMessage, this.pendingResumeThreadId || void 0) : null;
|
|
5999
6295
|
if (this.pendingResumeFallbackParams && resumeErrorClassification?.kind === "missing_rollout") {
|
|
6000
6296
|
events.push(resumeErrorClassification.telemetry);
|
|
6297
|
+
events.push(resumeErrorClassification.recovery);
|
|
6298
|
+
if (this.pendingInitialPrompt) {
|
|
6299
|
+
this.pendingInitialPrompt = prependCodexRecoveryNotice(
|
|
6300
|
+
this.pendingInitialPrompt,
|
|
6301
|
+
resumeErrorClassification.recovery
|
|
6302
|
+
);
|
|
6303
|
+
}
|
|
6001
6304
|
this.sendThreadRequest("thread/start", this.pendingResumeFallbackParams);
|
|
6002
6305
|
this.pendingResumeFallbackParams = null;
|
|
6003
6306
|
return events;
|
|
@@ -6005,12 +6308,14 @@ var CodexDriver = class {
|
|
|
6005
6308
|
this.pendingThreadRequestId = null;
|
|
6006
6309
|
this.pendingThreadRequestMethod = null;
|
|
6007
6310
|
this.pendingResumeFallbackParams = null;
|
|
6311
|
+
this.pendingResumeThreadId = null;
|
|
6008
6312
|
events.push(requestMethod ? { kind: "error", message: errorMessage, startupRequestMethod: requestMethod } : { kind: "error", message: errorMessage });
|
|
6009
6313
|
return events;
|
|
6010
6314
|
}
|
|
6011
6315
|
this.pendingThreadRequestId = null;
|
|
6012
6316
|
this.pendingThreadRequestMethod = null;
|
|
6013
6317
|
this.pendingResumeFallbackParams = null;
|
|
6318
|
+
this.pendingResumeThreadId = null;
|
|
6014
6319
|
}
|
|
6015
6320
|
if (isResponse && message.id === this.pendingInitialTurnRequestId) {
|
|
6016
6321
|
this.pendingInitialTurnRequestId = null;
|
|
@@ -6025,6 +6330,21 @@ var CodexDriver = class {
|
|
|
6025
6330
|
}
|
|
6026
6331
|
return events;
|
|
6027
6332
|
}
|
|
6333
|
+
if (isResponse && message.id !== void 0 && this.pendingDeliveryRequests.has(message.id)) {
|
|
6334
|
+
const requestMethod = this.pendingDeliveryRequests.get(message.id);
|
|
6335
|
+
this.pendingDeliveryRequests.delete(message.id);
|
|
6336
|
+
if (hasJsonRpcField(message, "error")) {
|
|
6337
|
+
const params = message.error ?? {};
|
|
6338
|
+
events.push({
|
|
6339
|
+
kind: "delivery_error",
|
|
6340
|
+
message: message.error?.message || "Codex app-server request failed",
|
|
6341
|
+
requestMethod,
|
|
6342
|
+
source: "codex_app_server_response",
|
|
6343
|
+
payloadBytes: payloadBytes2(params)
|
|
6344
|
+
});
|
|
6345
|
+
}
|
|
6346
|
+
return events;
|
|
6347
|
+
}
|
|
6028
6348
|
const result = this.normalizer.normalizeMessage(message);
|
|
6029
6349
|
if (result.turnStarted) {
|
|
6030
6350
|
this.pendingInitialTurnRequestId = null;
|
|
@@ -6043,9 +6363,11 @@ var CodexDriver = class {
|
|
|
6043
6363
|
const mode = opts?.mode || "busy";
|
|
6044
6364
|
if (mode === "busy") {
|
|
6045
6365
|
if (!this.normalizer.canSteerBusy) return null;
|
|
6366
|
+
const id2 = this.nextRequestId();
|
|
6367
|
+
this.pendingDeliveryRequests.set(id2, "turn/steer");
|
|
6046
6368
|
return JSON.stringify({
|
|
6047
6369
|
jsonrpc: "2.0",
|
|
6048
|
-
id:
|
|
6370
|
+
id: id2,
|
|
6049
6371
|
method: "turn/steer",
|
|
6050
6372
|
params: {
|
|
6051
6373
|
threadId: this.normalizer.threadId,
|
|
@@ -6054,9 +6376,11 @@ var CodexDriver = class {
|
|
|
6054
6376
|
}
|
|
6055
6377
|
});
|
|
6056
6378
|
}
|
|
6379
|
+
const id = this.nextRequestId();
|
|
6380
|
+
this.pendingDeliveryRequests.set(id, "turn/start");
|
|
6057
6381
|
return JSON.stringify({
|
|
6058
6382
|
jsonrpc: "2.0",
|
|
6059
|
-
id
|
|
6383
|
+
id,
|
|
6060
6384
|
method: "turn/start",
|
|
6061
6385
|
params: {
|
|
6062
6386
|
threadId: this.normalizer.threadId,
|
|
@@ -6112,9 +6436,11 @@ var CodexDriver = class {
|
|
|
6112
6436
|
this.pendingThreadRequestId = id;
|
|
6113
6437
|
this.pendingThreadRequestMethod = method;
|
|
6114
6438
|
this.pendingResumeFallbackParams = null;
|
|
6439
|
+
this.pendingResumeThreadId = null;
|
|
6115
6440
|
if (method === "thread/resume") {
|
|
6116
6441
|
const { threadId: _threadId, ...freshParams } = params;
|
|
6117
6442
|
this.pendingResumeFallbackParams = freshParams;
|
|
6443
|
+
this.pendingResumeThreadId = typeof _threadId === "string" && _threadId.trim() ? _threadId.trim() : null;
|
|
6118
6444
|
}
|
|
6119
6445
|
return id;
|
|
6120
6446
|
}
|
|
@@ -6126,12 +6452,194 @@ var CodexDriver = class {
|
|
|
6126
6452
|
}) + "\n");
|
|
6127
6453
|
}
|
|
6128
6454
|
async detectModels() {
|
|
6129
|
-
return detectCodexModels();
|
|
6455
|
+
return await detectCodexModelsFromAppServer() ?? detectCodexModels(resolveCodexHomeRootFromEnv());
|
|
6130
6456
|
}
|
|
6131
6457
|
};
|
|
6132
|
-
function
|
|
6133
|
-
|
|
6134
|
-
|
|
6458
|
+
function asNonEmptyString(value) {
|
|
6459
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
|
|
6460
|
+
}
|
|
6461
|
+
function modelListPage(result) {
|
|
6462
|
+
if (!result || typeof result !== "object") return null;
|
|
6463
|
+
const object = result;
|
|
6464
|
+
const entries = Array.isArray(object.data) ? object.data : Array.isArray(object.models) ? object.models : null;
|
|
6465
|
+
if (!entries) return null;
|
|
6466
|
+
return {
|
|
6467
|
+
entries,
|
|
6468
|
+
nextCursor: asNonEmptyString(object.nextCursor)
|
|
6469
|
+
};
|
|
6470
|
+
}
|
|
6471
|
+
function modelListRequestParams(cursor) {
|
|
6472
|
+
return cursor ? { cursor } : {};
|
|
6473
|
+
}
|
|
6474
|
+
function stringArray(values, read) {
|
|
6475
|
+
const result = [];
|
|
6476
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6477
|
+
for (const value of values) {
|
|
6478
|
+
const item = read(value);
|
|
6479
|
+
if (!item || seen.has(item)) continue;
|
|
6480
|
+
seen.add(item);
|
|
6481
|
+
result.push(item);
|
|
6482
|
+
}
|
|
6483
|
+
return result;
|
|
6484
|
+
}
|
|
6485
|
+
function codexReasoningEfforts(value) {
|
|
6486
|
+
if (!Array.isArray(value)) return [];
|
|
6487
|
+
return stringArray(value, (entry) => {
|
|
6488
|
+
if (typeof entry === "string") return asNonEmptyString(entry);
|
|
6489
|
+
if (!entry || typeof entry !== "object") return null;
|
|
6490
|
+
const object = entry;
|
|
6491
|
+
return asNonEmptyString(object.reasoningEffort) ?? asNonEmptyString(object.id);
|
|
6492
|
+
});
|
|
6493
|
+
}
|
|
6494
|
+
function codexServiceTierIds(value) {
|
|
6495
|
+
if (!Array.isArray(value)) return [];
|
|
6496
|
+
return stringArray(value, (entry) => {
|
|
6497
|
+
if (typeof entry === "string") return asNonEmptyString(entry);
|
|
6498
|
+
if (!entry || typeof entry !== "object") return null;
|
|
6499
|
+
const object = entry;
|
|
6500
|
+
return asNonEmptyString(object.id) ?? asNonEmptyString(object.serviceTier);
|
|
6501
|
+
});
|
|
6502
|
+
}
|
|
6503
|
+
function codexModelInfoFromAppServer(entry) {
|
|
6504
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry)) return null;
|
|
6505
|
+
const object = entry;
|
|
6506
|
+
if (object.hidden === true) return null;
|
|
6507
|
+
const id = asNonEmptyString(object.id) ?? asNonEmptyString(object.model) ?? asNonEmptyString(object.slug);
|
|
6508
|
+
if (!id) return null;
|
|
6509
|
+
const label = asNonEmptyString(object.displayName) ?? asNonEmptyString(object.display_name) ?? asNonEmptyString(object.label) ?? id;
|
|
6510
|
+
const supportedReasoningEfforts = codexReasoningEfforts(object.supportedReasoningEfforts);
|
|
6511
|
+
const serviceTiers = codexServiceTierIds(object.serviceTiers);
|
|
6512
|
+
const additionalSpeedTiers = codexServiceTierIds(object.additionalSpeedTiers);
|
|
6513
|
+
const runtimeServiceTiers = serviceTiers.length > 0 ? serviceTiers : additionalSpeedTiers;
|
|
6514
|
+
const defaultReasoningEffort = asNonEmptyString(object.defaultReasoningEffort);
|
|
6515
|
+
const defaultServiceTier = asNonEmptyString(object.defaultServiceTier);
|
|
6516
|
+
return {
|
|
6517
|
+
id,
|
|
6518
|
+
label,
|
|
6519
|
+
verified: "launchable",
|
|
6520
|
+
...supportedReasoningEfforts.length > 0 ? { supportedReasoningEfforts } : {},
|
|
6521
|
+
...defaultReasoningEffort ? { defaultReasoningEffort } : {},
|
|
6522
|
+
...runtimeServiceTiers.length > 0 ? { serviceTiers: runtimeServiceTiers } : {},
|
|
6523
|
+
...defaultServiceTier ? { defaultServiceTier } : {}
|
|
6524
|
+
};
|
|
6525
|
+
}
|
|
6526
|
+
function codexModelSetFromAppServerEntries(entries) {
|
|
6527
|
+
const models = [];
|
|
6528
|
+
let defaultModel;
|
|
6529
|
+
for (const entry of entries) {
|
|
6530
|
+
const model = codexModelInfoFromAppServer(entry);
|
|
6531
|
+
if (!model) continue;
|
|
6532
|
+
models.push(model);
|
|
6533
|
+
if (!defaultModel && typeof entry === "object" && entry && entry.isDefault === true) {
|
|
6534
|
+
defaultModel = model.id;
|
|
6535
|
+
}
|
|
6536
|
+
}
|
|
6537
|
+
return models.length > 0 ? { models, default: defaultModel } : null;
|
|
6538
|
+
}
|
|
6539
|
+
async function detectCodexModelsFromAppServer(options = {}) {
|
|
6540
|
+
const env = options.env ?? process.env;
|
|
6541
|
+
let launch;
|
|
6542
|
+
try {
|
|
6543
|
+
launch = resolveCodexSpawn(["app-server", "--listen", "stdio://"], { env });
|
|
6544
|
+
} catch {
|
|
6545
|
+
return null;
|
|
6546
|
+
}
|
|
6547
|
+
return await new Promise((resolve) => {
|
|
6548
|
+
const timeoutMs = options.timeoutMs ?? 5e3;
|
|
6549
|
+
const proc = spawn2(launch.command, launch.args, {
|
|
6550
|
+
cwd: options.cwd ?? process.cwd(),
|
|
6551
|
+
stdio: ["pipe", "pipe", "ignore"],
|
|
6552
|
+
env,
|
|
6553
|
+
shell: launch.shell
|
|
6554
|
+
});
|
|
6555
|
+
let settled = false;
|
|
6556
|
+
let buffer = "";
|
|
6557
|
+
let requestId = 0;
|
|
6558
|
+
let initializeRequestId = null;
|
|
6559
|
+
let modelListRequestId = null;
|
|
6560
|
+
let pageCount = 0;
|
|
6561
|
+
const entries = [];
|
|
6562
|
+
const finish = (result) => {
|
|
6563
|
+
if (settled) return;
|
|
6564
|
+
settled = true;
|
|
6565
|
+
clearTimeout(timer);
|
|
6566
|
+
proc.kill();
|
|
6567
|
+
resolve(result);
|
|
6568
|
+
};
|
|
6569
|
+
const timer = setTimeout(() => finish(null), timeoutMs);
|
|
6570
|
+
const sendRequest = (method, params) => {
|
|
6571
|
+
requestId += 1;
|
|
6572
|
+
const id = requestId;
|
|
6573
|
+
proc.stdin?.write(JSON.stringify({ jsonrpc: "2.0", id, method, params }) + "\n");
|
|
6574
|
+
return id;
|
|
6575
|
+
};
|
|
6576
|
+
const sendNotification = (method, params) => {
|
|
6577
|
+
proc.stdin?.write(JSON.stringify({ jsonrpc: "2.0", method, params }) + "\n");
|
|
6578
|
+
};
|
|
6579
|
+
const requestModelPage = (cursor) => {
|
|
6580
|
+
pageCount += 1;
|
|
6581
|
+
modelListRequestId = sendRequest("model/list", modelListRequestParams(cursor));
|
|
6582
|
+
};
|
|
6583
|
+
proc.once("error", () => finish(null));
|
|
6584
|
+
proc.once("exit", () => finish(null));
|
|
6585
|
+
proc.stdout?.on("data", (chunk) => {
|
|
6586
|
+
if (settled) return;
|
|
6587
|
+
buffer += chunk.toString();
|
|
6588
|
+
for (; ; ) {
|
|
6589
|
+
const newline = buffer.indexOf("\n");
|
|
6590
|
+
if (newline === -1) break;
|
|
6591
|
+
const line = buffer.slice(0, newline).trim();
|
|
6592
|
+
buffer = buffer.slice(newline + 1);
|
|
6593
|
+
if (!line) continue;
|
|
6594
|
+
const message = parseCodexJsonRpcLine(line);
|
|
6595
|
+
if (!message || !isJsonRpcResponse(message)) continue;
|
|
6596
|
+
if (message.id === initializeRequestId) {
|
|
6597
|
+
if (!hasJsonRpcField(message, "result") || !isCompatibleInitializeResult(message.result)) {
|
|
6598
|
+
finish(null);
|
|
6599
|
+
return;
|
|
6600
|
+
}
|
|
6601
|
+
sendNotification("initialized", {});
|
|
6602
|
+
requestModelPage(null);
|
|
6603
|
+
continue;
|
|
6604
|
+
}
|
|
6605
|
+
if (message.id === modelListRequestId) {
|
|
6606
|
+
if (!hasJsonRpcField(message, "result")) {
|
|
6607
|
+
finish(null);
|
|
6608
|
+
return;
|
|
6609
|
+
}
|
|
6610
|
+
const page = modelListPage(message.result);
|
|
6611
|
+
if (!page) {
|
|
6612
|
+
finish(null);
|
|
6613
|
+
return;
|
|
6614
|
+
}
|
|
6615
|
+
entries.push(...page.entries);
|
|
6616
|
+
if (page.nextCursor && pageCount < 5) {
|
|
6617
|
+
requestModelPage(page.nextCursor);
|
|
6618
|
+
continue;
|
|
6619
|
+
}
|
|
6620
|
+
finish(codexModelSetFromAppServerEntries(entries));
|
|
6621
|
+
return;
|
|
6622
|
+
}
|
|
6623
|
+
}
|
|
6624
|
+
});
|
|
6625
|
+
initializeRequestId = sendRequest("initialize", {
|
|
6626
|
+
clientInfo: { name: "slock-daemon", version: "1.0.0" },
|
|
6627
|
+
capabilities: { experimentalApi: true }
|
|
6628
|
+
});
|
|
6629
|
+
});
|
|
6630
|
+
}
|
|
6631
|
+
function detectCodexModels(home = resolveCodexHomeRootFromEnv()) {
|
|
6632
|
+
let cachePath = null;
|
|
6633
|
+
let configPath = null;
|
|
6634
|
+
for (const root of codexStateRootCandidates(home)) {
|
|
6635
|
+
const candidate = path7.join(root, "models_cache.json");
|
|
6636
|
+
if (existsSync5(candidate)) {
|
|
6637
|
+
cachePath = candidate;
|
|
6638
|
+
configPath = path7.join(root, "config.toml");
|
|
6639
|
+
break;
|
|
6640
|
+
}
|
|
6641
|
+
}
|
|
6642
|
+
if (!cachePath || !configPath) return null;
|
|
6135
6643
|
let models = [];
|
|
6136
6644
|
try {
|
|
6137
6645
|
const raw = readFileSync2(cachePath, "utf8");
|
|
@@ -6584,11 +7092,11 @@ function detectCursorModels(runCommand = runCursorModelsCommand) {
|
|
|
6584
7092
|
return parseCursorModelsOutput(String(result.stdout || ""));
|
|
6585
7093
|
}
|
|
6586
7094
|
function buildCursorModelProbeEnv(deps = {}) {
|
|
6587
|
-
return withWindowsUserEnvironment({
|
|
7095
|
+
return scrubDaemonChildEnv(withWindowsUserEnvironment({
|
|
6588
7096
|
...deps.env ?? process.env,
|
|
6589
7097
|
FORCE_COLOR: "0",
|
|
6590
7098
|
NO_COLOR: "1"
|
|
6591
|
-
}, deps);
|
|
7099
|
+
}, deps));
|
|
6592
7100
|
}
|
|
6593
7101
|
function runCursorModelsCommand() {
|
|
6594
7102
|
return spawnSync("cursor-agent", ["models"], {
|
|
@@ -6601,7 +7109,7 @@ function runCursorModelsCommand() {
|
|
|
6601
7109
|
// src/drivers/gemini.ts
|
|
6602
7110
|
import { execFileSync as execFileSync3, spawn as spawn6 } from "child_process";
|
|
6603
7111
|
import { existsSync as existsSync6 } from "fs";
|
|
6604
|
-
import
|
|
7112
|
+
import path8 from "path";
|
|
6605
7113
|
async function buildGeminiSpawnEnv(ctx, platform = process.platform) {
|
|
6606
7114
|
const { spawnEnv } = await prepareCliTransport(ctx, { NO_COLOR: "1" }, platform);
|
|
6607
7115
|
const launchEnvVars = runtimeConfigToLaunchFields(ctx.config).envVars;
|
|
@@ -6644,8 +7152,8 @@ function resolveGeminiSpawn(commandArgs, deps = {}) {
|
|
|
6644
7152
|
}
|
|
6645
7153
|
const execFileSyncFn = deps.execFileSyncFn ?? execFileSync3;
|
|
6646
7154
|
const existsSyncFn = deps.existsSyncFn ?? existsSync6;
|
|
6647
|
-
const env = deps.env ?? process.env;
|
|
6648
|
-
const winPath =
|
|
7155
|
+
const env = scrubDaemonChildEnv({ ...deps.env ?? process.env });
|
|
7156
|
+
const winPath = path8.win32;
|
|
6649
7157
|
let geminiEntry = null;
|
|
6650
7158
|
try {
|
|
6651
7159
|
const globalRoot = normalizeExecOutput2(execFileSyncFn("npm", ["root", "-g"], {
|
|
@@ -6781,12 +7289,15 @@ var GeminiDriver = class {
|
|
|
6781
7289
|
// src/drivers/kimi.ts
|
|
6782
7290
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
6783
7291
|
import { spawn as spawn7 } from "child_process";
|
|
6784
|
-
import { existsSync as existsSync7, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
6785
|
-
import
|
|
6786
|
-
import
|
|
7292
|
+
import { chmodSync, existsSync as existsSync7, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
7293
|
+
import os5 from "os";
|
|
7294
|
+
import path9 from "path";
|
|
6787
7295
|
var KIMI_WIRE_PROTOCOL_VERSION = "1.3";
|
|
6788
7296
|
var KIMI_SYSTEM_PROMPT_FILE = ".slock-kimi-system.md";
|
|
6789
7297
|
var KIMI_AGENT_FILE = ".slock-kimi-agent.yaml";
|
|
7298
|
+
var KIMI_GENERATED_CONFIG_FILE = ".slock-kimi-config.toml";
|
|
7299
|
+
var SLOCK_KIMI_CONFIG_CONTENT_ENV = "SLOCK_KIMI_CONFIG_CONTENT";
|
|
7300
|
+
var SLOCK_KIMI_CONFIG_FILE_ENV = "SLOCK_KIMI_CONFIG_FILE";
|
|
6790
7301
|
function parseToolArguments(raw) {
|
|
6791
7302
|
if (typeof raw !== "string") return raw;
|
|
6792
7303
|
try {
|
|
@@ -6795,6 +7306,73 @@ function parseToolArguments(raw) {
|
|
|
6795
7306
|
return raw;
|
|
6796
7307
|
}
|
|
6797
7308
|
}
|
|
7309
|
+
function readKimiConfigSource(home = os5.homedir(), env = process.env) {
|
|
7310
|
+
const inlineConfig = env[SLOCK_KIMI_CONFIG_CONTENT_ENV];
|
|
7311
|
+
if (inlineConfig && inlineConfig.trim()) {
|
|
7312
|
+
return {
|
|
7313
|
+
raw: inlineConfig,
|
|
7314
|
+
explicitPath: null,
|
|
7315
|
+
sourcePath: SLOCK_KIMI_CONFIG_CONTENT_ENV
|
|
7316
|
+
};
|
|
7317
|
+
}
|
|
7318
|
+
const explicitPath = env[SLOCK_KIMI_CONFIG_FILE_ENV];
|
|
7319
|
+
const configPath = explicitPath && explicitPath.trim() ? explicitPath : path9.join(home, ".kimi", "config.toml");
|
|
7320
|
+
try {
|
|
7321
|
+
return {
|
|
7322
|
+
raw: readFileSync3(configPath, "utf8"),
|
|
7323
|
+
explicitPath: explicitPath && explicitPath.trim() ? explicitPath : null,
|
|
7324
|
+
sourcePath: configPath
|
|
7325
|
+
};
|
|
7326
|
+
} catch {
|
|
7327
|
+
return {
|
|
7328
|
+
raw: null,
|
|
7329
|
+
explicitPath: explicitPath && explicitPath.trim() ? explicitPath : null,
|
|
7330
|
+
sourcePath: configPath
|
|
7331
|
+
};
|
|
7332
|
+
}
|
|
7333
|
+
}
|
|
7334
|
+
function buildKimiSpawnEnv(env = process.env) {
|
|
7335
|
+
const spawnEnv = { ...env, FORCE_COLOR: "0", NO_COLOR: "1" };
|
|
7336
|
+
delete spawnEnv[SLOCK_KIMI_CONFIG_CONTENT_ENV];
|
|
7337
|
+
delete spawnEnv[SLOCK_KIMI_CONFIG_FILE_ENV];
|
|
7338
|
+
return scrubDaemonChildEnv(spawnEnv);
|
|
7339
|
+
}
|
|
7340
|
+
function buildKimiEffectiveEnv(ctx, overrideEnv) {
|
|
7341
|
+
return {
|
|
7342
|
+
...process.env,
|
|
7343
|
+
...ctx.config.envVars || {},
|
|
7344
|
+
...overrideEnv || {}
|
|
7345
|
+
};
|
|
7346
|
+
}
|
|
7347
|
+
function buildKimiLaunchOptions(ctx, opts = {}) {
|
|
7348
|
+
const env = buildKimiEffectiveEnv(ctx, opts.env);
|
|
7349
|
+
const source = readKimiConfigSource(opts.home ?? os5.homedir(), env);
|
|
7350
|
+
const args = [];
|
|
7351
|
+
let configFilePath = null;
|
|
7352
|
+
let configContent = null;
|
|
7353
|
+
if (source.explicitPath) {
|
|
7354
|
+
configFilePath = source.explicitPath;
|
|
7355
|
+
} else if (source.raw !== null && source.sourcePath === SLOCK_KIMI_CONFIG_CONTENT_ENV) {
|
|
7356
|
+
configFilePath = path9.join(ctx.workingDirectory, KIMI_GENERATED_CONFIG_FILE);
|
|
7357
|
+
configContent = source.raw;
|
|
7358
|
+
if (opts.writeGeneratedConfig !== false) {
|
|
7359
|
+
writeFileSync3(configFilePath, source.raw, { encoding: "utf8", mode: 384 });
|
|
7360
|
+
chmodSync(configFilePath, 384);
|
|
7361
|
+
}
|
|
7362
|
+
}
|
|
7363
|
+
if (configFilePath) {
|
|
7364
|
+
args.push("--config-file", configFilePath);
|
|
7365
|
+
}
|
|
7366
|
+
if (ctx.config.model && ctx.config.model !== "default") {
|
|
7367
|
+
args.push("--model", ctx.config.model);
|
|
7368
|
+
}
|
|
7369
|
+
return {
|
|
7370
|
+
args,
|
|
7371
|
+
env: buildKimiSpawnEnv(env),
|
|
7372
|
+
configFilePath,
|
|
7373
|
+
configContent
|
|
7374
|
+
};
|
|
7375
|
+
}
|
|
6798
7376
|
function resolveKimiSpawn(commandArgs, deps = {}) {
|
|
6799
7377
|
return {
|
|
6800
7378
|
command: resolveCommandOnPath("kimi", deps) ?? "kimi",
|
|
@@ -6818,7 +7396,25 @@ var KimiDriver = class {
|
|
|
6818
7396
|
};
|
|
6819
7397
|
model = {
|
|
6820
7398
|
detectedModelsVerifiedAs: "launchable",
|
|
6821
|
-
toLaunchSpec: (modelId) =>
|
|
7399
|
+
toLaunchSpec: (modelId, ctx, opts) => {
|
|
7400
|
+
if (!ctx) return { args: ["--model", modelId] };
|
|
7401
|
+
const launchCtx = {
|
|
7402
|
+
...ctx,
|
|
7403
|
+
config: {
|
|
7404
|
+
...ctx.config,
|
|
7405
|
+
model: modelId
|
|
7406
|
+
}
|
|
7407
|
+
};
|
|
7408
|
+
const launch = buildKimiLaunchOptions(launchCtx, {
|
|
7409
|
+
home: opts?.home,
|
|
7410
|
+
writeGeneratedConfig: false
|
|
7411
|
+
});
|
|
7412
|
+
return {
|
|
7413
|
+
args: launch.args,
|
|
7414
|
+
env: launch.env,
|
|
7415
|
+
configFiles: launch.configFilePath ? [launch.configFilePath] : void 0
|
|
7416
|
+
};
|
|
7417
|
+
}
|
|
6822
7418
|
};
|
|
6823
7419
|
supportsStdinNotification = true;
|
|
6824
7420
|
busyDeliveryMode = "direct";
|
|
@@ -6830,8 +7426,8 @@ var KimiDriver = class {
|
|
|
6830
7426
|
this.sessionId = ctx.config.sessionId || randomUUID2();
|
|
6831
7427
|
this.sessionAnnounced = false;
|
|
6832
7428
|
this.promptRequestId = randomUUID2();
|
|
6833
|
-
const systemPromptPath =
|
|
6834
|
-
const agentFilePath =
|
|
7429
|
+
const systemPromptPath = path9.join(ctx.workingDirectory, KIMI_SYSTEM_PROMPT_FILE);
|
|
7430
|
+
const agentFilePath = path9.join(ctx.workingDirectory, KIMI_AGENT_FILE);
|
|
6835
7431
|
if (!isResume || !existsSync7(systemPromptPath)) {
|
|
6836
7432
|
writeFileSync3(systemPromptPath, ctx.prompt, "utf8");
|
|
6837
7433
|
}
|
|
@@ -6842,21 +7438,23 @@ var KimiDriver = class {
|
|
|
6842
7438
|
` system_prompt_path: ./${KIMI_SYSTEM_PROMPT_FILE}`,
|
|
6843
7439
|
""
|
|
6844
7440
|
].join("\n"), "utf8");
|
|
7441
|
+
const launch = buildKimiLaunchOptions(ctx);
|
|
6845
7442
|
const args = [
|
|
6846
7443
|
"--wire",
|
|
6847
7444
|
"--yolo",
|
|
6848
7445
|
"--agent-file",
|
|
6849
7446
|
agentFilePath,
|
|
6850
7447
|
"--session",
|
|
6851
|
-
this.sessionId
|
|
7448
|
+
this.sessionId,
|
|
7449
|
+
...launch.args
|
|
6852
7450
|
];
|
|
6853
7451
|
const launchRuntimeFields = runtimeConfigToLaunchFields(ctx.config);
|
|
6854
7452
|
if (launchRuntimeFields.model && launchRuntimeFields.model !== "default") {
|
|
6855
7453
|
args.push("--model", launchRuntimeFields.model);
|
|
6856
7454
|
}
|
|
6857
7455
|
const spawnEnv = (await prepareCliTransport(ctx, { NO_COLOR: "1" })).spawnEnv;
|
|
6858
|
-
const
|
|
6859
|
-
const proc = spawn7(
|
|
7456
|
+
const spawnTarget = resolveKimiSpawn(args);
|
|
7457
|
+
const proc = spawn7(spawnTarget.command, spawnTarget.args, {
|
|
6860
7458
|
cwd: ctx.workingDirectory,
|
|
6861
7459
|
stdio: ["pipe", "pipe", "pipe"],
|
|
6862
7460
|
env: spawnEnv,
|
|
@@ -6864,7 +7462,7 @@ var KimiDriver = class {
|
|
|
6864
7462
|
// and has an 8191-character command-line limit. Kimi's official
|
|
6865
7463
|
// installer/uv entrypoint is an executable, so launch it directly and
|
|
6866
7464
|
// keep prompts on stdin / files instead of routing through cmd.exe.
|
|
6867
|
-
shell:
|
|
7465
|
+
shell: spawnTarget.shell
|
|
6868
7466
|
});
|
|
6869
7467
|
proc.stdin?.write(JSON.stringify({
|
|
6870
7468
|
jsonrpc: "2.0",
|
|
@@ -6977,14 +7575,9 @@ var KimiDriver = class {
|
|
|
6977
7575
|
return detectKimiModels();
|
|
6978
7576
|
}
|
|
6979
7577
|
};
|
|
6980
|
-
function detectKimiModels(home =
|
|
6981
|
-
const
|
|
6982
|
-
|
|
6983
|
-
try {
|
|
6984
|
-
raw = readFileSync3(configPath, "utf8");
|
|
6985
|
-
} catch {
|
|
6986
|
-
return null;
|
|
6987
|
-
}
|
|
7578
|
+
function detectKimiModels(home = os5.homedir(), opts = {}) {
|
|
7579
|
+
const raw = readKimiConfigSource(home, opts.env).raw;
|
|
7580
|
+
if (raw === null) return null;
|
|
6988
7581
|
const models = [];
|
|
6989
7582
|
const sectionRe = /^\s*\[models(?:\.([^\]]+)|"\.[^"]+"|\."[^"]+")\s*\]\s*$/gm;
|
|
6990
7583
|
const lineRe = /^\s*\[models\.(.+?)\s*\]\s*$/gm;
|
|
@@ -7007,7 +7600,7 @@ function detectKimiModels(home = os4.homedir()) {
|
|
|
7007
7600
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
7008
7601
|
import { EventEmitter } from "events";
|
|
7009
7602
|
import { mkdirSync as mkdirSync3, readFileSync as readFileSync4 } from "fs";
|
|
7010
|
-
import
|
|
7603
|
+
import path10 from "path";
|
|
7011
7604
|
import { createRequire as createRequire2 } from "module";
|
|
7012
7605
|
import {
|
|
7013
7606
|
createKimiHarness,
|
|
@@ -7032,7 +7625,7 @@ function createKimiSdkEventMappingState(sessionId = null) {
|
|
|
7032
7625
|
};
|
|
7033
7626
|
}
|
|
7034
7627
|
function buildKimiSessionDir(workingDirectory) {
|
|
7035
|
-
return
|
|
7628
|
+
return path10.join(workingDirectory, KIMI_SESSION_DIR);
|
|
7036
7629
|
}
|
|
7037
7630
|
function kimiErrorMessage(error) {
|
|
7038
7631
|
if (typeof error === "string" && error.trim()) return error.trim();
|
|
@@ -7159,7 +7752,7 @@ async function createKimiAgentSessionForContext(ctx, sessionId) {
|
|
|
7159
7752
|
const cliTransport = await prepareCliTransport(ctx, { NO_COLOR: "1" });
|
|
7160
7753
|
const spawnEnv = cliTransport.spawnEnv;
|
|
7161
7754
|
const wrapperPath = cliTransport.wrapperPath;
|
|
7162
|
-
const homeDir = spawnEnv.KIMI_HOME || (process.env.HOME ?
|
|
7755
|
+
const homeDir = spawnEnv.KIMI_HOME || (process.env.HOME ? path10.join(process.env.HOME, ".kimi") : path10.join(ctx.workingDirectory, ".kimi"));
|
|
7163
7756
|
mkdirSync3(homeDir, { recursive: true });
|
|
7164
7757
|
const harness = createKimiHarness({
|
|
7165
7758
|
homeDir,
|
|
@@ -7384,7 +7977,7 @@ So instead of \`raft message send ...\`, run \`${this.wrapperPath} message send
|
|
|
7384
7977
|
};
|
|
7385
7978
|
function detectKimiSdkModels(home = resolveKimiHome(), ctx = {}) {
|
|
7386
7979
|
const span = ctx.span;
|
|
7387
|
-
const configPath =
|
|
7980
|
+
const configPath = path10.join(home, "config.toml");
|
|
7388
7981
|
const homeFromEnv = Boolean(process.env.KIMI_CODE_HOME);
|
|
7389
7982
|
const emit2 = (outcome, extra = {}) => {
|
|
7390
7983
|
span?.addEvent("daemon.kimi_sdk.models.config", {
|
|
@@ -7492,8 +8085,8 @@ var KimiSdkDriver = class {
|
|
|
7492
8085
|
// src/drivers/opencode.ts
|
|
7493
8086
|
import { spawn as spawn8, spawnSync as spawnSync2 } from "child_process";
|
|
7494
8087
|
import { existsSync as existsSync8, readFileSync as readFileSync5 } from "fs";
|
|
7495
|
-
import
|
|
7496
|
-
import
|
|
8088
|
+
import os6 from "os";
|
|
8089
|
+
import path11 from "path";
|
|
7497
8090
|
var SLOCK_AGENT_NAME = "slock";
|
|
7498
8091
|
var NO_MESSAGE_PROMPT = "No new messages are pending. Stop now.";
|
|
7499
8092
|
var FIRST_MESSAGE_TASK_PREFIX = "First message task (system-triggered):";
|
|
@@ -7521,8 +8114,8 @@ function parseUserOpenCodeConfig(ctx) {
|
|
|
7521
8114
|
const raw = runtimeConfigToLaunchFields(ctx.config).envVars?.OPENCODE_CONFIG_CONTENT;
|
|
7522
8115
|
return parseOpenCodeConfigContent(raw);
|
|
7523
8116
|
}
|
|
7524
|
-
function readLocalOpenCodeConfig(home =
|
|
7525
|
-
const configPath =
|
|
8117
|
+
function readLocalOpenCodeConfig(home = os6.homedir()) {
|
|
8118
|
+
const configPath = path11.join(home, ".config", "opencode", "opencode.json");
|
|
7526
8119
|
try {
|
|
7527
8120
|
return parseOpenCodeConfigContent(readFileSync5(configPath, "utf8"));
|
|
7528
8121
|
} catch {
|
|
@@ -7582,7 +8175,7 @@ function mergeOpenCodeConfigs(localConfig, envConfig) {
|
|
|
7582
8175
|
}
|
|
7583
8176
|
};
|
|
7584
8177
|
}
|
|
7585
|
-
function buildOpenCodeConfig(ctx, home =
|
|
8178
|
+
function buildOpenCodeConfig(ctx, home = os6.homedir()) {
|
|
7586
8179
|
const userConfig = mergeOpenCodeConfigs(readLocalOpenCodeConfig(home), parseUserOpenCodeConfig(ctx));
|
|
7587
8180
|
const userAgents = recordField(userConfig.agent);
|
|
7588
8181
|
const userSlockAgent = recordField(userAgents[SLOCK_AGENT_NAME]);
|
|
@@ -7600,7 +8193,7 @@ function buildOpenCodeConfig(ctx, home = os5.homedir()) {
|
|
|
7600
8193
|
mcp: recordField(userConfig.mcp)
|
|
7601
8194
|
};
|
|
7602
8195
|
}
|
|
7603
|
-
async function buildOpenCodeLaunchOptions(ctx, home =
|
|
8196
|
+
async function buildOpenCodeLaunchOptions(ctx, home = os6.homedir(), version = null) {
|
|
7604
8197
|
const slock = await prepareCliTransport(ctx, { NO_COLOR: "1" });
|
|
7605
8198
|
const config = buildOpenCodeConfig(ctx, home);
|
|
7606
8199
|
const env = {
|
|
@@ -7699,7 +8292,7 @@ function formatOpenCodeLabelToken(token) {
|
|
|
7699
8292
|
if (/^\d/.test(token)) return token;
|
|
7700
8293
|
return normalized.charAt(0).toUpperCase() + normalized.slice(1);
|
|
7701
8294
|
}
|
|
7702
|
-
function detectOpenCodeModels(home =
|
|
8295
|
+
function detectOpenCodeModels(home = os6.homedir(), runCommand = runOpenCodeModelsCommand) {
|
|
7703
8296
|
const commandResult = runCommand(home);
|
|
7704
8297
|
if (commandResult.error || commandResult.status !== 0) return null;
|
|
7705
8298
|
return parseOpenCodeModelsOutput(commandResult.stdout);
|
|
@@ -7708,7 +8301,7 @@ function runOpenCodeModelsCommand(home, deps = {}) {
|
|
|
7708
8301
|
const platform = deps.platform ?? process.platform;
|
|
7709
8302
|
const spawnSyncFn = deps.spawnSyncFn ?? spawnSync2;
|
|
7710
8303
|
const result = spawnSyncFn("opencode", ["models"], {
|
|
7711
|
-
env: { ...process.env, HOME: home, FORCE_COLOR: "0", NO_COLOR: "1" },
|
|
8304
|
+
env: scrubDaemonChildEnv({ ...process.env, HOME: home, FORCE_COLOR: "0", NO_COLOR: "1" }),
|
|
7712
8305
|
encoding: "utf8",
|
|
7713
8306
|
timeout: 5e3,
|
|
7714
8307
|
shell: platform === "win32"
|
|
@@ -7720,11 +8313,11 @@ function runOpenCodeModelsCommand(home, deps = {}) {
|
|
|
7720
8313
|
};
|
|
7721
8314
|
}
|
|
7722
8315
|
function isWindowsCommandShim(commandPath) {
|
|
7723
|
-
const ext =
|
|
8316
|
+
const ext = path11.win32.extname(commandPath).toLowerCase();
|
|
7724
8317
|
return ext === ".cmd" || ext === ".bat";
|
|
7725
8318
|
}
|
|
7726
8319
|
function opencodePackageEntryCandidates(packageRoot) {
|
|
7727
|
-
const winPath =
|
|
8320
|
+
const winPath = path11.win32;
|
|
7728
8321
|
return [
|
|
7729
8322
|
winPath.join(packageRoot, "bin", "opencode.exe"),
|
|
7730
8323
|
winPath.join(packageRoot, "bin", "opencode.js"),
|
|
@@ -7733,7 +8326,7 @@ function opencodePackageEntryCandidates(packageRoot) {
|
|
|
7733
8326
|
];
|
|
7734
8327
|
}
|
|
7735
8328
|
function openCodeSpecForEntry(entry, commandArgs) {
|
|
7736
|
-
if (
|
|
8329
|
+
if (path11.win32.extname(entry).toLowerCase() === ".exe") {
|
|
7737
8330
|
return { command: entry, args: commandArgs, shell: false };
|
|
7738
8331
|
}
|
|
7739
8332
|
return { command: process.execPath, args: [entry, ...commandArgs], shell: false };
|
|
@@ -7742,7 +8335,7 @@ function resolveWindowsOpenCodePackageEntry(commandPath, deps = {}) {
|
|
|
7742
8335
|
const existsSyncFn = deps.existsSyncFn ?? existsSync8;
|
|
7743
8336
|
const execFileSyncFn = deps.execFileSyncFn;
|
|
7744
8337
|
const env = deps.env ?? process.env;
|
|
7745
|
-
const winPath =
|
|
8338
|
+
const winPath = path11.win32;
|
|
7746
8339
|
const candidates = [];
|
|
7747
8340
|
if (execFileSyncFn) {
|
|
7748
8341
|
try {
|
|
@@ -7770,7 +8363,7 @@ function resolveWindowsOpenCodePackageEntry(commandPath, deps = {}) {
|
|
|
7770
8363
|
function extractWindowsShimTargets(commandPath, deps = {}) {
|
|
7771
8364
|
if (!isWindowsCommandShim(commandPath)) return [];
|
|
7772
8365
|
const readFileSyncFn = deps.readFileSyncFn ?? readFileSync5;
|
|
7773
|
-
const commandDir =
|
|
8366
|
+
const commandDir = path11.win32.dirname(commandPath);
|
|
7774
8367
|
let raw;
|
|
7775
8368
|
try {
|
|
7776
8369
|
raw = String(readFileSyncFn(commandPath, "utf8"));
|
|
@@ -7781,7 +8374,7 @@ function extractWindowsShimTargets(commandPath, deps = {}) {
|
|
|
7781
8374
|
const dp0Pattern = /%~dp0\\?([^"\r\n]*?opencode\.(?:exe|js|mjs|cjs))/gi;
|
|
7782
8375
|
for (const match of raw.matchAll(dp0Pattern)) {
|
|
7783
8376
|
const relative = match[1]?.replace(/^\\+/, "");
|
|
7784
|
-
if (relative) candidates.push(
|
|
8377
|
+
if (relative) candidates.push(path11.win32.normalize(path11.win32.join(commandDir, relative)));
|
|
7785
8378
|
}
|
|
7786
8379
|
return candidates;
|
|
7787
8380
|
}
|
|
@@ -7795,7 +8388,7 @@ function resolveOpenCodeSpawn(commandArgs, deps = {}) {
|
|
|
7795
8388
|
};
|
|
7796
8389
|
}
|
|
7797
8390
|
const command = resolveCommandOnPath("opencode", deps);
|
|
7798
|
-
if (command &&
|
|
8391
|
+
if (command && path11.win32.extname(command).toLowerCase() === ".exe") {
|
|
7799
8392
|
return { command, args: commandArgs, shell: false };
|
|
7800
8393
|
}
|
|
7801
8394
|
const packageEntry = resolveWindowsOpenCodePackageEntry(command, deps);
|
|
@@ -7900,7 +8493,7 @@ var OpenCodeDriver = class {
|
|
|
7900
8493
|
if (unsupportedMessage) {
|
|
7901
8494
|
throw new Error(unsupportedMessage);
|
|
7902
8495
|
}
|
|
7903
|
-
const launch = await buildOpenCodeLaunchOptions(ctx,
|
|
8496
|
+
const launch = await buildOpenCodeLaunchOptions(ctx, os6.homedir(), version);
|
|
7904
8497
|
const spawnSpec = resolveOpenCodeSpawn(launch.args);
|
|
7905
8498
|
const proc = spawn8(spawnSpec.command, spawnSpec.args, {
|
|
7906
8499
|
cwd: ctx.workingDirectory,
|
|
@@ -7968,7 +8561,7 @@ var OpenCodeDriver = class {
|
|
|
7968
8561
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
7969
8562
|
import { EventEmitter as EventEmitter2 } from "events";
|
|
7970
8563
|
import { mkdirSync as mkdirSync4, readdirSync as readdirSync2 } from "fs";
|
|
7971
|
-
import
|
|
8564
|
+
import path12 from "path";
|
|
7972
8565
|
import {
|
|
7973
8566
|
AuthStorage,
|
|
7974
8567
|
createBashTool,
|
|
@@ -7995,7 +8588,7 @@ function createPiSdkEventMappingState(sessionId = null) {
|
|
|
7995
8588
|
};
|
|
7996
8589
|
}
|
|
7997
8590
|
function buildPiSessionDir(workingDirectory) {
|
|
7998
|
-
return
|
|
8591
|
+
return path12.join(workingDirectory, PI_SESSION_DIR);
|
|
7999
8592
|
}
|
|
8000
8593
|
async function buildPiSpawnEnv(ctx) {
|
|
8001
8594
|
return (await prepareCliTransport(ctx, { NO_COLOR: "1" })).spawnEnv;
|
|
@@ -8017,7 +8610,7 @@ function findPiSessionFile(sessionDir, sessionId) {
|
|
|
8017
8610
|
}
|
|
8018
8611
|
const suffix = `_${sessionId}.jsonl`;
|
|
8019
8612
|
const match = entries.find((entry) => entry.endsWith(suffix));
|
|
8020
|
-
return match ?
|
|
8613
|
+
return match ? path12.join(sessionDir, match) : null;
|
|
8021
8614
|
}
|
|
8022
8615
|
function detectPiModelsFromRegistry(modelRegistry) {
|
|
8023
8616
|
const models = [];
|
|
@@ -8253,7 +8846,7 @@ async function createPiAgentSessionForContext(ctx, sessionId) {
|
|
|
8253
8846
|
try {
|
|
8254
8847
|
const spawnEnv = await buildPiSpawnEnv(ctx);
|
|
8255
8848
|
const agentDir = spawnEnv.PI_CODING_AGENT_DIR || getAgentDir();
|
|
8256
|
-
const authStorage = AuthStorage.create(
|
|
8849
|
+
const authStorage = AuthStorage.create(path12.join(agentDir, "auth.json"));
|
|
8257
8850
|
const settingsManager = SettingsManager.create(ctx.workingDirectory, agentDir);
|
|
8258
8851
|
const services = await createAgentSessionServices({
|
|
8259
8852
|
cwd: ctx.workingDirectory,
|
|
@@ -8652,6 +9245,9 @@ var ChildProcessRuntimeSession = class {
|
|
|
8652
9245
|
get currentSessionId() {
|
|
8653
9246
|
return this.driver.currentSessionId;
|
|
8654
9247
|
}
|
|
9248
|
+
get currentRuntimeHomeDir() {
|
|
9249
|
+
return this.driver.currentRuntimeHomeDir;
|
|
9250
|
+
}
|
|
8655
9251
|
get exitCode() {
|
|
8656
9252
|
return this.process?.exitCode ?? null;
|
|
8657
9253
|
}
|
|
@@ -8775,7 +9371,7 @@ function getDriver(runtimeId) {
|
|
|
8775
9371
|
|
|
8776
9372
|
// src/workspaces.ts
|
|
8777
9373
|
import { readdir, rm, stat } from "fs/promises";
|
|
8778
|
-
import
|
|
9374
|
+
import path13 from "path";
|
|
8779
9375
|
function isValidWorkspaceDirectoryName(directoryName) {
|
|
8780
9376
|
return !directoryName.includes("/") && !directoryName.includes("\\") && !directoryName.includes("..");
|
|
8781
9377
|
}
|
|
@@ -8783,7 +9379,7 @@ function resolveWorkspaceDirectoryPath(dataDir, directoryName) {
|
|
|
8783
9379
|
if (!isValidWorkspaceDirectoryName(directoryName)) {
|
|
8784
9380
|
return null;
|
|
8785
9381
|
}
|
|
8786
|
-
return
|
|
9382
|
+
return path13.join(dataDir, directoryName);
|
|
8787
9383
|
}
|
|
8788
9384
|
function emptyWorkspaceDirectorySummary(latestMtime = /* @__PURE__ */ new Date(0)) {
|
|
8789
9385
|
return {
|
|
@@ -8832,7 +9428,7 @@ async function summarizeWorkspaceDirectory(dirPath) {
|
|
|
8832
9428
|
return summary;
|
|
8833
9429
|
}
|
|
8834
9430
|
const childSummaries = await Promise.all(
|
|
8835
|
-
entries.map((entry) => summarizeWorkspaceEntry(
|
|
9431
|
+
entries.map((entry) => summarizeWorkspaceEntry(path13.join(dirPath, entry.name), entry))
|
|
8836
9432
|
);
|
|
8837
9433
|
for (const childSummary of childSummaries) {
|
|
8838
9434
|
summary = mergeWorkspaceDirectorySummaries(summary, childSummary);
|
|
@@ -8851,7 +9447,7 @@ async function scanWorkspaceDirectories(dataDir) {
|
|
|
8851
9447
|
if (!entry.isDirectory()) {
|
|
8852
9448
|
return null;
|
|
8853
9449
|
}
|
|
8854
|
-
const dirPath =
|
|
9450
|
+
const dirPath = path13.join(dataDir, entry.name);
|
|
8855
9451
|
try {
|
|
8856
9452
|
const summary = await summarizeWorkspaceDirectory(dirPath);
|
|
8857
9453
|
return {
|
|
@@ -9400,17 +9996,17 @@ function allowedTranscriptRootsForRuntime(runtime, homeDir, workspaceDir) {
|
|
|
9400
9996
|
const roots = [workspaceDir];
|
|
9401
9997
|
switch (runtime) {
|
|
9402
9998
|
case "claude":
|
|
9403
|
-
roots.push(
|
|
9999
|
+
roots.push(path14.join(homeDir, ".claude"));
|
|
9404
10000
|
break;
|
|
9405
10001
|
case "codex":
|
|
9406
|
-
roots.push(
|
|
10002
|
+
roots.push(homeDir, path14.join(homeDir, ".codex"));
|
|
9407
10003
|
break;
|
|
9408
10004
|
case "kimi":
|
|
9409
10005
|
case "kimi-sdk":
|
|
9410
|
-
roots.push(
|
|
10006
|
+
roots.push(path14.join(homeDir, ".kimi"));
|
|
9411
10007
|
break;
|
|
9412
10008
|
case "pi":
|
|
9413
|
-
roots.push(
|
|
10009
|
+
roots.push(path14.join(homeDir, ".pi"), path14.join(homeDir, ".pi", "agent"));
|
|
9414
10010
|
break;
|
|
9415
10011
|
}
|
|
9416
10012
|
return roots;
|
|
@@ -9421,8 +10017,8 @@ async function isPathWithinAllowedRoots(filePath, roots) {
|
|
|
9421
10017
|
for (const root of roots) {
|
|
9422
10018
|
const realRoot = await realpath(root).catch(() => null);
|
|
9423
10019
|
if (!realRoot) continue;
|
|
9424
|
-
const rel =
|
|
9425
|
-
if (!rel.startsWith("..") && !
|
|
10020
|
+
const rel = path14.relative(realRoot, real);
|
|
10021
|
+
if (!rel.startsWith("..") && !path14.isAbsolute(rel)) return true;
|
|
9426
10022
|
}
|
|
9427
10023
|
return false;
|
|
9428
10024
|
}
|
|
@@ -9469,12 +10065,12 @@ function findSessionJsonl(root, predicate) {
|
|
|
9469
10065
|
for (const entry of entries) {
|
|
9470
10066
|
if (++visited > maxEntries) return null;
|
|
9471
10067
|
if (!entry.isFile() || !predicate(entry.name)) continue;
|
|
9472
|
-
return
|
|
10068
|
+
return path14.join(dir, entry.name);
|
|
9473
10069
|
}
|
|
9474
10070
|
for (const entry of entries) {
|
|
9475
10071
|
if (++visited > maxEntries) return null;
|
|
9476
10072
|
if (!entry.isDirectory()) continue;
|
|
9477
|
-
const found = visit(
|
|
10073
|
+
const found = visit(path14.join(dir, entry.name), depth - 1);
|
|
9478
10074
|
if (found) return found;
|
|
9479
10075
|
}
|
|
9480
10076
|
return null;
|
|
@@ -9482,7 +10078,7 @@ function findSessionJsonl(root, predicate) {
|
|
|
9482
10078
|
return visit(root, maxDepth);
|
|
9483
10079
|
}
|
|
9484
10080
|
function findKimiSdkSessionDir(sessionId, agentId, homeDir) {
|
|
9485
|
-
const indexPath =
|
|
10081
|
+
const indexPath = path14.join(homeDir, ".kimi", "session_index.jsonl");
|
|
9486
10082
|
try {
|
|
9487
10083
|
const index = readFileSync6(indexPath, "utf8");
|
|
9488
10084
|
for (const line of index.split("\n")) {
|
|
@@ -9497,12 +10093,12 @@ function findKimiSdkSessionDir(sessionId, agentId, homeDir) {
|
|
|
9497
10093
|
}
|
|
9498
10094
|
} catch {
|
|
9499
10095
|
}
|
|
9500
|
-
const sessionsRoot =
|
|
10096
|
+
const sessionsRoot = path14.join(homeDir, ".kimi", "sessions");
|
|
9501
10097
|
try {
|
|
9502
10098
|
const prefix = agentId ? `wd_${agentId}_` : `wd_`;
|
|
9503
10099
|
for (const entry of readdirSync3(sessionsRoot, { withFileTypes: true })) {
|
|
9504
10100
|
if (!entry.isDirectory() || !entry.name.startsWith(prefix)) continue;
|
|
9505
|
-
const candidate =
|
|
10101
|
+
const candidate = path14.join(sessionsRoot, entry.name, `session_${sessionId}`);
|
|
9506
10102
|
if (existsSync9(candidate)) return candidate;
|
|
9507
10103
|
}
|
|
9508
10104
|
} catch {
|
|
@@ -9511,16 +10107,16 @@ function findKimiSdkSessionDir(sessionId, agentId, homeDir) {
|
|
|
9511
10107
|
}
|
|
9512
10108
|
function findPiSessionFile2(sessionId, workingDirectory, homeDir) {
|
|
9513
10109
|
if (workingDirectory) {
|
|
9514
|
-
const piSessionsDir =
|
|
10110
|
+
const piSessionsDir = path14.join(workingDirectory, ".pi-sessions");
|
|
9515
10111
|
try {
|
|
9516
|
-
const files = readdirSync3(piSessionsDir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => ({ name: e.name, path:
|
|
10112
|
+
const files = readdirSync3(piSessionsDir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl")).map((e) => ({ name: e.name, path: path14.join(piSessionsDir, e.name), stat: statSync(path14.join(piSessionsDir, e.name)) })).filter((f) => f.stat.isFile() && f.name.includes(sessionId)).sort((a, b) => b.stat.mtimeMs - a.stat.mtimeMs);
|
|
9517
10113
|
if (files[0]) return files[0].path;
|
|
9518
10114
|
} catch {
|
|
9519
10115
|
}
|
|
9520
10116
|
}
|
|
9521
10117
|
const legacyRoots = [
|
|
9522
|
-
|
|
9523
|
-
|
|
10118
|
+
path14.join(homeDir, ".pi", "agent"),
|
|
10119
|
+
path14.join(homeDir, ".pi")
|
|
9524
10120
|
];
|
|
9525
10121
|
for (const root of legacyRoots) {
|
|
9526
10122
|
const found = findSessionJsonl(root, (filename) => filename.endsWith(".jsonl") && filename.includes(sessionId));
|
|
@@ -9534,9 +10130,9 @@ function safeSessionFilename(value) {
|
|
|
9534
10130
|
}
|
|
9535
10131
|
function writeRuntimeSessionHandoff(runtime, sessionId, fallbackDir) {
|
|
9536
10132
|
try {
|
|
9537
|
-
const dir =
|
|
10133
|
+
const dir = path14.join(fallbackDir, ".slock", "runtime-sessions");
|
|
9538
10134
|
mkdirSync5(dir, { recursive: true });
|
|
9539
|
-
const filePath =
|
|
10135
|
+
const filePath = path14.join(dir, `${runtime}-${safeSessionFilename(sessionId)}.jsonl`);
|
|
9540
10136
|
writeFileSync4(filePath, JSON.stringify({
|
|
9541
10137
|
type: "runtime_session_handoff",
|
|
9542
10138
|
runtime,
|
|
@@ -9555,27 +10151,40 @@ function writeRuntimeSessionHandoff(runtime, sessionId, fallbackDir) {
|
|
|
9555
10151
|
return null;
|
|
9556
10152
|
}
|
|
9557
10153
|
}
|
|
9558
|
-
function resolveRuntimeHomeDir(config, defaultHomeDir, workspacePath) {
|
|
10154
|
+
function resolveRuntimeHomeDir(config, defaultHomeDir, workspacePath, opts = {}) {
|
|
9559
10155
|
if (isClaudeCustomProviderConfig(config)) {
|
|
9560
10156
|
return getClaudeProviderStatePaths(workspacePath).home;
|
|
9561
10157
|
}
|
|
10158
|
+
if (config.runtime === "codex") {
|
|
10159
|
+
return resolveCodexHomeRootFromConfig(config, defaultHomeDir, workspacePath, process.env, opts);
|
|
10160
|
+
}
|
|
9562
10161
|
return defaultHomeDir;
|
|
9563
10162
|
}
|
|
9564
|
-
function ensureRuntimeHomeDir(config, defaultHomeDir, workspacePath) {
|
|
10163
|
+
function ensureRuntimeHomeDir(config, defaultHomeDir, workspacePath, opts = {}) {
|
|
9565
10164
|
if (isClaudeCustomProviderConfig(config)) {
|
|
9566
10165
|
return ensureClaudeProviderStatePaths(workspacePath).home;
|
|
9567
10166
|
}
|
|
10167
|
+
if (config.runtime === "codex") {
|
|
10168
|
+
const home = resolveCodexHomeRootFromConfig(config, defaultHomeDir, workspacePath, process.env, opts);
|
|
10169
|
+
if (opts.agentId) {
|
|
10170
|
+
mkdirSync5(home, { recursive: true });
|
|
10171
|
+
}
|
|
10172
|
+
return home;
|
|
10173
|
+
}
|
|
9568
10174
|
return defaultHomeDir;
|
|
9569
10175
|
}
|
|
9570
|
-
function resolveRuntimeSessionRef(runtime, sessionId, homeDir =
|
|
10176
|
+
function resolveRuntimeSessionRef(runtime, sessionId, homeDir = os7.homedir(), fallbackDir, opts) {
|
|
9571
10177
|
let resolvedPath = null;
|
|
9572
10178
|
let lookupMethod = "none";
|
|
9573
10179
|
if (runtime === "claude") {
|
|
9574
10180
|
lookupMethod = "claude_jsonl";
|
|
9575
|
-
resolvedPath = findSessionJsonl(
|
|
10181
|
+
resolvedPath = findSessionJsonl(path14.join(homeDir, ".claude", "projects"), (filename) => filename === `${sessionId}.jsonl`);
|
|
9576
10182
|
} else if (runtime === "codex") {
|
|
9577
10183
|
lookupMethod = "codex_jsonl";
|
|
9578
|
-
|
|
10184
|
+
for (const root of codexSessionRootCandidates(homeDir)) {
|
|
10185
|
+
resolvedPath = findSessionJsonl(root, (filename) => filename.endsWith(".jsonl") && filename.includes(sessionId));
|
|
10186
|
+
if (resolvedPath) break;
|
|
10187
|
+
}
|
|
9579
10188
|
} else if (runtime === "kimi-sdk" || runtime === "kimi") {
|
|
9580
10189
|
lookupMethod = "kimi_sdk_index";
|
|
9581
10190
|
resolvedPath = findKimiSdkSessionDir(sessionId, opts?.agentId, homeDir);
|
|
@@ -10312,6 +10921,28 @@ function runtimeDiagnosticTraceAttrs(event) {
|
|
|
10312
10921
|
session_id_present: Boolean(event.sessionId)
|
|
10313
10922
|
};
|
|
10314
10923
|
}
|
|
10924
|
+
function runtimeRecoveryTrajectoryEntry(event) {
|
|
10925
|
+
const lines = [event.message];
|
|
10926
|
+
if (event.details && event.details !== event.message) {
|
|
10927
|
+
lines.push(event.details);
|
|
10928
|
+
}
|
|
10929
|
+
return {
|
|
10930
|
+
kind: "system",
|
|
10931
|
+
title: "Codex resume recovery",
|
|
10932
|
+
text: lines.join("\n")
|
|
10933
|
+
};
|
|
10934
|
+
}
|
|
10935
|
+
function runtimeRecoveryTraceAttrs(event) {
|
|
10936
|
+
return {
|
|
10937
|
+
kind: event.kind,
|
|
10938
|
+
source: event.source,
|
|
10939
|
+
resume_error_class: event.resumeErrorClass,
|
|
10940
|
+
recovery_action: event.recoveryAction,
|
|
10941
|
+
requested_session_id_present: Boolean(event.requestedSessionId),
|
|
10942
|
+
message_present: Boolean(event.message),
|
|
10943
|
+
details_present: Boolean(event.details)
|
|
10944
|
+
};
|
|
10945
|
+
}
|
|
10315
10946
|
function currentErrorCandidates(ap) {
|
|
10316
10947
|
return [
|
|
10317
10948
|
ap.runtimeErrorSinceProgress ? ap.lastRuntimeError : null,
|
|
@@ -10635,6 +11266,7 @@ var AgentProcessManager = class _AgentProcessManager {
|
|
|
10635
11266
|
sendToServer;
|
|
10636
11267
|
daemonApiKey;
|
|
10637
11268
|
serverUrl;
|
|
11269
|
+
slockHome;
|
|
10638
11270
|
dataDir;
|
|
10639
11271
|
runtimeSessionHomeDir;
|
|
10640
11272
|
driverResolver;
|
|
@@ -10664,8 +11296,9 @@ var AgentProcessManager = class _AgentProcessManager {
|
|
|
10664
11296
|
this.sendToServer = sendToServer;
|
|
10665
11297
|
this.daemonApiKey = daemonApiKey;
|
|
10666
11298
|
this.serverUrl = opts.serverUrl;
|
|
10667
|
-
this.
|
|
10668
|
-
this.
|
|
11299
|
+
this.slockHome = opts.slockHome ? path14.resolve(opts.slockHome) : resolveSlockHome();
|
|
11300
|
+
this.dataDir = opts.dataDir || resolveSlockHomePath("agents", this.slockHome);
|
|
11301
|
+
this.runtimeSessionHomeDir = opts.runtimeSessionHomeDir || os7.homedir();
|
|
10669
11302
|
this.driverResolver = opts.driverResolver || getDriver;
|
|
10670
11303
|
this.defaultAgentEnvVarsProvider = opts.defaultAgentEnvVarsProvider || null;
|
|
10671
11304
|
this.tracer = opts.tracer ?? noopTracer;
|
|
@@ -10794,6 +11427,70 @@ var AgentProcessManager = class _AgentProcessManager {
|
|
|
10794
11427
|
this.sendStdinNotification(agentId);
|
|
10795
11428
|
}, delayMs);
|
|
10796
11429
|
}
|
|
11430
|
+
flushAsyncRejectedIdleDelivery(agentId) {
|
|
11431
|
+
const ap = this.agents.get(agentId);
|
|
11432
|
+
if (!ap) return false;
|
|
11433
|
+
const count = ap.notifications.takePendingAndClearTimer();
|
|
11434
|
+
if (count === 0) return false;
|
|
11435
|
+
if (!ap.driver.supportsStdinNotification || !ap.sessionId || ap.inbox.length === 0) {
|
|
11436
|
+
ap.notifications.add(count);
|
|
11437
|
+
this.recordDaemonTrace("daemon.agent.stdin_delivery.async_rejected.retry", {
|
|
11438
|
+
agentId,
|
|
11439
|
+
runtime: ap.config.runtime,
|
|
11440
|
+
model: ap.config.model,
|
|
11441
|
+
launchId: ap.launchId || void 0,
|
|
11442
|
+
mode: "idle",
|
|
11443
|
+
outcome: "queued_without_stdin",
|
|
11444
|
+
inbox_count: ap.inbox.length,
|
|
11445
|
+
pending_notification_count: ap.notifications.pendingCount,
|
|
11446
|
+
session_id_present: Boolean(ap.sessionId),
|
|
11447
|
+
supports_stdin_notification: ap.driver.supportsStdinNotification
|
|
11448
|
+
});
|
|
11449
|
+
return false;
|
|
11450
|
+
}
|
|
11451
|
+
if (!this.isApmIdle(ap)) {
|
|
11452
|
+
ap.notifications.add(count);
|
|
11453
|
+
return this.sendStdinNotification(agentId, { forceUnsupportedRetry: true });
|
|
11454
|
+
}
|
|
11455
|
+
ap.notifications.pruneContributedToPending(ap.inbox, ap.sessionId);
|
|
11456
|
+
const messages = ap.notifications.filterUncontributedMessages(ap.inbox, ap.sessionId);
|
|
11457
|
+
if (messages.length === 0) {
|
|
11458
|
+
this.recordDaemonTrace("daemon.agent.stdin_delivery.async_rejected.retry", {
|
|
11459
|
+
agentId,
|
|
11460
|
+
runtime: ap.config.runtime,
|
|
11461
|
+
model: ap.config.model,
|
|
11462
|
+
launchId: ap.launchId || void 0,
|
|
11463
|
+
mode: "idle",
|
|
11464
|
+
outcome: "suppressed_already_contributed",
|
|
11465
|
+
inbox_count: ap.inbox.length,
|
|
11466
|
+
pending_notification_count: count,
|
|
11467
|
+
session_id_present: true
|
|
11468
|
+
});
|
|
11469
|
+
return false;
|
|
11470
|
+
}
|
|
11471
|
+
this.commitApmIdleState(agentId, ap, false);
|
|
11472
|
+
this.startRuntimeTrace(agentId, ap, "async-rejected-idle-delivery-retry", messages);
|
|
11473
|
+
this.broadcastActivity(agentId, "working", "Message received");
|
|
11474
|
+
const accepted = this.deliverInboxUpdateViaStdin(
|
|
11475
|
+
agentId,
|
|
11476
|
+
ap,
|
|
11477
|
+
messages,
|
|
11478
|
+
"idle",
|
|
11479
|
+
"async_rejected_idle_delivery_retry"
|
|
11480
|
+
);
|
|
11481
|
+
this.recordDaemonTrace("daemon.agent.stdin_delivery.async_rejected.retry", {
|
|
11482
|
+
agentId,
|
|
11483
|
+
runtime: ap.config.runtime,
|
|
11484
|
+
model: ap.config.model,
|
|
11485
|
+
launchId: ap.launchId || void 0,
|
|
11486
|
+
mode: "idle",
|
|
11487
|
+
outcome: accepted ? "written" : "not_written",
|
|
11488
|
+
inbox_count: ap.inbox.length,
|
|
11489
|
+
messages_count: messages.length,
|
|
11490
|
+
session_id_present: true
|
|
11491
|
+
});
|
|
11492
|
+
return accepted;
|
|
11493
|
+
}
|
|
10797
11494
|
isApmIdle(ap) {
|
|
10798
11495
|
return ap.gatedSteering.isIdle;
|
|
10799
11496
|
}
|
|
@@ -11252,6 +11949,23 @@ var AgentProcessManager = class _AgentProcessManager {
|
|
|
11252
11949
|
...runtimeDiagnosticTraceAttrs(event)
|
|
11253
11950
|
});
|
|
11254
11951
|
}
|
|
11952
|
+
recordRuntimeRecoveryActivity(agentId, ap, event) {
|
|
11953
|
+
this.sendToServer({
|
|
11954
|
+
type: "agent:activity",
|
|
11955
|
+
agentId,
|
|
11956
|
+
activity: ap.lastActivity || "online",
|
|
11957
|
+
detail: ap.lastActivityDetail || "",
|
|
11958
|
+
entries: [runtimeRecoveryTrajectoryEntry(event)],
|
|
11959
|
+
launchId: ap.launchId || void 0,
|
|
11960
|
+
clientSeq: this.nextActivityClientSeq(agentId)
|
|
11961
|
+
});
|
|
11962
|
+
this.recordDaemonTrace("daemon.runtime.recovery.visible", {
|
|
11963
|
+
agentId,
|
|
11964
|
+
launchId: ap.launchId || void 0,
|
|
11965
|
+
runtime: ap.config.runtime,
|
|
11966
|
+
...runtimeRecoveryTraceAttrs(event)
|
|
11967
|
+
});
|
|
11968
|
+
}
|
|
11255
11969
|
recordDaemonTrace(name, attrs, status = "ok", parentTraceparent) {
|
|
11256
11970
|
const span = this.tracer.startSpan(name, {
|
|
11257
11971
|
parent: parseTraceparent(parentTraceparent),
|
|
@@ -11589,26 +12303,26 @@ var AgentProcessManager = class _AgentProcessManager {
|
|
|
11589
12303
|
let pendingStartRebind;
|
|
11590
12304
|
const originalLaunchId = launchId || null;
|
|
11591
12305
|
try {
|
|
11592
|
-
const agentDataDir =
|
|
12306
|
+
const agentDataDir = path14.join(this.dataDir, agentId);
|
|
11593
12307
|
await mkdir(agentDataDir, { recursive: true });
|
|
11594
12308
|
const initialRuntimeConfig = withLocalRuntimeContext(config, agentId, agentDataDir);
|
|
11595
|
-
const memoryMdPath =
|
|
12309
|
+
const memoryMdPath = path14.join(agentDataDir, "MEMORY.md");
|
|
11596
12310
|
try {
|
|
11597
12311
|
await access(memoryMdPath);
|
|
11598
12312
|
} catch {
|
|
11599
12313
|
const initialMemoryMd = buildInitialMemoryMd(initialRuntimeConfig);
|
|
11600
12314
|
await writeFile(memoryMdPath, initialMemoryMd);
|
|
11601
12315
|
}
|
|
11602
|
-
const notesDir =
|
|
12316
|
+
const notesDir = path14.join(agentDataDir, "notes");
|
|
11603
12317
|
await mkdir(notesDir, { recursive: true });
|
|
11604
12318
|
if (getOnboardingSeedMode(config) === FIRST_CINDY_SEED_MODE) {
|
|
11605
12319
|
const seedFiles = buildOnboardingSeedFiles();
|
|
11606
12320
|
for (const { relativePath, content } of seedFiles) {
|
|
11607
|
-
const fullPath =
|
|
12321
|
+
const fullPath = path14.join(agentDataDir, relativePath);
|
|
11608
12322
|
try {
|
|
11609
12323
|
await access(fullPath);
|
|
11610
12324
|
} catch {
|
|
11611
|
-
await mkdir(
|
|
12325
|
+
await mkdir(path14.dirname(fullPath), { recursive: true });
|
|
11612
12326
|
await writeFile(fullPath, content);
|
|
11613
12327
|
}
|
|
11614
12328
|
}
|
|
@@ -11762,6 +12476,7 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
|
|
|
11762
12476
|
workingDirectory: agentDataDir,
|
|
11763
12477
|
slockCliPath: this.slockCliPath,
|
|
11764
12478
|
daemonApiKey: this.daemonApiKey,
|
|
12479
|
+
slockHome: this.slockHome,
|
|
11765
12480
|
launchId: effectiveLaunchId,
|
|
11766
12481
|
agentCredentialProxyInboxCoordinator: this.createAgentProxyInboxCoordinator(agentId),
|
|
11767
12482
|
cliTransportTraceDir: this.cliTransportTraceDir,
|
|
@@ -12921,7 +13636,7 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
|
|
|
12921
13636
|
return true;
|
|
12922
13637
|
}
|
|
12923
13638
|
async resetWorkspace(agentId) {
|
|
12924
|
-
const agentDataDir =
|
|
13639
|
+
const agentDataDir = path14.join(this.dataDir, agentId);
|
|
12925
13640
|
try {
|
|
12926
13641
|
await rm2(agentDataDir, { recursive: true, force: true });
|
|
12927
13642
|
logger.info(`[Agent ${agentId}] Workspace reset complete (${agentDataDir})`);
|
|
@@ -12981,9 +13696,9 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
|
|
|
12981
13696
|
}
|
|
12982
13697
|
return result;
|
|
12983
13698
|
}
|
|
12984
|
-
buildRuntimeProfileReport(agentId, config, sessionId, launchId) {
|
|
12985
|
-
const workspacePath =
|
|
12986
|
-
const runtimeHomeDir = resolveRuntimeHomeDir(config, this.runtimeSessionHomeDir, workspacePath);
|
|
13699
|
+
buildRuntimeProfileReport(agentId, config, sessionId, launchId, observedRuntimeHomeDir) {
|
|
13700
|
+
const workspacePath = path14.join(this.dataDir, agentId);
|
|
13701
|
+
const runtimeHomeDir = observedRuntimeHomeDir || resolveRuntimeHomeDir(config, this.runtimeSessionHomeDir, workspacePath, { agentId, slockHome: this.slockHome });
|
|
12987
13702
|
return {
|
|
12988
13703
|
agentId,
|
|
12989
13704
|
launchId,
|
|
@@ -13004,7 +13719,13 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
|
|
|
13004
13719
|
getAgentRuntimeProfileReport(agentId) {
|
|
13005
13720
|
const running = this.agents.get(agentId);
|
|
13006
13721
|
if (running) {
|
|
13007
|
-
return this.buildRuntimeProfileReport(
|
|
13722
|
+
return this.buildRuntimeProfileReport(
|
|
13723
|
+
agentId,
|
|
13724
|
+
running.config,
|
|
13725
|
+
running.sessionId,
|
|
13726
|
+
running.launchId,
|
|
13727
|
+
running.runtime.currentRuntimeHomeDir
|
|
13728
|
+
);
|
|
13008
13729
|
}
|
|
13009
13730
|
const idle = this.idleAgentConfigs.get(agentId);
|
|
13010
13731
|
if (idle) {
|
|
@@ -13277,7 +13998,7 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
|
|
|
13277
13998
|
}
|
|
13278
13999
|
// Workspace file browsing
|
|
13279
14000
|
async getFileTree(agentId, dirPath) {
|
|
13280
|
-
const agentDir =
|
|
14001
|
+
const agentDir = path14.join(this.dataDir, agentId);
|
|
13281
14002
|
try {
|
|
13282
14003
|
await stat2(agentDir);
|
|
13283
14004
|
} catch {
|
|
@@ -13285,8 +14006,8 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
|
|
|
13285
14006
|
}
|
|
13286
14007
|
let targetDir = agentDir;
|
|
13287
14008
|
if (dirPath) {
|
|
13288
|
-
const resolved =
|
|
13289
|
-
if (!resolved.startsWith(agentDir +
|
|
14009
|
+
const resolved = path14.resolve(agentDir, dirPath);
|
|
14010
|
+
if (!resolved.startsWith(agentDir + path14.sep) && resolved !== agentDir) {
|
|
13290
14011
|
return [];
|
|
13291
14012
|
}
|
|
13292
14013
|
targetDir = resolved;
|
|
@@ -13294,14 +14015,14 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
|
|
|
13294
14015
|
return this.listDirectoryChildren(targetDir, agentDir);
|
|
13295
14016
|
}
|
|
13296
14017
|
async readFile(agentId, filePath) {
|
|
13297
|
-
const agentDir =
|
|
13298
|
-
const resolved =
|
|
13299
|
-
if (!resolved.startsWith(agentDir +
|
|
14018
|
+
const agentDir = path14.join(this.dataDir, agentId);
|
|
14019
|
+
const resolved = path14.resolve(agentDir, filePath);
|
|
14020
|
+
if (!resolved.startsWith(agentDir + path14.sep) && resolved !== agentDir) {
|
|
13300
14021
|
throw new Error("Access denied");
|
|
13301
14022
|
}
|
|
13302
14023
|
const info = await stat2(resolved);
|
|
13303
14024
|
if (info.isDirectory()) throw new Error("Cannot read a directory");
|
|
13304
|
-
const ext =
|
|
14025
|
+
const ext = path14.extname(resolved).toLowerCase();
|
|
13305
14026
|
if (WORKSPACE_TEXT_EXTENSIONS.has(ext) || ext === "") {
|
|
13306
14027
|
if (info.size > WORKSPACE_TEXT_FILE_MAX_BYTES) throw new Error("File too large");
|
|
13307
14028
|
const content = await readFile(resolved, "utf-8");
|
|
@@ -13352,8 +14073,8 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
|
|
|
13352
14073
|
};
|
|
13353
14074
|
}
|
|
13354
14075
|
const runtime = config.runtime;
|
|
13355
|
-
const workspaceDir =
|
|
13356
|
-
const homeDir = ensureRuntimeHomeDir(config, this.runtimeSessionHomeDir, workspaceDir);
|
|
14076
|
+
const workspaceDir = path14.join(this.dataDir, agentId);
|
|
14077
|
+
const homeDir = agent?.runtime.currentRuntimeHomeDir || ensureRuntimeHomeDir(config, this.runtimeSessionHomeDir, workspaceDir, { agentId, slockHome: this.slockHome });
|
|
13357
14078
|
if (!actualSessionId) {
|
|
13358
14079
|
return {
|
|
13359
14080
|
runtime,
|
|
@@ -13391,7 +14112,7 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
|
|
|
13391
14112
|
let redacted = false;
|
|
13392
14113
|
if (ref.reachable && ref.path) {
|
|
13393
14114
|
try {
|
|
13394
|
-
const resolved =
|
|
14115
|
+
const resolved = path14.resolve(ref.path);
|
|
13395
14116
|
const allowedRoots = allowedTranscriptRootsForRuntime(runtime, homeDir, workspaceDir);
|
|
13396
14117
|
if (!await isPathWithinAllowedRoots(resolved, allowedRoots)) {
|
|
13397
14118
|
throw new Error("resolved session path is outside allowed runtime directories");
|
|
@@ -13402,7 +14123,7 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
|
|
|
13402
14123
|
throw new Error("symbolic links are not allowed");
|
|
13403
14124
|
}
|
|
13404
14125
|
if (info.isDirectory()) {
|
|
13405
|
-
targetPath =
|
|
14126
|
+
targetPath = path14.join(resolved, "state.json");
|
|
13406
14127
|
}
|
|
13407
14128
|
if (!await isPathWithinAllowedRoots(targetPath, allowedRoots)) {
|
|
13408
14129
|
throw new Error("resolved session state path is outside allowed runtime directories");
|
|
@@ -13514,14 +14235,22 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
|
|
|
13514
14235
|
const idle = this.idleAgentConfigs.get(agentId);
|
|
13515
14236
|
const config = agent?.config ?? idle?.config ?? null;
|
|
13516
14237
|
const runtime = runtimeHint || config?.runtime || "claude";
|
|
13517
|
-
const workspaceDir =
|
|
13518
|
-
const
|
|
14238
|
+
const workspaceDir = path14.join(this.dataDir, agentId);
|
|
14239
|
+
const hostHome = os7.homedir();
|
|
14240
|
+
const home = agent?.runtime.currentRuntimeHomeDir || (config ? ensureRuntimeHomeDir(config, hostHome, workspaceDir, { agentId, slockHome: this.slockHome }) : runtime === "codex" ? resolveCodexHomeRootFromEnv(process.env, { defaultHomeDir: hostHome, cwd: workspaceDir }) : hostHome);
|
|
13519
14241
|
const paths = _AgentProcessManager.SKILL_PATHS[runtime] || _AgentProcessManager.SKILL_PATHS.claude;
|
|
14242
|
+
const globalDirs = runtime === "codex" ? [
|
|
14243
|
+
path14.join(home, "skills"),
|
|
14244
|
+
path14.join(home, "skills", ".system"),
|
|
14245
|
+
path14.join(home, ".agents", "skills"),
|
|
14246
|
+
...hasConfiguredCodexHome(config) ? [] : [path14.join(hostHome, ".agents", "skills")]
|
|
14247
|
+
] : paths.global.map((p) => path14.join(home, p));
|
|
14248
|
+
const workspaceDirs = paths.workspace.map((p) => path14.join(workspaceDir, p));
|
|
13520
14249
|
const globalResults = await Promise.all(
|
|
13521
|
-
|
|
14250
|
+
globalDirs.map((dir) => this.scanSkillsDir(dir))
|
|
13522
14251
|
);
|
|
13523
14252
|
const workspaceResults = await Promise.all(
|
|
13524
|
-
|
|
14253
|
+
workspaceDirs.map((dir) => this.scanSkillsDir(dir))
|
|
13525
14254
|
);
|
|
13526
14255
|
const dedup = (skills) => {
|
|
13527
14256
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -13550,7 +14279,7 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
|
|
|
13550
14279
|
const skills = [];
|
|
13551
14280
|
for (const entry of entries) {
|
|
13552
14281
|
if (entry.isDirectory() || entry.isSymbolicLink()) {
|
|
13553
|
-
const skillMd =
|
|
14282
|
+
const skillMd = path14.join(dir, entry.name, "SKILL.md");
|
|
13554
14283
|
try {
|
|
13555
14284
|
const content = await readFile(skillMd, "utf-8");
|
|
13556
14285
|
const skill = this.parseSkillMd(entry.name, content);
|
|
@@ -13561,7 +14290,7 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
|
|
|
13561
14290
|
} else if (entry.name.endsWith(".md")) {
|
|
13562
14291
|
const cmdName = entry.name.replace(/\.md$/, "");
|
|
13563
14292
|
try {
|
|
13564
|
-
const content = await readFile(
|
|
14293
|
+
const content = await readFile(path14.join(dir, entry.name), "utf-8");
|
|
13565
14294
|
const skill = this.parseSkillMd(cmdName, content);
|
|
13566
14295
|
skill.sourcePath = dir;
|
|
13567
14296
|
skills.push(skill);
|
|
@@ -13982,6 +14711,43 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
|
|
|
13982
14711
|
recordRuntimeTraceEvent(agentId, ap, name, attrs) {
|
|
13983
14712
|
this.startRuntimeTrace(agentId, ap, "runtime-progress").addEvent(name, attrs);
|
|
13984
14713
|
}
|
|
14714
|
+
restoreRuntimeDeliveryAfterAsyncRejection(agentId, ap, event) {
|
|
14715
|
+
const pendingBefore = ap.notifications.pendingCount;
|
|
14716
|
+
const restoredMessages = ap.inbox.filter(
|
|
14717
|
+
(message) => ap.notifications.hasContributedMessage(message, ap.sessionId)
|
|
14718
|
+
);
|
|
14719
|
+
ap.notifications.clearNoticeFingerprint();
|
|
14720
|
+
const restoredNotificationCount = ap.driver.supportsStdinNotification && ap.sessionId && restoredMessages.length > 0 ? ap.notifications.add(restoredMessages.length) : 0;
|
|
14721
|
+
if (event.requestMethod === "turn/start") {
|
|
14722
|
+
this.commitApmIdleState(agentId, ap, true);
|
|
14723
|
+
}
|
|
14724
|
+
const idleRetryScheduled = event.requestMethod === "turn/start" && restoredNotificationCount > 0 ? ap.notifications.schedule(() => {
|
|
14725
|
+
this.flushAsyncRejectedIdleDelivery(agentId);
|
|
14726
|
+
}, this.stdinNotificationRetryMs) : false;
|
|
14727
|
+
const attrs = {
|
|
14728
|
+
request_method: event.requestMethod,
|
|
14729
|
+
source: event.source,
|
|
14730
|
+
payloadBytes: event.payloadBytes,
|
|
14731
|
+
inbox_count: ap.inbox.length,
|
|
14732
|
+
restored_messages_count: restoredMessages.length,
|
|
14733
|
+
pending_notification_count_before: pendingBefore,
|
|
14734
|
+
pending_notification_count_after: ap.notifications.pendingCount,
|
|
14735
|
+
restored_notification_count: restoredNotificationCount,
|
|
14736
|
+
session_id_present: Boolean(ap.sessionId),
|
|
14737
|
+
supports_stdin_notification: ap.driver.supportsStdinNotification,
|
|
14738
|
+
busy_delivery_mode: ap.driver.busyDeliveryMode,
|
|
14739
|
+
restored_idle_state: event.requestMethod === "turn/start",
|
|
14740
|
+
idle_retry_scheduled: idleRetryScheduled
|
|
14741
|
+
};
|
|
14742
|
+
this.recordRuntimeTraceEvent(agentId, ap, "runtime.delivery.async_rejected", attrs);
|
|
14743
|
+
this.recordDaemonTrace("daemon.agent.stdin_delivery.async_rejected", {
|
|
14744
|
+
agentId,
|
|
14745
|
+
launchId: ap.launchId || void 0,
|
|
14746
|
+
runtime: ap.config.runtime,
|
|
14747
|
+
model: ap.config.model,
|
|
14748
|
+
...attrs
|
|
14749
|
+
}, "error");
|
|
14750
|
+
}
|
|
13985
14751
|
noteRuntimeProgress(ap, eventKind) {
|
|
13986
14752
|
ap.runtimeProgress.noteRuntimeEvent(eventKind);
|
|
13987
14753
|
this.invalidateRecoveryErrorView(ap);
|
|
@@ -14170,7 +14936,7 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
|
|
|
14170
14936
|
if ((ap.driver.startupReadiness ?? "first_event") !== "initial_turn") {
|
|
14171
14937
|
return true;
|
|
14172
14938
|
}
|
|
14173
|
-
return event.kind !== "session_init" && event.kind !== "internal_progress" && event.kind !== "runtime_diagnostic";
|
|
14939
|
+
return event.kind !== "session_init" && event.kind !== "internal_progress" && event.kind !== "runtime_diagnostic" && event.kind !== "runtime_recovery";
|
|
14174
14940
|
}
|
|
14175
14941
|
handleRuntimeStartupTimeout(agentId, ap, timeoutMs) {
|
|
14176
14942
|
const current = this.agents.get(agentId);
|
|
@@ -14366,6 +15132,21 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
|
|
|
14366
15132
|
if (ap) this.recordRuntimeTelemetry(agentId, ap, event);
|
|
14367
15133
|
return;
|
|
14368
15134
|
}
|
|
15135
|
+
if (event.kind === "delivery_error") {
|
|
15136
|
+
if (ap) {
|
|
15137
|
+
this.restoreRuntimeDeliveryAfterAsyncRejection(agentId, ap, event);
|
|
15138
|
+
} else {
|
|
15139
|
+
this.recordDaemonTrace("daemon.agent.delivery_error.received_without_process", {
|
|
15140
|
+
agentId,
|
|
15141
|
+
event_kind: event.kind,
|
|
15142
|
+
runtime: driver.id,
|
|
15143
|
+
request_method: event.requestMethod,
|
|
15144
|
+
source: event.source,
|
|
15145
|
+
payloadBytes: event.payloadBytes
|
|
15146
|
+
});
|
|
15147
|
+
}
|
|
15148
|
+
return;
|
|
15149
|
+
}
|
|
14369
15150
|
if (ap && isStartupRequestErrorEvent(event)) {
|
|
14370
15151
|
this.handleRuntimeStartupRequestError(agentId, ap, event);
|
|
14371
15152
|
return;
|
|
@@ -14382,13 +15163,15 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
|
|
|
14382
15163
|
source: event.source,
|
|
14383
15164
|
itemType: event.itemType,
|
|
14384
15165
|
payloadBytes: event.payloadBytes
|
|
14385
|
-
} : event.kind === "runtime_diagnostic" ? runtimeDiagnosticTraceAttrs(event) : { kind: event.kind };
|
|
15166
|
+
} : event.kind === "runtime_diagnostic" ? runtimeDiagnosticTraceAttrs(event) : event.kind === "runtime_recovery" ? runtimeRecoveryTraceAttrs(event) : { kind: event.kind };
|
|
14386
15167
|
this.recordRuntimeTraceEvent(agentId, ap, "runtime.event.received", eventAttrs);
|
|
14387
|
-
|
|
15168
|
+
const recordProgressObservedAfterStall = () => {
|
|
15169
|
+
if (!wasStalled) return;
|
|
14388
15170
|
this.recordRuntimeTraceEvent(agentId, ap, "runtime.progress.observed", { afterStall: true });
|
|
14389
|
-
}
|
|
15171
|
+
};
|
|
14390
15172
|
if (event.kind === "internal_progress") {
|
|
14391
15173
|
ap.runtimeProgress.noteInternalProgress();
|
|
15174
|
+
recordProgressObservedAfterStall();
|
|
14392
15175
|
this.invalidateRecoveryErrorView(ap);
|
|
14393
15176
|
this.clearRuntimeErrorDeliveryBackoffAfterProgress(agentId, ap, event.kind);
|
|
14394
15177
|
this.recordRuntimeTraceEvent(agentId, ap, "runtime.progress.internal_observed", {
|
|
@@ -14405,11 +15188,17 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
|
|
|
14405
15188
|
}
|
|
14406
15189
|
if (event.kind === "runtime_diagnostic") {
|
|
14407
15190
|
this.noteRuntimeProgress(ap, event.kind);
|
|
15191
|
+
recordProgressObservedAfterStall();
|
|
14408
15192
|
this.clearRuntimeErrorDeliveryBackoffAfterProgress(agentId, ap, event.kind);
|
|
14409
15193
|
this.recordRuntimeDiagnosticActivity(agentId, ap, event);
|
|
14410
15194
|
return;
|
|
14411
15195
|
}
|
|
15196
|
+
if (event.kind === "runtime_recovery") {
|
|
15197
|
+
this.recordRuntimeRecoveryActivity(agentId, ap, event);
|
|
15198
|
+
return;
|
|
15199
|
+
}
|
|
14412
15200
|
this.noteRuntimeProgress(ap, event.kind);
|
|
15201
|
+
recordProgressObservedAfterStall();
|
|
14413
15202
|
} else if (event.kind !== "internal_progress") {
|
|
14414
15203
|
this.recordDaemonTrace("daemon.agent.event.received_without_process", {
|
|
14415
15204
|
agentId,
|
|
@@ -15166,8 +15955,8 @@ ${RESPONSE_TARGET_HINT}`);
|
|
|
15166
15955
|
const nodes = [];
|
|
15167
15956
|
for (const entry of entries) {
|
|
15168
15957
|
if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
|
|
15169
|
-
const fullPath =
|
|
15170
|
-
const relativePath =
|
|
15958
|
+
const fullPath = path14.join(dir, entry.name);
|
|
15959
|
+
const relativePath = path14.relative(rootDir, fullPath);
|
|
15171
15960
|
let info;
|
|
15172
15961
|
try {
|
|
15173
15962
|
info = await stat2(fullPath);
|
|
@@ -15542,8 +16331,8 @@ var ReminderCache = class {
|
|
|
15542
16331
|
// src/machineLock.ts
|
|
15543
16332
|
import { createHash as createHash4, randomUUID as randomUUID6 } from "crypto";
|
|
15544
16333
|
import { mkdirSync as mkdirSync6, readFileSync as readFileSync7, rmSync as rmSync3, statSync as statSync2, writeFileSync as writeFileSync5 } from "fs";
|
|
15545
|
-
import
|
|
15546
|
-
import
|
|
16334
|
+
import os8 from "os";
|
|
16335
|
+
import path15 from "path";
|
|
15547
16336
|
var INCOMPLETE_LOCK_STALE_MS = 3e4;
|
|
15548
16337
|
var DaemonMachineLockConflictError = class extends Error {
|
|
15549
16338
|
code = "DAEMON_MACHINE_LOCK_HELD";
|
|
@@ -15565,7 +16354,7 @@ function resolveDefaultMachineStateRoot() {
|
|
|
15565
16354
|
return resolveSlockHomePath("machines");
|
|
15566
16355
|
}
|
|
15567
16356
|
function ownerPath(lockDir) {
|
|
15568
|
-
return
|
|
16357
|
+
return path15.join(lockDir, "owner.json");
|
|
15569
16358
|
}
|
|
15570
16359
|
function readOwner(lockDir) {
|
|
15571
16360
|
try {
|
|
@@ -15595,8 +16384,8 @@ function acquireDaemonMachineLock(options) {
|
|
|
15595
16384
|
const rootDir = options.rootDir ?? resolveDefaultMachineStateRoot();
|
|
15596
16385
|
const fingerprint = apiKeyFingerprint(options.apiKey);
|
|
15597
16386
|
const lockId = getDaemonMachineLockId(options.apiKey);
|
|
15598
|
-
const machineDir =
|
|
15599
|
-
const lockDir =
|
|
16387
|
+
const machineDir = path15.join(rootDir, lockId);
|
|
16388
|
+
const lockDir = path15.join(machineDir, "daemon.lock");
|
|
15600
16389
|
const token = randomUUID6();
|
|
15601
16390
|
mkdirSync6(machineDir, { recursive: true });
|
|
15602
16391
|
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
@@ -15605,7 +16394,7 @@ function acquireDaemonMachineLock(options) {
|
|
|
15605
16394
|
const owner = {
|
|
15606
16395
|
pid: process.pid,
|
|
15607
16396
|
token,
|
|
15608
|
-
hostname:
|
|
16397
|
+
hostname: os8.hostname(),
|
|
15609
16398
|
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
15610
16399
|
serverUrl: options.serverUrl,
|
|
15611
16400
|
apiKeyFingerprint: fingerprint.slice(0, 16)
|
|
@@ -15657,7 +16446,7 @@ function acquireDaemonMachineLock(options) {
|
|
|
15657
16446
|
|
|
15658
16447
|
// src/localTraceSink.ts
|
|
15659
16448
|
import { appendFileSync, mkdirSync as mkdirSync7, readdirSync as readdirSync4, rmSync as rmSync4, statSync as statSync3, writeFileSync as writeFileSync6 } from "fs";
|
|
15660
|
-
import
|
|
16449
|
+
import path16 from "path";
|
|
15661
16450
|
var DEFAULT_MAX_FILE_BYTES = 5 * 1024 * 1024;
|
|
15662
16451
|
var DEFAULT_MAX_FILE_AGE_MS = 5 * 60 * 1e3;
|
|
15663
16452
|
var DEFAULT_MAX_FILES = 8;
|
|
@@ -15694,7 +16483,7 @@ var LocalRotatingTraceSink = class {
|
|
|
15694
16483
|
currentSize = 0;
|
|
15695
16484
|
sequence = 0;
|
|
15696
16485
|
constructor(options) {
|
|
15697
|
-
this.traceDir =
|
|
16486
|
+
this.traceDir = path16.join(options.machineDir, "traces");
|
|
15698
16487
|
this.maxFileBytes = Math.max(1024, Math.floor(options.maxFileBytes ?? DEFAULT_MAX_FILE_BYTES));
|
|
15699
16488
|
const baseAgeMs = Math.max(1e3, Math.floor(options.maxFileAgeMs ?? DEFAULT_MAX_FILE_AGE_MS));
|
|
15700
16489
|
const ageJitterMs = Math.max(0, Math.floor(options.maxFileAgeJitterMs ?? 0));
|
|
@@ -15724,7 +16513,7 @@ var LocalRotatingTraceSink = class {
|
|
|
15724
16513
|
const nowMs = this.nowMsProvider();
|
|
15725
16514
|
const shouldRotateForAge = this.currentFileOpenedAtMs !== null && nowMs - this.currentFileOpenedAtMs >= this.maxFileAgeMs;
|
|
15726
16515
|
if (!this.currentFile || this.currentSize + nextBytes > this.maxFileBytes || shouldRotateForAge) {
|
|
15727
|
-
this.currentFile =
|
|
16516
|
+
this.currentFile = path16.join(
|
|
15728
16517
|
this.traceDir,
|
|
15729
16518
|
`daemon-trace-${safeTimestamp(nowMs)}-${process.pid}-${String(this.sequence++).padStart(4, "0")}.jsonl`
|
|
15730
16519
|
);
|
|
@@ -15739,7 +16528,7 @@ var LocalRotatingTraceSink = class {
|
|
|
15739
16528
|
const excess = files.length - this.maxFiles;
|
|
15740
16529
|
if (excess <= 0) return;
|
|
15741
16530
|
for (const file of files.slice(0, excess)) {
|
|
15742
|
-
rmSync4(
|
|
16531
|
+
rmSync4(path16.join(this.traceDir, file), { force: true });
|
|
15743
16532
|
}
|
|
15744
16533
|
}
|
|
15745
16534
|
};
|
|
@@ -15830,7 +16619,7 @@ function isDiagnosticErrorAttr(key) {
|
|
|
15830
16619
|
import { createHash as createHash6, randomUUID as randomUUID7 } from "crypto";
|
|
15831
16620
|
import { gzipSync as gzipSync2 } from "zlib";
|
|
15832
16621
|
import { mkdir as mkdir2, readFile as readFile2, readdir as readdir3, stat as stat3, writeFile as writeFile2 } from "fs/promises";
|
|
15833
|
-
import
|
|
16622
|
+
import path17 from "path";
|
|
15834
16623
|
|
|
15835
16624
|
// src/traceJitter.ts
|
|
15836
16625
|
import { createHash as createHash5 } from "crypto";
|
|
@@ -15929,7 +16718,7 @@ var DaemonTraceBundleUploader = class {
|
|
|
15929
16718
|
}, nextMs);
|
|
15930
16719
|
}
|
|
15931
16720
|
async findUploadCandidates() {
|
|
15932
|
-
const traceDir =
|
|
16721
|
+
const traceDir = path17.join(this.options.machineDir, "traces");
|
|
15933
16722
|
let names;
|
|
15934
16723
|
try {
|
|
15935
16724
|
names = await readdir3(traceDir);
|
|
@@ -15941,8 +16730,8 @@ var DaemonTraceBundleUploader = class {
|
|
|
15941
16730
|
const currentFile = this.options.currentFileProvider?.();
|
|
15942
16731
|
const candidates = [];
|
|
15943
16732
|
for (const name of names.filter((entry) => entry.startsWith("daemon-trace-") && entry.endsWith(".jsonl")).sort()) {
|
|
15944
|
-
const file =
|
|
15945
|
-
if (currentFile &&
|
|
16733
|
+
const file = path17.join(traceDir, name);
|
|
16734
|
+
if (currentFile && path17.resolve(file) === path17.resolve(currentFile)) continue;
|
|
15946
16735
|
if (await this.isUploaded(file)) continue;
|
|
15947
16736
|
try {
|
|
15948
16737
|
const info = await stat3(file);
|
|
@@ -16016,8 +16805,8 @@ var DaemonTraceBundleUploader = class {
|
|
|
16016
16805
|
}
|
|
16017
16806
|
}
|
|
16018
16807
|
uploadStatePath(file) {
|
|
16019
|
-
const stateDir =
|
|
16020
|
-
return
|
|
16808
|
+
const stateDir = path17.join(this.options.machineDir, "trace-uploads");
|
|
16809
|
+
return path17.join(stateDir, `${path17.basename(file)}.uploaded.json`);
|
|
16021
16810
|
}
|
|
16022
16811
|
async isUploaded(file) {
|
|
16023
16812
|
try {
|
|
@@ -16029,9 +16818,9 @@ var DaemonTraceBundleUploader = class {
|
|
|
16029
16818
|
}
|
|
16030
16819
|
async markUploaded(file, metadata) {
|
|
16031
16820
|
const stateFile = this.uploadStatePath(file);
|
|
16032
|
-
await mkdir2(
|
|
16821
|
+
await mkdir2(path17.dirname(stateFile), { recursive: true, mode: 448 });
|
|
16033
16822
|
await writeFile2(stateFile, `${JSON.stringify({
|
|
16034
|
-
file:
|
|
16823
|
+
file: path17.basename(file),
|
|
16035
16824
|
uploadedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
16036
16825
|
...metadata
|
|
16037
16826
|
}, null, 2)}
|
|
@@ -16125,7 +16914,7 @@ var DAEMON_CORE_TRACE_ATTR_CONTRACTS = {
|
|
|
16125
16914
|
spanAttrs: ["agentId", "event_kind", "runtime"]
|
|
16126
16915
|
}
|
|
16127
16916
|
};
|
|
16128
|
-
var DAEMON_CLI_USAGE =
|
|
16917
|
+
var DAEMON_CLI_USAGE = `Usage: slock-daemon --server-url <url> (--api-key <key> or ${DAEMON_API_KEY_ENV}=<key>)`;
|
|
16129
16918
|
var RunnerCredentialMintError2 = class extends Error {
|
|
16130
16919
|
code;
|
|
16131
16920
|
retryable;
|
|
@@ -16161,9 +16950,9 @@ function runnerCredentialErrorDetail2(error) {
|
|
|
16161
16950
|
async function waitForRunnerCredentialRetry2() {
|
|
16162
16951
|
await new Promise((resolve) => setTimeout(resolve, RUNNER_CREDENTIAL_MINT_RETRY_DELAY_MS2));
|
|
16163
16952
|
}
|
|
16164
|
-
function parseDaemonCliArgs(args) {
|
|
16953
|
+
function parseDaemonCliArgs(args, env = {}) {
|
|
16165
16954
|
let serverUrl = "";
|
|
16166
|
-
let apiKey = "";
|
|
16955
|
+
let apiKey = env[DAEMON_API_KEY_ENV] ?? "";
|
|
16167
16956
|
for (let i = 0; i < args.length; i++) {
|
|
16168
16957
|
if (args[i] === "--server-url" && args[i + 1]) serverUrl = args[++i];
|
|
16169
16958
|
if (args[i] === "--api-key" && args[i + 1]) apiKey = args[++i];
|
|
@@ -16180,13 +16969,13 @@ function readDaemonVersion(moduleUrl = import.meta.url) {
|
|
|
16180
16969
|
}
|
|
16181
16970
|
}
|
|
16182
16971
|
function resolveSlockCliPath(moduleUrl = import.meta.url) {
|
|
16183
|
-
const thisDir =
|
|
16184
|
-
const bundledDistPath =
|
|
16972
|
+
const thisDir = path18.dirname(fileURLToPath(moduleUrl));
|
|
16973
|
+
const bundledDistPath = path18.resolve(thisDir, "cli", "index.js");
|
|
16185
16974
|
try {
|
|
16186
16975
|
accessSync(bundledDistPath);
|
|
16187
16976
|
return bundledDistPath;
|
|
16188
16977
|
} catch {
|
|
16189
|
-
const workspaceDistPath =
|
|
16978
|
+
const workspaceDistPath = path18.resolve(thisDir, "..", "..", "cli", "dist", "index.js");
|
|
16190
16979
|
accessSync(workspaceDistPath);
|
|
16191
16980
|
return workspaceDistPath;
|
|
16192
16981
|
}
|
|
@@ -16200,11 +16989,12 @@ function resolveSlockCliPathOrEmpty(moduleUrl = import.meta.url) {
|
|
|
16200
16989
|
}
|
|
16201
16990
|
async function runBundledSlockCli(argv) {
|
|
16202
16991
|
process.argv = [process.execPath, "slock", ...argv];
|
|
16203
|
-
await import("./dist-
|
|
16992
|
+
await import("./dist-5BEASCX5.js");
|
|
16204
16993
|
}
|
|
16205
16994
|
function detectRuntimes(tracer = noopTracer) {
|
|
16206
16995
|
const ids = [];
|
|
16207
16996
|
const versions = {};
|
|
16997
|
+
const diagnostics = {};
|
|
16208
16998
|
const span = tracer.startSpan("daemon.runtime.detect", {
|
|
16209
16999
|
surface: "daemon",
|
|
16210
17000
|
kind: "internal",
|
|
@@ -16220,20 +17010,26 @@ function detectRuntimes(tracer = noopTracer) {
|
|
|
16220
17010
|
const probe = driver.probe();
|
|
16221
17011
|
if (!probe.available) {
|
|
16222
17012
|
if (probe.version) versions[runtime.id] = probe.version;
|
|
17013
|
+
if (probe.diagnostic) diagnostics[runtime.id] = probe.diagnostic;
|
|
16223
17014
|
span.addEvent("daemon.runtime.detect.checked", {
|
|
16224
17015
|
runtime: runtime.id,
|
|
16225
17016
|
outcome: "unavailable",
|
|
16226
17017
|
version_present: Boolean(probe.version),
|
|
17018
|
+
diagnostic_present: Boolean(probe.diagnostic),
|
|
17019
|
+
...probe.diagnostic ? { diagnostic: probe.diagnostic } : {},
|
|
16227
17020
|
binary_path_present: false
|
|
16228
17021
|
});
|
|
16229
17022
|
continue;
|
|
16230
17023
|
}
|
|
16231
17024
|
ids.push(runtime.id);
|
|
16232
17025
|
if (probe.version) versions[runtime.id] = probe.version;
|
|
17026
|
+
if (probe.diagnostic) diagnostics[runtime.id] = probe.diagnostic;
|
|
16233
17027
|
span.addEvent("daemon.runtime.detect.checked", {
|
|
16234
17028
|
runtime: runtime.id,
|
|
16235
17029
|
outcome: "available",
|
|
16236
17030
|
version_present: Boolean(probe.version),
|
|
17031
|
+
diagnostic_present: Boolean(probe.diagnostic),
|
|
17032
|
+
...probe.diagnostic ? { diagnostic: probe.diagnostic } : {},
|
|
16237
17033
|
binary_path_present: false
|
|
16238
17034
|
});
|
|
16239
17035
|
continue;
|
|
@@ -16276,7 +17072,7 @@ function detectRuntimes(tracer = noopTracer) {
|
|
|
16276
17072
|
detected_runtime_count: ids.length
|
|
16277
17073
|
}
|
|
16278
17074
|
});
|
|
16279
|
-
return { ids, versions };
|
|
17075
|
+
return { ids, versions, ...Object.keys(diagnostics).length > 0 ? { diagnostics } : {} };
|
|
16280
17076
|
}
|
|
16281
17077
|
function readPositiveIntegerEnv3(name, fallback) {
|
|
16282
17078
|
const raw = process.env[name];
|
|
@@ -16398,7 +17194,7 @@ var DaemonCore = class {
|
|
|
16398
17194
|
}
|
|
16399
17195
|
resolveMachineStateRoot() {
|
|
16400
17196
|
if (this.options.machineStateDir) return this.options.machineStateDir;
|
|
16401
|
-
if (this.options.dataDir) return
|
|
17197
|
+
if (this.options.dataDir) return path18.join(path18.dirname(this.options.dataDir), "machines");
|
|
16402
17198
|
return resolveDefaultMachineStateRoot();
|
|
16403
17199
|
}
|
|
16404
17200
|
shouldEnableLocalTrace() {
|
|
@@ -16425,7 +17221,7 @@ var DaemonCore = class {
|
|
|
16425
17221
|
sink: this.localTraceSink
|
|
16426
17222
|
}));
|
|
16427
17223
|
this.agentManager.setTracer(this.tracer);
|
|
16428
|
-
this.agentManager.setCliTransportTraceDir(
|
|
17224
|
+
this.agentManager.setCliTransportTraceDir(path18.join(machineDir, "traces"));
|
|
16429
17225
|
}
|
|
16430
17226
|
installTraceBundleUploader(machineDir) {
|
|
16431
17227
|
if (!this.shouldEnableLocalTrace()) return;
|
|
@@ -16973,9 +17769,12 @@ var DaemonCore = class {
|
|
|
16973
17769
|
});
|
|
16974
17770
|
}
|
|
16975
17771
|
handleConnect() {
|
|
16976
|
-
const { ids: runtimes, versions: runtimeVersions } = this.runtimeDetector();
|
|
17772
|
+
const { ids: runtimes, versions: runtimeVersions, diagnostics: runtimeDiagnostics = {} } = this.runtimeDetector();
|
|
16977
17773
|
const runtimeInfo = runtimes.map((id) => runtimeVersions[id] ? `${id} (${runtimeVersions[id]})` : id);
|
|
16978
17774
|
logger.info(`[Daemon] Detected runtimes: ${runtimeInfo.join(", ") || "none"}`);
|
|
17775
|
+
for (const [runtime, diagnostic] of Object.entries(runtimeDiagnostics)) {
|
|
17776
|
+
logger.warn(`[Daemon] Runtime ${runtime} diagnostic: ${diagnostic}`);
|
|
17777
|
+
}
|
|
16979
17778
|
if (!this.opencliWrappersRegenerated) {
|
|
16980
17779
|
this.opencliWrappersRegenerated = true;
|
|
16981
17780
|
try {
|
|
@@ -16995,8 +17794,8 @@ var DaemonCore = class {
|
|
|
16995
17794
|
capabilities: ["agent:start", "agent:stop", "agent:deliver", "workspace:files"],
|
|
16996
17795
|
runtimes,
|
|
16997
17796
|
runningAgents: runningAgentIds,
|
|
16998
|
-
hostname: this.options.hostname ??
|
|
16999
|
-
os: this.options.osDescription ?? `${
|
|
17797
|
+
hostname: this.options.hostname ?? os9.hostname(),
|
|
17798
|
+
os: this.options.osDescription ?? `${os9.platform()} ${os9.arch()}`,
|
|
17000
17799
|
daemonVersion: this.daemonVersion,
|
|
17001
17800
|
...this.computerVersion ? { computerVersion: this.computerVersion } : {}
|
|
17002
17801
|
});
|
|
@@ -17077,6 +17876,8 @@ var DaemonCore = class {
|
|
|
17077
17876
|
|
|
17078
17877
|
export {
|
|
17079
17878
|
subscribeDaemonLogs,
|
|
17879
|
+
DAEMON_API_KEY_ENV,
|
|
17880
|
+
scrubDaemonAuthEnv,
|
|
17080
17881
|
resolveWorkspaceDirectoryPath,
|
|
17081
17882
|
scanWorkspaceDirectories,
|
|
17082
17883
|
deleteWorkspaceDirectory,
|