@sleds/cli 0.1.71 → 0.1.72
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/sleds.mjs +1254 -945
- package/package.json +1 -1
package/dist/sleds.mjs
CHANGED
|
@@ -5878,16 +5878,22 @@ var init_recommend = __esm(() => {
|
|
|
5878
5878
|
var init_profile2 = __esm(() => {
|
|
5879
5879
|
init_profile();
|
|
5880
5880
|
});
|
|
5881
|
+
// ../../packages/shared/src/slack/verification.ts
|
|
5882
|
+
var init_verification = () => {};
|
|
5883
|
+
|
|
5881
5884
|
// ../../packages/shared/src/slack/mention.ts
|
|
5882
|
-
var MENTION_HELP;
|
|
5885
|
+
var HELD_STAGES, MENTION_HELP;
|
|
5883
5886
|
var init_mention = __esm(() => {
|
|
5884
5887
|
init_intake();
|
|
5885
5888
|
init_brief();
|
|
5889
|
+
init_verification();
|
|
5890
|
+
HELD_STAGES = new Set(["on_sled", "verification"]);
|
|
5886
5891
|
MENTION_HELP = [
|
|
5887
5892
|
"Here's what I can do:",
|
|
5888
5893
|
"• *@SLEDS file this*: turn the message above into a request for engineering",
|
|
5889
5894
|
"• *@SLEDS status*: see where something stands",
|
|
5890
|
-
"You can also ask me to *watch* or *mute* a thread, or *run QW-123*."
|
|
5895
|
+
"You can also ask me to *watch* or *mute* a thread, or *run QW-123*.",
|
|
5896
|
+
"When something waits for checking: *pass QW-123*, or *fail QW-123* and what's wrong."
|
|
5891
5897
|
].join(`
|
|
5892
5898
|
`);
|
|
5893
5899
|
});
|
|
@@ -6974,7 +6980,7 @@ var init_sentry = () => {};
|
|
|
6974
6980
|
var init_outside = () => {};
|
|
6975
6981
|
|
|
6976
6982
|
// ../../packages/shared/src/pack/pack.ts
|
|
6977
|
-
var LANDING_GAP_MS;
|
|
6983
|
+
var SIGNED_MOCK_LINE = "- signed mock:", RELATED_MOCK_LINE = "- approved mock on", APPROVED_MOCK_HEADING = "### The approved mock", LANDING_GAP_MS;
|
|
6978
6984
|
var init_pack = __esm(() => {
|
|
6979
6985
|
init_flags();
|
|
6980
6986
|
init_profile();
|
|
@@ -7637,6 +7643,50 @@ var init_say = __esm(() => {
|
|
|
7637
7643
|
];
|
|
7638
7644
|
});
|
|
7639
7645
|
|
|
7646
|
+
// ../../packages/shared/src/route/look.ts
|
|
7647
|
+
function lookComparisonOf(body) {
|
|
7648
|
+
const at = body.indexOf(LOOK_OPEN);
|
|
7649
|
+
if (at < 0)
|
|
7650
|
+
return;
|
|
7651
|
+
const end = body.indexOf(LOOK_CLOSE, at + LOOK_OPEN.length);
|
|
7652
|
+
if (end < 0)
|
|
7653
|
+
return;
|
|
7654
|
+
const block = body.slice(at + LOOK_OPEN.length, end);
|
|
7655
|
+
const differences = [];
|
|
7656
|
+
for (const line of block.split(`
|
|
7657
|
+
`)) {
|
|
7658
|
+
const m = CHECK.exec(line);
|
|
7659
|
+
if (m?.[2])
|
|
7660
|
+
differences.push({ text: m[2], fixed: m[1] !== " " });
|
|
7661
|
+
}
|
|
7662
|
+
return { shots: block.match(IMAGE)?.length ?? 0, differences };
|
|
7663
|
+
}
|
|
7664
|
+
function lookComparisonLines(c) {
|
|
7665
|
+
const open = c.differences.filter((d) => !d.fixed);
|
|
7666
|
+
const fixed = c.differences.length - open.length;
|
|
7667
|
+
const shots = c.shots > 0 ? "The PR sets the preview's screenshots beside the mock." : "The PR's comparison carries no screenshots — check the preview against the mock yourself.";
|
|
7668
|
+
if (c.differences.length === 0)
|
|
7669
|
+
return `${shots} The session found no differences from the mock.`;
|
|
7670
|
+
const listed = open.slice(0, LOOK_LISTED).map((d) => `- ${d.text.slice(0, 140)}`);
|
|
7671
|
+
const more = open.length > LOOK_LISTED ? [`- …and ${open.length - LOOK_LISTED} more`] : [];
|
|
7672
|
+
const head = open.length ? `${open.length} ${open.length === 1 ? "difference" : "differences"} from the mock still open${fixed ? ` (${fixed} fixed)` : ""}:` : `All ${fixed} ${fixed === 1 ? "difference" : "differences"} from the mock are marked fixed.`;
|
|
7673
|
+
return [`${shots} ${head}`, ...listed, ...more].join(`
|
|
7674
|
+
`);
|
|
7675
|
+
}
|
|
7676
|
+
function lookComparisonPrompt(item) {
|
|
7677
|
+
return [
|
|
7678
|
+
`- Before the look, compare what you built to the approved mock — the person looking must not have to eyeball it. Once the draft PR's preview is up (the Vercel check or its bot comment on the PR), screenshot the preview with Playwright (\`pnpm dlx playwright screenshot --full-page --viewport-size "1440,900" <url> preview-<screen>.png\`; \`pnpm dlx playwright install chromium\` first if it has no browser) on each screen the mock shows, at the mock's width. If the preview asks for a sign-in Playwright cannot pass, screenshot the same screens from \`pnpm dev\` and say so in the block.`,
|
|
7679
|
+
`- Put each screenshot (and the mock, when it is an image) on the item with \`sleds attach ${item} --file <shot.png>\`; it prints the link to use in the PR body.`,
|
|
7680
|
+
`- In the PR body, under the header, add one block between \`${LOOK_OPEN}\` and \`${LOOK_CLOSE}\`: a table with the mock and the preview side by side, one row per screen (\`| Mock | Preview |\`, each cell an image), then **Differences from the mock** as a checklist — one \`- [ ]\` line for every difference you see: anything missing, added, moved, resized, restyled, a different colour, copy or data. List what you mean to fix too; check a line (\`- [x]\`) only once a push fixed it, and update the block each time. If you find none after checking each part of the mock, write \`No differences found.\` in place of the checklist. The engine raises the look from this block and lists the open lines to the person.`
|
|
7681
|
+
].join(`
|
|
7682
|
+
`);
|
|
7683
|
+
}
|
|
7684
|
+
var LOOK_OPEN = "<!-- sleds:look -->", LOOK_CLOSE = "<!-- /sleds:look -->", CHECK, IMAGE, LOOK_LISTED = 12;
|
|
7685
|
+
var init_look = __esm(() => {
|
|
7686
|
+
CHECK = /^\s*[-*]\s+\[([ xX])\]\s+(.+?)\s*$/;
|
|
7687
|
+
IMAGE = /!\[[^\]]*\]\([^)\s]+[^)]*\)|<img\s[^>]*src=/gi;
|
|
7688
|
+
});
|
|
7689
|
+
|
|
7640
7690
|
// ../../packages/shared/src/route/engine.ts
|
|
7641
7691
|
function seatSlots(atOnce) {
|
|
7642
7692
|
if (typeof atOnce !== "number" || !Number.isFinite(atOnce))
|
|
@@ -7804,6 +7854,32 @@ function visualSurface(pack) {
|
|
|
7804
7854
|
return pack.split(`
|
|
7805
7855
|
`).filter((l) => /^\s*-\s*(\*\*)?touches(\*\*)?\s*:/i.test(l)).some((l) => VISUAL_PATH.test(l.replace(/^[^:]*:/, " ")));
|
|
7806
7856
|
}
|
|
7857
|
+
function approvedMockIn(pack) {
|
|
7858
|
+
const lines = pack.split(`
|
|
7859
|
+
`).map((l) => l.trim());
|
|
7860
|
+
if (lines.some((l) => l === APPROVED_MOCK_HEADING || l.startsWith(SIGNED_MOCK_LINE)))
|
|
7861
|
+
return { kind: "own" };
|
|
7862
|
+
const related = lines.filter((l) => l.startsWith(RELATED_MOCK_LINE));
|
|
7863
|
+
return related.length ? { kind: "related", lines: related } : null;
|
|
7864
|
+
}
|
|
7865
|
+
function mockLines(visual, pack, parkTool) {
|
|
7866
|
+
const approved = approvedMockIn(pack);
|
|
7867
|
+
const draftRule = `If a person's answer says to draw one, it is a draft, not the design: label it \`${ENGINE_DRAFT_LABEL}\` on the header's Mocks line (\`[${ENGINE_DRAFT_LABEL}](url)\`), in the PR body, and in the artifact's own title and first heading.`;
|
|
7868
|
+
const ask = parkTool ? `park with the SLEDS \`${parkTool}\` tool before you write any code` : "write the question as the last thing you say and stop, before you write any code";
|
|
7869
|
+
const stop = `${ask}: say which screen it changes, that the pack names no approved mock (none signed on this item, its parent, siblings or related items), and offer the options — a link to the approved design to build to, a yes to draw an engine draft for the look, or hold until a mock is signed.`;
|
|
7870
|
+
const compare = visual ? "" : `, and the built preview's screenshots beside it with every difference from the mock as a \`- [ ]\` checklist, between \`${LOOK_OPEN}\` and \`${LOOK_CLOSE}\` (SL-2213)`;
|
|
7871
|
+
if (approved?.kind === "own")
|
|
7872
|
+
return [
|
|
7873
|
+
`- ${visual ? "This node has a visual surface, and" : "If the change turns out to have a visual surface:"} the item has a signed mock (\`The approved mock\` at the top of part 1 of the pack: the pinned copy as signed, and what changed since). Build to it — do not draw your own; where that block says the mock changed since approval, it says what to do. Put its link on the header's Mocks line and say in the PR body "Built to the approved mock: <its name>". ${visual ? "Open the PR as a draft (`gh pr create --draft`) with a screenshot of the built screen beside the mock; a person looks there and marks it ready." : `Open the PR as a draft (\`gh pr create --draft\`) with the mock in its body${compare}.`}`
|
|
7874
|
+
];
|
|
7875
|
+
if (approved?.kind === "related")
|
|
7876
|
+
return [
|
|
7877
|
+
`- ${visual ? "This node has a visual surface, and" : "If the change turns out to have a visual surface:"} no mock is signed on this item, but a related item has an approved one (the \`approved mock on\` line in part 1 of the pack: ${approved.lines.map((l) => `\`${l.slice(RELATED_MOCK_LINE.length).split(":")[0]?.trim()}\``).join(", ")}). If it covers the screen this node changes, build to it — do not draw your own — and say so at the top of the PR body: "Built to <key>'s approved mock: <its link>", with the link on the header's Mocks line. If it does not cover this screen, ${stop} ${draftRule} Open the PR as a draft (\`gh pr create --draft\`) with the mock in its body${compare || " and a screenshot of the built screen"}.`
|
|
7878
|
+
];
|
|
7879
|
+
return [
|
|
7880
|
+
visual ? `- This node has a visual surface and the pack names no approved mock. Before building, ${stop} ${draftRule} The look happens on the PR, not in chat: open it as a draft (\`gh pr create --draft\`) with the mock in its body, and a person looks there and marks it ready.` : `- If the change turns out to have a visual surface, the pack names no approved mock: ${stop} ${draftRule} The look happens on the PR, not in chat: open it as a draft (\`gh pr create --draft\`) with the mock — a screenshot or the artifact link — in its body${compare}.`
|
|
7881
|
+
];
|
|
7882
|
+
}
|
|
7807
7883
|
function packItemLink(pack) {
|
|
7808
7884
|
const at = pack.indexOf(PR_HEADER_OPEN);
|
|
7809
7885
|
if (at < 0)
|
|
@@ -7848,8 +7924,10 @@ function nodePrompt(o) {
|
|
|
7848
7924
|
"- Stay inside this node's scope. Work another node needs goes in the PR description, not in this branch.",
|
|
7849
7925
|
`- End every comment and reply you post on the PR with the line \`${ENGINE_MARK}\`, so the engine knows it is yours and not a reviewer's.`,
|
|
7850
7926
|
"- The approved brief and this route are the go-ahead: a person said yes to them before this session started. Build, commit, push and open the PR; a park is for a question the record does not settle, not for a go-ahead to build or push.",
|
|
7851
|
-
visual
|
|
7927
|
+
...mockLines(visual, claim.pack, o.sledsTools && claim.runId ? toolName("run", o.engineMcp) : null)
|
|
7852
7928
|
];
|
|
7929
|
+
if (visual)
|
|
7930
|
+
lines.push(lookComparisonPrompt(claim.item));
|
|
7853
7931
|
const lookBar = lookBarLine(claim);
|
|
7854
7932
|
if (lookBar)
|
|
7855
7933
|
lines.push(lookBar);
|
|
@@ -7907,16 +7985,22 @@ ${claim.pack.trim()}
|
|
|
7907
7985
|
}
|
|
7908
7986
|
function mockPrompt(o) {
|
|
7909
7987
|
const base = o.base ?? "main";
|
|
7988
|
+
const r = o.revise;
|
|
7989
|
+
const reviseLines = r ? [
|
|
7990
|
+
`- This run revises the item's current mock, \`${r.name}\`: read its HTML at \`${r.path}\` first. Draw its next version, not a new mock — the same screen, the same design tokens and components — and keep everything the brief does not ask to change.`,
|
|
7991
|
+
`- Say what changed from \`${r.name}\` in a short note inside the HTML. Leave \`${r.path}\` as it is: the next version goes only to \`${o.out}\`.`
|
|
7992
|
+
] : [];
|
|
7910
7993
|
const lines = [
|
|
7911
7994
|
`You are drawing a mock for ${o.item} — "${o.title}"${o.engine ? ` — started by ${o.engine}` : ""}. Nobody is at the keyboard: a person signs the mock before the build gets its nodes.`,
|
|
7912
7995
|
"",
|
|
7996
|
+
...reviseLines,
|
|
7913
7997
|
"- Draw one self-contained HTML file: CSS and JS inline, no other files, nothing loaded from the network. Build it from the repo's real design tokens and components (read them in the code: colors, type, spacing, radii) and data shaped like the real thing.",
|
|
7914
7998
|
"- Draw it on the screen the change lives on: find that page or component in this checkout and show it as it is today, with the change in place, so a person can compare it with the product. If the change has no screen of its own, draw the one a person sees it from.",
|
|
7915
7999
|
`- Write the HTML only to \`${o.out}\` — that one file, outside this checkout. Write nothing anywhere else.`,
|
|
7916
8000
|
`- Change no code: this checkout is \`origin/${base}\`, for reading. Do not edit, create or delete a file in it, and make no branch, commit, push or PR. The engine checks: a checkout left changed, or a commit, fails the run and nothing is attached.`,
|
|
7917
8001
|
"- Draw no bar or link back to the item: `/a/` adds the item's bar (its key, title and Open in SLEDS) when it serves the mock.",
|
|
7918
8002
|
"- Ask nobody: a mock run cannot park. Where the brief leaves something open, draw the plainest reading and say it in a short note inside the HTML.",
|
|
7919
|
-
"- Once the file is written, stop. The engine reads it and attaches it to the item as its mock, marked as the next version."
|
|
8003
|
+
r ? `- Once the file is written, stop. The engine reads it and attaches it to the item as the next version of \`${r.name}\`.` : "- Once the file is written, stop. The engine reads it and attaches it to the item as its mock, marked as the next version."
|
|
7920
8004
|
];
|
|
7921
8005
|
return `${lines.join(`
|
|
7922
8006
|
`)}
|
|
@@ -8190,10 +8274,12 @@ function eventPrompt(o) {
|
|
|
8190
8274
|
return reviewPrompt({ ...o, event });
|
|
8191
8275
|
return ciTwicePrompt({ ...o, event });
|
|
8192
8276
|
}
|
|
8193
|
-
var DEFAULT_SEAT = "\x00default", MAX_SEAT_AT_ONCE = 16, HOLD_DEFAULTS, DRAFT_NODE = "draft", MOCK_NODE = "mock", BRANCH_FIELDS, PR_TITLE_FIELDS, ENGINE_MCP_SERVER = "sleds", RUN_TOKEN_ENV = "SLEDS_RUN_TOKEN", NO_RUN_TOKEN = "no run token from SLEDS: this session acts as the seat", SANDBOX_DOMAIN, SANDBOX_DEFAULT_ALLOW, toolName = (name, engineMcp) => engineMcp ? `mcp__${ENGINE_MCP_SERVER}__${name}` : name, ENGINE_MARK = "<!-- sleds:engine -->", VISUAL_PATH, HEADER_ITEM_LINK, APPROACH_SHAPE, AUTONOMY_SAYS, IRREVERSIBLE = "deleting or migrating data in place; deploying outside the playbook's window; anything that leaves the org (a message to a customer, a publish, a release, an email); spend past the band or the allowance; force-pushing or deleting a branch someone else holds; granting or removing access; changing the brief. When in doubt, it is irreversible.", oneLine = (s, max) => s.replace(/\s+/g, " ").trim().slice(0, max), VERDICT_SHAPE, DECIDER_RULES, codes = (xs) => xs.map((x) => `\`${x}\``).join(", "), RESOLVE_MAX_FILES = 8;
|
|
8277
|
+
var DEFAULT_SEAT = "\x00default", MAX_SEAT_AT_ONCE = 16, HOLD_DEFAULTS, DRAFT_NODE = "draft", MOCK_NODE = "mock", BRANCH_FIELDS, PR_TITLE_FIELDS, ENGINE_MCP_SERVER = "sleds", RUN_TOKEN_ENV = "SLEDS_RUN_TOKEN", NO_RUN_TOKEN = "no run token from SLEDS: this session acts as the seat", SANDBOX_DOMAIN, SANDBOX_DEFAULT_ALLOW, toolName = (name, engineMcp) => engineMcp ? `mcp__${ENGINE_MCP_SERVER}__${name}` : name, ENGINE_MARK = "<!-- sleds:engine -->", VISUAL_PATH, ENGINE_DRAFT_LABEL = "Engine draft — not the approved mock", HEADER_ITEM_LINK, APPROACH_SHAPE, AUTONOMY_SAYS, IRREVERSIBLE = "deleting or migrating data in place; deploying outside the playbook's window; anything that leaves the org (a message to a customer, a publish, a release, an email); spend past the band or the allowance; force-pushing or deleting a branch someone else holds; granting or removing access; changing the brief. When in doubt, it is irreversible.", oneLine = (s, max) => s.replace(/\s+/g, " ").trim().slice(0, max), VERDICT_SHAPE, DECIDER_RULES, codes = (xs) => xs.map((x) => `\`${x}\``).join(", "), RESOLVE_MAX_FILES = 8;
|
|
8194
8278
|
var init_engine = __esm(() => {
|
|
8195
8279
|
init_mockBar();
|
|
8280
|
+
init_pack();
|
|
8196
8281
|
init_prHeader();
|
|
8282
|
+
init_look();
|
|
8197
8283
|
init_route();
|
|
8198
8284
|
HOLD_DEFAULTS = {
|
|
8199
8285
|
holdCpu: 85,
|
|
@@ -8857,86 +8943,6 @@ var init_config = __esm(() => {
|
|
|
8857
8943
|
init_settings();
|
|
8858
8944
|
});
|
|
8859
8945
|
|
|
8860
|
-
// src/meter.ts
|
|
8861
|
-
import { createHash } from "node:crypto";
|
|
8862
|
-
import { existsSync as existsSync6, mkdirSync as mkdirSync6, readFileSync as readFileSync6, renameSync as renameSync3, writeFileSync as writeFileSync6 } from "node:fs";
|
|
8863
|
-
import { join as join6 } from "node:path";
|
|
8864
|
-
var METER_CACHE_TTL_MS = 1e4, METER_TIMEOUT_MS = 1500, isObject7 = (v) => typeof v === "object" && v !== null && !Array.isArray(v), num4 = (v) => typeof v === "number" && Number.isFinite(v) ? v : undefined, meterCachePath = (home) => join6(configDir(home), "meter.json"), meterCacheKey = (src) => createHash("sha256").update(`${src.proxyUrl}
|
|
8865
|
-
${src.token}`).digest("hex").slice(0, 16), readMeterCache = (home, now, source) => {
|
|
8866
|
-
const p = meterCachePath(home);
|
|
8867
|
-
if (!existsSync6(p))
|
|
8868
|
-
return null;
|
|
8869
|
-
try {
|
|
8870
|
-
const raw = JSON.parse(readFileSync6(p, "utf8"));
|
|
8871
|
-
if (!isObject7(raw))
|
|
8872
|
-
return null;
|
|
8873
|
-
if (source !== undefined && raw.source !== source)
|
|
8874
|
-
return null;
|
|
8875
|
-
const fetchedAt = num4(raw.fetchedAt);
|
|
8876
|
-
if (fetchedAt === undefined || now - fetchedAt >= METER_CACHE_TTL_MS || fetchedAt > now)
|
|
8877
|
-
return null;
|
|
8878
|
-
return parseMeter(raw.meter);
|
|
8879
|
-
} catch {
|
|
8880
|
-
return null;
|
|
8881
|
-
}
|
|
8882
|
-
}, writeMeterCache = (home, meter, now, source) => {
|
|
8883
|
-
const dir = configDir(home);
|
|
8884
|
-
mkdirSync6(dir, { recursive: true, mode: 448 });
|
|
8885
|
-
const target = meterCachePath(home);
|
|
8886
|
-
const tmp = `${target}.${process.pid}.tmp`;
|
|
8887
|
-
const file = { fetchedAt: now, meter, ...source ? { source } : {} };
|
|
8888
|
-
writeFileSync6(tmp, `${JSON.stringify(file)}
|
|
8889
|
-
`, { mode: 384 });
|
|
8890
|
-
renameSync3(tmp, target);
|
|
8891
|
-
}, fetchMeter = async (o) => {
|
|
8892
|
-
const fetchFn = o.fetchFn ?? fetch;
|
|
8893
|
-
try {
|
|
8894
|
-
const res = await fetchFn(`${o.proxyUrl}/proxy/meter`, {
|
|
8895
|
-
headers: { authorization: `Bearer ${o.token}` },
|
|
8896
|
-
signal: AbortSignal.timeout(o.timeoutMs ?? METER_TIMEOUT_MS)
|
|
8897
|
-
});
|
|
8898
|
-
if (!res.ok)
|
|
8899
|
-
return null;
|
|
8900
|
-
return parseMeter(await res.json());
|
|
8901
|
-
} catch {
|
|
8902
|
-
return null;
|
|
8903
|
-
}
|
|
8904
|
-
}, meterSource = (home, tokenOverride, org) => {
|
|
8905
|
-
const cfg = readConfig(home);
|
|
8906
|
-
const settings = existsSync6(settingsPath(home)) ? readSettings(home) : {};
|
|
8907
|
-
const inSettings = readProxy(settings);
|
|
8908
|
-
const proxyUrl = inSettings?.url ?? cfg.proxyUrl;
|
|
8909
|
-
const picked = selectOrg(cfg, org?.flag, org?.env ?? process.env);
|
|
8910
|
-
if (picked.from === "flag" || picked.from === "env") {
|
|
8911
|
-
const token = tokenOverride ?? picked.seat?.token;
|
|
8912
|
-
return proxyUrl && token ? { proxyUrl, token } : null;
|
|
8913
|
-
}
|
|
8914
|
-
const token = tokenOverride ?? inSettings?.token ?? cfg.token;
|
|
8915
|
-
return proxyUrl && token ? { proxyUrl, token } : null;
|
|
8916
|
-
}, loadMeter = async (o) => {
|
|
8917
|
-
const now = o.now ?? Date.now();
|
|
8918
|
-
const src = meterSource(o.home, undefined, { env: o.env });
|
|
8919
|
-
if (!src)
|
|
8920
|
-
return null;
|
|
8921
|
-
const key = meterCacheKey(src);
|
|
8922
|
-
const cached = readMeterCache(o.home, now, key);
|
|
8923
|
-
if (cached)
|
|
8924
|
-
return cached;
|
|
8925
|
-
const fresh = await fetchMeter({ ...src, fetchFn: o.fetchFn, timeoutMs: o.timeoutMs });
|
|
8926
|
-
if (fresh) {
|
|
8927
|
-
try {
|
|
8928
|
-
writeMeterCache(o.home, fresh, now, key);
|
|
8929
|
-
} catch {}
|
|
8930
|
-
}
|
|
8931
|
-
return fresh;
|
|
8932
|
-
};
|
|
8933
|
-
var init_meter = __esm(() => {
|
|
8934
|
-
init_format();
|
|
8935
|
-
init_config();
|
|
8936
|
-
init_settings();
|
|
8937
|
-
init_format();
|
|
8938
|
-
});
|
|
8939
|
-
|
|
8940
8946
|
// ../../packages/shared/src/index.ts
|
|
8941
8947
|
var init_src = __esm(() => {
|
|
8942
8948
|
init_pricing();
|
|
@@ -8966,6 +8972,7 @@ var init_src = __esm(() => {
|
|
|
8966
8972
|
init_agent();
|
|
8967
8973
|
init_copy();
|
|
8968
8974
|
init_channel();
|
|
8975
|
+
init_verification();
|
|
8969
8976
|
init_productHits();
|
|
8970
8977
|
init_model();
|
|
8971
8978
|
init_parse();
|
|
@@ -9005,6 +9012,7 @@ var init_src = __esm(() => {
|
|
|
9005
9012
|
init_reshape();
|
|
9006
9013
|
init_say();
|
|
9007
9014
|
init_engine();
|
|
9015
|
+
init_look();
|
|
9008
9016
|
init_sources();
|
|
9009
9017
|
init_verdict();
|
|
9010
9018
|
init_seatNeeded();
|
|
@@ -9015,7 +9023,7 @@ var init_src = __esm(() => {
|
|
|
9015
9023
|
});
|
|
9016
9024
|
|
|
9017
9025
|
// src/engine/json.ts
|
|
9018
|
-
var
|
|
9026
|
+
var isObject7 = (v) => typeof v === "object" && v !== null && !Array.isArray(v), str7 = (v) => typeof v === "string" ? v : undefined, num4 = (v) => typeof v === "number" && Number.isFinite(v) ? v : undefined, strings = (v) => Array.isArray(v) ? v.filter((x) => typeof x === "string") : [];
|
|
9019
9027
|
|
|
9020
9028
|
// src/engine/machine.ts
|
|
9021
9029
|
import { cpus as osCpus, loadavg as osLoadavg } from "node:os";
|
|
@@ -9118,7 +9126,7 @@ function machineAllows(sample, atOnce, thresholds = DEFAULT_THRESHOLDS, prev) {
|
|
|
9118
9126
|
};
|
|
9119
9127
|
}
|
|
9120
9128
|
function parseMachineSample(v) {
|
|
9121
|
-
if (!
|
|
9129
|
+
if (!isObject7(v))
|
|
9122
9130
|
return;
|
|
9123
9131
|
const { at, cpuPct, load1, cores, loadPerCore, pressure } = v;
|
|
9124
9132
|
const nums = [at, cpuPct, load1, cores, loadPerCore];
|
|
@@ -9134,7 +9142,7 @@ function parseMachineSample(v) {
|
|
|
9134
9142
|
};
|
|
9135
9143
|
}
|
|
9136
9144
|
function parseMachineHold(v) {
|
|
9137
|
-
if (!
|
|
9145
|
+
if (!isObject7(v) || v.reason !== "machine busy")
|
|
9138
9146
|
return;
|
|
9139
9147
|
if (v.level !== "strained" && v.level !== "busy")
|
|
9140
9148
|
return;
|
|
@@ -9157,36 +9165,36 @@ var init_machine = __esm(() => {
|
|
|
9157
9165
|
|
|
9158
9166
|
// src/engine/state.ts
|
|
9159
9167
|
import {
|
|
9160
|
-
existsSync as
|
|
9168
|
+
existsSync as existsSync6,
|
|
9161
9169
|
linkSync,
|
|
9162
|
-
mkdirSync as
|
|
9163
|
-
readFileSync as
|
|
9164
|
-
renameSync as
|
|
9170
|
+
mkdirSync as mkdirSync6,
|
|
9171
|
+
readFileSync as readFileSync6,
|
|
9172
|
+
renameSync as renameSync3,
|
|
9165
9173
|
rmSync,
|
|
9166
|
-
writeFileSync as
|
|
9174
|
+
writeFileSync as writeFileSync6
|
|
9167
9175
|
} from "node:fs";
|
|
9168
|
-
import { dirname as
|
|
9176
|
+
import { dirname as dirname5, join as join7 } from "node:path";
|
|
9169
9177
|
function engineSlug(engine) {
|
|
9170
9178
|
return slugify(engine.replace(/^engine:/, ""), 80) || "engine";
|
|
9171
9179
|
}
|
|
9172
9180
|
function orgStateDir(stateDir, org) {
|
|
9173
|
-
return org ?
|
|
9181
|
+
return org ? join7(stateDir, "orgs", slugify(org, 80) || "org") : stateDir;
|
|
9174
9182
|
}
|
|
9175
9183
|
function adoptLegacyState(stateDir, org, engine, pidAlive) {
|
|
9176
9184
|
const from = statePath(stateDir, engine);
|
|
9177
9185
|
const to = statePath(orgStateDir(stateDir, org), engine);
|
|
9178
|
-
if (!
|
|
9186
|
+
if (!existsSync6(from) || existsSync6(to))
|
|
9179
9187
|
return false;
|
|
9180
9188
|
const held = readLock(lockPath(stateDir, engine));
|
|
9181
9189
|
if (held && pidAlive(held.pid))
|
|
9182
9190
|
return false;
|
|
9183
|
-
|
|
9184
|
-
|
|
9191
|
+
mkdirSync6(dirname5(to), { recursive: true, mode: 448 });
|
|
9192
|
+
renameSync3(from, to);
|
|
9185
9193
|
return true;
|
|
9186
9194
|
}
|
|
9187
9195
|
function seatStateDir(orgDir, email) {
|
|
9188
9196
|
const slug = email?.trim() ? slugify(email.trim(), 80) : "";
|
|
9189
|
-
return slug ?
|
|
9197
|
+
return slug ? join7(orgDir, "seats", slug) : orgDir;
|
|
9190
9198
|
}
|
|
9191
9199
|
function adoptOrgState(orgDir, email, engine, pidAlive) {
|
|
9192
9200
|
const seatDir = seatStateDir(orgDir, email);
|
|
@@ -9194,23 +9202,23 @@ function adoptOrgState(orgDir, email, engine, pidAlive) {
|
|
|
9194
9202
|
return false;
|
|
9195
9203
|
const from = statePath(orgDir, engine);
|
|
9196
9204
|
const to = statePath(seatDir, engine);
|
|
9197
|
-
if (!
|
|
9205
|
+
if (!existsSync6(from) || existsSync6(to))
|
|
9198
9206
|
return false;
|
|
9199
9207
|
const held = readLock(lockPath(orgDir, engine));
|
|
9200
9208
|
if (held && pidAlive(held.pid))
|
|
9201
9209
|
return false;
|
|
9202
|
-
|
|
9203
|
-
|
|
9210
|
+
mkdirSync6(dirname5(to), { recursive: true, mode: 448 });
|
|
9211
|
+
renameSync3(from, to);
|
|
9204
9212
|
return true;
|
|
9205
9213
|
}
|
|
9206
9214
|
function statePath(stateDir, engine) {
|
|
9207
|
-
return
|
|
9215
|
+
return join7(stateDir, `${engineSlug(engine)}.json`);
|
|
9208
9216
|
}
|
|
9209
9217
|
function lockPath(stateDir, engine) {
|
|
9210
|
-
return
|
|
9218
|
+
return join7(stateDir, `${engineSlug(engine)}.lock`);
|
|
9211
9219
|
}
|
|
9212
9220
|
function parseHandle(handle) {
|
|
9213
|
-
if (!
|
|
9221
|
+
if (!isObject7(handle))
|
|
9214
9222
|
return null;
|
|
9215
9223
|
if (typeof handle.runner !== "string" || typeof handle.id !== "string")
|
|
9216
9224
|
return null;
|
|
@@ -9222,14 +9230,14 @@ function parseHandle(handle) {
|
|
|
9222
9230
|
cwd: handle.cwd,
|
|
9223
9231
|
...typeof handle.log === "string" ? { log: handle.log } : {},
|
|
9224
9232
|
...typeof handle.group === "string" ? { group: handle.group } : {},
|
|
9225
|
-
...
|
|
9233
|
+
...isObject7(handle.own) && typeof handle.own.branch === "string" && typeof handle.own.head === "string" ? { own: { branch: handle.own.branch, head: handle.own.head } } : {}
|
|
9226
9234
|
};
|
|
9227
9235
|
}
|
|
9228
9236
|
function parseDecisionEvent(v) {
|
|
9229
|
-
if (!
|
|
9237
|
+
if (!isObject7(v) || typeof v.node !== "string" || typeof v.pr !== "string")
|
|
9230
9238
|
return null;
|
|
9231
9239
|
if (v.kind === "landed") {
|
|
9232
|
-
const downstream = Array.isArray(v.downstream) ? v.downstream.filter(
|
|
9240
|
+
const downstream = Array.isArray(v.downstream) ? v.downstream.filter(isObject7).flatMap((n) => typeof n.key === "string" ? [
|
|
9233
9241
|
{
|
|
9234
9242
|
key: n.key,
|
|
9235
9243
|
title: typeof n.title === "string" ? n.title : n.key,
|
|
@@ -9293,7 +9301,7 @@ function parseDecisionEvent(v) {
|
|
|
9293
9301
|
return null;
|
|
9294
9302
|
}
|
|
9295
9303
|
function parsePlan(v) {
|
|
9296
|
-
if (!
|
|
9304
|
+
if (!isObject7(v))
|
|
9297
9305
|
return;
|
|
9298
9306
|
const plan = {
|
|
9299
9307
|
...typeof v.approach === "string" ? { approach: v.approach } : {},
|
|
@@ -9304,7 +9312,7 @@ function parsePlan(v) {
|
|
|
9304
9312
|
return Object.keys(plan).length ? plan : undefined;
|
|
9305
9313
|
}
|
|
9306
9314
|
function parseDecision(v) {
|
|
9307
|
-
if (!
|
|
9315
|
+
if (!isObject7(v))
|
|
9308
9316
|
return null;
|
|
9309
9317
|
const { item, node, decisionId, repoPath, cwd } = v;
|
|
9310
9318
|
if (typeof item !== "string" || typeof node !== "string")
|
|
@@ -9314,7 +9322,7 @@ function parseDecision(v) {
|
|
|
9314
9322
|
const event = parseDecisionEvent(v.event);
|
|
9315
9323
|
if (!event)
|
|
9316
9324
|
return null;
|
|
9317
|
-
const a =
|
|
9325
|
+
const a = isObject7(v.answerer) ? v.answerer : null;
|
|
9318
9326
|
const handle = a ? parseHandle(a.handle) : null;
|
|
9319
9327
|
return {
|
|
9320
9328
|
item,
|
|
@@ -9338,7 +9346,7 @@ function parseDecision(v) {
|
|
|
9338
9346
|
};
|
|
9339
9347
|
}
|
|
9340
9348
|
function parseConflicted(v) {
|
|
9341
|
-
if (!
|
|
9349
|
+
if (!isObject7(v) || typeof v.base !== "string" || typeof v.since !== "number")
|
|
9342
9350
|
return;
|
|
9343
9351
|
const at = (k) => typeof v[k] === "number" ? { [k]: v[k] } : {};
|
|
9344
9352
|
return {
|
|
@@ -9353,19 +9361,19 @@ function parseConflicted(v) {
|
|
|
9353
9361
|
};
|
|
9354
9362
|
}
|
|
9355
9363
|
function parseMerged(v) {
|
|
9356
|
-
if (!
|
|
9364
|
+
if (!isObject7(v))
|
|
9357
9365
|
return null;
|
|
9358
9366
|
const { item, node, url, repoPath } = v;
|
|
9359
9367
|
return typeof item === "string" && typeof node === "string" && typeof url === "string" && typeof repoPath === "string" ? { item, node, url, repoPath } : null;
|
|
9360
9368
|
}
|
|
9361
9369
|
function parseParked(v) {
|
|
9362
|
-
if (!
|
|
9370
|
+
if (!isObject7(v) || typeof v.question !== "string" || typeof v.at !== "number")
|
|
9363
9371
|
return;
|
|
9364
9372
|
const a = v.answerer;
|
|
9365
9373
|
let answerer;
|
|
9366
|
-
if (
|
|
9374
|
+
if (isObject7(a) && (a.ended === "answered" || a.ended === "escalated" || a.ended === "none")) {
|
|
9367
9375
|
answerer = { ended: a.ended };
|
|
9368
|
-
} else if (
|
|
9376
|
+
} else if (isObject7(a) && typeof a.decisionId === "string" && typeof a.runId === "string" && typeof a.until === "number") {
|
|
9369
9377
|
const handle = parseHandle(a.handle);
|
|
9370
9378
|
if (handle)
|
|
9371
9379
|
answerer = {
|
|
@@ -9387,7 +9395,7 @@ function parseParked(v) {
|
|
|
9387
9395
|
};
|
|
9388
9396
|
}
|
|
9389
9397
|
function parseRun(v) {
|
|
9390
|
-
if (!
|
|
9398
|
+
if (!isObject7(v))
|
|
9391
9399
|
return null;
|
|
9392
9400
|
const { item, node, title, branch, repoPath, startedAt } = v;
|
|
9393
9401
|
if (typeof item !== "string" || typeof node !== "string")
|
|
@@ -9398,13 +9406,13 @@ function parseRun(v) {
|
|
|
9398
9406
|
if (!handle)
|
|
9399
9407
|
return null;
|
|
9400
9408
|
const parked = parseParked(v.parked);
|
|
9401
|
-
const conflicted =
|
|
9409
|
+
const conflicted = isObject7(v.pr) ? parseConflicted(v.pr.conflicted) : undefined;
|
|
9402
9410
|
return {
|
|
9403
9411
|
item,
|
|
9404
9412
|
node,
|
|
9405
9413
|
title: typeof title === "string" ? title : "",
|
|
9406
9414
|
...v.kind === "draft" || v.kind === "mock" ? { kind: v.kind } : {},
|
|
9407
|
-
...
|
|
9415
|
+
...isObject7(v.mock) && typeof v.mock.out === "string" && typeof v.mock.base === "string" ? {
|
|
9408
9416
|
mock: {
|
|
9409
9417
|
out: v.mock.out,
|
|
9410
9418
|
base: v.mock.base,
|
|
@@ -9417,7 +9425,7 @@ function parseRun(v) {
|
|
|
9417
9425
|
...typeof v.leaseUntil === "number" ? { leaseUntil: v.leaseUntil } : {},
|
|
9418
9426
|
...typeof v.mcpConfig === "string" ? { mcpConfig: v.mcpConfig } : {},
|
|
9419
9427
|
...v.onRunToken === true ? { onRunToken: true } : {},
|
|
9420
|
-
...
|
|
9428
|
+
...isObject7(v.group) && typeof v.group.key === "string" && typeof v.group.title === "string" ? { group: { key: v.group.key, title: v.group.title } } : {},
|
|
9421
9429
|
...typeof v.ticket === "string" ? { ticket: v.ticket } : {},
|
|
9422
9430
|
branch,
|
|
9423
9431
|
repoPath,
|
|
@@ -9428,7 +9436,7 @@ function parseRun(v) {
|
|
|
9428
9436
|
...typeof v.seenTicks === "number" ? { seenTicks: v.seenTicks } : {},
|
|
9429
9437
|
...typeof v.answeredAt === "number" ? { answeredAt: v.answeredAt } : {},
|
|
9430
9438
|
...typeof v.band === "string" ? { band: v.band } : {},
|
|
9431
|
-
...
|
|
9439
|
+
...isObject7(v.permission) && typeof v.permission.decisionId === "string" && typeof v.permission.at === "number" ? {
|
|
9432
9440
|
permission: {
|
|
9433
9441
|
decisionId: v.permission.decisionId,
|
|
9434
9442
|
options: Array.isArray(v.permission.options) ? v.permission.options.filter((x) => typeof x === "string") : [],
|
|
@@ -9441,17 +9449,17 @@ function parseRun(v) {
|
|
|
9441
9449
|
...v.permission.gaveUp === true ? { gaveUp: true } : {}
|
|
9442
9450
|
}
|
|
9443
9451
|
} : {},
|
|
9444
|
-
...
|
|
9445
|
-
...
|
|
9452
|
+
...isObject7(v.provider) && typeof v.provider.why === "string" && typeof v.provider.since === "number" && typeof v.provider.tries === "number" ? { provider: { why: v.provider.why, since: v.provider.since, tries: v.provider.tries } } : {},
|
|
9453
|
+
...isObject7(v.atPrompt) && typeof v.atPrompt.since === "number" && typeof v.atPrompt.text === "string" ? { atPrompt: { since: v.atPrompt.since, text: v.atPrompt.text } } : {},
|
|
9446
9454
|
...parked ? { parked } : {},
|
|
9447
|
-
...
|
|
9455
|
+
...isObject7(v.pr) && typeof v.pr.url === "string" ? {
|
|
9448
9456
|
pr: {
|
|
9449
9457
|
url: v.pr.url,
|
|
9450
9458
|
failing: Array.isArray(v.pr.failing) ? v.pr.failing.filter((x) => typeof x === "string") : [],
|
|
9451
9459
|
feedback: typeof v.pr.feedback === "number" ? v.pr.feedback : 0,
|
|
9452
9460
|
...typeof v.pr.authorFeedback === "number" ? { authorFeedback: v.pr.authorFeedback } : {},
|
|
9453
9461
|
...typeof v.pr.selfNudges === "number" ? { selfNudges: v.pr.selfNudges } : {},
|
|
9454
|
-
...
|
|
9462
|
+
...isObject7(v.pr.feedbackRead) && typeof v.pr.feedbackRead.updatedAt === "string" && typeof v.pr.feedbackRead.all === "number" && typeof v.pr.feedbackRead.author === "number" && typeof v.pr.feedbackRead.at === "number" ? {
|
|
9455
9463
|
feedbackRead: {
|
|
9456
9464
|
updatedAt: v.pr.feedbackRead.updatedAt,
|
|
9457
9465
|
all: v.pr.feedbackRead.all,
|
|
@@ -9467,13 +9475,14 @@ function parseRun(v) {
|
|
|
9467
9475
|
...typeof v.pr.posted === "string" ? { posted: v.pr.posted } : {},
|
|
9468
9476
|
...Array.isArray(v.pr.failedHeads) ? { failedHeads: v.pr.failedHeads.filter((x) => typeof x === "string") } : {},
|
|
9469
9477
|
...typeof v.pr.conflict === "string" ? { conflict: v.pr.conflict } : {},
|
|
9470
|
-
...
|
|
9478
|
+
...isObject7(v.pr.conflictCheck) && typeof v.pr.conflictCheck.head === "string" && typeof v.pr.conflictCheck.at === "number" ? { conflictCheck: { head: v.pr.conflictCheck.head, at: v.pr.conflictCheck.at } } : {},
|
|
9471
9479
|
...typeof v.pr.resolving === "string" ? { resolving: v.pr.resolving } : {},
|
|
9472
9480
|
...conflicted ? { conflicted } : {},
|
|
9473
9481
|
...typeof v.pr.reviewed === "string" ? { reviewed: v.pr.reviewed } : {},
|
|
9474
9482
|
...typeof v.pr.look === "string" ? { look: v.pr.look } : {},
|
|
9483
|
+
...typeof v.pr.lookWait === "number" ? { lookWait: v.pr.lookWait } : {},
|
|
9475
9484
|
...typeof v.pr.instructAt === "number" ? { instructAt: v.pr.instructAt } : {},
|
|
9476
|
-
...
|
|
9485
|
+
...isObject7(v.pr.instructed) && Array.isArray(v.pr.instructed.ids) && (v.pr.instructed.how === "told" || v.pr.instructed.how === "restarted") ? {
|
|
9477
9486
|
instructed: {
|
|
9478
9487
|
ids: v.pr.instructed.ids.filter((x) => typeof x === "string"),
|
|
9479
9488
|
how: v.pr.instructed.how
|
|
@@ -9488,11 +9497,11 @@ function parseRun(v) {
|
|
|
9488
9497
|
function parseState(text) {
|
|
9489
9498
|
try {
|
|
9490
9499
|
const raw = JSON.parse(text);
|
|
9491
|
-
if (!
|
|
9500
|
+
if (!isObject7(raw) || !Array.isArray(raw.runs))
|
|
9492
9501
|
return { runs: [] };
|
|
9493
9502
|
const decisions = Array.isArray(raw.decisions) ? raw.decisions.map(parseDecision).filter((x) => x !== null) : [];
|
|
9494
9503
|
const merged = Array.isArray(raw.merged) ? raw.merged.map(parseMerged).filter((x) => x !== null) : [];
|
|
9495
|
-
const slowStarts =
|
|
9504
|
+
const slowStarts = isObject7(raw.slowStarts) ? Object.fromEntries(Object.entries(raw.slowStarts).filter((e) => typeof e[1] === "number" && e[1] > 0)) : {};
|
|
9496
9505
|
return {
|
|
9497
9506
|
runs: raw.runs.map(parseRun).filter((r) => r !== null),
|
|
9498
9507
|
...decisions.length ? { decisions } : {},
|
|
@@ -9506,14 +9515,14 @@ function parseState(text) {
|
|
|
9506
9515
|
function stateVersion(text) {
|
|
9507
9516
|
try {
|
|
9508
9517
|
const raw = JSON.parse(text);
|
|
9509
|
-
return
|
|
9518
|
+
return isObject7(raw) && typeof raw.v === "number" ? raw.v : 1;
|
|
9510
9519
|
} catch {
|
|
9511
9520
|
return 1;
|
|
9512
9521
|
}
|
|
9513
9522
|
}
|
|
9514
9523
|
function readState(path) {
|
|
9515
9524
|
try {
|
|
9516
|
-
return parseState(
|
|
9525
|
+
return parseState(readFileSync6(path, "utf8"));
|
|
9517
9526
|
} catch {
|
|
9518
9527
|
return { runs: [] };
|
|
9519
9528
|
}
|
|
@@ -9521,7 +9530,7 @@ function readState(path) {
|
|
|
9521
9530
|
function readStateFile(path) {
|
|
9522
9531
|
let text;
|
|
9523
9532
|
try {
|
|
9524
|
-
text =
|
|
9533
|
+
text = readFileSync6(path, "utf8");
|
|
9525
9534
|
} catch {
|
|
9526
9535
|
return { state: { runs: [] } };
|
|
9527
9536
|
}
|
|
@@ -9533,18 +9542,18 @@ function readStateFile(path) {
|
|
|
9533
9542
|
return { state: parseState(text) };
|
|
9534
9543
|
}
|
|
9535
9544
|
function writeState(path, state) {
|
|
9536
|
-
|
|
9545
|
+
mkdirSync6(dirname5(path), { recursive: true, mode: 448 });
|
|
9537
9546
|
const tmp = `${path}.${process.pid}.tmp`;
|
|
9538
|
-
|
|
9547
|
+
writeFileSync6(tmp, `${JSON.stringify({ v: STATE_VERSION, ...state }, null, 2)}
|
|
9539
9548
|
`, {
|
|
9540
9549
|
mode: 384
|
|
9541
9550
|
});
|
|
9542
|
-
|
|
9551
|
+
renameSync3(tmp, path);
|
|
9543
9552
|
}
|
|
9544
9553
|
function parseLock(text) {
|
|
9545
9554
|
try {
|
|
9546
9555
|
const v = JSON.parse(text);
|
|
9547
|
-
if (!
|
|
9556
|
+
if (!isObject7(v))
|
|
9548
9557
|
return null;
|
|
9549
9558
|
const { engine, pid, host, startedAt } = v;
|
|
9550
9559
|
if (typeof engine !== "string" || typeof host !== "string")
|
|
@@ -9555,7 +9564,7 @@ function parseLock(text) {
|
|
|
9555
9564
|
const machine = parseMachineSample(v.machine);
|
|
9556
9565
|
const hold = parseMachineHold(v.hold);
|
|
9557
9566
|
const rh = v.runnerHold;
|
|
9558
|
-
const runnerHold =
|
|
9567
|
+
const runnerHold = isObject7(rh) && typeof rh.why === "string" && rh.why && typeof rh.since === "number" ? { why: rh.why, since: rh.since } : undefined;
|
|
9559
9568
|
return {
|
|
9560
9569
|
v: n(v.v, 1),
|
|
9561
9570
|
engine,
|
|
@@ -9579,24 +9588,24 @@ function parseLock(text) {
|
|
|
9579
9588
|
}
|
|
9580
9589
|
function readLock(path) {
|
|
9581
9590
|
try {
|
|
9582
|
-
return parseLock(
|
|
9591
|
+
return parseLock(readFileSync6(path, "utf8"));
|
|
9583
9592
|
} catch {
|
|
9584
9593
|
return null;
|
|
9585
9594
|
}
|
|
9586
9595
|
}
|
|
9587
9596
|
function writeLock(path, lock) {
|
|
9588
|
-
|
|
9597
|
+
mkdirSync6(dirname5(path), { recursive: true, mode: 448 });
|
|
9589
9598
|
const tmp = `${path}.${process.pid}.tmp`;
|
|
9590
|
-
|
|
9599
|
+
writeFileSync6(tmp, `${JSON.stringify(lock, null, 2)}
|
|
9591
9600
|
`, { mode: 384 });
|
|
9592
|
-
|
|
9601
|
+
renameSync3(tmp, path);
|
|
9593
9602
|
}
|
|
9594
9603
|
function claimLock(path, lock, pidAlive) {
|
|
9595
9604
|
const live = (held) => held !== null && held.host === lock.host && held.pid !== lock.pid && pidAlive(held.pid);
|
|
9596
|
-
|
|
9605
|
+
mkdirSync6(dirname5(path), { recursive: true, mode: 448 });
|
|
9597
9606
|
const tmp = `${path}.${lock.pid}.tmp`;
|
|
9598
9607
|
const aside = `${path}.${lock.pid}.stale`;
|
|
9599
|
-
|
|
9608
|
+
writeFileSync6(tmp, `${JSON.stringify(lock, null, 2)}
|
|
9600
9609
|
`, { mode: 384 });
|
|
9601
9610
|
try {
|
|
9602
9611
|
for (let i = 0;i < 3; i++) {
|
|
@@ -9611,7 +9620,7 @@ function claimLock(path, lock, pidAlive) {
|
|
|
9611
9620
|
if (live(held))
|
|
9612
9621
|
return held;
|
|
9613
9622
|
try {
|
|
9614
|
-
|
|
9623
|
+
renameSync3(path, aside);
|
|
9615
9624
|
} catch (e) {
|
|
9616
9625
|
if (e.code === "ENOENT")
|
|
9617
9626
|
continue;
|
|
@@ -9636,7 +9645,7 @@ function clearLock(path, pid) {
|
|
|
9636
9645
|
rmSync(path, { force: true });
|
|
9637
9646
|
}
|
|
9638
9647
|
function removedEnginesPath(seatDir) {
|
|
9639
|
-
return
|
|
9648
|
+
return join7(seatDir, "removed-engines.json");
|
|
9640
9649
|
}
|
|
9641
9650
|
function parseRemovedEngines(text) {
|
|
9642
9651
|
let raw;
|
|
@@ -9645,10 +9654,10 @@ function parseRemovedEngines(text) {
|
|
|
9645
9654
|
} catch {
|
|
9646
9655
|
return [];
|
|
9647
9656
|
}
|
|
9648
|
-
const list =
|
|
9657
|
+
const list = isObject7(raw) && Array.isArray(raw.engines) ? raw.engines : [];
|
|
9649
9658
|
const out = [];
|
|
9650
9659
|
for (const e of list) {
|
|
9651
|
-
if (!
|
|
9660
|
+
if (!isObject7(e) || typeof e.name !== "string" || !e.name)
|
|
9652
9661
|
continue;
|
|
9653
9662
|
if (!Array.isArray(e.args) || !e.args.every((a) => typeof a === "string"))
|
|
9654
9663
|
continue;
|
|
@@ -9663,7 +9672,7 @@ function parseRemovedEngines(text) {
|
|
|
9663
9672
|
}
|
|
9664
9673
|
function readRemovedEngines(seatDir) {
|
|
9665
9674
|
try {
|
|
9666
|
-
return parseRemovedEngines(
|
|
9675
|
+
return parseRemovedEngines(readFileSync6(removedEnginesPath(seatDir), "utf8"));
|
|
9667
9676
|
} catch {
|
|
9668
9677
|
return [];
|
|
9669
9678
|
}
|
|
@@ -9674,8 +9683,8 @@ function writeRemovedEngines(seatDir, engines) {
|
|
|
9674
9683
|
rmSync(path, { force: true });
|
|
9675
9684
|
return;
|
|
9676
9685
|
}
|
|
9677
|
-
|
|
9678
|
-
|
|
9686
|
+
mkdirSync6(seatDir, { recursive: true, mode: 448 });
|
|
9687
|
+
writeFileSync6(path, `${JSON.stringify({ v: 1, engines }, null, 2)}
|
|
9679
9688
|
`, { mode: 384 });
|
|
9680
9689
|
}
|
|
9681
9690
|
var STATE_VERSION = 1, strs = (v) => Array.isArray(v) ? v.filter((x) => typeof x === "string") : [];
|
|
@@ -9684,6 +9693,86 @@ var init_state = __esm(() => {
|
|
|
9684
9693
|
init_machine();
|
|
9685
9694
|
});
|
|
9686
9695
|
|
|
9696
|
+
// src/meter.ts
|
|
9697
|
+
import { createHash } from "node:crypto";
|
|
9698
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync7, readFileSync as readFileSync7, renameSync as renameSync4, writeFileSync as writeFileSync7 } from "node:fs";
|
|
9699
|
+
import { join as join8 } from "node:path";
|
|
9700
|
+
var METER_CACHE_TTL_MS = 1e4, METER_TIMEOUT_MS = 1500, isObject8 = (v) => typeof v === "object" && v !== null && !Array.isArray(v), num5 = (v) => typeof v === "number" && Number.isFinite(v) ? v : undefined, meterCachePath = (home) => join8(configDir(home), "meter.json"), meterCacheKey = (src) => createHash("sha256").update(`${src.proxyUrl}
|
|
9701
|
+
${src.token}`).digest("hex").slice(0, 16), readMeterCache = (home, now, source) => {
|
|
9702
|
+
const p = meterCachePath(home);
|
|
9703
|
+
if (!existsSync7(p))
|
|
9704
|
+
return null;
|
|
9705
|
+
try {
|
|
9706
|
+
const raw = JSON.parse(readFileSync7(p, "utf8"));
|
|
9707
|
+
if (!isObject8(raw))
|
|
9708
|
+
return null;
|
|
9709
|
+
if (source !== undefined && raw.source !== source)
|
|
9710
|
+
return null;
|
|
9711
|
+
const fetchedAt = num5(raw.fetchedAt);
|
|
9712
|
+
if (fetchedAt === undefined || now - fetchedAt >= METER_CACHE_TTL_MS || fetchedAt > now)
|
|
9713
|
+
return null;
|
|
9714
|
+
return parseMeter(raw.meter);
|
|
9715
|
+
} catch {
|
|
9716
|
+
return null;
|
|
9717
|
+
}
|
|
9718
|
+
}, writeMeterCache = (home, meter, now, source) => {
|
|
9719
|
+
const dir = configDir(home);
|
|
9720
|
+
mkdirSync7(dir, { recursive: true, mode: 448 });
|
|
9721
|
+
const target = meterCachePath(home);
|
|
9722
|
+
const tmp = `${target}.${process.pid}.tmp`;
|
|
9723
|
+
const file = { fetchedAt: now, meter, ...source ? { source } : {} };
|
|
9724
|
+
writeFileSync7(tmp, `${JSON.stringify(file)}
|
|
9725
|
+
`, { mode: 384 });
|
|
9726
|
+
renameSync4(tmp, target);
|
|
9727
|
+
}, fetchMeter = async (o) => {
|
|
9728
|
+
const fetchFn = o.fetchFn ?? fetch;
|
|
9729
|
+
try {
|
|
9730
|
+
const res = await fetchFn(`${o.proxyUrl}/proxy/meter`, {
|
|
9731
|
+
headers: { authorization: `Bearer ${o.token}` },
|
|
9732
|
+
signal: AbortSignal.timeout(o.timeoutMs ?? METER_TIMEOUT_MS)
|
|
9733
|
+
});
|
|
9734
|
+
if (!res.ok)
|
|
9735
|
+
return null;
|
|
9736
|
+
return parseMeter(await res.json());
|
|
9737
|
+
} catch {
|
|
9738
|
+
return null;
|
|
9739
|
+
}
|
|
9740
|
+
}, meterSource = (home, tokenOverride, org) => {
|
|
9741
|
+
const cfg = readConfig(home);
|
|
9742
|
+
const settings = existsSync7(settingsPath(home)) ? readSettings(home) : {};
|
|
9743
|
+
const inSettings = readProxy(settings);
|
|
9744
|
+
const proxyUrl = inSettings?.url ?? cfg.proxyUrl;
|
|
9745
|
+
const picked = selectOrg(cfg, org?.flag, org?.env ?? process.env);
|
|
9746
|
+
if (picked.from === "flag" || picked.from === "env") {
|
|
9747
|
+
const token = tokenOverride ?? picked.seat?.token;
|
|
9748
|
+
return proxyUrl && token ? { proxyUrl, token } : null;
|
|
9749
|
+
}
|
|
9750
|
+
const token = tokenOverride ?? inSettings?.token ?? cfg.token;
|
|
9751
|
+
return proxyUrl && token ? { proxyUrl, token } : null;
|
|
9752
|
+
}, loadMeter = async (o) => {
|
|
9753
|
+
const now = o.now ?? Date.now();
|
|
9754
|
+
const src = meterSource(o.home, undefined, { env: o.env });
|
|
9755
|
+
if (!src)
|
|
9756
|
+
return null;
|
|
9757
|
+
const key = meterCacheKey(src);
|
|
9758
|
+
const cached = readMeterCache(o.home, now, key);
|
|
9759
|
+
if (cached)
|
|
9760
|
+
return cached;
|
|
9761
|
+
const fresh = await fetchMeter({ ...src, fetchFn: o.fetchFn, timeoutMs: o.timeoutMs });
|
|
9762
|
+
if (fresh) {
|
|
9763
|
+
try {
|
|
9764
|
+
writeMeterCache(o.home, fresh, now, key);
|
|
9765
|
+
} catch {}
|
|
9766
|
+
}
|
|
9767
|
+
return fresh;
|
|
9768
|
+
};
|
|
9769
|
+
var init_meter = __esm(() => {
|
|
9770
|
+
init_format();
|
|
9771
|
+
init_config();
|
|
9772
|
+
init_settings();
|
|
9773
|
+
init_format();
|
|
9774
|
+
});
|
|
9775
|
+
|
|
9687
9776
|
// src/seat.ts
|
|
9688
9777
|
var SEAT_POST_MIN_INTERVAL_MS2, readStdin2 = (timeoutMs, stdin = process.stdin) => new Promise((resolve) => {
|
|
9689
9778
|
if (stdin.isTTY) {
|
|
@@ -9748,6 +9837,7 @@ init_mention();
|
|
|
9748
9837
|
init_agent();
|
|
9749
9838
|
init_copy();
|
|
9750
9839
|
init_channel();
|
|
9840
|
+
init_verification();
|
|
9751
9841
|
init_productHits();
|
|
9752
9842
|
init_model();
|
|
9753
9843
|
init_parse();
|
|
@@ -9787,6 +9877,7 @@ init_routeFix();
|
|
|
9787
9877
|
init_reshape();
|
|
9788
9878
|
init_say();
|
|
9789
9879
|
init_engine();
|
|
9880
|
+
init_look();
|
|
9790
9881
|
init_sources();
|
|
9791
9882
|
init_verdict();
|
|
9792
9883
|
init_seatNeeded();
|
|
@@ -10066,339 +10157,10 @@ function runCodex(home, args, deps = {}) {
|
|
|
10066
10157
|
return r.status ?? 1;
|
|
10067
10158
|
}
|
|
10068
10159
|
|
|
10069
|
-
// src/commands/
|
|
10070
|
-
|
|
10160
|
+
// src/commands/attach.ts
|
|
10161
|
+
init_server();
|
|
10071
10162
|
import { readFileSync as readFileSync16, statSync as statSync7 } from "node:fs";
|
|
10072
|
-
import { basename as
|
|
10073
|
-
|
|
10074
|
-
// src/musher.ts
|
|
10075
|
-
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
10076
|
-
import { createPublicKey, verify as cryptoVerify } from "node:crypto";
|
|
10077
|
-
import { basename as basename2, dirname as dirname5, join as join7 } from "node:path";
|
|
10078
|
-
var MUSHER_LABEL = "ai.sleds.musher";
|
|
10079
|
-
var MUSHER_INTERVAL_S = 300;
|
|
10080
|
-
var DEFAULT_PERMISSION_MODE = "acceptEdits";
|
|
10081
|
-
var PERMISSION_MODES = [
|
|
10082
|
-
"acceptEdits",
|
|
10083
|
-
"auto",
|
|
10084
|
-
"bypassPermissions",
|
|
10085
|
-
"default",
|
|
10086
|
-
"dontAsk",
|
|
10087
|
-
"plan"
|
|
10088
|
-
];
|
|
10089
|
-
var DEFAULT_TIMEOUT_MINUTES = 90;
|
|
10090
|
-
var SUMMARY_MAX = 2000;
|
|
10091
|
-
var musherLabel = (env = process.env) => {
|
|
10092
|
-
const sh = env.SLEDS_HOME?.trim();
|
|
10093
|
-
if (!sh)
|
|
10094
|
-
return MUSHER_LABEL;
|
|
10095
|
-
const tag = basename2(sh).replace(/^\.+/, "").replace(/[^A-Za-z0-9_-]+/g, "-") || "seat";
|
|
10096
|
-
return `${MUSHER_LABEL}.${tag}`;
|
|
10097
|
-
};
|
|
10098
|
-
var musherPlistPath = (home, env = process.env) => join7(home, "Library", "LaunchAgents", `${musherLabel(env)}.plist`);
|
|
10099
|
-
var musherLogPath = (configDir) => join7(configDir, "musher.log");
|
|
10100
|
-
var xmlEscape = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
10101
|
-
var musherPath = (home, execPath, currentPath = "") => {
|
|
10102
|
-
const parts = [
|
|
10103
|
-
dirname5(execPath),
|
|
10104
|
-
join7(home, ".sleds", "bin"),
|
|
10105
|
-
join7(home, ".local", "bin"),
|
|
10106
|
-
join7(home, ".bun", "bin"),
|
|
10107
|
-
"/opt/homebrew/bin",
|
|
10108
|
-
"/usr/local/bin",
|
|
10109
|
-
"/usr/bin",
|
|
10110
|
-
"/bin",
|
|
10111
|
-
...currentPath.split(":").filter(Boolean)
|
|
10112
|
-
];
|
|
10113
|
-
return [...new Set(parts)].join(":");
|
|
10114
|
-
};
|
|
10115
|
-
var buildMusherPlist = (o) => {
|
|
10116
|
-
const label = o.label ?? MUSHER_LABEL;
|
|
10117
|
-
const args = [...o.sledsArgv, "musher", "tick"].map((a) => ` <string>${xmlEscape(a)}</string>`).join(`
|
|
10118
|
-
`);
|
|
10119
|
-
const env = Object.entries(o.env).filter(([, v]) => v !== "").map(([k, v]) => ` <key>${xmlEscape(k)}</key>
|
|
10120
|
-
<string>${xmlEscape(v)}</string>`).join(`
|
|
10121
|
-
`);
|
|
10122
|
-
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
10123
|
-
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
10124
|
-
<plist version="1.0">
|
|
10125
|
-
<dict>
|
|
10126
|
-
<key>Label</key>
|
|
10127
|
-
<string>${label}</string>
|
|
10128
|
-
<key>ProgramArguments</key>
|
|
10129
|
-
<array>
|
|
10130
|
-
${args}
|
|
10131
|
-
</array>
|
|
10132
|
-
<key>EnvironmentVariables</key>
|
|
10133
|
-
<dict>
|
|
10134
|
-
${env}
|
|
10135
|
-
</dict>
|
|
10136
|
-
<key>StartInterval</key>
|
|
10137
|
-
<integer>${MUSHER_INTERVAL_S}</integer>
|
|
10138
|
-
<key>RunAtLoad</key>
|
|
10139
|
-
<true/>
|
|
10140
|
-
<key>StandardOutPath</key>
|
|
10141
|
-
<string>${xmlEscape(o.logPath)}</string>
|
|
10142
|
-
<key>StandardErrorPath</key>
|
|
10143
|
-
<string>${xmlEscape(o.logPath)}</string>
|
|
10144
|
-
</dict>
|
|
10145
|
-
</plist>
|
|
10146
|
-
`;
|
|
10147
|
-
};
|
|
10148
|
-
var RESUME_PROMPT = [
|
|
10149
|
-
"SLEDS musher: the usage limit that stopped this session has reset, and the seat's owner",
|
|
10150
|
-
"scheduled this unattended run to continue it. Pick up exactly where the session left off:",
|
|
10151
|
-
"finish the task that was in flight, run the checks you would normally run, follow the repo's",
|
|
10152
|
-
"own conventions for branches and commits, and do not start unrelated work. If you are blocked",
|
|
10153
|
-
"on a decision only the owner can make, stop there and say so. Finish with a summary under",
|
|
10154
|
-
"200 words: what was done, what remains, anything the owner must decide."
|
|
10155
|
-
].join(" ");
|
|
10156
|
-
var NO_SESSION_PROMPT = [
|
|
10157
|
-
"SLEDS musher: a deferred job started on this seat, but no Claude Code session was recorded",
|
|
10158
|
-
"to resume. Do not guess at work. Reply with one line saying so, and stop."
|
|
10159
|
-
].join(" ");
|
|
10160
|
-
var claudeArgs = (o) => [
|
|
10161
|
-
"-p",
|
|
10162
|
-
o.sessionId ? RESUME_PROMPT : NO_SESSION_PROMPT,
|
|
10163
|
-
...o.sessionId ? ["--resume", o.sessionId] : [],
|
|
10164
|
-
...o.model ? ["--model", o.model] : [],
|
|
10165
|
-
"--output-format",
|
|
10166
|
-
"json",
|
|
10167
|
-
"--permission-mode",
|
|
10168
|
-
o.permissionMode
|
|
10169
|
-
];
|
|
10170
|
-
var parseClaudeOutput = (stdout, exitCode) => {
|
|
10171
|
-
const lines = stdout.split(`
|
|
10172
|
-
`).map((l) => l.trim()).filter(Boolean);
|
|
10173
|
-
for (let i = lines.length - 1;i >= 0; i--) {
|
|
10174
|
-
const line = lines[i] ?? "";
|
|
10175
|
-
if (!line.startsWith("{"))
|
|
10176
|
-
continue;
|
|
10177
|
-
try {
|
|
10178
|
-
const j = JSON.parse(line);
|
|
10179
|
-
if (j.type !== "result" && typeof j.result !== "string")
|
|
10180
|
-
continue;
|
|
10181
|
-
const isError = j.is_error === true || typeof j.subtype === "string" && j.subtype !== "success";
|
|
10182
|
-
const text = typeof j.result === "string" ? j.result : "";
|
|
10183
|
-
const models = j.modelUsage;
|
|
10184
|
-
const model = typeof j.model === "string" ? j.model : models && typeof models === "object" ? Object.keys(models)[0] : undefined;
|
|
10185
|
-
return {
|
|
10186
|
-
ok: !isError && exitCode === 0,
|
|
10187
|
-
summary: (text || (isError ? "Claude Code reported an error" : "")).slice(0, SUMMARY_MAX),
|
|
10188
|
-
...typeof j.session_id === "string" ? { sessionId: j.session_id } : {},
|
|
10189
|
-
...model ? { model } : {},
|
|
10190
|
-
...typeof j.duration_ms === "number" ? { durationMs: j.duration_ms } : {},
|
|
10191
|
-
...typeof j.total_cost_usd === "number" ? { costUsd: j.total_cost_usd } : {}
|
|
10192
|
-
};
|
|
10193
|
-
} catch {}
|
|
10194
|
-
}
|
|
10195
|
-
const tail = lines.slice(-5).join(" ").slice(0, SUMMARY_MAX);
|
|
10196
|
-
return { ok: false, summary: tail || `claude exited ${exitCode ?? "without a code"}` };
|
|
10197
|
-
};
|
|
10198
|
-
var defaultExecCapture = (cmd, args, o) => {
|
|
10199
|
-
const r = spawnSync2(cmd, [...args], {
|
|
10200
|
-
cwd: o.cwd,
|
|
10201
|
-
encoding: "utf8",
|
|
10202
|
-
timeout: o.timeoutMs,
|
|
10203
|
-
maxBuffer: 64 * 1024 * 1024,
|
|
10204
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
10205
|
-
env: { ...process.env, SLEDS_MUSHER: "1" }
|
|
10206
|
-
});
|
|
10207
|
-
const timedOut = r.error?.code === "ETIMEDOUT";
|
|
10208
|
-
return {
|
|
10209
|
-
stdout: r.stdout ?? "",
|
|
10210
|
-
stderr: r.stderr ?? "",
|
|
10211
|
-
status: r.status,
|
|
10212
|
-
...timedOut ? { timedOut } : r.error ? { error: r.error.message } : {}
|
|
10213
|
-
};
|
|
10214
|
-
};
|
|
10215
|
-
var musherClient = (o) => {
|
|
10216
|
-
const fetchFn = o.fetchFn ?? fetch;
|
|
10217
|
-
const headers = { authorization: `Bearer ${o.token}`, "content-type": "application/json" };
|
|
10218
|
-
const call = async (path, body) => {
|
|
10219
|
-
try {
|
|
10220
|
-
const res = await fetchFn(`${o.proxyUrl}${path}`, {
|
|
10221
|
-
method: body === undefined ? "GET" : "POST",
|
|
10222
|
-
headers,
|
|
10223
|
-
...body === undefined ? {} : { body: JSON.stringify(body) },
|
|
10224
|
-
signal: AbortSignal.timeout(o.timeoutMs ?? 1e4)
|
|
10225
|
-
});
|
|
10226
|
-
if (!res.ok)
|
|
10227
|
-
return null;
|
|
10228
|
-
return await res.json();
|
|
10229
|
-
} catch {
|
|
10230
|
-
return null;
|
|
10231
|
-
}
|
|
10232
|
-
};
|
|
10233
|
-
return {
|
|
10234
|
-
list: () => call("/proxy/musher"),
|
|
10235
|
-
start: (jobId, local) => call("/proxy/musher/start", { jobId, ...local }),
|
|
10236
|
-
finish: async (input) => await call("/proxy/musher/finish", input) !== null,
|
|
10237
|
-
defer: (input) => call("/proxy/defer", input),
|
|
10238
|
-
attestation: (jobId) => call(`/proxy/attest/${encodeURIComponent(jobId)}`)
|
|
10239
|
-
};
|
|
10240
|
-
};
|
|
10241
|
-
var gitHead = (cwd, exec) => {
|
|
10242
|
-
if (!cwd)
|
|
10243
|
-
return null;
|
|
10244
|
-
const r = exec("git", ["rev-parse", "HEAD"], { cwd, timeoutMs: 5000 });
|
|
10245
|
-
const sha = r.stdout.trim();
|
|
10246
|
-
return r.status === 0 && /^[0-9a-f]{40}$/.test(sha) ? sha : null;
|
|
10247
|
-
};
|
|
10248
|
-
var gitNewCommits = (cwd, before, after, exec) => {
|
|
10249
|
-
if (!cwd || !after || after === before)
|
|
10250
|
-
return [];
|
|
10251
|
-
if (!before)
|
|
10252
|
-
return [after];
|
|
10253
|
-
const r = exec("git", ["rev-list", `${before}..${after}`], { cwd, timeoutMs: 5000 });
|
|
10254
|
-
if (r.status !== 0)
|
|
10255
|
-
return [after];
|
|
10256
|
-
return r.stdout.split(`
|
|
10257
|
-
`).map((l) => l.trim()).filter((l) => /^[0-9a-f]{40}$/.test(l)).slice(0, 40);
|
|
10258
|
-
};
|
|
10259
|
-
var collectOutputs = (commits, summary) => {
|
|
10260
|
-
const out = commits.map((c) => `git:${c}`);
|
|
10261
|
-
for (const m of summary.matchAll(/https:\/\/github\.com\/[\w.-]+\/[\w.-]+\/pull\/\d+/g))
|
|
10262
|
-
if (!out.includes(`pr:${m[0]}`))
|
|
10263
|
-
out.push(`pr:${m[0]}`);
|
|
10264
|
-
return out.slice(0, 50);
|
|
10265
|
-
};
|
|
10266
|
-
var runJob = async (o) => {
|
|
10267
|
-
const log = o.log ?? (() => {});
|
|
10268
|
-
const sessionId = o.job.claudeSessionId ?? o.fallbackSession?.id ?? null;
|
|
10269
|
-
const cwd = o.job.cwd ?? o.fallbackSession?.cwd ?? undefined;
|
|
10270
|
-
const started = await o.client.start(o.job.jobId, {
|
|
10271
|
-
...sessionId ? { claudeSessionId: sessionId } : {},
|
|
10272
|
-
...cwd ? { cwd } : {},
|
|
10273
|
-
host: o.host
|
|
10274
|
-
});
|
|
10275
|
-
if (!started)
|
|
10276
|
-
return { kind: "skipped", reason: "control plane unreachable" };
|
|
10277
|
-
if (!started.ok)
|
|
10278
|
-
return { kind: "skipped", reason: started.reason };
|
|
10279
|
-
const model = o.job.model ?? started.model ?? o.fallbackSession?.model ?? null;
|
|
10280
|
-
const args = claudeArgs({ sessionId, model, permissionMode: o.permissionMode });
|
|
10281
|
-
log(`musher: running job ${o.job.jobId} (${sessionId ? `resume ${sessionId}` : "no session"}${model ? ` · ${model}` : ""}${cwd ? ` · ${cwd}` : ""})`);
|
|
10282
|
-
const exec = o.exec ?? defaultExecCapture;
|
|
10283
|
-
const headBefore = gitHead(cwd, exec);
|
|
10284
|
-
const t0 = Date.now();
|
|
10285
|
-
const r = exec(o.claudePath, args, { cwd, timeoutMs: o.timeoutMs });
|
|
10286
|
-
const durationMs = Date.now() - t0;
|
|
10287
|
-
const result = r.error ? { ok: false, summary: `could not run ${o.claudePath}: ${r.error}` } : parseClaudeOutput(r.stdout, r.status);
|
|
10288
|
-
if (!r.error && (r.timedOut || r.status === null)) {
|
|
10289
|
-
result.ok = false;
|
|
10290
|
-
result.summary = `timed out after ${Math.round(o.timeoutMs / 60000)} min. ${result.summary}`.trim();
|
|
10291
|
-
}
|
|
10292
|
-
const outputs = collectOutputs(gitNewCommits(cwd, headBefore, gitHead(cwd, exec), exec), result.summary);
|
|
10293
|
-
await o.client.finish({
|
|
10294
|
-
jobId: o.job.jobId,
|
|
10295
|
-
runId: started.runId,
|
|
10296
|
-
ok: result.ok,
|
|
10297
|
-
summary: result.summary,
|
|
10298
|
-
...outputs.length ? { outputs } : {},
|
|
10299
|
-
...result.model ?? model ? { model: result.model ?? model } : {},
|
|
10300
|
-
durationMs: result.durationMs ?? durationMs,
|
|
10301
|
-
...result.sessionId ?? sessionId ? { claudeSessionId: result.sessionId ?? sessionId } : {}
|
|
10302
|
-
});
|
|
10303
|
-
log(`musher: job ${o.job.jobId} ${result.ok ? "delivered" : "failed"} in ${Math.round(durationMs / 1000)}s`);
|
|
10304
|
-
return { kind: "ran", ok: result.ok, summary: result.summary, durationMs, outputs };
|
|
10305
|
-
};
|
|
10306
|
-
var verifyAttestation = (payload, sig, publicKeyB64) => {
|
|
10307
|
-
try {
|
|
10308
|
-
const pub = createPublicKey({
|
|
10309
|
-
key: Buffer.from(publicKeyB64, "base64"),
|
|
10310
|
-
format: "der",
|
|
10311
|
-
type: "spki"
|
|
10312
|
-
});
|
|
10313
|
-
const raw = Buffer.from(sig.replace(/-/g, "+").replace(/_/g, "/"), "base64");
|
|
10314
|
-
return cryptoVerify(null, Buffer.from(payload, "utf8"), pub, raw);
|
|
10315
|
-
} catch {
|
|
10316
|
-
return false;
|
|
10317
|
-
}
|
|
10318
|
-
};
|
|
10319
|
-
var parsePayload = (payload) => {
|
|
10320
|
-
const out = {};
|
|
10321
|
-
for (const line of payload.split(`
|
|
10322
|
-
`).slice(1)) {
|
|
10323
|
-
const eq = line.indexOf("=");
|
|
10324
|
-
if (eq > 0)
|
|
10325
|
-
out[line.slice(0, eq)] = line.slice(eq + 1);
|
|
10326
|
-
}
|
|
10327
|
-
return out;
|
|
10328
|
-
};
|
|
10329
|
-
|
|
10330
|
-
// src/switch.ts
|
|
10331
|
-
init_settings();
|
|
10332
|
-
var isObject8 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
10333
|
-
var envOf2 = (settings) => isObject8(settings.env) ? settings.env : {};
|
|
10334
|
-
var capturePriorEnv = (settings) => {
|
|
10335
|
-
const env = envOf2(settings);
|
|
10336
|
-
const prior = { hadEnv: isObject8(settings.env) };
|
|
10337
|
-
const url = env[BASE_URL_KEY];
|
|
10338
|
-
const token = env[AUTH_TOKEN_KEY];
|
|
10339
|
-
if (typeof url === "string")
|
|
10340
|
-
prior[BASE_URL_KEY] = url;
|
|
10341
|
-
if (typeof token === "string")
|
|
10342
|
-
prior[AUTH_TOKEN_KEY] = token;
|
|
10343
|
-
return prior;
|
|
10344
|
-
};
|
|
10345
|
-
var switchOn = (settings, cfg) => applyProxy(settings, cfg);
|
|
10346
|
-
var switchOff = (settings, prior) => {
|
|
10347
|
-
const hadEnv = prior.hadEnv === true;
|
|
10348
|
-
const stripped = removeProxy(settings);
|
|
10349
|
-
const env = { ...envOf2(stripped) };
|
|
10350
|
-
const url = prior[BASE_URL_KEY];
|
|
10351
|
-
const token = prior[AUTH_TOKEN_KEY];
|
|
10352
|
-
if (url !== undefined)
|
|
10353
|
-
env[BASE_URL_KEY] = url;
|
|
10354
|
-
if (token !== undefined)
|
|
10355
|
-
env[AUTH_TOKEN_KEY] = token;
|
|
10356
|
-
if (Object.keys(env).length === 0 && !hadEnv) {
|
|
10357
|
-
const { env: _env, ...rest } = stripped;
|
|
10358
|
-
return rest;
|
|
10359
|
-
}
|
|
10360
|
-
return { ...stripped, env };
|
|
10361
|
-
};
|
|
10362
|
-
var envToRestore = (priors, proxyUrls) => priors.find((p) => p !== undefined && !isSledsProxyEnv({ env: p }, proxyUrls)) ?? {};
|
|
10363
|
-
var RELATIVE = /^\+(?:(\d+)h)?(?:(\d+)m)?$/;
|
|
10364
|
-
var parseUntilReset = (input, nowMs) => {
|
|
10365
|
-
const trimmed = input.trim();
|
|
10366
|
-
const rel = RELATIVE.exec(trimmed);
|
|
10367
|
-
let deadline;
|
|
10368
|
-
if (rel) {
|
|
10369
|
-
const hours = Number(rel[1] ?? 0);
|
|
10370
|
-
const minutes = Number(rel[2] ?? 0);
|
|
10371
|
-
if (hours === 0 && minutes === 0) {
|
|
10372
|
-
throw new Error(`--until-reset: "${input}" is zero; use something like +5h or +90m`);
|
|
10373
|
-
}
|
|
10374
|
-
deadline = nowMs + (hours * 60 + minutes) * 60000;
|
|
10375
|
-
} else {
|
|
10376
|
-
deadline = Date.parse(trimmed);
|
|
10377
|
-
if (Number.isNaN(deadline)) {
|
|
10378
|
-
throw new Error(`--until-reset: "${input}" is not +<n>h[<n>m] or an ISO timestamp`);
|
|
10379
|
-
}
|
|
10380
|
-
}
|
|
10381
|
-
if (deadline <= nowMs) {
|
|
10382
|
-
throw new Error(`--until-reset: ${trimmed} is in the past`);
|
|
10383
|
-
}
|
|
10384
|
-
return deadline;
|
|
10385
|
-
};
|
|
10386
|
-
var formatLocal = (ms, tz) => new Intl.DateTimeFormat("en-US", {
|
|
10387
|
-
month: "short",
|
|
10388
|
-
day: "numeric",
|
|
10389
|
-
hour: "numeric",
|
|
10390
|
-
minute: "2-digit",
|
|
10391
|
-
timeZoneName: "short",
|
|
10392
|
-
...tz ? { timeZone: tz } : {}
|
|
10393
|
-
}).format(new Date(ms));
|
|
10394
|
-
var formatDuration = (ms) => {
|
|
10395
|
-
const total = Math.max(0, Math.round(ms / 60000));
|
|
10396
|
-
const h = Math.floor(total / 60);
|
|
10397
|
-
const m = total % 60;
|
|
10398
|
-
if (h === 0)
|
|
10399
|
-
return `${m}m`;
|
|
10400
|
-
return m === 0 ? `${h}h` : `${h}h ${m}m`;
|
|
10401
|
-
};
|
|
10163
|
+
import { basename as basename6 } from "node:path";
|
|
10402
10164
|
|
|
10403
10165
|
// src/commands/engine.ts
|
|
10404
10166
|
init_src();
|
|
@@ -10415,7 +10177,7 @@ import {
|
|
|
10415
10177
|
writeFileSync as writeFileSync15
|
|
10416
10178
|
} from "node:fs";
|
|
10417
10179
|
import { hostname, tmpdir, userInfo } from "node:os";
|
|
10418
|
-
import { dirname as
|
|
10180
|
+
import { dirname as dirname14, isAbsolute as isAbsolute3, join as join23, resolve as resolve8 } from "node:path";
|
|
10419
10181
|
|
|
10420
10182
|
// src/engine/beat.ts
|
|
10421
10183
|
var BEAT_EVERY_MS = 60000;
|
|
@@ -10427,7 +10189,7 @@ function beatBody(state, flags, host = {}, cap = {}) {
|
|
|
10427
10189
|
name: flags.name,
|
|
10428
10190
|
os: host.os ?? process.platform,
|
|
10429
10191
|
runner: flags.runner,
|
|
10430
|
-
version: host.version ?? "0.1.
|
|
10192
|
+
version: host.version ?? "0.1.72" ?? "dev",
|
|
10431
10193
|
running: live.length,
|
|
10432
10194
|
items: live.slice(0, BEAT_ITEMS).map((r) => `${r.item}/${r.node}`),
|
|
10433
10195
|
...cap.atOnce !== undefined ? { atOnce: cap.atOnce } : {},
|
|
@@ -10487,7 +10249,7 @@ function beater(client, now, everyMs = BEAT_EVERY_MS) {
|
|
|
10487
10249
|
|
|
10488
10250
|
// src/engine/credential.ts
|
|
10489
10251
|
import { homedir } from "node:os";
|
|
10490
|
-
import { join as
|
|
10252
|
+
import { join as join6 } from "node:path";
|
|
10491
10253
|
var API_KEY_VAR = "ANTHROPIC_API_KEY";
|
|
10492
10254
|
var SEAT_TOKEN_VAR = "CLAUDE_CODE_OAUTH_TOKEN";
|
|
10493
10255
|
function namesVar(text, name) {
|
|
@@ -10501,7 +10263,7 @@ function namesVar(text, name) {
|
|
|
10501
10263
|
});
|
|
10502
10264
|
}
|
|
10503
10265
|
function loginPath(env, home = homedir()) {
|
|
10504
|
-
return
|
|
10266
|
+
return join6(env.CLAUDE_CONFIG_DIR?.trim() || join6(home, ".claude"), ".credentials.json");
|
|
10505
10267
|
}
|
|
10506
10268
|
function detectCredential(env, o) {
|
|
10507
10269
|
const file = o.boxEnvText ?? "";
|
|
@@ -10552,7 +10314,7 @@ function clean(v) {
|
|
|
10552
10314
|
return stripControl(v);
|
|
10553
10315
|
if (Array.isArray(v))
|
|
10554
10316
|
return v.map(clean);
|
|
10555
|
-
if (
|
|
10317
|
+
if (isObject7(v))
|
|
10556
10318
|
return Object.fromEntries(Object.entries(v).map(([k, x]) => [k, clean(x)]));
|
|
10557
10319
|
return v;
|
|
10558
10320
|
}
|
|
@@ -10567,18 +10329,18 @@ function routeView(raw, o) {
|
|
|
10567
10329
|
const r = clean(raw);
|
|
10568
10330
|
const width = Math.max(60, o.width ?? 100);
|
|
10569
10331
|
const key = str7(r.key) ?? str7(r.project) ?? "?";
|
|
10570
|
-
const nodes = (Array.isArray(r.nodes) ? r.nodes : []).filter(
|
|
10332
|
+
const nodes = (Array.isArray(r.nodes) ? r.nodes : []).filter(isObject7);
|
|
10571
10333
|
if (nodes.length === 0)
|
|
10572
10334
|
return `${c.bold(key)} has no route — it runs as one node. Draft one with the \`route\` tool, or on the item.`;
|
|
10573
|
-
const states =
|
|
10574
|
-
const runs = (Array.isArray(r.runs) ? r.runs : []).filter(
|
|
10335
|
+
const states = isObject7(r.states) ? r.states : {};
|
|
10336
|
+
const runs = (Array.isArray(r.runs) ? r.runs : []).filter(isObject7);
|
|
10575
10337
|
const stateFor = (n) => str7(states[String(n.key)]) ?? str7(n.state) ?? "pending";
|
|
10576
10338
|
const title = str7(r.title) ?? "";
|
|
10577
10339
|
const line = str7(r.line) ?? "";
|
|
10578
10340
|
const out = [
|
|
10579
10341
|
`${c.bold(key)} ${clip3(title, width - key.length - line.length - 6)} ${c.dim(line)}`
|
|
10580
10342
|
];
|
|
10581
|
-
const open = (Array.isArray(r.blockers) ? r.blockers : []).filter(
|
|
10343
|
+
const open = (Array.isArray(r.blockers) ? r.blockers : []).filter(isObject7).filter((b) => b.landed !== true).map((b) => String(b.key));
|
|
10582
10344
|
if (open.length)
|
|
10583
10345
|
out.push(c.yellow(`waits on ${open.join(", ")} — an item that has not landed`));
|
|
10584
10346
|
const order = waves(nodes.map((n) => ({ key: String(n.key), blockedBy: strings(n.blockedBy) }))) ?? [nodes.map((n) => String(n.key))];
|
|
@@ -10921,6 +10683,7 @@ function parsePrView(stdout) {
|
|
|
10921
10683
|
}
|
|
10922
10684
|
const mergeCommit = typeof o.mergeCommit === "object" && o.mergeCommit !== null ? o.mergeCommit.oid : undefined;
|
|
10923
10685
|
const mock = typeof o.body === "string" ? mockOf(o.body) : undefined;
|
|
10686
|
+
const comparison = typeof o.body === "string" ? lookComparisonOf(o.body) : undefined;
|
|
10924
10687
|
return {
|
|
10925
10688
|
state: o.state,
|
|
10926
10689
|
author: loginOf(o.author),
|
|
@@ -10936,6 +10699,7 @@ function parsePrView(stdout) {
|
|
|
10936
10699
|
autoMerge: typeof o.autoMergeRequest === "object" && o.autoMergeRequest !== null,
|
|
10937
10700
|
queued: false,
|
|
10938
10701
|
...mock ? { mock } : {},
|
|
10702
|
+
...comparison ? { comparison } : {},
|
|
10939
10703
|
...typeof o.headRefOid === "string" && o.headRefOid ? { head: o.headRefOid } : {},
|
|
10940
10704
|
...typeof mergeCommit === "string" && mergeCommit ? { mergeCommit } : {}
|
|
10941
10705
|
};
|
|
@@ -11142,17 +10906,17 @@ function repoOf(summary) {
|
|
|
11142
10906
|
return /\(([^()\s]+)\)\s*$/.exec(summary)?.[1];
|
|
11143
10907
|
}
|
|
11144
10908
|
var categoryOf = (fields) => {
|
|
11145
|
-
if (!
|
|
10909
|
+
if (!isObject7(fields) || !isObject7(fields.status))
|
|
11146
10910
|
return "new";
|
|
11147
10911
|
const cat = fields.status.statusCategory;
|
|
11148
|
-
return
|
|
10912
|
+
return isObject7(cat) && str7(cat.key) || "new";
|
|
11149
10913
|
};
|
|
11150
10914
|
function jiraNode(issue) {
|
|
11151
|
-
const fields =
|
|
10915
|
+
const fields = isObject7(issue.fields) ? issue.fields : {};
|
|
11152
10916
|
const key = String(issue.key);
|
|
11153
10917
|
const summary = str7(fields.summary) ?? key;
|
|
11154
|
-
const links = Array.isArray(fields.issuelinks) ? fields.issuelinks.filter(
|
|
11155
|
-
const blockers = links.filter((l) =>
|
|
10918
|
+
const links = Array.isArray(fields.issuelinks) ? fields.issuelinks.filter(isObject7) : [];
|
|
10919
|
+
const blockers = links.filter((l) => isObject7(l.type) && l.type.name === "Blocks" && isObject7(l.inwardIssue)).map((l) => {
|
|
11156
10920
|
const inward = l.inwardIssue;
|
|
11157
10921
|
return { issue: String(inward.key), category: categoryOf(inward.fields) };
|
|
11158
10922
|
});
|
|
@@ -11191,7 +10955,7 @@ function adfText(doc) {
|
|
|
11191
10955
|
out.push(n);
|
|
11192
10956
|
return;
|
|
11193
10957
|
}
|
|
11194
|
-
if (!
|
|
10958
|
+
if (!isObject7(n))
|
|
11195
10959
|
return;
|
|
11196
10960
|
if (n.type === "text" && typeof n.text === "string")
|
|
11197
10961
|
out.push(n.text);
|
|
@@ -11272,7 +11036,7 @@ function jiraSource(o) {
|
|
|
11272
11036
|
} catch {
|
|
11273
11037
|
json = null;
|
|
11274
11038
|
}
|
|
11275
|
-
return { ok: res.ok, status: res.status, json:
|
|
11039
|
+
return { ok: res.ok, status: res.status, json: isObject7(json) ? json : null };
|
|
11276
11040
|
};
|
|
11277
11041
|
const errorOf = (r) => {
|
|
11278
11042
|
const msgs = Array.isArray(r.json?.errorMessages) ? r.json.errorMessages : [];
|
|
@@ -11289,7 +11053,7 @@ function jiraSource(o) {
|
|
|
11289
11053
|
if (!r.ok)
|
|
11290
11054
|
throw new Error(`Jira: could not read ${epic}'s children — ${errorOf(r)}`);
|
|
11291
11055
|
if (Array.isArray(r.json?.issues))
|
|
11292
|
-
issues.push(...r.json.issues.filter(
|
|
11056
|
+
issues.push(...r.json.issues.filter(isObject7));
|
|
11293
11057
|
token = str7(r.json?.nextPageToken);
|
|
11294
11058
|
if (!token || r.json?.isLast === true)
|
|
11295
11059
|
break;
|
|
@@ -11318,8 +11082,8 @@ function jiraSource(o) {
|
|
|
11318
11082
|
};
|
|
11319
11083
|
const transitionTo = async (issue, category) => {
|
|
11320
11084
|
const t = await call(`/rest/api/3/issue/${issue}/transitions`);
|
|
11321
|
-
const list = Array.isArray(t.json?.transitions) ? t.json.transitions.filter(
|
|
11322
|
-
const hit = list.find((x) =>
|
|
11085
|
+
const list = Array.isArray(t.json?.transitions) ? t.json.transitions.filter(isObject7) : [];
|
|
11086
|
+
const hit = list.find((x) => isObject7(x.to) && categoryOf({ status: x.to }) === category && x.id !== undefined);
|
|
11323
11087
|
if (!hit)
|
|
11324
11088
|
return { ok: false };
|
|
11325
11089
|
const r = await write(issue, "status", "transitions", { transition: { id: String(hit.id) } });
|
|
@@ -11442,12 +11206,12 @@ import {
|
|
|
11442
11206
|
statSync,
|
|
11443
11207
|
writeFileSync as writeFileSync8
|
|
11444
11208
|
} from "node:fs";
|
|
11445
|
-
import { dirname as
|
|
11209
|
+
import { dirname as dirname6, join as join9 } from "node:path";
|
|
11446
11210
|
var SEAT_POST_MIN_DELTA_PCT = 1;
|
|
11447
11211
|
var SEAT_POST_MIN_INTERVAL_MS = 5 * 60000;
|
|
11448
11212
|
var SEAT_POST_TIMEOUT_MS = 1500;
|
|
11449
11213
|
var STDIN_TIMEOUT_MS = 300;
|
|
11450
|
-
var
|
|
11214
|
+
var isObject9 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
11451
11215
|
var num6 = (v) => typeof v === "number" && Number.isFinite(v) ? v : undefined;
|
|
11452
11216
|
var EPOCH_MS_THRESHOLD = 100000000000;
|
|
11453
11217
|
var parseResetsAt = (v) => {
|
|
@@ -11464,7 +11228,7 @@ var parseResetsAt = (v) => {
|
|
|
11464
11228
|
return;
|
|
11465
11229
|
};
|
|
11466
11230
|
var parseBar = (v) => {
|
|
11467
|
-
if (!
|
|
11231
|
+
if (!isObject9(v))
|
|
11468
11232
|
return;
|
|
11469
11233
|
const usedPct = num6(v.used_percentage) ?? num6(v.usedPct);
|
|
11470
11234
|
const resetsAt = parseResetsAt(v.resets_at ?? v.resetsAt);
|
|
@@ -11473,14 +11237,14 @@ var parseBar = (v) => {
|
|
|
11473
11237
|
return { usedPct, resetsAt };
|
|
11474
11238
|
};
|
|
11475
11239
|
var parseSeatWindow = (raw, capturedAt) => {
|
|
11476
|
-
if (!
|
|
11240
|
+
if (!isObject9(raw))
|
|
11477
11241
|
return null;
|
|
11478
|
-
const limits =
|
|
11242
|
+
const limits = isObject9(raw.rate_limits) ? raw.rate_limits : raw;
|
|
11479
11243
|
const fiveHour = parseBar(limits.five_hour ?? limits.fiveHour);
|
|
11480
11244
|
const sevenDay = parseBar(limits.seven_day ?? limits.sevenDay);
|
|
11481
11245
|
const spendLimit = parseBar(limits.spend_limit ?? limits.spendLimit);
|
|
11482
11246
|
const models = {};
|
|
11483
|
-
if (
|
|
11247
|
+
if (isObject9(limits.models))
|
|
11484
11248
|
for (const [k, v] of Object.entries(limits.models)) {
|
|
11485
11249
|
const bar = parseBar(v);
|
|
11486
11250
|
if (bar)
|
|
@@ -11540,11 +11304,11 @@ var formatSeatFragment = (w, now = Date.now()) => {
|
|
|
11540
11304
|
};
|
|
11541
11305
|
var APPROACHING_PCT = 90;
|
|
11542
11306
|
var SEAT_FILE = "seat.json";
|
|
11543
|
-
var legacySeatStatePath = (home) =>
|
|
11307
|
+
var legacySeatStatePath = (home) => join9(configDir(home), SEAT_FILE);
|
|
11544
11308
|
var seatStatePath = (home, key) => {
|
|
11545
11309
|
if (!key?.org?.trim() && !key?.email?.trim())
|
|
11546
11310
|
return legacySeatStatePath(home);
|
|
11547
|
-
return
|
|
11311
|
+
return join9(seatStateDir(orgStateDir(configDir(home), key.org?.trim()), key.email), SEAT_FILE);
|
|
11548
11312
|
};
|
|
11549
11313
|
var seatKeyFor = (home, env = process.env, org) => {
|
|
11550
11314
|
const { slug, seat } = selectOrg(readConfig(home), org, env);
|
|
@@ -11554,16 +11318,16 @@ var allSeatStatePaths = (home) => {
|
|
|
11554
11318
|
const root = configDir(home);
|
|
11555
11319
|
const dirs = (d) => {
|
|
11556
11320
|
try {
|
|
11557
|
-
return readdirSync(d, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) =>
|
|
11321
|
+
return readdirSync(d, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => join9(d, e.name));
|
|
11558
11322
|
} catch {
|
|
11559
11323
|
return [];
|
|
11560
11324
|
}
|
|
11561
11325
|
};
|
|
11562
|
-
const keyed = dirs(
|
|
11563
|
-
|
|
11564
|
-
...dirs(
|
|
11326
|
+
const keyed = dirs(join9(root, "orgs")).flatMap((org) => [
|
|
11327
|
+
join9(org, SEAT_FILE),
|
|
11328
|
+
...dirs(join9(org, "seats")).map((seat) => join9(seat, SEAT_FILE))
|
|
11565
11329
|
]);
|
|
11566
|
-
const noOrg = dirs(
|
|
11330
|
+
const noOrg = dirs(join9(root, "seats")).map((seat) => join9(seat, SEAT_FILE));
|
|
11567
11331
|
return [legacySeatStatePath(home), ...[...keyed, ...noOrg].filter((p) => existsSync8(p))];
|
|
11568
11332
|
};
|
|
11569
11333
|
var adoptLegacySeatState = (home, target) => {
|
|
@@ -11571,12 +11335,12 @@ var adoptLegacySeatState = (home, target) => {
|
|
|
11571
11335
|
if (target === legacy || existsSync8(target) || !existsSync8(legacy))
|
|
11572
11336
|
return;
|
|
11573
11337
|
try {
|
|
11574
|
-
mkdirSync8(
|
|
11338
|
+
mkdirSync8(dirname6(target), { recursive: true, mode: 448 });
|
|
11575
11339
|
renameSync5(legacy, target);
|
|
11576
11340
|
} catch {}
|
|
11577
11341
|
};
|
|
11578
11342
|
var parseWindowStored = (v) => {
|
|
11579
|
-
if (!
|
|
11343
|
+
if (!isObject9(v))
|
|
11580
11344
|
return;
|
|
11581
11345
|
const capturedAt = num6(v.capturedAt);
|
|
11582
11346
|
if (capturedAt === undefined)
|
|
@@ -11584,7 +11348,7 @@ var parseWindowStored = (v) => {
|
|
|
11584
11348
|
return parseSeatWindow(v, capturedAt) ?? undefined;
|
|
11585
11349
|
};
|
|
11586
11350
|
var parseSeatState = (raw) => {
|
|
11587
|
-
if (!
|
|
11351
|
+
if (!isObject9(raw))
|
|
11588
11352
|
return {};
|
|
11589
11353
|
const out = {};
|
|
11590
11354
|
const window = parseWindowStored(raw.window);
|
|
@@ -11593,7 +11357,7 @@ var parseSeatState = (raw) => {
|
|
|
11593
11357
|
const lastPostedAt = num6(raw.lastPostedAt);
|
|
11594
11358
|
if (lastPostedAt !== undefined)
|
|
11595
11359
|
out.lastPostedAt = lastPostedAt;
|
|
11596
|
-
if (
|
|
11360
|
+
if (isObject9(raw.lastPosted)) {
|
|
11597
11361
|
const lp = {};
|
|
11598
11362
|
const f = num6(raw.lastPosted.fiveHour);
|
|
11599
11363
|
const s = num6(raw.lastPosted.sevenDay);
|
|
@@ -11609,11 +11373,11 @@ var parseSeatState = (raw) => {
|
|
|
11609
11373
|
const lastWallResetsAt = num6(raw.lastWallResetsAt);
|
|
11610
11374
|
if (lastWallResetsAt !== undefined)
|
|
11611
11375
|
out.lastWallResetsAt = lastWallResetsAt;
|
|
11612
|
-
if (
|
|
11376
|
+
if (isObject9(raw.warned)) {
|
|
11613
11377
|
const warned = {};
|
|
11614
11378
|
for (const bar of ["fiveHour", "sevenDay", "spendLimit", "credits"]) {
|
|
11615
11379
|
const w = raw.warned[bar];
|
|
11616
|
-
if (!
|
|
11380
|
+
if (!isObject9(w))
|
|
11617
11381
|
continue;
|
|
11618
11382
|
const entry = {};
|
|
11619
11383
|
const ap = num6(w.approaching);
|
|
@@ -11626,11 +11390,11 @@ var parseSeatState = (raw) => {
|
|
|
11626
11390
|
}
|
|
11627
11391
|
out.warned = warned;
|
|
11628
11392
|
}
|
|
11629
|
-
if (
|
|
11393
|
+
if (isObject9(raw.told)) {
|
|
11630
11394
|
const told = {};
|
|
11631
11395
|
for (const bar of ["fiveHour", "sevenDay", "spendLimit", "credits"]) {
|
|
11632
11396
|
const w = raw.told[bar];
|
|
11633
|
-
if (!
|
|
11397
|
+
if (!isObject9(w))
|
|
11634
11398
|
continue;
|
|
11635
11399
|
const entry = {};
|
|
11636
11400
|
const ap = num6(w.approaching);
|
|
@@ -11643,7 +11407,7 @@ var parseSeatState = (raw) => {
|
|
|
11643
11407
|
}
|
|
11644
11408
|
out.told = told;
|
|
11645
11409
|
}
|
|
11646
|
-
if (
|
|
11410
|
+
if (isObject9(raw.transcriptScan) && typeof raw.transcriptScan.path === "string") {
|
|
11647
11411
|
const offset = num6(raw.transcriptScan.offset);
|
|
11648
11412
|
const hitAt = num6(raw.transcriptScan.hitAt);
|
|
11649
11413
|
out.transcriptScan = {
|
|
@@ -11655,9 +11419,9 @@ var parseSeatState = (raw) => {
|
|
|
11655
11419
|
const session = parseSeatSession(raw.session);
|
|
11656
11420
|
if (session)
|
|
11657
11421
|
out.session = session;
|
|
11658
|
-
if (
|
|
11422
|
+
if (isObject9(raw.cockpit) && raw.cockpit.kind === "cmux") {
|
|
11659
11423
|
const c = { kind: "cmux" };
|
|
11660
|
-
if (
|
|
11424
|
+
if (isObject9(raw.cockpit.lines)) {
|
|
11661
11425
|
const lines = {};
|
|
11662
11426
|
for (const [k, v] of Object.entries(raw.cockpit.lines))
|
|
11663
11427
|
if (typeof v === "string")
|
|
@@ -11667,9 +11431,9 @@ var parseSeatState = (raw) => {
|
|
|
11667
11431
|
if (raw.cockpit.progress === true)
|
|
11668
11432
|
c.progress = true;
|
|
11669
11433
|
const f = raw.cockpit.feed;
|
|
11670
|
-
if (
|
|
11434
|
+
if (isObject9(f) && num6(f.at) !== undefined) {
|
|
11671
11435
|
const strs = (v) => Array.isArray(v) ? v.filter((x) => typeof x === "string") : [];
|
|
11672
|
-
const j =
|
|
11436
|
+
const j = isObject9(f.jobs) ? f.jobs : {};
|
|
11673
11437
|
c.feed = {
|
|
11674
11438
|
at: num6(f.at),
|
|
11675
11439
|
handoffs: strs(f.handoffs),
|
|
@@ -11685,7 +11449,7 @@ var parseSeatState = (raw) => {
|
|
|
11685
11449
|
}
|
|
11686
11450
|
out.cockpit = c;
|
|
11687
11451
|
}
|
|
11688
|
-
if (
|
|
11452
|
+
if (isObject9(raw.estimate)) {
|
|
11689
11453
|
const e = raw.estimate;
|
|
11690
11454
|
const project = typeof e.project === "string" ? e.project : undefined;
|
|
11691
11455
|
const [lo, hi, lm, hm, at] = [e.lowUsd, e.highUsd, e.lowMin, e.highMin, e.at].map(num6);
|
|
@@ -11695,7 +11459,7 @@ var parseSeatState = (raw) => {
|
|
|
11695
11459
|
return out;
|
|
11696
11460
|
};
|
|
11697
11461
|
var parseSeatSession = (v) => {
|
|
11698
|
-
if (!
|
|
11462
|
+
if (!isObject9(v) || typeof v.id !== "string" || !v.id)
|
|
11699
11463
|
return;
|
|
11700
11464
|
const at = num6(v.at);
|
|
11701
11465
|
if (at === undefined)
|
|
@@ -11713,12 +11477,12 @@ var seatSessionFromStdin = (text, now) => {
|
|
|
11713
11477
|
return null;
|
|
11714
11478
|
try {
|
|
11715
11479
|
const raw = JSON.parse(trimmed);
|
|
11716
|
-
if (!
|
|
11480
|
+
if (!isObject9(raw) || typeof raw.session_id !== "string" || !raw.session_id)
|
|
11717
11481
|
return null;
|
|
11718
11482
|
const out = { id: raw.session_id, at: now };
|
|
11719
11483
|
if (typeof raw.cwd === "string" && raw.cwd)
|
|
11720
11484
|
out.cwd = raw.cwd;
|
|
11721
|
-
const model =
|
|
11485
|
+
const model = isObject9(raw.model) ? raw.model.id : raw.model;
|
|
11722
11486
|
if (typeof model === "string" && model)
|
|
11723
11487
|
out.model = model;
|
|
11724
11488
|
return out;
|
|
@@ -11752,7 +11516,7 @@ var readSeatState = (home, key) => {
|
|
|
11752
11516
|
};
|
|
11753
11517
|
var writeSeatState = (home, state, key) => {
|
|
11754
11518
|
const target = seatStatePath(home, key);
|
|
11755
|
-
mkdirSync8(
|
|
11519
|
+
mkdirSync8(dirname6(target), { recursive: true, mode: 448 });
|
|
11756
11520
|
const tmp = `${target}.${process.pid}.tmp`;
|
|
11757
11521
|
writeFileSync8(tmp, `${JSON.stringify(state)}
|
|
11758
11522
|
`, { mode: 384 });
|
|
@@ -11828,7 +11592,7 @@ var entryText = (v) => {
|
|
|
11828
11592
|
return v;
|
|
11829
11593
|
if (!Array.isArray(v))
|
|
11830
11594
|
return "";
|
|
11831
|
-
return v.map((b) =>
|
|
11595
|
+
return v.map((b) => isObject9(b) && b.type === "text" && typeof b.text === "string" ? b.text : "").join(`
|
|
11832
11596
|
`);
|
|
11833
11597
|
};
|
|
11834
11598
|
var isCreditsLine = (line) => {
|
|
@@ -11840,9 +11604,9 @@ var isCreditsLine = (line) => {
|
|
|
11840
11604
|
} catch {
|
|
11841
11605
|
return false;
|
|
11842
11606
|
}
|
|
11843
|
-
if (!
|
|
11607
|
+
if (!isObject9(raw))
|
|
11844
11608
|
return false;
|
|
11845
|
-
const message =
|
|
11609
|
+
const message = isObject9(raw.message) ? raw.message : undefined;
|
|
11846
11610
|
const texts = raw.type === "system" ? [entryText(raw.content), entryText(raw.text)] : raw.type === "assistant" && raw.isApiErrorMessage === true ? [entryText(message?.content)] : [];
|
|
11847
11611
|
return texts.some((t) => CREDITS_LINE.test(t));
|
|
11848
11612
|
};
|
|
@@ -11851,7 +11615,7 @@ var creditsHitIn = (text) => text.split(`
|
|
|
11851
11615
|
var transcriptPathFromStdin = (text) => {
|
|
11852
11616
|
try {
|
|
11853
11617
|
const raw = JSON.parse(text.trim());
|
|
11854
|
-
return
|
|
11618
|
+
return isObject9(raw) && typeof raw.transcript_path === "string" && raw.transcript_path ? raw.transcript_path : null;
|
|
11855
11619
|
} catch {
|
|
11856
11620
|
return null;
|
|
11857
11621
|
}
|
|
@@ -11943,11 +11707,11 @@ var readStdin = (timeoutMs, stdin = process.stdin) => new Promise((resolve) => {
|
|
|
11943
11707
|
init_config();
|
|
11944
11708
|
init_meter();
|
|
11945
11709
|
var HOOK_STDIN_TIMEOUT_MS = 1000;
|
|
11946
|
-
var
|
|
11710
|
+
var isObject10 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
11947
11711
|
var notificationType = (text) => {
|
|
11948
11712
|
try {
|
|
11949
11713
|
const raw = JSON.parse(text);
|
|
11950
|
-
if (!
|
|
11714
|
+
if (!isObject10(raw))
|
|
11951
11715
|
return;
|
|
11952
11716
|
return typeof raw.notification_type === "string" ? raw.notification_type : undefined;
|
|
11953
11717
|
} catch {
|
|
@@ -11956,7 +11720,7 @@ var notificationType = (text) => {
|
|
|
11956
11720
|
};
|
|
11957
11721
|
|
|
11958
11722
|
// src/commands/permissionEvent.ts
|
|
11959
|
-
var
|
|
11723
|
+
var isObject11 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
11960
11724
|
var NOT_A_TOOL = new Set(["askuserquestion", "exitplanmode", "enterplanmode"]);
|
|
11961
11725
|
var isToolPermission = (message) => {
|
|
11962
11726
|
const tool = /permission to use\s+(.+?)\.?\s*$/i.exec(message)?.[1];
|
|
@@ -11965,7 +11729,7 @@ var isToolPermission = (message) => {
|
|
|
11965
11729
|
var readPermissionMark = (file) => {
|
|
11966
11730
|
try {
|
|
11967
11731
|
const raw = JSON.parse(readFileSync9(file, "utf8"));
|
|
11968
|
-
if (!
|
|
11732
|
+
if (!isObject11(raw) || typeof raw.at !== "number")
|
|
11969
11733
|
return null;
|
|
11970
11734
|
return { message: typeof raw.message === "string" ? raw.message : "", at: raw.at };
|
|
11971
11735
|
} catch {
|
|
@@ -11977,9 +11741,9 @@ var clearPermissionMark = (file) => {
|
|
|
11977
11741
|
};
|
|
11978
11742
|
|
|
11979
11743
|
// src/runners/exec.ts
|
|
11980
|
-
import { spawn, spawnSync as
|
|
11744
|
+
import { spawn, spawnSync as spawnSync2 } from "node:child_process";
|
|
11981
11745
|
import { closeSync as closeSync2, fstatSync, openSync as openSync2, readSync as readSync2 } from "node:fs";
|
|
11982
|
-
import { basename as
|
|
11746
|
+
import { basename as basename2, dirname as dirname7, join as join10 } from "node:path";
|
|
11983
11747
|
|
|
11984
11748
|
// src/runners/sandbox.ts
|
|
11985
11749
|
var absRule = (dir) => `/${dir.replace(/\/+$/, "")}/**`;
|
|
@@ -12068,7 +11832,7 @@ var logTimeouts = (exec, log) => (cmd, args, o) => {
|
|
|
12068
11832
|
};
|
|
12069
11833
|
var defaultExec = (cmd, args, o) => {
|
|
12070
11834
|
const timeoutMs = o?.timeoutMs ?? EXEC_TIMEOUT_MS;
|
|
12071
|
-
const r =
|
|
11835
|
+
const r = spawnSync2(cmd, [...args], {
|
|
12072
11836
|
cwd: o?.cwd,
|
|
12073
11837
|
input: o?.input,
|
|
12074
11838
|
env: o?.env ? { ...process.env, ...o.env } : undefined,
|
|
@@ -12156,8 +11920,8 @@ var readLogTail = (path) => {
|
|
|
12156
11920
|
}
|
|
12157
11921
|
};
|
|
12158
11922
|
var logPathFor = (promptFile, ext, dir) => {
|
|
12159
|
-
const base =
|
|
12160
|
-
return
|
|
11923
|
+
const base = basename2(promptFile).replace(/\.md$/i, "");
|
|
11924
|
+
return join10(dir ?? dirname7(promptFile), `${base}.${ext}`);
|
|
12161
11925
|
};
|
|
12162
11926
|
var tailText = (s, bytes = 4096) => {
|
|
12163
11927
|
if (s.length <= bytes)
|
|
@@ -12208,9 +11972,9 @@ function eventOpenOf(j) {
|
|
|
12208
11972
|
var answerNode = (node) => `${node}-answer`;
|
|
12209
11973
|
var AUTONOMIES = ["ask", "decide_and_flag", "decide"];
|
|
12210
11974
|
function loggedDecision(d) {
|
|
12211
|
-
if (!
|
|
11975
|
+
if (!isObject7(d) || d.state !== "answered" || !isObject7(d.answer))
|
|
12212
11976
|
return null;
|
|
12213
|
-
const q =
|
|
11977
|
+
const q = isObject7(d.question) ? str7(d.question.md) : undefined;
|
|
12214
11978
|
const md = str7(d.answer.md);
|
|
12215
11979
|
if (!q || !md)
|
|
12216
11980
|
return null;
|
|
@@ -12344,30 +12108,30 @@ function mocksOf(s) {
|
|
|
12344
12108
|
return m && typeof m.finishMock === "function" && typeof m.failMock === "function" ? s : null;
|
|
12345
12109
|
}
|
|
12346
12110
|
function mockRunOf(row) {
|
|
12347
|
-
const m =
|
|
12348
|
-
return { asked:
|
|
12111
|
+
const m = isObject7(row.mockRun) ? row.mockRun : {};
|
|
12112
|
+
return { asked: isObject7(m.asked), running: isObject7(m.running) };
|
|
12349
12113
|
}
|
|
12350
12114
|
function askedMocks(r) {
|
|
12351
|
-
const mine = Array.isArray(r.mine) ? r.mine.filter(
|
|
12115
|
+
const mine = Array.isArray(r.mine) ? r.mine.filter(isObject7) : [];
|
|
12352
12116
|
return mine.filter((row) => {
|
|
12353
12117
|
const m = mockRunOf(row);
|
|
12354
12118
|
return m.asked && !m.running;
|
|
12355
12119
|
});
|
|
12356
12120
|
}
|
|
12357
12121
|
function mockBandText(b) {
|
|
12358
|
-
const lo =
|
|
12359
|
-
const hi =
|
|
12122
|
+
const lo = num4(b.lowMin);
|
|
12123
|
+
const hi = num4(b.highMin);
|
|
12360
12124
|
return lo !== undefined && hi !== undefined ? `${lo}–${hi} min` : undefined;
|
|
12361
12125
|
}
|
|
12362
12126
|
function instructionsFrom(waiting) {
|
|
12363
12127
|
if (!Array.isArray(waiting))
|
|
12364
12128
|
return [];
|
|
12365
|
-
return waiting.filter(
|
|
12129
|
+
return waiting.filter(isObject7).flatMap((w) => {
|
|
12366
12130
|
const id = str7(w.id);
|
|
12367
12131
|
const md = str7(w.md);
|
|
12368
12132
|
if (!id || !md)
|
|
12369
12133
|
return [];
|
|
12370
|
-
const f =
|
|
12134
|
+
const f = isObject7(w.finding) ? w.finding : null;
|
|
12371
12135
|
const kind = f?.kind === "review" || f?.kind === "bot" ? f.kind : null;
|
|
12372
12136
|
const url = f ? str7(f.url) : undefined;
|
|
12373
12137
|
const by = f ? str7(f.by) : undefined;
|
|
@@ -12391,11 +12155,11 @@ function statesLanded(states) {
|
|
|
12391
12155
|
return all.length > 0 && all.every((s) => s === "landed" || s === "skipped") && all.some((s) => s === "landed");
|
|
12392
12156
|
}
|
|
12393
12157
|
function armedTerms(armed) {
|
|
12394
|
-
if (!
|
|
12158
|
+
if (!isObject7(armed))
|
|
12395
12159
|
return { seatIds: [] };
|
|
12396
|
-
const atOnce =
|
|
12160
|
+
const atOnce = num4(armed.atOnce);
|
|
12397
12161
|
const runner = str7(armed.runner);
|
|
12398
|
-
const seatAtOnce = Array.isArray(armed.seatAtOnce) ? armed.seatAtOnce.map((x) =>
|
|
12162
|
+
const seatAtOnce = Array.isArray(armed.seatAtOnce) ? armed.seatAtOnce.map((x) => num4(x) ?? 1) : undefined;
|
|
12399
12163
|
return {
|
|
12400
12164
|
...atOnce !== undefined ? { atOnce } : {},
|
|
12401
12165
|
seatIds: strings(armed.seatIds),
|
|
@@ -12447,10 +12211,10 @@ async function readOrSay(client, path, what) {
|
|
|
12447
12211
|
function routeItem(q, r) {
|
|
12448
12212
|
if (!r || r.ok === false)
|
|
12449
12213
|
throw new Error(`${q}: not found on SLEDS, or ${UNREACHABLE3} — check the key and the token`);
|
|
12450
|
-
const nodes = Array.isArray(r.nodes) ? r.nodes.filter(
|
|
12214
|
+
const nodes = Array.isArray(r.nodes) ? r.nodes.filter(isObject7) : [];
|
|
12451
12215
|
if (nodes.length === 0)
|
|
12452
12216
|
throw new Error(`${q} has no route — draft one with the \`route\` tool first`);
|
|
12453
|
-
const states =
|
|
12217
|
+
const states = isObject7(r.states) ? r.states : {};
|
|
12454
12218
|
const found = nodes.filter((n) => n.state === "running").map((n) => String(n.key));
|
|
12455
12219
|
const running = found.length > 0 ? found : keysIn(states, "running");
|
|
12456
12220
|
const held = heldOf(r, running);
|
|
@@ -12464,12 +12228,12 @@ function routeItem(q, r) {
|
|
|
12464
12228
|
};
|
|
12465
12229
|
}
|
|
12466
12230
|
function heldOf(r, running) {
|
|
12467
|
-
const runs = Array.isArray(r?.runs) ? r.runs.filter(
|
|
12231
|
+
const runs = Array.isArray(r?.runs) ? r.runs.filter(isObject7) : [];
|
|
12468
12232
|
return runs.flatMap((x) => {
|
|
12469
12233
|
const node = str7(x.node);
|
|
12470
12234
|
const runId = str7(x.runId);
|
|
12471
12235
|
const engine = str7(x.engine);
|
|
12472
|
-
const startedAt =
|
|
12236
|
+
const startedAt = num4(x.startedAt);
|
|
12473
12237
|
if (!node || !running.includes(node) || !runId || !engine || startedAt === undefined)
|
|
12474
12238
|
return [];
|
|
12475
12239
|
return [{ node, runId, engine, startedAt }];
|
|
@@ -12478,7 +12242,7 @@ function heldOf(r, running) {
|
|
|
12478
12242
|
function groupOf(j, item) {
|
|
12479
12243
|
if (!j || j.ok === false)
|
|
12480
12244
|
return null;
|
|
12481
|
-
const parent =
|
|
12245
|
+
const parent = isObject7(j.parent) ? j.parent : null;
|
|
12482
12246
|
const parentKey = str7(parent?.key)?.trim();
|
|
12483
12247
|
if (parent && parentKey)
|
|
12484
12248
|
return { key: parentKey, title: str7(parent.title) ?? parentKey };
|
|
@@ -12489,7 +12253,7 @@ function groupOf(j, item) {
|
|
|
12489
12253
|
function runOf(v) {
|
|
12490
12254
|
if (!Array.isArray(v))
|
|
12491
12255
|
return;
|
|
12492
|
-
return v.filter(
|
|
12256
|
+
return v.filter(isObject7).flatMap((x) => {
|
|
12493
12257
|
const repo = str7(x.repo)?.trim();
|
|
12494
12258
|
if (!repo)
|
|
12495
12259
|
return [];
|
|
@@ -12503,21 +12267,21 @@ function sameEngine(a, b) {
|
|
|
12503
12267
|
return bare(a) === bare(b);
|
|
12504
12268
|
}
|
|
12505
12269
|
function armedFor(armed, engine) {
|
|
12506
|
-
if (!
|
|
12270
|
+
if (!isObject7(armed))
|
|
12507
12271
|
return false;
|
|
12508
12272
|
const where = str7(armed.engine);
|
|
12509
12273
|
return !engine || !where?.trim() || sameEngine(where, engine);
|
|
12510
12274
|
}
|
|
12511
12275
|
function sledItems(r, armedOnly, engine) {
|
|
12512
|
-
const mine = Array.isArray(r.mine) ? r.mine.filter(
|
|
12276
|
+
const mine = Array.isArray(r.mine) ? r.mine.filter(isObject7) : [];
|
|
12513
12277
|
const out = [];
|
|
12514
12278
|
for (const row of mine) {
|
|
12515
12279
|
const route = row.route;
|
|
12516
|
-
if (!
|
|
12280
|
+
if (!isObject7(route))
|
|
12517
12281
|
continue;
|
|
12518
12282
|
if (armedOnly && !armedFor(route.armed, engine))
|
|
12519
12283
|
continue;
|
|
12520
|
-
const states =
|
|
12284
|
+
const states = isObject7(route.states) ? route.states : {};
|
|
12521
12285
|
out.push({
|
|
12522
12286
|
item: str7(row.key) ?? String(row.project),
|
|
12523
12287
|
ready: strings(route.ready),
|
|
@@ -12551,10 +12315,10 @@ var PROFILE_TEXT = [
|
|
|
12551
12315
|
];
|
|
12552
12316
|
var SHELL_TEXT = ["agent", "launcher", "mode"];
|
|
12553
12317
|
function profileOf(r) {
|
|
12554
|
-
if (!r || r.ok === false || !
|
|
12318
|
+
if (!r || r.ok === false || !isObject7(r.profile))
|
|
12555
12319
|
return null;
|
|
12556
12320
|
const p = r.profile;
|
|
12557
|
-
const member =
|
|
12321
|
+
const member = isObject7(r.member) ? r.member : {};
|
|
12558
12322
|
const out = {
|
|
12559
12323
|
pickup: p.pickup === "auto" && member.pickup === "auto" ? "auto" : "approve",
|
|
12560
12324
|
...HOLD_DEFAULTS2,
|
|
@@ -12577,23 +12341,23 @@ function profileOf(r) {
|
|
|
12577
12341
|
}
|
|
12578
12342
|
if (p.pickup === "auto" && out.pickup !== "auto")
|
|
12579
12343
|
notYours.push("pickup");
|
|
12580
|
-
const atOnce =
|
|
12344
|
+
const atOnce = num4(p.atOnce);
|
|
12581
12345
|
if (atOnce !== undefined && atOnce >= 1)
|
|
12582
12346
|
out.atOnce = Math.round(atOnce);
|
|
12583
|
-
const seatAtOnce =
|
|
12347
|
+
const seatAtOnce = num4(r.seatAtOnce);
|
|
12584
12348
|
if (seatAtOnce !== undefined && Number.isInteger(seatAtOnce) && seatAtOnce >= 1)
|
|
12585
12349
|
out.seatAtOnce = seatAtOnce;
|
|
12586
12350
|
if (typeof p.mcpStrict === "boolean")
|
|
12587
12351
|
out.mcpStrict = p.mcpStrict;
|
|
12588
|
-
const holdCpu =
|
|
12352
|
+
const holdCpu = num4(p.holdCpu);
|
|
12589
12353
|
if (holdCpu !== undefined && holdCpu > 0 && holdCpu <= 100)
|
|
12590
12354
|
out.holdCpu = holdCpu;
|
|
12591
|
-
const holdLoad =
|
|
12355
|
+
const holdLoad = num4(p.holdLoad);
|
|
12592
12356
|
if (holdLoad !== undefined && holdLoad > 0)
|
|
12593
12357
|
out.holdLoad = holdLoad;
|
|
12594
12358
|
if (p.holdPressure === "warn" || p.holdPressure === "critical")
|
|
12595
12359
|
out.holdPressure = p.holdPressure;
|
|
12596
|
-
const drainMaxMin =
|
|
12360
|
+
const drainMaxMin = num4(p.drainMaxMin);
|
|
12597
12361
|
if (drainMaxMin !== undefined && Number.isInteger(drainMaxMin) && drainMaxMin >= 0)
|
|
12598
12362
|
out.drainMaxMin = drainMaxMin;
|
|
12599
12363
|
if (Array.isArray(p.mcpAllow)) {
|
|
@@ -12622,12 +12386,12 @@ async function readProfile(client) {
|
|
|
12622
12386
|
}
|
|
12623
12387
|
}
|
|
12624
12388
|
function nextPickup(r, o) {
|
|
12625
|
-
const mine = Array.isArray(r.mine) ? r.mine.filter(
|
|
12389
|
+
const mine = Array.isArray(r.mine) ? r.mine.filter(isObject7) : [];
|
|
12626
12390
|
for (const row of mine) {
|
|
12627
12391
|
const route = row.route;
|
|
12628
|
-
if (!
|
|
12392
|
+
if (!isObject7(route) || !armedFor(route.armed, o.engine))
|
|
12629
12393
|
continue;
|
|
12630
|
-
const states =
|
|
12394
|
+
const states = isObject7(route.states) ? route.states : {};
|
|
12631
12395
|
if (statesLanded(states))
|
|
12632
12396
|
continue;
|
|
12633
12397
|
if (strings(route.ready).length > 0)
|
|
@@ -12637,15 +12401,15 @@ function nextPickup(r, o) {
|
|
|
12637
12401
|
return null;
|
|
12638
12402
|
for (const row of mine) {
|
|
12639
12403
|
const route = row.route;
|
|
12640
|
-
if (!
|
|
12404
|
+
if (!isObject7(route) || isObject7(route.armed) || route.draftParked)
|
|
12641
12405
|
continue;
|
|
12642
12406
|
if (isPrMirror(row.source))
|
|
12643
12407
|
continue;
|
|
12644
12408
|
if (route.packable === false)
|
|
12645
12409
|
continue;
|
|
12646
|
-
if (
|
|
12410
|
+
if (isObject7(route.elsewhere))
|
|
12647
12411
|
continue;
|
|
12648
|
-
const states =
|
|
12412
|
+
const states = isObject7(route.states) ? route.states : {};
|
|
12649
12413
|
if (statesLanded(states) || keysIn(states, "running").length > 0)
|
|
12650
12414
|
continue;
|
|
12651
12415
|
if (strings(route.ready).length > 0 || redraftDue(route))
|
|
@@ -12654,45 +12418,45 @@ function nextPickup(r, o) {
|
|
|
12654
12418
|
return null;
|
|
12655
12419
|
}
|
|
12656
12420
|
function sledRunning(r) {
|
|
12657
|
-
const mine = Array.isArray(r) ? r : Array.isArray(r.mine) ? r.mine.filter(
|
|
12421
|
+
const mine = Array.isArray(r) ? r : Array.isArray(r.mine) ? r.mine.filter(isObject7) : [];
|
|
12658
12422
|
let running = 0;
|
|
12659
12423
|
for (const row of mine) {
|
|
12660
12424
|
const route = row.route;
|
|
12661
|
-
if (
|
|
12425
|
+
if (isObject7(route) && route.drafting === true)
|
|
12662
12426
|
running++;
|
|
12663
12427
|
if (mockRunOf(row).running)
|
|
12664
12428
|
running++;
|
|
12665
|
-
if (!
|
|
12429
|
+
if (!isObject7(route) || !isObject7(route.armed))
|
|
12666
12430
|
continue;
|
|
12667
|
-
running += keysIn(
|
|
12431
|
+
running += keysIn(isObject7(route.states) ? route.states : {}, "running").length;
|
|
12668
12432
|
}
|
|
12669
12433
|
return running;
|
|
12670
12434
|
}
|
|
12671
12435
|
function armedDrafts(r, engine) {
|
|
12672
|
-
const mine = Array.isArray(r.mine) ? r.mine.filter(
|
|
12436
|
+
const mine = Array.isArray(r.mine) ? r.mine.filter(isObject7) : [];
|
|
12673
12437
|
return mine.filter((row) => {
|
|
12674
12438
|
const route = row.route;
|
|
12675
|
-
if (!
|
|
12439
|
+
if (!isObject7(route) || !armedFor(route.armed, engine) || route.implicit !== true)
|
|
12676
12440
|
return false;
|
|
12677
12441
|
if (route.drafting === true || route.proposed === true || route.draftParked)
|
|
12678
12442
|
return false;
|
|
12679
|
-
if (
|
|
12443
|
+
if (isObject7(route.elsewhere))
|
|
12680
12444
|
return false;
|
|
12681
12445
|
if (strings(route.needsRoute).length === 0 || isPrMirror(row.source))
|
|
12682
12446
|
return false;
|
|
12683
|
-
const states =
|
|
12447
|
+
const states = isObject7(route.states) ? route.states : {};
|
|
12684
12448
|
return !statesLanded(states) && keysIn(states, "running").length === 0;
|
|
12685
12449
|
});
|
|
12686
12450
|
}
|
|
12687
12451
|
function redraftDue(route) {
|
|
12688
|
-
return
|
|
12452
|
+
return isObject7(route) && isObject7(route.redraft) && route.drafting !== true && route.proposed !== true;
|
|
12689
12453
|
}
|
|
12690
12454
|
function routeText(route, states) {
|
|
12691
|
-
const nodes = Array.isArray(route?.nodes) ? route.nodes.filter(
|
|
12455
|
+
const nodes = Array.isArray(route?.nodes) ? route.nodes.filter(isObject7) : [];
|
|
12692
12456
|
if (nodes.length > 0)
|
|
12693
12457
|
return nodes.map((n) => `${String(n.key)} · ${str7(n.title) ?? String(n.key)} — ${str7(n.state) ?? "ready"}`).join(`
|
|
12694
12458
|
`);
|
|
12695
|
-
return Object.entries(
|
|
12459
|
+
return Object.entries(isObject7(states) ? states : {}).map(([k, v]) => `${k} — ${String(v)}`).join(`
|
|
12696
12460
|
`);
|
|
12697
12461
|
}
|
|
12698
12462
|
function sledsSource(client, o) {
|
|
@@ -12707,7 +12471,7 @@ function sledsSource(client, o) {
|
|
|
12707
12471
|
if (!row)
|
|
12708
12472
|
return null;
|
|
12709
12473
|
const item = str7(row.key) ?? String(row.project);
|
|
12710
|
-
const why =
|
|
12474
|
+
const why = isObject7(row.route) ? strings(row.route.needsRoute) : [];
|
|
12711
12475
|
if (why.length > 0 || redraftDue(row.route))
|
|
12712
12476
|
return draft(row, item, why);
|
|
12713
12477
|
const a = await client.postFull("/proxy/route/arm", { project: str7(row.project) ?? item });
|
|
@@ -12717,12 +12481,12 @@ function sledsSource(client, o) {
|
|
|
12717
12481
|
}
|
|
12718
12482
|
const armed = a.json?.armed;
|
|
12719
12483
|
if (!armedFor(armed, engine)) {
|
|
12720
|
-
o.log?.(`Pickup: Auto armed ${item} for ${
|
|
12484
|
+
o.log?.(`Pickup: Auto armed ${item} for ${isObject7(armed) ? str7(armed.engine) : "another engine"}`);
|
|
12721
12485
|
return null;
|
|
12722
12486
|
}
|
|
12723
12487
|
o.log?.(`Pickup: Auto armed ${item}, the next ready item on your sled`);
|
|
12724
|
-
const route =
|
|
12725
|
-
const states =
|
|
12488
|
+
const route = isObject7(row.route) ? row.route : {};
|
|
12489
|
+
const states = isObject7(route.states) ? route.states : {};
|
|
12726
12490
|
return {
|
|
12727
12491
|
item,
|
|
12728
12492
|
ready: strings(route.ready),
|
|
@@ -12733,7 +12497,7 @@ function sledsSource(client, o) {
|
|
|
12733
12497
|
}
|
|
12734
12498
|
async function draft(row, item, why, started = false) {
|
|
12735
12499
|
const project = str7(row.project) ?? item;
|
|
12736
|
-
const pending =
|
|
12500
|
+
const pending = isObject7(row.route) && isObject7(row.route.redraft) ? row.route.redraft : null;
|
|
12737
12501
|
const runner = typeof o.runner === "function" ? o.runner() : o.runner;
|
|
12738
12502
|
const r = await client.postFull("/proxy/route", {
|
|
12739
12503
|
project,
|
|
@@ -12751,22 +12515,22 @@ function sledsSource(client, o) {
|
|
|
12751
12515
|
let brief = null;
|
|
12752
12516
|
try {
|
|
12753
12517
|
brief = await client.get(`/proxy/route?q=${encodeURIComponent(project)}&draft=1`);
|
|
12754
|
-
pack = (
|
|
12518
|
+
pack = (isObject7(brief?.draft) ? str7(brief.draft.pack) : undefined) ?? "";
|
|
12755
12519
|
} catch {
|
|
12756
12520
|
pack = "";
|
|
12757
12521
|
}
|
|
12758
12522
|
let redraft;
|
|
12759
12523
|
if (pending) {
|
|
12760
|
-
const full =
|
|
12524
|
+
const full = isObject7(brief?.redraft) ? brief.redraft : {};
|
|
12761
12525
|
redraft = {
|
|
12762
12526
|
md: str7(full.md) ?? str7(pending.md) ?? "",
|
|
12763
12527
|
by: str7(full.by) ?? "a person",
|
|
12764
12528
|
decision: str7(full.decisionId) ?? str7(pending.decisionId) ?? "",
|
|
12765
|
-
route: routeText(brief,
|
|
12529
|
+
route: routeText(brief, isObject7(row.route) ? row.route.states : null)
|
|
12766
12530
|
};
|
|
12767
12531
|
}
|
|
12768
12532
|
o.log?.(redraft ? `${item}: planning the route again from ${redraft.by}'s answer — it waits for a yes` : `${started ? `${item}: Start` : "Pickup: Auto"} is planning ${started ? "its" : `${item}'s`} route first (${why.join(", ")}) — it waits for a yes`);
|
|
12769
|
-
const leaseUntil =
|
|
12533
|
+
const leaseUntil = num4(j.leaseUntil);
|
|
12770
12534
|
const claim = {
|
|
12771
12535
|
item,
|
|
12772
12536
|
node: DRAFT_NODE,
|
|
@@ -12827,9 +12591,9 @@ function sledsSource(client, o) {
|
|
|
12827
12591
|
mockRefused.delete(item);
|
|
12828
12592
|
const j = r.json;
|
|
12829
12593
|
const key = str7(j.key) ?? item;
|
|
12830
|
-
const band =
|
|
12594
|
+
const band = isObject7(j.band) ? mockBandText(j.band) : undefined;
|
|
12831
12595
|
o.log?.(`Pickup: Auto is drawing ${key}'s mock — a no-code session${band ? `, sized ${band}` : ""}`);
|
|
12832
|
-
const leaseUntil =
|
|
12596
|
+
const leaseUntil = num4(j.leaseUntil);
|
|
12833
12597
|
return {
|
|
12834
12598
|
item: key,
|
|
12835
12599
|
node: MOCK_NODE,
|
|
@@ -12895,10 +12659,10 @@ function sledsSource(client, o) {
|
|
|
12895
12659
|
profileRead ??= readProfile(client);
|
|
12896
12660
|
return profileRead;
|
|
12897
12661
|
};
|
|
12898
|
-
const mine = Array.isArray(r.mine) ? r.mine.filter(
|
|
12662
|
+
const mine = Array.isArray(r.mine) ? r.mine.filter(isObject7) : [];
|
|
12899
12663
|
for (const row of mine) {
|
|
12900
12664
|
const route = row.route;
|
|
12901
|
-
if (!
|
|
12665
|
+
if (!isObject7(route) || !armedFor(route.armed, o.engine) || !redraftDue(route))
|
|
12902
12666
|
continue;
|
|
12903
12667
|
const item = str7(row.key) ?? String(row.project);
|
|
12904
12668
|
const claimed = await draft(row, item, strings(route.needsRoute));
|
|
@@ -12918,7 +12682,7 @@ function sledsSource(client, o) {
|
|
|
12918
12682
|
it.ready = [];
|
|
12919
12683
|
if (room <= 0)
|
|
12920
12684
|
continue;
|
|
12921
|
-
const route =
|
|
12685
|
+
const route = isObject7(row.route) ? row.route : {};
|
|
12922
12686
|
const claimed = await draft(row, item, strings(route.needsRoute), true);
|
|
12923
12687
|
if (claimed?.draft && it) {
|
|
12924
12688
|
it.draft = claimed.draft;
|
|
@@ -12959,17 +12723,17 @@ function sledsSource(client, o) {
|
|
|
12959
12723
|
});
|
|
12960
12724
|
if (!r)
|
|
12961
12725
|
return { ok: false, error: UNREACHABLE3 };
|
|
12962
|
-
const taken = Array.isArray(r.json?.taken) ? r.json.taken.filter(
|
|
12726
|
+
const taken = Array.isArray(r.json?.taken) ? r.json.taken.filter(isObject7) : [];
|
|
12963
12727
|
const hit = taken.find((x) => x.node === node) ?? taken[0];
|
|
12964
12728
|
if (r.status >= 400 || !hit) {
|
|
12965
|
-
const failed = Array.isArray(r.json?.failed) ? r.json.failed.filter(
|
|
12729
|
+
const failed = Array.isArray(r.json?.failed) ? r.json.failed.filter(isObject7) : [];
|
|
12966
12730
|
return { ok: false, error: str7(failed[0]?.error) ?? serverMessage(r) };
|
|
12967
12731
|
}
|
|
12968
12732
|
let repos = strings(hit.repos);
|
|
12969
12733
|
if (!Array.isArray(hit.repos)) {
|
|
12970
12734
|
try {
|
|
12971
12735
|
const route = await routeOf(item);
|
|
12972
|
-
const nodes = Array.isArray(route?.nodes) ? route.nodes.filter(
|
|
12736
|
+
const nodes = Array.isArray(route?.nodes) ? route.nodes.filter(isObject7) : [];
|
|
12973
12737
|
repos = strings(nodes.find((n) => n.key === (str7(hit.node) ?? node))?.repos);
|
|
12974
12738
|
} catch {
|
|
12975
12739
|
repos = [];
|
|
@@ -12981,7 +12745,7 @@ function sledsSource(client, o) {
|
|
|
12981
12745
|
} catch {
|
|
12982
12746
|
group = null;
|
|
12983
12747
|
}
|
|
12984
|
-
const leaseUntil =
|
|
12748
|
+
const leaseUntil = num4(hit.leaseUntil);
|
|
12985
12749
|
const runToken = str7(hit.runToken) ?? (taken.length === 1 ? str7(r.json?.runToken) : undefined);
|
|
12986
12750
|
const run = runOf(hit.run);
|
|
12987
12751
|
const claim = {
|
|
@@ -13020,17 +12784,17 @@ function sledsSource(client, o) {
|
|
|
13020
12784
|
} catch {
|
|
13021
12785
|
route = null;
|
|
13022
12786
|
}
|
|
13023
|
-
if (!
|
|
12787
|
+
if (!isObject7(route))
|
|
13024
12788
|
return "running";
|
|
13025
12789
|
if (claim.kind === "draft") {
|
|
13026
12790
|
const filed = Array.isArray(route.nodes) && route.nodes.length > 0;
|
|
13027
|
-
if (filed ||
|
|
12791
|
+
if (filed || isObject7(route.proposed) || isObject7(route.elsewhere))
|
|
13028
12792
|
return "done";
|
|
13029
|
-
if (
|
|
12793
|
+
if (isObject7(route.draftParked))
|
|
13030
12794
|
return "parked";
|
|
13031
12795
|
return "lost";
|
|
13032
12796
|
}
|
|
13033
|
-
const nodes = Array.isArray(route.nodes) ? route.nodes.filter(
|
|
12797
|
+
const nodes = Array.isArray(route.nodes) ? route.nodes.filter(isObject7) : [];
|
|
13034
12798
|
const state = nodes.find((n) => n.key === claim.node)?.state;
|
|
13035
12799
|
if (state === "parked")
|
|
13036
12800
|
return "parked";
|
|
@@ -13078,7 +12842,7 @@ function sledsSource(client, o) {
|
|
|
13078
12842
|
},
|
|
13079
12843
|
async openDecision(item, node) {
|
|
13080
12844
|
const route = await routeOf(item);
|
|
13081
|
-
const decisions = Array.isArray(route?.decisions) ? route.decisions.filter(
|
|
12845
|
+
const decisions = Array.isArray(route?.decisions) ? route.decisions.filter(isObject7) : [];
|
|
13082
12846
|
const open = decisions.find((x) => x.state === "open" && x.node === node);
|
|
13083
12847
|
return open ? str7(open.id) ?? null : null;
|
|
13084
12848
|
},
|
|
@@ -13113,11 +12877,11 @@ function sledsSource(client, o) {
|
|
|
13113
12877
|
return "running";
|
|
13114
12878
|
try {
|
|
13115
12879
|
const route = await routeOf(a.item);
|
|
13116
|
-
const decisions = Array.isArray(route?.decisions) ? route.decisions.filter(
|
|
12880
|
+
const decisions = Array.isArray(route?.decisions) ? route.decisions.filter(isObject7) : [];
|
|
13117
12881
|
const d = decisions.find((x) => x.id === a.decisionId);
|
|
13118
|
-
if (d?.state === "answered" &&
|
|
12882
|
+
if (d?.state === "answered" && isObject7(d.answerer) && d.answerer.verdict === "answered")
|
|
13119
12883
|
return "answered";
|
|
13120
|
-
if (d?.state === "answered" &&
|
|
12884
|
+
if (d?.state === "answered" && isObject7(d.answerer) && d.answerer.verdict === "released")
|
|
13121
12885
|
return "released";
|
|
13122
12886
|
if (d?.state === "escalated")
|
|
13123
12887
|
return "escalated";
|
|
@@ -13200,16 +12964,16 @@ function sledsSource(client, o) {
|
|
|
13200
12964
|
},
|
|
13201
12965
|
async decisionOf(item, decisionId) {
|
|
13202
12966
|
const route = await routeOf(item);
|
|
13203
|
-
const decisions = Array.isArray(route?.decisions) ? route.decisions.filter(
|
|
12967
|
+
const decisions = Array.isArray(route?.decisions) ? route.decisions.filter(isObject7) : [];
|
|
13204
12968
|
const d = decisions.find((x) => x.id === decisionId);
|
|
13205
12969
|
if (!d)
|
|
13206
12970
|
return null;
|
|
13207
|
-
const answer =
|
|
12971
|
+
const answer = isObject7(d.answer) ? str7(d.answer.md) : undefined;
|
|
13208
12972
|
return { state: str7(d.state) ?? "", ...answer ? { answer } : {} };
|
|
13209
12973
|
},
|
|
13210
12974
|
async routeBriefs(item) {
|
|
13211
12975
|
const route = await routeOf(item);
|
|
13212
|
-
const nodes = Array.isArray(route?.nodes) ? route.nodes.filter(
|
|
12976
|
+
const nodes = Array.isArray(route?.nodes) ? route.nodes.filter(isObject7) : [];
|
|
13213
12977
|
return nodes.flatMap((n) => {
|
|
13214
12978
|
const key = str7(n.key);
|
|
13215
12979
|
const { plan } = nodePlanOf(n.plan);
|
|
@@ -13499,9 +13263,9 @@ function providerFailure(screen) {
|
|
|
13499
13263
|
// src/engine/worktree.ts
|
|
13500
13264
|
init_src();
|
|
13501
13265
|
import { appendFileSync, existsSync as existsSync9, mkdirSync as mkdirSync10 } from "node:fs";
|
|
13502
|
-
import { dirname as
|
|
13266
|
+
import { dirname as dirname8, isAbsolute, join as join11 } from "node:path";
|
|
13503
13267
|
function worktreePath(repoPath, name) {
|
|
13504
|
-
return
|
|
13268
|
+
return join11(repoPath, ".worktrees", name);
|
|
13505
13269
|
}
|
|
13506
13270
|
var fail2 = (what, r) => new Error(`${what} failed: ${(r.stderr || r.stdout).trim() || `exit ${r.status}`}`);
|
|
13507
13271
|
function defaultBranch(exec, repoPath) {
|
|
@@ -13524,7 +13288,7 @@ function defaultBranch(exec, repoPath) {
|
|
|
13524
13288
|
var realWorktreeFs = {
|
|
13525
13289
|
exists: existsSync9,
|
|
13526
13290
|
append: (p, text) => {
|
|
13527
|
-
mkdirSync10(
|
|
13291
|
+
mkdirSync10(dirname8(p), { recursive: true });
|
|
13528
13292
|
appendFileSync(p, text);
|
|
13529
13293
|
}
|
|
13530
13294
|
};
|
|
@@ -13536,7 +13300,7 @@ function ensureIgnored(exec, repoPath, fs = realWorktreeFs) {
|
|
|
13536
13300
|
if (common.status !== 0)
|
|
13537
13301
|
return;
|
|
13538
13302
|
const dir = common.stdout.trim();
|
|
13539
|
-
const exclude =
|
|
13303
|
+
const exclude = join11(isAbsolute(dir) ? dir : join11(repoPath, dir), "info", "exclude");
|
|
13540
13304
|
fs.append(exclude, `
|
|
13541
13305
|
# sleds engine: one worktree per route node
|
|
13542
13306
|
.worktrees/
|
|
@@ -13548,7 +13312,7 @@ function ensureWorktree(exec, repoPath, branch, path, base = "main", fs = realWo
|
|
|
13548
13312
|
return path;
|
|
13549
13313
|
}
|
|
13550
13314
|
function makeWorktree(exec, repoPath, branch, path, base, fs, log) {
|
|
13551
|
-
if (fs.exists(
|
|
13315
|
+
if (fs.exists(join11(path, ".git"))) {
|
|
13552
13316
|
fastForwardUntouched(exec, path, base, log);
|
|
13553
13317
|
return path;
|
|
13554
13318
|
}
|
|
@@ -13643,13 +13407,13 @@ function installArgv(command) {
|
|
|
13643
13407
|
return rest.every((a) => INSTALL_FLAGS.has(a)) ? argv : null;
|
|
13644
13408
|
}
|
|
13645
13409
|
function lockfileInstall(path, exists) {
|
|
13646
|
-
if (exists(
|
|
13410
|
+
if (exists(join11(path, "pnpm-lock.yaml")))
|
|
13647
13411
|
return ["pnpm", "install", "--frozen-lockfile"];
|
|
13648
|
-
if (exists(
|
|
13412
|
+
if (exists(join11(path, "bun.lock")) || exists(join11(path, "bun.lockb")))
|
|
13649
13413
|
return ["bun", "install", "--frozen-lockfile"];
|
|
13650
|
-
if (exists(
|
|
13414
|
+
if (exists(join11(path, "yarn.lock")))
|
|
13651
13415
|
return ["yarn", "install", "--frozen-lockfile"];
|
|
13652
|
-
if (exists(
|
|
13416
|
+
if (exists(join11(path, "package-lock.json")))
|
|
13653
13417
|
return ["npm", "ci"];
|
|
13654
13418
|
return null;
|
|
13655
13419
|
}
|
|
@@ -13707,7 +13471,7 @@ function claimRunOf(run, repo) {
|
|
|
13707
13471
|
};
|
|
13708
13472
|
}
|
|
13709
13473
|
function ensureInstalled(exec, path, fs, o = {}) {
|
|
13710
|
-
if (!fs.exists(
|
|
13474
|
+
if (!fs.exists(join11(path, "package.json")) || fs.exists(join11(path, "node_modules")))
|
|
13711
13475
|
return null;
|
|
13712
13476
|
const argv = installArgv(o.command) ?? lockfileInstall(path, fs.exists);
|
|
13713
13477
|
if (!argv)
|
|
@@ -13722,7 +13486,7 @@ function ensureInstalled(exec, path, fs, o = {}) {
|
|
|
13722
13486
|
return { argv, ok };
|
|
13723
13487
|
}
|
|
13724
13488
|
function ensureDetachedWorktree(exec, repoPath, path, base = "main", fs = realWorktreeFs) {
|
|
13725
|
-
if (fs.exists(
|
|
13489
|
+
if (fs.exists(join11(path, ".git")))
|
|
13726
13490
|
return path;
|
|
13727
13491
|
ensureIgnored(exec, repoPath, fs);
|
|
13728
13492
|
const f = exec("git", ["-C", repoPath, "fetch", "origin", base]);
|
|
@@ -15890,9 +15654,16 @@ ${instructionNudge(url, items)}`;
|
|
|
15890
15654
|
function reviewNudge(url, count) {
|
|
15891
15655
|
return `New review feedback on your PR (${count} ${count === 1 ? "comment" : "comments"} from people so far): ${url}. Read all of it (gh pr view ${url} --comments, and the inline threads), answer each comment on its own thread with the fix or a reasoned reply, push, and leave the threads for the reviewer to resolve. End every comment and reply you post on the PR with the line ${ENGINE_MARK} so the engine knows it is yours and not the reviewer's.`;
|
|
15892
15656
|
}
|
|
15893
|
-
function lookQuestion(url, mock) {
|
|
15894
|
-
|
|
15657
|
+
function lookQuestion(url, mock, comparison) {
|
|
15658
|
+
const head = `A draft PR waits for your look: ${url}.${mock ? ` The mock: ${mock}.` : " Its body names no mock; the PR is the place to look."}`;
|
|
15659
|
+
const compared = comparison ? lookComparisonLines(comparison) : "No comparison came: the PR does not set the preview beside the mock — compare them yourself before it goes on.";
|
|
15660
|
+
return `${head}
|
|
15661
|
+
|
|
15662
|
+
${compared}
|
|
15663
|
+
|
|
15664
|
+
Looks good marks it ready for review.`;
|
|
15895
15665
|
}
|
|
15666
|
+
var LOOK_WAIT_MS = 30 * 60000;
|
|
15896
15667
|
async function judgeLook(d, run, view) {
|
|
15897
15668
|
const looks = looksOf(d.source);
|
|
15898
15669
|
const pr = run.pr;
|
|
@@ -15900,15 +15671,25 @@ async function judgeLook(d, run, view) {
|
|
|
15900
15671
|
return;
|
|
15901
15672
|
const draft = view.state === "OPEN" && view.draft;
|
|
15902
15673
|
if (draft && !pr.look) {
|
|
15674
|
+
if (!view.comparison) {
|
|
15675
|
+
if (pr.lookWait === undefined) {
|
|
15676
|
+
pr.lookWait = d.now();
|
|
15677
|
+
d.log(`${ref(run)}: ${pr.url} is a draft — the look waits for the preview's comparison`);
|
|
15678
|
+
return;
|
|
15679
|
+
}
|
|
15680
|
+
if (d.now() - pr.lookWait < LOOK_WAIT_MS)
|
|
15681
|
+
return;
|
|
15682
|
+
}
|
|
15903
15683
|
try {
|
|
15904
15684
|
const r = await looks.openLook(run.runId, {
|
|
15905
|
-
md: lookQuestion(pr.url, view.mock),
|
|
15685
|
+
md: lookQuestion(pr.url, view.mock, view.comparison),
|
|
15906
15686
|
pr: pr.url,
|
|
15907
15687
|
...view.mock ? { mock: view.mock } : {}
|
|
15908
15688
|
}, d.engine);
|
|
15909
15689
|
if (!r.decisionId)
|
|
15910
15690
|
return;
|
|
15911
15691
|
pr.look = r.decisionId;
|
|
15692
|
+
pr.lookWait = undefined;
|
|
15912
15693
|
if (r.opened)
|
|
15913
15694
|
d.log(`${ref(run)}: ${pr.url} is a draft — a look waits for a person`);
|
|
15914
15695
|
} catch (e) {
|
|
@@ -15924,6 +15705,8 @@ async function judgeLook(d, run, view) {
|
|
|
15924
15705
|
d.log(`${ref(run)}: could not clear the look on ${pr.url}: ${message(e)}`);
|
|
15925
15706
|
}
|
|
15926
15707
|
}
|
|
15708
|
+
if (!draft)
|
|
15709
|
+
pr.lookWait = undefined;
|
|
15927
15710
|
}
|
|
15928
15711
|
async function follow(d, state, run, claim, runner, finished, attention, changes, decided) {
|
|
15929
15712
|
const pr = run.pr;
|
|
@@ -16864,7 +16647,7 @@ async function settleEvent(d, events, state, dec, attention, decided) {
|
|
|
16864
16647
|
init_machine();
|
|
16865
16648
|
|
|
16866
16649
|
// src/engine/repos.ts
|
|
16867
|
-
import { basename as
|
|
16650
|
+
import { basename as basename3, dirname as dirname9, join as join12 } from "node:path";
|
|
16868
16651
|
function splitReposDirs(raw) {
|
|
16869
16652
|
return (raw ?? "").split(/[:\n]/).map((d) => d.trim()).filter(Boolean);
|
|
16870
16653
|
}
|
|
@@ -16876,7 +16659,7 @@ function resolveRepoPath(o) {
|
|
|
16876
16659
|
error: `No repo for ${o.repos.length ? o.repos.join(", ") : "this node"}: --repo ${o.repo} is not a git checkout. Clone the repo there, or start the engine with --repo set to a clone.`
|
|
16877
16660
|
};
|
|
16878
16661
|
}
|
|
16879
|
-
const names = o.repos.map((r) =>
|
|
16662
|
+
const names = o.repos.map((r) => basename3(r.trim())).filter(Boolean);
|
|
16880
16663
|
const dirs = o.reposDirs ?? [];
|
|
16881
16664
|
if (dirs.length === 0 || names.length === 0) {
|
|
16882
16665
|
if (insideCheckout(o.cwd, o.exists))
|
|
@@ -16891,21 +16674,21 @@ function resolveRepoPath(o) {
|
|
|
16891
16674
|
if (name.startsWith("."))
|
|
16892
16675
|
continue;
|
|
16893
16676
|
for (const dir of dirs) {
|
|
16894
|
-
const p =
|
|
16895
|
-
if (o.exists(
|
|
16677
|
+
const p = join12(dir, name);
|
|
16678
|
+
if (o.exists(join12(p, ".git")))
|
|
16896
16679
|
return p;
|
|
16897
16680
|
}
|
|
16898
16681
|
}
|
|
16899
16682
|
const want = o.repos.join(", ");
|
|
16900
|
-
const where = names.flatMap((n) => dirs.map((d) =>
|
|
16683
|
+
const where = names.flatMap((n) => dirs.map((d) => join12(d, n))).join(" or ");
|
|
16901
16684
|
return {
|
|
16902
16685
|
error: `No checkout of ${want} on this engine's machine: expected ${where}. Clone it there (or pass --repo).`
|
|
16903
16686
|
};
|
|
16904
16687
|
}
|
|
16905
|
-
var isRoot = (p) =>
|
|
16688
|
+
var isRoot = (p) => dirname9(p) === p;
|
|
16906
16689
|
function insideCheckout(dir, exists) {
|
|
16907
|
-
for (let d = dir;!isRoot(d); d =
|
|
16908
|
-
if (exists(
|
|
16690
|
+
for (let d = dir;!isRoot(d); d = dirname9(d)) {
|
|
16691
|
+
if (exists(join12(d, ".git")))
|
|
16909
16692
|
return true;
|
|
16910
16693
|
}
|
|
16911
16694
|
return false;
|
|
@@ -16950,7 +16733,7 @@ init_meter();
|
|
|
16950
16733
|
|
|
16951
16734
|
// src/runners/gitGuard.ts
|
|
16952
16735
|
import { statSync as statSync2 } from "node:fs";
|
|
16953
|
-
import { basename as
|
|
16736
|
+
import { basename as basename4, dirname as dirname10, join as join13, resolve as resolve6 } from "node:path";
|
|
16954
16737
|
var GIT_GUARD_ENV = {
|
|
16955
16738
|
GIT_CONFIG_COUNT: "4",
|
|
16956
16739
|
GIT_CONFIG_KEY_0: "core.fsmonitor",
|
|
@@ -16983,13 +16766,13 @@ var isFile = (p) => statSync2(p, { throwIfNoEntry: false })?.isFile() ?? false;
|
|
|
16983
16766
|
var isDir = (p) => statSync2(p, { throwIfNoEntry: false })?.isDirectory() ?? false;
|
|
16984
16767
|
function ownGitDirs(dir, stat = { isFile, isDir }) {
|
|
16985
16768
|
const wt = resolve6(dir);
|
|
16986
|
-
if (
|
|
16769
|
+
if (basename4(dirname10(wt)) !== ".worktrees")
|
|
16987
16770
|
return null;
|
|
16988
|
-
const common =
|
|
16989
|
-
if (!stat.isFile(
|
|
16771
|
+
const common = join13(dirname10(dirname10(wt)), ".git");
|
|
16772
|
+
if (!stat.isFile(join13(wt, ".git")) || !stat.isDir(common))
|
|
16990
16773
|
return null;
|
|
16991
16774
|
return {
|
|
16992
|
-
GIT_DIR:
|
|
16775
|
+
GIT_DIR: join13(common, "worktrees", basename4(wt)),
|
|
16993
16776
|
GIT_COMMON_DIR: common,
|
|
16994
16777
|
GIT_WORK_TREE: wt
|
|
16995
16778
|
};
|
|
@@ -16999,14 +16782,14 @@ var callDir = (args, cwd) => {
|
|
|
16999
16782
|
return args[0] === "-C" && args[1] ? resolve6(base, args[1]) : base;
|
|
17000
16783
|
};
|
|
17001
16784
|
var GUARDED = new Set(["git", "gh"]);
|
|
17002
|
-
var guardGit = (exec, guard = gitGuardEnv) => (cmd, args, o) => GUARDED.has(
|
|
16785
|
+
var guardGit = (exec, guard = gitGuardEnv) => (cmd, args, o) => GUARDED.has(basename4(cmd)) ? exec(cmd, args, {
|
|
17003
16786
|
...o,
|
|
17004
16787
|
env: { ...o?.env, ...guard(), ...ownGitDirs(callDir(args, o?.cwd)) }
|
|
17005
16788
|
}) : exec(cmd, args, o);
|
|
17006
16789
|
|
|
17007
16790
|
// src/runners/cmux.ts
|
|
17008
16791
|
import { existsSync as existsSync10, rmSync as rmSync3, writeFileSync as writeFileSync10 } from "node:fs";
|
|
17009
|
-
import { delimiter, join as
|
|
16792
|
+
import { delimiter, join as join14 } from "node:path";
|
|
17010
16793
|
|
|
17011
16794
|
// src/keychain.ts
|
|
17012
16795
|
var CMUX_KEYCHAIN_SERVICE = "ai.sleds.cmux";
|
|
@@ -17037,7 +16820,7 @@ var clearCmuxPassword = (exec) => exec("security", ["delete-generic-password", .
|
|
|
17037
16820
|
var CMUX_APP_BIN = "/Applications/cmux.app/Contents/Resources/bin/cmux";
|
|
17038
16821
|
var resolveCmuxBin = (exists = existsSync10, path = process.env.PATH ?? "") => {
|
|
17039
16822
|
for (const dir of path.split(delimiter)) {
|
|
17040
|
-
if (dir && exists(
|
|
16823
|
+
if (dir && exists(join14(dir, "cmux")))
|
|
17041
16824
|
return "cmux";
|
|
17042
16825
|
}
|
|
17043
16826
|
return exists(CMUX_APP_BIN) ? CMUX_APP_BIN : "cmux";
|
|
@@ -18052,7 +17835,7 @@ ${renderTranscript(eventMessages(all))}`;
|
|
|
18052
17835
|
|
|
18053
17836
|
// src/runners/orca.ts
|
|
18054
17837
|
import { existsSync as existsSync11, lstatSync, readlinkSync, writeFileSync as writeFileSync11 } from "node:fs";
|
|
18055
|
-
import { join as
|
|
17838
|
+
import { join as join15, resolve as resolve7 } from "node:path";
|
|
18056
17839
|
var obj3 = (v) => v !== null && typeof v === "object" && !Array.isArray(v) ? v : null;
|
|
18057
17840
|
var str11 = (v) => typeof v === "string" && v.length > 0 ? v : null;
|
|
18058
17841
|
var parseOrcaJson = (stdout) => {
|
|
@@ -18115,7 +17898,7 @@ var realFs = { lstat: lstatSync, readlink: readlinkSync, exists: existsSync11 };
|
|
|
18115
17898
|
var ORCA_LINK_FIX = "reinstall Orca's shell command from Orca (it links `orca` onto your PATH)";
|
|
18116
17899
|
function danglingOrca(path, fs) {
|
|
18117
17900
|
for (const dir of path.split(":").filter(Boolean)) {
|
|
18118
|
-
const link =
|
|
17901
|
+
const link = join15(dir, "orca");
|
|
18119
17902
|
try {
|
|
18120
17903
|
if (!fs.lstat(link).isSymbolicLink())
|
|
18121
17904
|
return null;
|
|
@@ -18413,9 +18196,9 @@ function restoreRunner(name, exec = defaultExec) {
|
|
|
18413
18196
|
|
|
18414
18197
|
// src/runtime.ts
|
|
18415
18198
|
import { homedir as homedir2 } from "node:os";
|
|
18416
|
-
import { join as
|
|
18199
|
+
import { join as join16, win32 } from "node:path";
|
|
18417
18200
|
var isCompiled = (argv1 = process.argv[1]) => Boolean(argv1 && (argv1.startsWith("/$bunfs/") || argv1.startsWith("B:\\~BUN\\")));
|
|
18418
|
-
var sledsLink = (home = homedir2(), platform = process.platform) => platform === "win32" ? win32.join(process.env.LOCALAPPDATA ?? win32.join(home, "AppData", "Local"), "sleds", "bin", "sleds.exe") :
|
|
18201
|
+
var sledsLink = (home = homedir2(), platform = process.platform) => platform === "win32" ? win32.join(process.env.LOCALAPPDATA ?? win32.join(home, "AppData", "Local"), "sleds", "bin", "sleds.exe") : join16(home, ".sleds", "bin", "sleds");
|
|
18419
18202
|
|
|
18420
18203
|
// src/commands/engine.ts
|
|
18421
18204
|
init_settings();
|
|
@@ -18434,7 +18217,7 @@ import {
|
|
|
18434
18217
|
writeSync as writeSync2
|
|
18435
18218
|
} from "node:fs";
|
|
18436
18219
|
import { homedir as homedir7 } from "node:os";
|
|
18437
|
-
import { join as
|
|
18220
|
+
import { join as join22 } from "node:path";
|
|
18438
18221
|
|
|
18439
18222
|
// ../../packages/shared/src/updates/manifest.ts
|
|
18440
18223
|
var CLI_PLATFORMS = [
|
|
@@ -18546,14 +18329,14 @@ import {
|
|
|
18546
18329
|
var RELEASE_PUBLIC_KEY = "MCowBQYDK2VwAyEADIZiQghghQlN6WoLDF9xLmqMeFSQL4crcCBT4wINNCc=";
|
|
18547
18330
|
|
|
18548
18331
|
// ../../packages/shared/src/updates/verify.ts
|
|
18549
|
-
import { createPrivateKey, createPublicKey
|
|
18332
|
+
import { createPrivateKey, createPublicKey, sign, verify } from "node:crypto";
|
|
18550
18333
|
var B64_RE = /^[A-Za-z0-9+/]+={0,2}$/;
|
|
18551
18334
|
function verifyManifest(text, signatureB64, publicKeySpkiB64) {
|
|
18552
18335
|
try {
|
|
18553
18336
|
const sig = signatureB64.trim();
|
|
18554
18337
|
if (!B64_RE.test(sig))
|
|
18555
18338
|
return false;
|
|
18556
|
-
const key =
|
|
18339
|
+
const key = createPublicKey({
|
|
18557
18340
|
key: Buffer.from(publicKeySpkiB64, "base64"),
|
|
18558
18341
|
format: "der",
|
|
18559
18342
|
type: "spki"
|
|
@@ -18577,12 +18360,12 @@ import {
|
|
|
18577
18360
|
writeFileSync as writeFileSync12
|
|
18578
18361
|
} from "node:fs";
|
|
18579
18362
|
import { homedir as homedir3 } from "node:os";
|
|
18580
|
-
import { dirname as
|
|
18363
|
+
import { dirname as dirname11, join as join17, win32 as win322 } from "node:path";
|
|
18581
18364
|
var UPDATE_LOCK_STALE_MS = 10 * 60000;
|
|
18582
18365
|
function sledsRoot(home = homedir3(), platform = process.platform) {
|
|
18583
|
-
return platform === "win32" ? win322.join(process.env.LOCALAPPDATA ?? win322.join(home, "AppData", "Local"), "sleds") :
|
|
18366
|
+
return platform === "win32" ? win322.join(process.env.LOCALAPPDATA ?? win322.join(home, "AppData", "Local"), "sleds") : join17(home, ".sleds");
|
|
18584
18367
|
}
|
|
18585
|
-
var pathFor = (platform) => platform === "win32" ? win322 : { join:
|
|
18368
|
+
var pathFor = (platform) => platform === "win32" ? win322 : { join: join17 };
|
|
18586
18369
|
function versionDir(home, v, platform = process.platform) {
|
|
18587
18370
|
return pathFor(platform).join(sledsRoot(home, platform), "versions", v);
|
|
18588
18371
|
}
|
|
@@ -18655,7 +18438,7 @@ function readUpdateState(home) {
|
|
|
18655
18438
|
}
|
|
18656
18439
|
function writeUpdateState(home, s) {
|
|
18657
18440
|
const path = updateStatePath(home);
|
|
18658
|
-
mkdirSync11(
|
|
18441
|
+
mkdirSync11(dirname11(path), { recursive: true, mode: 448 });
|
|
18659
18442
|
const tmp = `${path}.${process.pid}.${randomUUID()}.tmp`;
|
|
18660
18443
|
writeFileSync12(tmp, `${JSON.stringify(s, null, 2)}
|
|
18661
18444
|
`, { mode: 384 });
|
|
@@ -18733,7 +18516,7 @@ function breakStale(path, seen, token) {
|
|
|
18733
18516
|
async function withUpdateLock(home, fn, o = {}) {
|
|
18734
18517
|
const waitMs = o.waitMs ?? 30000;
|
|
18735
18518
|
const path = updateLockPath(home);
|
|
18736
|
-
mkdirSync11(
|
|
18519
|
+
mkdirSync11(dirname11(path), { recursive: true, mode: 448 });
|
|
18737
18520
|
const token = randomUUID();
|
|
18738
18521
|
const tmp = `${path}.${token}.tmp`;
|
|
18739
18522
|
writeFileSync12(tmp, `${JSON.stringify({ pid: process.pid, at: Date.now(), token })}
|
|
@@ -18812,7 +18595,7 @@ async function fetchVersion(o) {
|
|
|
18812
18595
|
const platform = o.platform ?? process.platform;
|
|
18813
18596
|
const arch = o.arch ?? process.arch;
|
|
18814
18597
|
const publicKey = o.publicKey ?? RELEASE_PUBLIC_KEY;
|
|
18815
|
-
const running = o.running ?? "0.1.
|
|
18598
|
+
const running = o.running ?? "0.1.72";
|
|
18816
18599
|
if (!publicKey)
|
|
18817
18600
|
return { ok: false, why: "no release key yet" };
|
|
18818
18601
|
if (!VERSION_RE2.test(o.version))
|
|
@@ -18907,19 +18690,19 @@ import {
|
|
|
18907
18690
|
writeFileSync as writeFileSync14
|
|
18908
18691
|
} from "node:fs";
|
|
18909
18692
|
import { homedir as homedir4 } from "node:os";
|
|
18910
|
-
import { basename as
|
|
18693
|
+
import { basename as basename5, delimiter as delimiter2, dirname as dirname12, isAbsolute as isAbsolute2, join as join20, relative } from "node:path";
|
|
18911
18694
|
|
|
18912
18695
|
// src/commands/engineSystemd.ts
|
|
18913
|
-
import { join as
|
|
18696
|
+
import { join as join18 } from "node:path";
|
|
18914
18697
|
var BOX_ENV_UNIT_PATH = "%h/.config/sleds/box.env";
|
|
18915
18698
|
function boxEnvPath(home) {
|
|
18916
|
-
return
|
|
18699
|
+
return join18(home, ".config", "sleds", "box.env");
|
|
18917
18700
|
}
|
|
18918
18701
|
function engineUnitDir(home) {
|
|
18919
|
-
return
|
|
18702
|
+
return join18(home, ".config", "systemd", "user");
|
|
18920
18703
|
}
|
|
18921
18704
|
function engineUnitPath(home, label) {
|
|
18922
|
-
return
|
|
18705
|
+
return join18(engineUnitDir(home), `${label}.service`);
|
|
18923
18706
|
}
|
|
18924
18707
|
function systemdQuote(s) {
|
|
18925
18708
|
const body = s.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/\n/g, "\\n").replace(/%/g, "%%").replace(/\$/g, "$$$$");
|
|
@@ -18959,20 +18742,20 @@ function parseEngineUnit(text) {
|
|
|
18959
18742
|
}
|
|
18960
18743
|
|
|
18961
18744
|
// src/schedule.ts
|
|
18962
|
-
import { spawnSync as
|
|
18745
|
+
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
18963
18746
|
import { existsSync as existsSync13, mkdirSync as mkdirSync13, rmSync as rmSync6, writeFileSync as writeFileSync13 } from "node:fs";
|
|
18964
|
-
import { join as
|
|
18747
|
+
import { join as join19 } from "node:path";
|
|
18965
18748
|
var REVERT_LABEL = "ai.sleds.revert";
|
|
18966
18749
|
var defaultExec2 = (cmd, args) => {
|
|
18967
|
-
const r =
|
|
18750
|
+
const r = spawnSync3(cmd, [...args], { stdio: ["ignore", "ignore", "pipe"], encoding: "utf8" });
|
|
18968
18751
|
if (r.error)
|
|
18969
18752
|
return { ok: false, stderr: r.error.message };
|
|
18970
18753
|
return { ok: r.status === 0, stderr: r.stderr ?? "" };
|
|
18971
18754
|
};
|
|
18972
|
-
var plistPath = (home) =>
|
|
18973
|
-
var
|
|
18755
|
+
var plistPath = (home) => join19(home, "Library", "LaunchAgents", `${REVERT_LABEL}.plist`);
|
|
18756
|
+
var xmlEscape = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
18974
18757
|
var buildLaunchdPlist = (sledsArgv, deadline) => {
|
|
18975
|
-
const args = [...sledsArgv, "off"].map((a) => ` <string>${
|
|
18758
|
+
const args = [...sledsArgv, "off"].map((a) => ` <string>${xmlEscape(a)}</string>`).join(`
|
|
18976
18759
|
`);
|
|
18977
18760
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
18978
18761
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
@@ -19008,7 +18791,7 @@ var scheduleRevert = (d, deadlineMs) => {
|
|
|
19008
18791
|
if (d.platform === "darwin") {
|
|
19009
18792
|
const p = plistPath(d.home);
|
|
19010
18793
|
try {
|
|
19011
|
-
mkdirSync13(
|
|
18794
|
+
mkdirSync13(join19(d.home, "Library", "LaunchAgents"), { recursive: true });
|
|
19012
18795
|
d.exec("launchctl", ["unload", p]);
|
|
19013
18796
|
writeFileSync13(p, buildLaunchdPlist(d.sledsArgv, deadline));
|
|
19014
18797
|
const r = d.exec("launchctl", ["load", p]);
|
|
@@ -19060,9 +18843,9 @@ var HOOK_SUBS = [
|
|
|
19060
18843
|
"stop-event",
|
|
19061
18844
|
"permission-event"
|
|
19062
18845
|
];
|
|
19063
|
-
var migrateBakDir = (home) =>
|
|
19064
|
-
var manifestPath = (home) =>
|
|
19065
|
-
var
|
|
18846
|
+
var migrateBakDir = (home) => join20(sledsRoot(home), "migrate.bak");
|
|
18847
|
+
var manifestPath = (home) => join20(migrateBakDir(home), "manifest.json");
|
|
18848
|
+
var xmlEscape2 = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
19066
18849
|
var xmlUnescape = (s) => s.replace(/</g, "<").replace(/>/g, ">").replace(/&/g, "&");
|
|
19067
18850
|
var shQuote = (s) => /^[\w./~-]+$/.test(s) ? s : `'${s.replace(/'/g, "'\\''")}'`;
|
|
19068
18851
|
function rewritePlist(text, link) {
|
|
@@ -19083,7 +18866,7 @@ function rewritePlist(text, link) {
|
|
|
19083
18866
|
return null;
|
|
19084
18867
|
const from = bodyAt + first.index;
|
|
19085
18868
|
const to = bodyAt + last.index + last[0].length;
|
|
19086
|
-
return `${text.slice(0, from)}<string>${
|
|
18869
|
+
return `${text.slice(0, from)}<string>${xmlEscape2(link)}</string>${text.slice(to)}`;
|
|
19087
18870
|
}
|
|
19088
18871
|
function rewriteUnit(text, link) {
|
|
19089
18872
|
const line = /^ExecStart=(.*)$/m.exec(text);
|
|
@@ -19161,15 +18944,15 @@ function rewriteSettings(text, link) {
|
|
|
19161
18944
|
}
|
|
19162
18945
|
var listDir = (dir, keep) => {
|
|
19163
18946
|
try {
|
|
19164
|
-
return readdirSync2(dir).filter(keep).sort().map((n) =>
|
|
18947
|
+
return readdirSync2(dir).filter(keep).sort().map((n) => join20(dir, n));
|
|
19165
18948
|
} catch {
|
|
19166
18949
|
return [];
|
|
19167
18950
|
}
|
|
19168
18951
|
};
|
|
19169
18952
|
function unitFiles(home) {
|
|
19170
|
-
const agents = listDir(
|
|
18953
|
+
const agents = listDir(join20(home, "Library", "LaunchAgents"), (n) => n.startsWith("ai.sleds.") && n.endsWith(".plist")).map((path) => ({
|
|
19171
18954
|
path,
|
|
19172
|
-
...
|
|
18955
|
+
...basename5(path).startsWith("ai.sleds.revert") ? {} : { reload: "launchd" }
|
|
19173
18956
|
}));
|
|
19174
18957
|
const units = listDir(engineUnitDir(home), (n) => n.startsWith("ai.sleds.") && n.endsWith(".service")).map((path) => ({ path, reload: "systemd" }));
|
|
19175
18958
|
return [...agents, ...units];
|
|
@@ -19179,7 +18962,7 @@ function unitClaudeDir(text) {
|
|
|
19179
18962
|
return plist ? xmlUnescape(plist) : undefined;
|
|
19180
18963
|
}
|
|
19181
18964
|
function claudeDirs(home, env) {
|
|
19182
|
-
const dirs = [
|
|
18965
|
+
const dirs = [join20(home, ".claude"), claudeDir(home, env)];
|
|
19183
18966
|
for (const u of unitFiles(home)) {
|
|
19184
18967
|
try {
|
|
19185
18968
|
const d = unitClaudeDir(readFileSync13(u.path, "utf8"));
|
|
@@ -19203,7 +18986,7 @@ function migrationPlan(home, link, env = process.env) {
|
|
|
19203
18986
|
out.push({ ...u, text: next });
|
|
19204
18987
|
}
|
|
19205
18988
|
for (const dir of claudeDirs(home, env)) {
|
|
19206
|
-
const path =
|
|
18989
|
+
const path = join20(dir, "settings.json");
|
|
19207
18990
|
let text;
|
|
19208
18991
|
try {
|
|
19209
18992
|
text = readFileSync13(path, "utf8");
|
|
@@ -19218,7 +19001,7 @@ function migrationPlan(home, link, env = process.env) {
|
|
|
19218
19001
|
}
|
|
19219
19002
|
var backupFor = (home, path) => {
|
|
19220
19003
|
const rel = relative(home, path);
|
|
19221
|
-
return rel.startsWith("..") || isAbsolute2(rel) ?
|
|
19004
|
+
return rel.startsWith("..") || isAbsolute2(rel) ? join20(migrateBakDir(home), "abs", path) : join20(migrateBakDir(home), rel);
|
|
19222
19005
|
};
|
|
19223
19006
|
function writeKeepingMode(path, text) {
|
|
19224
19007
|
let mode = 420;
|
|
@@ -19235,7 +19018,7 @@ function copyInto(from, to) {
|
|
|
19235
19018
|
renameSync9(tmp, to);
|
|
19236
19019
|
}
|
|
19237
19020
|
function pointLink(link, bin) {
|
|
19238
|
-
mkdirSync14(
|
|
19021
|
+
mkdirSync14(dirname12(link), { recursive: true, mode: 448 });
|
|
19239
19022
|
const tmp = `${link}.tmp`;
|
|
19240
19023
|
rmSync7(tmp, { force: true });
|
|
19241
19024
|
symlinkSync(bin, tmp);
|
|
@@ -19260,7 +19043,7 @@ function reloadScript(lock, files) {
|
|
|
19260
19043
|
for (const a of agents)
|
|
19261
19044
|
lines.push(`launchctl unload ${shQuote(a.path)} 2>/dev/null; launchctl load ${shQuote(a.path)}`);
|
|
19262
19045
|
if (units.length)
|
|
19263
|
-
lines.push("systemctl --user daemon-reload", `systemctl --user --no-block restart ${units.map((u) => shQuote(
|
|
19046
|
+
lines.push("systemctl --user daemon-reload", `systemctl --user --no-block restart ${units.map((u) => shQuote(basename5(u.path))).join(" ")}`);
|
|
19264
19047
|
if (!lines.length)
|
|
19265
19048
|
return null;
|
|
19266
19049
|
return [
|
|
@@ -19354,7 +19137,7 @@ async function migrateToBinary(o) {
|
|
|
19354
19137
|
rmSync7(migrateBakDir(home), { recursive: true, force: true });
|
|
19355
19138
|
for (const p of plan) {
|
|
19356
19139
|
const backup = backupFor(home, p.path);
|
|
19357
|
-
mkdirSync14(
|
|
19140
|
+
mkdirSync14(dirname12(backup), { recursive: true, mode: 448 });
|
|
19358
19141
|
copyFileSync(p.path, backup);
|
|
19359
19142
|
manifest.files.push({ path: p.path, backup, ...p.reload ? { reload: p.reload } : {} });
|
|
19360
19143
|
}
|
|
@@ -19388,7 +19171,7 @@ async function migrateToBinary(o) {
|
|
|
19388
19171
|
log(`sleds stays on the npm install: ${result.why}`);
|
|
19389
19172
|
return { ok: false, why: result.why };
|
|
19390
19173
|
}
|
|
19391
|
-
const binDir =
|
|
19174
|
+
const binDir = dirname12(link);
|
|
19392
19175
|
if (!(env.PATH ?? "").split(delimiter2).includes(binDir))
|
|
19393
19176
|
log(`${binDir} is not on your PATH — add it in your shell profile to run this sleds from a terminal (sleds never edits it)`);
|
|
19394
19177
|
reload(home, result.files, detach);
|
|
@@ -19408,10 +19191,10 @@ import {
|
|
|
19408
19191
|
symlinkSync as symlinkSync2
|
|
19409
19192
|
} from "node:fs";
|
|
19410
19193
|
import { homedir as homedir5 } from "node:os";
|
|
19411
|
-
import { dirname as
|
|
19194
|
+
import { dirname as dirname13, join as join21 } from "node:path";
|
|
19412
19195
|
var NO_PREVIOUS = "no previous version on this machine";
|
|
19413
19196
|
function allStateFiles(home = homedir5(), env = process.env) {
|
|
19414
|
-
const roots = [...new Set([configDir(home, env),
|
|
19197
|
+
const roots = [...new Set([configDir(home, env), join21(home, ".config", "sleds")])];
|
|
19415
19198
|
const out = [];
|
|
19416
19199
|
const walk = (dir) => {
|
|
19417
19200
|
let names;
|
|
@@ -19422,20 +19205,20 @@ function allStateFiles(home = homedir5(), env = process.env) {
|
|
|
19422
19205
|
}
|
|
19423
19206
|
for (const n of names.sort())
|
|
19424
19207
|
if (n.endsWith(".json") && n !== "removed-engines.json")
|
|
19425
|
-
out.push(
|
|
19208
|
+
out.push(join21(dir, n));
|
|
19426
19209
|
for (const sub of ["orgs", "seats"]) {
|
|
19427
19210
|
let kids;
|
|
19428
19211
|
try {
|
|
19429
|
-
kids = readdirSync3(
|
|
19212
|
+
kids = readdirSync3(join21(dir, sub));
|
|
19430
19213
|
} catch {
|
|
19431
19214
|
continue;
|
|
19432
19215
|
}
|
|
19433
19216
|
for (const k of kids.sort())
|
|
19434
|
-
walk(
|
|
19217
|
+
walk(join21(dir, sub, k));
|
|
19435
19218
|
}
|
|
19436
19219
|
};
|
|
19437
19220
|
for (const r of roots)
|
|
19438
|
-
walk(
|
|
19221
|
+
walk(join21(r, "engine"));
|
|
19439
19222
|
return out;
|
|
19440
19223
|
}
|
|
19441
19224
|
var backupPath2 = (file, v) => `${file}.${v}.bak`;
|
|
@@ -19449,7 +19232,7 @@ function pointBinAt(home, v, platform) {
|
|
|
19449
19232
|
const target = versionBin(home, v, platform);
|
|
19450
19233
|
if (!existsSync14(target))
|
|
19451
19234
|
throw new Error(`${target} is missing — sleds ${v} is not downloaded`);
|
|
19452
|
-
mkdirSync15(
|
|
19235
|
+
mkdirSync15(dirname13(bin), { recursive: true, mode: 448 });
|
|
19453
19236
|
if (platform === "win32") {
|
|
19454
19237
|
replaceAside(bin, target);
|
|
19455
19238
|
return;
|
|
@@ -19521,7 +19304,7 @@ function applyConfirm(s, home, o = {}) {
|
|
|
19521
19304
|
if (!s.current)
|
|
19522
19305
|
return;
|
|
19523
19306
|
for (const f of o.stateFiles ?? allStateFiles(home)) {
|
|
19524
|
-
const dir =
|
|
19307
|
+
const dir = dirname13(f);
|
|
19525
19308
|
const prefix = `${f.slice(dir.length + 1)}.`;
|
|
19526
19309
|
let names;
|
|
19527
19310
|
try {
|
|
@@ -19531,10 +19314,10 @@ function applyConfirm(s, home, o = {}) {
|
|
|
19531
19314
|
}
|
|
19532
19315
|
for (const n of names)
|
|
19533
19316
|
if (n.startsWith(prefix) && n.endsWith(".bak"))
|
|
19534
|
-
rmSync8(
|
|
19317
|
+
rmSync8(join21(dir, n), { force: true });
|
|
19535
19318
|
}
|
|
19536
19319
|
const keep = new Set([s.current, s.previous, s.drain?.to].filter(Boolean));
|
|
19537
|
-
const versions =
|
|
19320
|
+
const versions = dirname13(versionDir(home, s.current, platform));
|
|
19538
19321
|
let names = [];
|
|
19539
19322
|
try {
|
|
19540
19323
|
names = readdirSync3(versions);
|
|
@@ -19803,7 +19586,7 @@ async function machineAnswer(client, tokens) {
|
|
|
19803
19586
|
var FETCH_LOCK_TOUCH_MS = 30000;
|
|
19804
19587
|
async function fetchOnce(o) {
|
|
19805
19588
|
const dir = versionDir(o.home, o.version, o.platform);
|
|
19806
|
-
const lock =
|
|
19589
|
+
const lock = join22(dir, "fetch.lock");
|
|
19807
19590
|
mkdirSync16(dir, { recursive: true, mode: 493 });
|
|
19808
19591
|
let fd;
|
|
19809
19592
|
try {
|
|
@@ -20038,7 +19821,7 @@ function engineUpdater(o) {
|
|
|
20038
19821
|
|
|
20039
19822
|
// src/version.ts
|
|
20040
19823
|
function cliVersion(env) {
|
|
20041
|
-
return "0.1.
|
|
19824
|
+
return "0.1.72";
|
|
20042
19825
|
}
|
|
20043
19826
|
|
|
20044
19827
|
// src/commands/update.ts
|
|
@@ -20329,7 +20112,7 @@ function flagsFromProfile(flags, given, profile, home) {
|
|
|
20329
20112
|
}
|
|
20330
20113
|
}
|
|
20331
20114
|
if (profile.reposDir && !has("repos-dir") && !has("repo")) {
|
|
20332
|
-
out.reposDir = splitReposDirs(profile.reposDir).map((d) => home && /^~(\/|$)/.test(d) ?
|
|
20115
|
+
out.reposDir = splitReposDirs(profile.reposDir).map((d) => home && /^~(\/|$)/.test(d) ? join23(home, d.slice(1)) : d).join(":");
|
|
20333
20116
|
used.push(`repos ${profile.reposDir}`);
|
|
20334
20117
|
}
|
|
20335
20118
|
if (profile.mcpStrict !== undefined && !has("strict-mcp") && !has("no-strict-mcp")) {
|
|
@@ -20424,7 +20207,7 @@ function engineClient(o, org, breaker) {
|
|
|
20424
20207
|
...src,
|
|
20425
20208
|
...breaker ? { fetchFn: breaker.fetch } : {},
|
|
20426
20209
|
timeoutMs: ENGINE_TIMEOUT_MS,
|
|
20427
|
-
version: "0.1.
|
|
20210
|
+
version: "0.1.72"
|
|
20428
20211
|
});
|
|
20429
20212
|
const asked = org?.trim() || env.SLEDS_ORG?.trim();
|
|
20430
20213
|
if (asked && !selectOrg(readConfig(o.home), org, env).seat)
|
|
@@ -20464,12 +20247,12 @@ function memberMcpConfigs(o, cwd) {
|
|
|
20464
20247
|
});
|
|
20465
20248
|
const claudeDir = (o.env ?? process.env).CLAUDE_CONFIG_DIR;
|
|
20466
20249
|
return [
|
|
20467
|
-
read(claudeDir ?
|
|
20468
|
-
...cwd ? [read(
|
|
20250
|
+
read(claudeDir ? join23(claudeDir, ".claude.json") : join23(o.home, ".claude.json")),
|
|
20251
|
+
...cwd ? [read(join23(cwd, ".mcp.json"))] : []
|
|
20469
20252
|
];
|
|
20470
20253
|
}
|
|
20471
20254
|
function engineStateDir(o, org, seat) {
|
|
20472
|
-
return seatStateDir(orgStateDir(o.stateDir ??
|
|
20255
|
+
return seatStateDir(orgStateDir(o.stateDir ?? join23(configDir(o.home, o.env ?? process.env), "engine"), org), seat);
|
|
20473
20256
|
}
|
|
20474
20257
|
function engineSeat(o, org) {
|
|
20475
20258
|
try {
|
|
@@ -20499,9 +20282,9 @@ function engineDeps(o, flags, source, runner, stateName) {
|
|
|
20499
20282
|
const repo = flags.repo ? resolve8(cwd, flags.repo) : undefined;
|
|
20500
20283
|
const reposDirs = splitReposDirs(flags.reposDir).map((d) => resolve8(cwd, d));
|
|
20501
20284
|
const { branch, prTitle } = flags;
|
|
20502
|
-
const hooksDir =
|
|
20285
|
+
const hooksDir = join23(stateDir, "hooks");
|
|
20503
20286
|
const pnpmStores = new Map;
|
|
20504
|
-
const permissionMark = (name) =>
|
|
20287
|
+
const permissionMark = (name) => join23(hooksDir, `${name}.permission.json`);
|
|
20505
20288
|
const withHook = (name, settings) => applyPermissionHook(settings, [...o.sledsArgv ?? ["sleds"], "permission-event", "--mark", permissionMark(name)].map(shq2).join(" "));
|
|
20506
20289
|
return {
|
|
20507
20290
|
source,
|
|
@@ -20526,9 +20309,9 @@ function engineDeps(o, flags, source, runner, stateName) {
|
|
|
20526
20309
|
sandbox: true,
|
|
20527
20310
|
writeSandboxSettings: o.writeSandboxSettings ?? ((name, cwd, allow, readOnly) => {
|
|
20528
20311
|
const gitCommonDir = gitCommonDirOf(exec, cwd);
|
|
20529
|
-
const dir =
|
|
20312
|
+
const dir = join23(stateDir, "sandbox");
|
|
20530
20313
|
mkdirSync17(dir, { recursive: true, mode: 448 });
|
|
20531
|
-
const p =
|
|
20314
|
+
const p = join23(dir, `${name}.json`);
|
|
20532
20315
|
const walls = engineSandboxSettings(o.home, o.env ?? process.env, gitCommonDir, [
|
|
20533
20316
|
...SANDBOX_DEFAULT_ALLOW,
|
|
20534
20317
|
...flags.sandboxAllow ?? []
|
|
@@ -20551,7 +20334,7 @@ function engineDeps(o, flags, source, runner, stateName) {
|
|
|
20551
20334
|
} : {},
|
|
20552
20335
|
writeHookSettings: (name, allow, readOnly) => {
|
|
20553
20336
|
mkdirSync17(hooksDir, { recursive: true, mode: 448 });
|
|
20554
|
-
const p =
|
|
20337
|
+
const p = join23(hooksDir, `${name}.json`);
|
|
20555
20338
|
const deny = readOnlyDenyRules(readOnly ?? []);
|
|
20556
20339
|
const permissions = {
|
|
20557
20340
|
...allow?.length ? { allow: [...allow] } : {},
|
|
@@ -20578,9 +20361,9 @@ function engineDeps(o, flags, source, runner, stateName) {
|
|
|
20578
20361
|
exists
|
|
20579
20362
|
}),
|
|
20580
20363
|
writeMcpConfig: o.writeMcpConfig ?? ((name, runToken, worktree) => {
|
|
20581
|
-
const dir =
|
|
20364
|
+
const dir = join23(stateDir, "mcp");
|
|
20582
20365
|
mkdirSync17(dir, { recursive: true, mode: 448 });
|
|
20583
|
-
const p =
|
|
20366
|
+
const p = join23(dir, `${name}.json`);
|
|
20584
20367
|
let others = {};
|
|
20585
20368
|
if (flags.strictMcp && flags.mcpAllow?.length) {
|
|
20586
20369
|
const r = mcpPassThrough(flags.mcpAllow, memberMcpConfigs(o, worktree));
|
|
@@ -20596,16 +20379,16 @@ function engineDeps(o, flags, source, runner, stateName) {
|
|
|
20596
20379
|
}),
|
|
20597
20380
|
removeMcpConfig: o.removeMcpConfig ?? ((p) => rmSync10(p, { force: true })),
|
|
20598
20381
|
writePrompt: o.writePrompt ?? ((name, text) => {
|
|
20599
|
-
const dir =
|
|
20382
|
+
const dir = join23(stateDir, "prompts");
|
|
20600
20383
|
mkdirSync17(dir, { recursive: true, mode: 448 });
|
|
20601
|
-
const p =
|
|
20384
|
+
const p = join23(dir, `${name}.md`);
|
|
20602
20385
|
writeFileSync15(p, text, { mode: 384 });
|
|
20603
20386
|
return p;
|
|
20604
20387
|
}),
|
|
20605
20388
|
mockOut: (name) => {
|
|
20606
|
-
const dir =
|
|
20389
|
+
const dir = join23(tmpdir(), "sleds-mocks");
|
|
20607
20390
|
mkdirSync17(dir, { recursive: true, mode: 448 });
|
|
20608
|
-
const p =
|
|
20391
|
+
const p = join23(dir, `${name}.html`);
|
|
20609
20392
|
rmSync10(p, { force: true });
|
|
20610
20393
|
return p;
|
|
20611
20394
|
},
|
|
@@ -20640,14 +20423,14 @@ function engineDeps(o, flags, source, runner, stateName) {
|
|
|
20640
20423
|
}
|
|
20641
20424
|
function sandboxDenyRead(home, env) {
|
|
20642
20425
|
return {
|
|
20643
|
-
dirs: [...new Set([configDir(home, env),
|
|
20426
|
+
dirs: [...new Set([configDir(home, env), join23(home, ".config", "sleds")])],
|
|
20644
20427
|
files: [
|
|
20645
20428
|
...new Set([
|
|
20646
20429
|
tokenPath(home, env),
|
|
20647
|
-
|
|
20430
|
+
join23(home, ".sleds-token"),
|
|
20648
20431
|
settingsPath(home, env),
|
|
20649
20432
|
backupPath(home, env),
|
|
20650
|
-
|
|
20433
|
+
join23(claudeDir(home, env), "settings.local.json")
|
|
20651
20434
|
])
|
|
20652
20435
|
]
|
|
20653
20436
|
};
|
|
@@ -20689,7 +20472,7 @@ function engineReadDirs(exec, cwd, exists, stores) {
|
|
|
20689
20472
|
})();
|
|
20690
20473
|
const pnpmStore = (() => {
|
|
20691
20474
|
try {
|
|
20692
|
-
if (!exists(
|
|
20475
|
+
if (!exists(join23(cwd, "pnpm-lock.yaml")))
|
|
20693
20476
|
return null;
|
|
20694
20477
|
const key = common ?? cwd;
|
|
20695
20478
|
const known = stores.get(key);
|
|
@@ -20714,7 +20497,7 @@ function engineReadDirs(exec, cwd, exists, stores) {
|
|
|
20714
20497
|
}
|
|
20715
20498
|
var LENT_NEEDS_SANDBOX = "a lent engine runs every session sandboxed (spec 48 rule 10) — add --sandbox to --lent-by";
|
|
20716
20499
|
function lenderHome(accountHome, lentBy) {
|
|
20717
|
-
return isAbsolute3(lentBy) ? resolve8(lentBy) :
|
|
20500
|
+
return isAbsolute3(lentBy) ? resolve8(lentBy) : join23(dirname14(accountHome), lentBy);
|
|
20718
20501
|
}
|
|
20719
20502
|
function lentHomeProblems(accountHome, lentBy, modeOf) {
|
|
20720
20503
|
const lender = lenderHome(accountHome, lentBy);
|
|
@@ -20782,7 +20565,7 @@ async function driveEngine(o, flags, deps, until = {}) {
|
|
|
20782
20565
|
runner: deps.runner.name,
|
|
20783
20566
|
atOnce: flags.atOnce,
|
|
20784
20567
|
interval: flags.interval,
|
|
20785
|
-
cliVersion: "0.1.
|
|
20568
|
+
cliVersion: "0.1.72"
|
|
20786
20569
|
};
|
|
20787
20570
|
const beat = (checkedAt) => {
|
|
20788
20571
|
const m = deps.machine;
|
|
@@ -21004,126 +20787,562 @@ function parsePauseArgs(argv, host) {
|
|
|
21004
20787
|
} else
|
|
21005
20788
|
return { error: `unknown argument ${a}` };
|
|
21006
20789
|
}
|
|
21007
|
-
return {
|
|
21008
|
-
name: got.name ?? defaultEngineName(host),
|
|
21009
|
-
json,
|
|
21010
|
-
...got.org ? { org: got.org } : {},
|
|
21011
|
-
...got.why ? { why: got.why } : {}
|
|
21012
|
-
};
|
|
21013
|
-
}
|
|
21014
|
-
var isRunning = (r) => !r.pr && !r.parked;
|
|
21015
|
-
async function releaseRunning(o) {
|
|
21016
|
-
const state = o.read();
|
|
21017
|
-
const out = { released: 0, kept: [], errors: [] };
|
|
21018
|
-
const gone = new Set;
|
|
21019
|
-
for (const run of state.runs.filter(isRunning)) {
|
|
21020
|
-
const at = `${run.item}/${run.node}`;
|
|
21021
|
-
const runner = o.runnerFor ? o.runnerFor(run.handle.runner, o.exec) : restoreRunner(run.handle.runner, o.exec);
|
|
21022
|
-
try {
|
|
21023
|
-
runner?.stop(run.handle);
|
|
21024
|
-
} catch (e) {
|
|
21025
|
-
o.log(`${at}: could not stop the session: ${e instanceof Error ? e.message : String(e)}`);
|
|
21026
|
-
}
|
|
21027
|
-
try {
|
|
21028
|
-
await o.source.report(claimOf(run), { kind: "release", why: o.why }, o.engine);
|
|
21029
|
-
} catch (e) {
|
|
21030
|
-
out.errors.push(`${at}: ${e instanceof Error ? e.message : String(e)}`);
|
|
21031
|
-
continue;
|
|
21032
|
-
}
|
|
21033
|
-
gone.add(run);
|
|
21034
|
-
out.released++;
|
|
21035
|
-
out.kept.push(run.handle.cwd);
|
|
21036
|
-
if (run.mcpConfig)
|
|
21037
|
-
rmSync10(run.mcpConfig, { force: true });
|
|
20790
|
+
return {
|
|
20791
|
+
name: got.name ?? defaultEngineName(host),
|
|
20792
|
+
json,
|
|
20793
|
+
...got.org ? { org: got.org } : {},
|
|
20794
|
+
...got.why ? { why: got.why } : {}
|
|
20795
|
+
};
|
|
20796
|
+
}
|
|
20797
|
+
var isRunning = (r) => !r.pr && !r.parked;
|
|
20798
|
+
async function releaseRunning(o) {
|
|
20799
|
+
const state = o.read();
|
|
20800
|
+
const out = { released: 0, kept: [], errors: [] };
|
|
20801
|
+
const gone = new Set;
|
|
20802
|
+
for (const run of state.runs.filter(isRunning)) {
|
|
20803
|
+
const at = `${run.item}/${run.node}`;
|
|
20804
|
+
const runner = o.runnerFor ? o.runnerFor(run.handle.runner, o.exec) : restoreRunner(run.handle.runner, o.exec);
|
|
20805
|
+
try {
|
|
20806
|
+
runner?.stop(run.handle);
|
|
20807
|
+
} catch (e) {
|
|
20808
|
+
o.log(`${at}: could not stop the session: ${e instanceof Error ? e.message : String(e)}`);
|
|
20809
|
+
}
|
|
20810
|
+
try {
|
|
20811
|
+
await o.source.report(claimOf(run), { kind: "release", why: o.why }, o.engine);
|
|
20812
|
+
} catch (e) {
|
|
20813
|
+
out.errors.push(`${at}: ${e instanceof Error ? e.message : String(e)}`);
|
|
20814
|
+
continue;
|
|
20815
|
+
}
|
|
20816
|
+
gone.add(run);
|
|
20817
|
+
out.released++;
|
|
20818
|
+
out.kept.push(run.handle.cwd);
|
|
20819
|
+
if (run.mcpConfig)
|
|
20820
|
+
rmSync10(run.mcpConfig, { force: true });
|
|
20821
|
+
}
|
|
20822
|
+
if (gone.size)
|
|
20823
|
+
o.write({ ...state, runs: state.runs.filter((r) => !gone.has(r)) });
|
|
20824
|
+
return out;
|
|
20825
|
+
}
|
|
20826
|
+
var PAUSE_WAIT_MS = 90000;
|
|
20827
|
+
async function enginePauseCmd(o) {
|
|
20828
|
+
const log = o.log ?? console.log;
|
|
20829
|
+
const error = o.error ?? console.error;
|
|
20830
|
+
const host = o.host ?? hostname();
|
|
20831
|
+
const parsed = parsePauseArgs(o.argv, host);
|
|
20832
|
+
if ("error" in parsed) {
|
|
20833
|
+
error(parsed.error);
|
|
20834
|
+
error(ENGINE_PAUSE_USAGE);
|
|
20835
|
+
return 2;
|
|
20836
|
+
}
|
|
20837
|
+
const engine = `engine:${parsed.name}`;
|
|
20838
|
+
const which = engineOrg(o, parsed.org);
|
|
20839
|
+
const org = which.slug && (which.seated || parsed.org) ? which.slug : null;
|
|
20840
|
+
const seat = engineSeat(o, org ?? undefined) ?? null;
|
|
20841
|
+
const seatDir = engineStateDir(o, org, seat);
|
|
20842
|
+
const orgDir = engineStateDir(o, org);
|
|
20843
|
+
const has = (d) => realExists(statePath(d, engine)) || realExists(lockPath(d, engine));
|
|
20844
|
+
const dir = !has(seatDir) && has(orgDir) ? orgDir : seatDir;
|
|
20845
|
+
const alive = o.pidAlive ?? realPidAlive2;
|
|
20846
|
+
const sleep = o.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
20847
|
+
const kill = o.kill ?? ((pid, sig) => void process.kill(pid, sig));
|
|
20848
|
+
const lock = readLock(lockPath(dir, engine));
|
|
20849
|
+
let stopped = false;
|
|
20850
|
+
if (lock && lock.host === host && lock.pid !== process.pid && alive(lock.pid)) {
|
|
20851
|
+
try {
|
|
20852
|
+
kill(lock.pid, "SIGTERM");
|
|
20853
|
+
} catch {}
|
|
20854
|
+
for (let waited = 0;alive(lock.pid) && waited < PAUSE_WAIT_MS; waited += 250)
|
|
20855
|
+
await sleep(250);
|
|
20856
|
+
if (alive(lock.pid)) {
|
|
20857
|
+
error(`${engine} (pid ${lock.pid}) did not stop within ${PAUSE_WAIT_MS / 1000} s — nothing was paused. Try again, or stop it by hand.`);
|
|
20858
|
+
return 1;
|
|
20859
|
+
}
|
|
20860
|
+
stopped = true;
|
|
20861
|
+
}
|
|
20862
|
+
const file = statePath(dir, engine);
|
|
20863
|
+
const state = readState(file);
|
|
20864
|
+
const result = {
|
|
20865
|
+
released: 0,
|
|
20866
|
+
kept: [],
|
|
20867
|
+
following: 0,
|
|
20868
|
+
parked: 0,
|
|
20869
|
+
stopped,
|
|
20870
|
+
errors: []
|
|
20871
|
+
};
|
|
20872
|
+
result.following = state.runs.filter((r) => r.pr).length;
|
|
20873
|
+
result.parked = state.runs.filter((r) => r.parked).length;
|
|
20874
|
+
let source = o.source;
|
|
20875
|
+
if (state.runs.some(isRunning) && !source) {
|
|
20876
|
+
const c = orgClient(o, parsed.org);
|
|
20877
|
+
if ("error" in c) {
|
|
20878
|
+
error(c.error);
|
|
20879
|
+
return 1;
|
|
20880
|
+
}
|
|
20881
|
+
source = sledsSource(c, { engine, log });
|
|
20882
|
+
}
|
|
20883
|
+
if (source) {
|
|
20884
|
+
const r = await releaseRunning({
|
|
20885
|
+
read: () => state,
|
|
20886
|
+
write: (next) => writeState(file, next),
|
|
20887
|
+
source,
|
|
20888
|
+
engine,
|
|
20889
|
+
why: parsed.why ?? `paused on ${defaultEngineName(host)} (sleds engine pause)`,
|
|
20890
|
+
exec: guardGit(o.exec ?? defaultExec),
|
|
20891
|
+
...o.runnerFor ? { runnerFor: o.runnerFor } : {},
|
|
20892
|
+
log
|
|
20893
|
+
});
|
|
20894
|
+
result.released = r.released;
|
|
20895
|
+
result.kept = r.kept;
|
|
20896
|
+
result.errors = r.errors;
|
|
20897
|
+
}
|
|
20898
|
+
if (parsed.json)
|
|
20899
|
+
log(JSON.stringify(result, null, 2));
|
|
20900
|
+
else {
|
|
20901
|
+
const n = (k, one) => `${k} ${one}${k === 1 ? "" : "s"}`;
|
|
20902
|
+
log(`${engine} paused${seat ? ` (${seat})` : ""}: ${stopped ? "the engine stopped" : "the engine was not running"} · ${n(result.released, "session")} released · ${n(result.following, "PR")} still followed · ${n(result.parked, "parked session")} kept`);
|
|
20903
|
+
for (const w of result.kept)
|
|
20904
|
+
log(` kept ${w}`);
|
|
20905
|
+
for (const e of result.errors)
|
|
20906
|
+
error(` not released, retry with \`sleds engine pause\`: ${e}`);
|
|
20907
|
+
}
|
|
20908
|
+
return result.errors.length ? 1 : 0;
|
|
20909
|
+
}
|
|
20910
|
+
|
|
20911
|
+
// src/commands/attach.ts
|
|
20912
|
+
var ATTACH_USAGE = "usage: sleds attach <key> --file <path> [--kind screenshot|prototype|spec|doc|other] [--mock] [--json]";
|
|
20913
|
+
var ATTACH_MAX_BYTES = 4 * 1024 * 1024;
|
|
20914
|
+
var KINDS2 = new Set(["spec", "prototype", "screenshot", "doc", "other"]);
|
|
20915
|
+
function parseAttachArgs(argv) {
|
|
20916
|
+
let key;
|
|
20917
|
+
let file;
|
|
20918
|
+
let kind;
|
|
20919
|
+
let mock = false;
|
|
20920
|
+
let json = false;
|
|
20921
|
+
for (let i = 0;i < argv.length; i++) {
|
|
20922
|
+
const a = argv[i];
|
|
20923
|
+
if (a === "--json")
|
|
20924
|
+
json = true;
|
|
20925
|
+
else if (a === "--mock")
|
|
20926
|
+
mock = true;
|
|
20927
|
+
else if (a === "--file" || a === "--kind") {
|
|
20928
|
+
const value = argv[i + 1];
|
|
20929
|
+
if (value === undefined || value.startsWith("--"))
|
|
20930
|
+
return { error: `${a} needs a value` };
|
|
20931
|
+
if (a === "--file")
|
|
20932
|
+
file = value;
|
|
20933
|
+
else if (KINDS2.has(value))
|
|
20934
|
+
kind = value;
|
|
20935
|
+
else
|
|
20936
|
+
return { error: `--kind is one of ${[...KINDS2].join(", ")}` };
|
|
20937
|
+
i++;
|
|
20938
|
+
} else if (a.startsWith("--"))
|
|
20939
|
+
return { error: `unknown flag ${a}` };
|
|
20940
|
+
else if (key === undefined)
|
|
20941
|
+
key = a;
|
|
20942
|
+
else
|
|
20943
|
+
return { error: `one item and one --file at a time (${a}?)` };
|
|
20944
|
+
}
|
|
20945
|
+
if (!key)
|
|
20946
|
+
return { error: "which item?" };
|
|
20947
|
+
if (!file)
|
|
20948
|
+
return { error: "--file names the file to put on the item" };
|
|
20949
|
+
return { key, file, ...kind ? { kind } : {}, mock, json };
|
|
20950
|
+
}
|
|
20951
|
+
function attachEncoding(mime) {
|
|
20952
|
+
return /^text\/|^application\/json$|^image\/svg\+xml$/.test(mime) ? "text" : "base64";
|
|
20953
|
+
}
|
|
20954
|
+
async function attachCmd(o) {
|
|
20955
|
+
const log = o.log ?? console.log;
|
|
20956
|
+
const error = o.error ?? console.error;
|
|
20957
|
+
const a = parseAttachArgs(o.argv);
|
|
20958
|
+
if ("error" in a) {
|
|
20959
|
+
error(a.error);
|
|
20960
|
+
error(ATTACH_USAGE);
|
|
20961
|
+
return 2;
|
|
20962
|
+
}
|
|
20963
|
+
let bytes;
|
|
20964
|
+
try {
|
|
20965
|
+
if (!o.readFile && statSync7(a.file).size > ATTACH_MAX_BYTES) {
|
|
20966
|
+
error(`${a.file}: a file on an item is at most 4 MB`);
|
|
20967
|
+
return 1;
|
|
20968
|
+
}
|
|
20969
|
+
bytes = (o.readFile ?? readFileSync16)(a.file);
|
|
20970
|
+
} catch {
|
|
20971
|
+
error(`${a.file}: cannot read it`);
|
|
20972
|
+
return 1;
|
|
20973
|
+
}
|
|
20974
|
+
if (bytes.byteLength > ATTACH_MAX_BYTES) {
|
|
20975
|
+
error(`${a.file}: a file on an item is at most 4 MB`);
|
|
20976
|
+
return 1;
|
|
20977
|
+
}
|
|
20978
|
+
const name = basename6(a.file);
|
|
20979
|
+
const mime = mimeFromName(name);
|
|
20980
|
+
const encoding = attachEncoding(mime);
|
|
20981
|
+
const client = engineClient({ home: o.home, ...o.client ? { client: o.client } : {} });
|
|
20982
|
+
if ("error" in client) {
|
|
20983
|
+
error(client.error);
|
|
20984
|
+
return 1;
|
|
20985
|
+
}
|
|
20986
|
+
const r = await client.postFull("/proxy/asset", {
|
|
20987
|
+
project: a.key,
|
|
20988
|
+
name,
|
|
20989
|
+
mime,
|
|
20990
|
+
content: encoding === "base64" ? bytes.toString("base64") : bytes.toString("utf8"),
|
|
20991
|
+
...encoding === "base64" ? { encoding } : {},
|
|
20992
|
+
...a.kind ? { kind: a.kind } : {},
|
|
20993
|
+
...a.mock ? { mock: true } : {}
|
|
20994
|
+
});
|
|
20995
|
+
if (!r) {
|
|
20996
|
+
error(`${a.key}: SLEDS unreachable — nothing stored`);
|
|
20997
|
+
return 1;
|
|
20998
|
+
}
|
|
20999
|
+
if (a.json)
|
|
21000
|
+
log(JSON.stringify(r.json ?? { ok: false, error: `HTTP ${r.status}` }));
|
|
21001
|
+
if (r.status >= 300) {
|
|
21002
|
+
const why = typeof r.json?.error === "string" ? r.json.error : `HTTP ${r.status}`;
|
|
21003
|
+
if (!a.json)
|
|
21004
|
+
error(r.status === 404 && !r.json ? `${a.key}: SLEDS does not know this seat — run \`sleds init\`` : `${a.key}: ${why}`);
|
|
21005
|
+
return 1;
|
|
21006
|
+
}
|
|
21007
|
+
const url = typeof r.json?.url === "string" ? r.json.url : "";
|
|
21008
|
+
if (!a.json)
|
|
21009
|
+
log(url || `${name} is on ${a.key}`);
|
|
21010
|
+
return 0;
|
|
21011
|
+
}
|
|
21012
|
+
|
|
21013
|
+
// src/commands/verify.ts
|
|
21014
|
+
init_meter();
|
|
21015
|
+
import { readFileSync as readFileSync17, statSync as statSync8 } from "node:fs";
|
|
21016
|
+
import { basename as basename8, extname } from "node:path";
|
|
21017
|
+
|
|
21018
|
+
// src/musher.ts
|
|
21019
|
+
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
21020
|
+
import { createPublicKey as createPublicKey2, verify as cryptoVerify } from "node:crypto";
|
|
21021
|
+
import { basename as basename7, dirname as dirname15, join as join24 } from "node:path";
|
|
21022
|
+
var MUSHER_LABEL = "ai.sleds.musher";
|
|
21023
|
+
var MUSHER_INTERVAL_S = 300;
|
|
21024
|
+
var DEFAULT_PERMISSION_MODE = "acceptEdits";
|
|
21025
|
+
var PERMISSION_MODES = [
|
|
21026
|
+
"acceptEdits",
|
|
21027
|
+
"auto",
|
|
21028
|
+
"bypassPermissions",
|
|
21029
|
+
"default",
|
|
21030
|
+
"dontAsk",
|
|
21031
|
+
"plan"
|
|
21032
|
+
];
|
|
21033
|
+
var DEFAULT_TIMEOUT_MINUTES = 90;
|
|
21034
|
+
var SUMMARY_MAX = 2000;
|
|
21035
|
+
var musherLabel = (env = process.env) => {
|
|
21036
|
+
const sh = env.SLEDS_HOME?.trim();
|
|
21037
|
+
if (!sh)
|
|
21038
|
+
return MUSHER_LABEL;
|
|
21039
|
+
const tag = basename7(sh).replace(/^\.+/, "").replace(/[^A-Za-z0-9_-]+/g, "-") || "seat";
|
|
21040
|
+
return `${MUSHER_LABEL}.${tag}`;
|
|
21041
|
+
};
|
|
21042
|
+
var musherPlistPath = (home, env = process.env) => join24(home, "Library", "LaunchAgents", `${musherLabel(env)}.plist`);
|
|
21043
|
+
var musherLogPath = (configDir) => join24(configDir, "musher.log");
|
|
21044
|
+
var xmlEscape3 = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
21045
|
+
var musherPath = (home, execPath, currentPath = "") => {
|
|
21046
|
+
const parts = [
|
|
21047
|
+
dirname15(execPath),
|
|
21048
|
+
join24(home, ".sleds", "bin"),
|
|
21049
|
+
join24(home, ".local", "bin"),
|
|
21050
|
+
join24(home, ".bun", "bin"),
|
|
21051
|
+
"/opt/homebrew/bin",
|
|
21052
|
+
"/usr/local/bin",
|
|
21053
|
+
"/usr/bin",
|
|
21054
|
+
"/bin",
|
|
21055
|
+
...currentPath.split(":").filter(Boolean)
|
|
21056
|
+
];
|
|
21057
|
+
return [...new Set(parts)].join(":");
|
|
21058
|
+
};
|
|
21059
|
+
var buildMusherPlist = (o) => {
|
|
21060
|
+
const label = o.label ?? MUSHER_LABEL;
|
|
21061
|
+
const args = [...o.sledsArgv, "musher", "tick"].map((a) => ` <string>${xmlEscape3(a)}</string>`).join(`
|
|
21062
|
+
`);
|
|
21063
|
+
const env = Object.entries(o.env).filter(([, v]) => v !== "").map(([k, v]) => ` <key>${xmlEscape3(k)}</key>
|
|
21064
|
+
<string>${xmlEscape3(v)}</string>`).join(`
|
|
21065
|
+
`);
|
|
21066
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
21067
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
21068
|
+
<plist version="1.0">
|
|
21069
|
+
<dict>
|
|
21070
|
+
<key>Label</key>
|
|
21071
|
+
<string>${label}</string>
|
|
21072
|
+
<key>ProgramArguments</key>
|
|
21073
|
+
<array>
|
|
21074
|
+
${args}
|
|
21075
|
+
</array>
|
|
21076
|
+
<key>EnvironmentVariables</key>
|
|
21077
|
+
<dict>
|
|
21078
|
+
${env}
|
|
21079
|
+
</dict>
|
|
21080
|
+
<key>StartInterval</key>
|
|
21081
|
+
<integer>${MUSHER_INTERVAL_S}</integer>
|
|
21082
|
+
<key>RunAtLoad</key>
|
|
21083
|
+
<true/>
|
|
21084
|
+
<key>StandardOutPath</key>
|
|
21085
|
+
<string>${xmlEscape3(o.logPath)}</string>
|
|
21086
|
+
<key>StandardErrorPath</key>
|
|
21087
|
+
<string>${xmlEscape3(o.logPath)}</string>
|
|
21088
|
+
</dict>
|
|
21089
|
+
</plist>
|
|
21090
|
+
`;
|
|
21091
|
+
};
|
|
21092
|
+
var RESUME_PROMPT = [
|
|
21093
|
+
"SLEDS musher: the usage limit that stopped this session has reset, and the seat's owner",
|
|
21094
|
+
"scheduled this unattended run to continue it. Pick up exactly where the session left off:",
|
|
21095
|
+
"finish the task that was in flight, run the checks you would normally run, follow the repo's",
|
|
21096
|
+
"own conventions for branches and commits, and do not start unrelated work. If you are blocked",
|
|
21097
|
+
"on a decision only the owner can make, stop there and say so. Finish with a summary under",
|
|
21098
|
+
"200 words: what was done, what remains, anything the owner must decide."
|
|
21099
|
+
].join(" ");
|
|
21100
|
+
var NO_SESSION_PROMPT = [
|
|
21101
|
+
"SLEDS musher: a deferred job started on this seat, but no Claude Code session was recorded",
|
|
21102
|
+
"to resume. Do not guess at work. Reply with one line saying so, and stop."
|
|
21103
|
+
].join(" ");
|
|
21104
|
+
var claudeArgs = (o) => [
|
|
21105
|
+
"-p",
|
|
21106
|
+
o.sessionId ? RESUME_PROMPT : NO_SESSION_PROMPT,
|
|
21107
|
+
...o.sessionId ? ["--resume", o.sessionId] : [],
|
|
21108
|
+
...o.model ? ["--model", o.model] : [],
|
|
21109
|
+
"--output-format",
|
|
21110
|
+
"json",
|
|
21111
|
+
"--permission-mode",
|
|
21112
|
+
o.permissionMode
|
|
21113
|
+
];
|
|
21114
|
+
var parseClaudeOutput = (stdout, exitCode) => {
|
|
21115
|
+
const lines = stdout.split(`
|
|
21116
|
+
`).map((l) => l.trim()).filter(Boolean);
|
|
21117
|
+
for (let i = lines.length - 1;i >= 0; i--) {
|
|
21118
|
+
const line = lines[i] ?? "";
|
|
21119
|
+
if (!line.startsWith("{"))
|
|
21120
|
+
continue;
|
|
21121
|
+
try {
|
|
21122
|
+
const j = JSON.parse(line);
|
|
21123
|
+
if (j.type !== "result" && typeof j.result !== "string")
|
|
21124
|
+
continue;
|
|
21125
|
+
const isError = j.is_error === true || typeof j.subtype === "string" && j.subtype !== "success";
|
|
21126
|
+
const text = typeof j.result === "string" ? j.result : "";
|
|
21127
|
+
const models = j.modelUsage;
|
|
21128
|
+
const model = typeof j.model === "string" ? j.model : models && typeof models === "object" ? Object.keys(models)[0] : undefined;
|
|
21129
|
+
return {
|
|
21130
|
+
ok: !isError && exitCode === 0,
|
|
21131
|
+
summary: (text || (isError ? "Claude Code reported an error" : "")).slice(0, SUMMARY_MAX),
|
|
21132
|
+
...typeof j.session_id === "string" ? { sessionId: j.session_id } : {},
|
|
21133
|
+
...model ? { model } : {},
|
|
21134
|
+
...typeof j.duration_ms === "number" ? { durationMs: j.duration_ms } : {},
|
|
21135
|
+
...typeof j.total_cost_usd === "number" ? { costUsd: j.total_cost_usd } : {}
|
|
21136
|
+
};
|
|
21137
|
+
} catch {}
|
|
21138
|
+
}
|
|
21139
|
+
const tail = lines.slice(-5).join(" ").slice(0, SUMMARY_MAX);
|
|
21140
|
+
return { ok: false, summary: tail || `claude exited ${exitCode ?? "without a code"}` };
|
|
21141
|
+
};
|
|
21142
|
+
var defaultExecCapture = (cmd, args, o) => {
|
|
21143
|
+
const r = spawnSync4(cmd, [...args], {
|
|
21144
|
+
cwd: o.cwd,
|
|
21145
|
+
encoding: "utf8",
|
|
21146
|
+
timeout: o.timeoutMs,
|
|
21147
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
21148
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
21149
|
+
env: { ...process.env, SLEDS_MUSHER: "1" }
|
|
21150
|
+
});
|
|
21151
|
+
const timedOut = r.error?.code === "ETIMEDOUT";
|
|
21152
|
+
return {
|
|
21153
|
+
stdout: r.stdout ?? "",
|
|
21154
|
+
stderr: r.stderr ?? "",
|
|
21155
|
+
status: r.status,
|
|
21156
|
+
...timedOut ? { timedOut } : r.error ? { error: r.error.message } : {}
|
|
21157
|
+
};
|
|
21158
|
+
};
|
|
21159
|
+
var musherClient = (o) => {
|
|
21160
|
+
const fetchFn = o.fetchFn ?? fetch;
|
|
21161
|
+
const headers = { authorization: `Bearer ${o.token}`, "content-type": "application/json" };
|
|
21162
|
+
const call = async (path, body) => {
|
|
21163
|
+
try {
|
|
21164
|
+
const res = await fetchFn(`${o.proxyUrl}${path}`, {
|
|
21165
|
+
method: body === undefined ? "GET" : "POST",
|
|
21166
|
+
headers,
|
|
21167
|
+
...body === undefined ? {} : { body: JSON.stringify(body) },
|
|
21168
|
+
signal: AbortSignal.timeout(o.timeoutMs ?? 1e4)
|
|
21169
|
+
});
|
|
21170
|
+
if (!res.ok)
|
|
21171
|
+
return null;
|
|
21172
|
+
return await res.json();
|
|
21173
|
+
} catch {
|
|
21174
|
+
return null;
|
|
21175
|
+
}
|
|
21176
|
+
};
|
|
21177
|
+
return {
|
|
21178
|
+
list: () => call("/proxy/musher"),
|
|
21179
|
+
start: (jobId, local) => call("/proxy/musher/start", { jobId, ...local }),
|
|
21180
|
+
finish: async (input) => await call("/proxy/musher/finish", input) !== null,
|
|
21181
|
+
defer: (input) => call("/proxy/defer", input),
|
|
21182
|
+
attestation: (jobId) => call(`/proxy/attest/${encodeURIComponent(jobId)}`)
|
|
21183
|
+
};
|
|
21184
|
+
};
|
|
21185
|
+
var gitHead = (cwd, exec) => {
|
|
21186
|
+
if (!cwd)
|
|
21187
|
+
return null;
|
|
21188
|
+
const r = exec("git", ["rev-parse", "HEAD"], { cwd, timeoutMs: 5000 });
|
|
21189
|
+
const sha = r.stdout.trim();
|
|
21190
|
+
return r.status === 0 && /^[0-9a-f]{40}$/.test(sha) ? sha : null;
|
|
21191
|
+
};
|
|
21192
|
+
var gitNewCommits = (cwd, before, after, exec) => {
|
|
21193
|
+
if (!cwd || !after || after === before)
|
|
21194
|
+
return [];
|
|
21195
|
+
if (!before)
|
|
21196
|
+
return [after];
|
|
21197
|
+
const r = exec("git", ["rev-list", `${before}..${after}`], { cwd, timeoutMs: 5000 });
|
|
21198
|
+
if (r.status !== 0)
|
|
21199
|
+
return [after];
|
|
21200
|
+
return r.stdout.split(`
|
|
21201
|
+
`).map((l) => l.trim()).filter((l) => /^[0-9a-f]{40}$/.test(l)).slice(0, 40);
|
|
21202
|
+
};
|
|
21203
|
+
var collectOutputs = (commits, summary) => {
|
|
21204
|
+
const out = commits.map((c) => `git:${c}`);
|
|
21205
|
+
for (const m of summary.matchAll(/https:\/\/github\.com\/[\w.-]+\/[\w.-]+\/pull\/\d+/g))
|
|
21206
|
+
if (!out.includes(`pr:${m[0]}`))
|
|
21207
|
+
out.push(`pr:${m[0]}`);
|
|
21208
|
+
return out.slice(0, 50);
|
|
21209
|
+
};
|
|
21210
|
+
var runJob = async (o) => {
|
|
21211
|
+
const log = o.log ?? (() => {});
|
|
21212
|
+
const sessionId = o.job.claudeSessionId ?? o.fallbackSession?.id ?? null;
|
|
21213
|
+
const cwd = o.job.cwd ?? o.fallbackSession?.cwd ?? undefined;
|
|
21214
|
+
const started = await o.client.start(o.job.jobId, {
|
|
21215
|
+
...sessionId ? { claudeSessionId: sessionId } : {},
|
|
21216
|
+
...cwd ? { cwd } : {},
|
|
21217
|
+
host: o.host
|
|
21218
|
+
});
|
|
21219
|
+
if (!started)
|
|
21220
|
+
return { kind: "skipped", reason: "control plane unreachable" };
|
|
21221
|
+
if (!started.ok)
|
|
21222
|
+
return { kind: "skipped", reason: started.reason };
|
|
21223
|
+
const model = o.job.model ?? started.model ?? o.fallbackSession?.model ?? null;
|
|
21224
|
+
const args = claudeArgs({ sessionId, model, permissionMode: o.permissionMode });
|
|
21225
|
+
log(`musher: running job ${o.job.jobId} (${sessionId ? `resume ${sessionId}` : "no session"}${model ? ` · ${model}` : ""}${cwd ? ` · ${cwd}` : ""})`);
|
|
21226
|
+
const exec = o.exec ?? defaultExecCapture;
|
|
21227
|
+
const headBefore = gitHead(cwd, exec);
|
|
21228
|
+
const t0 = Date.now();
|
|
21229
|
+
const r = exec(o.claudePath, args, { cwd, timeoutMs: o.timeoutMs });
|
|
21230
|
+
const durationMs = Date.now() - t0;
|
|
21231
|
+
const result = r.error ? { ok: false, summary: `could not run ${o.claudePath}: ${r.error}` } : parseClaudeOutput(r.stdout, r.status);
|
|
21232
|
+
if (!r.error && (r.timedOut || r.status === null)) {
|
|
21233
|
+
result.ok = false;
|
|
21234
|
+
result.summary = `timed out after ${Math.round(o.timeoutMs / 60000)} min. ${result.summary}`.trim();
|
|
21235
|
+
}
|
|
21236
|
+
const outputs = collectOutputs(gitNewCommits(cwd, headBefore, gitHead(cwd, exec), exec), result.summary);
|
|
21237
|
+
await o.client.finish({
|
|
21238
|
+
jobId: o.job.jobId,
|
|
21239
|
+
runId: started.runId,
|
|
21240
|
+
ok: result.ok,
|
|
21241
|
+
summary: result.summary,
|
|
21242
|
+
...outputs.length ? { outputs } : {},
|
|
21243
|
+
...result.model ?? model ? { model: result.model ?? model } : {},
|
|
21244
|
+
durationMs: result.durationMs ?? durationMs,
|
|
21245
|
+
...result.sessionId ?? sessionId ? { claudeSessionId: result.sessionId ?? sessionId } : {}
|
|
21246
|
+
});
|
|
21247
|
+
log(`musher: job ${o.job.jobId} ${result.ok ? "delivered" : "failed"} in ${Math.round(durationMs / 1000)}s`);
|
|
21248
|
+
return { kind: "ran", ok: result.ok, summary: result.summary, durationMs, outputs };
|
|
21249
|
+
};
|
|
21250
|
+
var verifyAttestation = (payload, sig, publicKeyB64) => {
|
|
21251
|
+
try {
|
|
21252
|
+
const pub = createPublicKey2({
|
|
21253
|
+
key: Buffer.from(publicKeyB64, "base64"),
|
|
21254
|
+
format: "der",
|
|
21255
|
+
type: "spki"
|
|
21256
|
+
});
|
|
21257
|
+
const raw = Buffer.from(sig.replace(/-/g, "+").replace(/_/g, "/"), "base64");
|
|
21258
|
+
return cryptoVerify(null, Buffer.from(payload, "utf8"), pub, raw);
|
|
21259
|
+
} catch {
|
|
21260
|
+
return false;
|
|
21261
|
+
}
|
|
21262
|
+
};
|
|
21263
|
+
var parsePayload = (payload) => {
|
|
21264
|
+
const out = {};
|
|
21265
|
+
for (const line of payload.split(`
|
|
21266
|
+
`).slice(1)) {
|
|
21267
|
+
const eq = line.indexOf("=");
|
|
21268
|
+
if (eq > 0)
|
|
21269
|
+
out[line.slice(0, eq)] = line.slice(eq + 1);
|
|
21038
21270
|
}
|
|
21039
|
-
if (gone.size)
|
|
21040
|
-
o.write({ ...state, runs: state.runs.filter((r) => !gone.has(r)) });
|
|
21041
21271
|
return out;
|
|
21042
|
-
}
|
|
21043
|
-
|
|
21044
|
-
|
|
21045
|
-
|
|
21046
|
-
|
|
21047
|
-
|
|
21048
|
-
|
|
21049
|
-
|
|
21050
|
-
|
|
21051
|
-
|
|
21052
|
-
|
|
21272
|
+
};
|
|
21273
|
+
|
|
21274
|
+
// src/switch.ts
|
|
21275
|
+
init_settings();
|
|
21276
|
+
var isObject12 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
21277
|
+
var envOf2 = (settings) => isObject12(settings.env) ? settings.env : {};
|
|
21278
|
+
var capturePriorEnv = (settings) => {
|
|
21279
|
+
const env = envOf2(settings);
|
|
21280
|
+
const prior = { hadEnv: isObject12(settings.env) };
|
|
21281
|
+
const url = env[BASE_URL_KEY];
|
|
21282
|
+
const token = env[AUTH_TOKEN_KEY];
|
|
21283
|
+
if (typeof url === "string")
|
|
21284
|
+
prior[BASE_URL_KEY] = url;
|
|
21285
|
+
if (typeof token === "string")
|
|
21286
|
+
prior[AUTH_TOKEN_KEY] = token;
|
|
21287
|
+
return prior;
|
|
21288
|
+
};
|
|
21289
|
+
var switchOn = (settings, cfg) => applyProxy(settings, cfg);
|
|
21290
|
+
var switchOff = (settings, prior) => {
|
|
21291
|
+
const hadEnv = prior.hadEnv === true;
|
|
21292
|
+
const stripped = removeProxy(settings);
|
|
21293
|
+
const env = { ...envOf2(stripped) };
|
|
21294
|
+
const url = prior[BASE_URL_KEY];
|
|
21295
|
+
const token = prior[AUTH_TOKEN_KEY];
|
|
21296
|
+
if (url !== undefined)
|
|
21297
|
+
env[BASE_URL_KEY] = url;
|
|
21298
|
+
if (token !== undefined)
|
|
21299
|
+
env[AUTH_TOKEN_KEY] = token;
|
|
21300
|
+
if (Object.keys(env).length === 0 && !hadEnv) {
|
|
21301
|
+
const { env: _env, ...rest } = stripped;
|
|
21302
|
+
return rest;
|
|
21053
21303
|
}
|
|
21054
|
-
|
|
21055
|
-
|
|
21056
|
-
|
|
21057
|
-
|
|
21058
|
-
|
|
21059
|
-
const
|
|
21060
|
-
const
|
|
21061
|
-
|
|
21062
|
-
|
|
21063
|
-
|
|
21064
|
-
|
|
21065
|
-
|
|
21066
|
-
|
|
21067
|
-
if (lock && lock.host === host && lock.pid !== process.pid && alive(lock.pid)) {
|
|
21068
|
-
try {
|
|
21069
|
-
kill(lock.pid, "SIGTERM");
|
|
21070
|
-
} catch {}
|
|
21071
|
-
for (let waited = 0;alive(lock.pid) && waited < PAUSE_WAIT_MS; waited += 250)
|
|
21072
|
-
await sleep(250);
|
|
21073
|
-
if (alive(lock.pid)) {
|
|
21074
|
-
error(`${engine} (pid ${lock.pid}) did not stop within ${PAUSE_WAIT_MS / 1000} s — nothing was paused. Try again, or stop it by hand.`);
|
|
21075
|
-
return 1;
|
|
21304
|
+
return { ...stripped, env };
|
|
21305
|
+
};
|
|
21306
|
+
var envToRestore = (priors, proxyUrls) => priors.find((p) => p !== undefined && !isSledsProxyEnv({ env: p }, proxyUrls)) ?? {};
|
|
21307
|
+
var RELATIVE = /^\+(?:(\d+)h)?(?:(\d+)m)?$/;
|
|
21308
|
+
var parseUntilReset = (input, nowMs) => {
|
|
21309
|
+
const trimmed = input.trim();
|
|
21310
|
+
const rel = RELATIVE.exec(trimmed);
|
|
21311
|
+
let deadline;
|
|
21312
|
+
if (rel) {
|
|
21313
|
+
const hours = Number(rel[1] ?? 0);
|
|
21314
|
+
const minutes = Number(rel[2] ?? 0);
|
|
21315
|
+
if (hours === 0 && minutes === 0) {
|
|
21316
|
+
throw new Error(`--until-reset: "${input}" is zero; use something like +5h or +90m`);
|
|
21076
21317
|
}
|
|
21077
|
-
|
|
21078
|
-
}
|
|
21079
|
-
|
|
21080
|
-
|
|
21081
|
-
|
|
21082
|
-
released: 0,
|
|
21083
|
-
kept: [],
|
|
21084
|
-
following: 0,
|
|
21085
|
-
parked: 0,
|
|
21086
|
-
stopped,
|
|
21087
|
-
errors: []
|
|
21088
|
-
};
|
|
21089
|
-
result.following = state.runs.filter((r) => r.pr).length;
|
|
21090
|
-
result.parked = state.runs.filter((r) => r.parked).length;
|
|
21091
|
-
let source = o.source;
|
|
21092
|
-
if (state.runs.some(isRunning) && !source) {
|
|
21093
|
-
const c = orgClient(o, parsed.org);
|
|
21094
|
-
if ("error" in c) {
|
|
21095
|
-
error(c.error);
|
|
21096
|
-
return 1;
|
|
21318
|
+
deadline = nowMs + (hours * 60 + minutes) * 60000;
|
|
21319
|
+
} else {
|
|
21320
|
+
deadline = Date.parse(trimmed);
|
|
21321
|
+
if (Number.isNaN(deadline)) {
|
|
21322
|
+
throw new Error(`--until-reset: "${input}" is not +<n>h[<n>m] or an ISO timestamp`);
|
|
21097
21323
|
}
|
|
21098
|
-
source = sledsSource(c, { engine, log });
|
|
21099
|
-
}
|
|
21100
|
-
if (source) {
|
|
21101
|
-
const r = await releaseRunning({
|
|
21102
|
-
read: () => state,
|
|
21103
|
-
write: (next) => writeState(file, next),
|
|
21104
|
-
source,
|
|
21105
|
-
engine,
|
|
21106
|
-
why: parsed.why ?? `paused on ${defaultEngineName(host)} (sleds engine pause)`,
|
|
21107
|
-
exec: guardGit(o.exec ?? defaultExec),
|
|
21108
|
-
...o.runnerFor ? { runnerFor: o.runnerFor } : {},
|
|
21109
|
-
log
|
|
21110
|
-
});
|
|
21111
|
-
result.released = r.released;
|
|
21112
|
-
result.kept = r.kept;
|
|
21113
|
-
result.errors = r.errors;
|
|
21114
21324
|
}
|
|
21115
|
-
if (
|
|
21116
|
-
|
|
21117
|
-
else {
|
|
21118
|
-
const n = (k, one) => `${k} ${one}${k === 1 ? "" : "s"}`;
|
|
21119
|
-
log(`${engine} paused${seat ? ` (${seat})` : ""}: ${stopped ? "the engine stopped" : "the engine was not running"} · ${n(result.released, "session")} released · ${n(result.following, "PR")} still followed · ${n(result.parked, "parked session")} kept`);
|
|
21120
|
-
for (const w of result.kept)
|
|
21121
|
-
log(` kept ${w}`);
|
|
21122
|
-
for (const e of result.errors)
|
|
21123
|
-
error(` not released, retry with \`sleds engine pause\`: ${e}`);
|
|
21325
|
+
if (deadline <= nowMs) {
|
|
21326
|
+
throw new Error(`--until-reset: ${trimmed} is in the past`);
|
|
21124
21327
|
}
|
|
21125
|
-
return
|
|
21126
|
-
}
|
|
21328
|
+
return deadline;
|
|
21329
|
+
};
|
|
21330
|
+
var formatLocal = (ms, tz) => new Intl.DateTimeFormat("en-US", {
|
|
21331
|
+
month: "short",
|
|
21332
|
+
day: "numeric",
|
|
21333
|
+
hour: "numeric",
|
|
21334
|
+
minute: "2-digit",
|
|
21335
|
+
timeZoneName: "short",
|
|
21336
|
+
...tz ? { timeZone: tz } : {}
|
|
21337
|
+
}).format(new Date(ms));
|
|
21338
|
+
var formatDuration = (ms) => {
|
|
21339
|
+
const total = Math.max(0, Math.round(ms / 60000));
|
|
21340
|
+
const h = Math.floor(total / 60);
|
|
21341
|
+
const m = total % 60;
|
|
21342
|
+
if (h === 0)
|
|
21343
|
+
return `${m}m`;
|
|
21344
|
+
return m === 0 ? `${h}h` : `${h}h ${m}m`;
|
|
21345
|
+
};
|
|
21127
21346
|
|
|
21128
21347
|
// src/commands/verify.ts
|
|
21129
21348
|
var VERDICT_USAGE = [
|
|
@@ -21204,17 +21423,17 @@ async function verdictCmd(o) {
|
|
|
21204
21423
|
let screenshot;
|
|
21205
21424
|
if (a.file) {
|
|
21206
21425
|
try {
|
|
21207
|
-
if (!o.readFile &&
|
|
21426
|
+
if (!o.readFile && statSync8(a.file).size > SHOT_MAX_BYTES) {
|
|
21208
21427
|
error(`${a.file}: a screenshot is at most 4 MB`);
|
|
21209
21428
|
return 1;
|
|
21210
21429
|
}
|
|
21211
|
-
const bytes = (o.readFile ??
|
|
21430
|
+
const bytes = (o.readFile ?? readFileSync17)(a.file);
|
|
21212
21431
|
if (bytes.byteLength > SHOT_MAX_BYTES) {
|
|
21213
21432
|
error(`${a.file}: a screenshot is at most 4 MB`);
|
|
21214
21433
|
return 1;
|
|
21215
21434
|
}
|
|
21216
21435
|
screenshot = {
|
|
21217
|
-
name:
|
|
21436
|
+
name: basename8(a.file),
|
|
21218
21437
|
mime: shotMime(a.file),
|
|
21219
21438
|
content: bytes.toString("base64")
|
|
21220
21439
|
};
|
|
@@ -21473,7 +21692,7 @@ import {
|
|
|
21473
21692
|
existsSync as existsSync21,
|
|
21474
21693
|
lstatSync as lstatSync2,
|
|
21475
21694
|
mkdtempSync,
|
|
21476
|
-
readFileSync as
|
|
21695
|
+
readFileSync as readFileSync22,
|
|
21477
21696
|
readlinkSync as readlinkSync4,
|
|
21478
21697
|
rmSync as rmSync13,
|
|
21479
21698
|
writeFileSync as writeFileSync19
|
|
@@ -21483,7 +21702,7 @@ import { delimiter as delimiter3, dirname as dirname18, join as join27, resolve
|
|
|
21483
21702
|
|
|
21484
21703
|
// src/agentMcp.ts
|
|
21485
21704
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
21486
|
-
import { existsSync as existsSync18, mkdirSync as mkdirSync18, readFileSync as
|
|
21705
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync18, readFileSync as readFileSync18, writeFileSync as writeFileSync16 } from "node:fs";
|
|
21487
21706
|
import { dirname as dirname16, join as join25, resolve as resolve9 } from "node:path";
|
|
21488
21707
|
init_settings();
|
|
21489
21708
|
var MCP_SERVER2 = "sleds";
|
|
@@ -21491,7 +21710,7 @@ var AGENT_NAME2 = { "claude-code": "Claude Code", codex: "Codex" };
|
|
|
21491
21710
|
var claudeUserConfigPath2 = (home, env = process.env) => env.CLAUDE_CONFIG_DIR?.trim() ? join25(claudeDir(home, env), ".claude.json") : join25(home, ".claude.json");
|
|
21492
21711
|
function hasClaudeMcp2(home, env = process.env) {
|
|
21493
21712
|
try {
|
|
21494
|
-
const raw = JSON.parse(
|
|
21713
|
+
const raw = JSON.parse(readFileSync18(claudeUserConfigPath2(home, env), "utf8"));
|
|
21495
21714
|
return Boolean(raw.mcpServers?.[MCP_SERVER2]);
|
|
21496
21715
|
} catch {
|
|
21497
21716
|
return false;
|
|
@@ -21501,7 +21720,7 @@ function hasCodexMcp2(home) {
|
|
|
21501
21720
|
const path = codexConfigPath(home);
|
|
21502
21721
|
if (!existsSync18(path))
|
|
21503
21722
|
return false;
|
|
21504
|
-
return new RegExp(`^\\s*\\[mcp_servers\\.${MCP_SERVER2}\\]\\s*$`, "m").test(
|
|
21723
|
+
return new RegExp(`^\\s*\\[mcp_servers\\.${MCP_SERVER2}\\]\\s*$`, "m").test(readFileSync18(path, "utf8"));
|
|
21505
21724
|
}
|
|
21506
21725
|
var hasAgentMcp2 = (agent, home, env = process.env) => agent === "codex" ? hasCodexMcp2(home) : hasClaudeMcp2(home, env);
|
|
21507
21726
|
var seatHome2 = (home, env) => {
|
|
@@ -21581,7 +21800,7 @@ async function offerMcpResult2(o) {
|
|
|
21581
21800
|
return no;
|
|
21582
21801
|
if (o.agent === "codex") {
|
|
21583
21802
|
const path = codexConfigPath(o.home);
|
|
21584
|
-
const prior = existsSync18(path) ?
|
|
21803
|
+
const prior = existsSync18(path) ? readFileSync18(path, "utf8") : "";
|
|
21585
21804
|
mkdirSync18(dirname16(path), { recursive: true });
|
|
21586
21805
|
writeFileSync16(path, applyCodexMcp2(prior, o.home, env), { mode: 384 });
|
|
21587
21806
|
return {
|
|
@@ -21881,14 +22100,14 @@ init_config();
|
|
|
21881
22100
|
import {
|
|
21882
22101
|
existsSync as existsSync19,
|
|
21883
22102
|
mkdirSync as mkdirSync19,
|
|
21884
|
-
readFileSync as
|
|
22103
|
+
readFileSync as readFileSync19,
|
|
21885
22104
|
readdirSync as readdirSync4,
|
|
21886
22105
|
realpathSync,
|
|
21887
22106
|
rmSync as rmSync11,
|
|
21888
22107
|
writeFileSync as writeFileSync17
|
|
21889
22108
|
} from "node:fs";
|
|
21890
22109
|
import { hostname as hostname3 } from "node:os";
|
|
21891
|
-
import { basename as
|
|
22110
|
+
import { basename as basename9, dirname as dirname17, isAbsolute as isAbsolute4, join as join26 } from "node:path";
|
|
21892
22111
|
init_state();
|
|
21893
22112
|
var ENGINE_LABEL = "ai.sleds.engine";
|
|
21894
22113
|
var ENGINE_INSTALL_USAGE = `usage: sleds engine install [engine flags] | sleds engine uninstall [--name <n>] [--org <slug>]
|
|
@@ -22015,7 +22234,7 @@ function readEngines(dir, suffix, manager, parse) {
|
|
|
22015
22234
|
const path = join26(dir, name);
|
|
22016
22235
|
let parsed;
|
|
22017
22236
|
try {
|
|
22018
|
-
parsed = parse(
|
|
22237
|
+
parsed = parse(readFileSync19(path, "utf8"), name);
|
|
22019
22238
|
} catch {
|
|
22020
22239
|
parsed = null;
|
|
22021
22240
|
}
|
|
@@ -22035,7 +22254,7 @@ function installedEngines(home) {
|
|
|
22035
22254
|
...readEngines(join26(home, "Library", "LaunchAgents"), ".plist", "launchd", parseEnginePlist),
|
|
22036
22255
|
...readEngines(engineUnitDir(home), ".service", "systemd", (text, file) => {
|
|
22037
22256
|
const parsed = parseEngineUnit(text);
|
|
22038
|
-
return parsed && { label:
|
|
22257
|
+
return parsed && { label: basename9(file, ".service"), ...parsed };
|
|
22039
22258
|
})
|
|
22040
22259
|
];
|
|
22041
22260
|
}
|
|
@@ -22122,7 +22341,7 @@ function installUnit(a) {
|
|
|
22122
22341
|
const log = o.log ?? console.log;
|
|
22123
22342
|
const error = o.error ?? console.error;
|
|
22124
22343
|
const unit = engineUnitPath(o.home, label);
|
|
22125
|
-
const unitName =
|
|
22344
|
+
const unitName = basename9(unit);
|
|
22126
22345
|
const systemctl = (...args) => exec("systemctl", ["--user", ...args]);
|
|
22127
22346
|
mkdirSync19(dirname17(unit), { recursive: true });
|
|
22128
22347
|
if (existsSync19(unit))
|
|
@@ -22132,7 +22351,7 @@ function installUnit(a) {
|
|
|
22132
22351
|
continue;
|
|
22133
22352
|
if (engineArg(other.programArgs, "name") !== parsed.name)
|
|
22134
22353
|
continue;
|
|
22135
|
-
systemctl("disable", "--now",
|
|
22354
|
+
systemctl("disable", "--now", basename9(other.plist));
|
|
22136
22355
|
rmSync11(other.plist, { force: true });
|
|
22137
22356
|
log(`replaced ${other.label}, this engine as installed before`);
|
|
22138
22357
|
}
|
|
@@ -22191,18 +22410,18 @@ function engineUninstall(o) {
|
|
|
22191
22410
|
const unit = file.endsWith(".service");
|
|
22192
22411
|
const exec = o.exec ?? defaultExec2;
|
|
22193
22412
|
if (unit)
|
|
22194
|
-
exec("systemctl", ["--user", "disable", "--now",
|
|
22413
|
+
exec("systemctl", ["--user", "disable", "--now", basename9(file)]);
|
|
22195
22414
|
else
|
|
22196
22415
|
exec("launchctl", ["unload", file]);
|
|
22197
22416
|
rmSync11(file, { force: true });
|
|
22198
22417
|
if (unit)
|
|
22199
22418
|
exec("systemctl", ["--user", "daemon-reload"]);
|
|
22200
|
-
log(`engine:${name} removed: ${
|
|
22419
|
+
log(`engine:${name} removed: ${basename9(file, unit ? ".service" : ".plist")} — its sessions keep running`);
|
|
22201
22420
|
return 0;
|
|
22202
22421
|
}
|
|
22203
22422
|
|
|
22204
22423
|
// src/commands/musher.ts
|
|
22205
|
-
import { existsSync as existsSync20, mkdirSync as mkdirSync20, readFileSync as
|
|
22424
|
+
import { existsSync as existsSync20, mkdirSync as mkdirSync20, readFileSync as readFileSync20, rmSync as rmSync12, writeFileSync as writeFileSync18 } from "node:fs";
|
|
22206
22425
|
init_config();
|
|
22207
22426
|
init_meter();
|
|
22208
22427
|
var defaultWhich = (cmd) => {
|
|
@@ -22237,7 +22456,7 @@ var musherAgentState = (home, env = process.env) => {
|
|
|
22237
22456
|
if (!existsSync20(plist))
|
|
22238
22457
|
return { installed: false, thisSeat: false };
|
|
22239
22458
|
try {
|
|
22240
|
-
const text =
|
|
22459
|
+
const text = readFileSync20(plist, "utf8");
|
|
22241
22460
|
const want = env.SLEDS_HOME?.trim();
|
|
22242
22461
|
const has = /<key>SLEDS_HOME<\/key>\s*<string>([^<]*)<\/string>/.exec(text)?.[1];
|
|
22243
22462
|
return { installed: true, thisSeat: (want ?? undefined) === (has ?? undefined) };
|
|
@@ -22247,7 +22466,7 @@ var musherAgentState = (home, env = process.env) => {
|
|
|
22247
22466
|
};
|
|
22248
22467
|
|
|
22249
22468
|
// src/claudeAccount.ts
|
|
22250
|
-
import { readFileSync as
|
|
22469
|
+
import { readFileSync as readFileSync21 } from "node:fs";
|
|
22251
22470
|
var PLANS = {
|
|
22252
22471
|
claude_max: "Max",
|
|
22253
22472
|
claude_pro: "Pro",
|
|
@@ -22276,7 +22495,7 @@ var parseClaudeAccount = (raw) => {
|
|
|
22276
22495
|
};
|
|
22277
22496
|
var readClaudeAccount = (home, env = process.env) => {
|
|
22278
22497
|
try {
|
|
22279
|
-
return parseClaudeAccount(JSON.parse(
|
|
22498
|
+
return parseClaudeAccount(JSON.parse(readFileSync21(claudeUserConfigPath2(home, env), "utf8")));
|
|
22280
22499
|
} catch {
|
|
22281
22500
|
return null;
|
|
22282
22501
|
}
|
|
@@ -22879,7 +23098,7 @@ function boxChecks(o, env, which, need) {
|
|
|
22879
23098
|
const file = boxEnvPath(o.home);
|
|
22880
23099
|
let boxEnvText = null;
|
|
22881
23100
|
try {
|
|
22882
|
-
boxEnvText =
|
|
23101
|
+
boxEnvText = readFileSync22(file, "utf8");
|
|
22883
23102
|
} catch {
|
|
22884
23103
|
boxEnvText = null;
|
|
22885
23104
|
}
|
|
@@ -22997,10 +23216,10 @@ import {
|
|
|
22997
23216
|
appendFileSync as appendFileSync3,
|
|
22998
23217
|
chmodSync as chmodSync6,
|
|
22999
23218
|
mkdirSync as mkdirSync21,
|
|
23000
|
-
readFileSync as
|
|
23219
|
+
readFileSync as readFileSync23,
|
|
23001
23220
|
existsSync as realExists2,
|
|
23002
23221
|
rmSync as rmSync14,
|
|
23003
|
-
statSync as
|
|
23222
|
+
statSync as statSync9,
|
|
23004
23223
|
writeFileSync as writeFileSync20
|
|
23005
23224
|
} from "node:fs";
|
|
23006
23225
|
import { hostname as hostname4, tmpdir as tmpdir3, userInfo as userInfo3 } from "node:os";
|
|
@@ -23411,7 +23630,7 @@ function engineClient2(o, org, breaker) {
|
|
|
23411
23630
|
...src,
|
|
23412
23631
|
...breaker ? { fetchFn: breaker.fetch } : {},
|
|
23413
23632
|
timeoutMs: ENGINE_TIMEOUT_MS2,
|
|
23414
|
-
version: "0.1.
|
|
23633
|
+
version: "0.1.72"
|
|
23415
23634
|
});
|
|
23416
23635
|
const asked = org?.trim() || env.SLEDS_ORG?.trim();
|
|
23417
23636
|
if (asked && !selectOrg(readConfig(o.home), org, env).seat)
|
|
@@ -23453,7 +23672,7 @@ function realPidAlive3(pid) {
|
|
|
23453
23672
|
function memberMcpConfigs2(o, cwd) {
|
|
23454
23673
|
const read = o.readJson ?? ((p) => {
|
|
23455
23674
|
try {
|
|
23456
|
-
return JSON.parse(
|
|
23675
|
+
return JSON.parse(readFileSync23(p, "utf8"));
|
|
23457
23676
|
} catch {
|
|
23458
23677
|
return null;
|
|
23459
23678
|
}
|
|
@@ -23488,7 +23707,7 @@ function engineCredential(o) {
|
|
|
23488
23707
|
const file = boxEnvPath(o.home);
|
|
23489
23708
|
let boxEnvText = null;
|
|
23490
23709
|
try {
|
|
23491
|
-
boxEnvText =
|
|
23710
|
+
boxEnvText = readFileSync23(file, "utf8");
|
|
23492
23711
|
} catch {}
|
|
23493
23712
|
return detectCredential(o.env ?? process.env, {
|
|
23494
23713
|
home: o.home,
|
|
@@ -23620,7 +23839,7 @@ function engineDeps2(o, flags, source, runner, stateName) {
|
|
|
23620
23839
|
},
|
|
23621
23840
|
readMock: (p) => {
|
|
23622
23841
|
try {
|
|
23623
|
-
return
|
|
23842
|
+
return readFileSync23(p, "utf8");
|
|
23624
23843
|
} catch {
|
|
23625
23844
|
return null;
|
|
23626
23845
|
}
|
|
@@ -23759,7 +23978,7 @@ function lentHomeProblems2(accountHome, lentBy, modeOf) {
|
|
|
23759
23978
|
}
|
|
23760
23979
|
var homeMode2 = (path) => {
|
|
23761
23980
|
try {
|
|
23762
|
-
return
|
|
23981
|
+
return statSync9(path).mode & 4095;
|
|
23763
23982
|
} catch {
|
|
23764
23983
|
return null;
|
|
23765
23984
|
}
|
|
@@ -23804,7 +24023,7 @@ async function driveEngine2(o, flags, deps, until = {}) {
|
|
|
23804
24023
|
runner: deps.runner.name,
|
|
23805
24024
|
atOnce: flags.atOnce,
|
|
23806
24025
|
interval: flags.interval,
|
|
23807
|
-
cliVersion: "0.1.
|
|
24026
|
+
cliVersion: "0.1.72"
|
|
23808
24027
|
};
|
|
23809
24028
|
const beat = (checkedAt) => {
|
|
23810
24029
|
const m = deps.machine;
|
|
@@ -24434,14 +24653,14 @@ init_config();
|
|
|
24434
24653
|
import {
|
|
24435
24654
|
existsSync as existsSync22,
|
|
24436
24655
|
mkdirSync as mkdirSync22,
|
|
24437
|
-
readFileSync as
|
|
24656
|
+
readFileSync as readFileSync24,
|
|
24438
24657
|
readdirSync as readdirSync6,
|
|
24439
24658
|
realpathSync as realpathSync2,
|
|
24440
24659
|
rmSync as rmSync15,
|
|
24441
24660
|
writeFileSync as writeFileSync21
|
|
24442
24661
|
} from "node:fs";
|
|
24443
24662
|
import { hostname as hostname5 } from "node:os";
|
|
24444
|
-
import { basename as
|
|
24663
|
+
import { basename as basename10, dirname as dirname20, isAbsolute as isAbsolute6, join as join29 } from "node:path";
|
|
24445
24664
|
init_state();
|
|
24446
24665
|
var ENGINE_LABEL2 = "ai.sleds.engine";
|
|
24447
24666
|
var ENGINE_INSTALL_USAGE2 = `usage: sleds engine install [engine flags] | sleds engine uninstall [--name <n>] [--org <slug>]
|
|
@@ -24568,7 +24787,7 @@ function readEngines2(dir, suffix, manager, parse) {
|
|
|
24568
24787
|
const path = join29(dir, name);
|
|
24569
24788
|
let parsed;
|
|
24570
24789
|
try {
|
|
24571
|
-
parsed = parse(
|
|
24790
|
+
parsed = parse(readFileSync24(path, "utf8"), name);
|
|
24572
24791
|
} catch {
|
|
24573
24792
|
parsed = null;
|
|
24574
24793
|
}
|
|
@@ -24588,7 +24807,7 @@ function installedEngines2(home) {
|
|
|
24588
24807
|
...readEngines2(join29(home, "Library", "LaunchAgents"), ".plist", "launchd", parseEnginePlist2),
|
|
24589
24808
|
...readEngines2(engineUnitDir(home), ".service", "systemd", (text, file) => {
|
|
24590
24809
|
const parsed = parseEngineUnit(text);
|
|
24591
|
-
return parsed && { label:
|
|
24810
|
+
return parsed && { label: basename10(file, ".service"), ...parsed };
|
|
24592
24811
|
})
|
|
24593
24812
|
];
|
|
24594
24813
|
}
|
|
@@ -24719,7 +24938,7 @@ function installUnit2(a) {
|
|
|
24719
24938
|
const log = o.log ?? console.log;
|
|
24720
24939
|
const error = o.error ?? console.error;
|
|
24721
24940
|
const unit = engineUnitPath(o.home, label);
|
|
24722
|
-
const unitName =
|
|
24941
|
+
const unitName = basename10(unit);
|
|
24723
24942
|
const systemctl = (...args) => exec("systemctl", ["--user", ...args]);
|
|
24724
24943
|
mkdirSync22(dirname20(unit), { recursive: true });
|
|
24725
24944
|
if (existsSync22(unit))
|
|
@@ -24729,7 +24948,7 @@ function installUnit2(a) {
|
|
|
24729
24948
|
continue;
|
|
24730
24949
|
if (engineArg2(other.programArgs, "name") !== parsed.name)
|
|
24731
24950
|
continue;
|
|
24732
|
-
systemctl("disable", "--now",
|
|
24951
|
+
systemctl("disable", "--now", basename10(other.plist));
|
|
24733
24952
|
rmSync15(other.plist, { force: true });
|
|
24734
24953
|
log(`replaced ${other.label}, this engine as installed before`);
|
|
24735
24954
|
}
|
|
@@ -24788,13 +25007,13 @@ function engineUninstall2(o) {
|
|
|
24788
25007
|
const unit = file.endsWith(".service");
|
|
24789
25008
|
const exec = o.exec ?? defaultExec2;
|
|
24790
25009
|
if (unit)
|
|
24791
|
-
exec("systemctl", ["--user", "disable", "--now",
|
|
25010
|
+
exec("systemctl", ["--user", "disable", "--now", basename10(file)]);
|
|
24792
25011
|
else
|
|
24793
25012
|
exec("launchctl", ["unload", file]);
|
|
24794
25013
|
rmSync15(file, { force: true });
|
|
24795
25014
|
if (unit)
|
|
24796
25015
|
exec("systemctl", ["--user", "daemon-reload"]);
|
|
24797
|
-
log(`engine:${name} removed: ${
|
|
25016
|
+
log(`engine:${name} removed: ${basename10(file, unit ? ".service" : ".plist")} — its sessions keep running`);
|
|
24798
25017
|
return 0;
|
|
24799
25018
|
}
|
|
24800
25019
|
|
|
@@ -24922,7 +25141,7 @@ import { closeSync as closeSync5, fstatSync as fstatSync2, openSync as openSync5
|
|
|
24922
25141
|
import { hostname as hostname6 } from "node:os";
|
|
24923
25142
|
|
|
24924
25143
|
// src/commands/engineStatus.ts
|
|
24925
|
-
import { existsSync as existsSync23, readFileSync as
|
|
25144
|
+
import { existsSync as existsSync23, readFileSync as readFileSync25 } from "node:fs";
|
|
24926
25145
|
init_state();
|
|
24927
25146
|
|
|
24928
25147
|
// src/engine/status.ts
|
|
@@ -25222,7 +25441,7 @@ var engineLogCmd = (o) => {
|
|
|
25222
25441
|
|
|
25223
25442
|
// src/commands/engineProfile.ts
|
|
25224
25443
|
init_src();
|
|
25225
|
-
import { existsSync as existsSync24, readFileSync as
|
|
25444
|
+
import { existsSync as existsSync24, readFileSync as readFileSync26 } from "node:fs";
|
|
25226
25445
|
import { hostname as hostname7 } from "node:os";
|
|
25227
25446
|
var PROFILE_USAGE = "usage: sleds engine profile [--json] | sleds engine profile set <field>=<value>… [--workspace] [--json] | sleds engine profile set --stdin [--workspace] [--json] | sleds engine profile --strict-mcp [--mcp-allow <a,b>] | --no-strict-mcp [--workspace] [--json] | sleds engine profile --sandbox [--sandbox-allow <a,b>] | --no-sandbox [--workspace] [--json] | sleds engine profile set --hold on|off [--workspace] [--json] | sleds engine profile set cmuxPassword=<pw> | --cmux-password <pw> [--json]";
|
|
25228
25447
|
var PROFILE_FIELDS = [
|
|
@@ -25493,7 +25712,7 @@ async function engineProfileCmd(o) {
|
|
|
25493
25712
|
const rest = words.slice(1);
|
|
25494
25713
|
let stdin = null;
|
|
25495
25714
|
if (fromStdin) {
|
|
25496
|
-
const taken = cmuxPasswordFromJson((o.stdin ?? (() =>
|
|
25715
|
+
const taken = cmuxPasswordFromJson((o.stdin ?? (() => readFileSync26(0, "utf8")))());
|
|
25497
25716
|
if ("error" in taken || taken.password !== undefined && password !== undefined) {
|
|
25498
25717
|
error("error" in taken ? taken.error : "the cmux password is given once");
|
|
25499
25718
|
error(PROFILE_USAGE);
|
|
@@ -25578,7 +25797,7 @@ var keychainLine = (k) => k === "set" ? "cmuxPassword: set (Keychain)" : k === "
|
|
|
25578
25797
|
|
|
25579
25798
|
// src/commands/engineStatus.ts
|
|
25580
25799
|
init_state();
|
|
25581
|
-
import { existsSync as existsSync25, readFileSync as
|
|
25800
|
+
import { existsSync as existsSync25, readFileSync as readFileSync27 } from "node:fs";
|
|
25582
25801
|
import { hostname as hostname8 } from "node:os";
|
|
25583
25802
|
var ENGINE_STATUS_USAGE = "usage: sleds engine status [--name <n>] [--org <slug>] [--json]";
|
|
25584
25803
|
function parseStatusArgs(argv, host) {
|
|
@@ -25634,7 +25853,7 @@ function readEngineStatus(stateDir, engine, host, pidAlive, seat) {
|
|
|
25634
25853
|
}
|
|
25635
25854
|
function safeRead(path) {
|
|
25636
25855
|
try {
|
|
25637
|
-
return
|
|
25856
|
+
return readFileSync27(path, "utf8");
|
|
25638
25857
|
} catch {
|
|
25639
25858
|
return "";
|
|
25640
25859
|
}
|
|
@@ -25755,7 +25974,7 @@ init_meter();
|
|
|
25755
25974
|
|
|
25756
25975
|
// src/owed.ts
|
|
25757
25976
|
init_config();
|
|
25758
|
-
import { existsSync as existsSync26, mkdirSync as mkdirSync23, readFileSync as
|
|
25977
|
+
import { existsSync as existsSync26, mkdirSync as mkdirSync23, readFileSync as readFileSync28, renameSync as renameSync11, writeFileSync as writeFileSync22 } from "node:fs";
|
|
25759
25978
|
import { dirname as dirname21, join as join30 } from "node:path";
|
|
25760
25979
|
var owedPath = (home) => join30(configDir(home), "owed.json");
|
|
25761
25980
|
var sessionPath = (home) => join30(configDir(home), "session.json");
|
|
@@ -25776,7 +25995,7 @@ var readJson = (p) => {
|
|
|
25776
25995
|
if (!existsSync26(p))
|
|
25777
25996
|
return null;
|
|
25778
25997
|
try {
|
|
25779
|
-
return JSON.parse(
|
|
25998
|
+
return JSON.parse(readFileSync28(p, "utf8"));
|
|
25780
25999
|
} catch {
|
|
25781
26000
|
return null;
|
|
25782
26001
|
}
|
|
@@ -25916,7 +26135,7 @@ function contextFor(deps) {
|
|
|
25916
26135
|
...src,
|
|
25917
26136
|
fetchFn: deps.fetchFn,
|
|
25918
26137
|
timeoutMs: deps.timeoutMs,
|
|
25919
|
-
version: "0.1.
|
|
26138
|
+
version: "0.1.72"
|
|
25920
26139
|
}), deps.home, now) : null;
|
|
25921
26140
|
return {
|
|
25922
26141
|
channel: "code",
|
|
@@ -26990,9 +27209,9 @@ var login = async (o) => {
|
|
|
26990
27209
|
// src/commands/logout.ts
|
|
26991
27210
|
init_config();
|
|
26992
27211
|
init_state();
|
|
26993
|
-
import { existsSync as existsSync28, readFileSync as
|
|
27212
|
+
import { existsSync as existsSync28, readFileSync as readFileSync29, rmSync as rmSync16 } from "node:fs";
|
|
26994
27213
|
import { hostname as hostname10 } from "node:os";
|
|
26995
|
-
import { basename as
|
|
27214
|
+
import { basename as basename11 } from "node:path";
|
|
26996
27215
|
init_settings();
|
|
26997
27216
|
var LOGOUT_USAGE = "usage: sleds logout [--org <slug>] [--json]";
|
|
26998
27217
|
function parseLogoutArgs(argv) {
|
|
@@ -27116,7 +27335,7 @@ async function logout(o) {
|
|
|
27116
27335
|
if (!e.org) {
|
|
27117
27336
|
const exec = o.exec ?? defaultExec2;
|
|
27118
27337
|
if (e.manager === "systemd") {
|
|
27119
|
-
exec("systemctl", ["--user", "disable", "--now",
|
|
27338
|
+
exec("systemctl", ["--user", "disable", "--now", basename11(e.plist)]);
|
|
27120
27339
|
rmSync16(e.plist, { force: true });
|
|
27121
27340
|
exec("systemctl", ["--user", "daemon-reload"]);
|
|
27122
27341
|
} else {
|
|
@@ -27155,7 +27374,7 @@ async function logout(o) {
|
|
|
27155
27374
|
};
|
|
27156
27375
|
writeConfig(o.home, next);
|
|
27157
27376
|
const tp = tokenPath(o.home, env);
|
|
27158
|
-
if (existsSync28(tp) &&
|
|
27377
|
+
if (existsSync28(tp) && readFileSync29(tp, "utf8").trim() === seat.token)
|
|
27159
27378
|
rmSync16(tp, { force: true });
|
|
27160
27379
|
const active = next.activeOrg ?? next.org?.slug ?? null;
|
|
27161
27380
|
const result = { ok: true, email, org: slug, paused, active };
|
|
@@ -27233,7 +27452,7 @@ var meter = async (o) => {
|
|
|
27233
27452
|
init_config();
|
|
27234
27453
|
init_meter();
|
|
27235
27454
|
import { spawnSync as spawnSync7 } from "node:child_process";
|
|
27236
|
-
import { existsSync as existsSync29, mkdirSync as mkdirSync25, readFileSync as
|
|
27455
|
+
import { existsSync as existsSync29, mkdirSync as mkdirSync25, readFileSync as readFileSync30, rmSync as rmSync17, writeFileSync as writeFileSync24 } from "node:fs";
|
|
27237
27456
|
import { hostname as hostname11 } from "node:os";
|
|
27238
27457
|
import { dirname as dirname22 } from "node:path";
|
|
27239
27458
|
var defaultWhich3 = (cmd) => {
|
|
@@ -27753,7 +27972,7 @@ var packCmd = async (o) => {
|
|
|
27753
27972
|
};
|
|
27754
27973
|
|
|
27755
27974
|
// src/commands/permissionEvent.ts
|
|
27756
|
-
import { chmodSync as chmodSync7, mkdirSync as mkdirSync26, readFileSync as
|
|
27975
|
+
import { chmodSync as chmodSync7, mkdirSync as mkdirSync26, readFileSync as readFileSync31, renameSync as renameSync12, rmSync as rmSync19, writeFileSync as writeFileSync26 } from "node:fs";
|
|
27757
27976
|
import { dirname as dirname23 } from "node:path";
|
|
27758
27977
|
var isObject13 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
27759
27978
|
var messageOf = (text) => {
|
|
@@ -27950,7 +28169,7 @@ async function reopenCmd(o) {
|
|
|
27950
28169
|
|
|
27951
28170
|
// src/commands/route.ts
|
|
27952
28171
|
init_src();
|
|
27953
|
-
import { readFileSync as
|
|
28172
|
+
import { readFileSync as readFileSync32 } from "node:fs";
|
|
27954
28173
|
import { hostname as hostname12 } from "node:os";
|
|
27955
28174
|
var ARM_USAGE = "usage: sleds route arm <key> [--off] [--json] [--name <engine>] [--at-once <n>] [--runner tmux|headless|command|orca|cmux] [--runner-cmd '<launcher>'] [--agent '<command>'] [--mode <permission-mode>] [--model <id>] [--effort <e>] [--branch '<template>'] [--pr-title '<template>'] [--repos-dir <dir>]";
|
|
27956
28175
|
var USAGE2 = "usage: sleds route <key> [--long | --dot | --json] | sleds route arm <key> [--off] [--json] | sleds route answer <key>/<node> --stdin | sleds route instruct <key>/<node> --stdin [--voice] | sleds route propose <key> --file <nodes.json> | sleds route approve <key> [--voice --stdin] | sleds route redraft <key> | sleds route single <key> | sleds route elsewhere <key> [--note <text>] | sleds route decisions [<key>] [--flagged] | sleds route decision <key> <id> --seen | --answer --stdin [--route accept|keep|redraft] | --keep-route | --apply [--answer --stdin] | --overrule --stdin | --ready | sleds route run <key> [--at-once <n>] [--runner tmux|headless|command|orca|cmux] [--runner-cmd '<launcher>'] [--agent '<command>'] [--interval <s>] [--lease <min>] [--idle <min>] [--repo <path>] [--repos-dir <dir>] [--mode <permission-mode>] [--model <id>] [--branch '<template>'] [--pr-title '<template>'] [--once]";
|
|
@@ -28133,7 +28352,7 @@ async function answerCmd(o, argv) {
|
|
|
28133
28352
|
const words = argv.filter((a) => a !== "--json" && a !== "--stdin");
|
|
28134
28353
|
const ref = words[0] ?? "";
|
|
28135
28354
|
const slash = ref.lastIndexOf("/");
|
|
28136
|
-
const answer = (fromStdin ? (o.stdin ?? (() =>
|
|
28355
|
+
const answer = (fromStdin ? (o.stdin ?? (() => readFileSync32(0, "utf8")))() : words.slice(1).join(" ")).trim();
|
|
28137
28356
|
if (slash <= 0 || slash === ref.length - 1 || fromStdin && words.length > 1) {
|
|
28138
28357
|
error(ANSWER_USAGE);
|
|
28139
28358
|
return 2;
|
|
@@ -28178,7 +28397,7 @@ async function instructCmd(o, argv) {
|
|
|
28178
28397
|
error(INSTRUCT_USAGE);
|
|
28179
28398
|
return 2;
|
|
28180
28399
|
}
|
|
28181
|
-
const text = fromStdin ? (o.stdin ?? (() =>
|
|
28400
|
+
const text = fromStdin ? (o.stdin ?? (() => readFileSync32(0, "utf8")))() : words.slice(1).join(" ");
|
|
28182
28401
|
const { md, heard } = voice ? splitVoiceStdin(text) : { md: text.trim(), heard: undefined };
|
|
28183
28402
|
if (!md) {
|
|
28184
28403
|
error("an instruction needs some text");
|
|
@@ -28271,7 +28490,7 @@ async function approveCmd(o, argv) {
|
|
|
28271
28490
|
error(APPROVE_USAGE);
|
|
28272
28491
|
return 2;
|
|
28273
28492
|
}
|
|
28274
|
-
const heard = a.voice ? (o.stdin ?? (() =>
|
|
28493
|
+
const heard = a.voice ? (o.stdin ?? (() => readFileSync32(0, "utf8")))().trim() : undefined;
|
|
28275
28494
|
let nodes;
|
|
28276
28495
|
let approach;
|
|
28277
28496
|
if (a.file) {
|
|
@@ -28394,7 +28613,7 @@ async function decisionCmd(o, argv) {
|
|
|
28394
28613
|
error(DECISION_USAGE);
|
|
28395
28614
|
return 2;
|
|
28396
28615
|
}
|
|
28397
|
-
const md = seen || routeAlone ? "" : (fromStdin ? (o.stdin ?? (() =>
|
|
28616
|
+
const md = seen || routeAlone ? "" : (fromStdin ? (o.stdin ?? (() => readFileSync32(0, "utf8")))() : rest.join(" ")).trim();
|
|
28398
28617
|
if (!seen && !routeAlone && (!md || fromStdin && rest.length > 0)) {
|
|
28399
28618
|
error(md ? DECISION_USAGE : `${answer ? "an answer" : "an overrule"} needs some text`);
|
|
28400
28619
|
return 2;
|
|
@@ -28573,7 +28792,7 @@ function approvedLine(key, j) {
|
|
|
28573
28792
|
function readNodes(o, a) {
|
|
28574
28793
|
let text;
|
|
28575
28794
|
try {
|
|
28576
|
-
text = a.file ? (o.readFile ?? ((p) =>
|
|
28795
|
+
text = a.file ? (o.readFile ?? ((p) => readFileSync32(p, "utf8")))(a.file) : (o.stdin ?? (() => readFileSync32(0, "utf8")))();
|
|
28577
28796
|
} catch (e) {
|
|
28578
28797
|
return { error: e instanceof Error ? e.message : String(e) };
|
|
28579
28798
|
}
|
|
@@ -29010,7 +29229,7 @@ async function seatRevokeCmd(o) {
|
|
|
29010
29229
|
|
|
29011
29230
|
// src/commands/seatSync.ts
|
|
29012
29231
|
import { execFileSync as execFileSync6 } from "node:child_process";
|
|
29013
|
-
import { existsSync as existsSync31, mkdirSync as mkdirSync27, readFileSync as
|
|
29232
|
+
import { existsSync as existsSync31, mkdirSync as mkdirSync27, readFileSync as readFileSync33, readdirSync as readdirSync7, rmSync as rmSync21, writeFileSync as writeFileSync27 } from "node:fs";
|
|
29014
29233
|
import { platform as platform2 } from "node:os";
|
|
29015
29234
|
import { dirname as dirname24, join as join33 } from "node:path";
|
|
29016
29235
|
|
|
@@ -29360,7 +29579,7 @@ function findCookieDb(home, source) {
|
|
|
29360
29579
|
return db;
|
|
29361
29580
|
}
|
|
29362
29581
|
const localStatePath = join33(root, "Local State");
|
|
29363
|
-
const localState = existsSync31(localStatePath) ?
|
|
29582
|
+
const localState = existsSync31(localStatePath) ? readFileSync33(localStatePath, "utf8") : null;
|
|
29364
29583
|
const wanted = source.profile ?? "Default";
|
|
29365
29584
|
const { dir, ambiguous } = resolveProfileDir(localState, wanted);
|
|
29366
29585
|
if (ambiguous)
|
|
@@ -29542,7 +29761,7 @@ var seatSync = async (o) => {
|
|
|
29542
29761
|
};
|
|
29543
29762
|
function readSeatToken(home, source) {
|
|
29544
29763
|
try {
|
|
29545
|
-
return
|
|
29764
|
+
return readFileSync33(seatTokenPath(home, source), "utf8").trim() || undefined;
|
|
29546
29765
|
} catch {
|
|
29547
29766
|
return;
|
|
29548
29767
|
}
|
|
@@ -29628,7 +29847,7 @@ import { homedir as homedir8 } from "node:os";
|
|
|
29628
29847
|
import { join as join37, resolve as resolve12 } from "node:path";
|
|
29629
29848
|
|
|
29630
29849
|
// src/sleuth/export.ts
|
|
29631
|
-
import { existsSync as existsSync32, mkdirSync as mkdirSync28, readFileSync as
|
|
29850
|
+
import { existsSync as existsSync32, mkdirSync as mkdirSync28, readFileSync as readFileSync34, renameSync as renameSync13, writeFileSync as writeFileSync28 } from "node:fs";
|
|
29632
29851
|
import { dirname as dirname25, join as join34 } from "node:path";
|
|
29633
29852
|
|
|
29634
29853
|
// src/sleuth/graphql.ts
|
|
@@ -30183,7 +30402,7 @@ var writeAtomic = (path, body) => {
|
|
|
30183
30402
|
var jsonl = (items) => items.length ? `${items.map((i) => JSON.stringify(i)).join(`
|
|
30184
30403
|
`)}
|
|
30185
30404
|
` : "";
|
|
30186
|
-
var readJsonl = (path) =>
|
|
30405
|
+
var readJsonl = (path) => readFileSync34(path, "utf8").split(`
|
|
30187
30406
|
`).filter((l) => l.trim()).map((l) => JSON.parse(l));
|
|
30188
30407
|
var CANNOT_QUERY = /Cannot query field "(\w+)" on type "(\w+)"/;
|
|
30189
30408
|
var TOO_DEEP = /\bmax(imum)?\b.{0,24}\bdepth\b|\btoo deep\b/i;
|
|
@@ -30640,9 +30859,9 @@ var exportSleuth = async (o) => {
|
|
|
30640
30859
|
// src/sleuth/import.ts
|
|
30641
30860
|
init_src();
|
|
30642
30861
|
import { execFileSync as execFileSync7 } from "node:child_process";
|
|
30643
|
-
import { mkdtempSync as mkdtempSync2, readFileSync as
|
|
30862
|
+
import { mkdtempSync as mkdtempSync2, readFileSync as readFileSync35, readdirSync as readdirSync8, rmSync as rmSync22, statSync as statSync10 } from "node:fs";
|
|
30644
30863
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
30645
|
-
import { basename as
|
|
30864
|
+
import { basename as basename12, join as join35 } from "node:path";
|
|
30646
30865
|
var httpFetch = (url, init) => fetch(url, { ...init, body: init.body === "" ? undefined : init.body });
|
|
30647
30866
|
|
|
30648
30867
|
class SleuthImportError extends Error {
|
|
@@ -30654,7 +30873,7 @@ class SleuthImportError extends Error {
|
|
|
30654
30873
|
}
|
|
30655
30874
|
var isDir2 = (p) => {
|
|
30656
30875
|
try {
|
|
30657
|
-
return
|
|
30876
|
+
return statSync10(p).isDirectory();
|
|
30658
30877
|
} catch {
|
|
30659
30878
|
return false;
|
|
30660
30879
|
}
|
|
@@ -30668,7 +30887,7 @@ var entries = (p) => {
|
|
|
30668
30887
|
};
|
|
30669
30888
|
function changesRoot(dir) {
|
|
30670
30889
|
const here = [join35(dir, "data", "changes"), join35(dir, "changes")];
|
|
30671
|
-
if (
|
|
30890
|
+
if (basename12(dir) === "changes")
|
|
30672
30891
|
here.unshift(dir);
|
|
30673
30892
|
const below = entries(dir).map((e) => join35(dir, e)).filter(isDir2).flatMap((d) => [join35(d, "data", "changes"), join35(d, "changes")]);
|
|
30674
30893
|
return [...here, ...below].find(isDir2);
|
|
@@ -30683,7 +30902,7 @@ function* readChanges(dir) {
|
|
|
30683
30902
|
continue;
|
|
30684
30903
|
for (const name of entries(pdir).filter((f) => f.endsWith(".jsonl"))) {
|
|
30685
30904
|
const file = join35(pdir, name);
|
|
30686
|
-
const lines =
|
|
30905
|
+
const lines = readFileSync35(file, "utf8").split(`
|
|
30687
30906
|
`);
|
|
30688
30907
|
for (let i = 0;i < lines.length; i++) {
|
|
30689
30908
|
const text = lines[i].trim();
|
|
@@ -30704,7 +30923,7 @@ var systemUnzip = (zip, dest) => {
|
|
|
30704
30923
|
function openExport(path, unzip = systemUnzip) {
|
|
30705
30924
|
let file = false;
|
|
30706
30925
|
try {
|
|
30707
|
-
const s =
|
|
30926
|
+
const s = statSync10(path);
|
|
30708
30927
|
if (s.isDirectory())
|
|
30709
30928
|
return { dir: path, done: () => {} };
|
|
30710
30929
|
file = s.isFile();
|
|
@@ -31094,11 +31313,12 @@ var repoOk = (v) => REPO_RE.test(v);
|
|
|
31094
31313
|
|
|
31095
31314
|
// src/sleuth/reconcile.ts
|
|
31096
31315
|
init_src();
|
|
31097
|
-
import { readFileSync as
|
|
31316
|
+
import { readFileSync as readFileSync36, readdirSync as readdirSync9 } from "node:fs";
|
|
31098
31317
|
import { dirname as dirname26, join as join36 } from "node:path";
|
|
31099
31318
|
var OFF = 0.1;
|
|
31100
31319
|
var isObj8 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
|
|
31101
31320
|
var nums = (v) => Array.isArray(v) ? v.map((x) => typeof x === "number" && Number.isFinite(x) ? x : 0) : [];
|
|
31321
|
+
var sum = (xs) => xs.reduce((a, b) => a + b, 0);
|
|
31102
31322
|
var MONTH_FILE = /^(\d{4}-(0[1-9]|1[0-2]))\.json$/;
|
|
31103
31323
|
function sleuthMonth(json, project, month) {
|
|
31104
31324
|
if (!isObj8(json))
|
|
@@ -31108,17 +31328,22 @@ function sleuthMonth(json, project, month) {
|
|
|
31108
31328
|
return "no metricFrequency";
|
|
31109
31329
|
const perDay = nums(freq.datapoints);
|
|
31110
31330
|
const leadPerDay = isObj8(json.metricLeadTime) ? nums(json.metricLeadTime.datapoints) : [];
|
|
31111
|
-
const deploys = Math.round(perDay
|
|
31331
|
+
const deploys = Math.round(sum(perDay));
|
|
31112
31332
|
let weighted = 0;
|
|
31113
31333
|
for (let i = 0;i < perDay.length; i++)
|
|
31114
31334
|
weighted += perDay[i] * (leadPerDay[i] ?? 0);
|
|
31335
|
+
const failed = isObj8(json.metricFailureRate) ? Math.round(sum(nums(json.metricFailureRate.datapoints))) : null;
|
|
31336
|
+
const failedFor = isObj8(json.metricMttr) ? sum(nums(json.metricMttr.datapoints)) : null;
|
|
31115
31337
|
return {
|
|
31116
31338
|
project,
|
|
31117
31339
|
month,
|
|
31118
31340
|
environment: typeof json.environment === "string" ? json.environment.toLowerCase() : "",
|
|
31119
31341
|
deploys,
|
|
31120
|
-
flags: nums(freq.ffDeploys)
|
|
31121
|
-
lead: deploys ? Math.round(weighted / deploys) : null
|
|
31342
|
+
flags: sum(nums(freq.ffDeploys)),
|
|
31343
|
+
lead: deploys ? Math.round(weighted / deploys) : null,
|
|
31344
|
+
failed,
|
|
31345
|
+
failureRate: failed !== null && deploys ? failed / deploys : null,
|
|
31346
|
+
mttr: failed && failedFor !== null ? Math.round(failedFor / failed) : null
|
|
31122
31347
|
};
|
|
31123
31348
|
}
|
|
31124
31349
|
function metricsRoot(dir) {
|
|
@@ -31146,7 +31371,7 @@ function readMetrics(dir) {
|
|
|
31146
31371
|
continue;
|
|
31147
31372
|
let json;
|
|
31148
31373
|
try {
|
|
31149
|
-
json = JSON.parse(
|
|
31374
|
+
json = JSON.parse(readFileSync36(join36(root, project, name), "utf8"));
|
|
31150
31375
|
} catch {
|
|
31151
31376
|
errors.push(`${project}/${name}: not JSON`);
|
|
31152
31377
|
continue;
|
|
@@ -31208,24 +31433,43 @@ ${env.env.slug}
|
|
|
31208
31433
|
${s.month}`);
|
|
31209
31434
|
if (!s.deploys && !o?.deploys)
|
|
31210
31435
|
continue;
|
|
31436
|
+
const sledsDeploys = o?.deploys ?? 0;
|
|
31211
31437
|
const sledsLead = o?.lead?.workingByDeploy ?? null;
|
|
31212
|
-
const dDeploys = delta(s.deploys,
|
|
31438
|
+
const dDeploys = delta(s.deploys, sledsDeploys);
|
|
31213
31439
|
const dLead = s.lead !== null && sledsLead !== null ? delta(s.lead, sledsLead) : null;
|
|
31440
|
+
const sledsFailed = o ? o.failed ?? null : 0;
|
|
31441
|
+
const sledsRate = sledsFailed !== null && sledsDeploys ? sledsFailed / sledsDeploys : null;
|
|
31442
|
+
const sledsRecover = o?.recover ?? null;
|
|
31443
|
+
const compared = s.failed !== null && sledsFailed !== null;
|
|
31444
|
+
const dRate = compared && s.failureRate !== null && sledsRate !== null ? delta(s.failureRate, sledsRate) : null;
|
|
31445
|
+
const dRecover = s.mttr !== null && sledsRecover !== null ? delta(s.mttr, sledsRecover.mean) : null;
|
|
31446
|
+
const over = (d) => d !== null && Math.abs(d) > OFF;
|
|
31214
31447
|
rows.push({
|
|
31215
31448
|
project: s.project,
|
|
31216
31449
|
repo,
|
|
31217
31450
|
environment: env.env.slug,
|
|
31218
31451
|
month: s.month,
|
|
31219
|
-
sleuth: {
|
|
31452
|
+
sleuth: {
|
|
31453
|
+
deploys: s.deploys,
|
|
31454
|
+
lead: s.lead,
|
|
31455
|
+
failed: s.failed,
|
|
31456
|
+
failureRate: s.failureRate,
|
|
31457
|
+
mttr: s.mttr
|
|
31458
|
+
},
|
|
31220
31459
|
sleds: {
|
|
31221
|
-
deploys:
|
|
31460
|
+
deploys: sledsDeploys,
|
|
31222
31461
|
prs: o?.prs ?? 0,
|
|
31223
31462
|
missing: o?.missing ?? 0,
|
|
31224
|
-
lead: o?.lead ?? null
|
|
31463
|
+
lead: o?.lead ?? null,
|
|
31464
|
+
failed: sledsFailed,
|
|
31465
|
+
failureRate: sledsRate,
|
|
31466
|
+
recover: sledsRecover
|
|
31225
31467
|
},
|
|
31226
31468
|
deltaDeploys: dDeploys,
|
|
31227
31469
|
deltaLead: dLead,
|
|
31228
|
-
|
|
31470
|
+
deltaFailureRate: dRate,
|
|
31471
|
+
deltaRecover: dRecover,
|
|
31472
|
+
off: dDeploys === null || over(dDeploys) || over(dLead) || over(dRate) || over(dRecover) || compared && !s.failed !== !sledsFailed
|
|
31229
31473
|
});
|
|
31230
31474
|
}
|
|
31231
31475
|
const flagOnly = new Map;
|
|
@@ -31295,6 +31539,65 @@ async function reconcileSleuth(o) {
|
|
|
31295
31539
|
}
|
|
31296
31540
|
var hours = (s) => s === null || s === undefined ? "—" : `${(s / 3600).toFixed(1)}h`;
|
|
31297
31541
|
var pct = (d, sledsHas) => d === null ? sledsHas ? "new" : "—" : `${d >= 0 ? "+" : ""}${Math.round(d * 100)}%`;
|
|
31542
|
+
var rate = (x) => x === null ? "—" : `${(x * 100).toFixed(1)}%`;
|
|
31543
|
+
function columns(head, body) {
|
|
31544
|
+
const widths = head.map((h, i) => Math.max(h.length, ...body.map((row) => row[i].length)));
|
|
31545
|
+
const fmt = (row) => ` ${row.map((c, i) => i < 2 ? c.padEnd(widths[i]) : c.padStart(widths[i])).join(" ")}`.trimEnd();
|
|
31546
|
+
return [fmt(head), ...body.map(fmt)];
|
|
31547
|
+
}
|
|
31548
|
+
function stabilityTable(r) {
|
|
31549
|
+
if (!r.rows.length)
|
|
31550
|
+
return [];
|
|
31551
|
+
if (r.rows.every((x) => x.sleuth.failed === null))
|
|
31552
|
+
return [
|
|
31553
|
+
"",
|
|
31554
|
+
" Change failure rate and time to recover not compared: Sleuth's series has no metricFailureRate or metricMttr — export them again with export_metrics.sh."
|
|
31555
|
+
];
|
|
31556
|
+
if (r.rows.every((x) => x.sleds.failed === null))
|
|
31557
|
+
return [
|
|
31558
|
+
"",
|
|
31559
|
+
" Change failure rate and time to recover not compared: SLEDS did not answer with them — its deploy is older than SL-2202."
|
|
31560
|
+
];
|
|
31561
|
+
const failing = r.rows.filter((x) => (x.sleuth.failed ?? 0) > 0 || (x.sleds.failed ?? 0) > 0);
|
|
31562
|
+
const out = [
|
|
31563
|
+
"",
|
|
31564
|
+
"Change failure rate (failed ÷ deploys) and time to recover in wall-clock hours, the months with a failure on either side. Sleuth's time to recover is how long a failed change stayed failed; SLEDS's runs from a failed deploy to the next deploy to its target that held — mean beside mean, SLEDS's median after",
|
|
31565
|
+
""
|
|
31566
|
+
];
|
|
31567
|
+
if (!failing.length)
|
|
31568
|
+
return [...out, " (no failure on either side)"];
|
|
31569
|
+
const n = (x) => x === null ? "—" : String(x);
|
|
31570
|
+
return [
|
|
31571
|
+
...out,
|
|
31572
|
+
...columns([
|
|
31573
|
+
"project",
|
|
31574
|
+
"month",
|
|
31575
|
+
"Sleuth failed",
|
|
31576
|
+
"SLEDS failed",
|
|
31577
|
+
"Sleuth rate",
|
|
31578
|
+
"SLEDS rate",
|
|
31579
|
+
"Δ",
|
|
31580
|
+
"Sleuth recover",
|
|
31581
|
+
"SLEDS recover",
|
|
31582
|
+
"Δ",
|
|
31583
|
+
"median",
|
|
31584
|
+
""
|
|
31585
|
+
], failing.map((x) => [
|
|
31586
|
+
x.project,
|
|
31587
|
+
x.month,
|
|
31588
|
+
n(x.sleuth.failed),
|
|
31589
|
+
n(x.sleds.failed),
|
|
31590
|
+
rate(x.sleuth.failureRate),
|
|
31591
|
+
rate(x.sleds.failureRate),
|
|
31592
|
+
pct(x.deltaFailureRate, (x.sleds.failed ?? 0) > 0),
|
|
31593
|
+
hours(x.sleuth.mttr),
|
|
31594
|
+
hours(x.sleds.recover?.mean),
|
|
31595
|
+
pct(x.deltaRecover, false),
|
|
31596
|
+
hours(x.sleds.recover?.median),
|
|
31597
|
+
x.off ? "!" : ""
|
|
31598
|
+
]))
|
|
31599
|
+
];
|
|
31600
|
+
}
|
|
31298
31601
|
function reconcileTable(r) {
|
|
31299
31602
|
const head = [
|
|
31300
31603
|
"project",
|
|
@@ -31324,16 +31627,14 @@ function reconcileTable(r) {
|
|
|
31324
31627
|
x.sleds.missing ? `${x.sleds.missing} of ${x.sleds.prs}` : "",
|
|
31325
31628
|
x.off ? "!" : ""
|
|
31326
31629
|
]);
|
|
31327
|
-
const widths = head.map((h, i) => Math.max(h.length, ...body.map((row) => row[i].length)));
|
|
31328
|
-
const fmt = (row) => ` ${row.map((c, i) => i < 2 ? c.padEnd(widths[i]) : c.padStart(widths[i])).join(" ")}`.trimEnd();
|
|
31329
31630
|
const out = [
|
|
31330
31631
|
`Sleuth beside SLEDS for ${r.org}, ${r.since} to ${r.until} — deploys a month; lead time in working hours (Mon–Fri 14:00–23:00 UTC), a mean over deploys as Sleuth counts it`,
|
|
31331
31632
|
"",
|
|
31332
|
-
|
|
31333
|
-
...body.map(fmt)
|
|
31633
|
+
...columns(head, body)
|
|
31334
31634
|
];
|
|
31335
31635
|
if (!r.rows.length)
|
|
31336
31636
|
out.push(" (no month with deploys on either side)");
|
|
31637
|
+
out.push(...stabilityTable(r));
|
|
31337
31638
|
if (r.skipped.length) {
|
|
31338
31639
|
out.push("", " not compared:");
|
|
31339
31640
|
for (const s of r.skipped)
|
|
@@ -31729,8 +32030,8 @@ var reconcileCmd = async (o, { words, flags, all }) => {
|
|
|
31729
32030
|
|
|
31730
32031
|
// src/commands/specEvent.ts
|
|
31731
32032
|
init_meter();
|
|
31732
|
-
import { readFileSync as
|
|
31733
|
-
import { basename as
|
|
32033
|
+
import { readFileSync as readFileSync37, statSync as statSync11 } from "node:fs";
|
|
32034
|
+
import { basename as basename13, isAbsolute as isAbsolute7, relative as relative2 } from "node:path";
|
|
31734
32035
|
var HOOK_STDIN_TIMEOUT_MS3 = 1000;
|
|
31735
32036
|
var ESTIMATE_TIMEOUT_MS = 4000;
|
|
31736
32037
|
var MIN_SPEC_CHARS = 200;
|
|
@@ -31743,12 +32044,12 @@ function isSpecPath(path) {
|
|
|
31743
32044
|
return false;
|
|
31744
32045
|
if (NOT_SPEC.test(path))
|
|
31745
32046
|
return false;
|
|
31746
|
-
return SPEC_DIRS.test(path) || SPEC_NAMES.test(
|
|
32047
|
+
return SPEC_DIRS.test(path) || SPEC_NAMES.test(basename13(path));
|
|
31747
32048
|
}
|
|
31748
32049
|
function specTitle(body, path) {
|
|
31749
32050
|
const m = /^#\s+(.+?)\s*$/m.exec(body);
|
|
31750
32051
|
const t = m?.[1]?.trim();
|
|
31751
|
-
return (t && t.length > 0 ? t :
|
|
32052
|
+
return (t && t.length > 0 ? t : basename13(path).replace(/\.(md|mdx)$/i, "")).slice(0, 120);
|
|
31752
32053
|
}
|
|
31753
32054
|
function looksLikeSpec(body) {
|
|
31754
32055
|
if (body.trim().length < MIN_SPEC_CHARS)
|
|
@@ -31783,9 +32084,9 @@ function projectKey(filePath, cwd) {
|
|
|
31783
32084
|
}
|
|
31784
32085
|
function readFileOrNull(path) {
|
|
31785
32086
|
try {
|
|
31786
|
-
if (
|
|
32087
|
+
if (statSync11(path).size > 2000000)
|
|
31787
32088
|
return null;
|
|
31788
|
-
return
|
|
32089
|
+
return readFileSync37(path, "utf8");
|
|
31789
32090
|
} catch {
|
|
31790
32091
|
return null;
|
|
31791
32092
|
}
|
|
@@ -31811,7 +32112,7 @@ var specEvent = async (o) => {
|
|
|
31811
32112
|
const spec = {
|
|
31812
32113
|
title: specTitle(body, input.filePath),
|
|
31813
32114
|
body: body.slice(0, MAX_SPEC_CHARS),
|
|
31814
|
-
repoHint: input.cwd ?
|
|
32115
|
+
repoHint: input.cwd ? basename13(input.cwd) : undefined
|
|
31815
32116
|
};
|
|
31816
32117
|
try {
|
|
31817
32118
|
const res = await (o.fetchFn ?? fetch)(`${src.proxyUrl}/proxy/estimate`, {
|
|
@@ -32130,7 +32431,7 @@ var announce = (o, events) => {
|
|
|
32130
32431
|
|
|
32131
32432
|
// src/commands/stopEvent.ts
|
|
32132
32433
|
init_meter();
|
|
32133
|
-
import { existsSync as existsSync34, readFileSync as
|
|
32434
|
+
import { existsSync as existsSync34, readFileSync as readFileSync38 } from "node:fs";
|
|
32134
32435
|
|
|
32135
32436
|
// src/transcript.ts
|
|
32136
32437
|
var isObject16 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
@@ -32231,7 +32532,7 @@ async function postTranscript(o, payload, now) {
|
|
|
32231
32532
|
}
|
|
32232
32533
|
if (!src)
|
|
32233
32534
|
return false;
|
|
32234
|
-
const read = o.readFile ?? ((p) => existsSync34(p) ?
|
|
32535
|
+
const read = o.readFile ?? ((p) => existsSync34(p) ? readFileSync38(p, "utf8") : null);
|
|
32235
32536
|
let text;
|
|
32236
32537
|
try {
|
|
32237
32538
|
text = read(path);
|
|
@@ -32309,7 +32610,7 @@ var stopEvent = async (o) => {
|
|
|
32309
32610
|
|
|
32310
32611
|
// src/commands/uninstall.ts
|
|
32311
32612
|
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
32312
|
-
import { existsSync as existsSync35, readFileSync as
|
|
32613
|
+
import { existsSync as existsSync35, readFileSync as readFileSync39, rmSync as rmSync23 } from "node:fs";
|
|
32313
32614
|
init_config();
|
|
32314
32615
|
init_meter();
|
|
32315
32616
|
init_settings();
|
|
@@ -32326,7 +32627,7 @@ var planUninstall = (o) => {
|
|
|
32326
32627
|
const changes = [];
|
|
32327
32628
|
const remove = [];
|
|
32328
32629
|
const codexPath = codexConfigPath(o.home);
|
|
32329
|
-
const codex = user && existsSync35(codexPath) && removeCodexProvider(
|
|
32630
|
+
const codex = user && existsSync35(codexPath) && removeCodexProvider(readFileSync39(codexPath, "utf8")) !== readFileSync39(codexPath, "utf8");
|
|
32330
32631
|
if (codex)
|
|
32331
32632
|
changes.push({ path: codexPath, what: 'removes the "sleds" provider' });
|
|
32332
32633
|
const priorStatusLine = user ? cfg.priorStatusLine : rec?.priorStatusLine;
|
|
@@ -32463,7 +32764,7 @@ var uninstall2 = async (o) => {
|
|
|
32463
32764
|
init_server();
|
|
32464
32765
|
import { existsSync as existsSync36 } from "node:fs";
|
|
32465
32766
|
import { homedir as homedir9, userInfo as userInfo4 } from "node:os";
|
|
32466
|
-
import { basename as
|
|
32767
|
+
import { basename as basename14 } from "node:path";
|
|
32467
32768
|
init_config();
|
|
32468
32769
|
init_state();
|
|
32469
32770
|
init_meter();
|
|
@@ -32528,7 +32829,7 @@ var realPidAlive4 = (pid) => {
|
|
|
32528
32829
|
};
|
|
32529
32830
|
function machineClient(home, env) {
|
|
32530
32831
|
const src = meterSource(home, undefined, { env });
|
|
32531
|
-
return src ? fetchClient({ ...src, version: "0.1.
|
|
32832
|
+
return src ? fetchClient({ ...src, version: "0.1.72" }) : null;
|
|
32532
32833
|
}
|
|
32533
32834
|
async function noteAnswer2(home, a, now) {
|
|
32534
32835
|
try {
|
|
@@ -32540,7 +32841,7 @@ async function noteAnswer2(home, a, now) {
|
|
|
32540
32841
|
}
|
|
32541
32842
|
function busyEngines(files) {
|
|
32542
32843
|
return files.map((f) => ({
|
|
32543
|
-
name:
|
|
32844
|
+
name: basename14(f, ".json"),
|
|
32544
32845
|
running: readState(f).runs.filter(isRunning).length
|
|
32545
32846
|
})).filter((e) => e.running > 0);
|
|
32546
32847
|
}
|
|
@@ -32722,8 +33023,8 @@ async function maybeNotice(cmd, argv, o) {
|
|
|
32722
33023
|
|
|
32723
33024
|
// src/commands/verify.ts
|
|
32724
33025
|
init_meter();
|
|
32725
|
-
import { readFileSync as
|
|
32726
|
-
import { basename as
|
|
33026
|
+
import { readFileSync as readFileSync40, statSync as statSync12 } from "node:fs";
|
|
33027
|
+
import { basename as basename15, extname as extname2 } from "node:path";
|
|
32727
33028
|
var jobIdFromTarget = (target) => {
|
|
32728
33029
|
const t = target.trim();
|
|
32729
33030
|
const m = /SLEDS-Attest:.*\bjob=([^\s]+)/.exec(t);
|
|
@@ -32848,17 +33149,17 @@ async function verdictCmd2(o) {
|
|
|
32848
33149
|
let screenshot;
|
|
32849
33150
|
if (a.file) {
|
|
32850
33151
|
try {
|
|
32851
|
-
if (!o.readFile &&
|
|
33152
|
+
if (!o.readFile && statSync12(a.file).size > SHOT_MAX_BYTES2) {
|
|
32852
33153
|
error(`${a.file}: a screenshot is at most 4 MB`);
|
|
32853
33154
|
return 1;
|
|
32854
33155
|
}
|
|
32855
|
-
const bytes = (o.readFile ??
|
|
33156
|
+
const bytes = (o.readFile ?? readFileSync40)(a.file);
|
|
32856
33157
|
if (bytes.byteLength > SHOT_MAX_BYTES2) {
|
|
32857
33158
|
error(`${a.file}: a screenshot is at most 4 MB`);
|
|
32858
33159
|
return 1;
|
|
32859
33160
|
}
|
|
32860
33161
|
screenshot = {
|
|
32861
|
-
name:
|
|
33162
|
+
name: basename15(a.file),
|
|
32862
33163
|
mime: shotMime2(a.file),
|
|
32863
33164
|
content: bytes.toString("base64")
|
|
32864
33165
|
};
|
|
@@ -32982,7 +33283,7 @@ var webhooksCmd = async (o) => {
|
|
|
32982
33283
|
|
|
32983
33284
|
// src/config.ts
|
|
32984
33285
|
init_settings();
|
|
32985
|
-
import { chmodSync as chmodSync8, existsSync as existsSync37, mkdirSync as mkdirSync29, readFileSync as
|
|
33286
|
+
import { chmodSync as chmodSync8, existsSync as existsSync37, mkdirSync as mkdirSync29, readFileSync as readFileSync41, renameSync as renameSync14, writeFileSync as writeFileSync29 } from "node:fs";
|
|
32986
33287
|
import { join as join38, resolve as resolve13 } from "node:path";
|
|
32987
33288
|
var configDir2 = (home, env = process.env) => {
|
|
32988
33289
|
const o = env.SLEDS_HOME?.trim();
|
|
@@ -33153,17 +33454,17 @@ var readConfig2 = (home, env = process.env) => {
|
|
|
33153
33454
|
const p = configPath2(home, env);
|
|
33154
33455
|
if (!existsSync37(p))
|
|
33155
33456
|
return {};
|
|
33156
|
-
return parseConfig2(JSON.parse(
|
|
33457
|
+
return parseConfig2(JSON.parse(readFileSync41(p, "utf8")));
|
|
33157
33458
|
};
|
|
33158
33459
|
|
|
33159
33460
|
// src/musher.ts
|
|
33160
|
-
import { basename as
|
|
33461
|
+
import { basename as basename16, dirname as dirname27, join as join39 } from "node:path";
|
|
33161
33462
|
var MUSHER_LABEL2 = "ai.sleds.musher";
|
|
33162
33463
|
var musherLabel2 = (env = process.env) => {
|
|
33163
33464
|
const sh = env.SLEDS_HOME?.trim();
|
|
33164
33465
|
if (!sh)
|
|
33165
33466
|
return MUSHER_LABEL2;
|
|
33166
|
-
const tag =
|
|
33467
|
+
const tag = basename16(sh).replace(/^\.+/, "").replace(/[^A-Za-z0-9_-]+/g, "-") || "seat";
|
|
33167
33468
|
return `${MUSHER_LABEL2}.${tag}`;
|
|
33168
33469
|
};
|
|
33169
33470
|
var musherPlistPath2 = (home, env = process.env) => join39(home, "Library", "LaunchAgents", `${musherLabel2(env)}.plist`);
|
|
@@ -33249,7 +33550,7 @@ var defaultExec5 = (cmd, args) => {
|
|
|
33249
33550
|
};
|
|
33250
33551
|
|
|
33251
33552
|
// src/settings.ts
|
|
33252
|
-
import { basename as
|
|
33553
|
+
import { basename as basename17, dirname as dirname28, join as join41, resolve as resolve14 } from "node:path";
|
|
33253
33554
|
var withSeatEnv2 = (command, home, env = process.env, org) => {
|
|
33254
33555
|
const parts = [];
|
|
33255
33556
|
const sh = env.SLEDS_HOME?.trim();
|
|
@@ -33465,6 +33766,12 @@ commands:
|
|
|
33465
33766
|
--json SLEDS's answer as it came
|
|
33466
33767
|
defect <key> "<what is wrong>" The same as verify fail <key> "\u2026" --defect
|
|
33467
33768
|
(--same-engineer, --file, --json).
|
|
33769
|
+
attach <key> --file <path> Put a file from disk on the item (4 MB at most) and print its link \u2014
|
|
33770
|
+
a preview screenshot for the PR's look, a spec, a prototype.
|
|
33771
|
+
--kind <k> screenshot \xB7 prototype \xB7 spec \xB7 doc \xB7 other (read from the
|
|
33772
|
+
name when absent)
|
|
33773
|
+
--mock mark it as the item's mock
|
|
33774
|
+
--json SLEDS's answer as it came
|
|
33468
33775
|
off Switch Claude Code back to your seat. Restores whatever \`on\` replaced.
|
|
33469
33776
|
uninstall The same as \`sleds init --undo\`: lists what SLEDS put in your user settings and
|
|
33470
33777
|
asks first (--yes skips), then takes it out. Keeps ~/.sleds-token.
|
|
@@ -33621,7 +33928,7 @@ var main = async (argv) => {
|
|
|
33621
33928
|
now: Date.now(),
|
|
33622
33929
|
stderr: (line) => console.error(line),
|
|
33623
33930
|
isTTY: !!process.stderr.isTTY,
|
|
33624
|
-
version: "0.1.
|
|
33931
|
+
version: "0.1.72"
|
|
33625
33932
|
});
|
|
33626
33933
|
switch (cmd) {
|
|
33627
33934
|
case "update":
|
|
@@ -33852,6 +34159,8 @@ var main = async (argv) => {
|
|
|
33852
34159
|
return verify2({ home, target: process.argv.slice(3).join(" ") || undefined });
|
|
33853
34160
|
case "defect":
|
|
33854
34161
|
return defectCmd({ home, argv: argv.slice(1) });
|
|
34162
|
+
case "attach":
|
|
34163
|
+
return attachCmd({ home, argv: argv.slice(1) });
|
|
33855
34164
|
case "uninstall":
|
|
33856
34165
|
return uninstall2({
|
|
33857
34166
|
home,
|
|
@@ -33889,7 +34198,7 @@ ${renderHelpText(argv[1])}`);
|
|
|
33889
34198
|
case "version":
|
|
33890
34199
|
case "--version":
|
|
33891
34200
|
case "-v":
|
|
33892
|
-
console.log("sleds 0.1.
|
|
34201
|
+
console.log("sleds 0.1.72");
|
|
33893
34202
|
return 0;
|
|
33894
34203
|
default:
|
|
33895
34204
|
console.error(`unknown command: ${cmd}
|