@slock-ai/daemon 0.56.1-play.20260605140553 → 0.57.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-YOVM6OOZ.js → chunk-DQN3TW2I.js} +453 -487
- package/dist/cli/index.js +33 -8
- package/dist/core.js +1 -9
- package/dist/index.js +3 -6
- package/package.json +1 -1
- package/dist/chat-bridge.js +0 -96
- package/dist/chunk-M2KQBJR3.js +0 -260
- package/dist/drivers/piSdkRunner.js +0 -96
|
@@ -1,14 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
DEFAULT_CHAT_BRIDGE_TOOL_TIMEOUT_MS,
|
|
3
|
-
buildWebSocketOptions,
|
|
4
|
-
daemonFetch,
|
|
5
|
-
executeJsonRequest,
|
|
6
|
-
executeResponseRequest,
|
|
7
|
-
logger
|
|
8
|
-
} from "./chunk-M2KQBJR3.js";
|
|
9
|
-
|
|
10
1
|
// src/core.ts
|
|
11
|
-
import
|
|
2
|
+
import path15 from "path";
|
|
12
3
|
import os7 from "os";
|
|
13
4
|
import { createRequire as createRequire2 } from "module";
|
|
14
5
|
import { accessSync } from "fs";
|
|
@@ -1274,10 +1265,10 @@ var DISPLAY_PLAN_CONFIG = {
|
|
|
1274
1265
|
};
|
|
1275
1266
|
|
|
1276
1267
|
// src/agentProcessManager.ts
|
|
1277
|
-
import { mkdirSync as
|
|
1268
|
+
import { mkdirSync as mkdirSync3, readdirSync as readdirSync2, statSync, writeFileSync as writeFileSync4 } from "fs";
|
|
1278
1269
|
import { mkdir, writeFile, access, readdir as readdir2, stat as stat2, readFile, rm as rm2 } from "fs/promises";
|
|
1279
1270
|
import { createHash as createHash3 } from "crypto";
|
|
1280
|
-
import
|
|
1271
|
+
import path11 from "path";
|
|
1281
1272
|
import os5 from "os";
|
|
1282
1273
|
|
|
1283
1274
|
// src/drivers/claude.ts
|
|
@@ -1989,19 +1980,6 @@ function listLegacySlockStatePaths(slockHome = resolveSlockHome(), homeDir = os.
|
|
|
1989
1980
|
return candidates.filter((candidate) => existsSync(candidate.path));
|
|
1990
1981
|
}
|
|
1991
1982
|
|
|
1992
|
-
// src/authEnv.ts
|
|
1993
|
-
var DAEMON_API_KEY_ENV = "SLOCK_MACHINE_API_KEY";
|
|
1994
|
-
var SLOCK_AGENT_TOKEN_ENV = "SLOCK_AGENT_TOKEN";
|
|
1995
|
-
function scrubDaemonAuthEnv(env) {
|
|
1996
|
-
delete env[DAEMON_API_KEY_ENV];
|
|
1997
|
-
return env;
|
|
1998
|
-
}
|
|
1999
|
-
function scrubDaemonChildEnv(env) {
|
|
2000
|
-
delete env[DAEMON_API_KEY_ENV];
|
|
2001
|
-
delete env[SLOCK_AGENT_TOKEN_ENV];
|
|
2002
|
-
return env;
|
|
2003
|
-
}
|
|
2004
|
-
|
|
2005
1983
|
// src/agentCredentialProxy.ts
|
|
2006
1984
|
import { randomBytes } from "crypto";
|
|
2007
1985
|
import http from "http";
|
|
@@ -2331,6 +2309,160 @@ function stripUndefined(value) {
|
|
|
2331
2309
|
return value;
|
|
2332
2310
|
}
|
|
2333
2311
|
|
|
2312
|
+
// src/proxy.ts
|
|
2313
|
+
import { HttpsProxyAgent } from "https-proxy-agent";
|
|
2314
|
+
import { ProxyAgent } from "undici";
|
|
2315
|
+
var fetchDispatcherCache = /* @__PURE__ */ new Map();
|
|
2316
|
+
function getFetchPreResponseTimeoutMs(env) {
|
|
2317
|
+
const parsed = Number.parseInt(env.SLOCK_DAEMON_FETCH_PRE_RESPONSE_TIMEOUT_MS || "", 10);
|
|
2318
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : 3e4;
|
|
2319
|
+
}
|
|
2320
|
+
function getDefaultPort(protocol) {
|
|
2321
|
+
switch (protocol) {
|
|
2322
|
+
case "https:":
|
|
2323
|
+
case "wss:":
|
|
2324
|
+
return "443";
|
|
2325
|
+
case "http:":
|
|
2326
|
+
case "ws:":
|
|
2327
|
+
return "80";
|
|
2328
|
+
default:
|
|
2329
|
+
return "";
|
|
2330
|
+
}
|
|
2331
|
+
}
|
|
2332
|
+
function hostMatchesNoProxyEntry(hostname, ruleHost) {
|
|
2333
|
+
if (!ruleHost) return false;
|
|
2334
|
+
const normalizedRule = ruleHost.replace(/^\*\./, ".").replace(/^\./, "").toLowerCase();
|
|
2335
|
+
const normalizedHost = hostname.toLowerCase();
|
|
2336
|
+
return normalizedHost === normalizedRule || normalizedHost.endsWith(`.${normalizedRule}`);
|
|
2337
|
+
}
|
|
2338
|
+
function getProxyUrlForTarget(targetUrl, env) {
|
|
2339
|
+
const protocol = new URL(targetUrl).protocol;
|
|
2340
|
+
switch (protocol) {
|
|
2341
|
+
case "wss:":
|
|
2342
|
+
return env.WSS_PROXY || env.wss_proxy || env.HTTPS_PROXY || env.https_proxy || env.ALL_PROXY || env.all_proxy;
|
|
2343
|
+
case "ws:":
|
|
2344
|
+
return env.WS_PROXY || env.ws_proxy || env.HTTP_PROXY || env.http_proxy || env.ALL_PROXY || env.all_proxy;
|
|
2345
|
+
case "https:":
|
|
2346
|
+
return env.HTTPS_PROXY || env.https_proxy || env.ALL_PROXY || env.all_proxy;
|
|
2347
|
+
case "http:":
|
|
2348
|
+
return env.HTTP_PROXY || env.http_proxy || env.ALL_PROXY || env.all_proxy;
|
|
2349
|
+
default:
|
|
2350
|
+
return env.ALL_PROXY || env.all_proxy;
|
|
2351
|
+
}
|
|
2352
|
+
}
|
|
2353
|
+
function shouldBypassProxy(targetUrl, env) {
|
|
2354
|
+
const rawNoProxy = env.NO_PROXY || env.no_proxy;
|
|
2355
|
+
if (!rawNoProxy) return false;
|
|
2356
|
+
const url = new URL(targetUrl);
|
|
2357
|
+
const hostname = url.hostname.toLowerCase();
|
|
2358
|
+
const port = url.port || getDefaultPort(url.protocol);
|
|
2359
|
+
return rawNoProxy.split(",").map((entry) => entry.trim()).filter(Boolean).some((entry) => {
|
|
2360
|
+
if (entry === "*") return true;
|
|
2361
|
+
const [ruleHost, rulePort] = entry.split(":", 2);
|
|
2362
|
+
if (rulePort && rulePort !== port) return false;
|
|
2363
|
+
return hostMatchesNoProxyEntry(hostname, ruleHost);
|
|
2364
|
+
});
|
|
2365
|
+
}
|
|
2366
|
+
function buildWebSocketOptions(wsUrl, env) {
|
|
2367
|
+
const proxyUrl = getProxyUrlForTarget(wsUrl, env);
|
|
2368
|
+
if (!proxyUrl) return void 0;
|
|
2369
|
+
if (shouldBypassProxy(wsUrl, env)) return void 0;
|
|
2370
|
+
return {
|
|
2371
|
+
agent: new HttpsProxyAgent(proxyUrl)
|
|
2372
|
+
};
|
|
2373
|
+
}
|
|
2374
|
+
function resolveProxyUrl(targetUrl, env) {
|
|
2375
|
+
const proxyUrl = getProxyUrlForTarget(targetUrl, env);
|
|
2376
|
+
if (!proxyUrl) return void 0;
|
|
2377
|
+
if (shouldBypassProxy(targetUrl, env)) return void 0;
|
|
2378
|
+
return proxyUrl;
|
|
2379
|
+
}
|
|
2380
|
+
function buildFetchDispatcher(targetUrl, env) {
|
|
2381
|
+
const proxyUrl = resolveProxyUrl(targetUrl, env);
|
|
2382
|
+
if (!proxyUrl) return void 0;
|
|
2383
|
+
const cached = fetchDispatcherCache.get(proxyUrl);
|
|
2384
|
+
if (cached) return cached;
|
|
2385
|
+
const timeoutMs = getFetchPreResponseTimeoutMs(env);
|
|
2386
|
+
const dispatcher = new ProxyAgent({
|
|
2387
|
+
uri: proxyUrl,
|
|
2388
|
+
// All three are pre-response and body-agnostic (see getFetchPreResponseTimeoutMs):
|
|
2389
|
+
// headersTimeout = headers-hang leg; requestTls.timeout = CONNECT-tunnel
|
|
2390
|
+
// establish leg; connect.timeout = socket to the proxy itself (defensive).
|
|
2391
|
+
connect: { timeout: timeoutMs },
|
|
2392
|
+
requestTls: { timeout: timeoutMs },
|
|
2393
|
+
headersTimeout: timeoutMs
|
|
2394
|
+
});
|
|
2395
|
+
fetchDispatcherCache.set(proxyUrl, dispatcher);
|
|
2396
|
+
return dispatcher;
|
|
2397
|
+
}
|
|
2398
|
+
function evictFetchDispatcher(targetUrl, env) {
|
|
2399
|
+
const proxyUrl = resolveProxyUrl(targetUrl, env);
|
|
2400
|
+
if (!proxyUrl) return false;
|
|
2401
|
+
const cached = fetchDispatcherCache.get(proxyUrl);
|
|
2402
|
+
if (!cached) return false;
|
|
2403
|
+
fetchDispatcherCache.delete(proxyUrl);
|
|
2404
|
+
void Promise.resolve().then(() => cached.close()).catch(() => cached.destroy?.(new Error("evicted"))).catch(() => {
|
|
2405
|
+
});
|
|
2406
|
+
return true;
|
|
2407
|
+
}
|
|
2408
|
+
|
|
2409
|
+
// src/daemonFetch.ts
|
|
2410
|
+
function withDaemonFetchProxy(input, init = {}, env = process.env) {
|
|
2411
|
+
const dispatcher = buildFetchDispatcher(input.toString(), env);
|
|
2412
|
+
return dispatcher ? { ...init, dispatcher } : init;
|
|
2413
|
+
}
|
|
2414
|
+
async function daemonFetch(input, init, env = process.env) {
|
|
2415
|
+
try {
|
|
2416
|
+
return await fetch(input, withDaemonFetchProxy(input, init, env));
|
|
2417
|
+
} catch (err) {
|
|
2418
|
+
evictFetchDispatcher(input.toString(), env);
|
|
2419
|
+
throw err;
|
|
2420
|
+
}
|
|
2421
|
+
}
|
|
2422
|
+
|
|
2423
|
+
// src/logger.ts
|
|
2424
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
2425
|
+
function timestamp() {
|
|
2426
|
+
const d = /* @__PURE__ */ new Date();
|
|
2427
|
+
const pad = (n) => String(n).padStart(2, "0");
|
|
2428
|
+
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
|
|
2429
|
+
}
|
|
2430
|
+
function format(level, msg) {
|
|
2431
|
+
return `${timestamp()} [${level}] ${msg}`;
|
|
2432
|
+
}
|
|
2433
|
+
function emit(event) {
|
|
2434
|
+
for (const listener of listeners) {
|
|
2435
|
+
listener(event);
|
|
2436
|
+
}
|
|
2437
|
+
}
|
|
2438
|
+
function subscribeDaemonLogs(listener) {
|
|
2439
|
+
listeners.add(listener);
|
|
2440
|
+
return () => {
|
|
2441
|
+
listeners.delete(listener);
|
|
2442
|
+
};
|
|
2443
|
+
}
|
|
2444
|
+
var logger = {
|
|
2445
|
+
info(msg) {
|
|
2446
|
+
const line = format("INFO", msg);
|
|
2447
|
+
console.log(line);
|
|
2448
|
+
emit({ level: "INFO", line, message: msg });
|
|
2449
|
+
},
|
|
2450
|
+
warn(msg) {
|
|
2451
|
+
const line = format("WARN", msg);
|
|
2452
|
+
console.warn(line);
|
|
2453
|
+
emit({ level: "WARN", line, message: msg });
|
|
2454
|
+
},
|
|
2455
|
+
error(msg, err) {
|
|
2456
|
+
const line = format("ERROR", msg);
|
|
2457
|
+
if (err) {
|
|
2458
|
+
console.error(line, err);
|
|
2459
|
+
} else {
|
|
2460
|
+
console.error(line);
|
|
2461
|
+
}
|
|
2462
|
+
emit({ level: "ERROR", line, message: msg, error: err });
|
|
2463
|
+
}
|
|
2464
|
+
};
|
|
2465
|
+
|
|
2334
2466
|
// src/agentCredentialProxy.ts
|
|
2335
2467
|
var registrations = /* @__PURE__ */ new Map();
|
|
2336
2468
|
var proxyServerState = null;
|
|
@@ -3157,9 +3289,7 @@ var LOOPBACK_NO_PROXY = "127.0.0.1,localhost";
|
|
|
3157
3289
|
var CLI_TRANSPORT_TRACE_DIR_ENV = "SLOCK_CLI_TRANSPORT_TRACE_DIR";
|
|
3158
3290
|
var safePathPart = (value) => value.replace(/[^a-zA-Z0-9_.-]/g, "_");
|
|
3159
3291
|
var RAW_CREDENTIAL_ENV_DENYLIST = [
|
|
3160
|
-
"
|
|
3161
|
-
"SLOCK_AGENT_CREDENTIAL_KEY",
|
|
3162
|
-
"SLOCK_AGENT_CREDENTIAL_KEY_FILE"
|
|
3292
|
+
"SLOCK_AGENT_CREDENTIAL_KEY"
|
|
3163
3293
|
];
|
|
3164
3294
|
var cachedOpencliBinPath;
|
|
3165
3295
|
function resolveOpencliBinPath() {
|
|
@@ -3374,7 +3504,7 @@ exec ${shellSingleQuote(process.execPath)} ${shellSingleQuote(opencliBinPath)} "
|
|
|
3374
3504
|
...agentCredentialProxy ? {} : { SLOCK_AGENT_TOKEN_FILE: tokenFile },
|
|
3375
3505
|
PATH: `${slockDir}${path2.delimiter}${process.env.PATH ?? ""}`
|
|
3376
3506
|
};
|
|
3377
|
-
|
|
3507
|
+
delete spawnEnv.SLOCK_AGENT_TOKEN;
|
|
3378
3508
|
for (const key of RAW_CREDENTIAL_ENV_DENYLIST) {
|
|
3379
3509
|
delete spawnEnv[key];
|
|
3380
3510
|
}
|
|
@@ -3803,7 +3933,7 @@ function resolveCommandOnWindows(command, env, execFileSyncFn, existsSyncFn) {
|
|
|
3803
3933
|
}
|
|
3804
3934
|
function resolveCommandOnPath(command, deps = {}) {
|
|
3805
3935
|
const platform = deps.platform ?? process.platform;
|
|
3806
|
-
const env =
|
|
3936
|
+
const env = withWindowsUserEnvironment(deps.env ?? process.env, deps);
|
|
3807
3937
|
const execFileSyncFn = deps.execFileSyncFn ?? execFileSync;
|
|
3808
3938
|
const existsSyncFn = deps.existsSyncFn ?? existsSync2;
|
|
3809
3939
|
if (platform === "win32") {
|
|
@@ -3829,7 +3959,7 @@ function firstExistingPath(candidates, deps = {}) {
|
|
|
3829
3959
|
return null;
|
|
3830
3960
|
}
|
|
3831
3961
|
function readCommandVersion(command, args = [], deps = {}) {
|
|
3832
|
-
const env =
|
|
3962
|
+
const env = withWindowsUserEnvironment(deps.env ?? process.env, deps);
|
|
3833
3963
|
const execFileSyncFn = deps.execFileSyncFn ?? execFileSync;
|
|
3834
3964
|
try {
|
|
3835
3965
|
const output = normalizeExecOutput(execFileSyncFn(command, [...args, "--version"], {
|
|
@@ -4526,7 +4656,7 @@ var CodexDriver = class {
|
|
|
4526
4656
|
};
|
|
4527
4657
|
communication = {
|
|
4528
4658
|
chat: "slock_cli",
|
|
4529
|
-
runtimeControl: "
|
|
4659
|
+
runtimeControl: "none"
|
|
4530
4660
|
};
|
|
4531
4661
|
session = {
|
|
4532
4662
|
recovery: "resume_or_fresh"
|
|
@@ -4543,50 +4673,6 @@ var CodexDriver = class {
|
|
|
4543
4673
|
probe() {
|
|
4544
4674
|
return probeCodex();
|
|
4545
4675
|
}
|
|
4546
|
-
buildRuntimeActionsConfigArgs(ctx) {
|
|
4547
|
-
const isTsSource = ctx.chatBridgePath.endsWith(".ts");
|
|
4548
|
-
const command = isTsSource ? "npx" : "node";
|
|
4549
|
-
const bridgeArgs = isTsSource ? [
|
|
4550
|
-
"tsx",
|
|
4551
|
-
ctx.chatBridgePath,
|
|
4552
|
-
"--agent-id",
|
|
4553
|
-
ctx.agentId,
|
|
4554
|
-
"--server-url",
|
|
4555
|
-
ctx.config.serverUrl,
|
|
4556
|
-
"--auth-token",
|
|
4557
|
-
ctx.config.authToken || ctx.daemonApiKey,
|
|
4558
|
-
"--runtime",
|
|
4559
|
-
this.id,
|
|
4560
|
-
...ctx.launchId ? ["--launch-id", ctx.launchId] : [],
|
|
4561
|
-
"--runtime-actions-only"
|
|
4562
|
-
] : [
|
|
4563
|
-
ctx.chatBridgePath,
|
|
4564
|
-
"--agent-id",
|
|
4565
|
-
ctx.agentId,
|
|
4566
|
-
"--server-url",
|
|
4567
|
-
ctx.config.serverUrl,
|
|
4568
|
-
"--auth-token",
|
|
4569
|
-
ctx.config.authToken || ctx.daemonApiKey,
|
|
4570
|
-
"--runtime",
|
|
4571
|
-
this.id,
|
|
4572
|
-
...ctx.launchId ? ["--launch-id", ctx.launchId] : [],
|
|
4573
|
-
"--runtime-actions-only"
|
|
4574
|
-
];
|
|
4575
|
-
return [
|
|
4576
|
-
"-c",
|
|
4577
|
-
`mcp_servers.chat.command=${JSON.stringify(command)}`,
|
|
4578
|
-
"-c",
|
|
4579
|
-
`mcp_servers.chat.args=${JSON.stringify(bridgeArgs)}`,
|
|
4580
|
-
"-c",
|
|
4581
|
-
"mcp_servers.chat.startup_timeout_sec=30",
|
|
4582
|
-
"-c",
|
|
4583
|
-
"mcp_servers.chat.tool_timeout_sec=120",
|
|
4584
|
-
"-c",
|
|
4585
|
-
"mcp_servers.chat.enabled=true",
|
|
4586
|
-
"-c",
|
|
4587
|
-
"mcp_servers.chat.required=true"
|
|
4588
|
-
];
|
|
4589
|
-
}
|
|
4590
4676
|
buildThreadRequest(ctx) {
|
|
4591
4677
|
const threadParams = {
|
|
4592
4678
|
cwd: ctx.workingDirectory,
|
|
@@ -4640,7 +4726,6 @@ var CodexDriver = class {
|
|
|
4640
4726
|
this.initialTurnStarted = false;
|
|
4641
4727
|
this.normalizer.reset({ threadId: ctx.config.sessionId || null });
|
|
4642
4728
|
const args = ["app-server", "--listen", "stdio://"];
|
|
4643
|
-
args.push(...this.buildRuntimeActionsConfigArgs(ctx));
|
|
4644
4729
|
const { command, args: spawnArgs } = resolveCodexSpawn(args);
|
|
4645
4730
|
const proc = spawn2(command, spawnArgs, {
|
|
4646
4731
|
cwd: ctx.workingDirectory,
|
|
@@ -4927,8 +5012,6 @@ var AntigravityDriver = class {
|
|
|
4927
5012
|
|
|
4928
5013
|
// src/drivers/copilot.ts
|
|
4929
5014
|
import { spawn as spawn4 } from "child_process";
|
|
4930
|
-
import path6 from "path";
|
|
4931
|
-
import { writeFileSync as writeFileSync3 } from "fs";
|
|
4932
5015
|
async function buildCopilotSpawnEnv(ctx) {
|
|
4933
5016
|
return (await prepareCliTransport(ctx, { NO_COLOR: "1" })).spawnEnv;
|
|
4934
5017
|
}
|
|
@@ -4942,7 +5025,7 @@ var CopilotDriver = class {
|
|
|
4942
5025
|
};
|
|
4943
5026
|
communication = {
|
|
4944
5027
|
chat: "slock_cli",
|
|
4945
|
-
runtimeControl: "
|
|
5028
|
+
runtimeControl: "none"
|
|
4946
5029
|
};
|
|
4947
5030
|
session = {
|
|
4948
5031
|
recovery: "resume_or_fresh"
|
|
@@ -4957,43 +5040,14 @@ var CopilotDriver = class {
|
|
|
4957
5040
|
usesSlockCliForCommunication = true;
|
|
4958
5041
|
sessionId = null;
|
|
4959
5042
|
sessionAnnounced = false;
|
|
4960
|
-
buildRuntimeActionsMcpConfig(ctx) {
|
|
4961
|
-
const isTsSource = ctx.chatBridgePath.endsWith(".ts");
|
|
4962
|
-
const command = isTsSource ? "npx" : "node";
|
|
4963
|
-
const bridgeArgs = isTsSource ? ["tsx", ctx.chatBridgePath] : [ctx.chatBridgePath];
|
|
4964
|
-
return JSON.stringify({
|
|
4965
|
-
mcpServers: {
|
|
4966
|
-
chat: {
|
|
4967
|
-
command,
|
|
4968
|
-
args: [
|
|
4969
|
-
...bridgeArgs,
|
|
4970
|
-
"--agent-id",
|
|
4971
|
-
ctx.agentId,
|
|
4972
|
-
"--server-url",
|
|
4973
|
-
ctx.config.serverUrl,
|
|
4974
|
-
"--auth-token",
|
|
4975
|
-
ctx.config.authToken || ctx.daemonApiKey,
|
|
4976
|
-
"--runtime",
|
|
4977
|
-
this.id,
|
|
4978
|
-
...ctx.launchId ? ["--launch-id", ctx.launchId] : [],
|
|
4979
|
-
"--runtime-actions-only"
|
|
4980
|
-
]
|
|
4981
|
-
}
|
|
4982
|
-
}
|
|
4983
|
-
});
|
|
4984
|
-
}
|
|
4985
5043
|
async spawn(ctx) {
|
|
4986
5044
|
this.sessionId = ctx.config.sessionId || null;
|
|
4987
5045
|
this.sessionAnnounced = false;
|
|
4988
|
-
const mcpConfigPath = path6.join(ctx.workingDirectory, ".slock-copilot-mcp.json");
|
|
4989
|
-
writeFileSync3(mcpConfigPath, this.buildRuntimeActionsMcpConfig(ctx), "utf8");
|
|
4990
5046
|
const args = [
|
|
4991
5047
|
"--output-format",
|
|
4992
5048
|
"json",
|
|
4993
5049
|
"--allow-all-tools",
|
|
4994
5050
|
"--allow-all-paths",
|
|
4995
|
-
"--additional-mcp-config",
|
|
4996
|
-
`@${mcpConfigPath}`,
|
|
4997
5051
|
"-p",
|
|
4998
5052
|
ctx.prompt
|
|
4999
5053
|
];
|
|
@@ -5102,8 +5156,6 @@ var CopilotDriver = class {
|
|
|
5102
5156
|
|
|
5103
5157
|
// src/drivers/cursor.ts
|
|
5104
5158
|
import { spawn as spawn5, spawnSync } from "child_process";
|
|
5105
|
-
import { writeFileSync as writeFileSync4, mkdirSync as mkdirSync2, existsSync as existsSync4 } from "fs";
|
|
5106
|
-
import path7 from "path";
|
|
5107
5159
|
async function buildCursorSpawnEnv(ctx, deps = {}) {
|
|
5108
5160
|
const { spawnEnv } = await prepareCliTransport(ctx, { NO_COLOR: "1" });
|
|
5109
5161
|
return withWindowsUserEnvironment(spawnEnv, deps);
|
|
@@ -5118,7 +5170,7 @@ var CursorDriver = class {
|
|
|
5118
5170
|
};
|
|
5119
5171
|
communication = {
|
|
5120
5172
|
chat: "slock_cli",
|
|
5121
|
-
runtimeControl: "
|
|
5173
|
+
runtimeControl: "none"
|
|
5122
5174
|
};
|
|
5123
5175
|
session = {
|
|
5124
5176
|
recovery: "resume_or_fresh"
|
|
@@ -5131,38 +5183,7 @@ var CursorDriver = class {
|
|
|
5131
5183
|
mcpToolPrefix = "mcp__chat__";
|
|
5132
5184
|
busyDeliveryMode = "none";
|
|
5133
5185
|
usesSlockCliForCommunication = true;
|
|
5134
|
-
buildRuntimeActionsMcpConfig(ctx) {
|
|
5135
|
-
const isTsSource = ctx.chatBridgePath.endsWith(".ts");
|
|
5136
|
-
const command = isTsSource ? "npx" : "node";
|
|
5137
|
-
const bridgeArgs = isTsSource ? ["tsx", ctx.chatBridgePath] : [ctx.chatBridgePath];
|
|
5138
|
-
return JSON.stringify({
|
|
5139
|
-
mcpServers: {
|
|
5140
|
-
chat: {
|
|
5141
|
-
command,
|
|
5142
|
-
args: [
|
|
5143
|
-
...bridgeArgs,
|
|
5144
|
-
"--agent-id",
|
|
5145
|
-
ctx.agentId,
|
|
5146
|
-
"--server-url",
|
|
5147
|
-
ctx.config.serverUrl,
|
|
5148
|
-
"--auth-token",
|
|
5149
|
-
ctx.config.authToken || ctx.daemonApiKey,
|
|
5150
|
-
"--runtime",
|
|
5151
|
-
this.id,
|
|
5152
|
-
...ctx.launchId ? ["--launch-id", ctx.launchId] : [],
|
|
5153
|
-
"--runtime-actions-only"
|
|
5154
|
-
]
|
|
5155
|
-
}
|
|
5156
|
-
}
|
|
5157
|
-
});
|
|
5158
|
-
}
|
|
5159
5186
|
async spawn(ctx) {
|
|
5160
|
-
const cursorDir = path7.join(ctx.workingDirectory, ".cursor");
|
|
5161
|
-
if (!existsSync4(cursorDir)) {
|
|
5162
|
-
mkdirSync2(cursorDir, { recursive: true });
|
|
5163
|
-
}
|
|
5164
|
-
const mcpConfigPath = path7.join(cursorDir, "mcp.json");
|
|
5165
|
-
writeFileSync4(mcpConfigPath, this.buildRuntimeActionsMcpConfig(ctx), "utf8");
|
|
5166
5187
|
const args = [
|
|
5167
5188
|
"--print",
|
|
5168
5189
|
"--output-format",
|
|
@@ -5292,11 +5313,11 @@ function detectCursorModels(runCommand = runCursorModelsCommand) {
|
|
|
5292
5313
|
return parseCursorModelsOutput(String(result.stdout || ""));
|
|
5293
5314
|
}
|
|
5294
5315
|
function buildCursorModelProbeEnv(deps = {}) {
|
|
5295
|
-
return
|
|
5316
|
+
return withWindowsUserEnvironment({
|
|
5296
5317
|
...deps.env ?? process.env,
|
|
5297
5318
|
FORCE_COLOR: "0",
|
|
5298
5319
|
NO_COLOR: "1"
|
|
5299
|
-
}, deps)
|
|
5320
|
+
}, deps);
|
|
5300
5321
|
}
|
|
5301
5322
|
function runCursorModelsCommand() {
|
|
5302
5323
|
return spawnSync("cursor-agent", ["models"], {
|
|
@@ -5308,8 +5329,8 @@ function runCursorModelsCommand() {
|
|
|
5308
5329
|
|
|
5309
5330
|
// src/drivers/gemini.ts
|
|
5310
5331
|
import { execFileSync as execFileSync3, spawn as spawn6 } from "child_process";
|
|
5311
|
-
import { existsSync as
|
|
5312
|
-
import
|
|
5332
|
+
import { existsSync as existsSync4 } from "fs";
|
|
5333
|
+
import path6 from "path";
|
|
5313
5334
|
async function buildGeminiSpawnEnv(ctx, platform = process.platform) {
|
|
5314
5335
|
const { spawnEnv } = await prepareCliTransport(ctx, { NO_COLOR: "1" }, platform);
|
|
5315
5336
|
const launchEnvVars = runtimeConfigToLaunchFields(ctx.config).envVars;
|
|
@@ -5351,9 +5372,9 @@ function resolveGeminiSpawn(commandArgs, deps = {}) {
|
|
|
5351
5372
|
return { command: resolveCommandOnPath("gemini", deps) ?? "gemini", args: commandArgs };
|
|
5352
5373
|
}
|
|
5353
5374
|
const execFileSyncFn = deps.execFileSyncFn ?? execFileSync3;
|
|
5354
|
-
const existsSyncFn = deps.existsSyncFn ??
|
|
5355
|
-
const env =
|
|
5356
|
-
const winPath =
|
|
5375
|
+
const existsSyncFn = deps.existsSyncFn ?? existsSync4;
|
|
5376
|
+
const env = deps.env ?? process.env;
|
|
5377
|
+
const winPath = path6.win32;
|
|
5357
5378
|
let geminiEntry = null;
|
|
5358
5379
|
try {
|
|
5359
5380
|
const globalRoot = normalizeExecOutput2(execFileSyncFn("npm", ["root", "-g"], {
|
|
@@ -5397,7 +5418,7 @@ var GeminiDriver = class {
|
|
|
5397
5418
|
};
|
|
5398
5419
|
communication = {
|
|
5399
5420
|
chat: "slock_cli",
|
|
5400
|
-
runtimeControl: "
|
|
5421
|
+
runtimeControl: "none"
|
|
5401
5422
|
};
|
|
5402
5423
|
session = {
|
|
5403
5424
|
recovery: "resume_or_fresh"
|
|
@@ -5415,7 +5436,6 @@ var GeminiDriver = class {
|
|
|
5415
5436
|
async spawn(ctx) {
|
|
5416
5437
|
this.sessionId = ctx.config.sessionId || null;
|
|
5417
5438
|
this.sessionAnnounced = false;
|
|
5418
|
-
this.writeGeminiSettings(ctx);
|
|
5419
5439
|
const { command, args } = resolveGeminiSpawn(buildGeminiArgs(ctx.config));
|
|
5420
5440
|
const spawnEnv = await buildGeminiSpawnEnv(ctx);
|
|
5421
5441
|
const proc = spawn6(command, args, {
|
|
@@ -5488,52 +5508,17 @@ var GeminiDriver = class {
|
|
|
5488
5508
|
messageNotificationStyle: "poll"
|
|
5489
5509
|
});
|
|
5490
5510
|
}
|
|
5491
|
-
writeGeminiSettings(ctx) {
|
|
5492
|
-
const geminiDir = path8.join(ctx.workingDirectory, ".gemini");
|
|
5493
|
-
mkdirSync3(geminiDir, { recursive: true });
|
|
5494
|
-
const settingsPath = path8.join(geminiDir, "settings.json");
|
|
5495
|
-
writeFileSync5(settingsPath, JSON.stringify(this.buildRuntimeActionsMcpSettings(ctx)), "utf8");
|
|
5496
|
-
}
|
|
5497
|
-
buildRuntimeActionsMcpSettings(ctx) {
|
|
5498
|
-
const isTsSource = ctx.chatBridgePath.endsWith(".ts");
|
|
5499
|
-
const command = isTsSource ? "npx" : "node";
|
|
5500
|
-
const bridgeArgs = isTsSource ? ["tsx", ctx.chatBridgePath] : [ctx.chatBridgePath];
|
|
5501
|
-
return {
|
|
5502
|
-
mcpServers: {
|
|
5503
|
-
chat: {
|
|
5504
|
-
command,
|
|
5505
|
-
args: [
|
|
5506
|
-
...bridgeArgs,
|
|
5507
|
-
"--agent-id",
|
|
5508
|
-
ctx.agentId,
|
|
5509
|
-
"--server-url",
|
|
5510
|
-
ctx.config.serverUrl,
|
|
5511
|
-
"--auth-token",
|
|
5512
|
-
ctx.config.authToken || ctx.daemonApiKey,
|
|
5513
|
-
"--runtime",
|
|
5514
|
-
this.id,
|
|
5515
|
-
...ctx.launchId ? ["--launch-id", ctx.launchId] : [],
|
|
5516
|
-
"--runtime-actions-only"
|
|
5517
|
-
]
|
|
5518
|
-
}
|
|
5519
|
-
}
|
|
5520
|
-
};
|
|
5521
|
-
}
|
|
5522
5511
|
};
|
|
5523
5512
|
|
|
5524
5513
|
// src/drivers/kimi.ts
|
|
5525
5514
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
5526
5515
|
import { spawn as spawn7 } from "child_process";
|
|
5527
|
-
import {
|
|
5516
|
+
import { existsSync as existsSync5, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
5528
5517
|
import os3 from "os";
|
|
5529
|
-
import
|
|
5518
|
+
import path7 from "path";
|
|
5530
5519
|
var KIMI_WIRE_PROTOCOL_VERSION = "1.3";
|
|
5531
5520
|
var KIMI_SYSTEM_PROMPT_FILE = ".slock-kimi-system.md";
|
|
5532
5521
|
var KIMI_AGENT_FILE = ".slock-kimi-agent.yaml";
|
|
5533
|
-
var KIMI_MCP_FILE = ".slock-kimi-mcp.json";
|
|
5534
|
-
var KIMI_GENERATED_CONFIG_FILE = ".slock-kimi-config.toml";
|
|
5535
|
-
var SLOCK_KIMI_CONFIG_CONTENT_ENV = "SLOCK_KIMI_CONFIG_CONTENT";
|
|
5536
|
-
var SLOCK_KIMI_CONFIG_FILE_ENV = "SLOCK_KIMI_CONFIG_FILE";
|
|
5537
5522
|
function parseToolArguments(raw) {
|
|
5538
5523
|
if (typeof raw !== "string") return raw;
|
|
5539
5524
|
try {
|
|
@@ -5542,73 +5527,6 @@ function parseToolArguments(raw) {
|
|
|
5542
5527
|
return raw;
|
|
5543
5528
|
}
|
|
5544
5529
|
}
|
|
5545
|
-
function readKimiConfigSource(home = os3.homedir(), env = process.env) {
|
|
5546
|
-
const inlineConfig = env[SLOCK_KIMI_CONFIG_CONTENT_ENV];
|
|
5547
|
-
if (inlineConfig && inlineConfig.trim()) {
|
|
5548
|
-
return {
|
|
5549
|
-
raw: inlineConfig,
|
|
5550
|
-
explicitPath: null,
|
|
5551
|
-
sourcePath: SLOCK_KIMI_CONFIG_CONTENT_ENV
|
|
5552
|
-
};
|
|
5553
|
-
}
|
|
5554
|
-
const explicitPath = env[SLOCK_KIMI_CONFIG_FILE_ENV];
|
|
5555
|
-
const configPath = explicitPath && explicitPath.trim() ? explicitPath : path9.join(home, ".kimi", "config.toml");
|
|
5556
|
-
try {
|
|
5557
|
-
return {
|
|
5558
|
-
raw: readFileSync3(configPath, "utf8"),
|
|
5559
|
-
explicitPath: explicitPath && explicitPath.trim() ? explicitPath : null,
|
|
5560
|
-
sourcePath: configPath
|
|
5561
|
-
};
|
|
5562
|
-
} catch {
|
|
5563
|
-
return {
|
|
5564
|
-
raw: null,
|
|
5565
|
-
explicitPath: explicitPath && explicitPath.trim() ? explicitPath : null,
|
|
5566
|
-
sourcePath: configPath
|
|
5567
|
-
};
|
|
5568
|
-
}
|
|
5569
|
-
}
|
|
5570
|
-
function buildKimiSpawnEnv(env = process.env) {
|
|
5571
|
-
const spawnEnv = { ...env, FORCE_COLOR: "0", NO_COLOR: "1" };
|
|
5572
|
-
delete spawnEnv[SLOCK_KIMI_CONFIG_CONTENT_ENV];
|
|
5573
|
-
delete spawnEnv[SLOCK_KIMI_CONFIG_FILE_ENV];
|
|
5574
|
-
return scrubDaemonChildEnv(spawnEnv);
|
|
5575
|
-
}
|
|
5576
|
-
function buildKimiEffectiveEnv(ctx, overrideEnv) {
|
|
5577
|
-
return {
|
|
5578
|
-
...process.env,
|
|
5579
|
-
...ctx.config.envVars || {},
|
|
5580
|
-
...overrideEnv || {}
|
|
5581
|
-
};
|
|
5582
|
-
}
|
|
5583
|
-
function buildKimiLaunchOptions(ctx, opts = {}) {
|
|
5584
|
-
const env = buildKimiEffectiveEnv(ctx, opts.env);
|
|
5585
|
-
const source = readKimiConfigSource(opts.home ?? os3.homedir(), env);
|
|
5586
|
-
const args = [];
|
|
5587
|
-
let configFilePath = null;
|
|
5588
|
-
let configContent = null;
|
|
5589
|
-
if (source.explicitPath) {
|
|
5590
|
-
configFilePath = source.explicitPath;
|
|
5591
|
-
} else if (source.raw !== null && source.sourcePath === SLOCK_KIMI_CONFIG_CONTENT_ENV) {
|
|
5592
|
-
configFilePath = path9.join(ctx.workingDirectory, KIMI_GENERATED_CONFIG_FILE);
|
|
5593
|
-
configContent = source.raw;
|
|
5594
|
-
if (opts.writeGeneratedConfig !== false) {
|
|
5595
|
-
writeFileSync6(configFilePath, source.raw, { encoding: "utf8", mode: 384 });
|
|
5596
|
-
chmodSync(configFilePath, 384);
|
|
5597
|
-
}
|
|
5598
|
-
}
|
|
5599
|
-
if (configFilePath) {
|
|
5600
|
-
args.push("--config-file", configFilePath);
|
|
5601
|
-
}
|
|
5602
|
-
if (ctx.config.model && ctx.config.model !== "default") {
|
|
5603
|
-
args.push("--model", ctx.config.model);
|
|
5604
|
-
}
|
|
5605
|
-
return {
|
|
5606
|
-
args,
|
|
5607
|
-
env: buildKimiSpawnEnv(env),
|
|
5608
|
-
configFilePath,
|
|
5609
|
-
configContent
|
|
5610
|
-
};
|
|
5611
|
-
}
|
|
5612
5530
|
function resolveKimiSpawn(commandArgs, deps = {}) {
|
|
5613
5531
|
return {
|
|
5614
5532
|
command: resolveCommandOnPath("kimi", deps) ?? "kimi",
|
|
@@ -5625,32 +5543,14 @@ var KimiDriver = class {
|
|
|
5625
5543
|
};
|
|
5626
5544
|
communication = {
|
|
5627
5545
|
chat: "slock_cli",
|
|
5628
|
-
runtimeControl: "
|
|
5546
|
+
runtimeControl: "none"
|
|
5629
5547
|
};
|
|
5630
5548
|
session = {
|
|
5631
5549
|
recovery: "resume_or_fresh"
|
|
5632
5550
|
};
|
|
5633
5551
|
model = {
|
|
5634
5552
|
detectedModelsVerifiedAs: "launchable",
|
|
5635
|
-
toLaunchSpec: (modelId
|
|
5636
|
-
if (!ctx) return { args: ["--model", modelId] };
|
|
5637
|
-
const launchCtx = {
|
|
5638
|
-
...ctx,
|
|
5639
|
-
config: {
|
|
5640
|
-
...ctx.config,
|
|
5641
|
-
model: modelId
|
|
5642
|
-
}
|
|
5643
|
-
};
|
|
5644
|
-
const launch = buildKimiLaunchOptions(launchCtx, {
|
|
5645
|
-
home: opts?.home,
|
|
5646
|
-
writeGeneratedConfig: false
|
|
5647
|
-
});
|
|
5648
|
-
return {
|
|
5649
|
-
args: launch.args,
|
|
5650
|
-
env: launch.env,
|
|
5651
|
-
configFiles: launch.configFilePath ? [launch.configFilePath] : void 0
|
|
5652
|
-
};
|
|
5653
|
-
}
|
|
5553
|
+
toLaunchSpec: (modelId) => ({ args: ["--model", modelId] })
|
|
5654
5554
|
};
|
|
5655
5555
|
supportsStdinNotification = true;
|
|
5656
5556
|
mcpToolPrefix = "";
|
|
@@ -5659,70 +5559,38 @@ var KimiDriver = class {
|
|
|
5659
5559
|
sessionId = null;
|
|
5660
5560
|
sessionAnnounced = false;
|
|
5661
5561
|
promptRequestId = null;
|
|
5662
|
-
buildChatBridgeArgs(ctx) {
|
|
5663
|
-
const isTsSource = ctx.chatBridgePath.endsWith(".ts");
|
|
5664
|
-
return [
|
|
5665
|
-
...isTsSource ? ["tsx", ctx.chatBridgePath] : [ctx.chatBridgePath],
|
|
5666
|
-
"--agent-id",
|
|
5667
|
-
ctx.agentId,
|
|
5668
|
-
"--server-url",
|
|
5669
|
-
ctx.config.serverUrl,
|
|
5670
|
-
"--auth-token",
|
|
5671
|
-
ctx.config.authToken || ctx.daemonApiKey,
|
|
5672
|
-
"--runtime",
|
|
5673
|
-
"kimi",
|
|
5674
|
-
...ctx.launchId ? ["--launch-id", ctx.launchId] : [],
|
|
5675
|
-
"--runtime-actions-only"
|
|
5676
|
-
];
|
|
5677
|
-
}
|
|
5678
5562
|
async spawn(ctx) {
|
|
5679
5563
|
const isResume = !!ctx.config.sessionId;
|
|
5680
5564
|
this.sessionId = ctx.config.sessionId || randomUUID2();
|
|
5681
5565
|
this.sessionAnnounced = false;
|
|
5682
5566
|
this.promptRequestId = randomUUID2();
|
|
5683
|
-
const
|
|
5684
|
-
const
|
|
5685
|
-
|
|
5686
|
-
|
|
5687
|
-
|
|
5688
|
-
|
|
5689
|
-
if (!isResume || !existsSync6(systemPromptPath)) {
|
|
5690
|
-
writeFileSync6(systemPromptPath, ctx.prompt, "utf8");
|
|
5691
|
-
}
|
|
5692
|
-
writeFileSync6(agentFilePath, [
|
|
5567
|
+
const systemPromptPath = path7.join(ctx.workingDirectory, KIMI_SYSTEM_PROMPT_FILE);
|
|
5568
|
+
const agentFilePath = path7.join(ctx.workingDirectory, KIMI_AGENT_FILE);
|
|
5569
|
+
if (!isResume || !existsSync5(systemPromptPath)) {
|
|
5570
|
+
writeFileSync3(systemPromptPath, ctx.prompt, "utf8");
|
|
5571
|
+
}
|
|
5572
|
+
writeFileSync3(agentFilePath, [
|
|
5693
5573
|
"version: 1",
|
|
5694
5574
|
"agent:",
|
|
5695
5575
|
" extend: default",
|
|
5696
5576
|
` system_prompt_path: ./${KIMI_SYSTEM_PROMPT_FILE}`,
|
|
5697
5577
|
""
|
|
5698
5578
|
].join("\n"), "utf8");
|
|
5699
|
-
writeFileSync6(mcpConfigPath, JSON.stringify({
|
|
5700
|
-
mcpServers: {
|
|
5701
|
-
chat: {
|
|
5702
|
-
command,
|
|
5703
|
-
args: bridgeArgs
|
|
5704
|
-
}
|
|
5705
|
-
}
|
|
5706
|
-
}), "utf8");
|
|
5707
|
-
const launch = buildKimiLaunchOptions(ctx);
|
|
5708
5579
|
const args = [
|
|
5709
5580
|
"--wire",
|
|
5710
5581
|
"--yolo",
|
|
5711
5582
|
"--agent-file",
|
|
5712
5583
|
agentFilePath,
|
|
5713
|
-
"--mcp-config-file",
|
|
5714
|
-
mcpConfigPath,
|
|
5715
5584
|
"--session",
|
|
5716
|
-
this.sessionId
|
|
5717
|
-
...launch.args
|
|
5585
|
+
this.sessionId
|
|
5718
5586
|
];
|
|
5719
5587
|
const launchRuntimeFields = runtimeConfigToLaunchFields(ctx.config);
|
|
5720
5588
|
if (launchRuntimeFields.model && launchRuntimeFields.model !== "default") {
|
|
5721
5589
|
args.push("--model", launchRuntimeFields.model);
|
|
5722
5590
|
}
|
|
5723
5591
|
const spawnEnv = (await prepareCliTransport(ctx, { NO_COLOR: "1" })).spawnEnv;
|
|
5724
|
-
const
|
|
5725
|
-
const proc = spawn7(
|
|
5592
|
+
const launch = resolveKimiSpawn(args);
|
|
5593
|
+
const proc = spawn7(launch.command, launch.args, {
|
|
5726
5594
|
cwd: ctx.workingDirectory,
|
|
5727
5595
|
stdio: ["pipe", "pipe", "pipe"],
|
|
5728
5596
|
env: spawnEnv,
|
|
@@ -5730,7 +5598,7 @@ var KimiDriver = class {
|
|
|
5730
5598
|
// and has an 8191-character command-line limit. Kimi's official
|
|
5731
5599
|
// installer/uv entrypoint is an executable, so launch it directly and
|
|
5732
5600
|
// keep prompts on stdin / files instead of routing through cmd.exe.
|
|
5733
|
-
shell:
|
|
5601
|
+
shell: launch.shell
|
|
5734
5602
|
});
|
|
5735
5603
|
proc.stdin?.write(JSON.stringify({
|
|
5736
5604
|
jsonrpc: "2.0",
|
|
@@ -5844,9 +5712,14 @@ var KimiDriver = class {
|
|
|
5844
5712
|
return detectKimiModels();
|
|
5845
5713
|
}
|
|
5846
5714
|
};
|
|
5847
|
-
function detectKimiModels(home = os3.homedir()
|
|
5848
|
-
const
|
|
5849
|
-
|
|
5715
|
+
function detectKimiModels(home = os3.homedir()) {
|
|
5716
|
+
const configPath = path7.join(home, ".kimi", "config.toml");
|
|
5717
|
+
let raw;
|
|
5718
|
+
try {
|
|
5719
|
+
raw = readFileSync3(configPath, "utf8");
|
|
5720
|
+
} catch {
|
|
5721
|
+
return null;
|
|
5722
|
+
}
|
|
5850
5723
|
const models = [];
|
|
5851
5724
|
const sectionRe = /^\s*\[models(?:\.([^\]]+)|"\.[^"]+"|\."[^"]+")\s*\]\s*$/gm;
|
|
5852
5725
|
const lineRe = /^\s*\[models\.(.+?)\s*\]\s*$/gm;
|
|
@@ -5867,9 +5740,9 @@ function detectKimiModels(home = os3.homedir(), opts = {}) {
|
|
|
5867
5740
|
|
|
5868
5741
|
// src/drivers/opencode.ts
|
|
5869
5742
|
import { spawn as spawn8, spawnSync as spawnSync2 } from "child_process";
|
|
5870
|
-
import { existsSync as
|
|
5743
|
+
import { existsSync as existsSync6, readFileSync as readFileSync4 } from "fs";
|
|
5871
5744
|
import os4 from "os";
|
|
5872
|
-
import
|
|
5745
|
+
import path8 from "path";
|
|
5873
5746
|
var CHAT_MCP_SERVER_NAME = "chat";
|
|
5874
5747
|
var CHAT_MCP_TOOL_PREFIX = `${CHAT_MCP_SERVER_NAME}_`;
|
|
5875
5748
|
var SLOCK_AGENT_NAME = "slock";
|
|
@@ -5884,23 +5757,6 @@ var OPENCODE_PROVIDER_LABELS = {
|
|
|
5884
5757
|
deepseek: "DeepSeek",
|
|
5885
5758
|
fusecode: "FuseCode"
|
|
5886
5759
|
};
|
|
5887
|
-
function buildChatBridgeCommand(ctx) {
|
|
5888
|
-
const isTsSource = ctx.chatBridgePath.endsWith(".ts");
|
|
5889
|
-
return [
|
|
5890
|
-
isTsSource ? "npx" : "node",
|
|
5891
|
-
...isTsSource ? ["tsx", ctx.chatBridgePath] : [ctx.chatBridgePath],
|
|
5892
|
-
"--agent-id",
|
|
5893
|
-
ctx.agentId,
|
|
5894
|
-
"--server-url",
|
|
5895
|
-
ctx.config.serverUrl,
|
|
5896
|
-
"--auth-token",
|
|
5897
|
-
ctx.config.authToken || ctx.daemonApiKey,
|
|
5898
|
-
"--runtime",
|
|
5899
|
-
"opencode",
|
|
5900
|
-
...ctx.launchId ? ["--launch-id", ctx.launchId] : [],
|
|
5901
|
-
"--runtime-actions-only"
|
|
5902
|
-
];
|
|
5903
|
-
}
|
|
5904
5760
|
function parseOpenCodeConfigContent(raw) {
|
|
5905
5761
|
if (!raw) return {};
|
|
5906
5762
|
try {
|
|
@@ -5917,7 +5773,7 @@ function parseUserOpenCodeConfig(ctx) {
|
|
|
5917
5773
|
return parseOpenCodeConfigContent(raw);
|
|
5918
5774
|
}
|
|
5919
5775
|
function readLocalOpenCodeConfig(home = os4.homedir()) {
|
|
5920
|
-
const configPath =
|
|
5776
|
+
const configPath = path8.join(home, ".config", "opencode", "opencode.json");
|
|
5921
5777
|
try {
|
|
5922
5778
|
return parseOpenCodeConfigContent(readFileSync4(configPath, "utf8"));
|
|
5923
5779
|
} catch {
|
|
@@ -5992,14 +5848,7 @@ function buildOpenCodeConfig(ctx, home = os4.homedir()) {
|
|
|
5992
5848
|
prompt: ctx.standingPrompt
|
|
5993
5849
|
}
|
|
5994
5850
|
},
|
|
5995
|
-
mcp:
|
|
5996
|
-
...recordField(userConfig.mcp),
|
|
5997
|
-
[CHAT_MCP_SERVER_NAME]: {
|
|
5998
|
-
type: "local",
|
|
5999
|
-
command: buildChatBridgeCommand(ctx),
|
|
6000
|
-
enabled: true
|
|
6001
|
-
}
|
|
6002
|
-
}
|
|
5851
|
+
mcp: recordField(userConfig.mcp)
|
|
6003
5852
|
};
|
|
6004
5853
|
}
|
|
6005
5854
|
async function buildOpenCodeLaunchOptions(ctx, home = os4.homedir(), version = null) {
|
|
@@ -6110,7 +5959,7 @@ function runOpenCodeModelsCommand(home, deps = {}) {
|
|
|
6110
5959
|
const platform = deps.platform ?? process.platform;
|
|
6111
5960
|
const spawnSyncFn = deps.spawnSyncFn ?? spawnSync2;
|
|
6112
5961
|
const result = spawnSyncFn("opencode", ["models"], {
|
|
6113
|
-
env:
|
|
5962
|
+
env: { ...process.env, HOME: home, FORCE_COLOR: "0", NO_COLOR: "1" },
|
|
6114
5963
|
encoding: "utf8",
|
|
6115
5964
|
timeout: 5e3,
|
|
6116
5965
|
shell: platform === "win32"
|
|
@@ -6122,11 +5971,11 @@ function runOpenCodeModelsCommand(home, deps = {}) {
|
|
|
6122
5971
|
};
|
|
6123
5972
|
}
|
|
6124
5973
|
function isWindowsCommandShim(commandPath) {
|
|
6125
|
-
const ext =
|
|
5974
|
+
const ext = path8.win32.extname(commandPath).toLowerCase();
|
|
6126
5975
|
return ext === ".cmd" || ext === ".bat";
|
|
6127
5976
|
}
|
|
6128
5977
|
function opencodePackageEntryCandidates(packageRoot) {
|
|
6129
|
-
const winPath =
|
|
5978
|
+
const winPath = path8.win32;
|
|
6130
5979
|
return [
|
|
6131
5980
|
winPath.join(packageRoot, "bin", "opencode.exe"),
|
|
6132
5981
|
winPath.join(packageRoot, "bin", "opencode.js"),
|
|
@@ -6135,16 +5984,16 @@ function opencodePackageEntryCandidates(packageRoot) {
|
|
|
6135
5984
|
];
|
|
6136
5985
|
}
|
|
6137
5986
|
function openCodeSpecForEntry(entry, commandArgs) {
|
|
6138
|
-
if (
|
|
5987
|
+
if (path8.win32.extname(entry).toLowerCase() === ".exe") {
|
|
6139
5988
|
return { command: entry, args: commandArgs, shell: false };
|
|
6140
5989
|
}
|
|
6141
5990
|
return { command: process.execPath, args: [entry, ...commandArgs], shell: false };
|
|
6142
5991
|
}
|
|
6143
5992
|
function resolveWindowsOpenCodePackageEntry(commandPath, deps = {}) {
|
|
6144
|
-
const existsSyncFn = deps.existsSyncFn ??
|
|
5993
|
+
const existsSyncFn = deps.existsSyncFn ?? existsSync6;
|
|
6145
5994
|
const execFileSyncFn = deps.execFileSyncFn;
|
|
6146
5995
|
const env = deps.env ?? process.env;
|
|
6147
|
-
const winPath =
|
|
5996
|
+
const winPath = path8.win32;
|
|
6148
5997
|
const candidates = [];
|
|
6149
5998
|
if (execFileSyncFn) {
|
|
6150
5999
|
try {
|
|
@@ -6172,7 +6021,7 @@ function resolveWindowsOpenCodePackageEntry(commandPath, deps = {}) {
|
|
|
6172
6021
|
function extractWindowsShimTargets(commandPath, deps = {}) {
|
|
6173
6022
|
if (!isWindowsCommandShim(commandPath)) return [];
|
|
6174
6023
|
const readFileSyncFn = deps.readFileSyncFn ?? readFileSync4;
|
|
6175
|
-
const commandDir =
|
|
6024
|
+
const commandDir = path8.win32.dirname(commandPath);
|
|
6176
6025
|
let raw;
|
|
6177
6026
|
try {
|
|
6178
6027
|
raw = String(readFileSyncFn(commandPath, "utf8"));
|
|
@@ -6183,7 +6032,7 @@ function extractWindowsShimTargets(commandPath, deps = {}) {
|
|
|
6183
6032
|
const dp0Pattern = /%~dp0\\?([^"\r\n]*?opencode\.(?:exe|js|mjs|cjs))/gi;
|
|
6184
6033
|
for (const match of raw.matchAll(dp0Pattern)) {
|
|
6185
6034
|
const relative = match[1]?.replace(/^\\+/, "");
|
|
6186
|
-
if (relative) candidates.push(
|
|
6035
|
+
if (relative) candidates.push(path8.win32.normalize(path8.win32.join(commandDir, relative)));
|
|
6187
6036
|
}
|
|
6188
6037
|
return candidates;
|
|
6189
6038
|
}
|
|
@@ -6197,7 +6046,7 @@ function resolveOpenCodeSpawn(commandArgs, deps = {}) {
|
|
|
6197
6046
|
};
|
|
6198
6047
|
}
|
|
6199
6048
|
const command = resolveCommandOnPath("opencode", deps);
|
|
6200
|
-
if (command &&
|
|
6049
|
+
if (command && path8.win32.extname(command).toLowerCase() === ".exe") {
|
|
6201
6050
|
return { command, args: commandArgs, shell: false };
|
|
6202
6051
|
}
|
|
6203
6052
|
const packageEntry = resolveWindowsOpenCodePackageEntry(command, deps);
|
|
@@ -6241,7 +6090,7 @@ var OpenCodeDriver = class {
|
|
|
6241
6090
|
};
|
|
6242
6091
|
communication = {
|
|
6243
6092
|
chat: "slock_cli",
|
|
6244
|
-
runtimeControl: "
|
|
6093
|
+
runtimeControl: "none"
|
|
6245
6094
|
};
|
|
6246
6095
|
session = {
|
|
6247
6096
|
recovery: "resume_or_fresh"
|
|
@@ -6372,8 +6221,8 @@ var OpenCodeDriver = class {
|
|
|
6372
6221
|
// src/drivers/pi.ts
|
|
6373
6222
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
6374
6223
|
import { EventEmitter } from "events";
|
|
6375
|
-
import { mkdirSync as
|
|
6376
|
-
import
|
|
6224
|
+
import { mkdirSync as mkdirSync2, readdirSync } from "fs";
|
|
6225
|
+
import path9 from "path";
|
|
6377
6226
|
import {
|
|
6378
6227
|
AuthStorage,
|
|
6379
6228
|
createBashTool,
|
|
@@ -6399,7 +6248,7 @@ function createPiSdkEventMappingState(sessionId = null) {
|
|
|
6399
6248
|
};
|
|
6400
6249
|
}
|
|
6401
6250
|
function buildPiSessionDir(workingDirectory) {
|
|
6402
|
-
return
|
|
6251
|
+
return path9.join(workingDirectory, PI_SESSION_DIR);
|
|
6403
6252
|
}
|
|
6404
6253
|
async function buildPiSpawnEnv(ctx) {
|
|
6405
6254
|
return (await prepareCliTransport(ctx, { NO_COLOR: "1" })).spawnEnv;
|
|
@@ -6421,7 +6270,7 @@ function findPiSessionFile(sessionDir, sessionId) {
|
|
|
6421
6270
|
}
|
|
6422
6271
|
const suffix = `_${sessionId}.jsonl`;
|
|
6423
6272
|
const match = entries.find((entry) => entry.endsWith(suffix));
|
|
6424
|
-
return match ?
|
|
6273
|
+
return match ? path9.join(sessionDir, match) : null;
|
|
6425
6274
|
}
|
|
6426
6275
|
function detectPiModelsFromRegistry(modelRegistry) {
|
|
6427
6276
|
const models = [];
|
|
@@ -6570,13 +6419,15 @@ var PI_RUNTIME_SESSION_DESCRIPTOR = {
|
|
|
6570
6419
|
busyDelivery: "direct",
|
|
6571
6420
|
postTurn: "keep_alive"
|
|
6572
6421
|
};
|
|
6422
|
+
var PI_IDLE_PROMPT_RETRY_MS = 25;
|
|
6423
|
+
var PI_IDLE_PROMPT_MAX_WAIT_MS = 1e3;
|
|
6573
6424
|
async function createPiAgentSessionForContext(ctx, sessionId) {
|
|
6574
6425
|
const sessionDir = buildPiSessionDir(ctx.workingDirectory);
|
|
6575
|
-
|
|
6426
|
+
mkdirSync2(sessionDir, { recursive: true });
|
|
6576
6427
|
const spawnEnv = await buildPiSpawnEnv(ctx);
|
|
6577
6428
|
const agentDir = spawnEnv.PI_CODING_AGENT_DIR || getAgentDir();
|
|
6578
|
-
const authStorage = AuthStorage.create(
|
|
6579
|
-
const modelRegistry = ModelRegistry.create(authStorage,
|
|
6429
|
+
const authStorage = AuthStorage.create(path9.join(agentDir, "auth.json"));
|
|
6430
|
+
const modelRegistry = ModelRegistry.create(authStorage, path9.join(agentDir, "models.json"));
|
|
6580
6431
|
const launchRuntimeFields = runtimeConfigToLaunchFields(ctx.config);
|
|
6581
6432
|
const model = resolvePiModelFromRegistry(launchRuntimeFields.model, modelRegistry);
|
|
6582
6433
|
if (launchRuntimeFields.model && launchRuntimeFields.model !== "default" && !model) {
|
|
@@ -6687,7 +6538,8 @@ var PiSdkRuntimeSession = class {
|
|
|
6687
6538
|
return { ok: true, acceptedAs: "steer" };
|
|
6688
6539
|
}
|
|
6689
6540
|
if (session.isStreaming) {
|
|
6690
|
-
|
|
6541
|
+
this.launchPromptAfterStreaming(input.text);
|
|
6542
|
+
return { ok: true, acceptedAs: "prompt" };
|
|
6691
6543
|
}
|
|
6692
6544
|
this.launchPrompt(input.text);
|
|
6693
6545
|
return { ok: true, acceptedAs: "prompt" };
|
|
@@ -6729,6 +6581,27 @@ var PiSdkRuntimeSession = class {
|
|
|
6729
6581
|
}
|
|
6730
6582
|
this.deferSdkCall(() => session.prompt(text));
|
|
6731
6583
|
}
|
|
6584
|
+
launchPromptAfterStreaming(text) {
|
|
6585
|
+
this.deferSdkCall(async () => {
|
|
6586
|
+
const session = this.session;
|
|
6587
|
+
if (!session) return;
|
|
6588
|
+
const ready = await this.waitForStreamingToClear(session);
|
|
6589
|
+
if (this.didClose || this.session !== session) {
|
|
6590
|
+
return;
|
|
6591
|
+
}
|
|
6592
|
+
await (ready ? session.prompt(text) : session.steer(text));
|
|
6593
|
+
});
|
|
6594
|
+
}
|
|
6595
|
+
async waitForStreamingToClear(session) {
|
|
6596
|
+
const deadline = Date.now() + PI_IDLE_PROMPT_MAX_WAIT_MS;
|
|
6597
|
+
while (!this.didClose && this.session === session && session.isStreaming) {
|
|
6598
|
+
if (Date.now() >= deadline) {
|
|
6599
|
+
return false;
|
|
6600
|
+
}
|
|
6601
|
+
await delay(PI_IDLE_PROMPT_RETRY_MS);
|
|
6602
|
+
}
|
|
6603
|
+
return !this.didClose && this.session === session && !session.isStreaming;
|
|
6604
|
+
}
|
|
6732
6605
|
deferSdkCall(invoke) {
|
|
6733
6606
|
setImmediate(() => {
|
|
6734
6607
|
if (this.didClose) return;
|
|
@@ -6840,6 +6713,12 @@ var PiDriver = class {
|
|
|
6840
6713
|
});
|
|
6841
6714
|
}
|
|
6842
6715
|
};
|
|
6716
|
+
function delay(ms) {
|
|
6717
|
+
return new Promise((resolve) => {
|
|
6718
|
+
const timer = setTimeout(resolve, ms);
|
|
6719
|
+
timer.unref?.();
|
|
6720
|
+
});
|
|
6721
|
+
}
|
|
6843
6722
|
|
|
6844
6723
|
// src/drivers/runtimeSession.ts
|
|
6845
6724
|
import { EventEmitter as EventEmitter2 } from "events";
|
|
@@ -6998,7 +6877,7 @@ function getDriver(runtimeId) {
|
|
|
6998
6877
|
|
|
6999
6878
|
// src/workspaces.ts
|
|
7000
6879
|
import { readdir, rm, stat } from "fs/promises";
|
|
7001
|
-
import
|
|
6880
|
+
import path10 from "path";
|
|
7002
6881
|
function isValidWorkspaceDirectoryName(directoryName) {
|
|
7003
6882
|
return !directoryName.includes("/") && !directoryName.includes("\\") && !directoryName.includes("..");
|
|
7004
6883
|
}
|
|
@@ -7006,7 +6885,7 @@ function resolveWorkspaceDirectoryPath(dataDir, directoryName) {
|
|
|
7006
6885
|
if (!isValidWorkspaceDirectoryName(directoryName)) {
|
|
7007
6886
|
return null;
|
|
7008
6887
|
}
|
|
7009
|
-
return
|
|
6888
|
+
return path10.join(dataDir, directoryName);
|
|
7010
6889
|
}
|
|
7011
6890
|
function emptyWorkspaceDirectorySummary(latestMtime = /* @__PURE__ */ new Date(0)) {
|
|
7012
6891
|
return {
|
|
@@ -7055,7 +6934,7 @@ async function summarizeWorkspaceDirectory(dirPath) {
|
|
|
7055
6934
|
return summary;
|
|
7056
6935
|
}
|
|
7057
6936
|
const childSummaries = await Promise.all(
|
|
7058
|
-
entries.map((entry) => summarizeWorkspaceEntry(
|
|
6937
|
+
entries.map((entry) => summarizeWorkspaceEntry(path10.join(dirPath, entry.name), entry))
|
|
7059
6938
|
);
|
|
7060
6939
|
for (const childSummary of childSummaries) {
|
|
7061
6940
|
summary = mergeWorkspaceDirectorySummaries(summary, childSummary);
|
|
@@ -7074,7 +6953,7 @@ async function scanWorkspaceDirectories(dataDir) {
|
|
|
7074
6953
|
if (!entry.isDirectory()) {
|
|
7075
6954
|
return null;
|
|
7076
6955
|
}
|
|
7077
|
-
const dirPath =
|
|
6956
|
+
const dirPath = path10.join(dataDir, entry.name);
|
|
7078
6957
|
try {
|
|
7079
6958
|
const summary = await summarizeWorkspaceDirectory(dirPath);
|
|
7080
6959
|
return {
|
|
@@ -7537,12 +7416,12 @@ function findSessionJsonl(root, predicate) {
|
|
|
7537
7416
|
for (const entry of entries) {
|
|
7538
7417
|
if (++visited > maxEntries) return null;
|
|
7539
7418
|
if (!entry.isFile() || !predicate(entry.name)) continue;
|
|
7540
|
-
return
|
|
7419
|
+
return path11.join(dir, entry.name);
|
|
7541
7420
|
}
|
|
7542
7421
|
for (const entry of entries) {
|
|
7543
7422
|
if (++visited > maxEntries) return null;
|
|
7544
7423
|
if (!entry.isDirectory()) continue;
|
|
7545
|
-
const found = visit(
|
|
7424
|
+
const found = visit(path11.join(dir, entry.name), depth - 1);
|
|
7546
7425
|
if (found) return found;
|
|
7547
7426
|
}
|
|
7548
7427
|
return null;
|
|
@@ -7555,10 +7434,10 @@ function safeSessionFilename(value) {
|
|
|
7555
7434
|
}
|
|
7556
7435
|
function writeRuntimeSessionHandoff(runtime, sessionId, fallbackDir) {
|
|
7557
7436
|
try {
|
|
7558
|
-
const dir =
|
|
7559
|
-
|
|
7560
|
-
const filePath =
|
|
7561
|
-
|
|
7437
|
+
const dir = path11.join(fallbackDir, ".slock", "runtime-sessions");
|
|
7438
|
+
mkdirSync3(dir, { recursive: true });
|
|
7439
|
+
const filePath = path11.join(dir, `${runtime}-${safeSessionFilename(sessionId)}.jsonl`);
|
|
7440
|
+
writeFileSync4(filePath, JSON.stringify({
|
|
7562
7441
|
type: "runtime_session_handoff",
|
|
7563
7442
|
runtime,
|
|
7564
7443
|
sessionId,
|
|
@@ -7577,7 +7456,7 @@ function writeRuntimeSessionHandoff(runtime, sessionId, fallbackDir) {
|
|
|
7577
7456
|
}
|
|
7578
7457
|
}
|
|
7579
7458
|
function resolveRuntimeSessionRef(runtime, sessionId, homeDir = os5.homedir(), fallbackDir) {
|
|
7580
|
-
const directPath =
|
|
7459
|
+
const directPath = path11.isAbsolute(sessionId) ? sessionId : null;
|
|
7581
7460
|
if (directPath) {
|
|
7582
7461
|
try {
|
|
7583
7462
|
if (statSync(directPath).isFile()) {
|
|
@@ -7586,7 +7465,7 @@ function resolveRuntimeSessionRef(runtime, sessionId, homeDir = os5.homedir(), f
|
|
|
7586
7465
|
} catch {
|
|
7587
7466
|
}
|
|
7588
7467
|
}
|
|
7589
|
-
const resolvedPath = runtime === "claude" ? findSessionJsonl(
|
|
7468
|
+
const resolvedPath = runtime === "claude" ? findSessionJsonl(path11.join(homeDir, ".claude", "projects"), (filename) => filename === `${sessionId}.jsonl`) : runtime === "codex" ? findSessionJsonl(path11.join(homeDir, ".codex", "sessions"), (filename) => filename.endsWith(".jsonl") && filename.includes(sessionId)) : null;
|
|
7590
7469
|
if (!resolvedPath && fallbackDir) {
|
|
7591
7470
|
const fallback = writeRuntimeSessionHandoff(runtime, sessionId, fallbackDir);
|
|
7592
7471
|
if (fallback) return fallback;
|
|
@@ -8189,8 +8068,7 @@ function runtimeProfileTurnControl(kind, key, source) {
|
|
|
8189
8068
|
source,
|
|
8190
8069
|
keyHash: hashRuntimeProfileKey(key) ?? null,
|
|
8191
8070
|
keyPresent: Boolean(key),
|
|
8192
|
-
injectedAtMs: Date.now()
|
|
8193
|
-
migrationDoneToolObserved: false
|
|
8071
|
+
injectedAtMs: Date.now()
|
|
8194
8072
|
};
|
|
8195
8073
|
}
|
|
8196
8074
|
function pushRecentLines(lines, chunk, maxLines, maxLineLength) {
|
|
@@ -8266,6 +8144,9 @@ function classifyStickyTerminalFailure(ap) {
|
|
|
8266
8144
|
if (isRuntimeStartTimeoutText(terminalFailure.detail)) return null;
|
|
8267
8145
|
return null;
|
|
8268
8146
|
}
|
|
8147
|
+
function isAuthClassTerminalLine(text) {
|
|
8148
|
+
return buildRuntimeErrorDiagnosticEnvelope(text).spanAttrs.runtime_error_action_required === true;
|
|
8149
|
+
}
|
|
8269
8150
|
function isProviderStreamFailureText(text) {
|
|
8270
8151
|
return /stream closed before response\.completed|error decoding response body/i.test(text);
|
|
8271
8152
|
}
|
|
@@ -8583,7 +8464,6 @@ var AgentProcessManager = class _AgentProcessManager {
|
|
|
8583
8464
|
startingInboxes = /* @__PURE__ */ new Map();
|
|
8584
8465
|
/** Cached configs for agents whose process exited normally — enables auto-restart on next message */
|
|
8585
8466
|
idleAgentConfigs = /* @__PURE__ */ new Map();
|
|
8586
|
-
chatBridgePath;
|
|
8587
8467
|
slockCliPath;
|
|
8588
8468
|
sendToServer;
|
|
8589
8469
|
daemonApiKey;
|
|
@@ -8601,8 +8481,7 @@ var AgentProcessManager = class _AgentProcessManager {
|
|
|
8601
8481
|
agentVisibleMessageIds = /* @__PURE__ */ new Map();
|
|
8602
8482
|
daemonVersion;
|
|
8603
8483
|
computerVersion;
|
|
8604
|
-
constructor(
|
|
8605
|
-
this.chatBridgePath = chatBridgePath;
|
|
8484
|
+
constructor(sendToServer, daemonApiKey, opts) {
|
|
8606
8485
|
this.slockCliPath = opts.slockCliPath ?? "";
|
|
8607
8486
|
this.sendToServer = sendToServer;
|
|
8608
8487
|
this.daemonApiKey = daemonApiKey;
|
|
@@ -9129,7 +9008,7 @@ var AgentProcessManager = class _AgentProcessManager {
|
|
|
9129
9008
|
);
|
|
9130
9009
|
wakeMessage = void 0;
|
|
9131
9010
|
}
|
|
9132
|
-
const agentDataDir =
|
|
9011
|
+
const agentDataDir = path11.join(this.dataDir, agentId);
|
|
9133
9012
|
await mkdir(agentDataDir, { recursive: true });
|
|
9134
9013
|
let runtimeConfig = withLocalRuntimeContext(config, agentId, agentDataDir);
|
|
9135
9014
|
const legacyRuntimeProfileControl = runtimeConfig.runtimeProfileControl?.kind === "migration" ? runtimeConfig.runtimeProfileControl : null;
|
|
@@ -9143,23 +9022,23 @@ var AgentProcessManager = class _AgentProcessManager {
|
|
|
9143
9022
|
);
|
|
9144
9023
|
runtimeConfig = { ...runtimeConfig, runtimeProfileControl: null };
|
|
9145
9024
|
}
|
|
9146
|
-
const memoryMdPath =
|
|
9025
|
+
const memoryMdPath = path11.join(agentDataDir, "MEMORY.md");
|
|
9147
9026
|
try {
|
|
9148
9027
|
await access(memoryMdPath);
|
|
9149
9028
|
} catch {
|
|
9150
9029
|
const initialMemoryMd = buildInitialMemoryMd(runtimeConfig);
|
|
9151
9030
|
await writeFile(memoryMdPath, initialMemoryMd);
|
|
9152
9031
|
}
|
|
9153
|
-
const notesDir =
|
|
9032
|
+
const notesDir = path11.join(agentDataDir, "notes");
|
|
9154
9033
|
await mkdir(notesDir, { recursive: true });
|
|
9155
9034
|
if (getOnboardingSeedMode(config) === FIRST_CINDY_SEED_MODE) {
|
|
9156
9035
|
const seedFiles = buildOnboardingSeedFiles();
|
|
9157
9036
|
for (const { relativePath, content } of seedFiles) {
|
|
9158
|
-
const fullPath =
|
|
9037
|
+
const fullPath = path11.join(agentDataDir, relativePath);
|
|
9159
9038
|
try {
|
|
9160
9039
|
await access(fullPath);
|
|
9161
9040
|
} catch {
|
|
9162
|
-
await mkdir(
|
|
9041
|
+
await mkdir(path11.dirname(fullPath), { recursive: true });
|
|
9163
9042
|
await writeFile(fullPath, content);
|
|
9164
9043
|
}
|
|
9165
9044
|
}
|
|
@@ -9267,7 +9146,6 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
9267
9146
|
standingPrompt,
|
|
9268
9147
|
prompt,
|
|
9269
9148
|
workingDirectory: agentDataDir,
|
|
9270
|
-
chatBridgePath: this.chatBridgePath,
|
|
9271
9149
|
slockCliPath: this.slockCliPath,
|
|
9272
9150
|
daemonApiKey: this.daemonApiKey,
|
|
9273
9151
|
launchId: launchId || null,
|
|
@@ -9414,7 +9292,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
9414
9292
|
const startupTimeoutTermination = ap.expectedTerminationReason === "startup_timeout";
|
|
9415
9293
|
const expectedTermination = Boolean(ap.expectedTerminationReason);
|
|
9416
9294
|
const stickyTerminalFailureDetail = classifyStickyTerminalFailure(ap);
|
|
9417
|
-
const processEndedCleanly = !stickyTerminalFailureDetail && (finalCode === 0 || expectedTermination && !ap.lastRuntimeError);
|
|
9295
|
+
const processEndedCleanly = !stickyTerminalFailureDetail && !startupTimeoutTermination && (finalCode === 0 || expectedTermination && !ap.lastRuntimeError);
|
|
9418
9296
|
const terminalFailureDetail = processEndedCleanly ? null : stickyTerminalFailureDetail ?? classifyTerminalFailure(ap);
|
|
9419
9297
|
const resumeRecoveryReason = resumeSessionRecoveryReason(ap);
|
|
9420
9298
|
const shouldColdStartResumeSession = resumeRecoveryReason !== null;
|
|
@@ -9980,20 +9858,37 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
9980
9858
|
}));
|
|
9981
9859
|
return true;
|
|
9982
9860
|
}
|
|
9983
|
-
|
|
9984
|
-
|
|
9985
|
-
|
|
9986
|
-
|
|
9987
|
-
|
|
9988
|
-
|
|
9989
|
-
|
|
9990
|
-
|
|
9991
|
-
|
|
9992
|
-
|
|
9993
|
-
|
|
9994
|
-
|
|
9995
|
-
|
|
9996
|
-
|
|
9861
|
+
if (stickyTerminalFailure.actionRequired) {
|
|
9862
|
+
if (ap.lastRuntimeError && isAuthClassTerminalLine(ap.lastRuntimeError)) {
|
|
9863
|
+
ap.lastRuntimeError = null;
|
|
9864
|
+
}
|
|
9865
|
+
ap.recentStderr = ap.recentStderr.filter((line) => !isAuthClassTerminalLine(line));
|
|
9866
|
+
this.recordDaemonTrace("daemon.agent.delivery.routed", this.deliveryTraceAttrs(agentId, message, {
|
|
9867
|
+
outcome: "user_turn_recover_from_sticky_terminal_error",
|
|
9868
|
+
accepted: true,
|
|
9869
|
+
process_present: true,
|
|
9870
|
+
runtime: ap.config.runtime,
|
|
9871
|
+
session_id_present: Boolean(ap.sessionId),
|
|
9872
|
+
launchId: ap.launchId || void 0,
|
|
9873
|
+
is_idle: ap.isIdle,
|
|
9874
|
+
inbox_count: ap.inbox.length
|
|
9875
|
+
}));
|
|
9876
|
+
} else {
|
|
9877
|
+
ap.inbox.push(message);
|
|
9878
|
+
this.recordDaemonTrace("daemon.agent.delivery.routed", this.deliveryTraceAttrs(agentId, message, {
|
|
9879
|
+
outcome: "queued_terminal_runtime_error",
|
|
9880
|
+
accepted: true,
|
|
9881
|
+
process_present: true,
|
|
9882
|
+
runtime: ap.config.runtime,
|
|
9883
|
+
session_id_present: Boolean(ap.sessionId),
|
|
9884
|
+
launchId: ap.launchId || void 0,
|
|
9885
|
+
is_idle: ap.isIdle,
|
|
9886
|
+
inbox_count: ap.inbox.length
|
|
9887
|
+
}));
|
|
9888
|
+
this.sendAgentStatus(agentId, "inactive", ap.launchId);
|
|
9889
|
+
this.broadcastActivity(agentId, "error", stickyTerminalFailure.detail);
|
|
9890
|
+
return true;
|
|
9891
|
+
}
|
|
9997
9892
|
}
|
|
9998
9893
|
if (ap.isIdle && ap.driver.supportsStdinNotification && ap.sessionId) {
|
|
9999
9894
|
if (transientDelivery) {
|
|
@@ -10161,7 +10056,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
10161
10056
|
return true;
|
|
10162
10057
|
}
|
|
10163
10058
|
async resetWorkspace(agentId) {
|
|
10164
|
-
const agentDataDir =
|
|
10059
|
+
const agentDataDir = path11.join(this.dataDir, agentId);
|
|
10165
10060
|
try {
|
|
10166
10061
|
await rm2(agentDataDir, { recursive: true, force: true });
|
|
10167
10062
|
logger.info(`[Agent ${agentId}] Workspace reset complete (${agentDataDir})`);
|
|
@@ -10222,7 +10117,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
10222
10117
|
return result;
|
|
10223
10118
|
}
|
|
10224
10119
|
buildRuntimeProfileReport(agentId, config, sessionId, launchId) {
|
|
10225
|
-
const workspacePath =
|
|
10120
|
+
const workspacePath = path11.join(this.dataDir, agentId);
|
|
10226
10121
|
return {
|
|
10227
10122
|
agentId,
|
|
10228
10123
|
launchId,
|
|
@@ -10481,7 +10376,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
10481
10376
|
}
|
|
10482
10377
|
// Workspace file browsing
|
|
10483
10378
|
async getFileTree(agentId, dirPath) {
|
|
10484
|
-
const agentDir =
|
|
10379
|
+
const agentDir = path11.join(this.dataDir, agentId);
|
|
10485
10380
|
try {
|
|
10486
10381
|
await stat2(agentDir);
|
|
10487
10382
|
} catch {
|
|
@@ -10489,8 +10384,8 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
10489
10384
|
}
|
|
10490
10385
|
let targetDir = agentDir;
|
|
10491
10386
|
if (dirPath) {
|
|
10492
|
-
const resolved =
|
|
10493
|
-
if (!resolved.startsWith(agentDir +
|
|
10387
|
+
const resolved = path11.resolve(agentDir, dirPath);
|
|
10388
|
+
if (!resolved.startsWith(agentDir + path11.sep) && resolved !== agentDir) {
|
|
10494
10389
|
return [];
|
|
10495
10390
|
}
|
|
10496
10391
|
targetDir = resolved;
|
|
@@ -10498,14 +10393,14 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
10498
10393
|
return this.listDirectoryChildren(targetDir, agentDir);
|
|
10499
10394
|
}
|
|
10500
10395
|
async readFile(agentId, filePath) {
|
|
10501
|
-
const agentDir =
|
|
10502
|
-
const resolved =
|
|
10503
|
-
if (!resolved.startsWith(agentDir +
|
|
10396
|
+
const agentDir = path11.join(this.dataDir, agentId);
|
|
10397
|
+
const resolved = path11.resolve(agentDir, filePath);
|
|
10398
|
+
if (!resolved.startsWith(agentDir + path11.sep) && resolved !== agentDir) {
|
|
10504
10399
|
throw new Error("Access denied");
|
|
10505
10400
|
}
|
|
10506
10401
|
const info = await stat2(resolved);
|
|
10507
10402
|
if (info.isDirectory()) throw new Error("Cannot read a directory");
|
|
10508
|
-
const ext =
|
|
10403
|
+
const ext = path11.extname(resolved).toLowerCase();
|
|
10509
10404
|
if (WORKSPACE_TEXT_EXTENSIONS.has(ext) || ext === "") {
|
|
10510
10405
|
if (info.size > WORKSPACE_TEXT_FILE_MAX_BYTES) throw new Error("File too large");
|
|
10511
10406
|
const content = await readFile(resolved, "utf-8");
|
|
@@ -10540,13 +10435,13 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
10540
10435
|
const agent = this.agents.get(agentId);
|
|
10541
10436
|
const runtime = runtimeHint || agent?.config.runtime || "claude";
|
|
10542
10437
|
const home = os5.homedir();
|
|
10543
|
-
const workspaceDir =
|
|
10438
|
+
const workspaceDir = path11.join(this.dataDir, agentId);
|
|
10544
10439
|
const paths = _AgentProcessManager.SKILL_PATHS[runtime] || _AgentProcessManager.SKILL_PATHS.claude;
|
|
10545
10440
|
const globalResults = await Promise.all(
|
|
10546
|
-
paths.global.map((p) => this.scanSkillsDir(
|
|
10441
|
+
paths.global.map((p) => this.scanSkillsDir(path11.join(home, p)))
|
|
10547
10442
|
);
|
|
10548
10443
|
const workspaceResults = await Promise.all(
|
|
10549
|
-
paths.workspace.map((p) => this.scanSkillsDir(
|
|
10444
|
+
paths.workspace.map((p) => this.scanSkillsDir(path11.join(workspaceDir, p)))
|
|
10550
10445
|
);
|
|
10551
10446
|
const dedup = (skills) => {
|
|
10552
10447
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -10575,7 +10470,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
10575
10470
|
const skills = [];
|
|
10576
10471
|
for (const entry of entries) {
|
|
10577
10472
|
if (entry.isDirectory() || entry.isSymbolicLink()) {
|
|
10578
|
-
const skillMd =
|
|
10473
|
+
const skillMd = path11.join(dir, entry.name, "SKILL.md");
|
|
10579
10474
|
try {
|
|
10580
10475
|
const content = await readFile(skillMd, "utf-8");
|
|
10581
10476
|
const skill = this.parseSkillMd(entry.name, content);
|
|
@@ -10586,7 +10481,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
10586
10481
|
} else if (entry.name.endsWith(".md")) {
|
|
10587
10482
|
const cmdName = entry.name.replace(/\.md$/, "");
|
|
10588
10483
|
try {
|
|
10589
|
-
const content = await readFile(
|
|
10484
|
+
const content = await readFile(path11.join(dir, entry.name), "utf-8");
|
|
10590
10485
|
const skill = this.parseSkillMd(cmdName, content);
|
|
10591
10486
|
skill.sourcePath = dir;
|
|
10592
10487
|
skills.push(skill);
|
|
@@ -10906,8 +10801,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
10906
10801
|
runtime_profile_key_hash: control.keyHash || void 0,
|
|
10907
10802
|
runtime_profile_key_present: control.keyPresent,
|
|
10908
10803
|
runtime_profile_pending_age_ms: pendingAgeMs,
|
|
10909
|
-
runtime_profile_requires_ack: false
|
|
10910
|
-
runtime_profile_migration_done_observed: control.kind === "migration" ? control.migrationDoneToolObserved : void 0
|
|
10804
|
+
runtime_profile_requires_ack: false
|
|
10911
10805
|
};
|
|
10912
10806
|
}
|
|
10913
10807
|
activateRuntimeProfileTurnControl(ap, control) {
|
|
@@ -10919,16 +10813,6 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
10919
10813
|
if (!notification) return null;
|
|
10920
10814
|
return runtimeProfileTurnControl(notification.kind, notification.key, source);
|
|
10921
10815
|
}
|
|
10922
|
-
noteRuntimeProfileToolCall(agentId, ap, toolName) {
|
|
10923
|
-
const control = ap.runtimeProfileTurnControl;
|
|
10924
|
-
if (!control || control.kind !== "migration") return;
|
|
10925
|
-
if (!toolName.includes("runtime_profile_migration_done")) return;
|
|
10926
|
-
control.migrationDoneToolObserved = true;
|
|
10927
|
-
this.recordRuntimeTraceEvent(agentId, ap, "runtime_profile.migration_done_tool.observed", {
|
|
10928
|
-
...this.runtimeProfileTurnControlTraceAttrs(control),
|
|
10929
|
-
tool: toolName
|
|
10930
|
-
});
|
|
10931
|
-
}
|
|
10932
10816
|
finalizeRuntimeProfileTurnControl(agentId, ap, terminal) {
|
|
10933
10817
|
const control = ap.runtimeProfileTurnControl;
|
|
10934
10818
|
if (!control) return {};
|
|
@@ -10937,7 +10821,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
10937
10821
|
return {
|
|
10938
10822
|
...attrs,
|
|
10939
10823
|
runtime_profile_turn_terminal: terminal,
|
|
10940
|
-
runtime_profile_turn_outcome: control.kind === "migration" ?
|
|
10824
|
+
runtime_profile_turn_outcome: control.kind === "migration" ? "reset_session_notice" : "notice_only"
|
|
10941
10825
|
};
|
|
10942
10826
|
}
|
|
10943
10827
|
startRuntimeTrace(agentId, ap, reason, messages, inputTraceAttrs = {}) {
|
|
@@ -11342,7 +11226,6 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
11342
11226
|
const invocation = normalizeToolDisplayInvocation(event.name, event.input);
|
|
11343
11227
|
if (ap) {
|
|
11344
11228
|
const reduction = reduceApmGatedToolUse(ap.gatedSteering, { kind: "tool_call" });
|
|
11345
|
-
this.noteRuntimeProfileToolCall(agentId, ap, invocation.toolName);
|
|
11346
11229
|
this.recordRuntimeTraceEvent(agentId, ap, "tool.call.started", { tool: invocation.toolName });
|
|
11347
11230
|
this.commitGatedSteeringDecisionState(agentId, ap, reduction.nextState, {
|
|
11348
11231
|
event: "tool_call",
|
|
@@ -11923,8 +11806,8 @@ ${RESPONSE_TARGET_HINT}`);
|
|
|
11923
11806
|
const nodes = [];
|
|
11924
11807
|
for (const entry of entries) {
|
|
11925
11808
|
if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
|
|
11926
|
-
const fullPath =
|
|
11927
|
-
const relativePath =
|
|
11809
|
+
const fullPath = path11.join(dir, entry.name);
|
|
11810
|
+
const relativePath = path11.relative(rootDir, fullPath);
|
|
11928
11811
|
let info;
|
|
11929
11812
|
try {
|
|
11930
11813
|
info = await stat2(fullPath);
|
|
@@ -12215,7 +12098,7 @@ var ReminderCache = class {
|
|
|
12215
12098
|
logger.warn(`[ReminderCache] Invalid fireAt for ${job.reminderId}: ${job.fireAt}`);
|
|
12216
12099
|
return null;
|
|
12217
12100
|
}
|
|
12218
|
-
const
|
|
12101
|
+
const delay2 = Math.max(0, Math.min(this.maxDelayMs, fireAt - this.clock.now()));
|
|
12219
12102
|
return this.clock.setTimeout(() => {
|
|
12220
12103
|
this.entries.delete(job.reminderId);
|
|
12221
12104
|
try {
|
|
@@ -12223,15 +12106,15 @@ var ReminderCache = class {
|
|
|
12223
12106
|
} catch (err) {
|
|
12224
12107
|
logger.error(`[ReminderCache] onFire threw for ${job.reminderId}`, err);
|
|
12225
12108
|
}
|
|
12226
|
-
},
|
|
12109
|
+
}, delay2);
|
|
12227
12110
|
}
|
|
12228
12111
|
};
|
|
12229
12112
|
|
|
12230
12113
|
// src/machineLock.ts
|
|
12231
12114
|
import { createHash as createHash4, randomUUID as randomUUID4 } from "crypto";
|
|
12232
|
-
import { mkdirSync as
|
|
12115
|
+
import { mkdirSync as mkdirSync4, readFileSync as readFileSync5, rmSync as rmSync3, statSync as statSync2, writeFileSync as writeFileSync5 } from "fs";
|
|
12233
12116
|
import os6 from "os";
|
|
12234
|
-
import
|
|
12117
|
+
import path12 from "path";
|
|
12235
12118
|
var INCOMPLETE_LOCK_STALE_MS = 3e4;
|
|
12236
12119
|
var DaemonMachineLockConflictError = class extends Error {
|
|
12237
12120
|
code = "DAEMON_MACHINE_LOCK_HELD";
|
|
@@ -12253,7 +12136,7 @@ function resolveDefaultMachineStateRoot() {
|
|
|
12253
12136
|
return resolveSlockHomePath("machines");
|
|
12254
12137
|
}
|
|
12255
12138
|
function ownerPath(lockDir) {
|
|
12256
|
-
return
|
|
12139
|
+
return path12.join(lockDir, "owner.json");
|
|
12257
12140
|
}
|
|
12258
12141
|
function readOwner(lockDir) {
|
|
12259
12142
|
try {
|
|
@@ -12283,13 +12166,13 @@ function acquireDaemonMachineLock(options) {
|
|
|
12283
12166
|
const rootDir = options.rootDir ?? resolveDefaultMachineStateRoot();
|
|
12284
12167
|
const fingerprint = apiKeyFingerprint(options.apiKey);
|
|
12285
12168
|
const lockId = getDaemonMachineLockId(options.apiKey);
|
|
12286
|
-
const machineDir =
|
|
12287
|
-
const lockDir =
|
|
12169
|
+
const machineDir = path12.join(rootDir, lockId);
|
|
12170
|
+
const lockDir = path12.join(machineDir, "daemon.lock");
|
|
12288
12171
|
const token = randomUUID4();
|
|
12289
|
-
|
|
12172
|
+
mkdirSync4(machineDir, { recursive: true });
|
|
12290
12173
|
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
12291
12174
|
try {
|
|
12292
|
-
|
|
12175
|
+
mkdirSync4(lockDir);
|
|
12293
12176
|
const owner = {
|
|
12294
12177
|
pid: process.pid,
|
|
12295
12178
|
token,
|
|
@@ -12299,7 +12182,7 @@ function acquireDaemonMachineLock(options) {
|
|
|
12299
12182
|
apiKeyFingerprint: fingerprint.slice(0, 16)
|
|
12300
12183
|
};
|
|
12301
12184
|
try {
|
|
12302
|
-
|
|
12185
|
+
writeFileSync5(ownerPath(lockDir), `${JSON.stringify(owner, null, 2)}
|
|
12303
12186
|
`, { mode: 384 });
|
|
12304
12187
|
} catch (err) {
|
|
12305
12188
|
rmSync3(lockDir, { recursive: true, force: true });
|
|
@@ -12314,7 +12197,7 @@ function acquireDaemonMachineLock(options) {
|
|
|
12314
12197
|
if (currentOwner?.pid === process.pid && currentOwner.token === token) {
|
|
12315
12198
|
const released = { ...currentOwner, pid: 0 };
|
|
12316
12199
|
try {
|
|
12317
|
-
|
|
12200
|
+
writeFileSync5(ownerPath(lockDir), `${JSON.stringify(released, null, 2)}
|
|
12318
12201
|
`, {
|
|
12319
12202
|
mode: 384
|
|
12320
12203
|
});
|
|
@@ -12344,8 +12227,8 @@ function acquireDaemonMachineLock(options) {
|
|
|
12344
12227
|
}
|
|
12345
12228
|
|
|
12346
12229
|
// src/localTraceSink.ts
|
|
12347
|
-
import { appendFileSync, mkdirSync as
|
|
12348
|
-
import
|
|
12230
|
+
import { appendFileSync, mkdirSync as mkdirSync5, readdirSync as readdirSync3, rmSync as rmSync4, statSync as statSync3, writeFileSync as writeFileSync6 } from "fs";
|
|
12231
|
+
import path13 from "path";
|
|
12349
12232
|
var DEFAULT_MAX_FILE_BYTES = 5 * 1024 * 1024;
|
|
12350
12233
|
var DEFAULT_MAX_FILE_AGE_MS = 5 * 60 * 1e3;
|
|
12351
12234
|
var DEFAULT_MAX_FILES = 8;
|
|
@@ -12382,7 +12265,7 @@ var LocalRotatingTraceSink = class {
|
|
|
12382
12265
|
currentSize = 0;
|
|
12383
12266
|
sequence = 0;
|
|
12384
12267
|
constructor(options) {
|
|
12385
|
-
this.traceDir =
|
|
12268
|
+
this.traceDir = path13.join(options.machineDir, "traces");
|
|
12386
12269
|
this.maxFileBytes = Math.max(1024, Math.floor(options.maxFileBytes ?? DEFAULT_MAX_FILE_BYTES));
|
|
12387
12270
|
const baseAgeMs = Math.max(1e3, Math.floor(options.maxFileAgeMs ?? DEFAULT_MAX_FILE_AGE_MS));
|
|
12388
12271
|
const ageJitterMs = Math.max(0, Math.floor(options.maxFileAgeJitterMs ?? 0));
|
|
@@ -12408,15 +12291,15 @@ var LocalRotatingTraceSink = class {
|
|
|
12408
12291
|
return this.currentFile;
|
|
12409
12292
|
}
|
|
12410
12293
|
ensureFile(nextBytes) {
|
|
12411
|
-
|
|
12294
|
+
mkdirSync5(this.traceDir, { recursive: true, mode: 448 });
|
|
12412
12295
|
const nowMs = this.nowMsProvider();
|
|
12413
12296
|
const shouldRotateForAge = this.currentFileOpenedAtMs !== null && nowMs - this.currentFileOpenedAtMs >= this.maxFileAgeMs;
|
|
12414
12297
|
if (!this.currentFile || this.currentSize + nextBytes > this.maxFileBytes || shouldRotateForAge) {
|
|
12415
|
-
this.currentFile =
|
|
12298
|
+
this.currentFile = path13.join(
|
|
12416
12299
|
this.traceDir,
|
|
12417
12300
|
`daemon-trace-${safeTimestamp(nowMs)}-${process.pid}-${String(this.sequence++).padStart(4, "0")}.jsonl`
|
|
12418
12301
|
);
|
|
12419
|
-
|
|
12302
|
+
writeFileSync6(this.currentFile, "", { flag: "a", mode: 384 });
|
|
12420
12303
|
this.currentSize = statSync3(this.currentFile).size;
|
|
12421
12304
|
this.currentFileOpenedAtMs = nowMs;
|
|
12422
12305
|
this.pruneOldFiles();
|
|
@@ -12427,7 +12310,7 @@ var LocalRotatingTraceSink = class {
|
|
|
12427
12310
|
const excess = files.length - this.maxFiles;
|
|
12428
12311
|
if (excess <= 0) return;
|
|
12429
12312
|
for (const file of files.slice(0, excess)) {
|
|
12430
|
-
rmSync4(
|
|
12313
|
+
rmSync4(path13.join(this.traceDir, file), { force: true });
|
|
12431
12314
|
}
|
|
12432
12315
|
}
|
|
12433
12316
|
};
|
|
@@ -12518,11 +12401,108 @@ function isDiagnosticErrorAttr(key) {
|
|
|
12518
12401
|
import { createHash as createHash6, randomUUID as randomUUID5 } from "crypto";
|
|
12519
12402
|
import { gzipSync } from "zlib";
|
|
12520
12403
|
import { mkdir as mkdir2, readFile as readFile2, readdir as readdir3, stat as stat3, writeFile as writeFile2 } from "fs/promises";
|
|
12521
|
-
import
|
|
12404
|
+
import path14 from "path";
|
|
12405
|
+
|
|
12406
|
+
// src/chatBridgeRequest.ts
|
|
12407
|
+
var DEFAULT_CHAT_BRIDGE_TOOL_TIMEOUT_MS = Number.parseInt(
|
|
12408
|
+
process.env.SLOCK_CHAT_BRIDGE_TOOL_TIMEOUT_MS || "",
|
|
12409
|
+
10
|
|
12410
|
+
) || 6e4;
|
|
12411
|
+
var ChatBridgeToolTimeoutError = class extends Error {
|
|
12412
|
+
toolName;
|
|
12413
|
+
target;
|
|
12414
|
+
timeoutMs;
|
|
12415
|
+
durationMs;
|
|
12416
|
+
constructor(toolName, target, timeoutMs, durationMs) {
|
|
12417
|
+
super(`${toolName} timed out after ${timeoutMs}ms${target ? ` (target: ${target})` : ""}`);
|
|
12418
|
+
this.name = "ChatBridgeToolTimeoutError";
|
|
12419
|
+
this.toolName = toolName;
|
|
12420
|
+
this.target = target;
|
|
12421
|
+
this.timeoutMs = timeoutMs;
|
|
12422
|
+
this.durationMs = durationMs;
|
|
12423
|
+
}
|
|
12424
|
+
};
|
|
12425
|
+
function describeError(err) {
|
|
12426
|
+
if (err instanceof Error) return `${err.name}: ${err.message}`;
|
|
12427
|
+
return String(err);
|
|
12428
|
+
}
|
|
12429
|
+
async function executeJsonRequest(url, init, {
|
|
12430
|
+
toolName,
|
|
12431
|
+
target = null,
|
|
12432
|
+
timeoutMs = DEFAULT_CHAT_BRIDGE_TOOL_TIMEOUT_MS,
|
|
12433
|
+
fetchImpl,
|
|
12434
|
+
now = () => Date.now(),
|
|
12435
|
+
warn = (message) => logger.warn(message)
|
|
12436
|
+
}) {
|
|
12437
|
+
const startedAt = now();
|
|
12438
|
+
const timeoutController = new AbortController();
|
|
12439
|
+
const signals = [timeoutController.signal];
|
|
12440
|
+
if (init.signal) signals.push(init.signal);
|
|
12441
|
+
const signal = signals.length === 1 ? signals[0] : AbortSignal.any(signals);
|
|
12442
|
+
const timeout = setTimeout(() => {
|
|
12443
|
+
timeoutController.abort();
|
|
12444
|
+
}, timeoutMs);
|
|
12445
|
+
timeout.unref?.();
|
|
12446
|
+
try {
|
|
12447
|
+
const response = await fetchImpl(url, { ...init, signal });
|
|
12448
|
+
const data = await response.json();
|
|
12449
|
+
return { response, data, durationMs: now() - startedAt };
|
|
12450
|
+
} catch (err) {
|
|
12451
|
+
const durationMs = now() - startedAt;
|
|
12452
|
+
if (timeoutController.signal.aborted && !init.signal?.aborted) {
|
|
12453
|
+
warn(
|
|
12454
|
+
`[ChatBridgeTimeout] tool=${toolName} target=${target ?? "-"} duration_ms=${durationMs} timeout_ms=${timeoutMs} outcome=timeout`
|
|
12455
|
+
);
|
|
12456
|
+
throw new ChatBridgeToolTimeoutError(toolName, target, timeoutMs, durationMs);
|
|
12457
|
+
}
|
|
12458
|
+
warn(
|
|
12459
|
+
`[ChatBridgeError] tool=${toolName} target=${target ?? "-"} duration_ms=${durationMs} outcome=error error=${describeError(err)}`
|
|
12460
|
+
);
|
|
12461
|
+
throw err;
|
|
12462
|
+
} finally {
|
|
12463
|
+
clearTimeout(timeout);
|
|
12464
|
+
}
|
|
12465
|
+
}
|
|
12466
|
+
async function executeResponseRequest(url, init, {
|
|
12467
|
+
toolName,
|
|
12468
|
+
target = null,
|
|
12469
|
+
timeoutMs = DEFAULT_CHAT_BRIDGE_TOOL_TIMEOUT_MS,
|
|
12470
|
+
fetchImpl,
|
|
12471
|
+
now = () => Date.now(),
|
|
12472
|
+
warn = (message) => logger.warn(message)
|
|
12473
|
+
}) {
|
|
12474
|
+
const startedAt = now();
|
|
12475
|
+
const timeoutController = new AbortController();
|
|
12476
|
+
const signals = [timeoutController.signal];
|
|
12477
|
+
if (init.signal) signals.push(init.signal);
|
|
12478
|
+
const signal = signals.length === 1 ? signals[0] : AbortSignal.any(signals);
|
|
12479
|
+
const timeout = setTimeout(() => {
|
|
12480
|
+
timeoutController.abort();
|
|
12481
|
+
}, timeoutMs);
|
|
12482
|
+
timeout.unref?.();
|
|
12483
|
+
try {
|
|
12484
|
+
const response = await fetchImpl(url, { ...init, signal });
|
|
12485
|
+
return { response, durationMs: now() - startedAt };
|
|
12486
|
+
} catch (err) {
|
|
12487
|
+
const durationMs = now() - startedAt;
|
|
12488
|
+
if (timeoutController.signal.aborted && !init.signal?.aborted) {
|
|
12489
|
+
warn(
|
|
12490
|
+
`[ChatBridgeTimeout] tool=${toolName} target=${target ?? "-"} duration_ms=${durationMs} timeout_ms=${timeoutMs} outcome=timeout`
|
|
12491
|
+
);
|
|
12492
|
+
throw new ChatBridgeToolTimeoutError(toolName, target, timeoutMs, durationMs);
|
|
12493
|
+
}
|
|
12494
|
+
warn(
|
|
12495
|
+
`[ChatBridgeError] tool=${toolName} target=${target ?? "-"} duration_ms=${durationMs} outcome=error error=${describeError(err)}`
|
|
12496
|
+
);
|
|
12497
|
+
throw err;
|
|
12498
|
+
} finally {
|
|
12499
|
+
clearTimeout(timeout);
|
|
12500
|
+
}
|
|
12501
|
+
}
|
|
12522
12502
|
|
|
12523
12503
|
// src/directUploadCapability.ts
|
|
12524
|
-
function joinUrl(base,
|
|
12525
|
-
return `${base.replace(/\/+$/, "")}${
|
|
12504
|
+
function joinUrl(base, path16) {
|
|
12505
|
+
return `${base.replace(/\/+$/, "")}${path16}`;
|
|
12526
12506
|
}
|
|
12527
12507
|
function jsonHeaders(apiKey) {
|
|
12528
12508
|
return {
|
|
@@ -12741,7 +12721,7 @@ var DaemonTraceBundleUploader = class {
|
|
|
12741
12721
|
}, nextMs);
|
|
12742
12722
|
}
|
|
12743
12723
|
async findUploadCandidates() {
|
|
12744
|
-
const traceDir =
|
|
12724
|
+
const traceDir = path14.join(this.options.machineDir, "traces");
|
|
12745
12725
|
let names;
|
|
12746
12726
|
try {
|
|
12747
12727
|
names = await readdir3(traceDir);
|
|
@@ -12753,8 +12733,8 @@ var DaemonTraceBundleUploader = class {
|
|
|
12753
12733
|
const currentFile = this.options.currentFileProvider?.();
|
|
12754
12734
|
const candidates = [];
|
|
12755
12735
|
for (const name of names.filter((entry) => entry.startsWith("daemon-trace-") && entry.endsWith(".jsonl")).sort()) {
|
|
12756
|
-
const file =
|
|
12757
|
-
if (currentFile &&
|
|
12736
|
+
const file = path14.join(traceDir, name);
|
|
12737
|
+
if (currentFile && path14.resolve(file) === path14.resolve(currentFile)) continue;
|
|
12758
12738
|
if (await this.isUploaded(file)) continue;
|
|
12759
12739
|
try {
|
|
12760
12740
|
const info = await stat3(file);
|
|
@@ -12828,8 +12808,8 @@ var DaemonTraceBundleUploader = class {
|
|
|
12828
12808
|
}
|
|
12829
12809
|
}
|
|
12830
12810
|
uploadStatePath(file) {
|
|
12831
|
-
const stateDir =
|
|
12832
|
-
return
|
|
12811
|
+
const stateDir = path14.join(this.options.machineDir, "trace-uploads");
|
|
12812
|
+
return path14.join(stateDir, `${path14.basename(file)}.uploaded.json`);
|
|
12833
12813
|
}
|
|
12834
12814
|
async isUploaded(file) {
|
|
12835
12815
|
try {
|
|
@@ -12841,9 +12821,9 @@ var DaemonTraceBundleUploader = class {
|
|
|
12841
12821
|
}
|
|
12842
12822
|
async markUploaded(file, metadata) {
|
|
12843
12823
|
const stateFile = this.uploadStatePath(file);
|
|
12844
|
-
await mkdir2(
|
|
12824
|
+
await mkdir2(path14.dirname(stateFile), { recursive: true, mode: 448 });
|
|
12845
12825
|
await writeFile2(stateFile, `${JSON.stringify({
|
|
12846
|
-
file:
|
|
12826
|
+
file: path14.basename(file),
|
|
12847
12827
|
uploadedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
12848
12828
|
...metadata
|
|
12849
12829
|
}, null, 2)}
|
|
@@ -12865,7 +12845,7 @@ var DEFAULT_TRACE_UPLOAD_URL = "https://slock-trace-upload.botiverse.dev";
|
|
|
12865
12845
|
var RUNNER_CREDENTIAL_SCOPES = ["send", "read", "mentions", "tasks", "reactions", "server", "channels", "knowledge"];
|
|
12866
12846
|
var RUNNER_CREDENTIAL_MINT_MAX_ATTEMPTS2 = 3;
|
|
12867
12847
|
var RUNNER_CREDENTIAL_MINT_RETRY_DELAY_MS2 = 250;
|
|
12868
|
-
var DAEMON_CLI_USAGE =
|
|
12848
|
+
var DAEMON_CLI_USAGE = "Usage: slock-daemon --server-url <url> --api-key <key>";
|
|
12869
12849
|
var RunnerCredentialMintError2 = class extends Error {
|
|
12870
12850
|
code;
|
|
12871
12851
|
retryable;
|
|
@@ -12901,9 +12881,9 @@ function runnerCredentialErrorDetail2(error) {
|
|
|
12901
12881
|
async function waitForRunnerCredentialRetry2() {
|
|
12902
12882
|
await new Promise((resolve) => setTimeout(resolve, RUNNER_CREDENTIAL_MINT_RETRY_DELAY_MS2));
|
|
12903
12883
|
}
|
|
12904
|
-
function parseDaemonCliArgs(args
|
|
12884
|
+
function parseDaemonCliArgs(args) {
|
|
12905
12885
|
let serverUrl = "";
|
|
12906
|
-
let apiKey =
|
|
12886
|
+
let apiKey = "";
|
|
12907
12887
|
for (let i = 0; i < args.length; i++) {
|
|
12908
12888
|
if (args[i] === "--server-url" && args[i + 1]) serverUrl = args[++i];
|
|
12909
12889
|
if (args[i] === "--api-key" && args[i + 1]) apiKey = args[++i];
|
|
@@ -12919,24 +12899,14 @@ function readDaemonVersion(moduleUrl = import.meta.url) {
|
|
|
12919
12899
|
return "0.0.0-dev";
|
|
12920
12900
|
}
|
|
12921
12901
|
}
|
|
12922
|
-
function resolveChatBridgePath(moduleUrl = import.meta.url) {
|
|
12923
|
-
const dirname = path17.dirname(fileURLToPath(moduleUrl));
|
|
12924
|
-
const jsPath = path17.resolve(dirname, "chat-bridge.js");
|
|
12925
|
-
try {
|
|
12926
|
-
accessSync(jsPath);
|
|
12927
|
-
return jsPath;
|
|
12928
|
-
} catch {
|
|
12929
|
-
return path17.resolve(dirname, "chat-bridge.ts");
|
|
12930
|
-
}
|
|
12931
|
-
}
|
|
12932
12902
|
function resolveSlockCliPath(moduleUrl = import.meta.url) {
|
|
12933
|
-
const thisDir =
|
|
12934
|
-
const bundledDistPath =
|
|
12903
|
+
const thisDir = path15.dirname(fileURLToPath(moduleUrl));
|
|
12904
|
+
const bundledDistPath = path15.resolve(thisDir, "cli", "index.js");
|
|
12935
12905
|
try {
|
|
12936
12906
|
accessSync(bundledDistPath);
|
|
12937
12907
|
return bundledDistPath;
|
|
12938
12908
|
} catch {
|
|
12939
|
-
const workspaceDistPath =
|
|
12909
|
+
const workspaceDistPath = path15.resolve(thisDir, "..", "..", "cli", "dist", "index.js");
|
|
12940
12910
|
accessSync(workspaceDistPath);
|
|
12941
12911
|
return workspaceDistPath;
|
|
12942
12912
|
}
|
|
@@ -13073,7 +13043,6 @@ var DaemonCore = class {
|
|
|
13073
13043
|
// bundle version). Reported in `ready` so the server can surface the
|
|
13074
13044
|
// Computer's own version (distinct from the underlying daemonVersion).
|
|
13075
13045
|
computerVersion;
|
|
13076
|
-
chatBridgePath;
|
|
13077
13046
|
slockCliPath;
|
|
13078
13047
|
slockHome;
|
|
13079
13048
|
runtimeDetector;
|
|
@@ -13089,7 +13058,6 @@ var DaemonCore = class {
|
|
|
13089
13058
|
this.options = options;
|
|
13090
13059
|
this.daemonVersion = options.daemonVersion ?? readDaemonVersion();
|
|
13091
13060
|
this.computerVersion = (process.env.SLOCK_COMPUTER_VERSION || "").trim() || null;
|
|
13092
|
-
this.chatBridgePath = options.chatBridgePath ?? resolveChatBridgePath();
|
|
13093
13061
|
this.slockCliPath = options.slockCliPath ?? resolveSlockCliPath();
|
|
13094
13062
|
this.slockHome = resolveSlockHome();
|
|
13095
13063
|
process.env[SLOCK_HOME_ENV] = this.slockHome;
|
|
@@ -13110,7 +13078,7 @@ var DaemonCore = class {
|
|
|
13110
13078
|
daemonVersion: this.daemonVersion,
|
|
13111
13079
|
computerVersion: this.computerVersion
|
|
13112
13080
|
};
|
|
13113
|
-
this.agentManager = options.agentManagerFactory ? options.agentManagerFactory(
|
|
13081
|
+
this.agentManager = options.agentManagerFactory ? options.agentManagerFactory((msg) => connection.send(msg), options.apiKey, agentManagerOptions) : new AgentProcessManager((msg) => connection.send(msg), options.apiKey, agentManagerOptions);
|
|
13114
13082
|
const connectionFactory = options.connectionFactory ?? ((connOptions) => new DaemonConnection(connOptions));
|
|
13115
13083
|
connection = connectionFactory({
|
|
13116
13084
|
serverUrl: options.serverUrl,
|
|
@@ -13125,7 +13093,7 @@ var DaemonCore = class {
|
|
|
13125
13093
|
}
|
|
13126
13094
|
resolveMachineStateRoot() {
|
|
13127
13095
|
if (this.options.machineStateDir) return this.options.machineStateDir;
|
|
13128
|
-
if (this.options.dataDir) return
|
|
13096
|
+
if (this.options.dataDir) return path15.join(path15.dirname(this.options.dataDir), "machines");
|
|
13129
13097
|
return resolveDefaultMachineStateRoot();
|
|
13130
13098
|
}
|
|
13131
13099
|
shouldEnableLocalTrace() {
|
|
@@ -13151,7 +13119,7 @@ var DaemonCore = class {
|
|
|
13151
13119
|
sink: this.localTraceSink
|
|
13152
13120
|
}));
|
|
13153
13121
|
this.agentManager.setTracer(this.tracer);
|
|
13154
|
-
this.agentManager.setCliTransportTraceDir(
|
|
13122
|
+
this.agentManager.setCliTransportTraceDir(path15.join(machineDir, "traces"));
|
|
13155
13123
|
}
|
|
13156
13124
|
installTraceBundleUploader(machineDir) {
|
|
13157
13125
|
if (!this.shouldEnableLocalTrace()) return;
|
|
@@ -13684,15 +13652,13 @@ var DaemonCore = class {
|
|
|
13684
13652
|
};
|
|
13685
13653
|
|
|
13686
13654
|
export {
|
|
13687
|
-
|
|
13688
|
-
scrubDaemonAuthEnv,
|
|
13655
|
+
subscribeDaemonLogs,
|
|
13689
13656
|
resolveWorkspaceDirectoryPath,
|
|
13690
13657
|
scanWorkspaceDirectories,
|
|
13691
13658
|
deleteWorkspaceDirectory,
|
|
13692
13659
|
DAEMON_CLI_USAGE,
|
|
13693
13660
|
parseDaemonCliArgs,
|
|
13694
13661
|
readDaemonVersion,
|
|
13695
|
-
resolveChatBridgePath,
|
|
13696
13662
|
resolveSlockCliPath,
|
|
13697
13663
|
detectRuntimes,
|
|
13698
13664
|
DaemonCore
|