svamp-cli 0.2.225 → 0.2.227
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/agentCommands-7sqKMVIC.mjs +526 -0
- package/dist/auth-BfDZbHl6.mjs +83 -0
- package/dist/caddy-CuTbE3NY.mjs +322 -0
- package/dist/cli.mjs +2338 -0
- package/dist/commands-CU8JDM2d.mjs +428 -0
- package/dist/commands-CWP-J9Cf.mjs +610 -0
- package/dist/commands-CnlQyDxb.mjs +2762 -0
- package/dist/commands-D2iQ2v7_.mjs +196 -0
- package/dist/commands-DA_Nx893.mjs +265 -0
- package/dist/commands-H9h_Mtc4.mjs +493 -0
- package/dist/commands-YML8Rs_R.mjs +643 -0
- package/dist/fleet-B_78L11T.mjs +356 -0
- package/dist/frpc-BQyt6j5A.mjs +681 -0
- package/dist/headlessCli-CYfN9XvR.mjs +333 -0
- package/dist/httpServer-B1KVQJfm.mjs +276 -0
- package/dist/index.mjs +22 -0
- package/dist/package-VYP3g593.mjs +63 -0
- package/dist/pinnedClaudeCode-VIupR1NK.mjs +58 -0
- package/dist/rpc-DMj8ZJPz.mjs +92 -0
- package/dist/rpc-a0fp9HhD.mjs +194 -0
- package/dist/run-DkjwFIFH.mjs +1086 -0
- package/dist/run-LEPH8aka.mjs +16075 -0
- package/dist/runStore-CtptN7US.mjs +168 -0
- package/dist/sandboxDetect-DNTcbgWD.mjs +12 -0
- package/dist/scheduler-Bz80Ipep.mjs +102 -0
- package/dist/serveCommands-u_GoFaBX.mjs +310 -0
- package/dist/serveManager-9vhexH1L.mjs +781 -0
- package/dist/serviceManager-hlOVxkhW.mjs +78 -0
- package/dist/sideband-RJijk2GE.mjs +80 -0
- package/dist/store-BTs0H_y0.mjs +148 -0
- package/dist/supervisorLock-DmfzJx7B.mjs +159 -0
- package/package.json +1 -1
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { spawn, exec as exec$1 } from 'node:child_process';
|
|
2
|
+
import { promisify } from 'node:util';
|
|
3
|
+
|
|
4
|
+
const PINNED_CLAUDE_CODE_VERSION = "2.1.195";
|
|
5
|
+
const exec = promisify(exec$1);
|
|
6
|
+
async function readClaudeVersion() {
|
|
7
|
+
try {
|
|
8
|
+
const { stdout } = await exec("claude --version", { timeout: 1e4 });
|
|
9
|
+
const m = stdout.trim().match(/(\d+\.\d+\.\d+(?:[-.][\w]+)?)/);
|
|
10
|
+
return m ? m[1] : null;
|
|
11
|
+
} catch {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
function runInstaller(version, log) {
|
|
16
|
+
return new Promise((resolve) => {
|
|
17
|
+
const proc = spawn("claude", ["install", version], { stdio: ["ignore", "pipe", "pipe"] });
|
|
18
|
+
let stderr = "";
|
|
19
|
+
proc.stdout?.on("data", (b) => log(`[claude install] ${b.toString().trimEnd()}`));
|
|
20
|
+
proc.stderr?.on("data", (b) => {
|
|
21
|
+
const s = b.toString();
|
|
22
|
+
stderr += s;
|
|
23
|
+
log(`[claude install] ${s.trimEnd()}`);
|
|
24
|
+
});
|
|
25
|
+
proc.on("error", (e) => {
|
|
26
|
+
stderr += String(e);
|
|
27
|
+
resolve({ ok: false, stderr });
|
|
28
|
+
});
|
|
29
|
+
proc.on("exit", (code) => resolve({ ok: code === 0, stderr }));
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
async function ensureClaudeCodeVersion(log, pinned = PINNED_CLAUDE_CODE_VERSION, opts) {
|
|
33
|
+
const autoInstall = opts?.allowAutoInstall !== false;
|
|
34
|
+
const current = await readClaudeVersion();
|
|
35
|
+
if (!current) {
|
|
36
|
+
log(`[claude-version] 'claude' not on PATH \u2014 please run the Anthropic installer once: curl -fsSL https://claude.ai/install.sh | sh`);
|
|
37
|
+
return { kind: "not-installed", want: pinned };
|
|
38
|
+
}
|
|
39
|
+
if (current === pinned) {
|
|
40
|
+
log(`[claude-version] OK \u2014 claude ${current} matches pinned ${pinned}`);
|
|
41
|
+
return { kind: "ok", version: current };
|
|
42
|
+
}
|
|
43
|
+
if (!autoInstall) {
|
|
44
|
+
log(`[claude-version] DRIFT \u2014 installed ${current} \u2260 pinned ${pinned} (auto-install disabled)`);
|
|
45
|
+
return { kind: "skipped", reason: `installed=${current} pinned=${pinned}` };
|
|
46
|
+
}
|
|
47
|
+
log(`[claude-version] DRIFT \u2014 installed ${current} \u2260 pinned ${pinned}; running 'claude install ${pinned}'`);
|
|
48
|
+
const { ok, stderr } = await runInstaller(pinned, log);
|
|
49
|
+
if (!ok) {
|
|
50
|
+
log(`[claude-version] install failed for ${pinned}: ${stderr.trim().slice(0, 400)}`);
|
|
51
|
+
return { kind: "install-failed", from: current, want: pinned, error: stderr.slice(0, 400) };
|
|
52
|
+
}
|
|
53
|
+
const after = await readClaudeVersion();
|
|
54
|
+
log(`[claude-version] installer finished; now reports ${after ?? "unknown"}`);
|
|
55
|
+
return { kind: "installed", from: current, to: after ?? pinned };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export { PINNED_CLAUDE_CODE_VERSION, ensureClaudeCodeVersion };
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { m as resolveProjectRoot } from './run-LEPH8aka.mjs';
|
|
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
|
+
import { g as getRun, l as listRuns, r as runWorkflow } from './runStore-CtptN7US.mjs';
|
|
4
|
+
import 'os';
|
|
5
|
+
import 'fs/promises';
|
|
6
|
+
import 'fs';
|
|
7
|
+
import 'path';
|
|
8
|
+
import 'url';
|
|
9
|
+
import 'child_process';
|
|
10
|
+
import 'crypto';
|
|
11
|
+
import 'node:crypto';
|
|
12
|
+
import 'node:fs';
|
|
13
|
+
import 'node:child_process';
|
|
14
|
+
import 'util';
|
|
15
|
+
import 'node:path';
|
|
16
|
+
import 'node:events';
|
|
17
|
+
import 'node:os';
|
|
18
|
+
import '@agentclientprotocol/sdk';
|
|
19
|
+
import '@modelcontextprotocol/sdk/client/index.js';
|
|
20
|
+
import '@modelcontextprotocol/sdk/client/stdio.js';
|
|
21
|
+
import '@modelcontextprotocol/sdk/types.js';
|
|
22
|
+
import 'zod';
|
|
23
|
+
import 'node:fs/promises';
|
|
24
|
+
import 'node:util';
|
|
25
|
+
import 'yaml';
|
|
26
|
+
|
|
27
|
+
async function workflowRpc(cwd, params) {
|
|
28
|
+
const root = resolveProjectRoot(cwd || process.cwd());
|
|
29
|
+
const op = params.op;
|
|
30
|
+
switch (op) {
|
|
31
|
+
case "list":
|
|
32
|
+
return listWorkflows(root);
|
|
33
|
+
case "show": {
|
|
34
|
+
const wf = getWorkflow(root, String(params.name));
|
|
35
|
+
return { meta: wf, yaml: wf ? rawWorkflow(root, String(params.name)) || "" : null };
|
|
36
|
+
}
|
|
37
|
+
case "add": {
|
|
38
|
+
const on = {};
|
|
39
|
+
const crons = Array.isArray(params.cron) ? params.cron.map(String) : params.cron ? [String(params.cron)] : [];
|
|
40
|
+
if (crons.length) on.schedule = crons.map((c) => ({ cron: c }));
|
|
41
|
+
if (params.dispatch || params.workflow_dispatch) on.workflow_dispatch = true;
|
|
42
|
+
if (params.channel) on.channel = String(params.channel);
|
|
43
|
+
if (Array.isArray(params.issue) && params.issue.length) on.issue = params.issue.map(String);
|
|
44
|
+
const runs = Array.isArray(params.runs) ? params.runs.map(String).filter(Boolean) : [];
|
|
45
|
+
if (!params.name || !runs.length) throw new Error("workflow add: name and at least one run step required");
|
|
46
|
+
const wf = {
|
|
47
|
+
name: String(params.name),
|
|
48
|
+
on: Object.keys(on).length ? on : void 0,
|
|
49
|
+
jobs: { run: { steps: runs.map((r) => ({ run: r })) } },
|
|
50
|
+
session: params.session || null
|
|
51
|
+
};
|
|
52
|
+
saveWorkflow(root, wf);
|
|
53
|
+
return wf;
|
|
54
|
+
}
|
|
55
|
+
case "remove":
|
|
56
|
+
return { removed: removeWorkflow(root, String(params.name)) };
|
|
57
|
+
case "enable":
|
|
58
|
+
case "disable": {
|
|
59
|
+
const wf = setWorkflowEnabled(root, String(params.name), op === "enable");
|
|
60
|
+
if (!wf) throw new Error(`Workflow not found: ${params.name}`);
|
|
61
|
+
return wf;
|
|
62
|
+
}
|
|
63
|
+
case "run": {
|
|
64
|
+
const wf = getWorkflow(root, String(params.name));
|
|
65
|
+
if (!wf) throw new Error(`Workflow not found: ${params.name}`);
|
|
66
|
+
const run = await runWorkflow(root, wf, { trigger: "manual", actor: params.actor || params.session || null });
|
|
67
|
+
const out = [`\u25B6 ran workflow "${wf.name}" (${run.steps.length} step${run.steps.length === 1 ? "" : "s"}) \u2192 ${run.status}`];
|
|
68
|
+
for (const s of run.steps) {
|
|
69
|
+
out.push(` [${s.index + 1}] $ ${s.cmd}`);
|
|
70
|
+
if (s.stdout) out.push(s.stdout.trimEnd());
|
|
71
|
+
if (s.stderr) out.push(s.stderr.trimEnd());
|
|
72
|
+
if (s.timedOut) out.push(` \u2717 step ${s.index + 1} timed out.`);
|
|
73
|
+
else if (s.exitCode !== 0) out.push(` \u2717 step ${s.index + 1} failed (exit ${s.exitCode ?? "signal"}).`);
|
|
74
|
+
}
|
|
75
|
+
out.push(run.status === "success" ? `\u2713 workflow "${wf.name}" completed.` : `\u2717 workflow "${wf.name}" failed.`);
|
|
76
|
+
return { ok: run.status === "success", output: out.join("\n"), runId: run.id };
|
|
77
|
+
}
|
|
78
|
+
case "runs": {
|
|
79
|
+
const limit = Number(params.limit) > 0 ? Number(params.limit) : void 0;
|
|
80
|
+
return { runs: listRuns(root, String(params.name), limit) };
|
|
81
|
+
}
|
|
82
|
+
case "run-detail": {
|
|
83
|
+
const run = getRun(root, String(params.name), String(params.runId));
|
|
84
|
+
if (!run) throw new Error(`Run not found: ${params.name}/${params.runId}`);
|
|
85
|
+
return run;
|
|
86
|
+
}
|
|
87
|
+
default:
|
|
88
|
+
throw new Error(`workflow rpc: unknown op "${op}"`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export { workflowRpc };
|
|
@@ -0,0 +1,194 @@
|
|
|
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-LEPH8aka.mjs';
|
|
2
|
+
import 'os';
|
|
3
|
+
import 'fs/promises';
|
|
4
|
+
import 'fs';
|
|
5
|
+
import 'path';
|
|
6
|
+
import 'url';
|
|
7
|
+
import 'child_process';
|
|
8
|
+
import 'crypto';
|
|
9
|
+
import 'node:crypto';
|
|
10
|
+
import 'node:fs';
|
|
11
|
+
import 'node:child_process';
|
|
12
|
+
import 'util';
|
|
13
|
+
import 'node:path';
|
|
14
|
+
import 'node:events';
|
|
15
|
+
import 'node:os';
|
|
16
|
+
import '@agentclientprotocol/sdk';
|
|
17
|
+
import '@modelcontextprotocol/sdk/client/index.js';
|
|
18
|
+
import '@modelcontextprotocol/sdk/client/stdio.js';
|
|
19
|
+
import '@modelcontextprotocol/sdk/types.js';
|
|
20
|
+
import 'zod';
|
|
21
|
+
import 'node:fs/promises';
|
|
22
|
+
import 'node:util';
|
|
23
|
+
|
|
24
|
+
function followUpCount(body) {
|
|
25
|
+
if (!body) return 0;
|
|
26
|
+
return (body.match(/\*\*Follow-up/g) || []).length;
|
|
27
|
+
}
|
|
28
|
+
function notifyOwnerOnFollowUp(issue, text, author, deps) {
|
|
29
|
+
if (!deps.notifySession) return;
|
|
30
|
+
if (!issue || !text.trim()) return;
|
|
31
|
+
const owner = issue.session;
|
|
32
|
+
if (!owner) return;
|
|
33
|
+
if (issue.status === "in_progress") return;
|
|
34
|
+
if (author && author === owner) return;
|
|
35
|
+
deps.notifySession(
|
|
36
|
+
owner,
|
|
37
|
+
`User added a follow-up (comment ${followUpCount(issue.body)}) to issue #${issue.id} \u2014 triage the change and decide: reopen+work, or leave closed.`
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
function compact(i) {
|
|
41
|
+
const { body, original, ...rest } = i;
|
|
42
|
+
return rest;
|
|
43
|
+
}
|
|
44
|
+
function buildVerify(p) {
|
|
45
|
+
if (p.verifyCmd) return { type: "command", text: String(p.verifyCmd) };
|
|
46
|
+
if (p.verify) return { type: "agent", text: String(p.verify) };
|
|
47
|
+
if (p.manual) return { type: "manual" };
|
|
48
|
+
if (p.noVerify) return null;
|
|
49
|
+
return void 0;
|
|
50
|
+
}
|
|
51
|
+
function ownerScoped(items, session) {
|
|
52
|
+
if (!session) return items;
|
|
53
|
+
return items.filter((i) => isVisibleTo(i, session));
|
|
54
|
+
}
|
|
55
|
+
const STATUS_MAP = {
|
|
56
|
+
ready: "ready",
|
|
57
|
+
start: "in_progress",
|
|
58
|
+
close: "archived",
|
|
59
|
+
done: "archived",
|
|
60
|
+
reopen: "ready",
|
|
61
|
+
archive: "archived",
|
|
62
|
+
backlog: "ready"
|
|
63
|
+
};
|
|
64
|
+
function issueRpc(cwd, params, deps = {}) {
|
|
65
|
+
const root = resolveProjectRoot(cwd || process.cwd());
|
|
66
|
+
const op = params.op;
|
|
67
|
+
switch (op) {
|
|
68
|
+
case "list": {
|
|
69
|
+
const opts = { includeArchived: params.status === "all" || params.status === "archived" || params.includeArchived };
|
|
70
|
+
if (params.status && params.status !== "all") opts.status = params.status;
|
|
71
|
+
if (params.label) opts.label = params.label;
|
|
72
|
+
if (params.scope) opts.scope = params.scope;
|
|
73
|
+
return ownerScoped(listIssues(root, opts), params.session).map(compact);
|
|
74
|
+
}
|
|
75
|
+
case "show":
|
|
76
|
+
return getIssue(root, String(params.id));
|
|
77
|
+
case "search":
|
|
78
|
+
return ownerScoped(searchIssues(root, String(params.query || "")), params.session).map(compact);
|
|
79
|
+
case "pending": {
|
|
80
|
+
const items = ownerScoped(listIssues(root), params.session).filter((i) => i.status === "ready" || i.status === "in_progress");
|
|
81
|
+
return { pending: items.map((i) => i.id), count: items.length };
|
|
82
|
+
}
|
|
83
|
+
case "add": {
|
|
84
|
+
const owner = params.session || null;
|
|
85
|
+
const scope = params.scope || (owner ? "session" : "project");
|
|
86
|
+
let title = params.title ? String(params.title) : "";
|
|
87
|
+
let body = params.body ? String(params.body) : void 0;
|
|
88
|
+
let original;
|
|
89
|
+
if (!title) {
|
|
90
|
+
const src = (body || "").trim();
|
|
91
|
+
if (!src) throw new Error("issue add: title or body required");
|
|
92
|
+
const nl = src.indexOf("\n");
|
|
93
|
+
title = (nl === -1 ? src : src.slice(0, nl)).trim().slice(0, 200);
|
|
94
|
+
original = src;
|
|
95
|
+
body = void 0;
|
|
96
|
+
}
|
|
97
|
+
const created = addIssue(root, {
|
|
98
|
+
title,
|
|
99
|
+
status: "ready",
|
|
100
|
+
scope,
|
|
101
|
+
labels: Array.isArray(params.labels) ? params.labels.map(String) : [],
|
|
102
|
+
verify: buildVerify(params) ?? null,
|
|
103
|
+
session: scope === "session" ? owner : null,
|
|
104
|
+
// Record the creating session as the owner (#0099) so a project issue stays
|
|
105
|
+
// visible to its creator/parent (and the "all" view) but doesn't leak into
|
|
106
|
+
// unrelated parallel sessions. Null owner (no session) → globally shared.
|
|
107
|
+
owner,
|
|
108
|
+
original,
|
|
109
|
+
body
|
|
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;
|
|
116
|
+
}
|
|
117
|
+
case "comment": {
|
|
118
|
+
const text = String(params.text || "");
|
|
119
|
+
const updated = addComment(root, String(params.id), text);
|
|
120
|
+
notifyOwnerOnFollowUp(updated, text, params.session || null, deps);
|
|
121
|
+
return updated;
|
|
122
|
+
}
|
|
123
|
+
case "pause": {
|
|
124
|
+
const question = params.question ? { text: String(params.question), options: Array.isArray(params.options) ? params.options.map(String) : [] } : void 0;
|
|
125
|
+
const updated = pauseIssue(root, String(params.id), question);
|
|
126
|
+
if (!updated) throw new Error(`Issue not found: ${params.id}`);
|
|
127
|
+
if (question) notifyOwnerOnFollowUp(updated, `needs your input: ${question.text}`, params.session || null, deps);
|
|
128
|
+
return updated;
|
|
129
|
+
}
|
|
130
|
+
case "resume": {
|
|
131
|
+
const updated = resumeIssue(root, String(params.id), params.answer ? String(params.answer) : void 0);
|
|
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));
|
|
135
|
+
return updated;
|
|
136
|
+
}
|
|
137
|
+
case "status": {
|
|
138
|
+
const status = STATUS_MAP[params.status];
|
|
139
|
+
if (!status) throw new Error(`issue status: unknown status "${params.status}"`);
|
|
140
|
+
const patch = { status };
|
|
141
|
+
if (status === "in_progress" && params.session) {
|
|
142
|
+
const cur = getIssue(root, String(params.id));
|
|
143
|
+
if (cur && cur.scope === "project" && !cur.session) patch.session = params.session;
|
|
144
|
+
}
|
|
145
|
+
const updated = updateIssue(root, String(params.id), patch);
|
|
146
|
+
if (!updated) throw new Error(`Issue not found: ${params.id}`);
|
|
147
|
+
return updated;
|
|
148
|
+
}
|
|
149
|
+
case "work": {
|
|
150
|
+
const patch = { status: "in_progress", answer: null };
|
|
151
|
+
if (params.branch) patch.branch = String(params.branch);
|
|
152
|
+
const worker = params.session || null;
|
|
153
|
+
const cur = getIssue(root, String(params.id));
|
|
154
|
+
if (worker && cur && cur.scope === "project" && !cur.session) patch.session = worker;
|
|
155
|
+
const updated = updateIssue(root, String(params.id), patch);
|
|
156
|
+
if (!updated) throw new Error(`Issue not found: ${params.id}`);
|
|
157
|
+
return updated;
|
|
158
|
+
}
|
|
159
|
+
case "edit": {
|
|
160
|
+
const patch = {};
|
|
161
|
+
if (params.title != null) patch.title = String(params.title);
|
|
162
|
+
if (Array.isArray(params.labels)) patch.labels = params.labels.map(String);
|
|
163
|
+
const v = buildVerify(params);
|
|
164
|
+
if (v !== void 0) patch.verify = v;
|
|
165
|
+
if (params.scope) patch.scope = params.scope;
|
|
166
|
+
if (params.unclaim) patch.session = null;
|
|
167
|
+
else if (params.session != null) patch.session = String(params.session);
|
|
168
|
+
if (params.body != null) patch.body = String(params.body);
|
|
169
|
+
if (params.status) patch.status = params.status;
|
|
170
|
+
if (params.disposition) patch.disposition = params.disposition === "crew" ? "crew" : "inline";
|
|
171
|
+
if (params.triaged) patch.triaged = true;
|
|
172
|
+
const updated = updateIssue(root, String(params.id), patch);
|
|
173
|
+
if (!updated) throw new Error(`Issue not found: ${params.id}`);
|
|
174
|
+
return updated;
|
|
175
|
+
}
|
|
176
|
+
case "triage": {
|
|
177
|
+
const patch = { triaged: true };
|
|
178
|
+
if (params.title != null) patch.title = String(params.title);
|
|
179
|
+
if (Array.isArray(params.labels) && params.labels.length) patch.labels = params.labels.map(String);
|
|
180
|
+
if (params.disposition) patch.disposition = params.disposition === "crew" ? "crew" : "inline";
|
|
181
|
+
const v = buildVerify(params);
|
|
182
|
+
if (v) patch.verify = v;
|
|
183
|
+
if (params.body != null) patch.body = String(params.body);
|
|
184
|
+
patch.status = "ready";
|
|
185
|
+
const updated = updateIssue(root, String(params.id), patch);
|
|
186
|
+
if (!updated) throw new Error(`Issue not found: ${params.id}`);
|
|
187
|
+
return updated;
|
|
188
|
+
}
|
|
189
|
+
default:
|
|
190
|
+
throw new Error(`issue rpc: unknown op "${op}"`);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export { issueRpc };
|