svamp-cli 0.2.346 → 0.2.358
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/bin/skills/artifact/SKILL.md +19 -5
- package/bin/skills/crew/SKILL.md +42 -11
- package/dist/{acpBackend-BZ1MJhQV.mjs → acpBackend-UaBD4zL3.mjs} +3 -0
- package/dist/{agentCommands-B2Nl7Fof.mjs → agentCommands-C_KvvYFp.mjs} +5 -5
- package/dist/{claudeAuth-iAerdaMr.mjs → claudeAuth-DMDvPNhO.mjs} +55 -6
- package/dist/cli.mjs +164 -86
- package/dist/{commands-D69mnkYu.mjs → commands-B19lVZjm.mjs} +10 -3
- package/dist/{commands-BB1Kcyt-.mjs → commands-Bmoy6Rlw.mjs} +34 -4
- package/dist/{commands-CiRCwjkJ.mjs → commands-CFBKkfX8.mjs} +9 -9
- package/dist/{commands-D1pZq3d4.mjs → commands-CcdoQIkb.mjs} +126 -25
- package/dist/{commands-BOpoVBOM.mjs → commands-DH_YQrAP.mjs} +5 -21
- package/dist/{commands-H4PsTGn8.mjs → commands-DRxANaS5.mjs} +65 -19
- package/dist/{commands-C2aODeVc.mjs → commands-nkvTnUJj.mjs} +29 -13
- package/dist/{detectIsolation-CzoDCEnh.mjs → detectIsolation-CrV8IFDv.mjs} +36 -16
- package/dist/{fleet-DM_Q7w69.mjs → fleet-Ca-UjJNL.mjs} +40 -15
- package/dist/friendlyName-B-OEwt0t.mjs +341 -0
- package/dist/{headlessCli-C8HzQvis.mjs → headlessCli-BpTXz6FD.mjs} +24 -16
- package/dist/{hookSettings-DYMTUgVA.mjs → hookSettings-CvvUhwCK.mjs} +294 -55
- package/dist/{friendlyName-1UZcyDhu.mjs → inboxGuard-CDqmIypF.mjs} +32 -347
- package/dist/index.mjs +10 -9
- package/dist/{loopVerify-B47sSjxe.mjs → loopVerify-CxAKJB5a.mjs} +1 -1
- package/dist/{notifyCommands-D-IKIxiq.mjs → notifyCommands-CCUE18Q-.mjs} +1 -1
- package/dist/package-DTTWvJbp.mjs +64 -0
- package/dist/{rpc-Cf0grcru.mjs → rpc-CAlAHQAy.mjs} +8 -3
- package/dist/{rpc-BB6RF4-F.mjs → rpc-CacreLQ8.mjs} +13 -9
- package/dist/{run-ChdsgaSD.mjs → run-Bc81iurl.mjs} +27 -8
- package/dist/{run-DkjwF-zA.mjs → run-DKOND4dO.mjs} +222 -73
- package/dist/{scheduler-BY30ZrB9.mjs → scheduler-IyLWBF8T.mjs} +28 -10
- package/dist/{serveAuth-DbVLRCRR.mjs → serveAuth-4M0vwMyj.mjs} +53 -11
- package/dist/{serveCommands-CUHUiYnZ.mjs → serveCommands-B-Ym_QXc.mjs} +8 -8
- package/dist/{store-Bn0ByYev.mjs → store-D8dok6_d.mjs} +62 -14
- package/package.json +3 -3
- package/dist/package-DtuINqf5.mjs +0 -64
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { r as resolveProjectRoot } from './store-
|
|
1
|
+
import { r as resolveProjectRoot } from './store-D8dok6_d.mjs';
|
|
2
2
|
import { w as wantsHelp } from './wantsHelp-6bMOeNUz.mjs';
|
|
3
3
|
import { s as setWorkflowEnabled, i as isWorkflowEnabled, r as removeWorkflow, g as getWorkflow, l as listWorkflows, c as workflowSteps, a as saveWorkflow, b as rawWorkflow } from './store-fi0f-ff1.mjs';
|
|
4
4
|
import { v as validateCronExpr, d as describeNextFire } from './cron-hHGdb5kU.mjs';
|
|
@@ -21,7 +21,7 @@ function positional(args) {
|
|
|
21
21
|
for (let i = 0; i < args.length; i++) {
|
|
22
22
|
const a = args[i];
|
|
23
23
|
if (a.startsWith("--")) {
|
|
24
|
-
if (a !== "--json") i++;
|
|
24
|
+
if (a !== "--json" && a !== "--force" && a !== "--replace") i++;
|
|
25
25
|
continue;
|
|
26
26
|
}
|
|
27
27
|
out.push(a);
|
|
@@ -75,6 +75,13 @@ async function workflowCommand(args) {
|
|
|
75
75
|
if (onKinds.includes("idle")) on.idle = true;
|
|
76
76
|
const owner = flag(rest, "--session") || process.env.SVAMP_SESSION_ID || null;
|
|
77
77
|
const wf = { name, on: Object.keys(on).length ? on : void 0, jobs: { run: { steps: runs.map((r) => ({ run: r })) } }, session: owner };
|
|
78
|
+
if (!rest.includes("--force") && !rest.includes("--replace") && getWorkflow(root, name)) {
|
|
79
|
+
console.error(`Workflow "${name}" already exists \u2014 refusing to replace it (that would discard its steps, schedule and owning session).`);
|
|
80
|
+
console.error(` svamp workflow show ${name} # see what is there now`);
|
|
81
|
+
console.error(` svamp workflow add ${name} --force \u2026 # deliberately replace it`);
|
|
82
|
+
console.error(` svamp workflow remove ${name} # or remove it first`);
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
78
85
|
saveWorkflow(root, wf);
|
|
79
86
|
const nSteps = workflowSteps(wf).length;
|
|
80
87
|
if (json) console.log(JSON.stringify(wf));
|
|
@@ -147,7 +154,7 @@ async function workflowCommand(args) {
|
|
|
147
154
|
console.error(`Workflow not found: ${name}`);
|
|
148
155
|
process.exit(1);
|
|
149
156
|
}
|
|
150
|
-
const { runWorkflow } = await import('./run-
|
|
157
|
+
const { runWorkflow } = await import('./run-DKOND4dO.mjs').then(function (n) { return n.f; });
|
|
151
158
|
const run = await runWorkflow(root, wf, { trigger: "manual", actor: process.env.SVAMP_SESSION_ID || null });
|
|
152
159
|
console.log(`\u25B6 ran workflow "${wf.name}" (${run.steps.length} step${run.steps.length === 1 ? "" : "s"}) \u2192 ${run.status}`);
|
|
153
160
|
for (const st of run.steps) {
|
|
@@ -1,21 +1,22 @@
|
|
|
1
|
-
import { connectAndResolveSession } from './commands-
|
|
1
|
+
import { a as connectAndResolveSession } from './commands-CcdoQIkb.mjs';
|
|
2
2
|
import { w as wantsHelp } from './wantsHelp-6bMOeNUz.mjs';
|
|
3
3
|
import 'node:fs';
|
|
4
4
|
import 'node:child_process';
|
|
5
5
|
import 'node:path';
|
|
6
6
|
import 'node:os';
|
|
7
7
|
import './hyphaClient-ybivOjZo.mjs';
|
|
8
|
-
import './friendlyName-
|
|
8
|
+
import './friendlyName-B-OEwt0t.mjs';
|
|
9
9
|
import 'node:crypto';
|
|
10
10
|
import './types-57J3Re0n.mjs';
|
|
11
11
|
import './securityContext-Cm5UTCuD.mjs';
|
|
12
|
-
import './loopVerify-
|
|
12
|
+
import './loopVerify-CxAKJB5a.mjs';
|
|
13
13
|
import './instance-CeHz5C8v.mjs';
|
|
14
14
|
import 'fs';
|
|
15
15
|
import 'path';
|
|
16
16
|
import 'os';
|
|
17
|
-
import './store-
|
|
17
|
+
import './store-D8dok6_d.mjs';
|
|
18
18
|
import './fileLock-BMPwCrB6.mjs';
|
|
19
|
+
import './inboxGuard-CDqmIypF.mjs';
|
|
19
20
|
import './flushExit-C-i6SGjj.mjs';
|
|
20
21
|
|
|
21
22
|
function argVal(args, name) {
|
|
@@ -111,6 +112,27 @@ async function outpostInstall(args) {
|
|
|
111
112
|
if (info.downloadBase) console.log("Direct download: " + info.downloadBase);
|
|
112
113
|
}
|
|
113
114
|
}
|
|
115
|
+
async function outpostRotate(args) {
|
|
116
|
+
const dl = argVal(args, "--download-base");
|
|
117
|
+
if (!args.includes("--yes") && !args.includes("-y")) {
|
|
118
|
+
console.log("This REVOKES this session's outpost token and mints a new one.");
|
|
119
|
+
console.log("Every currently-connected outpost will stop working until it re-runs the new");
|
|
120
|
+
console.log("install command. Re-run with --yes to proceed.");
|
|
121
|
+
process.exit(1);
|
|
122
|
+
}
|
|
123
|
+
const info = await withSession((m, id) => m.sessionRPC(id, "outpostRotateToken", dl ? { params: { downloadBase: dl } } : {}));
|
|
124
|
+
if (!info || info.error) {
|
|
125
|
+
console.error(`Could not rotate the outpost token: ${info?.error || "unknown error"}`);
|
|
126
|
+
process.exit(1);
|
|
127
|
+
}
|
|
128
|
+
console.log("\u2713 outpost token rotated \u2014 the previous token no longer works.\n");
|
|
129
|
+
console.log("Any machine that was connected must re-run the install command below:\n");
|
|
130
|
+
const gen = info.install || {};
|
|
131
|
+
if (gen.unix) console.log(" macOS / Linux:\n " + gen.unix + "\n");
|
|
132
|
+
if (gen.windows) console.log(" Windows (PowerShell):\n " + gen.windows + "\n");
|
|
133
|
+
if (info.pairingCode) console.log(` \u2026or the short pairing code: ${info.pairingCode}
|
|
134
|
+
`);
|
|
135
|
+
}
|
|
114
136
|
function usage() {
|
|
115
137
|
console.log(`svamp outpost \u2014 drive a connected remote machine (FDE outpost)
|
|
116
138
|
|
|
@@ -121,6 +143,10 @@ function usage() {
|
|
|
121
143
|
stdout/stderr/exit code synchronously (like a local command).
|
|
122
144
|
With one outpost connected, --machine is optional.
|
|
123
145
|
svamp outpost install [--os <os>] Reprint the install one-liner(s) for this session's outpost
|
|
146
|
+
svamp outpost rotate [--yes] REVOKE this session's outpost token and mint a new one.
|
|
147
|
+
Use after the install one-liner has been shared somewhere it
|
|
148
|
+
should not have been. Every currently-connected outpost stops
|
|
149
|
+
working and must re-run the new install command.
|
|
124
150
|
|
|
125
151
|
With several machines connected, target each by id, e.g.:
|
|
126
152
|
svamp outpost exec --machine build-mac "uname -a"
|
|
@@ -149,6 +175,10 @@ async function outpostCommand(args) {
|
|
|
149
175
|
await outpostInstall(args.slice(1));
|
|
150
176
|
return;
|
|
151
177
|
}
|
|
178
|
+
if (sub === "rotate" || sub === "revoke") {
|
|
179
|
+
await outpostRotate(args.slice(1));
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
152
182
|
console.error(`unknown outpost command: ${sub}`);
|
|
153
183
|
usage();
|
|
154
184
|
process.exit(1);
|
|
@@ -61,7 +61,7 @@ async function serviceExpose(args) {
|
|
|
61
61
|
process.exit(1);
|
|
62
62
|
}
|
|
63
63
|
if (foreground) {
|
|
64
|
-
const { runFrpcTunnel } = await import('./hookSettings-
|
|
64
|
+
const { runFrpcTunnel } = await import('./hookSettings-CvvUhwCK.mjs').then(function (n) { return n.w; });
|
|
65
65
|
await runFrpcTunnel(name, ports, void 0, {
|
|
66
66
|
group,
|
|
67
67
|
groupKey,
|
|
@@ -71,7 +71,7 @@ async function serviceExpose(args) {
|
|
|
71
71
|
});
|
|
72
72
|
return;
|
|
73
73
|
}
|
|
74
|
-
const { connectAndGetMachine } = await import('./commands-
|
|
74
|
+
const { connectAndGetMachine } = await import('./commands-CcdoQIkb.mjs').then(function (n) { return n.d; });
|
|
75
75
|
const { server, machine } = await connectAndGetMachine();
|
|
76
76
|
try {
|
|
77
77
|
const status = await machine.tunnelStart({
|
|
@@ -93,7 +93,7 @@ async function serviceExpose(args) {
|
|
|
93
93
|
console.log(` port ${port}: ${url}`);
|
|
94
94
|
}
|
|
95
95
|
if (process.env.SVAMP_SESSION_ID) {
|
|
96
|
-
const { autoAddSessionLink } = await import('./agentCommands-
|
|
96
|
+
const { autoAddSessionLink } = await import('./agentCommands-C_KvvYFp.mjs');
|
|
97
97
|
let added = 0;
|
|
98
98
|
for (const [port, url] of urlEntries) {
|
|
99
99
|
const label = urlEntries.length > 1 ? `${name}:${port}` : name;
|
|
@@ -129,8 +129,8 @@ async function serviceServe(args) {
|
|
|
129
129
|
const resolvedDir = path.resolve(directory);
|
|
130
130
|
console.log(`Serving ${resolvedDir}`);
|
|
131
131
|
const http = await import('http');
|
|
132
|
-
const { serveStaticMount } = await import('./hookSettings-
|
|
133
|
-
const { getFreePort } = await import('./hookSettings-
|
|
132
|
+
const { serveStaticMount } = await import('./hookSettings-CvvUhwCK.mjs').then(function (n) { return n.x; });
|
|
133
|
+
const { getFreePort } = await import('./hookSettings-CvvUhwCK.mjs').then(function (n) { return n.w; });
|
|
134
134
|
const server = http.createServer((req, res) => {
|
|
135
135
|
const u = new URL(req.url || "/", "http://127.0.0.1");
|
|
136
136
|
let rel = u.pathname;
|
|
@@ -153,7 +153,7 @@ async function serviceServe(args) {
|
|
|
153
153
|
resolve(18080);
|
|
154
154
|
});
|
|
155
155
|
});
|
|
156
|
-
const { runFrpcTunnel } = await import('./hookSettings-
|
|
156
|
+
const { runFrpcTunnel } = await import('./hookSettings-CvvUhwCK.mjs').then(function (n) { return n.w; });
|
|
157
157
|
void server;
|
|
158
158
|
await runFrpcTunnel(name, [servePort]);
|
|
159
159
|
} catch (err) {
|
|
@@ -163,7 +163,7 @@ async function serviceServe(args) {
|
|
|
163
163
|
}
|
|
164
164
|
async function serviceList(_args) {
|
|
165
165
|
try {
|
|
166
|
-
const { connectAndGetMachine } = await import('./commands-
|
|
166
|
+
const { connectAndGetMachine } = await import('./commands-CcdoQIkb.mjs').then(function (n) { return n.d; });
|
|
167
167
|
const { server, machine } = await connectAndGetMachine();
|
|
168
168
|
try {
|
|
169
169
|
const tunnels = await machine.tunnelList({});
|
|
@@ -203,11 +203,11 @@ async function serviceDelete(args) {
|
|
|
203
203
|
process.exit(1);
|
|
204
204
|
}
|
|
205
205
|
try {
|
|
206
|
-
const { connectAndGetMachine } = await import('./commands-
|
|
206
|
+
const { connectAndGetMachine } = await import('./commands-CcdoQIkb.mjs').then(function (n) { return n.d; });
|
|
207
207
|
const { server, machine } = await connectAndGetMachine();
|
|
208
208
|
try {
|
|
209
209
|
await machine.tunnelStop({ name });
|
|
210
|
-
const { removeSessionLinkByService } = await import('./agentCommands-
|
|
210
|
+
const { removeSessionLinkByService } = await import('./agentCommands-C_KvvYFp.mjs');
|
|
211
211
|
removeSessionLinkByService("tunnel", name);
|
|
212
212
|
console.log(`Stopped tunnel '${name}'.`);
|
|
213
213
|
} catch (err) {
|
|
@@ -3,18 +3,12 @@ import { execSync, execFileSync } from 'node:child_process';
|
|
|
3
3
|
import { basename, resolve, join, isAbsolute } from 'node:path';
|
|
4
4
|
import os from 'node:os';
|
|
5
5
|
import { c as connectToHypha } from './hyphaClient-ybivOjZo.mjs';
|
|
6
|
-
import { f as formatHandle,
|
|
6
|
+
import { f as formatHandle, s as shortId, p as parseHandle, h as handleMatchesMetadata } from './friendlyName-B-OEwt0t.mjs';
|
|
7
7
|
import { n as normalizeAllowedUser } from './types-57J3Re0n.mjs';
|
|
8
8
|
import { loadSecurityContextConfig, resolveSecurityContext, buildSecurityContextFromFlags, mergeSecurityContexts } from './securityContext-Cm5UTCuD.mjs';
|
|
9
|
-
import { b as buildSessionShareUrl, U as UNBOUNDED_LOOP_ITERATIONS, a as buildMachineShareUrl } from './loopVerify-
|
|
9
|
+
import { b as buildSessionShareUrl, U as UNBOUNDED_LOOP_ITERATIONS, a as buildMachineShareUrl } from './loopVerify-CxAKJB5a.mjs';
|
|
10
|
+
import { computeOutboundHop, resolveOutboundUrgency, registerAwaitingReply } from './inboxGuard-CDqmIypF.mjs';
|
|
10
11
|
import { f as flushStdout } from './flushExit-C-i6SGjj.mjs';
|
|
11
|
-
import 'node:crypto';
|
|
12
|
-
import './instance-CeHz5C8v.mjs';
|
|
13
|
-
import 'fs';
|
|
14
|
-
import 'path';
|
|
15
|
-
import 'os';
|
|
16
|
-
import './store-Bn0ByYev.mjs';
|
|
17
|
-
import './fileLock-BMPwCrB6.mjs';
|
|
18
12
|
|
|
19
13
|
function formatTime(ts) {
|
|
20
14
|
if (!ts) return "-";
|
|
@@ -83,6 +77,23 @@ function formatJson(data) {
|
|
|
83
77
|
return JSON.stringify(data, null, 2);
|
|
84
78
|
}
|
|
85
79
|
|
|
80
|
+
function positionalArgs(args, valueFlags) {
|
|
81
|
+
const out = [];
|
|
82
|
+
for (let i = 0; i < args.length; i++) {
|
|
83
|
+
const a = args[i];
|
|
84
|
+
if (a === "--") break;
|
|
85
|
+
if (a.startsWith("-") && a !== "-") {
|
|
86
|
+
if (!a.includes("=") && valueFlags.has(a)) i++;
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
out.push(a);
|
|
90
|
+
}
|
|
91
|
+
return out;
|
|
92
|
+
}
|
|
93
|
+
function firstPositional(args, valueFlags) {
|
|
94
|
+
return positionalArgs(args, valueFlags)[0];
|
|
95
|
+
}
|
|
96
|
+
|
|
86
97
|
function machineLabelOf(machine, index) {
|
|
87
98
|
return String(
|
|
88
99
|
machine?.metadata?.displayName || machine?.metadata?.host || machine?.machineId || machine?.id || `machine #${index}`
|
|
@@ -1835,6 +1846,7 @@ async function sendCore(machine, fullId, message, opts) {
|
|
|
1835
1846
|
} catch {
|
|
1836
1847
|
}
|
|
1837
1848
|
await new Promise((r) => setTimeout(r, 2e3));
|
|
1849
|
+
const modelPreSeq = wantResponse ? await snapshotLatestSeq(machine, fullId) : 0;
|
|
1838
1850
|
const meta = { model: opts.model, sentFrom: "svamp-cli" };
|
|
1839
1851
|
const contentStr = JSON.stringify({ role: "user", content: { type: "text", text: message }, meta });
|
|
1840
1852
|
const sendRes = await machine.sessionRPC(fullId, "sendMessage", {
|
|
@@ -1860,7 +1872,7 @@ async function sendCore(machine, fullId, message, opts) {
|
|
|
1860
1872
|
}
|
|
1861
1873
|
let mResponse;
|
|
1862
1874
|
if (wantResponse) {
|
|
1863
|
-
mResponse = await collectAssistantResponse(machine, fullId,
|
|
1875
|
+
mResponse = await collectAssistantResponse(machine, fullId, modelPreSeq);
|
|
1864
1876
|
}
|
|
1865
1877
|
return {
|
|
1866
1878
|
sessionId: fullId,
|
|
@@ -1884,8 +1896,14 @@ async function sendCore(machine, fullId, message, opts) {
|
|
|
1884
1896
|
const preSeq = wantResponse ? await snapshotLatestSeq(machine, fullId) : 0;
|
|
1885
1897
|
const callerSessionId = process.env.SVAMP_SESSION_ID;
|
|
1886
1898
|
const hop = computeOutboundHop(callerSessionId);
|
|
1887
|
-
|
|
1888
|
-
|
|
1899
|
+
const { urgency, downgraded } = resolveOutboundUrgency({
|
|
1900
|
+
explicit: opts?.urgency,
|
|
1901
|
+
whenIdle: opts?.whenIdle,
|
|
1902
|
+
fromInboxTurn: hop.fromInboxTurn
|
|
1903
|
+
});
|
|
1904
|
+
if (downgraded) {
|
|
1905
|
+
console.error("note: sent non-urgent \u2014 this turn was inbox-triggered (anti-cascade safeguard C). Pass --urgency urgent to override.");
|
|
1906
|
+
}
|
|
1889
1907
|
const inboxMessage = {
|
|
1890
1908
|
messageId: shortId(),
|
|
1891
1909
|
body: message,
|
|
@@ -2680,16 +2698,19 @@ async function sessionLoopStatus(sessionIdPartial, machineId) {
|
|
|
2680
2698
|
return;
|
|
2681
2699
|
}
|
|
2682
2700
|
const config = await readJsonFile(`${base}/loop.config.json`);
|
|
2683
|
-
const verdict = await readJsonFile(`${base}/evaluator-verdict.json`);
|
|
2684
2701
|
console.log(`Loop on session ${fullId.slice(0, 8)}:`);
|
|
2685
|
-
const
|
|
2702
|
+
const maxRaw = state.max_iterations ?? config?.max_iterations;
|
|
2703
|
+
const maxN = typeof maxRaw === "number" && maxRaw > 0 && maxRaw < 1e6 ? maxRaw : null;
|
|
2704
|
+
const turns = state.ledger?.turns ?? state.iteration ?? 0;
|
|
2686
2705
|
console.log(` Phase: ${state.phase || (state.active === false ? "inactive" : "running")}`);
|
|
2687
|
-
console.log(` Iteration: ${
|
|
2688
|
-
|
|
2706
|
+
console.log(` Iteration: ${turns}${maxN ? ` / ${maxN}` : " (no iteration cap)"}`);
|
|
2707
|
+
const oracleCmd = state.oracle?.command ?? state.oracle ?? config?.oracle?.command;
|
|
2708
|
+
if (typeof oracleCmd === "string" && oracleCmd) console.log(` Oracle: ${oracleCmd}`);
|
|
2689
2709
|
if (state.last_oracle) console.log(` Last oracle: ${String(state.last_oracle).split("\n")[0]}`);
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
}
|
|
2710
|
+
const verdict = state.last_verdict ?? state.verdict;
|
|
2711
|
+
console.log(` Evaluator: ${verdict ? `${verdict.verdict ?? verdict}${verdict.reason ? ` \u2014 ${verdict.reason}` : ""}` : "on (no verdict yet)"}`);
|
|
2712
|
+
if (Number.isFinite(state.auto_resumes) && state.auto_resumes > 0) console.log(` Auto-resumes: ${state.auto_resumes}`);
|
|
2713
|
+
if (Number.isFinite(state.holds) && state.holds > 0) console.log(` Holds: ${state.holds}`);
|
|
2693
2714
|
if (state.gave_up_reason) console.log(` Gave up: ${state.gave_up_reason}`);
|
|
2694
2715
|
if (Array.isArray(state.extensions) && state.extensions.length) {
|
|
2695
2716
|
const totalTurns = state.extensions.reduce((s, e) => s + (Number.isFinite(e?.grantedTurns) && e.grantedTurns > 0 ? Math.floor(e.grantedTurns) : 0), 0);
|
|
@@ -2709,8 +2730,14 @@ async function sessionInboxSend(sessionIdPartial, body, machineId, opts) {
|
|
|
2709
2730
|
try {
|
|
2710
2731
|
const callerSessionId = process.env.SVAMP_SESSION_ID;
|
|
2711
2732
|
const hop = computeOutboundHop(callerSessionId);
|
|
2712
|
-
|
|
2713
|
-
|
|
2733
|
+
const { urgency, downgraded } = resolveOutboundUrgency({
|
|
2734
|
+
explicit: opts?.urgency,
|
|
2735
|
+
whenIdle: opts?.whenIdle,
|
|
2736
|
+
fromInboxTurn: hop.fromInboxTurn
|
|
2737
|
+
});
|
|
2738
|
+
if (downgraded) {
|
|
2739
|
+
console.error("note: sent non-urgent \u2014 this turn was inbox-triggered (anti-cascade safeguard C). Pass --urgency urgent to override.");
|
|
2740
|
+
}
|
|
2714
2741
|
const message = {
|
|
2715
2742
|
messageId: shortId(),
|
|
2716
2743
|
body,
|
|
@@ -2797,7 +2824,21 @@ ${msg.body}`);
|
|
|
2797
2824
|
await server.disconnect();
|
|
2798
2825
|
}
|
|
2799
2826
|
}
|
|
2800
|
-
|
|
2827
|
+
const REPLY_VALUE_FLAGS = /* @__PURE__ */ new Set(["--urgency", "--subject"]);
|
|
2828
|
+
function replyPositionals(args) {
|
|
2829
|
+
return positionalArgs(args, REPLY_VALUE_FLAGS);
|
|
2830
|
+
}
|
|
2831
|
+
const SEND_VALUE_FLAGS = /* @__PURE__ */ new Set([
|
|
2832
|
+
"--timeout",
|
|
2833
|
+
"--subject",
|
|
2834
|
+
"--urgency",
|
|
2835
|
+
"--model",
|
|
2836
|
+
"--issue-title"
|
|
2837
|
+
]);
|
|
2838
|
+
function sendPositionals(args) {
|
|
2839
|
+
return positionalArgs(args, SEND_VALUE_FLAGS);
|
|
2840
|
+
}
|
|
2841
|
+
async function sessionInboxReply(sessionIdPartial, messageId, body, machineId, opts) {
|
|
2801
2842
|
const { server, machine, fullId } = await connectAndResolveSession(sessionIdPartial, machineId);
|
|
2802
2843
|
try {
|
|
2803
2844
|
const result = await machine.sessionRPC(fullId, "getInbox", {});
|
|
@@ -2831,10 +2872,12 @@ async function sessionInboxReply(sessionIdPartial, messageId, body, machineId) {
|
|
|
2831
2872
|
fromSession: fullId,
|
|
2832
2873
|
to: original.fromSession,
|
|
2833
2874
|
subject: original.subject ? `Re: ${original.subject}` : void 0,
|
|
2834
|
-
// A reply wakes the party who is WAITING for it — deliver urgent by
|
|
2875
|
+
// A reply wakes the party who is WAITING for it — deliver urgent by DEFAULT
|
|
2835
2876
|
// (owner directive: replies default urgent). The hop cap + circuit breaker still
|
|
2836
2877
|
// bound any runaway A→B→A cascade; hopCount below carries the depth for that cap.
|
|
2837
|
-
|
|
2878
|
+
// The default is deliberate and safeguard C does NOT apply here (#0290); an
|
|
2879
|
+
// explicit --urgency / --when-idle is honoured so a caller can opt out by hand.
|
|
2880
|
+
urgency: opts?.urgency ?? (opts?.whenIdle ? "normal" : "urgent"),
|
|
2838
2881
|
hopCount: hop.hopCount,
|
|
2839
2882
|
replyTo: original.messageId,
|
|
2840
2883
|
threadId: original.threadId || original.messageId
|
|
@@ -2868,4 +2911,62 @@ async function sessionInboxClear(sessionIdPartial, machineId, opts) {
|
|
|
2868
2911
|
}
|
|
2869
2912
|
}
|
|
2870
2913
|
|
|
2871
|
-
|
|
2914
|
+
var commands = /*#__PURE__*/Object.freeze({
|
|
2915
|
+
__proto__: null,
|
|
2916
|
+
REPLY_VALUE_FLAGS: REPLY_VALUE_FLAGS,
|
|
2917
|
+
SEND_VALUE_FLAGS: SEND_VALUE_FLAGS,
|
|
2918
|
+
collectAssistantResponse: collectAssistantResponse,
|
|
2919
|
+
connectAndGetMachine: connectAndGetMachine,
|
|
2920
|
+
connectAndResolveSession: connectAndResolveSession,
|
|
2921
|
+
createWorktree: createWorktree,
|
|
2922
|
+
generateWorktreeName: generateWorktreeName,
|
|
2923
|
+
isSelfBtw: isSelfBtw,
|
|
2924
|
+
machineExec: machineExec,
|
|
2925
|
+
machineInfo: machineInfo,
|
|
2926
|
+
machineLs: machineLs,
|
|
2927
|
+
machineShare: machineShare,
|
|
2928
|
+
parseShareArg: parseShareArg,
|
|
2929
|
+
queryCore: queryCore,
|
|
2930
|
+
renderMessage: renderMessage,
|
|
2931
|
+
replyPositionals: replyPositionals,
|
|
2932
|
+
resolveSessionId: resolveSessionId,
|
|
2933
|
+
sendCore: sendCore,
|
|
2934
|
+
sendPositionals: sendPositionals,
|
|
2935
|
+
sessionApprove: sessionApprove,
|
|
2936
|
+
sessionArchive: sessionArchive,
|
|
2937
|
+
sessionAttach: sessionAttach,
|
|
2938
|
+
sessionDelete: sessionDelete,
|
|
2939
|
+
sessionDeny: sessionDeny,
|
|
2940
|
+
sessionEditMessage: sessionEditMessage,
|
|
2941
|
+
sessionInboxClear: sessionInboxClear,
|
|
2942
|
+
sessionInboxList: sessionInboxList,
|
|
2943
|
+
sessionInboxRead: sessionInboxRead,
|
|
2944
|
+
sessionInboxReply: sessionInboxReply,
|
|
2945
|
+
sessionInboxSend: sessionInboxSend,
|
|
2946
|
+
sessionInfo: sessionInfo,
|
|
2947
|
+
sessionList: sessionList,
|
|
2948
|
+
sessionLoopCancel: sessionLoopCancel,
|
|
2949
|
+
sessionLoopExtend: sessionLoopExtend,
|
|
2950
|
+
sessionLoopStart: sessionLoopStart,
|
|
2951
|
+
sessionLoopStatus: sessionLoopStatus,
|
|
2952
|
+
sessionMachines: sessionMachines,
|
|
2953
|
+
sessionMessages: sessionMessages,
|
|
2954
|
+
sessionQuery: sessionQuery,
|
|
2955
|
+
sessionRefineLastReply: sessionRefineLastReply,
|
|
2956
|
+
sessionResume: sessionResume,
|
|
2957
|
+
sessionSend: sessionSend,
|
|
2958
|
+
sessionShare: sessionShare,
|
|
2959
|
+
sessionSpawn: sessionSpawn,
|
|
2960
|
+
sessionUndoEdit: sessionUndoEdit,
|
|
2961
|
+
sessionWait: sessionWait,
|
|
2962
|
+
sessionWhoami: sessionWhoami,
|
|
2963
|
+
snapshotLatestSeq: snapshotLatestSeq,
|
|
2964
|
+
validateSendOptions: validateSendOptions,
|
|
2965
|
+
wiseAnnounceCli: wiseAnnounceCli,
|
|
2966
|
+
wiseAskCli: wiseAskCli,
|
|
2967
|
+
wiseJoinMeetingCli: wiseJoinMeetingCli,
|
|
2968
|
+
wiseLeaveMeetingCli: wiseLeaveMeetingCli,
|
|
2969
|
+
wiseMeetingsCli: wiseMeetingsCli
|
|
2970
|
+
});
|
|
2971
|
+
|
|
2972
|
+
export { connectAndResolveSession as a, createWorktree as b, connectAndGetMachine as c, commands as d, firstPositional as f, resolveSessionId as r };
|
|
@@ -1,40 +1,24 @@
|
|
|
1
1
|
import { writeFileSync, readFileSync } from 'fs';
|
|
2
2
|
import { resolve } from 'path';
|
|
3
|
-
import { connectAndGetMachine } from './commands-
|
|
3
|
+
import { f as firstPositional, c as connectAndGetMachine } from './commands-CcdoQIkb.mjs';
|
|
4
4
|
import { w as wantsHelp } from './wantsHelp-6bMOeNUz.mjs';
|
|
5
5
|
import 'node:fs';
|
|
6
6
|
import 'node:child_process';
|
|
7
7
|
import 'node:path';
|
|
8
8
|
import 'node:os';
|
|
9
9
|
import './hyphaClient-ybivOjZo.mjs';
|
|
10
|
-
import './friendlyName-
|
|
10
|
+
import './friendlyName-B-OEwt0t.mjs';
|
|
11
11
|
import 'node:crypto';
|
|
12
12
|
import './types-57J3Re0n.mjs';
|
|
13
13
|
import './securityContext-Cm5UTCuD.mjs';
|
|
14
|
-
import './loopVerify-
|
|
14
|
+
import './loopVerify-CxAKJB5a.mjs';
|
|
15
15
|
import './instance-CeHz5C8v.mjs';
|
|
16
16
|
import 'os';
|
|
17
|
-
import './store-
|
|
17
|
+
import './store-D8dok6_d.mjs';
|
|
18
18
|
import './fileLock-BMPwCrB6.mjs';
|
|
19
|
+
import './inboxGuard-CDqmIypF.mjs';
|
|
19
20
|
import './flushExit-C-i6SGjj.mjs';
|
|
20
21
|
|
|
21
|
-
function positionalArgs(args, valueFlags) {
|
|
22
|
-
const out = [];
|
|
23
|
-
for (let i = 0; i < args.length; i++) {
|
|
24
|
-
const a = args[i];
|
|
25
|
-
if (a === "--") break;
|
|
26
|
-
if (a.startsWith("-") && a !== "-") {
|
|
27
|
-
if (!a.includes("=") && valueFlags.has(a)) i++;
|
|
28
|
-
continue;
|
|
29
|
-
}
|
|
30
|
-
out.push(a);
|
|
31
|
-
}
|
|
32
|
-
return out;
|
|
33
|
-
}
|
|
34
|
-
function firstPositional(args, valueFlags) {
|
|
35
|
-
return positionalArgs(args, valueFlags)[0];
|
|
36
|
-
}
|
|
37
|
-
|
|
38
22
|
const PROCESS_VALUE_FLAGS = /* @__PURE__ */ new Set([
|
|
39
23
|
"-o",
|
|
40
24
|
"--output",
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
-
import { join } from 'node:path';
|
|
2
|
+
import { join, delimiter } from 'node:path';
|
|
3
3
|
import { a as flushAndExit } from './flushExit-C-i6SGjj.mjs';
|
|
4
|
-
import { r as resolveProjectRoot, s as searchIssues, l as listIssues,
|
|
4
|
+
import { r as resolveProjectRoot, s as searchIssues, l as listIssues, j as isPendingIssue, f as resumeIssue, h as pauseIssue, b as addComment, a as applyTriageStatus, u as updateIssue, p as parseScopeArg, I as ISSUE_SCOPES, d as parseStatusArg, e as ISSUE_STATUSES, g as getIssue, m as checkVerifyCommand, v as verifyGatePass, k as isVisibleTo, n as summarize, i as addIssue } from './store-D8dok6_d.mjs';
|
|
5
5
|
import 'node:crypto';
|
|
6
6
|
import 'node:child_process';
|
|
7
7
|
import './fileLock-BMPwCrB6.mjs';
|
|
8
8
|
|
|
9
|
+
function commandExistsOnPath(name) {
|
|
10
|
+
if (name === "true" || name === "false") return true;
|
|
11
|
+
for (const dir of (process.env.PATH || "").split(delimiter)) {
|
|
12
|
+
if (dir && existsSync(join(dir, name))) return true;
|
|
13
|
+
}
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
9
16
|
const STATUS_GLYPH = {
|
|
10
17
|
ready: "\u25C9",
|
|
11
18
|
in_progress: "\u25D0",
|
|
@@ -55,6 +62,7 @@ const VALUE_FLAGS = /* @__PURE__ */ new Set([
|
|
|
55
62
|
"--label",
|
|
56
63
|
"--option",
|
|
57
64
|
"--question",
|
|
65
|
+
"--root",
|
|
58
66
|
"--scope",
|
|
59
67
|
"--session",
|
|
60
68
|
"--status",
|
|
@@ -81,17 +89,42 @@ function shortSess(s) {
|
|
|
81
89
|
}
|
|
82
90
|
function fmtIssue(i) {
|
|
83
91
|
const tri = i.triaged === false ? " \u25B3triage" : "";
|
|
84
|
-
const
|
|
85
|
-
const disp = i.disposition === "crew" ?
|
|
92
|
+
const holder = shortSess(i.session);
|
|
93
|
+
const disp = i.disposition === "crew" ? holder ? ` {crew:${holder}}` : " {crew}" : holder ? ` {session:${holder}}` : "";
|
|
86
94
|
const label = i.labels.length ? ` [${i.labels.join(", ")}]` : "";
|
|
87
95
|
const v = i.verify ? ` (verify:${i.verify.type})` : "";
|
|
88
96
|
const br = i.branch ? ` {branch:${i.branch}}` : "";
|
|
89
97
|
const ans = i.answer ? " \u21A9answered" : "";
|
|
90
98
|
return `#${i.id} ${STATUS_GLYPH[i.status]} ${i.title}${tri}${disp}${label}${v}${br}${ans}`;
|
|
91
99
|
}
|
|
100
|
+
function verifyGateRefusal(verb, id, res) {
|
|
101
|
+
const via = verb === "archive" ? " via edit" : "";
|
|
102
|
+
const escape = verb === "archive" ? "Use `svamp issue archive` for an obsolete/duplicate item, or pass --force to override." : "Fix the issue, or pass --force to override.";
|
|
103
|
+
if (res.notRunnable) {
|
|
104
|
+
return `Refusing to ${verb} #${id}${via}: its verify-cmd could not be RUN (command not found) \u2014 the ORACLE is mis-specified, not the fix.
|
|
105
|
+
$ ${res.cmd}
|
|
106
|
+
${res.output || ""}
|
|
107
|
+
Repair it, then ${verb} again:
|
|
108
|
+
svamp issue edit ${id} --verify-cmd "<a command that fails while the bug stands>"
|
|
109
|
+
svamp issue edit ${id} --verify "<a criterion>" # when no shell command can express it
|
|
110
|
+
(${escape})`;
|
|
111
|
+
}
|
|
112
|
+
return `Refusing to ${verb} #${id}${via}: its verify-cmd failed \u2014 the fix is not verified.
|
|
113
|
+
$ ${res.cmd}
|
|
114
|
+
${res.output || ""}
|
|
115
|
+
(${escape})`;
|
|
116
|
+
}
|
|
92
117
|
function buildVerify(args) {
|
|
93
118
|
const cmd = flag(args, "--verify-cmd");
|
|
94
|
-
if (cmd)
|
|
119
|
+
if (cmd) {
|
|
120
|
+
const bare = cmd.trim();
|
|
121
|
+
if (/^[A-Za-z_][A-Za-z0-9_-]*$/.test(bare) && !commandExistsOnPath(bare)) {
|
|
122
|
+
console.error(`Refusing to set --verify-cmd "${bare}": that is a single word and it is not an executable on PATH, so the gate could never pass and the issue could never be closed.`);
|
|
123
|
+
console.error(`Did you mean --verify "${bare}" (an evaluator criterion), or a real command?`);
|
|
124
|
+
process.exit(1);
|
|
125
|
+
}
|
|
126
|
+
return { type: "command", text: cmd };
|
|
127
|
+
}
|
|
95
128
|
const agent = flag(args, "--verify");
|
|
96
129
|
if (agent) return { type: "agent", text: agent };
|
|
97
130
|
if (has(args, "--manual")) return { type: "manual" };
|
|
@@ -100,7 +133,12 @@ function buildVerify(args) {
|
|
|
100
133
|
async function issueCommand(args) {
|
|
101
134
|
const sub = args.some((a) => a === "--help" || a === "-h") ? "help" : args[0];
|
|
102
135
|
const rest = args.slice(1);
|
|
103
|
-
const
|
|
136
|
+
const rootFlag = flag(rest, "--root");
|
|
137
|
+
if (rootFlag !== void 0 && !existsSync(join(rootFlag, ".svamp", "issues"))) {
|
|
138
|
+
console.error(`svamp issue: no tracker at ${rootFlag} \u2014 expected ${join(rootFlag, ".svamp", "issues")}`);
|
|
139
|
+
process.exit(1);
|
|
140
|
+
}
|
|
141
|
+
const root = rootFlag ?? resolveProjectRoot();
|
|
104
142
|
const json = has(args, "--json");
|
|
105
143
|
const sessionId = process.env.SVAMP_SESSION_ID || null;
|
|
106
144
|
const out = (text) => console.log(text);
|
|
@@ -126,7 +164,12 @@ async function issueCommand(args) {
|
|
|
126
164
|
}
|
|
127
165
|
const labels = rest.filter((a, idx) => rest[idx - 1] === "--label");
|
|
128
166
|
const owner = flag(rest, "--session") || sessionId;
|
|
129
|
-
const
|
|
167
|
+
const rawScope = flag(rest, "--scope");
|
|
168
|
+
const scope = rawScope == null ? owner ? "session" : "project" : parseScopeArg(rawScope);
|
|
169
|
+
if (!scope) {
|
|
170
|
+
console.error(`Invalid --scope "${rawScope}". Must be one of: ${ISSUE_SCOPES.join(", ")}.`);
|
|
171
|
+
process.exit(1);
|
|
172
|
+
}
|
|
130
173
|
const issue = addIssue(root, {
|
|
131
174
|
title,
|
|
132
175
|
// New issues are actionable immediately (#0049) — there is no backlog to promote from.
|
|
@@ -241,12 +284,10 @@ ${issue.body}`);
|
|
|
241
284
|
} else {
|
|
242
285
|
const res = checkVerifyCommand(root, current);
|
|
243
286
|
if (!res.ok) {
|
|
244
|
-
console.error(
|
|
245
|
-
$ ${res.cmd}
|
|
246
|
-
${res.output || ""}
|
|
247
|
-
(Fix the issue, or pass --force to override.)`);
|
|
287
|
+
console.error(verifyGateRefusal("close", id, res));
|
|
248
288
|
process.exit(1);
|
|
249
289
|
}
|
|
290
|
+
console.error(verifyGatePass(res));
|
|
250
291
|
}
|
|
251
292
|
}
|
|
252
293
|
}
|
|
@@ -297,12 +338,10 @@ ${res.output || ""}
|
|
|
297
338
|
} else {
|
|
298
339
|
const res = checkVerifyCommand(root, current);
|
|
299
340
|
if (!res.ok) {
|
|
300
|
-
console.error(
|
|
301
|
-
$ ${res.cmd}
|
|
302
|
-
${res.output || ""}
|
|
303
|
-
(Use \`svamp issue archive\` for an obsolete/duplicate item, or pass --force to override.)`);
|
|
341
|
+
console.error(verifyGateRefusal("archive", id, res));
|
|
304
342
|
process.exit(1);
|
|
305
343
|
}
|
|
344
|
+
console.error(verifyGatePass(res));
|
|
306
345
|
}
|
|
307
346
|
}
|
|
308
347
|
}
|
|
@@ -334,7 +373,10 @@ ${res.output || ""}
|
|
|
334
373
|
const tv = buildVerify(rest);
|
|
335
374
|
if (tv) patch.verify = tv;
|
|
336
375
|
if (flag(rest, "--body")) patch.body = flag(rest, "--body");
|
|
337
|
-
patch
|
|
376
|
+
applyTriageStatus(root, id, patch, (m) => {
|
|
377
|
+
console.error(m);
|
|
378
|
+
process.exit(1);
|
|
379
|
+
});
|
|
338
380
|
const updated = updateIssue(root, id, patch);
|
|
339
381
|
if (!updated) {
|
|
340
382
|
console.error(`Issue not found: ${id}`);
|
|
@@ -407,6 +449,7 @@ the user explicitly reserved): re-run with \`--blocked "<the specific blocker>"\
|
|
|
407
449
|
const pending = listIssues(root).filter(inScope).filter(isPendingIssue);
|
|
408
450
|
if (json) console.log(JSON.stringify(pending));
|
|
409
451
|
else out(pending.length ? `${pending.length} pending: ${pending.map((i) => "#" + i.id).join(" ")}` : "No pending issues.");
|
|
452
|
+
console.error(`tracker: ${join(root, ".svamp", "issues")}${mine ? ` scope: session ${mine}` : " scope: all"}`);
|
|
410
453
|
await flushAndExit(pending.length ? 1 : 0);
|
|
411
454
|
break;
|
|
412
455
|
}
|
|
@@ -528,8 +571,11 @@ the user explicitly reserved): re-run with \`--blocked "<the specific blocker>"\
|
|
|
528
571
|
" # A paused issue drops out of `pending`, so a loop converges cleanly instead",
|
|
529
572
|
' # of spinning on it. NOT for "please check my work" \u2014 close finished work.',
|
|
530
573
|
' resume <id> [--answer "\u2026"] # un-pause (the user answering a --question resumes it automatically)',
|
|
531
|
-
" pending [--session <id>] [--mine] # exit 0 when NO issue is open \u2014 i.e. every
|
|
532
|
-
" # archived or paused. Counted by EXCLUSION, not an allow-list (#107). The loop oracle.",
|
|
574
|
+
" pending [--session <id>] [--mine] [--root <path>] # exit 0 when NO issue is open \u2014 i.e. every",
|
|
575
|
+
" # issue is archived or paused. Counted by EXCLUSION, not an allow-list (#107). The loop oracle.",
|
|
576
|
+
" # It names the tracker it read on stderr. Pass --root to PIN that tracker instead of",
|
|
577
|
+
" # walking up from the cwd: from the wrong directory the verdict is a clean exit 0 about",
|
|
578
|
+
" # somebody else's backlog, and it reads identically to your own being done (#0315).",
|
|
533
579
|
' search "<query>" [--json]',
|
|
534
580
|
" guide <triage|work> # the triage / work-loop procedure (so triggers can stay short)"
|
|
535
581
|
].join("\n"));
|
|
@@ -540,4 +586,4 @@ the user explicitly reserved): re-run with \`--blocked "<the specific blocker>"\
|
|
|
540
586
|
}
|
|
541
587
|
}
|
|
542
588
|
|
|
543
|
-
export { VALUE_FLAGS, issueCommand, loopActiveForCwd, positional };
|
|
589
|
+
export { VALUE_FLAGS, fmtIssue, issueCommand, loopActiveForCwd, positional };
|