@botiverse/raft-daemon 0.60.0-play.20260615140421 → 0.61.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-E5YOBAA3.js → chunk-XMSXOB5R.js} +583 -221
- package/dist/cli/index.js +15 -1
- package/dist/core.js +1 -5
- package/dist/{dist-GKTG7LRO.js → dist-6YUWBDWX.js} +15 -1
- package/dist/index.js +3 -5
- package/package.json +2 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/core.ts
|
|
2
|
-
import
|
|
2
|
+
import path17 from "path";
|
|
3
3
|
import os8 from "os";
|
|
4
|
-
import { createRequire as
|
|
4
|
+
import { createRequire as createRequire3 } from "module";
|
|
5
5
|
import { accessSync } from "fs";
|
|
6
6
|
import { fileURLToPath } from "url";
|
|
7
7
|
|
|
@@ -1298,7 +1298,11 @@ var RUNTIMES = [
|
|
|
1298
1298
|
{ id: "claude", displayName: "Claude Code", binary: "claude", supported: true },
|
|
1299
1299
|
{ id: "codex", displayName: "Codex CLI", binary: "codex", supported: true },
|
|
1300
1300
|
{ id: "antigravity", displayName: "Antigravity CLI", binary: "agy", supported: true },
|
|
1301
|
-
|
|
1301
|
+
// Kimi: prefer the in-process SDK (`kimi-sdk` → "Kimi Code") for new agents.
|
|
1302
|
+
// The legacy `kimi` (kimi-cli child-process) entry stays for backward compat
|
|
1303
|
+
// with existing `runtime=kimi` agents but is labelled deprecated.
|
|
1304
|
+
{ id: "kimi-sdk", displayName: "Kimi Code", binary: "", supported: true },
|
|
1305
|
+
{ id: "kimi", displayName: "Kimi CLI (deprecated)", binary: "kimi", supported: true },
|
|
1302
1306
|
{ id: "copilot", displayName: "Copilot CLI", binary: "copilot", supported: true },
|
|
1303
1307
|
{ id: "cursor", displayName: "Cursor CLI", binary: "cursor-agent", supported: true },
|
|
1304
1308
|
{ id: "gemini", displayName: "Gemini CLI", binary: "gemini", supported: true },
|
|
@@ -1366,6 +1370,15 @@ var RUNTIME_MODELS = {
|
|
|
1366
1370
|
// built-in option is to defer to whatever default model the CLI already uses.
|
|
1367
1371
|
kimi: [
|
|
1368
1372
|
{ id: "default", label: "Configured Default" }
|
|
1373
|
+
],
|
|
1374
|
+
// kimi-sdk runs the Kimi Code SDK in-process. Surface the canonical model
|
|
1375
|
+
// first so getDefaultModel("kimi-sdk") returns it (without a static entry,
|
|
1376
|
+
// useRuntimeModels falls back to Claude's list and getDefaultModel returns
|
|
1377
|
+
// "sonnet" — which the SDK driver would pass through to the Kimi session
|
|
1378
|
+
// and the LLM call would fail). Mirrors detectKimiSdkModels() in the daemon.
|
|
1379
|
+
"kimi-sdk": [
|
|
1380
|
+
{ id: "kimi-code/kimi-for-coding", label: "Kimi-K2.6 (Kimi for Coding)", verified: "launchable" },
|
|
1381
|
+
{ id: "kimi-k2-0905-preview", label: "Kimi K2 (preview)", verified: "suggestion_only" }
|
|
1369
1382
|
]
|
|
1370
1383
|
};
|
|
1371
1384
|
function getDefaultModel(runtimeId) {
|
|
@@ -1551,10 +1564,10 @@ var DISPLAY_PLAN_CONFIG = {
|
|
|
1551
1564
|
};
|
|
1552
1565
|
|
|
1553
1566
|
// src/agentProcessManager.ts
|
|
1554
|
-
import { mkdirSync as
|
|
1567
|
+
import { mkdirSync as mkdirSync5, readdirSync as readdirSync3, statSync, writeFileSync as writeFileSync4 } from "fs";
|
|
1555
1568
|
import { mkdir, writeFile, access, readdir as readdir2, stat as stat2, readFile, rm as rm2 } from "fs/promises";
|
|
1556
1569
|
import { createHash as createHash3 } from "crypto";
|
|
1557
|
-
import
|
|
1570
|
+
import path13 from "path";
|
|
1558
1571
|
import os6 from "os";
|
|
1559
1572
|
|
|
1560
1573
|
// src/drivers/claude.ts
|
|
@@ -2143,19 +2156,6 @@ function listLegacySlockStatePaths(slockHome = resolveSlockHome(), homeDir = os.
|
|
|
2143
2156
|
return candidates.filter((candidate) => existsSync(candidate.path));
|
|
2144
2157
|
}
|
|
2145
2158
|
|
|
2146
|
-
// src/authEnv.ts
|
|
2147
|
-
var DAEMON_API_KEY_ENV = "SLOCK_MACHINE_API_KEY";
|
|
2148
|
-
var SLOCK_AGENT_TOKEN_ENV = "SLOCK_AGENT_TOKEN";
|
|
2149
|
-
function scrubDaemonAuthEnv(env) {
|
|
2150
|
-
delete env[DAEMON_API_KEY_ENV];
|
|
2151
|
-
return env;
|
|
2152
|
-
}
|
|
2153
|
-
function scrubDaemonChildEnv(env) {
|
|
2154
|
-
delete env[DAEMON_API_KEY_ENV];
|
|
2155
|
-
delete env[SLOCK_AGENT_TOKEN_ENV];
|
|
2156
|
-
return env;
|
|
2157
|
-
}
|
|
2158
|
-
|
|
2159
2159
|
// src/agentCredentialProxy.ts
|
|
2160
2160
|
import { randomBytes } from "crypto";
|
|
2161
2161
|
import http from "http";
|
|
@@ -3367,6 +3367,7 @@ function routeFamilyForPath(pathname) {
|
|
|
3367
3367
|
function daemonUpstreamTargetHostClass(url) {
|
|
3368
3368
|
const hostname = url.hostname.toLowerCase();
|
|
3369
3369
|
if (hostname === "api.slock.ai") return "api.slock.ai";
|
|
3370
|
+
if (hostname === "api.raft.build") return "api.raft.build";
|
|
3370
3371
|
return "custom_server";
|
|
3371
3372
|
}
|
|
3372
3373
|
function upstreamLayerForProxyError(err) {
|
|
@@ -3643,9 +3644,7 @@ var LOOPBACK_NO_PROXY = "127.0.0.1,localhost";
|
|
|
3643
3644
|
var CLI_TRANSPORT_TRACE_DIR_ENV = "SLOCK_CLI_TRANSPORT_TRACE_DIR";
|
|
3644
3645
|
var safePathPart = (value) => value.replace(/[^a-zA-Z0-9_.-]/g, "_");
|
|
3645
3646
|
var RAW_CREDENTIAL_ENV_DENYLIST = [
|
|
3646
|
-
"
|
|
3647
|
-
"SLOCK_AGENT_CREDENTIAL_KEY",
|
|
3648
|
-
"SLOCK_AGENT_CREDENTIAL_KEY_FILE"
|
|
3647
|
+
"SLOCK_AGENT_CREDENTIAL_KEY"
|
|
3649
3648
|
];
|
|
3650
3649
|
function deriveCliFallbackCandidates(cliPath) {
|
|
3651
3650
|
if (!cliPath || cliPath === "__cli") return [];
|
|
@@ -3960,7 +3959,7 @@ set "SLOCK_AGENT_ACTIVE_CAPABILITIES=${DEFAULT_ACTIVE_CAPABILITIES}"\r
|
|
|
3960
3959
|
...agentCredentialProxy ? {} : { SLOCK_AGENT_TOKEN_FILE: tokenFile },
|
|
3961
3960
|
PATH: `${slockDir}${path2.delimiter}${process.env.PATH ?? ""}`
|
|
3962
3961
|
};
|
|
3963
|
-
|
|
3962
|
+
delete spawnEnv.SLOCK_AGENT_TOKEN;
|
|
3964
3963
|
for (const key of RAW_CREDENTIAL_ENV_DENYLIST) {
|
|
3965
3964
|
delete spawnEnv[key];
|
|
3966
3965
|
}
|
|
@@ -4395,7 +4394,7 @@ function requiresWindowsShell(command, platform = process.platform) {
|
|
|
4395
4394
|
}
|
|
4396
4395
|
function resolveCommandOnPath(command, deps = {}) {
|
|
4397
4396
|
const platform = deps.platform ?? process.platform;
|
|
4398
|
-
const env =
|
|
4397
|
+
const env = withWindowsUserEnvironment(deps.env ?? process.env, deps);
|
|
4399
4398
|
const execFileSyncFn = deps.execFileSyncFn ?? execFileSync;
|
|
4400
4399
|
const existsSyncFn = deps.existsSyncFn ?? existsSync3;
|
|
4401
4400
|
if (platform === "win32") {
|
|
@@ -4421,7 +4420,7 @@ function firstExistingPath(candidates, deps = {}) {
|
|
|
4421
4420
|
return null;
|
|
4422
4421
|
}
|
|
4423
4422
|
function readCommandVersion(command, args = [], deps = {}) {
|
|
4424
|
-
const env =
|
|
4423
|
+
const env = withWindowsUserEnvironment(deps.env ?? process.env, deps);
|
|
4425
4424
|
const execFileSyncFn = deps.execFileSyncFn ?? execFileSync;
|
|
4426
4425
|
try {
|
|
4427
4426
|
const output = normalizeExecOutput(execFileSyncFn(command, [...args, "--version"], {
|
|
@@ -5815,11 +5814,11 @@ function detectCursorModels(runCommand = runCursorModelsCommand) {
|
|
|
5815
5814
|
return parseCursorModelsOutput(String(result.stdout || ""));
|
|
5816
5815
|
}
|
|
5817
5816
|
function buildCursorModelProbeEnv(deps = {}) {
|
|
5818
|
-
return
|
|
5817
|
+
return withWindowsUserEnvironment({
|
|
5819
5818
|
...deps.env ?? process.env,
|
|
5820
5819
|
FORCE_COLOR: "0",
|
|
5821
5820
|
NO_COLOR: "1"
|
|
5822
|
-
}, deps)
|
|
5821
|
+
}, deps);
|
|
5823
5822
|
}
|
|
5824
5823
|
function runCursorModelsCommand() {
|
|
5825
5824
|
return spawnSync("cursor-agent", ["models"], {
|
|
@@ -5875,7 +5874,7 @@ function resolveGeminiSpawn(commandArgs, deps = {}) {
|
|
|
5875
5874
|
}
|
|
5876
5875
|
const execFileSyncFn = deps.execFileSyncFn ?? execFileSync3;
|
|
5877
5876
|
const existsSyncFn = deps.existsSyncFn ?? existsSync6;
|
|
5878
|
-
const env =
|
|
5877
|
+
const env = deps.env ?? process.env;
|
|
5879
5878
|
const winPath = path7.win32;
|
|
5880
5879
|
let geminiEntry = null;
|
|
5881
5880
|
try {
|
|
@@ -6012,15 +6011,12 @@ var GeminiDriver = class {
|
|
|
6012
6011
|
// src/drivers/kimi.ts
|
|
6013
6012
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
6014
6013
|
import { spawn as spawn7 } from "child_process";
|
|
6015
|
-
import {
|
|
6014
|
+
import { existsSync as existsSync7, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
6016
6015
|
import os4 from "os";
|
|
6017
6016
|
import path8 from "path";
|
|
6018
6017
|
var KIMI_WIRE_PROTOCOL_VERSION = "1.3";
|
|
6019
6018
|
var KIMI_SYSTEM_PROMPT_FILE = ".slock-kimi-system.md";
|
|
6020
6019
|
var KIMI_AGENT_FILE = ".slock-kimi-agent.yaml";
|
|
6021
|
-
var KIMI_GENERATED_CONFIG_FILE = ".slock-kimi-config.toml";
|
|
6022
|
-
var SLOCK_KIMI_CONFIG_CONTENT_ENV = "SLOCK_KIMI_CONFIG_CONTENT";
|
|
6023
|
-
var SLOCK_KIMI_CONFIG_FILE_ENV = "SLOCK_KIMI_CONFIG_FILE";
|
|
6024
6020
|
function parseToolArguments(raw) {
|
|
6025
6021
|
if (typeof raw !== "string") return raw;
|
|
6026
6022
|
try {
|
|
@@ -6029,73 +6025,6 @@ function parseToolArguments(raw) {
|
|
|
6029
6025
|
return raw;
|
|
6030
6026
|
}
|
|
6031
6027
|
}
|
|
6032
|
-
function readKimiConfigSource(home = os4.homedir(), env = process.env) {
|
|
6033
|
-
const inlineConfig = env[SLOCK_KIMI_CONFIG_CONTENT_ENV];
|
|
6034
|
-
if (inlineConfig && inlineConfig.trim()) {
|
|
6035
|
-
return {
|
|
6036
|
-
raw: inlineConfig,
|
|
6037
|
-
explicitPath: null,
|
|
6038
|
-
sourcePath: SLOCK_KIMI_CONFIG_CONTENT_ENV
|
|
6039
|
-
};
|
|
6040
|
-
}
|
|
6041
|
-
const explicitPath = env[SLOCK_KIMI_CONFIG_FILE_ENV];
|
|
6042
|
-
const configPath = explicitPath && explicitPath.trim() ? explicitPath : path8.join(home, ".kimi", "config.toml");
|
|
6043
|
-
try {
|
|
6044
|
-
return {
|
|
6045
|
-
raw: readFileSync3(configPath, "utf8"),
|
|
6046
|
-
explicitPath: explicitPath && explicitPath.trim() ? explicitPath : null,
|
|
6047
|
-
sourcePath: configPath
|
|
6048
|
-
};
|
|
6049
|
-
} catch {
|
|
6050
|
-
return {
|
|
6051
|
-
raw: null,
|
|
6052
|
-
explicitPath: explicitPath && explicitPath.trim() ? explicitPath : null,
|
|
6053
|
-
sourcePath: configPath
|
|
6054
|
-
};
|
|
6055
|
-
}
|
|
6056
|
-
}
|
|
6057
|
-
function buildKimiSpawnEnv(env = process.env) {
|
|
6058
|
-
const spawnEnv = { ...env, FORCE_COLOR: "0", NO_COLOR: "1" };
|
|
6059
|
-
delete spawnEnv[SLOCK_KIMI_CONFIG_CONTENT_ENV];
|
|
6060
|
-
delete spawnEnv[SLOCK_KIMI_CONFIG_FILE_ENV];
|
|
6061
|
-
return scrubDaemonChildEnv(spawnEnv);
|
|
6062
|
-
}
|
|
6063
|
-
function buildKimiEffectiveEnv(ctx, overrideEnv) {
|
|
6064
|
-
return {
|
|
6065
|
-
...process.env,
|
|
6066
|
-
...ctx.config.envVars || {},
|
|
6067
|
-
...overrideEnv || {}
|
|
6068
|
-
};
|
|
6069
|
-
}
|
|
6070
|
-
function buildKimiLaunchOptions(ctx, opts = {}) {
|
|
6071
|
-
const env = buildKimiEffectiveEnv(ctx, opts.env);
|
|
6072
|
-
const source = readKimiConfigSource(opts.home ?? os4.homedir(), env);
|
|
6073
|
-
const args = [];
|
|
6074
|
-
let configFilePath = null;
|
|
6075
|
-
let configContent = null;
|
|
6076
|
-
if (source.explicitPath) {
|
|
6077
|
-
configFilePath = source.explicitPath;
|
|
6078
|
-
} else if (source.raw !== null && source.sourcePath === SLOCK_KIMI_CONFIG_CONTENT_ENV) {
|
|
6079
|
-
configFilePath = path8.join(ctx.workingDirectory, KIMI_GENERATED_CONFIG_FILE);
|
|
6080
|
-
configContent = source.raw;
|
|
6081
|
-
if (opts.writeGeneratedConfig !== false) {
|
|
6082
|
-
writeFileSync3(configFilePath, source.raw, { encoding: "utf8", mode: 384 });
|
|
6083
|
-
chmodSync(configFilePath, 384);
|
|
6084
|
-
}
|
|
6085
|
-
}
|
|
6086
|
-
if (configFilePath) {
|
|
6087
|
-
args.push("--config-file", configFilePath);
|
|
6088
|
-
}
|
|
6089
|
-
if (ctx.config.model && ctx.config.model !== "default") {
|
|
6090
|
-
args.push("--model", ctx.config.model);
|
|
6091
|
-
}
|
|
6092
|
-
return {
|
|
6093
|
-
args,
|
|
6094
|
-
env: buildKimiSpawnEnv(env),
|
|
6095
|
-
configFilePath,
|
|
6096
|
-
configContent
|
|
6097
|
-
};
|
|
6098
|
-
}
|
|
6099
6028
|
function resolveKimiSpawn(commandArgs, deps = {}) {
|
|
6100
6029
|
return {
|
|
6101
6030
|
command: resolveCommandOnPath("kimi", deps) ?? "kimi",
|
|
@@ -6119,25 +6048,7 @@ var KimiDriver = class {
|
|
|
6119
6048
|
};
|
|
6120
6049
|
model = {
|
|
6121
6050
|
detectedModelsVerifiedAs: "launchable",
|
|
6122
|
-
toLaunchSpec: (modelId
|
|
6123
|
-
if (!ctx) return { args: ["--model", modelId] };
|
|
6124
|
-
const launchCtx = {
|
|
6125
|
-
...ctx,
|
|
6126
|
-
config: {
|
|
6127
|
-
...ctx.config,
|
|
6128
|
-
model: modelId
|
|
6129
|
-
}
|
|
6130
|
-
};
|
|
6131
|
-
const launch = buildKimiLaunchOptions(launchCtx, {
|
|
6132
|
-
home: opts?.home,
|
|
6133
|
-
writeGeneratedConfig: false
|
|
6134
|
-
});
|
|
6135
|
-
return {
|
|
6136
|
-
args: launch.args,
|
|
6137
|
-
env: launch.env,
|
|
6138
|
-
configFiles: launch.configFilePath ? [launch.configFilePath] : void 0
|
|
6139
|
-
};
|
|
6140
|
-
}
|
|
6051
|
+
toLaunchSpec: (modelId) => ({ args: ["--model", modelId] })
|
|
6141
6052
|
};
|
|
6142
6053
|
supportsStdinNotification = true;
|
|
6143
6054
|
busyDeliveryMode = "direct";
|
|
@@ -6161,23 +6072,21 @@ var KimiDriver = class {
|
|
|
6161
6072
|
` system_prompt_path: ./${KIMI_SYSTEM_PROMPT_FILE}`,
|
|
6162
6073
|
""
|
|
6163
6074
|
].join("\n"), "utf8");
|
|
6164
|
-
const launch = buildKimiLaunchOptions(ctx);
|
|
6165
6075
|
const args = [
|
|
6166
6076
|
"--wire",
|
|
6167
6077
|
"--yolo",
|
|
6168
6078
|
"--agent-file",
|
|
6169
6079
|
agentFilePath,
|
|
6170
6080
|
"--session",
|
|
6171
|
-
this.sessionId
|
|
6172
|
-
...launch.args
|
|
6081
|
+
this.sessionId
|
|
6173
6082
|
];
|
|
6174
6083
|
const launchRuntimeFields = runtimeConfigToLaunchFields(ctx.config);
|
|
6175
6084
|
if (launchRuntimeFields.model && launchRuntimeFields.model !== "default") {
|
|
6176
6085
|
args.push("--model", launchRuntimeFields.model);
|
|
6177
6086
|
}
|
|
6178
6087
|
const spawnEnv = (await prepareCliTransport(ctx, { NO_COLOR: "1" })).spawnEnv;
|
|
6179
|
-
const
|
|
6180
|
-
const proc = spawn7(
|
|
6088
|
+
const launch = resolveKimiSpawn(args);
|
|
6089
|
+
const proc = spawn7(launch.command, launch.args, {
|
|
6181
6090
|
cwd: ctx.workingDirectory,
|
|
6182
6091
|
stdio: ["pipe", "pipe", "pipe"],
|
|
6183
6092
|
env: spawnEnv,
|
|
@@ -6185,7 +6094,7 @@ var KimiDriver = class {
|
|
|
6185
6094
|
// and has an 8191-character command-line limit. Kimi's official
|
|
6186
6095
|
// installer/uv entrypoint is an executable, so launch it directly and
|
|
6187
6096
|
// keep prompts on stdin / files instead of routing through cmd.exe.
|
|
6188
|
-
shell:
|
|
6097
|
+
shell: launch.shell
|
|
6189
6098
|
});
|
|
6190
6099
|
proc.stdin?.write(JSON.stringify({
|
|
6191
6100
|
jsonrpc: "2.0",
|
|
@@ -6298,9 +6207,14 @@ var KimiDriver = class {
|
|
|
6298
6207
|
return detectKimiModels();
|
|
6299
6208
|
}
|
|
6300
6209
|
};
|
|
6301
|
-
function detectKimiModels(home = os4.homedir()
|
|
6302
|
-
const
|
|
6303
|
-
|
|
6210
|
+
function detectKimiModels(home = os4.homedir()) {
|
|
6211
|
+
const configPath = path8.join(home, ".kimi", "config.toml");
|
|
6212
|
+
let raw;
|
|
6213
|
+
try {
|
|
6214
|
+
raw = readFileSync3(configPath, "utf8");
|
|
6215
|
+
} catch {
|
|
6216
|
+
return null;
|
|
6217
|
+
}
|
|
6304
6218
|
const models = [];
|
|
6305
6219
|
const sectionRe = /^\s*\[models(?:\.([^\]]+)|"\.[^"]+"|\."[^"]+")\s*\]\s*$/gm;
|
|
6306
6220
|
const lineRe = /^\s*\[models\.(.+?)\s*\]\s*$/gm;
|
|
@@ -6319,11 +6233,455 @@ function detectKimiModels(home = os4.homedir(), opts = {}) {
|
|
|
6319
6233
|
return { models, default: defaultModel };
|
|
6320
6234
|
}
|
|
6321
6235
|
|
|
6236
|
+
// src/drivers/kimi-sdk.ts
|
|
6237
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
6238
|
+
import { EventEmitter } from "events";
|
|
6239
|
+
import { mkdirSync as mkdirSync3 } from "fs";
|
|
6240
|
+
import path9 from "path";
|
|
6241
|
+
import { createRequire as createRequire2 } from "module";
|
|
6242
|
+
import {
|
|
6243
|
+
createKimiHarness
|
|
6244
|
+
} from "@botiverse/kimi-code-sdk";
|
|
6245
|
+
var requireFromHere = createRequire2(import.meta.url);
|
|
6246
|
+
var KIMI_CODE_USER_AGENT_PRODUCT = "kimi-code-cli";
|
|
6247
|
+
var KIMI_CODE_HOST_VERSION = "0.14.3";
|
|
6248
|
+
function getDaemonVersion() {
|
|
6249
|
+
try {
|
|
6250
|
+
const pkg = requireFromHere("../../package.json");
|
|
6251
|
+
return pkg.version || "0.0.0";
|
|
6252
|
+
} catch {
|
|
6253
|
+
return "0.0.0";
|
|
6254
|
+
}
|
|
6255
|
+
}
|
|
6256
|
+
var KIMI_SESSION_DIR = ".kimi-sessions";
|
|
6257
|
+
function createKimiSdkEventMappingState(sessionId = null) {
|
|
6258
|
+
return {
|
|
6259
|
+
sessionId,
|
|
6260
|
+
sessionAnnounced: false
|
|
6261
|
+
};
|
|
6262
|
+
}
|
|
6263
|
+
function buildKimiSessionDir(workingDirectory) {
|
|
6264
|
+
return path9.join(workingDirectory, KIMI_SESSION_DIR);
|
|
6265
|
+
}
|
|
6266
|
+
function kimiErrorMessage(error) {
|
|
6267
|
+
if (typeof error === "string" && error.trim()) return error.trim();
|
|
6268
|
+
if (error && typeof error === "object") {
|
|
6269
|
+
const record = error;
|
|
6270
|
+
if (typeof record.message === "string" && record.message.trim()) return record.message.trim();
|
|
6271
|
+
try {
|
|
6272
|
+
return JSON.stringify(error);
|
|
6273
|
+
} catch {
|
|
6274
|
+
}
|
|
6275
|
+
}
|
|
6276
|
+
return "Unknown Kimi error";
|
|
6277
|
+
}
|
|
6278
|
+
function pushSessionInitIfNeeded(state, events) {
|
|
6279
|
+
if (!state.sessionAnnounced && state.sessionId) {
|
|
6280
|
+
events.push({ kind: "session_init", sessionId: state.sessionId });
|
|
6281
|
+
state.sessionAnnounced = true;
|
|
6282
|
+
}
|
|
6283
|
+
}
|
|
6284
|
+
function mapKimiSdkEventToParsedEvents(event, state) {
|
|
6285
|
+
const events = [];
|
|
6286
|
+
pushSessionInitIfNeeded(state, events);
|
|
6287
|
+
switch (event.type) {
|
|
6288
|
+
// ── content streaming → ParsedEvent ──
|
|
6289
|
+
case "thinking.delta":
|
|
6290
|
+
if (typeof event.delta === "string" && event.delta.length > 0) {
|
|
6291
|
+
events.push({ kind: "thinking", text: event.delta });
|
|
6292
|
+
}
|
|
6293
|
+
return events;
|
|
6294
|
+
case "assistant.delta":
|
|
6295
|
+
if (typeof event.delta === "string" && event.delta.length > 0) {
|
|
6296
|
+
events.push({ kind: "text", text: event.delta });
|
|
6297
|
+
}
|
|
6298
|
+
return events;
|
|
6299
|
+
case "tool.call.started":
|
|
6300
|
+
events.push({
|
|
6301
|
+
kind: "tool_call",
|
|
6302
|
+
name: event.name || "unknown_tool",
|
|
6303
|
+
input: event.args ?? {}
|
|
6304
|
+
});
|
|
6305
|
+
return events;
|
|
6306
|
+
case "tool.result":
|
|
6307
|
+
events.push({ kind: "tool_output", name: "" });
|
|
6308
|
+
return events;
|
|
6309
|
+
case "compaction.started":
|
|
6310
|
+
events.push({ kind: "compaction_started" });
|
|
6311
|
+
return events;
|
|
6312
|
+
case "compaction.completed":
|
|
6313
|
+
events.push({ kind: "compaction_finished" });
|
|
6314
|
+
return events;
|
|
6315
|
+
case "error":
|
|
6316
|
+
events.push({ kind: "error", message: kimiErrorMessage(event) });
|
|
6317
|
+
return events;
|
|
6318
|
+
// ── THE single turn-triggering source class ──
|
|
6319
|
+
case "turn.ended":
|
|
6320
|
+
events.push({ kind: "turn_end", sessionId: state.sessionId || void 0 });
|
|
6321
|
+
return events;
|
|
6322
|
+
// ── explicit drops (RS-004) ──
|
|
6323
|
+
// `warning` is non-fatal in the SDK's vocabulary; mapping it to
|
|
6324
|
+
// ParsedEvent.kind="error" would latch the agent into APM's error state
|
|
6325
|
+
// (lastRuntimeError set by `runtime.error`, then NOT cleared by the
|
|
6326
|
+
// following turn_end) — so a warning would brick the agent until
|
|
6327
|
+
// restart. Drop it here; the SDK's own log already records it.
|
|
6328
|
+
case "warning":
|
|
6329
|
+
// turn / step lifecycle (state-only, no parsed payload)
|
|
6330
|
+
case "turn.started":
|
|
6331
|
+
case "turn.step.started":
|
|
6332
|
+
case "turn.step.completed":
|
|
6333
|
+
case "turn.step.retrying":
|
|
6334
|
+
case "turn.step.interrupted":
|
|
6335
|
+
// tool-call progress / hooks (could elevate to internal_progress in future)
|
|
6336
|
+
case "tool.call.delta":
|
|
6337
|
+
case "tool.progress":
|
|
6338
|
+
case "hook.result":
|
|
6339
|
+
// status / meta updates
|
|
6340
|
+
case "agent.status.updated":
|
|
6341
|
+
case "session.meta.updated":
|
|
6342
|
+
case "goal.updated":
|
|
6343
|
+
case "skill.activated":
|
|
6344
|
+
// MCP infra
|
|
6345
|
+
case "tool.list.updated":
|
|
6346
|
+
case "mcp.server.status":
|
|
6347
|
+
// subagent lifecycle (v0: drop; could surface later)
|
|
6348
|
+
case "subagent.spawned":
|
|
6349
|
+
case "subagent.started":
|
|
6350
|
+
case "subagent.suspended":
|
|
6351
|
+
case "subagent.completed":
|
|
6352
|
+
case "subagent.failed":
|
|
6353
|
+
// compaction sub-cases
|
|
6354
|
+
case "compaction.blocked":
|
|
6355
|
+
case "compaction.cancelled":
|
|
6356
|
+
// out-of-band
|
|
6357
|
+
case "background.task.started":
|
|
6358
|
+
case "background.task.terminated":
|
|
6359
|
+
case "cron.fired":
|
|
6360
|
+
return events;
|
|
6361
|
+
default: {
|
|
6362
|
+
const _exhaustive = event;
|
|
6363
|
+
return _exhaustive;
|
|
6364
|
+
}
|
|
6365
|
+
}
|
|
6366
|
+
}
|
|
6367
|
+
var KIMI_SDK_RUNTIME_SESSION_DESCRIPTOR = {
|
|
6368
|
+
transport: "sdk",
|
|
6369
|
+
lifecycle: "sdk_session",
|
|
6370
|
+
input: {
|
|
6371
|
+
initial: "start",
|
|
6372
|
+
idle: "sdk_prompt",
|
|
6373
|
+
busy: "sdk_steer"
|
|
6374
|
+
},
|
|
6375
|
+
readiness: "sdk_ready",
|
|
6376
|
+
turnBoundary: "sdk_event",
|
|
6377
|
+
startPolicy: "immediate",
|
|
6378
|
+
inFlightWake: "steer",
|
|
6379
|
+
busyDelivery: "direct",
|
|
6380
|
+
postTurn: "keep_alive"
|
|
6381
|
+
};
|
|
6382
|
+
async function createKimiAgentSessionForContext(ctx, sessionId) {
|
|
6383
|
+
const sessionDir = buildKimiSessionDir(ctx.workingDirectory);
|
|
6384
|
+
mkdirSync3(sessionDir, { recursive: true });
|
|
6385
|
+
const cliTransport = await prepareCliTransport(ctx, { NO_COLOR: "1" });
|
|
6386
|
+
const spawnEnv = cliTransport.spawnEnv;
|
|
6387
|
+
const wrapperPath = cliTransport.wrapperPath;
|
|
6388
|
+
const homeDir = spawnEnv.KIMI_HOME || (process.env.HOME ? path9.join(process.env.HOME, ".kimi") : path9.join(ctx.workingDirectory, ".kimi"));
|
|
6389
|
+
mkdirSync3(homeDir, { recursive: true });
|
|
6390
|
+
const harness = createKimiHarness({
|
|
6391
|
+
homeDir,
|
|
6392
|
+
identity: {
|
|
6393
|
+
userAgentProduct: KIMI_CODE_USER_AGENT_PRODUCT,
|
|
6394
|
+
version: KIMI_CODE_HOST_VERSION,
|
|
6395
|
+
userAgentSuffix: `slock-daemon/${getDaemonVersion()}`
|
|
6396
|
+
}
|
|
6397
|
+
});
|
|
6398
|
+
const launchRuntimeFields = runtimeConfigToLaunchFields(ctx.config);
|
|
6399
|
+
const sessionFields = {
|
|
6400
|
+
workDir: ctx.workingDirectory,
|
|
6401
|
+
...launchRuntimeFields.model && launchRuntimeFields.model !== "default" ? { model: launchRuntimeFields.model } : {}
|
|
6402
|
+
};
|
|
6403
|
+
let session;
|
|
6404
|
+
if (ctx.config.sessionId) {
|
|
6405
|
+
try {
|
|
6406
|
+
session = await harness.resumeSession({ ...sessionFields, id: ctx.config.sessionId });
|
|
6407
|
+
} catch (resumeError) {
|
|
6408
|
+
void resumeError;
|
|
6409
|
+
session = await harness.createSession(sessionFields);
|
|
6410
|
+
}
|
|
6411
|
+
} else {
|
|
6412
|
+
session = await harness.createSession(sessionFields);
|
|
6413
|
+
}
|
|
6414
|
+
return { harness, session, wrapperPath };
|
|
6415
|
+
}
|
|
6416
|
+
var KimiSdkRuntimeSession = class {
|
|
6417
|
+
constructor(ctx, setCurrentSessionId, sessionFactory = createKimiAgentSessionForContext) {
|
|
6418
|
+
this.ctx = ctx;
|
|
6419
|
+
this.setCurrentSessionId = setCurrentSessionId;
|
|
6420
|
+
this.sessionFactory = sessionFactory;
|
|
6421
|
+
this.mappingState = createKimiSdkEventMappingState(ctx.config.sessionId || null);
|
|
6422
|
+
}
|
|
6423
|
+
descriptor = KIMI_SDK_RUNTIME_SESSION_DESCRIPTOR;
|
|
6424
|
+
events = new EventEmitter();
|
|
6425
|
+
mappingState;
|
|
6426
|
+
harness = null;
|
|
6427
|
+
session = null;
|
|
6428
|
+
wrapperPath = null;
|
|
6429
|
+
unsubscribe = null;
|
|
6430
|
+
started = false;
|
|
6431
|
+
didClose = false;
|
|
6432
|
+
requestedStopReason;
|
|
6433
|
+
exitInfo = null;
|
|
6434
|
+
get pid() {
|
|
6435
|
+
return void 0;
|
|
6436
|
+
}
|
|
6437
|
+
get currentSessionId() {
|
|
6438
|
+
return this.mappingState.sessionId;
|
|
6439
|
+
}
|
|
6440
|
+
get exitCode() {
|
|
6441
|
+
return this.exitInfo?.code ?? null;
|
|
6442
|
+
}
|
|
6443
|
+
get signalCode() {
|
|
6444
|
+
return this.exitInfo?.signal ?? null;
|
|
6445
|
+
}
|
|
6446
|
+
get closed() {
|
|
6447
|
+
return this.didClose;
|
|
6448
|
+
}
|
|
6449
|
+
on(event, cb) {
|
|
6450
|
+
this.events.on(event, cb);
|
|
6451
|
+
}
|
|
6452
|
+
async start(input) {
|
|
6453
|
+
if (this.started) {
|
|
6454
|
+
return { ok: false, reason: "runtime_error", error: "runtime session already started" };
|
|
6455
|
+
}
|
|
6456
|
+
if (this.didClose) return { ok: false, reason: "closed" };
|
|
6457
|
+
this.started = true;
|
|
6458
|
+
const sessionId = input.sessionId || this.ctx.config.sessionId || randomUUID3();
|
|
6459
|
+
this.mappingState.sessionId = sessionId;
|
|
6460
|
+
this.setCurrentSessionId(sessionId);
|
|
6461
|
+
const { harness, session, wrapperPath } = await this.sessionFactory(
|
|
6462
|
+
{
|
|
6463
|
+
...this.ctx,
|
|
6464
|
+
config: {
|
|
6465
|
+
...this.ctx.config,
|
|
6466
|
+
sessionId
|
|
6467
|
+
}
|
|
6468
|
+
},
|
|
6469
|
+
sessionId
|
|
6470
|
+
);
|
|
6471
|
+
this.harness = harness;
|
|
6472
|
+
this.session = session;
|
|
6473
|
+
this.wrapperPath = wrapperPath;
|
|
6474
|
+
this.mappingState.sessionId = session.id;
|
|
6475
|
+
this.setCurrentSessionId(session.id);
|
|
6476
|
+
session.setApprovalHandler(() => ({ decision: "approved", scope: "session" }));
|
|
6477
|
+
this.unsubscribe = session.onEvent((event) => {
|
|
6478
|
+
for (const parsed of mapKimiSdkEventToParsedEvents(event, this.mappingState)) {
|
|
6479
|
+
this.events.emit("runtime_event", parsed);
|
|
6480
|
+
}
|
|
6481
|
+
});
|
|
6482
|
+
this.emitSessionInit();
|
|
6483
|
+
const firstTurnText = this.composeFirstTurnPreamble(input.text);
|
|
6484
|
+
this.launchPrompt(firstTurnText);
|
|
6485
|
+
return { ok: true, acceptedAs: "prompt" };
|
|
6486
|
+
}
|
|
6487
|
+
composeFirstTurnPreamble(turnText) {
|
|
6488
|
+
const sections = [];
|
|
6489
|
+
if (this.ctx.standingPrompt) {
|
|
6490
|
+
sections.push(this.ctx.standingPrompt);
|
|
6491
|
+
}
|
|
6492
|
+
if (this.wrapperPath) {
|
|
6493
|
+
sections.push(
|
|
6494
|
+
`## CLI invocation note (Kimi SDK in-process runtime)
|
|
6495
|
+
|
|
6496
|
+
When you run \`raft\` CLI commands from your bash tool, **use this absolute path** because PATH is not pre-injected for the in-process Kimi SDK:
|
|
6497
|
+
|
|
6498
|
+
\`\`\`
|
|
6499
|
+
${this.wrapperPath}
|
|
6500
|
+
\`\`\`
|
|
6501
|
+
|
|
6502
|
+
So instead of \`raft message send ...\`, run \`${this.wrapperPath} message send ...\` (every \`raft\` reference in the protocol above maps to this wrapper). The wrapper carries this agent's identity automatically; do not pass auth tokens explicitly.`
|
|
6503
|
+
);
|
|
6504
|
+
}
|
|
6505
|
+
sections.push(turnText);
|
|
6506
|
+
return sections.join("\n\n---\n\n");
|
|
6507
|
+
}
|
|
6508
|
+
send(input) {
|
|
6509
|
+
if (this.didClose) return { ok: false, reason: "closed" };
|
|
6510
|
+
const session = this.session;
|
|
6511
|
+
if (!session) return { ok: false, reason: "closed" };
|
|
6512
|
+
if (input.mode === "busy") {
|
|
6513
|
+
this.deferSdkCall(() => session.steer(input.text));
|
|
6514
|
+
return { ok: true, acceptedAs: "steer" };
|
|
6515
|
+
}
|
|
6516
|
+
this.launchPrompt(input.text);
|
|
6517
|
+
return { ok: true, acceptedAs: "prompt" };
|
|
6518
|
+
}
|
|
6519
|
+
async stop(opts) {
|
|
6520
|
+
if (this.didClose) return;
|
|
6521
|
+
this.requestedStopReason = opts?.reason;
|
|
6522
|
+
const signal = opts?.signal ?? "SIGTERM";
|
|
6523
|
+
const session = this.session;
|
|
6524
|
+
if (session) {
|
|
6525
|
+
try {
|
|
6526
|
+
await session.cancel();
|
|
6527
|
+
} catch (error) {
|
|
6528
|
+
this.events.emit("stderr", kimiErrorMessage(error));
|
|
6529
|
+
}
|
|
6530
|
+
}
|
|
6531
|
+
await this.disposeSession();
|
|
6532
|
+
this.emitExitAndClose(null, signal);
|
|
6533
|
+
}
|
|
6534
|
+
async dispose() {
|
|
6535
|
+
if (this.didClose) return;
|
|
6536
|
+
await this.disposeSession();
|
|
6537
|
+
this.emitExitAndClose(0, null);
|
|
6538
|
+
}
|
|
6539
|
+
emitSessionInit() {
|
|
6540
|
+
const sessionId = this.mappingState.sessionId;
|
|
6541
|
+
if (!sessionId || this.mappingState.sessionAnnounced) return;
|
|
6542
|
+
this.mappingState.sessionAnnounced = true;
|
|
6543
|
+
this.events.emit("runtime_event", { kind: "session_init", sessionId });
|
|
6544
|
+
}
|
|
6545
|
+
launchPrompt(text) {
|
|
6546
|
+
const session = this.session;
|
|
6547
|
+
if (!session) {
|
|
6548
|
+
this.events.emit("runtime_event", {
|
|
6549
|
+
kind: "error",
|
|
6550
|
+
message: "Kimi SDK session is not started"
|
|
6551
|
+
});
|
|
6552
|
+
return;
|
|
6553
|
+
}
|
|
6554
|
+
this.deferSdkCall(() => session.prompt(text));
|
|
6555
|
+
}
|
|
6556
|
+
deferSdkCall(invoke) {
|
|
6557
|
+
setImmediate(() => {
|
|
6558
|
+
if (this.didClose) return;
|
|
6559
|
+
try {
|
|
6560
|
+
void invoke().catch((error) => {
|
|
6561
|
+
if (this.didClose) return;
|
|
6562
|
+
this.events.emit("runtime_event", {
|
|
6563
|
+
kind: "error",
|
|
6564
|
+
message: kimiErrorMessage(error)
|
|
6565
|
+
});
|
|
6566
|
+
});
|
|
6567
|
+
} catch (error) {
|
|
6568
|
+
if (this.didClose) return;
|
|
6569
|
+
this.events.emit("runtime_event", {
|
|
6570
|
+
kind: "error",
|
|
6571
|
+
message: kimiErrorMessage(error)
|
|
6572
|
+
});
|
|
6573
|
+
}
|
|
6574
|
+
});
|
|
6575
|
+
}
|
|
6576
|
+
async disposeSession() {
|
|
6577
|
+
const unsubscribe = this.unsubscribe;
|
|
6578
|
+
this.unsubscribe = null;
|
|
6579
|
+
try {
|
|
6580
|
+
unsubscribe?.();
|
|
6581
|
+
} catch {
|
|
6582
|
+
}
|
|
6583
|
+
const session = this.session;
|
|
6584
|
+
this.session = null;
|
|
6585
|
+
try {
|
|
6586
|
+
await session?.close();
|
|
6587
|
+
} catch (error) {
|
|
6588
|
+
this.events.emit("stderr", kimiErrorMessage(error));
|
|
6589
|
+
}
|
|
6590
|
+
const harness = this.harness;
|
|
6591
|
+
this.harness = null;
|
|
6592
|
+
try {
|
|
6593
|
+
await harness?.close();
|
|
6594
|
+
} catch (error) {
|
|
6595
|
+
this.events.emit("stderr", kimiErrorMessage(error));
|
|
6596
|
+
}
|
|
6597
|
+
}
|
|
6598
|
+
emitExitAndClose(code, signal) {
|
|
6599
|
+
if (this.didClose) return;
|
|
6600
|
+
this.didClose = true;
|
|
6601
|
+
const info = {
|
|
6602
|
+
code,
|
|
6603
|
+
signal,
|
|
6604
|
+
reason: this.requestedStopReason ? "requested" : "runtime_exit"
|
|
6605
|
+
};
|
|
6606
|
+
this.exitInfo = info;
|
|
6607
|
+
this.events.emit("exit", info);
|
|
6608
|
+
this.events.emit("close", info);
|
|
6609
|
+
}
|
|
6610
|
+
};
|
|
6611
|
+
var KIMI_SDK_DEFAULT_MODELS = [
|
|
6612
|
+
// Canonical Kimi Code SDK model (matches the `default_model` upstream
|
|
6613
|
+
// ships in `~/.kimi/config.toml` after `kimi login`). Mirrored as the first
|
|
6614
|
+
// entry in `RUNTIME_MODELS["kimi-sdk"]` (packages/shared/src/index.ts) so
|
|
6615
|
+
// both the daemon's launch resolution and the web's getDefaultModel agree.
|
|
6616
|
+
{ id: "kimi-code/kimi-for-coding", label: "Kimi-K2.6 (Kimi for Coding)", verified: "launchable" },
|
|
6617
|
+
{ id: "kimi-k2-0905-preview", label: "Kimi K2 (preview)", verified: "suggestion_only" }
|
|
6618
|
+
];
|
|
6619
|
+
function detectKimiSdkModels() {
|
|
6620
|
+
return { models: KIMI_SDK_DEFAULT_MODELS };
|
|
6621
|
+
}
|
|
6622
|
+
var KimiSdkDriver = class {
|
|
6623
|
+
id = "kimi-sdk";
|
|
6624
|
+
supportsNativeStandingPrompt = true;
|
|
6625
|
+
lifecycle = {
|
|
6626
|
+
kind: "persistent",
|
|
6627
|
+
stdin: "direct",
|
|
6628
|
+
inFlightWake: "steer"
|
|
6629
|
+
};
|
|
6630
|
+
communication = {
|
|
6631
|
+
chat: "slock_cli",
|
|
6632
|
+
runtimeControl: "none"
|
|
6633
|
+
};
|
|
6634
|
+
session = {
|
|
6635
|
+
recovery: "resume_or_fresh"
|
|
6636
|
+
};
|
|
6637
|
+
model = {
|
|
6638
|
+
detectedModelsVerifiedAs: "suggestion_only",
|
|
6639
|
+
toLaunchSpec: (modelId) => ({ params: { model: modelId } })
|
|
6640
|
+
};
|
|
6641
|
+
supportsStdinNotification = true;
|
|
6642
|
+
busyDeliveryMode = "direct";
|
|
6643
|
+
sessionId = null;
|
|
6644
|
+
get currentSessionId() {
|
|
6645
|
+
return this.sessionId;
|
|
6646
|
+
}
|
|
6647
|
+
probe() {
|
|
6648
|
+
return { available: true };
|
|
6649
|
+
}
|
|
6650
|
+
async detectModels() {
|
|
6651
|
+
return detectKimiSdkModels();
|
|
6652
|
+
}
|
|
6653
|
+
createSession(ctx) {
|
|
6654
|
+
this.sessionId = ctx.config.sessionId || null;
|
|
6655
|
+
return new KimiSdkRuntimeSession(ctx, (sessionId) => {
|
|
6656
|
+
this.sessionId = sessionId;
|
|
6657
|
+
});
|
|
6658
|
+
}
|
|
6659
|
+
async spawn(_ctx) {
|
|
6660
|
+
throw new Error("KimiSdkDriver uses a native RuntimeSession; child-process spawn is unsupported");
|
|
6661
|
+
}
|
|
6662
|
+
parseLine(_line) {
|
|
6663
|
+
return [];
|
|
6664
|
+
}
|
|
6665
|
+
encodeStdinMessage(_text, _sessionId, _opts) {
|
|
6666
|
+
return null;
|
|
6667
|
+
}
|
|
6668
|
+
buildSystemPrompt(config, _agentId) {
|
|
6669
|
+
return buildCliTransportSystemPrompt(config, {
|
|
6670
|
+
extraCriticalRules: [],
|
|
6671
|
+
postStartupNotes: [
|
|
6672
|
+
"**Kimi SDK runtime note:** Slock keeps Kimi running as a persistent SDK session. While you are working, Slock may send inbox-count notifications into the current turn; call `raft message check` at natural breakpoints."
|
|
6673
|
+
],
|
|
6674
|
+
includeStdinNotificationSection: true,
|
|
6675
|
+
messageNotificationStyle: "direct"
|
|
6676
|
+
});
|
|
6677
|
+
}
|
|
6678
|
+
};
|
|
6679
|
+
|
|
6322
6680
|
// src/drivers/opencode.ts
|
|
6323
6681
|
import { spawn as spawn8, spawnSync as spawnSync2 } from "child_process";
|
|
6324
6682
|
import { existsSync as existsSync8, readFileSync as readFileSync4 } from "fs";
|
|
6325
6683
|
import os5 from "os";
|
|
6326
|
-
import
|
|
6684
|
+
import path10 from "path";
|
|
6327
6685
|
var SLOCK_AGENT_NAME = "slock";
|
|
6328
6686
|
var NO_MESSAGE_PROMPT = "No new messages are pending. Stop now.";
|
|
6329
6687
|
var FIRST_MESSAGE_TASK_PREFIX = "First message task (system-triggered):";
|
|
@@ -6352,7 +6710,7 @@ function parseUserOpenCodeConfig(ctx) {
|
|
|
6352
6710
|
return parseOpenCodeConfigContent(raw);
|
|
6353
6711
|
}
|
|
6354
6712
|
function readLocalOpenCodeConfig(home = os5.homedir()) {
|
|
6355
|
-
const configPath =
|
|
6713
|
+
const configPath = path10.join(home, ".config", "opencode", "opencode.json");
|
|
6356
6714
|
try {
|
|
6357
6715
|
return parseOpenCodeConfigContent(readFileSync4(configPath, "utf8"));
|
|
6358
6716
|
} catch {
|
|
@@ -6538,7 +6896,7 @@ function runOpenCodeModelsCommand(home, deps = {}) {
|
|
|
6538
6896
|
const platform = deps.platform ?? process.platform;
|
|
6539
6897
|
const spawnSyncFn = deps.spawnSyncFn ?? spawnSync2;
|
|
6540
6898
|
const result = spawnSyncFn("opencode", ["models"], {
|
|
6541
|
-
env:
|
|
6899
|
+
env: { ...process.env, HOME: home, FORCE_COLOR: "0", NO_COLOR: "1" },
|
|
6542
6900
|
encoding: "utf8",
|
|
6543
6901
|
timeout: 5e3,
|
|
6544
6902
|
shell: platform === "win32"
|
|
@@ -6550,11 +6908,11 @@ function runOpenCodeModelsCommand(home, deps = {}) {
|
|
|
6550
6908
|
};
|
|
6551
6909
|
}
|
|
6552
6910
|
function isWindowsCommandShim(commandPath) {
|
|
6553
|
-
const ext =
|
|
6911
|
+
const ext = path10.win32.extname(commandPath).toLowerCase();
|
|
6554
6912
|
return ext === ".cmd" || ext === ".bat";
|
|
6555
6913
|
}
|
|
6556
6914
|
function opencodePackageEntryCandidates(packageRoot) {
|
|
6557
|
-
const winPath =
|
|
6915
|
+
const winPath = path10.win32;
|
|
6558
6916
|
return [
|
|
6559
6917
|
winPath.join(packageRoot, "bin", "opencode.exe"),
|
|
6560
6918
|
winPath.join(packageRoot, "bin", "opencode.js"),
|
|
@@ -6563,7 +6921,7 @@ function opencodePackageEntryCandidates(packageRoot) {
|
|
|
6563
6921
|
];
|
|
6564
6922
|
}
|
|
6565
6923
|
function openCodeSpecForEntry(entry, commandArgs) {
|
|
6566
|
-
if (
|
|
6924
|
+
if (path10.win32.extname(entry).toLowerCase() === ".exe") {
|
|
6567
6925
|
return { command: entry, args: commandArgs, shell: false };
|
|
6568
6926
|
}
|
|
6569
6927
|
return { command: process.execPath, args: [entry, ...commandArgs], shell: false };
|
|
@@ -6572,7 +6930,7 @@ function resolveWindowsOpenCodePackageEntry(commandPath, deps = {}) {
|
|
|
6572
6930
|
const existsSyncFn = deps.existsSyncFn ?? existsSync8;
|
|
6573
6931
|
const execFileSyncFn = deps.execFileSyncFn;
|
|
6574
6932
|
const env = deps.env ?? process.env;
|
|
6575
|
-
const winPath =
|
|
6933
|
+
const winPath = path10.win32;
|
|
6576
6934
|
const candidates = [];
|
|
6577
6935
|
if (execFileSyncFn) {
|
|
6578
6936
|
try {
|
|
@@ -6600,7 +6958,7 @@ function resolveWindowsOpenCodePackageEntry(commandPath, deps = {}) {
|
|
|
6600
6958
|
function extractWindowsShimTargets(commandPath, deps = {}) {
|
|
6601
6959
|
if (!isWindowsCommandShim(commandPath)) return [];
|
|
6602
6960
|
const readFileSyncFn = deps.readFileSyncFn ?? readFileSync4;
|
|
6603
|
-
const commandDir =
|
|
6961
|
+
const commandDir = path10.win32.dirname(commandPath);
|
|
6604
6962
|
let raw;
|
|
6605
6963
|
try {
|
|
6606
6964
|
raw = String(readFileSyncFn(commandPath, "utf8"));
|
|
@@ -6611,7 +6969,7 @@ function extractWindowsShimTargets(commandPath, deps = {}) {
|
|
|
6611
6969
|
const dp0Pattern = /%~dp0\\?([^"\r\n]*?opencode\.(?:exe|js|mjs|cjs))/gi;
|
|
6612
6970
|
for (const match of raw.matchAll(dp0Pattern)) {
|
|
6613
6971
|
const relative = match[1]?.replace(/^\\+/, "");
|
|
6614
|
-
if (relative) candidates.push(
|
|
6972
|
+
if (relative) candidates.push(path10.win32.normalize(path10.win32.join(commandDir, relative)));
|
|
6615
6973
|
}
|
|
6616
6974
|
return candidates;
|
|
6617
6975
|
}
|
|
@@ -6625,7 +6983,7 @@ function resolveOpenCodeSpawn(commandArgs, deps = {}) {
|
|
|
6625
6983
|
};
|
|
6626
6984
|
}
|
|
6627
6985
|
const command = resolveCommandOnPath("opencode", deps);
|
|
6628
|
-
if (command &&
|
|
6986
|
+
if (command && path10.win32.extname(command).toLowerCase() === ".exe") {
|
|
6629
6987
|
return { command, args: commandArgs, shell: false };
|
|
6630
6988
|
}
|
|
6631
6989
|
const packageEntry = resolveWindowsOpenCodePackageEntry(command, deps);
|
|
@@ -6795,10 +7153,10 @@ var OpenCodeDriver = class {
|
|
|
6795
7153
|
};
|
|
6796
7154
|
|
|
6797
7155
|
// src/drivers/pi.ts
|
|
6798
|
-
import { randomUUID as
|
|
6799
|
-
import { EventEmitter } from "events";
|
|
6800
|
-
import { mkdirSync as
|
|
6801
|
-
import
|
|
7156
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
7157
|
+
import { EventEmitter as EventEmitter2 } from "events";
|
|
7158
|
+
import { mkdirSync as mkdirSync4, readdirSync as readdirSync2 } from "fs";
|
|
7159
|
+
import path11 from "path";
|
|
6802
7160
|
import {
|
|
6803
7161
|
AuthStorage,
|
|
6804
7162
|
createBashTool,
|
|
@@ -6824,7 +7182,7 @@ function createPiSdkEventMappingState(sessionId = null) {
|
|
|
6824
7182
|
};
|
|
6825
7183
|
}
|
|
6826
7184
|
function buildPiSessionDir(workingDirectory) {
|
|
6827
|
-
return
|
|
7185
|
+
return path11.join(workingDirectory, PI_SESSION_DIR);
|
|
6828
7186
|
}
|
|
6829
7187
|
async function buildPiSpawnEnv(ctx) {
|
|
6830
7188
|
return (await prepareCliTransport(ctx, { NO_COLOR: "1" })).spawnEnv;
|
|
@@ -6846,7 +7204,7 @@ function findPiSessionFile(sessionDir, sessionId) {
|
|
|
6846
7204
|
}
|
|
6847
7205
|
const suffix = `_${sessionId}.jsonl`;
|
|
6848
7206
|
const match = entries.find((entry) => entry.endsWith(suffix));
|
|
6849
|
-
return match ?
|
|
7207
|
+
return match ? path11.join(sessionDir, match) : null;
|
|
6850
7208
|
}
|
|
6851
7209
|
function detectPiModelsFromRegistry(modelRegistry) {
|
|
6852
7210
|
const models = [];
|
|
@@ -6959,7 +7317,7 @@ function piErrorMessage(error) {
|
|
|
6959
7317
|
}
|
|
6960
7318
|
return "Unknown Pi error";
|
|
6961
7319
|
}
|
|
6962
|
-
function
|
|
7320
|
+
function pushSessionInitIfNeeded2(state, events) {
|
|
6963
7321
|
if (!state.sessionAnnounced && state.sessionId) {
|
|
6964
7322
|
events.push({ kind: "session_init", sessionId: state.sessionId });
|
|
6965
7323
|
state.sessionAnnounced = true;
|
|
@@ -6996,7 +7354,7 @@ function mapPiAssistantMessageEvent(assistantEvent, state) {
|
|
|
6996
7354
|
}
|
|
6997
7355
|
function mapPiSdkEventToParsedEvents(event, state) {
|
|
6998
7356
|
const events = [];
|
|
6999
|
-
|
|
7357
|
+
pushSessionInitIfNeeded2(state, events);
|
|
7000
7358
|
switch (event.type) {
|
|
7001
7359
|
case "agent_start":
|
|
7002
7360
|
case "turn_start":
|
|
@@ -7061,7 +7419,7 @@ var PI_IDLE_PROMPT_RETRY_MS = 25;
|
|
|
7061
7419
|
var PI_IDLE_PROMPT_MAX_WAIT_MS = 1e3;
|
|
7062
7420
|
async function createPiAgentSessionForContext(ctx, sessionId) {
|
|
7063
7421
|
const sessionDir = buildPiSessionDir(ctx.workingDirectory);
|
|
7064
|
-
|
|
7422
|
+
mkdirSync4(sessionDir, { recursive: true });
|
|
7065
7423
|
const launchRuntimeFields = runtimeConfigToLaunchFields(ctx.config);
|
|
7066
7424
|
const requestedModel = launchRuntimeFields.model || "default";
|
|
7067
7425
|
const traceSpan = ctx.tracer?.startSpan("daemon.pi.session.create", {
|
|
@@ -7079,7 +7437,7 @@ async function createPiAgentSessionForContext(ctx, sessionId) {
|
|
|
7079
7437
|
try {
|
|
7080
7438
|
const spawnEnv = await buildPiSpawnEnv(ctx);
|
|
7081
7439
|
const agentDir = spawnEnv.PI_CODING_AGENT_DIR || getAgentDir();
|
|
7082
|
-
const authStorage = AuthStorage.create(
|
|
7440
|
+
const authStorage = AuthStorage.create(path11.join(agentDir, "auth.json"));
|
|
7083
7441
|
const settingsManager = SettingsManager.create(ctx.workingDirectory, agentDir);
|
|
7084
7442
|
const services = await createAgentSessionServices({
|
|
7085
7443
|
cwd: ctx.workingDirectory,
|
|
@@ -7191,7 +7549,7 @@ var PiSdkRuntimeSession = class {
|
|
|
7191
7549
|
this.mappingState = createPiSdkEventMappingState(ctx.config.sessionId || null);
|
|
7192
7550
|
}
|
|
7193
7551
|
descriptor = PI_RUNTIME_SESSION_DESCRIPTOR;
|
|
7194
|
-
events = new
|
|
7552
|
+
events = new EventEmitter2();
|
|
7195
7553
|
mappingState;
|
|
7196
7554
|
session = null;
|
|
7197
7555
|
unsubscribe = null;
|
|
@@ -7223,7 +7581,7 @@ var PiSdkRuntimeSession = class {
|
|
|
7223
7581
|
}
|
|
7224
7582
|
if (this.didClose) return { ok: false, reason: "closed" };
|
|
7225
7583
|
this.started = true;
|
|
7226
|
-
const sessionId = input.sessionId || this.ctx.config.sessionId ||
|
|
7584
|
+
const sessionId = input.sessionId || this.ctx.config.sessionId || randomUUID4();
|
|
7227
7585
|
this.mappingState.sessionId = sessionId;
|
|
7228
7586
|
this.setCurrentSessionId(sessionId);
|
|
7229
7587
|
const session = await this.sessionFactory({
|
|
@@ -7434,7 +7792,7 @@ function delay(ms) {
|
|
|
7434
7792
|
}
|
|
7435
7793
|
|
|
7436
7794
|
// src/drivers/runtimeSession.ts
|
|
7437
|
-
import { EventEmitter as
|
|
7795
|
+
import { EventEmitter as EventEmitter3 } from "events";
|
|
7438
7796
|
function descriptorFromDriver(driver) {
|
|
7439
7797
|
const lifecycle = driver.lifecycle.kind === "per_turn" ? "turn_based" : "persistent_stream";
|
|
7440
7798
|
const idle = driver.supportsStdinNotification ? "stdin" : "unsupported";
|
|
@@ -7462,7 +7820,7 @@ var ChildProcessRuntimeSession = class {
|
|
|
7462
7820
|
this.descriptor = descriptorFromDriver(driver);
|
|
7463
7821
|
}
|
|
7464
7822
|
descriptor;
|
|
7465
|
-
events = new
|
|
7823
|
+
events = new EventEmitter3();
|
|
7466
7824
|
process = null;
|
|
7467
7825
|
started = false;
|
|
7468
7826
|
stdoutBuffer = "";
|
|
@@ -7575,7 +7933,13 @@ var driverFactories = {
|
|
|
7575
7933
|
copilot: () => new CopilotDriver(),
|
|
7576
7934
|
cursor: () => new CursorDriver(),
|
|
7577
7935
|
gemini: () => new GeminiDriver(),
|
|
7936
|
+
// Two separate Kimi runtimes (per #proj-runtime:cc818e65 6/16 consensus):
|
|
7937
|
+
// - `kimi` = legacy kimi-cli child-process driver. Backward-compat for
|
|
7938
|
+
// existing `runtime=kimi` agents. Frontend marks deprecated.
|
|
7939
|
+
// - `kimi-sdk` = canonical in-process SDK driver. Frontend label "Kimi Code".
|
|
7940
|
+
// No alias / no auto-migration; explicit pick at agent-create time.
|
|
7578
7941
|
kimi: () => new KimiDriver(),
|
|
7942
|
+
"kimi-sdk": () => new KimiSdkDriver(),
|
|
7579
7943
|
opencode: () => new OpenCodeDriver(),
|
|
7580
7944
|
pi: () => new PiDriver()
|
|
7581
7945
|
};
|
|
@@ -7590,7 +7954,7 @@ function getDriver(runtimeId) {
|
|
|
7590
7954
|
|
|
7591
7955
|
// src/workspaces.ts
|
|
7592
7956
|
import { readdir, rm, stat } from "fs/promises";
|
|
7593
|
-
import
|
|
7957
|
+
import path12 from "path";
|
|
7594
7958
|
function isValidWorkspaceDirectoryName(directoryName) {
|
|
7595
7959
|
return !directoryName.includes("/") && !directoryName.includes("\\") && !directoryName.includes("..");
|
|
7596
7960
|
}
|
|
@@ -7598,7 +7962,7 @@ function resolveWorkspaceDirectoryPath(dataDir, directoryName) {
|
|
|
7598
7962
|
if (!isValidWorkspaceDirectoryName(directoryName)) {
|
|
7599
7963
|
return null;
|
|
7600
7964
|
}
|
|
7601
|
-
return
|
|
7965
|
+
return path12.join(dataDir, directoryName);
|
|
7602
7966
|
}
|
|
7603
7967
|
function emptyWorkspaceDirectorySummary(latestMtime = /* @__PURE__ */ new Date(0)) {
|
|
7604
7968
|
return {
|
|
@@ -7647,7 +8011,7 @@ async function summarizeWorkspaceDirectory(dirPath) {
|
|
|
7647
8011
|
return summary;
|
|
7648
8012
|
}
|
|
7649
8013
|
const childSummaries = await Promise.all(
|
|
7650
|
-
entries.map((entry) => summarizeWorkspaceEntry(
|
|
8014
|
+
entries.map((entry) => summarizeWorkspaceEntry(path12.join(dirPath, entry.name), entry))
|
|
7651
8015
|
);
|
|
7652
8016
|
for (const childSummary of childSummaries) {
|
|
7653
8017
|
summary = mergeWorkspaceDirectorySummaries(summary, childSummary);
|
|
@@ -7666,7 +8030,7 @@ async function scanWorkspaceDirectories(dataDir) {
|
|
|
7666
8030
|
if (!entry.isDirectory()) {
|
|
7667
8031
|
return null;
|
|
7668
8032
|
}
|
|
7669
|
-
const dirPath =
|
|
8033
|
+
const dirPath = path12.join(dataDir, entry.name);
|
|
7670
8034
|
try {
|
|
7671
8035
|
const summary = await summarizeWorkspaceDirectory(dirPath);
|
|
7672
8036
|
return {
|
|
@@ -8217,12 +8581,12 @@ function findSessionJsonl(root, predicate) {
|
|
|
8217
8581
|
for (const entry of entries) {
|
|
8218
8582
|
if (++visited > maxEntries) return null;
|
|
8219
8583
|
if (!entry.isFile() || !predicate(entry.name)) continue;
|
|
8220
|
-
return
|
|
8584
|
+
return path13.join(dir, entry.name);
|
|
8221
8585
|
}
|
|
8222
8586
|
for (const entry of entries) {
|
|
8223
8587
|
if (++visited > maxEntries) return null;
|
|
8224
8588
|
if (!entry.isDirectory()) continue;
|
|
8225
|
-
const found = visit(
|
|
8589
|
+
const found = visit(path13.join(dir, entry.name), depth - 1);
|
|
8226
8590
|
if (found) return found;
|
|
8227
8591
|
}
|
|
8228
8592
|
return null;
|
|
@@ -8235,9 +8599,9 @@ function safeSessionFilename(value) {
|
|
|
8235
8599
|
}
|
|
8236
8600
|
function writeRuntimeSessionHandoff(runtime, sessionId, fallbackDir) {
|
|
8237
8601
|
try {
|
|
8238
|
-
const dir =
|
|
8239
|
-
|
|
8240
|
-
const filePath =
|
|
8602
|
+
const dir = path13.join(fallbackDir, ".slock", "runtime-sessions");
|
|
8603
|
+
mkdirSync5(dir, { recursive: true });
|
|
8604
|
+
const filePath = path13.join(dir, `${runtime}-${safeSessionFilename(sessionId)}.jsonl`);
|
|
8241
8605
|
writeFileSync4(filePath, JSON.stringify({
|
|
8242
8606
|
type: "runtime_session_handoff",
|
|
8243
8607
|
runtime,
|
|
@@ -8269,7 +8633,7 @@ function ensureRuntimeHomeDir(config, defaultHomeDir, workspacePath) {
|
|
|
8269
8633
|
return defaultHomeDir;
|
|
8270
8634
|
}
|
|
8271
8635
|
function resolveRuntimeSessionRef(runtime, sessionId, homeDir = os6.homedir(), fallbackDir) {
|
|
8272
|
-
const directPath =
|
|
8636
|
+
const directPath = path13.isAbsolute(sessionId) ? sessionId : null;
|
|
8273
8637
|
if (directPath) {
|
|
8274
8638
|
try {
|
|
8275
8639
|
if (statSync(directPath).isFile()) {
|
|
@@ -8278,7 +8642,7 @@ function resolveRuntimeSessionRef(runtime, sessionId, homeDir = os6.homedir(), f
|
|
|
8278
8642
|
} catch {
|
|
8279
8643
|
}
|
|
8280
8644
|
}
|
|
8281
|
-
const resolvedPath = runtime === "claude" ? findSessionJsonl(
|
|
8645
|
+
const resolvedPath = runtime === "claude" ? findSessionJsonl(path13.join(homeDir, ".claude", "projects"), (filename) => filename === `${sessionId}.jsonl`) : runtime === "codex" ? findSessionJsonl(path13.join(homeDir, ".codex", "sessions"), (filename) => filename.endsWith(".jsonl") && filename.includes(sessionId)) : null;
|
|
8282
8646
|
if (!resolvedPath && fallbackDir) {
|
|
8283
8647
|
const fallback = writeRuntimeSessionHandoff(runtime, sessionId, fallbackDir);
|
|
8284
8648
|
if (fallback) return fallback;
|
|
@@ -10229,7 +10593,7 @@ var AgentProcessManager = class _AgentProcessManager {
|
|
|
10229
10593
|
);
|
|
10230
10594
|
wakeMessage = void 0;
|
|
10231
10595
|
}
|
|
10232
|
-
const agentDataDir =
|
|
10596
|
+
const agentDataDir = path13.join(this.dataDir, agentId);
|
|
10233
10597
|
await mkdir(agentDataDir, { recursive: true });
|
|
10234
10598
|
let runtimeConfig = withLocalRuntimeContext(config, agentId, agentDataDir);
|
|
10235
10599
|
const legacyRuntimeProfileControl = runtimeConfig.runtimeProfileControl?.kind === "migration" ? runtimeConfig.runtimeProfileControl : null;
|
|
@@ -10243,23 +10607,23 @@ var AgentProcessManager = class _AgentProcessManager {
|
|
|
10243
10607
|
);
|
|
10244
10608
|
runtimeConfig = { ...runtimeConfig, runtimeProfileControl: null };
|
|
10245
10609
|
}
|
|
10246
|
-
const memoryMdPath =
|
|
10610
|
+
const memoryMdPath = path13.join(agentDataDir, "MEMORY.md");
|
|
10247
10611
|
try {
|
|
10248
10612
|
await access(memoryMdPath);
|
|
10249
10613
|
} catch {
|
|
10250
10614
|
const initialMemoryMd = buildInitialMemoryMd(runtimeConfig);
|
|
10251
10615
|
await writeFile(memoryMdPath, initialMemoryMd);
|
|
10252
10616
|
}
|
|
10253
|
-
const notesDir =
|
|
10617
|
+
const notesDir = path13.join(agentDataDir, "notes");
|
|
10254
10618
|
await mkdir(notesDir, { recursive: true });
|
|
10255
10619
|
if (getOnboardingSeedMode(config) === FIRST_CINDY_SEED_MODE) {
|
|
10256
10620
|
const seedFiles = buildOnboardingSeedFiles();
|
|
10257
10621
|
for (const { relativePath, content } of seedFiles) {
|
|
10258
|
-
const fullPath =
|
|
10622
|
+
const fullPath = path13.join(agentDataDir, relativePath);
|
|
10259
10623
|
try {
|
|
10260
10624
|
await access(fullPath);
|
|
10261
10625
|
} catch {
|
|
10262
|
-
await mkdir(
|
|
10626
|
+
await mkdir(path13.dirname(fullPath), { recursive: true });
|
|
10263
10627
|
await writeFile(fullPath, content);
|
|
10264
10628
|
}
|
|
10265
10629
|
}
|
|
@@ -11486,7 +11850,7 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
|
|
|
11486
11850
|
return true;
|
|
11487
11851
|
}
|
|
11488
11852
|
async resetWorkspace(agentId) {
|
|
11489
|
-
const agentDataDir =
|
|
11853
|
+
const agentDataDir = path13.join(this.dataDir, agentId);
|
|
11490
11854
|
try {
|
|
11491
11855
|
await rm2(agentDataDir, { recursive: true, force: true });
|
|
11492
11856
|
logger.info(`[Agent ${agentId}] Workspace reset complete (${agentDataDir})`);
|
|
@@ -11547,7 +11911,7 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
|
|
|
11547
11911
|
return result;
|
|
11548
11912
|
}
|
|
11549
11913
|
buildRuntimeProfileReport(agentId, config, sessionId, launchId) {
|
|
11550
|
-
const workspacePath =
|
|
11914
|
+
const workspacePath = path13.join(this.dataDir, agentId);
|
|
11551
11915
|
const runtimeHomeDir = resolveRuntimeHomeDir(config, this.runtimeSessionHomeDir, workspacePath);
|
|
11552
11916
|
return {
|
|
11553
11917
|
agentId,
|
|
@@ -11841,7 +12205,7 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
|
|
|
11841
12205
|
}
|
|
11842
12206
|
// Workspace file browsing
|
|
11843
12207
|
async getFileTree(agentId, dirPath) {
|
|
11844
|
-
const agentDir =
|
|
12208
|
+
const agentDir = path13.join(this.dataDir, agentId);
|
|
11845
12209
|
try {
|
|
11846
12210
|
await stat2(agentDir);
|
|
11847
12211
|
} catch {
|
|
@@ -11849,8 +12213,8 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
|
|
|
11849
12213
|
}
|
|
11850
12214
|
let targetDir = agentDir;
|
|
11851
12215
|
if (dirPath) {
|
|
11852
|
-
const resolved =
|
|
11853
|
-
if (!resolved.startsWith(agentDir +
|
|
12216
|
+
const resolved = path13.resolve(agentDir, dirPath);
|
|
12217
|
+
if (!resolved.startsWith(agentDir + path13.sep) && resolved !== agentDir) {
|
|
11854
12218
|
return [];
|
|
11855
12219
|
}
|
|
11856
12220
|
targetDir = resolved;
|
|
@@ -11858,14 +12222,14 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
|
|
|
11858
12222
|
return this.listDirectoryChildren(targetDir, agentDir);
|
|
11859
12223
|
}
|
|
11860
12224
|
async readFile(agentId, filePath) {
|
|
11861
|
-
const agentDir =
|
|
11862
|
-
const resolved =
|
|
11863
|
-
if (!resolved.startsWith(agentDir +
|
|
12225
|
+
const agentDir = path13.join(this.dataDir, agentId);
|
|
12226
|
+
const resolved = path13.resolve(agentDir, filePath);
|
|
12227
|
+
if (!resolved.startsWith(agentDir + path13.sep) && resolved !== agentDir) {
|
|
11864
12228
|
throw new Error("Access denied");
|
|
11865
12229
|
}
|
|
11866
12230
|
const info = await stat2(resolved);
|
|
11867
12231
|
if (info.isDirectory()) throw new Error("Cannot read a directory");
|
|
11868
|
-
const ext =
|
|
12232
|
+
const ext = path13.extname(resolved).toLowerCase();
|
|
11869
12233
|
if (WORKSPACE_TEXT_EXTENSIONS.has(ext) || ext === "") {
|
|
11870
12234
|
if (info.size > WORKSPACE_TEXT_FILE_MAX_BYTES) throw new Error("File too large");
|
|
11871
12235
|
const content = await readFile(resolved, "utf-8");
|
|
@@ -11901,14 +12265,14 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
|
|
|
11901
12265
|
const idle = this.idleAgentConfigs.get(agentId);
|
|
11902
12266
|
const config = agent?.config ?? idle?.config ?? null;
|
|
11903
12267
|
const runtime = runtimeHint || config?.runtime || "claude";
|
|
11904
|
-
const workspaceDir =
|
|
12268
|
+
const workspaceDir = path13.join(this.dataDir, agentId);
|
|
11905
12269
|
const home = config ? ensureRuntimeHomeDir(config, os6.homedir(), workspaceDir) : os6.homedir();
|
|
11906
12270
|
const paths = _AgentProcessManager.SKILL_PATHS[runtime] || _AgentProcessManager.SKILL_PATHS.claude;
|
|
11907
12271
|
const globalResults = await Promise.all(
|
|
11908
|
-
paths.global.map((p) => this.scanSkillsDir(
|
|
12272
|
+
paths.global.map((p) => this.scanSkillsDir(path13.join(home, p)))
|
|
11909
12273
|
);
|
|
11910
12274
|
const workspaceResults = await Promise.all(
|
|
11911
|
-
paths.workspace.map((p) => this.scanSkillsDir(
|
|
12275
|
+
paths.workspace.map((p) => this.scanSkillsDir(path13.join(workspaceDir, p)))
|
|
11912
12276
|
);
|
|
11913
12277
|
const dedup = (skills) => {
|
|
11914
12278
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -11937,7 +12301,7 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
|
|
|
11937
12301
|
const skills = [];
|
|
11938
12302
|
for (const entry of entries) {
|
|
11939
12303
|
if (entry.isDirectory() || entry.isSymbolicLink()) {
|
|
11940
|
-
const skillMd =
|
|
12304
|
+
const skillMd = path13.join(dir, entry.name, "SKILL.md");
|
|
11941
12305
|
try {
|
|
11942
12306
|
const content = await readFile(skillMd, "utf-8");
|
|
11943
12307
|
const skill = this.parseSkillMd(entry.name, content);
|
|
@@ -11948,7 +12312,7 @@ Use ${communicationCommand("read_history")} to catch up on the channels listed a
|
|
|
11948
12312
|
} else if (entry.name.endsWith(".md")) {
|
|
11949
12313
|
const cmdName = entry.name.replace(/\.md$/, "");
|
|
11950
12314
|
try {
|
|
11951
|
-
const content = await readFile(
|
|
12315
|
+
const content = await readFile(path13.join(dir, entry.name), "utf-8");
|
|
11952
12316
|
const skill = this.parseSkillMd(cmdName, content);
|
|
11953
12317
|
skill.sourcePath = dir;
|
|
11954
12318
|
skills.push(skill);
|
|
@@ -13428,8 +13792,8 @@ ${RESPONSE_TARGET_HINT}`);
|
|
|
13428
13792
|
const nodes = [];
|
|
13429
13793
|
for (const entry of entries) {
|
|
13430
13794
|
if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
|
|
13431
|
-
const fullPath =
|
|
13432
|
-
const relativePath =
|
|
13795
|
+
const fullPath = path13.join(dir, entry.name);
|
|
13796
|
+
const relativePath = path13.relative(rootDir, fullPath);
|
|
13433
13797
|
let info;
|
|
13434
13798
|
try {
|
|
13435
13799
|
info = await stat2(fullPath);
|
|
@@ -13802,10 +14166,10 @@ var ReminderCache = class {
|
|
|
13802
14166
|
};
|
|
13803
14167
|
|
|
13804
14168
|
// src/machineLock.ts
|
|
13805
|
-
import { createHash as createHash4, randomUUID as
|
|
13806
|
-
import { mkdirSync as
|
|
14169
|
+
import { createHash as createHash4, randomUUID as randomUUID5 } from "crypto";
|
|
14170
|
+
import { mkdirSync as mkdirSync6, readFileSync as readFileSync5, rmSync as rmSync3, statSync as statSync2, writeFileSync as writeFileSync5 } from "fs";
|
|
13807
14171
|
import os7 from "os";
|
|
13808
|
-
import
|
|
14172
|
+
import path14 from "path";
|
|
13809
14173
|
var INCOMPLETE_LOCK_STALE_MS = 3e4;
|
|
13810
14174
|
var DaemonMachineLockConflictError = class extends Error {
|
|
13811
14175
|
code = "DAEMON_MACHINE_LOCK_HELD";
|
|
@@ -13827,7 +14191,7 @@ function resolveDefaultMachineStateRoot() {
|
|
|
13827
14191
|
return resolveSlockHomePath("machines");
|
|
13828
14192
|
}
|
|
13829
14193
|
function ownerPath(lockDir) {
|
|
13830
|
-
return
|
|
14194
|
+
return path14.join(lockDir, "owner.json");
|
|
13831
14195
|
}
|
|
13832
14196
|
function readOwner(lockDir) {
|
|
13833
14197
|
try {
|
|
@@ -13857,13 +14221,13 @@ function acquireDaemonMachineLock(options) {
|
|
|
13857
14221
|
const rootDir = options.rootDir ?? resolveDefaultMachineStateRoot();
|
|
13858
14222
|
const fingerprint = apiKeyFingerprint(options.apiKey);
|
|
13859
14223
|
const lockId = getDaemonMachineLockId(options.apiKey);
|
|
13860
|
-
const machineDir =
|
|
13861
|
-
const lockDir =
|
|
13862
|
-
const token =
|
|
13863
|
-
|
|
14224
|
+
const machineDir = path14.join(rootDir, lockId);
|
|
14225
|
+
const lockDir = path14.join(machineDir, "daemon.lock");
|
|
14226
|
+
const token = randomUUID5();
|
|
14227
|
+
mkdirSync6(machineDir, { recursive: true });
|
|
13864
14228
|
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
13865
14229
|
try {
|
|
13866
|
-
|
|
14230
|
+
mkdirSync6(lockDir);
|
|
13867
14231
|
const owner = {
|
|
13868
14232
|
pid: process.pid,
|
|
13869
14233
|
token,
|
|
@@ -13918,8 +14282,8 @@ function acquireDaemonMachineLock(options) {
|
|
|
13918
14282
|
}
|
|
13919
14283
|
|
|
13920
14284
|
// src/localTraceSink.ts
|
|
13921
|
-
import { appendFileSync, mkdirSync as
|
|
13922
|
-
import
|
|
14285
|
+
import { appendFileSync, mkdirSync as mkdirSync7, readdirSync as readdirSync4, rmSync as rmSync4, statSync as statSync3, writeFileSync as writeFileSync6 } from "fs";
|
|
14286
|
+
import path15 from "path";
|
|
13923
14287
|
var DEFAULT_MAX_FILE_BYTES = 5 * 1024 * 1024;
|
|
13924
14288
|
var DEFAULT_MAX_FILE_AGE_MS = 5 * 60 * 1e3;
|
|
13925
14289
|
var DEFAULT_MAX_FILES = 8;
|
|
@@ -13956,7 +14320,7 @@ var LocalRotatingTraceSink = class {
|
|
|
13956
14320
|
currentSize = 0;
|
|
13957
14321
|
sequence = 0;
|
|
13958
14322
|
constructor(options) {
|
|
13959
|
-
this.traceDir =
|
|
14323
|
+
this.traceDir = path15.join(options.machineDir, "traces");
|
|
13960
14324
|
this.maxFileBytes = Math.max(1024, Math.floor(options.maxFileBytes ?? DEFAULT_MAX_FILE_BYTES));
|
|
13961
14325
|
const baseAgeMs = Math.max(1e3, Math.floor(options.maxFileAgeMs ?? DEFAULT_MAX_FILE_AGE_MS));
|
|
13962
14326
|
const ageJitterMs = Math.max(0, Math.floor(options.maxFileAgeJitterMs ?? 0));
|
|
@@ -13982,11 +14346,11 @@ var LocalRotatingTraceSink = class {
|
|
|
13982
14346
|
return this.currentFile;
|
|
13983
14347
|
}
|
|
13984
14348
|
ensureFile(nextBytes) {
|
|
13985
|
-
|
|
14349
|
+
mkdirSync7(this.traceDir, { recursive: true, mode: 448 });
|
|
13986
14350
|
const nowMs = this.nowMsProvider();
|
|
13987
14351
|
const shouldRotateForAge = this.currentFileOpenedAtMs !== null && nowMs - this.currentFileOpenedAtMs >= this.maxFileAgeMs;
|
|
13988
14352
|
if (!this.currentFile || this.currentSize + nextBytes > this.maxFileBytes || shouldRotateForAge) {
|
|
13989
|
-
this.currentFile =
|
|
14353
|
+
this.currentFile = path15.join(
|
|
13990
14354
|
this.traceDir,
|
|
13991
14355
|
`daemon-trace-${safeTimestamp(nowMs)}-${process.pid}-${String(this.sequence++).padStart(4, "0")}.jsonl`
|
|
13992
14356
|
);
|
|
@@ -14001,7 +14365,7 @@ var LocalRotatingTraceSink = class {
|
|
|
14001
14365
|
const excess = files.length - this.maxFiles;
|
|
14002
14366
|
if (excess <= 0) return;
|
|
14003
14367
|
for (const file of files.slice(0, excess)) {
|
|
14004
|
-
rmSync4(
|
|
14368
|
+
rmSync4(path15.join(this.traceDir, file), { force: true });
|
|
14005
14369
|
}
|
|
14006
14370
|
}
|
|
14007
14371
|
};
|
|
@@ -14089,10 +14453,10 @@ function isDiagnosticErrorAttr(key) {
|
|
|
14089
14453
|
}
|
|
14090
14454
|
|
|
14091
14455
|
// src/traceBundleUpload.ts
|
|
14092
|
-
import { createHash as createHash6, randomUUID as
|
|
14456
|
+
import { createHash as createHash6, randomUUID as randomUUID6 } from "crypto";
|
|
14093
14457
|
import { gzipSync } from "zlib";
|
|
14094
14458
|
import { mkdir as mkdir2, readFile as readFile2, readdir as readdir3, stat as stat3, writeFile as writeFile2 } from "fs/promises";
|
|
14095
|
-
import
|
|
14459
|
+
import path16 from "path";
|
|
14096
14460
|
|
|
14097
14461
|
// src/chatBridgeRequest.ts
|
|
14098
14462
|
var DEFAULT_CHAT_BRIDGE_TOOL_TIMEOUT_MS = Number.parseInt(
|
|
@@ -14192,8 +14556,8 @@ async function executeResponseRequest(url, init, {
|
|
|
14192
14556
|
}
|
|
14193
14557
|
|
|
14194
14558
|
// src/directUploadCapability.ts
|
|
14195
|
-
function joinUrl(base,
|
|
14196
|
-
return `${base.replace(/\/+$/, "")}${
|
|
14559
|
+
function joinUrl(base, path18) {
|
|
14560
|
+
return `${base.replace(/\/+$/, "")}${path18}`;
|
|
14197
14561
|
}
|
|
14198
14562
|
function jsonHeaders(apiKey) {
|
|
14199
14563
|
return {
|
|
@@ -14412,7 +14776,7 @@ var DaemonTraceBundleUploader = class {
|
|
|
14412
14776
|
}, nextMs);
|
|
14413
14777
|
}
|
|
14414
14778
|
async findUploadCandidates() {
|
|
14415
|
-
const traceDir =
|
|
14779
|
+
const traceDir = path16.join(this.options.machineDir, "traces");
|
|
14416
14780
|
let names;
|
|
14417
14781
|
try {
|
|
14418
14782
|
names = await readdir3(traceDir);
|
|
@@ -14424,8 +14788,8 @@ var DaemonTraceBundleUploader = class {
|
|
|
14424
14788
|
const currentFile = this.options.currentFileProvider?.();
|
|
14425
14789
|
const candidates = [];
|
|
14426
14790
|
for (const name of names.filter((entry) => entry.startsWith("daemon-trace-") && entry.endsWith(".jsonl")).sort()) {
|
|
14427
|
-
const file =
|
|
14428
|
-
if (currentFile &&
|
|
14791
|
+
const file = path16.join(traceDir, name);
|
|
14792
|
+
if (currentFile && path16.resolve(file) === path16.resolve(currentFile)) continue;
|
|
14429
14793
|
if (await this.isUploaded(file)) continue;
|
|
14430
14794
|
try {
|
|
14431
14795
|
const info = await stat3(file);
|
|
@@ -14457,7 +14821,7 @@ var DaemonTraceBundleUploader = class {
|
|
|
14457
14821
|
}
|
|
14458
14822
|
const gzipped = gzipSync(raw);
|
|
14459
14823
|
const bundleSha256 = sha256Hex(gzipped);
|
|
14460
|
-
const bundleId =
|
|
14824
|
+
const bundleId = randomUUID6();
|
|
14461
14825
|
await uploadWithSignedCapability({
|
|
14462
14826
|
serverUrl: this.options.serverUrl,
|
|
14463
14827
|
apiKey: this.options.apiKey,
|
|
@@ -14499,8 +14863,8 @@ var DaemonTraceBundleUploader = class {
|
|
|
14499
14863
|
}
|
|
14500
14864
|
}
|
|
14501
14865
|
uploadStatePath(file) {
|
|
14502
|
-
const stateDir =
|
|
14503
|
-
return
|
|
14866
|
+
const stateDir = path16.join(this.options.machineDir, "trace-uploads");
|
|
14867
|
+
return path16.join(stateDir, `${path16.basename(file)}.uploaded.json`);
|
|
14504
14868
|
}
|
|
14505
14869
|
async isUploaded(file) {
|
|
14506
14870
|
try {
|
|
@@ -14512,9 +14876,9 @@ var DaemonTraceBundleUploader = class {
|
|
|
14512
14876
|
}
|
|
14513
14877
|
async markUploaded(file, metadata) {
|
|
14514
14878
|
const stateFile = this.uploadStatePath(file);
|
|
14515
|
-
await mkdir2(
|
|
14879
|
+
await mkdir2(path16.dirname(stateFile), { recursive: true, mode: 448 });
|
|
14516
14880
|
await writeFile2(stateFile, `${JSON.stringify({
|
|
14517
|
-
file:
|
|
14881
|
+
file: path16.basename(file),
|
|
14518
14882
|
uploadedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
14519
14883
|
...metadata
|
|
14520
14884
|
}, null, 2)}
|
|
@@ -14599,7 +14963,7 @@ var DAEMON_CORE_TRACE_ATTR_CONTRACTS = {
|
|
|
14599
14963
|
spanAttrs: ["running_agents_count", "idle_agents_count"]
|
|
14600
14964
|
}
|
|
14601
14965
|
};
|
|
14602
|
-
var DAEMON_CLI_USAGE =
|
|
14966
|
+
var DAEMON_CLI_USAGE = "Usage: slock-daemon --server-url <url> --api-key <key>";
|
|
14603
14967
|
var RunnerCredentialMintError2 = class extends Error {
|
|
14604
14968
|
code;
|
|
14605
14969
|
retryable;
|
|
@@ -14635,9 +14999,9 @@ function runnerCredentialErrorDetail2(error) {
|
|
|
14635
14999
|
async function waitForRunnerCredentialRetry2() {
|
|
14636
15000
|
await new Promise((resolve) => setTimeout(resolve, RUNNER_CREDENTIAL_MINT_RETRY_DELAY_MS2));
|
|
14637
15001
|
}
|
|
14638
|
-
function parseDaemonCliArgs(args
|
|
15002
|
+
function parseDaemonCliArgs(args) {
|
|
14639
15003
|
let serverUrl = "";
|
|
14640
|
-
let apiKey =
|
|
15004
|
+
let apiKey = "";
|
|
14641
15005
|
for (let i = 0; i < args.length; i++) {
|
|
14642
15006
|
if (args[i] === "--server-url" && args[i + 1]) serverUrl = args[++i];
|
|
14643
15007
|
if (args[i] === "--api-key" && args[i + 1]) apiKey = args[++i];
|
|
@@ -14647,20 +15011,20 @@ function parseDaemonCliArgs(args, env = {}) {
|
|
|
14647
15011
|
}
|
|
14648
15012
|
function readDaemonVersion(moduleUrl = import.meta.url) {
|
|
14649
15013
|
try {
|
|
14650
|
-
const require2 =
|
|
15014
|
+
const require2 = createRequire3(moduleUrl);
|
|
14651
15015
|
return require2("../package.json").version;
|
|
14652
15016
|
} catch {
|
|
14653
15017
|
return "0.0.0-dev";
|
|
14654
15018
|
}
|
|
14655
15019
|
}
|
|
14656
15020
|
function resolveSlockCliPath(moduleUrl = import.meta.url) {
|
|
14657
|
-
const thisDir =
|
|
14658
|
-
const bundledDistPath =
|
|
15021
|
+
const thisDir = path17.dirname(fileURLToPath(moduleUrl));
|
|
15022
|
+
const bundledDistPath = path17.resolve(thisDir, "cli", "index.js");
|
|
14659
15023
|
try {
|
|
14660
15024
|
accessSync(bundledDistPath);
|
|
14661
15025
|
return bundledDistPath;
|
|
14662
15026
|
} catch {
|
|
14663
|
-
const workspaceDistPath =
|
|
15027
|
+
const workspaceDistPath = path17.resolve(thisDir, "..", "..", "cli", "dist", "index.js");
|
|
14664
15028
|
accessSync(workspaceDistPath);
|
|
14665
15029
|
return workspaceDistPath;
|
|
14666
15030
|
}
|
|
@@ -14674,7 +15038,7 @@ function resolveSlockCliPathOrEmpty(moduleUrl = import.meta.url) {
|
|
|
14674
15038
|
}
|
|
14675
15039
|
async function runBundledSlockCli(argv) {
|
|
14676
15040
|
process.argv = [process.execPath, "slock", ...argv];
|
|
14677
|
-
await import("./dist-
|
|
15041
|
+
await import("./dist-6YUWBDWX.js");
|
|
14678
15042
|
}
|
|
14679
15043
|
function detectRuntimes(tracer = noopTracer) {
|
|
14680
15044
|
const ids = [];
|
|
@@ -14866,7 +15230,7 @@ var DaemonCore = class {
|
|
|
14866
15230
|
}
|
|
14867
15231
|
resolveMachineStateRoot() {
|
|
14868
15232
|
if (this.options.machineStateDir) return this.options.machineStateDir;
|
|
14869
|
-
if (this.options.dataDir) return
|
|
15233
|
+
if (this.options.dataDir) return path17.join(path17.dirname(this.options.dataDir), "machines");
|
|
14870
15234
|
return resolveDefaultMachineStateRoot();
|
|
14871
15235
|
}
|
|
14872
15236
|
shouldEnableLocalTrace() {
|
|
@@ -14893,7 +15257,7 @@ var DaemonCore = class {
|
|
|
14893
15257
|
sink: this.localTraceSink
|
|
14894
15258
|
}));
|
|
14895
15259
|
this.agentManager.setTracer(this.tracer);
|
|
14896
|
-
this.agentManager.setCliTransportTraceDir(
|
|
15260
|
+
this.agentManager.setCliTransportTraceDir(path17.join(machineDir, "traces"));
|
|
14897
15261
|
}
|
|
14898
15262
|
installTraceBundleUploader(machineDir) {
|
|
14899
15263
|
if (!this.shouldEnableLocalTrace()) return;
|
|
@@ -15501,8 +15865,6 @@ var DaemonCore = class {
|
|
|
15501
15865
|
};
|
|
15502
15866
|
|
|
15503
15867
|
export {
|
|
15504
|
-
DAEMON_API_KEY_ENV,
|
|
15505
|
-
scrubDaemonAuthEnv,
|
|
15506
15868
|
subscribeDaemonLogs,
|
|
15507
15869
|
resolveWorkspaceDirectoryPath,
|
|
15508
15870
|
scanWorkspaceDirectories,
|