@sleds/cli 0.1.42 → 0.1.43
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 +359 -86
- package/package.json +1 -1
package/dist/sleds.mjs
CHANGED
|
@@ -1083,6 +1083,83 @@ var init_verbs = __esm(() => {
|
|
|
1083
1083
|
];
|
|
1084
1084
|
});
|
|
1085
1085
|
|
|
1086
|
+
// ../../packages/shared/src/intake/forms.ts
|
|
1087
|
+
function norm(label) {
|
|
1088
|
+
return label.replace(/[*_`~]/g, "").replace(/\(s\)/gi, "s").replace(/[:?]+\s*$/, "").replace(/\s+/g, " ").trim().toLowerCase();
|
|
1089
|
+
}
|
|
1090
|
+
function readForm(text) {
|
|
1091
|
+
const lines = text.split(/\r?\n/);
|
|
1092
|
+
for (const def of FORMS) {
|
|
1093
|
+
const found = [];
|
|
1094
|
+
let cur = null;
|
|
1095
|
+
let known = 0;
|
|
1096
|
+
for (const raw of lines) {
|
|
1097
|
+
const line = raw.trim();
|
|
1098
|
+
if (!line)
|
|
1099
|
+
continue;
|
|
1100
|
+
const inline = /^\**([^:*]{2,60}?)\**\s*:\s*(.+)$/.exec(line);
|
|
1101
|
+
const whole = norm(line);
|
|
1102
|
+
const slotWhole = def.labels[whole];
|
|
1103
|
+
const slotInline = inline ? def.labels[norm(inline[1] ?? "")] : undefined;
|
|
1104
|
+
if (slotWhole) {
|
|
1105
|
+
cur = { label: line.replace(/[*_]/g, "").replace(/:\s*$/, ""), slot: slotWhole, value: [] };
|
|
1106
|
+
found.push(cur);
|
|
1107
|
+
known++;
|
|
1108
|
+
} else if (slotInline && inline) {
|
|
1109
|
+
cur = { label: (inline[1] ?? "").trim(), slot: slotInline, value: [inline[2] ?? ""] };
|
|
1110
|
+
found.push(cur);
|
|
1111
|
+
known++;
|
|
1112
|
+
} else if (/^\*[^*]{2,60}\*:?$/.test(line) && cur) {
|
|
1113
|
+
cur = { label: line.replace(/[*:]/g, "").trim(), slot: null, value: [] };
|
|
1114
|
+
found.push(cur);
|
|
1115
|
+
} else if (cur)
|
|
1116
|
+
cur.value.push(line);
|
|
1117
|
+
}
|
|
1118
|
+
if (known < def.min)
|
|
1119
|
+
continue;
|
|
1120
|
+
const val = (f) => f.value.join(" ").trim();
|
|
1121
|
+
const of = (slot) => found.filter((f) => f.slot === slot && val(f)).map((f) => ({ label: f.label, v: val(f) }));
|
|
1122
|
+
const ask = of("ask")[0]?.v;
|
|
1123
|
+
const who = of("for").map((x) => x.v);
|
|
1124
|
+
const extra = found.filter((f) => f.slot === null && val(f)).map((f) => `${f.label}: ${val(f)}`);
|
|
1125
|
+
const why = [who.length > 0 ? `For ${who.join(", ")}.` : "", ask ?? "", ...extra].filter(Boolean).join(" ");
|
|
1126
|
+
const touches = of("touches").map((x) => `${x.label} ${x.v}`).join(" · ");
|
|
1127
|
+
const n = of("demand")[0]?.v;
|
|
1128
|
+
const demand = n ? /^\d+$/.test(n) ? `${n} clients affected` : n : undefined;
|
|
1129
|
+
const rev = of("revenue")[0]?.v;
|
|
1130
|
+
return {
|
|
1131
|
+
form: def.name,
|
|
1132
|
+
...ask ? { ask } : {},
|
|
1133
|
+
...why ? { why } : {},
|
|
1134
|
+
...touches ? { touches } : {},
|
|
1135
|
+
...demand ? { demand } : {},
|
|
1136
|
+
...rev && YES.test(rev) ? { worth: "high · impacting revenue" } : {}
|
|
1137
|
+
};
|
|
1138
|
+
}
|
|
1139
|
+
return null;
|
|
1140
|
+
}
|
|
1141
|
+
var FORMS, YES;
|
|
1142
|
+
var init_forms = __esm(() => {
|
|
1143
|
+
FORMS = [
|
|
1144
|
+
{
|
|
1145
|
+
name: "Create Tech Support Ticket",
|
|
1146
|
+
labels: {
|
|
1147
|
+
"users experiencing the issue": "for",
|
|
1148
|
+
"user experiencing the issue": "for",
|
|
1149
|
+
sids: "touches",
|
|
1150
|
+
sid: "touches",
|
|
1151
|
+
"location ids": "touches",
|
|
1152
|
+
"location id": "touches",
|
|
1153
|
+
"issue description": "ask",
|
|
1154
|
+
"number of clients affected": "demand",
|
|
1155
|
+
"is the issue currently impacting revenue": "revenue"
|
|
1156
|
+
},
|
|
1157
|
+
min: 3
|
|
1158
|
+
}
|
|
1159
|
+
];
|
|
1160
|
+
YES = /^(yes|y|yep|true|definitely|it is)\b/i;
|
|
1161
|
+
});
|
|
1162
|
+
|
|
1086
1163
|
// ../../packages/shared/src/intake/brief.ts
|
|
1087
1164
|
function labelOf(line) {
|
|
1088
1165
|
const h = /^#{1,6}\s+(.+?)\s*#*\s*$/.exec(line);
|
|
@@ -1155,13 +1232,16 @@ function worthFromAnswer(answer) {
|
|
|
1155
1232
|
function draftBrief(input) {
|
|
1156
1233
|
const text = (input.text ?? "").trim();
|
|
1157
1234
|
const a = input.answers ?? {};
|
|
1158
|
-
const
|
|
1159
|
-
const
|
|
1235
|
+
const form = readForm(text);
|
|
1236
|
+
const parsed = sections(text);
|
|
1237
|
+
const preamble = parsed.preamble;
|
|
1238
|
+
const byKey = form ? { ...parsed.byKey, why: form.why, touches: form.touches, demand: form.demand } : parsed.byKey;
|
|
1239
|
+
const askText = a.ask?.trim() || (form?.ask ? askFrom(form.ask, form.ask) : askFrom(text, preamble));
|
|
1160
1240
|
if (!askText)
|
|
1161
1241
|
return null;
|
|
1162
1242
|
const ask = a.ask?.trim() ? { text: clip(a.ask, MAX_ASK), from: "filer" } : { text: clip(askText, MAX_ASK), from: "artifact" };
|
|
1163
1243
|
const pick = (k) => field(a[k], "filer") ?? field(byKey[k], "artifact");
|
|
1164
|
-
const worth = worthFromAnswer(a.worth) ?? parseWorth(text) ?? undefined;
|
|
1244
|
+
const worth = worthFromAnswer(a.worth) ?? parseWorth(text) ?? worthFromAnswer(form?.worth) ?? undefined;
|
|
1165
1245
|
const sources = [...new Set((input.links ?? []).map((l) => l.trim()).filter(Boolean))].slice(0, MAX_SOURCES);
|
|
1166
1246
|
return {
|
|
1167
1247
|
ask,
|
|
@@ -1288,6 +1368,7 @@ var MAX_FIELD = 280, MAX_ASK = 120, MAX_SOURCES = 12, QUESTIONS, REQUIRED_TO_FIL
|
|
|
1288
1368
|
}, fromWord = (f) => f.from === "filer" ? "from you" : f.from === "product" ? "from the product map" : "from what you sent";
|
|
1289
1369
|
var init_brief = __esm(() => {
|
|
1290
1370
|
init_worth();
|
|
1371
|
+
init_forms();
|
|
1291
1372
|
QUESTIONS = {
|
|
1292
1373
|
why: "Who is it for, and why now?",
|
|
1293
1374
|
done: "What does done look like, in your words?",
|
|
@@ -1769,7 +1850,7 @@ function buildRoute(drafts, opts = {}) {
|
|
|
1769
1850
|
problems.push({ level: "error", text: "a route needs at least one node" });
|
|
1770
1851
|
if (drafts.length > MAX_NODES)
|
|
1771
1852
|
problems.push({ level: "error", text: `a route holds at most ${MAX_NODES} nodes` });
|
|
1772
|
-
const given = drafts.map((d) => d.key ?
|
|
1853
|
+
const given = drafts.map((d) => d.key ? norm2(d.key) : "");
|
|
1773
1854
|
const fresh = mintKeys(given.filter((k) => !k).length, given.filter((k) => k));
|
|
1774
1855
|
let f = 0;
|
|
1775
1856
|
const keys = given.map((k) => k || fresh[f++]);
|
|
@@ -1784,7 +1865,7 @@ function buildRoute(drafts, opts = {}) {
|
|
|
1784
1865
|
const title = stripControl(d.title.replace(/\s+/g, " ")).trim().slice(0, 160);
|
|
1785
1866
|
if (!title)
|
|
1786
1867
|
problems.push({ level: "error", node: key, text: `node ${key} has no title` });
|
|
1787
|
-
const blockedBy = [...new Set((d.blockedBy ?? []).map(
|
|
1868
|
+
const blockedBy = [...new Set((d.blockedBy ?? []).map(norm2).filter(Boolean))];
|
|
1788
1869
|
for (const b of blockedBy) {
|
|
1789
1870
|
if (b === key)
|
|
1790
1871
|
problems.push({ level: "error", node: key, text: `node ${key} blocks itself` });
|
|
@@ -1961,7 +2042,7 @@ ${state}`)}, fillcolor="${fill}", color="${border}"${style}];`);
|
|
|
1961
2042
|
`)}
|
|
1962
2043
|
`;
|
|
1963
2044
|
}
|
|
1964
|
-
var ROUTE_APPROACH_MAX = 2000, PLAN_APPROACH_MAX = 1200, PLAN_LIST_MAX = 8, PLAN_LINE_MAX = 240, CONTROL, MAX_NODES = 24, DEPTH_WARN = 4,
|
|
2045
|
+
var ROUTE_APPROACH_MAX = 2000, PLAN_APPROACH_MAX = 1200, PLAN_LIST_MAX = 8, PLAN_LINE_MAX = 240, CONTROL, MAX_NODES = 24, DEPTH_WARN = 4, norm2 = (s) => s.trim().toUpperCase(), AREA_ROOTS, NOT_AREAS, sameRepo = (a, b) => a.length === 0 || b.length === 0 || a.some((r) => b.includes(r)), DOT_COLORS, ROUTE_DRAFT_RULE = "Draft the route: PR-sized nodes, file-disjoint where they run in parallel, each with a title, the files or areas it touches, the repo, and the nodes it waits on (by key: A, B, C…). Prefer wide waves over chains deeper than four. Make the tough calls once, so each node's session follows them: an `approach` paragraph for the whole route, and on each node a `plan` — its approach, what it `provides` that later nodes rely on (names, shapes, files), what it `expects` from the nodes it waits on, and the `doneChecks` that say it landed. Show the graph and the plans as text and ask for a yes; file nothing before it. Then `route {q, approach, nodes: [{key, title, touches, repos, blockedBy, plan: {approach, provides, expects, doneChecks}}], confirm: true}`.";
|
|
1965
2046
|
var init_route = __esm(() => {
|
|
1966
2047
|
CONTROL = /[\u0000-\u0008\u000b-\u001f\u007f-\u009f]/g;
|
|
1967
2048
|
AREA_ROOTS = new Set(["apps", "packages", "services", "libs", "crates", "modules"]);
|
|
@@ -5546,6 +5627,44 @@ var init_fieldMap = __esm(() => {
|
|
|
5546
5627
|
var SEPT_30 = "/whats-new/2026-09-30", WHATS_NEW;
|
|
5547
5628
|
var init_whatsNew = __esm(() => {
|
|
5548
5629
|
WHATS_NEW = [
|
|
5630
|
+
{
|
|
5631
|
+
date: "2026-10-21",
|
|
5632
|
+
title: "The Slack thread is the item's discussion",
|
|
5633
|
+
lede: "An item filed from a Slack thread keeps that thread. What people say there is on the item, what is said on the item goes back there, every move is one line in the thread, and everyone who has spoken hears what happens next.",
|
|
5634
|
+
sections: [
|
|
5635
|
+
{
|
|
5636
|
+
title: "Replies are comments; moves are lines",
|
|
5637
|
+
where: "Slack, after Filed as",
|
|
5638
|
+
body: "After Filed as, a reply in the thread is a comment on the item, as that person, marked from Slack. Approve, defer, take, land and archive each post one line in the thread with a link to the item. The item's Details has Slack, which opens the thread."
|
|
5639
|
+
},
|
|
5640
|
+
{
|
|
5641
|
+
title: "Comments go out",
|
|
5642
|
+
where: "The item › Discussion",
|
|
5643
|
+
body: "A comment written on the item is posted in its thread as the person who wrote it, and to Jira when the comments switch is on. The line under the composer says where it will go. SLEDS's own strips stay on SLEDS."
|
|
5644
|
+
},
|
|
5645
|
+
{
|
|
5646
|
+
title: "Watchers",
|
|
5647
|
+
where: "The item › Discussion, and @SLEDS in the thread",
|
|
5648
|
+
body: "Whoever filed it, holds it, or has spoken on it hears each move — once, never their own. Watch on the Discussion adds you; Unwatch stops it. In a thread, @SLEDS watch QW-123 ties an item to that thread, @SLEDS status answers with the item's status, and @SLEDS ask: … puts a question to the filer."
|
|
5649
|
+
},
|
|
5650
|
+
{
|
|
5651
|
+
title: "Forms are read as fields",
|
|
5652
|
+
where: "Slack, filing from a workflow post",
|
|
5653
|
+
body: "A support ticket form posted by a Slack workflow is read field by field: the issue description is the ask, who is affected and why go to the why, the IDs to what it touches, the count of clients to demand, and a yes on revenue to a high worth. The draft then asks only what the form did not say."
|
|
5654
|
+
},
|
|
5655
|
+
{
|
|
5656
|
+
title: "Which workspace, picked",
|
|
5657
|
+
where: "Slack, filing",
|
|
5658
|
+
body: "A channel tied to a workspace files there. With several workspaces and none tied to the channel, SLEDS asks which, as a numbered pick: reply with the number. The Jira key is never typed — the Filed as reply shows it."
|
|
5659
|
+
}
|
|
5660
|
+
],
|
|
5661
|
+
also: [
|
|
5662
|
+
{
|
|
5663
|
+
label: "Fixed",
|
|
5664
|
+
text: "An ask filed from Slack now creates its Jira ticket in the workspace it was filed on, and the reply names the key or says why none was made."
|
|
5665
|
+
}
|
|
5666
|
+
]
|
|
5667
|
+
},
|
|
5549
5668
|
{
|
|
5550
5669
|
date: "2026-10-20",
|
|
5551
5670
|
title: "Intake: the gate gets its own page",
|
|
@@ -6575,7 +6694,7 @@ function nodePrompt(o) {
|
|
|
6575
6694
|
`- Work on branch \`${o.branch}\` from the latest \`origin/${base}\` (create it if this checkout is not on it). One branch, one PR.`,
|
|
6576
6695
|
`- Open the PR against \`${base}\` with \`gh pr create${visual ? " --draft" : ""}\`${o.prTitle ? ` and title it exactly \`${o.prTitle}\` (the repo's CI checks it)` : ""}. Its body carries \`SLEDS-Node: ${claim.node}\` on the line under \`SLEDS-Source:\` when the pack names a source.`,
|
|
6577
6696
|
...claim.pack.includes(PR_HEADER_OPEN) ? [
|
|
6578
|
-
`- The PR body starts with the pack's PR header block (\`${PR_HEADER_OPEN}\` … \`${PR_HEADER_CLOSE}\`, in its part 5), above everything else
|
|
6697
|
+
`- The PR body starts with the pack's PR header block (\`${PR_HEADER_OPEN}\` … \`${PR_HEADER_CLOSE}\`, in its part 5), above everything else. The pack wrote it before your work existed: when you make a mock (a screenshot or an artifact) or write a doc, put its link on that part's line in place of \`None\` — not only lower in the body (SL-1746). When you edit the body later, keep it on top.`
|
|
6579
6698
|
] : [],
|
|
6580
6699
|
"- Run the repo's own gate before you push. Never merge: a person (or the musher, when the attachment says so) does.",
|
|
6581
6700
|
"- Stay inside this node's scope. Work another node needs goes in the PR description, not in this branch.",
|
|
@@ -7553,6 +7672,7 @@ var init_src = __esm(() => {
|
|
|
7553
7672
|
init_guides();
|
|
7554
7673
|
init_verbs();
|
|
7555
7674
|
init_brief();
|
|
7675
|
+
init_forms();
|
|
7556
7676
|
init_related();
|
|
7557
7677
|
init_rank();
|
|
7558
7678
|
init_markdown2();
|
|
@@ -8253,6 +8373,7 @@ init_cowork();
|
|
|
8253
8373
|
init_guides();
|
|
8254
8374
|
init_verbs();
|
|
8255
8375
|
init_brief();
|
|
8376
|
+
init_forms();
|
|
8256
8377
|
init_related();
|
|
8257
8378
|
init_rank();
|
|
8258
8379
|
init_markdown2();
|
|
@@ -9232,12 +9353,13 @@ var scanTranscriptForCredits = (path, prior) => {
|
|
|
9232
9353
|
return { hit: false, next: prior && prior.path === path ? prior : { path, offset: 0 } };
|
|
9233
9354
|
}
|
|
9234
9355
|
};
|
|
9235
|
-
var seatWindowBody = (w) => ({
|
|
9356
|
+
var seatWindowBody = (w, account) => ({
|
|
9236
9357
|
capturedAt: w.capturedAt,
|
|
9237
9358
|
source: "claude",
|
|
9238
9359
|
...w.fiveHour ? { fiveHour: w.fiveHour } : {},
|
|
9239
9360
|
...w.sevenDay ? { sevenDay: w.sevenDay } : {},
|
|
9240
|
-
...w.spendLimit ? { spendLimit: w.spendLimit } : {}
|
|
9361
|
+
...w.spendLimit ? { spendLimit: w.spendLimit } : {},
|
|
9362
|
+
...account ? { account } : {}
|
|
9241
9363
|
});
|
|
9242
9364
|
var postJson = async (o, path, body) => {
|
|
9243
9365
|
const fetchFn = o.fetchFn ?? fetch;
|
|
@@ -9253,7 +9375,7 @@ var postJson = async (o, path, body) => {
|
|
|
9253
9375
|
return false;
|
|
9254
9376
|
}
|
|
9255
9377
|
};
|
|
9256
|
-
var postSeatWindow = (o, w) => postJson(o, "/proxy/seat", seatWindowBody(w));
|
|
9378
|
+
var postSeatWindow = (o, w, account) => postJson(o, "/proxy/seat", seatWindowBody(w, account));
|
|
9257
9379
|
var postSeatWall = (o, input) => postJson(o, "/proxy/seat-wall", { source: "claude", ...input });
|
|
9258
9380
|
var SEAT_WALL_LINE = "Seat limit hit. sleds on --until-reset to continue on the platform key, or sleds defer to resume here at the reset.";
|
|
9259
9381
|
var SEAT_WALL_LINE_NO_KEY = "Seat limit hit. sleds defer resumes this session on this Mac at the reset; /sled 5 to hand off — this org has no platform key to switch to.";
|
|
@@ -9447,7 +9569,7 @@ import {
|
|
|
9447
9569
|
existsSync as existsSync16,
|
|
9448
9570
|
lstatSync,
|
|
9449
9571
|
mkdtempSync,
|
|
9450
|
-
readFileSync as
|
|
9572
|
+
readFileSync as readFileSync17,
|
|
9451
9573
|
readlinkSync,
|
|
9452
9574
|
rmSync as rmSync8,
|
|
9453
9575
|
writeFileSync as writeFileSync17
|
|
@@ -9850,7 +9972,7 @@ function resolveRepoPath(o) {
|
|
|
9850
9972
|
const want = o.repos.length ? o.repos.join(", ") : "this node";
|
|
9851
9973
|
const dir = names[0] ? ` (the folder that holds ${names[0]})` : "";
|
|
9852
9974
|
return {
|
|
9853
|
-
error: `No repo for ${want}: this engine runs in ${o.cwd}, which is not a git checkout. Set Repos
|
|
9975
|
+
error: `No repo for ${want}: this engine runs in ${o.cwd}, which is not a git checkout. Set Repos folders in Settings › Running work${dir}, or start the engine with --repo.`
|
|
9854
9976
|
};
|
|
9855
9977
|
}
|
|
9856
9978
|
for (const name of names) {
|
|
@@ -10375,7 +10497,7 @@ function cmuxRunner(exec, deps = {}) {
|
|
|
10375
10497
|
throw new Error(`cmux send-key ${h.id} failed: ${failed(r)}`);
|
|
10376
10498
|
},
|
|
10377
10499
|
stop(h) {
|
|
10378
|
-
|
|
10500
|
+
closeWorkspace(h.id);
|
|
10379
10501
|
if (!h.group)
|
|
10380
10502
|
return;
|
|
10381
10503
|
const l = cmux(LIST_GROUPS);
|
|
@@ -10444,7 +10566,7 @@ function beatBody(state, flags, host = {}, cap = {}) {
|
|
|
10444
10566
|
name: flags.name,
|
|
10445
10567
|
os: host.os ?? process.platform,
|
|
10446
10568
|
runner: flags.runner,
|
|
10447
|
-
version: host.version ?? "0.1.
|
|
10569
|
+
version: host.version ?? "0.1.43" ?? "dev",
|
|
10448
10570
|
running: live.length,
|
|
10449
10571
|
items: live.slice(0, BEAT_ITEMS).map((r) => `${r.item}/${r.node}`),
|
|
10450
10572
|
...cap.atOnce !== undefined ? { atOnce: cap.atOnce } : {},
|
|
@@ -10463,10 +10585,13 @@ function beatBody(state, flags, host = {}, cap = {}) {
|
|
|
10463
10585
|
}
|
|
10464
10586
|
async function postBeat(client, body) {
|
|
10465
10587
|
try {
|
|
10466
|
-
const r = await client.
|
|
10467
|
-
|
|
10588
|
+
const r = await client.postFull("/proxy/engine/beat", { ...body });
|
|
10589
|
+
if (r?.status === 200 && r.json?.ok === true)
|
|
10590
|
+
return { ok: true };
|
|
10591
|
+
const error = r?.json?.error;
|
|
10592
|
+
return r?.status === 409 && typeof error === "string" ? { ok: false, refused: error } : { ok: false };
|
|
10468
10593
|
} catch {
|
|
10469
|
-
return false;
|
|
10594
|
+
return { ok: false };
|
|
10470
10595
|
}
|
|
10471
10596
|
}
|
|
10472
10597
|
function beater(client, now, everyMs = BEAT_EVERY_MS) {
|
|
@@ -11254,6 +11379,11 @@ var notificationType = (text) => {
|
|
|
11254
11379
|
|
|
11255
11380
|
// src/commands/permissionEvent.ts
|
|
11256
11381
|
var isObject12 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
11382
|
+
var NOT_A_TOOL = new Set(["askuserquestion", "exitplanmode", "enterplanmode"]);
|
|
11383
|
+
var isToolPermission = (message) => {
|
|
11384
|
+
const tool = /permission to use\s+(.+?)\.?\s*$/i.exec(message)?.[1];
|
|
11385
|
+
return !tool || !NOT_A_TOOL.has(tool.replace(/[\s_-]/g, "").toLowerCase());
|
|
11386
|
+
};
|
|
11257
11387
|
var readPermissionMark = (file) => {
|
|
11258
11388
|
try {
|
|
11259
11389
|
const raw = JSON.parse(readFileSync10(file, "utf8"));
|
|
@@ -12136,7 +12266,36 @@ var DIALOG_ASKS = /^Do you want to .+\?$/;
|
|
|
12136
12266
|
var DIALOG_OPTION = /^(❯\s*)?(\d)\.\s+(.+)$/;
|
|
12137
12267
|
var DIALOG_FOOTER = /^(?:esc to |tab to |enter to |ctrl\+)/i;
|
|
12138
12268
|
var unbox = (line) => line.trimEnd().replace(/^\s*[│┃║]\s?/, "").replace(/\s*[│┃║]$/, "");
|
|
12269
|
+
var PICKER_CHIP = /^[☐☒✔✓□■]\s+\S/;
|
|
12270
|
+
var PICKER_OPTION = /^(?:Type something\.?|Chat about this|Submit answers?)$/i;
|
|
12271
|
+
var PICKER_FOOTER = /\benter to select\b|\bto navigate\b/i;
|
|
12272
|
+
var PICKER_ASKS = /^(?:Would you like to proceed\?|Ready to code\?)$/;
|
|
12273
|
+
var PICKER_REACH = 40;
|
|
12274
|
+
function choicePicker(screen) {
|
|
12275
|
+
const lines = screen.split(`
|
|
12276
|
+
`).map((l) => unbox(l).trim());
|
|
12277
|
+
let c = -1;
|
|
12278
|
+
for (let i = lines.length - 1;i >= 0; i--)
|
|
12279
|
+
if (/^❯\s*\d\.\s/.test(lines[i])) {
|
|
12280
|
+
c = i;
|
|
12281
|
+
break;
|
|
12282
|
+
}
|
|
12283
|
+
if (c < 0)
|
|
12284
|
+
return false;
|
|
12285
|
+
let from = c;
|
|
12286
|
+
while (from > 0 && c - from < PICKER_REACH && !/^⏺/.test(lines[from - 1]))
|
|
12287
|
+
from--;
|
|
12288
|
+
for (let i = from;i < lines.length; i++) {
|
|
12289
|
+
const t = lines[i];
|
|
12290
|
+
const choice = DIALOG_OPTION.exec(t)?.[3]?.trim() ?? "";
|
|
12291
|
+
if (PICKER_CHIP.test(t) || PICKER_ASKS.test(t) || PICKER_OPTION.test(choice) || i > c && PICKER_FOOTER.test(t))
|
|
12292
|
+
return true;
|
|
12293
|
+
}
|
|
12294
|
+
return false;
|
|
12295
|
+
}
|
|
12139
12296
|
function permissionDialog(screen) {
|
|
12297
|
+
if (choicePicker(screen))
|
|
12298
|
+
return null;
|
|
12140
12299
|
const raw = screen.split(`
|
|
12141
12300
|
`);
|
|
12142
12301
|
const lines = raw.map(unbox);
|
|
@@ -13151,7 +13310,11 @@ async function settlePermission(d, runner, run, shown) {
|
|
|
13151
13310
|
run.permission = undefined;
|
|
13152
13311
|
return false;
|
|
13153
13312
|
}
|
|
13154
|
-
|
|
13313
|
+
let mark = markFile ? readPermissionMark(markFile) : null;
|
|
13314
|
+
if (mark && markFile && (!isToolPermission(mark.message) || runner.readsSession && choicePicker(shown))) {
|
|
13315
|
+
clearPermissionMark(markFile);
|
|
13316
|
+
mark = null;
|
|
13317
|
+
}
|
|
13155
13318
|
if (!dialog && !mark)
|
|
13156
13319
|
return false;
|
|
13157
13320
|
if (!dialog && runner.readsSession && !run.seenTicks)
|
|
@@ -15315,7 +15478,7 @@ var statusLine2 = (session, events, now) => {
|
|
|
15315
15478
|
return `managed session: idle — its turn ended${money}`;
|
|
15316
15479
|
}
|
|
15317
15480
|
};
|
|
15318
|
-
var
|
|
15481
|
+
var YES2 = /^\s*(?:y|yes|allow|ok|okay|go|go ahead|approve[d]?)\b/i;
|
|
15319
15482
|
function managedRunner(exec, deps = {}) {
|
|
15320
15483
|
const env = deps.env ?? process.env;
|
|
15321
15484
|
const readFile = deps.readFile ?? ((p) => readFileSync12(p, "utf8"));
|
|
@@ -15440,7 +15603,7 @@ ${renderTranscript(eventMessages(all))}`;
|
|
|
15440
15603
|
const idle = lastIdle(all);
|
|
15441
15604
|
const asks = str9(obj2(idle?.stop_reason)?.type) === "requires_action" ? pendingAsks(all, idle) : [];
|
|
15442
15605
|
if (asks.length) {
|
|
15443
|
-
const allow =
|
|
15606
|
+
const allow = YES2.test(text);
|
|
15444
15607
|
api("POST", `/v1/sessions/${h.id}/events`, {
|
|
15445
15608
|
events: asks.map((e) => ({
|
|
15446
15609
|
type: "user.tool_confirmation",
|
|
@@ -16336,7 +16499,7 @@ async function driveEngine(o, flags, deps, until = {}) {
|
|
|
16336
16499
|
runner: deps.runner.name,
|
|
16337
16500
|
atOnce: flags.atOnce,
|
|
16338
16501
|
interval: flags.interval,
|
|
16339
|
-
cliVersion: "0.1.
|
|
16502
|
+
cliVersion: "0.1.43"
|
|
16340
16503
|
};
|
|
16341
16504
|
const beat = (checkedAt) => {
|
|
16342
16505
|
const m = deps.machine;
|
|
@@ -16647,7 +16810,6 @@ async function enginePauseCmd(o) {
|
|
|
16647
16810
|
|
|
16648
16811
|
// src/commands/engineInstall.ts
|
|
16649
16812
|
init_config();
|
|
16650
|
-
init_state();
|
|
16651
16813
|
import {
|
|
16652
16814
|
existsSync as existsSync14,
|
|
16653
16815
|
mkdirSync as mkdirSync14,
|
|
@@ -16659,6 +16821,7 @@ import {
|
|
|
16659
16821
|
} from "node:fs";
|
|
16660
16822
|
import { hostname as hostname3 } from "node:os";
|
|
16661
16823
|
import { basename as basename4, dirname as dirname12, isAbsolute as isAbsolute2, join as join18 } from "node:path";
|
|
16824
|
+
init_state();
|
|
16662
16825
|
|
|
16663
16826
|
// src/schedule.ts
|
|
16664
16827
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
@@ -17146,6 +17309,42 @@ var musherAgentState = (home, env = process.env) => {
|
|
|
17146
17309
|
}
|
|
17147
17310
|
};
|
|
17148
17311
|
|
|
17312
|
+
// src/claudeAccount.ts
|
|
17313
|
+
import { readFileSync as readFileSync16 } from "node:fs";
|
|
17314
|
+
var PLANS = {
|
|
17315
|
+
claude_max: "Max",
|
|
17316
|
+
claude_pro: "Pro",
|
|
17317
|
+
claude_team: "Team",
|
|
17318
|
+
claude_enterprise: "Enterprise"
|
|
17319
|
+
};
|
|
17320
|
+
var str11 = (v) => typeof v === "string" && v.trim() !== "" ? v.trim() : undefined;
|
|
17321
|
+
var parseClaudeAccount = (raw) => {
|
|
17322
|
+
if (typeof raw !== "object" || raw === null)
|
|
17323
|
+
return null;
|
|
17324
|
+
const acct = raw.oauthAccount;
|
|
17325
|
+
if (typeof acct !== "object" || acct === null)
|
|
17326
|
+
return null;
|
|
17327
|
+
const a = acct;
|
|
17328
|
+
const email = str11(a.emailAddress);
|
|
17329
|
+
if (!email)
|
|
17330
|
+
return null;
|
|
17331
|
+
const out = { email };
|
|
17332
|
+
const type = str11(a.organizationType);
|
|
17333
|
+
if (type && PLANS[type])
|
|
17334
|
+
out.plan = PLANS[type];
|
|
17335
|
+
const orgName = str11(a.organizationName);
|
|
17336
|
+
if (orgName)
|
|
17337
|
+
out.orgName = orgName;
|
|
17338
|
+
return out;
|
|
17339
|
+
};
|
|
17340
|
+
var readClaudeAccount = (home, env = process.env) => {
|
|
17341
|
+
try {
|
|
17342
|
+
return parseClaudeAccount(JSON.parse(readFileSync16(claudeUserConfigPath2(home, env), "utf8")));
|
|
17343
|
+
} catch {
|
|
17344
|
+
return null;
|
|
17345
|
+
}
|
|
17346
|
+
};
|
|
17347
|
+
|
|
17149
17348
|
// src/commands/status.ts
|
|
17150
17349
|
init_config();
|
|
17151
17350
|
init_settings();
|
|
@@ -17630,12 +17829,12 @@ function engineChecks(o, env) {
|
|
|
17630
17829
|
level: "warn",
|
|
17631
17830
|
name: "repos dir",
|
|
17632
17831
|
detail: `${dirs.join(" → ")} — ${missing.join(" and ")} ${missing.length === 1 ? "does" : "do"} not exist`,
|
|
17633
|
-
fix: "create the folder or drop it from Repos
|
|
17832
|
+
fix: "create the folder or drop it from Repos folders in Settings › Running work"
|
|
17634
17833
|
} : dirs.length ? { level: "ok", name: "repos dir", detail: dirs.join(" → ") } : repo ? { level: "ok", name: "repos dir", detail: repo } : {
|
|
17635
17834
|
level: "warn",
|
|
17636
17835
|
name: "repos dir",
|
|
17637
|
-
detail: `${e.label} names no --repos-dir — it works only if
|
|
17638
|
-
fix: "set Repos
|
|
17836
|
+
detail: `${e.label} names no --repos-dir — it works only if your engine profile sets Repos folders`,
|
|
17837
|
+
fix: "set Repos folders in Settings › Running work, or sleds engine install --repos-dir ~/code"
|
|
17639
17838
|
});
|
|
17640
17839
|
}
|
|
17641
17840
|
return checks;
|
|
@@ -17645,7 +17844,7 @@ function boxChecks(o, env, which, need) {
|
|
|
17645
17844
|
const file = boxEnvPath(o.home);
|
|
17646
17845
|
let named = false;
|
|
17647
17846
|
try {
|
|
17648
|
-
named = /^\s*(?:export\s+)?ANTHROPIC_API_KEY\s*=\s*\S/m.test(
|
|
17847
|
+
named = /^\s*(?:export\s+)?ANTHROPIC_API_KEY\s*=\s*\S/m.test(readFileSync17(file, "utf8"));
|
|
17649
17848
|
} catch {
|
|
17650
17849
|
named = false;
|
|
17651
17850
|
}
|
|
@@ -17751,7 +17950,7 @@ import {
|
|
|
17751
17950
|
appendFileSync as appendFileSync3,
|
|
17752
17951
|
chmodSync as chmodSync5,
|
|
17753
17952
|
mkdirSync as mkdirSync16,
|
|
17754
|
-
readFileSync as
|
|
17953
|
+
readFileSync as readFileSync18,
|
|
17755
17954
|
existsSync as realExists2,
|
|
17756
17955
|
rmSync as rmSync9,
|
|
17757
17956
|
writeFileSync as writeFileSync18
|
|
@@ -18173,7 +18372,7 @@ function realPidAlive2(pid) {
|
|
|
18173
18372
|
function memberMcpConfigs2(o, cwd) {
|
|
18174
18373
|
const read = o.readJson ?? ((p) => {
|
|
18175
18374
|
try {
|
|
18176
|
-
return JSON.parse(
|
|
18375
|
+
return JSON.parse(readFileSync18(p, "utf8"));
|
|
18177
18376
|
} catch {
|
|
18178
18377
|
return null;
|
|
18179
18378
|
}
|
|
@@ -18398,7 +18597,7 @@ async function driveEngine2(o, flags, deps, until = {}) {
|
|
|
18398
18597
|
runner: deps.runner.name,
|
|
18399
18598
|
atOnce: flags.atOnce,
|
|
18400
18599
|
interval: flags.interval,
|
|
18401
|
-
cliVersion: "0.1.
|
|
18600
|
+
cliVersion: "0.1.43"
|
|
18402
18601
|
};
|
|
18403
18602
|
const beat = (checkedAt) => {
|
|
18404
18603
|
const m = deps.machine;
|
|
@@ -18705,6 +18904,13 @@ var engineCmd = async (o) => {
|
|
|
18705
18904
|
if (client) {
|
|
18706
18905
|
const send = beater(client, o.now ?? Date.now);
|
|
18707
18906
|
const who = { name: flags.name, runner: runner.name };
|
|
18907
|
+
let refused;
|
|
18908
|
+
const sayRefused = (r) => {
|
|
18909
|
+
if (!r || r.ok || !r.refused || r.refused === refused)
|
|
18910
|
+
return;
|
|
18911
|
+
refused = r.refused;
|
|
18912
|
+
error(`${r.refused}. This engine is not shown as up until it beats under a name of its own.`);
|
|
18913
|
+
};
|
|
18708
18914
|
afterTick = () => {
|
|
18709
18915
|
try {
|
|
18710
18916
|
const m = deps.machine;
|
|
@@ -18712,7 +18918,7 @@ var engineCmd = async (o) => {
|
|
|
18712
18918
|
atOnce: deps.atOnce,
|
|
18713
18919
|
...m?.last ? { machine: m.last } : {},
|
|
18714
18920
|
...m?.hold && !m.off ? { hold: m.hold } : {}
|
|
18715
|
-
}));
|
|
18921
|
+
}))?.then(sayRefused, () => {});
|
|
18716
18922
|
} catch {}
|
|
18717
18923
|
};
|
|
18718
18924
|
}
|
|
@@ -18840,11 +19046,10 @@ async function enginePauseCmd2(o) {
|
|
|
18840
19046
|
|
|
18841
19047
|
// src/commands/engineInstall.ts
|
|
18842
19048
|
init_config();
|
|
18843
|
-
init_state();
|
|
18844
19049
|
import {
|
|
18845
19050
|
existsSync as existsSync17,
|
|
18846
19051
|
mkdirSync as mkdirSync17,
|
|
18847
|
-
readFileSync as
|
|
19052
|
+
readFileSync as readFileSync19,
|
|
18848
19053
|
readdirSync as readdirSync4,
|
|
18849
19054
|
realpathSync as realpathSync2,
|
|
18850
19055
|
rmSync as rmSync10,
|
|
@@ -18852,6 +19057,7 @@ import {
|
|
|
18852
19057
|
} from "node:fs";
|
|
18853
19058
|
import { hostname as hostname5 } from "node:os";
|
|
18854
19059
|
import { basename as basename5, dirname as dirname13, isAbsolute as isAbsolute3, join as join21 } from "node:path";
|
|
19060
|
+
init_state();
|
|
18855
19061
|
var ENGINE_LABEL2 = "ai.sleds.engine";
|
|
18856
19062
|
var ENGINE_INSTALL_USAGE2 = `usage: sleds engine install [engine flags] | sleds engine uninstall [--name <n>] [--org <slug>]
|
|
18857
19063
|
${ENGINE_USAGE}`;
|
|
@@ -18970,7 +19176,7 @@ function readEngines2(dir, suffix, manager, parse) {
|
|
|
18970
19176
|
const path = join21(dir, name);
|
|
18971
19177
|
let parsed;
|
|
18972
19178
|
try {
|
|
18973
|
-
parsed = parse(
|
|
19179
|
+
parsed = parse(readFileSync19(path, "utf8"), name);
|
|
18974
19180
|
} catch {
|
|
18975
19181
|
parsed = null;
|
|
18976
19182
|
}
|
|
@@ -18995,6 +19201,50 @@ function installedEngines2(home) {
|
|
|
18995
19201
|
];
|
|
18996
19202
|
}
|
|
18997
19203
|
var unsupported2 = (platform) => `sleds engine install needs launchd (macOS) or systemd (Linux). On ${platform}, keep \`sleds engine\` running under your own service manager (a scheduled task, tmux).`;
|
|
19204
|
+
var REPOS_DIR_NEEDED = "Set the folder your repos are cloned in first: `sleds engine profile set reposDir=~/code` (Settings › Running work › Repos folders), or `sleds engine install --repos-dir ~/code`. An installed engine starts outside any checkout, so without one every node it takes parks on No repo.";
|
|
19205
|
+
async function ensureReposDir(o) {
|
|
19206
|
+
const log = o.log ?? console.log;
|
|
19207
|
+
const error = o.error ?? console.error;
|
|
19208
|
+
const parsed = parseEngineArgs(o.argv, o.host ?? hostname5());
|
|
19209
|
+
if ("error" in parsed)
|
|
19210
|
+
return true;
|
|
19211
|
+
if (parsed.given.includes("repos-dir") || parsed.given.includes("repo"))
|
|
19212
|
+
return true;
|
|
19213
|
+
const client = engineClient({ home: o.home, ...o.env ? { env: o.env } : {}, ...o.client ? { client: o.client } : {} }, parsed.flags.org);
|
|
19214
|
+
if ("error" in client)
|
|
19215
|
+
return true;
|
|
19216
|
+
const profile = await readProfile(client);
|
|
19217
|
+
if (!profile) {
|
|
19218
|
+
log("note: your engine profile could not be read — if it names no repos folder, the engine says so when it starts");
|
|
19219
|
+
return true;
|
|
19220
|
+
}
|
|
19221
|
+
if (profile.reposDir)
|
|
19222
|
+
return true;
|
|
19223
|
+
if (!o.ask) {
|
|
19224
|
+
error(REPOS_DIR_NEEDED);
|
|
19225
|
+
return false;
|
|
19226
|
+
}
|
|
19227
|
+
const answer = (await o.ask("Where are your repos cloned? Folders searched in order, split on : (~/code): ")).trim();
|
|
19228
|
+
const dirs = splitReposDirs(answer);
|
|
19229
|
+
if (dirs.length === 0) {
|
|
19230
|
+
error(REPOS_DIR_NEEDED);
|
|
19231
|
+
return false;
|
|
19232
|
+
}
|
|
19233
|
+
const exists = o.exists ?? existsSync17;
|
|
19234
|
+
const missing = dirs.filter((d) => !exists(/^~(\/|$)/.test(d) ? join21(o.home, d.slice(1)) : d));
|
|
19235
|
+
if (missing.length) {
|
|
19236
|
+
error(`Not a folder on this machine: ${missing.join(", ")}. ${REPOS_DIR_NEEDED}`);
|
|
19237
|
+
return false;
|
|
19238
|
+
}
|
|
19239
|
+
const r = await client.postFull("/proxy/engine/profile", { profile: { reposDir: dirs.join(":") } }).catch(() => null);
|
|
19240
|
+
if (!r || r.status >= 300 || r.json?.ok === false) {
|
|
19241
|
+
const why = typeof r?.json?.error === "string" ? r.json.error : "SLEDS unreachable";
|
|
19242
|
+
error(`The repos folder was not saved (${why}). ${REPOS_DIR_NEEDED}`);
|
|
19243
|
+
return false;
|
|
19244
|
+
}
|
|
19245
|
+
log(`repos folders saved to your engine profile: ${dirs.join(" → ")}`);
|
|
19246
|
+
return true;
|
|
19247
|
+
}
|
|
18998
19248
|
function engineInstall2(o) {
|
|
18999
19249
|
const log = o.log ?? console.log;
|
|
19000
19250
|
const error = o.error ?? console.error;
|
|
@@ -19169,13 +19419,13 @@ function ago(at, now) {
|
|
|
19169
19419
|
|
|
19170
19420
|
// src/commands/engineList.ts
|
|
19171
19421
|
var ENGINE_LIST_USAGE = "usage: sleds engine list [--json]";
|
|
19172
|
-
var
|
|
19422
|
+
var str12 = (x) => typeof x === "string" ? x : "";
|
|
19173
19423
|
var numOrNull = (x) => typeof x === "number" && Number.isFinite(x) ? x : null;
|
|
19174
19424
|
function machineOf(x) {
|
|
19175
19425
|
if (!x || typeof x !== "object")
|
|
19176
19426
|
return null;
|
|
19177
19427
|
const m = x;
|
|
19178
|
-
const out = { pressure:
|
|
19428
|
+
const out = { pressure: str12(m.pressure) || "unknown" };
|
|
19179
19429
|
for (const k of ["cpuPct", "load1", "cores", "loadPerCore"]) {
|
|
19180
19430
|
const n = numOrNull(m[k]);
|
|
19181
19431
|
if (n !== null)
|
|
@@ -19191,8 +19441,8 @@ function workOf(x) {
|
|
|
19191
19441
|
if (!w || typeof w !== "object")
|
|
19192
19442
|
return [];
|
|
19193
19443
|
const o = w;
|
|
19194
|
-
const item =
|
|
19195
|
-
return item ? [{ item, node:
|
|
19444
|
+
const item = str12(o.item);
|
|
19445
|
+
return item ? [{ item, node: str12(o.node), title: typeof o.title === "string" ? o.title : null }] : [];
|
|
19196
19446
|
});
|
|
19197
19447
|
}
|
|
19198
19448
|
function engineRows(raw) {
|
|
@@ -19201,16 +19451,16 @@ function engineRows(raw) {
|
|
|
19201
19451
|
if (!r || typeof r !== "object")
|
|
19202
19452
|
return [];
|
|
19203
19453
|
const e = r;
|
|
19204
|
-
const name =
|
|
19454
|
+
const name = str12(e.name);
|
|
19205
19455
|
if (!name)
|
|
19206
19456
|
return [];
|
|
19207
19457
|
return [
|
|
19208
19458
|
{
|
|
19209
19459
|
name,
|
|
19210
|
-
email:
|
|
19211
|
-
os:
|
|
19212
|
-
runner:
|
|
19213
|
-
version:
|
|
19460
|
+
email: str12(e.email),
|
|
19461
|
+
os: str12(e.os),
|
|
19462
|
+
runner: str12(e.runner),
|
|
19463
|
+
version: str12(e.version),
|
|
19214
19464
|
running: typeof e.running === "number" ? e.running : 0,
|
|
19215
19465
|
items: Array.isArray(e.items) ? e.items.filter((i) => typeof i === "string") : [],
|
|
19216
19466
|
seatKind: typeof e.seatKind === "string" ? e.seatKind : null,
|
|
@@ -19263,7 +19513,7 @@ var engineListCmd = async (o) => {
|
|
|
19263
19513
|
return 1;
|
|
19264
19514
|
}
|
|
19265
19515
|
if (r.status !== 200 || !r.json || r.json.ok === false) {
|
|
19266
|
-
error(
|
|
19516
|
+
error(str12(r.json?.error) || `HTTP ${r.status}`);
|
|
19267
19517
|
return 1;
|
|
19268
19518
|
}
|
|
19269
19519
|
const rows = engineRows(r.json);
|
|
@@ -19280,7 +19530,7 @@ import { closeSync as closeSync3, fstatSync as fstatSync2, openSync as openSync3
|
|
|
19280
19530
|
import { hostname as hostname6 } from "node:os";
|
|
19281
19531
|
|
|
19282
19532
|
// src/commands/engineStatus.ts
|
|
19283
|
-
import { existsSync as existsSync18, readFileSync as
|
|
19533
|
+
import { existsSync as existsSync18, readFileSync as readFileSync20 } from "node:fs";
|
|
19284
19534
|
init_state();
|
|
19285
19535
|
|
|
19286
19536
|
// src/engine/status.ts
|
|
@@ -19570,7 +19820,7 @@ var engineLogCmd = (o) => {
|
|
|
19570
19820
|
|
|
19571
19821
|
// src/commands/engineProfile.ts
|
|
19572
19822
|
init_src();
|
|
19573
|
-
import { existsSync as existsSync19, readFileSync as
|
|
19823
|
+
import { existsSync as existsSync19, readFileSync as readFileSync21 } from "node:fs";
|
|
19574
19824
|
import { hostname as hostname7 } from "node:os";
|
|
19575
19825
|
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]";
|
|
19576
19826
|
var PROFILE_FIELDS = [
|
|
@@ -19835,7 +20085,7 @@ async function engineProfileCmd(o) {
|
|
|
19835
20085
|
const rest = words.slice(1);
|
|
19836
20086
|
let stdin = null;
|
|
19837
20087
|
if (fromStdin) {
|
|
19838
|
-
const taken = cmuxPasswordFromJson((o.stdin ?? (() =>
|
|
20088
|
+
const taken = cmuxPasswordFromJson((o.stdin ?? (() => readFileSync21(0, "utf8")))());
|
|
19839
20089
|
if ("error" in taken || taken.password !== undefined && password !== undefined) {
|
|
19840
20090
|
error("error" in taken ? taken.error : "the cmux password is given once");
|
|
19841
20091
|
error(PROFILE_USAGE);
|
|
@@ -19920,7 +20170,7 @@ var keychainLine = (k) => k === "set" ? "cmuxPassword: set (Keychain)" : k === "
|
|
|
19920
20170
|
|
|
19921
20171
|
// src/commands/engineStatus.ts
|
|
19922
20172
|
init_state();
|
|
19923
|
-
import { existsSync as existsSync20, readFileSync as
|
|
20173
|
+
import { existsSync as existsSync20, readFileSync as readFileSync22 } from "node:fs";
|
|
19924
20174
|
import { hostname as hostname8 } from "node:os";
|
|
19925
20175
|
var ENGINE_STATUS_USAGE = "usage: sleds engine status [--name <n>] [--org <slug>] [--json]";
|
|
19926
20176
|
function parseStatusArgs(argv, host) {
|
|
@@ -19976,7 +20226,7 @@ function readEngineStatus(stateDir, engine, host, pidAlive, seat) {
|
|
|
19976
20226
|
}
|
|
19977
20227
|
function safeRead(path) {
|
|
19978
20228
|
try {
|
|
19979
|
-
return
|
|
20229
|
+
return readFileSync22(path, "utf8");
|
|
19980
20230
|
} catch {
|
|
19981
20231
|
return "";
|
|
19982
20232
|
}
|
|
@@ -20097,28 +20347,28 @@ init_meter();
|
|
|
20097
20347
|
|
|
20098
20348
|
// src/owed.ts
|
|
20099
20349
|
init_config();
|
|
20100
|
-
import { existsSync as existsSync21, mkdirSync as mkdirSync18, readFileSync as
|
|
20350
|
+
import { existsSync as existsSync21, mkdirSync as mkdirSync18, readFileSync as readFileSync23, renameSync as renameSync7, writeFileSync as writeFileSync20 } from "node:fs";
|
|
20101
20351
|
import { dirname as dirname14, join as join22 } from "node:path";
|
|
20102
20352
|
var owedPath = (home) => join22(configDir(home), "owed.json");
|
|
20103
20353
|
var sessionPath = (home) => join22(configDir(home), "session.json");
|
|
20104
20354
|
var OWED_TTL_MS = 3 * 24 * 60 * 60000;
|
|
20105
|
-
var
|
|
20355
|
+
var str13 = (v) => typeof v === "string" ? v : undefined;
|
|
20106
20356
|
function sourceKey(s) {
|
|
20107
20357
|
const trim = (x) => x.trim().slice(0, 120);
|
|
20108
|
-
const kind =
|
|
20109
|
-
const project = trim(
|
|
20110
|
-
const doc =
|
|
20111
|
-
const item =
|
|
20358
|
+
const kind = str13(s.kind) ?? "manual";
|
|
20359
|
+
const project = trim(str13(s.project) ?? "");
|
|
20360
|
+
const doc = str13(s.doc);
|
|
20361
|
+
const item = str13(s.item);
|
|
20112
20362
|
return `${kind}:${project}${doc ? `/${trim(doc)}` : ""}${item ? `#${trim(item)}` : ""}`;
|
|
20113
20363
|
}
|
|
20114
20364
|
function sourceText2(s) {
|
|
20115
|
-
return [`${
|
|
20365
|
+
return [`${str13(s.kind) ?? "?"} ${str13(s.project) ?? "?"}`, str13(s.doc), str13(s.item)].filter(Boolean).join(" › ");
|
|
20116
20366
|
}
|
|
20117
20367
|
var readJson = (p) => {
|
|
20118
20368
|
if (!existsSync21(p))
|
|
20119
20369
|
return null;
|
|
20120
20370
|
try {
|
|
20121
|
-
return JSON.parse(
|
|
20371
|
+
return JSON.parse(readFileSync23(p, "utf8"));
|
|
20122
20372
|
} catch {
|
|
20123
20373
|
return null;
|
|
20124
20374
|
}
|
|
@@ -21145,7 +21395,7 @@ var login = async (o) => {
|
|
|
21145
21395
|
// src/commands/logout.ts
|
|
21146
21396
|
init_config();
|
|
21147
21397
|
init_state();
|
|
21148
|
-
import { existsSync as existsSync22, readFileSync as
|
|
21398
|
+
import { existsSync as existsSync22, readFileSync as readFileSync24, rmSync as rmSync11 } from "node:fs";
|
|
21149
21399
|
import { hostname as hostname10 } from "node:os";
|
|
21150
21400
|
init_settings();
|
|
21151
21401
|
var LOGOUT_USAGE = "usage: sleds logout [--org <slug>] [--json]";
|
|
@@ -21302,7 +21552,7 @@ async function logout(o) {
|
|
|
21302
21552
|
};
|
|
21303
21553
|
writeConfig(o.home, next);
|
|
21304
21554
|
const tp = tokenPath(o.home, env);
|
|
21305
|
-
if (existsSync22(tp) &&
|
|
21555
|
+
if (existsSync22(tp) && readFileSync24(tp, "utf8").trim() === seat.token)
|
|
21306
21556
|
rmSync11(tp, { force: true });
|
|
21307
21557
|
const active = next.activeOrg ?? next.org?.slug ?? null;
|
|
21308
21558
|
const result = { ok: true, email, org: slug, paused, active };
|
|
@@ -21380,7 +21630,7 @@ var meter = async (o) => {
|
|
|
21380
21630
|
init_config();
|
|
21381
21631
|
init_meter();
|
|
21382
21632
|
import { spawnSync as spawnSync7 } from "node:child_process";
|
|
21383
|
-
import { existsSync as existsSync23, mkdirSync as mkdirSync20, readFileSync as
|
|
21633
|
+
import { existsSync as existsSync23, mkdirSync as mkdirSync20, readFileSync as readFileSync25, rmSync as rmSync12, writeFileSync as writeFileSync22 } from "node:fs";
|
|
21384
21634
|
import { hostname as hostname11 } from "node:os";
|
|
21385
21635
|
import { dirname as dirname15 } from "node:path";
|
|
21386
21636
|
var defaultWhich3 = (cmd) => {
|
|
@@ -21857,7 +22107,7 @@ var packCmd = async (o) => {
|
|
|
21857
22107
|
};
|
|
21858
22108
|
|
|
21859
22109
|
// src/commands/permissionEvent.ts
|
|
21860
|
-
import { chmodSync as chmodSync6, mkdirSync as mkdirSync21, readFileSync as
|
|
22110
|
+
import { chmodSync as chmodSync6, mkdirSync as mkdirSync21, readFileSync as readFileSync26, renameSync as renameSync8, rmSync as rmSync14, writeFileSync as writeFileSync24 } from "node:fs";
|
|
21861
22111
|
import { dirname as dirname16 } from "node:path";
|
|
21862
22112
|
var isObject13 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
21863
22113
|
var messageOf = (text) => {
|
|
@@ -21868,12 +22118,20 @@ var messageOf = (text) => {
|
|
|
21868
22118
|
return "";
|
|
21869
22119
|
}
|
|
21870
22120
|
};
|
|
22121
|
+
var NOT_A_TOOL2 = new Set(["askuserquestion", "exitplanmode", "enterplanmode"]);
|
|
22122
|
+
var isToolPermission2 = (message) => {
|
|
22123
|
+
const tool = /permission to use\s+(.+?)\.?\s*$/i.exec(message)?.[1];
|
|
22124
|
+
return !tool || !NOT_A_TOOL2.has(tool.replace(/[\s_-]/g, "").toLowerCase());
|
|
22125
|
+
};
|
|
21871
22126
|
var permissionEvent = async (o) => {
|
|
21872
22127
|
try {
|
|
21873
22128
|
const input = o.stdin ?? await readStdin(HOOK_STDIN_TIMEOUT_MS);
|
|
21874
22129
|
if (!o.mark || notificationType(input) !== "permission_prompt")
|
|
21875
22130
|
return 0;
|
|
21876
|
-
const
|
|
22131
|
+
const message = messageOf(input);
|
|
22132
|
+
if (!isToolPermission2(message))
|
|
22133
|
+
return 0;
|
|
22134
|
+
const mark = { message, at: (o.now ?? Date.now)() };
|
|
21877
22135
|
mkdirSync21(dirname16(o.mark), { recursive: true, mode: 448 });
|
|
21878
22136
|
const tmp = `${o.mark}.${process.pid}.tmp`;
|
|
21879
22137
|
writeFileSync24(tmp, `${JSON.stringify(mark)}
|
|
@@ -21968,7 +22226,7 @@ var promptEvent = async (o) => {
|
|
|
21968
22226
|
|
|
21969
22227
|
// src/commands/route.ts
|
|
21970
22228
|
init_src();
|
|
21971
|
-
import { readFileSync as
|
|
22229
|
+
import { readFileSync as readFileSync27 } from "node:fs";
|
|
21972
22230
|
import { hostname as hostname12 } from "node:os";
|
|
21973
22231
|
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>]";
|
|
21974
22232
|
var USAGE = "usage: sleds route <key> [--long | --dot | --json] | sleds route arm <key> [--off] [--json] | sleds route answer <key>/<node> --stdin | sleds route propose <key> --file <nodes.json> | sleds route approve <key> | sleds route redraft <key> | sleds route single <key> | 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]";
|
|
@@ -22141,7 +22399,7 @@ async function answerCmd(o, argv) {
|
|
|
22141
22399
|
const words = argv.filter((a) => a !== "--json" && a !== "--stdin");
|
|
22142
22400
|
const ref = words[0] ?? "";
|
|
22143
22401
|
const slash = ref.lastIndexOf("/");
|
|
22144
|
-
const answer = (fromStdin ? (o.stdin ?? (() =>
|
|
22402
|
+
const answer = (fromStdin ? (o.stdin ?? (() => readFileSync27(0, "utf8")))() : words.slice(1).join(" ")).trim();
|
|
22145
22403
|
if (slash <= 0 || slash === ref.length - 1 || fromStdin && words.length > 1) {
|
|
22146
22404
|
error(ANSWER_USAGE);
|
|
22147
22405
|
return 2;
|
|
@@ -22338,7 +22596,7 @@ async function decisionCmd(o, argv) {
|
|
|
22338
22596
|
error(DECISION_USAGE);
|
|
22339
22597
|
return 2;
|
|
22340
22598
|
}
|
|
22341
|
-
const md = seen || routeAlone ? "" : (fromStdin ? (o.stdin ?? (() =>
|
|
22599
|
+
const md = seen || routeAlone ? "" : (fromStdin ? (o.stdin ?? (() => readFileSync27(0, "utf8")))() : rest.join(" ")).trim();
|
|
22342
22600
|
if (!seen && !routeAlone && (!md || fromStdin && rest.length > 0)) {
|
|
22343
22601
|
error(md ? DECISION_USAGE : `${answer ? "an answer" : "an overrule"} needs some text`);
|
|
22344
22602
|
return 2;
|
|
@@ -22479,7 +22737,7 @@ function approvedLine(key, j) {
|
|
|
22479
22737
|
function readNodes(o, a) {
|
|
22480
22738
|
let text;
|
|
22481
22739
|
try {
|
|
22482
|
-
text = a.file ? (o.readFile ?? ((p) =>
|
|
22740
|
+
text = a.file ? (o.readFile ?? ((p) => readFileSync27(p, "utf8")))(a.file) : (o.stdin ?? (() => readFileSync27(0, "utf8")))();
|
|
22483
22741
|
} catch (e) {
|
|
22484
22742
|
return { error: e instanceof Error ? e.message : String(e) };
|
|
22485
22743
|
}
|
|
@@ -22790,7 +23048,7 @@ var seatEvent = async (o) => {
|
|
|
22790
23048
|
|
|
22791
23049
|
// src/commands/seatSync.ts
|
|
22792
23050
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
22793
|
-
import { existsSync as existsSync25, mkdirSync as mkdirSync22, readFileSync as
|
|
23051
|
+
import { existsSync as existsSync25, mkdirSync as mkdirSync22, readFileSync as readFileSync28, readdirSync as readdirSync5, rmSync as rmSync16, writeFileSync as writeFileSync25 } from "node:fs";
|
|
22794
23052
|
import { platform as platform2 } from "node:os";
|
|
22795
23053
|
import { dirname as dirname17, join as join25 } from "node:path";
|
|
22796
23054
|
|
|
@@ -23140,7 +23398,7 @@ function findCookieDb(home, source) {
|
|
|
23140
23398
|
return db;
|
|
23141
23399
|
}
|
|
23142
23400
|
const localStatePath = join25(root, "Local State");
|
|
23143
|
-
const localState = existsSync25(localStatePath) ?
|
|
23401
|
+
const localState = existsSync25(localStatePath) ? readFileSync28(localStatePath, "utf8") : null;
|
|
23144
23402
|
const wanted = source.profile ?? "Default";
|
|
23145
23403
|
const { dir, ambiguous } = resolveProfileDir(localState, wanted);
|
|
23146
23404
|
if (ambiguous)
|
|
@@ -23320,7 +23578,7 @@ var seatSync = async (o) => {
|
|
|
23320
23578
|
};
|
|
23321
23579
|
function readSeatToken(home, source) {
|
|
23322
23580
|
try {
|
|
23323
|
-
return
|
|
23581
|
+
return readFileSync28(seatTokenPath(home, source), "utf8").trim() || undefined;
|
|
23324
23582
|
} catch {
|
|
23325
23583
|
return;
|
|
23326
23584
|
}
|
|
@@ -23403,7 +23661,7 @@ var sessionEvent = async (o) => {
|
|
|
23403
23661
|
|
|
23404
23662
|
// src/commands/specEvent.ts
|
|
23405
23663
|
init_meter();
|
|
23406
|
-
import { readFileSync as
|
|
23664
|
+
import { readFileSync as readFileSync29, statSync as statSync2 } from "node:fs";
|
|
23407
23665
|
import { basename as basename6, isAbsolute as isAbsolute4, relative } from "node:path";
|
|
23408
23666
|
var HOOK_STDIN_TIMEOUT_MS3 = 1000;
|
|
23409
23667
|
var ESTIMATE_TIMEOUT_MS = 4000;
|
|
@@ -23459,7 +23717,7 @@ function readFileOrNull(path) {
|
|
|
23459
23717
|
try {
|
|
23460
23718
|
if (statSync2(path).size > 2000000)
|
|
23461
23719
|
return null;
|
|
23462
|
-
return
|
|
23720
|
+
return readFileSync29(path, "utf8");
|
|
23463
23721
|
} catch {
|
|
23464
23722
|
return null;
|
|
23465
23723
|
}
|
|
@@ -23518,9 +23776,9 @@ var specEvent = async (o) => {
|
|
|
23518
23776
|
};
|
|
23519
23777
|
|
|
23520
23778
|
// src/commands/status.ts
|
|
23779
|
+
import { existsSync as existsSync26 } from "node:fs";
|
|
23521
23780
|
init_config();
|
|
23522
23781
|
init_settings();
|
|
23523
|
-
import { existsSync as existsSync26 } from "node:fs";
|
|
23524
23782
|
var HEALTH_TIMEOUT_MS2 = 4000;
|
|
23525
23783
|
var checkHealth2 = async (url, fetchFn = fetch, timeoutMs = HEALTH_TIMEOUT_MS2) => {
|
|
23526
23784
|
try {
|
|
@@ -23550,6 +23808,13 @@ var fetchProxyStatus = async (url, fetchFn = fetch, timeoutMs = HEALTH_TIMEOUT_M
|
|
|
23550
23808
|
}
|
|
23551
23809
|
};
|
|
23552
23810
|
var row2 = (label, value) => `${label.padEnd(12)}${value}`;
|
|
23811
|
+
var claudeLine = (c, seatEmail) => {
|
|
23812
|
+
if (!c)
|
|
23813
|
+
return "no Claude login found (signed out, or on an API key)";
|
|
23814
|
+
const org = c.orgName && (c.plan === "Team" || c.plan === "Enterprise") ? ` (${c.orgName})` : "";
|
|
23815
|
+
const other = seatEmail && seatEmail.toLowerCase() !== c.email.toLowerCase() ? " — not the seat's account" : "";
|
|
23816
|
+
return `${c.email}${c.plan ? ` · ${c.plan}` : ""}${org}${other}`;
|
|
23817
|
+
};
|
|
23553
23818
|
var formatStatus = (s) => {
|
|
23554
23819
|
const lines = [];
|
|
23555
23820
|
const stale = s.mode === "on" && !s.pointed;
|
|
@@ -23582,6 +23847,8 @@ var formatStatus = (s) => {
|
|
|
23582
23847
|
lines.push(row2("Seat:", `${s.email}${s.agentKind ? ` · ${s.agentKind}` : ""}`));
|
|
23583
23848
|
else if (s.agentKind)
|
|
23584
23849
|
lines.push(row2("Agent:", s.agentKind));
|
|
23850
|
+
if (s.claude !== undefined)
|
|
23851
|
+
lines.push(row2("Claude:", claudeLine(s.claude, s.email)));
|
|
23585
23852
|
if (s.org)
|
|
23586
23853
|
lines.push(row2("Org:", `${s.org.name}${s.org.slug ? ` (${s.org.slug})` : ""} · ${s.org.plan} · ${s.org.upstream === "none" ? "no platform key (walls: hold or hand off)" : s.org.upstream === "own" ? "platform key" : "shared key"}${s.orgFrom === "env" ? " · from SLEDS_ORG" : ""}`));
|
|
23587
23854
|
if (s.otherOrgs)
|
|
@@ -23627,6 +23894,8 @@ var status3 = async (o) => {
|
|
|
23627
23894
|
info.agentKind = cfg.agentKind;
|
|
23628
23895
|
if (cfg.wiring)
|
|
23629
23896
|
info.wiring = cfg.wiring;
|
|
23897
|
+
if (cfg.agentKind !== "codex")
|
|
23898
|
+
info.claude = readClaudeAccount(o.home, o.env ?? process.env);
|
|
23630
23899
|
if (org)
|
|
23631
23900
|
info.org = {
|
|
23632
23901
|
name: org.name,
|
|
@@ -23748,7 +24017,7 @@ var rememberSeat = (o, key, window, session, now, input) => {
|
|
|
23748
24017
|
const posts = [];
|
|
23749
24018
|
if (src && shouldPostSeat(prior, window, now)) {
|
|
23750
24019
|
state = markPosted(state, window, now);
|
|
23751
|
-
posts.push(postSeatWindow({ ...src, fetchFn: o.fetchFn, timeoutMs: o.timeoutMs ?? SEAT_POST_TIMEOUT_MS }, window));
|
|
24020
|
+
posts.push(postSeatWindow({ ...src, fetchFn: o.fetchFn, timeoutMs: o.timeoutMs ?? SEAT_POST_TIMEOUT_MS }, window, readClaudeAccount(o.home, o.env ?? process.env)));
|
|
23752
24021
|
}
|
|
23753
24022
|
const events = seatWallEvents(prior, window);
|
|
23754
24023
|
const credits = creditsEvent(o, prior, input, now);
|
|
@@ -23788,7 +24057,7 @@ var announce = (o, events) => {
|
|
|
23788
24057
|
|
|
23789
24058
|
// src/commands/stopEvent.ts
|
|
23790
24059
|
init_meter();
|
|
23791
|
-
import { existsSync as existsSync27, readFileSync as
|
|
24060
|
+
import { existsSync as existsSync27, readFileSync as readFileSync30 } from "node:fs";
|
|
23792
24061
|
|
|
23793
24062
|
// src/transcript.ts
|
|
23794
24063
|
var isObject16 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
@@ -23884,7 +24153,7 @@ async function postTranscript(o, payload, now) {
|
|
|
23884
24153
|
const src = meterSource(o.home);
|
|
23885
24154
|
if (!src)
|
|
23886
24155
|
return false;
|
|
23887
|
-
const read = o.readFile ?? ((p) => existsSync27(p) ?
|
|
24156
|
+
const read = o.readFile ?? ((p) => existsSync27(p) ? readFileSync30(p, "utf8") : null);
|
|
23888
24157
|
let text;
|
|
23889
24158
|
try {
|
|
23890
24159
|
text = read(path);
|
|
@@ -24105,7 +24374,7 @@ var verify = async (o) => {
|
|
|
24105
24374
|
|
|
24106
24375
|
// src/commands/webhooks.ts
|
|
24107
24376
|
var USAGE2 = "usage: sleds webhooks [--json] | sleds webhooks deliveries <id or name> [--json]";
|
|
24108
|
-
var
|
|
24377
|
+
var str14 = (x) => typeof x === "string" ? x : "";
|
|
24109
24378
|
function ago3(at, now) {
|
|
24110
24379
|
const m = Math.max(0, Math.floor((now - at) / 60000));
|
|
24111
24380
|
if (m < 1)
|
|
@@ -24121,7 +24390,7 @@ function webhookLines(raw, now) {
|
|
|
24121
24390
|
if (!rows.length)
|
|
24122
24391
|
return ["no webhooks — add one in the app: Settings › Integrations › Webhooks"];
|
|
24123
24392
|
return rows.map((h) => {
|
|
24124
|
-
let host =
|
|
24393
|
+
let host = str14(h.url);
|
|
24125
24394
|
try {
|
|
24126
24395
|
host = new URL(host.replace(/\{[a-z.]+\}/g, "x")).host;
|
|
24127
24396
|
} catch {}
|
|
@@ -24129,21 +24398,21 @@ function webhookLines(raw, now) {
|
|
|
24129
24398
|
const last = h.lastDelivery;
|
|
24130
24399
|
const lastText = last?.at ? `last ${last.status ?? "—"} ${last.state ?? ""} ${ago3(last.at, now)}`.replace(/\s+/g, " ") : "nothing sent yet";
|
|
24131
24400
|
const off = h.enabled ? "on " : "off";
|
|
24132
|
-
const why = !h.enabled && h.disabledWhy ? ` (${
|
|
24133
|
-
return `${off} ${
|
|
24401
|
+
const why = !h.enabled && h.disabledWhy ? ` (${str14(h.disabledWhy)})` : "";
|
|
24402
|
+
return `${off} ${str14(h.name)} ${host} ${events.includes("*") ? "all events" : events.join(",")} ${lastText}${why} [${str14(h.id)}]`;
|
|
24134
24403
|
});
|
|
24135
24404
|
}
|
|
24136
24405
|
function deliveryLines(raw, now) {
|
|
24137
24406
|
const j = clean(raw);
|
|
24138
24407
|
const rows = Array.isArray(j.deliveries) ? j.deliveries : [];
|
|
24139
|
-
const name =
|
|
24408
|
+
const name = str14(j.webhook?.name);
|
|
24140
24409
|
if (!rows.length)
|
|
24141
24410
|
return [`${name}: nothing sent yet`];
|
|
24142
24411
|
return [
|
|
24143
24412
|
`${name} — the last ${rows.length}`,
|
|
24144
24413
|
...rows.map((d) => {
|
|
24145
|
-
const result = d.status !== null && d.status !== undefined ? String(d.status) :
|
|
24146
|
-
return `${
|
|
24414
|
+
const result = d.status !== null && d.status !== undefined ? String(d.status) : str14(d.error) || "—";
|
|
24415
|
+
return `${str14(d.state).padEnd(9)} ${result.padEnd(5)} ${str14(d.event).padEnd(20)} ${str14(d.key) || "—"} ${ago3(Number(d.at), now)} tries ${d.attempts} ${str14(d.deliveryId)}`;
|
|
24147
24416
|
})
|
|
24148
24417
|
];
|
|
24149
24418
|
}
|
|
@@ -24174,7 +24443,7 @@ var webhooksCmd = async (o) => {
|
|
|
24174
24443
|
return 1;
|
|
24175
24444
|
}
|
|
24176
24445
|
if (r.status !== 200 || !r.json) {
|
|
24177
|
-
const why =
|
|
24446
|
+
const why = str14(r.json?.error) || `HTTP ${r.status}`;
|
|
24178
24447
|
error(r.status === 404 && !r.json ? "SLEDS does not know this seat — run `sleds init`" : why);
|
|
24179
24448
|
return 1;
|
|
24180
24449
|
}
|
|
@@ -24188,7 +24457,7 @@ var webhooksCmd = async (o) => {
|
|
|
24188
24457
|
|
|
24189
24458
|
// src/config.ts
|
|
24190
24459
|
init_settings();
|
|
24191
|
-
import { chmodSync as chmodSync7, existsSync as existsSync29, mkdirSync as mkdirSync23, readFileSync as
|
|
24460
|
+
import { chmodSync as chmodSync7, existsSync as existsSync29, mkdirSync as mkdirSync23, readFileSync as readFileSync31, renameSync as renameSync9, writeFileSync as writeFileSync26 } from "node:fs";
|
|
24192
24461
|
import { join as join26, resolve as resolve10 } from "node:path";
|
|
24193
24462
|
var configDir2 = (home, env = process.env) => {
|
|
24194
24463
|
const o = env.SLEDS_HOME?.trim();
|
|
@@ -24328,7 +24597,7 @@ var readConfig2 = (home) => {
|
|
|
24328
24597
|
const p = configPath2(home);
|
|
24329
24598
|
if (!existsSync29(p))
|
|
24330
24599
|
return {};
|
|
24331
|
-
return parseConfig2(JSON.parse(
|
|
24600
|
+
return parseConfig2(JSON.parse(readFileSync31(p, "utf8")));
|
|
24332
24601
|
};
|
|
24333
24602
|
|
|
24334
24603
|
// src/runners/exec.ts
|
|
@@ -24688,8 +24957,12 @@ var main = async (argv) => {
|
|
|
24688
24957
|
return engineLogCmd({ home, argv: argv.slice(2) });
|
|
24689
24958
|
if (cmd === "engine" && argv[1] === "list")
|
|
24690
24959
|
return engineListCmd({ home, argv: argv.slice(2) });
|
|
24691
|
-
if (cmd === "engine" && argv[1] === "install")
|
|
24960
|
+
if (cmd === "engine" && argv[1] === "install") {
|
|
24961
|
+
const ask = process.stdin.isTTY ? promptStdin : undefined;
|
|
24962
|
+
if (!await ensureReposDir({ home, argv: argv.slice(2), ...ask ? { ask } : {} }))
|
|
24963
|
+
return 1;
|
|
24692
24964
|
return engineInstall2({ home, argv: argv.slice(2), sledsArgv: sledsArgv() });
|
|
24965
|
+
}
|
|
24693
24966
|
if (cmd === "engine" && argv[1] === "uninstall")
|
|
24694
24967
|
return engineUninstall2({ home, argv: argv.slice(2), sledsArgv: sledsArgv() });
|
|
24695
24968
|
if (cmd === "engine" && argv[1] === "profile")
|
|
@@ -24875,7 +25148,7 @@ ${renderHelpText(argv[1])}`);
|
|
|
24875
25148
|
case "version":
|
|
24876
25149
|
case "--version":
|
|
24877
25150
|
case "-v":
|
|
24878
|
-
console.log("sleds 0.1.
|
|
25151
|
+
console.log("sleds 0.1.43");
|
|
24879
25152
|
return 0;
|
|
24880
25153
|
default:
|
|
24881
25154
|
console.error(`unknown command: ${cmd}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sleds/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.43",
|
|
4
4
|
"description": "SLEDS CLI — the cost and limits of AI agent work, decided at the wall. Point Claude Code at a SLEDS proxy; estimate before you run; hold, switch model, or run overnight when you hit a limit.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|