@slock-ai/daemon 0.55.5 → 0.55.7-play.20260602150229
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-NXNXMFLC.js → chunk-OV4XD66N.js} +640 -125
- package/dist/cli/index.js +56 -2
- package/dist/core.js +6 -2
- package/dist/drivers/piSdkRunner.js +96 -0
- package/dist/index.js +5 -3
- package/package.json +3 -1
|
@@ -360,6 +360,40 @@ var NoopActiveSpan = class {
|
|
|
360
360
|
}
|
|
361
361
|
};
|
|
362
362
|
var noopTracer = new NoopTracer();
|
|
363
|
+
function createScopedTracer(tracer, scopeAttrs) {
|
|
364
|
+
if (!Object.keys(scopeAttrs).length) return tracer;
|
|
365
|
+
return new ScopedTracer(tracer, scopeAttrs);
|
|
366
|
+
}
|
|
367
|
+
var ScopedTracer = class {
|
|
368
|
+
constructor(tracer, scopeAttrs) {
|
|
369
|
+
this.tracer = tracer;
|
|
370
|
+
this.scopeAttrs = scopeAttrs;
|
|
371
|
+
}
|
|
372
|
+
startSpan(name, options) {
|
|
373
|
+
const span = this.tracer.startSpan(name, {
|
|
374
|
+
...options,
|
|
375
|
+
attrs: mergeAttrs(options.attrs, this.scopeAttrs)
|
|
376
|
+
});
|
|
377
|
+
return new ScopedActiveSpan(span, this.scopeAttrs);
|
|
378
|
+
}
|
|
379
|
+
};
|
|
380
|
+
var ScopedActiveSpan = class {
|
|
381
|
+
constructor(span, scopeAttrs) {
|
|
382
|
+
this.span = span;
|
|
383
|
+
this.scopeAttrs = scopeAttrs;
|
|
384
|
+
this.context = span.context;
|
|
385
|
+
}
|
|
386
|
+
context;
|
|
387
|
+
addEvent(name, attrs) {
|
|
388
|
+
this.span.addEvent(name, mergeAttrs(attrs, this.scopeAttrs));
|
|
389
|
+
}
|
|
390
|
+
end(status, options) {
|
|
391
|
+
this.span.end(status, options ? {
|
|
392
|
+
...options,
|
|
393
|
+
attrs: mergeAttrs(options.attrs, this.scopeAttrs)
|
|
394
|
+
} : void 0);
|
|
395
|
+
}
|
|
396
|
+
};
|
|
363
397
|
var BasicTracer = class {
|
|
364
398
|
sink;
|
|
365
399
|
clock;
|
|
@@ -904,6 +938,26 @@ var actionCardActionSchema = z.discriminatedUnion("type", [
|
|
|
904
938
|
channelAddMemberOperationSchema
|
|
905
939
|
]);
|
|
906
940
|
|
|
941
|
+
// ../shared/src/agentInbox.ts
|
|
942
|
+
function formatAgentInboxDelta(rows) {
|
|
943
|
+
if (rows.length === 0) return "Inbox update: no pending targets";
|
|
944
|
+
return [
|
|
945
|
+
`Inbox update: ${rows.length} changed target${rows.length === 1 ? "" : "s"}`,
|
|
946
|
+
...rows.map((row) => `${row.target} ${formatAgentInboxRowDetails(row)}`)
|
|
947
|
+
].join("\n");
|
|
948
|
+
}
|
|
949
|
+
function formatAgentInboxRowDetails(row) {
|
|
950
|
+
const parts = [`pending: ${row.pendingCount} message${row.pendingCount === 1 ? "" : "s"}`];
|
|
951
|
+
if (row.firstPendingMsgId) parts.push(`first msg=${shortMessageId(row.firstPendingMsgId)}`);
|
|
952
|
+
if (row.latestSenderName) parts.push(`latest @${row.latestSenderName}`);
|
|
953
|
+
if (row.latestMsgId) parts.push(`latest msg=${shortMessageId(row.latestMsgId)}`);
|
|
954
|
+
parts.push(...row.flags);
|
|
955
|
+
return parts.join(" \xB7 ");
|
|
956
|
+
}
|
|
957
|
+
function shortMessageId(value) {
|
|
958
|
+
return value.slice(0, 8);
|
|
959
|
+
}
|
|
960
|
+
|
|
907
961
|
// ../shared/src/translationLanguages.ts
|
|
908
962
|
var SUPPORTED_TRANSLATION_LANGUAGE_CODES = [
|
|
909
963
|
"en",
|
|
@@ -996,7 +1050,7 @@ var RUNTIMES = [
|
|
|
996
1050
|
{ id: "cursor", displayName: "Cursor CLI", binary: "cursor-agent", supported: true },
|
|
997
1051
|
{ id: "gemini", displayName: "Gemini CLI", binary: "gemini", supported: true },
|
|
998
1052
|
{ id: "opencode", displayName: "OpenCode", binary: "opencode", supported: true },
|
|
999
|
-
{ id: "pi", displayName: "Pi
|
|
1053
|
+
{ id: "pi", displayName: "Pi", binary: "pi", supported: true }
|
|
1000
1054
|
];
|
|
1001
1055
|
var RUNTIME_MODELS = {
|
|
1002
1056
|
claude: [
|
|
@@ -1049,9 +1103,7 @@ var RUNTIME_MODELS = {
|
|
|
1049
1103
|
{ id: "fusecode/opus[1m]", label: "Opus 1M via FuseCode", verified: "suggestion_only" }
|
|
1050
1104
|
],
|
|
1051
1105
|
pi: [
|
|
1052
|
-
{ id: "default", label: "Configured Default / Auto", verified: "suggestion_only" }
|
|
1053
|
-
{ id: "deepseek/deepseek-v4-pro", label: "DeepSeek V4 Pro (Pi)", verified: "suggestion_only" },
|
|
1054
|
-
{ id: "deepseek/deepseek-v4-flash", label: "DeepSeek V4 Flash (Pi)", verified: "suggestion_only" }
|
|
1106
|
+
{ id: "default", label: "Configured Default / Auto", verified: "suggestion_only" }
|
|
1055
1107
|
],
|
|
1056
1108
|
// Kimi CLI resolves model keys from each user's local config, so the safest
|
|
1057
1109
|
// built-in option is to defer to whatever default model the CLI already uses.
|
|
@@ -1208,7 +1260,7 @@ var DISPLAY_PLAN_CONFIG = {
|
|
|
1208
1260
|
};
|
|
1209
1261
|
|
|
1210
1262
|
// src/agentProcessManager.ts
|
|
1211
|
-
import { mkdirSync as mkdirSync5, readdirSync, statSync, writeFileSync as writeFileSync7 } from "fs";
|
|
1263
|
+
import { mkdirSync as mkdirSync5, readdirSync as readdirSync2, statSync, writeFileSync as writeFileSync7 } from "fs";
|
|
1212
1264
|
import { mkdir, writeFile, access, readdir as readdir2, stat as stat2, readFile, rm as rm2 } from "fs/promises";
|
|
1213
1265
|
import { createHash as createHash3 } from "crypto";
|
|
1214
1266
|
import path13 from "path";
|
|
@@ -1806,6 +1858,19 @@ function listLegacySlockStatePaths(slockHome = resolveSlockHome(), homeDir = os.
|
|
|
1806
1858
|
return candidates.filter((candidate) => existsSync(candidate.path));
|
|
1807
1859
|
}
|
|
1808
1860
|
|
|
1861
|
+
// src/authEnv.ts
|
|
1862
|
+
var DAEMON_API_KEY_ENV = "SLOCK_MACHINE_API_KEY";
|
|
1863
|
+
var SLOCK_AGENT_TOKEN_ENV = "SLOCK_AGENT_TOKEN";
|
|
1864
|
+
function scrubDaemonAuthEnv(env) {
|
|
1865
|
+
delete env[DAEMON_API_KEY_ENV];
|
|
1866
|
+
return env;
|
|
1867
|
+
}
|
|
1868
|
+
function scrubDaemonChildEnv(env) {
|
|
1869
|
+
delete env[DAEMON_API_KEY_ENV];
|
|
1870
|
+
delete env[SLOCK_AGENT_TOKEN_ENV];
|
|
1871
|
+
return env;
|
|
1872
|
+
}
|
|
1873
|
+
|
|
1809
1874
|
// src/agentCredentialProxy.ts
|
|
1810
1875
|
import { randomBytes } from "crypto";
|
|
1811
1876
|
import http from "http";
|
|
@@ -2061,6 +2126,80 @@ function reduceApmGatedFlushReadiness(state, input) {
|
|
|
2061
2126
|
};
|
|
2062
2127
|
}
|
|
2063
2128
|
|
|
2129
|
+
// src/agentInboxProjection.ts
|
|
2130
|
+
function projectAgentInboxSnapshot(messages) {
|
|
2131
|
+
const buckets = /* @__PURE__ */ new Map();
|
|
2132
|
+
for (const message of messages) {
|
|
2133
|
+
const target = formatInboxMessageTarget(message);
|
|
2134
|
+
if (!target) continue;
|
|
2135
|
+
const bucket = buckets.get(target) ?? [];
|
|
2136
|
+
bucket.push(message);
|
|
2137
|
+
buckets.set(target, bucket);
|
|
2138
|
+
}
|
|
2139
|
+
return [...buckets.entries()].map(([target, bucket]) => projectBucket(target, bucket)).sort((a, b) => (b.latestSeq ?? 0) - (a.latestSeq ?? 0) || a.target.localeCompare(b.target));
|
|
2140
|
+
}
|
|
2141
|
+
function projectBucket(target, messages) {
|
|
2142
|
+
const sorted = [...messages].sort(compareInboxMessages);
|
|
2143
|
+
const first = sorted[0];
|
|
2144
|
+
const latest = sorted[sorted.length - 1];
|
|
2145
|
+
const flags = /* @__PURE__ */ new Set();
|
|
2146
|
+
for (const message of messages) {
|
|
2147
|
+
if (message.channel_type === "thread") flags.add("thread");
|
|
2148
|
+
if (message.channel_type === "dm") flags.add("dm");
|
|
2149
|
+
if (message.task_number || message.task_status) flags.add("task");
|
|
2150
|
+
if (message.mention === true || message.mentioned === true) flags.add("mention");
|
|
2151
|
+
}
|
|
2152
|
+
return stripUndefined({
|
|
2153
|
+
target,
|
|
2154
|
+
channelId: latest.channel_id ?? latest.parent_channel_id,
|
|
2155
|
+
channelType: latest.channel_type,
|
|
2156
|
+
pendingCount: messages.length,
|
|
2157
|
+
firstPendingMsgId: messageId(first),
|
|
2158
|
+
firstPendingSeq: messageSeq(first),
|
|
2159
|
+
latestMsgId: messageId(latest),
|
|
2160
|
+
latestSeq: messageSeq(latest),
|
|
2161
|
+
latestSenderName: latest.sender_name ?? latest.senderName,
|
|
2162
|
+
latestSenderType: normalizeSenderType(latest.sender_type ?? latest.senderType),
|
|
2163
|
+
flags: [...flags].sort()
|
|
2164
|
+
});
|
|
2165
|
+
}
|
|
2166
|
+
function compareInboxMessages(a, b) {
|
|
2167
|
+
return (messageSeq(a) ?? 0) - (messageSeq(b) ?? 0) || (messageId(a) ?? "").localeCompare(messageId(b) ?? "");
|
|
2168
|
+
}
|
|
2169
|
+
function formatInboxMessageTarget(message) {
|
|
2170
|
+
if (message.channel_type === "thread" && message.parent_channel_name && message.channel_name) {
|
|
2171
|
+
const shortId = shortMessageId2(String(message.channel_name).startsWith("thread-") ? String(message.channel_name).slice("thread-".length) : String(message.channel_name));
|
|
2172
|
+
if (message.parent_channel_type === "dm") return `dm:@${message.parent_channel_name}:${shortId}`;
|
|
2173
|
+
return `#${message.parent_channel_name}:${shortId}`;
|
|
2174
|
+
}
|
|
2175
|
+
if (message.channel_type === "dm" && message.channel_name) return `dm:@${message.channel_name}`;
|
|
2176
|
+
if (message.channel_name) return `#${message.channel_name}`;
|
|
2177
|
+
return null;
|
|
2178
|
+
}
|
|
2179
|
+
function messageId(message) {
|
|
2180
|
+
if (!message) return void 0;
|
|
2181
|
+
return nonEmptyString(message.message_id) ?? nonEmptyString(message.id);
|
|
2182
|
+
}
|
|
2183
|
+
function messageSeq(message) {
|
|
2184
|
+
if (!message || typeof message.seq !== "number" || !Number.isFinite(message.seq) || message.seq <= 0) return void 0;
|
|
2185
|
+
return Math.floor(message.seq);
|
|
2186
|
+
}
|
|
2187
|
+
function shortMessageId2(value) {
|
|
2188
|
+
return value.slice(0, 8);
|
|
2189
|
+
}
|
|
2190
|
+
function normalizeSenderType(value) {
|
|
2191
|
+
return value === "human" || value === "agent" || value === "system" ? value : void 0;
|
|
2192
|
+
}
|
|
2193
|
+
function nonEmptyString(value) {
|
|
2194
|
+
return typeof value === "string" && value.trim().length > 0 ? value : void 0;
|
|
2195
|
+
}
|
|
2196
|
+
function stripUndefined(value) {
|
|
2197
|
+
for (const key of Object.keys(value)) {
|
|
2198
|
+
if (value[key] === void 0) delete value[key];
|
|
2199
|
+
}
|
|
2200
|
+
return value;
|
|
2201
|
+
}
|
|
2202
|
+
|
|
2064
2203
|
// src/agentCredentialProxy.ts
|
|
2065
2204
|
var registrations = /* @__PURE__ */ new Map();
|
|
2066
2205
|
var proxyServerState = null;
|
|
@@ -2204,6 +2343,14 @@ async function handleProxyRequest(req, res) {
|
|
|
2204
2343
|
}
|
|
2205
2344
|
let sendTarget;
|
|
2206
2345
|
const sideEffectAction = agentApiSideEffectAction(target.pathname);
|
|
2346
|
+
if (method === "GET" && target.pathname === "/internal/agent-api/inbox") {
|
|
2347
|
+
const localInbox = localAgentApiInboxResponse(registration);
|
|
2348
|
+
if (localInbox) {
|
|
2349
|
+
res.writeHead(localInbox.status, { "content-type": "application/json" });
|
|
2350
|
+
res.end(JSON.stringify(localInbox.body));
|
|
2351
|
+
return;
|
|
2352
|
+
}
|
|
2353
|
+
}
|
|
2207
2354
|
if (method === "GET" && target.pathname === "/internal/agent-api/events") {
|
|
2208
2355
|
const localEvents = localAgentApiEventsResponse(registration, target);
|
|
2209
2356
|
if (localEvents) {
|
|
@@ -2347,6 +2494,7 @@ function transportNormalizedErrorForError(target, err, launchId) {
|
|
|
2347
2494
|
function routeFamilyForPath(pathname) {
|
|
2348
2495
|
if (pathname === "/internal/agent-api/send") return "agent-api/send";
|
|
2349
2496
|
if (pathname === "/internal/agent-api/events") return "agent-api/events";
|
|
2497
|
+
if (pathname === "/internal/agent-api/inbox") return "agent-api/inbox";
|
|
2350
2498
|
if (pathname === "/internal/agent-api/receive-ack") return "agent-api/events";
|
|
2351
2499
|
if (pathname === "/internal/agent-api/tasks/claim") return "tasks/claim";
|
|
2352
2500
|
if (pathname === "/internal/agent-api/tasks/update-status") return "tasks/update";
|
|
@@ -2403,13 +2551,13 @@ async function readRequestBody(req) {
|
|
|
2403
2551
|
}
|
|
2404
2552
|
return Buffer.concat(chunks);
|
|
2405
2553
|
}
|
|
2406
|
-
function
|
|
2554
|
+
function messageSeq2(message) {
|
|
2407
2555
|
return Number(message.seq ?? 0);
|
|
2408
2556
|
}
|
|
2409
2557
|
function maxMessageSeq(messages) {
|
|
2410
2558
|
let maxSeq = 0;
|
|
2411
2559
|
for (const message of messages) {
|
|
2412
|
-
const seq = Math.floor(
|
|
2560
|
+
const seq = Math.floor(messageSeq2(message));
|
|
2413
2561
|
if (Number.isFinite(seq) && seq > 0) maxSeq = Math.max(maxSeq, seq);
|
|
2414
2562
|
}
|
|
2415
2563
|
return maxSeq > 0 ? maxSeq : void 0;
|
|
@@ -2423,7 +2571,7 @@ function isSelfAuthoredMessage(registration, message) {
|
|
|
2423
2571
|
return messageSenderId(message) === registration.agentId;
|
|
2424
2572
|
}
|
|
2425
2573
|
function isMessageModelSeen(coordinator, target, message) {
|
|
2426
|
-
const seq = Math.floor(
|
|
2574
|
+
const seq = Math.floor(messageSeq2(message));
|
|
2427
2575
|
const boundary = coordinator.getBoundary(target);
|
|
2428
2576
|
if (Number.isFinite(seq) && seq > 0 && typeof boundary === "number" && boundary >= seq) return true;
|
|
2429
2577
|
return coordinator.isMessageModelSeen?.({ target, message }) === true;
|
|
@@ -2433,12 +2581,31 @@ function resolveFreshnessBoundary(messages) {
|
|
|
2433
2581
|
return typeof seenUpToSeq === "number" ? { ok: true, seenUpToSeq } : { ok: false, reason: "missing_seq_boundary" };
|
|
2434
2582
|
}
|
|
2435
2583
|
function sortBySeq(messages) {
|
|
2436
|
-
return [...messages].sort((a, b) =>
|
|
2584
|
+
return [...messages].sort((a, b) => messageSeq2(a) - messageSeq2(b));
|
|
2437
2585
|
}
|
|
2438
2586
|
function latestVisibleMessages(messages, limit) {
|
|
2439
2587
|
const sorted = sortBySeq(messages);
|
|
2440
2588
|
return sorted.slice(Math.max(0, sorted.length - limit));
|
|
2441
2589
|
}
|
|
2590
|
+
function localAgentApiInboxResponse(registration) {
|
|
2591
|
+
const coordinator = registration.inboxCoordinator;
|
|
2592
|
+
if (!coordinator) return void 0;
|
|
2593
|
+
const pending = coordinator.getAllPendingMessages?.() ?? [];
|
|
2594
|
+
const rows = projectAgentInboxSnapshot(pending);
|
|
2595
|
+
coordinator.recordInboxSnapshot?.({
|
|
2596
|
+
source: "agent_api_inbox_check",
|
|
2597
|
+
rows,
|
|
2598
|
+
pendingMessageCount: pending.length
|
|
2599
|
+
});
|
|
2600
|
+
return {
|
|
2601
|
+
status: 200,
|
|
2602
|
+
body: {
|
|
2603
|
+
rows,
|
|
2604
|
+
pending_targets: rows.length,
|
|
2605
|
+
pending_messages: pending.length
|
|
2606
|
+
}
|
|
2607
|
+
};
|
|
2608
|
+
}
|
|
2442
2609
|
function parseAgentApiEventsQuery(target) {
|
|
2443
2610
|
const limit = Math.min(Math.max(Number(target.searchParams.get("limit")) || 50, 1), 200);
|
|
2444
2611
|
const sinceRaw = target.searchParams.get("since")?.trim() ?? "";
|
|
@@ -2469,7 +2636,7 @@ function localAgentApiEventsResponse(registration, target) {
|
|
|
2469
2636
|
if (pending.length === 0) return void 0;
|
|
2470
2637
|
const normalized = sortBySeq(normalizeVisibleMessages(pending));
|
|
2471
2638
|
const filtered = parsedQuery.sinceSeq !== null ? normalized.filter((message) => {
|
|
2472
|
-
const seq =
|
|
2639
|
+
const seq = messageSeq2(message);
|
|
2473
2640
|
return Number.isFinite(seq) && seq > parsedQuery.sinceSeq;
|
|
2474
2641
|
}) : normalized;
|
|
2475
2642
|
const events = filtered.slice(0, parsedQuery.limit);
|
|
@@ -2794,12 +2961,12 @@ function consumeVisibleResponse(registration, targetUrl, sendTarget, responseTex
|
|
|
2794
2961
|
return;
|
|
2795
2962
|
}
|
|
2796
2963
|
if (targetUrl.pathname === "/internal/agent-api/send" && parsed.state === "sent") {
|
|
2797
|
-
const
|
|
2798
|
-
if (sendTarget &&
|
|
2964
|
+
const messageSeq3 = typeof parsed.messageSeq === "number" && Number.isFinite(parsed.messageSeq) ? Math.floor(parsed.messageSeq) : void 0;
|
|
2965
|
+
if (sendTarget && messageSeq3 && messageSeq3 > 0) {
|
|
2799
2966
|
coordinator.consumeVisibleMessages({
|
|
2800
2967
|
target: sendTarget,
|
|
2801
|
-
messages: normalizeVisibleMessages([{ seq:
|
|
2802
|
-
boundarySeq:
|
|
2968
|
+
messages: normalizeVisibleMessages([{ seq: messageSeq3, id: parsed.messageId }], sendTarget),
|
|
2969
|
+
boundarySeq: messageSeq3,
|
|
2803
2970
|
source: "agent_api_send_commit"
|
|
2804
2971
|
});
|
|
2805
2972
|
}
|
|
@@ -2859,7 +3026,9 @@ var LOOPBACK_NO_PROXY = "127.0.0.1,localhost";
|
|
|
2859
3026
|
var CLI_TRANSPORT_TRACE_DIR_ENV = "SLOCK_CLI_TRANSPORT_TRACE_DIR";
|
|
2860
3027
|
var safePathPart = (value) => value.replace(/[^a-zA-Z0-9_.-]/g, "_");
|
|
2861
3028
|
var RAW_CREDENTIAL_ENV_DENYLIST = [
|
|
2862
|
-
"
|
|
3029
|
+
"SLOCK_AGENT_TOKEN",
|
|
3030
|
+
"SLOCK_AGENT_CREDENTIAL_KEY",
|
|
3031
|
+
"SLOCK_AGENT_CREDENTIAL_KEY_FILE"
|
|
2863
3032
|
];
|
|
2864
3033
|
var cachedOpencliBinPath;
|
|
2865
3034
|
function resolveOpencliBinPath() {
|
|
@@ -3074,7 +3243,7 @@ exec ${shellSingleQuote(process.execPath)} ${shellSingleQuote(opencliBinPath)} "
|
|
|
3074
3243
|
...agentCredentialProxy ? {} : { SLOCK_AGENT_TOKEN_FILE: tokenFile },
|
|
3075
3244
|
PATH: `${slockDir}${path2.delimiter}${process.env.PATH ?? ""}`
|
|
3076
3245
|
};
|
|
3077
|
-
|
|
3246
|
+
scrubDaemonChildEnv(spawnEnv);
|
|
3078
3247
|
for (const key of RAW_CREDENTIAL_ENV_DENYLIST) {
|
|
3079
3248
|
delete spawnEnv[key];
|
|
3080
3249
|
}
|
|
@@ -3175,7 +3344,7 @@ function collectModelUsageAttrs(value) {
|
|
|
3175
3344
|
modelUsageMaxOutputTokens: aggregate.maxOutputTokens
|
|
3176
3345
|
});
|
|
3177
3346
|
}
|
|
3178
|
-
function parseClaudeResultUsageTelemetry(event) {
|
|
3347
|
+
function parseClaudeResultUsageTelemetry(event, sessionId) {
|
|
3179
3348
|
const usage = event.usage && typeof event.usage === "object" ? event.usage : void 0;
|
|
3180
3349
|
const totalCostUsd = finiteNumber(event.total_cost_usd);
|
|
3181
3350
|
const modelUsageAttrs = collectModelUsageAttrs(event.modelUsage);
|
|
@@ -3224,12 +3393,16 @@ function parseClaudeResultUsageTelemetry(event) {
|
|
|
3224
3393
|
name: "token_usage",
|
|
3225
3394
|
source: "claude_result_usage",
|
|
3226
3395
|
usageKind: "per_turn",
|
|
3227
|
-
...
|
|
3396
|
+
...sessionId ? { sessionId } : {},
|
|
3228
3397
|
...typeof event.uuid === "string" && event.uuid ? { runtimeResultId: event.uuid } : {},
|
|
3229
3398
|
attrs
|
|
3230
3399
|
};
|
|
3231
3400
|
}
|
|
3232
3401
|
var ClaudeEventNormalizer = class {
|
|
3402
|
+
currentSession = null;
|
|
3403
|
+
get currentSessionId() {
|
|
3404
|
+
return this.currentSession;
|
|
3405
|
+
}
|
|
3233
3406
|
normalizeLine(line) {
|
|
3234
3407
|
let event;
|
|
3235
3408
|
try {
|
|
@@ -3238,13 +3411,17 @@ var ClaudeEventNormalizer = class {
|
|
|
3238
3411
|
return [];
|
|
3239
3412
|
}
|
|
3240
3413
|
const events = [];
|
|
3414
|
+
const eventSessionId = finiteString(event.session_id);
|
|
3415
|
+
if (eventSessionId) {
|
|
3416
|
+
this.currentSession = eventSessionId;
|
|
3417
|
+
}
|
|
3241
3418
|
const pushResultError = (message, fallback) => {
|
|
3242
3419
|
events.push({ kind: "error", message: collectResultErrorDetail(message, fallback) });
|
|
3243
3420
|
};
|
|
3244
3421
|
switch (event.type) {
|
|
3245
3422
|
case "system":
|
|
3246
|
-
if (event.subtype === "init" &&
|
|
3247
|
-
events.push({ kind: "session_init", sessionId:
|
|
3423
|
+
if (event.subtype === "init" && eventSessionId) {
|
|
3424
|
+
events.push({ kind: "session_init", sessionId: eventSessionId });
|
|
3248
3425
|
}
|
|
3249
3426
|
if (event.subtype === "status" && event.status === "compacting") {
|
|
3250
3427
|
events.push({ kind: "compaction_started" });
|
|
@@ -3303,7 +3480,8 @@ var ClaudeEventNormalizer = class {
|
|
|
3303
3480
|
case "result": {
|
|
3304
3481
|
const subtype = typeof event.subtype === "string" ? event.subtype : "success";
|
|
3305
3482
|
const stopReason = typeof event.stop_reason === "string" ? event.stop_reason : null;
|
|
3306
|
-
const
|
|
3483
|
+
const resultSessionId = eventSessionId ?? this.currentSession;
|
|
3484
|
+
const usageTelemetry = parseClaudeResultUsageTelemetry(event, resultSessionId);
|
|
3307
3485
|
switch (subtype) {
|
|
3308
3486
|
case "success":
|
|
3309
3487
|
if (event.is_error && stopReason !== "max_tokens") {
|
|
@@ -3326,7 +3504,7 @@ var ClaudeEventNormalizer = class {
|
|
|
3326
3504
|
break;
|
|
3327
3505
|
}
|
|
3328
3506
|
if (usageTelemetry) events.push(usageTelemetry);
|
|
3329
|
-
events.push({ kind: "turn_end", sessionId:
|
|
3507
|
+
events.push({ kind: "turn_end", sessionId: resultSessionId || void 0 });
|
|
3330
3508
|
break;
|
|
3331
3509
|
}
|
|
3332
3510
|
}
|
|
@@ -3494,7 +3672,7 @@ function resolveCommandOnWindows(command, env, execFileSyncFn, existsSyncFn) {
|
|
|
3494
3672
|
}
|
|
3495
3673
|
function resolveCommandOnPath(command, deps = {}) {
|
|
3496
3674
|
const platform = deps.platform ?? process.platform;
|
|
3497
|
-
const env = withWindowsUserEnvironment(deps.env ?? process.env, deps);
|
|
3675
|
+
const env = scrubDaemonChildEnv({ ...withWindowsUserEnvironment(deps.env ?? process.env, deps) });
|
|
3498
3676
|
const execFileSyncFn = deps.execFileSyncFn ?? execFileSync;
|
|
3499
3677
|
const existsSyncFn = deps.existsSyncFn ?? existsSync2;
|
|
3500
3678
|
if (platform === "win32") {
|
|
@@ -3520,7 +3698,7 @@ function firstExistingPath(candidates, deps = {}) {
|
|
|
3520
3698
|
return null;
|
|
3521
3699
|
}
|
|
3522
3700
|
function readCommandVersion(command, args = [], deps = {}) {
|
|
3523
|
-
const env = withWindowsUserEnvironment(deps.env ?? process.env, deps);
|
|
3701
|
+
const env = scrubDaemonChildEnv({ ...withWindowsUserEnvironment(deps.env ?? process.env, deps) });
|
|
3524
3702
|
const execFileSyncFn = deps.execFileSyncFn ?? execFileSync;
|
|
3525
3703
|
try {
|
|
3526
3704
|
const output = normalizeExecOutput(execFileSyncFn(command, [...args, "--version"], {
|
|
@@ -3680,6 +3858,9 @@ var ClaudeDriver = class {
|
|
|
3680
3858
|
parseLine(line) {
|
|
3681
3859
|
return this.eventNormalizer.normalizeLine(line);
|
|
3682
3860
|
}
|
|
3861
|
+
get currentSessionId() {
|
|
3862
|
+
return this.eventNormalizer.currentSessionId;
|
|
3863
|
+
}
|
|
3683
3864
|
encodeStdinMessage(text, sessionId, _opts) {
|
|
3684
3865
|
return JSON.stringify({
|
|
3685
3866
|
type: "user",
|
|
@@ -3861,6 +4042,9 @@ function rawResponseItemProgressEvent(message) {
|
|
|
3861
4042
|
payloadBytes
|
|
3862
4043
|
};
|
|
3863
4044
|
}
|
|
4045
|
+
function nonEmptyString2(value) {
|
|
4046
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
4047
|
+
}
|
|
3864
4048
|
var CodexEventNormalizer = class {
|
|
3865
4049
|
mcpToolPrefix;
|
|
3866
4050
|
currentThreadId = null;
|
|
@@ -3913,10 +4097,17 @@ var CodexEventNormalizer = class {
|
|
|
3913
4097
|
}
|
|
3914
4098
|
const telemetry = parseCodexTelemetryEvent(message);
|
|
3915
4099
|
if (telemetry) {
|
|
4100
|
+
const telemetrySessionId = nonEmptyString2(message.params?.threadId) ?? nonEmptyString2(message.params?.thread?.id) ?? nonEmptyString2(message.params?.sessionId);
|
|
4101
|
+
const telemetryTurnId = nonEmptyString2(message.params?.turnId) ?? nonEmptyString2(message.params?.turn?.id);
|
|
4102
|
+
if (telemetrySessionId) {
|
|
4103
|
+
this.currentThreadId = telemetrySessionId;
|
|
4104
|
+
}
|
|
4105
|
+
const sessionId = telemetrySessionId ?? this.currentThreadId ?? void 0;
|
|
4106
|
+
const turnId = telemetryTurnId ?? this.turnState.activeTurnId ?? void 0;
|
|
3916
4107
|
events.push({
|
|
3917
4108
|
...telemetry,
|
|
3918
|
-
...
|
|
3919
|
-
...
|
|
4109
|
+
...sessionId ? { sessionId } : {},
|
|
4110
|
+
...turnId ? { turnId } : {}
|
|
3920
4111
|
});
|
|
3921
4112
|
return { events };
|
|
3922
4113
|
}
|
|
@@ -4365,6 +4556,9 @@ var CodexDriver = class {
|
|
|
4365
4556
|
}
|
|
4366
4557
|
return result.events;
|
|
4367
4558
|
}
|
|
4559
|
+
get currentSessionId() {
|
|
4560
|
+
return this.normalizer.threadId;
|
|
4561
|
+
}
|
|
4368
4562
|
encodeStdinMessage(text, sessionId, opts) {
|
|
4369
4563
|
if (!this.normalizer.threadId && sessionId) {
|
|
4370
4564
|
this.normalizer.adoptThreadId(sessionId);
|
|
@@ -4967,11 +5161,11 @@ function detectCursorModels(runCommand = runCursorModelsCommand) {
|
|
|
4967
5161
|
return parseCursorModelsOutput(String(result.stdout || ""));
|
|
4968
5162
|
}
|
|
4969
5163
|
function buildCursorModelProbeEnv(deps = {}) {
|
|
4970
|
-
return withWindowsUserEnvironment({
|
|
5164
|
+
return scrubDaemonChildEnv(withWindowsUserEnvironment({
|
|
4971
5165
|
...deps.env ?? process.env,
|
|
4972
5166
|
FORCE_COLOR: "0",
|
|
4973
5167
|
NO_COLOR: "1"
|
|
4974
|
-
}, deps);
|
|
5168
|
+
}, deps));
|
|
4975
5169
|
}
|
|
4976
5170
|
function runCursorModelsCommand() {
|
|
4977
5171
|
return spawnSync("cursor-agent", ["models"], {
|
|
@@ -5027,7 +5221,7 @@ function resolveGeminiSpawn(commandArgs, deps = {}) {
|
|
|
5027
5221
|
}
|
|
5028
5222
|
const execFileSyncFn = deps.execFileSyncFn ?? execFileSync3;
|
|
5029
5223
|
const existsSyncFn = deps.existsSyncFn ?? existsSync5;
|
|
5030
|
-
const env = deps.env ?? process.env;
|
|
5224
|
+
const env = scrubDaemonChildEnv({ ...deps.env ?? process.env });
|
|
5031
5225
|
const winPath = path8.win32;
|
|
5032
5226
|
let geminiEntry = null;
|
|
5033
5227
|
try {
|
|
@@ -5199,13 +5393,16 @@ var GeminiDriver = class {
|
|
|
5199
5393
|
// src/drivers/kimi.ts
|
|
5200
5394
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
5201
5395
|
import { spawn as spawn7 } from "child_process";
|
|
5202
|
-
import { existsSync as existsSync6, readFileSync as readFileSync3, writeFileSync as writeFileSync6 } from "fs";
|
|
5396
|
+
import { chmodSync, existsSync as existsSync6, readFileSync as readFileSync3, writeFileSync as writeFileSync6 } from "fs";
|
|
5203
5397
|
import os3 from "os";
|
|
5204
5398
|
import path9 from "path";
|
|
5205
5399
|
var KIMI_WIRE_PROTOCOL_VERSION = "1.3";
|
|
5206
5400
|
var KIMI_SYSTEM_PROMPT_FILE = ".slock-kimi-system.md";
|
|
5207
5401
|
var KIMI_AGENT_FILE = ".slock-kimi-agent.yaml";
|
|
5208
5402
|
var KIMI_MCP_FILE = ".slock-kimi-mcp.json";
|
|
5403
|
+
var KIMI_GENERATED_CONFIG_FILE = ".slock-kimi-config.toml";
|
|
5404
|
+
var SLOCK_KIMI_CONFIG_CONTENT_ENV = "SLOCK_KIMI_CONFIG_CONTENT";
|
|
5405
|
+
var SLOCK_KIMI_CONFIG_FILE_ENV = "SLOCK_KIMI_CONFIG_FILE";
|
|
5209
5406
|
function parseToolArguments(raw) {
|
|
5210
5407
|
if (typeof raw !== "string") return raw;
|
|
5211
5408
|
try {
|
|
@@ -5214,6 +5411,73 @@ function parseToolArguments(raw) {
|
|
|
5214
5411
|
return raw;
|
|
5215
5412
|
}
|
|
5216
5413
|
}
|
|
5414
|
+
function readKimiConfigSource(home = os3.homedir(), env = process.env) {
|
|
5415
|
+
const inlineConfig = env[SLOCK_KIMI_CONFIG_CONTENT_ENV];
|
|
5416
|
+
if (inlineConfig && inlineConfig.trim()) {
|
|
5417
|
+
return {
|
|
5418
|
+
raw: inlineConfig,
|
|
5419
|
+
explicitPath: null,
|
|
5420
|
+
sourcePath: SLOCK_KIMI_CONFIG_CONTENT_ENV
|
|
5421
|
+
};
|
|
5422
|
+
}
|
|
5423
|
+
const explicitPath = env[SLOCK_KIMI_CONFIG_FILE_ENV];
|
|
5424
|
+
const configPath = explicitPath && explicitPath.trim() ? explicitPath : path9.join(home, ".kimi", "config.toml");
|
|
5425
|
+
try {
|
|
5426
|
+
return {
|
|
5427
|
+
raw: readFileSync3(configPath, "utf8"),
|
|
5428
|
+
explicitPath: explicitPath && explicitPath.trim() ? explicitPath : null,
|
|
5429
|
+
sourcePath: configPath
|
|
5430
|
+
};
|
|
5431
|
+
} catch {
|
|
5432
|
+
return {
|
|
5433
|
+
raw: null,
|
|
5434
|
+
explicitPath: explicitPath && explicitPath.trim() ? explicitPath : null,
|
|
5435
|
+
sourcePath: configPath
|
|
5436
|
+
};
|
|
5437
|
+
}
|
|
5438
|
+
}
|
|
5439
|
+
function buildKimiSpawnEnv(env = process.env) {
|
|
5440
|
+
const spawnEnv = { ...env, FORCE_COLOR: "0", NO_COLOR: "1" };
|
|
5441
|
+
delete spawnEnv[SLOCK_KIMI_CONFIG_CONTENT_ENV];
|
|
5442
|
+
delete spawnEnv[SLOCK_KIMI_CONFIG_FILE_ENV];
|
|
5443
|
+
return scrubDaemonChildEnv(spawnEnv);
|
|
5444
|
+
}
|
|
5445
|
+
function buildKimiEffectiveEnv(ctx, overrideEnv) {
|
|
5446
|
+
return {
|
|
5447
|
+
...process.env,
|
|
5448
|
+
...ctx.config.envVars || {},
|
|
5449
|
+
...overrideEnv || {}
|
|
5450
|
+
};
|
|
5451
|
+
}
|
|
5452
|
+
function buildKimiLaunchOptions(ctx, opts = {}) {
|
|
5453
|
+
const env = buildKimiEffectiveEnv(ctx, opts.env);
|
|
5454
|
+
const source = readKimiConfigSource(opts.home ?? os3.homedir(), env);
|
|
5455
|
+
const args = [];
|
|
5456
|
+
let configFilePath = null;
|
|
5457
|
+
let configContent = null;
|
|
5458
|
+
if (source.explicitPath) {
|
|
5459
|
+
configFilePath = source.explicitPath;
|
|
5460
|
+
} else if (source.raw !== null && source.sourcePath === SLOCK_KIMI_CONFIG_CONTENT_ENV) {
|
|
5461
|
+
configFilePath = path9.join(ctx.workingDirectory, KIMI_GENERATED_CONFIG_FILE);
|
|
5462
|
+
configContent = source.raw;
|
|
5463
|
+
if (opts.writeGeneratedConfig !== false) {
|
|
5464
|
+
writeFileSync6(configFilePath, source.raw, { encoding: "utf8", mode: 384 });
|
|
5465
|
+
chmodSync(configFilePath, 384);
|
|
5466
|
+
}
|
|
5467
|
+
}
|
|
5468
|
+
if (configFilePath) {
|
|
5469
|
+
args.push("--config-file", configFilePath);
|
|
5470
|
+
}
|
|
5471
|
+
if (ctx.config.model && ctx.config.model !== "default") {
|
|
5472
|
+
args.push("--model", ctx.config.model);
|
|
5473
|
+
}
|
|
5474
|
+
return {
|
|
5475
|
+
args,
|
|
5476
|
+
env: buildKimiSpawnEnv(env),
|
|
5477
|
+
configFilePath,
|
|
5478
|
+
configContent
|
|
5479
|
+
};
|
|
5480
|
+
}
|
|
5217
5481
|
function resolveKimiSpawn(commandArgs, deps = {}) {
|
|
5218
5482
|
return {
|
|
5219
5483
|
command: resolveCommandOnPath("kimi", deps) ?? "kimi",
|
|
@@ -5237,7 +5501,25 @@ var KimiDriver = class {
|
|
|
5237
5501
|
};
|
|
5238
5502
|
model = {
|
|
5239
5503
|
detectedModelsVerifiedAs: "launchable",
|
|
5240
|
-
toLaunchSpec: (modelId) =>
|
|
5504
|
+
toLaunchSpec: (modelId, ctx, opts) => {
|
|
5505
|
+
if (!ctx) return { args: ["--model", modelId] };
|
|
5506
|
+
const launchCtx = {
|
|
5507
|
+
...ctx,
|
|
5508
|
+
config: {
|
|
5509
|
+
...ctx.config,
|
|
5510
|
+
model: modelId
|
|
5511
|
+
}
|
|
5512
|
+
};
|
|
5513
|
+
const launch = buildKimiLaunchOptions(launchCtx, {
|
|
5514
|
+
home: opts?.home,
|
|
5515
|
+
writeGeneratedConfig: false
|
|
5516
|
+
});
|
|
5517
|
+
return {
|
|
5518
|
+
args: launch.args,
|
|
5519
|
+
env: launch.env,
|
|
5520
|
+
configFiles: launch.configFilePath ? [launch.configFilePath] : void 0
|
|
5521
|
+
};
|
|
5522
|
+
}
|
|
5241
5523
|
};
|
|
5242
5524
|
supportsStdinNotification = true;
|
|
5243
5525
|
mcpToolPrefix = "";
|
|
@@ -5291,6 +5573,7 @@ var KimiDriver = class {
|
|
|
5291
5573
|
}
|
|
5292
5574
|
}
|
|
5293
5575
|
}), "utf8");
|
|
5576
|
+
const launch = buildKimiLaunchOptions(ctx);
|
|
5294
5577
|
const args = [
|
|
5295
5578
|
"--wire",
|
|
5296
5579
|
"--yolo",
|
|
@@ -5299,15 +5582,16 @@ var KimiDriver = class {
|
|
|
5299
5582
|
"--mcp-config-file",
|
|
5300
5583
|
mcpConfigPath,
|
|
5301
5584
|
"--session",
|
|
5302
|
-
this.sessionId
|
|
5585
|
+
this.sessionId,
|
|
5586
|
+
...launch.args
|
|
5303
5587
|
];
|
|
5304
5588
|
const launchRuntimeFields = runtimeConfigToLaunchFields(ctx.config);
|
|
5305
5589
|
if (launchRuntimeFields.model && launchRuntimeFields.model !== "default") {
|
|
5306
5590
|
args.push("--model", launchRuntimeFields.model);
|
|
5307
5591
|
}
|
|
5308
5592
|
const spawnEnv = (await prepareCliTransport(ctx, { NO_COLOR: "1" })).spawnEnv;
|
|
5309
|
-
const
|
|
5310
|
-
const proc = spawn7(
|
|
5593
|
+
const spawnTarget = resolveKimiSpawn(args);
|
|
5594
|
+
const proc = spawn7(spawnTarget.command, spawnTarget.args, {
|
|
5311
5595
|
cwd: ctx.workingDirectory,
|
|
5312
5596
|
stdio: ["pipe", "pipe", "pipe"],
|
|
5313
5597
|
env: spawnEnv,
|
|
@@ -5315,7 +5599,7 @@ var KimiDriver = class {
|
|
|
5315
5599
|
// and has an 8191-character command-line limit. Kimi's official
|
|
5316
5600
|
// installer/uv entrypoint is an executable, so launch it directly and
|
|
5317
5601
|
// keep prompts on stdin / files instead of routing through cmd.exe.
|
|
5318
|
-
shell:
|
|
5602
|
+
shell: spawnTarget.shell
|
|
5319
5603
|
});
|
|
5320
5604
|
proc.stdin?.write(JSON.stringify({
|
|
5321
5605
|
jsonrpc: "2.0",
|
|
@@ -5429,14 +5713,9 @@ var KimiDriver = class {
|
|
|
5429
5713
|
return detectKimiModels();
|
|
5430
5714
|
}
|
|
5431
5715
|
};
|
|
5432
|
-
function detectKimiModels(home = os3.homedir()) {
|
|
5433
|
-
const
|
|
5434
|
-
|
|
5435
|
-
try {
|
|
5436
|
-
raw = readFileSync3(configPath, "utf8");
|
|
5437
|
-
} catch {
|
|
5438
|
-
return null;
|
|
5439
|
-
}
|
|
5716
|
+
function detectKimiModels(home = os3.homedir(), opts = {}) {
|
|
5717
|
+
const raw = readKimiConfigSource(home, opts.env).raw;
|
|
5718
|
+
if (raw === null) return null;
|
|
5440
5719
|
const models = [];
|
|
5441
5720
|
const sectionRe = /^\s*\[models(?:\.([^\]]+)|"\.[^"]+"|\."[^"]+")\s*\]\s*$/gm;
|
|
5442
5721
|
const lineRe = /^\s*\[models\.(.+?)\s*\]\s*$/gm;
|
|
@@ -5700,7 +5979,7 @@ function runOpenCodeModelsCommand(home, deps = {}) {
|
|
|
5700
5979
|
const platform = deps.platform ?? process.platform;
|
|
5701
5980
|
const spawnSyncFn = deps.spawnSyncFn ?? spawnSync2;
|
|
5702
5981
|
const result = spawnSyncFn("opencode", ["models"], {
|
|
5703
|
-
env: { ...process.env, HOME: home, FORCE_COLOR: "0", NO_COLOR: "1" },
|
|
5982
|
+
env: scrubDaemonChildEnv({ ...process.env, HOME: home, FORCE_COLOR: "0", NO_COLOR: "1" }),
|
|
5704
5983
|
encoding: "utf8",
|
|
5705
5984
|
timeout: 5e3,
|
|
5706
5985
|
shell: platform === "win32"
|
|
@@ -5961,12 +6240,23 @@ var OpenCodeDriver = class {
|
|
|
5961
6240
|
|
|
5962
6241
|
// src/drivers/pi.ts
|
|
5963
6242
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
5964
|
-
import {
|
|
5965
|
-
import { mkdirSync as mkdirSync4 } from "fs";
|
|
6243
|
+
import { EventEmitter } from "events";
|
|
6244
|
+
import { mkdirSync as mkdirSync4, readdirSync } from "fs";
|
|
6245
|
+
import { PassThrough, Writable } from "stream";
|
|
5966
6246
|
import path11 from "path";
|
|
6247
|
+
import {
|
|
6248
|
+
AuthStorage,
|
|
6249
|
+
createBashTool,
|
|
6250
|
+
createAgentSession,
|
|
6251
|
+
DefaultResourceLoader,
|
|
6252
|
+
getAgentDir,
|
|
6253
|
+
ModelRegistry,
|
|
6254
|
+
SessionManager,
|
|
6255
|
+
SettingsManager,
|
|
6256
|
+
VERSION as PI_SDK_VERSION
|
|
6257
|
+
} from "@earendil-works/pi-coding-agent";
|
|
5967
6258
|
var PI_SESSION_DIR = ".pi-sessions";
|
|
5968
6259
|
var PI_PROVIDER_LABELS = {
|
|
5969
|
-
deepseek: "DeepSeek",
|
|
5970
6260
|
google: "Google",
|
|
5971
6261
|
openai: "OpenAI",
|
|
5972
6262
|
openrouter: "OpenRouter"
|
|
@@ -5974,69 +6264,51 @@ var PI_PROVIDER_LABELS = {
|
|
|
5974
6264
|
function buildPiSessionDir(workingDirectory) {
|
|
5975
6265
|
return path11.join(workingDirectory, PI_SESSION_DIR);
|
|
5976
6266
|
}
|
|
5977
|
-
function
|
|
5978
|
-
|
|
5979
|
-
|
|
5980
|
-
|
|
5981
|
-
|
|
5982
|
-
|
|
5983
|
-
|
|
5984
|
-
"
|
|
5985
|
-
ctx.standingPrompt
|
|
5986
|
-
];
|
|
5987
|
-
if (launchRuntimeFields.model && launchRuntimeFields.model !== "default") {
|
|
5988
|
-
args.push("--model", launchRuntimeFields.model);
|
|
5989
|
-
}
|
|
5990
|
-
if (launchRuntimeFields.reasoningEffort) {
|
|
5991
|
-
args.push("--thinking", launchRuntimeFields.reasoningEffort);
|
|
6267
|
+
async function buildPiSpawnEnv(ctx) {
|
|
6268
|
+
return (await prepareCliTransport(ctx, { NO_COLOR: "1" })).spawnEnv;
|
|
6269
|
+
}
|
|
6270
|
+
function resolvePiModelFromRegistry(modelId, modelRegistry) {
|
|
6271
|
+
if (!modelId || modelId === "default") return void 0;
|
|
6272
|
+
const [provider, ...modelParts] = modelId.split("/");
|
|
6273
|
+
if (provider && modelParts.length > 0) {
|
|
6274
|
+
return modelRegistry.find(provider, modelParts.join("/"));
|
|
5992
6275
|
}
|
|
5993
|
-
|
|
5994
|
-
|
|
6276
|
+
return modelRegistry.getAll().find((model) => model.id === modelId);
|
|
6277
|
+
}
|
|
6278
|
+
function findPiSessionFile(sessionDir, sessionId) {
|
|
6279
|
+
let entries;
|
|
6280
|
+
try {
|
|
6281
|
+
entries = readdirSync(sessionDir);
|
|
6282
|
+
} catch {
|
|
6283
|
+
return null;
|
|
5995
6284
|
}
|
|
5996
|
-
|
|
6285
|
+
const suffix = `_${sessionId}.jsonl`;
|
|
6286
|
+
const match = entries.find((entry) => entry.endsWith(suffix));
|
|
6287
|
+
return match ? path11.join(sessionDir, match) : null;
|
|
5997
6288
|
}
|
|
5998
|
-
|
|
5999
|
-
|
|
6289
|
+
function piSdkEventToJsonLine(event) {
|
|
6290
|
+
if (event.type === "agent_end") {
|
|
6291
|
+
return JSON.stringify({ type: "agent_end" });
|
|
6292
|
+
}
|
|
6293
|
+
return JSON.stringify(event);
|
|
6000
6294
|
}
|
|
6001
|
-
function
|
|
6002
|
-
const stripAnsi = (value) => value.replace(/\u001b\[[0-9;]*m/g, "");
|
|
6295
|
+
function detectPiModelsFromRegistry(modelRegistry) {
|
|
6003
6296
|
const models = [];
|
|
6004
6297
|
const seen = /* @__PURE__ */ new Set();
|
|
6005
|
-
for (const
|
|
6006
|
-
const
|
|
6007
|
-
if (!line || /^provider\s+model\s+/i.test(line) || /^[-\s]+$/.test(line)) continue;
|
|
6008
|
-
const columns = line.split(/\s+/);
|
|
6009
|
-
const provider = columns[0];
|
|
6010
|
-
const model = columns[1];
|
|
6011
|
-
if (!provider || !model || provider.startsWith("-") || model.startsWith("-")) continue;
|
|
6012
|
-
if (/^(yes|no)$/i.test(model)) continue;
|
|
6013
|
-
const id = `${provider}/${model}`;
|
|
6298
|
+
for (const model of modelRegistry.getAvailable()) {
|
|
6299
|
+
const id = `${model.provider}/${model.id}`;
|
|
6014
6300
|
if (seen.has(id)) continue;
|
|
6015
6301
|
seen.add(id);
|
|
6016
6302
|
models.push({
|
|
6017
6303
|
id,
|
|
6018
|
-
label: `${humanizePiSegment(model)} \xB7 ${PI_PROVIDER_LABELS[provider] || humanizePiSegment(provider)}`,
|
|
6304
|
+
label: `${model.name || humanizePiSegment(model.id)} \xB7 ${PI_PROVIDER_LABELS[model.provider] || humanizePiSegment(model.provider)}`,
|
|
6019
6305
|
verified: "launchable"
|
|
6020
6306
|
});
|
|
6021
6307
|
}
|
|
6022
6308
|
return models.length > 0 ? { models } : null;
|
|
6023
6309
|
}
|
|
6024
|
-
function detectPiModels(
|
|
6025
|
-
|
|
6026
|
-
if (result.error || result.status !== 0) return null;
|
|
6027
|
-
return parsePiModelsOutput(result.stdout);
|
|
6028
|
-
}
|
|
6029
|
-
function runPiModelsCommand() {
|
|
6030
|
-
const result = spawnSync3("pi", ["--list-models"], {
|
|
6031
|
-
env: { ...process.env, FORCE_COLOR: "0", NO_COLOR: "1" },
|
|
6032
|
-
encoding: "utf8",
|
|
6033
|
-
timeout: 5e3
|
|
6034
|
-
});
|
|
6035
|
-
return {
|
|
6036
|
-
status: result.status,
|
|
6037
|
-
stdout: String(result.stdout || ""),
|
|
6038
|
-
error: result.error
|
|
6039
|
-
};
|
|
6310
|
+
function detectPiModels(modelRegistry = ModelRegistry.create(AuthStorage.create())) {
|
|
6311
|
+
return detectPiModelsFromRegistry(modelRegistry);
|
|
6040
6312
|
}
|
|
6041
6313
|
function humanizePiSegment(value) {
|
|
6042
6314
|
return value.split(/[-_/]/).filter(Boolean).map(formatPiLabelToken).join(" ");
|
|
@@ -6046,7 +6318,6 @@ function formatPiLabelToken(token) {
|
|
|
6046
6318
|
const specialCases = {
|
|
6047
6319
|
ai: "AI",
|
|
6048
6320
|
api: "API",
|
|
6049
|
-
deepseek: "DeepSeek",
|
|
6050
6321
|
flash: "Flash",
|
|
6051
6322
|
gpt: "GPT",
|
|
6052
6323
|
pro: "Pro",
|
|
@@ -6070,6 +6341,116 @@ function piErrorMessage(error) {
|
|
|
6070
6341
|
}
|
|
6071
6342
|
return "Unknown Pi error";
|
|
6072
6343
|
}
|
|
6344
|
+
var PiSdkProcess = class extends EventEmitter {
|
|
6345
|
+
constructor(session) {
|
|
6346
|
+
super();
|
|
6347
|
+
this.session = session;
|
|
6348
|
+
this.stdin = new Writable({
|
|
6349
|
+
write: (chunk, _encoding, callback) => {
|
|
6350
|
+
this.handleInput(String(chunk)).then(
|
|
6351
|
+
() => callback(),
|
|
6352
|
+
(error) => {
|
|
6353
|
+
this.writeError(error);
|
|
6354
|
+
callback();
|
|
6355
|
+
}
|
|
6356
|
+
);
|
|
6357
|
+
}
|
|
6358
|
+
});
|
|
6359
|
+
this.session.subscribe((event) => {
|
|
6360
|
+
this.writeStdout(piSdkEventToJsonLine(event));
|
|
6361
|
+
});
|
|
6362
|
+
}
|
|
6363
|
+
stdout = new PassThrough();
|
|
6364
|
+
stderr = new PassThrough();
|
|
6365
|
+
stdin;
|
|
6366
|
+
pid = void 0;
|
|
6367
|
+
exitCode = null;
|
|
6368
|
+
signalCode = null;
|
|
6369
|
+
killed = false;
|
|
6370
|
+
buffer = "";
|
|
6371
|
+
closed = false;
|
|
6372
|
+
kill(signal = "SIGTERM") {
|
|
6373
|
+
if (this.closed) return false;
|
|
6374
|
+
this.killed = true;
|
|
6375
|
+
this.signalCode = typeof signal === "string" ? signal : null;
|
|
6376
|
+
void this.shutdown(null, this.signalCode);
|
|
6377
|
+
return true;
|
|
6378
|
+
}
|
|
6379
|
+
ref() {
|
|
6380
|
+
return this;
|
|
6381
|
+
}
|
|
6382
|
+
unref() {
|
|
6383
|
+
return this;
|
|
6384
|
+
}
|
|
6385
|
+
async handleInput(chunk) {
|
|
6386
|
+
this.buffer += chunk;
|
|
6387
|
+
const lines = this.buffer.split("\n");
|
|
6388
|
+
this.buffer = lines.pop() || "";
|
|
6389
|
+
for (const line of lines) {
|
|
6390
|
+
if (!line.trim() || this.closed) continue;
|
|
6391
|
+
await this.handleCommand(line);
|
|
6392
|
+
}
|
|
6393
|
+
}
|
|
6394
|
+
async handleCommand(raw) {
|
|
6395
|
+
let command;
|
|
6396
|
+
try {
|
|
6397
|
+
command = JSON.parse(raw);
|
|
6398
|
+
} catch (error) {
|
|
6399
|
+
this.writeError(error);
|
|
6400
|
+
return;
|
|
6401
|
+
}
|
|
6402
|
+
const id = typeof command.id === "string" ? command.id : void 0;
|
|
6403
|
+
try {
|
|
6404
|
+
if (command.type === "prompt") {
|
|
6405
|
+
await this.session.prompt(String(command.message ?? ""));
|
|
6406
|
+
this.writeStdout(JSON.stringify({ id, type: "response", command: "prompt", success: true }));
|
|
6407
|
+
} else if (command.type === "steer") {
|
|
6408
|
+
await this.session.steer(String(command.message ?? ""));
|
|
6409
|
+
this.writeStdout(JSON.stringify({ id, type: "response", command: "steer", success: true }));
|
|
6410
|
+
} else {
|
|
6411
|
+
throw new Error(`Unsupported Pi SDK command: ${command.type || "unknown"}`);
|
|
6412
|
+
}
|
|
6413
|
+
} catch (error) {
|
|
6414
|
+
this.writeStdout(JSON.stringify({
|
|
6415
|
+
id,
|
|
6416
|
+
type: "response",
|
|
6417
|
+
command: command.type || "unknown",
|
|
6418
|
+
success: false,
|
|
6419
|
+
error: piErrorMessage(error)
|
|
6420
|
+
}));
|
|
6421
|
+
}
|
|
6422
|
+
}
|
|
6423
|
+
writeStdout(line) {
|
|
6424
|
+
if (this.closed) return;
|
|
6425
|
+
this.stdout.write(line + "\n");
|
|
6426
|
+
}
|
|
6427
|
+
writeError(error) {
|
|
6428
|
+
if (this.closed) return;
|
|
6429
|
+
this.stderr.write(piErrorMessage(error) + "\n");
|
|
6430
|
+
}
|
|
6431
|
+
async shutdown(code, signal) {
|
|
6432
|
+
if (this.closed) return;
|
|
6433
|
+
this.closed = true;
|
|
6434
|
+
this.exitCode = code;
|
|
6435
|
+
this.signalCode = signal;
|
|
6436
|
+
try {
|
|
6437
|
+
if (this.session.isStreaming) {
|
|
6438
|
+
await this.session.abort();
|
|
6439
|
+
}
|
|
6440
|
+
} catch (error) {
|
|
6441
|
+
this.stderr.write(piErrorMessage(error) + "\n");
|
|
6442
|
+
}
|
|
6443
|
+
try {
|
|
6444
|
+
this.session.dispose();
|
|
6445
|
+
} catch {
|
|
6446
|
+
}
|
|
6447
|
+
this.stdin.destroy();
|
|
6448
|
+
this.stdout.end();
|
|
6449
|
+
this.stderr.end();
|
|
6450
|
+
this.emit("exit", code, signal);
|
|
6451
|
+
this.emit("close", code, signal);
|
|
6452
|
+
}
|
|
6453
|
+
};
|
|
6073
6454
|
var PiDriver = class {
|
|
6074
6455
|
id = "pi";
|
|
6075
6456
|
supportsNativeStandingPrompt = true;
|
|
@@ -6087,7 +6468,7 @@ var PiDriver = class {
|
|
|
6087
6468
|
};
|
|
6088
6469
|
model = {
|
|
6089
6470
|
detectedModelsVerifiedAs: "launchable",
|
|
6090
|
-
toLaunchSpec: (modelId) => ({
|
|
6471
|
+
toLaunchSpec: (modelId) => ({ params: { model: modelId } })
|
|
6091
6472
|
};
|
|
6092
6473
|
supportsStdinNotification = true;
|
|
6093
6474
|
mcpToolPrefix = "";
|
|
@@ -6099,11 +6480,9 @@ var PiDriver = class {
|
|
|
6099
6480
|
requestId = 0;
|
|
6100
6481
|
process = null;
|
|
6101
6482
|
probe() {
|
|
6102
|
-
const command = resolveCommandOnPath("pi");
|
|
6103
|
-
if (!command) return { available: false };
|
|
6104
6483
|
return {
|
|
6105
6484
|
available: true,
|
|
6106
|
-
version:
|
|
6485
|
+
version: PI_SDK_VERSION
|
|
6107
6486
|
};
|
|
6108
6487
|
}
|
|
6109
6488
|
async detectModels() {
|
|
@@ -6114,15 +6493,57 @@ var PiDriver = class {
|
|
|
6114
6493
|
this.sessionAnnounced = false;
|
|
6115
6494
|
this.sawTextDelta = false;
|
|
6116
6495
|
this.requestId = 0;
|
|
6117
|
-
|
|
6118
|
-
|
|
6496
|
+
const sessionDir = buildPiSessionDir(ctx.workingDirectory);
|
|
6497
|
+
mkdirSync4(sessionDir, { recursive: true });
|
|
6498
|
+
const spawnEnv = await buildPiSpawnEnv(ctx);
|
|
6499
|
+
const agentDir = spawnEnv.PI_CODING_AGENT_DIR || getAgentDir();
|
|
6500
|
+
const authStorage = AuthStorage.create(path11.join(agentDir, "auth.json"));
|
|
6501
|
+
const modelRegistry = ModelRegistry.create(authStorage, path11.join(agentDir, "models.json"));
|
|
6502
|
+
const launchRuntimeFields = runtimeConfigToLaunchFields(ctx.config);
|
|
6503
|
+
const model = resolvePiModelFromRegistry(launchRuntimeFields.model, modelRegistry);
|
|
6504
|
+
if (launchRuntimeFields.model && launchRuntimeFields.model !== "default" && !model) {
|
|
6505
|
+
throw new Error(`Pi model not found: ${launchRuntimeFields.model}`);
|
|
6506
|
+
}
|
|
6507
|
+
const settingsManager = SettingsManager.inMemory({ compaction: { enabled: false } });
|
|
6508
|
+
const resourceLoader = new DefaultResourceLoader({
|
|
6119
6509
|
cwd: ctx.workingDirectory,
|
|
6120
|
-
|
|
6121
|
-
|
|
6122
|
-
|
|
6510
|
+
agentDir,
|
|
6511
|
+
settingsManager,
|
|
6512
|
+
systemPromptOverride: () => ctx.standingPrompt
|
|
6513
|
+
});
|
|
6514
|
+
await resourceLoader.reload();
|
|
6515
|
+
const existingSessionFile = ctx.config.sessionId ? findPiSessionFile(sessionDir, ctx.config.sessionId) : null;
|
|
6516
|
+
const sessionManager = existingSessionFile ? SessionManager.open(existingSessionFile, sessionDir, ctx.workingDirectory) : SessionManager.create(ctx.workingDirectory, sessionDir, { id: this.sessionId });
|
|
6517
|
+
const { session } = await createAgentSession({
|
|
6518
|
+
cwd: ctx.workingDirectory,
|
|
6519
|
+
agentDir,
|
|
6520
|
+
model,
|
|
6521
|
+
thinkingLevel: launchRuntimeFields.reasoningEffort,
|
|
6522
|
+
authStorage,
|
|
6523
|
+
modelRegistry,
|
|
6524
|
+
resourceLoader,
|
|
6525
|
+
customTools: [
|
|
6526
|
+
createBashTool(ctx.workingDirectory, {
|
|
6527
|
+
spawnHook: (spawnContext) => ({
|
|
6528
|
+
...spawnContext,
|
|
6529
|
+
env: {
|
|
6530
|
+
...spawnContext.env,
|
|
6531
|
+
...spawnEnv
|
|
6532
|
+
}
|
|
6533
|
+
})
|
|
6534
|
+
})
|
|
6535
|
+
],
|
|
6536
|
+
sessionManager,
|
|
6537
|
+
settingsManager
|
|
6123
6538
|
});
|
|
6539
|
+
this.sessionId = session.sessionId;
|
|
6540
|
+
const proc = new PiSdkProcess(session);
|
|
6124
6541
|
this.process = proc;
|
|
6125
|
-
|
|
6542
|
+
setImmediate(() => {
|
|
6543
|
+
if (this.process === proc && !proc.killed) {
|
|
6544
|
+
this.sendRpcCommand("prompt", { message: ctx.prompt });
|
|
6545
|
+
}
|
|
6546
|
+
});
|
|
6126
6547
|
return { process: proc };
|
|
6127
6548
|
}
|
|
6128
6549
|
parseLine(line) {
|
|
@@ -6211,7 +6632,7 @@ var PiDriver = class {
|
|
|
6211
6632
|
toolPrefix: "",
|
|
6212
6633
|
extraCriticalRules: [],
|
|
6213
6634
|
postStartupNotes: [
|
|
6214
|
-
"**Pi runtime note:** Slock keeps Pi running
|
|
6635
|
+
"**Pi runtime note:** Slock keeps Pi running as a persistent SDK session. While you are working, Slock may send inbox-count notifications into the current turn; call `slock message check` at natural breakpoints."
|
|
6215
6636
|
],
|
|
6216
6637
|
includeStdinNotificationSection: true,
|
|
6217
6638
|
messageNotificationStyle: "direct"
|
|
@@ -6506,7 +6927,7 @@ function runtimeDisplayName(runtimeId) {
|
|
|
6506
6927
|
case "opencode":
|
|
6507
6928
|
return "OpenCode";
|
|
6508
6929
|
case "pi":
|
|
6509
|
-
return "Pi
|
|
6930
|
+
return "Pi";
|
|
6510
6931
|
default:
|
|
6511
6932
|
return runtimeId || "This runtime";
|
|
6512
6933
|
}
|
|
@@ -6752,8 +7173,8 @@ function formatVisibleMessageTarget(message) {
|
|
|
6752
7173
|
}
|
|
6753
7174
|
return null;
|
|
6754
7175
|
}
|
|
6755
|
-
function getMessageShortId(
|
|
6756
|
-
return
|
|
7176
|
+
function getMessageShortId(messageId2) {
|
|
7177
|
+
return messageId2.startsWith("thread-") ? messageId2.slice(7) : messageId2.slice(0, 8);
|
|
6757
7178
|
}
|
|
6758
7179
|
var RESPONSE_TARGET_HINT = "Reply in the channel or create/reply in a thread as appropriate; use each message's `target` and `msg` fields to choose the exact target.";
|
|
6759
7180
|
function findSessionJsonl(root, predicate) {
|
|
@@ -6764,7 +7185,7 @@ function findSessionJsonl(root, predicate) {
|
|
|
6764
7185
|
if (depth < 0 || visited >= maxEntries) return null;
|
|
6765
7186
|
let entries;
|
|
6766
7187
|
try {
|
|
6767
|
-
entries =
|
|
7188
|
+
entries = readdirSync2(dir, { withFileTypes: true }).sort((a, b) => b.name.localeCompare(a.name));
|
|
6768
7189
|
} catch {
|
|
6769
7190
|
return null;
|
|
6770
7191
|
}
|
|
@@ -7724,6 +8145,30 @@ function runtimeTraceCounterAttrs(ap) {
|
|
|
7724
8145
|
runtime_thinking_events_count: ap.runtimeTraceCounters.thinkingEvents
|
|
7725
8146
|
};
|
|
7726
8147
|
}
|
|
8148
|
+
var RUNTIME_TELEMETRY_RESERVED_ATTR_KEYS = /* @__PURE__ */ new Set([
|
|
8149
|
+
"agentId",
|
|
8150
|
+
"launchId",
|
|
8151
|
+
"runtime",
|
|
8152
|
+
"model",
|
|
8153
|
+
"telemetry_name",
|
|
8154
|
+
"source",
|
|
8155
|
+
"usageKind",
|
|
8156
|
+
"sessionId",
|
|
8157
|
+
"turnId",
|
|
8158
|
+
"runtimeResultId",
|
|
8159
|
+
"daemonVersion",
|
|
8160
|
+
"daemon_version",
|
|
8161
|
+
"computerVersion",
|
|
8162
|
+
"computer_version"
|
|
8163
|
+
]);
|
|
8164
|
+
function sanitizeRuntimeTelemetryPayloadAttrs(attrs) {
|
|
8165
|
+
const sanitized = {};
|
|
8166
|
+
for (const [key, value] of Object.entries(attrs)) {
|
|
8167
|
+
if (RUNTIME_TELEMETRY_RESERVED_ATTR_KEYS.has(key)) continue;
|
|
8168
|
+
sanitized[key] = value;
|
|
8169
|
+
}
|
|
8170
|
+
return sanitized;
|
|
8171
|
+
}
|
|
7727
8172
|
function getMessageDeliveryText(driver) {
|
|
7728
8173
|
return driver.supportsStdinNotification ? "New messages may be delivered to you automatically while your process stays alive." : "The daemon will automatically restart you when new messages arrive.";
|
|
7729
8174
|
}
|
|
@@ -7934,6 +8379,13 @@ var AgentProcessManager = class _AgentProcessManager {
|
|
|
7934
8379
|
getPendingMessages: (target) => this.pendingVisibleMessages(agentId, target),
|
|
7935
8380
|
isMessageModelSeen: ({ target, message }) => this.isVisibleMessageModelSeen(agentId, target, message),
|
|
7936
8381
|
getAllPendingMessages: () => this.allPendingVisibleMessages(agentId),
|
|
8382
|
+
recordInboxSnapshot: (input) => {
|
|
8383
|
+
this.recordDaemonTrace("daemon.agent.inbox_projection.snapshot", {
|
|
8384
|
+
agentId,
|
|
8385
|
+
source: input.source,
|
|
8386
|
+
...this.inboxProjectionTraceAttrs(input.rows, input.pendingMessageCount)
|
|
8387
|
+
});
|
|
8388
|
+
},
|
|
7937
8389
|
consumeVisibleMessages: (input) => this.consumeVisibleMessages(agentId, input),
|
|
7938
8390
|
recordDrainOutcome: (input) => {
|
|
7939
8391
|
this.recordDaemonTrace("daemon.agent.drain.outcome", {
|
|
@@ -9860,6 +10312,29 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
9860
10312
|
...messageProducerFactTraceAttrs(messages)
|
|
9861
10313
|
};
|
|
9862
10314
|
}
|
|
10315
|
+
inboxProjectionTraceAttrs(rows, pendingMessageCount) {
|
|
10316
|
+
let maxPendingCount = 0;
|
|
10317
|
+
let mentionTargetCount = 0;
|
|
10318
|
+
let threadTargetCount = 0;
|
|
10319
|
+
let dmTargetCount = 0;
|
|
10320
|
+
let taskTargetCount = 0;
|
|
10321
|
+
for (const row of rows) {
|
|
10322
|
+
maxPendingCount = Math.max(maxPendingCount, row.pendingCount);
|
|
10323
|
+
if (row.flags.includes("mention")) mentionTargetCount += 1;
|
|
10324
|
+
if (row.flags.includes("thread")) threadTargetCount += 1;
|
|
10325
|
+
if (row.flags.includes("dm")) dmTargetCount += 1;
|
|
10326
|
+
if (row.flags.includes("task")) taskTargetCount += 1;
|
|
10327
|
+
}
|
|
10328
|
+
return {
|
|
10329
|
+
inbox_target_count: rows.length,
|
|
10330
|
+
pending_message_count: pendingMessageCount,
|
|
10331
|
+
max_pending_per_target: maxPendingCount,
|
|
10332
|
+
mention_target_count: mentionTargetCount,
|
|
10333
|
+
thread_target_count: threadTargetCount,
|
|
10334
|
+
dm_target_count: dmTargetCount,
|
|
10335
|
+
task_target_count: taskTargetCount
|
|
10336
|
+
};
|
|
10337
|
+
}
|
|
9863
10338
|
runtimeProfileTurnControlTraceAttrs(control) {
|
|
9864
10339
|
if (!control) return {};
|
|
9865
10340
|
const pendingAgeMs = Math.max(0, Date.now() - control.injectedAtMs);
|
|
@@ -10458,11 +10933,13 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
10458
10933
|
}
|
|
10459
10934
|
}
|
|
10460
10935
|
recordRuntimeTelemetry(agentId, ap, event) {
|
|
10936
|
+
const sessionId = ap.driver.currentSessionId ?? event.sessionId;
|
|
10937
|
+
const payloadAttrs = sanitizeRuntimeTelemetryPayloadAttrs(event.attrs);
|
|
10461
10938
|
const telemetryAttrs = {
|
|
10462
|
-
...
|
|
10939
|
+
...payloadAttrs,
|
|
10463
10940
|
...event.source ? { source: event.source } : {},
|
|
10464
10941
|
...event.usageKind ? { usageKind: event.usageKind } : {},
|
|
10465
|
-
...
|
|
10942
|
+
...sessionId ? { sessionId } : {},
|
|
10466
10943
|
...event.turnId ? { turnId: event.turnId } : {},
|
|
10467
10944
|
...event.runtimeResultId ? { runtimeResultId: event.runtimeResultId } : {}
|
|
10468
10945
|
};
|
|
@@ -10548,11 +11025,29 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
10548
11025
|
}
|
|
10549
11026
|
const inboxCount = ap.inbox.length;
|
|
10550
11027
|
if (inboxCount === 0) return false;
|
|
10551
|
-
const
|
|
10552
|
-
|
|
11028
|
+
const inboxRows = projectAgentInboxSnapshot(ap.inbox);
|
|
11029
|
+
const notification = `[Slock inbox notice:
|
|
11030
|
+
${formatAgentInboxDelta(inboxRows)}]`;
|
|
11031
|
+
const notificationByteCount = Buffer.byteLength(notification, "utf8");
|
|
11032
|
+
const projectionAttrs = this.inboxProjectionTraceAttrs(inboxRows, inboxCount);
|
|
11033
|
+
this.recordDaemonTrace("daemon.agent.inbox_projection.delta", {
|
|
11034
|
+
agentId,
|
|
11035
|
+
source: "busy_stdin_notification",
|
|
11036
|
+
...projectionAttrs
|
|
11037
|
+
});
|
|
11038
|
+
logger.info(`[Agent ${agentId}] Sending stdin inbox update: ${inboxRows.length} changed target(s), ${inboxCount} pending message(s)`);
|
|
10553
11039
|
const encoded = ap.driver.encodeStdinMessage(notification, ap.sessionId, { mode: "busy" });
|
|
10554
11040
|
if (encoded) {
|
|
10555
11041
|
ap.process.stdin?.write(encoded + "\n");
|
|
11042
|
+
this.recordDaemonTrace("daemon.agent.inbox_update.pushed", {
|
|
11043
|
+
agentId,
|
|
11044
|
+
runtime: ap.config.runtime,
|
|
11045
|
+
model: ap.config.model,
|
|
11046
|
+
launchId: ap.launchId || void 0,
|
|
11047
|
+
mode: "busy",
|
|
11048
|
+
notification_byte_count: notificationByteCount,
|
|
11049
|
+
...projectionAttrs
|
|
11050
|
+
});
|
|
10556
11051
|
this.recordDaemonTrace("daemon.agent.stdin_notification", {
|
|
10557
11052
|
agentId,
|
|
10558
11053
|
runtime: ap.config.runtime,
|
|
@@ -10562,6 +11057,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
10562
11057
|
mode: "busy",
|
|
10563
11058
|
pending_notification_count: count,
|
|
10564
11059
|
inbox_count: inboxCount,
|
|
11060
|
+
inbox_target_count: inboxRows.length,
|
|
10565
11061
|
session_id_present: true
|
|
10566
11062
|
});
|
|
10567
11063
|
return true;
|
|
@@ -10579,6 +11075,7 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
10579
11075
|
retry_scheduled: retryScheduled,
|
|
10580
11076
|
notification_timer_present: ap.notifications.hasTimer,
|
|
10581
11077
|
inbox_count: inboxCount,
|
|
11078
|
+
inbox_target_count: inboxRows.length,
|
|
10582
11079
|
session_id_present: true
|
|
10583
11080
|
}, "error");
|
|
10584
11081
|
return false;
|
|
@@ -11116,7 +11613,7 @@ function acquireDaemonMachineLock(options) {
|
|
|
11116
11613
|
}
|
|
11117
11614
|
|
|
11118
11615
|
// src/localTraceSink.ts
|
|
11119
|
-
import { appendFileSync, mkdirSync as mkdirSync7, readdirSync as
|
|
11616
|
+
import { appendFileSync, mkdirSync as mkdirSync7, readdirSync as readdirSync3, rmSync as rmSync4, statSync as statSync3, writeFileSync as writeFileSync9 } from "fs";
|
|
11120
11617
|
import path15 from "path";
|
|
11121
11618
|
var DEFAULT_MAX_FILE_BYTES = 5 * 1024 * 1024;
|
|
11122
11619
|
var DEFAULT_MAX_FILE_AGE_MS = 5 * 60 * 1e3;
|
|
@@ -11195,7 +11692,7 @@ var LocalRotatingTraceSink = class {
|
|
|
11195
11692
|
}
|
|
11196
11693
|
}
|
|
11197
11694
|
pruneOldFiles() {
|
|
11198
|
-
const files =
|
|
11695
|
+
const files = readdirSync3(this.traceDir).filter((name) => name.startsWith("daemon-trace-") && name.endsWith(".jsonl")).sort();
|
|
11199
11696
|
const excess = files.length - this.maxFiles;
|
|
11200
11697
|
if (excess <= 0) return;
|
|
11201
11698
|
for (const file of files.slice(0, excess)) {
|
|
@@ -11637,7 +12134,7 @@ var DEFAULT_TRACE_UPLOAD_URL = "https://slock-trace-upload.botiverse.dev";
|
|
|
11637
12134
|
var RUNNER_CREDENTIAL_SCOPES = ["send", "read", "mentions", "tasks", "reactions", "server", "channels", "knowledge"];
|
|
11638
12135
|
var RUNNER_CREDENTIAL_MINT_MAX_ATTEMPTS2 = 3;
|
|
11639
12136
|
var RUNNER_CREDENTIAL_MINT_RETRY_DELAY_MS2 = 250;
|
|
11640
|
-
var DAEMON_CLI_USAGE =
|
|
12137
|
+
var DAEMON_CLI_USAGE = `Usage: slock-daemon --server-url <url> (--api-key <key> or ${DAEMON_API_KEY_ENV}=<key>)`;
|
|
11641
12138
|
var RunnerCredentialMintError2 = class extends Error {
|
|
11642
12139
|
code;
|
|
11643
12140
|
retryable;
|
|
@@ -11673,9 +12170,9 @@ function runnerCredentialErrorDetail2(error) {
|
|
|
11673
12170
|
async function waitForRunnerCredentialRetry2() {
|
|
11674
12171
|
await new Promise((resolve) => setTimeout(resolve, RUNNER_CREDENTIAL_MINT_RETRY_DELAY_MS2));
|
|
11675
12172
|
}
|
|
11676
|
-
function parseDaemonCliArgs(args) {
|
|
12173
|
+
function parseDaemonCliArgs(args, env = {}) {
|
|
11677
12174
|
let serverUrl = "";
|
|
11678
|
-
let apiKey = "";
|
|
12175
|
+
let apiKey = env[DAEMON_API_KEY_ENV] ?? "";
|
|
11679
12176
|
for (let i = 0; i < args.length; i++) {
|
|
11680
12177
|
if (args[i] === "--server-url" && args[i + 1]) serverUrl = args[++i];
|
|
11681
12178
|
if (args[i] === "--api-key" && args[i + 1]) apiKey = args[++i];
|
|
@@ -11864,7 +12361,7 @@ var DaemonCore = class {
|
|
|
11864
12361
|
this.slockHome = resolveSlockHome();
|
|
11865
12362
|
process.env[SLOCK_HOME_ENV] = this.slockHome;
|
|
11866
12363
|
this.injectedTracer = Boolean(options.tracer);
|
|
11867
|
-
this.tracer = options.tracer ?? noopTracer;
|
|
12364
|
+
this.tracer = this.withDaemonTraceScope(options.tracer ?? noopTracer);
|
|
11868
12365
|
this.runtimeDetector = options.runtimeDetector ?? (() => detectRuntimes(this.tracer));
|
|
11869
12366
|
this.reminderCache = new ReminderCache({
|
|
11870
12367
|
clock: options.reminderClock,
|
|
@@ -11915,9 +12412,9 @@ var DaemonCore = class {
|
|
|
11915
12412
|
maxFileAgeJitterMs: jitter.maxFileAgeJitterMs,
|
|
11916
12413
|
maxFiles: this.options.localTraceMaxFiles ?? readPositiveIntegerEnv3("SLOCK_DAEMON_TRACE_MAX_FILES", 8)
|
|
11917
12414
|
});
|
|
11918
|
-
this.tracer = new BasicTracer({
|
|
12415
|
+
this.tracer = this.withDaemonTraceScope(new BasicTracer({
|
|
11919
12416
|
sink: this.localTraceSink
|
|
11920
|
-
});
|
|
12417
|
+
}));
|
|
11921
12418
|
this.agentManager.setTracer(this.tracer);
|
|
11922
12419
|
this.agentManager.setCliTransportTraceDir(path17.join(machineDir, "traces"));
|
|
11923
12420
|
}
|
|
@@ -12011,6 +12508,23 @@ var DaemonCore = class {
|
|
|
12011
12508
|
});
|
|
12012
12509
|
span.end(status);
|
|
12013
12510
|
}
|
|
12511
|
+
withDaemonTraceScope(tracer) {
|
|
12512
|
+
return createScopedTracer(tracer, this.daemonTraceScopeAttrs());
|
|
12513
|
+
}
|
|
12514
|
+
daemonTraceScopeAttrs() {
|
|
12515
|
+
return {
|
|
12516
|
+
daemonVersion: this.daemonVersion,
|
|
12517
|
+
daemon_version: this.daemonVersion,
|
|
12518
|
+
daemon_version_present: Boolean(this.daemonVersion),
|
|
12519
|
+
...this.computerVersion ? {
|
|
12520
|
+
computerVersion: this.computerVersion,
|
|
12521
|
+
computer_version: this.computerVersion,
|
|
12522
|
+
computer_version_present: true
|
|
12523
|
+
} : {
|
|
12524
|
+
computer_version_present: false
|
|
12525
|
+
}
|
|
12526
|
+
};
|
|
12527
|
+
}
|
|
12014
12528
|
async requestRunnerCredentialOnce(agentId, config) {
|
|
12015
12529
|
const url = new URL(`/internal/computer/runners/${encodeURIComponent(agentId)}/credentials`, this.options.serverUrl);
|
|
12016
12530
|
const res = await daemonFetch(url, {
|
|
@@ -12371,8 +12885,7 @@ var DaemonCore = class {
|
|
|
12371
12885
|
runtimes_count: runtimes.length,
|
|
12372
12886
|
running_agents_count: runningAgentIds.length,
|
|
12373
12887
|
idle_agents_count: idleAgentSessions.length,
|
|
12374
|
-
runtime_profile_reports_count: runtimeProfileReports.length
|
|
12375
|
-
daemon_version_present: Boolean(this.daemonVersion)
|
|
12888
|
+
runtime_profile_reports_count: runtimeProfileReports.length
|
|
12376
12889
|
});
|
|
12377
12890
|
for (const agentId of runningAgentIds) {
|
|
12378
12891
|
const sessionId = this.agentManager.getAgentSessionId(agentId);
|
|
@@ -12426,6 +12939,8 @@ var DaemonCore = class {
|
|
|
12426
12939
|
};
|
|
12427
12940
|
|
|
12428
12941
|
export {
|
|
12942
|
+
DAEMON_API_KEY_ENV,
|
|
12943
|
+
scrubDaemonAuthEnv,
|
|
12429
12944
|
resolveWorkspaceDirectoryPath,
|
|
12430
12945
|
scanWorkspaceDirectories,
|
|
12431
12946
|
deleteWorkspaceDirectory,
|