@sleds/cli 0.1.46 → 0.1.47
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/README.md +4 -2
- package/dist/sleds.mjs +450 -229
- package/package.json +2 -1
package/dist/sleds.mjs
CHANGED
|
@@ -295,7 +295,6 @@ var init_sledSort = __esm(() => {
|
|
|
295
295
|
function slugify(text, max = 63) {
|
|
296
296
|
return text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, max);
|
|
297
297
|
}
|
|
298
|
-
|
|
299
298
|
// ../../packages/shared/src/seat/agents.ts
|
|
300
299
|
var init_agents = () => {};
|
|
301
300
|
// ../../packages/shared/src/seat/burn.ts
|
|
@@ -2086,7 +2085,7 @@ ${state}`)}, fillcolor="${fill}", color="${border}"${style}];`);
|
|
|
2086
2085
|
`)}
|
|
2087
2086
|
`;
|
|
2088
2087
|
}
|
|
2089
|
-
var ROUTE_APPROACH_MAX = 2000, PLAN_APPROACH_MAX = 1200, PLAN_LIST_MAX = 8, PLAN_LINE_MAX = 240, CONTROL, MAX_NODES = 24, DEPTH_WARN = 4, norm2 = (s) => s.trim().toUpperCase(), AREA_ROOTS, NOT_AREAS, sameRepo = (a, b) => a.length === 0 || b.length === 0 || a.some((r) => b.includes(r)), DOT_COLORS, ROUTE_DRAFT_RULE = "
|
|
2088
|
+
var ROUTE_APPROACH_MAX = 2000, PLAN_APPROACH_MAX = 1200, PLAN_LIST_MAX = 8, PLAN_LINE_MAX = 240, CONTROL, MAX_NODES = 24, DEPTH_WARN = 4, norm2 = (s) => s.trim().toUpperCase(), AREA_ROOTS, NOT_AREAS, sameRepo = (a, b) => a.length === 0 || b.length === 0 || a.some((r) => b.includes(r)), DOT_COLORS, ROUTE_DRAFT_RULE = "Plan the route: PR-sized nodes, file-disjoint where they run in parallel, each with a title, the files or areas it touches, the repo, and the nodes it waits on (by key: A, B, C…). Prefer wide waves over chains deeper than four. Make the tough calls once, so each node's session follows them: an `approach` paragraph for the whole route, and on each node a `plan` — its approach, what it `provides` that later nodes rely on (names, shapes, files), what it `expects` from the nodes it waits on, and the `doneChecks` that say it landed. Show the graph and the plans as text and ask for a yes; file nothing before it. An item with children takes no nodes: its children are the work, and their order lives in their blockedBy. Then `route {q, approach, nodes: [{key, title, touches, repos, blockedBy, plan: {approach, provides, expects, doneChecks}}], confirm: true}`.";
|
|
2090
2089
|
var init_route = __esm(() => {
|
|
2091
2090
|
CONTROL = /[\u0000-\u0008\u000b-\u001f\u007f-\u009f]/g;
|
|
2092
2091
|
AREA_ROOTS = new Set(["apps", "packages", "services", "libs", "crates", "modules"]);
|
|
@@ -2598,7 +2597,11 @@ function failureText(e, timeoutMs) {
|
|
|
2598
2597
|
function fetchClient(o) {
|
|
2599
2598
|
const fetchFn = o.fetchFn ?? fetch;
|
|
2600
2599
|
const base = o.proxyUrl.replace(/\/+$/, "");
|
|
2601
|
-
const headers = {
|
|
2600
|
+
const headers = {
|
|
2601
|
+
"content-type": "application/json",
|
|
2602
|
+
authorization: `Bearer ${o.token}`,
|
|
2603
|
+
...o.version ? { "x-sleds-version": o.version } : {}
|
|
2604
|
+
};
|
|
2602
2605
|
const timeout = () => AbortSignal.timeout(o.timeoutMs ?? MCP_TIMEOUT_MS);
|
|
2603
2606
|
return {
|
|
2604
2607
|
async post(path, body) {
|
|
@@ -3411,7 +3414,7 @@ An engine (or you) takes a ready node with \`sled {take: "${key}/<key>"}\`; Run
|
|
|
3411
3414
|
}
|
|
3412
3415
|
if (nodes.length > 0)
|
|
3413
3416
|
return {
|
|
3414
|
-
text: "Show the person the graph as text and ask for a yes; then call route again with the same nodes and confirm: true. With nobody to ask (a
|
|
3417
|
+
text: "Show the person the graph as text and ask for a yes; then call route again with the same nodes and confirm: true. With nobody to ask (a planning session), call again with propose: true instead.",
|
|
3415
3418
|
isError: true
|
|
3416
3419
|
};
|
|
3417
3420
|
const r = await ctx.client.get(`/proxy/route?q=${encodeURIComponent(q)}`);
|
|
@@ -3425,7 +3428,7 @@ An engine (or you) takes a ready node with \`sled {take: "${key}/<key>"}\`; Run
|
|
|
3425
3428
|
const key = str5(r.key) ?? q;
|
|
3426
3429
|
const n = Array.isArray(proposed.nodes) ? proposed.nodes.length : 0;
|
|
3427
3430
|
return {
|
|
3428
|
-
text: `${proposalText(str5(r.text)) || `${key} · route
|
|
3431
|
+
text: `${proposalText(str5(r.text)) || `${key} · route planned, not filed — ${n} nodes`}
|
|
3429
3432
|
|
|
3430
3433
|
${PROPOSED_NEXT(key)}`,
|
|
3431
3434
|
structured: { key, nodes: 0, proposed: n }
|
|
@@ -4434,7 +4437,7 @@ async function handleLine(line, ctx) {
|
|
|
4434
4437
|
return isNotification ? null : errorResponse(id, -32601, `method not found: ${method}`);
|
|
4435
4438
|
}
|
|
4436
4439
|
}
|
|
4437
|
-
var PROTOCOL_VERSION = "2025-06-18", SERVER_INFO, SERVER_INSTRUCTIONS, MCP_TIMEOUT_MS = 5000, sourceSchema, specSchema, TOOLS, VIEW_TOOLS, NOT_SET_UP, UNREACHABLE, isObject4 = (v) => typeof v === "object" && v !== null && !Array.isArray(v), num3 = (v) => typeof v === "number" && Number.isFinite(v) ? v : undefined, str5 = (v) => typeof v === "string" ? v : undefined, errorMessage = (j) => isObject4(j?.error) ? str5(j.error.message) : str5(j?.error), proposalText = (t) => (t ?? "").replace(/\n*Nothing runs until a person says yes:[^\n]*$/, ""), PROPOSED_NEXT = (key) => `Nothing runs until a person approves it: Approve in the SLEDS app or on the item page, or \`sleds route approve ${key}\`. If you are a
|
|
4440
|
+
var PROTOCOL_VERSION = "2025-06-18", SERVER_INFO, SERVER_INSTRUCTIONS, MCP_TIMEOUT_MS = 5000, sourceSchema, specSchema, TOOLS, VIEW_TOOLS, NOT_SET_UP, UNREACHABLE, isObject4 = (v) => typeof v === "object" && v !== null && !Array.isArray(v), num3 = (v) => typeof v === "number" && Number.isFinite(v) ? v : undefined, str5 = (v) => typeof v === "string" ? v : undefined, errorMessage = (j) => isObject4(j?.error) ? str5(j.error.message) : str5(j?.error), proposalText = (t) => (t ?? "").replace(/\n*Nothing runs until a person says yes:[^\n]*$/, ""), PROPOSED_NEXT = (key) => `Nothing runs until a person approves it: Approve in the SLEDS app or on the item page, or \`sleds route approve ${key}\`. If you are a planning session, stop here.`, strList = (v) => Array.isArray(v) ? v.filter((x) => typeof x === "string") : undefined, RELATION_HOWS, UI_RESOURCES, response = (id, result) => JSON.stringify({ jsonrpc: "2.0", id, result }), errorResponse = (id, code, message) => JSON.stringify({ jsonrpc: "2.0", id, error: { code, message } });
|
|
4438
4441
|
var init_server = __esm(() => {
|
|
4439
4442
|
init_worth();
|
|
4440
4443
|
init_intake();
|
|
@@ -4722,7 +4725,7 @@ var init_server = __esm(() => {
|
|
|
4722
4725
|
},
|
|
4723
4726
|
{
|
|
4724
4727
|
name: "route",
|
|
4725
|
-
description: "The route — an item's internal order as PR-sized nodes with blockers (spec 26). With only `q`: the route as filed (each node's state, what it waits on, the ready set, where each run can be watched), or, when none is filed, the pack and the
|
|
4728
|
+
description: "The route — an item's internal order as PR-sized nodes with blockers (spec 26). With only `q`: the route as filed (each node's state, what it waits on, the ready set, where each run can be watched), or, when none is filed, the pack and the planning rule so you plan one (Plan route — the AI step; a person's hand editor on the item page is Edit route). Planning: PR-sized nodes, file-disjoint where they run in parallel, each with a title, the files or areas it touches, the repo, and the nodes it waits on by key (A, B, C…); prefer wide waves over chains deeper than four. Make the tough calls once: an `approach` for the route and a `plan` on each node (its approach, what it provides to later nodes, what it expects from the nodes it waits on, its done-checks), so each node's session follows them instead of re-planning. Show the graph and the plans as text and ask for a yes; file nothing before it. Then call again with `nodes` and `confirm: true`. An item with children is refused nodes — its children are the work: set their order with blockedBy on them. The item lands only when every child has landed. Planning it again shows what changed; a node with a run or a PR is never removed. Ready is computed from landed blockers, never set. With nobody to ask (a planning session an engine started, spec 26 §5.1): call with `nodes` and `propose: true` instead — the route is held on the item for a person's yes and nothing is filed; then stop. A read of an item with a proposal shows it as planned, not filed.",
|
|
4726
4729
|
inputSchema: {
|
|
4727
4730
|
type: "object",
|
|
4728
4731
|
properties: {
|
|
@@ -4733,7 +4736,7 @@ var init_server = __esm(() => {
|
|
|
4733
4736
|
},
|
|
4734
4737
|
nodes: {
|
|
4735
4738
|
type: "array",
|
|
4736
|
-
description: "The
|
|
4739
|
+
description: "The planned nodes, in route order. Keys are minted (A, B, C…) when absent.",
|
|
4737
4740
|
items: {
|
|
4738
4741
|
type: "object",
|
|
4739
4742
|
properties: {
|
|
@@ -4789,7 +4792,7 @@ var init_server = __esm(() => {
|
|
|
4789
4792
|
},
|
|
4790
4793
|
propose: {
|
|
4791
4794
|
type: "boolean",
|
|
4792
|
-
description: "true holds the nodes on the item as a
|
|
4795
|
+
description: "true holds the nodes on the item as a planned route, waiting for a person's yes; nothing is filed. For a planning session with nobody at the keyboard — with a person here, ask and confirm instead."
|
|
4793
4796
|
},
|
|
4794
4797
|
disjoint: {
|
|
4795
4798
|
type: "boolean",
|
|
@@ -6455,11 +6458,15 @@ var init_flags = () => {};
|
|
|
6455
6458
|
// ../../packages/shared/src/sentry/sentry.ts
|
|
6456
6459
|
var init_sentry = () => {};
|
|
6457
6460
|
|
|
6461
|
+
// ../../packages/shared/src/pack/outside.ts
|
|
6462
|
+
var init_outside = () => {};
|
|
6463
|
+
|
|
6458
6464
|
// ../../packages/shared/src/pack/pack.ts
|
|
6459
6465
|
var init_pack = __esm(() => {
|
|
6460
6466
|
init_flags();
|
|
6461
6467
|
init_profile();
|
|
6462
6468
|
init_sentry();
|
|
6469
|
+
init_outside();
|
|
6463
6470
|
init_setup();
|
|
6464
6471
|
});
|
|
6465
6472
|
// ../../packages/shared/src/pack/prHeader.ts
|
|
@@ -6471,6 +6478,7 @@ var init_pack2 = __esm(() => {
|
|
|
6471
6478
|
init_setup();
|
|
6472
6479
|
init_pack();
|
|
6473
6480
|
init_prHeader();
|
|
6481
|
+
init_outside();
|
|
6474
6482
|
});
|
|
6475
6483
|
|
|
6476
6484
|
// ../../packages/shared/src/deploys/deploys.ts
|
|
@@ -8588,8 +8596,8 @@ var init_seat = __esm(() => {
|
|
|
8588
8596
|
});
|
|
8589
8597
|
|
|
8590
8598
|
// src/index.ts
|
|
8591
|
-
import { realpathSync as realpathSync3 } from "fs";
|
|
8592
|
-
import { homedir, platform as platform3 } from "os";
|
|
8599
|
+
import { existsSync as existsSync31, realpathSync as realpathSync3 } from "fs";
|
|
8600
|
+
import { homedir as homedir3, platform as platform3 } from "os";
|
|
8593
8601
|
import { fileURLToPath } from "url";
|
|
8594
8602
|
|
|
8595
8603
|
// ../../packages/shared/src/index.ts
|
|
@@ -9930,7 +9938,7 @@ import {
|
|
|
9930
9938
|
writeFileSync as writeFileSync17
|
|
9931
9939
|
} from "node:fs";
|
|
9932
9940
|
import { tmpdir } from "node:os";
|
|
9933
|
-
import { join as
|
|
9941
|
+
import { join as join21, resolve as resolve9 } from "node:path";
|
|
9934
9942
|
|
|
9935
9943
|
// src/agentMcp.ts
|
|
9936
9944
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
@@ -10387,20 +10395,37 @@ import { basename as basename3, dirname as dirname10, join as join12 } from "nod
|
|
|
10387
10395
|
|
|
10388
10396
|
// src/runners/sandbox.ts
|
|
10389
10397
|
var absRule = (dir) => `/${dir.replace(/\/+$/, "")}/**`;
|
|
10398
|
+
var gitDenyWrite = (gitCommonDir) => {
|
|
10399
|
+
const g = gitCommonDir.replace(/\/+$/, "");
|
|
10400
|
+
return {
|
|
10401
|
+
files: [`${g}/config`, `${g}/config.worktree`, `${g}/worktrees/*/config.worktree`],
|
|
10402
|
+
dirs: [`${g}/hooks`]
|
|
10403
|
+
};
|
|
10404
|
+
};
|
|
10390
10405
|
var sandboxSettings = (o) => {
|
|
10391
10406
|
const domains = [...new Set(o.allow ?? [])];
|
|
10407
|
+
const git = gitDenyWrite(o.gitCommonDir);
|
|
10392
10408
|
return {
|
|
10393
10409
|
sandbox: {
|
|
10394
10410
|
enabled: true,
|
|
10395
10411
|
allowUnsandboxedCommands: false,
|
|
10396
10412
|
failIfUnavailable: true,
|
|
10397
|
-
filesystem: {
|
|
10413
|
+
filesystem: {
|
|
10414
|
+
denyRead: [...o.denyRead],
|
|
10415
|
+
allowWrite: [o.gitCommonDir],
|
|
10416
|
+
denyWrite: [...git.files, ...git.dirs]
|
|
10417
|
+
},
|
|
10398
10418
|
network: { allowedDomains: domains, strictAllowlist: true }
|
|
10399
10419
|
},
|
|
10400
10420
|
permissions: {
|
|
10401
|
-
deny:
|
|
10421
|
+
deny: [
|
|
10422
|
+
...o.denyRead.flatMap((d) => [`Read(${absRule(d)})`, `Edit(${absRule(d)})`]),
|
|
10423
|
+
...git.files.map((f) => `Edit(/${f})`),
|
|
10424
|
+
...git.dirs.map((d) => `Edit(${absRule(d)})`)
|
|
10425
|
+
],
|
|
10402
10426
|
allow: [`Edit(${absRule(o.gitCommonDir)})`, ...domains.map((d) => `WebFetch(domain:${d})`)]
|
|
10403
|
-
}
|
|
10427
|
+
},
|
|
10428
|
+
env: { CLAUDE_CODE_SUBPROCESS_ENV_SCRUB: "1" }
|
|
10404
10429
|
};
|
|
10405
10430
|
};
|
|
10406
10431
|
var sandboxAgentKind = (agent) => {
|
|
@@ -11131,7 +11156,7 @@ function beatBody(state, flags, host = {}, cap = {}) {
|
|
|
11131
11156
|
name: flags.name,
|
|
11132
11157
|
os: host.os ?? process.platform,
|
|
11133
11158
|
runner: flags.runner,
|
|
11134
|
-
version: host.version ?? "0.1.
|
|
11159
|
+
version: host.version ?? "0.1.47" ?? "dev",
|
|
11135
11160
|
running: live.length,
|
|
11136
11161
|
items: live.slice(0, BEAT_ITEMS).map((r) => `${r.item}/${r.node}`),
|
|
11137
11162
|
...cap.atOnce !== undefined ? { atOnce: cap.atOnce } : {},
|
|
@@ -11148,13 +11173,28 @@ function beatBody(state, flags, host = {}, cap = {}) {
|
|
|
11148
11173
|
} : {}
|
|
11149
11174
|
};
|
|
11150
11175
|
}
|
|
11176
|
+
var versionOrNull = (v) => v === null || typeof v === "string";
|
|
11177
|
+
function updateOf(v) {
|
|
11178
|
+
if (typeof v !== "object" || v === null)
|
|
11179
|
+
return;
|
|
11180
|
+
const { target, minimum, manifestUrl } = v;
|
|
11181
|
+
return versionOrNull(target) && versionOrNull(minimum) && versionOrNull(manifestUrl) ? { target, minimum, manifestUrl } : undefined;
|
|
11182
|
+
}
|
|
11151
11183
|
async function postBeat(client, body) {
|
|
11152
11184
|
try {
|
|
11153
11185
|
const r = await client.postFull("/proxy/engine/beat", { ...body });
|
|
11154
|
-
if (r?.status === 200 && r.json?.ok === true)
|
|
11155
|
-
|
|
11186
|
+
if (r?.status === 200 && r.json?.ok === true) {
|
|
11187
|
+
const update = updateOf(r.json.update);
|
|
11188
|
+
return update ? { ok: true, update } : { ok: true };
|
|
11189
|
+
}
|
|
11156
11190
|
const error = r?.json?.error;
|
|
11157
|
-
|
|
11191
|
+
if (typeof error !== "string")
|
|
11192
|
+
return { ok: false };
|
|
11193
|
+
if (r?.status === 409)
|
|
11194
|
+
return { ok: false, refused: error };
|
|
11195
|
+
if (r?.status === 426)
|
|
11196
|
+
return { ok: false, refused: error, below: true };
|
|
11197
|
+
return { ok: false };
|
|
11158
11198
|
} catch {
|
|
11159
11199
|
return { ok: false };
|
|
11160
11200
|
}
|
|
@@ -12207,6 +12247,18 @@ function groupOf(j, item) {
|
|
|
12207
12247
|
const title = str6(j.title);
|
|
12208
12248
|
return title ? { key, title } : null;
|
|
12209
12249
|
}
|
|
12250
|
+
function runOf(v) {
|
|
12251
|
+
if (!Array.isArray(v))
|
|
12252
|
+
return;
|
|
12253
|
+
return v.filter(isObject8).flatMap((x) => {
|
|
12254
|
+
const repo = str6(x.repo)?.trim();
|
|
12255
|
+
if (!repo)
|
|
12256
|
+
return [];
|
|
12257
|
+
const install = str6(x.install)?.trim();
|
|
12258
|
+
const gate = str6(x.gate)?.trim();
|
|
12259
|
+
return [{ repo, ...install ? { install } : {}, ...gate ? { gate } : {} }];
|
|
12260
|
+
});
|
|
12261
|
+
}
|
|
12210
12262
|
function sameEngine(a, b) {
|
|
12211
12263
|
const bare = (s) => s.trim().replace(/^engine:/, "").toLowerCase();
|
|
12212
12264
|
return bare(a) === bare(b);
|
|
@@ -12258,14 +12310,14 @@ var PROFILE_TEXT = [
|
|
|
12258
12310
|
"reposDir",
|
|
12259
12311
|
"engine"
|
|
12260
12312
|
];
|
|
12261
|
-
var SHELL_TEXT = ["agent", "launcher"];
|
|
12313
|
+
var SHELL_TEXT = ["agent", "launcher", "mode"];
|
|
12262
12314
|
function profileOf(r) {
|
|
12263
12315
|
if (!r || r.ok === false || !isObject8(r.profile))
|
|
12264
12316
|
return null;
|
|
12265
12317
|
const p = r.profile;
|
|
12266
12318
|
const member = isObject8(r.member) ? r.member : {};
|
|
12267
12319
|
const out = {
|
|
12268
|
-
pickup: p.pickup === "auto" ? "auto" : "approve",
|
|
12320
|
+
pickup: p.pickup === "auto" && member.pickup === "auto" ? "auto" : "approve",
|
|
12269
12321
|
...HOLD_DEFAULTS2,
|
|
12270
12322
|
holdOff: p.holdOff === true
|
|
12271
12323
|
};
|
|
@@ -12284,8 +12336,8 @@ function profileOf(r) {
|
|
|
12284
12336
|
else if (str6(p[k])?.trim())
|
|
12285
12337
|
notYours.push(k);
|
|
12286
12338
|
}
|
|
12287
|
-
if (
|
|
12288
|
-
|
|
12339
|
+
if (p.pickup === "auto" && out.pickup !== "auto")
|
|
12340
|
+
notYours.push("pickup");
|
|
12289
12341
|
const atOnce = num5(p.atOnce);
|
|
12290
12342
|
if (atOnce !== undefined && atOnce >= 1)
|
|
12291
12343
|
out.atOnce = Math.round(atOnce);
|
|
@@ -12304,13 +12356,17 @@ function profileOf(r) {
|
|
|
12304
12356
|
if (names.length)
|
|
12305
12357
|
out.mcpAllow = names;
|
|
12306
12358
|
}
|
|
12307
|
-
if (
|
|
12359
|
+
if (p.sandbox === true || p.sandbox === false && member.sandbox === false)
|
|
12308
12360
|
out.sandbox = p.sandbox;
|
|
12361
|
+
else if (p.sandbox === false)
|
|
12362
|
+
notYours.push("sandbox");
|
|
12309
12363
|
if (Array.isArray(p.sandboxAllow)) {
|
|
12310
12364
|
const hosts = p.sandboxAllow.filter((x) => typeof x === "string" && x.trim() !== "");
|
|
12311
12365
|
if (hosts.length)
|
|
12312
12366
|
out.sandboxAllow = hosts;
|
|
12313
12367
|
}
|
|
12368
|
+
if (notYours.length)
|
|
12369
|
+
out.notYours = notYours;
|
|
12314
12370
|
return out;
|
|
12315
12371
|
}
|
|
12316
12372
|
async function readProfile(client) {
|
|
@@ -12436,7 +12492,7 @@ function sledsSource(client, o) {
|
|
|
12436
12492
|
...o.leaseMin !== undefined ? { leaseMin: o.leaseMin } : {}
|
|
12437
12493
|
});
|
|
12438
12494
|
if (!r || r.status >= 300 || !r.json || r.json.ok === false) {
|
|
12439
|
-
o.log?.(`${pending ? `${item}: could not claim
|
|
12495
|
+
o.log?.(`${pending ? `${item}: could not claim it to plan its route again` : started ? `${item}: Start could not claim it for planning` : `Pickup: Auto could not claim ${item} for planning`} — ${r ? serverMessage(r) : UNREACHABLE2}`);
|
|
12440
12496
|
return null;
|
|
12441
12497
|
}
|
|
12442
12498
|
const j = r.json;
|
|
@@ -12458,7 +12514,7 @@ function sledsSource(client, o) {
|
|
|
12458
12514
|
route: routeText(brief, isObject8(row.route) ? row.route.states : null)
|
|
12459
12515
|
};
|
|
12460
12516
|
}
|
|
12461
|
-
o.log?.(redraft ? `${item}:
|
|
12517
|
+
o.log?.(redraft ? `${item}: planning the route again from ${redraft.by}'s answer — it waits for a yes` : `${started ? `${item}: Start` : "Pickup: Auto"} is planning ${started ? "its" : `${item}'s`} route first (${why.join(", ")}) — it waits for a yes`);
|
|
12462
12518
|
const leaseUntil = num5(j.leaseUntil);
|
|
12463
12519
|
const claim = {
|
|
12464
12520
|
item,
|
|
@@ -12560,6 +12616,7 @@ function sledsSource(client, o) {
|
|
|
12560
12616
|
}
|
|
12561
12617
|
const leaseUntil = num5(hit.leaseUntil);
|
|
12562
12618
|
const runToken = str6(hit.runToken) ?? (taken.length === 1 ? str6(r.json?.runToken) : undefined);
|
|
12619
|
+
const run = runOf(hit.run);
|
|
12563
12620
|
const claim = {
|
|
12564
12621
|
item,
|
|
12565
12622
|
node: str6(hit.node) ?? node,
|
|
@@ -12571,7 +12628,8 @@ function sledsSource(client, o) {
|
|
|
12571
12628
|
...t.seatId ? { seatId: t.seatId } : {},
|
|
12572
12629
|
...str6(hit.answer) ? { answer: str6(hit.answer) } : {},
|
|
12573
12630
|
...runToken ? { runToken } : {},
|
|
12574
|
-
...group ? { group } : {}
|
|
12631
|
+
...group ? { group } : {},
|
|
12632
|
+
...run ? { run } : {}
|
|
12575
12633
|
};
|
|
12576
12634
|
return { ok: true, claim };
|
|
12577
12635
|
},
|
|
@@ -13091,17 +13149,20 @@ var MANAGERS = new Set(["pnpm", "npm", "yarn", "bun"]);
|
|
|
13091
13149
|
var INSTALL_VERBS = new Set(["install", "i", "ci"]);
|
|
13092
13150
|
function installArgv(command) {
|
|
13093
13151
|
const line = command?.trim().replace(/^`|`$/g, "") ?? "";
|
|
13094
|
-
if (!line || /[;&|<>$`()]/.test(line))
|
|
13152
|
+
if (!line || /[;&|<>$`()\n]/.test(line))
|
|
13095
13153
|
return null;
|
|
13096
13154
|
const argv = shellWords(line);
|
|
13097
13155
|
const [tool, verb] = argv;
|
|
13098
13156
|
if (!tool || !MANAGERS.has(tool))
|
|
13099
13157
|
return null;
|
|
13100
|
-
|
|
13101
|
-
|
|
13102
|
-
|
|
13158
|
+
let rest;
|
|
13159
|
+
if (tool === "yarn")
|
|
13160
|
+
rest = argv.slice(verb === "install" ? 2 : 1);
|
|
13161
|
+
else if (verb && INSTALL_VERBS.has(verb))
|
|
13162
|
+
rest = argv.slice(2);
|
|
13163
|
+
else
|
|
13103
13164
|
return null;
|
|
13104
|
-
return argv;
|
|
13165
|
+
return rest.every((a) => a.startsWith("-")) ? argv : null;
|
|
13105
13166
|
}
|
|
13106
13167
|
function lockfileInstall(path, exists) {
|
|
13107
13168
|
if (exists(join15(path, "pnpm-lock.yaml")))
|
|
@@ -13114,57 +13175,59 @@ function lockfileInstall(path, exists) {
|
|
|
13114
13175
|
return ["npm", "ci"];
|
|
13115
13176
|
return null;
|
|
13116
13177
|
}
|
|
13117
|
-
|
|
13118
|
-
|
|
13119
|
-
|
|
13120
|
-
|
|
13121
|
-
|
|
13122
|
-
|
|
13123
|
-
|
|
13124
|
-
|
|
13125
|
-
|
|
13126
|
-
|
|
13127
|
-
|
|
13128
|
-
|
|
13129
|
-
|
|
13130
|
-
|
|
13131
|
-
|
|
13132
|
-
|
|
13133
|
-
|
|
13134
|
-
|
|
13135
|
-
|
|
13136
|
-
|
|
13137
|
-
|
|
13138
|
-
|
|
13139
|
-
|
|
13140
|
-
const
|
|
13141
|
-
|
|
13142
|
-
|
|
13143
|
-
|
|
13144
|
-
|
|
13145
|
-
|
|
13146
|
-
|
|
13147
|
-
|
|
13148
|
-
continue;
|
|
13149
|
-
const m = line.match(/^\s*-\s*([^:`]+?):\s*`(.+)`\s*$/);
|
|
13150
|
-
if (!m?.[1] || !m[2])
|
|
13151
|
-
continue;
|
|
13152
|
-
const name = m[1].trim().toLowerCase();
|
|
13153
|
-
if (name === "done means" || name.startsWith("try it"))
|
|
13154
|
-
continue;
|
|
13155
|
-
if (want && name === want)
|
|
13156
|
-
return m[2];
|
|
13157
|
-
first ??= m[2];
|
|
13158
|
-
}
|
|
13159
|
-
return first;
|
|
13178
|
+
var INTERPRETERS = new Set([
|
|
13179
|
+
"node",
|
|
13180
|
+
"bun",
|
|
13181
|
+
"deno",
|
|
13182
|
+
"python",
|
|
13183
|
+
"python3",
|
|
13184
|
+
"sh",
|
|
13185
|
+
"bash",
|
|
13186
|
+
"zsh",
|
|
13187
|
+
"fish",
|
|
13188
|
+
"npx",
|
|
13189
|
+
"pnpx",
|
|
13190
|
+
"bunx",
|
|
13191
|
+
"dlx",
|
|
13192
|
+
"env",
|
|
13193
|
+
"eval",
|
|
13194
|
+
"exec",
|
|
13195
|
+
"ruby",
|
|
13196
|
+
"perl",
|
|
13197
|
+
"sudo"
|
|
13198
|
+
]);
|
|
13199
|
+
function runsInterpreter(part) {
|
|
13200
|
+
const [first = "", second, third] = part.split(/\s+/);
|
|
13201
|
+
const tool = first.split("/").pop() ?? first;
|
|
13202
|
+
if (tool.includes("=") || INTERPRETERS.has(tool))
|
|
13203
|
+
return true;
|
|
13204
|
+
if (!MANAGERS.has(tool))
|
|
13205
|
+
return false;
|
|
13206
|
+
if (second === "dlx" || second === "x")
|
|
13207
|
+
return true;
|
|
13208
|
+
return second === "exec" && third !== undefined && INTERPRETERS.has(third.split("/").pop() ?? "");
|
|
13160
13209
|
}
|
|
13161
13210
|
function gateAllowRules(gate) {
|
|
13162
13211
|
const whole = gate?.trim();
|
|
13163
13212
|
if (!whole)
|
|
13164
13213
|
return [];
|
|
13214
|
+
if (/[$`()<>|&\n]/.test(whole.replace(/&&|\|\|/g, " ")))
|
|
13215
|
+
return [];
|
|
13165
13216
|
const parts = whole.split(/&&|\|\||;/).map((p) => p.trim()).filter(Boolean);
|
|
13217
|
+
if (parts.some(runsInterpreter))
|
|
13218
|
+
return [];
|
|
13166
13219
|
return [...new Set([whole, ...parts])].map((c) => `Bash(${c})`);
|
|
13167
13220
|
}
|
|
13221
|
+
function claimRunOf(run, repo) {
|
|
13222
|
+
if (!run?.length)
|
|
13223
|
+
return {};
|
|
13224
|
+
const want = repo?.trim().toLowerCase();
|
|
13225
|
+
const hit = want && run.find((r) => r.repo.trim().toLowerCase() === want) || run[0];
|
|
13226
|
+
return {
|
|
13227
|
+
...hit?.install ? { install: hit.install } : {},
|
|
13228
|
+
...hit?.gate ? { gate: hit.gate } : {}
|
|
13229
|
+
};
|
|
13230
|
+
}
|
|
13168
13231
|
function ensureInstalled(exec, path, fs, o = {}) {
|
|
13169
13232
|
if (!fs.exists(join15(path, "package.json")) || fs.exists(join15(path, "node_modules")))
|
|
13170
13233
|
return null;
|
|
@@ -13722,10 +13785,10 @@ async function tickOnce(d) {
|
|
|
13722
13785
|
let mcpConfig;
|
|
13723
13786
|
try {
|
|
13724
13787
|
const base = d.defaultBranch(d.exec, repoPath);
|
|
13725
|
-
const
|
|
13788
|
+
const { install, gate } = claimRunOf(claim.run, claim.repos[0]);
|
|
13789
|
+
const worktree = d.runner.makesWorktree ? repoPath : d.ensureWorktree(d.exec, repoPath, branch, worktreePath(repoPath, name), base, install) ?? worktreePath(repoPath, name);
|
|
13726
13790
|
const prTitle = d.prTitleOf?.(claim);
|
|
13727
13791
|
mcpConfig = engineMcpConfigFor(d, name, claim.runToken, at, worktree);
|
|
13728
|
-
const gate = packGateOf(claim.pack, claim.repos[0]);
|
|
13729
13792
|
const allow = gateAllowRules(gate);
|
|
13730
13793
|
const prompt = nodePrompt({
|
|
13731
13794
|
claim,
|
|
@@ -14699,7 +14762,7 @@ async function startDraft(d, claim, why, state, started, finished) {
|
|
|
14699
14762
|
};
|
|
14700
14763
|
state.runs.push(run);
|
|
14701
14764
|
d.writeState(state);
|
|
14702
|
-
d.log(claim.redraft ? `${at}:
|
|
14765
|
+
d.log(claim.redraft ? `${at}: planning the route again from ${claim.redraft.by}'s answer — it waits for a yes` : `${at}: planning the route${why.length ? ` (${why.join(", ")})` : ""} — it waits for a yes, unless it is one node inside the brief's touches`);
|
|
14703
14766
|
try {
|
|
14704
14767
|
await d.source.heartbeat(claim, watch);
|
|
14705
14768
|
} catch (e) {
|
|
@@ -14716,7 +14779,7 @@ async function settleDraft(d, run, claim, runner, finished) {
|
|
|
14716
14779
|
return true;
|
|
14717
14780
|
}
|
|
14718
14781
|
if (beat === "done") {
|
|
14719
|
-
d.log(`${ref(run)}: route
|
|
14782
|
+
d.log(`${ref(run)}: route planned — it waits for a person's yes`);
|
|
14720
14783
|
endDraft(d, run, runner);
|
|
14721
14784
|
return false;
|
|
14722
14785
|
}
|
|
@@ -14730,7 +14793,7 @@ async function settleDraft(d, run, claim, runner, finished) {
|
|
|
14730
14793
|
return false;
|
|
14731
14794
|
}
|
|
14732
14795
|
if (beat === "lost") {
|
|
14733
|
-
d.log(`${ref(run)}: the
|
|
14796
|
+
d.log(`${ref(run)}: the planning claim was lost — stopping the session`);
|
|
14734
14797
|
endDraft(d, run, runner);
|
|
14735
14798
|
return false;
|
|
14736
14799
|
}
|
|
@@ -14746,7 +14809,7 @@ async function settleDraft(d, run, claim, runner, finished) {
|
|
|
14746
14809
|
let log = "";
|
|
14747
14810
|
if (status === "exited") {
|
|
14748
14811
|
try {
|
|
14749
|
-
log = runner.read(run.handle) || "The
|
|
14812
|
+
log = runner.read(run.handle) || "The planning session exited with no route proposed.";
|
|
14750
14813
|
} catch (e) {
|
|
14751
14814
|
log = `(the session's output could not be read: ${message(e)})`;
|
|
14752
14815
|
}
|
|
@@ -15689,6 +15752,18 @@ init_machine();
|
|
|
15689
15752
|
init_state();
|
|
15690
15753
|
init_meter();
|
|
15691
15754
|
|
|
15755
|
+
// src/runners/gitGuard.ts
|
|
15756
|
+
import { basename as basename4 } from "node:path";
|
|
15757
|
+
var GIT_GUARD_ENV = {
|
|
15758
|
+
GIT_CONFIG_COUNT: "2",
|
|
15759
|
+
GIT_CONFIG_KEY_0: "core.fsmonitor",
|
|
15760
|
+
GIT_CONFIG_VALUE_0: "false",
|
|
15761
|
+
GIT_CONFIG_KEY_1: "core.hooksPath",
|
|
15762
|
+
GIT_CONFIG_VALUE_1: "/dev/null"
|
|
15763
|
+
};
|
|
15764
|
+
var GUARDED = new Set(["git", "gh"]);
|
|
15765
|
+
var guardGit = (exec) => (cmd, args, o) => GUARDED.has(basename4(cmd)) ? exec(cmd, args, { ...o, env: { ...o?.env, ...GIT_GUARD_ENV } }) : exec(cmd, args, o);
|
|
15766
|
+
|
|
15692
15767
|
// src/runners/command.ts
|
|
15693
15768
|
var expandCommandTemplate = (template, o) => {
|
|
15694
15769
|
const values = {
|
|
@@ -16630,7 +16705,7 @@ function flagsFromProfile(flags, given, profile, home) {
|
|
|
16630
16705
|
const used = [];
|
|
16631
16706
|
const skipped = [];
|
|
16632
16707
|
for (const k of profile.notYours ?? [])
|
|
16633
|
-
skipped.push(`${k} (the workspace default — the engine
|
|
16708
|
+
skipped.push(`${k} (the workspace default — the engine takes it only from your own profile)`);
|
|
16634
16709
|
if (profile.atOnce !== undefined && !has("at-once")) {
|
|
16635
16710
|
out.atOnce = profile.atOnce;
|
|
16636
16711
|
used.push(`at-once ${profile.atOnce}`);
|
|
@@ -16794,7 +16869,11 @@ function engineClient(o, org) {
|
|
|
16794
16869
|
const env = o.env ?? process.env;
|
|
16795
16870
|
const src = meterSource(o.home, undefined, { ...org ? { flag: org } : {}, env });
|
|
16796
16871
|
if (src)
|
|
16797
|
-
return fetchClient({
|
|
16872
|
+
return fetchClient({
|
|
16873
|
+
...src,
|
|
16874
|
+
timeoutMs: ENGINE_TIMEOUT_MS,
|
|
16875
|
+
version: "0.1.47"
|
|
16876
|
+
});
|
|
16798
16877
|
const asked = org?.trim() || env.SLEDS_ORG?.trim();
|
|
16799
16878
|
if (asked && !selectOrg(readConfig(o.home), org, env).seat)
|
|
16800
16879
|
return {
|
|
@@ -16858,7 +16937,7 @@ function engineToken(o, org) {
|
|
|
16858
16937
|
}
|
|
16859
16938
|
var withToken = (token, now) => token ? { token, tokenNow: now } : {};
|
|
16860
16939
|
function engineDeps(o, flags, source, runner, stateName) {
|
|
16861
|
-
const exec = o.exec ?? defaultExec;
|
|
16940
|
+
const exec = guardGit(o.exec ?? defaultExec);
|
|
16862
16941
|
const cwd = o.cwd ?? process.cwd();
|
|
16863
16942
|
const exists = o.exists ?? realExists;
|
|
16864
16943
|
const log = o.log ?? console.log;
|
|
@@ -16989,7 +17068,15 @@ function engineDeps(o, flags, source, runner, stateName) {
|
|
|
16989
17068
|
function sandboxDenyRead(home, env) {
|
|
16990
17069
|
return {
|
|
16991
17070
|
dirs: [...new Set([configDir(home, env), join16(home, ".config", "sleds")])],
|
|
16992
|
-
files: [
|
|
17071
|
+
files: [
|
|
17072
|
+
...new Set([
|
|
17073
|
+
tokenPath(home, env),
|
|
17074
|
+
join16(home, ".sleds-token"),
|
|
17075
|
+
settingsPath(home, env),
|
|
17076
|
+
backupPath(home, env),
|
|
17077
|
+
join16(claudeDir(home, env), "settings.local.json")
|
|
17078
|
+
])
|
|
17079
|
+
]
|
|
16993
17080
|
};
|
|
16994
17081
|
}
|
|
16995
17082
|
function engineSandboxSettings(home, env, gitCommonDir, allow) {
|
|
@@ -17046,7 +17133,7 @@ async function driveEngine(o, flags, deps, until = {}) {
|
|
|
17046
17133
|
runner: deps.runner.name,
|
|
17047
17134
|
atOnce: flags.atOnce,
|
|
17048
17135
|
interval: flags.interval,
|
|
17049
|
-
cliVersion: "0.1.
|
|
17136
|
+
cliVersion: "0.1.47"
|
|
17050
17137
|
};
|
|
17051
17138
|
const beat = (checkedAt) => {
|
|
17052
17139
|
const m = deps.machine;
|
|
@@ -17232,7 +17319,7 @@ async function drive(o, flags, deps, until, beat) {
|
|
|
17232
17319
|
var SEAT_CHANGED_EXIT = 3;
|
|
17233
17320
|
function engineRunner(o, flags) {
|
|
17234
17321
|
const runnerFor = o.runnerFor ?? runnerFor2;
|
|
17235
|
-
return runnerFor(flags.runner, o.exec ?? defaultExec, {
|
|
17322
|
+
return runnerFor(flags.runner, guardGit(o.exec ?? defaultExec), {
|
|
17236
17323
|
...flags.runnerCmd ? { command: flags.runnerCmd } : {}
|
|
17237
17324
|
});
|
|
17238
17325
|
}
|
|
@@ -17319,7 +17406,7 @@ async function enginePauseCmd(o) {
|
|
|
17319
17406
|
source = sledsSource(c, { engine, log });
|
|
17320
17407
|
}
|
|
17321
17408
|
const why = parsed.why ?? `paused on ${defaultEngineName(host)} (sleds engine pause)`;
|
|
17322
|
-
const exec = o.exec ?? defaultExec;
|
|
17409
|
+
const exec = guardGit(o.exec ?? defaultExec);
|
|
17323
17410
|
const gone = new Set;
|
|
17324
17411
|
for (const run of running) {
|
|
17325
17412
|
const at = `${run.item}/${run.node}`;
|
|
@@ -17368,13 +17455,18 @@ import {
|
|
|
17368
17455
|
writeFileSync as writeFileSync15
|
|
17369
17456
|
} from "node:fs";
|
|
17370
17457
|
import { hostname as hostname3 } from "node:os";
|
|
17371
|
-
import { basename as
|
|
17458
|
+
import { basename as basename5, dirname as dirname12, isAbsolute as isAbsolute2, join as join20 } from "node:path";
|
|
17372
17459
|
init_state();
|
|
17373
17460
|
|
|
17461
|
+
// src/runtime.ts
|
|
17462
|
+
import { homedir } from "node:os";
|
|
17463
|
+
import { join as join17, win32 } from "node:path";
|
|
17464
|
+
var sledsLink = (home = homedir(), platform = process.platform) => platform === "win32" ? win32.join(process.env.LOCALAPPDATA ?? win32.join(home, "AppData", "Local"), "sleds", "bin", "sleds.exe") : join17(home, ".sleds", "bin", "sleds");
|
|
17465
|
+
|
|
17374
17466
|
// src/schedule.ts
|
|
17375
17467
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
17376
17468
|
import { existsSync as existsSync14, mkdirSync as mkdirSync13, rmSync as rmSync5, writeFileSync as writeFileSync14 } from "node:fs";
|
|
17377
|
-
import { join as
|
|
17469
|
+
import { join as join18 } from "node:path";
|
|
17378
17470
|
var REVERT_LABEL = "ai.sleds.revert";
|
|
17379
17471
|
var defaultExec2 = (cmd, args) => {
|
|
17380
17472
|
const r = spawnSync4(cmd, [...args], { stdio: ["ignore", "ignore", "pipe"], encoding: "utf8" });
|
|
@@ -17382,7 +17474,7 @@ var defaultExec2 = (cmd, args) => {
|
|
|
17382
17474
|
return { ok: false, stderr: r.error.message };
|
|
17383
17475
|
return { ok: r.status === 0, stderr: r.stderr ?? "" };
|
|
17384
17476
|
};
|
|
17385
|
-
var plistPath = (home) =>
|
|
17477
|
+
var plistPath = (home) => join18(home, "Library", "LaunchAgents", `${REVERT_LABEL}.plist`);
|
|
17386
17478
|
var xmlEscape2 = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
17387
17479
|
var buildLaunchdPlist = (sledsArgv, deadline) => {
|
|
17388
17480
|
const args = [...sledsArgv, "off"].map((a) => ` <string>${xmlEscape2(a)}</string>`).join(`
|
|
@@ -17421,7 +17513,7 @@ var scheduleRevert = (d, deadlineMs) => {
|
|
|
17421
17513
|
if (d.platform === "darwin") {
|
|
17422
17514
|
const p = plistPath(d.home);
|
|
17423
17515
|
try {
|
|
17424
|
-
mkdirSync13(
|
|
17516
|
+
mkdirSync13(join18(d.home, "Library", "LaunchAgents"), { recursive: true });
|
|
17425
17517
|
d.exec("launchctl", ["unload", p]);
|
|
17426
17518
|
writeFileSync14(p, buildLaunchdPlist(d.sledsArgv, deadline));
|
|
17427
17519
|
const r = d.exec("launchctl", ["load", p]);
|
|
@@ -17461,16 +17553,16 @@ var cancelRevert = (d, kind) => {
|
|
|
17461
17553
|
};
|
|
17462
17554
|
|
|
17463
17555
|
// src/commands/engineSystemd.ts
|
|
17464
|
-
import { join as
|
|
17556
|
+
import { join as join19 } from "node:path";
|
|
17465
17557
|
var BOX_ENV_UNIT_PATH = "%h/.config/sleds/box.env";
|
|
17466
17558
|
function boxEnvPath(home) {
|
|
17467
|
-
return
|
|
17559
|
+
return join19(home, ".config", "sleds", "box.env");
|
|
17468
17560
|
}
|
|
17469
17561
|
function engineUnitDir(home) {
|
|
17470
|
-
return
|
|
17562
|
+
return join19(home, ".config", "systemd", "user");
|
|
17471
17563
|
}
|
|
17472
17564
|
function engineUnitPath(home, label) {
|
|
17473
|
-
return
|
|
17565
|
+
return join19(engineUnitDir(home), `${label}.service`);
|
|
17474
17566
|
}
|
|
17475
17567
|
function systemdQuote(s) {
|
|
17476
17568
|
const body = s.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/\n/g, "\\n").replace(/%/g, "%%").replace(/\$/g, "$$$$");
|
|
@@ -17513,9 +17605,10 @@ function parseEngineUnit(text) {
|
|
|
17513
17605
|
var ENGINE_LABEL = "ai.sleds.engine";
|
|
17514
17606
|
var ENGINE_INSTALL_USAGE = `usage: sleds engine install [engine flags] | sleds engine uninstall [--name <n>] [--org <slug>]
|
|
17515
17607
|
${ENGINE_USAGE}`;
|
|
17516
|
-
function stableArgv(argv, realpath = realpathSync) {
|
|
17608
|
+
function stableArgv(argv, realpath = realpathSync, home) {
|
|
17609
|
+
const link = sledsLink(home);
|
|
17517
17610
|
return argv.map((a) => {
|
|
17518
|
-
if (!isAbsolute2(a))
|
|
17611
|
+
if (!isAbsolute2(a) || a === link)
|
|
17519
17612
|
return a;
|
|
17520
17613
|
try {
|
|
17521
17614
|
return realpath(a);
|
|
@@ -17528,13 +17621,13 @@ function engineLabel(name, org, seat) {
|
|
|
17528
17621
|
return [ENGINE_LABEL, org, seat?.trim(), name].filter((p) => Boolean(p)).map((p, i) => i === 0 ? p : engineSlug(p)).join(".");
|
|
17529
17622
|
}
|
|
17530
17623
|
function enginePlistPath(home, name, org, seat) {
|
|
17531
|
-
return
|
|
17624
|
+
return join20(home, "Library", "LaunchAgents", `${engineLabel(name, org, seat)}.plist`);
|
|
17532
17625
|
}
|
|
17533
17626
|
function engineLogPath(stateDir, name) {
|
|
17534
|
-
return
|
|
17627
|
+
return join20(stateDir, `${engineSlug(name)}.log`);
|
|
17535
17628
|
}
|
|
17536
17629
|
function engineEventsPath(stateDir, name) {
|
|
17537
|
-
return
|
|
17630
|
+
return join20(stateDir, `${engineSlug(name)}.events.jsonl`);
|
|
17538
17631
|
}
|
|
17539
17632
|
var xmlEscape3 = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
17540
17633
|
function buildEnginePlist(o) {
|
|
@@ -17631,7 +17724,7 @@ function readEngines(dir, suffix, manager, parse) {
|
|
|
17631
17724
|
}
|
|
17632
17725
|
const out = [];
|
|
17633
17726
|
for (const name of names.filter((n) => n.startsWith(`${ENGINE_LABEL}.`) && n.endsWith(suffix))) {
|
|
17634
|
-
const path =
|
|
17727
|
+
const path = join20(dir, name);
|
|
17635
17728
|
let parsed;
|
|
17636
17729
|
try {
|
|
17637
17730
|
parsed = parse(readFileSync14(path, "utf8"), name);
|
|
@@ -17651,10 +17744,10 @@ function readEngines(dir, suffix, manager, parse) {
|
|
|
17651
17744
|
}
|
|
17652
17745
|
function installedEngines(home) {
|
|
17653
17746
|
return [
|
|
17654
|
-
...readEngines(
|
|
17747
|
+
...readEngines(join20(home, "Library", "LaunchAgents"), ".plist", "launchd", parseEnginePlist),
|
|
17655
17748
|
...readEngines(engineUnitDir(home), ".service", "systemd", (text, file) => {
|
|
17656
17749
|
const parsed = parseEngineUnit(text);
|
|
17657
|
-
return parsed && { label:
|
|
17750
|
+
return parsed && { label: basename5(file, ".service"), ...parsed };
|
|
17658
17751
|
})
|
|
17659
17752
|
];
|
|
17660
17753
|
}
|
|
@@ -17689,7 +17782,7 @@ function engineInstall(o) {
|
|
|
17689
17782
|
const label = engineLabel(parsed.name, parsed.org, seat);
|
|
17690
17783
|
const logPath = engineLogPath(stateDir, parsed.name);
|
|
17691
17784
|
mkdirSync14(stateDir, { recursive: true, mode: 448 });
|
|
17692
|
-
const sledsArgv = stableArgv(o.sledsArgv, o.realpath);
|
|
17785
|
+
const sledsArgv = stableArgv(o.sledsArgv, o.realpath, o.home);
|
|
17693
17786
|
const execPath = sledsArgv[0] ?? process.execPath;
|
|
17694
17787
|
const agentEnv = {
|
|
17695
17788
|
PATH: musherPath(o.home, execPath, env.PATH ?? ""),
|
|
@@ -17741,7 +17834,7 @@ function installUnit(a) {
|
|
|
17741
17834
|
const log = o.log ?? console.log;
|
|
17742
17835
|
const error = o.error ?? console.error;
|
|
17743
17836
|
const unit = engineUnitPath(o.home, label);
|
|
17744
|
-
const unitName =
|
|
17837
|
+
const unitName = basename5(unit);
|
|
17745
17838
|
const systemctl = (...args) => exec("systemctl", ["--user", ...args]);
|
|
17746
17839
|
mkdirSync14(dirname12(unit), { recursive: true });
|
|
17747
17840
|
if (existsSync15(unit))
|
|
@@ -17751,7 +17844,7 @@ function installUnit(a) {
|
|
|
17751
17844
|
continue;
|
|
17752
17845
|
if (engineArg(other.programArgs, "name") !== parsed.name)
|
|
17753
17846
|
continue;
|
|
17754
|
-
systemctl("disable", "--now",
|
|
17847
|
+
systemctl("disable", "--now", basename5(other.plist));
|
|
17755
17848
|
rmSync6(other.plist, { force: true });
|
|
17756
17849
|
log(`replaced ${other.label}, this engine as installed before`);
|
|
17757
17850
|
}
|
|
@@ -17810,13 +17903,13 @@ function engineUninstall(o) {
|
|
|
17810
17903
|
const unit = file.endsWith(".service");
|
|
17811
17904
|
const exec = o.exec ?? defaultExec2;
|
|
17812
17905
|
if (unit)
|
|
17813
|
-
exec("systemctl", ["--user", "disable", "--now",
|
|
17906
|
+
exec("systemctl", ["--user", "disable", "--now", basename5(file)]);
|
|
17814
17907
|
else
|
|
17815
17908
|
exec("launchctl", ["unload", file]);
|
|
17816
17909
|
rmSync6(file, { force: true });
|
|
17817
17910
|
if (unit)
|
|
17818
17911
|
exec("systemctl", ["--user", "daemon-reload"]);
|
|
17819
|
-
log(`engine:${name} removed: ${
|
|
17912
|
+
log(`engine:${name} removed: ${basename5(file, unit ? ".service" : ".plist")} — its sessions keep running`);
|
|
17820
17913
|
return 0;
|
|
17821
17914
|
}
|
|
17822
17915
|
|
|
@@ -17933,7 +18026,7 @@ function nodeOk(version, min = NODE_MIN) {
|
|
|
17933
18026
|
}
|
|
17934
18027
|
var MARK = { ok: "ok ", warn: "warn", fail: "FAIL" };
|
|
17935
18028
|
function formatDoctor(checks) {
|
|
17936
|
-
const lines = checks.map((c) => `${MARK[c.level]} ${c.name.padEnd(
|
|
18029
|
+
const lines = checks.map((c) => `${MARK[c.level]} ${c.name.padEnd(15)} ${c.detail}`);
|
|
17937
18030
|
const fixes = checks.filter((c) => c.level !== "ok" && c.fix);
|
|
17938
18031
|
if (fixes.length > 0) {
|
|
17939
18032
|
lines.push("");
|
|
@@ -17973,7 +18066,7 @@ async function runDoctor(o) {
|
|
|
17973
18066
|
level: "fail",
|
|
17974
18067
|
name: "config",
|
|
17975
18068
|
detail: `${configPath(home)} does not exist${overrides.length ? ` (this shell has ${overrides.join(" ")})` : ""}`,
|
|
17976
|
-
fix: overrides.length ? "unset SLEDS_HOME CLAUDE_CONFIG_DIR — or run `sleds init` for this seat" : "sleds init
|
|
18069
|
+
fix: overrides.length ? "unset SLEDS_HOME CLAUDE_CONFIG_DIR — or run `sleds init` for this seat" : "sleds init"
|
|
17977
18070
|
});
|
|
17978
18071
|
} else {
|
|
17979
18072
|
checks.push({
|
|
@@ -18003,7 +18096,7 @@ async function runDoctor(o) {
|
|
|
18003
18096
|
level: "warn",
|
|
18004
18097
|
name: "claude",
|
|
18005
18098
|
detail: `${sPath} carries a different token (${maskToken(pointed.token)}) than ${configPath(home)} (${maskToken(cfg.token)})`,
|
|
18006
|
-
fix: "sleds init
|
|
18099
|
+
fix: "sleds init (or `sleds login` as the seat you mean)"
|
|
18007
18100
|
});
|
|
18008
18101
|
} else {
|
|
18009
18102
|
checks.push({ level: "ok", name: "claude", detail: `${sPath} → ${pointed.url}` });
|
|
@@ -18169,13 +18262,16 @@ async function runDoctor(o) {
|
|
|
18169
18262
|
}
|
|
18170
18263
|
var SANDBOX_PROBE = "sandbox-probe";
|
|
18171
18264
|
var PROBE_ENV = "SLEDS_DOCTOR_PROBE";
|
|
18265
|
+
var SETTINGS_ENV = "SLEDS_DOCTOR_SETTINGS";
|
|
18172
18266
|
var SANDBOX_PROBE_COMMAND = [
|
|
18173
18267
|
`cat "$${PROBE_ENV}"; echo "SLEDS_CAT_EXIT=$?"`,
|
|
18268
|
+
`[ -n "$ANTHROPIC_AUTH_TOKEN$ANTHROPIC_API_KEY" ]; echo "SLEDS_ENV_EMPTY=$?"`,
|
|
18269
|
+
`cat "$${SETTINGS_ENV}" >/dev/null; echo "SLEDS_SETTINGS_EXIT=$?"`,
|
|
18174
18270
|
`curl -sS -m 10 -o /dev/null -w "SLEDS_CURL_CODE=%{http_code}\\n" https://example.com; echo "SLEDS_CURL_EXIT=$?"`,
|
|
18175
18271
|
`gh api user -q .login; echo "SLEDS_GH_EXIT=$?"`
|
|
18176
18272
|
].join("; ");
|
|
18177
18273
|
var marker = (out, name) => new RegExp(`${name}=(\\d+)`).exec(out)?.[1] ?? null;
|
|
18178
|
-
function readSandboxProbe(run, nonce) {
|
|
18274
|
+
function readSandboxProbe(run, nonce, o = {}) {
|
|
18179
18275
|
const out = `${run.stdout}
|
|
18180
18276
|
${run.stderr}`;
|
|
18181
18277
|
const failed = run.status !== 0;
|
|
@@ -18197,6 +18293,34 @@ ${run.stderr}`;
|
|
|
18197
18293
|
detail: catExit === "0" ? "cat succeeded but printed no nonce — inconclusive" : `${why} — inconclusive`,
|
|
18198
18294
|
fix
|
|
18199
18295
|
};
|
|
18296
|
+
const leaked = Boolean(o.token) && out.includes(o.token);
|
|
18297
|
+
const envEmpty = marker(out, "SLEDS_ENV_EMPTY");
|
|
18298
|
+
const envRow = envEmpty === "0" ? {
|
|
18299
|
+
level: "fail",
|
|
18300
|
+
name: "sandbox env",
|
|
18301
|
+
detail: "a sandboxed session's shell has ANTHROPIC_AUTH_TOKEN or ANTHROPIC_API_KEY — the seat token is readable",
|
|
18302
|
+
fix: "update Claude Code: the sandbox settings' env sets CLAUDE_CODE_SUBPROCESS_ENV_SCRUB, which 2.1.310 honors"
|
|
18303
|
+
} : envEmpty !== null ? {
|
|
18304
|
+
level: "ok",
|
|
18305
|
+
name: "sandbox env",
|
|
18306
|
+
detail: "the session's shell has no Anthropic credential in its env"
|
|
18307
|
+
} : { level: "warn", name: "sandbox env", detail: `${why} — inconclusive`, fix };
|
|
18308
|
+
const settingsExit = marker(out, "SLEDS_SETTINGS_EXIT");
|
|
18309
|
+
const settingsRow = leaked || settingsExit === "0" && o.settingsExists !== false ? {
|
|
18310
|
+
level: "fail",
|
|
18311
|
+
name: "sandbox settings read",
|
|
18312
|
+
detail: leaked ? "the seat token appeared in a sandboxed session's output" : "a sandboxed session read Claude Code's settings.json — a proxied seat's token is readable",
|
|
18313
|
+
fix: "check that the sandbox settings deny the Claude settings files (sandbox.filesystem.denyRead)"
|
|
18314
|
+
} : o.settingsExists === false ? {
|
|
18315
|
+
level: "warn",
|
|
18316
|
+
name: "sandbox settings read",
|
|
18317
|
+
detail: "Claude Code has no settings.json for this seat — nothing to guard yet",
|
|
18318
|
+
fix: "sleds init"
|
|
18319
|
+
} : settingsExit !== null ? {
|
|
18320
|
+
level: "ok",
|
|
18321
|
+
name: "sandbox settings read",
|
|
18322
|
+
detail: "Claude Code's settings.json is unreadable from a sandboxed session"
|
|
18323
|
+
} : { level: "warn", name: "sandbox settings read", detail: `${why} — inconclusive`, fix };
|
|
18200
18324
|
const code = marker(out, "SLEDS_CURL_CODE");
|
|
18201
18325
|
const curlExit = marker(out, "SLEDS_CURL_EXIT");
|
|
18202
18326
|
const egress = code !== null && code !== "000" ? {
|
|
@@ -18221,8 +18345,15 @@ ${run.stderr}`;
|
|
|
18221
18345
|
detail: ghExit === null ? `${why} — inconclusive` : `gh fails inside the sandbox (exit ${ghExit}) — a sandboxed node cannot push or open its PR`,
|
|
18222
18346
|
fix: ghExit === null ? fix : "gh auth status; api.github.com on the allowlist; on macOS gh (Go) needs sandbox.enableWeakerNetworkIsolation for TLS"
|
|
18223
18347
|
};
|
|
18224
|
-
return [read, egress, github];
|
|
18348
|
+
return [read, envRow, settingsRow, egress, github];
|
|
18225
18349
|
}
|
|
18350
|
+
var proxyToken = (home, env) => {
|
|
18351
|
+
try {
|
|
18352
|
+
return readProxy(readSettings(home, env))?.token;
|
|
18353
|
+
} catch {
|
|
18354
|
+
return;
|
|
18355
|
+
}
|
|
18356
|
+
};
|
|
18226
18357
|
function sandboxChecks(o, env) {
|
|
18227
18358
|
const which = (c) => (o.which ?? defaultWhich2)(c)[0] ?? null;
|
|
18228
18359
|
const exec = o.exec ?? sessionExec;
|
|
@@ -18247,17 +18378,14 @@ function sandboxChecks(o, env) {
|
|
|
18247
18378
|
}
|
|
18248
18379
|
];
|
|
18249
18380
|
const nonce = o.nonce ?? `sleds-probe-${randomBytes(16).toString("hex")}`;
|
|
18250
|
-
const probe =
|
|
18251
|
-
const work = mkdtempSync(
|
|
18381
|
+
const probe = join21(dir, SANDBOX_PROBE);
|
|
18382
|
+
const work = mkdtempSync(join21(tmpdir(), "sleds-sandbox-"));
|
|
18252
18383
|
try {
|
|
18253
18384
|
writeFileSync17(probe, `${nonce}
|
|
18254
18385
|
`, { mode: 384 });
|
|
18255
|
-
const settingsFile =
|
|
18256
|
-
const settings =
|
|
18257
|
-
|
|
18258
|
-
gitCommonDir: work,
|
|
18259
|
-
allow: SANDBOX_DEFAULT_ALLOW
|
|
18260
|
-
});
|
|
18386
|
+
const settingsFile = join21(work, "settings.json");
|
|
18387
|
+
const settings = engineSandboxSettings(o.home, env, work, SANDBOX_DEFAULT_ALLOW);
|
|
18388
|
+
const claudeSettings = settingsPath(o.home, env);
|
|
18261
18389
|
writeFileSync17(settingsFile, JSON.stringify(settings, null, 2), { mode: 384 });
|
|
18262
18390
|
const prompt = `Run exactly this one Bash command, once, then reply with its complete output verbatim and nothing else:
|
|
18263
18391
|
|
|
@@ -18266,6 +18394,7 @@ ${SANDBOX_PROBE_COMMAND}`;
|
|
|
18266
18394
|
"-u",
|
|
18267
18395
|
"SLEDS_TOKEN",
|
|
18268
18396
|
`${PROBE_ENV}=${probe}`,
|
|
18397
|
+
`${SETTINGS_ENV}=${claudeSettings}`,
|
|
18269
18398
|
claude,
|
|
18270
18399
|
"-p",
|
|
18271
18400
|
"--model",
|
|
@@ -18278,7 +18407,9 @@ ${SANDBOX_PROBE_COMMAND}`;
|
|
|
18278
18407
|
"3",
|
|
18279
18408
|
prompt
|
|
18280
18409
|
], { cwd: work });
|
|
18281
|
-
|
|
18410
|
+
const settingsExists = existsSync17(claudeSettings);
|
|
18411
|
+
const token = settingsExists ? proxyToken(o.home, env) : undefined;
|
|
18412
|
+
return readSandboxProbe(run, nonce, { ...token ? { token } : {}, settingsExists });
|
|
18282
18413
|
} finally {
|
|
18283
18414
|
rmSync8(probe, { force: true });
|
|
18284
18415
|
rmSync8(work, { recursive: true, force: true });
|
|
@@ -18515,7 +18646,7 @@ import {
|
|
|
18515
18646
|
writeFileSync as writeFileSync18
|
|
18516
18647
|
} from "node:fs";
|
|
18517
18648
|
import { hostname as hostname4 } from "node:os";
|
|
18518
|
-
import { join as
|
|
18649
|
+
import { join as join22, resolve as resolve10 } from "node:path";
|
|
18519
18650
|
init_machine();
|
|
18520
18651
|
init_state();
|
|
18521
18652
|
init_meter();
|
|
@@ -18697,7 +18828,7 @@ function flagsFromProfile2(flags, given, profile, home) {
|
|
|
18697
18828
|
const used = [];
|
|
18698
18829
|
const skipped = [];
|
|
18699
18830
|
for (const k of profile.notYours ?? [])
|
|
18700
|
-
skipped.push(`${k} (the workspace default — the engine
|
|
18831
|
+
skipped.push(`${k} (the workspace default — the engine takes it only from your own profile)`);
|
|
18701
18832
|
if (profile.atOnce !== undefined && !has("at-once")) {
|
|
18702
18833
|
out.atOnce = profile.atOnce;
|
|
18703
18834
|
used.push(`at-once ${profile.atOnce}`);
|
|
@@ -18770,7 +18901,7 @@ function flagsFromProfile2(flags, given, profile, home) {
|
|
|
18770
18901
|
}
|
|
18771
18902
|
}
|
|
18772
18903
|
if (profile.reposDir && !has("repos-dir") && !has("repo")) {
|
|
18773
|
-
out.reposDir = splitReposDirs(profile.reposDir).map((d) => home && /^~(\/|$)/.test(d) ?
|
|
18904
|
+
out.reposDir = splitReposDirs(profile.reposDir).map((d) => home && /^~(\/|$)/.test(d) ? join22(home, d.slice(1)) : d).join(":");
|
|
18774
18905
|
used.push(`repos ${profile.reposDir}`);
|
|
18775
18906
|
}
|
|
18776
18907
|
if (profile.mcpStrict !== undefined && !has("strict-mcp") && !has("no-strict-mcp")) {
|
|
@@ -18913,7 +19044,11 @@ function engineClient2(o, org) {
|
|
|
18913
19044
|
const env = o.env ?? process.env;
|
|
18914
19045
|
const src = meterSource(o.home, undefined, { ...org ? { flag: org } : {}, env });
|
|
18915
19046
|
if (src)
|
|
18916
|
-
return fetchClient({
|
|
19047
|
+
return fetchClient({
|
|
19048
|
+
...src,
|
|
19049
|
+
timeoutMs: ENGINE_TIMEOUT_MS2,
|
|
19050
|
+
version: "0.1.47"
|
|
19051
|
+
});
|
|
18917
19052
|
const asked = org?.trim() || env.SLEDS_ORG?.trim();
|
|
18918
19053
|
if (asked && !selectOrg(readConfig(o.home), org, env).seat)
|
|
18919
19054
|
return {
|
|
@@ -18961,12 +19096,12 @@ function memberMcpConfigs2(o, cwd) {
|
|
|
18961
19096
|
});
|
|
18962
19097
|
const claudeDir = (o.env ?? process.env).CLAUDE_CONFIG_DIR;
|
|
18963
19098
|
return [
|
|
18964
|
-
read(claudeDir ?
|
|
18965
|
-
...cwd ? [read(
|
|
19099
|
+
read(claudeDir ? join22(claudeDir, ".claude.json") : join22(o.home, ".claude.json")),
|
|
19100
|
+
...cwd ? [read(join22(cwd, ".mcp.json"))] : []
|
|
18966
19101
|
];
|
|
18967
19102
|
}
|
|
18968
19103
|
function engineStateDir2(o, org, seat) {
|
|
18969
|
-
return seatStateDir(orgStateDir(o.stateDir ??
|
|
19104
|
+
return seatStateDir(orgStateDir(o.stateDir ?? join22(configDir(o.home, o.env ?? process.env), "engine"), org), seat);
|
|
18970
19105
|
}
|
|
18971
19106
|
function engineSeat2(o, org) {
|
|
18972
19107
|
try {
|
|
@@ -18986,7 +19121,7 @@ function engineToken2(o, org) {
|
|
|
18986
19121
|
}
|
|
18987
19122
|
var withToken2 = (token, now) => token ? { token, tokenNow: now } : {};
|
|
18988
19123
|
function engineDeps2(o, flags, source, runner, stateName) {
|
|
18989
|
-
const exec = o.exec ?? defaultExec;
|
|
19124
|
+
const exec = guardGit(o.exec ?? defaultExec);
|
|
18990
19125
|
const cwd = o.cwd ?? process.cwd();
|
|
18991
19126
|
const exists = o.exists ?? realExists2;
|
|
18992
19127
|
const log = o.log ?? console.log;
|
|
@@ -18996,8 +19131,8 @@ function engineDeps2(o, flags, source, runner, stateName) {
|
|
|
18996
19131
|
const repo = flags.repo ? resolve10(cwd, flags.repo) : undefined;
|
|
18997
19132
|
const reposDirs = splitReposDirs(flags.reposDir).map((d) => resolve10(cwd, d));
|
|
18998
19133
|
const { branch, prTitle } = flags;
|
|
18999
|
-
const hooksDir =
|
|
19000
|
-
const permissionMark = (name) =>
|
|
19134
|
+
const hooksDir = join22(stateDir, "hooks");
|
|
19135
|
+
const permissionMark = (name) => join22(hooksDir, `${name}.permission.json`);
|
|
19001
19136
|
const withHook = (name, settings) => applyPermissionHook(settings, [...o.sledsArgv ?? ["sleds"], "permission-event", "--mark", permissionMark(name)].map(shq2).join(" "));
|
|
19002
19137
|
return {
|
|
19003
19138
|
source,
|
|
@@ -19022,9 +19157,9 @@ function engineDeps2(o, flags, source, runner, stateName) {
|
|
|
19022
19157
|
sandbox: true,
|
|
19023
19158
|
writeSandboxSettings: o.writeSandboxSettings ?? ((name, cwd, allow) => {
|
|
19024
19159
|
const gitCommonDir = gitCommonDirOf2(exec, cwd);
|
|
19025
|
-
const dir =
|
|
19160
|
+
const dir = join22(stateDir, "sandbox");
|
|
19026
19161
|
mkdirSync16(dir, { recursive: true, mode: 448 });
|
|
19027
|
-
const p =
|
|
19162
|
+
const p = join22(dir, `${name}.json`);
|
|
19028
19163
|
const walls = engineSandboxSettings2(o.home, o.env ?? process.env, gitCommonDir, [
|
|
19029
19164
|
...SANDBOX_DEFAULT_ALLOW,
|
|
19030
19165
|
...flags.sandboxAllow ?? []
|
|
@@ -19041,7 +19176,7 @@ function engineDeps2(o, flags, source, runner, stateName) {
|
|
|
19041
19176
|
} : {},
|
|
19042
19177
|
writeHookSettings: (name, allow) => {
|
|
19043
19178
|
mkdirSync16(hooksDir, { recursive: true, mode: 448 });
|
|
19044
|
-
const p =
|
|
19179
|
+
const p = join22(hooksDir, `${name}.json`);
|
|
19045
19180
|
const base = allow?.length ? { permissions: { allow: [...allow] } } : {};
|
|
19046
19181
|
writeFileSync18(p, `${JSON.stringify(withHook(name, base), null, 2)}
|
|
19047
19182
|
`, { mode: 384 });
|
|
@@ -19069,9 +19204,9 @@ function engineDeps2(o, flags, source, runner, stateName) {
|
|
|
19069
19204
|
exists
|
|
19070
19205
|
}),
|
|
19071
19206
|
writeMcpConfig: o.writeMcpConfig ?? ((name, runToken, worktree) => {
|
|
19072
|
-
const dir =
|
|
19207
|
+
const dir = join22(stateDir, "mcp");
|
|
19073
19208
|
mkdirSync16(dir, { recursive: true, mode: 448 });
|
|
19074
|
-
const p =
|
|
19209
|
+
const p = join22(dir, `${name}.json`);
|
|
19075
19210
|
let others = {};
|
|
19076
19211
|
if (flags.strictMcp && flags.mcpAllow?.length) {
|
|
19077
19212
|
const r = mcpPassThrough(flags.mcpAllow, memberMcpConfigs2(o, worktree));
|
|
@@ -19087,9 +19222,9 @@ function engineDeps2(o, flags, source, runner, stateName) {
|
|
|
19087
19222
|
}),
|
|
19088
19223
|
removeMcpConfig: o.removeMcpConfig ?? ((p) => rmSync9(p, { force: true })),
|
|
19089
19224
|
writePrompt: o.writePrompt ?? ((name, text) => {
|
|
19090
|
-
const dir =
|
|
19225
|
+
const dir = join22(stateDir, "prompts");
|
|
19091
19226
|
mkdirSync16(dir, { recursive: true, mode: 448 });
|
|
19092
|
-
const p =
|
|
19227
|
+
const p = join22(dir, `${name}.md`);
|
|
19093
19228
|
writeFileSync18(p, text, { mode: 384 });
|
|
19094
19229
|
return p;
|
|
19095
19230
|
}),
|
|
@@ -19116,8 +19251,16 @@ function engineDeps2(o, flags, source, runner, stateName) {
|
|
|
19116
19251
|
}
|
|
19117
19252
|
function sandboxDenyRead2(home, env) {
|
|
19118
19253
|
return {
|
|
19119
|
-
dirs: [...new Set([configDir(home, env),
|
|
19120
|
-
files: [
|
|
19254
|
+
dirs: [...new Set([configDir(home, env), join22(home, ".config", "sleds")])],
|
|
19255
|
+
files: [
|
|
19256
|
+
...new Set([
|
|
19257
|
+
tokenPath(home, env),
|
|
19258
|
+
join22(home, ".sleds-token"),
|
|
19259
|
+
settingsPath(home, env),
|
|
19260
|
+
backupPath(home, env),
|
|
19261
|
+
join22(claudeDir(home, env), "settings.local.json")
|
|
19262
|
+
])
|
|
19263
|
+
]
|
|
19121
19264
|
};
|
|
19122
19265
|
}
|
|
19123
19266
|
function engineSandboxSettings2(home, env, gitCommonDir, allow) {
|
|
@@ -19141,6 +19284,8 @@ function sandboxRefusal(flags) {
|
|
|
19141
19284
|
return "sandboxed sessions: the conductor runner starts them in Conductor's cloud, where the engine cannot put the sandbox on — use another runner, or --no-sandbox";
|
|
19142
19285
|
if (flags.agent && sandboxAgentKind(flags.agent) === null)
|
|
19143
19286
|
return `sandboxed sessions: --agent '${flags.agent}' is neither Claude Code nor Codex, so the engine cannot sandbox it — use one of those, or --no-sandbox`;
|
|
19287
|
+
if (flags.agent && sandboxAgentKind(flags.agent) === "codex")
|
|
19288
|
+
return "sandboxed sessions: Codex's sandbox walls writes, not reads — the seat token stays readable; use Claude Code, or --no-sandbox";
|
|
19144
19289
|
return null;
|
|
19145
19290
|
}
|
|
19146
19291
|
function pinOrg3(configJson, org) {
|
|
@@ -19183,7 +19328,7 @@ async function driveEngine2(o, flags, deps, until = {}) {
|
|
|
19183
19328
|
runner: deps.runner.name,
|
|
19184
19329
|
atOnce: flags.atOnce,
|
|
19185
19330
|
interval: flags.interval,
|
|
19186
|
-
cliVersion: "0.1.
|
|
19331
|
+
cliVersion: "0.1.47"
|
|
19187
19332
|
};
|
|
19188
19333
|
const beat = (checkedAt) => {
|
|
19189
19334
|
const m = deps.machine;
|
|
@@ -19369,7 +19514,7 @@ async function drive2(o, flags, deps, until, beat) {
|
|
|
19369
19514
|
var SEAT_CHANGED_EXIT2 = 3;
|
|
19370
19515
|
function engineRunner2(o, flags) {
|
|
19371
19516
|
const runnerFor = o.runnerFor ?? runnerFor2;
|
|
19372
|
-
return runnerFor(flags.runner, o.exec ?? defaultExec, {
|
|
19517
|
+
return runnerFor(flags.runner, guardGit(o.exec ?? defaultExec), {
|
|
19373
19518
|
...flags.runnerCmd ? { command: flags.runnerCmd } : {}
|
|
19374
19519
|
});
|
|
19375
19520
|
}
|
|
@@ -19510,7 +19655,7 @@ var engineCmd = async (o) => {
|
|
|
19510
19655
|
if (!r || r.ok || !r.refused || r.refused === refused)
|
|
19511
19656
|
return;
|
|
19512
19657
|
refused = r.refused;
|
|
19513
|
-
error(`${r.refused}. This engine is not shown as up until it beats under a name of its own.`);
|
|
19658
|
+
error(r.below ? `${r.refused}. This engine is not shown as up until it beats on a version SLEDS serves.` : `${r.refused}. This engine is not shown as up until it beats under a name of its own.`);
|
|
19514
19659
|
};
|
|
19515
19660
|
afterTick = () => {
|
|
19516
19661
|
try {
|
|
@@ -19608,7 +19753,7 @@ async function enginePauseCmd2(o) {
|
|
|
19608
19753
|
source = sledsSource(c, { engine, log });
|
|
19609
19754
|
}
|
|
19610
19755
|
const why = parsed.why ?? `paused on ${defaultEngineName2(host)} (sleds engine pause)`;
|
|
19611
|
-
const exec = o.exec ?? defaultExec;
|
|
19756
|
+
const exec = guardGit(o.exec ?? defaultExec);
|
|
19612
19757
|
const gone = new Set;
|
|
19613
19758
|
for (const run of running) {
|
|
19614
19759
|
const at = `${run.item}/${run.node}`;
|
|
@@ -19657,14 +19802,15 @@ import {
|
|
|
19657
19802
|
writeFileSync as writeFileSync19
|
|
19658
19803
|
} from "node:fs";
|
|
19659
19804
|
import { hostname as hostname5 } from "node:os";
|
|
19660
|
-
import { basename as
|
|
19805
|
+
import { basename as basename6, dirname as dirname13, isAbsolute as isAbsolute3, join as join23 } from "node:path";
|
|
19661
19806
|
init_state();
|
|
19662
19807
|
var ENGINE_LABEL2 = "ai.sleds.engine";
|
|
19663
19808
|
var ENGINE_INSTALL_USAGE2 = `usage: sleds engine install [engine flags] | sleds engine uninstall [--name <n>] [--org <slug>]
|
|
19664
19809
|
${ENGINE_USAGE}`;
|
|
19665
|
-
function stableArgv2(argv, realpath = realpathSync2) {
|
|
19810
|
+
function stableArgv2(argv, realpath = realpathSync2, home) {
|
|
19811
|
+
const link = sledsLink(home);
|
|
19666
19812
|
return argv.map((a) => {
|
|
19667
|
-
if (!isAbsolute3(a))
|
|
19813
|
+
if (!isAbsolute3(a) || a === link)
|
|
19668
19814
|
return a;
|
|
19669
19815
|
try {
|
|
19670
19816
|
return realpath(a);
|
|
@@ -19677,13 +19823,13 @@ function engineLabel2(name, org, seat) {
|
|
|
19677
19823
|
return [ENGINE_LABEL2, org, seat?.trim(), name].filter((p) => Boolean(p)).map((p, i) => i === 0 ? p : engineSlug(p)).join(".");
|
|
19678
19824
|
}
|
|
19679
19825
|
function enginePlistPath2(home, name, org, seat) {
|
|
19680
|
-
return
|
|
19826
|
+
return join23(home, "Library", "LaunchAgents", `${engineLabel2(name, org, seat)}.plist`);
|
|
19681
19827
|
}
|
|
19682
19828
|
function engineLogPath2(stateDir, name) {
|
|
19683
|
-
return
|
|
19829
|
+
return join23(stateDir, `${engineSlug(name)}.log`);
|
|
19684
19830
|
}
|
|
19685
19831
|
function engineEventsPath2(stateDir, name) {
|
|
19686
|
-
return
|
|
19832
|
+
return join23(stateDir, `${engineSlug(name)}.events.jsonl`);
|
|
19687
19833
|
}
|
|
19688
19834
|
var xmlEscape4 = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
19689
19835
|
function buildEnginePlist2(o) {
|
|
@@ -19780,7 +19926,7 @@ function readEngines2(dir, suffix, manager, parse) {
|
|
|
19780
19926
|
}
|
|
19781
19927
|
const out = [];
|
|
19782
19928
|
for (const name of names.filter((n) => n.startsWith(`${ENGINE_LABEL2}.`) && n.endsWith(suffix))) {
|
|
19783
|
-
const path =
|
|
19929
|
+
const path = join23(dir, name);
|
|
19784
19930
|
let parsed;
|
|
19785
19931
|
try {
|
|
19786
19932
|
parsed = parse(readFileSync19(path, "utf8"), name);
|
|
@@ -19800,10 +19946,10 @@ function readEngines2(dir, suffix, manager, parse) {
|
|
|
19800
19946
|
}
|
|
19801
19947
|
function installedEngines2(home) {
|
|
19802
19948
|
return [
|
|
19803
|
-
...readEngines2(
|
|
19949
|
+
...readEngines2(join23(home, "Library", "LaunchAgents"), ".plist", "launchd", parseEnginePlist2),
|
|
19804
19950
|
...readEngines2(engineUnitDir(home), ".service", "systemd", (text, file) => {
|
|
19805
19951
|
const parsed = parseEngineUnit(text);
|
|
19806
|
-
return parsed && { label:
|
|
19952
|
+
return parsed && { label: basename6(file, ".service"), ...parsed };
|
|
19807
19953
|
})
|
|
19808
19954
|
];
|
|
19809
19955
|
}
|
|
@@ -19838,7 +19984,7 @@ async function ensureReposDir(o) {
|
|
|
19838
19984
|
return false;
|
|
19839
19985
|
}
|
|
19840
19986
|
const exists = o.exists ?? existsSync18;
|
|
19841
|
-
const missing = dirs.filter((d) => !exists(/^~(\/|$)/.test(d) ?
|
|
19987
|
+
const missing = dirs.filter((d) => !exists(/^~(\/|$)/.test(d) ? join23(o.home, d.slice(1)) : d));
|
|
19842
19988
|
if (missing.length) {
|
|
19843
19989
|
error(`Not a folder on this machine: ${missing.join(", ")}. ${REPOS_DIR_NEEDED}`);
|
|
19844
19990
|
return false;
|
|
@@ -19882,7 +20028,7 @@ function engineInstall2(o) {
|
|
|
19882
20028
|
const label = engineLabel2(parsed.name, parsed.org, seat);
|
|
19883
20029
|
const logPath = engineLogPath2(stateDir, parsed.name);
|
|
19884
20030
|
mkdirSync17(stateDir, { recursive: true, mode: 448 });
|
|
19885
|
-
const sledsArgv = stableArgv2(o.sledsArgv, o.realpath);
|
|
20031
|
+
const sledsArgv = stableArgv2(o.sledsArgv, o.realpath, o.home);
|
|
19886
20032
|
const execPath = sledsArgv[0] ?? process.execPath;
|
|
19887
20033
|
const agentEnv = {
|
|
19888
20034
|
PATH: musherPath(o.home, execPath, env.PATH ?? ""),
|
|
@@ -19934,7 +20080,7 @@ function installUnit2(a) {
|
|
|
19934
20080
|
const log = o.log ?? console.log;
|
|
19935
20081
|
const error = o.error ?? console.error;
|
|
19936
20082
|
const unit = engineUnitPath(o.home, label);
|
|
19937
|
-
const unitName =
|
|
20083
|
+
const unitName = basename6(unit);
|
|
19938
20084
|
const systemctl = (...args) => exec("systemctl", ["--user", ...args]);
|
|
19939
20085
|
mkdirSync17(dirname13(unit), { recursive: true });
|
|
19940
20086
|
if (existsSync18(unit))
|
|
@@ -19944,7 +20090,7 @@ function installUnit2(a) {
|
|
|
19944
20090
|
continue;
|
|
19945
20091
|
if (engineArg2(other.programArgs, "name") !== parsed.name)
|
|
19946
20092
|
continue;
|
|
19947
|
-
systemctl("disable", "--now",
|
|
20093
|
+
systemctl("disable", "--now", basename6(other.plist));
|
|
19948
20094
|
rmSync10(other.plist, { force: true });
|
|
19949
20095
|
log(`replaced ${other.label}, this engine as installed before`);
|
|
19950
20096
|
}
|
|
@@ -20003,13 +20149,13 @@ function engineUninstall2(o) {
|
|
|
20003
20149
|
const unit = file.endsWith(".service");
|
|
20004
20150
|
const exec = o.exec ?? defaultExec2;
|
|
20005
20151
|
if (unit)
|
|
20006
|
-
exec("systemctl", ["--user", "disable", "--now",
|
|
20152
|
+
exec("systemctl", ["--user", "disable", "--now", basename6(file)]);
|
|
20007
20153
|
else
|
|
20008
20154
|
exec("launchctl", ["unload", file]);
|
|
20009
20155
|
rmSync10(file, { force: true });
|
|
20010
20156
|
if (unit)
|
|
20011
20157
|
exec("systemctl", ["--user", "daemon-reload"]);
|
|
20012
|
-
log(`engine:${name} removed: ${
|
|
20158
|
+
log(`engine:${name} removed: ${basename6(file, unit ? ".service" : ".plist")} — its sessions keep running`);
|
|
20013
20159
|
return 0;
|
|
20014
20160
|
}
|
|
20015
20161
|
|
|
@@ -20955,9 +21101,9 @@ init_meter();
|
|
|
20955
21101
|
// src/owed.ts
|
|
20956
21102
|
init_config();
|
|
20957
21103
|
import { existsSync as existsSync22, mkdirSync as mkdirSync18, readFileSync as readFileSync23, renameSync as renameSync7, writeFileSync as writeFileSync20 } from "node:fs";
|
|
20958
|
-
import { dirname as dirname14, join as
|
|
20959
|
-
var owedPath = (home) =>
|
|
20960
|
-
var sessionPath = (home) =>
|
|
21104
|
+
import { dirname as dirname14, join as join24 } from "node:path";
|
|
21105
|
+
var owedPath = (home) => join24(configDir(home), "owed.json");
|
|
21106
|
+
var sessionPath = (home) => join24(configDir(home), "session.json");
|
|
20961
21107
|
var OWED_TTL_MS = 3 * 24 * 60 * 60000;
|
|
20962
21108
|
var str13 = (v) => typeof v === "string" ? v : undefined;
|
|
20963
21109
|
function sourceKey(s) {
|
|
@@ -21111,7 +21257,12 @@ function trackingClient(client, home, now) {
|
|
|
21111
21257
|
function contextFor(deps) {
|
|
21112
21258
|
const src = meterSource(deps.home, runTokenOf(deps.env));
|
|
21113
21259
|
const now = deps.now ?? Date.now;
|
|
21114
|
-
const client = src ? trackingClient(fetchClient({
|
|
21260
|
+
const client = src ? trackingClient(fetchClient({
|
|
21261
|
+
...src,
|
|
21262
|
+
fetchFn: deps.fetchFn,
|
|
21263
|
+
timeoutMs: deps.timeoutMs,
|
|
21264
|
+
version: "0.1.47"
|
|
21265
|
+
}), deps.home, now) : null;
|
|
21115
21266
|
return {
|
|
21116
21267
|
channel: "code",
|
|
21117
21268
|
client,
|
|
@@ -21380,7 +21531,7 @@ var DEVICE_REASONS = {
|
|
|
21380
21531
|
bad_answer: "the proxy gave an answer this CLI does not understand — update it: curl -fsSL sleds.ai/install | sh"
|
|
21381
21532
|
};
|
|
21382
21533
|
function deviceFailureText(reason) {
|
|
21383
|
-
return `Sign-in did not complete: ${DEVICE_REASONS[reason]} Or mint a seat on the dashboard (Settings › Your seat & tools) and run \`sleds init
|
|
21534
|
+
return `Sign-in did not complete: ${DEVICE_REASONS[reason]} Or mint a seat on the dashboard (Settings › Your seat & tools), set it as SLEDS_TOKEN and run \`sleds init\`.`;
|
|
21384
21535
|
}
|
|
21385
21536
|
function parseStart(body) {
|
|
21386
21537
|
if (typeof body !== "object" || body === null)
|
|
@@ -21642,7 +21793,7 @@ var SIGNUP_REASONS = {
|
|
|
21642
21793
|
not_configured: "the proxy is not set up for self-serve signup yet.",
|
|
21643
21794
|
team: "the team needs a name (2–80 characters).",
|
|
21644
21795
|
personal_email: "a team needs a work email — that domain is a personal mailbox. Sign up as an individual instead, or use your company address.",
|
|
21645
|
-
org_exists: "someone at your company already set up SLEDS. Ask them
|
|
21796
|
+
org_exists: "someone at your company already set up SLEDS. Ask them to invite you (Members → invite), then run `sleds init` and sign in through the browser.",
|
|
21646
21797
|
unavailable: "the proxy could not reach its control plane. Try again in a moment.",
|
|
21647
21798
|
unreachable: "could not reach the proxy.",
|
|
21648
21799
|
code: "that code is six digits.",
|
|
@@ -21769,7 +21920,7 @@ var resolveToken = async (o) => {
|
|
|
21769
21920
|
return null;
|
|
21770
21921
|
}
|
|
21771
21922
|
log(`Created ${team} with you as owner (${email}).${credential ? " Your platform key is stored encrypted as the org's upstream key." : " No platform key yet — add one on the dashboard (Admin → Keys) to unlock continue / overnight / switch at a wall."}`);
|
|
21772
|
-
log("Invite your team on the dashboard (Members → invite by email, Admin → Mint a seat); each person runs `sleds init
|
|
21923
|
+
log("Invite your team on the dashboard (Members → invite by email, Admin → Mint a seat); each person runs `sleds init` and signs in through the browser.");
|
|
21773
21924
|
return { token: r.token, source: "signup" };
|
|
21774
21925
|
}
|
|
21775
21926
|
const credential = (await o.prompt("Your Anthropic API key (sk-ant-…, stored encrypted, spends only your account): ")).trim();
|
|
@@ -21793,7 +21944,7 @@ var init = async (o) => {
|
|
|
21793
21944
|
}
|
|
21794
21945
|
const resolved = await resolveToken(o);
|
|
21795
21946
|
if (!resolved) {
|
|
21796
|
-
error(o.signup ? "Signup did not complete. Nothing was changed." : "No seat token. Run `sleds init` without --non-interactive to sign in through the browser, or
|
|
21947
|
+
error(o.signup ? "Signup did not complete. Nothing was changed." : "No seat token. Run `sleds init` without --non-interactive to sign in through the browser, or set SLEDS_TOKEN (never the token on the command line).");
|
|
21797
21948
|
return 2;
|
|
21798
21949
|
}
|
|
21799
21950
|
if (!isSeatToken(resolved.token)) {
|
|
@@ -22509,7 +22660,7 @@ var on = (o) => {
|
|
|
22509
22660
|
return 2;
|
|
22510
22661
|
}
|
|
22511
22662
|
if (!isSeatToken(token)) {
|
|
22512
|
-
error("Saved token is not a sled_ token. Run `sleds
|
|
22663
|
+
error("Saved token is not a sled_ token. Run `sleds login` to sign in again.");
|
|
22513
22664
|
return 2;
|
|
22514
22665
|
}
|
|
22515
22666
|
if (cfg.org && !cfg.org.capabilities.upstreamKey) {
|
|
@@ -22677,7 +22828,7 @@ var orgCmd = (o) => {
|
|
|
22677
22828
|
init_src();
|
|
22678
22829
|
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
22679
22830
|
import { writeFileSync as writeFileSync23 } from "node:fs";
|
|
22680
|
-
import { join as
|
|
22831
|
+
import { join as join25 } from "node:path";
|
|
22681
22832
|
function packFileName(key) {
|
|
22682
22833
|
return `pack-${slugify(key, 80) || "item"}.md`;
|
|
22683
22834
|
}
|
|
@@ -22705,7 +22856,7 @@ var packCmd = async (o) => {
|
|
|
22705
22856
|
log(r.text);
|
|
22706
22857
|
return 0;
|
|
22707
22858
|
}
|
|
22708
|
-
const path =
|
|
22859
|
+
const path = join25(o.cwd ?? process.cwd(), packFileName(key));
|
|
22709
22860
|
(o.write ?? ((p, t) => writeFileSync23(p, t.endsWith(`
|
|
22710
22861
|
`) ? t : `${t}
|
|
22711
22862
|
`)))(path, r.text);
|
|
@@ -22964,7 +23115,9 @@ function parseVerbArgs(argv, allowed) {
|
|
|
22964
23115
|
if (flag === "name")
|
|
22965
23116
|
out.name = value;
|
|
22966
23117
|
i++;
|
|
22967
|
-
} else if (
|
|
23118
|
+
} else if (a.startsWith("-"))
|
|
23119
|
+
return { error: `unknown flag ${a}` };
|
|
23120
|
+
else if (out.key === undefined)
|
|
22968
23121
|
out.key = a;
|
|
22969
23122
|
else
|
|
22970
23123
|
return { error: `one item at a time — "${a}" is extra` };
|
|
@@ -23146,7 +23299,7 @@ async function proposeCmd(o, argv) {
|
|
|
23146
23299
|
log(`- ${w}`);
|
|
23147
23300
|
const shown = typeof r.json?.key === "string" ? r.json.key : a.key;
|
|
23148
23301
|
const text = typeof r.json?.text === "string" ? r.json.text : "";
|
|
23149
|
-
log(text.replace(/\n*Nothing runs until a person says yes:[^\n]*$/, "") || `${shown} · route
|
|
23302
|
+
log(text.replace(/\n*Nothing runs until a person says yes:[^\n]*$/, "") || `${shown} · route planned, not filed`);
|
|
23150
23303
|
log("");
|
|
23151
23304
|
log(`Nothing runs until a person approves it: \`sleds route approve ${shown}\`, or Approve in the app.`);
|
|
23152
23305
|
});
|
|
@@ -23188,7 +23341,7 @@ async function approveCmd(o, argv) {
|
|
|
23188
23341
|
return said(o, a.key, a.json, r, () => log(approvedLine(a.key, r.json ?? {})));
|
|
23189
23342
|
}
|
|
23190
23343
|
async function redraftCmd(o, argv) {
|
|
23191
|
-
return oneVerb(o, argv, REDRAFT_USAGE, { draft: "retry" }, "nothing
|
|
23344
|
+
return oneVerb(o, argv, REDRAFT_USAGE, { draft: "retry" }, "nothing planned again", (key) => redraftLine(key));
|
|
23192
23345
|
}
|
|
23193
23346
|
async function singleCmd(o, argv) {
|
|
23194
23347
|
return oneVerb(o, argv, SINGLE_USAGE, { single: true }, "nothing changed", (key) => singleLine(key));
|
|
@@ -23216,17 +23369,17 @@ async function oneVerb(o, argv, usage, body, unreachable, line) {
|
|
|
23216
23369
|
return said(o, a.key, a.json, r, () => log(line(shown)));
|
|
23217
23370
|
}
|
|
23218
23371
|
function redraftLine(key) {
|
|
23219
|
-
return `${key}
|
|
23372
|
+
return `${key} plan again asked — the engine plans its route on its next check`;
|
|
23220
23373
|
}
|
|
23221
23374
|
function singleLine(key) {
|
|
23222
|
-
return `${key} runs as one node — it is not
|
|
23375
|
+
return `${key} runs as one node — it is not planned again`;
|
|
23223
23376
|
}
|
|
23224
23377
|
function answeredLine(key, route, held) {
|
|
23225
23378
|
const nodes = Array.isArray(held) && held.length ? ` (${held.join(", ")})` : "";
|
|
23226
23379
|
if (route === "accept")
|
|
23227
23380
|
return `${key}: change accepted — what it held${nodes} waits until the route is re-filed`;
|
|
23228
23381
|
if (route === "redraft")
|
|
23229
|
-
return `${key}:
|
|
23382
|
+
return `${key}: plan again asked — what it held${nodes} waits until the route is re-filed`;
|
|
23230
23383
|
if (route === "keep")
|
|
23231
23384
|
return `${key}: route kept as filed — what it held is released`;
|
|
23232
23385
|
return `${key}: answered — what it held is released`;
|
|
@@ -23303,12 +23456,24 @@ function lookToReady(route, id) {
|
|
|
23303
23456
|
return { error: `no decision ${id} on this item` };
|
|
23304
23457
|
if (d.kind !== "look")
|
|
23305
23458
|
return { error: `decision ${id} is not a look — --ready marks a look` };
|
|
23459
|
+
if (d.state === "superseded" || d.state === "answered")
|
|
23460
|
+
return { settled: `decision ${id} is ${d.state}` };
|
|
23306
23461
|
if (d.state !== "escalated")
|
|
23307
23462
|
return { error: `decision ${id} is ${String(d.state)} — not a look you owe` };
|
|
23308
23463
|
const about = d.about && typeof d.about === "object" ? d.about : {};
|
|
23309
23464
|
const pr = Array.isArray(about.prs) ? about.prs.find((p) => typeof p === "string" && p) : undefined;
|
|
23310
23465
|
return typeof pr === "string" ? { pr } : { error: `decision ${id} names no PR` };
|
|
23311
23466
|
}
|
|
23467
|
+
function prLookState(stdout) {
|
|
23468
|
+
try {
|
|
23469
|
+
const j = JSON.parse(stdout);
|
|
23470
|
+
if (!j || typeof j.isDraft !== "boolean" || typeof j.state !== "string")
|
|
23471
|
+
return null;
|
|
23472
|
+
return { isDraft: j.isDraft, state: j.state };
|
|
23473
|
+
} catch {
|
|
23474
|
+
return null;
|
|
23475
|
+
}
|
|
23476
|
+
}
|
|
23312
23477
|
async function readyCmd(o, argv) {
|
|
23313
23478
|
const log = o.log ?? console.log;
|
|
23314
23479
|
const error = o.error ?? console.error;
|
|
@@ -23329,6 +23494,13 @@ async function readyCmd(o, argv) {
|
|
|
23329
23494
|
error(reader.error);
|
|
23330
23495
|
return 1;
|
|
23331
23496
|
}
|
|
23497
|
+
const settled = (why) => {
|
|
23498
|
+
if (json)
|
|
23499
|
+
log(JSON.stringify({ ok: true, settled: why }));
|
|
23500
|
+
else
|
|
23501
|
+
log(`${key}: the look is already settled — nothing to do`);
|
|
23502
|
+
return 0;
|
|
23503
|
+
};
|
|
23332
23504
|
const route = await reader.read(key).catch((e) => {
|
|
23333
23505
|
error(e instanceof Error ? e.message : String(e));
|
|
23334
23506
|
return;
|
|
@@ -23340,12 +23512,25 @@ async function readyCmd(o, argv) {
|
|
|
23340
23512
|
error(`${key}: ${look.error}`);
|
|
23341
23513
|
return 1;
|
|
23342
23514
|
}
|
|
23343
|
-
|
|
23344
|
-
|
|
23345
|
-
|
|
23515
|
+
if ("settled" in look)
|
|
23516
|
+
return settled(look.settled);
|
|
23517
|
+
const exec = o.exec ?? defaultExec;
|
|
23518
|
+
const view = exec("gh", ["pr", "view", look.pr, "--json", "isDraft,state"]);
|
|
23519
|
+
const pr = view.status === 0 ? prLookState(view.stdout) : null;
|
|
23520
|
+
if (!pr) {
|
|
23521
|
+
error(view.stderr.trim() || (view.status === 0 ? `gh pr view ${look.pr} said nothing readable` : `gh pr view ${look.pr} exited ${view.status}`));
|
|
23346
23522
|
error(`${key}: the look is not answered`);
|
|
23347
23523
|
return 1;
|
|
23348
23524
|
}
|
|
23525
|
+
const draft = pr.state === "OPEN" && pr.isDraft;
|
|
23526
|
+
if (draft) {
|
|
23527
|
+
const gh = exec("gh", ["pr", "ready", look.pr]);
|
|
23528
|
+
if (gh.status !== 0) {
|
|
23529
|
+
error(gh.stderr.trim() || `gh pr ready ${look.pr} exited ${gh.status}`);
|
|
23530
|
+
error(`${key}: the look is not answered`);
|
|
23531
|
+
return 1;
|
|
23532
|
+
}
|
|
23533
|
+
}
|
|
23349
23534
|
const r = await client.postFull("/proxy/route/decision", {
|
|
23350
23535
|
project: key,
|
|
23351
23536
|
id,
|
|
@@ -23355,7 +23540,13 @@ async function readyCmd(o, argv) {
|
|
|
23355
23540
|
error(`${key}: ${look.pr} is ready for review, but SLEDS is unreachable — the look is not answered`);
|
|
23356
23541
|
return 1;
|
|
23357
23542
|
}
|
|
23358
|
-
|
|
23543
|
+
if (r.status >= 300 || r.json?.ok === false) {
|
|
23544
|
+
const again = await reader.read(key).catch(() => null);
|
|
23545
|
+
const now = lookToReady(again ?? null, id);
|
|
23546
|
+
if ("settled" in now)
|
|
23547
|
+
return settled(now.settled);
|
|
23548
|
+
}
|
|
23549
|
+
return said(o, key, json, r, () => log(draft ? `${key}: ${look.pr} marked ready for review — the look is answered` : `${key}: ${look.pr} is ${pr.state === "OPEN" ? "already ready for review" : pr.state.toLowerCase()} — the look is answered`));
|
|
23359
23550
|
}
|
|
23360
23551
|
var DECISIONS_USAGE = "usage: sleds route decisions [<key>] [--flagged] [--json]";
|
|
23361
23552
|
function decisionsLines(raw) {
|
|
@@ -23368,7 +23559,7 @@ function decisionsLines(raw) {
|
|
|
23368
23559
|
const first = q.replace(/\s+/g, " ").trim().slice(0, 100);
|
|
23369
23560
|
const where = [d.project && !j.project ? d.project : null, d.node].filter(Boolean).join("/");
|
|
23370
23561
|
const flag = d.flagged ? " · decided for you" : "";
|
|
23371
|
-
const pending = d.redraftPending ? " ·
|
|
23562
|
+
const pending = d.redraftPending ? " · plan again pending" : "";
|
|
23372
23563
|
return `${String(d.state)}${flag}${pending} ${where || "—"} ${first} [${String(d.id)}]`;
|
|
23373
23564
|
});
|
|
23374
23565
|
}
|
|
@@ -23584,12 +23775,14 @@ function routeReader(o, org) {
|
|
|
23584
23775
|
read: (k) => readOrSay(client, `/proxy/route?q=${encodeURIComponent(k)}`, k)
|
|
23585
23776
|
};
|
|
23586
23777
|
}
|
|
23587
|
-
var SLED_USAGE = "usage: sleds sled --json | sleds sled top <KEY>";
|
|
23778
|
+
var SLED_USAGE = "usage: sleds sled --json | sleds sled top <KEY> | sleds sled order <KEY>…";
|
|
23588
23779
|
async function sledCmd(o) {
|
|
23589
23780
|
const log = o.log ?? console.log;
|
|
23590
23781
|
const error = o.error ?? console.error;
|
|
23591
23782
|
const top = o.argv[0] === "top" && o.argv.length === 2 && !o.argv[1]?.startsWith("-");
|
|
23592
|
-
|
|
23783
|
+
const keys = o.argv.slice(1);
|
|
23784
|
+
const order = o.argv[0] === "order" && keys.length > 0 && keys.every((k) => k.trim() && !k.startsWith("-"));
|
|
23785
|
+
if (!top && !order && (o.argv.length !== 1 || o.argv[0] !== "--json")) {
|
|
23593
23786
|
error(SLED_USAGE);
|
|
23594
23787
|
return 2;
|
|
23595
23788
|
}
|
|
@@ -23600,6 +23793,8 @@ async function sledCmd(o) {
|
|
|
23600
23793
|
}
|
|
23601
23794
|
if (top)
|
|
23602
23795
|
return sledTop(client, o.argv[1], log, error);
|
|
23796
|
+
if (order)
|
|
23797
|
+
return sledOrder(client, keys, log, error);
|
|
23603
23798
|
try {
|
|
23604
23799
|
log(JSON.stringify(await readOrSay(client, "/proxy/sled", "the sled")));
|
|
23605
23800
|
return 0;
|
|
@@ -23621,6 +23816,19 @@ async function sledTop(client, key, log, error) {
|
|
|
23621
23816
|
log(`${typeof r.json?.key === "string" ? r.json.key : key} is first on your sled`);
|
|
23622
23817
|
return 0;
|
|
23623
23818
|
}
|
|
23819
|
+
async function sledOrder(client, keys, log, error) {
|
|
23820
|
+
const r = await client.postFull("/proxy/sled/order", { order: keys });
|
|
23821
|
+
if (!r) {
|
|
23822
|
+
error("SLEDS unreachable — the sled is unchanged");
|
|
23823
|
+
return 1;
|
|
23824
|
+
}
|
|
23825
|
+
if (r.status >= 300 || r.json?.ok === false) {
|
|
23826
|
+
error(typeof r.json?.error === "string" ? r.json.error : `sled order: HTTP ${r.status}`);
|
|
23827
|
+
return 1;
|
|
23828
|
+
}
|
|
23829
|
+
log(`${typeof r.json?.ordered === "number" ? r.json.ordered : keys.length} ordered on your sled`);
|
|
23830
|
+
return 0;
|
|
23831
|
+
}
|
|
23624
23832
|
|
|
23625
23833
|
// src/commands/run.ts
|
|
23626
23834
|
init_config();
|
|
@@ -23726,12 +23934,12 @@ var seatEvent = async (o) => {
|
|
|
23726
23934
|
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
23727
23935
|
import { existsSync as existsSync26, mkdirSync as mkdirSync22, readFileSync as readFileSync28, readdirSync as readdirSync5, rmSync as rmSync16, writeFileSync as writeFileSync25 } from "node:fs";
|
|
23728
23936
|
import { platform as platform2 } from "node:os";
|
|
23729
|
-
import { dirname as dirname17, join as
|
|
23937
|
+
import { dirname as dirname17, join as join27 } from "node:path";
|
|
23730
23938
|
|
|
23731
23939
|
// src/cookieDb.ts
|
|
23732
23940
|
import { copyFileSync, rmSync as rmSync15 } from "node:fs";
|
|
23733
23941
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
23734
|
-
import { join as
|
|
23942
|
+
import { join as join26 } from "node:path";
|
|
23735
23943
|
var QUERY = "SELECT name, hex(encrypted_value) AS ev FROM cookies WHERE host_key LIKE '%claude.ai%'";
|
|
23736
23944
|
var isBun = () => typeof globalThis.Bun !== "undefined";
|
|
23737
23945
|
async function queryRows(dbPath) {
|
|
@@ -23760,7 +23968,7 @@ function nodeSqlite() {
|
|
|
23760
23968
|
return mod;
|
|
23761
23969
|
}
|
|
23762
23970
|
async function readCookieRows(dbPath) {
|
|
23763
|
-
const copy =
|
|
23971
|
+
const copy = join26(tmpdir2(), `sleds-cookies-${process.pid}-${Date.now()}.sqlite`);
|
|
23764
23972
|
copyFileSync(dbPath, copy);
|
|
23765
23973
|
try {
|
|
23766
23974
|
const rows = await queryRows(copy);
|
|
@@ -24053,7 +24261,7 @@ function findFile(root, name) {
|
|
|
24053
24261
|
continue;
|
|
24054
24262
|
}
|
|
24055
24263
|
for (const e of entries) {
|
|
24056
|
-
const p =
|
|
24264
|
+
const p = join27(dir, e.name);
|
|
24057
24265
|
if (e.isDirectory())
|
|
24058
24266
|
stack.push(p);
|
|
24059
24267
|
else if (e.name === name)
|
|
@@ -24064,7 +24272,7 @@ function findFile(root, name) {
|
|
|
24064
24272
|
}
|
|
24065
24273
|
function findCookieDb(home, source) {
|
|
24066
24274
|
const b = BROWSERS[source.browser];
|
|
24067
|
-
const root =
|
|
24275
|
+
const root = join27(home, APP_SUPPORT, b.appDir);
|
|
24068
24276
|
if (!existsSync26(root))
|
|
24069
24277
|
throw new Error(`no ${source.browser} data at ${root} (is it installed?)`);
|
|
24070
24278
|
if (!b.profiled) {
|
|
@@ -24073,7 +24281,7 @@ function findCookieDb(home, source) {
|
|
|
24073
24281
|
throw new Error(`no cookie store under ${root}`);
|
|
24074
24282
|
return db;
|
|
24075
24283
|
}
|
|
24076
|
-
const localStatePath =
|
|
24284
|
+
const localStatePath = join27(root, "Local State");
|
|
24077
24285
|
const localState = existsSync26(localStatePath) ? readFileSync28(localStatePath, "utf8") : null;
|
|
24078
24286
|
const wanted = source.profile ?? "Default";
|
|
24079
24287
|
const { dir, ambiguous } = resolveProfileDir(localState, wanted);
|
|
@@ -24081,7 +24289,7 @@ function findCookieDb(home, source) {
|
|
|
24081
24289
|
throw new Error(`"${wanted}" names ${ambiguous.length} ${source.browser} profiles (${ambiguous.join(", ")}) — pass the directory or the account email instead`);
|
|
24082
24290
|
if (!dir)
|
|
24083
24291
|
throw new Error(`no ${source.browser} profile named "${wanted}" (check chrome://version)`);
|
|
24084
|
-
const db = cookieDbCandidates(
|
|
24292
|
+
const db = cookieDbCandidates(join27(root, dir)).find((p) => existsSync26(p));
|
|
24085
24293
|
if (!db)
|
|
24086
24294
|
throw new Error(`profile "${dir}" has no cookie store yet (open claude.ai in it once)`);
|
|
24087
24295
|
return db;
|
|
@@ -24123,11 +24331,11 @@ function fetchSeatUsage(jar, org, now, run) {
|
|
|
24123
24331
|
return { usage: null, status };
|
|
24124
24332
|
}
|
|
24125
24333
|
}
|
|
24126
|
-
function launchAgentPlist(
|
|
24334
|
+
function launchAgentPlist(argv, home, source) {
|
|
24127
24335
|
const label = launchLabel(source);
|
|
24128
|
-
const log =
|
|
24336
|
+
const log = join27(home, ".config", "sleds", `${label.slice("ai.sleds.".length)}.log`);
|
|
24129
24337
|
const esc = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
24130
|
-
const args = [
|
|
24338
|
+
const args = [...argv, "seat-sync", ...sourceArgs(source)].map((a) => ` <string>${esc(a)}</string>`).join(`
|
|
24131
24339
|
`);
|
|
24132
24340
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
24133
24341
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
@@ -24147,16 +24355,14 @@ ${args}
|
|
|
24147
24355
|
`;
|
|
24148
24356
|
}
|
|
24149
24357
|
function plistPath2(home, source) {
|
|
24150
|
-
return
|
|
24358
|
+
return join27(home, "Library", "LaunchAgents", `${launchLabel(source)}.plist`);
|
|
24151
24359
|
}
|
|
24152
|
-
function install(home, argv, source, log) {
|
|
24153
|
-
|
|
24154
|
-
|
|
24155
|
-
if (!script) {
|
|
24156
|
-
log("cannot resolve the sleds script path to install the timer");
|
|
24360
|
+
function install(home, argv, source, log, launchctl) {
|
|
24361
|
+
if (!argv[0]) {
|
|
24362
|
+
log("cannot resolve the sleds command to install the timer");
|
|
24157
24363
|
return 1;
|
|
24158
24364
|
}
|
|
24159
|
-
const dir =
|
|
24365
|
+
const dir = join27(home, "Library", "LaunchAgents");
|
|
24160
24366
|
mkdirSync22(dir, { recursive: true });
|
|
24161
24367
|
const path = plistPath2(home, source);
|
|
24162
24368
|
const tokenPath = seatTokenPath(home, source);
|
|
@@ -24166,11 +24372,11 @@ function install(home, argv, source, log) {
|
|
|
24166
24372
|
writeFileSync25(tokenPath, `${source.token}
|
|
24167
24373
|
`, { mode: 384 });
|
|
24168
24374
|
}
|
|
24169
|
-
writeFileSync25(path, launchAgentPlist(
|
|
24375
|
+
writeFileSync25(path, launchAgentPlist(argv, home, source), { mode: 384 });
|
|
24170
24376
|
try {
|
|
24171
|
-
|
|
24377
|
+
launchctl(["unload", path]);
|
|
24172
24378
|
} catch {}
|
|
24173
|
-
|
|
24379
|
+
launchctl(["load", "-w", path]);
|
|
24174
24380
|
log(`seat-sync timer installed (every ${SYNC_INTERVAL_S / 60} min) → ${path}`);
|
|
24175
24381
|
return 0;
|
|
24176
24382
|
}
|
|
@@ -24195,7 +24401,9 @@ var seatSync = async (o) => {
|
|
|
24195
24401
|
if (source.uninstall)
|
|
24196
24402
|
return uninstall(o.home, source, log);
|
|
24197
24403
|
if (source.install)
|
|
24198
|
-
return install(o.home, [process.execPath, process.argv[1] ?? ""], source, log)
|
|
24404
|
+
return install(o.home, o.sledsArgv ?? [process.execPath, process.argv[1] ?? ""], source, log, o.launchctl ?? ((args) => {
|
|
24405
|
+
execFileSync5("launchctl", args, args[0] === "unload" ? { stdio: "ignore" } : {});
|
|
24406
|
+
}));
|
|
24199
24407
|
if (platform2() !== "darwin" && !o.readCookieRows) {
|
|
24200
24408
|
log("seat-sync is macOS-only for now.");
|
|
24201
24409
|
return 2;
|
|
@@ -24338,7 +24546,7 @@ var sessionEvent = async (o) => {
|
|
|
24338
24546
|
// src/commands/specEvent.ts
|
|
24339
24547
|
init_meter();
|
|
24340
24548
|
import { readFileSync as readFileSync29, statSync as statSync2 } from "node:fs";
|
|
24341
|
-
import { basename as
|
|
24549
|
+
import { basename as basename7, isAbsolute as isAbsolute4, relative } from "node:path";
|
|
24342
24550
|
var HOOK_STDIN_TIMEOUT_MS3 = 1000;
|
|
24343
24551
|
var ESTIMATE_TIMEOUT_MS = 4000;
|
|
24344
24552
|
var MIN_SPEC_CHARS = 200;
|
|
@@ -24351,12 +24559,12 @@ function isSpecPath(path) {
|
|
|
24351
24559
|
return false;
|
|
24352
24560
|
if (NOT_SPEC.test(path))
|
|
24353
24561
|
return false;
|
|
24354
|
-
return SPEC_DIRS.test(path) || SPEC_NAMES.test(
|
|
24562
|
+
return SPEC_DIRS.test(path) || SPEC_NAMES.test(basename7(path));
|
|
24355
24563
|
}
|
|
24356
24564
|
function specTitle(body, path) {
|
|
24357
24565
|
const m = /^#\s+(.+?)\s*$/m.exec(body);
|
|
24358
24566
|
const t = m?.[1]?.trim();
|
|
24359
|
-
return (t && t.length > 0 ? t :
|
|
24567
|
+
return (t && t.length > 0 ? t : basename7(path).replace(/\.(md|mdx)$/i, "")).slice(0, 120);
|
|
24360
24568
|
}
|
|
24361
24569
|
function looksLikeSpec(body) {
|
|
24362
24570
|
if (body.trim().length < MIN_SPEC_CHARS)
|
|
@@ -24414,7 +24622,7 @@ var specEvent = async (o) => {
|
|
|
24414
24622
|
const spec = {
|
|
24415
24623
|
title: specTitle(body, input.filePath),
|
|
24416
24624
|
body: body.slice(0, MAX_SPEC_CHARS),
|
|
24417
|
-
repoHint: input.cwd ?
|
|
24625
|
+
repoHint: input.cwd ? basename7(input.cwd) : undefined
|
|
24418
24626
|
};
|
|
24419
24627
|
try {
|
|
24420
24628
|
const res = await (o.fetchFn ?? fetch)(`${src.proxyUrl}/proxy/estimate`, {
|
|
@@ -25134,12 +25342,12 @@ var webhooksCmd = async (o) => {
|
|
|
25134
25342
|
// src/config.ts
|
|
25135
25343
|
init_settings();
|
|
25136
25344
|
import { chmodSync as chmodSync7, existsSync as existsSync30, mkdirSync as mkdirSync23, readFileSync as readFileSync31, renameSync as renameSync9, writeFileSync as writeFileSync26 } from "node:fs";
|
|
25137
|
-
import { join as
|
|
25345
|
+
import { join as join28, resolve as resolve11 } from "node:path";
|
|
25138
25346
|
var configDir2 = (home, env = process.env) => {
|
|
25139
25347
|
const o = env.SLEDS_HOME?.trim();
|
|
25140
|
-
return o ? resolve11(home, o) :
|
|
25348
|
+
return o ? resolve11(home, o) : join28(home, ".config", "sleds");
|
|
25141
25349
|
};
|
|
25142
|
-
var configPath2 = (home) =>
|
|
25350
|
+
var configPath2 = (home) => join28(configDir2(home), "config.json");
|
|
25143
25351
|
var isObject17 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
25144
25352
|
var optString2 = (v) => typeof v === "string" ? v : undefined;
|
|
25145
25353
|
var parsePriorEnv2 = (v) => {
|
|
@@ -25315,6 +25523,12 @@ function runnerFor3(name, exec = defaultExec, o = {}) {
|
|
|
25315
25523
|
}
|
|
25316
25524
|
}
|
|
25317
25525
|
|
|
25526
|
+
// src/runtime.ts
|
|
25527
|
+
import { homedir as homedir2 } from "node:os";
|
|
25528
|
+
import { join as join29, win32 as win322 } from "node:path";
|
|
25529
|
+
var isCompiled = (argv1 = process.argv[1]) => Boolean(argv1 && (argv1.startsWith("/$bunfs/") || argv1.startsWith("B:\\~BUN\\")));
|
|
25530
|
+
var sledsLink2 = (home = homedir2(), platform = process.platform) => platform === "win32" ? win322.join(process.env.LOCALAPPDATA ?? win322.join(home, "AppData", "Local"), "sleds", "bin", "sleds.exe") : join29(home, ".sleds", "bin", "sleds");
|
|
25531
|
+
|
|
25318
25532
|
// src/schedule.ts
|
|
25319
25533
|
import { spawnSync as spawnSync11 } from "node:child_process";
|
|
25320
25534
|
var defaultExec5 = (cmd, args) => {
|
|
@@ -25325,7 +25539,7 @@ var defaultExec5 = (cmd, args) => {
|
|
|
25325
25539
|
};
|
|
25326
25540
|
|
|
25327
25541
|
// src/settings.ts
|
|
25328
|
-
import { dirname as dirname18, join as
|
|
25542
|
+
import { dirname as dirname18, join as join30, resolve as resolve12 } from "node:path";
|
|
25329
25543
|
var withSeatEnv2 = (command, home, env = process.env, org) => {
|
|
25330
25544
|
const parts = [];
|
|
25331
25545
|
const sh = env.SLEDS_HOME?.trim();
|
|
@@ -25421,6 +25635,7 @@ commands:
|
|
|
25421
25635
|
Token from SLEDS_DEPLOY_TOKEN (Settings \u203A Deploys). SLEDS down never fails a release.
|
|
25422
25636
|
sled --json What is on your sled (mine with each route, proposed, sent), for a front end.
|
|
25423
25637
|
sleds sled top KEY put KEY first on your sled; the engine picks it next
|
|
25638
|
+
sleds sled order KEY\u2026 those items in this order, in the places they hold; the rest stay
|
|
25424
25639
|
route <key> Print an item's route: its nodes, what each waits on, what is ready, where each
|
|
25425
25640
|
run can be watched.
|
|
25426
25641
|
--dot Graphviz instead: \`sleds route QW-142 --dot | dot -Tpng -o route.png\`
|
|
@@ -25430,10 +25645,10 @@ commands:
|
|
|
25430
25645
|
disarms; --name <engine> sends it to that engine; --json)
|
|
25431
25646
|
answer <key>/<node> answer a parked node: the words after it, or --stdin; it
|
|
25432
25647
|
goes back to ready and the engine takes it (--json)
|
|
25433
|
-
propose <key> hold a
|
|
25434
|
-
nothing (a
|
|
25648
|
+
propose <key> hold a planned route on the item for a person's yes, filing
|
|
25649
|
+
nothing (a planning session with no connector): --file
|
|
25435
25650
|
<nodes.json> or --stdin, --name <engine> (--json)
|
|
25436
|
-
approve <key> a person's yes to a
|
|
25651
|
+
approve <key> a person's yes to a planned route: files it and, under
|
|
25437
25652
|
Pickup: Auto, arms it; --file <nodes.json> approves an
|
|
25438
25653
|
edited set instead (--json)
|
|
25439
25654
|
run <key> run the engine for this one item until its route lands
|
|
@@ -25469,8 +25684,8 @@ commands:
|
|
|
25469
25684
|
high, xhigh or max. With --agent, a claude command gets it;
|
|
25470
25685
|
another runs as given and the engine says so
|
|
25471
25686
|
--decider-effort <e> the effort every answerer launches with; default the node's
|
|
25472
|
-
--drafter-model <id> the model a
|
|
25473
|
-
--drafter-effort <e> the effort a
|
|
25687
|
+
--drafter-model <id> the model a planning session launches with; default the node's
|
|
25688
|
+
--drafter-effort <e> the effort a planning session launches with; default the node's
|
|
25474
25689
|
--pr-title '<template>' the PR title the session must use: {key} {ticket} {item}
|
|
25475
25690
|
{node} {title}, e.g. 'feat: [{key}] {title}'
|
|
25476
25691
|
Flags left out come from your engine profile in SLEDS (Settings); with Pickup:
|
|
@@ -25597,14 +25812,20 @@ var hookStdin = async () => {
|
|
|
25597
25812
|
const text = await readStdin2(300);
|
|
25598
25813
|
return text.trim() ? text : undefined;
|
|
25599
25814
|
};
|
|
25600
|
-
var sledsArgv = (execPath = process.execPath, script = process.argv[1], realpath
|
|
25815
|
+
var sledsArgv = (execPath = process.execPath, script = process.argv[1], realpath, o = {}) => {
|
|
25816
|
+
if (isCompiled(script)) {
|
|
25817
|
+
const link = sledsLink2(o.home);
|
|
25818
|
+
return stableArgv2([(o.exists ?? existsSync31)(link) ? link : execPath], realpath, o.home);
|
|
25819
|
+
}
|
|
25820
|
+
return stableArgv2(script ? [execPath, script] : [execPath], realpath, o.home);
|
|
25821
|
+
};
|
|
25601
25822
|
var shellQuote = (s) => /^[\w./-]+$/.test(s) ? s : `'${s.replace(/'/g, "'\\''")}'`;
|
|
25602
|
-
var statusLineCommand = (argv, home =
|
|
25603
|
-
var seatEventCommand = (argv, home =
|
|
25604
|
-
var promptEventCommand = (argv, home =
|
|
25605
|
-
var sessionEventCommand = (argv, home =
|
|
25606
|
-
var stopEventCommand = (argv, home =
|
|
25607
|
-
var specEventCommand = (argv, home =
|
|
25823
|
+
var statusLineCommand = (argv, home = homedir3()) => withSeatEnv2([...argv, "statusline"].map(shellQuote).join(" "), home);
|
|
25824
|
+
var seatEventCommand = (argv, home = homedir3()) => withSeatEnv2([...argv, "seat-event"].map(shellQuote).join(" "), home);
|
|
25825
|
+
var promptEventCommand = (argv, home = homedir3()) => withSeatEnv2([...argv, "prompt-event"].map(shellQuote).join(" "), home);
|
|
25826
|
+
var sessionEventCommand = (argv, home = homedir3()) => withSeatEnv2([...argv, "session-event"].map(shellQuote).join(" "), home);
|
|
25827
|
+
var stopEventCommand = (argv, home = homedir3()) => withSeatEnv2([...argv, "stop-event"].map(shellQuote).join(" "), home);
|
|
25828
|
+
var specEventCommand = (argv, home = homedir3()) => withSeatEnv2([...argv, "spec-event"].map(shellQuote).join(" "), home);
|
|
25608
25829
|
var mcpFlag = (flags) => flags["no-mcp"] === true ? false : flags.mcp === true ? true : undefined;
|
|
25609
25830
|
var main = async (argv) => {
|
|
25610
25831
|
const { cmd, flags } = parseArgs(argv);
|
|
@@ -25612,7 +25833,7 @@ var main = async (argv) => {
|
|
|
25612
25833
|
console.log(commandUsage(cmd));
|
|
25613
25834
|
return 0;
|
|
25614
25835
|
}
|
|
25615
|
-
const home =
|
|
25836
|
+
const home = homedir3();
|
|
25616
25837
|
const scheduler = {
|
|
25617
25838
|
platform: platform3(),
|
|
25618
25839
|
home,
|
|
@@ -25822,7 +26043,7 @@ var main = async (argv) => {
|
|
|
25822
26043
|
case "mcp":
|
|
25823
26044
|
return mcp({ home });
|
|
25824
26045
|
case "seat-sync":
|
|
25825
|
-
return seatSync({ home, argv: process.argv.slice(3) });
|
|
26046
|
+
return seatSync({ home, argv: process.argv.slice(3), sledsArgv: sledsArgv() });
|
|
25826
26047
|
case "statusline":
|
|
25827
26048
|
return statusline({ home });
|
|
25828
26049
|
case "help":
|
|
@@ -25835,7 +26056,7 @@ ${renderHelpText(argv[1])}`);
|
|
|
25835
26056
|
case "version":
|
|
25836
26057
|
case "--version":
|
|
25837
26058
|
case "-v":
|
|
25838
|
-
console.log("sleds 0.1.
|
|
26059
|
+
console.log("sleds 0.1.47");
|
|
25839
26060
|
return 0;
|
|
25840
26061
|
default:
|
|
25841
26062
|
console.error(`unknown command: ${cmd}
|