@slock-ai/daemon 0.54.2 → 0.55.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-7ZOPGUXT.js → chunk-6Q3U5STT.js} +441 -318
- package/dist/cli/index.js +1217 -689
- package/dist/core.js +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
|
@@ -9,11 +9,35 @@ import {
|
|
|
9
9
|
|
|
10
10
|
// src/core.ts
|
|
11
11
|
import path16 from "path";
|
|
12
|
-
import
|
|
12
|
+
import os7 from "os";
|
|
13
13
|
import { createRequire as createRequire2 } from "module";
|
|
14
14
|
import { accessSync } from "fs";
|
|
15
15
|
import { fileURLToPath } from "url";
|
|
16
16
|
|
|
17
|
+
// ../shared/src/slockRefs.ts
|
|
18
|
+
var SLOCK_REF_CHANNEL_NAME_PATTERN = String.raw`[\p{L}\p{N}_-]+`;
|
|
19
|
+
var SLOCK_REF_USER_NAME_PATTERN = SLOCK_REF_CHANNEL_NAME_PATTERN;
|
|
20
|
+
var SLOCK_REF_DM_PEER_PATTERN = String.raw`[\w-]+`;
|
|
21
|
+
var SLOCK_REF_THREAD_SHORT_ID_PATTERN = String.raw`[\da-f]{6,8}`;
|
|
22
|
+
var SLOCK_REF_MESSAGE_ID_PATTERN = String.raw`[A-Za-z0-9][A-Za-z0-9-]{1,63}`;
|
|
23
|
+
var SLOCK_REF_TASK_NUMBER_PATTERN = String.raw`[1-9]\d*`;
|
|
24
|
+
var USER_RE = new RegExp(String.raw`^@(${SLOCK_REF_USER_NAME_PATTERN})$`, "u");
|
|
25
|
+
var CHANNEL_RE = new RegExp(String.raw`^#(${SLOCK_REF_CHANNEL_NAME_PATTERN})$`, "u");
|
|
26
|
+
var CHANNEL_THREAD_RE = new RegExp(
|
|
27
|
+
String.raw`^#(${SLOCK_REF_CHANNEL_NAME_PATTERN}):(${SLOCK_REF_THREAD_SHORT_ID_PATTERN})$`,
|
|
28
|
+
"iu"
|
|
29
|
+
);
|
|
30
|
+
var DM_RE = new RegExp(String.raw`^dm:@(${SLOCK_REF_DM_PEER_PATTERN})$`, "iu");
|
|
31
|
+
var DM_THREAD_RE = new RegExp(
|
|
32
|
+
String.raw`^dm:@(${SLOCK_REF_DM_PEER_PATTERN}):(${SLOCK_REF_THREAD_SHORT_ID_PATTERN})$`,
|
|
33
|
+
"iu"
|
|
34
|
+
);
|
|
35
|
+
var TASK_RE = new RegExp(String.raw`^task\s+#(${SLOCK_REF_TASK_NUMBER_PATTERN})$`, "iu");
|
|
36
|
+
var CHANNEL_MESSAGE_RE = new RegExp(
|
|
37
|
+
String.raw`^#(${SLOCK_REF_CHANNEL_NAME_PATTERN})(?::(${SLOCK_REF_THREAD_SHORT_ID_PATTERN}))?\s+msg=(${SLOCK_REF_MESSAGE_ID_PATTERN})$`,
|
|
38
|
+
"iu"
|
|
39
|
+
);
|
|
40
|
+
|
|
17
41
|
// ../shared/src/tracing/index.ts
|
|
18
42
|
var DEFAULT_TRACE_FLAGS = "00";
|
|
19
43
|
var TRACEPARENT_VERSION = "00";
|
|
@@ -724,6 +748,7 @@ var SERVER_CAPABILITY_MATRIX = {
|
|
|
724
748
|
};
|
|
725
749
|
|
|
726
750
|
// ../shared/src/index.ts
|
|
751
|
+
var RUNTIME_CONFIG_VERSION = 1;
|
|
727
752
|
var RUNTIMES = [
|
|
728
753
|
{ id: "claude", displayName: "Claude Code", binary: "claude", supported: true },
|
|
729
754
|
{ id: "codex", displayName: "Codex CLI", binary: "codex", supported: true },
|
|
@@ -734,6 +759,164 @@ var RUNTIMES = [
|
|
|
734
759
|
{ id: "gemini", displayName: "Gemini CLI", binary: "gemini", supported: true },
|
|
735
760
|
{ id: "opencode", displayName: "OpenCode", binary: "opencode", supported: true }
|
|
736
761
|
];
|
|
762
|
+
var RUNTIME_MODELS = {
|
|
763
|
+
claude: [
|
|
764
|
+
{ id: "opus", label: "Opus" },
|
|
765
|
+
{ id: "sonnet", label: "Sonnet" },
|
|
766
|
+
{ id: "haiku", label: "Haiku" }
|
|
767
|
+
],
|
|
768
|
+
codex: [
|
|
769
|
+
{ id: "gpt-5.5", label: "GPT-5.5" },
|
|
770
|
+
{ id: "gpt-5.4", label: "GPT-5.4" },
|
|
771
|
+
{ id: "gpt-5.3-codex", label: "GPT-5.3 Codex" },
|
|
772
|
+
{ id: "gpt-5.3-codex-spark", label: "GPT-5.3 Codex Spark" },
|
|
773
|
+
{ id: "gpt-5.2-codex", label: "GPT-5.2 Codex" },
|
|
774
|
+
{ id: "gpt-5.2", label: "GPT-5.2" },
|
|
775
|
+
{ id: "gpt-5.1-codex-max", label: "GPT-5.1 Codex Max" },
|
|
776
|
+
{ id: "gpt-5.1-codex", label: "GPT-5.1 Codex" },
|
|
777
|
+
{ id: "gpt-5-codex", label: "GPT-5 Codex" },
|
|
778
|
+
{ id: "gpt-5", label: "GPT-5" }
|
|
779
|
+
],
|
|
780
|
+
antigravity: [
|
|
781
|
+
{ id: "default", label: "AGY configured default", verified: "suggestion_only" }
|
|
782
|
+
],
|
|
783
|
+
copilot: [
|
|
784
|
+
{ id: "gpt-5.4", label: "GPT-5.4" },
|
|
785
|
+
{ id: "gpt-5.2", label: "GPT-5.2" },
|
|
786
|
+
{ id: "claude-4-sonnet", label: "Claude 4 Sonnet" },
|
|
787
|
+
{ id: "claude-4.5-sonnet", label: "Claude 4.5 Sonnet" }
|
|
788
|
+
],
|
|
789
|
+
cursor: [
|
|
790
|
+
{ id: "composer-2-fast", label: "Composer 2 Fast" },
|
|
791
|
+
{ id: "composer-2", label: "Composer 2" },
|
|
792
|
+
{ id: "auto", label: "Auto" }
|
|
793
|
+
],
|
|
794
|
+
gemini: [
|
|
795
|
+
{ id: "default", label: "Configured Default / Auto", verified: "suggestion_only" },
|
|
796
|
+
{ id: "gemini-3.1-pro-preview", label: "Gemini 3.1 Pro (Preview)" },
|
|
797
|
+
{ id: "gemini-3-flash-preview", label: "Gemini 3 Flash (Preview)" },
|
|
798
|
+
{ id: "gemini-2.5-pro", label: "Gemini 2.5 Pro" },
|
|
799
|
+
{ id: "gemini-2.5-flash", label: "Gemini 2.5 Flash" }
|
|
800
|
+
],
|
|
801
|
+
opencode: [
|
|
802
|
+
{ id: "default", label: "Configured Default / Auto", verified: "suggestion_only" },
|
|
803
|
+
{ id: "deepseek/deepseek-v4-pro", label: "DeepSeek V4 Pro (OpenCode)", verified: "suggestion_only" },
|
|
804
|
+
{ id: "openrouter/anthropic/claude-opus-4.5", label: "Claude Opus 4.5 via OpenRouter", verified: "suggestion_only" },
|
|
805
|
+
{ id: "fusecode/opus[1m]", label: "Opus 1M via FuseCode", verified: "suggestion_only" }
|
|
806
|
+
],
|
|
807
|
+
// Kimi CLI resolves model keys from each user's local config, so the safest
|
|
808
|
+
// built-in option is to defer to whatever default model the CLI already uses.
|
|
809
|
+
kimi: [
|
|
810
|
+
{ id: "default", label: "Configured Default" }
|
|
811
|
+
]
|
|
812
|
+
};
|
|
813
|
+
function getDefaultModel(runtimeId) {
|
|
814
|
+
const models = RUNTIME_MODELS[runtimeId];
|
|
815
|
+
return models?.[0]?.id ?? "sonnet";
|
|
816
|
+
}
|
|
817
|
+
var CONTROLLED_RUNTIME_ENV_KEYS = {
|
|
818
|
+
claude: ["ANTHROPIC_BASE_URL", "ANTHROPIC_API_KEY", "ANTHROPIC_CUSTOM_MODEL_OPTION"]
|
|
819
|
+
};
|
|
820
|
+
function isPlainRecord(value) {
|
|
821
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
822
|
+
}
|
|
823
|
+
function normalizeEnvVars(envVars) {
|
|
824
|
+
if (!isPlainRecord(envVars)) return null;
|
|
825
|
+
const normalized = {};
|
|
826
|
+
for (const [key, value] of Object.entries(envVars)) {
|
|
827
|
+
if (typeof key === "string" && typeof value === "string") {
|
|
828
|
+
normalized[key] = value;
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
return Object.keys(normalized).length > 0 ? normalized : null;
|
|
832
|
+
}
|
|
833
|
+
function getControlledRuntimeEnvKeys(runtime) {
|
|
834
|
+
return CONTROLLED_RUNTIME_ENV_KEYS[runtime] ?? [];
|
|
835
|
+
}
|
|
836
|
+
function stripControlledRuntimeEnvVars(runtime, envVars) {
|
|
837
|
+
const normalized = normalizeEnvVars(envVars);
|
|
838
|
+
if (!normalized) return null;
|
|
839
|
+
const controlled = new Set(getControlledRuntimeEnvKeys(runtime));
|
|
840
|
+
for (const key of controlled) {
|
|
841
|
+
delete normalized[key];
|
|
842
|
+
}
|
|
843
|
+
return Object.keys(normalized).length > 0 ? normalized : null;
|
|
844
|
+
}
|
|
845
|
+
function isPresetRuntimeModel(runtime, model) {
|
|
846
|
+
return (RUNTIME_MODELS[runtime] ?? []).some((candidate) => candidate.id === model);
|
|
847
|
+
}
|
|
848
|
+
function modelConfigFromLegacy(runtime, model) {
|
|
849
|
+
return isPresetRuntimeModel(runtime, model) ? { kind: "preset", id: model } : { kind: "custom", name: model };
|
|
850
|
+
}
|
|
851
|
+
function parseProviderConfig(runtime, value) {
|
|
852
|
+
if (runtime !== "claude") return void 0;
|
|
853
|
+
if (!isPlainRecord(value)) return { kind: "default" };
|
|
854
|
+
if (value.kind === "custom" && typeof value.apiUrl === "string" && value.apiUrl.trim() && typeof value.apiKey === "string" && value.apiKey.trim()) {
|
|
855
|
+
return { kind: "custom", apiUrl: value.apiUrl.trim(), apiKey: value.apiKey.trim() };
|
|
856
|
+
}
|
|
857
|
+
return { kind: "default" };
|
|
858
|
+
}
|
|
859
|
+
function parseModelConfig(runtime, value, fallback) {
|
|
860
|
+
if (!isPlainRecord(value)) return modelConfigFromLegacy(runtime, fallback);
|
|
861
|
+
if (value.kind === "custom" && typeof value.name === "string" && value.name.trim()) {
|
|
862
|
+
return { kind: "custom", name: value.name.trim() };
|
|
863
|
+
}
|
|
864
|
+
if (value.kind === "preset" && typeof value.id === "string" && value.id.trim()) {
|
|
865
|
+
return { kind: "preset", id: value.id.trim() };
|
|
866
|
+
}
|
|
867
|
+
return modelConfigFromLegacy(runtime, fallback);
|
|
868
|
+
}
|
|
869
|
+
function parseModeConfig(value) {
|
|
870
|
+
if (!isPlainRecord(value)) return { kind: "default" };
|
|
871
|
+
if (value.kind === "fast") return { kind: "fast" };
|
|
872
|
+
return { kind: "default" };
|
|
873
|
+
}
|
|
874
|
+
function hydrateRuntimeConfig(input) {
|
|
875
|
+
const stored = isPlainRecord(input.runtimeConfig) && input.runtimeConfig.version === RUNTIME_CONFIG_VERSION ? input.runtimeConfig : null;
|
|
876
|
+
const runtime = typeof stored?.runtime === "string" && stored.runtime.trim() || typeof input.runtime === "string" && input.runtime.trim() || "claude";
|
|
877
|
+
const fallbackModel = typeof input.model === "string" && input.model.trim() || getDefaultModel(runtime);
|
|
878
|
+
const legacyEnvVars = normalizeEnvVars(input.envVars);
|
|
879
|
+
const storedEnvVars = normalizeEnvVars(stored?.envVars);
|
|
880
|
+
const legacyClaudeApiUrl = runtime === "claude" ? legacyEnvVars?.ANTHROPIC_BASE_URL : void 0;
|
|
881
|
+
const legacyClaudeApiKey = runtime === "claude" ? legacyEnvVars?.ANTHROPIC_API_KEY : void 0;
|
|
882
|
+
const provider = stored ? parseProviderConfig(runtime, stored.provider) : runtime === "claude" && legacyClaudeApiUrl && legacyClaudeApiKey ? { kind: "custom", apiUrl: legacyClaudeApiUrl, apiKey: legacyClaudeApiKey } : runtime === "claude" ? { kind: "default" } : void 0;
|
|
883
|
+
return {
|
|
884
|
+
version: RUNTIME_CONFIG_VERSION,
|
|
885
|
+
runtime,
|
|
886
|
+
...provider ? { provider } : {},
|
|
887
|
+
model: stored ? parseModelConfig(runtime, stored.model, fallbackModel) : modelConfigFromLegacy(runtime, fallbackModel),
|
|
888
|
+
mode: stored ? parseModeConfig(stored.mode) : { kind: "default" },
|
|
889
|
+
reasoningEffort: stored?.reasoningEffort ?? input.reasoningEffort ?? null,
|
|
890
|
+
envVars: stripControlledRuntimeEnvVars(runtime, stored ? storedEnvVars : legacyEnvVars)
|
|
891
|
+
};
|
|
892
|
+
}
|
|
893
|
+
function runtimeConfigModelValue(config) {
|
|
894
|
+
return config.model.kind === "custom" ? config.model.name : config.model.id;
|
|
895
|
+
}
|
|
896
|
+
function runtimeConfigToLaunchFields(config) {
|
|
897
|
+
const normalized = isPlainRecord(config) && config.version === RUNTIME_CONFIG_VERSION ? hydrateRuntimeConfig({ runtimeConfig: config }) : hydrateRuntimeConfig(config);
|
|
898
|
+
const generatedEnvVars = {};
|
|
899
|
+
if (normalized.runtime === "claude") {
|
|
900
|
+
if (normalized.provider?.kind === "custom") {
|
|
901
|
+
generatedEnvVars.ANTHROPIC_BASE_URL = normalized.provider.apiUrl;
|
|
902
|
+
generatedEnvVars.ANTHROPIC_API_KEY = normalized.provider.apiKey;
|
|
903
|
+
}
|
|
904
|
+
if (normalized.model.kind === "custom") {
|
|
905
|
+
generatedEnvVars.ANTHROPIC_CUSTOM_MODEL_OPTION = normalized.model.name;
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
const envVars = {
|
|
909
|
+
...normalized.envVars ?? {},
|
|
910
|
+
...generatedEnvVars
|
|
911
|
+
};
|
|
912
|
+
return {
|
|
913
|
+
runtime: normalized.runtime,
|
|
914
|
+
model: runtimeConfigModelValue(normalized),
|
|
915
|
+
mode: normalized.mode,
|
|
916
|
+
reasoningEffort: normalized.reasoningEffort ?? null,
|
|
917
|
+
envVars: Object.keys(envVars).length > 0 ? envVars : null
|
|
918
|
+
};
|
|
919
|
+
}
|
|
737
920
|
var PLAN_CONFIG = {
|
|
738
921
|
free: {
|
|
739
922
|
displayName: "Hobby",
|
|
@@ -769,17 +952,14 @@ var DISPLAY_PLAN_CONFIG = {
|
|
|
769
952
|
};
|
|
770
953
|
|
|
771
954
|
// src/agentProcessManager.ts
|
|
772
|
-
import { mkdirSync as mkdirSync4, readdirSync
|
|
955
|
+
import { mkdirSync as mkdirSync4, readdirSync, statSync, writeFileSync as writeFileSync7 } from "fs";
|
|
773
956
|
import { mkdir, writeFile, access, readdir as readdir2, stat as stat2, readFile, rm as rm2 } from "fs/promises";
|
|
774
957
|
import { createHash as createHash2 } from "crypto";
|
|
775
958
|
import path12 from "path";
|
|
776
|
-
import
|
|
959
|
+
import os5 from "os";
|
|
777
960
|
|
|
778
961
|
// src/drivers/claude.ts
|
|
779
962
|
import { spawn } from "child_process";
|
|
780
|
-
import { existsSync as existsSync3, readdirSync, readFileSync as readFileSync2, statSync, writeFileSync as writeFileSync2 } from "fs";
|
|
781
|
-
import os2 from "os";
|
|
782
|
-
import path4 from "path";
|
|
783
963
|
|
|
784
964
|
// src/drivers/cliTransport.ts
|
|
785
965
|
import { mkdirSync, readFileSync, rmSync, writeFileSync } from "fs";
|
|
@@ -1949,7 +2129,7 @@ function unregisterAgentCredentialProxyForLaunch(input) {
|
|
|
1949
2129
|
// src/drivers/cliTransport.ts
|
|
1950
2130
|
var shellSingleQuote = (value) => `'${value.replace(/'/g, `'\\''`)}'`;
|
|
1951
2131
|
var powershellSingleQuote = (value) => `'${value.replace(/'/g, "''")}'`;
|
|
1952
|
-
var DEFAULT_ACTIVE_CAPABILITIES = "send,read,mentions,tasks,reactions,server,channels";
|
|
2132
|
+
var DEFAULT_ACTIVE_CAPABILITIES = "send,read,mentions,tasks,reactions,server,channels,knowledge";
|
|
1953
2133
|
var LOOPBACK_NO_PROXY = "127.0.0.1,localhost";
|
|
1954
2134
|
var safePathPart = (value) => value.replace(/[^a-zA-Z0-9_.-]/g, "_");
|
|
1955
2135
|
var RAW_CREDENTIAL_ENV_DENYLIST = [
|
|
@@ -2152,10 +2332,11 @@ exec ${shellSingleQuote(process.execPath)} ${shellSingleQuote(opencliBinPath)} "
|
|
|
2152
2332
|
}
|
|
2153
2333
|
}
|
|
2154
2334
|
const wrapperPath = platform === "win32" ? path2.join(slockDir, "slock.cmd") : posixWrapper;
|
|
2335
|
+
const launchRuntimeFields = runtimeConfigToLaunchFields(ctx.config);
|
|
2155
2336
|
const spawnEnv = {
|
|
2156
2337
|
...process.env,
|
|
2157
2338
|
FORCE_COLOR: "0",
|
|
2158
|
-
...
|
|
2339
|
+
...launchRuntimeFields.envVars || {},
|
|
2159
2340
|
...extraEnv,
|
|
2160
2341
|
...platform === "win32" ? windowsUtf8Env() : {},
|
|
2161
2342
|
...runtimeContextEnv(ctx.config),
|
|
@@ -2186,6 +2367,129 @@ exec ${shellSingleQuote(process.execPath)} ${shellSingleQuote(opencliBinPath)} "
|
|
|
2186
2367
|
};
|
|
2187
2368
|
}
|
|
2188
2369
|
|
|
2370
|
+
// src/drivers/claudeEventNormalizer.ts
|
|
2371
|
+
function collectResultErrorDetail(message, fallback) {
|
|
2372
|
+
const parts = [];
|
|
2373
|
+
if (Array.isArray(message.errors)) {
|
|
2374
|
+
for (const err of message.errors) {
|
|
2375
|
+
if (typeof err === "string" && err.trim()) parts.push(err.trim());
|
|
2376
|
+
}
|
|
2377
|
+
}
|
|
2378
|
+
if (typeof message.result === "string" && message.result.trim()) {
|
|
2379
|
+
parts.push(message.result.trim());
|
|
2380
|
+
}
|
|
2381
|
+
return parts.join(" | ") || fallback;
|
|
2382
|
+
}
|
|
2383
|
+
function isProviderApiFailureText(value, hasToolUse) {
|
|
2384
|
+
return !hasToolUse && /^\s*API Error:/i.test(value) && (/\b(?:ECONNRESET|EPIPE|ETIMEDOUT|ECONNREFUSED|ENOTFOUND|EAI_AGAIN)\b/i.test(value) || /\bUnable to connect to API\b/i.test(value) || /\b(?:timed out|timeout)\b/i.test(value) || /\b5\d{2}\b/.test(value));
|
|
2385
|
+
}
|
|
2386
|
+
var ClaudeEventNormalizer = class {
|
|
2387
|
+
normalizeLine(line) {
|
|
2388
|
+
let event;
|
|
2389
|
+
try {
|
|
2390
|
+
event = JSON.parse(line);
|
|
2391
|
+
} catch {
|
|
2392
|
+
return [];
|
|
2393
|
+
}
|
|
2394
|
+
const events = [];
|
|
2395
|
+
const pushResultError = (message, fallback) => {
|
|
2396
|
+
events.push({ kind: "error", message: collectResultErrorDetail(message, fallback) });
|
|
2397
|
+
};
|
|
2398
|
+
switch (event.type) {
|
|
2399
|
+
case "system":
|
|
2400
|
+
if (event.subtype === "init" && event.session_id) {
|
|
2401
|
+
events.push({ kind: "session_init", sessionId: event.session_id });
|
|
2402
|
+
}
|
|
2403
|
+
if (event.subtype === "status" && event.status === "compacting") {
|
|
2404
|
+
events.push({ kind: "compaction_started" });
|
|
2405
|
+
}
|
|
2406
|
+
if (event.subtype === "status" && event.status === "requesting") {
|
|
2407
|
+
events.push({
|
|
2408
|
+
kind: "internal_progress",
|
|
2409
|
+
source: "claude_system_status",
|
|
2410
|
+
itemType: "requesting",
|
|
2411
|
+
payloadBytes: Buffer.byteLength(line, "utf8")
|
|
2412
|
+
});
|
|
2413
|
+
}
|
|
2414
|
+
if (event.subtype === "compact_boundary") {
|
|
2415
|
+
events.push({ kind: "compaction_finished" });
|
|
2416
|
+
}
|
|
2417
|
+
break;
|
|
2418
|
+
case "stream_event":
|
|
2419
|
+
events.push({
|
|
2420
|
+
kind: "internal_progress",
|
|
2421
|
+
source: "claude_stream_event",
|
|
2422
|
+
itemType: typeof event.event?.type === "string" && event.event.type.length > 0 ? event.event.type : "unknown",
|
|
2423
|
+
payloadBytes: Buffer.byteLength(line, "utf8")
|
|
2424
|
+
});
|
|
2425
|
+
break;
|
|
2426
|
+
case "assistant": {
|
|
2427
|
+
const content = event.message?.content;
|
|
2428
|
+
if (Array.isArray(content)) {
|
|
2429
|
+
const hasToolUse = content.some((block) => block?.type === "tool_use");
|
|
2430
|
+
for (const block of content) {
|
|
2431
|
+
if (block.type === "thinking" && block.thinking) {
|
|
2432
|
+
events.push({ kind: "thinking", text: block.thinking });
|
|
2433
|
+
} else if (block.type === "text" && block.text) {
|
|
2434
|
+
if (isProviderApiFailureText(block.text, hasToolUse)) {
|
|
2435
|
+
events.push({ kind: "error", message: block.text });
|
|
2436
|
+
} else {
|
|
2437
|
+
events.push({ kind: "text", text: block.text });
|
|
2438
|
+
}
|
|
2439
|
+
} else if (block.type === "tool_use") {
|
|
2440
|
+
events.push({ kind: "tool_call", name: block.name || "unknown_tool", input: block.input });
|
|
2441
|
+
}
|
|
2442
|
+
}
|
|
2443
|
+
}
|
|
2444
|
+
break;
|
|
2445
|
+
}
|
|
2446
|
+
case "user": {
|
|
2447
|
+
const content = event.message?.content;
|
|
2448
|
+
if (Array.isArray(content)) {
|
|
2449
|
+
for (const block of content) {
|
|
2450
|
+
if (block.type === "tool_result") {
|
|
2451
|
+
events.push({ kind: "tool_output", name: block.name || block.tool_use_id || "tool_result" });
|
|
2452
|
+
}
|
|
2453
|
+
}
|
|
2454
|
+
}
|
|
2455
|
+
break;
|
|
2456
|
+
}
|
|
2457
|
+
case "result": {
|
|
2458
|
+
const subtype = typeof event.subtype === "string" ? event.subtype : "success";
|
|
2459
|
+
const stopReason = typeof event.stop_reason === "string" ? event.stop_reason : null;
|
|
2460
|
+
switch (subtype) {
|
|
2461
|
+
case "success":
|
|
2462
|
+
if (event.is_error && stopReason !== "max_tokens") {
|
|
2463
|
+
pushResultError(event, "Execution failed");
|
|
2464
|
+
}
|
|
2465
|
+
break;
|
|
2466
|
+
case "error_during_execution":
|
|
2467
|
+
if (stopReason !== "max_tokens") {
|
|
2468
|
+
pushResultError(event, "Execution failed");
|
|
2469
|
+
}
|
|
2470
|
+
break;
|
|
2471
|
+
case "error_max_budget_usd":
|
|
2472
|
+
pushResultError(event, "Budget limit exceeded");
|
|
2473
|
+
break;
|
|
2474
|
+
case "error_max_turns":
|
|
2475
|
+
pushResultError(event, "Max turns exceeded");
|
|
2476
|
+
break;
|
|
2477
|
+
case "error_max_structured_output_retries":
|
|
2478
|
+
pushResultError(event, "Structured output retries exceeded");
|
|
2479
|
+
break;
|
|
2480
|
+
}
|
|
2481
|
+
events.push({ kind: "turn_end", sessionId: event.session_id });
|
|
2482
|
+
break;
|
|
2483
|
+
}
|
|
2484
|
+
}
|
|
2485
|
+
return events;
|
|
2486
|
+
}
|
|
2487
|
+
};
|
|
2488
|
+
|
|
2489
|
+
// src/drivers/claudeLaunch.ts
|
|
2490
|
+
import { writeFileSync as writeFileSync2 } from "fs";
|
|
2491
|
+
import path4 from "path";
|
|
2492
|
+
|
|
2189
2493
|
// src/drivers/probe.ts
|
|
2190
2494
|
import { execFileSync } from "child_process";
|
|
2191
2495
|
import { existsSync as existsSync2 } from "fs";
|
|
@@ -2386,12 +2690,10 @@ function resolveHomePath(relativePath, deps = {}) {
|
|
|
2386
2690
|
return path3.join(homeDir, relativePath);
|
|
2387
2691
|
}
|
|
2388
2692
|
|
|
2389
|
-
// src/drivers/
|
|
2693
|
+
// src/drivers/claudeLaunch.ts
|
|
2390
2694
|
var CLAUDE_DESKTOP_CLI_RELATIVE_PATH = path4.join("Applications", "Claude Code URL Handler.app", "Contents", "MacOS", "claude");
|
|
2391
2695
|
var CLAUDE_DESKTOP_CLI_SYSTEM_PATH = "/Applications/Claude Code URL Handler.app/Contents/MacOS/claude";
|
|
2392
2696
|
var CLAUDE_SYSTEM_PROMPT_FILE = "claude-system-prompt.md";
|
|
2393
|
-
var CLAUDE_MCP_CONFIG_FILE = "claude-mcp-config.json";
|
|
2394
|
-
var SLOCK_RUNTIME_ACTIONS_MCP_SERVER_NAME = "chat";
|
|
2395
2697
|
var CLAUDE_DISALLOWED_TOOLS = [
|
|
2396
2698
|
"EnterPlanMode",
|
|
2397
2699
|
"ExitPlanMode",
|
|
@@ -2417,81 +2719,54 @@ function probeClaude(deps = {}) {
|
|
|
2417
2719
|
version: readCommandVersion(command, [], deps) ?? void 0
|
|
2418
2720
|
};
|
|
2419
2721
|
}
|
|
2420
|
-
function
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2722
|
+
function buildClaudeArgs(config, opts) {
|
|
2723
|
+
const launchRuntimeFields = runtimeConfigToLaunchFields(config);
|
|
2724
|
+
const args = [
|
|
2725
|
+
"--allow-dangerously-skip-permissions",
|
|
2726
|
+
"--dangerously-skip-permissions",
|
|
2727
|
+
"--verbose",
|
|
2728
|
+
"--permission-mode",
|
|
2729
|
+
"bypassPermissions",
|
|
2730
|
+
"--output-format",
|
|
2731
|
+
"stream-json",
|
|
2732
|
+
"--input-format",
|
|
2733
|
+
"stream-json",
|
|
2734
|
+
"--include-partial-messages",
|
|
2735
|
+
"--model",
|
|
2736
|
+
launchRuntimeFields.model || "sonnet",
|
|
2737
|
+
"--disallowed-tools",
|
|
2738
|
+
CLAUDE_DISALLOWED_TOOLS,
|
|
2739
|
+
"--append-system-prompt-file",
|
|
2740
|
+
opts.standingPromptFilePath
|
|
2741
|
+
];
|
|
2742
|
+
if (launchRuntimeFields.reasoningEffort) {
|
|
2743
|
+
args.push("--effort", launchRuntimeFields.reasoningEffort);
|
|
2428
2744
|
}
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
expandClaudeMcpConfigVariables(readFileSync2(configPath, "utf8"), vars)
|
|
2435
|
-
);
|
|
2436
|
-
if (!isRecord(parsed) || !isRecord(parsed.mcpServers)) return null;
|
|
2437
|
-
return parsed.mcpServers;
|
|
2438
|
-
} catch (err) {
|
|
2439
|
-
logger.warn(
|
|
2440
|
-
`[Claude] failed to read MCP config ${configPath}: ${err instanceof Error ? err.message : String(err)}`
|
|
2441
|
-
);
|
|
2442
|
-
return null;
|
|
2745
|
+
if (launchRuntimeFields.mode.kind === "fast") {
|
|
2746
|
+
args.push("--bare");
|
|
2747
|
+
}
|
|
2748
|
+
if (config.sessionId) {
|
|
2749
|
+
args.push("--resume", config.sessionId);
|
|
2443
2750
|
}
|
|
2751
|
+
return args;
|
|
2444
2752
|
}
|
|
2445
|
-
function
|
|
2446
|
-
const
|
|
2447
|
-
|
|
2753
|
+
function writeClaudeSystemPromptFile(standingPrompt, slockDir) {
|
|
2754
|
+
const systemPromptPath = path4.join(slockDir, CLAUDE_SYSTEM_PROMPT_FILE);
|
|
2755
|
+
writeFileSync2(systemPromptPath, standingPrompt, { mode: 384 });
|
|
2756
|
+
return systemPromptPath;
|
|
2448
2757
|
}
|
|
2449
|
-
function
|
|
2450
|
-
const
|
|
2451
|
-
const
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
}
|
|
2758
|
+
function buildClaudeSpawnSpec(claudeCommand, platform = process.platform) {
|
|
2759
|
+
const lowerClaudeCommand = claudeCommand?.toLowerCase();
|
|
2760
|
+
const isBatchFile = Boolean(
|
|
2761
|
+
platform === "win32" && lowerClaudeCommand && (lowerClaudeCommand.endsWith(".cmd") || lowerClaudeCommand.endsWith(".bat"))
|
|
2762
|
+
);
|
|
2763
|
+
return {
|
|
2764
|
+
command: claudeCommand ?? "claude",
|
|
2765
|
+
shell: platform === "win32" && (!claudeCommand || isBatchFile)
|
|
2458
2766
|
};
|
|
2459
|
-
pushIfFile(path4.join(home, ".claude.json"));
|
|
2460
|
-
pushIfFile(path4.join(ctx.workingDirectory, ".mcp.json"));
|
|
2461
|
-
const pluginRoot = path4.join(resolveClaudeConfigDir(ctx, home), "plugins");
|
|
2462
|
-
try {
|
|
2463
|
-
for (const entry of readdirSync(pluginRoot)) {
|
|
2464
|
-
const pluginPath = path4.join(pluginRoot, entry);
|
|
2465
|
-
const configPath = path4.join(pluginPath, ".mcp.json");
|
|
2466
|
-
try {
|
|
2467
|
-
if (existsSync3(configPath) && statSync(configPath).isFile()) {
|
|
2468
|
-
files.push({
|
|
2469
|
-
path: configPath,
|
|
2470
|
-
vars: { CLAUDE_PLUGIN_ROOT: pluginPath }
|
|
2471
|
-
});
|
|
2472
|
-
}
|
|
2473
|
-
} catch {
|
|
2474
|
-
}
|
|
2475
|
-
}
|
|
2476
|
-
} catch {
|
|
2477
|
-
}
|
|
2478
|
-
return files;
|
|
2479
|
-
}
|
|
2480
|
-
function buildClaudeUserMcpServers(ctx, home) {
|
|
2481
|
-
const servers = /* @__PURE__ */ Object.create(null);
|
|
2482
|
-
for (const configFile of collectClaudeMcpConfigFiles(ctx, home)) {
|
|
2483
|
-
const mcpServers = readClaudeMcpServers(configFile.path, configFile.vars);
|
|
2484
|
-
if (!mcpServers) continue;
|
|
2485
|
-
for (const [name, server] of Object.entries(mcpServers)) {
|
|
2486
|
-
if (!isRecord(server)) {
|
|
2487
|
-
logger.warn(`[Claude] ignoring invalid MCP server "${name}" in ${configFile.path}`);
|
|
2488
|
-
continue;
|
|
2489
|
-
}
|
|
2490
|
-
servers[name] = server;
|
|
2491
|
-
}
|
|
2492
|
-
}
|
|
2493
|
-
return servers;
|
|
2494
2767
|
}
|
|
2768
|
+
|
|
2769
|
+
// src/drivers/claude.ts
|
|
2495
2770
|
var ClaudeDriver = class {
|
|
2496
2771
|
id = "claude";
|
|
2497
2772
|
lifecycle = {
|
|
@@ -2501,7 +2776,7 @@ var ClaudeDriver = class {
|
|
|
2501
2776
|
};
|
|
2502
2777
|
communication = {
|
|
2503
2778
|
chat: "slock_cli",
|
|
2504
|
-
runtimeControl: "
|
|
2779
|
+
runtimeControl: "none"
|
|
2505
2780
|
};
|
|
2506
2781
|
session = {
|
|
2507
2782
|
recovery: "resume_or_fresh"
|
|
@@ -2511,107 +2786,37 @@ var ClaudeDriver = class {
|
|
|
2511
2786
|
toLaunchSpec: (modelId) => ({ args: ["--model", modelId] })
|
|
2512
2787
|
};
|
|
2513
2788
|
supportsStdinNotification = true;
|
|
2514
|
-
mcpToolPrefix = "
|
|
2789
|
+
mcpToolPrefix = "";
|
|
2515
2790
|
usesSlockCliForCommunication = true;
|
|
2516
2791
|
// Claude Code supports same-turn steering, but raw stdin injection at an
|
|
2517
2792
|
// arbitrary busy instant can collide with active signed thinking blocks. The
|
|
2518
2793
|
// daemon therefore gates busy delivery on Claude stream-json boundaries.
|
|
2519
2794
|
busyDeliveryMode = "gated";
|
|
2520
2795
|
supportsNativeStandingPrompt = true;
|
|
2796
|
+
eventNormalizer = new ClaudeEventNormalizer();
|
|
2521
2797
|
probe() {
|
|
2522
2798
|
return probeClaude();
|
|
2523
2799
|
}
|
|
2524
|
-
buildClaudeArgs(config,
|
|
2525
|
-
|
|
2526
|
-
"--allow-dangerously-skip-permissions",
|
|
2527
|
-
"--dangerously-skip-permissions",
|
|
2528
|
-
"--verbose",
|
|
2529
|
-
"--permission-mode",
|
|
2530
|
-
"bypassPermissions",
|
|
2531
|
-
"--output-format",
|
|
2532
|
-
"stream-json",
|
|
2533
|
-
"--input-format",
|
|
2534
|
-
"stream-json",
|
|
2535
|
-
"--model",
|
|
2536
|
-
config.model || "sonnet",
|
|
2537
|
-
"--disallowed-tools",
|
|
2538
|
-
CLAUDE_DISALLOWED_TOOLS
|
|
2539
|
-
];
|
|
2540
|
-
if (opts.standingPromptFilePath) {
|
|
2541
|
-
args.push("--append-system-prompt-file", opts.standingPromptFilePath);
|
|
2542
|
-
} else {
|
|
2543
|
-
args.push("--append-system-prompt", standingPrompt);
|
|
2544
|
-
}
|
|
2545
|
-
if (config.sessionId) {
|
|
2546
|
-
args.push("--resume", config.sessionId);
|
|
2547
|
-
}
|
|
2548
|
-
return args;
|
|
2549
|
-
}
|
|
2550
|
-
buildRuntimeActionsMcpServer(ctx) {
|
|
2551
|
-
const isTsSource = ctx.chatBridgePath.endsWith(".ts");
|
|
2552
|
-
const command = isTsSource ? "npx" : "node";
|
|
2553
|
-
const bridgeArgs = isTsSource ? ["tsx", ctx.chatBridgePath] : [ctx.chatBridgePath];
|
|
2554
|
-
return {
|
|
2555
|
-
command,
|
|
2556
|
-
args: [
|
|
2557
|
-
...bridgeArgs,
|
|
2558
|
-
"--agent-id",
|
|
2559
|
-
ctx.agentId,
|
|
2560
|
-
"--server-url",
|
|
2561
|
-
ctx.config.serverUrl,
|
|
2562
|
-
"--auth-token",
|
|
2563
|
-
ctx.config.authToken || ctx.daemonApiKey,
|
|
2564
|
-
"--runtime",
|
|
2565
|
-
this.id,
|
|
2566
|
-
...ctx.launchId ? ["--launch-id", ctx.launchId] : [],
|
|
2567
|
-
"--runtime-actions-only"
|
|
2568
|
-
]
|
|
2569
|
-
};
|
|
2570
|
-
}
|
|
2571
|
-
buildRuntimeActionsMcpConfig(ctx, home = os2.homedir()) {
|
|
2572
|
-
const userMcpServers = buildClaudeUserMcpServers(ctx, home);
|
|
2573
|
-
if (Object.prototype.hasOwnProperty.call(userMcpServers, SLOCK_RUNTIME_ACTIONS_MCP_SERVER_NAME)) {
|
|
2574
|
-
logger.warn(
|
|
2575
|
-
`[Agent ${ctx.agentId}] Claude user MCP server "${SLOCK_RUNTIME_ACTIONS_MCP_SERVER_NAME}" is reserved by Slock runtime actions and will be ignored`
|
|
2576
|
-
);
|
|
2577
|
-
}
|
|
2578
|
-
return JSON.stringify({
|
|
2579
|
-
mcpServers: {
|
|
2580
|
-
...userMcpServers,
|
|
2581
|
-
[SLOCK_RUNTIME_ACTIONS_MCP_SERVER_NAME]: this.buildRuntimeActionsMcpServer(ctx)
|
|
2582
|
-
}
|
|
2583
|
-
});
|
|
2584
|
-
}
|
|
2585
|
-
writeClaudeLaunchFiles(ctx, slockDir, home = os2.homedir()) {
|
|
2586
|
-
const systemPromptPath = path4.join(slockDir, CLAUDE_SYSTEM_PROMPT_FILE);
|
|
2587
|
-
const mcpConfigPath = path4.join(slockDir, CLAUDE_MCP_CONFIG_FILE);
|
|
2588
|
-
writeFileSync2(systemPromptPath, ctx.standingPrompt, { mode: 384 });
|
|
2589
|
-
writeFileSync2(mcpConfigPath, this.buildRuntimeActionsMcpConfig(ctx, home), { mode: 384 });
|
|
2590
|
-
return { systemPromptPath, mcpConfigPath };
|
|
2800
|
+
buildClaudeArgs(config, opts) {
|
|
2801
|
+
return buildClaudeArgs(config, opts);
|
|
2591
2802
|
}
|
|
2592
2803
|
async spawn(ctx) {
|
|
2593
2804
|
const { slockDir, tokenFile, spawnEnv } = await prepareCliTransport(ctx);
|
|
2594
|
-
const
|
|
2595
|
-
const args = this.buildClaudeArgs(ctx.config,
|
|
2805
|
+
const systemPromptPath = writeClaudeSystemPromptFile(ctx.standingPrompt, slockDir);
|
|
2806
|
+
const args = this.buildClaudeArgs(ctx.config, {
|
|
2596
2807
|
standingPromptFilePath: systemPromptPath
|
|
2597
2808
|
});
|
|
2598
|
-
args.push("--mcp-config", mcpConfigPath, "--strict-mcp-config");
|
|
2599
2809
|
delete spawnEnv.CLAUDECODE;
|
|
2600
2810
|
logger.info(
|
|
2601
2811
|
`[Agent ${ctx.agentId}] transport=cli cli=${ctx.slockCliPath} token_file=${tokenFile}`
|
|
2602
2812
|
);
|
|
2603
2813
|
const claudeCommand = resolveClaudeCommand();
|
|
2604
|
-
const
|
|
2605
|
-
const
|
|
2606
|
-
const isBatchFile = Boolean(
|
|
2607
|
-
isWindows && lowerClaudeCommand && (lowerClaudeCommand.endsWith(".cmd") || lowerClaudeCommand.endsWith(".bat"))
|
|
2608
|
-
);
|
|
2609
|
-
const useShell = isWindows && (!claudeCommand || isBatchFile);
|
|
2610
|
-
const proc = spawn(claudeCommand ?? "claude", args, {
|
|
2814
|
+
const spawnSpec = buildClaudeSpawnSpec(claudeCommand);
|
|
2815
|
+
const proc = spawn(spawnSpec.command, args, {
|
|
2611
2816
|
cwd: ctx.workingDirectory,
|
|
2612
2817
|
stdio: ["pipe", "pipe", "pipe"],
|
|
2613
2818
|
env: spawnEnv,
|
|
2614
|
-
shell:
|
|
2819
|
+
shell: spawnSpec.shell
|
|
2615
2820
|
});
|
|
2616
2821
|
const stdinMsg = JSON.stringify({
|
|
2617
2822
|
type: "user",
|
|
@@ -2625,99 +2830,7 @@ var ClaudeDriver = class {
|
|
|
2625
2830
|
return { process: proc };
|
|
2626
2831
|
}
|
|
2627
2832
|
parseLine(line) {
|
|
2628
|
-
|
|
2629
|
-
try {
|
|
2630
|
-
event = JSON.parse(line);
|
|
2631
|
-
} catch {
|
|
2632
|
-
return [];
|
|
2633
|
-
}
|
|
2634
|
-
const events = [];
|
|
2635
|
-
const pushResultError = (message, fallback) => {
|
|
2636
|
-
const parts = [];
|
|
2637
|
-
if (Array.isArray(message.errors)) {
|
|
2638
|
-
for (const err of message.errors) {
|
|
2639
|
-
if (typeof err === "string" && err.trim()) parts.push(err.trim());
|
|
2640
|
-
}
|
|
2641
|
-
}
|
|
2642
|
-
if (typeof message.result === "string" && message.result.trim()) {
|
|
2643
|
-
parts.push(message.result.trim());
|
|
2644
|
-
}
|
|
2645
|
-
const detail = parts.join(" | ") || fallback;
|
|
2646
|
-
events.push({ kind: "error", message: detail });
|
|
2647
|
-
};
|
|
2648
|
-
const isProviderApiFailureText = (value, hasToolUse) => !hasToolUse && /^\s*API Error:/i.test(value) && (/\b(?:ECONNRESET|EPIPE|ETIMEDOUT|ECONNREFUSED|ENOTFOUND|EAI_AGAIN)\b/i.test(value) || /\bUnable to connect to API\b/i.test(value) || /\b(?:timed out|timeout)\b/i.test(value) || /\b5\d{2}\b/.test(value));
|
|
2649
|
-
switch (event.type) {
|
|
2650
|
-
case "system":
|
|
2651
|
-
if (event.subtype === "init" && event.session_id) {
|
|
2652
|
-
events.push({ kind: "session_init", sessionId: event.session_id });
|
|
2653
|
-
}
|
|
2654
|
-
if (event.subtype === "status" && event.status === "compacting") {
|
|
2655
|
-
events.push({ kind: "compaction_started" });
|
|
2656
|
-
}
|
|
2657
|
-
if (event.subtype === "compact_boundary") {
|
|
2658
|
-
events.push({ kind: "compaction_finished" });
|
|
2659
|
-
}
|
|
2660
|
-
break;
|
|
2661
|
-
case "assistant": {
|
|
2662
|
-
const content = event.message?.content;
|
|
2663
|
-
if (Array.isArray(content)) {
|
|
2664
|
-
const hasToolUse = content.some((block) => block?.type === "tool_use");
|
|
2665
|
-
for (const block of content) {
|
|
2666
|
-
if (block.type === "thinking" && block.thinking) {
|
|
2667
|
-
events.push({ kind: "thinking", text: block.thinking });
|
|
2668
|
-
} else if (block.type === "text" && block.text) {
|
|
2669
|
-
if (isProviderApiFailureText(block.text, hasToolUse)) {
|
|
2670
|
-
events.push({ kind: "error", message: block.text });
|
|
2671
|
-
} else {
|
|
2672
|
-
events.push({ kind: "text", text: block.text });
|
|
2673
|
-
}
|
|
2674
|
-
} else if (block.type === "tool_use") {
|
|
2675
|
-
events.push({ kind: "tool_call", name: block.name || "unknown_tool", input: block.input });
|
|
2676
|
-
}
|
|
2677
|
-
}
|
|
2678
|
-
}
|
|
2679
|
-
break;
|
|
2680
|
-
}
|
|
2681
|
-
case "user": {
|
|
2682
|
-
const content = event.message?.content;
|
|
2683
|
-
if (Array.isArray(content)) {
|
|
2684
|
-
for (const block of content) {
|
|
2685
|
-
if (block.type === "tool_result") {
|
|
2686
|
-
events.push({ kind: "tool_output", name: block.name || block.tool_use_id || "tool_result" });
|
|
2687
|
-
}
|
|
2688
|
-
}
|
|
2689
|
-
}
|
|
2690
|
-
break;
|
|
2691
|
-
}
|
|
2692
|
-
case "result": {
|
|
2693
|
-
const subtype = typeof event.subtype === "string" ? event.subtype : "success";
|
|
2694
|
-
const stopReason = typeof event.stop_reason === "string" ? event.stop_reason : null;
|
|
2695
|
-
switch (subtype) {
|
|
2696
|
-
case "success":
|
|
2697
|
-
if (event.is_error && stopReason !== "max_tokens") {
|
|
2698
|
-
pushResultError(event, "Execution failed");
|
|
2699
|
-
}
|
|
2700
|
-
break;
|
|
2701
|
-
case "error_during_execution":
|
|
2702
|
-
if (stopReason !== "max_tokens") {
|
|
2703
|
-
pushResultError(event, "Execution failed");
|
|
2704
|
-
}
|
|
2705
|
-
break;
|
|
2706
|
-
case "error_max_budget_usd":
|
|
2707
|
-
pushResultError(event, "Budget limit exceeded");
|
|
2708
|
-
break;
|
|
2709
|
-
case "error_max_turns":
|
|
2710
|
-
pushResultError(event, "Max turns exceeded");
|
|
2711
|
-
break;
|
|
2712
|
-
case "error_max_structured_output_retries":
|
|
2713
|
-
pushResultError(event, "Structured output retries exceeded");
|
|
2714
|
-
break;
|
|
2715
|
-
}
|
|
2716
|
-
events.push({ kind: "turn_end", sessionId: event.session_id });
|
|
2717
|
-
break;
|
|
2718
|
-
}
|
|
2719
|
-
}
|
|
2720
|
-
return events;
|
|
2833
|
+
return this.eventNormalizer.normalizeLine(line);
|
|
2721
2834
|
}
|
|
2722
2835
|
encodeStdinMessage(text, sessionId, _opts) {
|
|
2723
2836
|
return JSON.stringify({
|
|
@@ -2731,7 +2844,7 @@ var ClaudeDriver = class {
|
|
|
2731
2844
|
}
|
|
2732
2845
|
buildSystemPrompt(config, _agentId) {
|
|
2733
2846
|
return buildCliTransportSystemPrompt(config, {
|
|
2734
|
-
toolPrefix: "
|
|
2847
|
+
toolPrefix: "",
|
|
2735
2848
|
extraCriticalRules: [],
|
|
2736
2849
|
postStartupNotes: [
|
|
2737
2850
|
"**Claude runtime note:** While you are busy, Slock batches inbox-count notifications instead of injecting message content. Use `slock message check` at natural breakpoints to pull the pending messages before side-effect actions that depend on current context."
|
|
@@ -2744,8 +2857,8 @@ var ClaudeDriver = class {
|
|
|
2744
2857
|
|
|
2745
2858
|
// src/drivers/codex.ts
|
|
2746
2859
|
import { spawn as spawn2, execFileSync as execFileSync2, execSync } from "child_process";
|
|
2747
|
-
import { existsSync as
|
|
2748
|
-
import
|
|
2860
|
+
import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
|
|
2861
|
+
import os2 from "os";
|
|
2749
2862
|
import path5 from "path";
|
|
2750
2863
|
|
|
2751
2864
|
// src/runtimeTurnState.ts
|
|
@@ -3107,7 +3220,7 @@ var CodexEventNormalizer = class {
|
|
|
3107
3220
|
|
|
3108
3221
|
// src/drivers/codex.ts
|
|
3109
3222
|
function ensureGitRepoForCodex(workingDirectory, deps = {}) {
|
|
3110
|
-
const existsSyncFn = deps.existsSyncFn ??
|
|
3223
|
+
const existsSyncFn = deps.existsSyncFn ?? existsSync3;
|
|
3111
3224
|
const execSyncFn = deps.execSyncFn ?? execSync;
|
|
3112
3225
|
const gitDir = path5.join(workingDirectory, ".git");
|
|
3113
3226
|
if (existsSyncFn(gitDir)) return;
|
|
@@ -3125,7 +3238,7 @@ function isWindowsSandboxRunner(commandPath) {
|
|
|
3125
3238
|
return path5.basename(commandPath).toLowerCase().startsWith("codex-command-runner");
|
|
3126
3239
|
}
|
|
3127
3240
|
function resolveWindowsNpmCodexEntry(deps = {}) {
|
|
3128
|
-
const existsSyncFn = deps.existsSyncFn ??
|
|
3241
|
+
const existsSyncFn = deps.existsSyncFn ?? existsSync3;
|
|
3129
3242
|
const execFileSyncFn = deps.execFileSyncFn ?? execFileSync2;
|
|
3130
3243
|
const env = deps.env ?? process.env;
|
|
3131
3244
|
const winPath = path5.win32;
|
|
@@ -3147,7 +3260,7 @@ function resolveWindowsNpmCodexEntry(deps = {}) {
|
|
|
3147
3260
|
return null;
|
|
3148
3261
|
}
|
|
3149
3262
|
function resolveWindowsCodexDesktopEntry(deps = {}) {
|
|
3150
|
-
const existsSyncFn = deps.existsSyncFn ??
|
|
3263
|
+
const existsSyncFn = deps.existsSyncFn ?? existsSync3;
|
|
3151
3264
|
const env = deps.env ?? process.env;
|
|
3152
3265
|
const homeDir = deps.homeDir;
|
|
3153
3266
|
const winPath = path5.win32;
|
|
@@ -3299,11 +3412,15 @@ var CodexDriver = class {
|
|
|
3299
3412
|
// the daemon. They replace the previous transcript-mtime heuristic.
|
|
3300
3413
|
experimentalRawEvents: true
|
|
3301
3414
|
};
|
|
3302
|
-
|
|
3303
|
-
|
|
3415
|
+
const launchRuntimeFields = runtimeConfigToLaunchFields(ctx.config);
|
|
3416
|
+
if (launchRuntimeFields.model) {
|
|
3417
|
+
threadParams.model = launchRuntimeFields.model;
|
|
3418
|
+
}
|
|
3419
|
+
if (launchRuntimeFields.reasoningEffort) {
|
|
3420
|
+
threadParams.config = { model_reasoning_effort: launchRuntimeFields.reasoningEffort };
|
|
3304
3421
|
}
|
|
3305
|
-
if (
|
|
3306
|
-
threadParams.
|
|
3422
|
+
if (launchRuntimeFields.mode.kind === "fast") {
|
|
3423
|
+
threadParams.serviceTier = "priority";
|
|
3307
3424
|
}
|
|
3308
3425
|
if (ctx.config.sessionId) {
|
|
3309
3426
|
return {
|
|
@@ -3459,12 +3576,12 @@ var CodexDriver = class {
|
|
|
3459
3576
|
return detectCodexModels();
|
|
3460
3577
|
}
|
|
3461
3578
|
};
|
|
3462
|
-
function detectCodexModels(home =
|
|
3579
|
+
function detectCodexModels(home = os2.homedir()) {
|
|
3463
3580
|
const cachePath = path5.join(home, ".codex", "models_cache.json");
|
|
3464
3581
|
const configPath = path5.join(home, ".codex", "config.toml");
|
|
3465
3582
|
let models = [];
|
|
3466
3583
|
try {
|
|
3467
|
-
const raw =
|
|
3584
|
+
const raw = readFileSync2(cachePath, "utf8");
|
|
3468
3585
|
const parsed = JSON.parse(raw);
|
|
3469
3586
|
const entries = Array.isArray(parsed?.models) ? parsed.models : [];
|
|
3470
3587
|
for (const entry of entries) {
|
|
@@ -3481,7 +3598,7 @@ function detectCodexModels(home = os3.homedir()) {
|
|
|
3481
3598
|
if (models.length === 0) return null;
|
|
3482
3599
|
let defaultModel;
|
|
3483
3600
|
try {
|
|
3484
|
-
const raw =
|
|
3601
|
+
const raw = readFileSync2(configPath, "utf8");
|
|
3485
3602
|
const match = raw.match(/^\s*model\s*=\s*"([^"]+)"/m);
|
|
3486
3603
|
if (match) defaultModel = match[1];
|
|
3487
3604
|
} catch {
|
|
@@ -3512,7 +3629,7 @@ function buildAntigravityArgs(ctx) {
|
|
|
3512
3629
|
const args = [
|
|
3513
3630
|
"--print",
|
|
3514
3631
|
"--print-timeout",
|
|
3515
|
-
ctx.config.envVars?.ANTIGRAVITY_PRINT_TIMEOUT || DEFAULT_PRINT_TIMEOUT,
|
|
3632
|
+
runtimeConfigToLaunchFields(ctx.config).envVars?.ANTIGRAVITY_PRINT_TIMEOUT || DEFAULT_PRINT_TIMEOUT,
|
|
3516
3633
|
"--dangerously-skip-permissions"
|
|
3517
3634
|
];
|
|
3518
3635
|
if (ctx.config.sessionId) {
|
|
@@ -3691,11 +3808,12 @@ var CopilotDriver = class {
|
|
|
3691
3808
|
"-p",
|
|
3692
3809
|
ctx.prompt
|
|
3693
3810
|
];
|
|
3694
|
-
|
|
3695
|
-
|
|
3811
|
+
const launchRuntimeFields = runtimeConfigToLaunchFields(ctx.config);
|
|
3812
|
+
if (launchRuntimeFields.model && launchRuntimeFields.model !== "default") {
|
|
3813
|
+
args.push("--model", launchRuntimeFields.model);
|
|
3696
3814
|
}
|
|
3697
|
-
if (
|
|
3698
|
-
args.push("--effort",
|
|
3815
|
+
if (launchRuntimeFields.reasoningEffort) {
|
|
3816
|
+
args.push("--effort", launchRuntimeFields.reasoningEffort);
|
|
3699
3817
|
}
|
|
3700
3818
|
if (ctx.config.sessionId) {
|
|
3701
3819
|
args.push(`--resume=${ctx.config.sessionId}`);
|
|
@@ -3795,7 +3913,7 @@ var CopilotDriver = class {
|
|
|
3795
3913
|
|
|
3796
3914
|
// src/drivers/cursor.ts
|
|
3797
3915
|
import { spawn as spawn5, spawnSync } from "child_process";
|
|
3798
|
-
import { writeFileSync as writeFileSync4, mkdirSync as mkdirSync2, existsSync as
|
|
3916
|
+
import { writeFileSync as writeFileSync4, mkdirSync as mkdirSync2, existsSync as existsSync4 } from "fs";
|
|
3799
3917
|
import path7 from "path";
|
|
3800
3918
|
async function buildCursorSpawnEnv(ctx, deps = {}) {
|
|
3801
3919
|
const { spawnEnv } = await prepareCliTransport(ctx, { NO_COLOR: "1" });
|
|
@@ -3851,7 +3969,7 @@ var CursorDriver = class {
|
|
|
3851
3969
|
}
|
|
3852
3970
|
async spawn(ctx) {
|
|
3853
3971
|
const cursorDir = path7.join(ctx.workingDirectory, ".cursor");
|
|
3854
|
-
if (!
|
|
3972
|
+
if (!existsSync4(cursorDir)) {
|
|
3855
3973
|
mkdirSync2(cursorDir, { recursive: true });
|
|
3856
3974
|
}
|
|
3857
3975
|
const mcpConfigPath = path7.join(cursorDir, "mcp.json");
|
|
@@ -3864,8 +3982,9 @@ var CursorDriver = class {
|
|
|
3864
3982
|
"--approve-mcps",
|
|
3865
3983
|
"--trust"
|
|
3866
3984
|
];
|
|
3867
|
-
|
|
3868
|
-
|
|
3985
|
+
const launchRuntimeFields = runtimeConfigToLaunchFields(ctx.config);
|
|
3986
|
+
if (launchRuntimeFields.model && launchRuntimeFields.model !== "default") {
|
|
3987
|
+
args.push("--model", launchRuntimeFields.model);
|
|
3869
3988
|
}
|
|
3870
3989
|
if (ctx.config.sessionId) {
|
|
3871
3990
|
args.push("--resume", ctx.config.sessionId);
|
|
@@ -4000,14 +4119,15 @@ function runCursorModelsCommand() {
|
|
|
4000
4119
|
|
|
4001
4120
|
// src/drivers/gemini.ts
|
|
4002
4121
|
import { execFileSync as execFileSync3, spawn as spawn6 } from "child_process";
|
|
4003
|
-
import { existsSync as
|
|
4122
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync3, writeFileSync as writeFileSync5 } from "fs";
|
|
4004
4123
|
import path8 from "path";
|
|
4005
4124
|
async function buildGeminiSpawnEnv(ctx, platform = process.platform) {
|
|
4006
4125
|
const { spawnEnv } = await prepareCliTransport(ctx, { NO_COLOR: "1" }, platform);
|
|
4007
|
-
|
|
4126
|
+
const launchEnvVars = runtimeConfigToLaunchFields(ctx.config).envVars;
|
|
4127
|
+
if (!Object.prototype.hasOwnProperty.call(launchEnvVars ?? {}, "GEMINI_CLI_TRUST_WORKSPACE")) {
|
|
4008
4128
|
spawnEnv.GEMINI_CLI_TRUST_WORKSPACE = "true";
|
|
4009
4129
|
}
|
|
4010
|
-
if (platform === "win32" && !Object.prototype.hasOwnProperty.call(
|
|
4130
|
+
if (platform === "win32" && !Object.prototype.hasOwnProperty.call(launchEnvVars ?? {}, "GEMINI_PTY_INFO")) {
|
|
4011
4131
|
spawnEnv.GEMINI_PTY_INFO = "child_process";
|
|
4012
4132
|
}
|
|
4013
4133
|
return spawnEnv;
|
|
@@ -4027,8 +4147,9 @@ function buildGeminiArgs(config) {
|
|
|
4027
4147
|
"-p",
|
|
4028
4148
|
""
|
|
4029
4149
|
];
|
|
4030
|
-
|
|
4031
|
-
|
|
4150
|
+
const launchRuntimeFields = runtimeConfigToLaunchFields(config);
|
|
4151
|
+
if (launchRuntimeFields.model && launchRuntimeFields.model !== "default") {
|
|
4152
|
+
args.push("--model", launchRuntimeFields.model);
|
|
4032
4153
|
}
|
|
4033
4154
|
if (config.sessionId) {
|
|
4034
4155
|
args.push("--resume", config.sessionId);
|
|
@@ -4041,7 +4162,7 @@ function resolveGeminiSpawn(commandArgs, deps = {}) {
|
|
|
4041
4162
|
return { command: resolveCommandOnPath("gemini", deps) ?? "gemini", args: commandArgs };
|
|
4042
4163
|
}
|
|
4043
4164
|
const execFileSyncFn = deps.execFileSyncFn ?? execFileSync3;
|
|
4044
|
-
const existsSyncFn = deps.existsSyncFn ??
|
|
4165
|
+
const existsSyncFn = deps.existsSyncFn ?? existsSync5;
|
|
4045
4166
|
const env = deps.env ?? process.env;
|
|
4046
4167
|
const winPath = path8.win32;
|
|
4047
4168
|
let geminiEntry = null;
|
|
@@ -4214,8 +4335,8 @@ var GeminiDriver = class {
|
|
|
4214
4335
|
// src/drivers/kimi.ts
|
|
4215
4336
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
4216
4337
|
import { spawn as spawn7 } from "child_process";
|
|
4217
|
-
import { existsSync as
|
|
4218
|
-
import
|
|
4338
|
+
import { existsSync as existsSync6, readFileSync as readFileSync3, writeFileSync as writeFileSync6 } from "fs";
|
|
4339
|
+
import os3 from "os";
|
|
4219
4340
|
import path9 from "path";
|
|
4220
4341
|
var KIMI_WIRE_PROTOCOL_VERSION = "1.3";
|
|
4221
4342
|
var KIMI_SYSTEM_PROMPT_FILE = ".slock-kimi-system.md";
|
|
@@ -4288,7 +4409,7 @@ var KimiDriver = class {
|
|
|
4288
4409
|
const systemPromptPath = path9.join(ctx.workingDirectory, KIMI_SYSTEM_PROMPT_FILE);
|
|
4289
4410
|
const agentFilePath = path9.join(ctx.workingDirectory, KIMI_AGENT_FILE);
|
|
4290
4411
|
const mcpConfigPath = path9.join(ctx.workingDirectory, KIMI_MCP_FILE);
|
|
4291
|
-
if (!isResume || !
|
|
4412
|
+
if (!isResume || !existsSync6(systemPromptPath)) {
|
|
4292
4413
|
writeFileSync6(systemPromptPath, ctx.prompt, "utf8");
|
|
4293
4414
|
}
|
|
4294
4415
|
writeFileSync6(agentFilePath, [
|
|
@@ -4316,8 +4437,9 @@ var KimiDriver = class {
|
|
|
4316
4437
|
"--session",
|
|
4317
4438
|
this.sessionId
|
|
4318
4439
|
];
|
|
4319
|
-
|
|
4320
|
-
|
|
4440
|
+
const launchRuntimeFields = runtimeConfigToLaunchFields(ctx.config);
|
|
4441
|
+
if (launchRuntimeFields.model && launchRuntimeFields.model !== "default") {
|
|
4442
|
+
args.push("--model", launchRuntimeFields.model);
|
|
4321
4443
|
}
|
|
4322
4444
|
const spawnEnv = (await prepareCliTransport(ctx, { NO_COLOR: "1" })).spawnEnv;
|
|
4323
4445
|
const launch = resolveKimiSpawn(args);
|
|
@@ -4443,11 +4565,11 @@ var KimiDriver = class {
|
|
|
4443
4565
|
return detectKimiModels();
|
|
4444
4566
|
}
|
|
4445
4567
|
};
|
|
4446
|
-
function detectKimiModels(home =
|
|
4568
|
+
function detectKimiModels(home = os3.homedir()) {
|
|
4447
4569
|
const configPath = path9.join(home, ".kimi", "config.toml");
|
|
4448
4570
|
let raw;
|
|
4449
4571
|
try {
|
|
4450
|
-
raw =
|
|
4572
|
+
raw = readFileSync3(configPath, "utf8");
|
|
4451
4573
|
} catch {
|
|
4452
4574
|
return null;
|
|
4453
4575
|
}
|
|
@@ -4471,8 +4593,8 @@ function detectKimiModels(home = os4.homedir()) {
|
|
|
4471
4593
|
|
|
4472
4594
|
// src/drivers/opencode.ts
|
|
4473
4595
|
import { spawn as spawn8, spawnSync as spawnSync2 } from "child_process";
|
|
4474
|
-
import { existsSync as
|
|
4475
|
-
import
|
|
4596
|
+
import { existsSync as existsSync7, readFileSync as readFileSync4 } from "fs";
|
|
4597
|
+
import os4 from "os";
|
|
4476
4598
|
import path10 from "path";
|
|
4477
4599
|
var CHAT_MCP_SERVER_NAME = "chat";
|
|
4478
4600
|
var CHAT_MCP_TOOL_PREFIX = `${CHAT_MCP_SERVER_NAME}_`;
|
|
@@ -4517,13 +4639,13 @@ function parseOpenCodeConfigContent(raw) {
|
|
|
4517
4639
|
return {};
|
|
4518
4640
|
}
|
|
4519
4641
|
function parseUserOpenCodeConfig(ctx) {
|
|
4520
|
-
const raw = ctx.config.envVars?.OPENCODE_CONFIG_CONTENT;
|
|
4642
|
+
const raw = runtimeConfigToLaunchFields(ctx.config).envVars?.OPENCODE_CONFIG_CONTENT;
|
|
4521
4643
|
return parseOpenCodeConfigContent(raw);
|
|
4522
4644
|
}
|
|
4523
|
-
function readLocalOpenCodeConfig(home =
|
|
4645
|
+
function readLocalOpenCodeConfig(home = os4.homedir()) {
|
|
4524
4646
|
const configPath = path10.join(home, ".config", "opencode", "opencode.json");
|
|
4525
4647
|
try {
|
|
4526
|
-
return parseOpenCodeConfigContent(
|
|
4648
|
+
return parseOpenCodeConfigContent(readFileSync4(configPath, "utf8"));
|
|
4527
4649
|
} catch {
|
|
4528
4650
|
}
|
|
4529
4651
|
return {};
|
|
@@ -4581,7 +4703,7 @@ function mergeOpenCodeConfigs(localConfig, envConfig) {
|
|
|
4581
4703
|
}
|
|
4582
4704
|
};
|
|
4583
4705
|
}
|
|
4584
|
-
function buildOpenCodeConfig(ctx, home =
|
|
4706
|
+
function buildOpenCodeConfig(ctx, home = os4.homedir()) {
|
|
4585
4707
|
const userConfig = mergeOpenCodeConfigs(readLocalOpenCodeConfig(home), parseUserOpenCodeConfig(ctx));
|
|
4586
4708
|
const userAgents = recordField(userConfig.agent);
|
|
4587
4709
|
const userSlockAgent = recordField(userAgents[SLOCK_AGENT_NAME]);
|
|
@@ -4606,7 +4728,7 @@ function buildOpenCodeConfig(ctx, home = os5.homedir()) {
|
|
|
4606
4728
|
}
|
|
4607
4729
|
};
|
|
4608
4730
|
}
|
|
4609
|
-
async function buildOpenCodeLaunchOptions(ctx, home =
|
|
4731
|
+
async function buildOpenCodeLaunchOptions(ctx, home = os4.homedir(), version = null) {
|
|
4610
4732
|
const slock = await prepareCliTransport(ctx, { NO_COLOR: "1" });
|
|
4611
4733
|
const config = buildOpenCodeConfig(ctx, home);
|
|
4612
4734
|
const env = {
|
|
@@ -4622,8 +4744,9 @@ async function buildOpenCodeLaunchOptions(ctx, home = os5.homedir(), version = n
|
|
|
4622
4744
|
"--dir",
|
|
4623
4745
|
ctx.workingDirectory
|
|
4624
4746
|
];
|
|
4625
|
-
|
|
4626
|
-
|
|
4747
|
+
const launchRuntimeFields = runtimeConfigToLaunchFields(ctx.config);
|
|
4748
|
+
if (launchRuntimeFields.model && launchRuntimeFields.model !== "default") {
|
|
4749
|
+
args.push("--model", launchRuntimeFields.model);
|
|
4627
4750
|
}
|
|
4628
4751
|
if (requiresAgentCliFlag(version)) {
|
|
4629
4752
|
args.push("--agent", SLOCK_AGENT_NAME);
|
|
@@ -4704,7 +4827,7 @@ function formatOpenCodeLabelToken(token) {
|
|
|
4704
4827
|
if (/^\d/.test(token)) return token;
|
|
4705
4828
|
return normalized.charAt(0).toUpperCase() + normalized.slice(1);
|
|
4706
4829
|
}
|
|
4707
|
-
function detectOpenCodeModels(home =
|
|
4830
|
+
function detectOpenCodeModels(home = os4.homedir(), runCommand = runOpenCodeModelsCommand) {
|
|
4708
4831
|
const commandResult = runCommand(home);
|
|
4709
4832
|
if (commandResult.error || commandResult.status !== 0) return null;
|
|
4710
4833
|
return parseOpenCodeModelsOutput(commandResult.stdout);
|
|
@@ -4744,7 +4867,7 @@ function openCodeSpecForEntry(entry, commandArgs) {
|
|
|
4744
4867
|
return { command: process.execPath, args: [entry, ...commandArgs], shell: false };
|
|
4745
4868
|
}
|
|
4746
4869
|
function resolveWindowsOpenCodePackageEntry(commandPath, deps = {}) {
|
|
4747
|
-
const existsSyncFn = deps.existsSyncFn ??
|
|
4870
|
+
const existsSyncFn = deps.existsSyncFn ?? existsSync7;
|
|
4748
4871
|
const execFileSyncFn = deps.execFileSyncFn;
|
|
4749
4872
|
const env = deps.env ?? process.env;
|
|
4750
4873
|
const winPath = path10.win32;
|
|
@@ -4774,7 +4897,7 @@ function resolveWindowsOpenCodePackageEntry(commandPath, deps = {}) {
|
|
|
4774
4897
|
}
|
|
4775
4898
|
function extractWindowsShimTargets(commandPath, deps = {}) {
|
|
4776
4899
|
if (!isWindowsCommandShim(commandPath)) return [];
|
|
4777
|
-
const readFileSyncFn = deps.readFileSyncFn ??
|
|
4900
|
+
const readFileSyncFn = deps.readFileSyncFn ?? readFileSync4;
|
|
4778
4901
|
const commandDir = path10.win32.dirname(commandPath);
|
|
4779
4902
|
let raw;
|
|
4780
4903
|
try {
|
|
@@ -4908,7 +5031,7 @@ var OpenCodeDriver = class {
|
|
|
4908
5031
|
if (unsupportedMessage) {
|
|
4909
5032
|
throw new Error(unsupportedMessage);
|
|
4910
5033
|
}
|
|
4911
|
-
const launch = await buildOpenCodeLaunchOptions(ctx,
|
|
5034
|
+
const launch = await buildOpenCodeLaunchOptions(ctx, os4.homedir(), version);
|
|
4912
5035
|
const spawnSpec = resolveOpenCodeSpawn(launch.args);
|
|
4913
5036
|
const proc = spawn8(spawnSpec.command, spawnSpec.args, {
|
|
4914
5037
|
cwd: ctx.workingDirectory,
|
|
@@ -5500,7 +5623,7 @@ function findSessionJsonl(root, predicate) {
|
|
|
5500
5623
|
if (depth < 0 || visited >= maxEntries) return null;
|
|
5501
5624
|
let entries;
|
|
5502
5625
|
try {
|
|
5503
|
-
entries =
|
|
5626
|
+
entries = readdirSync(dir, { withFileTypes: true }).sort((a, b) => b.name.localeCompare(a.name));
|
|
5504
5627
|
} catch {
|
|
5505
5628
|
return null;
|
|
5506
5629
|
}
|
|
@@ -5546,11 +5669,11 @@ function writeRuntimeSessionHandoff(runtime, sessionId, fallbackDir) {
|
|
|
5546
5669
|
return null;
|
|
5547
5670
|
}
|
|
5548
5671
|
}
|
|
5549
|
-
function resolveRuntimeSessionRef(runtime, sessionId, homeDir =
|
|
5672
|
+
function resolveRuntimeSessionRef(runtime, sessionId, homeDir = os5.homedir(), fallbackDir) {
|
|
5550
5673
|
const directPath = path12.isAbsolute(sessionId) ? sessionId : null;
|
|
5551
5674
|
if (directPath) {
|
|
5552
5675
|
try {
|
|
5553
|
-
if (
|
|
5676
|
+
if (statSync(directPath).isFile()) {
|
|
5554
5677
|
return { label: sessionId, path: directPath, runtime, reachable: true };
|
|
5555
5678
|
}
|
|
5556
5679
|
} catch {
|
|
@@ -6504,7 +6627,7 @@ var AgentProcessManager = class _AgentProcessManager {
|
|
|
6504
6627
|
this.daemonApiKey = daemonApiKey;
|
|
6505
6628
|
this.serverUrl = opts.serverUrl;
|
|
6506
6629
|
this.dataDir = opts.dataDir || resolveSlockHomePath("agents");
|
|
6507
|
-
this.runtimeSessionHomeDir = opts.runtimeSessionHomeDir ||
|
|
6630
|
+
this.runtimeSessionHomeDir = opts.runtimeSessionHomeDir || os5.homedir();
|
|
6508
6631
|
this.driverResolver = opts.driverResolver || getDriver;
|
|
6509
6632
|
this.defaultAgentEnvVarsProvider = opts.defaultAgentEnvVarsProvider || null;
|
|
6510
6633
|
this.tracer = opts.tracer ?? noopTracer;
|
|
@@ -7388,7 +7511,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
7388
7511
|
"X-Slock-Client": "daemon-server-session-worker"
|
|
7389
7512
|
},
|
|
7390
7513
|
body: JSON.stringify({
|
|
7391
|
-
scopes: ["send", "read", "mentions", "tasks", "reactions", "server", "channels"],
|
|
7514
|
+
scopes: ["send", "read", "mentions", "tasks", "reactions", "server", "channels", "knowledge"],
|
|
7392
7515
|
name: `runner:${config.runtime}:${agentId.slice(0, 8)}`
|
|
7393
7516
|
})
|
|
7394
7517
|
});
|
|
@@ -8199,7 +8322,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
8199
8322
|
async listSkills(agentId, runtimeHint) {
|
|
8200
8323
|
const agent = this.agents.get(agentId);
|
|
8201
8324
|
const runtime = runtimeHint || agent?.config.runtime || "claude";
|
|
8202
|
-
const home =
|
|
8325
|
+
const home = os5.homedir();
|
|
8203
8326
|
const workspaceDir = path12.join(this.dataDir, agentId);
|
|
8204
8327
|
const paths = _AgentProcessManager.SKILL_PATHS[runtime] || _AgentProcessManager.SKILL_PATHS.claude;
|
|
8205
8328
|
const globalResults = await Promise.all(
|
|
@@ -9626,8 +9749,8 @@ var ReminderCache = class {
|
|
|
9626
9749
|
|
|
9627
9750
|
// src/machineLock.ts
|
|
9628
9751
|
import { createHash as createHash3, randomUUID as randomUUID3 } from "crypto";
|
|
9629
|
-
import { mkdirSync as mkdirSync5, readFileSync as
|
|
9630
|
-
import
|
|
9752
|
+
import { mkdirSync as mkdirSync5, readFileSync as readFileSync5, rmSync as rmSync3, statSync as statSync2, writeFileSync as writeFileSync8 } from "fs";
|
|
9753
|
+
import os6 from "os";
|
|
9631
9754
|
import path13 from "path";
|
|
9632
9755
|
var INCOMPLETE_LOCK_STALE_MS = 3e4;
|
|
9633
9756
|
var DaemonMachineLockConflictError = class extends Error {
|
|
@@ -9654,14 +9777,14 @@ function ownerPath(lockDir) {
|
|
|
9654
9777
|
}
|
|
9655
9778
|
function readOwner(lockDir) {
|
|
9656
9779
|
try {
|
|
9657
|
-
return JSON.parse(
|
|
9780
|
+
return JSON.parse(readFileSync5(ownerPath(lockDir), "utf8"));
|
|
9658
9781
|
} catch {
|
|
9659
9782
|
return null;
|
|
9660
9783
|
}
|
|
9661
9784
|
}
|
|
9662
9785
|
function lockAgeMs(lockDir) {
|
|
9663
9786
|
try {
|
|
9664
|
-
return Date.now() -
|
|
9787
|
+
return Date.now() - statSync2(lockDir).mtimeMs;
|
|
9665
9788
|
} catch {
|
|
9666
9789
|
return null;
|
|
9667
9790
|
}
|
|
@@ -9690,7 +9813,7 @@ function acquireDaemonMachineLock(options) {
|
|
|
9690
9813
|
const owner = {
|
|
9691
9814
|
pid: process.pid,
|
|
9692
9815
|
token,
|
|
9693
|
-
hostname:
|
|
9816
|
+
hostname: os6.hostname(),
|
|
9694
9817
|
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9695
9818
|
serverUrl: options.serverUrl,
|
|
9696
9819
|
apiKeyFingerprint: fingerprint.slice(0, 16)
|
|
@@ -9733,7 +9856,7 @@ function acquireDaemonMachineLock(options) {
|
|
|
9733
9856
|
}
|
|
9734
9857
|
|
|
9735
9858
|
// src/localTraceSink.ts
|
|
9736
|
-
import { appendFileSync, mkdirSync as mkdirSync6, readdirSync as
|
|
9859
|
+
import { appendFileSync, mkdirSync as mkdirSync6, readdirSync as readdirSync2, rmSync as rmSync4, statSync as statSync3, writeFileSync as writeFileSync9 } from "fs";
|
|
9737
9860
|
import path14 from "path";
|
|
9738
9861
|
var DEFAULT_MAX_FILE_BYTES = 5 * 1024 * 1024;
|
|
9739
9862
|
var DEFAULT_MAX_FILE_AGE_MS = 5 * 60 * 1e3;
|
|
@@ -9805,13 +9928,13 @@ var LocalRotatingTraceSink = class {
|
|
|
9805
9928
|
`daemon-trace-${safeTimestamp(nowMs)}-${process.pid}-${String(this.sequence++).padStart(4, "0")}.jsonl`
|
|
9806
9929
|
);
|
|
9807
9930
|
writeFileSync9(this.currentFile, "", { flag: "a", mode: 384 });
|
|
9808
|
-
this.currentSize =
|
|
9931
|
+
this.currentSize = statSync3(this.currentFile).size;
|
|
9809
9932
|
this.currentFileOpenedAtMs = nowMs;
|
|
9810
9933
|
this.pruneOldFiles();
|
|
9811
9934
|
}
|
|
9812
9935
|
}
|
|
9813
9936
|
pruneOldFiles() {
|
|
9814
|
-
const files =
|
|
9937
|
+
const files = readdirSync2(this.traceDir).filter((name) => name.startsWith("daemon-trace-") && name.endsWith(".jsonl")).sort();
|
|
9815
9938
|
const excess = files.length - this.maxFiles;
|
|
9816
9939
|
if (excess <= 0) return;
|
|
9817
9940
|
for (const file of files.slice(0, excess)) {
|
|
@@ -10246,7 +10369,7 @@ function readPositiveIntegerEnv2(name, fallback) {
|
|
|
10246
10369
|
|
|
10247
10370
|
// src/core.ts
|
|
10248
10371
|
var DEFAULT_TRACE_UPLOAD_URL = "https://slock-trace-upload.botiverse.dev";
|
|
10249
|
-
var RUNNER_CREDENTIAL_SCOPES = ["send", "read", "mentions", "tasks", "reactions", "server", "channels"];
|
|
10372
|
+
var RUNNER_CREDENTIAL_SCOPES = ["send", "read", "mentions", "tasks", "reactions", "server", "channels", "knowledge"];
|
|
10250
10373
|
var RUNNER_CREDENTIAL_MINT_MAX_ATTEMPTS2 = 3;
|
|
10251
10374
|
var RUNNER_CREDENTIAL_MINT_RETRY_DELAY_MS2 = 250;
|
|
10252
10375
|
var DAEMON_CLI_USAGE = "Usage: slock-daemon --server-url <url> --api-key <key>";
|
|
@@ -10947,8 +11070,8 @@ var DaemonCore = class {
|
|
|
10947
11070
|
capabilities: ["agent:start", "agent:stop", "agent:deliver", "workspace:files"],
|
|
10948
11071
|
runtimes,
|
|
10949
11072
|
runningAgents: runningAgentIds,
|
|
10950
|
-
hostname: this.options.hostname ??
|
|
10951
|
-
os: this.options.osDescription ?? `${
|
|
11073
|
+
hostname: this.options.hostname ?? os7.hostname(),
|
|
11074
|
+
os: this.options.osDescription ?? `${os7.platform()} ${os7.arch()}`,
|
|
10952
11075
|
daemonVersion: this.daemonVersion
|
|
10953
11076
|
});
|
|
10954
11077
|
this.recordDaemonTrace("daemon.ready.sent", {
|