@sleds/cli 0.1.43 → 0.1.44
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 +678 -404
- package/package.json +1 -1
package/dist/sleds.mjs
CHANGED
|
@@ -21,6 +21,9 @@ var p = (input, output, cacheWrite, cacheWrite1h, cacheRead) => ({ input, output
|
|
|
21
21
|
}), OPENAI_PRICES, byLength = (t) => Object.keys(t).sort((a, b) => b.length - a.length), ANTHROPIC_KEYS, OPENAI_KEYS;
|
|
22
22
|
var init_pricing = __esm(() => {
|
|
23
23
|
ANTHROPIC_PRICES = {
|
|
24
|
+
"claude-opus-5-5": p(4, 20, 5, 8, 0.2),
|
|
25
|
+
"claude-sonnet-5-5": p(2, 10, 2.5, 4, 0.1),
|
|
26
|
+
"claude-haiku-5-5": p(0.1, 0.5, 0.125, 0.2, 0.01),
|
|
24
27
|
"claude-fable-5-1": p(10, 50, 12.5, 20, 0.25),
|
|
25
28
|
"claude-mythos-5-1": p(10, 50, 12.5, 20, 0.25),
|
|
26
29
|
"claude-fable-5": p(10, 50, 12.5, 20, 1),
|
|
@@ -794,10 +797,10 @@ var init_verbs = __esm(() => {
|
|
|
794
797
|
{
|
|
795
798
|
id: "update",
|
|
796
799
|
group: "meter",
|
|
797
|
-
want: "Change an item — its title, why, done, description, due day, what it sits under, or what it touches",
|
|
798
|
-
mcp: "update {project, ask?, why?, done?, smallest?, touches?, demand?, description?, due?, parent?, repos?, sensitivity?}",
|
|
800
|
+
want: "Change an item — its title, why, done, worth, description, due day, what it sits under, or what it touches",
|
|
801
|
+
mcp: "update {project, ask?, why?, done?, smallest?, touches?, demand?, worth?, carry?, description?, due?, parent?, repos?, sensitivity?}",
|
|
799
802
|
app: "Work › the item › click a field",
|
|
800
|
-
how: "The filer, an approver or an admin changes an item from chat or by clicking the field in the app; every change says who and through what (via Claude · Cowork, via ChatGPT, in the app) and the record keeps before and after. A change to the ask, done or smallest marks the band stale with a Re-size at hand — never re-sized silently. A mirrored ticket is the tracker's word and is not changed here."
|
|
803
|
+
how: "The filer, an approver or an admin changes an item from chat or by clicking the field in the app; every change says who and through what (via Claude · Cowork, via ChatGPT, in the app) and the record keeps before and after. A change to the ask, done or smallest marks the band stale with a Re-size at hand — never re-sized silently. Worth is the person's word in their words ('high · Acme renewal', '$5k–20k'; null clears it); on an epic, `carry: true` puts it on each child that has none, each child's record signed the same way. A mirrored ticket is the tracker's word and is not changed here."
|
|
801
804
|
},
|
|
802
805
|
{
|
|
803
806
|
id: "archive",
|
|
@@ -1085,7 +1088,19 @@ var init_verbs = __esm(() => {
|
|
|
1085
1088
|
|
|
1086
1089
|
// ../../packages/shared/src/intake/forms.ts
|
|
1087
1090
|
function norm(label) {
|
|
1088
|
-
return label.replace(/[*_`~]/g, "").replace(/\(s\)/gi, "s").replace(/[:?]+\s*$/, "").replace(/\s+/g, " ").trim().toLowerCase();
|
|
1091
|
+
return label.replace(/[*_`~]/g, "").replace(/\(s\)/gi, "s").replace(/[:?]+\s*$/, "").replace(/,\s*including\b.*$/i, "").replace(/\s+/g, " ").trim().toLowerCase();
|
|
1092
|
+
}
|
|
1093
|
+
function plain(s) {
|
|
1094
|
+
return s.replace(/[*_`~]+/g, "").replace(/\s+/g, " ").trim();
|
|
1095
|
+
}
|
|
1096
|
+
function titleOf(s, max = 80) {
|
|
1097
|
+
const t = plain(s);
|
|
1098
|
+
const first = /^(.+?[.!?])(\s|$)/.exec(t)?.[1] ?? t;
|
|
1099
|
+
if (first.length <= max)
|
|
1100
|
+
return first;
|
|
1101
|
+
const cut = first.slice(0, max);
|
|
1102
|
+
const sp = cut.lastIndexOf(" ");
|
|
1103
|
+
return `${(sp > max / 2 ? cut.slice(0, sp) : cut).replace(/[,;:\s]+$/, "")}…`;
|
|
1089
1104
|
}
|
|
1090
1105
|
function readForm(text) {
|
|
1091
1106
|
const lines = text.split(/\r?\n/);
|
|
@@ -1097,67 +1112,84 @@ function readForm(text) {
|
|
|
1097
1112
|
const line = raw.trim();
|
|
1098
1113
|
if (!line)
|
|
1099
1114
|
continue;
|
|
1115
|
+
const bold = /^\*[^*]{2,80}\*:?$/.test(line);
|
|
1116
|
+
const whole = line.length <= 80 ? slotOf(def, line) : null;
|
|
1100
1117
|
const inline = /^\**([^:*]{2,60}?)\**\s*:\s*(.+)$/.exec(line);
|
|
1101
|
-
const
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
if (slotWhole) {
|
|
1105
|
-
cur = { label: line.replace(/[*_]/g, "").replace(/:\s*$/, ""), slot: slotWhole, value: [] };
|
|
1118
|
+
const slotInline = inline ? slotOf(def, inline[1] ?? "") : null;
|
|
1119
|
+
if (whole && (bold || !inline)) {
|
|
1120
|
+
cur = { label: plain(norm(line)), slot: whole, value: [] };
|
|
1106
1121
|
found.push(cur);
|
|
1107
1122
|
known++;
|
|
1108
1123
|
} else if (slotInline && inline) {
|
|
1109
|
-
cur = { label: (inline[1] ?? "")
|
|
1124
|
+
cur = { label: plain(norm(inline[1] ?? "")), slot: slotInline, value: [inline[2] ?? ""] };
|
|
1110
1125
|
found.push(cur);
|
|
1111
1126
|
known++;
|
|
1112
|
-
} else if (
|
|
1113
|
-
cur = { label: line.replace(
|
|
1127
|
+
} else if (bold && cur) {
|
|
1128
|
+
cur = { label: plain(line.replace(/:$/, "")), slot: null, value: [] };
|
|
1114
1129
|
found.push(cur);
|
|
1115
1130
|
} else if (cur)
|
|
1116
1131
|
cur.value.push(line);
|
|
1117
1132
|
}
|
|
1118
1133
|
if (known < def.min)
|
|
1119
1134
|
continue;
|
|
1120
|
-
const val = (f) => f.value.join(" ")
|
|
1121
|
-
const
|
|
1122
|
-
const ask =
|
|
1123
|
-
const
|
|
1124
|
-
const
|
|
1125
|
-
const
|
|
1126
|
-
const
|
|
1127
|
-
const
|
|
1128
|
-
const
|
|
1129
|
-
const
|
|
1135
|
+
const val = (f) => plain(f.value.join(" "));
|
|
1136
|
+
const one = (slot) => found.find((f) => f.slot === slot && val(f));
|
|
1137
|
+
const ask = one("ask");
|
|
1138
|
+
const users = one("users");
|
|
1139
|
+
const sid = one("sid");
|
|
1140
|
+
const loc = one("location");
|
|
1141
|
+
const clients = one("clients");
|
|
1142
|
+
const rev = one("revenue");
|
|
1143
|
+
const n = clients ? val(clients) : "";
|
|
1144
|
+
const clientsText = n ? /^\d+$/.test(n) ? `${n} client${n === "1" ? "" : "s"} affected` : `clients affected: ${n}` : "";
|
|
1145
|
+
const r = rev ? val(rev) : "";
|
|
1146
|
+
const revenue = YES.test(r) ? true : NO.test(r) ? false : undefined;
|
|
1147
|
+
const revText = revenue === true ? "Impacting revenue" : revenue === false ? "No revenue impact" : "";
|
|
1148
|
+
const unknown = found.filter((f) => f.slot === null && val(f)).map((f) => `${f.label}: ${val(f)}`);
|
|
1149
|
+
const who = [
|
|
1150
|
+
users ? `Users: ${val(users)}` : "",
|
|
1151
|
+
sid ? `SID: ${val(sid)}` : "",
|
|
1152
|
+
loc ? `Location ${val(loc)}` : "",
|
|
1153
|
+
...unknown
|
|
1154
|
+
].filter(Boolean);
|
|
1155
|
+
const touches = who.join(" · ");
|
|
1156
|
+
const demand = [clientsText, revText].filter(Boolean).join(" · ");
|
|
1157
|
+
const details = [...who, clientsText, revText].filter(Boolean).join(" · ");
|
|
1130
1158
|
return {
|
|
1131
1159
|
form: def.name,
|
|
1132
|
-
...ask ? { ask } : {},
|
|
1133
|
-
...
|
|
1160
|
+
...ask ? { ask: val(ask) } : {},
|
|
1161
|
+
...details ? { details } : {},
|
|
1134
1162
|
...touches ? { touches } : {},
|
|
1135
1163
|
...demand ? { demand } : {},
|
|
1136
|
-
...
|
|
1164
|
+
...revenue !== undefined ? { revenue } : {}
|
|
1137
1165
|
};
|
|
1138
1166
|
}
|
|
1139
1167
|
return null;
|
|
1140
1168
|
}
|
|
1141
|
-
var FORMS, YES
|
|
1169
|
+
var FORMS, YES, NO, slotOf = (def, label) => {
|
|
1170
|
+
const n = norm(label);
|
|
1171
|
+
for (const [re, slot] of def.labels)
|
|
1172
|
+
if (re.test(n))
|
|
1173
|
+
return slot;
|
|
1174
|
+
return null;
|
|
1175
|
+
};
|
|
1142
1176
|
var init_forms = __esm(() => {
|
|
1143
1177
|
FORMS = [
|
|
1144
1178
|
{
|
|
1145
1179
|
name: "Create Tech Support Ticket",
|
|
1146
|
-
labels:
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
"number of clients affected": "demand",
|
|
1155
|
-
"is the issue currently impacting revenue": "revenue"
|
|
1156
|
-
},
|
|
1180
|
+
labels: [
|
|
1181
|
+
[/^users? experiencing\b/, "users"],
|
|
1182
|
+
[/^sids?\b/, "sid"],
|
|
1183
|
+
[/^location ids?\b/, "location"],
|
|
1184
|
+
[/^issue description\b/, "ask"],
|
|
1185
|
+
[/^(?:number of )?clients? affected\b|^number of clients\b/, "clients"],
|
|
1186
|
+
[/\bimpacting revenue\b|\brevenue impact\b/, "revenue"]
|
|
1187
|
+
],
|
|
1157
1188
|
min: 3
|
|
1158
1189
|
}
|
|
1159
1190
|
];
|
|
1160
1191
|
YES = /^(yes|y|yep|true|definitely|it is)\b/i;
|
|
1192
|
+
NO = /^(no|n|nope|false|not)\b/i;
|
|
1161
1193
|
});
|
|
1162
1194
|
|
|
1163
1195
|
// ../../packages/shared/src/intake/brief.ts
|
|
@@ -1235,13 +1267,14 @@ function draftBrief(input) {
|
|
|
1235
1267
|
const form = readForm(text);
|
|
1236
1268
|
const parsed = sections(text);
|
|
1237
1269
|
const preamble = parsed.preamble;
|
|
1238
|
-
const byKey = form ? {
|
|
1239
|
-
const
|
|
1270
|
+
const byKey = form ? { touches: form.touches, demand: form.demand } : parsed.byKey;
|
|
1271
|
+
const fromText = form?.ask ? form.ask : askFrom(text, preamble);
|
|
1272
|
+
const askText = a.ask?.trim() || (fromText ? titleOf(fromText) : undefined);
|
|
1240
1273
|
if (!askText)
|
|
1241
1274
|
return null;
|
|
1242
1275
|
const ask = a.ask?.trim() ? { text: clip(a.ask, MAX_ASK), from: "filer" } : { text: clip(askText, MAX_ASK), from: "artifact" };
|
|
1243
1276
|
const pick = (k) => field(a[k], "filer") ?? field(byKey[k], "artifact");
|
|
1244
|
-
const worth = worthFromAnswer(a.worth) ?? parseWorth(text) ??
|
|
1277
|
+
const worth = worthFromAnswer(a.worth) ?? parseWorth(text) ?? undefined;
|
|
1245
1278
|
const sources = [...new Set((input.links ?? []).map((l) => l.trim()).filter(Boolean))].slice(0, MAX_SOURCES);
|
|
1246
1279
|
return {
|
|
1247
1280
|
ask,
|
|
@@ -1370,11 +1403,11 @@ var init_brief = __esm(() => {
|
|
|
1370
1403
|
init_worth();
|
|
1371
1404
|
init_forms();
|
|
1372
1405
|
QUESTIONS = {
|
|
1373
|
-
why: "Who is
|
|
1374
|
-
done: "
|
|
1375
|
-
smallest: "What
|
|
1376
|
-
worth: "
|
|
1377
|
-
touches: "
|
|
1406
|
+
why: "Who is this for, and why does it matter now?",
|
|
1407
|
+
done: "How will we know it's done?",
|
|
1408
|
+
smallest: "What's the smallest version that would still help?",
|
|
1409
|
+
worth: "How important is this: high, medium, or low? If a specific customer is waiting on it, tell me who.",
|
|
1410
|
+
touches: "Which part of the product is this about?",
|
|
1378
1411
|
demand: "How many people have asked for this, or how often does it come up?"
|
|
1379
1412
|
};
|
|
1380
1413
|
REQUIRED_TO_FILE = ["why", "done"];
|
|
@@ -1635,7 +1668,8 @@ function intakePlan(g) {
|
|
|
1635
1668
|
card: g.card ? [...g.card] : base.card,
|
|
1636
1669
|
limits: [...g.limits ?? []],
|
|
1637
1670
|
followed: [...g.followed ?? []],
|
|
1638
|
-
text: g.text ?? ""
|
|
1671
|
+
text: g.text ?? "",
|
|
1672
|
+
...g.references ? { references: g.references } : {}
|
|
1639
1673
|
};
|
|
1640
1674
|
}
|
|
1641
1675
|
function planOpen(b, plan, extra = {}) {
|
|
@@ -1667,11 +1701,14 @@ var init_intake = __esm(() => {
|
|
|
1667
1701
|
ORDER = ["why", "done", "smallest", "worth", "touches", "demand"];
|
|
1668
1702
|
DEFAULT_CARD = CARD_FIELDS.filter((f) => f !== "product map details");
|
|
1669
1703
|
FIELD_WORDS = [
|
|
1670
|
-
["why", /\bwho is it for\b|\bwhy now\b|\bwho (?:hits|needs|asked)\b|\bwhy\b/i],
|
|
1671
|
-
["done", /\bdone\b|\blook like\b|\bsuccess\b|\bacceptance\b/i],
|
|
1704
|
+
["why", /\bwho is (?:it|this) for\b|\bwhy now\b|\bwho (?:hits|needs|asked)\b|\bwhy\b/i],
|
|
1705
|
+
["done", /\bdone\b|\blook like\b|\bsuccess\b|\bacceptance\b|\bis fixed\b|\bit'?s fixed\b/i],
|
|
1672
1706
|
["smallest", /\bsmallest\b|\bminimum\b|\bmvp\b|\bsmaller version\b/i],
|
|
1673
|
-
["worth", /\bworth\b|\bvalue to\b|\bthe business\b|\brevenue\b/i],
|
|
1674
|
-
[
|
|
1707
|
+
["worth", /\bworth\b|\bvalue to\b|\bthe business\b|\brevenue\b|\bhow important\b/i],
|
|
1708
|
+
[
|
|
1709
|
+
"touches",
|
|
1710
|
+
/\btouch(?:es)?\b|\bwhich (?:product|system|area)s?\b|\bwhere in the product\b|\bwhich part of the product\b/i
|
|
1711
|
+
],
|
|
1675
1712
|
["demand", /\bhow many\b|\bhow often\b|\bcome up\b|\basked for this\b/i]
|
|
1676
1713
|
];
|
|
1677
1714
|
});
|
|
@@ -3154,6 +3191,13 @@ async function updateTool(ctx, args) {
|
|
|
3154
3191
|
patch.repos = args.repos.split(/[,\s]+/).filter(Boolean);
|
|
3155
3192
|
if (Array.isArray(args.relations))
|
|
3156
3193
|
patch.relations = args.relations.filter(isObject4).map((r) => ({ key: str5(r.key)?.trim() ?? "", how: str5(r.how) ?? "relates" })).filter((r) => r.key && /^(blockedBy|blocks|relates|duplicates)$/.test(r.how));
|
|
3194
|
+
if (args.worth === null)
|
|
3195
|
+
patch.worth = null;
|
|
3196
|
+
else if (typeof args.worth === "string" && args.worth.trim()) {
|
|
3197
|
+
patch.worth = args.worth.trim();
|
|
3198
|
+
if (args.carry === true)
|
|
3199
|
+
patch.carry = true;
|
|
3200
|
+
}
|
|
3157
3201
|
if (args.sensitivity === null)
|
|
3158
3202
|
patch.sensitivity = null;
|
|
3159
3203
|
else if (typeof args.sensitivity === "string" && /^(public|internal|restricted)$/.test(args.sensitivity)) {
|
|
@@ -3163,7 +3207,7 @@ async function updateTool(ctx, args) {
|
|
|
3163
3207
|
}
|
|
3164
3208
|
if (Object.keys(patch).length === 0)
|
|
3165
3209
|
return {
|
|
3166
|
-
text: "Nothing to change. Pass the fields that change: ask, why, done, smallest, touches, demand, description, due, parent, repos, relations.",
|
|
3210
|
+
text: "Nothing to change. Pass the fields that change: ask, why, done, smallest, touches, demand, worth, description, due, parent, repos, relations.",
|
|
3167
3211
|
isError: true
|
|
3168
3212
|
};
|
|
3169
3213
|
const res = await postSaying(ctx, "/proxy/item/update", { project, ...patch }, "Could not update the item.");
|
|
@@ -3171,13 +3215,27 @@ async function updateTool(ctx, args) {
|
|
|
3171
3215
|
return res.fail;
|
|
3172
3216
|
const changed = Array.isArray(res.json.changed) ? res.json.changed.filter((x) => typeof x === "string") : [];
|
|
3173
3217
|
const key = str5(res.json.key) ?? project;
|
|
3218
|
+
const carried = carriedLine(res.json.carried);
|
|
3174
3219
|
if (changed.length === 0)
|
|
3175
|
-
return { text: `${key}: nothing differed from what is on the item
|
|
3220
|
+
return { text: `${key}: nothing differed from what is on the item.${carried}` };
|
|
3176
3221
|
const stale = res.json.sizeStale === true;
|
|
3177
3222
|
return {
|
|
3178
|
-
text: `${key} updated: ${changed.join(", ")}.${stale ? " The band was sized before this change — say so, and offer to re-size (estimate with the same source)." : ""}`
|
|
3223
|
+
text: `${key} updated: ${changed.join(", ")}.${carried}${stale ? " The band was sized before this change — say so, and offer to re-size (estimate with the same source)." : ""}`
|
|
3179
3224
|
};
|
|
3180
3225
|
}
|
|
3226
|
+
function carriedLine(c) {
|
|
3227
|
+
if (!isObject4(c))
|
|
3228
|
+
return "";
|
|
3229
|
+
const set = Array.isArray(c.set) ? c.set.filter((x) => typeof x === "string") : [];
|
|
3230
|
+
const valued = num3(c.valued) ?? 0;
|
|
3231
|
+
const skipped = num3(c.skipped) ?? 0;
|
|
3232
|
+
const parts = [
|
|
3233
|
+
set.length ? `worth set on ${set.length} ${set.length === 1 ? "child" : "children"} (${set.join(", ")})` : "no child took it",
|
|
3234
|
+
...valued ? [`${valued} already had a worth and kept it`] : [],
|
|
3235
|
+
...skipped ? [`${skipped} you may not change (a mirror, or not yours) — left as they were`] : []
|
|
3236
|
+
];
|
|
3237
|
+
return ` ${parts.join("; ").replace(/^./, (ch) => ch.toUpperCase())}.`;
|
|
3238
|
+
}
|
|
3181
3239
|
async function archiveTool(ctx, args) {
|
|
3182
3240
|
if (!ctx.client)
|
|
3183
3241
|
return NOT_SET_UP;
|
|
@@ -4854,7 +4912,7 @@ var init_server = __esm(() => {
|
|
|
4854
4912
|
},
|
|
4855
4913
|
{
|
|
4856
4914
|
name: "update",
|
|
4857
|
-
description: "Change an item on the sled — its title (`ask`), why, done, smallest, touches, demand, its description (markdown: the prose the brief does not hold), its due day, which item it sits under, the repo(s) it lands in, or its sensitivity (public · internal · restricted). Pass the item's key and only the fields that change. The filer, an approver or an admin may; a mirrored ticket cannot be changed here. A change to the ask, done or smallest marks the band stale — say so, and offer to re-size. Everything you write is signed as coming through you.",
|
|
4915
|
+
description: "Change an item on the sled — its title (`ask`), why, done, smallest, touches, demand, its worth, its description (markdown: the prose the brief does not hold), its due day, which item it sits under, the repo(s) it lands in, or its sensitivity (public · internal · restricted). Pass the item's key and only the fields that change. Worth is the person's word — never guess it; on an epic, `carry: true` puts it on the children that have none. The filer, an approver or an admin may; a mirrored ticket cannot be changed here. A change to the ask, done or smallest marks the band stale — say so, and offer to re-size. Everything you write is signed as coming through you.",
|
|
4858
4916
|
inputSchema: {
|
|
4859
4917
|
type: "object",
|
|
4860
4918
|
properties: {
|
|
@@ -4865,6 +4923,14 @@ var init_server = __esm(() => {
|
|
|
4865
4923
|
smallest: { type: "string" },
|
|
4866
4924
|
touches: { type: "string" },
|
|
4867
4925
|
demand: { type: "string" },
|
|
4926
|
+
worth: {
|
|
4927
|
+
type: ["string", "null"],
|
|
4928
|
+
description: "What the person said it is worth: a level (low · medium · high · critical), dollars, a customer — e.g. 'high · Acme renewal', '$5k–20k'. Null clears it."
|
|
4929
|
+
},
|
|
4930
|
+
carry: {
|
|
4931
|
+
type: "boolean",
|
|
4932
|
+
description: "With worth: put it on this item's children that have no worth yet, each on its own record. A child with a worth keeps it."
|
|
4933
|
+
},
|
|
4868
4934
|
description: {
|
|
4869
4935
|
type: "string",
|
|
4870
4936
|
description: "Markdown. Links and images inline. Empty clears it."
|
|
@@ -5323,9 +5389,33 @@ var init_outcome = __esm(() => {
|
|
|
5323
5389
|
});
|
|
5324
5390
|
|
|
5325
5391
|
// ../../packages/shared/src/slack/mention.ts
|
|
5392
|
+
var MENTION_HELP;
|
|
5326
5393
|
var init_mention = __esm(() => {
|
|
5327
5394
|
init_intake();
|
|
5328
5395
|
init_brief();
|
|
5396
|
+
MENTION_HELP = [
|
|
5397
|
+
"Here's what I can do:",
|
|
5398
|
+
"• *@SLEDS file this*: turn the message above into a request for engineering",
|
|
5399
|
+
"• *@SLEDS status*: see where something stands",
|
|
5400
|
+
"You can also ask me to *watch* or *mute* a thread, or *run QW-123*."
|
|
5401
|
+
].join(`
|
|
5402
|
+
`);
|
|
5403
|
+
});
|
|
5404
|
+
|
|
5405
|
+
// ../../packages/shared/src/slack/copy.ts
|
|
5406
|
+
var init_copy = __esm(() => {
|
|
5407
|
+
init_intake();
|
|
5408
|
+
init_forms();
|
|
5409
|
+
init_mention();
|
|
5410
|
+
init_mention();
|
|
5411
|
+
});
|
|
5412
|
+
|
|
5413
|
+
// ../../packages/shared/src/slack/agent.ts
|
|
5414
|
+
var init_agent = __esm(() => {
|
|
5415
|
+
init_intake();
|
|
5416
|
+
init_brief();
|
|
5417
|
+
init_copy();
|
|
5418
|
+
init_mention();
|
|
5329
5419
|
});
|
|
5330
5420
|
|
|
5331
5421
|
// ../../packages/shared/src/item/productHits.ts
|
|
@@ -5627,6 +5717,24 @@ var init_fieldMap = __esm(() => {
|
|
|
5627
5717
|
var SEPT_30 = "/whats-new/2026-09-30", WHATS_NEW;
|
|
5628
5718
|
var init_whatsNew = __esm(() => {
|
|
5629
5719
|
WHATS_NEW = [
|
|
5720
|
+
{
|
|
5721
|
+
date: "2026-10-22",
|
|
5722
|
+
title: "Policy is an org setting",
|
|
5723
|
+
lede: "There is one policy for the whole org, so it now lives under Settings beside Platform keys and AI Guidance, instead of on each workspace's rail where it read as a workspace's own. Nothing in it changed; old links redirect.",
|
|
5724
|
+
sections: [
|
|
5725
|
+
{
|
|
5726
|
+
title: "Where it went",
|
|
5727
|
+
where: "Settings › Policy",
|
|
5728
|
+
body: "Open your profile menu › Settings, then Policy. The page is the same: every rule as one sentence, saved as a new version. The rail's Plan group keeps Seats."
|
|
5729
|
+
}
|
|
5730
|
+
],
|
|
5731
|
+
also: [
|
|
5732
|
+
{
|
|
5733
|
+
label: "Next",
|
|
5734
|
+
text: "Each workspace's Jira projects get their own pages for fields and statuses, and the org's Jira page keeps only the connection, the webhook and what SLEDS may write."
|
|
5735
|
+
}
|
|
5736
|
+
]
|
|
5737
|
+
},
|
|
5630
5738
|
{
|
|
5631
5739
|
date: "2026-10-21",
|
|
5632
5740
|
title: "The Slack thread is the item's discussion",
|
|
@@ -5650,18 +5758,28 @@ var init_whatsNew = __esm(() => {
|
|
|
5650
5758
|
{
|
|
5651
5759
|
title: "Forms are read as fields",
|
|
5652
5760
|
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
|
|
5761
|
+
body: "A support ticket form posted by a Slack workflow is read field by field: the issue description is the title, the users and IDs go on one details line, and the count of clients and the revenue answer to demand. SLEDS then asks only what the form did not say."
|
|
5762
|
+
},
|
|
5763
|
+
{
|
|
5764
|
+
title: "Replies you can read",
|
|
5765
|
+
where: "Slack, filing from a thread",
|
|
5766
|
+
body: `One summary message per thread, kept up to date as you answer, with the title in plain words and the form's other fields on one line. Answer several questions at once, one per line, or say which one you're answering: "done means the sync works", "high priority". Say "send it to Core" to change the team before filing. A yes with something missing asks for just that one thing.`
|
|
5767
|
+
},
|
|
5768
|
+
{
|
|
5769
|
+
title: "A model can write the replies",
|
|
5770
|
+
where: "Policy › Intake",
|
|
5771
|
+
body: "Turn on Slack intake replies written by a model, Claude Haiku 5.5 by default, and it answers in the thread the way the channel's AI Guidance says: what it understood, a workaround when there is one, and the questions that matter for this kind of issue. It spends your own Anthropic key from Platform keys, up to a daily cap you set. Filing still waits for a yes, and it never sets the priority."
|
|
5654
5772
|
},
|
|
5655
5773
|
{
|
|
5656
5774
|
title: "Which workspace, picked",
|
|
5657
5775
|
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
|
|
5776
|
+
body: "A channel tied to a workspace files there. With several workspaces and none tied to the channel, SLEDS asks which team: reply with the number or the name. The Jira key is never typed — the Filed as reply shows it."
|
|
5659
5777
|
}
|
|
5660
5778
|
],
|
|
5661
5779
|
also: [
|
|
5662
5780
|
{
|
|
5663
5781
|
label: "Fixed",
|
|
5664
|
-
text: "An ask filed from Slack now creates its Jira ticket in the workspace it was filed on, and
|
|
5782
|
+
text: "An ask filed from Slack now creates its Jira ticket in the workspace it was filed on, and a stated priority sets the ticket's priority. A form posted by a Slack workflow is now read field by field."
|
|
5665
5783
|
}
|
|
5666
5784
|
]
|
|
5667
5785
|
},
|
|
@@ -6297,6 +6415,9 @@ var init_pack2 = __esm(() => {
|
|
|
6297
6415
|
init_prHeader();
|
|
6298
6416
|
});
|
|
6299
6417
|
|
|
6418
|
+
// ../../packages/shared/src/deploys/deploys.ts
|
|
6419
|
+
var init_deploys = () => {};
|
|
6420
|
+
|
|
6300
6421
|
// ../../packages/shared/src/newrelic/newrelic.ts
|
|
6301
6422
|
var init_newrelic = () => {};
|
|
6302
6423
|
|
|
@@ -7138,6 +7259,9 @@ var init_effort = __esm(() => {
|
|
|
7138
7259
|
EFFORTS = ["low", "medium", "high", "xhigh", "max"];
|
|
7139
7260
|
});
|
|
7140
7261
|
|
|
7262
|
+
// ../../packages/shared/src/workspaceLook.ts
|
|
7263
|
+
var init_workspaceLook = () => {};
|
|
7264
|
+
|
|
7141
7265
|
// src/settings.ts
|
|
7142
7266
|
import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
7143
7267
|
import { dirname, join, resolve as resolve2 } from "node:path";
|
|
@@ -7682,6 +7806,8 @@ var init_src = __esm(() => {
|
|
|
7682
7806
|
init_profile2();
|
|
7683
7807
|
init_outcome();
|
|
7684
7808
|
init_mention();
|
|
7809
|
+
init_agent();
|
|
7810
|
+
init_copy();
|
|
7685
7811
|
init_productHits();
|
|
7686
7812
|
init_model();
|
|
7687
7813
|
init_parse();
|
|
@@ -7696,6 +7822,7 @@ var init_src = __esm(() => {
|
|
|
7696
7822
|
init_cheatSheet();
|
|
7697
7823
|
init_pack2();
|
|
7698
7824
|
init_flags();
|
|
7825
|
+
init_deploys();
|
|
7699
7826
|
init_sentry();
|
|
7700
7827
|
init_newrelic();
|
|
7701
7828
|
init_musher();
|
|
@@ -7706,6 +7833,7 @@ var init_src = __esm(() => {
|
|
|
7706
7833
|
init_otlp();
|
|
7707
7834
|
init_session();
|
|
7708
7835
|
init_effort();
|
|
7836
|
+
init_workspaceLook();
|
|
7709
7837
|
});
|
|
7710
7838
|
|
|
7711
7839
|
// src/engine/json.ts
|
|
@@ -8383,6 +8511,8 @@ init_due();
|
|
|
8383
8511
|
init_profile2();
|
|
8384
8512
|
init_outcome();
|
|
8385
8513
|
init_mention();
|
|
8514
|
+
init_agent();
|
|
8515
|
+
init_copy();
|
|
8386
8516
|
init_productHits();
|
|
8387
8517
|
init_model();
|
|
8388
8518
|
init_parse();
|
|
@@ -8397,6 +8527,7 @@ init_whatsNew();
|
|
|
8397
8527
|
init_cheatSheet();
|
|
8398
8528
|
init_pack2();
|
|
8399
8529
|
init_flags();
|
|
8530
|
+
init_deploys();
|
|
8400
8531
|
init_sentry();
|
|
8401
8532
|
init_newrelic();
|
|
8402
8533
|
init_musher();
|
|
@@ -8407,6 +8538,7 @@ init_engine();
|
|
|
8407
8538
|
init_otlp();
|
|
8408
8539
|
init_session();
|
|
8409
8540
|
init_effort();
|
|
8541
|
+
init_workspaceLook();
|
|
8410
8542
|
|
|
8411
8543
|
// src/agentMcp.ts
|
|
8412
8544
|
import { execFileSync } from "node:child_process";
|
|
@@ -9566,16 +9698,16 @@ init_src();
|
|
|
9566
9698
|
import { execFileSync as execFileSync3, spawnSync as spawnSync5 } from "node:child_process";
|
|
9567
9699
|
import { randomBytes } from "node:crypto";
|
|
9568
9700
|
import {
|
|
9569
|
-
existsSync as
|
|
9570
|
-
lstatSync,
|
|
9701
|
+
existsSync as existsSync17,
|
|
9702
|
+
lstatSync as lstatSync2,
|
|
9571
9703
|
mkdtempSync,
|
|
9572
9704
|
readFileSync as readFileSync17,
|
|
9573
|
-
readlinkSync,
|
|
9705
|
+
readlinkSync as readlinkSync2,
|
|
9574
9706
|
rmSync as rmSync8,
|
|
9575
9707
|
writeFileSync as writeFileSync17
|
|
9576
9708
|
} from "node:fs";
|
|
9577
9709
|
import { tmpdir } from "node:os";
|
|
9578
|
-
import { join as
|
|
9710
|
+
import { join as join20, resolve as resolve9 } from "node:path";
|
|
9579
9711
|
|
|
9580
9712
|
// src/agentMcp.ts
|
|
9581
9713
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
@@ -10537,6 +10669,215 @@ function cmuxRunner(exec, deps = {}) {
|
|
|
10537
10669
|
};
|
|
10538
10670
|
}
|
|
10539
10671
|
|
|
10672
|
+
// src/runners/orca.ts
|
|
10673
|
+
import { existsSync as existsSync12, lstatSync, readlinkSync, writeFileSync as writeFileSync11 } from "node:fs";
|
|
10674
|
+
import { join as join14, resolve as resolve7 } from "node:path";
|
|
10675
|
+
var obj = (v) => v !== null && typeof v === "object" && !Array.isArray(v) ? v : null;
|
|
10676
|
+
var str8 = (v) => typeof v === "string" && v.length > 0 ? v : null;
|
|
10677
|
+
var parseOrcaJson = (stdout) => {
|
|
10678
|
+
try {
|
|
10679
|
+
return obj(JSON.parse(stdout));
|
|
10680
|
+
} catch {
|
|
10681
|
+
return null;
|
|
10682
|
+
}
|
|
10683
|
+
};
|
|
10684
|
+
var orcaError = (env) => {
|
|
10685
|
+
if (!env || env.ok !== false)
|
|
10686
|
+
return null;
|
|
10687
|
+
const e = obj(env.error);
|
|
10688
|
+
const message = str8(e?.message) ?? "Orca refused the call";
|
|
10689
|
+
const code = str8(e?.code);
|
|
10690
|
+
return code ? `${message} (${code})` : message;
|
|
10691
|
+
};
|
|
10692
|
+
var parseOrcaWorktree = (env) => {
|
|
10693
|
+
const result = obj(env.result) ?? {};
|
|
10694
|
+
return str8(obj(result.worktree)?.path) ?? str8(result.worktreePath) ?? str8(result.path);
|
|
10695
|
+
};
|
|
10696
|
+
var parseOrcaBranch = (env) => {
|
|
10697
|
+
const wt = obj(obj(env.result)?.worktree);
|
|
10698
|
+
const branch = str8(wt?.branch)?.replace(/^refs\/heads\//, "");
|
|
10699
|
+
const head = str8(wt?.head);
|
|
10700
|
+
return branch && head ? { branch, head } : null;
|
|
10701
|
+
};
|
|
10702
|
+
var parseOrcaTerminal = (env) => {
|
|
10703
|
+
const result = obj(env.result) ?? {};
|
|
10704
|
+
return str8(obj(result.terminal)?.handle) ?? str8(result.handle) ?? str8(result.terminalHandle) ?? null;
|
|
10705
|
+
};
|
|
10706
|
+
var orcaLauncher = (o) => `#!/bin/sh
|
|
10707
|
+
# sleds engine: ${o.name}
|
|
10708
|
+
exec ${agentShellCommand(o)}
|
|
10709
|
+
`;
|
|
10710
|
+
var orcaCommand = (launcher) => `sh ${shq2(launcher)}; exit`;
|
|
10711
|
+
var GONE = /exit|clos|gone|dead|stopp|kill/i;
|
|
10712
|
+
var orcaTerminalLive = (status, stdout) => {
|
|
10713
|
+
const env = parseOrcaJson(stdout);
|
|
10714
|
+
if (str8(obj(env?.error)?.code) === "runtime_unavailable")
|
|
10715
|
+
return true;
|
|
10716
|
+
if (status !== 0 || !env || env.ok === false)
|
|
10717
|
+
return false;
|
|
10718
|
+
const t = obj(obj(env.result)?.terminal) ?? obj(env.result) ?? {};
|
|
10719
|
+
if (typeof t.status === "string" && GONE.test(t.status))
|
|
10720
|
+
return false;
|
|
10721
|
+
if (t.exited === true || t.alive === false)
|
|
10722
|
+
return false;
|
|
10723
|
+
if (typeof t.exitCode === "number")
|
|
10724
|
+
return false;
|
|
10725
|
+
if (obj(t.exitCause))
|
|
10726
|
+
return false;
|
|
10727
|
+
if (t.orphaned === true && t.writable === false)
|
|
10728
|
+
return false;
|
|
10729
|
+
return true;
|
|
10730
|
+
};
|
|
10731
|
+
var realFs = { lstat: lstatSync, readlink: readlinkSync, exists: existsSync12 };
|
|
10732
|
+
var ORCA_LINK_FIX = "reinstall Orca's shell command from Orca (it links `orca` onto your PATH)";
|
|
10733
|
+
function danglingOrca(path, fs) {
|
|
10734
|
+
for (const dir of path.split(":").filter(Boolean)) {
|
|
10735
|
+
const link = join14(dir, "orca");
|
|
10736
|
+
try {
|
|
10737
|
+
if (!fs.lstat(link).isSymbolicLink())
|
|
10738
|
+
return null;
|
|
10739
|
+
const target = resolve7(dir, fs.readlink(link));
|
|
10740
|
+
if (!fs.exists(target))
|
|
10741
|
+
return { link, target };
|
|
10742
|
+
return null;
|
|
10743
|
+
} catch {}
|
|
10744
|
+
}
|
|
10745
|
+
return null;
|
|
10746
|
+
}
|
|
10747
|
+
function orcaPreflight(exec, path, fs = realFs) {
|
|
10748
|
+
let r;
|
|
10749
|
+
try {
|
|
10750
|
+
r = exec("orca", ["--version"], { env: { PATH: path } });
|
|
10751
|
+
} catch (e) {
|
|
10752
|
+
r = { status: 127, stdout: "", stderr: e instanceof Error ? e.message : String(e) };
|
|
10753
|
+
}
|
|
10754
|
+
if (r.status === 0) {
|
|
10755
|
+
return { ok: true, version: r.stdout.trim().split(`
|
|
10756
|
+
`)[0]?.trim() || "orca" };
|
|
10757
|
+
}
|
|
10758
|
+
const dangling = danglingOrca(path, fs);
|
|
10759
|
+
if (dangling) {
|
|
10760
|
+
return {
|
|
10761
|
+
ok: false,
|
|
10762
|
+
why: `${dangling.link} links to ${dangling.target}, which is gone`,
|
|
10763
|
+
fix: ORCA_LINK_FIX
|
|
10764
|
+
};
|
|
10765
|
+
}
|
|
10766
|
+
if (!path.split(":").includes("/usr/bin")) {
|
|
10767
|
+
return { ok: false, why: "the engine's PATH has no /usr/bin", fix: "sleds engine install" };
|
|
10768
|
+
}
|
|
10769
|
+
if (r.status === 127) {
|
|
10770
|
+
return { ok: false, why: "not installed (no `orca` on the PATH)", fix: ORCA_LINK_FIX };
|
|
10771
|
+
}
|
|
10772
|
+
const said = `${r.stderr}
|
|
10773
|
+
${r.stdout}`.split(`
|
|
10774
|
+
`).map((l) => l.trim()).find(Boolean);
|
|
10775
|
+
return {
|
|
10776
|
+
ok: false,
|
|
10777
|
+
why: `\`orca --version\` failed: ${said ?? `exit ${r.status}`}`,
|
|
10778
|
+
fix: "reinstall Orca, or its shell command from Orca"
|
|
10779
|
+
};
|
|
10780
|
+
}
|
|
10781
|
+
var launcherPath2 = (promptFile) => `${promptFile.replace(/\.md$/, "")}.orca.sh`;
|
|
10782
|
+
function orcaRunner(exec, deps = {}) {
|
|
10783
|
+
const writeFile = deps.writeFile ?? ((p, t) => writeFileSync11(p, t, { mode: 384 }));
|
|
10784
|
+
const orca = (args, what) => {
|
|
10785
|
+
const r = exec("orca", args);
|
|
10786
|
+
const env = parseOrcaJson(r.stdout);
|
|
10787
|
+
const refused = orcaError(env);
|
|
10788
|
+
if (refused)
|
|
10789
|
+
throw new Error(`${what}: ${refused}`);
|
|
10790
|
+
if (r.status !== 0 || !env) {
|
|
10791
|
+
throw new Error(`${what} failed: ${r.stderr.trim() || r.stdout.trim() || `exit ${r.status}`}`);
|
|
10792
|
+
}
|
|
10793
|
+
return env;
|
|
10794
|
+
};
|
|
10795
|
+
return {
|
|
10796
|
+
name: "orca",
|
|
10797
|
+
makesWorktree: true,
|
|
10798
|
+
readsSession: true,
|
|
10799
|
+
start(o) {
|
|
10800
|
+
const created = orca([
|
|
10801
|
+
"worktree",
|
|
10802
|
+
"create",
|
|
10803
|
+
"--repo",
|
|
10804
|
+
`path:${o.repoPath}`,
|
|
10805
|
+
"--name",
|
|
10806
|
+
o.name,
|
|
10807
|
+
"--base-branch",
|
|
10808
|
+
`origin/${o.base ?? "main"}`,
|
|
10809
|
+
"--no-parent",
|
|
10810
|
+
"--json"
|
|
10811
|
+
], `orca worktree create ${o.name}`);
|
|
10812
|
+
const cwd = parseOrcaWorktree(created);
|
|
10813
|
+
if (!cwd) {
|
|
10814
|
+
throw new Error(`orca worktree create ${o.name} returned no worktree path; the agent was not started`);
|
|
10815
|
+
}
|
|
10816
|
+
const launcher = launcherPath2(o.promptFile);
|
|
10817
|
+
writeFile(launcher, orcaLauncher(o));
|
|
10818
|
+
const shown = orca([
|
|
10819
|
+
"terminal",
|
|
10820
|
+
"create",
|
|
10821
|
+
"--worktree",
|
|
10822
|
+
`path:${cwd}`,
|
|
10823
|
+
"--title",
|
|
10824
|
+
o.name,
|
|
10825
|
+
"--command",
|
|
10826
|
+
orcaCommand(launcher),
|
|
10827
|
+
"--json"
|
|
10828
|
+
], `orca terminal create ${o.name} (worktree ${cwd})`);
|
|
10829
|
+
const terminal = parseOrcaTerminal(shown);
|
|
10830
|
+
if (!terminal) {
|
|
10831
|
+
throw new Error(`orca terminal create ${o.name} started in ${cwd} but returned no terminal handle`);
|
|
10832
|
+
}
|
|
10833
|
+
const own = parseOrcaBranch(created);
|
|
10834
|
+
const h = { runner: "orca", id: terminal, cwd, ...own ? { own } : {} };
|
|
10835
|
+
return h;
|
|
10836
|
+
},
|
|
10837
|
+
status(h) {
|
|
10838
|
+
const r = exec("orca", ["terminal", "show", "--terminal", h.id, "--json"]);
|
|
10839
|
+
return orcaTerminalLive(r.status, r.stdout) ? "running" : "exited";
|
|
10840
|
+
},
|
|
10841
|
+
read(h) {
|
|
10842
|
+
const r = exec("orca", ["terminal", "read", "--terminal", h.id, "--limit", "200"]);
|
|
10843
|
+
return r.status === 0 ? r.stdout : "";
|
|
10844
|
+
},
|
|
10845
|
+
send(h, text) {
|
|
10846
|
+
const r = exec("orca", ["terminal", "send", "--terminal", h.id, "--text", text, "--enter"]);
|
|
10847
|
+
if (r.status !== 0) {
|
|
10848
|
+
throw new Error(`orca terminal send ${h.id} failed: ${r.stderr.trim() || `exit ${r.status}`}`);
|
|
10849
|
+
}
|
|
10850
|
+
},
|
|
10851
|
+
stop(h) {
|
|
10852
|
+
exec("orca", ["terminal", "close", "--terminal", h.id]);
|
|
10853
|
+
},
|
|
10854
|
+
watchHint(h) {
|
|
10855
|
+
return `orca terminal show --terminal ${h.id}`;
|
|
10856
|
+
},
|
|
10857
|
+
probe() {
|
|
10858
|
+
try {
|
|
10859
|
+
const p = orcaPreflight(exec, process.env.PATH ?? "", deps.fs);
|
|
10860
|
+
return p.ok ? null : `orca: ${p.why} — ${p.fix}`;
|
|
10861
|
+
} catch {
|
|
10862
|
+
return "orca: not installed";
|
|
10863
|
+
}
|
|
10864
|
+
},
|
|
10865
|
+
removeWorktree(h, repoPath) {
|
|
10866
|
+
orca(["worktree", "rm", "--worktree", `path:${h.cwd}`, "--json"], `orca worktree rm ${h.cwd}`);
|
|
10867
|
+
if (!h.own)
|
|
10868
|
+
return;
|
|
10869
|
+
const ref = `refs/heads/${h.own.branch}`;
|
|
10870
|
+
const r = exec("git", ["-C", repoPath, "update-ref", "-d", ref, h.own.head]);
|
|
10871
|
+
if (r.status === 0)
|
|
10872
|
+
return;
|
|
10873
|
+
const still = exec("git", ["-C", repoPath, "rev-parse", "--verify", "--quiet", ref]);
|
|
10874
|
+
if (still.status !== 0)
|
|
10875
|
+
return;
|
|
10876
|
+
return `kept Orca's branch ${h.own.branch}: ${r.stderr.trim() || `exit ${r.status}`}`;
|
|
10877
|
+
}
|
|
10878
|
+
};
|
|
10879
|
+
}
|
|
10880
|
+
|
|
10540
10881
|
// src/commands/doctor.ts
|
|
10541
10882
|
init_settings();
|
|
10542
10883
|
|
|
@@ -10554,7 +10895,7 @@ import {
|
|
|
10554
10895
|
writeFileSync as writeFileSync13
|
|
10555
10896
|
} from "node:fs";
|
|
10556
10897
|
import { hostname as hostname2 } from "node:os";
|
|
10557
|
-
import { join as
|
|
10898
|
+
import { join as join16, resolve as resolve8 } from "node:path";
|
|
10558
10899
|
|
|
10559
10900
|
// src/engine/beat.ts
|
|
10560
10901
|
var BEAT_EVERY_MS = 60000;
|
|
@@ -10566,7 +10907,7 @@ function beatBody(state, flags, host = {}, cap = {}) {
|
|
|
10566
10907
|
name: flags.name,
|
|
10567
10908
|
os: host.os ?? process.platform,
|
|
10568
10909
|
runner: flags.runner,
|
|
10569
|
-
version: host.version ?? "0.1.
|
|
10910
|
+
version: host.version ?? "0.1.44" ?? "dev",
|
|
10570
10911
|
running: live.length,
|
|
10571
10912
|
items: live.slice(0, BEAT_ITEMS).map((r) => `${r.item}/${r.node}`),
|
|
10572
10913
|
...cap.atOnce !== undefined ? { atOnce: cap.atOnce } : {},
|
|
@@ -11359,7 +11700,7 @@ function jiraFromEnv(epic, gate, env = process.env) {
|
|
|
11359
11700
|
init_src();
|
|
11360
11701
|
|
|
11361
11702
|
// src/commands/permissionEvent.ts
|
|
11362
|
-
import { chmodSync as chmodSync3, mkdirSync as mkdirSync10, readFileSync as readFileSync10, renameSync as renameSync6, rmSync as rmSync3, writeFileSync as
|
|
11703
|
+
import { chmodSync as chmodSync3, mkdirSync as mkdirSync10, readFileSync as readFileSync10, renameSync as renameSync6, rmSync as rmSync3, writeFileSync as writeFileSync12 } from "node:fs";
|
|
11363
11704
|
|
|
11364
11705
|
// src/commands/seatEvent.ts
|
|
11365
11706
|
init_config();
|
|
@@ -11838,11 +12179,12 @@ function sledsSource(client, o) {
|
|
|
11838
12179
|
async function draft(row, item, why) {
|
|
11839
12180
|
const project = str6(row.project) ?? item;
|
|
11840
12181
|
const pending = isObject8(row.route) && isObject8(row.route.redraft) ? row.route.redraft : null;
|
|
12182
|
+
const runner = typeof o.runner === "function" ? o.runner() : o.runner;
|
|
11841
12183
|
const r = await client.postFull("/proxy/route", {
|
|
11842
12184
|
project,
|
|
11843
12185
|
draft: "take",
|
|
11844
12186
|
engine: o.engine,
|
|
11845
|
-
...
|
|
12187
|
+
...runner ? { runner } : {},
|
|
11846
12188
|
...o.leaseMin !== undefined ? { leaseMin: o.leaseMin } : {}
|
|
11847
12189
|
});
|
|
11848
12190
|
if (!r || r.status >= 300 || !r.json || r.json.ok === false) {
|
|
@@ -12370,10 +12712,10 @@ function providerFailure(screen) {
|
|
|
12370
12712
|
|
|
12371
12713
|
// src/engine/worktree.ts
|
|
12372
12714
|
init_src();
|
|
12373
|
-
import { appendFileSync, existsSync as
|
|
12374
|
-
import { dirname as dirname11, isAbsolute, join as
|
|
12715
|
+
import { appendFileSync, existsSync as existsSync13, mkdirSync as mkdirSync11 } from "node:fs";
|
|
12716
|
+
import { dirname as dirname11, isAbsolute, join as join15 } from "node:path";
|
|
12375
12717
|
function worktreePath(repoPath, name) {
|
|
12376
|
-
return
|
|
12718
|
+
return join15(repoPath, ".worktrees", name);
|
|
12377
12719
|
}
|
|
12378
12720
|
var fail = (what, r) => new Error(`${what} failed: ${(r.stderr || r.stdout).trim() || `exit ${r.status}`}`);
|
|
12379
12721
|
function defaultBranch(exec, repoPath) {
|
|
@@ -12394,7 +12736,7 @@ function defaultBranch(exec, repoPath) {
|
|
|
12394
12736
|
return "main";
|
|
12395
12737
|
}
|
|
12396
12738
|
var realWorktreeFs = {
|
|
12397
|
-
exists:
|
|
12739
|
+
exists: existsSync13,
|
|
12398
12740
|
append: (p, text) => {
|
|
12399
12741
|
mkdirSync11(dirname11(p), { recursive: true });
|
|
12400
12742
|
appendFileSync(p, text);
|
|
@@ -12408,7 +12750,7 @@ function ensureIgnored(exec, repoPath, fs = realWorktreeFs) {
|
|
|
12408
12750
|
if (common.status !== 0)
|
|
12409
12751
|
return;
|
|
12410
12752
|
const dir = common.stdout.trim();
|
|
12411
|
-
const exclude =
|
|
12753
|
+
const exclude = join15(isAbsolute(dir) ? dir : join15(repoPath, dir), "info", "exclude");
|
|
12412
12754
|
fs.append(exclude, `
|
|
12413
12755
|
# sleds engine: one worktree per route node
|
|
12414
12756
|
.worktrees/
|
|
@@ -12420,7 +12762,7 @@ function ensureWorktree(exec, repoPath, branch, path, base = "main", fs = realWo
|
|
|
12420
12762
|
return path;
|
|
12421
12763
|
}
|
|
12422
12764
|
function makeWorktree(exec, repoPath, branch, path, base, fs, log) {
|
|
12423
|
-
if (fs.exists(
|
|
12765
|
+
if (fs.exists(join15(path, ".git"))) {
|
|
12424
12766
|
fastForwardUntouched(exec, path, base, log);
|
|
12425
12767
|
return path;
|
|
12426
12768
|
}
|
|
@@ -12493,13 +12835,13 @@ function installArgv(command) {
|
|
|
12493
12835
|
return argv;
|
|
12494
12836
|
}
|
|
12495
12837
|
function lockfileInstall(path, exists) {
|
|
12496
|
-
if (exists(
|
|
12838
|
+
if (exists(join15(path, "pnpm-lock.yaml")))
|
|
12497
12839
|
return ["pnpm", "install", "--frozen-lockfile"];
|
|
12498
|
-
if (exists(
|
|
12840
|
+
if (exists(join15(path, "bun.lock")) || exists(join15(path, "bun.lockb")))
|
|
12499
12841
|
return ["bun", "install", "--frozen-lockfile"];
|
|
12500
|
-
if (exists(
|
|
12842
|
+
if (exists(join15(path, "yarn.lock")))
|
|
12501
12843
|
return ["yarn", "install", "--frozen-lockfile"];
|
|
12502
|
-
if (exists(
|
|
12844
|
+
if (exists(join15(path, "package-lock.json")))
|
|
12503
12845
|
return ["npm", "ci"];
|
|
12504
12846
|
return null;
|
|
12505
12847
|
}
|
|
@@ -12524,7 +12866,7 @@ function packInstallOf(pack, repo) {
|
|
|
12524
12866
|
return first;
|
|
12525
12867
|
}
|
|
12526
12868
|
function ensureInstalled(exec, path, fs, o = {}) {
|
|
12527
|
-
if (!fs.exists(
|
|
12869
|
+
if (!fs.exists(join15(path, "package.json")) || fs.exists(join15(path, "node_modules")))
|
|
12528
12870
|
return null;
|
|
12529
12871
|
const argv = installArgv(o.command) ?? lockfileInstall(path, fs.exists);
|
|
12530
12872
|
if (!argv)
|
|
@@ -12539,7 +12881,7 @@ function ensureInstalled(exec, path, fs, o = {}) {
|
|
|
12539
12881
|
return { argv, ok };
|
|
12540
12882
|
}
|
|
12541
12883
|
function ensureDetachedWorktree(exec, repoPath, path, base = "main", fs = realWorktreeFs) {
|
|
12542
|
-
if (fs.exists(
|
|
12884
|
+
if (fs.exists(join15(path, ".git")))
|
|
12543
12885
|
return path;
|
|
12544
12886
|
ensureIgnored(exec, repoPath, fs);
|
|
12545
12887
|
const f = exec("git", ["-C", repoPath, "fetch", "origin", base]);
|
|
@@ -12686,6 +13028,8 @@ async function tick(deps) {
|
|
|
12686
13028
|
deps.startBackoff = d.startBackoff;
|
|
12687
13029
|
deps.providerHold = d.providerHold;
|
|
12688
13030
|
deps.atOnce = d.atOnce;
|
|
13031
|
+
deps.runner = d.runner;
|
|
13032
|
+
deps.runnerRefused = d.runnerRefused;
|
|
12689
13033
|
}
|
|
12690
13034
|
removeEndedMcpConfigs(deps, made);
|
|
12691
13035
|
}
|
|
@@ -12728,6 +13072,7 @@ async function tickOnce(d) {
|
|
|
12728
13072
|
const changes = [];
|
|
12729
13073
|
const decided = [];
|
|
12730
13074
|
const save = () => d.writeState(state);
|
|
13075
|
+
await rereadRunner(d);
|
|
12731
13076
|
probeRunner(d);
|
|
12732
13077
|
if (d.startBackoff && --d.startBackoff.checks <= 0)
|
|
12733
13078
|
d.startBackoff = undefined;
|
|
@@ -13513,6 +13858,29 @@ async function rereadAtOnce(d) {
|
|
|
13513
13858
|
d.atOnce = next;
|
|
13514
13859
|
d.log(`at once now ${next}, from your engine profile`);
|
|
13515
13860
|
}
|
|
13861
|
+
async function rereadRunner(d) {
|
|
13862
|
+
if (!d.rereadRunner)
|
|
13863
|
+
return;
|
|
13864
|
+
let next = null;
|
|
13865
|
+
try {
|
|
13866
|
+
next = await d.rereadRunner(profileOf2(d));
|
|
13867
|
+
} catch {}
|
|
13868
|
+
if (next === null)
|
|
13869
|
+
return;
|
|
13870
|
+
if (typeof next === "string") {
|
|
13871
|
+
if (d.runnerRefused !== next)
|
|
13872
|
+
d.log(next);
|
|
13873
|
+
d.runnerRefused = next;
|
|
13874
|
+
return;
|
|
13875
|
+
}
|
|
13876
|
+
d.runnerRefused = undefined;
|
|
13877
|
+
if (next === d.runner)
|
|
13878
|
+
return;
|
|
13879
|
+
const was = d.runner.name;
|
|
13880
|
+
d.runner = next;
|
|
13881
|
+
d.runnerHold = undefined;
|
|
13882
|
+
d.log(`runner now ${next.name}, from your engine profile — new sessions start on it; running ones stay on ${was}`);
|
|
13883
|
+
}
|
|
13516
13884
|
async function rereadMachine(w, d) {
|
|
13517
13885
|
if (!w.reread)
|
|
13518
13886
|
return;
|
|
@@ -15057,8 +15425,8 @@ function commandRunner(template, deps = {}) {
|
|
|
15057
15425
|
|
|
15058
15426
|
// src/runners/conductor.ts
|
|
15059
15427
|
import { readFileSync as readFileSync11 } from "node:fs";
|
|
15060
|
-
var
|
|
15061
|
-
var
|
|
15428
|
+
var obj2 = (v) => v !== null && typeof v === "object" && !Array.isArray(v) ? v : null;
|
|
15429
|
+
var str9 = (v) => typeof v === "string" && v.length > 0 ? v : null;
|
|
15062
15430
|
var CONDUCTOR_API = "https://api.conductor.build";
|
|
15063
15431
|
var CLAUDE_MODELS = new Set([
|
|
15064
15432
|
"fable-5-1",
|
|
@@ -15115,7 +15483,7 @@ var splitCurl = (stdout) => {
|
|
|
15115
15483
|
const code = Number(stdout.slice(cut + 1).trim()) || 0;
|
|
15116
15484
|
let body = null;
|
|
15117
15485
|
try {
|
|
15118
|
-
body =
|
|
15486
|
+
body = obj2(JSON.parse(text));
|
|
15119
15487
|
} catch {
|
|
15120
15488
|
body = null;
|
|
15121
15489
|
}
|
|
@@ -15130,7 +15498,7 @@ var messageText = (content, depth = 0) => {
|
|
|
15130
15498
|
return content.map((c) => messageText(c, depth + 1)).filter(Boolean).join(`
|
|
15131
15499
|
`);
|
|
15132
15500
|
}
|
|
15133
|
-
const o =
|
|
15501
|
+
const o = obj2(content);
|
|
15134
15502
|
if (!o)
|
|
15135
15503
|
return String(content);
|
|
15136
15504
|
for (const k of ["text", "content", "message", "result"]) {
|
|
@@ -15138,12 +15506,12 @@ var messageText = (content, depth = 0) => {
|
|
|
15138
15506
|
if (t)
|
|
15139
15507
|
return t;
|
|
15140
15508
|
}
|
|
15141
|
-
return
|
|
15509
|
+
return str9(o.type) ? `(${o.type}${str9(o.name) ? ` ${o.name}` : ""})` : "";
|
|
15142
15510
|
};
|
|
15143
15511
|
var renderTranscript = (messages, keep = 40, clip = 2000) => messages.slice(-keep).map((m) => {
|
|
15144
15512
|
const t = messageText(m.content).trim();
|
|
15145
15513
|
const body = t.length > clip ? `${t.slice(0, clip)}…` : t;
|
|
15146
|
-
return body ? `[${
|
|
15514
|
+
return body ? `[${str9(m.type) ?? "message"}] ${body}` : "";
|
|
15147
15515
|
}).filter(Boolean).join(`
|
|
15148
15516
|
|
|
15149
15517
|
`);
|
|
@@ -15173,7 +15541,7 @@ function conductorRunner(exec, deps = {}) {
|
|
|
15173
15541
|
}
|
|
15174
15542
|
const res = splitCurl(r.stdout);
|
|
15175
15543
|
if (res.code < 200 || res.code >= 300 || !res.body) {
|
|
15176
|
-
const why =
|
|
15544
|
+
const why = str9(res.body?.userMessage) ?? str9(res.body?.message) ?? (res.text.trim().slice(0, 300) || "no body");
|
|
15177
15545
|
throw new Error(`conductor ${method} ${path}: HTTP ${res.code}: ${why}`);
|
|
15178
15546
|
}
|
|
15179
15547
|
return res.body;
|
|
@@ -15203,15 +15571,15 @@ function conductorRunner(exec, deps = {}) {
|
|
|
15203
15571
|
...effort ? { effort } : {},
|
|
15204
15572
|
message: prompt
|
|
15205
15573
|
});
|
|
15206
|
-
const workspace =
|
|
15207
|
-
const session =
|
|
15574
|
+
const workspace = str9(created.workspaceId);
|
|
15575
|
+
const session = str9(created.sessionId);
|
|
15208
15576
|
if (!workspace || !session) {
|
|
15209
15577
|
throw new Error(`conductor: workspace create for ${o.name} returned no workspace or session id`);
|
|
15210
15578
|
}
|
|
15211
|
-
if (!
|
|
15579
|
+
if (!obj2(created.initialMessage)) {
|
|
15212
15580
|
api("POST", `/v0/sessions/${session}/messages`, { message: prompt });
|
|
15213
15581
|
}
|
|
15214
|
-
const link =
|
|
15582
|
+
const link = str9(created.deepLink);
|
|
15215
15583
|
return {
|
|
15216
15584
|
runner: "conductor",
|
|
15217
15585
|
id: `${workspace}/${session}`,
|
|
@@ -15233,8 +15601,8 @@ function conductorRunner(exec, deps = {}) {
|
|
|
15233
15601
|
let line = "";
|
|
15234
15602
|
try {
|
|
15235
15603
|
const s = api("GET", `/v0/sessions/${session}/status`);
|
|
15236
|
-
state =
|
|
15237
|
-
const err =
|
|
15604
|
+
state = str9(s.status) ?? "unknown";
|
|
15605
|
+
const err = str9(s.lastError) ?? str9(s.errorMessage);
|
|
15238
15606
|
line = state === "working" ? `conductor session: working (checked ${new Date(now()).toISOString()})` : `conductor session: ${state}${err ? ` — ${err}` : ""}`;
|
|
15239
15607
|
} catch (e) {
|
|
15240
15608
|
line = `conductor session: status unread (${e instanceof Error ? e.message : String(e)})`;
|
|
@@ -15346,8 +15714,8 @@ function headlessRunner(deps = {}) {
|
|
|
15346
15714
|
// src/runners/managed.ts
|
|
15347
15715
|
init_src();
|
|
15348
15716
|
import { readFileSync as readFileSync12 } from "node:fs";
|
|
15349
|
-
var
|
|
15350
|
-
var
|
|
15717
|
+
var obj3 = (v) => v !== null && typeof v === "object" && !Array.isArray(v) ? v : null;
|
|
15718
|
+
var str10 = (v) => typeof v === "string" && v.length > 0 ? v : null;
|
|
15351
15719
|
var ANTHROPIC_API = "https://api.anthropic.com";
|
|
15352
15720
|
var MANAGED_BETA = "managed-agents-2026-04-01";
|
|
15353
15721
|
var DEFAULT_BUDGET_USD = 25;
|
|
@@ -15422,7 +15790,7 @@ var lastIdle = (events) => {
|
|
|
15422
15790
|
return null;
|
|
15423
15791
|
};
|
|
15424
15792
|
var pendingAsks = (events, idle) => {
|
|
15425
|
-
const ids =
|
|
15793
|
+
const ids = obj3(idle?.stop_reason)?.event_ids;
|
|
15426
15794
|
if (!Array.isArray(ids))
|
|
15427
15795
|
return [];
|
|
15428
15796
|
const want = new Set(ids.filter((x) => typeof x === "string"));
|
|
@@ -15443,7 +15811,7 @@ var eventMessages = (events) => {
|
|
|
15443
15811
|
case "agent.custom_tool_use":
|
|
15444
15812
|
out.push({
|
|
15445
15813
|
type: "tool",
|
|
15446
|
-
content: `(${
|
|
15814
|
+
content: `(${str10(e.name) ?? "tool"}${e.evaluated_permission === "ask" ? " — waiting on a yes" : ""})`
|
|
15447
15815
|
});
|
|
15448
15816
|
break;
|
|
15449
15817
|
case "session.error":
|
|
@@ -15454,9 +15822,9 @@ var eventMessages = (events) => {
|
|
|
15454
15822
|
return out;
|
|
15455
15823
|
};
|
|
15456
15824
|
var statusLine2 = (session, events, now) => {
|
|
15457
|
-
const status =
|
|
15458
|
-
const spent = usd4(
|
|
15459
|
-
const cap = usd4(
|
|
15825
|
+
const status = str10(session.status) ?? "unknown";
|
|
15826
|
+
const spent = usd4(obj3(obj3(session.usage)?.list_cost)?.amount);
|
|
15827
|
+
const cap = usd4(obj3(obj3(session.budget)?.max_list_cost)?.amount);
|
|
15460
15828
|
const money = spent ? ` · ${spent}${cap ? ` of ${cap}` : ""}` : "";
|
|
15461
15829
|
if (status === "running" || status === "rescheduling") {
|
|
15462
15830
|
return `managed session: ${status} (checked ${new Date(now).toISOString()})${money}`;
|
|
@@ -15464,10 +15832,10 @@ var statusLine2 = (session, events, now) => {
|
|
|
15464
15832
|
if (status !== "idle")
|
|
15465
15833
|
return `managed session: ${status}${money}`;
|
|
15466
15834
|
const idle = lastIdle(events);
|
|
15467
|
-
const why =
|
|
15835
|
+
const why = str10(obj3(idle?.stop_reason)?.type);
|
|
15468
15836
|
switch (why) {
|
|
15469
15837
|
case "requires_action": {
|
|
15470
|
-
const tools = pendingAsks(events, idle).map((e) =>
|
|
15838
|
+
const tools = pendingAsks(events, idle).map((e) => str10(e.name) ?? "a tool").join(", ");
|
|
15471
15839
|
return `managed session: idle — waiting on a yes for ${tools || "a tool call"} (answer yes to allow, anything else denies)${money}`;
|
|
15472
15840
|
}
|
|
15473
15841
|
case "budget_reached":
|
|
@@ -15501,7 +15869,7 @@ function managedRunner(exec, deps = {}) {
|
|
|
15501
15869
|
}
|
|
15502
15870
|
const res = splitCurl(r.stdout);
|
|
15503
15871
|
if (res.code < 200 || res.code >= 300 || !res.body) {
|
|
15504
|
-
const why =
|
|
15872
|
+
const why = str10(obj3(res.body?.error)?.message) ?? str10(res.body?.message) ?? (res.text.trim().slice(0, 300) || "no body");
|
|
15505
15873
|
throw new Error(`managed ${method} ${path}: HTTP ${res.code}: ${why}`);
|
|
15506
15874
|
}
|
|
15507
15875
|
return res.body;
|
|
@@ -15513,7 +15881,7 @@ function managedRunner(exec, deps = {}) {
|
|
|
15513
15881
|
const got = api("GET", `/v1/sessions/${id}/events?limit=1000${page ? `&page=${encodeURIComponent(page)}` : ""}`);
|
|
15514
15882
|
const data = Array.isArray(got.data) ? got.data : [];
|
|
15515
15883
|
out.push(...data);
|
|
15516
|
-
page =
|
|
15884
|
+
page = str10(got.next_page);
|
|
15517
15885
|
if (!page || data.length === 0)
|
|
15518
15886
|
break;
|
|
15519
15887
|
}
|
|
@@ -15576,7 +15944,7 @@ function managedRunner(exec, deps = {}) {
|
|
|
15576
15944
|
}
|
|
15577
15945
|
]
|
|
15578
15946
|
});
|
|
15579
|
-
const id =
|
|
15947
|
+
const id = str10(created.id);
|
|
15580
15948
|
if (!id)
|
|
15581
15949
|
throw new Error(`managed: session create for ${o.name} returned no id`);
|
|
15582
15950
|
return { runner: "managed", id, cwd: o.repoPath, log: consoleUrl(id) };
|
|
@@ -15601,7 +15969,7 @@ ${renderTranscript(eventMessages(all))}`;
|
|
|
15601
15969
|
const session = api("GET", `/v1/sessions/${h.id}`);
|
|
15602
15970
|
const all = session.status === "idle" ? events(h.id) : [];
|
|
15603
15971
|
const idle = lastIdle(all);
|
|
15604
|
-
const asks =
|
|
15972
|
+
const asks = str10(obj3(idle?.stop_reason)?.type) === "requires_action" ? pendingAsks(all, idle) : [];
|
|
15605
15973
|
if (asks.length) {
|
|
15606
15974
|
const allow = YES2.test(text);
|
|
15607
15975
|
api("POST", `/v1/sessions/${h.id}/events`, {
|
|
@@ -15650,156 +16018,6 @@ ${renderTranscript(eventMessages(all))}`;
|
|
|
15650
16018
|
};
|
|
15651
16019
|
}
|
|
15652
16020
|
|
|
15653
|
-
// src/runners/orca.ts
|
|
15654
|
-
import { writeFileSync as writeFileSync12 } from "node:fs";
|
|
15655
|
-
var obj3 = (v) => v !== null && typeof v === "object" && !Array.isArray(v) ? v : null;
|
|
15656
|
-
var str10 = (v) => typeof v === "string" && v.length > 0 ? v : null;
|
|
15657
|
-
var parseOrcaJson = (stdout) => {
|
|
15658
|
-
try {
|
|
15659
|
-
return obj3(JSON.parse(stdout));
|
|
15660
|
-
} catch {
|
|
15661
|
-
return null;
|
|
15662
|
-
}
|
|
15663
|
-
};
|
|
15664
|
-
var orcaError = (env) => {
|
|
15665
|
-
if (!env || env.ok !== false)
|
|
15666
|
-
return null;
|
|
15667
|
-
const e = obj3(env.error);
|
|
15668
|
-
const message = str10(e?.message) ?? "Orca refused the call";
|
|
15669
|
-
const code = str10(e?.code);
|
|
15670
|
-
return code ? `${message} (${code})` : message;
|
|
15671
|
-
};
|
|
15672
|
-
var parseOrcaWorktree = (env) => {
|
|
15673
|
-
const result = obj3(env.result) ?? {};
|
|
15674
|
-
return str10(obj3(result.worktree)?.path) ?? str10(result.worktreePath) ?? str10(result.path);
|
|
15675
|
-
};
|
|
15676
|
-
var parseOrcaBranch = (env) => {
|
|
15677
|
-
const wt = obj3(obj3(env.result)?.worktree);
|
|
15678
|
-
const branch = str10(wt?.branch)?.replace(/^refs\/heads\//, "");
|
|
15679
|
-
const head = str10(wt?.head);
|
|
15680
|
-
return branch && head ? { branch, head } : null;
|
|
15681
|
-
};
|
|
15682
|
-
var parseOrcaTerminal = (env) => {
|
|
15683
|
-
const result = obj3(env.result) ?? {};
|
|
15684
|
-
return str10(obj3(result.terminal)?.handle) ?? str10(result.handle) ?? str10(result.terminalHandle) ?? null;
|
|
15685
|
-
};
|
|
15686
|
-
var orcaLauncher = (o) => `#!/bin/sh
|
|
15687
|
-
# sleds engine: ${o.name}
|
|
15688
|
-
exec ${agentShellCommand(o)}
|
|
15689
|
-
`;
|
|
15690
|
-
var orcaCommand = (launcher) => `sh ${shq2(launcher)}; exit`;
|
|
15691
|
-
var GONE = /exit|clos|gone|dead|stopp|kill/i;
|
|
15692
|
-
var orcaTerminalLive = (status, stdout) => {
|
|
15693
|
-
const env = parseOrcaJson(stdout);
|
|
15694
|
-
if (str10(obj3(env?.error)?.code) === "runtime_unavailable")
|
|
15695
|
-
return true;
|
|
15696
|
-
if (status !== 0 || !env || env.ok === false)
|
|
15697
|
-
return false;
|
|
15698
|
-
const t = obj3(obj3(env.result)?.terminal) ?? obj3(env.result) ?? {};
|
|
15699
|
-
if (typeof t.status === "string" && GONE.test(t.status))
|
|
15700
|
-
return false;
|
|
15701
|
-
if (t.exited === true || t.alive === false)
|
|
15702
|
-
return false;
|
|
15703
|
-
if (typeof t.exitCode === "number")
|
|
15704
|
-
return false;
|
|
15705
|
-
if (obj3(t.exitCause))
|
|
15706
|
-
return false;
|
|
15707
|
-
if (t.orphaned === true && t.writable === false)
|
|
15708
|
-
return false;
|
|
15709
|
-
return true;
|
|
15710
|
-
};
|
|
15711
|
-
var launcherPath2 = (promptFile) => `${promptFile.replace(/\.md$/, "")}.orca.sh`;
|
|
15712
|
-
function orcaRunner(exec, deps = {}) {
|
|
15713
|
-
const writeFile = deps.writeFile ?? ((p, t) => writeFileSync12(p, t, { mode: 384 }));
|
|
15714
|
-
const orca = (args, what) => {
|
|
15715
|
-
const r = exec("orca", args);
|
|
15716
|
-
const env = parseOrcaJson(r.stdout);
|
|
15717
|
-
const refused = orcaError(env);
|
|
15718
|
-
if (refused)
|
|
15719
|
-
throw new Error(`${what}: ${refused}`);
|
|
15720
|
-
if (r.status !== 0 || !env) {
|
|
15721
|
-
throw new Error(`${what} failed: ${r.stderr.trim() || r.stdout.trim() || `exit ${r.status}`}`);
|
|
15722
|
-
}
|
|
15723
|
-
return env;
|
|
15724
|
-
};
|
|
15725
|
-
return {
|
|
15726
|
-
name: "orca",
|
|
15727
|
-
makesWorktree: true,
|
|
15728
|
-
readsSession: true,
|
|
15729
|
-
start(o) {
|
|
15730
|
-
const created = orca([
|
|
15731
|
-
"worktree",
|
|
15732
|
-
"create",
|
|
15733
|
-
"--repo",
|
|
15734
|
-
`path:${o.repoPath}`,
|
|
15735
|
-
"--name",
|
|
15736
|
-
o.name,
|
|
15737
|
-
"--base-branch",
|
|
15738
|
-
`origin/${o.base ?? "main"}`,
|
|
15739
|
-
"--no-parent",
|
|
15740
|
-
"--json"
|
|
15741
|
-
], `orca worktree create ${o.name}`);
|
|
15742
|
-
const cwd = parseOrcaWorktree(created);
|
|
15743
|
-
if (!cwd) {
|
|
15744
|
-
throw new Error(`orca worktree create ${o.name} returned no worktree path; the agent was not started`);
|
|
15745
|
-
}
|
|
15746
|
-
const launcher = launcherPath2(o.promptFile);
|
|
15747
|
-
writeFile(launcher, orcaLauncher(o));
|
|
15748
|
-
const shown = orca([
|
|
15749
|
-
"terminal",
|
|
15750
|
-
"create",
|
|
15751
|
-
"--worktree",
|
|
15752
|
-
`path:${cwd}`,
|
|
15753
|
-
"--title",
|
|
15754
|
-
o.name,
|
|
15755
|
-
"--command",
|
|
15756
|
-
orcaCommand(launcher),
|
|
15757
|
-
"--json"
|
|
15758
|
-
], `orca terminal create ${o.name} (worktree ${cwd})`);
|
|
15759
|
-
const terminal = parseOrcaTerminal(shown);
|
|
15760
|
-
if (!terminal) {
|
|
15761
|
-
throw new Error(`orca terminal create ${o.name} started in ${cwd} but returned no terminal handle`);
|
|
15762
|
-
}
|
|
15763
|
-
const own = parseOrcaBranch(created);
|
|
15764
|
-
const h = { runner: "orca", id: terminal, cwd, ...own ? { own } : {} };
|
|
15765
|
-
return h;
|
|
15766
|
-
},
|
|
15767
|
-
status(h) {
|
|
15768
|
-
const r = exec("orca", ["terminal", "show", "--terminal", h.id, "--json"]);
|
|
15769
|
-
return orcaTerminalLive(r.status, r.stdout) ? "running" : "exited";
|
|
15770
|
-
},
|
|
15771
|
-
read(h) {
|
|
15772
|
-
const r = exec("orca", ["terminal", "read", "--terminal", h.id, "--limit", "200"]);
|
|
15773
|
-
return r.status === 0 ? r.stdout : "";
|
|
15774
|
-
},
|
|
15775
|
-
send(h, text) {
|
|
15776
|
-
const r = exec("orca", ["terminal", "send", "--terminal", h.id, "--text", text, "--enter"]);
|
|
15777
|
-
if (r.status !== 0) {
|
|
15778
|
-
throw new Error(`orca terminal send ${h.id} failed: ${r.stderr.trim() || `exit ${r.status}`}`);
|
|
15779
|
-
}
|
|
15780
|
-
},
|
|
15781
|
-
stop(h) {
|
|
15782
|
-
exec("orca", ["terminal", "close", "--terminal", h.id]);
|
|
15783
|
-
},
|
|
15784
|
-
watchHint(h) {
|
|
15785
|
-
return `orca terminal show --terminal ${h.id}`;
|
|
15786
|
-
},
|
|
15787
|
-
removeWorktree(h, repoPath) {
|
|
15788
|
-
orca(["worktree", "rm", "--worktree", `path:${h.cwd}`, "--json"], `orca worktree rm ${h.cwd}`);
|
|
15789
|
-
if (!h.own)
|
|
15790
|
-
return;
|
|
15791
|
-
const ref = `refs/heads/${h.own.branch}`;
|
|
15792
|
-
const r = exec("git", ["-C", repoPath, "update-ref", "-d", ref, h.own.head]);
|
|
15793
|
-
if (r.status === 0)
|
|
15794
|
-
return;
|
|
15795
|
-
const still = exec("git", ["-C", repoPath, "rev-parse", "--verify", "--quiet", ref]);
|
|
15796
|
-
if (still.status !== 0)
|
|
15797
|
-
return;
|
|
15798
|
-
return `kept Orca's branch ${h.own.branch}: ${r.stderr.trim() || `exit ${r.status}`}`;
|
|
15799
|
-
}
|
|
15800
|
-
};
|
|
15801
|
-
}
|
|
15802
|
-
|
|
15803
16021
|
// src/runners/tmux.ts
|
|
15804
16022
|
var tmuxSession = (name) => `=${name}`;
|
|
15805
16023
|
var tmuxPane = (name) => `=${name}:`;
|
|
@@ -16160,7 +16378,7 @@ function flagsFromProfile(flags, given, profile, home) {
|
|
|
16160
16378
|
}
|
|
16161
16379
|
}
|
|
16162
16380
|
if (profile.reposDir && !has("repos-dir") && !has("repo")) {
|
|
16163
|
-
out.reposDir = splitReposDirs(profile.reposDir).map((d) => home && /^~(\/|$)/.test(d) ?
|
|
16381
|
+
out.reposDir = splitReposDirs(profile.reposDir).map((d) => home && /^~(\/|$)/.test(d) ? join16(home, d.slice(1)) : d).join(":");
|
|
16164
16382
|
used.push(`repos ${profile.reposDir}`);
|
|
16165
16383
|
}
|
|
16166
16384
|
if (profile.mcpStrict !== undefined && !has("strict-mcp") && !has("no-strict-mcp")) {
|
|
@@ -16290,12 +16508,12 @@ function memberMcpConfigs(o, cwd) {
|
|
|
16290
16508
|
});
|
|
16291
16509
|
const claudeDir = (o.env ?? process.env).CLAUDE_CONFIG_DIR;
|
|
16292
16510
|
return [
|
|
16293
|
-
read(claudeDir ?
|
|
16294
|
-
...cwd ? [read(
|
|
16511
|
+
read(claudeDir ? join16(claudeDir, ".claude.json") : join16(o.home, ".claude.json")),
|
|
16512
|
+
...cwd ? [read(join16(cwd, ".mcp.json"))] : []
|
|
16295
16513
|
];
|
|
16296
16514
|
}
|
|
16297
16515
|
function engineStateDir(o, org, seat) {
|
|
16298
|
-
return seatStateDir(orgStateDir(o.stateDir ??
|
|
16516
|
+
return seatStateDir(orgStateDir(o.stateDir ?? join16(configDir(o.home, o.env ?? process.env), "engine"), org), seat);
|
|
16299
16517
|
}
|
|
16300
16518
|
function engineSeat(o, org) {
|
|
16301
16519
|
try {
|
|
@@ -16322,11 +16540,11 @@ function engineDeps(o, flags, source, runner, stateName) {
|
|
|
16322
16540
|
const stateDir = engineStateDir(o, flags.org, flags.seat);
|
|
16323
16541
|
const file = statePath(stateDir, stateName);
|
|
16324
16542
|
const mcpOrg = flags.org && engineOrg(o, flags.org).seated ? flags.org : undefined;
|
|
16325
|
-
const repo = flags.repo ?
|
|
16326
|
-
const reposDirs = splitReposDirs(flags.reposDir).map((d) =>
|
|
16543
|
+
const repo = flags.repo ? resolve8(cwd, flags.repo) : undefined;
|
|
16544
|
+
const reposDirs = splitReposDirs(flags.reposDir).map((d) => resolve8(cwd, d));
|
|
16327
16545
|
const { branch, prTitle } = flags;
|
|
16328
|
-
const hooksDir =
|
|
16329
|
-
const permissionMark = (name) =>
|
|
16546
|
+
const hooksDir = join16(stateDir, "hooks");
|
|
16547
|
+
const permissionMark = (name) => join16(hooksDir, `${name}.permission.json`);
|
|
16330
16548
|
const withHook = (name, settings) => applyPermissionHook(settings, [...o.sledsArgv ?? ["sleds"], "permission-event", "--mark", permissionMark(name)].map(shq2).join(" "));
|
|
16331
16549
|
return {
|
|
16332
16550
|
source,
|
|
@@ -16351,9 +16569,9 @@ function engineDeps(o, flags, source, runner, stateName) {
|
|
|
16351
16569
|
sandbox: true,
|
|
16352
16570
|
writeSandboxSettings: o.writeSandboxSettings ?? ((name, cwd) => {
|
|
16353
16571
|
const gitCommonDir = gitCommonDirOf(exec, cwd);
|
|
16354
|
-
const dir =
|
|
16572
|
+
const dir = join16(stateDir, "sandbox");
|
|
16355
16573
|
mkdirSync12(dir, { recursive: true, mode: 448 });
|
|
16356
|
-
const p =
|
|
16574
|
+
const p = join16(dir, `${name}.json`);
|
|
16357
16575
|
const walls = engineSandboxSettings(o.home, o.env ?? process.env, gitCommonDir, [
|
|
16358
16576
|
...SANDBOX_DEFAULT_ALLOW,
|
|
16359
16577
|
...flags.sandboxAllow ?? []
|
|
@@ -16367,7 +16585,7 @@ function engineDeps(o, flags, source, runner, stateName) {
|
|
|
16367
16585
|
} : {},
|
|
16368
16586
|
writeHookSettings: (name) => {
|
|
16369
16587
|
mkdirSync12(hooksDir, { recursive: true, mode: 448 });
|
|
16370
|
-
const p =
|
|
16588
|
+
const p = join16(hooksDir, `${name}.json`);
|
|
16371
16589
|
writeFileSync13(p, `${JSON.stringify(withHook(name, {}), null, 2)}
|
|
16372
16590
|
`, { mode: 384 });
|
|
16373
16591
|
chmodSync4(p, 384);
|
|
@@ -16394,9 +16612,9 @@ function engineDeps(o, flags, source, runner, stateName) {
|
|
|
16394
16612
|
exists
|
|
16395
16613
|
}),
|
|
16396
16614
|
writeMcpConfig: o.writeMcpConfig ?? ((name, runToken, worktree) => {
|
|
16397
|
-
const dir =
|
|
16615
|
+
const dir = join16(stateDir, "mcp");
|
|
16398
16616
|
mkdirSync12(dir, { recursive: true, mode: 448 });
|
|
16399
|
-
const p =
|
|
16617
|
+
const p = join16(dir, `${name}.json`);
|
|
16400
16618
|
let others = {};
|
|
16401
16619
|
if (flags.strictMcp && flags.mcpAllow?.length) {
|
|
16402
16620
|
const r = mcpPassThrough(flags.mcpAllow, memberMcpConfigs(o, worktree));
|
|
@@ -16412,9 +16630,9 @@ function engineDeps(o, flags, source, runner, stateName) {
|
|
|
16412
16630
|
}),
|
|
16413
16631
|
removeMcpConfig: o.removeMcpConfig ?? ((p) => rmSync4(p, { force: true })),
|
|
16414
16632
|
writePrompt: o.writePrompt ?? ((name, text) => {
|
|
16415
|
-
const dir =
|
|
16633
|
+
const dir = join16(stateDir, "prompts");
|
|
16416
16634
|
mkdirSync12(dir, { recursive: true, mode: 448 });
|
|
16417
|
-
const p =
|
|
16635
|
+
const p = join16(dir, `${name}.md`);
|
|
16418
16636
|
writeFileSync13(p, text, { mode: 384 });
|
|
16419
16637
|
return p;
|
|
16420
16638
|
}),
|
|
@@ -16441,8 +16659,8 @@ function engineDeps(o, flags, source, runner, stateName) {
|
|
|
16441
16659
|
}
|
|
16442
16660
|
function sandboxDenyRead(home, env) {
|
|
16443
16661
|
return {
|
|
16444
|
-
dirs: [...new Set([configDir(home, env),
|
|
16445
|
-
files: [...new Set([tokenPath(home, env),
|
|
16662
|
+
dirs: [...new Set([configDir(home, env), join16(home, ".config", "sleds")])],
|
|
16663
|
+
files: [...new Set([tokenPath(home, env), join16(home, ".sleds-token")])]
|
|
16446
16664
|
};
|
|
16447
16665
|
}
|
|
16448
16666
|
function engineSandboxSettings(home, env, gitCommonDir, allow) {
|
|
@@ -16457,7 +16675,7 @@ function gitCommonDirOf(exec, cwd) {
|
|
|
16457
16675
|
const dir = r.status === 0 ? r.stdout.trim() : "";
|
|
16458
16676
|
if (!dir)
|
|
16459
16677
|
throw new Error(`git has no common dir for ${cwd}, so the sandbox has nowhere to commit`);
|
|
16460
|
-
return
|
|
16678
|
+
return resolve8(cwd, dir);
|
|
16461
16679
|
}
|
|
16462
16680
|
function pinOrg2(configJson, org) {
|
|
16463
16681
|
if (!org)
|
|
@@ -16499,13 +16717,14 @@ async function driveEngine(o, flags, deps, until = {}) {
|
|
|
16499
16717
|
runner: deps.runner.name,
|
|
16500
16718
|
atOnce: flags.atOnce,
|
|
16501
16719
|
interval: flags.interval,
|
|
16502
|
-
cliVersion: "0.1.
|
|
16720
|
+
cliVersion: "0.1.44"
|
|
16503
16721
|
};
|
|
16504
16722
|
const beat = (checkedAt) => {
|
|
16505
16723
|
const m = deps.machine;
|
|
16506
16724
|
try {
|
|
16507
16725
|
writeLock(lockFile, checkedAt === undefined ? lock : {
|
|
16508
16726
|
...lock,
|
|
16727
|
+
runner: deps.runner.name,
|
|
16509
16728
|
atOnce: deps.atOnce,
|
|
16510
16729
|
checkedAt,
|
|
16511
16730
|
nextCheckAt: checkedAt + flags.interval * 1000,
|
|
@@ -16811,7 +17030,7 @@ async function enginePauseCmd(o) {
|
|
|
16811
17030
|
// src/commands/engineInstall.ts
|
|
16812
17031
|
init_config();
|
|
16813
17032
|
import {
|
|
16814
|
-
existsSync as
|
|
17033
|
+
existsSync as existsSync15,
|
|
16815
17034
|
mkdirSync as mkdirSync14,
|
|
16816
17035
|
readFileSync as readFileSync14,
|
|
16817
17036
|
readdirSync as readdirSync2,
|
|
@@ -16820,13 +17039,13 @@ import {
|
|
|
16820
17039
|
writeFileSync as writeFileSync15
|
|
16821
17040
|
} from "node:fs";
|
|
16822
17041
|
import { hostname as hostname3 } from "node:os";
|
|
16823
|
-
import { basename as basename4, dirname as dirname12, isAbsolute as isAbsolute2, join as
|
|
17042
|
+
import { basename as basename4, dirname as dirname12, isAbsolute as isAbsolute2, join as join19 } from "node:path";
|
|
16824
17043
|
init_state();
|
|
16825
17044
|
|
|
16826
17045
|
// src/schedule.ts
|
|
16827
17046
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
16828
|
-
import { existsSync as
|
|
16829
|
-
import { join as
|
|
17047
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync13, rmSync as rmSync5, writeFileSync as writeFileSync14 } from "node:fs";
|
|
17048
|
+
import { join as join17 } from "node:path";
|
|
16830
17049
|
var REVERT_LABEL = "ai.sleds.revert";
|
|
16831
17050
|
var defaultExec2 = (cmd, args) => {
|
|
16832
17051
|
const r = spawnSync4(cmd, [...args], { stdio: ["ignore", "ignore", "pipe"], encoding: "utf8" });
|
|
@@ -16834,7 +17053,7 @@ var defaultExec2 = (cmd, args) => {
|
|
|
16834
17053
|
return { ok: false, stderr: r.error.message };
|
|
16835
17054
|
return { ok: r.status === 0, stderr: r.stderr ?? "" };
|
|
16836
17055
|
};
|
|
16837
|
-
var plistPath = (home) =>
|
|
17056
|
+
var plistPath = (home) => join17(home, "Library", "LaunchAgents", `${REVERT_LABEL}.plist`);
|
|
16838
17057
|
var xmlEscape2 = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
16839
17058
|
var buildLaunchdPlist = (sledsArgv, deadline) => {
|
|
16840
17059
|
const args = [...sledsArgv, "off"].map((a) => ` <string>${xmlEscape2(a)}</string>`).join(`
|
|
@@ -16873,7 +17092,7 @@ var scheduleRevert = (d, deadlineMs) => {
|
|
|
16873
17092
|
if (d.platform === "darwin") {
|
|
16874
17093
|
const p = plistPath(d.home);
|
|
16875
17094
|
try {
|
|
16876
|
-
mkdirSync13(
|
|
17095
|
+
mkdirSync13(join17(d.home, "Library", "LaunchAgents"), { recursive: true });
|
|
16877
17096
|
d.exec("launchctl", ["unload", p]);
|
|
16878
17097
|
writeFileSync14(p, buildLaunchdPlist(d.sledsArgv, deadline));
|
|
16879
17098
|
const r = d.exec("launchctl", ["load", p]);
|
|
@@ -16902,7 +17121,7 @@ var scheduleRevert = (d, deadlineMs) => {
|
|
|
16902
17121
|
var cancelRevert = (d, kind) => {
|
|
16903
17122
|
if (kind === "launchd" || d.platform === "darwin") {
|
|
16904
17123
|
const p = plistPath(d.home);
|
|
16905
|
-
if (
|
|
17124
|
+
if (existsSync14(p)) {
|
|
16906
17125
|
d.exec("launchctl", ["unload", p]);
|
|
16907
17126
|
rmSync5(p, { force: true });
|
|
16908
17127
|
}
|
|
@@ -16913,16 +17132,16 @@ var cancelRevert = (d, kind) => {
|
|
|
16913
17132
|
};
|
|
16914
17133
|
|
|
16915
17134
|
// src/commands/engineSystemd.ts
|
|
16916
|
-
import { join as
|
|
17135
|
+
import { join as join18 } from "node:path";
|
|
16917
17136
|
var BOX_ENV_UNIT_PATH = "%h/.config/sleds/box.env";
|
|
16918
17137
|
function boxEnvPath(home) {
|
|
16919
|
-
return
|
|
17138
|
+
return join18(home, ".config", "sleds", "box.env");
|
|
16920
17139
|
}
|
|
16921
17140
|
function engineUnitDir(home) {
|
|
16922
|
-
return
|
|
17141
|
+
return join18(home, ".config", "systemd", "user");
|
|
16923
17142
|
}
|
|
16924
17143
|
function engineUnitPath(home, label) {
|
|
16925
|
-
return
|
|
17144
|
+
return join18(engineUnitDir(home), `${label}.service`);
|
|
16926
17145
|
}
|
|
16927
17146
|
function systemdQuote(s) {
|
|
16928
17147
|
const body = s.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/\n/g, "\\n").replace(/%/g, "%%").replace(/\$/g, "$$$$");
|
|
@@ -16980,13 +17199,13 @@ function engineLabel(name, org, seat) {
|
|
|
16980
17199
|
return [ENGINE_LABEL, org, seat?.trim(), name].filter((p) => Boolean(p)).map((p, i) => i === 0 ? p : engineSlug(p)).join(".");
|
|
16981
17200
|
}
|
|
16982
17201
|
function enginePlistPath(home, name, org, seat) {
|
|
16983
|
-
return
|
|
17202
|
+
return join19(home, "Library", "LaunchAgents", `${engineLabel(name, org, seat)}.plist`);
|
|
16984
17203
|
}
|
|
16985
17204
|
function engineLogPath(stateDir, name) {
|
|
16986
|
-
return
|
|
17205
|
+
return join19(stateDir, `${engineSlug(name)}.log`);
|
|
16987
17206
|
}
|
|
16988
17207
|
function engineEventsPath(stateDir, name) {
|
|
16989
|
-
return
|
|
17208
|
+
return join19(stateDir, `${engineSlug(name)}.events.jsonl`);
|
|
16990
17209
|
}
|
|
16991
17210
|
var xmlEscape3 = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
16992
17211
|
function buildEnginePlist(o) {
|
|
@@ -17062,7 +17281,13 @@ function parseEnginePlist(text) {
|
|
|
17062
17281
|
if (!label || array === undefined)
|
|
17063
17282
|
return null;
|
|
17064
17283
|
const programArgs = [...array.matchAll(/<string>([^<]*)<\/string>/g)].map((m) => xmlUnescape(m[1] ?? ""));
|
|
17065
|
-
|
|
17284
|
+
const envDict = /<key>EnvironmentVariables<\/key>\s*<dict>([\s\S]*?)<\/dict>/.exec(text)?.[1];
|
|
17285
|
+
const path = envDict && /<key>PATH<\/key>\s*<string>([^<]*)<\/string>/.exec(envDict)?.[1];
|
|
17286
|
+
return {
|
|
17287
|
+
label: xmlUnescape(label),
|
|
17288
|
+
programArgs,
|
|
17289
|
+
...typeof path === "string" ? { path: xmlUnescape(path) } : {}
|
|
17290
|
+
};
|
|
17066
17291
|
}
|
|
17067
17292
|
function engineArg(programArgs, flag) {
|
|
17068
17293
|
const at = programArgs.indexOf(`--${flag}`);
|
|
@@ -17077,7 +17302,7 @@ function readEngines(dir, suffix, manager, parse) {
|
|
|
17077
17302
|
}
|
|
17078
17303
|
const out = [];
|
|
17079
17304
|
for (const name of names.filter((n) => n.startsWith(`${ENGINE_LABEL}.`) && n.endsWith(suffix))) {
|
|
17080
|
-
const path =
|
|
17305
|
+
const path = join19(dir, name);
|
|
17081
17306
|
let parsed;
|
|
17082
17307
|
try {
|
|
17083
17308
|
parsed = parse(readFileSync14(path, "utf8"), name);
|
|
@@ -17097,7 +17322,7 @@ function readEngines(dir, suffix, manager, parse) {
|
|
|
17097
17322
|
}
|
|
17098
17323
|
function installedEngines(home) {
|
|
17099
17324
|
return [
|
|
17100
|
-
...readEngines(
|
|
17325
|
+
...readEngines(join19(home, "Library", "LaunchAgents"), ".plist", "launchd", parseEnginePlist),
|
|
17101
17326
|
...readEngines(engineUnitDir(home), ".service", "systemd", (text, file) => {
|
|
17102
17327
|
const parsed = parseEngineUnit(text);
|
|
17103
17328
|
return parsed && { label: basename4(file, ".service"), ...parsed };
|
|
@@ -17148,7 +17373,7 @@ function engineInstall(o) {
|
|
|
17148
17373
|
return installUnit({ o, parsed, label, sledsArgv, env: agentEnv, logPath, exec });
|
|
17149
17374
|
const plist = enginePlistPath(o.home, parsed.name, parsed.org, seat);
|
|
17150
17375
|
mkdirSync14(dirname12(plist), { recursive: true });
|
|
17151
|
-
if (
|
|
17376
|
+
if (existsSync15(plist))
|
|
17152
17377
|
exec("launchctl", ["unload", plist]);
|
|
17153
17378
|
for (const other of installedEngines(o.home)) {
|
|
17154
17379
|
if (other.manager !== "launchd" || other.plist === plist || other.org !== parsed.org)
|
|
@@ -17160,7 +17385,7 @@ function engineInstall(o) {
|
|
|
17160
17385
|
log(`replaced ${other.label}, this engine as installed before`);
|
|
17161
17386
|
}
|
|
17162
17387
|
const legacy = enginePlistPath(o.home, parsed.name);
|
|
17163
|
-
if (parsed.org &&
|
|
17388
|
+
if (parsed.org && existsSync15(legacy)) {
|
|
17164
17389
|
const cfg = readConfig(o.home);
|
|
17165
17390
|
if (org.sole || parsed.org === (cfg.activeOrg ?? cfg.org?.slug)) {
|
|
17166
17391
|
exec("launchctl", ["unload", legacy]);
|
|
@@ -17190,7 +17415,7 @@ function installUnit(a) {
|
|
|
17190
17415
|
const unitName = basename4(unit);
|
|
17191
17416
|
const systemctl = (...args) => exec("systemctl", ["--user", ...args]);
|
|
17192
17417
|
mkdirSync14(dirname12(unit), { recursive: true });
|
|
17193
|
-
if (
|
|
17418
|
+
if (existsSync15(unit))
|
|
17194
17419
|
systemctl("stop", unitName);
|
|
17195
17420
|
for (const other of installedEngines(o.home)) {
|
|
17196
17421
|
if (other.manager !== "systemd" || other.plist === unit || other.org !== parsed.org)
|
|
@@ -17248,7 +17473,7 @@ function engineUninstall(o) {
|
|
|
17248
17473
|
...installed.filter((e) => e.manager === manager).map((e) => e.plist),
|
|
17249
17474
|
...args.org ? [] : [pathOf(manager)]
|
|
17250
17475
|
]);
|
|
17251
|
-
const file = candidates.find((p) =>
|
|
17476
|
+
const file = candidates.find((p) => existsSync15(p));
|
|
17252
17477
|
if (!file) {
|
|
17253
17478
|
log(`engine:${name} was not installed (no ${candidates[0]}).`);
|
|
17254
17479
|
return 0;
|
|
@@ -17267,20 +17492,20 @@ function engineUninstall(o) {
|
|
|
17267
17492
|
}
|
|
17268
17493
|
|
|
17269
17494
|
// src/commands/musher.ts
|
|
17270
|
-
import { existsSync as
|
|
17495
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync15, readFileSync as readFileSync15, rmSync as rmSync7, writeFileSync as writeFileSync16 } from "node:fs";
|
|
17271
17496
|
init_config();
|
|
17272
17497
|
init_meter();
|
|
17273
17498
|
var defaultWhich = (cmd) => {
|
|
17274
17499
|
const path = process.env.PATH ?? "";
|
|
17275
17500
|
for (const dir of path.split(":").filter(Boolean)) {
|
|
17276
17501
|
const p = `${dir}/${cmd}`;
|
|
17277
|
-
if (
|
|
17502
|
+
if (existsSync16(p))
|
|
17278
17503
|
return p;
|
|
17279
17504
|
}
|
|
17280
17505
|
return null;
|
|
17281
17506
|
};
|
|
17282
17507
|
var findClaude = (home, configured, which) => {
|
|
17283
|
-
if (configured &&
|
|
17508
|
+
if (configured && existsSync16(configured))
|
|
17284
17509
|
return configured;
|
|
17285
17510
|
const found = which("claude");
|
|
17286
17511
|
if (found)
|
|
@@ -17291,13 +17516,13 @@ var findClaude = (home, configured, which) => {
|
|
|
17291
17516
|
"/usr/local/bin/claude",
|
|
17292
17517
|
`${home}/.npm-global/bin/claude`
|
|
17293
17518
|
])
|
|
17294
|
-
if (
|
|
17519
|
+
if (existsSync16(p))
|
|
17295
17520
|
return p;
|
|
17296
17521
|
return null;
|
|
17297
17522
|
};
|
|
17298
17523
|
var musherAgentState = (home, env = process.env) => {
|
|
17299
17524
|
const plist = musherPlistPath(home, env);
|
|
17300
|
-
if (!
|
|
17525
|
+
if (!existsSync16(plist))
|
|
17301
17526
|
return { installed: false, thisSeat: false };
|
|
17302
17527
|
try {
|
|
17303
17528
|
const text = readFileSync15(plist, "utf8");
|
|
@@ -17413,7 +17638,7 @@ async function runDoctor(o) {
|
|
|
17413
17638
|
].filter(Boolean);
|
|
17414
17639
|
const cfgDir = configDir(home, env);
|
|
17415
17640
|
const cfg = readConfig(home);
|
|
17416
|
-
const cfgExists =
|
|
17641
|
+
const cfgExists = existsSync17(configPath(home));
|
|
17417
17642
|
if (!cfgExists) {
|
|
17418
17643
|
checks.push({
|
|
17419
17644
|
level: "fail",
|
|
@@ -17429,7 +17654,7 @@ async function runDoctor(o) {
|
|
|
17429
17654
|
});
|
|
17430
17655
|
}
|
|
17431
17656
|
const sPath = settingsPath(home);
|
|
17432
|
-
const settings =
|
|
17657
|
+
const settings = existsSync17(sPath) ? readSettings(home) : null;
|
|
17433
17658
|
const pointed = settings ? readProxy(settings) : null;
|
|
17434
17659
|
if (!settings) {
|
|
17435
17660
|
checks.push({
|
|
@@ -17476,7 +17701,7 @@ async function runDoctor(o) {
|
|
|
17476
17701
|
detail: `seat-event ${seat ? "on" : "missing"} · spec-event ${spec ? "on" : "missing"} · session-event ${session ? "on" : "missing"} · stop-event ${stop ? "on" : "missing"}`,
|
|
17477
17702
|
fix: all ? undefined : "sleds hooks"
|
|
17478
17703
|
});
|
|
17479
|
-
const want = env.SLEDS_HOME?.trim() ?
|
|
17704
|
+
const want = env.SLEDS_HOME?.trim() ? resolve9(home, env.SLEDS_HOME.trim()) : undefined;
|
|
17480
17705
|
const cmds = sledsCommandsIn(settings);
|
|
17481
17706
|
const wrong = cmds.filter((c) => {
|
|
17482
17707
|
const got = bakedHome(c);
|
|
@@ -17514,7 +17739,7 @@ async function runDoctor(o) {
|
|
|
17514
17739
|
fix: other.length + unpinned.length === 0 ? undefined : `${[...overrides, `SLEDS_ORG=${wantOrg}`].join(" ")} sleds hooks (pins the status line + hooks to ${wantOrg}; use the org this Claude config is for)`
|
|
17515
17740
|
});
|
|
17516
17741
|
}
|
|
17517
|
-
const skill =
|
|
17742
|
+
const skill = existsSync17(skillPath(home));
|
|
17518
17743
|
checks.push({
|
|
17519
17744
|
level: skill ? "ok" : "warn",
|
|
17520
17745
|
name: "skill",
|
|
@@ -17548,7 +17773,7 @@ async function runDoctor(o) {
|
|
|
17548
17773
|
const which = (o.which ?? defaultWhich2)("sleds");
|
|
17549
17774
|
const stale = which.filter((p) => {
|
|
17550
17775
|
try {
|
|
17551
|
-
const target =
|
|
17776
|
+
const target = lstatSync2(p).isSymbolicLink() ? readlinkSync2(p) : p;
|
|
17552
17777
|
return /\/src\/index\.ts$/.test(target) || /\.bun\/bin\/sleds$/.test(p);
|
|
17553
17778
|
} catch {
|
|
17554
17779
|
return false;
|
|
@@ -17683,7 +17908,7 @@ function sandboxChecks(o, env) {
|
|
|
17683
17908
|
fix: "npm install -g @anthropic-ai/claude-code"
|
|
17684
17909
|
}
|
|
17685
17910
|
];
|
|
17686
|
-
if (!
|
|
17911
|
+
if (!existsSync17(dir))
|
|
17687
17912
|
return [
|
|
17688
17913
|
{
|
|
17689
17914
|
level: "warn",
|
|
@@ -17693,12 +17918,12 @@ function sandboxChecks(o, env) {
|
|
|
17693
17918
|
}
|
|
17694
17919
|
];
|
|
17695
17920
|
const nonce = o.nonce ?? `sleds-probe-${randomBytes(16).toString("hex")}`;
|
|
17696
|
-
const probe =
|
|
17697
|
-
const work = mkdtempSync(
|
|
17921
|
+
const probe = join20(dir, SANDBOX_PROBE);
|
|
17922
|
+
const work = mkdtempSync(join20(tmpdir(), "sleds-sandbox-"));
|
|
17698
17923
|
try {
|
|
17699
17924
|
writeFileSync17(probe, `${nonce}
|
|
17700
17925
|
`, { mode: 384 });
|
|
17701
|
-
const settingsFile =
|
|
17926
|
+
const settingsFile = join20(work, "settings.json");
|
|
17702
17927
|
const settings = sandboxSettings({
|
|
17703
17928
|
denyRead: [dir],
|
|
17704
17929
|
gitCommonDir: work,
|
|
@@ -17734,7 +17959,7 @@ function engineChecks(o, env) {
|
|
|
17734
17959
|
const checks = [];
|
|
17735
17960
|
const which = (c) => (o.which ?? defaultWhich2)(c)[0] ?? null;
|
|
17736
17961
|
const exec = o.exec ?? defaultExec3;
|
|
17737
|
-
const exists = o.exists ??
|
|
17962
|
+
const exists = o.exists ?? existsSync17;
|
|
17738
17963
|
const platform = o.platform ?? process.platform;
|
|
17739
17964
|
const mac = platform === "darwin";
|
|
17740
17965
|
const linux = platform === "linux";
|
|
@@ -17776,6 +18001,11 @@ function engineChecks(o, env) {
|
|
|
17776
18001
|
fix: mac ? "brew install tmux" : "install tmux with your package manager"
|
|
17777
18002
|
});
|
|
17778
18003
|
}
|
|
18004
|
+
if (runner === "orca") {
|
|
18005
|
+
const path = engines.find((e) => engineArg(e.programArgs, "runner") === "orca")?.path ?? env.PATH ?? "";
|
|
18006
|
+
const p = orcaPreflight(exec, path, o.orcaFs);
|
|
18007
|
+
checks.push(p.ok ? { level: "ok", name: "orca", detail: `${p.version} · the engine's runner` } : { level: need, name: "orca", detail: p.why, fix: p.fix });
|
|
18008
|
+
}
|
|
17779
18009
|
if (linux)
|
|
17780
18010
|
checks.push(...boxChecks(o, env, which, need));
|
|
17781
18011
|
if (!manager)
|
|
@@ -17865,7 +18095,7 @@ function boxChecks(o, env, which, need) {
|
|
|
17865
18095
|
}
|
|
17866
18096
|
function cmuxCheck(o, env) {
|
|
17867
18097
|
const exec = o.exec ?? defaultExec3;
|
|
17868
|
-
const bin = resolveCmuxBin(o.exists ??
|
|
18098
|
+
const bin = resolveCmuxBin(o.exists ?? existsSync17, env.PATH ?? "");
|
|
17869
18099
|
const pw = readCmuxPassword(exec);
|
|
17870
18100
|
const ping = pw ? exec(bin, ["ping"], { env: { CMUX_SOCKET_PASSWORD: pw } }) : exec(bin, ["ping"]);
|
|
17871
18101
|
if (ping.status === 127)
|
|
@@ -17956,7 +18186,7 @@ import {
|
|
|
17956
18186
|
writeFileSync as writeFileSync18
|
|
17957
18187
|
} from "node:fs";
|
|
17958
18188
|
import { hostname as hostname4 } from "node:os";
|
|
17959
|
-
import { join as
|
|
18189
|
+
import { join as join21, resolve as resolve10 } from "node:path";
|
|
17960
18190
|
init_machine();
|
|
17961
18191
|
init_state();
|
|
17962
18192
|
init_meter();
|
|
@@ -18211,7 +18441,7 @@ function flagsFromProfile2(flags, given, profile, home) {
|
|
|
18211
18441
|
}
|
|
18212
18442
|
}
|
|
18213
18443
|
if (profile.reposDir && !has("repos-dir") && !has("repo")) {
|
|
18214
|
-
out.reposDir = splitReposDirs(profile.reposDir).map((d) => home && /^~(\/|$)/.test(d) ?
|
|
18444
|
+
out.reposDir = splitReposDirs(profile.reposDir).map((d) => home && /^~(\/|$)/.test(d) ? join21(home, d.slice(1)) : d).join(":");
|
|
18215
18445
|
used.push(`repos ${profile.reposDir}`);
|
|
18216
18446
|
}
|
|
18217
18447
|
if (profile.mcpStrict !== undefined && !has("strict-mcp") && !has("no-strict-mcp")) {
|
|
@@ -18301,6 +18531,29 @@ async function rereadAtOnce2(read, flags, given) {
|
|
|
18301
18531
|
const profile = await read();
|
|
18302
18532
|
return profile ? profile.atOnce ?? 1 : null;
|
|
18303
18533
|
}
|
|
18534
|
+
async function rereadRunner2(read, flags, given, home) {
|
|
18535
|
+
if (given.includes("runner"))
|
|
18536
|
+
return null;
|
|
18537
|
+
const profile = await read();
|
|
18538
|
+
if (!profile)
|
|
18539
|
+
return null;
|
|
18540
|
+
const base = {
|
|
18541
|
+
...flags,
|
|
18542
|
+
runner: "tmux",
|
|
18543
|
+
runnerCmd: given.includes("runner-cmd") ? flags.runnerCmd : undefined
|
|
18544
|
+
};
|
|
18545
|
+
const r = flagsFromProfile2(base, given, profile, home);
|
|
18546
|
+
const skipped = r.skipped.find((s) => s.startsWith("runner"));
|
|
18547
|
+
if (skipped)
|
|
18548
|
+
return { refused: `skipped from your engine profile: ${skipped} — fix it in Settings` };
|
|
18549
|
+
const refusal = sandboxRefusal({ sandbox: flags.sandbox, runner: r.flags.runner });
|
|
18550
|
+
if (refusal)
|
|
18551
|
+
return { refused: `runner ${r.flags.runner} not taken — ${refusal}` };
|
|
18552
|
+
return {
|
|
18553
|
+
runner: r.flags.runner,
|
|
18554
|
+
...r.flags.runner === "command" && r.flags.runnerCmd ? { runnerCmd: r.flags.runnerCmd } : {}
|
|
18555
|
+
};
|
|
18556
|
+
}
|
|
18304
18557
|
var PROFILE_RETRY_MS2 = [2000, 5000];
|
|
18305
18558
|
async function withProfile2(client, flags, given, home, retry) {
|
|
18306
18559
|
let profile = await readProfile(client);
|
|
@@ -18379,12 +18632,12 @@ function memberMcpConfigs2(o, cwd) {
|
|
|
18379
18632
|
});
|
|
18380
18633
|
const claudeDir = (o.env ?? process.env).CLAUDE_CONFIG_DIR;
|
|
18381
18634
|
return [
|
|
18382
|
-
read(claudeDir ?
|
|
18383
|
-
...cwd ? [read(
|
|
18635
|
+
read(claudeDir ? join21(claudeDir, ".claude.json") : join21(o.home, ".claude.json")),
|
|
18636
|
+
...cwd ? [read(join21(cwd, ".mcp.json"))] : []
|
|
18384
18637
|
];
|
|
18385
18638
|
}
|
|
18386
18639
|
function engineStateDir2(o, org, seat) {
|
|
18387
|
-
return seatStateDir(orgStateDir(o.stateDir ??
|
|
18640
|
+
return seatStateDir(orgStateDir(o.stateDir ?? join21(configDir(o.home, o.env ?? process.env), "engine"), org), seat);
|
|
18388
18641
|
}
|
|
18389
18642
|
function engineSeat2(o, org) {
|
|
18390
18643
|
try {
|
|
@@ -18411,11 +18664,11 @@ function engineDeps2(o, flags, source, runner, stateName) {
|
|
|
18411
18664
|
const stateDir = engineStateDir2(o, flags.org, flags.seat);
|
|
18412
18665
|
const file = statePath(stateDir, stateName);
|
|
18413
18666
|
const mcpOrg = flags.org && engineOrg2(o, flags.org).seated ? flags.org : undefined;
|
|
18414
|
-
const repo = flags.repo ?
|
|
18415
|
-
const reposDirs = splitReposDirs(flags.reposDir).map((d) =>
|
|
18667
|
+
const repo = flags.repo ? resolve10(cwd, flags.repo) : undefined;
|
|
18668
|
+
const reposDirs = splitReposDirs(flags.reposDir).map((d) => resolve10(cwd, d));
|
|
18416
18669
|
const { branch, prTitle } = flags;
|
|
18417
|
-
const hooksDir =
|
|
18418
|
-
const permissionMark = (name) =>
|
|
18670
|
+
const hooksDir = join21(stateDir, "hooks");
|
|
18671
|
+
const permissionMark = (name) => join21(hooksDir, `${name}.permission.json`);
|
|
18419
18672
|
const withHook = (name, settings) => applyPermissionHook(settings, [...o.sledsArgv ?? ["sleds"], "permission-event", "--mark", permissionMark(name)].map(shq2).join(" "));
|
|
18420
18673
|
return {
|
|
18421
18674
|
source,
|
|
@@ -18440,9 +18693,9 @@ function engineDeps2(o, flags, source, runner, stateName) {
|
|
|
18440
18693
|
sandbox: true,
|
|
18441
18694
|
writeSandboxSettings: o.writeSandboxSettings ?? ((name, cwd) => {
|
|
18442
18695
|
const gitCommonDir = gitCommonDirOf2(exec, cwd);
|
|
18443
|
-
const dir =
|
|
18696
|
+
const dir = join21(stateDir, "sandbox");
|
|
18444
18697
|
mkdirSync16(dir, { recursive: true, mode: 448 });
|
|
18445
|
-
const p =
|
|
18698
|
+
const p = join21(dir, `${name}.json`);
|
|
18446
18699
|
const walls = engineSandboxSettings2(o.home, o.env ?? process.env, gitCommonDir, [
|
|
18447
18700
|
...SANDBOX_DEFAULT_ALLOW,
|
|
18448
18701
|
...flags.sandboxAllow ?? []
|
|
@@ -18456,7 +18709,7 @@ function engineDeps2(o, flags, source, runner, stateName) {
|
|
|
18456
18709
|
} : {},
|
|
18457
18710
|
writeHookSettings: (name) => {
|
|
18458
18711
|
mkdirSync16(hooksDir, { recursive: true, mode: 448 });
|
|
18459
|
-
const p =
|
|
18712
|
+
const p = join21(hooksDir, `${name}.json`);
|
|
18460
18713
|
writeFileSync18(p, `${JSON.stringify(withHook(name, {}), null, 2)}
|
|
18461
18714
|
`, { mode: 384 });
|
|
18462
18715
|
chmodSync5(p, 384);
|
|
@@ -18483,9 +18736,9 @@ function engineDeps2(o, flags, source, runner, stateName) {
|
|
|
18483
18736
|
exists
|
|
18484
18737
|
}),
|
|
18485
18738
|
writeMcpConfig: o.writeMcpConfig ?? ((name, runToken, worktree) => {
|
|
18486
|
-
const dir =
|
|
18739
|
+
const dir = join21(stateDir, "mcp");
|
|
18487
18740
|
mkdirSync16(dir, { recursive: true, mode: 448 });
|
|
18488
|
-
const p =
|
|
18741
|
+
const p = join21(dir, `${name}.json`);
|
|
18489
18742
|
let others = {};
|
|
18490
18743
|
if (flags.strictMcp && flags.mcpAllow?.length) {
|
|
18491
18744
|
const r = mcpPassThrough(flags.mcpAllow, memberMcpConfigs2(o, worktree));
|
|
@@ -18501,9 +18754,9 @@ function engineDeps2(o, flags, source, runner, stateName) {
|
|
|
18501
18754
|
}),
|
|
18502
18755
|
removeMcpConfig: o.removeMcpConfig ?? ((p) => rmSync9(p, { force: true })),
|
|
18503
18756
|
writePrompt: o.writePrompt ?? ((name, text) => {
|
|
18504
|
-
const dir =
|
|
18757
|
+
const dir = join21(stateDir, "prompts");
|
|
18505
18758
|
mkdirSync16(dir, { recursive: true, mode: 448 });
|
|
18506
|
-
const p =
|
|
18759
|
+
const p = join21(dir, `${name}.md`);
|
|
18507
18760
|
writeFileSync18(p, text, { mode: 384 });
|
|
18508
18761
|
return p;
|
|
18509
18762
|
}),
|
|
@@ -18530,8 +18783,8 @@ function engineDeps2(o, flags, source, runner, stateName) {
|
|
|
18530
18783
|
}
|
|
18531
18784
|
function sandboxDenyRead2(home, env) {
|
|
18532
18785
|
return {
|
|
18533
|
-
dirs: [...new Set([configDir(home, env),
|
|
18534
|
-
files: [...new Set([tokenPath(home, env),
|
|
18786
|
+
dirs: [...new Set([configDir(home, env), join21(home, ".config", "sleds")])],
|
|
18787
|
+
files: [...new Set([tokenPath(home, env), join21(home, ".sleds-token")])]
|
|
18535
18788
|
};
|
|
18536
18789
|
}
|
|
18537
18790
|
function engineSandboxSettings2(home, env, gitCommonDir, allow) {
|
|
@@ -18546,7 +18799,7 @@ function gitCommonDirOf2(exec, cwd) {
|
|
|
18546
18799
|
const dir = r.status === 0 ? r.stdout.trim() : "";
|
|
18547
18800
|
if (!dir)
|
|
18548
18801
|
throw new Error(`git has no common dir for ${cwd}, so the sandbox has nowhere to commit`);
|
|
18549
|
-
return
|
|
18802
|
+
return resolve10(cwd, dir);
|
|
18550
18803
|
}
|
|
18551
18804
|
function sandboxRefusal(flags) {
|
|
18552
18805
|
if (!flags.sandbox)
|
|
@@ -18597,13 +18850,14 @@ async function driveEngine2(o, flags, deps, until = {}) {
|
|
|
18597
18850
|
runner: deps.runner.name,
|
|
18598
18851
|
atOnce: flags.atOnce,
|
|
18599
18852
|
interval: flags.interval,
|
|
18600
|
-
cliVersion: "0.1.
|
|
18853
|
+
cliVersion: "0.1.44"
|
|
18601
18854
|
};
|
|
18602
18855
|
const beat = (checkedAt) => {
|
|
18603
18856
|
const m = deps.machine;
|
|
18604
18857
|
try {
|
|
18605
18858
|
writeLock(lockFile, checkedAt === undefined ? lock : {
|
|
18606
18859
|
...lock,
|
|
18860
|
+
runner: deps.runner.name,
|
|
18607
18861
|
atOnce: deps.atOnce,
|
|
18608
18862
|
checkedAt,
|
|
18609
18863
|
nextCheckAt: checkedAt + flags.interval * 1000,
|
|
@@ -18876,7 +19130,7 @@ var engineCmd = async (o) => {
|
|
|
18876
19130
|
armedOnly: true,
|
|
18877
19131
|
engine: `engine:${flags.name}`,
|
|
18878
19132
|
...parsed.given.includes("at-once") ? { atOnce: flags.atOnce } : {},
|
|
18879
|
-
runner: runner.name,
|
|
19133
|
+
runner: () => deps.runner.name,
|
|
18880
19134
|
leaseMin: flags.lease,
|
|
18881
19135
|
log
|
|
18882
19136
|
});
|
|
@@ -18894,6 +19148,21 @@ var engineCmd = async (o) => {
|
|
|
18894
19148
|
const started = flags;
|
|
18895
19149
|
deps.rereadRoles = (read) => rereadRoles(read, started, parsed.given);
|
|
18896
19150
|
deps.rereadAtOnce = (read) => rereadAtOnce2(read, started, parsed.given);
|
|
19151
|
+
let current = { runner, cmd: flags.runner === "command" ? flags.runnerCmd : undefined };
|
|
19152
|
+
deps.rereadRunner = async (read) => {
|
|
19153
|
+
const next = await rereadRunner2(read, started, parsed.given, o.home);
|
|
19154
|
+
if (!next)
|
|
19155
|
+
return null;
|
|
19156
|
+
if ("refused" in next)
|
|
19157
|
+
return next.refused;
|
|
19158
|
+
if (next.runner === current.runner.name && next.runnerCmd === current.cmd)
|
|
19159
|
+
return current.runner;
|
|
19160
|
+
const made = engineRunner2(o, { ...started, ...next });
|
|
19161
|
+
if (!made)
|
|
19162
|
+
return `runner ${next.runner} not taken — this CLI cannot start it`;
|
|
19163
|
+
current = { runner: made, cmd: next.runnerCmd };
|
|
19164
|
+
return made;
|
|
19165
|
+
};
|
|
18897
19166
|
}
|
|
18898
19167
|
log(engineHeader2(terminalOf2(o).c, deps.engine, (source.name === "jira" ? `Jira epic ${flags.jira}` : pickup === "auto" ? "your sled, Pickup: Auto (it arms the next ready item)" : "the routes armed on your sled") + (flags.org ? ` · org ${flags.org}` : "") + (flags.seat ? ` · as ${flags.seat}` : ""), runner.name, flags));
|
|
18899
19168
|
if (flags.strictMcp && flags.agent)
|
|
@@ -18903,7 +19172,6 @@ var engineCmd = async (o) => {
|
|
|
18903
19172
|
let afterTick;
|
|
18904
19173
|
if (client) {
|
|
18905
19174
|
const send = beater(client, o.now ?? Date.now);
|
|
18906
|
-
const who = { name: flags.name, runner: runner.name };
|
|
18907
19175
|
let refused;
|
|
18908
19176
|
const sayRefused = (r) => {
|
|
18909
19177
|
if (!r || r.ok || !r.refused || r.refused === refused)
|
|
@@ -18914,7 +19182,7 @@ var engineCmd = async (o) => {
|
|
|
18914
19182
|
afterTick = () => {
|
|
18915
19183
|
try {
|
|
18916
19184
|
const m = deps.machine;
|
|
18917
|
-
send(beatBody(deps.readState(),
|
|
19185
|
+
send(beatBody(deps.readState(), { name: flags.name, runner: deps.runner.name }, {}, {
|
|
18918
19186
|
atOnce: deps.atOnce,
|
|
18919
19187
|
...m?.last ? { machine: m.last } : {},
|
|
18920
19188
|
...m?.hold && !m.off ? { hold: m.hold } : {}
|
|
@@ -19047,7 +19315,7 @@ async function enginePauseCmd2(o) {
|
|
|
19047
19315
|
// src/commands/engineInstall.ts
|
|
19048
19316
|
init_config();
|
|
19049
19317
|
import {
|
|
19050
|
-
existsSync as
|
|
19318
|
+
existsSync as existsSync18,
|
|
19051
19319
|
mkdirSync as mkdirSync17,
|
|
19052
19320
|
readFileSync as readFileSync19,
|
|
19053
19321
|
readdirSync as readdirSync4,
|
|
@@ -19056,7 +19324,7 @@ import {
|
|
|
19056
19324
|
writeFileSync as writeFileSync19
|
|
19057
19325
|
} from "node:fs";
|
|
19058
19326
|
import { hostname as hostname5 } from "node:os";
|
|
19059
|
-
import { basename as basename5, dirname as dirname13, isAbsolute as isAbsolute3, join as
|
|
19327
|
+
import { basename as basename5, dirname as dirname13, isAbsolute as isAbsolute3, join as join22 } from "node:path";
|
|
19060
19328
|
init_state();
|
|
19061
19329
|
var ENGINE_LABEL2 = "ai.sleds.engine";
|
|
19062
19330
|
var ENGINE_INSTALL_USAGE2 = `usage: sleds engine install [engine flags] | sleds engine uninstall [--name <n>] [--org <slug>]
|
|
@@ -19076,13 +19344,13 @@ function engineLabel2(name, org, seat) {
|
|
|
19076
19344
|
return [ENGINE_LABEL2, org, seat?.trim(), name].filter((p) => Boolean(p)).map((p, i) => i === 0 ? p : engineSlug(p)).join(".");
|
|
19077
19345
|
}
|
|
19078
19346
|
function enginePlistPath2(home, name, org, seat) {
|
|
19079
|
-
return
|
|
19347
|
+
return join22(home, "Library", "LaunchAgents", `${engineLabel2(name, org, seat)}.plist`);
|
|
19080
19348
|
}
|
|
19081
19349
|
function engineLogPath2(stateDir, name) {
|
|
19082
|
-
return
|
|
19350
|
+
return join22(stateDir, `${engineSlug(name)}.log`);
|
|
19083
19351
|
}
|
|
19084
19352
|
function engineEventsPath2(stateDir, name) {
|
|
19085
|
-
return
|
|
19353
|
+
return join22(stateDir, `${engineSlug(name)}.events.jsonl`);
|
|
19086
19354
|
}
|
|
19087
19355
|
var xmlEscape4 = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
19088
19356
|
function buildEnginePlist2(o) {
|
|
@@ -19158,7 +19426,13 @@ function parseEnginePlist2(text) {
|
|
|
19158
19426
|
if (!label || array === undefined)
|
|
19159
19427
|
return null;
|
|
19160
19428
|
const programArgs = [...array.matchAll(/<string>([^<]*)<\/string>/g)].map((m) => xmlUnescape2(m[1] ?? ""));
|
|
19161
|
-
|
|
19429
|
+
const envDict = /<key>EnvironmentVariables<\/key>\s*<dict>([\s\S]*?)<\/dict>/.exec(text)?.[1];
|
|
19430
|
+
const path = envDict && /<key>PATH<\/key>\s*<string>([^<]*)<\/string>/.exec(envDict)?.[1];
|
|
19431
|
+
return {
|
|
19432
|
+
label: xmlUnescape2(label),
|
|
19433
|
+
programArgs,
|
|
19434
|
+
...typeof path === "string" ? { path: xmlUnescape2(path) } : {}
|
|
19435
|
+
};
|
|
19162
19436
|
}
|
|
19163
19437
|
function engineArg2(programArgs, flag) {
|
|
19164
19438
|
const at = programArgs.indexOf(`--${flag}`);
|
|
@@ -19173,7 +19447,7 @@ function readEngines2(dir, suffix, manager, parse) {
|
|
|
19173
19447
|
}
|
|
19174
19448
|
const out = [];
|
|
19175
19449
|
for (const name of names.filter((n) => n.startsWith(`${ENGINE_LABEL2}.`) && n.endsWith(suffix))) {
|
|
19176
|
-
const path =
|
|
19450
|
+
const path = join22(dir, name);
|
|
19177
19451
|
let parsed;
|
|
19178
19452
|
try {
|
|
19179
19453
|
parsed = parse(readFileSync19(path, "utf8"), name);
|
|
@@ -19193,7 +19467,7 @@ function readEngines2(dir, suffix, manager, parse) {
|
|
|
19193
19467
|
}
|
|
19194
19468
|
function installedEngines2(home) {
|
|
19195
19469
|
return [
|
|
19196
|
-
...readEngines2(
|
|
19470
|
+
...readEngines2(join22(home, "Library", "LaunchAgents"), ".plist", "launchd", parseEnginePlist2),
|
|
19197
19471
|
...readEngines2(engineUnitDir(home), ".service", "systemd", (text, file) => {
|
|
19198
19472
|
const parsed = parseEngineUnit(text);
|
|
19199
19473
|
return parsed && { label: basename5(file, ".service"), ...parsed };
|
|
@@ -19230,8 +19504,8 @@ async function ensureReposDir(o) {
|
|
|
19230
19504
|
error(REPOS_DIR_NEEDED);
|
|
19231
19505
|
return false;
|
|
19232
19506
|
}
|
|
19233
|
-
const exists = o.exists ??
|
|
19234
|
-
const missing = dirs.filter((d) => !exists(/^~(\/|$)/.test(d) ?
|
|
19507
|
+
const exists = o.exists ?? existsSync18;
|
|
19508
|
+
const missing = dirs.filter((d) => !exists(/^~(\/|$)/.test(d) ? join22(o.home, d.slice(1)) : d));
|
|
19235
19509
|
if (missing.length) {
|
|
19236
19510
|
error(`Not a folder on this machine: ${missing.join(", ")}. ${REPOS_DIR_NEEDED}`);
|
|
19237
19511
|
return false;
|
|
@@ -19288,7 +19562,7 @@ function engineInstall2(o) {
|
|
|
19288
19562
|
return installUnit2({ o, parsed, label, sledsArgv, env: agentEnv, logPath, exec });
|
|
19289
19563
|
const plist = enginePlistPath2(o.home, parsed.name, parsed.org, seat);
|
|
19290
19564
|
mkdirSync17(dirname13(plist), { recursive: true });
|
|
19291
|
-
if (
|
|
19565
|
+
if (existsSync18(plist))
|
|
19292
19566
|
exec("launchctl", ["unload", plist]);
|
|
19293
19567
|
for (const other of installedEngines2(o.home)) {
|
|
19294
19568
|
if (other.manager !== "launchd" || other.plist === plist || other.org !== parsed.org)
|
|
@@ -19300,7 +19574,7 @@ function engineInstall2(o) {
|
|
|
19300
19574
|
log(`replaced ${other.label}, this engine as installed before`);
|
|
19301
19575
|
}
|
|
19302
19576
|
const legacy = enginePlistPath2(o.home, parsed.name);
|
|
19303
|
-
if (parsed.org &&
|
|
19577
|
+
if (parsed.org && existsSync18(legacy)) {
|
|
19304
19578
|
const cfg = readConfig(o.home);
|
|
19305
19579
|
if (org.sole || parsed.org === (cfg.activeOrg ?? cfg.org?.slug)) {
|
|
19306
19580
|
exec("launchctl", ["unload", legacy]);
|
|
@@ -19330,7 +19604,7 @@ function installUnit2(a) {
|
|
|
19330
19604
|
const unitName = basename5(unit);
|
|
19331
19605
|
const systemctl = (...args) => exec("systemctl", ["--user", ...args]);
|
|
19332
19606
|
mkdirSync17(dirname13(unit), { recursive: true });
|
|
19333
|
-
if (
|
|
19607
|
+
if (existsSync18(unit))
|
|
19334
19608
|
systemctl("stop", unitName);
|
|
19335
19609
|
for (const other of installedEngines2(o.home)) {
|
|
19336
19610
|
if (other.manager !== "systemd" || other.plist === unit || other.org !== parsed.org)
|
|
@@ -19388,7 +19662,7 @@ function engineUninstall2(o) {
|
|
|
19388
19662
|
...installed.filter((e) => e.manager === manager).map((e) => e.plist),
|
|
19389
19663
|
...args.org ? [] : [pathOf(manager)]
|
|
19390
19664
|
]);
|
|
19391
|
-
const file = candidates.find((p) =>
|
|
19665
|
+
const file = candidates.find((p) => existsSync18(p));
|
|
19392
19666
|
if (!file) {
|
|
19393
19667
|
log(`engine:${name} was not installed (no ${candidates[0]}).`);
|
|
19394
19668
|
return 0;
|
|
@@ -19530,7 +19804,7 @@ import { closeSync as closeSync3, fstatSync as fstatSync2, openSync as openSync3
|
|
|
19530
19804
|
import { hostname as hostname6 } from "node:os";
|
|
19531
19805
|
|
|
19532
19806
|
// src/commands/engineStatus.ts
|
|
19533
|
-
import { existsSync as
|
|
19807
|
+
import { existsSync as existsSync19, readFileSync as readFileSync20 } from "node:fs";
|
|
19534
19808
|
init_state();
|
|
19535
19809
|
|
|
19536
19810
|
// src/engine/status.ts
|
|
@@ -19713,7 +19987,7 @@ function statusDir(o, engine, org) {
|
|
|
19713
19987
|
const env = o.env ?? process.env;
|
|
19714
19988
|
const which = engineOrg({ home: o.home, env }, org);
|
|
19715
19989
|
const slug = which.seated || org ? which.slug : null;
|
|
19716
|
-
const has = (d) =>
|
|
19990
|
+
const has = (d) => existsSync19(statePath(d, engine)) || existsSync19(lockPath(d, engine));
|
|
19717
19991
|
const seat = engineSeat({ home: o.home, env }, slug ?? undefined);
|
|
19718
19992
|
const dir = engineStateDir({ ...o, env }, slug);
|
|
19719
19993
|
const seatDir = engineStateDir({ ...o, env }, slug, seat);
|
|
@@ -19820,7 +20094,7 @@ var engineLogCmd = (o) => {
|
|
|
19820
20094
|
|
|
19821
20095
|
// src/commands/engineProfile.ts
|
|
19822
20096
|
init_src();
|
|
19823
|
-
import { existsSync as
|
|
20097
|
+
import { existsSync as existsSync20, readFileSync as readFileSync21 } from "node:fs";
|
|
19824
20098
|
import { hostname as hostname7 } from "node:os";
|
|
19825
20099
|
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]";
|
|
19826
20100
|
var PROFILE_FIELDS = [
|
|
@@ -20048,7 +20322,7 @@ function localOf(o) {
|
|
|
20048
20322
|
return {
|
|
20049
20323
|
engine: `engine:${name}`,
|
|
20050
20324
|
canInstall,
|
|
20051
|
-
installed: canInstall &&
|
|
20325
|
+
installed: canInstall && existsSync20(enginePlistPath(o.home, name))
|
|
20052
20326
|
};
|
|
20053
20327
|
}
|
|
20054
20328
|
async function engineProfileCmd(o) {
|
|
@@ -20170,7 +20444,7 @@ var keychainLine = (k) => k === "set" ? "cmuxPassword: set (Keychain)" : k === "
|
|
|
20170
20444
|
|
|
20171
20445
|
// src/commands/engineStatus.ts
|
|
20172
20446
|
init_state();
|
|
20173
|
-
import { existsSync as
|
|
20447
|
+
import { existsSync as existsSync21, readFileSync as readFileSync22 } from "node:fs";
|
|
20174
20448
|
import { hostname as hostname8 } from "node:os";
|
|
20175
20449
|
var ENGINE_STATUS_USAGE = "usage: sleds engine status [--name <n>] [--org <slug>] [--json]";
|
|
20176
20450
|
function parseStatusArgs(argv, host) {
|
|
@@ -20199,7 +20473,7 @@ function statusDir2(o, engine, org) {
|
|
|
20199
20473
|
const env = o.env ?? process.env;
|
|
20200
20474
|
const which = engineOrg({ home: o.home, env }, org);
|
|
20201
20475
|
const slug = which.seated || org ? which.slug : null;
|
|
20202
|
-
const has = (d) =>
|
|
20476
|
+
const has = (d) => existsSync21(statePath(d, engine)) || existsSync21(lockPath(d, engine));
|
|
20203
20477
|
const seat = engineSeat({ home: o.home, env }, slug ?? undefined);
|
|
20204
20478
|
const dir = engineStateDir({ ...o, env }, slug);
|
|
20205
20479
|
const seatDir = engineStateDir({ ...o, env }, slug, seat);
|
|
@@ -20212,7 +20486,7 @@ function statusDir2(o, engine, org) {
|
|
|
20212
20486
|
}
|
|
20213
20487
|
function readEngineStatus(stateDir, engine, host, pidAlive, seat) {
|
|
20214
20488
|
const file = statePath(stateDir, engine);
|
|
20215
|
-
const text =
|
|
20489
|
+
const text = existsSync21(file) ? safeRead(file) : "";
|
|
20216
20490
|
return engineStatus({
|
|
20217
20491
|
engine,
|
|
20218
20492
|
state: text ? parseState(text) : { runs: [] },
|
|
@@ -20347,10 +20621,10 @@ init_meter();
|
|
|
20347
20621
|
|
|
20348
20622
|
// src/owed.ts
|
|
20349
20623
|
init_config();
|
|
20350
|
-
import { existsSync as
|
|
20351
|
-
import { dirname as dirname14, join as
|
|
20352
|
-
var owedPath = (home) =>
|
|
20353
|
-
var sessionPath = (home) =>
|
|
20624
|
+
import { existsSync as existsSync22, mkdirSync as mkdirSync18, readFileSync as readFileSync23, renameSync as renameSync7, writeFileSync as writeFileSync20 } from "node:fs";
|
|
20625
|
+
import { dirname as dirname14, join as join23 } from "node:path";
|
|
20626
|
+
var owedPath = (home) => join23(configDir(home), "owed.json");
|
|
20627
|
+
var sessionPath = (home) => join23(configDir(home), "session.json");
|
|
20354
20628
|
var OWED_TTL_MS = 3 * 24 * 60 * 60000;
|
|
20355
20629
|
var str13 = (v) => typeof v === "string" ? v : undefined;
|
|
20356
20630
|
function sourceKey(s) {
|
|
@@ -20365,7 +20639,7 @@ function sourceText2(s) {
|
|
|
20365
20639
|
return [`${str13(s.kind) ?? "?"} ${str13(s.project) ?? "?"}`, str13(s.doc), str13(s.item)].filter(Boolean).join(" › ");
|
|
20366
20640
|
}
|
|
20367
20641
|
var readJson = (p) => {
|
|
20368
|
-
if (!
|
|
20642
|
+
if (!existsSync22(p))
|
|
20369
20643
|
return null;
|
|
20370
20644
|
try {
|
|
20371
20645
|
return JSON.parse(readFileSync23(p, "utf8"));
|
|
@@ -21395,7 +21669,7 @@ var login = async (o) => {
|
|
|
21395
21669
|
// src/commands/logout.ts
|
|
21396
21670
|
init_config();
|
|
21397
21671
|
init_state();
|
|
21398
|
-
import { existsSync as
|
|
21672
|
+
import { existsSync as existsSync23, readFileSync as readFileSync24, rmSync as rmSync11 } from "node:fs";
|
|
21399
21673
|
import { hostname as hostname10 } from "node:os";
|
|
21400
21674
|
init_settings();
|
|
21401
21675
|
var LOGOUT_USAGE = "usage: sleds logout [--org <slug>] [--json]";
|
|
@@ -21552,7 +21826,7 @@ async function logout(o) {
|
|
|
21552
21826
|
};
|
|
21553
21827
|
writeConfig(o.home, next);
|
|
21554
21828
|
const tp = tokenPath(o.home, env);
|
|
21555
|
-
if (
|
|
21829
|
+
if (existsSync23(tp) && readFileSync24(tp, "utf8").trim() === seat.token)
|
|
21556
21830
|
rmSync11(tp, { force: true });
|
|
21557
21831
|
const active = next.activeOrg ?? next.org?.slug ?? null;
|
|
21558
21832
|
const result = { ok: true, email, org: slug, paused, active };
|
|
@@ -21630,20 +21904,20 @@ var meter = async (o) => {
|
|
|
21630
21904
|
init_config();
|
|
21631
21905
|
init_meter();
|
|
21632
21906
|
import { spawnSync as spawnSync7 } from "node:child_process";
|
|
21633
|
-
import { existsSync as
|
|
21907
|
+
import { existsSync as existsSync24, mkdirSync as mkdirSync20, readFileSync as readFileSync25, rmSync as rmSync12, writeFileSync as writeFileSync22 } from "node:fs";
|
|
21634
21908
|
import { hostname as hostname11 } from "node:os";
|
|
21635
21909
|
import { dirname as dirname15 } from "node:path";
|
|
21636
21910
|
var defaultWhich3 = (cmd) => {
|
|
21637
21911
|
const path = process.env.PATH ?? "";
|
|
21638
21912
|
for (const dir of path.split(":").filter(Boolean)) {
|
|
21639
21913
|
const p = `${dir}/${cmd}`;
|
|
21640
|
-
if (
|
|
21914
|
+
if (existsSync24(p))
|
|
21641
21915
|
return p;
|
|
21642
21916
|
}
|
|
21643
21917
|
return null;
|
|
21644
21918
|
};
|
|
21645
21919
|
var findClaude2 = (home, configured, which) => {
|
|
21646
|
-
if (configured &&
|
|
21920
|
+
if (configured && existsSync24(configured))
|
|
21647
21921
|
return configured;
|
|
21648
21922
|
const found = which("claude");
|
|
21649
21923
|
if (found)
|
|
@@ -21654,7 +21928,7 @@ var findClaude2 = (home, configured, which) => {
|
|
|
21654
21928
|
"/usr/local/bin/claude",
|
|
21655
21929
|
`${home}/.npm-global/bin/claude`
|
|
21656
21930
|
])
|
|
21657
|
-
if (
|
|
21931
|
+
if (existsSync24(p))
|
|
21658
21932
|
return p;
|
|
21659
21933
|
return null;
|
|
21660
21934
|
};
|
|
@@ -21680,7 +21954,7 @@ var musherInstall = (o) => {
|
|
|
21680
21954
|
...env.CLAUDE_CONFIG_DIR ? { CLAUDE_CONFIG_DIR: env.CLAUDE_CONFIG_DIR } : {}
|
|
21681
21955
|
};
|
|
21682
21956
|
const exec = o.exec ?? defaultExecSync;
|
|
21683
|
-
if (
|
|
21957
|
+
if (existsSync24(plist))
|
|
21684
21958
|
exec("launchctl", ["unload", plist]);
|
|
21685
21959
|
writeFileSync22(plist, buildMusherPlist({ sledsArgv: o.sledsArgv, env: agentEnv, logPath: musherLogPath(dir), label }));
|
|
21686
21960
|
const r = exec("launchctl", ["load", plist]);
|
|
@@ -21701,7 +21975,7 @@ var musherUninstall = (o) => {
|
|
|
21701
21975
|
const env = o.env ?? process.env;
|
|
21702
21976
|
const plist = musherPlistPath(o.home, env);
|
|
21703
21977
|
const exec = o.exec ?? defaultExecSync;
|
|
21704
|
-
if (
|
|
21978
|
+
if (existsSync24(plist)) {
|
|
21705
21979
|
exec("launchctl", ["unload", plist]);
|
|
21706
21980
|
rmSync12(plist, { force: true });
|
|
21707
21981
|
log(`musher removed: ${musherLabel(env)}`);
|
|
@@ -21736,7 +22010,7 @@ var musherStatus = async (o) => {
|
|
|
21736
22010
|
const env = o.env ?? process.env;
|
|
21737
22011
|
const plist = musherPlistPath(o.home, env);
|
|
21738
22012
|
const cfg = readConfig(o.home);
|
|
21739
|
-
log(
|
|
22013
|
+
log(existsSync24(plist) ? `agent ${musherLabel(env)} installed (${plist})` : "agent not installed — sleds musher --install");
|
|
21740
22014
|
const claude = findClaude2(o.home, cfg.musher?.claudePath, o.which ?? defaultWhich3);
|
|
21741
22015
|
log(`claude ${claude ?? "not found — sleds musher --claude /path/to/claude"}`);
|
|
21742
22016
|
log(`mode ${cfg.musher?.permissionMode ?? DEFAULT_PERMISSION_MODE} · timeout ${cfg.musher?.timeoutMinutes ?? DEFAULT_TIMEOUT_MINUTES} min`);
|
|
@@ -21966,7 +22240,7 @@ var on = (o) => {
|
|
|
21966
22240
|
init_config();
|
|
21967
22241
|
init_meter();
|
|
21968
22242
|
init_settings();
|
|
21969
|
-
import { existsSync as
|
|
22243
|
+
import { existsSync as existsSync25, rmSync as rmSync13 } from "node:fs";
|
|
21970
22244
|
var ORG_USAGE = "usage: sleds org list [--json] | sleds org use <slug>";
|
|
21971
22245
|
var orgRows = (cfg, activeSlug) => {
|
|
21972
22246
|
const seats = { ...cfg.orgs ?? {} };
|
|
@@ -22033,7 +22307,7 @@ var orgUse = (o) => {
|
|
|
22033
22307
|
}
|
|
22034
22308
|
writeConfig(o.home, withActiveOrg(cfg, slug, seat));
|
|
22035
22309
|
writeTokenFile(o.home, seat.token);
|
|
22036
|
-
if (
|
|
22310
|
+
if (existsSync25(settingsPath(o.home)) && cfg.mode !== "on") {
|
|
22037
22311
|
const settings = readSettings(o.home);
|
|
22038
22312
|
const pointed = readProxy(settings);
|
|
22039
22313
|
const url = pointed?.url ?? cfg.proxyUrl;
|
|
@@ -22070,7 +22344,7 @@ var orgCmd = (o) => {
|
|
|
22070
22344
|
init_src();
|
|
22071
22345
|
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
22072
22346
|
import { writeFileSync as writeFileSync23 } from "node:fs";
|
|
22073
|
-
import { join as
|
|
22347
|
+
import { join as join24 } from "node:path";
|
|
22074
22348
|
function packFileName(key) {
|
|
22075
22349
|
return `pack-${slugify(key, 80) || "item"}.md`;
|
|
22076
22350
|
}
|
|
@@ -22098,7 +22372,7 @@ var packCmd = async (o) => {
|
|
|
22098
22372
|
log(r.text);
|
|
22099
22373
|
return 0;
|
|
22100
22374
|
}
|
|
22101
|
-
const path =
|
|
22375
|
+
const path = join24(o.cwd ?? process.cwd(), packFileName(key));
|
|
22102
22376
|
(o.write ?? ((p, t) => writeFileSync23(p, t.endsWith(`
|
|
22103
22377
|
`) ? t : `${t}
|
|
22104
22378
|
`)))(path, r.text);
|
|
@@ -23048,14 +23322,14 @@ var seatEvent = async (o) => {
|
|
|
23048
23322
|
|
|
23049
23323
|
// src/commands/seatSync.ts
|
|
23050
23324
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
23051
|
-
import { existsSync as
|
|
23325
|
+
import { existsSync as existsSync26, mkdirSync as mkdirSync22, readFileSync as readFileSync28, readdirSync as readdirSync5, rmSync as rmSync16, writeFileSync as writeFileSync25 } from "node:fs";
|
|
23052
23326
|
import { platform as platform2 } from "node:os";
|
|
23053
|
-
import { dirname as dirname17, join as
|
|
23327
|
+
import { dirname as dirname17, join as join26 } from "node:path";
|
|
23054
23328
|
|
|
23055
23329
|
// src/cookieDb.ts
|
|
23056
23330
|
import { copyFileSync, rmSync as rmSync15 } from "node:fs";
|
|
23057
23331
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
23058
|
-
import { join as
|
|
23332
|
+
import { join as join25 } from "node:path";
|
|
23059
23333
|
var QUERY = "SELECT name, hex(encrypted_value) AS ev FROM cookies WHERE host_key LIKE '%claude.ai%'";
|
|
23060
23334
|
var isBun = () => typeof globalThis.Bun !== "undefined";
|
|
23061
23335
|
async function queryRows(dbPath) {
|
|
@@ -23084,7 +23358,7 @@ function nodeSqlite() {
|
|
|
23084
23358
|
return mod;
|
|
23085
23359
|
}
|
|
23086
23360
|
async function readCookieRows(dbPath) {
|
|
23087
|
-
const copy =
|
|
23361
|
+
const copy = join25(tmpdir2(), `sleds-cookies-${process.pid}-${Date.now()}.sqlite`);
|
|
23088
23362
|
copyFileSync(dbPath, copy);
|
|
23089
23363
|
try {
|
|
23090
23364
|
const rows = await queryRows(copy);
|
|
@@ -23368,7 +23642,7 @@ function findFile(root, name) {
|
|
|
23368
23642
|
const stack = [root];
|
|
23369
23643
|
while (stack.length > 0) {
|
|
23370
23644
|
const dir = stack.pop();
|
|
23371
|
-
if (!dir || !
|
|
23645
|
+
if (!dir || !existsSync26(dir))
|
|
23372
23646
|
continue;
|
|
23373
23647
|
let entries;
|
|
23374
23648
|
try {
|
|
@@ -23377,7 +23651,7 @@ function findFile(root, name) {
|
|
|
23377
23651
|
continue;
|
|
23378
23652
|
}
|
|
23379
23653
|
for (const e of entries) {
|
|
23380
|
-
const p =
|
|
23654
|
+
const p = join26(dir, e.name);
|
|
23381
23655
|
if (e.isDirectory())
|
|
23382
23656
|
stack.push(p);
|
|
23383
23657
|
else if (e.name === name)
|
|
@@ -23388,8 +23662,8 @@ function findFile(root, name) {
|
|
|
23388
23662
|
}
|
|
23389
23663
|
function findCookieDb(home, source) {
|
|
23390
23664
|
const b = BROWSERS[source.browser];
|
|
23391
|
-
const root =
|
|
23392
|
-
if (!
|
|
23665
|
+
const root = join26(home, APP_SUPPORT, b.appDir);
|
|
23666
|
+
if (!existsSync26(root))
|
|
23393
23667
|
throw new Error(`no ${source.browser} data at ${root} (is it installed?)`);
|
|
23394
23668
|
if (!b.profiled) {
|
|
23395
23669
|
const db = findFile(root, "Cookies");
|
|
@@ -23397,15 +23671,15 @@ function findCookieDb(home, source) {
|
|
|
23397
23671
|
throw new Error(`no cookie store under ${root}`);
|
|
23398
23672
|
return db;
|
|
23399
23673
|
}
|
|
23400
|
-
const localStatePath =
|
|
23401
|
-
const localState =
|
|
23674
|
+
const localStatePath = join26(root, "Local State");
|
|
23675
|
+
const localState = existsSync26(localStatePath) ? readFileSync28(localStatePath, "utf8") : null;
|
|
23402
23676
|
const wanted = source.profile ?? "Default";
|
|
23403
23677
|
const { dir, ambiguous } = resolveProfileDir(localState, wanted);
|
|
23404
23678
|
if (ambiguous)
|
|
23405
23679
|
throw new Error(`"${wanted}" names ${ambiguous.length} ${source.browser} profiles (${ambiguous.join(", ")}) — pass the directory or the account email instead`);
|
|
23406
23680
|
if (!dir)
|
|
23407
23681
|
throw new Error(`no ${source.browser} profile named "${wanted}" (check chrome://version)`);
|
|
23408
|
-
const db = cookieDbCandidates(
|
|
23682
|
+
const db = cookieDbCandidates(join26(root, dir)).find((p) => existsSync26(p));
|
|
23409
23683
|
if (!db)
|
|
23410
23684
|
throw new Error(`profile "${dir}" has no cookie store yet (open claude.ai in it once)`);
|
|
23411
23685
|
return db;
|
|
@@ -23449,7 +23723,7 @@ function fetchSeatUsage(jar, org, now, run) {
|
|
|
23449
23723
|
}
|
|
23450
23724
|
function launchAgentPlist(bun, script, home, source) {
|
|
23451
23725
|
const label = launchLabel(source);
|
|
23452
|
-
const log =
|
|
23726
|
+
const log = join26(home, ".config", "sleds", `${label.slice("ai.sleds.".length)}.log`);
|
|
23453
23727
|
const esc = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
23454
23728
|
const args = [bun, script, "seat-sync", ...sourceArgs(source)].map((a) => ` <string>${esc(a)}</string>`).join(`
|
|
23455
23729
|
`);
|
|
@@ -23471,7 +23745,7 @@ ${args}
|
|
|
23471
23745
|
`;
|
|
23472
23746
|
}
|
|
23473
23747
|
function plistPath2(home, source) {
|
|
23474
|
-
return
|
|
23748
|
+
return join26(home, "Library", "LaunchAgents", `${launchLabel(source)}.plist`);
|
|
23475
23749
|
}
|
|
23476
23750
|
function install(home, argv, source, log) {
|
|
23477
23751
|
const bun = argv[0] ?? process.execPath;
|
|
@@ -23480,7 +23754,7 @@ function install(home, argv, source, log) {
|
|
|
23480
23754
|
log("cannot resolve the sleds script path to install the timer");
|
|
23481
23755
|
return 1;
|
|
23482
23756
|
}
|
|
23483
|
-
const dir =
|
|
23757
|
+
const dir = join26(home, "Library", "LaunchAgents");
|
|
23484
23758
|
mkdirSync22(dir, { recursive: true });
|
|
23485
23759
|
const path = plistPath2(home, source);
|
|
23486
23760
|
const tokenPath = seatTokenPath(home, source);
|
|
@@ -23504,7 +23778,7 @@ function uninstall(home, source, log) {
|
|
|
23504
23778
|
execFileSync4("launchctl", ["unload", "-w", path], { stdio: "ignore" });
|
|
23505
23779
|
} catch {}
|
|
23506
23780
|
rmSync16(seatTokenPath(home, source), { force: true });
|
|
23507
|
-
log(
|
|
23781
|
+
log(existsSync26(path) ? `seat-sync timer removed (${path} can be deleted)` : "no seat-sync timer");
|
|
23508
23782
|
return 0;
|
|
23509
23783
|
}
|
|
23510
23784
|
var seatSync = async (o) => {
|
|
@@ -23776,7 +24050,7 @@ var specEvent = async (o) => {
|
|
|
23776
24050
|
};
|
|
23777
24051
|
|
|
23778
24052
|
// src/commands/status.ts
|
|
23779
|
-
import { existsSync as
|
|
24053
|
+
import { existsSync as existsSync27 } from "node:fs";
|
|
23780
24054
|
init_config();
|
|
23781
24055
|
init_settings();
|
|
23782
24056
|
var HEALTH_TIMEOUT_MS2 = 4000;
|
|
@@ -23864,7 +24138,7 @@ var status3 = async (o) => {
|
|
|
23864
24138
|
const log = o.log ?? console.log;
|
|
23865
24139
|
const nowMs = (o.now ?? Date.now)();
|
|
23866
24140
|
const cfg = readConfig(o.home);
|
|
23867
|
-
const settings =
|
|
24141
|
+
const settings = existsSync27(settingsPath(o.home)) ? readSettings(o.home) : {};
|
|
23868
24142
|
const inSettings = readProxy(settings);
|
|
23869
24143
|
const picked = selectOrg(cfg, undefined, o.env ?? process.env);
|
|
23870
24144
|
const viaEnv = picked.from === "env";
|
|
@@ -24057,7 +24331,7 @@ var announce = (o, events) => {
|
|
|
24057
24331
|
|
|
24058
24332
|
// src/commands/stopEvent.ts
|
|
24059
24333
|
init_meter();
|
|
24060
|
-
import { existsSync as
|
|
24334
|
+
import { existsSync as existsSync28, readFileSync as readFileSync30 } from "node:fs";
|
|
24061
24335
|
|
|
24062
24336
|
// src/transcript.ts
|
|
24063
24337
|
var isObject16 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
@@ -24153,7 +24427,7 @@ async function postTranscript(o, payload, now) {
|
|
|
24153
24427
|
const src = meterSource(o.home);
|
|
24154
24428
|
if (!src)
|
|
24155
24429
|
return false;
|
|
24156
|
-
const read = o.readFile ?? ((p) =>
|
|
24430
|
+
const read = o.readFile ?? ((p) => existsSync28(p) ? readFileSync30(p, "utf8") : null);
|
|
24157
24431
|
let text;
|
|
24158
24432
|
try {
|
|
24159
24433
|
text = read(path);
|
|
@@ -24231,7 +24505,7 @@ var stopEvent = async (o) => {
|
|
|
24231
24505
|
|
|
24232
24506
|
// src/commands/uninstall.ts
|
|
24233
24507
|
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
24234
|
-
import { existsSync as
|
|
24508
|
+
import { existsSync as existsSync29, rmSync as rmSync17 } from "node:fs";
|
|
24235
24509
|
init_config();
|
|
24236
24510
|
init_meter();
|
|
24237
24511
|
init_settings();
|
|
@@ -24244,7 +24518,7 @@ var uninstall2 = (o) => {
|
|
|
24244
24518
|
(o.log ?? console.log)(` ${codexLine}`);
|
|
24245
24519
|
const log = o.log ?? console.log;
|
|
24246
24520
|
const removed = [];
|
|
24247
|
-
if (
|
|
24521
|
+
if (existsSync29(settingsPath(o.home))) {
|
|
24248
24522
|
let settings = readSettings(o.home);
|
|
24249
24523
|
let changed = false;
|
|
24250
24524
|
if (hasEitherKey(settings)) {
|
|
@@ -24291,18 +24565,18 @@ var uninstall2 = (o) => {
|
|
|
24291
24565
|
writeSettings(o.home, settings);
|
|
24292
24566
|
}
|
|
24293
24567
|
for (const file of [meterCachePath(o.home), ...allSeatStatePaths(o.home)]) {
|
|
24294
|
-
if (
|
|
24568
|
+
if (existsSync29(file)) {
|
|
24295
24569
|
rmSync17(file, { force: true });
|
|
24296
24570
|
removed.push(file);
|
|
24297
24571
|
}
|
|
24298
24572
|
}
|
|
24299
24573
|
const skill = skillDir(o.home);
|
|
24300
|
-
if (
|
|
24574
|
+
if (existsSync29(skill)) {
|
|
24301
24575
|
rmSync17(skill, { recursive: true, force: true });
|
|
24302
24576
|
removed.push(skill);
|
|
24303
24577
|
}
|
|
24304
24578
|
const plist = musherPlistPath(o.home);
|
|
24305
|
-
if (
|
|
24579
|
+
if (existsSync29(plist)) {
|
|
24306
24580
|
(o.unloadAgent ?? defaultUnload)(plist);
|
|
24307
24581
|
rmSync17(plist, { force: true });
|
|
24308
24582
|
removed.push(`launchd agent ${musherLabel()}`);
|
|
@@ -24457,13 +24731,13 @@ var webhooksCmd = async (o) => {
|
|
|
24457
24731
|
|
|
24458
24732
|
// src/config.ts
|
|
24459
24733
|
init_settings();
|
|
24460
|
-
import { chmodSync as chmodSync7, existsSync as
|
|
24461
|
-
import { join as
|
|
24734
|
+
import { chmodSync as chmodSync7, existsSync as existsSync30, mkdirSync as mkdirSync23, readFileSync as readFileSync31, renameSync as renameSync9, writeFileSync as writeFileSync26 } from "node:fs";
|
|
24735
|
+
import { join as join27, resolve as resolve11 } from "node:path";
|
|
24462
24736
|
var configDir2 = (home, env = process.env) => {
|
|
24463
24737
|
const o = env.SLEDS_HOME?.trim();
|
|
24464
|
-
return o ?
|
|
24738
|
+
return o ? resolve11(home, o) : join27(home, ".config", "sleds");
|
|
24465
24739
|
};
|
|
24466
|
-
var configPath2 = (home) =>
|
|
24740
|
+
var configPath2 = (home) => join27(configDir2(home), "config.json");
|
|
24467
24741
|
var isObject17 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
24468
24742
|
var optString2 = (v) => typeof v === "string" ? v : undefined;
|
|
24469
24743
|
var parsePriorEnv2 = (v) => {
|
|
@@ -24595,7 +24869,7 @@ var parseOrgInfo2 = (raw) => {
|
|
|
24595
24869
|
};
|
|
24596
24870
|
var readConfig2 = (home) => {
|
|
24597
24871
|
const p = configPath2(home);
|
|
24598
|
-
if (!
|
|
24872
|
+
if (!existsSync30(p))
|
|
24599
24873
|
return {};
|
|
24600
24874
|
return parseConfig2(JSON.parse(readFileSync31(p, "utf8")));
|
|
24601
24875
|
};
|
|
@@ -24649,15 +24923,15 @@ var defaultExec5 = (cmd, args) => {
|
|
|
24649
24923
|
};
|
|
24650
24924
|
|
|
24651
24925
|
// src/settings.ts
|
|
24652
|
-
import { dirname as dirname18, join as
|
|
24926
|
+
import { dirname as dirname18, join as join28, resolve as resolve12 } from "node:path";
|
|
24653
24927
|
var withSeatEnv2 = (command, home, env = process.env, org) => {
|
|
24654
24928
|
const parts = [];
|
|
24655
24929
|
const sh = env.SLEDS_HOME?.trim();
|
|
24656
24930
|
const cc = env.CLAUDE_CONFIG_DIR?.trim();
|
|
24657
24931
|
if (sh)
|
|
24658
|
-
parts.push(`SLEDS_HOME=${shellWord2(
|
|
24932
|
+
parts.push(`SLEDS_HOME=${shellWord2(resolve12(home, sh))}`);
|
|
24659
24933
|
if (cc)
|
|
24660
|
-
parts.push(`CLAUDE_CONFIG_DIR=${shellWord2(
|
|
24934
|
+
parts.push(`CLAUDE_CONFIG_DIR=${shellWord2(resolve12(home, cc))}`);
|
|
24661
24935
|
parts.push(command);
|
|
24662
24936
|
return pinOrg4(parts.join(" "), org);
|
|
24663
24937
|
};
|
|
@@ -25148,7 +25422,7 @@ ${renderHelpText(argv[1])}`);
|
|
|
25148
25422
|
case "version":
|
|
25149
25423
|
case "--version":
|
|
25150
25424
|
case "-v":
|
|
25151
|
-
console.log("sleds 0.1.
|
|
25425
|
+
console.log("sleds 0.1.44");
|
|
25152
25426
|
return 0;
|
|
25153
25427
|
default:
|
|
25154
25428
|
console.error(`unknown command: ${cmd}
|