svamp-cli 0.2.204 → 0.2.206
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/loop/bin/stop-gate.mjs +84 -3
- package/bin/skills/loop/test/test-loop-gate.mjs +65 -12
- package/dist/{agentCommands-D92DfTGP.mjs → agentCommands-akIoZemu.mjs} +5 -5
- package/dist/{auth-BvO7QtaP.mjs → auth-Dzf0cndq.mjs} +1 -1
- package/dist/cli.mjs +63 -61
- package/dist/{commands-CHqMRENk.mjs → commands-8Rd6p4B4.mjs} +1 -1
- package/dist/{commands-wtMi-xJY.mjs → commands-BPhgtKi2.mjs} +2 -2
- package/dist/{commands-u68ODpBt.mjs → commands-BRmWVCNf.mjs} +34 -11
- package/dist/{commands-BduSUevP.mjs → commands-BfakuMvA.mjs} +2 -2
- package/dist/{commands-5AerKSMm.mjs → commands-Dp7BFqYl.mjs} +1 -1
- package/dist/{commands-DwWuWW99.mjs → commands-OMKB5-oS.mjs} +29 -11
- package/dist/{commands-Dyy_1c0I.mjs → commands-V6wL2BtU.mjs} +5 -5
- package/dist/{fleet-CFe5Kt6k.mjs → fleet-Ci190s0w.mjs} +1 -1
- package/dist/{frpc-DMV0fZBM.mjs → frpc-H52IJYcb.mjs} +1 -1
- package/dist/{headlessCli-COLHIWk8.mjs → headlessCli-tLrOER4U.mjs} +2 -2
- package/dist/index.mjs +1 -1
- package/dist/{package-CqGr9_jQ.mjs → package-MNPXOWOP.mjs} +1 -1
- package/dist/{rpc-CoNLjY5x.mjs → rpc-BHUHF_Mv.mjs} +10 -3
- package/dist/{rpc-DBpyHJUs.mjs → rpc-CFrVMETs.mjs} +1 -1
- package/dist/{run-CR8y6yQ7.mjs → run-C4OsABqC.mjs} +1 -1
- package/dist/{run-BfgkuBEg.mjs → run-C9ZeF2iG.mjs} +101 -18
- package/dist/{scheduler-C1_HeBdn.mjs → scheduler-ErjEISCv.mjs} +1 -1
- package/dist/{serveCommands-d3t4RkrF.mjs → serveCommands-feGogIWC.mjs} +5 -5
- package/dist/{serveManager-DA9elK4m.mjs → serveManager-Be-R7R8_.mjs} +2 -2
- package/dist/{sideband-DNLuglX3.mjs → sideband-cU4KDceu.mjs} +1 -1
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { execSync } from 'node:child_process';
|
|
2
|
-
import { m as resolveProjectRoot, w as searchIssues, v as listIssues, o as resumeIssue, p as pauseIssue, q as addComment, u as updateIssue, n as getIssue, x as isVisibleTo, z as summarize, t as addIssue } from './run-
|
|
2
|
+
import { m as resolveProjectRoot, w as searchIssues, v as listIssues, o as resumeIssue, p as pauseIssue, q as addComment, u as updateIssue, n as getIssue, x as isVisibleTo, z as summarize, t as addIssue } from './run-C9ZeF2iG.mjs';
|
|
3
3
|
import 'os';
|
|
4
4
|
import 'fs/promises';
|
|
5
5
|
import 'fs';
|
|
@@ -63,7 +63,8 @@ function fmtIssue(i) {
|
|
|
63
63
|
const label = i.labels.length ? ` [${i.labels.join(", ")}]` : "";
|
|
64
64
|
const v = i.verify ? ` (verify:${i.verify.type})` : "";
|
|
65
65
|
const br = i.branch ? ` {branch:${i.branch}}` : "";
|
|
66
|
-
|
|
66
|
+
const ans = i.answer ? " \u21A9answered" : "";
|
|
67
|
+
return `#${i.id} ${STATUS_GLYPH[i.status]} ${i.title}${tri}${disp}${label}${v}${br}${ans}`;
|
|
67
68
|
}
|
|
68
69
|
function buildVerify(args) {
|
|
69
70
|
const cmd = flag(args, "--verify-cmd");
|
|
@@ -157,6 +158,10 @@ ${s.ready} ready \xB7 ${s.in_progress} in-progress \xB7 ${s.archived} archived`)
|
|
|
157
158
|
}
|
|
158
159
|
out(fmtIssue(issue));
|
|
159
160
|
out(`status: ${issue.status} \xB7 scope: ${issue.scope} \xB7 created: ${issue.created}${issue.closed ? ` \xB7 closed: ${issue.closed}` : ""}`);
|
|
161
|
+
if (issue.answer) out(`
|
|
162
|
+
\u21A9 The user answered your question \u2014 act on this: ${issue.answer}`);
|
|
163
|
+
if (issue.question) out(`
|
|
164
|
+
\u23F8 Paused \u2014 awaiting your question: ${issue.question.text}`);
|
|
160
165
|
if (issue.original) out(`
|
|
161
166
|
Original request:
|
|
162
167
|
${issue.original}`);
|
|
@@ -175,7 +180,7 @@ ${issue.body}`);
|
|
|
175
180
|
const worker = flag(rest, "--session") || sessionId;
|
|
176
181
|
const cur = getIssue(root, id);
|
|
177
182
|
const claim = worker && cur && cur.scope === "project" && !cur.session ? { session: worker } : {};
|
|
178
|
-
const updated = updateIssue(root, id, { status: "in_progress", ...branch ? { branch } : {}, ...claim });
|
|
183
|
+
const updated = updateIssue(root, id, { status: "in_progress", answer: null, ...branch ? { branch } : {}, ...claim });
|
|
179
184
|
if (!updated) {
|
|
180
185
|
console.error(`Issue not found: ${id}`);
|
|
181
186
|
process.exit(1);
|
|
@@ -367,7 +372,9 @@ ${tail}
|
|
|
367
372
|
" - A question you can just answer \u2192 reply, then close.",
|
|
368
373
|
" - Belongs to another session/repo \u2192 say where it should go (and route it), then close/redirect.",
|
|
369
374
|
" B. UNDERSPECIFIED? Do not guess. Enrich from the codebase where you can, and CONFIRM with the user",
|
|
370
|
-
" for anything genuinely ambiguous (ask 1-2 sharp questions) BEFORE marking it ready.",
|
|
375
|
+
" for anything genuinely ambiguous (ask 1-2 sharp questions) BEFORE marking it ready. TRIAGE is THE",
|
|
376
|
+
" place to ask \u2014 the work loop runs on sensible defaults and will NOT stop to ask, so surface every",
|
|
377
|
+
' real question now (`svamp issue pause <id> --question "\u2026" [--option "A" --option "B"]`).',
|
|
371
378
|
" C. SPLIT if the post bundles several independent asks: `svamp issue add` one per piece (carry the",
|
|
372
379
|
" relevant context), triage each, keep the original as the primary.",
|
|
373
380
|
" D. AUTOMATION: if it implies running on a schedule/event, `svamp workflow add` it (instead of / in",
|
|
@@ -387,22 +394,33 @@ ${tail}
|
|
|
387
394
|
].join("\n"));
|
|
388
395
|
} else if (topic === "work") {
|
|
389
396
|
out([
|
|
390
|
-
"WORK the
|
|
391
|
-
"sessions' private items alone). List: svamp issue list --
|
|
397
|
+
"WORK the actionable issues in THIS session's backlog (your own + shared project items; leave other",
|
|
398
|
+
"sessions' private items alone). List them with: svamp issue list --session <id> (shows ready AND",
|
|
399
|
+
"in-progress \u2014 a RESUMED issue is in-progress, so a ready-only filter would hide it). An issue badged",
|
|
400
|
+
"\u21A9answered carries a fresh user answer \u2014 work that one FIRST.",
|
|
392
401
|
" TRIAGE FIRST any \u25B3triage (untriaged) issue \u2014 see `svamp issue guide triage`.",
|
|
393
402
|
" For each issue:",
|
|
394
|
-
" 1. On pickup: svamp issue
|
|
403
|
+
" 1. On pickup: `svamp issue show <id>` FIRST, then `svamp issue work <id>`. ALWAYS read show \u2014 its",
|
|
404
|
+
' top surfaces any "\u21A9 The user answered your question \u2014 act on this: \u2026" line. Picking up via',
|
|
405
|
+
" `work` clears that badge, so read it before you do. (status \u2192 in_progress; live status updates.)",
|
|
395
406
|
' 2. As you go: leave substantive `svamp issue comment <id> "\u2026"` notes \u2014 decisions, takeaways, blockers.',
|
|
396
407
|
" 3. Before closing: VERIFY with evidence \u2014 run its verify-cmd; for verify:agent cite the files/commit",
|
|
397
408
|
" that resolve it in a summary comment. Post the summary, THEN `svamp issue close <id>`.",
|
|
398
409
|
" NEVER close an issue that isn't genuinely resolved.",
|
|
399
410
|
" CONVERGE TO MAIN: if an issue used an isolated branch/worktree, merge it back to `main` (and remove",
|
|
400
411
|
" the worktree) BEFORE closing \u2014 never leave unmerged branches.",
|
|
401
|
-
"
|
|
412
|
+
"",
|
|
413
|
+
" DEFAULT FORWARD \u2014 DON'T PAUSE TO ASK QUESTIONS DURING WORK. Clarifying/preference questions belong in",
|
|
414
|
+
" TRIAGE, not here. While working, if something is ambiguous, pick the most sensible default, PROCEED, and",
|
|
415
|
+
" DOCUMENT the assumption in a `svamp issue comment` (so the user can correct it). An over-eager pause",
|
|
416
|
+
" defeats the whole point of an automated loop.",
|
|
417
|
+
" PAUSE ONLY when you are genuinely BLOCKED and cannot proceed by any reasonable default \u2014 e.g. you need a",
|
|
418
|
+
" secret/credential/access only the user has, an irreversible or destructive action needs sign-off, or the",
|
|
419
|
+
" user EXPLICITLY reserved the decision. In that case:",
|
|
402
420
|
' svamp issue pause <id> --question "\u2026" [--option "A" --option "B"]',
|
|
403
|
-
" A paused issue is EXCLUDED from `pending`, so the loop
|
|
404
|
-
"
|
|
405
|
-
|
|
421
|
+
" A paused issue is EXCLUDED from `pending`, so the loop stops cleanly. The user answers (app renders the",
|
|
422
|
+
" options as buttons) \u2192 it resumes in-progress, badged \u21A9answered with the answer surfaced at the top of",
|
|
423
|
+
" `show` \u2014 re-pick it up and act on the answer (do NOT re-ask the same question).",
|
|
406
424
|
" Keep going until `svamp issue pending --session <id>` is empty (paused issues don't count)."
|
|
407
425
|
].join("\n"));
|
|
408
426
|
} else {
|
|
@@ -58,7 +58,7 @@ async function serviceExpose(args) {
|
|
|
58
58
|
process.exit(1);
|
|
59
59
|
}
|
|
60
60
|
if (foreground) {
|
|
61
|
-
const { runFrpcTunnel } = await import('./frpc-
|
|
61
|
+
const { runFrpcTunnel } = await import('./frpc-H52IJYcb.mjs');
|
|
62
62
|
await runFrpcTunnel(name, ports, void 0, {
|
|
63
63
|
group,
|
|
64
64
|
groupKey,
|
|
@@ -68,7 +68,7 @@ async function serviceExpose(args) {
|
|
|
68
68
|
});
|
|
69
69
|
return;
|
|
70
70
|
}
|
|
71
|
-
const { connectAndGetMachine } = await import('./commands-
|
|
71
|
+
const { connectAndGetMachine } = await import('./commands-BRmWVCNf.mjs');
|
|
72
72
|
const { server, machine } = await connectAndGetMachine();
|
|
73
73
|
try {
|
|
74
74
|
const status = await machine.tunnelStart({
|
|
@@ -123,7 +123,7 @@ async function serviceServe(args) {
|
|
|
123
123
|
};
|
|
124
124
|
process.on("SIGINT", cleanup);
|
|
125
125
|
process.on("SIGTERM", cleanup);
|
|
126
|
-
const { runFrpcTunnel } = await import('./frpc-
|
|
126
|
+
const { runFrpcTunnel } = await import('./frpc-H52IJYcb.mjs');
|
|
127
127
|
await runFrpcTunnel(name, [caddyPort]);
|
|
128
128
|
} catch (err) {
|
|
129
129
|
console.error(`Error serving directory: ${err.message}`);
|
|
@@ -132,7 +132,7 @@ async function serviceServe(args) {
|
|
|
132
132
|
}
|
|
133
133
|
async function serviceList(_args) {
|
|
134
134
|
try {
|
|
135
|
-
const { connectAndGetMachine } = await import('./commands-
|
|
135
|
+
const { connectAndGetMachine } = await import('./commands-BRmWVCNf.mjs');
|
|
136
136
|
const { server, machine } = await connectAndGetMachine();
|
|
137
137
|
try {
|
|
138
138
|
const tunnels = await machine.tunnelList({});
|
|
@@ -172,7 +172,7 @@ async function serviceDelete(args) {
|
|
|
172
172
|
process.exit(1);
|
|
173
173
|
}
|
|
174
174
|
try {
|
|
175
|
-
const { connectAndGetMachine } = await import('./commands-
|
|
175
|
+
const { connectAndGetMachine } = await import('./commands-BRmWVCNf.mjs');
|
|
176
176
|
const { server, machine } = await connectAndGetMachine();
|
|
177
177
|
try {
|
|
178
178
|
await machine.tunnelStop({ name });
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import os from 'node:os';
|
|
4
|
-
import { c as connectToHypha } from './run-
|
|
4
|
+
import { c as connectToHypha } from './run-C9ZeF2iG.mjs';
|
|
5
5
|
import { PINNED_CLAUDE_CODE_VERSION } from './pinnedClaudeCode-HydRNEt7.mjs';
|
|
6
6
|
import 'os';
|
|
7
7
|
import 'fs/promises';
|
|
@@ -4,7 +4,7 @@ import { mkdirSync, writeFileSync, unlinkSync, existsSync, chmodSync, readFileSy
|
|
|
4
4
|
import { join } from 'path';
|
|
5
5
|
import { homedir, platform, arch } from 'os';
|
|
6
6
|
import { randomUUID, createHash } from 'crypto';
|
|
7
|
-
import { h as getFrpsSubdomainHost, i as getFrpsServerPort, j as getFrpsServerAddr } from './run-
|
|
7
|
+
import { h as getFrpsSubdomainHost, i as getFrpsServerPort, j as getFrpsServerAddr } from './run-C9ZeF2iG.mjs';
|
|
8
8
|
import 'fs/promises';
|
|
9
9
|
import 'url';
|
|
10
10
|
import 'node:crypto';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { P as resolveModel, a1 as describeMisconfiguration, a2 as buildMachineDeps } from './run-
|
|
2
|
-
import { handleRealtimeEvent, initMachineVoiceSession } from './sideband-
|
|
1
|
+
import { P as resolveModel, a1 as describeMisconfiguration, a2 as buildMachineDeps } from './run-C9ZeF2iG.mjs';
|
|
2
|
+
import { handleRealtimeEvent, initMachineVoiceSession } from './sideband-cU4KDceu.mjs';
|
|
3
3
|
import { WebSocket } from 'ws';
|
|
4
4
|
import { execSync, spawn } from 'child_process';
|
|
5
5
|
import 'os';
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { c as connectToHypha, a as createSessionStore, d as daemonStatus, g as getHyphaServerUrl, r as registerMachineService, s as startDaemon, b as stopDaemon } from './run-
|
|
1
|
+
export { c as connectToHypha, a as createSessionStore, d as daemonStatus, g as getHyphaServerUrl, r as registerMachineService, s as startDaemon, b as stopDaemon } from './run-C9ZeF2iG.mjs';
|
|
2
2
|
import 'os';
|
|
3
3
|
import 'fs/promises';
|
|
4
4
|
import 'fs';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { m as resolveProjectRoot, u as updateIssue, n as getIssue, o as resumeIssue, p as pauseIssue, q as addComment, t as addIssue, v as listIssues, w as searchIssues, x as isVisibleTo } from './run-
|
|
1
|
+
import { m as resolveProjectRoot, u as updateIssue, n as getIssue, o as resumeIssue, p as pauseIssue, q as addComment, t as addIssue, v as listIssues, w as searchIssues, x as isVisibleTo } from './run-C9ZeF2iG.mjs';
|
|
2
2
|
import 'os';
|
|
3
3
|
import 'fs/promises';
|
|
4
4
|
import 'fs';
|
|
@@ -94,7 +94,7 @@ function issueRpc(cwd, params, deps = {}) {
|
|
|
94
94
|
original = src;
|
|
95
95
|
body = void 0;
|
|
96
96
|
}
|
|
97
|
-
|
|
97
|
+
const created = addIssue(root, {
|
|
98
98
|
title,
|
|
99
99
|
status: "ready",
|
|
100
100
|
scope,
|
|
@@ -108,6 +108,11 @@ function issueRpc(cwd, params, deps = {}) {
|
|
|
108
108
|
original,
|
|
109
109
|
body
|
|
110
110
|
});
|
|
111
|
+
if (params.rekick) {
|
|
112
|
+
const loopOwner = created.session || created.owner;
|
|
113
|
+
if (loopOwner) deps.rekickLoopOwner?.(String(loopOwner), { skipStalled: true });
|
|
114
|
+
}
|
|
115
|
+
return created;
|
|
111
116
|
}
|
|
112
117
|
case "comment": {
|
|
113
118
|
const text = String(params.text || "");
|
|
@@ -125,6 +130,8 @@ function issueRpc(cwd, params, deps = {}) {
|
|
|
125
130
|
case "resume": {
|
|
126
131
|
const updated = resumeIssue(root, String(params.id), params.answer ? String(params.answer) : void 0);
|
|
127
132
|
if (!updated) throw new Error(`Issue not found: ${params.id}`);
|
|
133
|
+
const loopOwner = updated.session || updated.owner;
|
|
134
|
+
if (loopOwner) deps.rekickLoopOwner?.(String(loopOwner));
|
|
128
135
|
return updated;
|
|
129
136
|
}
|
|
130
137
|
case "status": {
|
|
@@ -140,7 +147,7 @@ function issueRpc(cwd, params, deps = {}) {
|
|
|
140
147
|
return updated;
|
|
141
148
|
}
|
|
142
149
|
case "work": {
|
|
143
|
-
const patch = { status: "in_progress" };
|
|
150
|
+
const patch = { status: "in_progress", answer: null };
|
|
144
151
|
if (params.branch) patch.branch = String(params.branch);
|
|
145
152
|
const worker = params.session || null;
|
|
146
153
|
const cur = getIssue(root, String(params.id));
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { m as resolveProjectRoot } from './run-
|
|
1
|
+
import { m as resolveProjectRoot } from './run-C9ZeF2iG.mjs';
|
|
2
2
|
import { g as getWorkflow, s as setWorkflowEnabled, r as removeWorkflow, a as saveWorkflow, b as rawWorkflow, l as listWorkflows } from './store-BTs0H_y0.mjs';
|
|
3
3
|
import { g as getRun, l as listRuns, r as runWorkflow } from './runStore-CtptN7US.mjs';
|
|
4
4
|
import 'os';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import { a3 as applyClaudeProxyEnv, a4 as composeSessionId, a5 as generateFriendlyName, c as connectToHypha, a as createSessionStore, r as registerMachineService, a6 as generateHookSettings } from './run-
|
|
1
|
+
import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import { a3 as applyClaudeProxyEnv, a4 as composeSessionId, a5 as generateFriendlyName, c as connectToHypha, a as createSessionStore, r as registerMachineService, a6 as generateHookSettings } from './run-C9ZeF2iG.mjs';
|
|
2
2
|
import os from 'node:os';
|
|
3
3
|
import { resolve, join } from 'node:path';
|
|
4
4
|
import { existsSync, readFileSync, watch } from 'node:fs';
|
|
@@ -2912,7 +2912,7 @@ async function registerMachineService(server, machineId, metadata, daemonState,
|
|
|
2912
2912
|
const tunnels = handlers.tunnels;
|
|
2913
2913
|
if (!tunnels) throw new Error("Tunnel management not available");
|
|
2914
2914
|
if (tunnels.has(params.name)) throw new Error(`Tunnel '${params.name}' already running`);
|
|
2915
|
-
const { FrpcTunnel } = await import('./frpc-
|
|
2915
|
+
const { FrpcTunnel } = await import('./frpc-H52IJYcb.mjs');
|
|
2916
2916
|
const tunnel = new FrpcTunnel({
|
|
2917
2917
|
name: params.name,
|
|
2918
2918
|
ports: params.ports,
|
|
@@ -3359,7 +3359,7 @@ QUESTION: ${params.question || "Summarize this concisely."}` }
|
|
|
3359
3359
|
}
|
|
3360
3360
|
const deps = buildSessionDeps(rpc, { cwd, ownerEmail: owner });
|
|
3361
3361
|
const sender = { name: context?.user?.email || context?.user?.id || "user", kind: "user", verified: true };
|
|
3362
|
-
const { toolsForRole } = await import('./sideband-
|
|
3362
|
+
const { toolsForRole } = await import('./sideband-cU4KDceu.mjs');
|
|
3363
3363
|
const r2 = await runWiseAgent({ message: params.message, sender, config: { tools: toolsForRole(role2) }, deps, transport, model: resolved.model });
|
|
3364
3364
|
return fmt(r2);
|
|
3365
3365
|
}
|
|
@@ -3458,7 +3458,7 @@ QUESTION: ${params.question || "Summarize this concisely."}` }
|
|
|
3458
3458
|
if (r.error || !r.sender) return { error: r.error || "unauthorized" };
|
|
3459
3459
|
const callId = "call_" + Math.random().toString(16).slice(2, 12);
|
|
3460
3460
|
const rendered = renderMessage(c, { sender: r.sender, body: { message: kwargs.message }, callId });
|
|
3461
|
-
const { queryCore } = await import('./commands-
|
|
3461
|
+
const { queryCore } = await import('./commands-BRmWVCNf.mjs');
|
|
3462
3462
|
const timeout = c.reply?.timeout_sec || 120;
|
|
3463
3463
|
let result;
|
|
3464
3464
|
try {
|
|
@@ -10406,7 +10406,7 @@ function normalizeStatus(s) {
|
|
|
10406
10406
|
if (s === "done") return "archived";
|
|
10407
10407
|
return s === "ready" || s === "in_progress" || s === "paused" || s === "archived" ? s : "ready";
|
|
10408
10408
|
}
|
|
10409
|
-
const FIELD_ORDER = ["id", "title", "status", "scope", "labels", "verify", "disposition", "triaged", "branch", "session", "owner", "original", "created", "closed", "question"];
|
|
10409
|
+
const FIELD_ORDER = ["id", "title", "status", "scope", "labels", "verify", "disposition", "triaged", "branch", "session", "owner", "original", "created", "closed", "question", "answer"];
|
|
10410
10410
|
function resolveProjectRoot(start = process.cwd()) {
|
|
10411
10411
|
let dir = start;
|
|
10412
10412
|
for (let i = 0; i < 40; i++) {
|
|
@@ -10468,6 +10468,7 @@ function parseIssue(content) {
|
|
|
10468
10468
|
created: String(fm.created ?? (/* @__PURE__ */ new Date()).toISOString()),
|
|
10469
10469
|
closed: fm.closed ?? null,
|
|
10470
10470
|
question: fm.question && typeof fm.question === "object" ? fm.question : null,
|
|
10471
|
+
answer: typeof fm.answer === "string" && fm.answer.trim() ? fm.answer : null,
|
|
10471
10472
|
body: (m[2] || "").trim() || void 0
|
|
10472
10473
|
};
|
|
10473
10474
|
}
|
|
@@ -10586,14 +10587,15 @@ Options: ${q.options.join(" \xB7 ")}` : "";
|
|
|
10586
10587
|
} else {
|
|
10587
10588
|
addComment(projectRoot, id, "\u23F8 Paused \u2014 waiting on your input.");
|
|
10588
10589
|
}
|
|
10589
|
-
return updateIssue(projectRoot, id, { status: "paused", question: q });
|
|
10590
|
+
return updateIssue(projectRoot, id, { status: "paused", question: q, answer: null });
|
|
10590
10591
|
}
|
|
10591
10592
|
function resumeIssue(projectRoot, id, answer) {
|
|
10592
10593
|
const cur = getIssue(projectRoot, id);
|
|
10593
10594
|
if (!cur) return null;
|
|
10594
|
-
|
|
10595
|
+
const a = answer && answer.trim() ? answer.trim() : "";
|
|
10596
|
+
if (a) addComment(projectRoot, id, `\u25B6 Resumed \u2014 your answer: ${a}`);
|
|
10595
10597
|
else addComment(projectRoot, id, "\u25B6 Resumed.");
|
|
10596
|
-
return updateIssue(projectRoot, id, { status: "in_progress", question: null });
|
|
10598
|
+
return updateIssue(projectRoot, id, { status: "in_progress", question: null, answer: a || null });
|
|
10597
10599
|
}
|
|
10598
10600
|
function routeCrewVerdict(projectRoot, childSessionId, v) {
|
|
10599
10601
|
const linked = listIssues(projectRoot, { includeArchived: true }).find((i) => i.disposition === "crew" && i.session === childSessionId);
|
|
@@ -11603,7 +11605,10 @@ function createSvampConfigChecker(directory, sessionId, getMetadata, setMetadata
|
|
|
11603
11605
|
announcedLoopStart = key;
|
|
11604
11606
|
const iter = typeof s.iteration === "number" ? s.iteration : 0;
|
|
11605
11607
|
const plural = iter === 1 ? "" : "s";
|
|
11606
|
-
const
|
|
11608
|
+
const gaveUpCfg = readLoopJson(directory, sessionId, "loop.config.json") || {};
|
|
11609
|
+
const curMax = typeof gaveUpCfg.max_iterations === "number" ? gaveUpCfg.max_iterations : iter;
|
|
11610
|
+
const nextMax = Math.max(curMax * 2, iter + 10);
|
|
11611
|
+
const msg = s.phase === "done" ? `\u{1F501} Loop complete \u2705 \u2014 finished after ${iter} iteration${plural}.` : `\u{1F501} Loop paused \u{1F6D1} \u2014 hit its iteration limit (${iter}/${curMax}) and did NOT finish${s.gave_up_reason ? ` (${s.gave_up_reason})` : ""}. Resume & extend with: svamp session loop-resume ${sessionId} --max ${nextMax}`;
|
|
11607
11612
|
sessionService.pushMessage(
|
|
11608
11613
|
s.phase === "gave_up" ? { type: "message", message: msg, level: "warning" } : { type: "message", message: msg },
|
|
11609
11614
|
"event"
|
|
@@ -11656,7 +11661,46 @@ function createSvampConfigChecker(directory, sessionId, getMetadata, setMetadata
|
|
|
11656
11661
|
}
|
|
11657
11662
|
const task = cfg && typeof cfg.task === "string" && cfg.task.trim() ? cfg.task.trim() : void 0;
|
|
11658
11663
|
const until = cfg && typeof cfg.until === "string" && cfg.until.trim() ? cfg.until.trim() : cfg && typeof cfg.criteria === "string" && cfg.criteria.trim() ? cfg.criteria.trim() : void 0;
|
|
11659
|
-
|
|
11664
|
+
const onlyLimit = cfg && typeof cfg === "object" && !task && !until && (typeof cfg.max_iterations === "number" || typeof cfg.max_rounds === "number" || cfg.budget);
|
|
11665
|
+
if (onlyLimit) {
|
|
11666
|
+
const existing = readLoopState(directory, sessionId);
|
|
11667
|
+
if (!existing) {
|
|
11668
|
+
sessionService.pushMessage({ type: "message", message: 'No loop to modify \u2014 start one with: svamp session loop <id> "<task>" --until "<criteria>" --max N', level: "warning" }, "event");
|
|
11669
|
+
} else {
|
|
11670
|
+
const newMax = typeof cfg.max_iterations === "number" ? cfg.max_iterations : typeof cfg.max_rounds === "number" ? cfg.max_rounds : void 0;
|
|
11671
|
+
try {
|
|
11672
|
+
const lcPath = join$1(getLoopDir(directory, sessionId), "loop.config.json");
|
|
11673
|
+
const lc = readLoopJson(directory, sessionId, "loop.config.json") || {};
|
|
11674
|
+
if (newMax != null) lc.max_iterations = newMax;
|
|
11675
|
+
const b = parseLoopBudget(cfg.budget);
|
|
11676
|
+
if (b) lc.budget = { ...lc.budget || {}, ...b };
|
|
11677
|
+
writeFileSync$1(lcPath, JSON.stringify(lc, null, 2));
|
|
11678
|
+
} catch {
|
|
11679
|
+
}
|
|
11680
|
+
const wasStopped = existing.active === false || existing.phase === "done" || existing.phase === "gave_up";
|
|
11681
|
+
if (wasStopped && existing.phase !== "cancelled") {
|
|
11682
|
+
try {
|
|
11683
|
+
const sp = join$1(getLoopDir(directory, sessionId), "loop-state.json");
|
|
11684
|
+
writeFileSync$1(sp, JSON.stringify({
|
|
11685
|
+
...existing,
|
|
11686
|
+
active: true,
|
|
11687
|
+
phase: "continue",
|
|
11688
|
+
iteration: 0,
|
|
11689
|
+
completed_at: void 0,
|
|
11690
|
+
gave_up_reason: void 0,
|
|
11691
|
+
stall_hinted: false,
|
|
11692
|
+
resumed_at: Date.now()
|
|
11693
|
+
}, null, 2));
|
|
11694
|
+
} catch {
|
|
11695
|
+
}
|
|
11696
|
+
const eq = getMetadata().messageQueue || [];
|
|
11697
|
+
setMetadata((m) => ({ ...m, messageQueue: [...eq, { id: randomUUID$1(), text: "Continue the loop. Read LOOP.md and keep working toward the exit conditions until the Stop gate confirms completion.", displayText: "\u{1F501} Resuming loop", createdAt: Date.now() }] }));
|
|
11698
|
+
}
|
|
11699
|
+
onLoopActivated?.();
|
|
11700
|
+
sessionService.pushMessage({ type: "message", message: `\u{1F501} Loop limit updated${newMax != null ? ` \u2192 max ${newMax} iterations` : ""}${wasStopped ? " \u2014 resuming" : ""}.` }, "event");
|
|
11701
|
+
logger.log(`[svampConfig] Loop limit modified (max=${newMax}, resumed=${wasStopped})`);
|
|
11702
|
+
}
|
|
11703
|
+
} else if (cfg && typeof cfg === "object" && (task || until)) {
|
|
11660
11704
|
const oracle = typeof cfg.oracle === "string" && cfg.oracle.trim() ? cfg.oracle.trim() : void 0;
|
|
11661
11705
|
const evaluator = cfg.evaluator !== false;
|
|
11662
11706
|
const maxIterations = typeof cfg.max_iterations === "number" ? cfg.max_iterations : typeof cfg.max_rounds === "number" ? cfg.max_rounds : 20;
|
|
@@ -12137,7 +12181,7 @@ async function startDaemon(options) {
|
|
|
12137
12181
|
saveExposedTunnels(list);
|
|
12138
12182
|
}
|
|
12139
12183
|
async function createExposedTunnel(spec) {
|
|
12140
|
-
const { FrpcTunnel } = await import('./frpc-
|
|
12184
|
+
const { FrpcTunnel } = await import('./frpc-H52IJYcb.mjs');
|
|
12141
12185
|
const tunnel = new FrpcTunnel({
|
|
12142
12186
|
name: spec.name,
|
|
12143
12187
|
ports: spec.ports,
|
|
@@ -12157,7 +12201,7 @@ async function startDaemon(options) {
|
|
|
12157
12201
|
return tunnel;
|
|
12158
12202
|
}
|
|
12159
12203
|
const tunnelRecreateState = /* @__PURE__ */ new Map();
|
|
12160
|
-
const { ServeManager } = await import('./serveManager-
|
|
12204
|
+
const { ServeManager } = await import('./serveManager-Be-R7R8_.mjs');
|
|
12161
12205
|
const serveManager = new ServeManager(SVAMP_HOME, (msg) => logger.log(`[SERVE] ${msg}`), hyphaServerUrl);
|
|
12162
12206
|
ensureAutoInstalledSkills(logger).catch(() => {
|
|
12163
12207
|
});
|
|
@@ -12260,6 +12304,17 @@ ${v.guidance ? v.guidance + "\n" : ""}Criteria: ${v.criteria || "(none)"}
|
|
|
12260
12304
|
} catch {
|
|
12261
12305
|
}
|
|
12262
12306
|
};
|
|
12307
|
+
const rekickLoopOwner = (sessionId, opts) => {
|
|
12308
|
+
try {
|
|
12309
|
+
const target = Array.from(pidToTrackedSession.values()).find((t) => t.svampSessionId === sessionId && !t.stopped);
|
|
12310
|
+
if (!target?.rekickLoop) {
|
|
12311
|
+
logger.log(`[issue] resume re-kick skipped \u2014 owner session ${sessionId.slice(0, 8)} not live on this machine`);
|
|
12312
|
+
return;
|
|
12313
|
+
}
|
|
12314
|
+
target.rekickLoop(opts);
|
|
12315
|
+
} catch {
|
|
12316
|
+
}
|
|
12317
|
+
};
|
|
12263
12318
|
server.on("services_registered", () => {
|
|
12264
12319
|
if (consecutiveHeartbeatFailures > 0) {
|
|
12265
12320
|
logger.log(`Hypha reconnection successful \u2014 services re-registered (resetting ${consecutiveHeartbeatFailures} failures)`);
|
|
@@ -14038,11 +14093,11 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
|
|
|
14038
14093
|
});
|
|
14039
14094
|
},
|
|
14040
14095
|
onIssue: async (params) => {
|
|
14041
|
-
const { issueRpc } = await import('./rpc-
|
|
14042
|
-
return issueRpc(params?.cwd || directory, params || {}, { notifySession: notifyIssueOwner });
|
|
14096
|
+
const { issueRpc } = await import('./rpc-BHUHF_Mv.mjs');
|
|
14097
|
+
return issueRpc(params?.cwd || directory, params || {}, { notifySession: notifyIssueOwner, rekickLoopOwner });
|
|
14043
14098
|
},
|
|
14044
14099
|
onWorkflow: async (params) => {
|
|
14045
|
-
const { workflowRpc } = await import('./rpc-
|
|
14100
|
+
const { workflowRpc } = await import('./rpc-CFrVMETs.mjs');
|
|
14046
14101
|
return workflowRpc(params?.cwd || directory, params || {});
|
|
14047
14102
|
},
|
|
14048
14103
|
onRipgrep: async (args, cwd) => {
|
|
@@ -14216,6 +14271,34 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
|
|
|
14216
14271
|
return claudeProcess || void 0;
|
|
14217
14272
|
}
|
|
14218
14273
|
};
|
|
14274
|
+
trackedSession.rekickLoop = (opts) => {
|
|
14275
|
+
if (trackedSession.stopped) return;
|
|
14276
|
+
const s = readLoopState(directory, sessionId);
|
|
14277
|
+
if (!s) return;
|
|
14278
|
+
if (s.phase === "cancelled") return;
|
|
14279
|
+
if (opts?.skipStalled && s.phase === "gave_up") return;
|
|
14280
|
+
if (typeof s.session_id === "string" && s.session_id !== sessionId) return;
|
|
14281
|
+
if (s.active === false || s.phase === "done" || s.phase === "gave_up") {
|
|
14282
|
+
try {
|
|
14283
|
+
const lp = join$1(getLoopDir(directory, sessionId), "loop-state.json");
|
|
14284
|
+
writeFileSync$1(lp, JSON.stringify({
|
|
14285
|
+
...s,
|
|
14286
|
+
active: true,
|
|
14287
|
+
phase: "continue",
|
|
14288
|
+
iteration: 0,
|
|
14289
|
+
completed_at: void 0,
|
|
14290
|
+
gave_up_reason: void 0,
|
|
14291
|
+
stall_hinted: false,
|
|
14292
|
+
resumed_at: Date.now()
|
|
14293
|
+
// #0156: re-arm the stall hint
|
|
14294
|
+
}, null, 2));
|
|
14295
|
+
} catch {
|
|
14296
|
+
}
|
|
14297
|
+
}
|
|
14298
|
+
logger.log(`[Session ${sessionId}] resumed issue \u2192 reactivating + re-kicking loop`);
|
|
14299
|
+
enqueueLoopContinue();
|
|
14300
|
+
processMessageQueueRef?.();
|
|
14301
|
+
};
|
|
14219
14302
|
pidToTrackedSession.set(randomUUID$1(), trackedSession);
|
|
14220
14303
|
sessionMetadata = { ...sessionMetadata, lifecycleState: "idle" };
|
|
14221
14304
|
sessionService.updateMetadata(sessionMetadata);
|
|
@@ -14552,11 +14635,11 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
|
|
|
14552
14635
|
});
|
|
14553
14636
|
},
|
|
14554
14637
|
onIssue: async (params) => {
|
|
14555
|
-
const { issueRpc } = await import('./rpc-
|
|
14556
|
-
return issueRpc(params?.cwd || directory, params || {}, { notifySession: notifyIssueOwner });
|
|
14638
|
+
const { issueRpc } = await import('./rpc-BHUHF_Mv.mjs');
|
|
14639
|
+
return issueRpc(params?.cwd || directory, params || {}, { notifySession: notifyIssueOwner, rekickLoopOwner });
|
|
14557
14640
|
},
|
|
14558
14641
|
onWorkflow: async (params) => {
|
|
14559
|
-
const { workflowRpc } = await import('./rpc-
|
|
14642
|
+
const { workflowRpc } = await import('./rpc-CFrVMETs.mjs');
|
|
14560
14643
|
return workflowRpc(params?.cwd || directory, params || {});
|
|
14561
14644
|
},
|
|
14562
14645
|
onRipgrep: async (args, cwd) => {
|
|
@@ -15330,7 +15413,7 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
|
|
|
15330
15413
|
const PING_TIMEOUT_MS = 15e3;
|
|
15331
15414
|
const POST_RECONNECT_GRACE_MS = 2e4;
|
|
15332
15415
|
const RECONNECT_JITTER_MS = 2500;
|
|
15333
|
-
const { WorkflowScheduler } = await import('./scheduler-
|
|
15416
|
+
const { WorkflowScheduler } = await import('./scheduler-ErjEISCv.mjs');
|
|
15334
15417
|
const workflowScheduler = new WorkflowScheduler({
|
|
15335
15418
|
projectRoots: () => {
|
|
15336
15419
|
const dirs = /* @__PURE__ */ new Set();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { m as resolveProjectRoot, y as cronMatches } from './run-
|
|
1
|
+
import { m as resolveProjectRoot, y as cronMatches } from './run-C9ZeF2iG.mjs';
|
|
2
2
|
import { l as listWorkflows, i as isWorkflowEnabled, w as workflowCrons } from './store-BTs0H_y0.mjs';
|
|
3
3
|
import { r as runWorkflow } from './runStore-CtptN7US.mjs';
|
|
4
4
|
import 'os';
|
|
@@ -54,7 +54,7 @@ async function handleServeCommand() {
|
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
async function serveAdd(args, machineId) {
|
|
57
|
-
const { connectAndGetMachine } = await import('./commands-
|
|
57
|
+
const { connectAndGetMachine } = await import('./commands-BRmWVCNf.mjs');
|
|
58
58
|
const pos = positionalArgs(args);
|
|
59
59
|
const name = pos[0];
|
|
60
60
|
if (!name) {
|
|
@@ -93,7 +93,7 @@ async function serveAdd(args, machineId) {
|
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
95
|
async function serveApply(args, machineId) {
|
|
96
|
-
const { connectAndGetMachine } = await import('./commands-
|
|
96
|
+
const { connectAndGetMachine } = await import('./commands-BRmWVCNf.mjs');
|
|
97
97
|
const fs = await import('fs');
|
|
98
98
|
const yaml = await import('yaml');
|
|
99
99
|
const file = positionalArgs(args)[0];
|
|
@@ -182,7 +182,7 @@ async function serveApply(args, machineId) {
|
|
|
182
182
|
}
|
|
183
183
|
}
|
|
184
184
|
async function serveRemove(args, machineId) {
|
|
185
|
-
const { connectAndGetMachine } = await import('./commands-
|
|
185
|
+
const { connectAndGetMachine } = await import('./commands-BRmWVCNf.mjs');
|
|
186
186
|
const pos = positionalArgs(args);
|
|
187
187
|
const name = pos[0];
|
|
188
188
|
if (!name) {
|
|
@@ -202,7 +202,7 @@ async function serveRemove(args, machineId) {
|
|
|
202
202
|
}
|
|
203
203
|
}
|
|
204
204
|
async function serveList(args, machineId) {
|
|
205
|
-
const { connectAndGetMachine } = await import('./commands-
|
|
205
|
+
const { connectAndGetMachine } = await import('./commands-BRmWVCNf.mjs');
|
|
206
206
|
const all = hasFlag(args, "--all", "-a");
|
|
207
207
|
const json = hasFlag(args, "--json");
|
|
208
208
|
const sessionId = getFlag(args, "--session");
|
|
@@ -235,7 +235,7 @@ async function serveList(args, machineId) {
|
|
|
235
235
|
}
|
|
236
236
|
}
|
|
237
237
|
async function serveInfo(machineId) {
|
|
238
|
-
const { connectAndGetMachine } = await import('./commands-
|
|
238
|
+
const { connectAndGetMachine } = await import('./commands-BRmWVCNf.mjs');
|
|
239
239
|
const { machine, server } = await connectAndGetMachine(machineId);
|
|
240
240
|
try {
|
|
241
241
|
const info = await machine.serveInfo();
|
|
@@ -4,7 +4,7 @@ import * as fs from 'fs';
|
|
|
4
4
|
import * as http from 'http';
|
|
5
5
|
import * as net from 'net';
|
|
6
6
|
import * as path from 'path';
|
|
7
|
-
import { k as getHyphaServerUrl, S as ServeAuth, l as hasCookieToken } from './run-
|
|
7
|
+
import { k as getHyphaServerUrl, S as ServeAuth, l as hasCookieToken } from './run-C9ZeF2iG.mjs';
|
|
8
8
|
import 'os';
|
|
9
9
|
import 'fs/promises';
|
|
10
10
|
import 'url';
|
|
@@ -733,7 +733,7 @@ class ServeManager {
|
|
|
733
733
|
const mount = this.mounts.get(mountName);
|
|
734
734
|
const subdomainOverride = mount?.access === "link" && mount.linkToken ? /* @__PURE__ */ new Map([[this.port, buildLinkSubdomain(subdomainSafe, mount.linkToken)]]) : void 0;
|
|
735
735
|
try {
|
|
736
|
-
const { FrpcTunnel } = await import('./frpc-
|
|
736
|
+
const { FrpcTunnel } = await import('./frpc-H52IJYcb.mjs');
|
|
737
737
|
let tunnel;
|
|
738
738
|
tunnel = new FrpcTunnel({
|
|
739
739
|
name: tunnelName,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { R as READ_ONLY_TOOLS, B as loadMachineContext, C as buildMachineInstructions, D as machineToolsForRole, E as buildMachineTools } from './run-
|
|
1
|
+
import { R as READ_ONLY_TOOLS, B as loadMachineContext, C as buildMachineInstructions, D as machineToolsForRole, E as buildMachineTools } from './run-C9ZeF2iG.mjs';
|
|
2
2
|
import 'node:child_process';
|
|
3
3
|
import 'os';
|
|
4
4
|
import 'fs/promises';
|