squadrant 0.26.0 → 0.26.2
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 +869 -473
- package/dist/index.js.map +1 -1
- package/dist/squadrantd.js +514 -187
- package/dist/squadrantd.js.map +1 -1
- package/package.json +1 -1
- package/plugin/skills/captain-ops/SKILL.md +5 -0
- package/plugin/skills/rules-ops/SKILL.md +58 -0
- package/templates/captain.claude.md +1 -0
- package/templates/captain.generic.md +4 -0
- package/templates/crew.claude.md +4 -0
- package/templates/crew.generic.md +4 -0
- package/templates/crew.opencode.md +4 -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
|
}
|
|
@@ -5076,11 +5076,11 @@ var init_captain_record = __esm({
|
|
|
5076
5076
|
// packages/core/dist/opencode-session.js
|
|
5077
5077
|
import { execFileSync as execFileSync4 } from "child_process";
|
|
5078
5078
|
async function listSessions(port, fetchImpl = fetch, timeoutMs = 5e3) {
|
|
5079
|
-
for (const
|
|
5079
|
+
for (const path29 of ["/session", "/api/session"]) {
|
|
5080
5080
|
const ac = new AbortController();
|
|
5081
5081
|
const t = setTimeout(() => ac.abort(), timeoutMs);
|
|
5082
5082
|
try {
|
|
5083
|
-
const res = await fetchImpl(`http://127.0.0.1:${port}${
|
|
5083
|
+
const res = await fetchImpl(`http://127.0.0.1:${port}${path29}`, { signal: ac.signal });
|
|
5084
5084
|
if (!res.ok)
|
|
5085
5085
|
continue;
|
|
5086
5086
|
const rows = await res.json();
|
|
@@ -5095,8 +5095,8 @@ async function listSessions(port, fetchImpl = fetch, timeoutMs = 5e3) {
|
|
|
5095
5095
|
}
|
|
5096
5096
|
function parseLiveOpencodeServers(psOutput) {
|
|
5097
5097
|
const out = [];
|
|
5098
|
-
for (const
|
|
5099
|
-
const m =
|
|
5098
|
+
for (const line2 of psOutput.split("\n")) {
|
|
5099
|
+
const m = line2.match(/^\s*(\d+)\s+(.+)$/);
|
|
5100
5100
|
if (!m)
|
|
5101
5101
|
continue;
|
|
5102
5102
|
const pid = Number(m[1]);
|
|
@@ -5122,8 +5122,8 @@ function defaultPsOutput() {
|
|
|
5122
5122
|
function defaultCwdOf(pid) {
|
|
5123
5123
|
try {
|
|
5124
5124
|
const out = execFileSync4("lsof", ["-a", "-p", String(pid), "-d", "cwd", "-Fn"], { encoding: "utf-8", timeout: 2e3 });
|
|
5125
|
-
const
|
|
5126
|
-
return
|
|
5125
|
+
const line2 = out.split("\n").find((l) => l.startsWith("n"));
|
|
5126
|
+
return line2 ? line2.slice(1) : null;
|
|
5127
5127
|
} catch {
|
|
5128
5128
|
return null;
|
|
5129
5129
|
}
|
|
@@ -5773,10 +5773,10 @@ function distBuiltAt() {
|
|
|
5773
5773
|
return 0;
|
|
5774
5774
|
}
|
|
5775
5775
|
}
|
|
5776
|
-
function gatherLogStats(
|
|
5776
|
+
function gatherLogStats(path29, now, windowMs) {
|
|
5777
5777
|
let sizeBytes = 0;
|
|
5778
5778
|
try {
|
|
5779
|
-
sizeBytes = statSync3(
|
|
5779
|
+
sizeBytes = statSync3(path29).size;
|
|
5780
5780
|
} catch {
|
|
5781
5781
|
return { errorCount: 0, sizeBytes: 0, windowMs };
|
|
5782
5782
|
}
|
|
@@ -5787,7 +5787,7 @@ function gatherLogStats(path28, now, windowMs) {
|
|
|
5787
5787
|
const len = sizeBytes - start;
|
|
5788
5788
|
let text = "";
|
|
5789
5789
|
try {
|
|
5790
|
-
const fd = openSync2(
|
|
5790
|
+
const fd = openSync2(path29, "r");
|
|
5791
5791
|
try {
|
|
5792
5792
|
const buf = Buffer.alloc(len);
|
|
5793
5793
|
readSync(fd, buf, 0, len, start);
|
|
@@ -5800,10 +5800,10 @@ function gatherLogStats(path28, now, windowMs) {
|
|
|
5800
5800
|
}
|
|
5801
5801
|
const cutoff = now - windowMs;
|
|
5802
5802
|
let errorCount = 0;
|
|
5803
|
-
for (const
|
|
5804
|
-
if (!/error|failed/i.test(
|
|
5803
|
+
for (const line2 of text.split("\n")) {
|
|
5804
|
+
if (!/error|failed/i.test(line2))
|
|
5805
5805
|
continue;
|
|
5806
|
-
const m =
|
|
5806
|
+
const m = line2.match(/\d{4}-\d{2}-\d{2}T[\d:.]+Z/);
|
|
5807
5807
|
if (m) {
|
|
5808
5808
|
const ts = Date.parse(m[0]);
|
|
5809
5809
|
if (!Number.isNaN(ts) && ts < cutoff)
|
|
@@ -7978,10 +7978,10 @@ function scan(bufRef, acc) {
|
|
|
7978
7978
|
let saw = false;
|
|
7979
7979
|
let idx;
|
|
7980
7980
|
while ((idx = bufRef.value.indexOf("\n")) !== -1) {
|
|
7981
|
-
const
|
|
7981
|
+
const line2 = bufRef.value.slice(0, idx).trim();
|
|
7982
7982
|
bufRef.value = bufRef.value.slice(idx + 1);
|
|
7983
|
-
if (
|
|
7984
|
-
const payload =
|
|
7983
|
+
if (line2.startsWith("data:")) {
|
|
7984
|
+
const payload = line2.slice(5).trim();
|
|
7985
7985
|
if (payload && payload !== "[DONE]") {
|
|
7986
7986
|
try {
|
|
7987
7987
|
if (absorb(JSON.parse(payload), acc))
|
|
@@ -8032,8 +8032,8 @@ var init_stream = __esm({
|
|
|
8032
8032
|
// packages/core/dist/router/shim.js
|
|
8033
8033
|
import { createServer as createServer3 } from "http";
|
|
8034
8034
|
import { Readable } from "stream";
|
|
8035
|
-
function joinUrl(base,
|
|
8036
|
-
return base.replace(/\/+$/, "") +
|
|
8035
|
+
function joinUrl(base, path29) {
|
|
8036
|
+
return base.replace(/\/+$/, "") + path29;
|
|
8037
8037
|
}
|
|
8038
8038
|
async function readBody(req) {
|
|
8039
8039
|
const chunks = [];
|
|
@@ -8209,8 +8209,8 @@ function createRouterShim(opts) {
|
|
|
8209
8209
|
writeJson(res, 200, { input_tokens: Math.max(1, Math.ceil(text.length / 4)) });
|
|
8210
8210
|
}
|
|
8211
8211
|
function handler(req, res) {
|
|
8212
|
-
const
|
|
8213
|
-
if (req.method === "POST" &&
|
|
8212
|
+
const path29 = pathnameOf(req.url);
|
|
8213
|
+
if (req.method === "POST" && path29 === "/v1/messages") {
|
|
8214
8214
|
void handleMessages(req, res).catch((err) => {
|
|
8215
8215
|
log(`router internal error: ${err instanceof Error ? err.message : String(err)}`);
|
|
8216
8216
|
if (!res.headersSent) {
|
|
@@ -8222,18 +8222,18 @@ function createRouterShim(opts) {
|
|
|
8222
8222
|
});
|
|
8223
8223
|
return;
|
|
8224
8224
|
}
|
|
8225
|
-
if (req.method === "POST" &&
|
|
8225
|
+
if (req.method === "POST" && path29 === "/v1/messages/count_tokens") {
|
|
8226
8226
|
void handleCountTokens(req, res).catch(() => {
|
|
8227
8227
|
if (!res.headersSent)
|
|
8228
8228
|
writeJson(res, 502, anthropicError(502, "api_error", "router internal error").body);
|
|
8229
8229
|
});
|
|
8230
8230
|
return;
|
|
8231
8231
|
}
|
|
8232
|
-
if (req.method === "GET" &&
|
|
8232
|
+
if (req.method === "GET" && path29 === "/v1/models") {
|
|
8233
8233
|
writeJson(res, 200, modelsList([...advertisedModels]));
|
|
8234
8234
|
return;
|
|
8235
8235
|
}
|
|
8236
|
-
if (req.method === "GET" &&
|
|
8236
|
+
if (req.method === "GET" && path29 === "/healthz") {
|
|
8237
8237
|
writeJson(res, 200, { ready: server?.listening === true, upstreamReachable, lastError });
|
|
8238
8238
|
return;
|
|
8239
8239
|
}
|
|
@@ -8502,11 +8502,11 @@ async function probeCaptainChannel(project, opts = {}) {
|
|
|
8502
8502
|
}
|
|
8503
8503
|
}
|
|
8504
8504
|
async function httpReachable(port, fetchImpl, timeoutMs) {
|
|
8505
|
-
for (const
|
|
8505
|
+
for (const path29 of ["/session", "/api/session"]) {
|
|
8506
8506
|
const ac = new AbortController();
|
|
8507
8507
|
const t = setTimeout(() => ac.abort(), timeoutMs);
|
|
8508
8508
|
try {
|
|
8509
|
-
const res = await fetchImpl(`http://127.0.0.1:${port}${
|
|
8509
|
+
const res = await fetchImpl(`http://127.0.0.1:${port}${path29}`, { signal: ac.signal });
|
|
8510
8510
|
if (res.ok)
|
|
8511
8511
|
return true;
|
|
8512
8512
|
} catch {
|
|
@@ -9288,8 +9288,12 @@ var init_paths = __esm({
|
|
|
9288
9288
|
|
|
9289
9289
|
// packages/core/dist/knowledge/store.js
|
|
9290
9290
|
import fs15 from "fs";
|
|
9291
|
+
import os7 from "os";
|
|
9291
9292
|
import path15 from "path";
|
|
9292
9293
|
import matter2 from "gray-matter";
|
|
9294
|
+
function duplicateIdProblem(id, ignored, used) {
|
|
9295
|
+
return `duplicate id ${id}: ${ignored} is ignored, ${used} is used (live files win over _proposed, then path order). Fix: rename the id in one file, or delete or move one of them.`;
|
|
9296
|
+
}
|
|
9293
9297
|
function splitStatement(body) {
|
|
9294
9298
|
const first = body.trim().split(/\n\s*\n/)[0] ?? "";
|
|
9295
9299
|
return first.replace(/\s+/g, " ").trim();
|
|
@@ -9334,7 +9338,7 @@ function loadRulesDir(dir, layer, opts = {}) {
|
|
|
9334
9338
|
const fm = parsed.data;
|
|
9335
9339
|
const prior = seen.get(fm.id);
|
|
9336
9340
|
if (prior) {
|
|
9337
|
-
errors.push({ file, problems: [
|
|
9341
|
+
errors.push({ file, problems: [duplicateIdProblem(fm.id, file, prior)] });
|
|
9338
9342
|
continue;
|
|
9339
9343
|
}
|
|
9340
9344
|
seen.set(fm.id, file);
|
|
@@ -9342,7 +9346,65 @@ function loadRulesDir(dir, layer, opts = {}) {
|
|
|
9342
9346
|
}
|
|
9343
9347
|
return { rules, errors };
|
|
9344
9348
|
}
|
|
9345
|
-
|
|
9349
|
+
function resolveSourceRef(ref, kbRoot, sources) {
|
|
9350
|
+
const bases = /* @__PURE__ */ new Set([kbRoot]);
|
|
9351
|
+
for (const s of sources) {
|
|
9352
|
+
let d = path15.resolve(kbRoot, expandHome(s.path.split(/[*?[{]/)[0]));
|
|
9353
|
+
for (let i = 0; i < 6 && d !== path15.dirname(d); i++) {
|
|
9354
|
+
d = path15.dirname(d);
|
|
9355
|
+
bases.add(d);
|
|
9356
|
+
}
|
|
9357
|
+
}
|
|
9358
|
+
const cands = [path15.resolve(kbRoot, expandHome(ref)), ...[...bases].map((b) => path15.join(b, ref))];
|
|
9359
|
+
return cands.find((c) => fs15.existsSync(c) && fs15.statSync(c).isFile());
|
|
9360
|
+
}
|
|
9361
|
+
function validateKb(opts) {
|
|
9362
|
+
const { rules, errors } = loadRulesDir(opts.rulesDir, "kb", { includeProposed: true });
|
|
9363
|
+
const checks = [];
|
|
9364
|
+
const dups = errors.filter((e) => e.problems.some((p) => p.startsWith("duplicate id")));
|
|
9365
|
+
const invalid = errors.filter((e) => !dups.includes(e));
|
|
9366
|
+
const proposed = rules.filter((r) => path15.relative(opts.rulesDir, r.file).split(path15.sep).includes(PROPOSED_DIR)).length;
|
|
9367
|
+
checks.push({ level: "ok", message: `${rules.length + errors.length} rule files read (${rules.length - proposed} live, ${proposed} proposed parsed OK)` });
|
|
9368
|
+
if (invalid.length)
|
|
9369
|
+
for (const e of invalid)
|
|
9370
|
+
checks.push({ level: "fail", message: `invalid ${e.file}: ${e.problems.join("; ")}` });
|
|
9371
|
+
else
|
|
9372
|
+
checks.push({ level: "ok", message: "no invalid rule files" });
|
|
9373
|
+
if (dups.length)
|
|
9374
|
+
for (const e of dups)
|
|
9375
|
+
checks.push({ level: "fail", message: e.problems.join("; ") });
|
|
9376
|
+
else
|
|
9377
|
+
checks.push({ level: "ok", message: "no duplicate ids" });
|
|
9378
|
+
const cache = /* @__PURE__ */ new Map();
|
|
9379
|
+
let verified = 0, unresolved = 0;
|
|
9380
|
+
for (const r of rules) {
|
|
9381
|
+
r.sources.forEach((src, i) => {
|
|
9382
|
+
const file = resolveSourceRef(src.ref, opts.kbRoot, opts.sources);
|
|
9383
|
+
if (!file) {
|
|
9384
|
+
unresolved++;
|
|
9385
|
+
return;
|
|
9386
|
+
}
|
|
9387
|
+
if (!cache.has(file))
|
|
9388
|
+
cache.set(file, fs15.readFileSync(file, "utf8"));
|
|
9389
|
+
if (cache.get(file).includes(src.quote))
|
|
9390
|
+
verified++;
|
|
9391
|
+
else
|
|
9392
|
+
checks.push({ level: "fail", message: `quote not found in ${file}: ${r.id} sources[${i}] (${r.file})` });
|
|
9393
|
+
});
|
|
9394
|
+
}
|
|
9395
|
+
if (!checks.some((c) => c.message.startsWith("quote not found")))
|
|
9396
|
+
checks.push({ level: "ok", message: `${verified} source quotes found in their source files` });
|
|
9397
|
+
if (unresolved)
|
|
9398
|
+
checks.push({ level: "skip", message: `${unresolved} source refs not resolvable on this machine, quote not checked` });
|
|
9399
|
+
if (opts.domains) {
|
|
9400
|
+
for (const r of rules) {
|
|
9401
|
+
if (!opts.domains.includes(r.domain))
|
|
9402
|
+
checks.push({ level: "warn", message: `${r.id}: domain '${r.domain}' not in allowed domains [${opts.domains.join(", ")}] (${r.file})` });
|
|
9403
|
+
}
|
|
9404
|
+
}
|
|
9405
|
+
return { checks, ok: !checks.some((c) => c.level === "fail") };
|
|
9406
|
+
}
|
|
9407
|
+
var NO_JS_FRONTMATTER, expandHome;
|
|
9346
9408
|
var init_store2 = __esm({
|
|
9347
9409
|
"packages/core/dist/knowledge/store.js"() {
|
|
9348
9410
|
init_dist();
|
|
@@ -9352,6 +9414,7 @@ var init_store2 = __esm({
|
|
|
9352
9414
|
throw new Error("only YAML front matter is allowed");
|
|
9353
9415
|
} } }
|
|
9354
9416
|
};
|
|
9417
|
+
expandHome = (p) => p === "~" || p.startsWith("~/") ? path15.join(os7.homedir(), p.slice(1)) : p;
|
|
9355
9418
|
}
|
|
9356
9419
|
});
|
|
9357
9420
|
|
|
@@ -9440,7 +9503,7 @@ var init_index_file = __esm({
|
|
|
9440
9503
|
|
|
9441
9504
|
// packages/core/dist/knowledge/search.js
|
|
9442
9505
|
function searchRules(rules, query, opts = {}) {
|
|
9443
|
-
const terms = query.toLowerCase().split(/\s+/).filter(Boolean);
|
|
9506
|
+
const terms = [...new Set(query.toLowerCase().split(/\s+/).filter(Boolean))];
|
|
9444
9507
|
if (terms.length === 0)
|
|
9445
9508
|
return [];
|
|
9446
9509
|
const statuses = opts.statuses ?? DEFAULT_SEARCH_STATUSES;
|
|
@@ -9452,30 +9515,45 @@ function searchRules(rules, query, opts = {}) {
|
|
|
9452
9515
|
const expanded = lower(rule.triggers?.expanded);
|
|
9453
9516
|
const when = (rule.triggers?.when ?? "").toLowerCase();
|
|
9454
9517
|
const statement = rule.statement.toLowerCase();
|
|
9518
|
+
const rationale = rationaleOf(rule);
|
|
9455
9519
|
const id = rule.id.toLowerCase();
|
|
9456
9520
|
let score = 0;
|
|
9521
|
+
let matched = 0;
|
|
9522
|
+
let curated = false;
|
|
9457
9523
|
for (const t of terms) {
|
|
9524
|
+
let s = 0;
|
|
9458
9525
|
if (id.includes(t))
|
|
9459
|
-
|
|
9526
|
+
s += 3;
|
|
9527
|
+
if (keywords.includes(t) || expanded.includes(t))
|
|
9528
|
+
curated = true;
|
|
9460
9529
|
if (keywords.includes(t))
|
|
9461
|
-
|
|
9530
|
+
s += 3;
|
|
9462
9531
|
if (expanded.includes(t))
|
|
9463
|
-
|
|
9532
|
+
s += 3;
|
|
9464
9533
|
if (when.includes(t))
|
|
9465
|
-
|
|
9534
|
+
s += 2;
|
|
9466
9535
|
if (statement.includes(t))
|
|
9467
|
-
|
|
9536
|
+
s += 2;
|
|
9537
|
+
if (rationale.includes(t))
|
|
9538
|
+
s += 1;
|
|
9539
|
+
if (s > 0) {
|
|
9540
|
+
matched++;
|
|
9541
|
+
score += s;
|
|
9542
|
+
}
|
|
9468
9543
|
}
|
|
9469
9544
|
if (score > 0)
|
|
9470
|
-
hits.push({ rule, score });
|
|
9545
|
+
hits.push({ rule, score, matched, curated });
|
|
9471
9546
|
}
|
|
9472
|
-
|
|
9547
|
+
const strong = terms.length >= 2 ? hits.filter((h) => h.matched >= 2 || h.curated) : hits;
|
|
9548
|
+
const out = strong.length ? strong : hits;
|
|
9549
|
+
return out.sort((a, b) => b.score - a.score || a.rule.id.localeCompare(b.rule.id));
|
|
9473
9550
|
}
|
|
9474
|
-
var DEFAULT_SEARCH_STATUSES, lower;
|
|
9551
|
+
var DEFAULT_SEARCH_STATUSES, lower, rationaleOf;
|
|
9475
9552
|
var init_search = __esm({
|
|
9476
9553
|
"packages/core/dist/knowledge/search.js"() {
|
|
9477
9554
|
DEFAULT_SEARCH_STATUSES = ["active", "stale"];
|
|
9478
9555
|
lower = (xs) => (xs ?? []).map((x) => x.toLowerCase());
|
|
9556
|
+
rationaleOf = (rule) => rule.body.slice(rule.statement.length).toLowerCase();
|
|
9479
9557
|
}
|
|
9480
9558
|
});
|
|
9481
9559
|
|
|
@@ -9611,28 +9689,28 @@ function requireSnippet() {
|
|
|
9611
9689
|
const maxLineLength = options.maxLength - (options.indent + lineNoLength + 3);
|
|
9612
9690
|
for (let i = 1; i <= options.linesBefore; i++) {
|
|
9613
9691
|
if (foundLineNo - i < 0) break;
|
|
9614
|
-
const
|
|
9692
|
+
const line22 = getLine(
|
|
9615
9693
|
mark2.buffer,
|
|
9616
9694
|
lineStarts[foundLineNo - i],
|
|
9617
9695
|
lineEnds[foundLineNo - i],
|
|
9618
9696
|
mark2.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo - i]),
|
|
9619
9697
|
maxLineLength
|
|
9620
9698
|
);
|
|
9621
|
-
result = common2.repeat(" ", options.indent) + padStart((mark2.line - i + 1).toString(), lineNoLength) + " | " +
|
|
9699
|
+
result = common2.repeat(" ", options.indent) + padStart((mark2.line - i + 1).toString(), lineNoLength) + " | " + line22.str + "\n" + result;
|
|
9622
9700
|
}
|
|
9623
|
-
const
|
|
9624
|
-
result += common2.repeat(" ", options.indent) + padStart((mark2.line + 1).toString(), lineNoLength) + " | " +
|
|
9625
|
-
result += common2.repeat("-", options.indent + lineNoLength + 3 +
|
|
9701
|
+
const line2 = getLine(mark2.buffer, lineStarts[foundLineNo], lineEnds[foundLineNo], mark2.position, maxLineLength);
|
|
9702
|
+
result += common2.repeat(" ", options.indent) + padStart((mark2.line + 1).toString(), lineNoLength) + " | " + line2.str + "\n";
|
|
9703
|
+
result += common2.repeat("-", options.indent + lineNoLength + 3 + line2.pos) + "^\n";
|
|
9626
9704
|
for (let i = 1; i <= options.linesAfter; i++) {
|
|
9627
9705
|
if (foundLineNo + i >= lineEnds.length) break;
|
|
9628
|
-
const
|
|
9706
|
+
const line22 = getLine(
|
|
9629
9707
|
mark2.buffer,
|
|
9630
9708
|
lineStarts[foundLineNo + i],
|
|
9631
9709
|
lineEnds[foundLineNo + i],
|
|
9632
9710
|
mark2.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo + i]),
|
|
9633
9711
|
maxLineLength
|
|
9634
9712
|
);
|
|
9635
|
-
result += common2.repeat(" ", options.indent) + padStart((mark2.line + i + 1).toString(), lineNoLength) + " | " +
|
|
9713
|
+
result += common2.repeat(" ", options.indent) + padStart((mark2.line + i + 1).toString(), lineNoLength) + " | " + line22.str + "\n";
|
|
9636
9714
|
}
|
|
9637
9715
|
return result.replace(/\n$/, "");
|
|
9638
9716
|
}
|
|
@@ -11919,17 +11997,17 @@ function requireDumper() {
|
|
|
11919
11997
|
let result = "";
|
|
11920
11998
|
const length = string.length;
|
|
11921
11999
|
while (position < length) {
|
|
11922
|
-
let
|
|
12000
|
+
let line2;
|
|
11923
12001
|
const next = string.indexOf("\n", position);
|
|
11924
12002
|
if (next === -1) {
|
|
11925
|
-
|
|
12003
|
+
line2 = string.slice(position);
|
|
11926
12004
|
position = length;
|
|
11927
12005
|
} else {
|
|
11928
|
-
|
|
12006
|
+
line2 = string.slice(position, next + 1);
|
|
11929
12007
|
position = next + 1;
|
|
11930
12008
|
}
|
|
11931
|
-
if (
|
|
11932
|
-
result +=
|
|
12009
|
+
if (line2.length && line2 !== "\n") result += ind;
|
|
12010
|
+
result += line2;
|
|
11933
12011
|
}
|
|
11934
12012
|
return result;
|
|
11935
12013
|
}
|
|
@@ -12114,15 +12192,15 @@ function requireDumper() {
|
|
|
12114
12192
|
let match;
|
|
12115
12193
|
while (match = lineRe.exec(string)) {
|
|
12116
12194
|
const prefix = match[1];
|
|
12117
|
-
const
|
|
12118
|
-
moreIndented =
|
|
12119
|
-
result += prefix + (!prevMoreIndented && !moreIndented &&
|
|
12195
|
+
const line2 = match[2];
|
|
12196
|
+
moreIndented = line2[0] === " ";
|
|
12197
|
+
result += prefix + (!prevMoreIndented && !moreIndented && line2 !== "" ? "\n" : "") + foldLine(line2, width);
|
|
12120
12198
|
prevMoreIndented = moreIndented;
|
|
12121
12199
|
}
|
|
12122
12200
|
return result;
|
|
12123
12201
|
}
|
|
12124
|
-
function foldLine(
|
|
12125
|
-
if (
|
|
12202
|
+
function foldLine(line2, width) {
|
|
12203
|
+
if (line2 === "" || line2[0] === " ") return line2;
|
|
12126
12204
|
const breakRe = / [^ ]/g;
|
|
12127
12205
|
let match;
|
|
12128
12206
|
let start = 0;
|
|
@@ -12130,20 +12208,20 @@ function requireDumper() {
|
|
|
12130
12208
|
let curr = 0;
|
|
12131
12209
|
let next = 0;
|
|
12132
12210
|
let result = "";
|
|
12133
|
-
while (match = breakRe.exec(
|
|
12211
|
+
while (match = breakRe.exec(line2)) {
|
|
12134
12212
|
next = match.index;
|
|
12135
12213
|
if (next - start > width) {
|
|
12136
12214
|
end = curr > start ? curr : next;
|
|
12137
|
-
result += "\n" +
|
|
12215
|
+
result += "\n" + line2.slice(start, end);
|
|
12138
12216
|
start = end + 1;
|
|
12139
12217
|
}
|
|
12140
12218
|
curr = next;
|
|
12141
12219
|
}
|
|
12142
12220
|
result += "\n";
|
|
12143
|
-
if (
|
|
12144
|
-
result +=
|
|
12221
|
+
if (line2.length - start > width && curr > start) {
|
|
12222
|
+
result += line2.slice(start, curr) + "\n" + line2.slice(curr + 1);
|
|
12145
12223
|
} else {
|
|
12146
|
-
result +=
|
|
12224
|
+
result += line2.slice(start);
|
|
12147
12225
|
}
|
|
12148
12226
|
return result.slice(1);
|
|
12149
12227
|
}
|
|
@@ -12552,6 +12630,220 @@ var init_sources = __esm({
|
|
|
12552
12630
|
}
|
|
12553
12631
|
});
|
|
12554
12632
|
|
|
12633
|
+
// packages/core/dist/knowledge/inject.js
|
|
12634
|
+
import fs19 from "fs";
|
|
12635
|
+
import path18 from "path";
|
|
12636
|
+
function sessionOrder(a, b) {
|
|
12637
|
+
const proj = (r) => r.layer.startsWith("project:") ? 0 : 1;
|
|
12638
|
+
const mod = (r) => r.modality === "must-not" ? 0 : 1;
|
|
12639
|
+
return proj(a) - proj(b) || mod(a) - mod(b) || a.id.localeCompare(b.id);
|
|
12640
|
+
}
|
|
12641
|
+
function formatSessionContext(kbs, rules, cap = SESSION_RULE_CAP) {
|
|
12642
|
+
const hard = rules.filter((r) => r.status === "active" && (r.modality === "must" || r.modality === "must-not")).sort(sessionOrder);
|
|
12643
|
+
const shown = hard.slice(0, cap);
|
|
12644
|
+
const lines = [
|
|
12645
|
+
`<squadrant-project-rules kb="${kbs.join(",")}">`,
|
|
12646
|
+
`Rules KB: ${kbs.join(", ")}. ${DATA_NOTE}`,
|
|
12647
|
+
...shown.map(line)
|
|
12648
|
+
];
|
|
12649
|
+
if (hard.length > shown.length)
|
|
12650
|
+
lines.push(`+${hard.length - shown.length} more: squadrant rules list --brief`);
|
|
12651
|
+
lines.push("Look up rules for a task with `squadrant rules search <terms>` / `squadrant rules show <id>` (rules-ops skill).");
|
|
12652
|
+
lines.push("</squadrant-project-rules>");
|
|
12653
|
+
return { text: lines.join("\n"), ids: shown.map((r) => r.id) };
|
|
12654
|
+
}
|
|
12655
|
+
function cleanPromptQuery(prompt) {
|
|
12656
|
+
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, " ");
|
|
12657
|
+
const terms = [];
|
|
12658
|
+
const add = (t) => {
|
|
12659
|
+
if (t.length < 3 && !SHORT_TERMS.has(t) || /^\d+$/.test(t) || STOPWORDS.has(t) || terms.includes(t))
|
|
12660
|
+
return;
|
|
12661
|
+
terms.push(t);
|
|
12662
|
+
};
|
|
12663
|
+
for (const raw of text.split(/[^a-z0-9._-]+/)) {
|
|
12664
|
+
const t = raw.replace(/^[._-]+|[._-]+$/g, "");
|
|
12665
|
+
if (STOPWORDS.has(t))
|
|
12666
|
+
continue;
|
|
12667
|
+
add(t);
|
|
12668
|
+
const parts = t.split(/[._-]+/);
|
|
12669
|
+
if (parts.length > 1 && parts.every((x) => x.length >= 3 && !PREFIXES.has(x)))
|
|
12670
|
+
parts.forEach(add);
|
|
12671
|
+
if (terms.length >= MAX_TERMS)
|
|
12672
|
+
break;
|
|
12673
|
+
}
|
|
12674
|
+
return terms.slice(0, MAX_TERMS).join(" ");
|
|
12675
|
+
}
|
|
12676
|
+
function wholeWordTerms(rule, terms) {
|
|
12677
|
+
const text = [
|
|
12678
|
+
rule.id,
|
|
12679
|
+
...rule.triggers?.keywords ?? [],
|
|
12680
|
+
...rule.triggers?.expanded ?? [],
|
|
12681
|
+
rule.triggers?.when ?? "",
|
|
12682
|
+
rule.statement
|
|
12683
|
+
].join("\n").toLowerCase();
|
|
12684
|
+
return terms.filter((t) => {
|
|
12685
|
+
const base = t.length > 4 ? t.replace(/(es|s)$/, "") : t;
|
|
12686
|
+
return new RegExp(`(^|[^a-z0-9])(?:${escapeRe(t)}|${escapeRe(base)}(?:s|es)?)($|[^a-z0-9])`).test(text);
|
|
12687
|
+
});
|
|
12688
|
+
}
|
|
12689
|
+
function selectPromptHits(hits, query, seen, opts = {}) {
|
|
12690
|
+
const minScore = opts.minScore ?? PROMPT_MIN_SCORE;
|
|
12691
|
+
const terms = query.split(" ").filter(Boolean);
|
|
12692
|
+
return hits.filter((h) => {
|
|
12693
|
+
if (seen.has(h.rule.id))
|
|
12694
|
+
return false;
|
|
12695
|
+
const n = wholeWordTerms(h.rule, terms).length;
|
|
12696
|
+
return n >= 2 && h.score >= minScore || n === 1 && h.score >= PROMPT_SINGLE_TERM_MIN_SCORE;
|
|
12697
|
+
}).slice(0, opts.cap ?? PROMPT_RULE_CAP);
|
|
12698
|
+
}
|
|
12699
|
+
function isSystemPrompt(prompt) {
|
|
12700
|
+
const t = prompt.trimStart();
|
|
12701
|
+
return /^(⚠|🗒|\[stale\b|CREW [A-Z]|Another Claude session sent a message)/u.test(t) || t.includes("<cross-session-message");
|
|
12702
|
+
}
|
|
12703
|
+
function promptText(prompt) {
|
|
12704
|
+
const m = BRIEF_POINTER_RE.exec(prompt.trimStart());
|
|
12705
|
+
if (!m)
|
|
12706
|
+
return prompt;
|
|
12707
|
+
try {
|
|
12708
|
+
return fs19.readFileSync(m[1], "utf8").slice(0, MAX_PROMPT_CHARS * 2);
|
|
12709
|
+
} catch {
|
|
12710
|
+
return prompt;
|
|
12711
|
+
}
|
|
12712
|
+
}
|
|
12713
|
+
function formatPromptContext(hits) {
|
|
12714
|
+
return [
|
|
12715
|
+
'<squadrant-project-rules match="prompt">',
|
|
12716
|
+
`Rules that may apply to this prompt. ${DATA_NOTE}`,
|
|
12717
|
+
...hits.map((h) => line(h.rule)),
|
|
12718
|
+
"</squadrant-project-rules>"
|
|
12719
|
+
].join("\n");
|
|
12720
|
+
}
|
|
12721
|
+
function injectStateDir(stateRoot) {
|
|
12722
|
+
return path18.join(stateRoot, "rules-inject");
|
|
12723
|
+
}
|
|
12724
|
+
function readSeenRules(stateRoot, sessionId) {
|
|
12725
|
+
try {
|
|
12726
|
+
const ids = JSON.parse(fs19.readFileSync(sessionFile(stateRoot, sessionId), "utf8"));
|
|
12727
|
+
return new Set(Array.isArray(ids) ? ids.filter((x) => typeof x === "string") : []);
|
|
12728
|
+
} catch {
|
|
12729
|
+
return /* @__PURE__ */ new Set();
|
|
12730
|
+
}
|
|
12731
|
+
}
|
|
12732
|
+
function recordSeenRules(stateRoot, sessionId, ids) {
|
|
12733
|
+
if (!ids.length)
|
|
12734
|
+
return;
|
|
12735
|
+
const seen = readSeenRules(stateRoot, sessionId);
|
|
12736
|
+
for (const id of ids)
|
|
12737
|
+
seen.add(id);
|
|
12738
|
+
fs19.mkdirSync(injectStateDir(stateRoot), { recursive: true });
|
|
12739
|
+
fs19.writeFileSync(sessionFile(stateRoot, sessionId), JSON.stringify([...seen]));
|
|
12740
|
+
}
|
|
12741
|
+
function pruneSeenRules(stateRoot, now = Date.now()) {
|
|
12742
|
+
const dir = injectStateDir(stateRoot);
|
|
12743
|
+
let names;
|
|
12744
|
+
try {
|
|
12745
|
+
names = fs19.readdirSync(dir);
|
|
12746
|
+
} catch {
|
|
12747
|
+
return;
|
|
12748
|
+
}
|
|
12749
|
+
for (const n of names) {
|
|
12750
|
+
const f = path18.join(dir, n);
|
|
12751
|
+
try {
|
|
12752
|
+
if (now - fs19.statSync(f).mtimeMs > SEEN_TTL_MS)
|
|
12753
|
+
fs19.unlinkSync(f);
|
|
12754
|
+
} catch {
|
|
12755
|
+
}
|
|
12756
|
+
}
|
|
12757
|
+
}
|
|
12758
|
+
async function withBudget(fn, budgetMs = INJECT_BUDGET_MS) {
|
|
12759
|
+
const start = Date.now();
|
|
12760
|
+
let timer;
|
|
12761
|
+
try {
|
|
12762
|
+
const timeout = new Promise((resolve4) => {
|
|
12763
|
+
timer = setTimeout(() => resolve4(null), budgetMs);
|
|
12764
|
+
});
|
|
12765
|
+
const out = await Promise.race([Promise.resolve().then(fn), timeout]);
|
|
12766
|
+
return Date.now() - start > budgetMs ? null : out;
|
|
12767
|
+
} catch {
|
|
12768
|
+
return null;
|
|
12769
|
+
} finally {
|
|
12770
|
+
clearTimeout(timer);
|
|
12771
|
+
}
|
|
12772
|
+
}
|
|
12773
|
+
function resolveInjectProject(cfg, cwd, env, project) {
|
|
12774
|
+
const named = project ?? env.SQUADRANT_CREW_PROJECT;
|
|
12775
|
+
if (named)
|
|
12776
|
+
return cfg.projects[named] ? named : null;
|
|
12777
|
+
let best = null;
|
|
12778
|
+
let bestLen = -1;
|
|
12779
|
+
for (const [name, pc] of Object.entries(cfg.projects)) {
|
|
12780
|
+
const root = resolveHome(pc.path);
|
|
12781
|
+
if ((cwd === root || cwd.startsWith(root + path18.sep)) && root.length > bestLen) {
|
|
12782
|
+
best = name;
|
|
12783
|
+
bestLen = root.length;
|
|
12784
|
+
}
|
|
12785
|
+
}
|
|
12786
|
+
return best;
|
|
12787
|
+
}
|
|
12788
|
+
function computeRulesInjection(i) {
|
|
12789
|
+
if (i.env.SQUADRANT_RULES_INJECT === "0")
|
|
12790
|
+
return null;
|
|
12791
|
+
const p = typeof i.payload === "object" && i.payload !== null ? i.payload : {};
|
|
12792
|
+
const cwd = typeof p.cwd === "string" && p.cwd ? p.cwd : i.cwd;
|
|
12793
|
+
const project = resolveInjectProject(i.cfg, cwd, i.env, i.project);
|
|
12794
|
+
if (!project)
|
|
12795
|
+
return null;
|
|
12796
|
+
const kbs = subscribedKbs(i.cfg, project);
|
|
12797
|
+
if (!kbs.length)
|
|
12798
|
+
return null;
|
|
12799
|
+
const sessionId = typeof p.session_id === "string" && p.session_id ? p.session_id : null;
|
|
12800
|
+
if (i.event === "session-start") {
|
|
12801
|
+
const { text, ids } = formatSessionContext(kbs, resolveProjectRules(i.cfg, project).rules);
|
|
12802
|
+
if (sessionId) {
|
|
12803
|
+
pruneSeenRules(i.stateRoot);
|
|
12804
|
+
recordSeenRules(i.stateRoot, sessionId, ids);
|
|
12805
|
+
}
|
|
12806
|
+
return text;
|
|
12807
|
+
}
|
|
12808
|
+
if (typeof p.prompt !== "string" || isSystemPrompt(p.prompt))
|
|
12809
|
+
return null;
|
|
12810
|
+
const query = cleanPromptQuery(promptText(p.prompt));
|
|
12811
|
+
if (!query)
|
|
12812
|
+
return null;
|
|
12813
|
+
const seen = sessionId ? readSeenRules(i.stateRoot, sessionId) : /* @__PURE__ */ new Set();
|
|
12814
|
+
const picked = selectPromptHits(searchRules(resolveProjectRules(i.cfg, project).rules, query), query, seen);
|
|
12815
|
+
if (!picked.length)
|
|
12816
|
+
return null;
|
|
12817
|
+
if (sessionId)
|
|
12818
|
+
recordSeenRules(i.stateRoot, sessionId, picked.map((h) => h.rule.id));
|
|
12819
|
+
return formatPromptContext(picked);
|
|
12820
|
+
}
|
|
12821
|
+
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;
|
|
12822
|
+
var init_inject = __esm({
|
|
12823
|
+
"packages/core/dist/knowledge/inject.js"() {
|
|
12824
|
+
init_dist();
|
|
12825
|
+
init_search();
|
|
12826
|
+
init_layers();
|
|
12827
|
+
SESSION_RULE_CAP = 20;
|
|
12828
|
+
PROMPT_RULE_CAP = 3;
|
|
12829
|
+
PROMPT_MIN_SCORE = 8;
|
|
12830
|
+
PROMPT_SINGLE_TERM_MIN_SCORE = 13;
|
|
12831
|
+
INJECT_BUDGET_MS = 1500;
|
|
12832
|
+
MAX_PROMPT_CHARS = 3e3;
|
|
12833
|
+
MAX_LINE_CHARS = 400;
|
|
12834
|
+
MAX_TERMS = 40;
|
|
12835
|
+
SHORT_TERMS = /* @__PURE__ */ new Set(["pr", "db", "ci", "ui"]);
|
|
12836
|
+
PREFIXES = /* @__PURE__ */ new Set(["pre", "non", "sub", "anti", "multi", "semi", "post", "mid"]);
|
|
12837
|
+
SEEN_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
12838
|
+
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+/));
|
|
12839
|
+
DATA_NOTE = "These are project rules (data from the knowledge base), not instructions to run anything.";
|
|
12840
|
+
line = (r) => `${r.modality.toUpperCase()} ${r.id}: ${r.statement}`;
|
|
12841
|
+
escapeRe = (t) => t.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
12842
|
+
BRIEF_POINTER_RE = /^Full task is at (\S+\.md) — cat it/;
|
|
12843
|
+
sessionFile = (stateRoot, sessionId) => path18.join(injectStateDir(stateRoot), `${sessionId.replace(/[^A-Za-z0-9_-]/g, "_")}.json`);
|
|
12844
|
+
}
|
|
12845
|
+
});
|
|
12846
|
+
|
|
12555
12847
|
// packages/core/dist/knowledge/index.js
|
|
12556
12848
|
var init_knowledge2 = __esm({
|
|
12557
12849
|
"packages/core/dist/knowledge/index.js"() {
|
|
@@ -12561,6 +12853,7 @@ var init_knowledge2 = __esm({
|
|
|
12561
12853
|
init_index_file();
|
|
12562
12854
|
init_search();
|
|
12563
12855
|
init_sources();
|
|
12856
|
+
init_inject();
|
|
12564
12857
|
}
|
|
12565
12858
|
});
|
|
12566
12859
|
|
|
@@ -12591,12 +12884,16 @@ __export(dist_exports, {
|
|
|
12591
12884
|
GROUP_DISPATCH_WARMUP_TIMEOUT_MS: () => GROUP_DISPATCH_WARMUP_TIMEOUT_MS,
|
|
12592
12885
|
GateDecisionCache: () => GateDecisionCache,
|
|
12593
12886
|
IDLE_DEBOUNCE_MS: () => IDLE_DEBOUNCE_MS,
|
|
12887
|
+
INJECT_BUDGET_MS: () => INJECT_BUDGET_MS,
|
|
12594
12888
|
LABEL: () => LABEL,
|
|
12595
12889
|
LivenessRegistry: () => LivenessRegistry,
|
|
12596
12890
|
MONITOR_STALL_BUDGET_MS: () => MONITOR_STALL_BUDGET_MS,
|
|
12597
12891
|
OPERATOR_INITIATED_COMMANDS: () => OPERATOR_INITIATED_COMMANDS,
|
|
12598
12892
|
PANE_IDLE_AFTER_MS: () => PANE_IDLE_AFTER_MS,
|
|
12599
12893
|
PROBE_QUIET_MS: () => PROBE_QUIET_MS,
|
|
12894
|
+
PROMPT_MIN_SCORE: () => PROMPT_MIN_SCORE,
|
|
12895
|
+
PROMPT_RULE_CAP: () => PROMPT_RULE_CAP,
|
|
12896
|
+
PROMPT_SINGLE_TERM_MIN_SCORE: () => PROMPT_SINGLE_TERM_MIN_SCORE,
|
|
12600
12897
|
PROPOSED_DIR: () => PROPOSED_DIR,
|
|
12601
12898
|
PROTOCOL_VERSION: () => PROTOCOL_VERSION,
|
|
12602
12899
|
READ_ONLY_CREW_SUBCOMMANDS: () => READ_ONLY_CREW_SUBCOMMANDS,
|
|
@@ -12604,6 +12901,7 @@ __export(dist_exports, {
|
|
|
12604
12901
|
ROUTER_READY_ATTEMPTS: () => ROUTER_READY_ATTEMPTS,
|
|
12605
12902
|
ROUTER_READY_DELAY_MS: () => ROUTER_READY_DELAY_MS,
|
|
12606
12903
|
SERVER_TOOL_TYPE_RE: () => SERVER_TOOL_TYPE_RE,
|
|
12904
|
+
SESSION_RULE_CAP: () => SESSION_RULE_CAP,
|
|
12607
12905
|
SIDE_SESSION_ENV: () => SIDE_SESSION_ENV,
|
|
12608
12906
|
SOURCES_TEMPLATE: () => SOURCES_TEMPLATE,
|
|
12609
12907
|
STALE_THRESHOLD_MS: () => STALE_THRESHOLD_MS,
|
|
@@ -12644,9 +12942,11 @@ __export(dist_exports, {
|
|
|
12644
12942
|
classifyCaptainPane: () => classifyCaptainPane,
|
|
12645
12943
|
classifyHealth: () => classifyHealth,
|
|
12646
12944
|
claudeEnvShadowsRouter: () => claudeEnvShadowsRouter,
|
|
12945
|
+
cleanPromptQuery: () => cleanPromptQuery,
|
|
12647
12946
|
clearPending: () => clearPending,
|
|
12648
12947
|
closeWorkItem: () => closeWorkItem,
|
|
12649
12948
|
compileIndex: () => compileIndex,
|
|
12949
|
+
computeRulesInjection: () => computeRulesInjection,
|
|
12650
12950
|
computeTemplateHash: () => computeTemplateHash,
|
|
12651
12951
|
consumeExitMarker: () => consumeExitMarker,
|
|
12652
12952
|
createAttach: () => createAttach,
|
|
@@ -12698,6 +12998,7 @@ __export(dist_exports, {
|
|
|
12698
12998
|
discoverCaptainSurface: () => discoverCaptainSurface,
|
|
12699
12999
|
discoverLiveOpencodeServer: () => discoverLiveOpencodeServer,
|
|
12700
13000
|
dispatchToSibling: () => dispatchToSibling,
|
|
13001
|
+
duplicateIdProblem: () => duplicateIdProblem,
|
|
12701
13002
|
encodeFrame: () => encodeFrame,
|
|
12702
13003
|
encodeMsg: () => encodeMsg,
|
|
12703
13004
|
ensureDaemon: () => ensureDaemon,
|
|
@@ -12719,6 +13020,8 @@ __export(dist_exports, {
|
|
|
12719
13020
|
formatLifecycle: () => formatLifecycle,
|
|
12720
13021
|
formatMediaReceipt: () => formatMediaReceipt,
|
|
12721
13022
|
formatPermissionDecision: () => formatPermissionDecision,
|
|
13023
|
+
formatPromptContext: () => formatPromptContext,
|
|
13024
|
+
formatSessionContext: () => formatSessionContext,
|
|
12722
13025
|
formatUsageLine: () => formatUsageLine,
|
|
12723
13026
|
formatWatchdogWarning: () => formatWatchdogWarning,
|
|
12724
13027
|
freshTrace: () => freshTrace,
|
|
@@ -12728,6 +13031,7 @@ __export(dist_exports, {
|
|
|
12728
13031
|
hasModalOptionList: () => hasModalOptionList,
|
|
12729
13032
|
healCmdFor: () => healCmdFor,
|
|
12730
13033
|
inboundBody: () => inboundBody,
|
|
13034
|
+
injectStateDir: () => injectStateDir,
|
|
12731
13035
|
isAuthorized: () => isAuthorized,
|
|
12732
13036
|
isBareSpawn: () => isBareSpawn,
|
|
12733
13037
|
isCaptainAlive: () => isCaptainAlive,
|
|
@@ -12743,6 +13047,7 @@ __export(dist_exports, {
|
|
|
12743
13047
|
isReadOnlyTopLevelCommand: () => isReadOnlyTopLevelCommand,
|
|
12744
13048
|
isSideTitle: () => isSideTitle,
|
|
12745
13049
|
isStickyAttention: () => isStickyAttention,
|
|
13050
|
+
isSystemPrompt: () => isSystemPrompt,
|
|
12746
13051
|
isTurnAccepted: () => isTurnAccepted,
|
|
12747
13052
|
isVersionUpgrade: () => isVersionUpgrade,
|
|
12748
13053
|
joinUrl: () => joinUrl,
|
|
@@ -12788,6 +13093,7 @@ __export(dist_exports, {
|
|
|
12788
13093
|
programArgsBlock: () => programArgsBlock,
|
|
12789
13094
|
projectHealth: () => projectHealth,
|
|
12790
13095
|
projectRulesDir: () => projectRulesDir,
|
|
13096
|
+
pruneSeenRules: () => pruneSeenRules,
|
|
12791
13097
|
pruneTopics: () => pruneTopics,
|
|
12792
13098
|
purgeExpiredWorkItems: () => purgeExpiredWorkItems,
|
|
12793
13099
|
readCaptainAddress: () => readCaptainAddress,
|
|
@@ -12795,11 +13101,13 @@ __export(dist_exports, {
|
|
|
12795
13101
|
readFromCursor: () => readFromCursor,
|
|
12796
13102
|
readIndex: () => readIndex,
|
|
12797
13103
|
readRunningMarker: () => readRunningMarker,
|
|
13104
|
+
readSeenRules: () => readSeenRules,
|
|
12798
13105
|
readUserIntent: () => readUserIntent,
|
|
12799
13106
|
realpathOrSelf: () => realpathOrSelf,
|
|
12800
13107
|
reapCrewChildren: () => reapCrewChildren,
|
|
12801
13108
|
reapOrphanedCrews: () => reapOrphanedCrews,
|
|
12802
13109
|
reconcileLiveness: () => reconcileLiveness,
|
|
13110
|
+
recordSeenRules: () => recordSeenRules,
|
|
12803
13111
|
recordSession: () => recordSession,
|
|
12804
13112
|
recoverStall: () => recoverStall,
|
|
12805
13113
|
reduce: () => reduce,
|
|
@@ -12821,6 +13129,7 @@ __export(dist_exports, {
|
|
|
12821
13129
|
resolveGateMode: () => resolveGateMode,
|
|
12822
13130
|
resolveGatePolicy: () => resolveGatePolicy,
|
|
12823
13131
|
resolveGateTools: () => resolveGateTools,
|
|
13132
|
+
resolveInjectProject: () => resolveInjectProject,
|
|
12824
13133
|
resolveProject: () => resolveProject,
|
|
12825
13134
|
resolveProjectRules: () => resolveProjectRules,
|
|
12826
13135
|
resolveRouterCredentials: () => resolveRouterCredentials,
|
|
@@ -12860,6 +13169,7 @@ __export(dist_exports, {
|
|
|
12860
13169
|
screenHasSplashMarker: () => screenHasSplashMarker,
|
|
12861
13170
|
screenHash: () => screenHash,
|
|
12862
13171
|
searchRules: () => searchRules,
|
|
13172
|
+
selectPromptHits: () => selectPromptHits,
|
|
12863
13173
|
sendRequest: () => sendRequest,
|
|
12864
13174
|
setLastUserId: () => setLastUserId,
|
|
12865
13175
|
setNotify: () => setNotify,
|
|
@@ -12885,8 +13195,11 @@ __export(dist_exports, {
|
|
|
12885
13195
|
topicName: () => topicName,
|
|
12886
13196
|
tryAcquireDaemonLock: () => tryAcquireDaemonLock,
|
|
12887
13197
|
usageFromJson: () => usageFromJson,
|
|
13198
|
+
validateKb: () => validateKb,
|
|
12888
13199
|
waitForCaptainDelivery: () => waitForCaptainDelivery,
|
|
12889
13200
|
waitForWarmup: () => waitForWarmup,
|
|
13201
|
+
wholeWordTerms: () => wholeWordTerms,
|
|
13202
|
+
withBudget: () => withBudget,
|
|
12890
13203
|
writeCaptainAddress: () => writeCaptainAddress,
|
|
12891
13204
|
writeCursor: () => writeCursor,
|
|
12892
13205
|
writeExitMarker: () => writeExitMarker,
|
|
@@ -12949,6 +13262,20 @@ var init_dist2 = __esm({
|
|
|
12949
13262
|
}
|
|
12950
13263
|
});
|
|
12951
13264
|
|
|
13265
|
+
// packages/cli/src/lib/suppress-sqlite-warning.ts
|
|
13266
|
+
function isSqliteExperimentalWarning(warning, type2) {
|
|
13267
|
+
const name = typeof warning === "object" && warning !== null ? warning.name : typeof type2 === "string" ? type2 : void 0;
|
|
13268
|
+
const message = typeof warning === "string" ? warning : warning?.message;
|
|
13269
|
+
return name === "ExperimentalWarning" && typeof message === "string" && /SQLite is an experimental feature/i.test(message);
|
|
13270
|
+
}
|
|
13271
|
+
var original = process.emitWarning.bind(process);
|
|
13272
|
+
process.emitWarning = ((warning, ...rest) => {
|
|
13273
|
+
const first = rest[0];
|
|
13274
|
+
const type2 = typeof first === "string" ? first : first?.type;
|
|
13275
|
+
if (isSqliteExperimentalWarning(warning, type2)) return;
|
|
13276
|
+
original(warning, ...rest);
|
|
13277
|
+
});
|
|
13278
|
+
|
|
12952
13279
|
// packages/cli/src/squadrantd.ts
|
|
12953
13280
|
init_dist2();
|
|
12954
13281
|
init_dist2();
|
|
@@ -12975,7 +13302,7 @@ import { readdirSync as readdirSync4, readFileSync as readFileSync12 } from "fs"
|
|
|
12975
13302
|
import { join as join18 } from "path";
|
|
12976
13303
|
|
|
12977
13304
|
// packages/agents/dist/claude/registry.js
|
|
12978
|
-
import
|
|
13305
|
+
import fs20 from "fs";
|
|
12979
13306
|
import { join as join17 } from "path";
|
|
12980
13307
|
import { homedir as homedir7 } from "os";
|
|
12981
13308
|
var CLAUDE_SESSIONS_DIR = join17(homedir7(), ".claude", "sessions");
|
|
@@ -13020,11 +13347,11 @@ function toLifecycleSnapshot(entry, taskId, alive, now) {
|
|
|
13020
13347
|
function readClaudeStatusBySocketPath(socketPath) {
|
|
13021
13348
|
let files;
|
|
13022
13349
|
try {
|
|
13023
|
-
files =
|
|
13350
|
+
files = fs20.readdirSync(CLAUDE_SESSIONS_DIR);
|
|
13024
13351
|
} catch {
|
|
13025
13352
|
return void 0;
|
|
13026
13353
|
}
|
|
13027
|
-
const entries = parseRegistryDir(files, (name) =>
|
|
13354
|
+
const entries = parseRegistryDir(files, (name) => fs20.readFileSync(join17(CLAUDE_SESSIONS_DIR, name), "utf8"));
|
|
13028
13355
|
const entry = entries.find((e) => e.messagingSocketPath === socketPath);
|
|
13029
13356
|
if (!entry)
|
|
13030
13357
|
return void 0;
|
|
@@ -13047,38 +13374,38 @@ import { homedir as homedir8 } from "os";
|
|
|
13047
13374
|
var SQUADRANT_STATE_DIR = join19(homedir8(), ".config", "squadrant", "state");
|
|
13048
13375
|
|
|
13049
13376
|
// packages/agents/dist/drivers/launch-cmd.js
|
|
13050
|
-
import
|
|
13051
|
-
import
|
|
13377
|
+
import fs21 from "fs";
|
|
13378
|
+
import path19 from "path";
|
|
13052
13379
|
|
|
13053
13380
|
// packages/agents/dist/projection/cursor.js
|
|
13054
13381
|
import { mkdir, readFile, writeFile } from "fs/promises";
|
|
13055
|
-
import
|
|
13056
|
-
import
|
|
13382
|
+
import path20 from "path";
|
|
13383
|
+
import os8 from "os";
|
|
13057
13384
|
|
|
13058
13385
|
// packages/agents/dist/projection/codex.js
|
|
13059
13386
|
import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
|
|
13060
|
-
import
|
|
13061
|
-
import
|
|
13387
|
+
import path21 from "path";
|
|
13388
|
+
import os9 from "os";
|
|
13062
13389
|
|
|
13063
13390
|
// packages/agents/dist/projection/gemini.js
|
|
13064
13391
|
import { mkdir as mkdir3, readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
|
|
13065
|
-
import
|
|
13066
|
-
import
|
|
13392
|
+
import path22 from "path";
|
|
13393
|
+
import os10 from "os";
|
|
13067
13394
|
|
|
13068
13395
|
// packages/agents/dist/projection/opencode.js
|
|
13069
13396
|
import { mkdir as mkdir4, readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
|
|
13070
|
-
import
|
|
13071
|
-
import
|
|
13397
|
+
import path23 from "path";
|
|
13398
|
+
import os11 from "os";
|
|
13072
13399
|
|
|
13073
13400
|
// packages/agents/dist/projection/opencode-skills.js
|
|
13074
|
-
import
|
|
13075
|
-
import
|
|
13076
|
-
import
|
|
13401
|
+
import fs22 from "fs";
|
|
13402
|
+
import os12 from "os";
|
|
13403
|
+
import path24 from "path";
|
|
13077
13404
|
var OPENCODE_SKILL_MARKER = ".squadrant-managed";
|
|
13078
13405
|
var MARKER_BODY = "squadrant\n";
|
|
13079
13406
|
function defaultOpencodeSkillsRoot(env = process.env) {
|
|
13080
|
-
const configHome = env.XDG_CONFIG_HOME ||
|
|
13081
|
-
return
|
|
13407
|
+
const configHome = env.XDG_CONFIG_HOME || path24.join(os12.homedir(), ".config");
|
|
13408
|
+
return path24.join(configHome, "opencode", "skills");
|
|
13082
13409
|
}
|
|
13083
13410
|
var SAFE_NAME = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
|
|
13084
13411
|
function parseSkillName(raw) {
|
|
@@ -13093,62 +13420,62 @@ function parseSkillName(raw) {
|
|
|
13093
13420
|
}
|
|
13094
13421
|
function listSourceSkills(sourceSkillsDir) {
|
|
13095
13422
|
const out = /* @__PURE__ */ new Map();
|
|
13096
|
-
if (!
|
|
13423
|
+
if (!fs22.existsSync(sourceSkillsDir))
|
|
13097
13424
|
return out;
|
|
13098
|
-
for (const entry of
|
|
13425
|
+
for (const entry of fs22.readdirSync(sourceSkillsDir, { withFileTypes: true })) {
|
|
13099
13426
|
if (!entry.isDirectory())
|
|
13100
13427
|
continue;
|
|
13101
|
-
const skillPath =
|
|
13102
|
-
if (!
|
|
13428
|
+
const skillPath = path24.join(sourceSkillsDir, entry.name, "SKILL.md");
|
|
13429
|
+
if (!fs22.existsSync(skillPath))
|
|
13103
13430
|
continue;
|
|
13104
|
-
const name = parseSkillName(
|
|
13431
|
+
const name = parseSkillName(fs22.readFileSync(skillPath, "utf-8"));
|
|
13105
13432
|
if (name && SAFE_NAME.test(name))
|
|
13106
13433
|
out.set(name, skillPath);
|
|
13107
13434
|
}
|
|
13108
13435
|
return out;
|
|
13109
13436
|
}
|
|
13110
13437
|
function hasMarker(dir) {
|
|
13111
|
-
return
|
|
13438
|
+
return fs22.existsSync(path24.join(dir, OPENCODE_SKILL_MARKER));
|
|
13112
13439
|
}
|
|
13113
13440
|
function syncOpencodeSkills(opts) {
|
|
13114
13441
|
const result = { written: [], unchanged: [], removed: [], skipped: [] };
|
|
13115
13442
|
const wanted = listSourceSkills(opts.sourceSkillsDir);
|
|
13116
|
-
if (wanted.size === 0 && !
|
|
13443
|
+
if (wanted.size === 0 && !fs22.existsSync(opts.sourceSkillsDir))
|
|
13117
13444
|
return result;
|
|
13118
13445
|
if (!opts.dryRun)
|
|
13119
|
-
|
|
13446
|
+
fs22.mkdirSync(opts.skillsRoot, { recursive: true });
|
|
13120
13447
|
for (const [name, srcPath] of wanted) {
|
|
13121
|
-
const targetDir =
|
|
13122
|
-
const targetSkill =
|
|
13448
|
+
const targetDir = path24.join(opts.skillsRoot, name);
|
|
13449
|
+
const targetSkill = path24.join(targetDir, "SKILL.md");
|
|
13123
13450
|
const managed = hasMarker(targetDir);
|
|
13124
|
-
if (
|
|
13451
|
+
if (fs22.existsSync(targetSkill) && !managed) {
|
|
13125
13452
|
result.skipped.push({ name, reason: "foreign-collision" });
|
|
13126
13453
|
continue;
|
|
13127
13454
|
}
|
|
13128
|
-
const current =
|
|
13129
|
-
if (current && current.equals(
|
|
13455
|
+
const current = fs22.existsSync(targetSkill) ? fs22.readFileSync(targetSkill) : null;
|
|
13456
|
+
if (current && current.equals(fs22.readFileSync(srcPath))) {
|
|
13130
13457
|
if (!managed && !opts.dryRun) {
|
|
13131
|
-
|
|
13458
|
+
fs22.writeFileSync(path24.join(targetDir, OPENCODE_SKILL_MARKER), MARKER_BODY);
|
|
13132
13459
|
}
|
|
13133
13460
|
result.unchanged.push(name);
|
|
13134
13461
|
continue;
|
|
13135
13462
|
}
|
|
13136
13463
|
if (!opts.dryRun) {
|
|
13137
|
-
|
|
13138
|
-
|
|
13139
|
-
|
|
13464
|
+
fs22.mkdirSync(targetDir, { recursive: true });
|
|
13465
|
+
fs22.copyFileSync(srcPath, targetSkill);
|
|
13466
|
+
fs22.writeFileSync(path24.join(targetDir, OPENCODE_SKILL_MARKER), MARKER_BODY);
|
|
13140
13467
|
}
|
|
13141
13468
|
result.written.push(name);
|
|
13142
13469
|
}
|
|
13143
|
-
if (
|
|
13144
|
-
for (const entry of
|
|
13470
|
+
if (fs22.existsSync(opts.skillsRoot)) {
|
|
13471
|
+
for (const entry of fs22.readdirSync(opts.skillsRoot, { withFileTypes: true })) {
|
|
13145
13472
|
if (!entry.isDirectory() || wanted.has(entry.name))
|
|
13146
13473
|
continue;
|
|
13147
|
-
const dir =
|
|
13474
|
+
const dir = path24.join(opts.skillsRoot, entry.name);
|
|
13148
13475
|
if (!hasMarker(dir))
|
|
13149
13476
|
continue;
|
|
13150
13477
|
if (!opts.dryRun)
|
|
13151
|
-
|
|
13478
|
+
fs22.rmSync(dir, { recursive: true, force: true });
|
|
13152
13479
|
result.removed.push(entry.name);
|
|
13153
13480
|
}
|
|
13154
13481
|
}
|
|
@@ -13156,7 +13483,7 @@ function syncOpencodeSkills(opts) {
|
|
|
13156
13483
|
}
|
|
13157
13484
|
function syncShippedOpencodeSkills(opts) {
|
|
13158
13485
|
return syncOpencodeSkills({
|
|
13159
|
-
sourceSkillsDir:
|
|
13486
|
+
sourceSkillsDir: path24.join(opts.pkgRoot, "plugin", "skills"),
|
|
13160
13487
|
skillsRoot: opts.skillsRoot ?? defaultOpencodeSkillsRoot(),
|
|
13161
13488
|
dryRun: opts.dryRun
|
|
13162
13489
|
});
|
|
@@ -13164,8 +13491,8 @@ function syncShippedOpencodeSkills(opts) {
|
|
|
13164
13491
|
|
|
13165
13492
|
// packages/agents/dist/projection/claude.js
|
|
13166
13493
|
import { mkdir as mkdir5, readFile as readFile5, writeFile as writeFile5 } from "fs/promises";
|
|
13167
|
-
import
|
|
13168
|
-
import
|
|
13494
|
+
import path25 from "path";
|
|
13495
|
+
import os13 from "os";
|
|
13169
13496
|
|
|
13170
13497
|
// packages/agents/dist/codex/app-server-client.js
|
|
13171
13498
|
import { EventEmitter } from "events";
|
|
@@ -13175,12 +13502,12 @@ function _parseChunk(acc, chunk) {
|
|
|
13175
13502
|
const out = [];
|
|
13176
13503
|
let idx;
|
|
13177
13504
|
while ((idx = acc.buf.indexOf("\n")) >= 0) {
|
|
13178
|
-
const
|
|
13505
|
+
const line2 = acc.buf.slice(0, idx);
|
|
13179
13506
|
acc.buf = acc.buf.slice(idx + 1);
|
|
13180
|
-
if (!
|
|
13507
|
+
if (!line2.trim())
|
|
13181
13508
|
continue;
|
|
13182
13509
|
try {
|
|
13183
|
-
out.push(JSON.parse(
|
|
13510
|
+
out.push(JSON.parse(line2));
|
|
13184
13511
|
} catch {
|
|
13185
13512
|
}
|
|
13186
13513
|
}
|
|
@@ -13902,9 +14229,9 @@ var OpencodeSseBridge = class {
|
|
|
13902
14229
|
buf += decoder.decode(value, { stream: true });
|
|
13903
14230
|
let nl;
|
|
13904
14231
|
while ((nl = buf.indexOf("\n")) >= 0) {
|
|
13905
|
-
const
|
|
14232
|
+
const line2 = buf.slice(0, nl);
|
|
13906
14233
|
buf = buf.slice(nl + 1);
|
|
13907
|
-
this.handleLine(taskId,
|
|
14234
|
+
this.handleLine(taskId, line2);
|
|
13908
14235
|
}
|
|
13909
14236
|
}
|
|
13910
14237
|
} finally {
|
|
@@ -13915,16 +14242,16 @@ var OpencodeSseBridge = class {
|
|
|
13915
14242
|
}
|
|
13916
14243
|
}
|
|
13917
14244
|
handleLine(taskId, rawLine) {
|
|
13918
|
-
let
|
|
13919
|
-
if (!
|
|
14245
|
+
let line2 = rawLine.trim();
|
|
14246
|
+
if (!line2)
|
|
13920
14247
|
return;
|
|
13921
|
-
if (
|
|
13922
|
-
|
|
13923
|
-
if (!
|
|
14248
|
+
if (line2.startsWith("data:"))
|
|
14249
|
+
line2 = line2.slice(5).trim();
|
|
14250
|
+
if (!line2.startsWith("{"))
|
|
13924
14251
|
return;
|
|
13925
14252
|
let json2;
|
|
13926
14253
|
try {
|
|
13927
|
-
json2 = JSON.parse(
|
|
14254
|
+
json2 = JSON.parse(line2);
|
|
13928
14255
|
} catch {
|
|
13929
14256
|
return;
|
|
13930
14257
|
}
|
|
@@ -14282,13 +14609,13 @@ function buildUserEnvelope(opts) {
|
|
|
14282
14609
|
};
|
|
14283
14610
|
}
|
|
14284
14611
|
function writeLine(socketPath, envelope, deps) {
|
|
14285
|
-
const
|
|
14612
|
+
const line2 = `${JSON.stringify(envelope)}
|
|
14286
14613
|
`;
|
|
14287
|
-
if (Buffer.byteLength(
|
|
14614
|
+
if (Buffer.byteLength(line2, "utf8") > MAX_LINE_BYTES) {
|
|
14288
14615
|
return Promise.resolve({
|
|
14289
14616
|
ok: false,
|
|
14290
14617
|
reason: "transport",
|
|
14291
|
-
error: `line exceeds the receiver's 1 MiB buffer cap (${Buffer.byteLength(
|
|
14618
|
+
error: `line exceeds the receiver's 1 MiB buffer cap (${Buffer.byteLength(line2, "utf8")} bytes)`
|
|
14292
14619
|
});
|
|
14293
14620
|
}
|
|
14294
14621
|
return new Promise((resolve4) => {
|
|
@@ -14308,7 +14635,7 @@ function writeLine(socketPath, envelope, deps) {
|
|
|
14308
14635
|
done({ ok: false, reason: "transport", error: `timeout after ${deps.timeoutMs ?? DEFAULT_TIMEOUT_MS}ms` });
|
|
14309
14636
|
}, deps.timeoutMs ?? DEFAULT_TIMEOUT_MS);
|
|
14310
14637
|
sock.on("connect", () => {
|
|
14311
|
-
sock.write(
|
|
14638
|
+
sock.write(line2, () => {
|
|
14312
14639
|
clearTimeout(timer);
|
|
14313
14640
|
try {
|
|
14314
14641
|
sock.end();
|
|
@@ -14469,20 +14796,20 @@ var ClaudeReceiptListener = class {
|
|
|
14469
14796
|
buf += chunk;
|
|
14470
14797
|
let nl;
|
|
14471
14798
|
while ((nl = buf.indexOf("\n")) !== -1) {
|
|
14472
|
-
const
|
|
14799
|
+
const line2 = buf.slice(0, nl);
|
|
14473
14800
|
buf = buf.slice(nl + 1);
|
|
14474
|
-
this.dispatch(
|
|
14801
|
+
this.dispatch(line2);
|
|
14475
14802
|
}
|
|
14476
14803
|
});
|
|
14477
14804
|
conn.on("error", () => {
|
|
14478
14805
|
});
|
|
14479
14806
|
}
|
|
14480
|
-
dispatch(
|
|
14481
|
-
if (!
|
|
14807
|
+
dispatch(line2) {
|
|
14808
|
+
if (!line2.trim())
|
|
14482
14809
|
return;
|
|
14483
14810
|
let f;
|
|
14484
14811
|
try {
|
|
14485
|
-
f = JSON.parse(
|
|
14812
|
+
f = JSON.parse(line2);
|
|
14486
14813
|
} catch {
|
|
14487
14814
|
this.deps.log?.(`claude-receipt: discarded non-JSON frame`);
|
|
14488
14815
|
return;
|
|
@@ -14509,9 +14836,9 @@ var ClaudeReceiptListener = class {
|
|
|
14509
14836
|
};
|
|
14510
14837
|
|
|
14511
14838
|
// packages/agents/dist/claude/api-key-approval.js
|
|
14512
|
-
import
|
|
14513
|
-
import
|
|
14514
|
-
import
|
|
14839
|
+
import fs23 from "fs";
|
|
14840
|
+
import os14 from "os";
|
|
14841
|
+
import path26 from "path";
|
|
14515
14842
|
|
|
14516
14843
|
// packages/agents/dist/opencode/http-channel.js
|
|
14517
14844
|
init_dist2();
|
|
@@ -14603,10 +14930,10 @@ var OpencodeHttpChannel = class {
|
|
|
14603
14930
|
return cached;
|
|
14604
14931
|
const directory = this.directoryFor?.(taskId);
|
|
14605
14932
|
const createdAfterMs = this.createdAfterFor?.(taskId);
|
|
14606
|
-
for (const
|
|
14933
|
+
for (const path29 of ["/session?", "/api/session?"]) {
|
|
14607
14934
|
let res;
|
|
14608
14935
|
try {
|
|
14609
|
-
res = await this.request(`http://127.0.0.1:${port}${
|
|
14936
|
+
res = await this.request(`http://127.0.0.1:${port}${path29}`, { method: "GET" });
|
|
14610
14937
|
} catch {
|
|
14611
14938
|
return void 0;
|
|
14612
14939
|
}
|
|
@@ -14784,13 +15111,13 @@ function parseDraftFromScreen(screen) {
|
|
|
14784
15111
|
if (topHR === -1)
|
|
14785
15112
|
return null;
|
|
14786
15113
|
const inputLines = lines.slice(topHR + 1, bottomHR);
|
|
14787
|
-
for (const
|
|
15114
|
+
for (const line2 of inputLines) {
|
|
14788
15115
|
let extracted;
|
|
14789
|
-
const boxMatch =
|
|
15116
|
+
const boxMatch = line2.match(/│\s*[>❯]\s+(.*?)\s*│/);
|
|
14790
15117
|
if (boxMatch) {
|
|
14791
15118
|
extracted = boxMatch[1].trim();
|
|
14792
15119
|
} else {
|
|
14793
|
-
const plainMatch =
|
|
15120
|
+
const plainMatch = line2.match(/^\s*[>❯]\s*(.*)$/);
|
|
14794
15121
|
if (plainMatch)
|
|
14795
15122
|
extracted = plainMatch[1].trim();
|
|
14796
15123
|
}
|
|
@@ -14868,8 +15195,8 @@ function readInputBoxRaw(screen, opts) {
|
|
|
14868
15195
|
if (topHR === -1)
|
|
14869
15196
|
return null;
|
|
14870
15197
|
const parts = [];
|
|
14871
|
-
for (const
|
|
14872
|
-
let s =
|
|
15198
|
+
for (const line2 of lines.slice(topHR + 1, bottomHR)) {
|
|
15199
|
+
let s = line2.replace(/│/g, " ");
|
|
14873
15200
|
s = s.replace(/^\s*[>❯]\s?/, "");
|
|
14874
15201
|
s = s.replace(/\s*[▌█▔▎▏]+\s*$/, "");
|
|
14875
15202
|
parts.push(s);
|
|
@@ -15342,9 +15669,9 @@ var NotifierRegistry = class {
|
|
|
15342
15669
|
};
|
|
15343
15670
|
|
|
15344
15671
|
// packages/workspaces/dist/workspaces/obsidian.js
|
|
15345
|
-
import
|
|
15672
|
+
import fs24 from "fs/promises";
|
|
15346
15673
|
import { existsSync as existsSync11 } from "fs";
|
|
15347
|
-
import
|
|
15674
|
+
import path27 from "path";
|
|
15348
15675
|
|
|
15349
15676
|
// packages/workspaces/dist/workspaces/registry.js
|
|
15350
15677
|
init_dist();
|
|
@@ -15442,18 +15769,18 @@ var CmuxEventsBridge = class {
|
|
|
15442
15769
|
this.buf += typeof chunk === "string" ? chunk : chunk.toString("utf-8");
|
|
15443
15770
|
let nl;
|
|
15444
15771
|
while ((nl = this.buf.indexOf("\n")) >= 0) {
|
|
15445
|
-
const
|
|
15772
|
+
const line2 = this.buf.slice(0, nl);
|
|
15446
15773
|
this.buf = this.buf.slice(nl + 1);
|
|
15447
|
-
this.handleLine(
|
|
15774
|
+
this.handleLine(line2);
|
|
15448
15775
|
}
|
|
15449
15776
|
}
|
|
15450
15777
|
handleLine(rawLine) {
|
|
15451
|
-
const
|
|
15452
|
-
if (!
|
|
15778
|
+
const line2 = rawLine.trim();
|
|
15779
|
+
if (!line2 || line2[0] !== "{")
|
|
15453
15780
|
return;
|
|
15454
15781
|
let f;
|
|
15455
15782
|
try {
|
|
15456
|
-
f = JSON.parse(
|
|
15783
|
+
f = JSON.parse(line2);
|
|
15457
15784
|
} catch {
|
|
15458
15785
|
return;
|
|
15459
15786
|
}
|
|
@@ -15894,9 +16221,9 @@ function defaultListFiles(dir) {
|
|
|
15894
16221
|
return [];
|
|
15895
16222
|
}
|
|
15896
16223
|
}
|
|
15897
|
-
function defaultReadFile(
|
|
16224
|
+
function defaultReadFile(path29) {
|
|
15898
16225
|
try {
|
|
15899
|
-
return readFileSync17(
|
|
16226
|
+
return readFileSync17(path29, "utf-8");
|
|
15900
16227
|
} catch {
|
|
15901
16228
|
return void 0;
|
|
15902
16229
|
}
|
|
@@ -16274,16 +16601,16 @@ function extractDetail(sub, payload) {
|
|
|
16274
16601
|
}
|
|
16275
16602
|
return void 0;
|
|
16276
16603
|
}
|
|
16277
|
-
function defaultReadFile2(
|
|
16604
|
+
function defaultReadFile2(path29) {
|
|
16278
16605
|
try {
|
|
16279
|
-
return readFileSync18(
|
|
16606
|
+
return readFileSync18(path29, "utf-8");
|
|
16280
16607
|
} catch {
|
|
16281
16608
|
return void 0;
|
|
16282
16609
|
}
|
|
16283
16610
|
}
|
|
16284
|
-
function defaultWriteFile(
|
|
16285
|
-
mkdirSync8(
|
|
16286
|
-
writeFileSync11(
|
|
16611
|
+
function defaultWriteFile(path29, content) {
|
|
16612
|
+
mkdirSync8(path29.replace(/\/[^/]+$/, ""), { recursive: true });
|
|
16613
|
+
writeFileSync11(path29, content, "utf-8");
|
|
16287
16614
|
}
|
|
16288
16615
|
|
|
16289
16616
|
// packages/workspaces/dist/crew-pane.js
|
|
@@ -16363,9 +16690,9 @@ init_dist();
|
|
|
16363
16690
|
|
|
16364
16691
|
// packages/cli/src/lib/daemon-restart-broadcast.ts
|
|
16365
16692
|
init_dist();
|
|
16366
|
-
import
|
|
16693
|
+
import path28 from "path";
|
|
16367
16694
|
function statePath2(stateRoot) {
|
|
16368
|
-
return
|
|
16695
|
+
return path28.join(stateRoot, "daemon-restart-state.json");
|
|
16369
16696
|
}
|
|
16370
16697
|
function computeRestartSignature(version, buildMtimeMs) {
|
|
16371
16698
|
return `${version}::${buildMtimeMs}`;
|
|
@@ -16414,7 +16741,7 @@ async function maybeBroadcastDaemonRestart(opts) {
|
|
|
16414
16741
|
|
|
16415
16742
|
// packages/cli/src/lib/captain-channel-factory.ts
|
|
16416
16743
|
import { createServer as createServer4, connect as netConnect } from "net";
|
|
16417
|
-
import
|
|
16744
|
+
import fs25 from "fs";
|
|
16418
16745
|
import { join as join26 } from "path";
|
|
16419
16746
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
16420
16747
|
import chalk2 from "chalk";
|
|
@@ -16423,15 +16750,15 @@ var shared;
|
|
|
16423
16750
|
var registryEntryPath = () => join26(CLAUDE_SESSIONS_DIR, `${process.pid}.json`);
|
|
16424
16751
|
function unregisterSenderIdentity() {
|
|
16425
16752
|
try {
|
|
16426
|
-
|
|
16753
|
+
fs25.unlinkSync(registryEntryPath());
|
|
16427
16754
|
} catch {
|
|
16428
16755
|
}
|
|
16429
16756
|
}
|
|
16430
16757
|
function registerSenderIdentity(socketPath) {
|
|
16431
16758
|
try {
|
|
16432
16759
|
unregisterSenderIdentity();
|
|
16433
|
-
|
|
16434
|
-
|
|
16760
|
+
fs25.mkdirSync(CLAUDE_SESSIONS_DIR, { recursive: true });
|
|
16761
|
+
fs25.writeFileSync(
|
|
16435
16762
|
registryEntryPath(),
|
|
16436
16763
|
JSON.stringify({
|
|
16437
16764
|
pid: process.pid,
|
|
@@ -16457,7 +16784,7 @@ async function sharedReceiptListener() {
|
|
|
16457
16784
|
// must never be the reason we refuse to start.
|
|
16458
16785
|
unlinkStale: (p) => {
|
|
16459
16786
|
try {
|
|
16460
|
-
|
|
16787
|
+
fs25.unlinkSync(p);
|
|
16461
16788
|
} catch {
|
|
16462
16789
|
}
|
|
16463
16790
|
},
|
|
@@ -16482,7 +16809,7 @@ async function buildCaptainChannel() {
|
|
|
16482
16809
|
// in /tmp/x registers cwd "/private/tmp/x" on macOS, so cwd matching silently
|
|
16483
16810
|
// missed and every captain ping reported accepted-unconfirmed.
|
|
16484
16811
|
statusFor: (taskId) => readClaudeStatusBySocketPath(captainSocketPath(taskId)),
|
|
16485
|
-
wire: (p, e) => writeLine(p, e, { connect: (
|
|
16812
|
+
wire: (p, e) => writeLine(p, e, { connect: (path29) => netConnect(path29) }),
|
|
16486
16813
|
receipts,
|
|
16487
16814
|
newMsgId: () => randomUUID5(),
|
|
16488
16815
|
sleep: (ms) => new Promise((r) => setTimeout(r, ms)),
|