@sleds/cli 0.1.37 → 0.1.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/sleds.mjs +746 -198
- package/package.json +1 -1
package/dist/sleds.mjs
CHANGED
|
@@ -894,7 +894,7 @@ var init_verbs = __esm(() => {
|
|
|
894
894
|
mcp: "a `Worth:` line in the spec you estimate (`Worth: high · $5k–20k · Acme renewal`)",
|
|
895
895
|
claudeCode: "`SLEDS-Worth:` line in the PR body",
|
|
896
896
|
app: "Work › the item › Worth…",
|
|
897
|
-
how: "A level, dollars when you know them, a note. Yours to state
|
|
897
|
+
how: "A level, dollars when you know them, a note. Yours to state — the tracker's priority is urgency, never worth; blank stays blank."
|
|
898
898
|
},
|
|
899
899
|
{
|
|
900
900
|
id: "intake",
|
|
@@ -5524,6 +5524,21 @@ var init_confluence = __esm(() => {
|
|
|
5524
5524
|
CONFLUENCE_READ_SCOPES_LINE = CONFLUENCE_READ_SCOPES.join(", ");
|
|
5525
5525
|
});
|
|
5526
5526
|
|
|
5527
|
+
// ../../packages/shared/src/tracker/fieldMap.ts
|
|
5528
|
+
var FILLED_ON_CREATE;
|
|
5529
|
+
var init_fieldMap = __esm(() => {
|
|
5530
|
+
FILLED_ON_CREATE = new Set([
|
|
5531
|
+
"summary",
|
|
5532
|
+
"description",
|
|
5533
|
+
"project",
|
|
5534
|
+
"issuetype",
|
|
5535
|
+
"parent",
|
|
5536
|
+
"reporter",
|
|
5537
|
+
"labels",
|
|
5538
|
+
"priority"
|
|
5539
|
+
]);
|
|
5540
|
+
});
|
|
5541
|
+
|
|
5527
5542
|
// ../../packages/shared/src/help/whatsNew.ts
|
|
5528
5543
|
var SEPT_30 = "/whats-new/2026-09-30", WHATS_NEW;
|
|
5529
5544
|
var init_whatsNew = __esm(() => {
|
|
@@ -7153,7 +7168,10 @@ var BASE_URL_KEY = "ANTHROPIC_BASE_URL", AUTH_TOKEN_KEY = "ANTHROPIC_AUTH_TOKEN"
|
|
|
7153
7168
|
if (!list.some(ours))
|
|
7154
7169
|
return { ...settings };
|
|
7155
7170
|
return withEventHooks(settings, event, list.filter((e) => !ours(e)));
|
|
7156
|
-
}, applySessionHook = (settings, command) => applyOnce(settings, SESSION_EVENT, isSledsSessionHook, sessionHookEntry(command)), removeSessionHook = (settings) => removeOurs(settings, SESSION_EVENT, isSledsSessionHook), hasSessionHook = (settings) => eventHooks(settings, SESSION_EVENT).some(isSledsSessionHook), applyStopHook = (settings, command) => applyOnce(settings, STOP_EVENT, isSledsStopHook, stopHookEntry(command)), removeStopHook = (settings) => removeOurs(settings, STOP_EVENT, isSledsStopHook), hasStopHook = (settings) => eventHooks(settings, STOP_EVENT).some(isSledsStopHook),
|
|
7171
|
+
}, applySessionHook = (settings, command) => applyOnce(settings, SESSION_EVENT, isSledsSessionHook, sessionHookEntry(command)), removeSessionHook = (settings) => removeOurs(settings, SESSION_EVENT, isSledsSessionHook), hasSessionHook = (settings) => eventHooks(settings, SESSION_EVENT).some(isSledsSessionHook), applyStopHook = (settings, command) => applyOnce(settings, STOP_EVENT, isSledsStopHook, stopHookEntry(command)), removeStopHook = (settings) => removeOurs(settings, STOP_EVENT, isSledsStopHook), hasStopHook = (settings) => eventHooks(settings, STOP_EVENT).some(isSledsStopHook), PERMISSION_EVENT_MATCHER = "permission_prompt", PERMISSION_EVENT_TIMEOUT_S = 5, isSledsPermissionHook, permissionHookEntry = (command) => ({
|
|
7172
|
+
matcher: PERMISSION_EVENT_MATCHER,
|
|
7173
|
+
hooks: [{ type: "command", command, timeout: PERMISSION_EVENT_TIMEOUT_S }]
|
|
7174
|
+
}), applyPermissionHook = (settings, command) => applyOnce(settings, NOTIFICATION_EVENT, isSledsPermissionHook, permissionHookEntry(command)), isSeatToken = (token) => /^sled_[A-Za-z0-9_-]+$/.test(token), maskToken = (token) => token.length <= 9 ? `${token.slice(0, 5)}…` : `${token.slice(0, 9)}…`, serialize = (settings) => `${JSON.stringify(settings, null, 2)}
|
|
7157
7175
|
`, hasClaudeCode = (home, env = process.env) => existsSync(claudeDir(home, env)), readSettings = (home, env = process.env) => {
|
|
7158
7176
|
const p = settingsPath(home, env);
|
|
7159
7177
|
if (!existsSync(p))
|
|
@@ -7193,6 +7211,7 @@ var init_settings = __esm(() => {
|
|
|
7193
7211
|
ORG_EXPORT = /(?:^|\s)SLEDS_ORG=(?:'[^']*'|\S+)(?=\s)/;
|
|
7194
7212
|
isSledsSessionHook = isSledsHookFor("session-event");
|
|
7195
7213
|
isSledsStopHook = isSledsHookFor("stop-event");
|
|
7214
|
+
isSledsPermissionHook = isSledsHookFor("permission-event");
|
|
7196
7215
|
});
|
|
7197
7216
|
|
|
7198
7217
|
// src/config.ts
|
|
@@ -7520,6 +7539,7 @@ var init_src = __esm(() => {
|
|
|
7520
7539
|
init_template();
|
|
7521
7540
|
init_statusMap();
|
|
7522
7541
|
init_confluence();
|
|
7542
|
+
init_fieldMap();
|
|
7523
7543
|
init_whatsNew();
|
|
7524
7544
|
init_cheatSheet();
|
|
7525
7545
|
init_pack2();
|
|
@@ -7935,6 +7955,14 @@ function parseRun(v) {
|
|
|
7935
7955
|
...typeof v.seenTicks === "number" ? { seenTicks: v.seenTicks } : {},
|
|
7936
7956
|
...typeof v.answeredAt === "number" ? { answeredAt: v.answeredAt } : {},
|
|
7937
7957
|
...typeof v.band === "string" ? { band: v.band } : {},
|
|
7958
|
+
...isObject8(v.permission) && typeof v.permission.decisionId === "string" && typeof v.permission.at === "number" ? {
|
|
7959
|
+
permission: {
|
|
7960
|
+
decisionId: v.permission.decisionId,
|
|
7961
|
+
options: Array.isArray(v.permission.options) ? v.permission.options.filter((x) => typeof x === "string") : [],
|
|
7962
|
+
at: v.permission.at,
|
|
7963
|
+
...v.permission.onScreen === true ? { onScreen: true } : {}
|
|
7964
|
+
}
|
|
7965
|
+
} : {},
|
|
7938
7966
|
...isObject8(v.provider) && typeof v.provider.why === "string" && typeof v.provider.since === "number" && typeof v.provider.tries === "number" ? { provider: { why: v.provider.why, since: v.provider.since, tries: v.provider.tries } } : {},
|
|
7939
7967
|
...parked ? { parked } : {},
|
|
7940
7968
|
...isObject8(v.pr) && typeof v.pr.url === "string" ? {
|
|
@@ -7952,7 +7980,8 @@ function parseRun(v) {
|
|
|
7952
7980
|
...typeof v.pr.conflict === "string" ? { conflict: v.pr.conflict } : {},
|
|
7953
7981
|
...typeof v.pr.resolving === "string" ? { resolving: v.pr.resolving } : {},
|
|
7954
7982
|
...conflicted ? { conflicted } : {},
|
|
7955
|
-
...typeof v.pr.reviewed === "string" ? { reviewed: v.pr.reviewed } : {}
|
|
7983
|
+
...typeof v.pr.reviewed === "string" ? { reviewed: v.pr.reviewed } : {},
|
|
7984
|
+
...typeof v.pr.look === "string" ? { look: v.pr.look } : {}
|
|
7956
7985
|
}
|
|
7957
7986
|
} : {}
|
|
7958
7987
|
};
|
|
@@ -8023,6 +8052,7 @@ function parseLock(text) {
|
|
|
8023
8052
|
runner: typeof v.runner === "string" ? v.runner : "",
|
|
8024
8053
|
atOnce: n(v.atOnce, 1),
|
|
8025
8054
|
interval: n(v.interval, 0),
|
|
8055
|
+
...typeof v.cliVersion === "string" && v.cliVersion ? { cliVersion: v.cliVersion } : {},
|
|
8026
8056
|
...typeof v.checkedAt === "number" ? { checkedAt: v.checkedAt } : {},
|
|
8027
8057
|
...typeof v.nextCheckAt === "number" ? { nextCheckAt: v.nextCheckAt } : {},
|
|
8028
8058
|
...machine ? { machine } : {},
|
|
@@ -8208,6 +8238,7 @@ init_intake();
|
|
|
8208
8238
|
init_template();
|
|
8209
8239
|
init_statusMap();
|
|
8210
8240
|
init_confluence();
|
|
8241
|
+
init_fieldMap();
|
|
8211
8242
|
init_whatsNew();
|
|
8212
8243
|
init_cheatSheet();
|
|
8213
8244
|
init_pack2();
|
|
@@ -9383,10 +9414,10 @@ import {
|
|
|
9383
9414
|
existsSync as existsSync16,
|
|
9384
9415
|
lstatSync,
|
|
9385
9416
|
mkdtempSync,
|
|
9386
|
-
readFileSync as
|
|
9417
|
+
readFileSync as readFileSync16,
|
|
9387
9418
|
readlinkSync,
|
|
9388
|
-
rmSync as
|
|
9389
|
-
writeFileSync as
|
|
9419
|
+
rmSync as rmSync8,
|
|
9420
|
+
writeFileSync as writeFileSync17
|
|
9390
9421
|
} from "node:fs";
|
|
9391
9422
|
import { tmpdir } from "node:os";
|
|
9392
9423
|
import { join as join19, resolve as resolve8 } from "node:path";
|
|
@@ -9878,6 +9909,14 @@ var withCodexSandbox = (agent, gitCommonDir) => {
|
|
|
9878
9909
|
return line;
|
|
9879
9910
|
return `${line} --sandbox workspace-write --add-dir ${shq(gitCommonDir)} -c sandbox_workspace_write.network_access=true`;
|
|
9880
9911
|
};
|
|
9912
|
+
var mainCheckoutOf = (gitCommonDir, cwd) => {
|
|
9913
|
+
const dir = gitCommonDir.replace(/\/+$/, "");
|
|
9914
|
+
if (!dir.endsWith("/.git"))
|
|
9915
|
+
return null;
|
|
9916
|
+
const main = dir.slice(0, -"/.git".length);
|
|
9917
|
+
return main && main !== cwd.replace(/\/+$/, "") ? main : null;
|
|
9918
|
+
};
|
|
9919
|
+
var claudeAddDirFlag = (mainCheckout) => mainCheckout ? ` --add-dir=${shq(mainCheckout)}` : "";
|
|
9881
9920
|
var shq = (s) => `'${s.replace(/'/g, `'\\''`)}'`;
|
|
9882
9921
|
|
|
9883
9922
|
// src/runners/exec.ts
|
|
@@ -9902,21 +9941,23 @@ var agentShellCommand = (o) => {
|
|
|
9902
9941
|
const prompt = `"$(cat ${shq2(o.promptFile)})"`;
|
|
9903
9942
|
const agent = o.agent?.trim();
|
|
9904
9943
|
if (agent)
|
|
9905
|
-
return `${sandboxedAgent(agent, o.sandbox)} ${prompt}`;
|
|
9944
|
+
return `${sandboxedAgent(agent, o.sandbox, o.mainCheckout)} ${prompt}`;
|
|
9906
9945
|
const model = o.model ? ` --model ${shq2(o.model)}` : "";
|
|
9907
9946
|
const effort = o.effort ? ` --effort ${shq2(o.effort)}` : "";
|
|
9908
|
-
return `${sandboxedAgent("claude", o.sandbox)}${mcpConfigFlag(o)} --permission-mode ${shq2(o.permissionMode)}${model}${effort} ${prompt}`;
|
|
9947
|
+
return `${sandboxedAgent("claude", o.sandbox, o.mainCheckout)}${hookSettingsFlag(o)}${mcpConfigFlag(o)} --permission-mode ${shq2(o.permissionMode)}${model}${effort} ${prompt}`;
|
|
9909
9948
|
};
|
|
9910
|
-
var sandboxedAgent = (agent, sandbox) => {
|
|
9911
|
-
if (!sandbox)
|
|
9912
|
-
return agent;
|
|
9949
|
+
var sandboxedAgent = (agent, sandbox, mainCheckout) => {
|
|
9913
9950
|
const kind = sandboxAgentKind(agent);
|
|
9951
|
+
const line = kind === "claude" ? `${agent}${claudeAddDirFlag(mainCheckout)}` : agent;
|
|
9952
|
+
if (!sandbox)
|
|
9953
|
+
return line;
|
|
9914
9954
|
if (kind === "claude")
|
|
9915
|
-
return `env -u SLEDS_TOKEN ${
|
|
9955
|
+
return `env -u SLEDS_TOKEN ${line} --settings ${shq2(sandbox.settingsFile)}`;
|
|
9916
9956
|
if (kind === "codex")
|
|
9917
9957
|
return `env -u SLEDS_TOKEN ${withCodexSandbox(agent, sandbox.gitCommonDir)}`;
|
|
9918
9958
|
return agent;
|
|
9919
9959
|
};
|
|
9960
|
+
var hookSettingsFlag = (o) => o.settingsFile && !o.sandbox ? ` --settings ${shq2(o.settingsFile)}` : "";
|
|
9920
9961
|
var mcpConfigFlag = (o) => o.mcpConfig ? ` --mcp-config ${shq2(o.mcpConfig)}${o.strictMcp ? " --strict-mcp-config" : ""}` : "";
|
|
9921
9962
|
var defaultSpawnDetached = (cmd, args, o) => {
|
|
9922
9963
|
const child = spawn(cmd, [...args], { cwd: o.cwd, detached: true, stdio: "ignore" });
|
|
@@ -9969,6 +10010,15 @@ var tailText = (s, bytes = 4096) => {
|
|
|
9969
10010
|
return nl >= 0 && nl < cut.length - 1 ? cut.slice(nl + 1) : cut;
|
|
9970
10011
|
};
|
|
9971
10012
|
|
|
10013
|
+
// src/runners/types.ts
|
|
10014
|
+
var watchTarget = (h) => ({
|
|
10015
|
+
runner: h.runner,
|
|
10016
|
+
handle: h.id,
|
|
10017
|
+
...h.log ? { log: h.log } : {},
|
|
10018
|
+
...h.group ? { group: h.group } : {}
|
|
10019
|
+
});
|
|
10020
|
+
var isRunnerKey = (key) => /^(?:[1-9]|esc)$/.test(key);
|
|
10021
|
+
|
|
9972
10022
|
// src/runners/cmux.ts
|
|
9973
10023
|
var CMUX_APP_BIN = "/Applications/cmux.app/Contents/Resources/bin/cmux";
|
|
9974
10024
|
var resolveCmuxBin = (exists = existsSync11, path = process.env.PATH ?? "") => {
|
|
@@ -10275,6 +10325,13 @@ function cmuxRunner(exec, deps = {}) {
|
|
|
10275
10325
|
return;
|
|
10276
10326
|
return pending() ? `the Enter was swallowed; pressed it ${again} more times and the text is still in the input` : `the Enter was swallowed; pressed it again${again > 1 ? ` (${again}×)` : ""}`;
|
|
10277
10327
|
},
|
|
10328
|
+
sendKey(h, key) {
|
|
10329
|
+
if (!isRunnerKey(key))
|
|
10330
|
+
throw new Error(`cmux send-key ${h.id}: no key ${JSON.stringify(key)}`);
|
|
10331
|
+
const r = cmux(["send-key", "--workspace", h.id, key === "esc" ? "escape" : key]);
|
|
10332
|
+
if (r.status !== 0)
|
|
10333
|
+
throw new Error(`cmux send-key ${h.id} failed: ${failed(r)}`);
|
|
10334
|
+
},
|
|
10278
10335
|
stop(h) {
|
|
10279
10336
|
cmux(["close-workspace", "--workspace", h.id]);
|
|
10280
10337
|
if (!h.group)
|
|
@@ -10325,12 +10382,12 @@ init_server();
|
|
|
10325
10382
|
init_config();
|
|
10326
10383
|
import {
|
|
10327
10384
|
appendFileSync as appendFileSync2,
|
|
10328
|
-
chmodSync as
|
|
10329
|
-
mkdirSync as
|
|
10330
|
-
readFileSync as
|
|
10385
|
+
chmodSync as chmodSync4,
|
|
10386
|
+
mkdirSync as mkdirSync12,
|
|
10387
|
+
readFileSync as readFileSync13,
|
|
10331
10388
|
existsSync as realExists,
|
|
10332
|
-
rmSync as
|
|
10333
|
-
writeFileSync as
|
|
10389
|
+
rmSync as rmSync4,
|
|
10390
|
+
writeFileSync as writeFileSync13
|
|
10334
10391
|
} from "node:fs";
|
|
10335
10392
|
import { hostname as hostname2 } from "node:os";
|
|
10336
10393
|
import { join as join15, resolve as resolve7 } from "node:path";
|
|
@@ -10345,7 +10402,7 @@ function beatBody(state, flags, host = {}, cap = {}) {
|
|
|
10345
10402
|
name: flags.name,
|
|
10346
10403
|
os: host.os ?? process.platform,
|
|
10347
10404
|
runner: flags.runner,
|
|
10348
|
-
version: host.version ?? "0.1.
|
|
10405
|
+
version: host.version ?? "0.1.39" ?? "dev",
|
|
10349
10406
|
running: live.length,
|
|
10350
10407
|
items: live.slice(0, BEAT_ITEMS).map((r) => `${r.item}/${r.node}`),
|
|
10351
10408
|
...cap.atOnce !== undefined ? { atOnce: cap.atOnce } : {},
|
|
@@ -10657,6 +10714,15 @@ function prForBranch(exec, repoPath, branch) {
|
|
|
10657
10714
|
return { error: e instanceof Error ? e.message : String(e) };
|
|
10658
10715
|
}
|
|
10659
10716
|
}
|
|
10717
|
+
var URL_RE = /https:\/\/[^\s)>\]"']+/;
|
|
10718
|
+
var ARTIFACT_RE = /https:\/\/claude\.ai\/[^\s)>\]"']*artifact\/[^\s)>\]"']+/;
|
|
10719
|
+
function mockOf(body) {
|
|
10720
|
+
const header = /<!--\s*sleds:header\s*-->([\s\S]*?)<!--\s*\/sleds:header\s*-->/.exec(body)?.[1];
|
|
10721
|
+
const line = header?.split(`
|
|
10722
|
+
`).find((l) => /\*\*Mocks\*\*\s*:/i.test(l));
|
|
10723
|
+
const fromHeader = line ? URL_RE.exec(line)?.[0] : undefined;
|
|
10724
|
+
return fromHeader ?? ARTIFACT_RE.exec(body)?.[0];
|
|
10725
|
+
}
|
|
10660
10726
|
var FAILED = new Set([
|
|
10661
10727
|
"FAILURE",
|
|
10662
10728
|
"ERROR",
|
|
@@ -10702,6 +10768,7 @@ function parsePrView(stdout) {
|
|
|
10702
10768
|
pending++;
|
|
10703
10769
|
}
|
|
10704
10770
|
const mergeCommit = typeof o.mergeCommit === "object" && o.mergeCommit !== null ? o.mergeCommit.oid : undefined;
|
|
10771
|
+
const mock = typeof o.body === "string" ? mockOf(o.body) : undefined;
|
|
10705
10772
|
return {
|
|
10706
10773
|
state: o.state,
|
|
10707
10774
|
author: loginOf(o.author),
|
|
@@ -10712,6 +10779,8 @@ function parsePrView(stdout) {
|
|
|
10712
10779
|
reviewDecision: typeof o.reviewDecision === "string" ? o.reviewDecision : "",
|
|
10713
10780
|
feedback: 0,
|
|
10714
10781
|
authorFeedback: 0,
|
|
10782
|
+
draft: o.isDraft === true,
|
|
10783
|
+
...mock ? { mock } : {},
|
|
10715
10784
|
...typeof o.headRefOid === "string" && o.headRefOid ? { head: o.headRefOid } : {},
|
|
10716
10785
|
...typeof mergeCommit === "string" && mergeCommit ? { mergeCommit } : {}
|
|
10717
10786
|
};
|
|
@@ -10766,7 +10835,7 @@ function prView(exec, repoPath, url) {
|
|
|
10766
10835
|
"view",
|
|
10767
10836
|
url,
|
|
10768
10837
|
"--json",
|
|
10769
|
-
"state,author,statusCheckRollup,reviewDecision,comments,reviews,headRefOid,mergeable,baseRefName,mergeCommit"
|
|
10838
|
+
"state,author,statusCheckRollup,reviewDecision,comments,reviews,headRefOid,mergeable,baseRefName,mergeCommit,isDraft,body"
|
|
10770
10839
|
], { cwd: repoPath });
|
|
10771
10840
|
const view = r.status === 0 ? parsePrView(r.stdout) : null;
|
|
10772
10841
|
if (!view || view.state !== "OPEN")
|
|
@@ -11078,13 +11147,40 @@ function jiraFromEnv(epic, env = process.env) {
|
|
|
11078
11147
|
// src/engine/loop.ts
|
|
11079
11148
|
init_src();
|
|
11080
11149
|
|
|
11081
|
-
// src/
|
|
11082
|
-
|
|
11083
|
-
|
|
11084
|
-
|
|
11085
|
-
|
|
11086
|
-
|
|
11087
|
-
|
|
11150
|
+
// src/commands/permissionEvent.ts
|
|
11151
|
+
import { chmodSync as chmodSync3, mkdirSync as mkdirSync10, readFileSync as readFileSync10, renameSync as renameSync6, rmSync as rmSync3, writeFileSync as writeFileSync11 } from "node:fs";
|
|
11152
|
+
|
|
11153
|
+
// src/commands/seatEvent.ts
|
|
11154
|
+
init_config();
|
|
11155
|
+
init_meter();
|
|
11156
|
+
var HOOK_STDIN_TIMEOUT_MS = 1000;
|
|
11157
|
+
var isObject11 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
11158
|
+
var notificationType = (text) => {
|
|
11159
|
+
try {
|
|
11160
|
+
const raw = JSON.parse(text);
|
|
11161
|
+
if (!isObject11(raw))
|
|
11162
|
+
return;
|
|
11163
|
+
return typeof raw.notification_type === "string" ? raw.notification_type : undefined;
|
|
11164
|
+
} catch {
|
|
11165
|
+
return;
|
|
11166
|
+
}
|
|
11167
|
+
};
|
|
11168
|
+
|
|
11169
|
+
// src/commands/permissionEvent.ts
|
|
11170
|
+
var isObject12 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
11171
|
+
var readPermissionMark = (file) => {
|
|
11172
|
+
try {
|
|
11173
|
+
const raw = JSON.parse(readFileSync10(file, "utf8"));
|
|
11174
|
+
if (!isObject12(raw) || typeof raw.at !== "number")
|
|
11175
|
+
return null;
|
|
11176
|
+
return { message: typeof raw.message === "string" ? raw.message : "", at: raw.at };
|
|
11177
|
+
} catch {
|
|
11178
|
+
return null;
|
|
11179
|
+
}
|
|
11180
|
+
};
|
|
11181
|
+
var clearPermissionMark = (file) => {
|
|
11182
|
+
rmSync3(file, { force: true });
|
|
11183
|
+
};
|
|
11088
11184
|
|
|
11089
11185
|
// src/engine/answerer.ts
|
|
11090
11186
|
init_src();
|
|
@@ -11232,6 +11328,14 @@ init_machine();
|
|
|
11232
11328
|
|
|
11233
11329
|
// src/engine/sledsSource.ts
|
|
11234
11330
|
init_src();
|
|
11331
|
+
function looksOf(s) {
|
|
11332
|
+
const l = s;
|
|
11333
|
+
return l && typeof l.openLook === "function" && typeof l.clearLook === "function" ? s : null;
|
|
11334
|
+
}
|
|
11335
|
+
function permissionsOf(s) {
|
|
11336
|
+
const p = s;
|
|
11337
|
+
return p && typeof p.openPermission === "function" && typeof p.clearPermission === "function" && typeof p.decisionOf === "function" ? s : null;
|
|
11338
|
+
}
|
|
11235
11339
|
var FAIL_LOG_MAX = 2000;
|
|
11236
11340
|
var UNREACHABLE2 = "SLEDS unreachable";
|
|
11237
11341
|
function keysIn(states, state) {
|
|
@@ -11373,20 +11477,34 @@ var PROFILE_TEXT = [
|
|
|
11373
11477
|
"reposDir",
|
|
11374
11478
|
"engine"
|
|
11375
11479
|
];
|
|
11480
|
+
var SHELL_TEXT = ["agent", "launcher"];
|
|
11376
11481
|
function profileOf(r) {
|
|
11377
11482
|
if (!r || r.ok === false || !isObject8(r.profile))
|
|
11378
11483
|
return null;
|
|
11379
11484
|
const p = r.profile;
|
|
11485
|
+
const member = isObject8(r.member) ? r.member : {};
|
|
11380
11486
|
const out = {
|
|
11381
11487
|
pickup: p.pickup === "auto" ? "auto" : "approve",
|
|
11382
11488
|
...HOLD_DEFAULTS2,
|
|
11383
11489
|
holdOff: p.holdOff === true
|
|
11384
11490
|
};
|
|
11385
11491
|
for (const k of PROFILE_TEXT) {
|
|
11492
|
+
if (SHELL_TEXT.includes(k))
|
|
11493
|
+
continue;
|
|
11386
11494
|
const v = str6(p[k])?.trim();
|
|
11387
11495
|
if (v)
|
|
11388
11496
|
out[k] = v;
|
|
11389
11497
|
}
|
|
11498
|
+
const notYours = [];
|
|
11499
|
+
for (const k of SHELL_TEXT) {
|
|
11500
|
+
const mine = str6(member[k])?.trim();
|
|
11501
|
+
if (mine)
|
|
11502
|
+
out[k] = mine;
|
|
11503
|
+
else if (str6(p[k])?.trim())
|
|
11504
|
+
notYours.push(k);
|
|
11505
|
+
}
|
|
11506
|
+
if (notYours.length)
|
|
11507
|
+
out.notYours = notYours;
|
|
11390
11508
|
const atOnce = num5(p.atOnce);
|
|
11391
11509
|
if (atOnce !== undefined && atOnce >= 1)
|
|
11392
11510
|
out.atOnce = Math.round(atOnce);
|
|
@@ -11746,6 +11864,57 @@ function sledsSource(client, o) {
|
|
|
11746
11864
|
throw new Error(serverMessage(r));
|
|
11747
11865
|
return eventOpenOf(r.json);
|
|
11748
11866
|
},
|
|
11867
|
+
async openLook(runId, look, engine) {
|
|
11868
|
+
const r = await client.postFull("/proxy/run", {
|
|
11869
|
+
runId,
|
|
11870
|
+
engine,
|
|
11871
|
+
event: {
|
|
11872
|
+
kind: "look",
|
|
11873
|
+
md: look.md,
|
|
11874
|
+
about: { prs: [look.pr], ...look.mock ? { mock: look.mock } : {} }
|
|
11875
|
+
}
|
|
11876
|
+
});
|
|
11877
|
+
if (!r)
|
|
11878
|
+
throw new Error(`${UNREACHABLE2} — the look not raised`);
|
|
11879
|
+
if (r.status >= 300 || !r.json || r.json.ok === false)
|
|
11880
|
+
throw new Error(serverMessage(r));
|
|
11881
|
+
const decisionId = str6(r.json.decisionId);
|
|
11882
|
+
const state = str6(r.json.state);
|
|
11883
|
+
return {
|
|
11884
|
+
opened: r.json.opened === true,
|
|
11885
|
+
...decisionId ? { decisionId } : {},
|
|
11886
|
+
...state ? { state } : {}
|
|
11887
|
+
};
|
|
11888
|
+
},
|
|
11889
|
+
async clearLook(runId, clear, engine) {
|
|
11890
|
+
const r = await client.postFull("/proxy/run", { runId, engine, clearLook: clear });
|
|
11891
|
+
if (!r)
|
|
11892
|
+
throw new Error(`${UNREACHABLE2} — the look not cleared`);
|
|
11893
|
+
if (r.status >= 300 || !r.json || r.json.ok === false)
|
|
11894
|
+
throw new Error(serverMessage(r));
|
|
11895
|
+
return r.json.cleared === true;
|
|
11896
|
+
},
|
|
11897
|
+
async openPermission(runId, p, engine) {
|
|
11898
|
+
const r = await client.postFull("/proxy/run", {
|
|
11899
|
+
runId,
|
|
11900
|
+
engine,
|
|
11901
|
+
event: { kind: "permission", md: p.md, about: { options: p.options } }
|
|
11902
|
+
});
|
|
11903
|
+
if (!r)
|
|
11904
|
+
throw new Error(`${UNREACHABLE2} — the permission not raised`);
|
|
11905
|
+
if (r.status >= 300 || !r.json || r.json.ok === false)
|
|
11906
|
+
throw new Error(serverMessage(r));
|
|
11907
|
+
const decisionId = str6(r.json.decisionId);
|
|
11908
|
+
return { opened: r.json.opened === true, ...decisionId ? { decisionId } : {} };
|
|
11909
|
+
},
|
|
11910
|
+
async clearPermission(runId, why, engine) {
|
|
11911
|
+
const r = await client.postFull("/proxy/run", { runId, engine, clearPermission: { why } });
|
|
11912
|
+
if (!r)
|
|
11913
|
+
throw new Error(`${UNREACHABLE2} — the permission not cleared`);
|
|
11914
|
+
if (r.status >= 300 || !r.json || r.json.ok === false)
|
|
11915
|
+
throw new Error(serverMessage(r));
|
|
11916
|
+
return r.json.cleared === true;
|
|
11917
|
+
},
|
|
11749
11918
|
async decisionOf(item, decisionId) {
|
|
11750
11919
|
const route = await routeOf(item);
|
|
11751
11920
|
const decisions = Array.isArray(route?.decisions) ? route.decisions.filter(isObject8) : [];
|
|
@@ -11877,6 +12046,63 @@ function askedAndStopped(screen) {
|
|
|
11877
12046
|
const last = (paras[paras.length - 1] ?? "").replace(/\s*\n\s*/g, " ");
|
|
11878
12047
|
return ASKS.test(last) || CONFIRMS.test(last);
|
|
11879
12048
|
}
|
|
12049
|
+
var DIALOG_ASKS = /^Do you want to .+\?$/;
|
|
12050
|
+
var DIALOG_OPTION = /^(❯\s*)?(\d)\.\s+(.+)$/;
|
|
12051
|
+
var DIALOG_FOOTER = /^(?:esc to |tab to |enter to |ctrl\+)/i;
|
|
12052
|
+
var unbox = (line) => line.trimEnd().replace(/^\s*[│┃║]\s?/, "").replace(/\s*[│┃║]$/, "");
|
|
12053
|
+
function permissionDialog(screen) {
|
|
12054
|
+
const raw = screen.split(`
|
|
12055
|
+
`);
|
|
12056
|
+
const lines = raw.map(unbox);
|
|
12057
|
+
let q = -1;
|
|
12058
|
+
for (let i = lines.length - 1;i >= 0; i--)
|
|
12059
|
+
if (DIALOG_ASKS.test(lines[i].trim())) {
|
|
12060
|
+
q = i;
|
|
12061
|
+
break;
|
|
12062
|
+
}
|
|
12063
|
+
if (q < 0)
|
|
12064
|
+
return null;
|
|
12065
|
+
const options = [];
|
|
12066
|
+
let cursors = 0;
|
|
12067
|
+
let i = q + 1;
|
|
12068
|
+
for (;i < lines.length; i++) {
|
|
12069
|
+
const t = lines[i].trim();
|
|
12070
|
+
const m = DIALOG_OPTION.exec(t);
|
|
12071
|
+
if (m) {
|
|
12072
|
+
if (m[2] !== String(options.length + 1))
|
|
12073
|
+
return null;
|
|
12074
|
+
if (m[1])
|
|
12075
|
+
cursors++;
|
|
12076
|
+
options.push({ key: m[2], label: m[3].replace(/\s*\(esc\)$/i, "") });
|
|
12077
|
+
} else if (t && options.length && !isRule(raw[i]) && !isPrompt(t) && !isFooter(t) && !DIALOG_FOOTER.test(t)) {
|
|
12078
|
+
const last = options[options.length - 1];
|
|
12079
|
+
last.label = `${last.label} ${t.replace(/\s*\(esc\)$/i, "")}`;
|
|
12080
|
+
} else
|
|
12081
|
+
break;
|
|
12082
|
+
}
|
|
12083
|
+
if (options.length < 2 || cursors !== 1)
|
|
12084
|
+
return null;
|
|
12085
|
+
for (;i < lines.length; i++) {
|
|
12086
|
+
const t = lines[i].trim();
|
|
12087
|
+
if (t && !isRule(raw[i]) && !DIALOG_FOOTER.test(t) && !isFooter(t))
|
|
12088
|
+
return null;
|
|
12089
|
+
}
|
|
12090
|
+
let from = 0;
|
|
12091
|
+
for (let j = q - 1;j >= 0; j--) {
|
|
12092
|
+
const t = lines[j].trim();
|
|
12093
|
+
if (isRule(raw[j]) || /^⏺/.test(t) || /^⎿/.test(t)) {
|
|
12094
|
+
from = j + 1;
|
|
12095
|
+
break;
|
|
12096
|
+
}
|
|
12097
|
+
}
|
|
12098
|
+
const body = lines.slice(from, q + 1);
|
|
12099
|
+
const indent = Math.min(...body.filter((l) => l.trim()).map((l) => /^\s*/.exec(l)[0].length));
|
|
12100
|
+
const text = body.map((l) => l.slice(indent)).join(`
|
|
12101
|
+
`).replace(/\n{3,}/g, `
|
|
12102
|
+
|
|
12103
|
+
`).trim();
|
|
12104
|
+
return { text, options };
|
|
12105
|
+
}
|
|
11880
12106
|
var PROVIDER_FAILURES = [
|
|
11881
12107
|
["connection lost", /\bconnection (?:lost|error)\b/i],
|
|
11882
12108
|
["credit balance too low", /\bcredit balance (?:is )?too low\b/i],
|
|
@@ -11899,7 +12125,7 @@ function providerFailure(screen) {
|
|
|
11899
12125
|
|
|
11900
12126
|
// src/engine/worktree.ts
|
|
11901
12127
|
init_src();
|
|
11902
|
-
import { appendFileSync, existsSync as existsSync12, mkdirSync as
|
|
12128
|
+
import { appendFileSync, existsSync as existsSync12, mkdirSync as mkdirSync11 } from "node:fs";
|
|
11903
12129
|
import { dirname as dirname11, isAbsolute, join as join14 } from "node:path";
|
|
11904
12130
|
function worktreePath(repoPath, name) {
|
|
11905
12131
|
return join14(repoPath, ".worktrees", name);
|
|
@@ -11925,7 +12151,7 @@ function defaultBranch(exec, repoPath) {
|
|
|
11925
12151
|
var realWorktreeFs = {
|
|
11926
12152
|
exists: existsSync12,
|
|
11927
12153
|
append: (p, text) => {
|
|
11928
|
-
|
|
12154
|
+
mkdirSync11(dirname11(p), { recursive: true });
|
|
11929
12155
|
appendFileSync(p, text);
|
|
11930
12156
|
}
|
|
11931
12157
|
};
|
|
@@ -12151,6 +12377,15 @@ function sandboxFor(d, name, cwd) {
|
|
|
12151
12377
|
throw new Error("sessions are sandboxed, but nothing writes their settings — not started");
|
|
12152
12378
|
return { sandbox: d.writeSandboxSettings(name, cwd) };
|
|
12153
12379
|
}
|
|
12380
|
+
function hooksFor(d, name) {
|
|
12381
|
+
if (d.sandbox || !d.writeHookSettings)
|
|
12382
|
+
return {};
|
|
12383
|
+
return { settingsFile: d.writeHookSettings(name) };
|
|
12384
|
+
}
|
|
12385
|
+
function mainCheckoutFor(d, cwd) {
|
|
12386
|
+
const main = d.mainCheckoutOf?.(cwd);
|
|
12387
|
+
return main ? { mainCheckout: main } : {};
|
|
12388
|
+
}
|
|
12154
12389
|
function engineMcpConfigFor(d, name, runToken, at, cwd) {
|
|
12155
12390
|
if (d.source.name !== "sleds" || d.agent?.trim() || !d.writeMcpConfig)
|
|
12156
12391
|
return;
|
|
@@ -12207,9 +12442,13 @@ async function tick(deps) {
|
|
|
12207
12442
|
deps.providerHold = d.providerHold;
|
|
12208
12443
|
deps.atOnce = d.atOnce;
|
|
12209
12444
|
}
|
|
12445
|
+
removeEndedMcpConfigs(deps, made);
|
|
12210
12446
|
}
|
|
12447
|
+
return report;
|
|
12448
|
+
}
|
|
12449
|
+
function removeEndedMcpConfigs(deps, made) {
|
|
12211
12450
|
if (!deps.removeMcpConfig || made.size === 0)
|
|
12212
|
-
return
|
|
12451
|
+
return;
|
|
12213
12452
|
const state = deps.readState();
|
|
12214
12453
|
const live = liveMcpConfigs(state);
|
|
12215
12454
|
for (const p of made) {
|
|
@@ -12227,7 +12466,6 @@ async function tick(deps) {
|
|
|
12227
12466
|
r.mcpConfig = undefined;
|
|
12228
12467
|
deps.writeState(state);
|
|
12229
12468
|
}
|
|
12230
|
-
return report;
|
|
12231
12469
|
}
|
|
12232
12470
|
async function tickOnce(d) {
|
|
12233
12471
|
d.tickProfile = profileOnce(d.readProfile);
|
|
@@ -12293,6 +12531,7 @@ async function tickOnce(d) {
|
|
|
12293
12531
|
}
|
|
12294
12532
|
continue;
|
|
12295
12533
|
} else if (pr) {
|
|
12534
|
+
await dropPermission(d, run, "the session opened its PR");
|
|
12296
12535
|
const outcome = { kind: "pr", ref: pr.url };
|
|
12297
12536
|
try {
|
|
12298
12537
|
await d.source.report(claim, outcome, d.engine);
|
|
@@ -12316,6 +12555,7 @@ async function tickOnce(d) {
|
|
|
12316
12555
|
}
|
|
12317
12556
|
}
|
|
12318
12557
|
if (status === "exited") {
|
|
12558
|
+
await dropPermission(d, run, "the session exited");
|
|
12319
12559
|
let log = "";
|
|
12320
12560
|
try {
|
|
12321
12561
|
log = runner.read(run.handle);
|
|
@@ -12365,6 +12605,11 @@ async function tickOnce(d) {
|
|
|
12365
12605
|
}
|
|
12366
12606
|
}
|
|
12367
12607
|
}
|
|
12608
|
+
if (await settlePermission(d, runner, run, shown)) {
|
|
12609
|
+
idle = false;
|
|
12610
|
+
asked = false;
|
|
12611
|
+
failing = null;
|
|
12612
|
+
}
|
|
12368
12613
|
const retry = failing !== null && (run.provider?.tries ?? 0) < PROVIDER_RETRIES;
|
|
12369
12614
|
if (idle || failing || needsHeartbeat(run.leaseUntil, d.now(), d.leaseMin)) {
|
|
12370
12615
|
let beat;
|
|
@@ -12615,6 +12860,8 @@ async function tickOnce(d) {
|
|
|
12615
12860
|
...launch.agent ? { agent: launch.agent } : {},
|
|
12616
12861
|
...mcpConfig ? { mcpConfig, ...d.strictMcp ? { strictMcp: true } : {} } : {},
|
|
12617
12862
|
...sandboxFor(d, name, worktree),
|
|
12863
|
+
...hooksFor(d, name),
|
|
12864
|
+
...mainCheckoutFor(d, worktree),
|
|
12618
12865
|
...claim.group ? { group: claim.group } : {}
|
|
12619
12866
|
};
|
|
12620
12867
|
} catch (e) {
|
|
@@ -12769,6 +13016,115 @@ function parkQuestion(screen, idleMin) {
|
|
|
12769
13016
|
function askedQuestion(screen) {
|
|
12770
13017
|
return `The session stopped and is waiting on an answer, with no PR. ${lastMessage(screen)}`;
|
|
12771
13018
|
}
|
|
13019
|
+
var MARK_OPTIONS = ["1 · Allow once", "esc · Deny"];
|
|
13020
|
+
function permissionKey(answer) {
|
|
13021
|
+
const m = /^\s*(\d|esc)\s*·/i.exec(answer);
|
|
13022
|
+
return m ? m[1].toLowerCase() : null;
|
|
13023
|
+
}
|
|
13024
|
+
async function settlePermission(d, runner, run, shown) {
|
|
13025
|
+
const perms = permissionsOf(d.source);
|
|
13026
|
+
if (!perms || !run.runId)
|
|
13027
|
+
return false;
|
|
13028
|
+
const at = ref(run);
|
|
13029
|
+
const markFile = d.permissionMark?.(sessionName(run.item, run.node));
|
|
13030
|
+
const dialog = runner.readsSession ? permissionDialog(shown) : null;
|
|
13031
|
+
const p = run.permission;
|
|
13032
|
+
if (p) {
|
|
13033
|
+
const gone = runner.readsSession && (p.onScreen ? !dialog : (run.seenAt ?? 0) > p.at);
|
|
13034
|
+
let now;
|
|
13035
|
+
try {
|
|
13036
|
+
now = await perms.decisionOf(run.item, p.decisionId);
|
|
13037
|
+
} catch (e) {
|
|
13038
|
+
d.log(`${at}: could not read the permission decision, asking next tick: ${message(e)}`);
|
|
13039
|
+
return true;
|
|
13040
|
+
}
|
|
13041
|
+
if (now?.state === "answered" && now.answer) {
|
|
13042
|
+
if (gone)
|
|
13043
|
+
d.log(`${at}: the permission was answered after its dialog closed — not pressed`);
|
|
13044
|
+
else if (!pressAnswer(d, runner, run, p.options, now.answer))
|
|
13045
|
+
return true;
|
|
13046
|
+
run.permission = undefined;
|
|
13047
|
+
run.answeredAt = d.now();
|
|
13048
|
+
if (markFile)
|
|
13049
|
+
clearPermissionMark(markFile);
|
|
13050
|
+
return true;
|
|
13051
|
+
}
|
|
13052
|
+
if (now?.state !== "open" && now?.state !== "escalated") {
|
|
13053
|
+
run.permission = undefined;
|
|
13054
|
+
return false;
|
|
13055
|
+
}
|
|
13056
|
+
if (!gone)
|
|
13057
|
+
return true;
|
|
13058
|
+
try {
|
|
13059
|
+
await perms.clearPermission(run.runId, "the dialog closed in the terminal", d.engine);
|
|
13060
|
+
} catch (e) {
|
|
13061
|
+
d.log(`${at}: could not clear the permission, trying next tick: ${message(e)}`);
|
|
13062
|
+
return true;
|
|
13063
|
+
}
|
|
13064
|
+
d.log(`${at}: the permission dialog closed before an answer — cleared`);
|
|
13065
|
+
run.permission = undefined;
|
|
13066
|
+
return false;
|
|
13067
|
+
}
|
|
13068
|
+
const mark = markFile ? readPermissionMark(markFile) : null;
|
|
13069
|
+
if (!dialog && !mark)
|
|
13070
|
+
return false;
|
|
13071
|
+
if (!dialog && runner.readsSession && !run.seenTicks)
|
|
13072
|
+
return false;
|
|
13073
|
+
const options = dialog ? dialog.options.map((o) => `${o.key} · ${o.label}`) : MARK_OPTIONS;
|
|
13074
|
+
const md = dialog?.text || mark?.message || "The session stopped at a permission dialog.";
|
|
13075
|
+
let opened;
|
|
13076
|
+
try {
|
|
13077
|
+
opened = await perms.openPermission(run.runId, { md, options }, d.engine);
|
|
13078
|
+
} catch (e) {
|
|
13079
|
+
d.log(`${at}: could not raise the permission dialog, trying next tick: ${message(e)}`);
|
|
13080
|
+
return true;
|
|
13081
|
+
}
|
|
13082
|
+
if (!opened.decisionId)
|
|
13083
|
+
return true;
|
|
13084
|
+
run.permission = {
|
|
13085
|
+
decisionId: opened.decisionId,
|
|
13086
|
+
options,
|
|
13087
|
+
at: d.now(),
|
|
13088
|
+
...dialog ? { onScreen: true } : {}
|
|
13089
|
+
};
|
|
13090
|
+
if (markFile)
|
|
13091
|
+
clearPermissionMark(markFile);
|
|
13092
|
+
d.log(`${at}: stopped at a permission dialog — it waits for a person (${runner.watchHint(run.handle)})`);
|
|
13093
|
+
return true;
|
|
13094
|
+
}
|
|
13095
|
+
function pressAnswer(d, runner, run, options, answer) {
|
|
13096
|
+
const at = ref(run);
|
|
13097
|
+
const key = permissionKey(answer);
|
|
13098
|
+
const offered = key !== null && options.some((o) => permissionKey(o) === key);
|
|
13099
|
+
try {
|
|
13100
|
+
if (key !== null && offered) {
|
|
13101
|
+
if (runner.sendKey)
|
|
13102
|
+
runner.sendKey(run.handle, key);
|
|
13103
|
+
else
|
|
13104
|
+
runner.send(run.handle, key);
|
|
13105
|
+
d.log(`${at}: the permission is answered — pressed ${key}; the session goes on`);
|
|
13106
|
+
} else {
|
|
13107
|
+
runner.sendKey?.(run.handle, "esc");
|
|
13108
|
+
const note = runner.send(run.handle, answer);
|
|
13109
|
+
d.log(`${at}: the permission is answered in words — Esc, then typed in${note ? ` (${note})` : ""}`);
|
|
13110
|
+
}
|
|
13111
|
+
return true;
|
|
13112
|
+
} catch (e) {
|
|
13113
|
+
d.log(`${at}: could not press the permission's answer, trying next tick: ${message(e)}`);
|
|
13114
|
+
return false;
|
|
13115
|
+
}
|
|
13116
|
+
}
|
|
13117
|
+
async function dropPermission(d, run, why) {
|
|
13118
|
+
const perms = permissionsOf(d.source);
|
|
13119
|
+
if (!run.permission || !perms || !run.runId)
|
|
13120
|
+
return;
|
|
13121
|
+
try {
|
|
13122
|
+
await perms.clearPermission(run.runId, why, d.engine);
|
|
13123
|
+
} catch (e) {
|
|
13124
|
+
d.log(`${ref(run)}: could not clear the permission (${why}): ${message(e)}`);
|
|
13125
|
+
}
|
|
13126
|
+
run.permission = undefined;
|
|
13127
|
+
}
|
|
12772
13128
|
var STILL_TICKS = 2;
|
|
12773
13129
|
function lastMessage(screen) {
|
|
12774
13130
|
const shown = stripTuiChrome(screen);
|
|
@@ -13202,6 +13558,8 @@ async function startAnswerer(d, answers, run) {
|
|
|
13202
13558
|
...launchOptions(launch),
|
|
13203
13559
|
...mcpConfig ? { mcpConfig, ...d.strictMcp ? { strictMcp: true } : {} } : {},
|
|
13204
13560
|
...sandboxFor(d, name, run.handle.cwd),
|
|
13561
|
+
...hooksFor(d, name),
|
|
13562
|
+
...mainCheckoutFor(d, run.handle.cwd),
|
|
13205
13563
|
...run.group ? { group: run.group } : {}
|
|
13206
13564
|
});
|
|
13207
13565
|
} catch (e) {
|
|
@@ -13376,7 +13734,9 @@ async function startDraft(d, claim, why, state, started, finished) {
|
|
|
13376
13734
|
permissionMode: d.permissionMode,
|
|
13377
13735
|
...launchOptions(launch),
|
|
13378
13736
|
...mcpConfig ? { mcpConfig, ...d.strictMcp ? { strictMcp: true } : {} } : {},
|
|
13379
|
-
...sandboxFor(d, name, worktree)
|
|
13737
|
+
...sandboxFor(d, name, worktree),
|
|
13738
|
+
...hooksFor(d, name),
|
|
13739
|
+
...mainCheckoutFor(d, worktree)
|
|
13380
13740
|
});
|
|
13381
13741
|
} catch (e) {
|
|
13382
13742
|
d.log(`${at}: could not start the drafter: ${message(e)}`);
|
|
@@ -13513,11 +13873,47 @@ var SELF_NUDGES = 2;
|
|
|
13513
13873
|
function reviewNudge(url, count) {
|
|
13514
13874
|
return `New review feedback on your PR (${count} ${count === 1 ? "comment" : "comments"} from people so far): ${url}. Read all of it (gh pr view ${url} --comments, and the inline threads), answer each comment on its own thread with the fix or a reasoned reply, push, and leave the threads for the reviewer to resolve. End every comment and reply you post on the PR with the line ${ENGINE_MARK} so the engine knows it is yours and not the reviewer's.`;
|
|
13515
13875
|
}
|
|
13876
|
+
function lookQuestion(url, mock) {
|
|
13877
|
+
return `A draft PR waits for your look: ${url}.${mock ? ` The mock: ${mock}.` : " Its body names no mock; the PR is the place to look."} Looks good marks it ready for review.`;
|
|
13878
|
+
}
|
|
13879
|
+
async function judgeLook(d, run, view) {
|
|
13880
|
+
const looks = looksOf(d.source);
|
|
13881
|
+
const pr = run.pr;
|
|
13882
|
+
if (!looks || !run.runId)
|
|
13883
|
+
return;
|
|
13884
|
+
const draft = view.state === "OPEN" && view.draft;
|
|
13885
|
+
if (draft && !pr.look) {
|
|
13886
|
+
try {
|
|
13887
|
+
const r = await looks.openLook(run.runId, {
|
|
13888
|
+
md: lookQuestion(pr.url, view.mock),
|
|
13889
|
+
pr: pr.url,
|
|
13890
|
+
...view.mock ? { mock: view.mock } : {}
|
|
13891
|
+
}, d.engine);
|
|
13892
|
+
if (!r.decisionId)
|
|
13893
|
+
return;
|
|
13894
|
+
pr.look = r.decisionId;
|
|
13895
|
+
if (r.opened)
|
|
13896
|
+
d.log(`${ref(run)}: ${pr.url} is a draft — a look waits for a person`);
|
|
13897
|
+
} catch (e) {
|
|
13898
|
+
d.log(`${ref(run)}: could not raise the look on ${pr.url}: ${message(e)}`);
|
|
13899
|
+
}
|
|
13900
|
+
} else if (!draft && pr.look) {
|
|
13901
|
+
const why = view.state === "MERGED" ? "the PR merged" : view.state === "CLOSED" ? "the PR closed without a merge" : "the PR left draft";
|
|
13902
|
+
try {
|
|
13903
|
+
if (await looks.clearLook(run.runId, { pr: pr.url, why }, d.engine))
|
|
13904
|
+
d.log(`${ref(run)}: the look on ${pr.url} is cleared — ${why}`);
|
|
13905
|
+
pr.look = undefined;
|
|
13906
|
+
} catch (e) {
|
|
13907
|
+
d.log(`${ref(run)}: could not clear the look on ${pr.url}: ${message(e)}`);
|
|
13908
|
+
}
|
|
13909
|
+
}
|
|
13910
|
+
}
|
|
13516
13911
|
async function follow(d, state, run, claim, runner, finished, attention, changes, decided) {
|
|
13517
13912
|
const pr = run.pr;
|
|
13518
13913
|
const view = d.prView(d.exec, run.repoPath, pr.url);
|
|
13519
13914
|
if (!view)
|
|
13520
13915
|
return true;
|
|
13916
|
+
await judgeLook(d, run, view);
|
|
13521
13917
|
if (view.state === "MERGED") {
|
|
13522
13918
|
const landed = await ripple(d, state, run, claim, runner, pr.url, finished, decided, view.head, view.mergeCommit);
|
|
13523
13919
|
return !landed;
|
|
@@ -14113,6 +14509,8 @@ function startResolver(d, run, e, answer) {
|
|
|
14113
14509
|
...launchOptions(launch),
|
|
14114
14510
|
...run.mcpConfig ? { mcpConfig: run.mcpConfig, ...d.strictMcp ? { strictMcp: true } : {} } : {},
|
|
14115
14511
|
...sandboxFor(d, name, run.handle.cwd),
|
|
14512
|
+
...hooksFor(d, name),
|
|
14513
|
+
...mainCheckoutFor(d, run.handle.cwd),
|
|
14116
14514
|
...run.group ? { group: run.group } : {}
|
|
14117
14515
|
});
|
|
14118
14516
|
} catch (err) {
|
|
@@ -14187,7 +14585,9 @@ async function startEventAnswerer(d, answers, state, dec, decided) {
|
|
|
14187
14585
|
permissionMode: d.permissionMode,
|
|
14188
14586
|
...launchOptions(launch),
|
|
14189
14587
|
...mcpConfig ? { mcpConfig, ...d.strictMcp ? { strictMcp: true } : {} } : {},
|
|
14190
|
-
...sandboxFor(d, name, worktree)
|
|
14588
|
+
...sandboxFor(d, name, worktree),
|
|
14589
|
+
...hooksFor(d, name),
|
|
14590
|
+
...mainCheckoutFor(d, worktree)
|
|
14191
14591
|
});
|
|
14192
14592
|
} catch (e) {
|
|
14193
14593
|
d.log(`${at}: could not start the ${KIND_SAYS[kind]} answerer — it goes to a person: ${message(e)}`);
|
|
@@ -14407,7 +14807,7 @@ function commandRunner(template, deps = {}) {
|
|
|
14407
14807
|
}
|
|
14408
14808
|
|
|
14409
14809
|
// src/runners/conductor.ts
|
|
14410
|
-
import { readFileSync as
|
|
14810
|
+
import { readFileSync as readFileSync11 } from "node:fs";
|
|
14411
14811
|
var obj = (v) => v !== null && typeof v === "object" && !Array.isArray(v) ? v : null;
|
|
14412
14812
|
var str8 = (v) => typeof v === "string" && v.length > 0 ? v : null;
|
|
14413
14813
|
var CONDUCTOR_API = "https://api.conductor.build";
|
|
@@ -14505,7 +14905,7 @@ var ids = (h) => {
|
|
|
14505
14905
|
var ENDED = new Set(["archived", "deleted"]);
|
|
14506
14906
|
function conductorRunner(exec, deps = {}) {
|
|
14507
14907
|
const env = deps.env ?? process.env;
|
|
14508
|
-
const readFile = deps.readFile ?? ((p) =>
|
|
14908
|
+
const readFile = deps.readFile ?? ((p) => readFileSync11(p, "utf8"));
|
|
14509
14909
|
const now = deps.now ?? Date.now;
|
|
14510
14910
|
const base = env.CONDUCTOR_API_URL?.trim() || CONDUCTOR_API;
|
|
14511
14911
|
const key = () => {
|
|
@@ -14624,8 +15024,8 @@ ${renderTranscript(messages)}`;
|
|
|
14624
15024
|
var headlessScript = (o, log) => {
|
|
14625
15025
|
const prompt = `"$(cat ${shq2(o.promptFile)})"`;
|
|
14626
15026
|
const agent = o.agent?.trim();
|
|
14627
|
-
const cmd = agent ? `${sandboxedAgent(agent, o.sandbox)} ${prompt}` : [
|
|
14628
|
-
`${sandboxedAgent("claude", o.sandbox)} -p`,
|
|
15027
|
+
const cmd = agent ? `${sandboxedAgent(agent, o.sandbox, o.mainCheckout)} ${prompt}` : [
|
|
15028
|
+
`${sandboxedAgent("claude", o.sandbox, o.mainCheckout)} -p`,
|
|
14629
15029
|
prompt,
|
|
14630
15030
|
...o.mcpConfig ? [mcpConfigFlag(o).trim()] : [],
|
|
14631
15031
|
"--output-format stream-json --verbose",
|
|
@@ -14696,7 +15096,7 @@ function headlessRunner(deps = {}) {
|
|
|
14696
15096
|
|
|
14697
15097
|
// src/runners/managed.ts
|
|
14698
15098
|
init_src();
|
|
14699
|
-
import { readFileSync as
|
|
15099
|
+
import { readFileSync as readFileSync12 } from "node:fs";
|
|
14700
15100
|
var obj2 = (v) => v !== null && typeof v === "object" && !Array.isArray(v) ? v : null;
|
|
14701
15101
|
var str9 = (v) => typeof v === "string" && v.length > 0 ? v : null;
|
|
14702
15102
|
var ANTHROPIC_API = "https://api.anthropic.com";
|
|
@@ -14832,7 +15232,7 @@ var statusLine2 = (session, events, now) => {
|
|
|
14832
15232
|
var YES = /^\s*(?:y|yes|allow|ok|okay|go|go ahead|approve[d]?)\b/i;
|
|
14833
15233
|
function managedRunner(exec, deps = {}) {
|
|
14834
15234
|
const env = deps.env ?? process.env;
|
|
14835
|
-
const readFile = deps.readFile ?? ((p) =>
|
|
15235
|
+
const readFile = deps.readFile ?? ((p) => readFileSync12(p, "utf8"));
|
|
14836
15236
|
const now = deps.now ?? Date.now;
|
|
14837
15237
|
const base = env.ANTHROPIC_BASE_URL?.trim() || ANTHROPIC_API;
|
|
14838
15238
|
const need = (name, where) => {
|
|
@@ -15002,7 +15402,7 @@ ${renderTranscript(eventMessages(all))}`;
|
|
|
15002
15402
|
}
|
|
15003
15403
|
|
|
15004
15404
|
// src/runners/orca.ts
|
|
15005
|
-
import { writeFileSync as
|
|
15405
|
+
import { writeFileSync as writeFileSync12 } from "node:fs";
|
|
15006
15406
|
var obj3 = (v) => v !== null && typeof v === "object" && !Array.isArray(v) ? v : null;
|
|
15007
15407
|
var str10 = (v) => typeof v === "string" && v.length > 0 ? v : null;
|
|
15008
15408
|
var parseOrcaJson = (stdout) => {
|
|
@@ -15061,7 +15461,7 @@ var orcaTerminalLive = (status, stdout) => {
|
|
|
15061
15461
|
};
|
|
15062
15462
|
var launcherPath2 = (promptFile) => `${promptFile.replace(/\.md$/, "")}.orca.sh`;
|
|
15063
15463
|
function orcaRunner(exec, deps = {}) {
|
|
15064
|
-
const writeFile = deps.writeFile ?? ((p, t) =>
|
|
15464
|
+
const writeFile = deps.writeFile ?? ((p, t) => writeFileSync12(p, t, { mode: 384 }));
|
|
15065
15465
|
const orca = (args, what) => {
|
|
15066
15466
|
const r = exec("orca", args);
|
|
15067
15467
|
const env = parseOrcaJson(r.stdout);
|
|
@@ -15201,6 +15601,14 @@ function tmuxRunner(exec) {
|
|
|
15201
15601
|
}
|
|
15202
15602
|
exec("tmux", ["send-keys", "-t", tmuxPane(h.id), "Enter"]);
|
|
15203
15603
|
},
|
|
15604
|
+
sendKey(h, key) {
|
|
15605
|
+
if (!isRunnerKey(key))
|
|
15606
|
+
throw new Error(`tmux send-keys ${h.id}: no key ${JSON.stringify(key)}`);
|
|
15607
|
+
const r = exec("tmux", ["send-keys", "-t", tmuxPane(h.id), key === "esc" ? "Escape" : key]);
|
|
15608
|
+
if (r.status !== 0) {
|
|
15609
|
+
throw new Error(`tmux send-keys ${h.id} failed: ${r.stderr.trim() || `exit ${r.status}`}`);
|
|
15610
|
+
}
|
|
15611
|
+
},
|
|
15204
15612
|
stop(h) {
|
|
15205
15613
|
exec("tmux", ["kill-session", "-t", tmuxSession(h.id)]);
|
|
15206
15614
|
},
|
|
@@ -15429,6 +15837,8 @@ function flagsFromProfile(flags, given, profile, home) {
|
|
|
15429
15837
|
const out = { ...flags };
|
|
15430
15838
|
const used = [];
|
|
15431
15839
|
const skipped = [];
|
|
15840
|
+
for (const k of profile.notYours ?? [])
|
|
15841
|
+
skipped.push(`${k} (the workspace default — the engine runs only one you set yourself)`);
|
|
15432
15842
|
if (profile.atOnce !== undefined && !has("at-once")) {
|
|
15433
15843
|
out.atOnce = profile.atOnce;
|
|
15434
15844
|
used.push(`at-once ${profile.atOnce}`);
|
|
@@ -15624,7 +16034,7 @@ function realPidAlive(pid) {
|
|
|
15624
16034
|
function memberMcpConfigs(o, cwd) {
|
|
15625
16035
|
const read = o.readJson ?? ((p) => {
|
|
15626
16036
|
try {
|
|
15627
|
-
return JSON.parse(
|
|
16037
|
+
return JSON.parse(readFileSync13(p, "utf8"));
|
|
15628
16038
|
} catch {
|
|
15629
16039
|
return null;
|
|
15630
16040
|
}
|
|
@@ -15666,6 +16076,9 @@ function engineDeps(o, flags, source, runner, stateName) {
|
|
|
15666
16076
|
const repo = flags.repo ? resolve7(cwd, flags.repo) : undefined;
|
|
15667
16077
|
const reposDirs = splitReposDirs(flags.reposDir).map((d) => resolve7(cwd, d));
|
|
15668
16078
|
const { branch, prTitle } = flags;
|
|
16079
|
+
const hooksDir = join15(stateDir, "hooks");
|
|
16080
|
+
const permissionMark = (name) => join15(hooksDir, `${name}.permission.json`);
|
|
16081
|
+
const withHook = (name, settings) => applyPermissionHook(settings, [...o.sledsArgv ?? ["sleds"], "permission-event", "--mark", permissionMark(name)].map(shq2).join(" "));
|
|
15669
16082
|
return {
|
|
15670
16083
|
source,
|
|
15671
16084
|
runner,
|
|
@@ -15690,18 +16103,35 @@ function engineDeps(o, flags, source, runner, stateName) {
|
|
|
15690
16103
|
writeSandboxSettings: o.writeSandboxSettings ?? ((name, cwd) => {
|
|
15691
16104
|
const gitCommonDir = gitCommonDirOf(exec, cwd);
|
|
15692
16105
|
const dir = join15(stateDir, "sandbox");
|
|
15693
|
-
|
|
16106
|
+
mkdirSync12(dir, { recursive: true, mode: 448 });
|
|
15694
16107
|
const p = join15(dir, `${name}.json`);
|
|
15695
|
-
const
|
|
16108
|
+
const walls = engineSandboxSettings(o.home, o.env ?? process.env, gitCommonDir, [
|
|
15696
16109
|
...SANDBOX_DEFAULT_ALLOW,
|
|
15697
16110
|
...flags.sandboxAllow ?? []
|
|
15698
16111
|
]);
|
|
15699
|
-
|
|
16112
|
+
const settings = withHook(name, { ...walls });
|
|
16113
|
+
writeFileSync13(p, `${JSON.stringify(settings, null, 2)}
|
|
15700
16114
|
`, { mode: 384 });
|
|
15701
|
-
|
|
16115
|
+
chmodSync4(p, 384);
|
|
15702
16116
|
return { settingsFile: p, gitCommonDir };
|
|
15703
16117
|
})
|
|
15704
16118
|
} : {},
|
|
16119
|
+
writeHookSettings: (name) => {
|
|
16120
|
+
mkdirSync12(hooksDir, { recursive: true, mode: 448 });
|
|
16121
|
+
const p = join15(hooksDir, `${name}.json`);
|
|
16122
|
+
writeFileSync13(p, `${JSON.stringify(withHook(name, {}), null, 2)}
|
|
16123
|
+
`, { mode: 384 });
|
|
16124
|
+
chmodSync4(p, 384);
|
|
16125
|
+
return p;
|
|
16126
|
+
},
|
|
16127
|
+
permissionMark,
|
|
16128
|
+
mainCheckoutOf: o.mainCheckoutOf ?? ((cwd) => {
|
|
16129
|
+
try {
|
|
16130
|
+
return mainCheckoutOf(gitCommonDirOf(exec, cwd), cwd);
|
|
16131
|
+
} catch {
|
|
16132
|
+
return null;
|
|
16133
|
+
}
|
|
16134
|
+
}),
|
|
15705
16135
|
...branch ? { branchOf: (claim) => branchFor(branch, claim) } : {},
|
|
15706
16136
|
...prTitle ? { prTitleOf: (claim) => prTitleFor(prTitle, claim) } : {},
|
|
15707
16137
|
now: o.now ?? Date.now,
|
|
@@ -15716,7 +16146,7 @@ function engineDeps(o, flags, source, runner, stateName) {
|
|
|
15716
16146
|
}),
|
|
15717
16147
|
writeMcpConfig: o.writeMcpConfig ?? ((name, runToken, worktree) => {
|
|
15718
16148
|
const dir = join15(stateDir, "mcp");
|
|
15719
|
-
|
|
16149
|
+
mkdirSync12(dir, { recursive: true, mode: 448 });
|
|
15720
16150
|
const p = join15(dir, `${name}.json`);
|
|
15721
16151
|
let others = {};
|
|
15722
16152
|
if (flags.strictMcp && flags.mcpAllow?.length) {
|
|
@@ -15727,16 +16157,16 @@ function engineDeps(o, flags, source, runner, stateName) {
|
|
|
15727
16157
|
if (r.refused.length)
|
|
15728
16158
|
log(`${name}: MCP pass-through refused ${r.refused.join(", ")} — the run's sleds server is the only SLEDS one`);
|
|
15729
16159
|
}
|
|
15730
|
-
|
|
15731
|
-
|
|
16160
|
+
writeFileSync13(p, pinOrg2(engineMcpConfig(runToken, others), mcpOrg), { mode: 384 });
|
|
16161
|
+
chmodSync4(p, 384);
|
|
15732
16162
|
return p;
|
|
15733
16163
|
}),
|
|
15734
|
-
removeMcpConfig: o.removeMcpConfig ?? ((p) =>
|
|
16164
|
+
removeMcpConfig: o.removeMcpConfig ?? ((p) => rmSync4(p, { force: true })),
|
|
15735
16165
|
writePrompt: o.writePrompt ?? ((name, text) => {
|
|
15736
16166
|
const dir = join15(stateDir, "prompts");
|
|
15737
|
-
|
|
16167
|
+
mkdirSync12(dir, { recursive: true, mode: 448 });
|
|
15738
16168
|
const p = join15(dir, `${name}.md`);
|
|
15739
|
-
|
|
16169
|
+
writeFileSync13(p, text, { mode: 384 });
|
|
15740
16170
|
return p;
|
|
15741
16171
|
}),
|
|
15742
16172
|
ensureWorktree: (e, repoPath, branch, path, base, install) => ensureWorktree(e, repoPath, branch, path, base, o.worktreeFs ?? { ...realWorktreeFs, exists }, { ...install ? { command: install } : {}, log: o.log ?? console.log }),
|
|
@@ -15819,7 +16249,8 @@ async function driveEngine(o, flags, deps, until = {}) {
|
|
|
15819
16249
|
startedAt: (o.now ?? Date.now)(),
|
|
15820
16250
|
runner: deps.runner.name,
|
|
15821
16251
|
atOnce: flags.atOnce,
|
|
15822
|
-
interval: flags.interval
|
|
16252
|
+
interval: flags.interval,
|
|
16253
|
+
cliVersion: "0.1.39"
|
|
15823
16254
|
};
|
|
15824
16255
|
const beat = (checkedAt) => {
|
|
15825
16256
|
const m = deps.machine;
|
|
@@ -16111,7 +16542,7 @@ async function enginePauseCmd(o) {
|
|
|
16111
16542
|
result.released++;
|
|
16112
16543
|
result.kept.push(run.handle.cwd);
|
|
16113
16544
|
if (run.mcpConfig)
|
|
16114
|
-
|
|
16545
|
+
rmSync4(run.mcpConfig, { force: true });
|
|
16115
16546
|
}
|
|
16116
16547
|
if (gone.size)
|
|
16117
16548
|
writeState(file, { ...state, runs: state.runs.filter((r) => !gone.has(r)) });
|
|
@@ -16133,19 +16564,19 @@ init_config();
|
|
|
16133
16564
|
init_state();
|
|
16134
16565
|
import {
|
|
16135
16566
|
existsSync as existsSync14,
|
|
16136
|
-
mkdirSync as
|
|
16137
|
-
readFileSync as
|
|
16567
|
+
mkdirSync as mkdirSync14,
|
|
16568
|
+
readFileSync as readFileSync14,
|
|
16138
16569
|
readdirSync as readdirSync2,
|
|
16139
16570
|
realpathSync,
|
|
16140
|
-
rmSync as
|
|
16141
|
-
writeFileSync as
|
|
16571
|
+
rmSync as rmSync6,
|
|
16572
|
+
writeFileSync as writeFileSync15
|
|
16142
16573
|
} from "node:fs";
|
|
16143
16574
|
import { hostname as hostname3 } from "node:os";
|
|
16144
16575
|
import { basename as basename4, dirname as dirname12, isAbsolute as isAbsolute2, join as join18 } from "node:path";
|
|
16145
16576
|
|
|
16146
16577
|
// src/schedule.ts
|
|
16147
16578
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
16148
|
-
import { existsSync as existsSync13, mkdirSync as
|
|
16579
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync13, rmSync as rmSync5, writeFileSync as writeFileSync14 } from "node:fs";
|
|
16149
16580
|
import { join as join16 } from "node:path";
|
|
16150
16581
|
var REVERT_LABEL = "ai.sleds.revert";
|
|
16151
16582
|
var defaultExec2 = (cmd, args) => {
|
|
@@ -16193,9 +16624,9 @@ var scheduleRevert = (d, deadlineMs) => {
|
|
|
16193
16624
|
if (d.platform === "darwin") {
|
|
16194
16625
|
const p = plistPath(d.home);
|
|
16195
16626
|
try {
|
|
16196
|
-
|
|
16627
|
+
mkdirSync13(join16(d.home, "Library", "LaunchAgents"), { recursive: true });
|
|
16197
16628
|
d.exec("launchctl", ["unload", p]);
|
|
16198
|
-
|
|
16629
|
+
writeFileSync14(p, buildLaunchdPlist(d.sledsArgv, deadline));
|
|
16199
16630
|
const r = d.exec("launchctl", ["load", p]);
|
|
16200
16631
|
if (r.ok)
|
|
16201
16632
|
return { kind: "launchd", detail: `launchd agent ${REVERT_LABEL}` };
|
|
@@ -16224,7 +16655,7 @@ var cancelRevert = (d, kind) => {
|
|
|
16224
16655
|
const p = plistPath(d.home);
|
|
16225
16656
|
if (existsSync13(p)) {
|
|
16226
16657
|
d.exec("launchctl", ["unload", p]);
|
|
16227
|
-
|
|
16658
|
+
rmSync5(p, { force: true });
|
|
16228
16659
|
}
|
|
16229
16660
|
}
|
|
16230
16661
|
if (kind === "systemd" || d.platform === "linux") {
|
|
@@ -16400,7 +16831,7 @@ function readEngines(dir, suffix, manager, parse) {
|
|
|
16400
16831
|
const path = join18(dir, name);
|
|
16401
16832
|
let parsed;
|
|
16402
16833
|
try {
|
|
16403
|
-
parsed = parse(
|
|
16834
|
+
parsed = parse(readFileSync14(path, "utf8"), name);
|
|
16404
16835
|
} catch {
|
|
16405
16836
|
parsed = null;
|
|
16406
16837
|
}
|
|
@@ -16454,7 +16885,7 @@ function engineInstall(o) {
|
|
|
16454
16885
|
const stateDir = seatStateDir(orgStateDir(baseDir, parsed.org), seat);
|
|
16455
16886
|
const label = engineLabel(parsed.name, parsed.org, seat);
|
|
16456
16887
|
const logPath = engineLogPath(stateDir, parsed.name);
|
|
16457
|
-
|
|
16888
|
+
mkdirSync14(stateDir, { recursive: true, mode: 448 });
|
|
16458
16889
|
const sledsArgv = stableArgv(o.sledsArgv, o.realpath);
|
|
16459
16890
|
const execPath = sledsArgv[0] ?? process.execPath;
|
|
16460
16891
|
const agentEnv = {
|
|
@@ -16467,7 +16898,7 @@ function engineInstall(o) {
|
|
|
16467
16898
|
if (platform === "linux")
|
|
16468
16899
|
return installUnit({ o, parsed, label, sledsArgv, env: agentEnv, logPath, exec });
|
|
16469
16900
|
const plist = enginePlistPath(o.home, parsed.name, parsed.org, seat);
|
|
16470
|
-
|
|
16901
|
+
mkdirSync14(dirname12(plist), { recursive: true });
|
|
16471
16902
|
if (existsSync14(plist))
|
|
16472
16903
|
exec("launchctl", ["unload", plist]);
|
|
16473
16904
|
for (const other of installedEngines(o.home)) {
|
|
@@ -16476,7 +16907,7 @@ function engineInstall(o) {
|
|
|
16476
16907
|
if (engineArg(other.programArgs, "name") !== parsed.name)
|
|
16477
16908
|
continue;
|
|
16478
16909
|
exec("launchctl", ["unload", other.plist]);
|
|
16479
|
-
|
|
16910
|
+
rmSync6(other.plist, { force: true });
|
|
16480
16911
|
log(`replaced ${other.label}, this engine as installed before`);
|
|
16481
16912
|
}
|
|
16482
16913
|
const legacy = enginePlistPath(o.home, parsed.name);
|
|
@@ -16484,12 +16915,12 @@ function engineInstall(o) {
|
|
|
16484
16915
|
const cfg = readConfig(o.home);
|
|
16485
16916
|
if (org.sole || parsed.org === (cfg.activeOrg ?? cfg.org?.slug)) {
|
|
16486
16917
|
exec("launchctl", ["unload", legacy]);
|
|
16487
|
-
|
|
16918
|
+
rmSync6(legacy, { force: true });
|
|
16488
16919
|
log(`replaced ${engineLabel(parsed.name)}, the engine installed before orgs`);
|
|
16489
16920
|
} else
|
|
16490
16921
|
log(`note: ${engineLabel(parsed.name)} (installed before orgs) still runs — \`sleds engine uninstall --name ${parsed.name}\` removes it if it was this org's`);
|
|
16491
16922
|
}
|
|
16492
|
-
|
|
16923
|
+
writeFileSync15(plist, buildEnginePlist({ label, sledsArgv, args: parsed.args, env: agentEnv, logPath }));
|
|
16493
16924
|
const r = exec("launchctl", ["load", plist]);
|
|
16494
16925
|
if (!r.ok) {
|
|
16495
16926
|
error(`launchctl load failed: ${r.stderr.trim() || "unknown"}`);
|
|
@@ -16509,7 +16940,7 @@ function installUnit(a) {
|
|
|
16509
16940
|
const unit = engineUnitPath(o.home, label);
|
|
16510
16941
|
const unitName = basename4(unit);
|
|
16511
16942
|
const systemctl = (...args) => exec("systemctl", ["--user", ...args]);
|
|
16512
|
-
|
|
16943
|
+
mkdirSync14(dirname12(unit), { recursive: true });
|
|
16513
16944
|
if (existsSync14(unit))
|
|
16514
16945
|
systemctl("stop", unitName);
|
|
16515
16946
|
for (const other of installedEngines(o.home)) {
|
|
@@ -16518,10 +16949,10 @@ function installUnit(a) {
|
|
|
16518
16949
|
if (engineArg(other.programArgs, "name") !== parsed.name)
|
|
16519
16950
|
continue;
|
|
16520
16951
|
systemctl("disable", "--now", basename4(other.plist));
|
|
16521
|
-
|
|
16952
|
+
rmSync6(other.plist, { force: true });
|
|
16522
16953
|
log(`replaced ${other.label}, this engine as installed before`);
|
|
16523
16954
|
}
|
|
16524
|
-
|
|
16955
|
+
writeFileSync15(unit, buildEngineUnit({
|
|
16525
16956
|
label,
|
|
16526
16957
|
name: parsed.name,
|
|
16527
16958
|
sledsArgv: a.sledsArgv,
|
|
@@ -16579,7 +17010,7 @@ function engineUninstall(o) {
|
|
|
16579
17010
|
exec("systemctl", ["--user", "disable", "--now", basename4(file)]);
|
|
16580
17011
|
else
|
|
16581
17012
|
exec("launchctl", ["unload", file]);
|
|
16582
|
-
|
|
17013
|
+
rmSync6(file, { force: true });
|
|
16583
17014
|
if (unit)
|
|
16584
17015
|
exec("systemctl", ["--user", "daemon-reload"]);
|
|
16585
17016
|
log(`engine:${name} removed: ${basename4(file, unit ? ".service" : ".plist")} — its sessions keep running`);
|
|
@@ -16587,7 +17018,7 @@ function engineUninstall(o) {
|
|
|
16587
17018
|
}
|
|
16588
17019
|
|
|
16589
17020
|
// src/commands/musher.ts
|
|
16590
|
-
import { existsSync as existsSync15, mkdirSync as
|
|
17021
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync15, readFileSync as readFileSync15, rmSync as rmSync7, writeFileSync as writeFileSync16 } from "node:fs";
|
|
16591
17022
|
init_config();
|
|
16592
17023
|
init_meter();
|
|
16593
17024
|
var defaultWhich = (cmd) => {
|
|
@@ -16620,7 +17051,7 @@ var musherAgentState = (home, env = process.env) => {
|
|
|
16620
17051
|
if (!existsSync15(plist))
|
|
16621
17052
|
return { installed: false, thisSeat: false };
|
|
16622
17053
|
try {
|
|
16623
|
-
const text =
|
|
17054
|
+
const text = readFileSync15(plist, "utf8");
|
|
16624
17055
|
const want = env.SLEDS_HOME?.trim();
|
|
16625
17056
|
const has = /<key>SLEDS_HOME<\/key>\s*<string>([^<]*)<\/string>/.exec(text)?.[1];
|
|
16626
17057
|
return { installed: true, thisSeat: (want ?? undefined) === (has ?? undefined) };
|
|
@@ -16980,7 +17411,7 @@ function sandboxChecks(o, env) {
|
|
|
16980
17411
|
const probe = join19(dir, SANDBOX_PROBE);
|
|
16981
17412
|
const work = mkdtempSync(join19(tmpdir(), "sleds-sandbox-"));
|
|
16982
17413
|
try {
|
|
16983
|
-
|
|
17414
|
+
writeFileSync17(probe, `${nonce}
|
|
16984
17415
|
`, { mode: 384 });
|
|
16985
17416
|
const settingsFile = join19(work, "settings.json");
|
|
16986
17417
|
const settings = sandboxSettings({
|
|
@@ -16988,7 +17419,7 @@ function sandboxChecks(o, env) {
|
|
|
16988
17419
|
gitCommonDir: work,
|
|
16989
17420
|
allow: SANDBOX_DEFAULT_ALLOW
|
|
16990
17421
|
});
|
|
16991
|
-
|
|
17422
|
+
writeFileSync17(settingsFile, JSON.stringify(settings, null, 2), { mode: 384 });
|
|
16992
17423
|
const prompt = `Run exactly this one Bash command, once, then reply with its complete output verbatim and nothing else:
|
|
16993
17424
|
|
|
16994
17425
|
${SANDBOX_PROBE_COMMAND}`;
|
|
@@ -17010,8 +17441,8 @@ ${SANDBOX_PROBE_COMMAND}`;
|
|
|
17010
17441
|
], { cwd: work });
|
|
17011
17442
|
return readSandboxProbe(run, nonce);
|
|
17012
17443
|
} finally {
|
|
17013
|
-
|
|
17014
|
-
|
|
17444
|
+
rmSync8(probe, { force: true });
|
|
17445
|
+
rmSync8(work, { recursive: true, force: true });
|
|
17015
17446
|
}
|
|
17016
17447
|
}
|
|
17017
17448
|
function engineChecks(o, env) {
|
|
@@ -17128,7 +17559,7 @@ function boxChecks(o, env, which, need) {
|
|
|
17128
17559
|
const file = boxEnvPath(o.home);
|
|
17129
17560
|
let named = false;
|
|
17130
17561
|
try {
|
|
17131
|
-
named = /^\s*(?:export\s+)?ANTHROPIC_API_KEY\s*=\s*\S/m.test(
|
|
17562
|
+
named = /^\s*(?:export\s+)?ANTHROPIC_API_KEY\s*=\s*\S/m.test(readFileSync16(file, "utf8"));
|
|
17132
17563
|
} catch {
|
|
17133
17564
|
named = false;
|
|
17134
17565
|
}
|
|
@@ -17232,12 +17663,12 @@ init_server();
|
|
|
17232
17663
|
init_config();
|
|
17233
17664
|
import {
|
|
17234
17665
|
appendFileSync as appendFileSync3,
|
|
17235
|
-
chmodSync as
|
|
17236
|
-
mkdirSync as
|
|
17237
|
-
readFileSync as
|
|
17666
|
+
chmodSync as chmodSync5,
|
|
17667
|
+
mkdirSync as mkdirSync16,
|
|
17668
|
+
readFileSync as readFileSync17,
|
|
17238
17669
|
existsSync as realExists2,
|
|
17239
|
-
rmSync as
|
|
17240
|
-
writeFileSync as
|
|
17670
|
+
rmSync as rmSync9,
|
|
17671
|
+
writeFileSync as writeFileSync18
|
|
17241
17672
|
} from "node:fs";
|
|
17242
17673
|
import { hostname as hostname4 } from "node:os";
|
|
17243
17674
|
import { join as join20, resolve as resolve9 } from "node:path";
|
|
@@ -17421,6 +17852,8 @@ function flagsFromProfile2(flags, given, profile, home) {
|
|
|
17421
17852
|
const out = { ...flags };
|
|
17422
17853
|
const used = [];
|
|
17423
17854
|
const skipped = [];
|
|
17855
|
+
for (const k of profile.notYours ?? [])
|
|
17856
|
+
skipped.push(`${k} (the workspace default — the engine runs only one you set yourself)`);
|
|
17424
17857
|
if (profile.atOnce !== undefined && !has("at-once")) {
|
|
17425
17858
|
out.atOnce = profile.atOnce;
|
|
17426
17859
|
used.push(`at-once ${profile.atOnce}`);
|
|
@@ -17645,7 +18078,7 @@ function realPidAlive2(pid) {
|
|
|
17645
18078
|
function memberMcpConfigs2(o, cwd) {
|
|
17646
18079
|
const read = o.readJson ?? ((p) => {
|
|
17647
18080
|
try {
|
|
17648
|
-
return JSON.parse(
|
|
18081
|
+
return JSON.parse(readFileSync17(p, "utf8"));
|
|
17649
18082
|
} catch {
|
|
17650
18083
|
return null;
|
|
17651
18084
|
}
|
|
@@ -17687,6 +18120,9 @@ function engineDeps2(o, flags, source, runner, stateName) {
|
|
|
17687
18120
|
const repo = flags.repo ? resolve9(cwd, flags.repo) : undefined;
|
|
17688
18121
|
const reposDirs = splitReposDirs(flags.reposDir).map((d) => resolve9(cwd, d));
|
|
17689
18122
|
const { branch, prTitle } = flags;
|
|
18123
|
+
const hooksDir = join20(stateDir, "hooks");
|
|
18124
|
+
const permissionMark = (name) => join20(hooksDir, `${name}.permission.json`);
|
|
18125
|
+
const withHook = (name, settings) => applyPermissionHook(settings, [...o.sledsArgv ?? ["sleds"], "permission-event", "--mark", permissionMark(name)].map(shq2).join(" "));
|
|
17690
18126
|
return {
|
|
17691
18127
|
source,
|
|
17692
18128
|
runner,
|
|
@@ -17711,18 +18147,35 @@ function engineDeps2(o, flags, source, runner, stateName) {
|
|
|
17711
18147
|
writeSandboxSettings: o.writeSandboxSettings ?? ((name, cwd) => {
|
|
17712
18148
|
const gitCommonDir = gitCommonDirOf2(exec, cwd);
|
|
17713
18149
|
const dir = join20(stateDir, "sandbox");
|
|
17714
|
-
|
|
18150
|
+
mkdirSync16(dir, { recursive: true, mode: 448 });
|
|
17715
18151
|
const p = join20(dir, `${name}.json`);
|
|
17716
|
-
const
|
|
18152
|
+
const walls = engineSandboxSettings2(o.home, o.env ?? process.env, gitCommonDir, [
|
|
17717
18153
|
...SANDBOX_DEFAULT_ALLOW,
|
|
17718
18154
|
...flags.sandboxAllow ?? []
|
|
17719
18155
|
]);
|
|
17720
|
-
|
|
18156
|
+
const settings = withHook(name, { ...walls });
|
|
18157
|
+
writeFileSync18(p, `${JSON.stringify(settings, null, 2)}
|
|
17721
18158
|
`, { mode: 384 });
|
|
17722
|
-
|
|
18159
|
+
chmodSync5(p, 384);
|
|
17723
18160
|
return { settingsFile: p, gitCommonDir };
|
|
17724
18161
|
})
|
|
17725
18162
|
} : {},
|
|
18163
|
+
writeHookSettings: (name) => {
|
|
18164
|
+
mkdirSync16(hooksDir, { recursive: true, mode: 448 });
|
|
18165
|
+
const p = join20(hooksDir, `${name}.json`);
|
|
18166
|
+
writeFileSync18(p, `${JSON.stringify(withHook(name, {}), null, 2)}
|
|
18167
|
+
`, { mode: 384 });
|
|
18168
|
+
chmodSync5(p, 384);
|
|
18169
|
+
return p;
|
|
18170
|
+
},
|
|
18171
|
+
permissionMark,
|
|
18172
|
+
mainCheckoutOf: o.mainCheckoutOf ?? ((cwd) => {
|
|
18173
|
+
try {
|
|
18174
|
+
return mainCheckoutOf(gitCommonDirOf2(exec, cwd), cwd);
|
|
18175
|
+
} catch {
|
|
18176
|
+
return null;
|
|
18177
|
+
}
|
|
18178
|
+
}),
|
|
17726
18179
|
...branch ? { branchOf: (claim) => branchFor(branch, claim) } : {},
|
|
17727
18180
|
...prTitle ? { prTitleOf: (claim) => prTitleFor(prTitle, claim) } : {},
|
|
17728
18181
|
now: o.now ?? Date.now,
|
|
@@ -17737,7 +18190,7 @@ function engineDeps2(o, flags, source, runner, stateName) {
|
|
|
17737
18190
|
}),
|
|
17738
18191
|
writeMcpConfig: o.writeMcpConfig ?? ((name, runToken, worktree) => {
|
|
17739
18192
|
const dir = join20(stateDir, "mcp");
|
|
17740
|
-
|
|
18193
|
+
mkdirSync16(dir, { recursive: true, mode: 448 });
|
|
17741
18194
|
const p = join20(dir, `${name}.json`);
|
|
17742
18195
|
let others = {};
|
|
17743
18196
|
if (flags.strictMcp && flags.mcpAllow?.length) {
|
|
@@ -17748,16 +18201,16 @@ function engineDeps2(o, flags, source, runner, stateName) {
|
|
|
17748
18201
|
if (r.refused.length)
|
|
17749
18202
|
log(`${name}: MCP pass-through refused ${r.refused.join(", ")} — the run's sleds server is the only SLEDS one`);
|
|
17750
18203
|
}
|
|
17751
|
-
|
|
17752
|
-
|
|
18204
|
+
writeFileSync18(p, pinOrg3(engineMcpConfig(runToken, others), mcpOrg), { mode: 384 });
|
|
18205
|
+
chmodSync5(p, 384);
|
|
17753
18206
|
return p;
|
|
17754
18207
|
}),
|
|
17755
|
-
removeMcpConfig: o.removeMcpConfig ?? ((p) =>
|
|
18208
|
+
removeMcpConfig: o.removeMcpConfig ?? ((p) => rmSync9(p, { force: true })),
|
|
17756
18209
|
writePrompt: o.writePrompt ?? ((name, text) => {
|
|
17757
18210
|
const dir = join20(stateDir, "prompts");
|
|
17758
|
-
|
|
18211
|
+
mkdirSync16(dir, { recursive: true, mode: 448 });
|
|
17759
18212
|
const p = join20(dir, `${name}.md`);
|
|
17760
|
-
|
|
18213
|
+
writeFileSync18(p, text, { mode: 384 });
|
|
17761
18214
|
return p;
|
|
17762
18215
|
}),
|
|
17763
18216
|
ensureWorktree: (e, repoPath, branch, path, base, install) => ensureWorktree(e, repoPath, branch, path, base, o.worktreeFs ?? { ...realWorktreeFs, exists }, { ...install ? { command: install } : {}, log: o.log ?? console.log }),
|
|
@@ -17849,7 +18302,8 @@ async function driveEngine2(o, flags, deps, until = {}) {
|
|
|
17849
18302
|
startedAt: (o.now ?? Date.now)(),
|
|
17850
18303
|
runner: deps.runner.name,
|
|
17851
18304
|
atOnce: flags.atOnce,
|
|
17852
|
-
interval: flags.interval
|
|
18305
|
+
interval: flags.interval,
|
|
18306
|
+
cliVersion: "0.1.39"
|
|
17853
18307
|
};
|
|
17854
18308
|
const beat = (checkedAt) => {
|
|
17855
18309
|
const m = deps.machine;
|
|
@@ -18255,7 +18709,7 @@ async function enginePauseCmd2(o) {
|
|
|
18255
18709
|
result.released++;
|
|
18256
18710
|
result.kept.push(run.handle.cwd);
|
|
18257
18711
|
if (run.mcpConfig)
|
|
18258
|
-
|
|
18712
|
+
rmSync9(run.mcpConfig, { force: true });
|
|
18259
18713
|
}
|
|
18260
18714
|
if (gone.size)
|
|
18261
18715
|
writeState(file, { ...state, runs: state.runs.filter((r) => !gone.has(r)) });
|
|
@@ -18277,12 +18731,12 @@ init_config();
|
|
|
18277
18731
|
init_state();
|
|
18278
18732
|
import {
|
|
18279
18733
|
existsSync as existsSync17,
|
|
18280
|
-
mkdirSync as
|
|
18281
|
-
readFileSync as
|
|
18734
|
+
mkdirSync as mkdirSync17,
|
|
18735
|
+
readFileSync as readFileSync18,
|
|
18282
18736
|
readdirSync as readdirSync4,
|
|
18283
18737
|
realpathSync as realpathSync2,
|
|
18284
|
-
rmSync as
|
|
18285
|
-
writeFileSync as
|
|
18738
|
+
rmSync as rmSync10,
|
|
18739
|
+
writeFileSync as writeFileSync19
|
|
18286
18740
|
} from "node:fs";
|
|
18287
18741
|
import { hostname as hostname5 } from "node:os";
|
|
18288
18742
|
import { basename as basename5, dirname as dirname13, isAbsolute as isAbsolute3, join as join21 } from "node:path";
|
|
@@ -18404,7 +18858,7 @@ function readEngines2(dir, suffix, manager, parse) {
|
|
|
18404
18858
|
const path = join21(dir, name);
|
|
18405
18859
|
let parsed;
|
|
18406
18860
|
try {
|
|
18407
|
-
parsed = parse(
|
|
18861
|
+
parsed = parse(readFileSync18(path, "utf8"), name);
|
|
18408
18862
|
} catch {
|
|
18409
18863
|
parsed = null;
|
|
18410
18864
|
}
|
|
@@ -18458,7 +18912,7 @@ function engineInstall2(o) {
|
|
|
18458
18912
|
const stateDir = seatStateDir(orgStateDir(baseDir, parsed.org), seat);
|
|
18459
18913
|
const label = engineLabel2(parsed.name, parsed.org, seat);
|
|
18460
18914
|
const logPath = engineLogPath2(stateDir, parsed.name);
|
|
18461
|
-
|
|
18915
|
+
mkdirSync17(stateDir, { recursive: true, mode: 448 });
|
|
18462
18916
|
const sledsArgv = stableArgv2(o.sledsArgv, o.realpath);
|
|
18463
18917
|
const execPath = sledsArgv[0] ?? process.execPath;
|
|
18464
18918
|
const agentEnv = {
|
|
@@ -18471,7 +18925,7 @@ function engineInstall2(o) {
|
|
|
18471
18925
|
if (platform === "linux")
|
|
18472
18926
|
return installUnit2({ o, parsed, label, sledsArgv, env: agentEnv, logPath, exec });
|
|
18473
18927
|
const plist = enginePlistPath2(o.home, parsed.name, parsed.org, seat);
|
|
18474
|
-
|
|
18928
|
+
mkdirSync17(dirname13(plist), { recursive: true });
|
|
18475
18929
|
if (existsSync17(plist))
|
|
18476
18930
|
exec("launchctl", ["unload", plist]);
|
|
18477
18931
|
for (const other of installedEngines2(o.home)) {
|
|
@@ -18480,7 +18934,7 @@ function engineInstall2(o) {
|
|
|
18480
18934
|
if (engineArg2(other.programArgs, "name") !== parsed.name)
|
|
18481
18935
|
continue;
|
|
18482
18936
|
exec("launchctl", ["unload", other.plist]);
|
|
18483
|
-
|
|
18937
|
+
rmSync10(other.plist, { force: true });
|
|
18484
18938
|
log(`replaced ${other.label}, this engine as installed before`);
|
|
18485
18939
|
}
|
|
18486
18940
|
const legacy = enginePlistPath2(o.home, parsed.name);
|
|
@@ -18488,12 +18942,12 @@ function engineInstall2(o) {
|
|
|
18488
18942
|
const cfg = readConfig(o.home);
|
|
18489
18943
|
if (org.sole || parsed.org === (cfg.activeOrg ?? cfg.org?.slug)) {
|
|
18490
18944
|
exec("launchctl", ["unload", legacy]);
|
|
18491
|
-
|
|
18945
|
+
rmSync10(legacy, { force: true });
|
|
18492
18946
|
log(`replaced ${engineLabel2(parsed.name)}, the engine installed before orgs`);
|
|
18493
18947
|
} else
|
|
18494
18948
|
log(`note: ${engineLabel2(parsed.name)} (installed before orgs) still runs — \`sleds engine uninstall --name ${parsed.name}\` removes it if it was this org's`);
|
|
18495
18949
|
}
|
|
18496
|
-
|
|
18950
|
+
writeFileSync19(plist, buildEnginePlist2({ label, sledsArgv, args: parsed.args, env: agentEnv, logPath }));
|
|
18497
18951
|
const r = exec("launchctl", ["load", plist]);
|
|
18498
18952
|
if (!r.ok) {
|
|
18499
18953
|
error(`launchctl load failed: ${r.stderr.trim() || "unknown"}`);
|
|
@@ -18513,7 +18967,7 @@ function installUnit2(a) {
|
|
|
18513
18967
|
const unit = engineUnitPath(o.home, label);
|
|
18514
18968
|
const unitName = basename5(unit);
|
|
18515
18969
|
const systemctl = (...args) => exec("systemctl", ["--user", ...args]);
|
|
18516
|
-
|
|
18970
|
+
mkdirSync17(dirname13(unit), { recursive: true });
|
|
18517
18971
|
if (existsSync17(unit))
|
|
18518
18972
|
systemctl("stop", unitName);
|
|
18519
18973
|
for (const other of installedEngines2(o.home)) {
|
|
@@ -18522,10 +18976,10 @@ function installUnit2(a) {
|
|
|
18522
18976
|
if (engineArg2(other.programArgs, "name") !== parsed.name)
|
|
18523
18977
|
continue;
|
|
18524
18978
|
systemctl("disable", "--now", basename5(other.plist));
|
|
18525
|
-
|
|
18979
|
+
rmSync10(other.plist, { force: true });
|
|
18526
18980
|
log(`replaced ${other.label}, this engine as installed before`);
|
|
18527
18981
|
}
|
|
18528
|
-
|
|
18982
|
+
writeFileSync19(unit, buildEngineUnit({
|
|
18529
18983
|
label,
|
|
18530
18984
|
name: parsed.name,
|
|
18531
18985
|
sledsArgv: a.sledsArgv,
|
|
@@ -18583,7 +19037,7 @@ function engineUninstall2(o) {
|
|
|
18583
19037
|
exec("systemctl", ["--user", "disable", "--now", basename5(file)]);
|
|
18584
19038
|
else
|
|
18585
19039
|
exec("launchctl", ["unload", file]);
|
|
18586
|
-
|
|
19040
|
+
rmSync10(file, { force: true });
|
|
18587
19041
|
if (unit)
|
|
18588
19042
|
exec("systemctl", ["--user", "daemon-reload"]);
|
|
18589
19043
|
log(`engine:${name} removed: ${basename5(file, unit ? ".service" : ".plist")} — its sessions keep running`);
|
|
@@ -18714,7 +19168,7 @@ import { closeSync as closeSync3, fstatSync as fstatSync2, openSync as openSync3
|
|
|
18714
19168
|
import { hostname as hostname6 } from "node:os";
|
|
18715
19169
|
|
|
18716
19170
|
// src/commands/engineStatus.ts
|
|
18717
|
-
import { existsSync as existsSync18, readFileSync as
|
|
19171
|
+
import { existsSync as existsSync18, readFileSync as readFileSync19 } from "node:fs";
|
|
18718
19172
|
init_state();
|
|
18719
19173
|
|
|
18720
19174
|
// src/engine/status.ts
|
|
@@ -18827,6 +19281,7 @@ function engineStatus(i) {
|
|
|
18827
19281
|
...opt("runner", lock.runner || undefined),
|
|
18828
19282
|
atOnce: lock.atOnce,
|
|
18829
19283
|
interval: lock.interval,
|
|
19284
|
+
cliVersion: lock.cliVersion ?? "",
|
|
18830
19285
|
...opt("checkedAt", iso2(lock.checkedAt)),
|
|
18831
19286
|
...opt("nextCheckAt", alive ? iso2(lock.nextCheckAt) : undefined),
|
|
18832
19287
|
...opt("machine", lock.machine ? { ...lock.machine, at: new Date(lock.machine.at).toISOString() } : undefined),
|
|
@@ -19003,7 +19458,7 @@ var engineLogCmd = (o) => {
|
|
|
19003
19458
|
|
|
19004
19459
|
// src/commands/engineProfile.ts
|
|
19005
19460
|
init_src();
|
|
19006
|
-
import { existsSync as existsSync19, readFileSync as
|
|
19461
|
+
import { existsSync as existsSync19, readFileSync as readFileSync20 } from "node:fs";
|
|
19007
19462
|
import { hostname as hostname7 } from "node:os";
|
|
19008
19463
|
var PROFILE_USAGE = "usage: sleds engine profile [--json] | sleds engine profile set <field>=<value>… [--workspace] [--json] | sleds engine profile set --stdin [--workspace] [--json] | sleds engine profile --strict-mcp [--mcp-allow <a,b>] | --no-strict-mcp [--workspace] [--json] | sleds engine profile --sandbox [--sandbox-allow <a,b>] | --no-sandbox [--workspace] [--json] | sleds engine profile set --hold on|off [--workspace] [--json] | sleds engine profile set cmuxPassword=<pw> | --cmux-password <pw> [--json]";
|
|
19009
19464
|
var PROFILE_FIELDS = [
|
|
@@ -19268,7 +19723,7 @@ async function engineProfileCmd(o) {
|
|
|
19268
19723
|
const rest = words.slice(1);
|
|
19269
19724
|
let stdin = null;
|
|
19270
19725
|
if (fromStdin) {
|
|
19271
|
-
const taken = cmuxPasswordFromJson((o.stdin ?? (() =>
|
|
19726
|
+
const taken = cmuxPasswordFromJson((o.stdin ?? (() => readFileSync20(0, "utf8")))());
|
|
19272
19727
|
if ("error" in taken || taken.password !== undefined && password !== undefined) {
|
|
19273
19728
|
error("error" in taken ? taken.error : "the cmux password is given once");
|
|
19274
19729
|
error(PROFILE_USAGE);
|
|
@@ -19353,7 +19808,7 @@ var keychainLine = (k) => k === "set" ? "cmuxPassword: set (Keychain)" : k === "
|
|
|
19353
19808
|
|
|
19354
19809
|
// src/commands/engineStatus.ts
|
|
19355
19810
|
init_state();
|
|
19356
|
-
import { existsSync as existsSync20, readFileSync as
|
|
19811
|
+
import { existsSync as existsSync20, readFileSync as readFileSync21 } from "node:fs";
|
|
19357
19812
|
import { hostname as hostname8 } from "node:os";
|
|
19358
19813
|
var ENGINE_STATUS_USAGE = "usage: sleds engine status [--name <n>] [--org <slug>] [--json]";
|
|
19359
19814
|
function parseStatusArgs(argv, host) {
|
|
@@ -19409,7 +19864,7 @@ function readEngineStatus(stateDir, engine, host, pidAlive, seat) {
|
|
|
19409
19864
|
}
|
|
19410
19865
|
function safeRead(path) {
|
|
19411
19866
|
try {
|
|
19412
|
-
return
|
|
19867
|
+
return readFileSync21(path, "utf8");
|
|
19413
19868
|
} catch {
|
|
19414
19869
|
return "";
|
|
19415
19870
|
}
|
|
@@ -19530,7 +19985,7 @@ init_meter();
|
|
|
19530
19985
|
|
|
19531
19986
|
// src/owed.ts
|
|
19532
19987
|
init_config();
|
|
19533
|
-
import { existsSync as existsSync21, mkdirSync as
|
|
19988
|
+
import { existsSync as existsSync21, mkdirSync as mkdirSync18, readFileSync as readFileSync22, renameSync as renameSync7, writeFileSync as writeFileSync20 } from "node:fs";
|
|
19534
19989
|
import { dirname as dirname14, join as join22 } from "node:path";
|
|
19535
19990
|
var owedPath = (home) => join22(configDir(home), "owed.json");
|
|
19536
19991
|
var sessionPath = (home) => join22(configDir(home), "session.json");
|
|
@@ -19551,17 +20006,17 @@ var readJson = (p) => {
|
|
|
19551
20006
|
if (!existsSync21(p))
|
|
19552
20007
|
return null;
|
|
19553
20008
|
try {
|
|
19554
|
-
return JSON.parse(
|
|
20009
|
+
return JSON.parse(readFileSync22(p, "utf8"));
|
|
19555
20010
|
} catch {
|
|
19556
20011
|
return null;
|
|
19557
20012
|
}
|
|
19558
20013
|
};
|
|
19559
20014
|
var writeJson = (p, v) => {
|
|
19560
|
-
|
|
20015
|
+
mkdirSync18(dirname14(p), { recursive: true, mode: 448 });
|
|
19561
20016
|
const tmp = `${p}.${process.pid}.tmp`;
|
|
19562
|
-
|
|
20017
|
+
writeFileSync20(tmp, `${JSON.stringify(v, null, 2)}
|
|
19563
20018
|
`, { mode: 384 });
|
|
19564
|
-
|
|
20019
|
+
renameSync7(tmp, p);
|
|
19565
20020
|
};
|
|
19566
20021
|
var readOwed = (home, now = Date.now()) => {
|
|
19567
20022
|
const f = readJson(owedPath(home));
|
|
@@ -19766,7 +20221,7 @@ var hooksOrg = (home, env = process.env) => {
|
|
|
19766
20221
|
};
|
|
19767
20222
|
|
|
19768
20223
|
// src/commands/init.ts
|
|
19769
|
-
import { mkdirSync as
|
|
20224
|
+
import { mkdirSync as mkdirSync19, writeFileSync as writeFileSync21 } from "node:fs";
|
|
19770
20225
|
import { createInterface } from "node:readline";
|
|
19771
20226
|
init_config();
|
|
19772
20227
|
init_state();
|
|
@@ -20453,8 +20908,8 @@ var init = async (o) => {
|
|
|
20453
20908
|
});
|
|
20454
20909
|
if (mcpLine)
|
|
20455
20910
|
wrote.push(mcpLine);
|
|
20456
|
-
|
|
20457
|
-
|
|
20911
|
+
mkdirSync19(skillDir(o.home), { recursive: true });
|
|
20912
|
+
writeFileSync21(skillPath(o.home), SKILL_MD);
|
|
20458
20913
|
wrote.push(`installed skill at ${skillPath(o.home)}`);
|
|
20459
20914
|
if (o.installMusher) {
|
|
20460
20915
|
const r = o.installMusher();
|
|
@@ -20578,7 +21033,7 @@ var login = async (o) => {
|
|
|
20578
21033
|
// src/commands/logout.ts
|
|
20579
21034
|
init_config();
|
|
20580
21035
|
init_state();
|
|
20581
|
-
import { existsSync as existsSync22, readFileSync as
|
|
21036
|
+
import { existsSync as existsSync22, readFileSync as readFileSync23, rmSync as rmSync11 } from "node:fs";
|
|
20582
21037
|
import { hostname as hostname10 } from "node:os";
|
|
20583
21038
|
init_settings();
|
|
20584
21039
|
var LOGOUT_USAGE = "usage: sleds logout [--org <slug>] [--json]";
|
|
@@ -20702,7 +21157,7 @@ async function logout(o) {
|
|
|
20702
21157
|
continue;
|
|
20703
21158
|
if (!e.org) {
|
|
20704
21159
|
(o.exec ?? defaultExec2)("launchctl", ["unload", e.plist]);
|
|
20705
|
-
|
|
21160
|
+
rmSync11(e.plist, { force: true });
|
|
20706
21161
|
continue;
|
|
20707
21162
|
}
|
|
20708
21163
|
engineUninstall({
|
|
@@ -20735,8 +21190,8 @@ async function logout(o) {
|
|
|
20735
21190
|
};
|
|
20736
21191
|
writeConfig(o.home, next);
|
|
20737
21192
|
const tp = tokenPath(o.home, env);
|
|
20738
|
-
if (existsSync22(tp) &&
|
|
20739
|
-
|
|
21193
|
+
if (existsSync22(tp) && readFileSync23(tp, "utf8").trim() === seat.token)
|
|
21194
|
+
rmSync11(tp, { force: true });
|
|
20740
21195
|
const active = next.activeOrg ?? next.org?.slug ?? null;
|
|
20741
21196
|
const result = { ok: true, email, org: slug, paused, active };
|
|
20742
21197
|
if (parsed.json)
|
|
@@ -20764,8 +21219,9 @@ var mcp = async (o) => {
|
|
|
20764
21219
|
(o.warn ?? ((line) => process.stderr.write(`${line}
|
|
20765
21220
|
`)))("sleds mcp: on this run's token (SLEDS_RUN_TOKEN), not the seat's");
|
|
20766
21221
|
let buffer = "";
|
|
21222
|
+
const decoder = new TextDecoder;
|
|
20767
21223
|
for await (const chunk of stdin) {
|
|
20768
|
-
buffer += typeof chunk === "string" ? chunk :
|
|
21224
|
+
buffer += typeof chunk === "string" ? chunk : decoder.decode(chunk, { stream: true });
|
|
20769
21225
|
let nl = buffer.indexOf(`
|
|
20770
21226
|
`);
|
|
20771
21227
|
while (nl !== -1) {
|
|
@@ -20778,6 +21234,7 @@ var mcp = async (o) => {
|
|
|
20778
21234
|
`);
|
|
20779
21235
|
}
|
|
20780
21236
|
}
|
|
21237
|
+
buffer += decoder.decode();
|
|
20781
21238
|
if (buffer.trim().length > 0) {
|
|
20782
21239
|
const out = await handleLine2(buffer, { home: o.home, env });
|
|
20783
21240
|
if (out !== null)
|
|
@@ -20811,7 +21268,7 @@ var meter = async (o) => {
|
|
|
20811
21268
|
init_config();
|
|
20812
21269
|
init_meter();
|
|
20813
21270
|
import { spawnSync as spawnSync7 } from "node:child_process";
|
|
20814
|
-
import { existsSync as existsSync23, mkdirSync as
|
|
21271
|
+
import { existsSync as existsSync23, mkdirSync as mkdirSync20, readFileSync as readFileSync24, rmSync as rmSync12, writeFileSync as writeFileSync22 } from "node:fs";
|
|
20815
21272
|
import { hostname as hostname11 } from "node:os";
|
|
20816
21273
|
import { dirname as dirname15 } from "node:path";
|
|
20817
21274
|
var defaultWhich3 = (cmd) => {
|
|
@@ -20851,8 +21308,8 @@ var musherInstall = (o) => {
|
|
|
20851
21308
|
const plist = musherPlistPath(o.home, env);
|
|
20852
21309
|
const label = musherLabel(env);
|
|
20853
21310
|
const dir = configDir(o.home, env);
|
|
20854
|
-
|
|
20855
|
-
|
|
21311
|
+
mkdirSync20(dirname15(plist), { recursive: true });
|
|
21312
|
+
mkdirSync20(dir, { recursive: true, mode: 448 });
|
|
20856
21313
|
const execPath = o.sledsArgv[0] ?? process.execPath;
|
|
20857
21314
|
const agentEnv = {
|
|
20858
21315
|
PATH: musherPath(o.home, execPath, env.PATH ?? ""),
|
|
@@ -20863,7 +21320,7 @@ var musherInstall = (o) => {
|
|
|
20863
21320
|
const exec = o.exec ?? defaultExecSync;
|
|
20864
21321
|
if (existsSync23(plist))
|
|
20865
21322
|
exec("launchctl", ["unload", plist]);
|
|
20866
|
-
|
|
21323
|
+
writeFileSync22(plist, buildMusherPlist({ sledsArgv: o.sledsArgv, env: agentEnv, logPath: musherLogPath(dir), label }));
|
|
20867
21324
|
const r = exec("launchctl", ["load", plist]);
|
|
20868
21325
|
if (!r.ok) {
|
|
20869
21326
|
error(`launchctl load failed: ${r.stderr.trim() || "unknown"}`);
|
|
@@ -20884,7 +21341,7 @@ var musherUninstall = (o) => {
|
|
|
20884
21341
|
const exec = o.exec ?? defaultExecSync;
|
|
20885
21342
|
if (existsSync23(plist)) {
|
|
20886
21343
|
exec("launchctl", ["unload", plist]);
|
|
20887
|
-
|
|
21344
|
+
rmSync12(plist, { force: true });
|
|
20888
21345
|
log(`musher removed: ${musherLabel(env)}`);
|
|
20889
21346
|
} else
|
|
20890
21347
|
log("musher was not installed.");
|
|
@@ -21147,7 +21604,7 @@ var on = (o) => {
|
|
|
21147
21604
|
init_config();
|
|
21148
21605
|
init_meter();
|
|
21149
21606
|
init_settings();
|
|
21150
|
-
import { existsSync as existsSync24, rmSync as
|
|
21607
|
+
import { existsSync as existsSync24, rmSync as rmSync13 } from "node:fs";
|
|
21151
21608
|
var ORG_USAGE = "usage: sleds org list [--json] | sleds org use <slug>";
|
|
21152
21609
|
var orgRows = (cfg, activeSlug) => {
|
|
21153
21610
|
const seats = { ...cfg.orgs ?? {} };
|
|
@@ -21224,7 +21681,7 @@ var orgUse = (o) => {
|
|
|
21224
21681
|
writeSettings(o.home, removeProxy(settings));
|
|
21225
21682
|
}
|
|
21226
21683
|
try {
|
|
21227
|
-
|
|
21684
|
+
rmSync13(meterCachePath(o.home), { force: true });
|
|
21228
21685
|
} catch {}
|
|
21229
21686
|
log(`Active org: ${seat.org?.name ? `${seat.org.name} (${slug})` : slug}${seat.email ? ` · ${seat.email}` : ""}.`);
|
|
21230
21687
|
log("Claude Code, the status line and the hooks act as this org now.");
|
|
@@ -21250,7 +21707,7 @@ var orgCmd = (o) => {
|
|
|
21250
21707
|
// src/commands/pack.ts
|
|
21251
21708
|
init_src();
|
|
21252
21709
|
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
21253
|
-
import { writeFileSync as
|
|
21710
|
+
import { writeFileSync as writeFileSync23 } from "node:fs";
|
|
21254
21711
|
import { join as join23 } from "node:path";
|
|
21255
21712
|
function packFileName(key) {
|
|
21256
21713
|
return `pack-${slugify(key, 80) || "item"}.md`;
|
|
@@ -21280,22 +21737,43 @@ var packCmd = async (o) => {
|
|
|
21280
21737
|
return 0;
|
|
21281
21738
|
}
|
|
21282
21739
|
const path = join23(o.cwd ?? process.cwd(), packFileName(key));
|
|
21283
|
-
(o.write ?? ((p, t) =>
|
|
21740
|
+
(o.write ?? ((p, t) => writeFileSync23(p, t.endsWith(`
|
|
21284
21741
|
`) ? t : `${t}
|
|
21285
21742
|
`)))(path, r.text);
|
|
21286
21743
|
log(`Wrote ${path} — hand it to any model. \`sleds pack ${key} --run\` starts Claude Code with it.`);
|
|
21287
21744
|
return 0;
|
|
21288
21745
|
};
|
|
21289
21746
|
|
|
21290
|
-
// src/commands/
|
|
21291
|
-
|
|
21292
|
-
|
|
21293
|
-
|
|
21294
|
-
|
|
21295
|
-
|
|
21296
|
-
|
|
21747
|
+
// src/commands/permissionEvent.ts
|
|
21748
|
+
import { chmodSync as chmodSync6, mkdirSync as mkdirSync21, readFileSync as readFileSync25, renameSync as renameSync8, rmSync as rmSync14, writeFileSync as writeFileSync24 } from "node:fs";
|
|
21749
|
+
import { dirname as dirname16 } from "node:path";
|
|
21750
|
+
var isObject13 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
21751
|
+
var messageOf = (text) => {
|
|
21752
|
+
try {
|
|
21753
|
+
const raw = JSON.parse(text);
|
|
21754
|
+
return isObject13(raw) && typeof raw.message === "string" ? raw.message : "";
|
|
21755
|
+
} catch {
|
|
21756
|
+
return "";
|
|
21757
|
+
}
|
|
21758
|
+
};
|
|
21759
|
+
var permissionEvent = async (o) => {
|
|
21760
|
+
try {
|
|
21761
|
+
const input = o.stdin ?? await readStdin(HOOK_STDIN_TIMEOUT_MS);
|
|
21762
|
+
if (!o.mark || notificationType(input) !== "permission_prompt")
|
|
21763
|
+
return 0;
|
|
21764
|
+
const mark = { message: messageOf(input), at: (o.now ?? Date.now)() };
|
|
21765
|
+
mkdirSync21(dirname16(o.mark), { recursive: true, mode: 448 });
|
|
21766
|
+
const tmp = `${o.mark}.${process.pid}.tmp`;
|
|
21767
|
+
writeFileSync24(tmp, `${JSON.stringify(mark)}
|
|
21768
|
+
`, { mode: 384 });
|
|
21769
|
+
renameSync8(tmp, o.mark);
|
|
21770
|
+
chmodSync6(o.mark, 384);
|
|
21771
|
+
} catch {}
|
|
21772
|
+
return 0;
|
|
21773
|
+
};
|
|
21297
21774
|
|
|
21298
21775
|
// src/commands/promptEvent.ts
|
|
21776
|
+
init_config();
|
|
21299
21777
|
var LABEL = {
|
|
21300
21778
|
fiveHour: "5-hour",
|
|
21301
21779
|
sevenDay: "weekly",
|
|
@@ -21378,16 +21856,16 @@ var promptEvent = async (o) => {
|
|
|
21378
21856
|
|
|
21379
21857
|
// src/commands/route.ts
|
|
21380
21858
|
init_src();
|
|
21381
|
-
import { readFileSync as
|
|
21859
|
+
import { readFileSync as readFileSync26 } from "node:fs";
|
|
21382
21860
|
import { hostname as hostname12 } from "node:os";
|
|
21383
21861
|
var ARM_USAGE = "usage: sleds route arm <key> [--off] [--json] [--name <engine>] [--at-once <n>] [--runner tmux|headless|command|orca|cmux] [--runner-cmd '<launcher>'] [--agent '<command>'] [--mode <permission-mode>] [--model <id>] [--effort <e>] [--branch '<template>'] [--pr-title '<template>'] [--repos-dir <dir>]";
|
|
21384
|
-
var USAGE = "usage: sleds route <key> [--long | --dot | --json] | sleds route arm <key> [--off] [--json] | sleds route answer <key>/<node> --stdin | sleds route propose <key> --file <nodes.json> | sleds route approve <key> | sleds route redraft <key> | sleds route single <key> | sleds route decisions [<key>] [--flagged] | sleds route decision <key> <id> --seen | --answer --stdin [--route accept|keep|redraft] | --keep-route | --apply [--answer --stdin] | --overrule --stdin | sleds route run <key> [--at-once <n>] [--runner tmux|headless|command|orca|cmux] [--runner-cmd '<launcher>'] [--agent '<command>'] [--interval <s>] [--lease <min>] [--idle <min>] [--repo <path>] [--repos-dir <dir>] [--mode <permission-mode>] [--model <id>] [--branch '<template>'] [--pr-title '<template>'] [--once]";
|
|
21862
|
+
var USAGE = "usage: sleds route <key> [--long | --dot | --json] | sleds route arm <key> [--off] [--json] | sleds route answer <key>/<node> --stdin | sleds route propose <key> --file <nodes.json> | sleds route approve <key> | sleds route redraft <key> | sleds route single <key> | sleds route decisions [<key>] [--flagged] | sleds route decision <key> <id> --seen | --answer --stdin [--route accept|keep|redraft] | --keep-route | --apply [--answer --stdin] | --overrule --stdin | --ready | sleds route run <key> [--at-once <n>] [--runner tmux|headless|command|orca|cmux] [--runner-cmd '<launcher>'] [--agent '<command>'] [--interval <s>] [--lease <min>] [--idle <min>] [--repo <path>] [--repos-dir <dir>] [--mode <permission-mode>] [--model <id>] [--branch '<template>'] [--pr-title '<template>'] [--once]";
|
|
21385
21863
|
var ANSWER_USAGE = "usage: sleds route answer <key>/<node> <answer…> | sleds route answer <key>/<node> --stdin [--json]";
|
|
21386
21864
|
var PROPOSE_USAGE = "usage: sleds route propose <key> (--file <nodes.json> | --stdin) [--name <engine>] [--json]";
|
|
21387
21865
|
var APPROVE_USAGE = "usage: sleds route approve <key> [--file <nodes.json>] [--json]";
|
|
21388
21866
|
var REDRAFT_USAGE = "usage: sleds route redraft <key> [--json]";
|
|
21389
21867
|
var SINGLE_USAGE = "usage: sleds route single <key> [--json]";
|
|
21390
|
-
var DECISION_USAGE = "usage: sleds route decision <key> <id> --seen | sleds route decision <key> <id> (--answer | --overrule) (<answer…> | --stdin) | sleds route decision <key> <id> [--answer (<answer…> | --stdin)] --route accept|keep|redraft | sleds route decision <key> <id> --keep-route | sleds route decision <key> <id> --apply [--answer (<answer…> | --stdin)] [--json]";
|
|
21868
|
+
var DECISION_USAGE = "usage: sleds route decision <key> <id> --seen | sleds route decision <key> <id> (--answer | --overrule) (<answer…> | --stdin) | sleds route decision <key> <id> [--answer (<answer…> | --stdin)] --route accept|keep|redraft | sleds route decision <key> <id> --keep-route | sleds route decision <key> <id> --apply [--answer (<answer…> | --stdin)] | sleds route decision <key> <id> --ready [--json]";
|
|
21391
21869
|
var ROUTE_VERDICTS = ["accept", "keep", "redraft"];
|
|
21392
21870
|
function nodesFromJson(text) {
|
|
21393
21871
|
let parsed;
|
|
@@ -21551,7 +22029,7 @@ async function answerCmd(o, argv) {
|
|
|
21551
22029
|
const words = argv.filter((a) => a !== "--json" && a !== "--stdin");
|
|
21552
22030
|
const ref = words[0] ?? "";
|
|
21553
22031
|
const slash = ref.lastIndexOf("/");
|
|
21554
|
-
const answer = (fromStdin ? (o.stdin ?? (() =>
|
|
22032
|
+
const answer = (fromStdin ? (o.stdin ?? (() => readFileSync26(0, "utf8")))() : words.slice(1).join(" ")).trim();
|
|
21555
22033
|
if (slash <= 0 || slash === ref.length - 1 || fromStdin && words.length > 1) {
|
|
21556
22034
|
error(ANSWER_USAGE);
|
|
21557
22035
|
return 2;
|
|
@@ -21716,6 +22194,8 @@ function appliedLine(key, applied) {
|
|
|
21716
22194
|
return a.changed === false ? `${key}: ${what} was already set — answered` : `${key}: set ${what} — answered`;
|
|
21717
22195
|
}
|
|
21718
22196
|
async function decisionCmd(o, argv) {
|
|
22197
|
+
if (argv.includes("--ready"))
|
|
22198
|
+
return readyCmd(o, argv);
|
|
21719
22199
|
const log = o.log ?? console.log;
|
|
21720
22200
|
const error = o.error ?? console.error;
|
|
21721
22201
|
const json = argv.includes("--json");
|
|
@@ -21746,7 +22226,7 @@ async function decisionCmd(o, argv) {
|
|
|
21746
22226
|
error(DECISION_USAGE);
|
|
21747
22227
|
return 2;
|
|
21748
22228
|
}
|
|
21749
|
-
const md = seen || routeAlone ? "" : (fromStdin ? (o.stdin ?? (() =>
|
|
22229
|
+
const md = seen || routeAlone ? "" : (fromStdin ? (o.stdin ?? (() => readFileSync26(0, "utf8")))() : rest.join(" ")).trim();
|
|
21750
22230
|
if (!seen && !routeAlone && (!md || fromStdin && rest.length > 0)) {
|
|
21751
22231
|
error(md ? DECISION_USAGE : `${answer ? "an answer" : "an overrule"} needs some text`);
|
|
21752
22232
|
return 2;
|
|
@@ -21769,6 +22249,68 @@ async function decisionCmd(o, argv) {
|
|
|
21769
22249
|
}
|
|
21770
22250
|
return said(o, key, json, r, () => log(seen ? `${key}: marked seen` : overrule ? `${key}: overruled — your answer stands in the log` : apply ? appliedLine(key, r.json?.applied) : answeredLine(key, r.json?.route ?? route, r.json?.held)));
|
|
21771
22251
|
}
|
|
22252
|
+
var LOOK_READY_ANSWER = "Looks good — marked ready for review.";
|
|
22253
|
+
function lookToReady(route, id) {
|
|
22254
|
+
const rows = Array.isArray(route?.decisions) ? route.decisions : [];
|
|
22255
|
+
const d = rows.find((r) => r.id === id);
|
|
22256
|
+
if (!d)
|
|
22257
|
+
return { error: `no decision ${id} on this item` };
|
|
22258
|
+
if (d.kind !== "look")
|
|
22259
|
+
return { error: `decision ${id} is not a look — --ready marks a look` };
|
|
22260
|
+
if (d.state !== "escalated")
|
|
22261
|
+
return { error: `decision ${id} is ${String(d.state)} — not a look you owe` };
|
|
22262
|
+
const about = d.about && typeof d.about === "object" ? d.about : {};
|
|
22263
|
+
const pr = Array.isArray(about.prs) ? about.prs.find((p) => typeof p === "string" && p) : undefined;
|
|
22264
|
+
return typeof pr === "string" ? { pr } : { error: `decision ${id} names no PR` };
|
|
22265
|
+
}
|
|
22266
|
+
async function readyCmd(o, argv) {
|
|
22267
|
+
const log = o.log ?? console.log;
|
|
22268
|
+
const error = o.error ?? console.error;
|
|
22269
|
+
const json = argv.includes("--json");
|
|
22270
|
+
const words = argv.filter((a) => a !== "--ready" && a !== "--json");
|
|
22271
|
+
const [key, id] = words;
|
|
22272
|
+
if (!key || !id || words.length !== 2 || words.some((w) => w.startsWith("--"))) {
|
|
22273
|
+
error(DECISION_USAGE);
|
|
22274
|
+
return 2;
|
|
22275
|
+
}
|
|
22276
|
+
const client = engineClient(o);
|
|
22277
|
+
if ("error" in client) {
|
|
22278
|
+
error(client.error);
|
|
22279
|
+
return 1;
|
|
22280
|
+
}
|
|
22281
|
+
const reader = routeReader(o);
|
|
22282
|
+
if ("error" in reader) {
|
|
22283
|
+
error(reader.error);
|
|
22284
|
+
return 1;
|
|
22285
|
+
}
|
|
22286
|
+
const route = await reader.read(key).catch((e) => {
|
|
22287
|
+
error(e instanceof Error ? e.message : String(e));
|
|
22288
|
+
return;
|
|
22289
|
+
});
|
|
22290
|
+
if (route === undefined)
|
|
22291
|
+
return 1;
|
|
22292
|
+
const look = lookToReady(route, id);
|
|
22293
|
+
if ("error" in look) {
|
|
22294
|
+
error(`${key}: ${look.error}`);
|
|
22295
|
+
return 1;
|
|
22296
|
+
}
|
|
22297
|
+
const gh = (o.exec ?? defaultExec)("gh", ["pr", "ready", look.pr]);
|
|
22298
|
+
if (gh.status !== 0) {
|
|
22299
|
+
error(gh.stderr.trim() || `gh pr ready ${look.pr} exited ${gh.status}`);
|
|
22300
|
+
error(`${key}: the look is not answered`);
|
|
22301
|
+
return 1;
|
|
22302
|
+
}
|
|
22303
|
+
const r = await client.postFull("/proxy/route/decision", {
|
|
22304
|
+
project: key,
|
|
22305
|
+
id,
|
|
22306
|
+
answer: LOOK_READY_ANSWER
|
|
22307
|
+
});
|
|
22308
|
+
if (!r) {
|
|
22309
|
+
error(`${key}: ${look.pr} is ready for review, but SLEDS is unreachable — the look is not answered`);
|
|
22310
|
+
return 1;
|
|
22311
|
+
}
|
|
22312
|
+
return said(o, key, json, r, () => log(`${key}: ${look.pr} marked ready for review — the look is answered`));
|
|
22313
|
+
}
|
|
21772
22314
|
var DECISIONS_USAGE = "usage: sleds route decisions [<key>] [--flagged] [--json]";
|
|
21773
22315
|
function decisionsLines(raw) {
|
|
21774
22316
|
const j = clean(raw);
|
|
@@ -21825,7 +22367,7 @@ function approvedLine(key, j) {
|
|
|
21825
22367
|
function readNodes(o, a) {
|
|
21826
22368
|
let text;
|
|
21827
22369
|
try {
|
|
21828
|
-
text = a.file ? (o.readFile ?? ((p) =>
|
|
22370
|
+
text = a.file ? (o.readFile ?? ((p) => readFileSync26(p, "utf8")))(a.file) : (o.stdin ?? (() => readFileSync26(0, "utf8")))();
|
|
21829
22371
|
} catch (e) {
|
|
21830
22372
|
return { error: e instanceof Error ? e.message : String(e) };
|
|
21831
22373
|
}
|
|
@@ -22099,11 +22641,11 @@ var run = async (o) => {
|
|
|
22099
22641
|
init_config();
|
|
22100
22642
|
init_meter();
|
|
22101
22643
|
var HOOK_STDIN_TIMEOUT_MS2 = 1000;
|
|
22102
|
-
var
|
|
22103
|
-
var
|
|
22644
|
+
var isObject14 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
22645
|
+
var notificationType2 = (text) => {
|
|
22104
22646
|
try {
|
|
22105
22647
|
const raw = JSON.parse(text);
|
|
22106
|
-
if (!
|
|
22648
|
+
if (!isObject14(raw))
|
|
22107
22649
|
return;
|
|
22108
22650
|
return typeof raw.notification_type === "string" ? raw.notification_type : undefined;
|
|
22109
22651
|
} catch {
|
|
@@ -22114,7 +22656,7 @@ var seatEvent = async (o) => {
|
|
|
22114
22656
|
const log = o.log ?? console.log;
|
|
22115
22657
|
const now = (o.now ?? Date.now)();
|
|
22116
22658
|
const input = o.stdin ?? await readStdin(HOOK_STDIN_TIMEOUT_MS2);
|
|
22117
|
-
const kind =
|
|
22659
|
+
const kind = notificationType2(input);
|
|
22118
22660
|
try {
|
|
22119
22661
|
const key = seatKeyFor(o.home, process.env);
|
|
22120
22662
|
const state = readSeatState(o.home, key);
|
|
@@ -22136,12 +22678,12 @@ var seatEvent = async (o) => {
|
|
|
22136
22678
|
|
|
22137
22679
|
// src/commands/seatSync.ts
|
|
22138
22680
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
22139
|
-
import { existsSync as existsSync25, mkdirSync as
|
|
22681
|
+
import { existsSync as existsSync25, mkdirSync as mkdirSync22, readFileSync as readFileSync27, readdirSync as readdirSync5, rmSync as rmSync16, writeFileSync as writeFileSync25 } from "node:fs";
|
|
22140
22682
|
import { platform as platform2 } from "node:os";
|
|
22141
|
-
import { dirname as
|
|
22683
|
+
import { dirname as dirname17, join as join25 } from "node:path";
|
|
22142
22684
|
|
|
22143
22685
|
// src/cookieDb.ts
|
|
22144
|
-
import { copyFileSync, rmSync as
|
|
22686
|
+
import { copyFileSync, rmSync as rmSync15 } from "node:fs";
|
|
22145
22687
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
22146
22688
|
import { join as join24 } from "node:path";
|
|
22147
22689
|
var QUERY = "SELECT name, hex(encrypted_value) AS ev FROM cookies WHERE host_key LIKE '%claude.ai%'";
|
|
@@ -22179,7 +22721,7 @@ async function readCookieRows(dbPath) {
|
|
|
22179
22721
|
return rows.map((r) => ({ name: r.name, encrypted_value: Buffer.from(r.ev, "hex") }));
|
|
22180
22722
|
} finally {
|
|
22181
22723
|
try {
|
|
22182
|
-
|
|
22724
|
+
rmSync15(copy, { force: true });
|
|
22183
22725
|
} catch {}
|
|
22184
22726
|
}
|
|
22185
22727
|
}
|
|
@@ -22264,8 +22806,8 @@ function resolveProfileDir(localStateJson, profile) {
|
|
|
22264
22806
|
if (localStateJson) {
|
|
22265
22807
|
try {
|
|
22266
22808
|
const raw = JSON.parse(localStateJson);
|
|
22267
|
-
const p =
|
|
22268
|
-
if (p &&
|
|
22809
|
+
const p = isObject15(raw) && isObject15(raw.profile) ? raw.profile : null;
|
|
22810
|
+
if (p && isObject15(p.info_cache))
|
|
22269
22811
|
cache = p.info_cache;
|
|
22270
22812
|
} catch {}
|
|
22271
22813
|
}
|
|
@@ -22274,7 +22816,7 @@ function resolveProfileDir(localStateJson, profile) {
|
|
|
22274
22816
|
const want = profile.toLowerCase();
|
|
22275
22817
|
const hits = [];
|
|
22276
22818
|
for (const [dir, info] of Object.entries(cache)) {
|
|
22277
|
-
if (!
|
|
22819
|
+
if (!isObject15(info))
|
|
22278
22820
|
continue;
|
|
22279
22821
|
const match = ["name", "user_name", "gaia_name"].some((k) => {
|
|
22280
22822
|
const v = info[k];
|
|
@@ -22313,15 +22855,15 @@ function sourceArgs(source) {
|
|
|
22313
22855
|
function seatTokenPath(home, source) {
|
|
22314
22856
|
return `${home}/.config/sleds/${launchLabel(source).slice("ai.sleds.".length)}.token`;
|
|
22315
22857
|
}
|
|
22316
|
-
var
|
|
22858
|
+
var isObject15 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
22317
22859
|
var num7 = (v) => typeof v === "number" && Number.isFinite(v) ? v : undefined;
|
|
22318
22860
|
var round22 = (n) => Math.round(n * 100) / 100;
|
|
22319
22861
|
function parseUsageResponse(raw, now = Date.now()) {
|
|
22320
|
-
if (!
|
|
22862
|
+
if (!isObject15(raw))
|
|
22321
22863
|
return null;
|
|
22322
22864
|
const out = { capturedAt: now, models: {} };
|
|
22323
22865
|
for (const [k, v] of Object.entries(raw)) {
|
|
22324
|
-
if (!
|
|
22866
|
+
if (!isObject15(v))
|
|
22325
22867
|
continue;
|
|
22326
22868
|
if (k === "extra_usage") {
|
|
22327
22869
|
const credits = num7(v.used_credits);
|
|
@@ -22486,7 +23028,7 @@ function findCookieDb(home, source) {
|
|
|
22486
23028
|
return db;
|
|
22487
23029
|
}
|
|
22488
23030
|
const localStatePath = join25(root, "Local State");
|
|
22489
|
-
const localState = existsSync25(localStatePath) ?
|
|
23031
|
+
const localState = existsSync25(localStatePath) ? readFileSync27(localStatePath, "utf8") : null;
|
|
22490
23032
|
const wanted = source.profile ?? "Default";
|
|
22491
23033
|
const { dir, ambiguous } = resolveProfileDir(localState, wanted);
|
|
22492
23034
|
if (ambiguous)
|
|
@@ -22569,16 +23111,16 @@ function install(home, argv, source, log) {
|
|
|
22569
23111
|
return 1;
|
|
22570
23112
|
}
|
|
22571
23113
|
const dir = join25(home, "Library", "LaunchAgents");
|
|
22572
|
-
|
|
23114
|
+
mkdirSync22(dir, { recursive: true });
|
|
22573
23115
|
const path = plistPath2(home, source);
|
|
22574
23116
|
const tokenPath = seatTokenPath(home, source);
|
|
22575
|
-
|
|
23117
|
+
rmSync16(tokenPath, { force: true });
|
|
22576
23118
|
if (source.token) {
|
|
22577
|
-
|
|
22578
|
-
|
|
23119
|
+
mkdirSync22(dirname17(tokenPath), { recursive: true, mode: 448 });
|
|
23120
|
+
writeFileSync25(tokenPath, `${source.token}
|
|
22579
23121
|
`, { mode: 384 });
|
|
22580
23122
|
}
|
|
22581
|
-
|
|
23123
|
+
writeFileSync25(path, launchAgentPlist(bun, script, home, source), { mode: 384 });
|
|
22582
23124
|
try {
|
|
22583
23125
|
execFileSync4("launchctl", ["unload", path], { stdio: "ignore" });
|
|
22584
23126
|
} catch {}
|
|
@@ -22591,7 +23133,7 @@ function uninstall(home, source, log) {
|
|
|
22591
23133
|
try {
|
|
22592
23134
|
execFileSync4("launchctl", ["unload", "-w", path], { stdio: "ignore" });
|
|
22593
23135
|
} catch {}
|
|
22594
|
-
|
|
23136
|
+
rmSync16(seatTokenPath(home, source), { force: true });
|
|
22595
23137
|
log(existsSync25(path) ? `seat-sync timer removed (${path} can be deleted)` : "no seat-sync timer");
|
|
22596
23138
|
return 0;
|
|
22597
23139
|
}
|
|
@@ -22666,7 +23208,7 @@ var seatSync = async (o) => {
|
|
|
22666
23208
|
};
|
|
22667
23209
|
function readSeatToken(home, source) {
|
|
22668
23210
|
try {
|
|
22669
|
-
return
|
|
23211
|
+
return readFileSync27(seatTokenPath(home, source), "utf8").trim() || undefined;
|
|
22670
23212
|
} catch {
|
|
22671
23213
|
return;
|
|
22672
23214
|
}
|
|
@@ -22749,7 +23291,7 @@ var sessionEvent = async (o) => {
|
|
|
22749
23291
|
|
|
22750
23292
|
// src/commands/specEvent.ts
|
|
22751
23293
|
init_meter();
|
|
22752
|
-
import { readFileSync as
|
|
23294
|
+
import { readFileSync as readFileSync28, statSync as statSync2 } from "node:fs";
|
|
22753
23295
|
import { basename as basename6, isAbsolute as isAbsolute4, relative } from "node:path";
|
|
22754
23296
|
var HOOK_STDIN_TIMEOUT_MS3 = 1000;
|
|
22755
23297
|
var ESTIMATE_TIMEOUT_MS = 4000;
|
|
@@ -22805,7 +23347,7 @@ function readFileOrNull(path) {
|
|
|
22805
23347
|
try {
|
|
22806
23348
|
if (statSync2(path).size > 2000000)
|
|
22807
23349
|
return null;
|
|
22808
|
-
return
|
|
23350
|
+
return readFileSync28(path, "utf8");
|
|
22809
23351
|
} catch {
|
|
22810
23352
|
return null;
|
|
22811
23353
|
}
|
|
@@ -23134,10 +23676,10 @@ var announce = (o, events) => {
|
|
|
23134
23676
|
|
|
23135
23677
|
// src/commands/stopEvent.ts
|
|
23136
23678
|
init_meter();
|
|
23137
|
-
import { existsSync as existsSync27, readFileSync as
|
|
23679
|
+
import { existsSync as existsSync27, readFileSync as readFileSync29 } from "node:fs";
|
|
23138
23680
|
|
|
23139
23681
|
// src/transcript.ts
|
|
23140
|
-
var
|
|
23682
|
+
var isObject16 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
23141
23683
|
var n = (v) => typeof v === "number" && Number.isFinite(v) ? v : 0;
|
|
23142
23684
|
function sumTranscript(text) {
|
|
23143
23685
|
const seen = new Set;
|
|
@@ -23158,7 +23700,7 @@ function sumTranscript(text) {
|
|
|
23158
23700
|
} catch {
|
|
23159
23701
|
continue;
|
|
23160
23702
|
}
|
|
23161
|
-
if (!
|
|
23703
|
+
if (!isObject16(j) || j.type !== "assistant" || !isObject16(j.message))
|
|
23162
23704
|
continue;
|
|
23163
23705
|
const m = j.message;
|
|
23164
23706
|
const id = typeof m.id === "string" ? m.id : typeof j.uuid === "string" ? j.uuid : undefined;
|
|
@@ -23167,7 +23709,7 @@ function sumTranscript(text) {
|
|
|
23167
23709
|
continue;
|
|
23168
23710
|
seen.add(id);
|
|
23169
23711
|
}
|
|
23170
|
-
const u =
|
|
23712
|
+
const u = isObject16(m.usage) ? m.usage : undefined;
|
|
23171
23713
|
if (!u)
|
|
23172
23714
|
continue;
|
|
23173
23715
|
const input = n(u.input_tokens);
|
|
@@ -23230,7 +23772,7 @@ async function postTranscript(o, payload, now) {
|
|
|
23230
23772
|
const src = meterSource(o.home);
|
|
23231
23773
|
if (!src)
|
|
23232
23774
|
return false;
|
|
23233
|
-
const read = o.readFile ?? ((p) => existsSync27(p) ?
|
|
23775
|
+
const read = o.readFile ?? ((p) => existsSync27(p) ? readFileSync29(p, "utf8") : null);
|
|
23234
23776
|
let text;
|
|
23235
23777
|
try {
|
|
23236
23778
|
text = read(path);
|
|
@@ -23308,7 +23850,7 @@ var stopEvent = async (o) => {
|
|
|
23308
23850
|
|
|
23309
23851
|
// src/commands/uninstall.ts
|
|
23310
23852
|
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
23311
|
-
import { existsSync as existsSync28, rmSync as
|
|
23853
|
+
import { existsSync as existsSync28, rmSync as rmSync17 } from "node:fs";
|
|
23312
23854
|
init_config();
|
|
23313
23855
|
init_meter();
|
|
23314
23856
|
init_settings();
|
|
@@ -23369,19 +23911,19 @@ var uninstall2 = (o) => {
|
|
|
23369
23911
|
}
|
|
23370
23912
|
for (const file of [meterCachePath(o.home), ...allSeatStatePaths(o.home)]) {
|
|
23371
23913
|
if (existsSync28(file)) {
|
|
23372
|
-
|
|
23914
|
+
rmSync17(file, { force: true });
|
|
23373
23915
|
removed.push(file);
|
|
23374
23916
|
}
|
|
23375
23917
|
}
|
|
23376
23918
|
const skill = skillDir(o.home);
|
|
23377
23919
|
if (existsSync28(skill)) {
|
|
23378
|
-
|
|
23920
|
+
rmSync17(skill, { recursive: true, force: true });
|
|
23379
23921
|
removed.push(skill);
|
|
23380
23922
|
}
|
|
23381
23923
|
const plist = musherPlistPath(o.home);
|
|
23382
23924
|
if (existsSync28(plist)) {
|
|
23383
23925
|
(o.unloadAgent ?? defaultUnload)(plist);
|
|
23384
|
-
|
|
23926
|
+
rmSync17(plist, { force: true });
|
|
23385
23927
|
removed.push(`launchd agent ${musherLabel()}`);
|
|
23386
23928
|
}
|
|
23387
23929
|
if (removed.length === 0) {
|
|
@@ -23534,17 +24076,17 @@ var webhooksCmd = async (o) => {
|
|
|
23534
24076
|
|
|
23535
24077
|
// src/config.ts
|
|
23536
24078
|
init_settings();
|
|
23537
|
-
import { chmodSync as
|
|
24079
|
+
import { chmodSync as chmodSync7, existsSync as existsSync29, mkdirSync as mkdirSync23, readFileSync as readFileSync30, renameSync as renameSync9, writeFileSync as writeFileSync26 } from "node:fs";
|
|
23538
24080
|
import { join as join26, resolve as resolve10 } from "node:path";
|
|
23539
24081
|
var configDir2 = (home, env = process.env) => {
|
|
23540
24082
|
const o = env.SLEDS_HOME?.trim();
|
|
23541
24083
|
return o ? resolve10(home, o) : join26(home, ".config", "sleds");
|
|
23542
24084
|
};
|
|
23543
24085
|
var configPath2 = (home) => join26(configDir2(home), "config.json");
|
|
23544
|
-
var
|
|
24086
|
+
var isObject17 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
23545
24087
|
var optString2 = (v) => typeof v === "string" ? v : undefined;
|
|
23546
24088
|
var parsePriorEnv2 = (v) => {
|
|
23547
|
-
if (!
|
|
24089
|
+
if (!isObject17(v))
|
|
23548
24090
|
return;
|
|
23549
24091
|
const out = {};
|
|
23550
24092
|
const url = optString2(v[BASE_URL_KEY]);
|
|
@@ -23559,7 +24101,7 @@ var parsePriorEnv2 = (v) => {
|
|
|
23559
24101
|
};
|
|
23560
24102
|
var parseSchedule2 = (v) => v === "launchd" || v === "systemd" || v === "manual" ? v : undefined;
|
|
23561
24103
|
var parseConfig2 = (raw) => {
|
|
23562
|
-
if (!
|
|
24104
|
+
if (!isObject17(raw))
|
|
23563
24105
|
return {};
|
|
23564
24106
|
const cfg = {};
|
|
23565
24107
|
const token = optString2(raw.token);
|
|
@@ -23609,11 +24151,11 @@ var parseConfig2 = (raw) => {
|
|
|
23609
24151
|
return cfg;
|
|
23610
24152
|
};
|
|
23611
24153
|
var parseOrgs2 = (raw) => {
|
|
23612
|
-
if (!
|
|
24154
|
+
if (!isObject17(raw))
|
|
23613
24155
|
return;
|
|
23614
24156
|
const out = {};
|
|
23615
24157
|
for (const [slug, v] of Object.entries(raw)) {
|
|
23616
|
-
if (!
|
|
24158
|
+
if (!isObject17(v))
|
|
23617
24159
|
continue;
|
|
23618
24160
|
const token = optString2(v.token);
|
|
23619
24161
|
if (!token)
|
|
@@ -23632,7 +24174,7 @@ var parseOrgs2 = (raw) => {
|
|
|
23632
24174
|
return Object.keys(out).length > 0 ? out : undefined;
|
|
23633
24175
|
};
|
|
23634
24176
|
var parseMusher2 = (raw) => {
|
|
23635
|
-
if (!
|
|
24177
|
+
if (!isObject17(raw))
|
|
23636
24178
|
return;
|
|
23637
24179
|
const out = {};
|
|
23638
24180
|
const pm = optString2(raw.permissionMode);
|
|
@@ -23648,7 +24190,7 @@ var parseMusher2 = (raw) => {
|
|
|
23648
24190
|
return out;
|
|
23649
24191
|
};
|
|
23650
24192
|
var parseOrgInfo2 = (raw) => {
|
|
23651
|
-
if (!
|
|
24193
|
+
if (!isObject17(raw) || !isObject17(raw.capabilities))
|
|
23652
24194
|
return;
|
|
23653
24195
|
const name = optString2(raw.name);
|
|
23654
24196
|
const slug = optString2(raw.slug);
|
|
@@ -23674,7 +24216,7 @@ var readConfig2 = (home) => {
|
|
|
23674
24216
|
const p = configPath2(home);
|
|
23675
24217
|
if (!existsSync29(p))
|
|
23676
24218
|
return {};
|
|
23677
|
-
return parseConfig2(JSON.parse(
|
|
24219
|
+
return parseConfig2(JSON.parse(readFileSync30(p, "utf8")));
|
|
23678
24220
|
};
|
|
23679
24221
|
|
|
23680
24222
|
// src/runners/exec.ts
|
|
@@ -23726,7 +24268,7 @@ var defaultExec5 = (cmd, args) => {
|
|
|
23726
24268
|
};
|
|
23727
24269
|
|
|
23728
24270
|
// src/settings.ts
|
|
23729
|
-
import { dirname as
|
|
24271
|
+
import { dirname as dirname18, join as join27, resolve as resolve11 } from "node:path";
|
|
23730
24272
|
var withSeatEnv2 = (command, home, env = process.env, org) => {
|
|
23731
24273
|
const parts = [];
|
|
23732
24274
|
const sh = env.SLEDS_HOME?.trim();
|
|
@@ -23749,15 +24291,16 @@ var pinOrg4 = (command, org) => {
|
|
|
23749
24291
|
return `${lead}SLEDS_ORG=${shellWord2(slug)} ${bare.slice(lead.length)}`;
|
|
23750
24292
|
};
|
|
23751
24293
|
var shellWord2 = (v) => /^[\w./~-]+$/.test(v) ? v : `'${v.replace(/'/g, "'\\''")}'`;
|
|
23752
|
-
var
|
|
24294
|
+
var isObject18 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
23753
24295
|
var isSledsHookFor2 = (sub) => (entry) => {
|
|
23754
|
-
if (!
|
|
24296
|
+
if (!isObject18(entry) || !Array.isArray(entry.hooks))
|
|
23755
24297
|
return false;
|
|
23756
24298
|
const re = new RegExp(`\\b${sub}\\b`);
|
|
23757
|
-
return entry.hooks.some((h) =>
|
|
24299
|
+
return entry.hooks.some((h) => isObject18(h) && h.type === "command" && typeof h.command === "string" && re.test(h.command));
|
|
23758
24300
|
};
|
|
23759
24301
|
var isSledsSessionHook2 = isSledsHookFor2("session-event");
|
|
23760
24302
|
var isSledsStopHook2 = isSledsHookFor2("stop-event");
|
|
24303
|
+
var isSledsPermissionHook2 = isSledsHookFor2("permission-event");
|
|
23761
24304
|
|
|
23762
24305
|
// src/index.ts
|
|
23763
24306
|
var USAGE3 = `usage: sleds <command> [options]
|
|
@@ -23907,6 +24450,8 @@ commands:
|
|
|
23907
24450
|
statusline Print the one-line meter Claude Code shows (installed by init; 10s cache).
|
|
23908
24451
|
hooks Register the Claude Code Notification hook for seat limits (init does this too).
|
|
23909
24452
|
seat-event Claude Code hook: record a seat wall and say how to continue. Reads hook JSON on stdin.
|
|
24453
|
+
permission-event --mark <file> Claude Code Notification hook the engine gives its sessions: on
|
|
24454
|
+
a permission dialog, write {message, at} to <file> for the engine. Local; exits 0.
|
|
23910
24455
|
session-event Claude Code SessionStart hook: states the loop and the rows this machine still
|
|
23911
24456
|
owes before the first turn. Reads hook JSON on stdin.
|
|
23912
24457
|
stop-event Claude Code Stop hook: a session that estimated a row and posted no actual is asked
|
|
@@ -24051,7 +24596,8 @@ var main = async (argv) => {
|
|
|
24051
24596
|
exec: defaultExec4,
|
|
24052
24597
|
runnerFor: runnerFor3,
|
|
24053
24598
|
sleep: (ms) => new Promise((r) => setTimeout(r, ms)),
|
|
24054
|
-
shouldStop: () => stopping
|
|
24599
|
+
shouldStop: () => stopping,
|
|
24600
|
+
sledsArgv: sledsArgv()
|
|
24055
24601
|
};
|
|
24056
24602
|
return cmd === "engine" ? engineCmd(io) : routeCmd(io);
|
|
24057
24603
|
}
|
|
@@ -24158,6 +24704,8 @@ var main = async (argv) => {
|
|
|
24158
24704
|
});
|
|
24159
24705
|
case "seat-event":
|
|
24160
24706
|
return seatEvent({ home });
|
|
24707
|
+
case "permission-event":
|
|
24708
|
+
return permissionEvent({ mark: stringFlag(flags, "mark") });
|
|
24161
24709
|
case "spec-event":
|
|
24162
24710
|
return specEvent({ home });
|
|
24163
24711
|
case "prompt-event":
|
|
@@ -24215,7 +24763,7 @@ ${renderHelpText(argv[1])}`);
|
|
|
24215
24763
|
case "version":
|
|
24216
24764
|
case "--version":
|
|
24217
24765
|
case "-v":
|
|
24218
|
-
console.log("sleds 0.1.
|
|
24766
|
+
console.log("sleds 0.1.39");
|
|
24219
24767
|
return 0;
|
|
24220
24768
|
default:
|
|
24221
24769
|
console.error(`unknown command: ${cmd}
|