squadrant 0.26.1 → 0.26.3
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/index.js +1186 -730
- package/dist/index.js.map +1 -1
- package/dist/squadrantd.js +566 -171
- package/dist/squadrantd.js.map +1 -1
- package/package.json +1 -1
- package/plugin/skills/rules-ops/SKILL.md +2 -0
package/dist/squadrantd.js
CHANGED
|
@@ -423,22 +423,22 @@ function defaultCmuxConfigPath() {
|
|
|
423
423
|
return join(homedir(), ".config", "cmux", "cmux.json");
|
|
424
424
|
}
|
|
425
425
|
function ensureSocketAutomation(opts = {}) {
|
|
426
|
-
const
|
|
427
|
-
if (!existsSync(
|
|
428
|
-
mkdirSync(dirname(
|
|
429
|
-
writeFileSync(
|
|
430
|
-
return { path:
|
|
426
|
+
const path29 = opts.path ?? defaultCmuxConfigPath();
|
|
427
|
+
if (!existsSync(path29)) {
|
|
428
|
+
mkdirSync(dirname(path29), { recursive: true });
|
|
429
|
+
writeFileSync(path29, MINIMAL_TEMPLATE);
|
|
430
|
+
return { path: path29, changed: true, alreadySet: false };
|
|
431
431
|
}
|
|
432
|
-
const text = readFileSync(
|
|
432
|
+
const text = readFileSync(path29, "utf-8");
|
|
433
433
|
const current = parse(text)?.automation?.socketControlMode;
|
|
434
434
|
if (current === AUTOMATION_MODE) {
|
|
435
|
-
return { path:
|
|
435
|
+
return { path: path29, changed: false, alreadySet: true };
|
|
436
436
|
}
|
|
437
437
|
const edits = modify(text, [...SOCKET_CONTROL_MODE_PATH], AUTOMATION_MODE, {
|
|
438
438
|
formattingOptions: { insertSpaces: true, tabSize: 2 }
|
|
439
439
|
});
|
|
440
|
-
writeFileSync(
|
|
441
|
-
return { path:
|
|
440
|
+
writeFileSync(path29, applyEdits(text, edits));
|
|
441
|
+
return { path: path29, changed: true, alreadySet: false };
|
|
442
442
|
}
|
|
443
443
|
var SOCKET_CONTROL_MODE_PATH, AUTOMATION_MODE, MINIMAL_TEMPLATE;
|
|
444
444
|
var init_cmux_config = __esm({
|
|
@@ -588,9 +588,9 @@ import { join as join4 } from "path";
|
|
|
588
588
|
function defaultStatePath() {
|
|
589
589
|
return join4(homedir3(), ".config", "squadrant", "state", "cmux-autoconfig.json");
|
|
590
590
|
}
|
|
591
|
-
function readState(
|
|
591
|
+
function readState(path29) {
|
|
592
592
|
try {
|
|
593
|
-
return JSON.parse(readConfigFileSync(
|
|
593
|
+
return JSON.parse(readConfigFileSync(path29));
|
|
594
594
|
} catch {
|
|
595
595
|
return {};
|
|
596
596
|
}
|
|
@@ -1774,12 +1774,12 @@ async function* readFromCursor(opts) {
|
|
|
1774
1774
|
continue;
|
|
1775
1775
|
throw e;
|
|
1776
1776
|
}
|
|
1777
|
-
for (const
|
|
1778
|
-
if (!
|
|
1777
|
+
for (const line2 of buf.split("\n")) {
|
|
1778
|
+
if (!line2.trim())
|
|
1779
1779
|
continue;
|
|
1780
1780
|
let entry;
|
|
1781
1781
|
try {
|
|
1782
|
-
entry = JSON.parse(
|
|
1782
|
+
entry = JSON.parse(line2);
|
|
1783
1783
|
} catch {
|
|
1784
1784
|
continue;
|
|
1785
1785
|
}
|
|
@@ -1881,17 +1881,17 @@ function createDecoder(onParseError) {
|
|
|
1881
1881
|
const out = [];
|
|
1882
1882
|
let idx;
|
|
1883
1883
|
while ((idx = buf.indexOf("\n")) >= 0) {
|
|
1884
|
-
const
|
|
1884
|
+
const line2 = buf.slice(0, idx);
|
|
1885
1885
|
buf = buf.slice(idx + 1);
|
|
1886
|
-
if (!
|
|
1886
|
+
if (!line2.trim())
|
|
1887
1887
|
continue;
|
|
1888
1888
|
try {
|
|
1889
|
-
const parsed = JSON.parse(
|
|
1889
|
+
const parsed = JSON.parse(line2);
|
|
1890
1890
|
if (typeof parsed === "object" && parsed !== null && parsed.type === "_keepalive")
|
|
1891
1891
|
continue;
|
|
1892
1892
|
out.push(parsed);
|
|
1893
1893
|
} catch {
|
|
1894
|
-
onParseError?.(
|
|
1894
|
+
onParseError?.(line2);
|
|
1895
1895
|
}
|
|
1896
1896
|
}
|
|
1897
1897
|
return out;
|
|
@@ -2051,11 +2051,11 @@ function encodeFrame(f) {
|
|
|
2051
2051
|
}
|
|
2052
2052
|
function decodeFrames(wire) {
|
|
2053
2053
|
const out = [];
|
|
2054
|
-
for (const
|
|
2055
|
-
if (!
|
|
2054
|
+
for (const line2 of wire.split("\n")) {
|
|
2055
|
+
if (!line2.trim())
|
|
2056
2056
|
continue;
|
|
2057
2057
|
try {
|
|
2058
|
-
const parsed = JSON.parse(
|
|
2058
|
+
const parsed = JSON.parse(line2);
|
|
2059
2059
|
if (parsed.type === "_keepalive")
|
|
2060
2060
|
continue;
|
|
2061
2061
|
out.push(parsed);
|
|
@@ -2537,10 +2537,10 @@ function detectForeignInstall(parsed, thisEntry, registeredEntryExists) {
|
|
|
2537
2537
|
isUpgrade: isVersionUpgrade(parsed.daemonEntry, thisEntry)
|
|
2538
2538
|
};
|
|
2539
2539
|
}
|
|
2540
|
-
function sanitizePathForPlist(
|
|
2540
|
+
function sanitizePathForPlist(path29) {
|
|
2541
2541
|
const seen = /* @__PURE__ */ new Set();
|
|
2542
2542
|
const stable = [];
|
|
2543
|
-
for (const p of
|
|
2543
|
+
for (const p of path29.split(":")) {
|
|
2544
2544
|
if (!p)
|
|
2545
2545
|
continue;
|
|
2546
2546
|
if (p.includes("/.claude/plugins/"))
|
|
@@ -3243,14 +3243,14 @@ function detectTrailingQuestion(text) {
|
|
|
3243
3243
|
let inFence = false;
|
|
3244
3244
|
let lastLine = null;
|
|
3245
3245
|
for (const raw of text.split(/\r?\n/)) {
|
|
3246
|
-
const
|
|
3247
|
-
if (
|
|
3246
|
+
const line2 = raw.trim();
|
|
3247
|
+
if (line2.startsWith("```")) {
|
|
3248
3248
|
inFence = !inFence;
|
|
3249
3249
|
continue;
|
|
3250
3250
|
}
|
|
3251
|
-
if (inFence ||
|
|
3251
|
+
if (inFence || line2 === "")
|
|
3252
3252
|
continue;
|
|
3253
|
-
lastLine =
|
|
3253
|
+
lastLine = line2;
|
|
3254
3254
|
}
|
|
3255
3255
|
if (lastLine && lastLine.endsWith("?"))
|
|
3256
3256
|
return lastLine;
|
|
@@ -3261,9 +3261,9 @@ function isQuotedLine(raw) {
|
|
|
3261
3261
|
return QUOTED_PREFIX_RE.test(noAnsi);
|
|
3262
3262
|
}
|
|
3263
3263
|
function stripChrome(raw) {
|
|
3264
|
-
let
|
|
3265
|
-
|
|
3266
|
-
const trimmed =
|
|
3264
|
+
let line2 = raw.replace(/\[[0-9;]*m/g, "");
|
|
3265
|
+
line2 = line2.replace(/^[\s│┃▏▕|]+/, "").replace(/[\s│┃▏▕|]+$/, "");
|
|
3266
|
+
const trimmed = line2.trim();
|
|
3267
3267
|
if (trimmed === "")
|
|
3268
3268
|
return null;
|
|
3269
3269
|
if (PURE_CHROME_RE.test(trimmed))
|
|
@@ -3924,12 +3924,12 @@ function extractUserIntentFromTranscript(jsonl) {
|
|
|
3924
3924
|
return null;
|
|
3925
3925
|
const lines = jsonl.split(/\r?\n/);
|
|
3926
3926
|
for (let i = lines.length - 1; i >= 0; i--) {
|
|
3927
|
-
const
|
|
3928
|
-
if (!
|
|
3927
|
+
const line2 = lines[i].trim();
|
|
3928
|
+
if (!line2)
|
|
3929
3929
|
continue;
|
|
3930
3930
|
let entry;
|
|
3931
3931
|
try {
|
|
3932
|
-
entry = JSON.parse(
|
|
3932
|
+
entry = JSON.parse(line2);
|
|
3933
3933
|
} catch {
|
|
3934
3934
|
continue;
|
|
3935
3935
|
}
|
|
@@ -4378,10 +4378,10 @@ async function reapCrewChildren(taskId, graceMs = 2e3, execFn = nodeExec) {
|
|
|
4378
4378
|
execFn("ps auxE", { maxBuffer: 64 * 1024 * 1024 }, (err, out) => err ? reject(err) : resolve4(out));
|
|
4379
4379
|
});
|
|
4380
4380
|
const pids = [];
|
|
4381
|
-
for (const
|
|
4382
|
-
if (!
|
|
4381
|
+
for (const line2 of stdout.split("\n").slice(1)) {
|
|
4382
|
+
if (!line2.includes(marker))
|
|
4383
4383
|
continue;
|
|
4384
|
-
const pid = parseInt(
|
|
4384
|
+
const pid = parseInt(line2.trim().split(/\s+/)[1], 10);
|
|
4385
4385
|
if (!isNaN(pid) && pid !== process.pid)
|
|
4386
4386
|
pids.push(pid);
|
|
4387
4387
|
}
|
|
@@ -4662,9 +4662,13 @@ async function runCrewSpawn(input, config, deps) {
|
|
|
4662
4662
|
await deps.runtime.sendToPane(pane2, `cd ${shellQuote(spawnCwd)} && ${envPrefix}${routerPrefix} ${niceCrewCommand(cliCommand2)}`);
|
|
4663
4663
|
const preLaunchScreen = await deps.runtime.readPaneScreen(pane2) ?? "";
|
|
4664
4664
|
const claudeFirstTurn = spillOversizedFirstTurn(firstTurnTask, rec.id);
|
|
4665
|
-
const
|
|
4665
|
+
const peerBrief = `${firstTurnTask}
|
|
4666
4666
|
|
|
4667
|
-
${buildCompletionProtocol(rec.id, input.project)}
|
|
4667
|
+
${buildCompletionProtocol(rec.id, input.project)}`;
|
|
4668
|
+
const peerResult = deps.sendFirstTurnPeer ? await deps.sendFirstTurnPeer({ pane: pane2, taskId: rec.id, project: input.project, messagingSocketPath, message: peerBrief }).catch(() => ({ kind: "fallback" })) : { kind: "fallback" };
|
|
4669
|
+
const sendPromise = peerResult.kind === "fallback" ? deps.sendFirstTurn(pane2, `${claudeFirstTurn}
|
|
4670
|
+
|
|
4671
|
+
${buildCompletionProtocol(rec.id, input.project)}`, preLaunchScreen) : Promise.resolve({ delivered: peerResult.kind === "delivered" });
|
|
4668
4672
|
let agentNotStarted = false;
|
|
4669
4673
|
const scrapeDelivered = sendPromise.then((r) => {
|
|
4670
4674
|
agentNotStarted = !!r.agentNotStarted;
|
|
@@ -5076,11 +5080,11 @@ var init_captain_record = __esm({
|
|
|
5076
5080
|
// packages/core/dist/opencode-session.js
|
|
5077
5081
|
import { execFileSync as execFileSync4 } from "child_process";
|
|
5078
5082
|
async function listSessions(port, fetchImpl = fetch, timeoutMs = 5e3) {
|
|
5079
|
-
for (const
|
|
5083
|
+
for (const path29 of ["/session", "/api/session"]) {
|
|
5080
5084
|
const ac = new AbortController();
|
|
5081
5085
|
const t = setTimeout(() => ac.abort(), timeoutMs);
|
|
5082
5086
|
try {
|
|
5083
|
-
const res = await fetchImpl(`http://127.0.0.1:${port}${
|
|
5087
|
+
const res = await fetchImpl(`http://127.0.0.1:${port}${path29}`, { signal: ac.signal });
|
|
5084
5088
|
if (!res.ok)
|
|
5085
5089
|
continue;
|
|
5086
5090
|
const rows = await res.json();
|
|
@@ -5095,8 +5099,8 @@ async function listSessions(port, fetchImpl = fetch, timeoutMs = 5e3) {
|
|
|
5095
5099
|
}
|
|
5096
5100
|
function parseLiveOpencodeServers(psOutput) {
|
|
5097
5101
|
const out = [];
|
|
5098
|
-
for (const
|
|
5099
|
-
const m =
|
|
5102
|
+
for (const line2 of psOutput.split("\n")) {
|
|
5103
|
+
const m = line2.match(/^\s*(\d+)\s+(.+)$/);
|
|
5100
5104
|
if (!m)
|
|
5101
5105
|
continue;
|
|
5102
5106
|
const pid = Number(m[1]);
|
|
@@ -5122,8 +5126,8 @@ function defaultPsOutput() {
|
|
|
5122
5126
|
function defaultCwdOf(pid) {
|
|
5123
5127
|
try {
|
|
5124
5128
|
const out = execFileSync4("lsof", ["-a", "-p", String(pid), "-d", "cwd", "-Fn"], { encoding: "utf-8", timeout: 2e3 });
|
|
5125
|
-
const
|
|
5126
|
-
return
|
|
5129
|
+
const line2 = out.split("\n").find((l) => l.startsWith("n"));
|
|
5130
|
+
return line2 ? line2.slice(1) : null;
|
|
5127
5131
|
} catch {
|
|
5128
5132
|
return null;
|
|
5129
5133
|
}
|
|
@@ -5773,10 +5777,10 @@ function distBuiltAt() {
|
|
|
5773
5777
|
return 0;
|
|
5774
5778
|
}
|
|
5775
5779
|
}
|
|
5776
|
-
function gatherLogStats(
|
|
5780
|
+
function gatherLogStats(path29, now, windowMs) {
|
|
5777
5781
|
let sizeBytes = 0;
|
|
5778
5782
|
try {
|
|
5779
|
-
sizeBytes = statSync3(
|
|
5783
|
+
sizeBytes = statSync3(path29).size;
|
|
5780
5784
|
} catch {
|
|
5781
5785
|
return { errorCount: 0, sizeBytes: 0, windowMs };
|
|
5782
5786
|
}
|
|
@@ -5787,7 +5791,7 @@ function gatherLogStats(path28, now, windowMs) {
|
|
|
5787
5791
|
const len = sizeBytes - start;
|
|
5788
5792
|
let text = "";
|
|
5789
5793
|
try {
|
|
5790
|
-
const fd = openSync2(
|
|
5794
|
+
const fd = openSync2(path29, "r");
|
|
5791
5795
|
try {
|
|
5792
5796
|
const buf = Buffer.alloc(len);
|
|
5793
5797
|
readSync(fd, buf, 0, len, start);
|
|
@@ -5800,10 +5804,10 @@ function gatherLogStats(path28, now, windowMs) {
|
|
|
5800
5804
|
}
|
|
5801
5805
|
const cutoff = now - windowMs;
|
|
5802
5806
|
let errorCount = 0;
|
|
5803
|
-
for (const
|
|
5804
|
-
if (!/error|failed/i.test(
|
|
5807
|
+
for (const line2 of text.split("\n")) {
|
|
5808
|
+
if (!/error|failed/i.test(line2))
|
|
5805
5809
|
continue;
|
|
5806
|
-
const m =
|
|
5810
|
+
const m = line2.match(/\d{4}-\d{2}-\d{2}T[\d:.]+Z/);
|
|
5807
5811
|
if (m) {
|
|
5808
5812
|
const ts = Date.parse(m[0]);
|
|
5809
5813
|
if (!Number.isNaN(ts) && ts < cutoff)
|
|
@@ -7978,10 +7982,10 @@ function scan(bufRef, acc) {
|
|
|
7978
7982
|
let saw = false;
|
|
7979
7983
|
let idx;
|
|
7980
7984
|
while ((idx = bufRef.value.indexOf("\n")) !== -1) {
|
|
7981
|
-
const
|
|
7985
|
+
const line2 = bufRef.value.slice(0, idx).trim();
|
|
7982
7986
|
bufRef.value = bufRef.value.slice(idx + 1);
|
|
7983
|
-
if (
|
|
7984
|
-
const payload =
|
|
7987
|
+
if (line2.startsWith("data:")) {
|
|
7988
|
+
const payload = line2.slice(5).trim();
|
|
7985
7989
|
if (payload && payload !== "[DONE]") {
|
|
7986
7990
|
try {
|
|
7987
7991
|
if (absorb(JSON.parse(payload), acc))
|
|
@@ -8032,8 +8036,8 @@ var init_stream = __esm({
|
|
|
8032
8036
|
// packages/core/dist/router/shim.js
|
|
8033
8037
|
import { createServer as createServer3 } from "http";
|
|
8034
8038
|
import { Readable } from "stream";
|
|
8035
|
-
function joinUrl(base,
|
|
8036
|
-
return base.replace(/\/+$/, "") +
|
|
8039
|
+
function joinUrl(base, path29) {
|
|
8040
|
+
return base.replace(/\/+$/, "") + path29;
|
|
8037
8041
|
}
|
|
8038
8042
|
async function readBody(req) {
|
|
8039
8043
|
const chunks = [];
|
|
@@ -8209,8 +8213,8 @@ function createRouterShim(opts) {
|
|
|
8209
8213
|
writeJson(res, 200, { input_tokens: Math.max(1, Math.ceil(text.length / 4)) });
|
|
8210
8214
|
}
|
|
8211
8215
|
function handler(req, res) {
|
|
8212
|
-
const
|
|
8213
|
-
if (req.method === "POST" &&
|
|
8216
|
+
const path29 = pathnameOf(req.url);
|
|
8217
|
+
if (req.method === "POST" && path29 === "/v1/messages") {
|
|
8214
8218
|
void handleMessages(req, res).catch((err) => {
|
|
8215
8219
|
log(`router internal error: ${err instanceof Error ? err.message : String(err)}`);
|
|
8216
8220
|
if (!res.headersSent) {
|
|
@@ -8222,18 +8226,18 @@ function createRouterShim(opts) {
|
|
|
8222
8226
|
});
|
|
8223
8227
|
return;
|
|
8224
8228
|
}
|
|
8225
|
-
if (req.method === "POST" &&
|
|
8229
|
+
if (req.method === "POST" && path29 === "/v1/messages/count_tokens") {
|
|
8226
8230
|
void handleCountTokens(req, res).catch(() => {
|
|
8227
8231
|
if (!res.headersSent)
|
|
8228
8232
|
writeJson(res, 502, anthropicError(502, "api_error", "router internal error").body);
|
|
8229
8233
|
});
|
|
8230
8234
|
return;
|
|
8231
8235
|
}
|
|
8232
|
-
if (req.method === "GET" &&
|
|
8236
|
+
if (req.method === "GET" && path29 === "/v1/models") {
|
|
8233
8237
|
writeJson(res, 200, modelsList([...advertisedModels]));
|
|
8234
8238
|
return;
|
|
8235
8239
|
}
|
|
8236
|
-
if (req.method === "GET" &&
|
|
8240
|
+
if (req.method === "GET" && path29 === "/healthz") {
|
|
8237
8241
|
writeJson(res, 200, { ready: server?.listening === true, upstreamReachable, lastError });
|
|
8238
8242
|
return;
|
|
8239
8243
|
}
|
|
@@ -8502,11 +8506,11 @@ async function probeCaptainChannel(project, opts = {}) {
|
|
|
8502
8506
|
}
|
|
8503
8507
|
}
|
|
8504
8508
|
async function httpReachable(port, fetchImpl, timeoutMs) {
|
|
8505
|
-
for (const
|
|
8509
|
+
for (const path29 of ["/session", "/api/session"]) {
|
|
8506
8510
|
const ac = new AbortController();
|
|
8507
8511
|
const t = setTimeout(() => ac.abort(), timeoutMs);
|
|
8508
8512
|
try {
|
|
8509
|
-
const res = await fetchImpl(`http://127.0.0.1:${port}${
|
|
8513
|
+
const res = await fetchImpl(`http://127.0.0.1:${port}${path29}`, { signal: ac.signal });
|
|
8510
8514
|
if (res.ok)
|
|
8511
8515
|
return true;
|
|
8512
8516
|
} catch {
|
|
@@ -8889,6 +8893,30 @@ async function runCrewAnswer(project, name, option, runtime, workspaceId, deps,
|
|
|
8889
8893
|
if (!crew) {
|
|
8890
8894
|
throw new Error(`Crew '${name}' not found for ${project}. Run 'squadrant crew list ${project}'.`);
|
|
8891
8895
|
}
|
|
8896
|
+
const match = runtime.findDialog && runtime.answerDialog ? await deps.dialogMatch?.() : void 0;
|
|
8897
|
+
if (match) {
|
|
8898
|
+
const dialog = await runtime.findDialog(match).catch(() => void 0);
|
|
8899
|
+
if (dialog) {
|
|
8900
|
+
const log2 = deps.log ?? (() => {
|
|
8901
|
+
});
|
|
8902
|
+
const options2 = dialog.options.map((o) => ({ ...o, highlighted: false }));
|
|
8903
|
+
let target2;
|
|
8904
|
+
try {
|
|
8905
|
+
target2 = resolveOption(options2, option);
|
|
8906
|
+
if (opts?.expect && !target2.label.toLowerCase().includes(opts.expect.toLowerCase()))
|
|
8907
|
+
target2 = void 0;
|
|
8908
|
+
} catch {
|
|
8909
|
+
target2 = void 0;
|
|
8910
|
+
}
|
|
8911
|
+
if (target2) {
|
|
8912
|
+
log2(`\u2192 answering ${target2.index}. "${target2.label}" via the runtime (no keystrokes)`);
|
|
8913
|
+
const ok2 = await runtime.answerDialog(dialog, opts?.text ? { text: opts.text } : { label: target2.label }).catch(() => false);
|
|
8914
|
+
if (ok2)
|
|
8915
|
+
return { selected: target2, closed: true };
|
|
8916
|
+
}
|
|
8917
|
+
log2("runtime answer not applied \u2014 falling back to keystrokes");
|
|
8918
|
+
}
|
|
8919
|
+
}
|
|
8892
8920
|
const modal = await deps.readModalOptions(crew);
|
|
8893
8921
|
if (!modal || modal.options.length === 0) {
|
|
8894
8922
|
throw new Error(`Crew '${name}' has no interactive option prompt visible right now \u2014 nothing to answer. Read its screen with 'squadrant crew read ${project} ${name}' to check its state.`);
|
|
@@ -9268,6 +9296,58 @@ var init_source = __esm({
|
|
|
9268
9296
|
}
|
|
9269
9297
|
});
|
|
9270
9298
|
|
|
9299
|
+
// packages/core/dist/peer-first-turn.js
|
|
9300
|
+
function screenShowsTrustPanel(screen) {
|
|
9301
|
+
return /do you trust the files in this folder|is this a project you created or one you trust|is this a project you trust/i.test(screen);
|
|
9302
|
+
}
|
|
9303
|
+
function trustPanelAcceptKeys(screen) {
|
|
9304
|
+
return /❯\s*(\d\.\s*)?No\b/.test(screen) ? ["Down", "Enter"] : ["Enter"];
|
|
9305
|
+
}
|
|
9306
|
+
async function deliverFirstTurnViaPeer(message, deps) {
|
|
9307
|
+
const pollMs = deps.pollMs ?? DEFAULT_POLL_MS2;
|
|
9308
|
+
const deadline = deps.now() + (deps.readyTimeoutMs ?? DEFAULT_READY_TIMEOUT_MS);
|
|
9309
|
+
let lastTrustAnswer = -Infinity;
|
|
9310
|
+
for (; ; ) {
|
|
9311
|
+
if (deps.statusOf()?.status === "idle")
|
|
9312
|
+
break;
|
|
9313
|
+
if (deps.now() >= deadline)
|
|
9314
|
+
return { kind: "fallback" };
|
|
9315
|
+
if (!deps.statusOf() && deps.now() - lastTrustAnswer >= TRUST_ANSWER_COOLDOWN_MS) {
|
|
9316
|
+
const screen = await deps.readScreen().catch(() => "");
|
|
9317
|
+
if (screenShowsTrustPanel(screen)) {
|
|
9318
|
+
lastTrustAnswer = deps.now();
|
|
9319
|
+
for (const key of trustPanelAcceptKeys(screen))
|
|
9320
|
+
await deps.pressKey(key).catch(() => {
|
|
9321
|
+
});
|
|
9322
|
+
}
|
|
9323
|
+
}
|
|
9324
|
+
await deps.sleep(pollMs);
|
|
9325
|
+
}
|
|
9326
|
+
const outcome = await deps.send(message);
|
|
9327
|
+
if (fallsBackToPane(outcome))
|
|
9328
|
+
return { kind: "fallback" };
|
|
9329
|
+
if (outcome.status === "accepted" && outcome.confirmed)
|
|
9330
|
+
return { kind: "delivered" };
|
|
9331
|
+
const confirmDeadline = deps.now() + (deps.confirmGraceMs ?? DEFAULT_CONFIRM_GRACE_MS);
|
|
9332
|
+
for (; ; ) {
|
|
9333
|
+
if (await deps.isConfirmed().catch(() => false))
|
|
9334
|
+
return { kind: "delivered" };
|
|
9335
|
+
if (deps.now() >= confirmDeadline)
|
|
9336
|
+
return { kind: "unconfirmed" };
|
|
9337
|
+
await deps.sleep(pollMs);
|
|
9338
|
+
}
|
|
9339
|
+
}
|
|
9340
|
+
var DEFAULT_READY_TIMEOUT_MS, DEFAULT_POLL_MS2, DEFAULT_CONFIRM_GRACE_MS, TRUST_ANSWER_COOLDOWN_MS;
|
|
9341
|
+
var init_peer_first_turn = __esm({
|
|
9342
|
+
"packages/core/dist/peer-first-turn.js"() {
|
|
9343
|
+
init_control_channel();
|
|
9344
|
+
DEFAULT_READY_TIMEOUT_MS = 9e4;
|
|
9345
|
+
DEFAULT_POLL_MS2 = 250;
|
|
9346
|
+
DEFAULT_CONFIRM_GRACE_MS = 1e4;
|
|
9347
|
+
TRUST_ANSWER_COOLDOWN_MS = 5e3;
|
|
9348
|
+
}
|
|
9349
|
+
});
|
|
9350
|
+
|
|
9271
9351
|
// packages/core/dist/knowledge/paths.js
|
|
9272
9352
|
import path14 from "path";
|
|
9273
9353
|
function kbDir(hubVault, kb) {
|
|
@@ -9689,28 +9769,28 @@ function requireSnippet() {
|
|
|
9689
9769
|
const maxLineLength = options.maxLength - (options.indent + lineNoLength + 3);
|
|
9690
9770
|
for (let i = 1; i <= options.linesBefore; i++) {
|
|
9691
9771
|
if (foundLineNo - i < 0) break;
|
|
9692
|
-
const
|
|
9772
|
+
const line22 = getLine(
|
|
9693
9773
|
mark2.buffer,
|
|
9694
9774
|
lineStarts[foundLineNo - i],
|
|
9695
9775
|
lineEnds[foundLineNo - i],
|
|
9696
9776
|
mark2.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo - i]),
|
|
9697
9777
|
maxLineLength
|
|
9698
9778
|
);
|
|
9699
|
-
result = common2.repeat(" ", options.indent) + padStart((mark2.line - i + 1).toString(), lineNoLength) + " | " +
|
|
9779
|
+
result = common2.repeat(" ", options.indent) + padStart((mark2.line - i + 1).toString(), lineNoLength) + " | " + line22.str + "\n" + result;
|
|
9700
9780
|
}
|
|
9701
|
-
const
|
|
9702
|
-
result += common2.repeat(" ", options.indent) + padStart((mark2.line + 1).toString(), lineNoLength) + " | " +
|
|
9703
|
-
result += common2.repeat("-", options.indent + lineNoLength + 3 +
|
|
9781
|
+
const line2 = getLine(mark2.buffer, lineStarts[foundLineNo], lineEnds[foundLineNo], mark2.position, maxLineLength);
|
|
9782
|
+
result += common2.repeat(" ", options.indent) + padStart((mark2.line + 1).toString(), lineNoLength) + " | " + line2.str + "\n";
|
|
9783
|
+
result += common2.repeat("-", options.indent + lineNoLength + 3 + line2.pos) + "^\n";
|
|
9704
9784
|
for (let i = 1; i <= options.linesAfter; i++) {
|
|
9705
9785
|
if (foundLineNo + i >= lineEnds.length) break;
|
|
9706
|
-
const
|
|
9786
|
+
const line22 = getLine(
|
|
9707
9787
|
mark2.buffer,
|
|
9708
9788
|
lineStarts[foundLineNo + i],
|
|
9709
9789
|
lineEnds[foundLineNo + i],
|
|
9710
9790
|
mark2.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo + i]),
|
|
9711
9791
|
maxLineLength
|
|
9712
9792
|
);
|
|
9713
|
-
result += common2.repeat(" ", options.indent) + padStart((mark2.line + i + 1).toString(), lineNoLength) + " | " +
|
|
9793
|
+
result += common2.repeat(" ", options.indent) + padStart((mark2.line + i + 1).toString(), lineNoLength) + " | " + line22.str + "\n";
|
|
9714
9794
|
}
|
|
9715
9795
|
return result.replace(/\n$/, "");
|
|
9716
9796
|
}
|
|
@@ -11997,17 +12077,17 @@ function requireDumper() {
|
|
|
11997
12077
|
let result = "";
|
|
11998
12078
|
const length = string.length;
|
|
11999
12079
|
while (position < length) {
|
|
12000
|
-
let
|
|
12080
|
+
let line2;
|
|
12001
12081
|
const next = string.indexOf("\n", position);
|
|
12002
12082
|
if (next === -1) {
|
|
12003
|
-
|
|
12083
|
+
line2 = string.slice(position);
|
|
12004
12084
|
position = length;
|
|
12005
12085
|
} else {
|
|
12006
|
-
|
|
12086
|
+
line2 = string.slice(position, next + 1);
|
|
12007
12087
|
position = next + 1;
|
|
12008
12088
|
}
|
|
12009
|
-
if (
|
|
12010
|
-
result +=
|
|
12089
|
+
if (line2.length && line2 !== "\n") result += ind;
|
|
12090
|
+
result += line2;
|
|
12011
12091
|
}
|
|
12012
12092
|
return result;
|
|
12013
12093
|
}
|
|
@@ -12192,15 +12272,15 @@ function requireDumper() {
|
|
|
12192
12272
|
let match;
|
|
12193
12273
|
while (match = lineRe.exec(string)) {
|
|
12194
12274
|
const prefix = match[1];
|
|
12195
|
-
const
|
|
12196
|
-
moreIndented =
|
|
12197
|
-
result += prefix + (!prevMoreIndented && !moreIndented &&
|
|
12275
|
+
const line2 = match[2];
|
|
12276
|
+
moreIndented = line2[0] === " ";
|
|
12277
|
+
result += prefix + (!prevMoreIndented && !moreIndented && line2 !== "" ? "\n" : "") + foldLine(line2, width);
|
|
12198
12278
|
prevMoreIndented = moreIndented;
|
|
12199
12279
|
}
|
|
12200
12280
|
return result;
|
|
12201
12281
|
}
|
|
12202
|
-
function foldLine(
|
|
12203
|
-
if (
|
|
12282
|
+
function foldLine(line2, width) {
|
|
12283
|
+
if (line2 === "" || line2[0] === " ") return line2;
|
|
12204
12284
|
const breakRe = / [^ ]/g;
|
|
12205
12285
|
let match;
|
|
12206
12286
|
let start = 0;
|
|
@@ -12208,20 +12288,20 @@ function requireDumper() {
|
|
|
12208
12288
|
let curr = 0;
|
|
12209
12289
|
let next = 0;
|
|
12210
12290
|
let result = "";
|
|
12211
|
-
while (match = breakRe.exec(
|
|
12291
|
+
while (match = breakRe.exec(line2)) {
|
|
12212
12292
|
next = match.index;
|
|
12213
12293
|
if (next - start > width) {
|
|
12214
12294
|
end = curr > start ? curr : next;
|
|
12215
|
-
result += "\n" +
|
|
12295
|
+
result += "\n" + line2.slice(start, end);
|
|
12216
12296
|
start = end + 1;
|
|
12217
12297
|
}
|
|
12218
12298
|
curr = next;
|
|
12219
12299
|
}
|
|
12220
12300
|
result += "\n";
|
|
12221
|
-
if (
|
|
12222
|
-
result +=
|
|
12301
|
+
if (line2.length - start > width && curr > start) {
|
|
12302
|
+
result += line2.slice(start, curr) + "\n" + line2.slice(curr + 1);
|
|
12223
12303
|
} else {
|
|
12224
|
-
result +=
|
|
12304
|
+
result += line2.slice(start);
|
|
12225
12305
|
}
|
|
12226
12306
|
return result.slice(1);
|
|
12227
12307
|
}
|
|
@@ -12630,6 +12710,220 @@ var init_sources = __esm({
|
|
|
12630
12710
|
}
|
|
12631
12711
|
});
|
|
12632
12712
|
|
|
12713
|
+
// packages/core/dist/knowledge/inject.js
|
|
12714
|
+
import fs19 from "fs";
|
|
12715
|
+
import path18 from "path";
|
|
12716
|
+
function sessionOrder(a, b) {
|
|
12717
|
+
const proj = (r) => r.layer.startsWith("project:") ? 0 : 1;
|
|
12718
|
+
const mod = (r) => r.modality === "must-not" ? 0 : 1;
|
|
12719
|
+
return proj(a) - proj(b) || mod(a) - mod(b) || a.id.localeCompare(b.id);
|
|
12720
|
+
}
|
|
12721
|
+
function formatSessionContext(kbs, rules, cap = SESSION_RULE_CAP) {
|
|
12722
|
+
const hard = rules.filter((r) => r.status === "active" && (r.modality === "must" || r.modality === "must-not")).sort(sessionOrder);
|
|
12723
|
+
const shown = hard.slice(0, cap);
|
|
12724
|
+
const lines = [
|
|
12725
|
+
`<squadrant-project-rules kb="${kbs.join(",")}">`,
|
|
12726
|
+
`Rules KB: ${kbs.join(", ")}. ${DATA_NOTE}`,
|
|
12727
|
+
...shown.map(line)
|
|
12728
|
+
];
|
|
12729
|
+
if (hard.length > shown.length)
|
|
12730
|
+
lines.push(`+${hard.length - shown.length} more: squadrant rules list --brief`);
|
|
12731
|
+
lines.push("Look up rules for a task with `squadrant rules search <terms>` / `squadrant rules show <id>` (rules-ops skill).");
|
|
12732
|
+
lines.push("</squadrant-project-rules>");
|
|
12733
|
+
return { text: lines.join("\n"), ids: shown.map((r) => r.id) };
|
|
12734
|
+
}
|
|
12735
|
+
function cleanPromptQuery(prompt) {
|
|
12736
|
+
const text = prompt.replace(/```[\s\S]*?(```|$)/g, " ").split("\n").filter((l) => l.length <= MAX_LINE_CHARS).join("\n").slice(0, MAX_PROMPT_CHARS).toLowerCase().replace(/https?:\/\/\S+/g, " ");
|
|
12737
|
+
const terms = [];
|
|
12738
|
+
const add = (t) => {
|
|
12739
|
+
if (t.length < 3 && !SHORT_TERMS.has(t) || /^\d+$/.test(t) || STOPWORDS.has(t) || terms.includes(t))
|
|
12740
|
+
return;
|
|
12741
|
+
terms.push(t);
|
|
12742
|
+
};
|
|
12743
|
+
for (const raw of text.split(/[^a-z0-9._-]+/)) {
|
|
12744
|
+
const t = raw.replace(/^[._-]+|[._-]+$/g, "");
|
|
12745
|
+
if (STOPWORDS.has(t))
|
|
12746
|
+
continue;
|
|
12747
|
+
add(t);
|
|
12748
|
+
const parts = t.split(/[._-]+/);
|
|
12749
|
+
if (parts.length > 1 && parts.every((x) => x.length >= 3 && !PREFIXES.has(x)))
|
|
12750
|
+
parts.forEach(add);
|
|
12751
|
+
if (terms.length >= MAX_TERMS)
|
|
12752
|
+
break;
|
|
12753
|
+
}
|
|
12754
|
+
return terms.slice(0, MAX_TERMS).join(" ");
|
|
12755
|
+
}
|
|
12756
|
+
function wholeWordTerms(rule, terms) {
|
|
12757
|
+
const text = [
|
|
12758
|
+
rule.id,
|
|
12759
|
+
...rule.triggers?.keywords ?? [],
|
|
12760
|
+
...rule.triggers?.expanded ?? [],
|
|
12761
|
+
rule.triggers?.when ?? "",
|
|
12762
|
+
rule.statement
|
|
12763
|
+
].join("\n").toLowerCase();
|
|
12764
|
+
return terms.filter((t) => {
|
|
12765
|
+
const base = t.length > 4 ? t.replace(/(es|s)$/, "") : t;
|
|
12766
|
+
return new RegExp(`(^|[^a-z0-9])(?:${escapeRe(t)}|${escapeRe(base)}(?:s|es)?)($|[^a-z0-9])`).test(text);
|
|
12767
|
+
});
|
|
12768
|
+
}
|
|
12769
|
+
function selectPromptHits(hits, query, seen, opts = {}) {
|
|
12770
|
+
const minScore = opts.minScore ?? PROMPT_MIN_SCORE;
|
|
12771
|
+
const terms = query.split(" ").filter(Boolean);
|
|
12772
|
+
return hits.filter((h) => {
|
|
12773
|
+
if (seen.has(h.rule.id))
|
|
12774
|
+
return false;
|
|
12775
|
+
const n = wholeWordTerms(h.rule, terms).length;
|
|
12776
|
+
return n >= 2 && h.score >= minScore || n === 1 && h.score >= PROMPT_SINGLE_TERM_MIN_SCORE;
|
|
12777
|
+
}).slice(0, opts.cap ?? PROMPT_RULE_CAP);
|
|
12778
|
+
}
|
|
12779
|
+
function isSystemPrompt(prompt) {
|
|
12780
|
+
const t = prompt.trimStart();
|
|
12781
|
+
return /^(⚠|🗒|\[stale\b|CREW [A-Z]|Another Claude session sent a message)/u.test(t) || t.includes("<cross-session-message");
|
|
12782
|
+
}
|
|
12783
|
+
function promptText(prompt) {
|
|
12784
|
+
const m = BRIEF_POINTER_RE.exec(prompt.trimStart());
|
|
12785
|
+
if (!m)
|
|
12786
|
+
return prompt;
|
|
12787
|
+
try {
|
|
12788
|
+
return fs19.readFileSync(m[1], "utf8").slice(0, MAX_PROMPT_CHARS * 2);
|
|
12789
|
+
} catch {
|
|
12790
|
+
return prompt;
|
|
12791
|
+
}
|
|
12792
|
+
}
|
|
12793
|
+
function formatPromptContext(hits) {
|
|
12794
|
+
return [
|
|
12795
|
+
'<squadrant-project-rules match="prompt">',
|
|
12796
|
+
`Rules that may apply to this prompt. ${DATA_NOTE}`,
|
|
12797
|
+
...hits.map((h) => line(h.rule)),
|
|
12798
|
+
"</squadrant-project-rules>"
|
|
12799
|
+
].join("\n");
|
|
12800
|
+
}
|
|
12801
|
+
function injectStateDir(stateRoot) {
|
|
12802
|
+
return path18.join(stateRoot, "rules-inject");
|
|
12803
|
+
}
|
|
12804
|
+
function readSeenRules(stateRoot, sessionId) {
|
|
12805
|
+
try {
|
|
12806
|
+
const ids = JSON.parse(fs19.readFileSync(sessionFile(stateRoot, sessionId), "utf8"));
|
|
12807
|
+
return new Set(Array.isArray(ids) ? ids.filter((x) => typeof x === "string") : []);
|
|
12808
|
+
} catch {
|
|
12809
|
+
return /* @__PURE__ */ new Set();
|
|
12810
|
+
}
|
|
12811
|
+
}
|
|
12812
|
+
function recordSeenRules(stateRoot, sessionId, ids) {
|
|
12813
|
+
if (!ids.length)
|
|
12814
|
+
return;
|
|
12815
|
+
const seen = readSeenRules(stateRoot, sessionId);
|
|
12816
|
+
for (const id of ids)
|
|
12817
|
+
seen.add(id);
|
|
12818
|
+
fs19.mkdirSync(injectStateDir(stateRoot), { recursive: true });
|
|
12819
|
+
fs19.writeFileSync(sessionFile(stateRoot, sessionId), JSON.stringify([...seen]));
|
|
12820
|
+
}
|
|
12821
|
+
function pruneSeenRules(stateRoot, now = Date.now()) {
|
|
12822
|
+
const dir = injectStateDir(stateRoot);
|
|
12823
|
+
let names;
|
|
12824
|
+
try {
|
|
12825
|
+
names = fs19.readdirSync(dir);
|
|
12826
|
+
} catch {
|
|
12827
|
+
return;
|
|
12828
|
+
}
|
|
12829
|
+
for (const n of names) {
|
|
12830
|
+
const f = path18.join(dir, n);
|
|
12831
|
+
try {
|
|
12832
|
+
if (now - fs19.statSync(f).mtimeMs > SEEN_TTL_MS)
|
|
12833
|
+
fs19.unlinkSync(f);
|
|
12834
|
+
} catch {
|
|
12835
|
+
}
|
|
12836
|
+
}
|
|
12837
|
+
}
|
|
12838
|
+
async function withBudget(fn, budgetMs = INJECT_BUDGET_MS) {
|
|
12839
|
+
const start = Date.now();
|
|
12840
|
+
let timer;
|
|
12841
|
+
try {
|
|
12842
|
+
const timeout = new Promise((resolve4) => {
|
|
12843
|
+
timer = setTimeout(() => resolve4(null), budgetMs);
|
|
12844
|
+
});
|
|
12845
|
+
const out = await Promise.race([Promise.resolve().then(fn), timeout]);
|
|
12846
|
+
return Date.now() - start > budgetMs ? null : out;
|
|
12847
|
+
} catch {
|
|
12848
|
+
return null;
|
|
12849
|
+
} finally {
|
|
12850
|
+
clearTimeout(timer);
|
|
12851
|
+
}
|
|
12852
|
+
}
|
|
12853
|
+
function resolveInjectProject(cfg, cwd, env, project) {
|
|
12854
|
+
const named = project ?? env.SQUADRANT_CREW_PROJECT;
|
|
12855
|
+
if (named)
|
|
12856
|
+
return cfg.projects[named] ? named : null;
|
|
12857
|
+
let best = null;
|
|
12858
|
+
let bestLen = -1;
|
|
12859
|
+
for (const [name, pc] of Object.entries(cfg.projects)) {
|
|
12860
|
+
const root = resolveHome(pc.path);
|
|
12861
|
+
if ((cwd === root || cwd.startsWith(root + path18.sep)) && root.length > bestLen) {
|
|
12862
|
+
best = name;
|
|
12863
|
+
bestLen = root.length;
|
|
12864
|
+
}
|
|
12865
|
+
}
|
|
12866
|
+
return best;
|
|
12867
|
+
}
|
|
12868
|
+
function computeRulesInjection(i) {
|
|
12869
|
+
if (i.env.SQUADRANT_RULES_INJECT === "0")
|
|
12870
|
+
return null;
|
|
12871
|
+
const p = typeof i.payload === "object" && i.payload !== null ? i.payload : {};
|
|
12872
|
+
const cwd = typeof p.cwd === "string" && p.cwd ? p.cwd : i.cwd;
|
|
12873
|
+
const project = resolveInjectProject(i.cfg, cwd, i.env, i.project);
|
|
12874
|
+
if (!project)
|
|
12875
|
+
return null;
|
|
12876
|
+
const kbs = subscribedKbs(i.cfg, project);
|
|
12877
|
+
if (!kbs.length)
|
|
12878
|
+
return null;
|
|
12879
|
+
const sessionId = typeof p.session_id === "string" && p.session_id ? p.session_id : null;
|
|
12880
|
+
if (i.event === "session-start") {
|
|
12881
|
+
const { text, ids } = formatSessionContext(kbs, resolveProjectRules(i.cfg, project).rules);
|
|
12882
|
+
if (sessionId) {
|
|
12883
|
+
pruneSeenRules(i.stateRoot);
|
|
12884
|
+
recordSeenRules(i.stateRoot, sessionId, ids);
|
|
12885
|
+
}
|
|
12886
|
+
return text;
|
|
12887
|
+
}
|
|
12888
|
+
if (typeof p.prompt !== "string" || isSystemPrompt(p.prompt))
|
|
12889
|
+
return null;
|
|
12890
|
+
const query = cleanPromptQuery(promptText(p.prompt));
|
|
12891
|
+
if (!query)
|
|
12892
|
+
return null;
|
|
12893
|
+
const seen = sessionId ? readSeenRules(i.stateRoot, sessionId) : /* @__PURE__ */ new Set();
|
|
12894
|
+
const picked = selectPromptHits(searchRules(resolveProjectRules(i.cfg, project).rules, query), query, seen);
|
|
12895
|
+
if (!picked.length)
|
|
12896
|
+
return null;
|
|
12897
|
+
if (sessionId)
|
|
12898
|
+
recordSeenRules(i.stateRoot, sessionId, picked.map((h) => h.rule.id));
|
|
12899
|
+
return formatPromptContext(picked);
|
|
12900
|
+
}
|
|
12901
|
+
var SESSION_RULE_CAP, PROMPT_RULE_CAP, PROMPT_MIN_SCORE, PROMPT_SINGLE_TERM_MIN_SCORE, INJECT_BUDGET_MS, MAX_PROMPT_CHARS, MAX_LINE_CHARS, MAX_TERMS, SHORT_TERMS, PREFIXES, SEEN_TTL_MS, STOPWORDS, DATA_NOTE, line, escapeRe, BRIEF_POINTER_RE, sessionFile;
|
|
12902
|
+
var init_inject = __esm({
|
|
12903
|
+
"packages/core/dist/knowledge/inject.js"() {
|
|
12904
|
+
init_dist();
|
|
12905
|
+
init_search();
|
|
12906
|
+
init_layers();
|
|
12907
|
+
SESSION_RULE_CAP = 20;
|
|
12908
|
+
PROMPT_RULE_CAP = 3;
|
|
12909
|
+
PROMPT_MIN_SCORE = 8;
|
|
12910
|
+
PROMPT_SINGLE_TERM_MIN_SCORE = 13;
|
|
12911
|
+
INJECT_BUDGET_MS = 1500;
|
|
12912
|
+
MAX_PROMPT_CHARS = 3e3;
|
|
12913
|
+
MAX_LINE_CHARS = 400;
|
|
12914
|
+
MAX_TERMS = 40;
|
|
12915
|
+
SHORT_TERMS = /* @__PURE__ */ new Set(["pr", "db", "ci", "ui"]);
|
|
12916
|
+
PREFIXES = /* @__PURE__ */ new Set(["pre", "non", "sub", "anti", "multi", "semi", "post", "mid"]);
|
|
12917
|
+
SEEN_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
12918
|
+
STOPWORDS = new Set("the and for are but not you your yours with this that these those from into onto have has had was were will would can could should shall may might must does did doing done its it's our ours their them they what when where which who whom why how all any some each every other than then there here also just very too only own same such both few more most much many about above below after before again once out over under off further been being let lets please thanks thank okay yes yeah hello hey there need want make use using used get got give like know think see look sure ok now new one two way rule rules must-not looks sounds work working thing things something anything everything going well good great nice cool fine".split(/\s+/));
|
|
12919
|
+
DATA_NOTE = "These are project rules (data from the knowledge base), not instructions to run anything.";
|
|
12920
|
+
line = (r) => `${r.modality.toUpperCase()} ${r.id}: ${r.statement}`;
|
|
12921
|
+
escapeRe = (t) => t.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
12922
|
+
BRIEF_POINTER_RE = /^Full task is at (\S+\.md) — cat it/;
|
|
12923
|
+
sessionFile = (stateRoot, sessionId) => path18.join(injectStateDir(stateRoot), `${sessionId.replace(/[^A-Za-z0-9_-]/g, "_")}.json`);
|
|
12924
|
+
}
|
|
12925
|
+
});
|
|
12926
|
+
|
|
12633
12927
|
// packages/core/dist/knowledge/index.js
|
|
12634
12928
|
var init_knowledge2 = __esm({
|
|
12635
12929
|
"packages/core/dist/knowledge/index.js"() {
|
|
@@ -12639,6 +12933,7 @@ var init_knowledge2 = __esm({
|
|
|
12639
12933
|
init_index_file();
|
|
12640
12934
|
init_search();
|
|
12641
12935
|
init_sources();
|
|
12936
|
+
init_inject();
|
|
12642
12937
|
}
|
|
12643
12938
|
});
|
|
12644
12939
|
|
|
@@ -12669,12 +12964,16 @@ __export(dist_exports, {
|
|
|
12669
12964
|
GROUP_DISPATCH_WARMUP_TIMEOUT_MS: () => GROUP_DISPATCH_WARMUP_TIMEOUT_MS,
|
|
12670
12965
|
GateDecisionCache: () => GateDecisionCache,
|
|
12671
12966
|
IDLE_DEBOUNCE_MS: () => IDLE_DEBOUNCE_MS,
|
|
12967
|
+
INJECT_BUDGET_MS: () => INJECT_BUDGET_MS,
|
|
12672
12968
|
LABEL: () => LABEL,
|
|
12673
12969
|
LivenessRegistry: () => LivenessRegistry,
|
|
12674
12970
|
MONITOR_STALL_BUDGET_MS: () => MONITOR_STALL_BUDGET_MS,
|
|
12675
12971
|
OPERATOR_INITIATED_COMMANDS: () => OPERATOR_INITIATED_COMMANDS,
|
|
12676
12972
|
PANE_IDLE_AFTER_MS: () => PANE_IDLE_AFTER_MS,
|
|
12677
12973
|
PROBE_QUIET_MS: () => PROBE_QUIET_MS,
|
|
12974
|
+
PROMPT_MIN_SCORE: () => PROMPT_MIN_SCORE,
|
|
12975
|
+
PROMPT_RULE_CAP: () => PROMPT_RULE_CAP,
|
|
12976
|
+
PROMPT_SINGLE_TERM_MIN_SCORE: () => PROMPT_SINGLE_TERM_MIN_SCORE,
|
|
12678
12977
|
PROPOSED_DIR: () => PROPOSED_DIR,
|
|
12679
12978
|
PROTOCOL_VERSION: () => PROTOCOL_VERSION,
|
|
12680
12979
|
READ_ONLY_CREW_SUBCOMMANDS: () => READ_ONLY_CREW_SUBCOMMANDS,
|
|
@@ -12682,6 +12981,7 @@ __export(dist_exports, {
|
|
|
12682
12981
|
ROUTER_READY_ATTEMPTS: () => ROUTER_READY_ATTEMPTS,
|
|
12683
12982
|
ROUTER_READY_DELAY_MS: () => ROUTER_READY_DELAY_MS,
|
|
12684
12983
|
SERVER_TOOL_TYPE_RE: () => SERVER_TOOL_TYPE_RE,
|
|
12984
|
+
SESSION_RULE_CAP: () => SESSION_RULE_CAP,
|
|
12685
12985
|
SIDE_SESSION_ENV: () => SIDE_SESSION_ENV,
|
|
12686
12986
|
SOURCES_TEMPLATE: () => SOURCES_TEMPLATE,
|
|
12687
12987
|
STALE_THRESHOLD_MS: () => STALE_THRESHOLD_MS,
|
|
@@ -12722,9 +13022,11 @@ __export(dist_exports, {
|
|
|
12722
13022
|
classifyCaptainPane: () => classifyCaptainPane,
|
|
12723
13023
|
classifyHealth: () => classifyHealth,
|
|
12724
13024
|
claudeEnvShadowsRouter: () => claudeEnvShadowsRouter,
|
|
13025
|
+
cleanPromptQuery: () => cleanPromptQuery,
|
|
12725
13026
|
clearPending: () => clearPending,
|
|
12726
13027
|
closeWorkItem: () => closeWorkItem,
|
|
12727
13028
|
compileIndex: () => compileIndex,
|
|
13029
|
+
computeRulesInjection: () => computeRulesInjection,
|
|
12728
13030
|
computeTemplateHash: () => computeTemplateHash,
|
|
12729
13031
|
consumeExitMarker: () => consumeExitMarker,
|
|
12730
13032
|
createAttach: () => createAttach,
|
|
@@ -12765,6 +13067,7 @@ __export(dist_exports, {
|
|
|
12765
13067
|
defaultIsPidAlive: () => defaultIsPidAlive,
|
|
12766
13068
|
defaultListenError: () => defaultListenError,
|
|
12767
13069
|
defaultWorkRoot: () => defaultWorkRoot,
|
|
13070
|
+
deliverFirstTurnViaPeer: () => deliverFirstTurnViaPeer,
|
|
12768
13071
|
deliverStartupPrompt: () => deliverStartupPrompt,
|
|
12769
13072
|
deliverToCaptain: () => deliverToCaptain,
|
|
12770
13073
|
deliverable: () => deliverable,
|
|
@@ -12798,6 +13101,8 @@ __export(dist_exports, {
|
|
|
12798
13101
|
formatLifecycle: () => formatLifecycle,
|
|
12799
13102
|
formatMediaReceipt: () => formatMediaReceipt,
|
|
12800
13103
|
formatPermissionDecision: () => formatPermissionDecision,
|
|
13104
|
+
formatPromptContext: () => formatPromptContext,
|
|
13105
|
+
formatSessionContext: () => formatSessionContext,
|
|
12801
13106
|
formatUsageLine: () => formatUsageLine,
|
|
12802
13107
|
formatWatchdogWarning: () => formatWatchdogWarning,
|
|
12803
13108
|
freshTrace: () => freshTrace,
|
|
@@ -12807,6 +13112,7 @@ __export(dist_exports, {
|
|
|
12807
13112
|
hasModalOptionList: () => hasModalOptionList,
|
|
12808
13113
|
healCmdFor: () => healCmdFor,
|
|
12809
13114
|
inboundBody: () => inboundBody,
|
|
13115
|
+
injectStateDir: () => injectStateDir,
|
|
12810
13116
|
isAuthorized: () => isAuthorized,
|
|
12811
13117
|
isBareSpawn: () => isBareSpawn,
|
|
12812
13118
|
isCaptainAlive: () => isCaptainAlive,
|
|
@@ -12822,6 +13128,7 @@ __export(dist_exports, {
|
|
|
12822
13128
|
isReadOnlyTopLevelCommand: () => isReadOnlyTopLevelCommand,
|
|
12823
13129
|
isSideTitle: () => isSideTitle,
|
|
12824
13130
|
isStickyAttention: () => isStickyAttention,
|
|
13131
|
+
isSystemPrompt: () => isSystemPrompt,
|
|
12825
13132
|
isTurnAccepted: () => isTurnAccepted,
|
|
12826
13133
|
isVersionUpgrade: () => isVersionUpgrade,
|
|
12827
13134
|
joinUrl: () => joinUrl,
|
|
@@ -12867,6 +13174,7 @@ __export(dist_exports, {
|
|
|
12867
13174
|
programArgsBlock: () => programArgsBlock,
|
|
12868
13175
|
projectHealth: () => projectHealth,
|
|
12869
13176
|
projectRulesDir: () => projectRulesDir,
|
|
13177
|
+
pruneSeenRules: () => pruneSeenRules,
|
|
12870
13178
|
pruneTopics: () => pruneTopics,
|
|
12871
13179
|
purgeExpiredWorkItems: () => purgeExpiredWorkItems,
|
|
12872
13180
|
readCaptainAddress: () => readCaptainAddress,
|
|
@@ -12874,11 +13182,13 @@ __export(dist_exports, {
|
|
|
12874
13182
|
readFromCursor: () => readFromCursor,
|
|
12875
13183
|
readIndex: () => readIndex,
|
|
12876
13184
|
readRunningMarker: () => readRunningMarker,
|
|
13185
|
+
readSeenRules: () => readSeenRules,
|
|
12877
13186
|
readUserIntent: () => readUserIntent,
|
|
12878
13187
|
realpathOrSelf: () => realpathOrSelf,
|
|
12879
13188
|
reapCrewChildren: () => reapCrewChildren,
|
|
12880
13189
|
reapOrphanedCrews: () => reapOrphanedCrews,
|
|
12881
13190
|
reconcileLiveness: () => reconcileLiveness,
|
|
13191
|
+
recordSeenRules: () => recordSeenRules,
|
|
12882
13192
|
recordSession: () => recordSession,
|
|
12883
13193
|
recoverStall: () => recoverStall,
|
|
12884
13194
|
reduce: () => reduce,
|
|
@@ -12900,6 +13210,7 @@ __export(dist_exports, {
|
|
|
12900
13210
|
resolveGateMode: () => resolveGateMode,
|
|
12901
13211
|
resolveGatePolicy: () => resolveGatePolicy,
|
|
12902
13212
|
resolveGateTools: () => resolveGateTools,
|
|
13213
|
+
resolveInjectProject: () => resolveInjectProject,
|
|
12903
13214
|
resolveProject: () => resolveProject,
|
|
12904
13215
|
resolveProjectRules: () => resolveProjectRules,
|
|
12905
13216
|
resolveRouterCredentials: () => resolveRouterCredentials,
|
|
@@ -12938,7 +13249,9 @@ __export(dist_exports, {
|
|
|
12938
13249
|
saveState: () => saveState,
|
|
12939
13250
|
screenHasSplashMarker: () => screenHasSplashMarker,
|
|
12940
13251
|
screenHash: () => screenHash,
|
|
13252
|
+
screenShowsTrustPanel: () => screenShowsTrustPanel,
|
|
12941
13253
|
searchRules: () => searchRules,
|
|
13254
|
+
selectPromptHits: () => selectPromptHits,
|
|
12942
13255
|
sendRequest: () => sendRequest,
|
|
12943
13256
|
setLastUserId: () => setLastUserId,
|
|
12944
13257
|
setNotify: () => setNotify,
|
|
@@ -12962,11 +13275,14 @@ __export(dist_exports, {
|
|
|
12962
13275
|
toControlEvent: () => toControlEvent,
|
|
12963
13276
|
topicKey: () => topicKey,
|
|
12964
13277
|
topicName: () => topicName,
|
|
13278
|
+
trustPanelAcceptKeys: () => trustPanelAcceptKeys,
|
|
12965
13279
|
tryAcquireDaemonLock: () => tryAcquireDaemonLock,
|
|
12966
13280
|
usageFromJson: () => usageFromJson,
|
|
12967
13281
|
validateKb: () => validateKb,
|
|
12968
13282
|
waitForCaptainDelivery: () => waitForCaptainDelivery,
|
|
12969
13283
|
waitForWarmup: () => waitForWarmup,
|
|
13284
|
+
wholeWordTerms: () => wholeWordTerms,
|
|
13285
|
+
withBudget: () => withBudget,
|
|
12970
13286
|
writeCaptainAddress: () => writeCaptainAddress,
|
|
12971
13287
|
writeCursor: () => writeCursor,
|
|
12972
13288
|
writeExitMarker: () => writeExitMarker,
|
|
@@ -13022,6 +13338,7 @@ var init_dist2 = __esm({
|
|
|
13022
13338
|
init_conformance();
|
|
13023
13339
|
init_source();
|
|
13024
13340
|
init_control_channel();
|
|
13341
|
+
init_peer_first_turn();
|
|
13025
13342
|
init_captain_channel();
|
|
13026
13343
|
init_captain_record();
|
|
13027
13344
|
init_opencode_session();
|
|
@@ -13069,7 +13386,7 @@ import { readdirSync as readdirSync4, readFileSync as readFileSync12 } from "fs"
|
|
|
13069
13386
|
import { join as join18 } from "path";
|
|
13070
13387
|
|
|
13071
13388
|
// packages/agents/dist/claude/registry.js
|
|
13072
|
-
import
|
|
13389
|
+
import fs20 from "fs";
|
|
13073
13390
|
import { join as join17 } from "path";
|
|
13074
13391
|
import { homedir as homedir7 } from "os";
|
|
13075
13392
|
var CLAUDE_SESSIONS_DIR = join17(homedir7(), ".claude", "sessions");
|
|
@@ -13114,11 +13431,11 @@ function toLifecycleSnapshot(entry, taskId, alive, now) {
|
|
|
13114
13431
|
function readClaudeStatusBySocketPath(socketPath) {
|
|
13115
13432
|
let files;
|
|
13116
13433
|
try {
|
|
13117
|
-
files =
|
|
13434
|
+
files = fs20.readdirSync(CLAUDE_SESSIONS_DIR);
|
|
13118
13435
|
} catch {
|
|
13119
13436
|
return void 0;
|
|
13120
13437
|
}
|
|
13121
|
-
const entries = parseRegistryDir(files, (name) =>
|
|
13438
|
+
const entries = parseRegistryDir(files, (name) => fs20.readFileSync(join17(CLAUDE_SESSIONS_DIR, name), "utf8"));
|
|
13122
13439
|
const entry = entries.find((e) => e.messagingSocketPath === socketPath);
|
|
13123
13440
|
if (!entry)
|
|
13124
13441
|
return void 0;
|
|
@@ -13141,38 +13458,38 @@ import { homedir as homedir8 } from "os";
|
|
|
13141
13458
|
var SQUADRANT_STATE_DIR = join19(homedir8(), ".config", "squadrant", "state");
|
|
13142
13459
|
|
|
13143
13460
|
// packages/agents/dist/drivers/launch-cmd.js
|
|
13144
|
-
import
|
|
13145
|
-
import
|
|
13461
|
+
import fs21 from "fs";
|
|
13462
|
+
import path19 from "path";
|
|
13146
13463
|
|
|
13147
13464
|
// packages/agents/dist/projection/cursor.js
|
|
13148
13465
|
import { mkdir, readFile, writeFile } from "fs/promises";
|
|
13149
|
-
import
|
|
13466
|
+
import path20 from "path";
|
|
13150
13467
|
import os8 from "os";
|
|
13151
13468
|
|
|
13152
13469
|
// packages/agents/dist/projection/codex.js
|
|
13153
13470
|
import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
|
|
13154
|
-
import
|
|
13471
|
+
import path21 from "path";
|
|
13155
13472
|
import os9 from "os";
|
|
13156
13473
|
|
|
13157
13474
|
// packages/agents/dist/projection/gemini.js
|
|
13158
13475
|
import { mkdir as mkdir3, readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
|
|
13159
|
-
import
|
|
13476
|
+
import path22 from "path";
|
|
13160
13477
|
import os10 from "os";
|
|
13161
13478
|
|
|
13162
13479
|
// packages/agents/dist/projection/opencode.js
|
|
13163
13480
|
import { mkdir as mkdir4, readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
|
|
13164
|
-
import
|
|
13481
|
+
import path23 from "path";
|
|
13165
13482
|
import os11 from "os";
|
|
13166
13483
|
|
|
13167
13484
|
// packages/agents/dist/projection/opencode-skills.js
|
|
13168
|
-
import
|
|
13485
|
+
import fs22 from "fs";
|
|
13169
13486
|
import os12 from "os";
|
|
13170
|
-
import
|
|
13487
|
+
import path24 from "path";
|
|
13171
13488
|
var OPENCODE_SKILL_MARKER = ".squadrant-managed";
|
|
13172
13489
|
var MARKER_BODY = "squadrant\n";
|
|
13173
13490
|
function defaultOpencodeSkillsRoot(env = process.env) {
|
|
13174
|
-
const configHome = env.XDG_CONFIG_HOME ||
|
|
13175
|
-
return
|
|
13491
|
+
const configHome = env.XDG_CONFIG_HOME || path24.join(os12.homedir(), ".config");
|
|
13492
|
+
return path24.join(configHome, "opencode", "skills");
|
|
13176
13493
|
}
|
|
13177
13494
|
var SAFE_NAME = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
|
|
13178
13495
|
function parseSkillName(raw) {
|
|
@@ -13187,62 +13504,62 @@ function parseSkillName(raw) {
|
|
|
13187
13504
|
}
|
|
13188
13505
|
function listSourceSkills(sourceSkillsDir) {
|
|
13189
13506
|
const out = /* @__PURE__ */ new Map();
|
|
13190
|
-
if (!
|
|
13507
|
+
if (!fs22.existsSync(sourceSkillsDir))
|
|
13191
13508
|
return out;
|
|
13192
|
-
for (const entry of
|
|
13509
|
+
for (const entry of fs22.readdirSync(sourceSkillsDir, { withFileTypes: true })) {
|
|
13193
13510
|
if (!entry.isDirectory())
|
|
13194
13511
|
continue;
|
|
13195
|
-
const skillPath =
|
|
13196
|
-
if (!
|
|
13512
|
+
const skillPath = path24.join(sourceSkillsDir, entry.name, "SKILL.md");
|
|
13513
|
+
if (!fs22.existsSync(skillPath))
|
|
13197
13514
|
continue;
|
|
13198
|
-
const name = parseSkillName(
|
|
13515
|
+
const name = parseSkillName(fs22.readFileSync(skillPath, "utf-8"));
|
|
13199
13516
|
if (name && SAFE_NAME.test(name))
|
|
13200
13517
|
out.set(name, skillPath);
|
|
13201
13518
|
}
|
|
13202
13519
|
return out;
|
|
13203
13520
|
}
|
|
13204
13521
|
function hasMarker(dir) {
|
|
13205
|
-
return
|
|
13522
|
+
return fs22.existsSync(path24.join(dir, OPENCODE_SKILL_MARKER));
|
|
13206
13523
|
}
|
|
13207
13524
|
function syncOpencodeSkills(opts) {
|
|
13208
13525
|
const result = { written: [], unchanged: [], removed: [], skipped: [] };
|
|
13209
13526
|
const wanted = listSourceSkills(opts.sourceSkillsDir);
|
|
13210
|
-
if (wanted.size === 0 && !
|
|
13527
|
+
if (wanted.size === 0 && !fs22.existsSync(opts.sourceSkillsDir))
|
|
13211
13528
|
return result;
|
|
13212
13529
|
if (!opts.dryRun)
|
|
13213
|
-
|
|
13530
|
+
fs22.mkdirSync(opts.skillsRoot, { recursive: true });
|
|
13214
13531
|
for (const [name, srcPath] of wanted) {
|
|
13215
|
-
const targetDir =
|
|
13216
|
-
const targetSkill =
|
|
13532
|
+
const targetDir = path24.join(opts.skillsRoot, name);
|
|
13533
|
+
const targetSkill = path24.join(targetDir, "SKILL.md");
|
|
13217
13534
|
const managed = hasMarker(targetDir);
|
|
13218
|
-
if (
|
|
13535
|
+
if (fs22.existsSync(targetSkill) && !managed) {
|
|
13219
13536
|
result.skipped.push({ name, reason: "foreign-collision" });
|
|
13220
13537
|
continue;
|
|
13221
13538
|
}
|
|
13222
|
-
const current =
|
|
13223
|
-
if (current && current.equals(
|
|
13539
|
+
const current = fs22.existsSync(targetSkill) ? fs22.readFileSync(targetSkill) : null;
|
|
13540
|
+
if (current && current.equals(fs22.readFileSync(srcPath))) {
|
|
13224
13541
|
if (!managed && !opts.dryRun) {
|
|
13225
|
-
|
|
13542
|
+
fs22.writeFileSync(path24.join(targetDir, OPENCODE_SKILL_MARKER), MARKER_BODY);
|
|
13226
13543
|
}
|
|
13227
13544
|
result.unchanged.push(name);
|
|
13228
13545
|
continue;
|
|
13229
13546
|
}
|
|
13230
13547
|
if (!opts.dryRun) {
|
|
13231
|
-
|
|
13232
|
-
|
|
13233
|
-
|
|
13548
|
+
fs22.mkdirSync(targetDir, { recursive: true });
|
|
13549
|
+
fs22.copyFileSync(srcPath, targetSkill);
|
|
13550
|
+
fs22.writeFileSync(path24.join(targetDir, OPENCODE_SKILL_MARKER), MARKER_BODY);
|
|
13234
13551
|
}
|
|
13235
13552
|
result.written.push(name);
|
|
13236
13553
|
}
|
|
13237
|
-
if (
|
|
13238
|
-
for (const entry of
|
|
13554
|
+
if (fs22.existsSync(opts.skillsRoot)) {
|
|
13555
|
+
for (const entry of fs22.readdirSync(opts.skillsRoot, { withFileTypes: true })) {
|
|
13239
13556
|
if (!entry.isDirectory() || wanted.has(entry.name))
|
|
13240
13557
|
continue;
|
|
13241
|
-
const dir =
|
|
13558
|
+
const dir = path24.join(opts.skillsRoot, entry.name);
|
|
13242
13559
|
if (!hasMarker(dir))
|
|
13243
13560
|
continue;
|
|
13244
13561
|
if (!opts.dryRun)
|
|
13245
|
-
|
|
13562
|
+
fs22.rmSync(dir, { recursive: true, force: true });
|
|
13246
13563
|
result.removed.push(entry.name);
|
|
13247
13564
|
}
|
|
13248
13565
|
}
|
|
@@ -13250,7 +13567,7 @@ function syncOpencodeSkills(opts) {
|
|
|
13250
13567
|
}
|
|
13251
13568
|
function syncShippedOpencodeSkills(opts) {
|
|
13252
13569
|
return syncOpencodeSkills({
|
|
13253
|
-
sourceSkillsDir:
|
|
13570
|
+
sourceSkillsDir: path24.join(opts.pkgRoot, "plugin", "skills"),
|
|
13254
13571
|
skillsRoot: opts.skillsRoot ?? defaultOpencodeSkillsRoot(),
|
|
13255
13572
|
dryRun: opts.dryRun
|
|
13256
13573
|
});
|
|
@@ -13258,7 +13575,7 @@ function syncShippedOpencodeSkills(opts) {
|
|
|
13258
13575
|
|
|
13259
13576
|
// packages/agents/dist/projection/claude.js
|
|
13260
13577
|
import { mkdir as mkdir5, readFile as readFile5, writeFile as writeFile5 } from "fs/promises";
|
|
13261
|
-
import
|
|
13578
|
+
import path25 from "path";
|
|
13262
13579
|
import os13 from "os";
|
|
13263
13580
|
|
|
13264
13581
|
// packages/agents/dist/codex/app-server-client.js
|
|
@@ -13269,12 +13586,12 @@ function _parseChunk(acc, chunk) {
|
|
|
13269
13586
|
const out = [];
|
|
13270
13587
|
let idx;
|
|
13271
13588
|
while ((idx = acc.buf.indexOf("\n")) >= 0) {
|
|
13272
|
-
const
|
|
13589
|
+
const line2 = acc.buf.slice(0, idx);
|
|
13273
13590
|
acc.buf = acc.buf.slice(idx + 1);
|
|
13274
|
-
if (!
|
|
13591
|
+
if (!line2.trim())
|
|
13275
13592
|
continue;
|
|
13276
13593
|
try {
|
|
13277
|
-
out.push(JSON.parse(
|
|
13594
|
+
out.push(JSON.parse(line2));
|
|
13278
13595
|
} catch {
|
|
13279
13596
|
}
|
|
13280
13597
|
}
|
|
@@ -13996,9 +14313,9 @@ var OpencodeSseBridge = class {
|
|
|
13996
14313
|
buf += decoder.decode(value, { stream: true });
|
|
13997
14314
|
let nl;
|
|
13998
14315
|
while ((nl = buf.indexOf("\n")) >= 0) {
|
|
13999
|
-
const
|
|
14316
|
+
const line2 = buf.slice(0, nl);
|
|
14000
14317
|
buf = buf.slice(nl + 1);
|
|
14001
|
-
this.handleLine(taskId,
|
|
14318
|
+
this.handleLine(taskId, line2);
|
|
14002
14319
|
}
|
|
14003
14320
|
}
|
|
14004
14321
|
} finally {
|
|
@@ -14009,16 +14326,16 @@ var OpencodeSseBridge = class {
|
|
|
14009
14326
|
}
|
|
14010
14327
|
}
|
|
14011
14328
|
handleLine(taskId, rawLine) {
|
|
14012
|
-
let
|
|
14013
|
-
if (!
|
|
14329
|
+
let line2 = rawLine.trim();
|
|
14330
|
+
if (!line2)
|
|
14014
14331
|
return;
|
|
14015
|
-
if (
|
|
14016
|
-
|
|
14017
|
-
if (!
|
|
14332
|
+
if (line2.startsWith("data:"))
|
|
14333
|
+
line2 = line2.slice(5).trim();
|
|
14334
|
+
if (!line2.startsWith("{"))
|
|
14018
14335
|
return;
|
|
14019
14336
|
let json2;
|
|
14020
14337
|
try {
|
|
14021
|
-
json2 = JSON.parse(
|
|
14338
|
+
json2 = JSON.parse(line2);
|
|
14022
14339
|
} catch {
|
|
14023
14340
|
return;
|
|
14024
14341
|
}
|
|
@@ -14376,13 +14693,13 @@ function buildUserEnvelope(opts) {
|
|
|
14376
14693
|
};
|
|
14377
14694
|
}
|
|
14378
14695
|
function writeLine(socketPath, envelope, deps) {
|
|
14379
|
-
const
|
|
14696
|
+
const line2 = `${JSON.stringify(envelope)}
|
|
14380
14697
|
`;
|
|
14381
|
-
if (Buffer.byteLength(
|
|
14698
|
+
if (Buffer.byteLength(line2, "utf8") > MAX_LINE_BYTES) {
|
|
14382
14699
|
return Promise.resolve({
|
|
14383
14700
|
ok: false,
|
|
14384
14701
|
reason: "transport",
|
|
14385
|
-
error: `line exceeds the receiver's 1 MiB buffer cap (${Buffer.byteLength(
|
|
14702
|
+
error: `line exceeds the receiver's 1 MiB buffer cap (${Buffer.byteLength(line2, "utf8")} bytes)`
|
|
14386
14703
|
});
|
|
14387
14704
|
}
|
|
14388
14705
|
return new Promise((resolve4) => {
|
|
@@ -14402,7 +14719,7 @@ function writeLine(socketPath, envelope, deps) {
|
|
|
14402
14719
|
done({ ok: false, reason: "transport", error: `timeout after ${deps.timeoutMs ?? DEFAULT_TIMEOUT_MS}ms` });
|
|
14403
14720
|
}, deps.timeoutMs ?? DEFAULT_TIMEOUT_MS);
|
|
14404
14721
|
sock.on("connect", () => {
|
|
14405
|
-
sock.write(
|
|
14722
|
+
sock.write(line2, () => {
|
|
14406
14723
|
clearTimeout(timer);
|
|
14407
14724
|
try {
|
|
14408
14725
|
sock.end();
|
|
@@ -14563,20 +14880,20 @@ var ClaudeReceiptListener = class {
|
|
|
14563
14880
|
buf += chunk;
|
|
14564
14881
|
let nl;
|
|
14565
14882
|
while ((nl = buf.indexOf("\n")) !== -1) {
|
|
14566
|
-
const
|
|
14883
|
+
const line2 = buf.slice(0, nl);
|
|
14567
14884
|
buf = buf.slice(nl + 1);
|
|
14568
|
-
this.dispatch(
|
|
14885
|
+
this.dispatch(line2);
|
|
14569
14886
|
}
|
|
14570
14887
|
});
|
|
14571
14888
|
conn.on("error", () => {
|
|
14572
14889
|
});
|
|
14573
14890
|
}
|
|
14574
|
-
dispatch(
|
|
14575
|
-
if (!
|
|
14891
|
+
dispatch(line2) {
|
|
14892
|
+
if (!line2.trim())
|
|
14576
14893
|
return;
|
|
14577
14894
|
let f;
|
|
14578
14895
|
try {
|
|
14579
|
-
f = JSON.parse(
|
|
14896
|
+
f = JSON.parse(line2);
|
|
14580
14897
|
} catch {
|
|
14581
14898
|
this.deps.log?.(`claude-receipt: discarded non-JSON frame`);
|
|
14582
14899
|
return;
|
|
@@ -14603,9 +14920,9 @@ var ClaudeReceiptListener = class {
|
|
|
14603
14920
|
};
|
|
14604
14921
|
|
|
14605
14922
|
// packages/agents/dist/claude/api-key-approval.js
|
|
14606
|
-
import
|
|
14923
|
+
import fs23 from "fs";
|
|
14607
14924
|
import os14 from "os";
|
|
14608
|
-
import
|
|
14925
|
+
import path26 from "path";
|
|
14609
14926
|
|
|
14610
14927
|
// packages/agents/dist/opencode/http-channel.js
|
|
14611
14928
|
init_dist2();
|
|
@@ -14697,10 +15014,10 @@ var OpencodeHttpChannel = class {
|
|
|
14697
15014
|
return cached;
|
|
14698
15015
|
const directory = this.directoryFor?.(taskId);
|
|
14699
15016
|
const createdAfterMs = this.createdAfterFor?.(taskId);
|
|
14700
|
-
for (const
|
|
15017
|
+
for (const path29 of ["/session?", "/api/session?"]) {
|
|
14701
15018
|
let res;
|
|
14702
15019
|
try {
|
|
14703
|
-
res = await this.request(`http://127.0.0.1:${port}${
|
|
15020
|
+
res = await this.request(`http://127.0.0.1:${port}${path29}`, { method: "GET" });
|
|
14704
15021
|
} catch {
|
|
14705
15022
|
return void 0;
|
|
14706
15023
|
}
|
|
@@ -14836,6 +15153,15 @@ async function cmuxHasInputGuards() {
|
|
|
14836
15153
|
inputGuardsCache = major > 0 || minor >= 65;
|
|
14837
15154
|
return inputGuardsCache;
|
|
14838
15155
|
}
|
|
15156
|
+
function feedSessionOf(item) {
|
|
15157
|
+
const parts = item.workstream_id?.split(":");
|
|
15158
|
+
if (parts?.[0] !== "cmux-feed-v1" || !parts[2])
|
|
15159
|
+
return void 0;
|
|
15160
|
+
return Buffer.from(parts[2], "base64").toString("utf-8");
|
|
15161
|
+
}
|
|
15162
|
+
async function feedRpc(method, params) {
|
|
15163
|
+
return JSON.parse(await cmux(["rpc", method, JSON.stringify(params)]));
|
|
15164
|
+
}
|
|
14839
15165
|
function parseList(output) {
|
|
14840
15166
|
let parsed;
|
|
14841
15167
|
try {
|
|
@@ -14878,13 +15204,13 @@ function parseDraftFromScreen(screen) {
|
|
|
14878
15204
|
if (topHR === -1)
|
|
14879
15205
|
return null;
|
|
14880
15206
|
const inputLines = lines.slice(topHR + 1, bottomHR);
|
|
14881
|
-
for (const
|
|
15207
|
+
for (const line2 of inputLines) {
|
|
14882
15208
|
let extracted;
|
|
14883
|
-
const boxMatch =
|
|
15209
|
+
const boxMatch = line2.match(/│\s*[>❯]\s+(.*?)\s*│/);
|
|
14884
15210
|
if (boxMatch) {
|
|
14885
15211
|
extracted = boxMatch[1].trim();
|
|
14886
15212
|
} else {
|
|
14887
|
-
const plainMatch =
|
|
15213
|
+
const plainMatch = line2.match(/^\s*[>❯]\s*(.*)$/);
|
|
14888
15214
|
if (plainMatch)
|
|
14889
15215
|
extracted = plainMatch[1].trim();
|
|
14890
15216
|
}
|
|
@@ -14962,8 +15288,8 @@ function readInputBoxRaw(screen, opts) {
|
|
|
14962
15288
|
if (topHR === -1)
|
|
14963
15289
|
return null;
|
|
14964
15290
|
const parts = [];
|
|
14965
|
-
for (const
|
|
14966
|
-
let s =
|
|
15291
|
+
for (const line2 of lines.slice(topHR + 1, bottomHR)) {
|
|
15292
|
+
let s = line2.replace(/│/g, " ");
|
|
14967
15293
|
s = s.replace(/^\s*[>❯]\s?/, "");
|
|
14968
15294
|
s = s.replace(/\s*[▌█▔▎▏]+\s*$/, "");
|
|
14969
15295
|
parts.push(s);
|
|
@@ -15200,6 +15526,26 @@ function createCmuxDriver() {
|
|
|
15200
15526
|
await cmux(["send-key", "--workspace", wsId, "--surface", surfaceId, "Enter"]);
|
|
15201
15527
|
return { workspaceId: wsId, surfaceId, title: opts.title };
|
|
15202
15528
|
},
|
|
15529
|
+
// #916: cmux >= 0.65 `surface.input_state` reads the render grid (incl. faint
|
|
15530
|
+
// spans) without touching the pane. The RPC needs a surface UUID, and an
|
|
15531
|
+
// unknown ref would silently fall back to the focused surface, so resolve the
|
|
15532
|
+
// ref through the tree first. Anything unexpected → undefined (old path).
|
|
15533
|
+
async inputState(pane) {
|
|
15534
|
+
try {
|
|
15535
|
+
if (!await cmuxHasInputGuards())
|
|
15536
|
+
return void 0;
|
|
15537
|
+
const tree = JSON.parse(await cmux(["tree", "--workspace", pane.workspaceId, "--json", "--id-format", "both"]));
|
|
15538
|
+
const id = tree.windows?.flatMap((w) => w.workspaces ?? []).flatMap((w) => w.panes ?? []).flatMap((p) => p.surfaces ?? []).find((s) => s.ref === pane.surfaceId)?.id;
|
|
15539
|
+
if (!id)
|
|
15540
|
+
return void 0;
|
|
15541
|
+
const r = JSON.parse(await cmux(["rpc", "surface.input_state", JSON.stringify({ surface_id: id })]));
|
|
15542
|
+
if (r.agent !== true)
|
|
15543
|
+
return "unknown";
|
|
15544
|
+
return r.state === "empty" || r.state === "draft" || r.state === "dialog" ? r.state : "unknown";
|
|
15545
|
+
} catch {
|
|
15546
|
+
return void 0;
|
|
15547
|
+
}
|
|
15548
|
+
},
|
|
15203
15549
|
async sendToSurface(surface, text, opts) {
|
|
15204
15550
|
const ws = surface.workspaceId;
|
|
15205
15551
|
const sf = surface.surfaceId;
|
|
@@ -15226,6 +15572,17 @@ function createCmuxDriver() {
|
|
|
15226
15572
|
`);
|
|
15227
15573
|
}
|
|
15228
15574
|
};
|
|
15575
|
+
if (opts?.agent !== "opencode") {
|
|
15576
|
+
const state = await this.inputState?.(surface);
|
|
15577
|
+
if (state === "draft")
|
|
15578
|
+
throw new DeferDelivery(null, "draft");
|
|
15579
|
+
if (state === "dialog")
|
|
15580
|
+
throw new DeferDelivery(null, "modal");
|
|
15581
|
+
if (state === "empty") {
|
|
15582
|
+
await deliver();
|
|
15583
|
+
return;
|
|
15584
|
+
}
|
|
15585
|
+
}
|
|
15229
15586
|
let screen = "";
|
|
15230
15587
|
try {
|
|
15231
15588
|
screen = await cmux(["read-screen", "--workspace", ws, "--surface", sf]);
|
|
@@ -15304,6 +15661,39 @@ function createCmuxDriver() {
|
|
|
15304
15661
|
args.push("--focus", "true");
|
|
15305
15662
|
await cmux(args);
|
|
15306
15663
|
},
|
|
15664
|
+
// Feed-backed structured answer (#918). cmux >= 0.65 only; any miss
|
|
15665
|
+
// (old cmux, no matching item, unsupported shape) is undefined so the
|
|
15666
|
+
// caller keeps the keystroke path.
|
|
15667
|
+
async findDialog(match) {
|
|
15668
|
+
if (!await cmuxHasInputGuards())
|
|
15669
|
+
return void 0;
|
|
15670
|
+
let items;
|
|
15671
|
+
try {
|
|
15672
|
+
items = (await feedRpc("feed.list", { pending_only: true })).items ?? [];
|
|
15673
|
+
} catch {
|
|
15674
|
+
return void 0;
|
|
15675
|
+
}
|
|
15676
|
+
const mine = items.filter((i) => match.agentSessionId ? feedSessionOf(i) === match.agentSessionId : !!match.cwd && i.cwd === match.cwd);
|
|
15677
|
+
if (mine.length !== 1 || !mine[0].request_id)
|
|
15678
|
+
return void 0;
|
|
15679
|
+
const item = mine[0];
|
|
15680
|
+
if (item.kind !== "question" || item.questions?.length !== 1)
|
|
15681
|
+
return void 0;
|
|
15682
|
+
const labels = (item.questions[0].options ?? []).map((o) => o.label ?? "");
|
|
15683
|
+
if (labels.length === 0)
|
|
15684
|
+
return void 0;
|
|
15685
|
+
return {
|
|
15686
|
+
id: item.request_id,
|
|
15687
|
+
options: labels.map((label, i) => ({ index: i + 1, label }))
|
|
15688
|
+
};
|
|
15689
|
+
},
|
|
15690
|
+
async answerDialog(dialog, answer) {
|
|
15691
|
+
const reply = answer.text ?? answer.label;
|
|
15692
|
+
if (!reply)
|
|
15693
|
+
return false;
|
|
15694
|
+
const res = await feedRpc("feed.question.reply", { request_id: dialog.id, selections: [reply] });
|
|
15695
|
+
return res.delivered === true;
|
|
15696
|
+
},
|
|
15307
15697
|
async showPatch(opts) {
|
|
15308
15698
|
const args = ["diff", "-", "--workspace", opts.workspaceId, "--layout", opts.layout ?? "split"];
|
|
15309
15699
|
if (opts.title)
|
|
@@ -15436,9 +15826,9 @@ var NotifierRegistry = class {
|
|
|
15436
15826
|
};
|
|
15437
15827
|
|
|
15438
15828
|
// packages/workspaces/dist/workspaces/obsidian.js
|
|
15439
|
-
import
|
|
15829
|
+
import fs24 from "fs/promises";
|
|
15440
15830
|
import { existsSync as existsSync11 } from "fs";
|
|
15441
|
-
import
|
|
15831
|
+
import path27 from "path";
|
|
15442
15832
|
|
|
15443
15833
|
// packages/workspaces/dist/workspaces/registry.js
|
|
15444
15834
|
init_dist();
|
|
@@ -15536,18 +15926,18 @@ var CmuxEventsBridge = class {
|
|
|
15536
15926
|
this.buf += typeof chunk === "string" ? chunk : chunk.toString("utf-8");
|
|
15537
15927
|
let nl;
|
|
15538
15928
|
while ((nl = this.buf.indexOf("\n")) >= 0) {
|
|
15539
|
-
const
|
|
15929
|
+
const line2 = this.buf.slice(0, nl);
|
|
15540
15930
|
this.buf = this.buf.slice(nl + 1);
|
|
15541
|
-
this.handleLine(
|
|
15931
|
+
this.handleLine(line2);
|
|
15542
15932
|
}
|
|
15543
15933
|
}
|
|
15544
15934
|
handleLine(rawLine) {
|
|
15545
|
-
const
|
|
15546
|
-
if (!
|
|
15935
|
+
const line2 = rawLine.trim();
|
|
15936
|
+
if (!line2 || line2[0] !== "{")
|
|
15547
15937
|
return;
|
|
15548
15938
|
let f;
|
|
15549
15939
|
try {
|
|
15550
|
-
f = JSON.parse(
|
|
15940
|
+
f = JSON.parse(line2);
|
|
15551
15941
|
} catch {
|
|
15552
15942
|
return;
|
|
15553
15943
|
}
|
|
@@ -15988,9 +16378,9 @@ function defaultListFiles(dir) {
|
|
|
15988
16378
|
return [];
|
|
15989
16379
|
}
|
|
15990
16380
|
}
|
|
15991
|
-
function defaultReadFile(
|
|
16381
|
+
function defaultReadFile(path29) {
|
|
15992
16382
|
try {
|
|
15993
|
-
return readFileSync17(
|
|
16383
|
+
return readFileSync17(path29, "utf-8");
|
|
15994
16384
|
} catch {
|
|
15995
16385
|
return void 0;
|
|
15996
16386
|
}
|
|
@@ -16368,16 +16758,16 @@ function extractDetail(sub, payload) {
|
|
|
16368
16758
|
}
|
|
16369
16759
|
return void 0;
|
|
16370
16760
|
}
|
|
16371
|
-
function defaultReadFile2(
|
|
16761
|
+
function defaultReadFile2(path29) {
|
|
16372
16762
|
try {
|
|
16373
|
-
return readFileSync18(
|
|
16763
|
+
return readFileSync18(path29, "utf-8");
|
|
16374
16764
|
} catch {
|
|
16375
16765
|
return void 0;
|
|
16376
16766
|
}
|
|
16377
16767
|
}
|
|
16378
|
-
function defaultWriteFile(
|
|
16379
|
-
mkdirSync8(
|
|
16380
|
-
writeFileSync11(
|
|
16768
|
+
function defaultWriteFile(path29, content) {
|
|
16769
|
+
mkdirSync8(path29.replace(/\/[^/]+$/, ""), { recursive: true });
|
|
16770
|
+
writeFileSync11(path29, content, "utf-8");
|
|
16381
16771
|
}
|
|
16382
16772
|
|
|
16383
16773
|
// packages/workspaces/dist/crew-pane.js
|
|
@@ -16404,6 +16794,11 @@ async function settleInputBox(runtime, pane) {
|
|
|
16404
16794
|
return sawContent;
|
|
16405
16795
|
}
|
|
16406
16796
|
async function confirmedSendToPane(runtime, pane, message) {
|
|
16797
|
+
const native = await runtime.inputState?.(pane).catch(() => void 0);
|
|
16798
|
+
if (native === "dialog")
|
|
16799
|
+
return { delivered: false, blockedByModal: true };
|
|
16800
|
+
if (native === "draft")
|
|
16801
|
+
return { delivered: false };
|
|
16407
16802
|
const preSendScreen = await runtime.readPaneScreen(pane) ?? "";
|
|
16408
16803
|
if (hasModalOptionList2(preSendScreen)) {
|
|
16409
16804
|
return { delivered: false, blockedByModal: true };
|
|
@@ -16457,9 +16852,9 @@ init_dist();
|
|
|
16457
16852
|
|
|
16458
16853
|
// packages/cli/src/lib/daemon-restart-broadcast.ts
|
|
16459
16854
|
init_dist();
|
|
16460
|
-
import
|
|
16855
|
+
import path28 from "path";
|
|
16461
16856
|
function statePath2(stateRoot) {
|
|
16462
|
-
return
|
|
16857
|
+
return path28.join(stateRoot, "daemon-restart-state.json");
|
|
16463
16858
|
}
|
|
16464
16859
|
function computeRestartSignature(version, buildMtimeMs) {
|
|
16465
16860
|
return `${version}::${buildMtimeMs}`;
|
|
@@ -16508,7 +16903,7 @@ async function maybeBroadcastDaemonRestart(opts) {
|
|
|
16508
16903
|
|
|
16509
16904
|
// packages/cli/src/lib/captain-channel-factory.ts
|
|
16510
16905
|
import { createServer as createServer4, connect as netConnect } from "net";
|
|
16511
|
-
import
|
|
16906
|
+
import fs25 from "fs";
|
|
16512
16907
|
import { join as join26 } from "path";
|
|
16513
16908
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
16514
16909
|
import chalk2 from "chalk";
|
|
@@ -16517,15 +16912,15 @@ var shared;
|
|
|
16517
16912
|
var registryEntryPath = () => join26(CLAUDE_SESSIONS_DIR, `${process.pid}.json`);
|
|
16518
16913
|
function unregisterSenderIdentity() {
|
|
16519
16914
|
try {
|
|
16520
|
-
|
|
16915
|
+
fs25.unlinkSync(registryEntryPath());
|
|
16521
16916
|
} catch {
|
|
16522
16917
|
}
|
|
16523
16918
|
}
|
|
16524
16919
|
function registerSenderIdentity(socketPath) {
|
|
16525
16920
|
try {
|
|
16526
16921
|
unregisterSenderIdentity();
|
|
16527
|
-
|
|
16528
|
-
|
|
16922
|
+
fs25.mkdirSync(CLAUDE_SESSIONS_DIR, { recursive: true });
|
|
16923
|
+
fs25.writeFileSync(
|
|
16529
16924
|
registryEntryPath(),
|
|
16530
16925
|
JSON.stringify({
|
|
16531
16926
|
pid: process.pid,
|
|
@@ -16551,7 +16946,7 @@ async function sharedReceiptListener() {
|
|
|
16551
16946
|
// must never be the reason we refuse to start.
|
|
16552
16947
|
unlinkStale: (p) => {
|
|
16553
16948
|
try {
|
|
16554
|
-
|
|
16949
|
+
fs25.unlinkSync(p);
|
|
16555
16950
|
} catch {
|
|
16556
16951
|
}
|
|
16557
16952
|
},
|
|
@@ -16576,7 +16971,7 @@ async function buildCaptainChannel() {
|
|
|
16576
16971
|
// in /tmp/x registers cwd "/private/tmp/x" on macOS, so cwd matching silently
|
|
16577
16972
|
// missed and every captain ping reported accepted-unconfirmed.
|
|
16578
16973
|
statusFor: (taskId) => readClaudeStatusBySocketPath(captainSocketPath(taskId)),
|
|
16579
|
-
wire: (p, e) => writeLine(p, e, { connect: (
|
|
16974
|
+
wire: (p, e) => writeLine(p, e, { connect: (path29) => netConnect(path29) }),
|
|
16580
16975
|
receipts,
|
|
16581
16976
|
newMsgId: () => randomUUID5(),
|
|
16582
16977
|
sleep: (ms) => new Promise((r) => setTimeout(r, ms)),
|