svamp-cli 0.2.143 → 0.2.145
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--pVW6oMC.mjs → agentCommands-A88RBPcw.mjs} +29 -19
- package/dist/{auth-kWcPeIWV.mjs → auth-PeW_vYYq.mjs} +1 -1
- package/dist/cli.mjs +62 -58
- package/dist/{commands-g6ked7YY.mjs → commands-C32pZOjP.mjs} +2 -2
- package/dist/{commands-YFns4NO9.mjs → commands-CQq9IPHT.mjs} +5 -5
- package/dist/{commands-DNTaAEcq.mjs → commands-Ch1QWOw5.mjs} +36 -22
- package/dist/commands-CnTCySqf.mjs +396 -0
- package/dist/{commands-6ko-4UCh.mjs → commands-DCnmdwyA.mjs} +2 -2
- package/dist/{commands-CGGPr3Uk.mjs → commands-DEsTyvId.mjs} +2 -2
- package/dist/{commands-BCFcd3e3.mjs → commands-vRj1CJJw.mjs} +1 -1
- package/dist/{fleet-DmElRgoe.mjs → fleet-DcEzZjXK.mjs} +1 -1
- package/dist/{frpc-Co_GG6Hr.mjs → frpc-MevmUvAf.mjs} +1 -1
- package/dist/{headlessCli-BkaYb9hu.mjs → headlessCli-C6LHBoWj.mjs} +2 -2
- package/dist/index.mjs +1 -1
- package/dist/{package-rxhXqgC8.mjs → package-CVMv1Bcz.mjs} +2 -2
- package/dist/{run-DsuM6onp.mjs → run-C_xwiN7C.mjs} +80 -14
- package/dist/{run-CqNMlJ7e.mjs → run-DeQmHou8.mjs} +1 -1
- package/dist/{serveCommands-D2LMQxmz.mjs → serveCommands-CT8FkNVX.mjs} +5 -5
- package/dist/{serveManager-CKpIYSav.mjs → serveManager-CK5APPYi.mjs} +2 -2
- package/dist/{sideband-C2OWGzaU.mjs → sideband-xxUkkrOq.mjs} +1 -1
- package/package.json +2 -2
|
@@ -2,7 +2,7 @@ import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
|
2
2
|
import { execSync } from 'node:child_process';
|
|
3
3
|
import { basename, resolve, join, isAbsolute } from 'node:path';
|
|
4
4
|
import os from 'node:os';
|
|
5
|
-
import { I as formatHandle, J as normalizeAllowedUser, K as loadSecurityContextConfig, L as resolveSecurityContext, M as buildSecurityContextFromFlags, N as mergeSecurityContexts, c as connectToHypha, O as buildSessionShareUrl, P as validateChecklist, Q as computeOutboundHop, m as shortId, T as buildMachineShareUrl, U as summarize, V as newItem, W as parseHandle, X as handleMatchesMetadata } from './run-
|
|
5
|
+
import { I as formatHandle, J as normalizeAllowedUser, K as loadSecurityContextConfig, L as resolveSecurityContext, M as buildSecurityContextFromFlags, N as mergeSecurityContexts, c as connectToHypha, O as buildSessionShareUrl, P as validateChecklist, Q as computeOutboundHop, m as shortId, T as buildMachineShareUrl, U as summarize, V as newItem, W as parseHandle, X as handleMatchesMetadata } from './run-C_xwiN7C.mjs';
|
|
6
6
|
import 'os';
|
|
7
7
|
import 'fs/promises';
|
|
8
8
|
import 'fs';
|
|
@@ -2729,36 +2729,50 @@ async function sessionInboxReply(sessionIdPartial, messageId, body, machineId) {
|
|
|
2729
2729
|
console.error(`Message ${messageId} not found in inbox.`);
|
|
2730
2730
|
process.exit(1);
|
|
2731
2731
|
}
|
|
2732
|
+
let channelDelivered = false;
|
|
2732
2733
|
if (original.channelId && original.correlationId) {
|
|
2733
2734
|
const rr = await machine.sessionRPC(fullId, "channelReply", { params: { channel: original.channelId, correlationId: original.correlationId, to: original.from, body } });
|
|
2734
2735
|
if (rr?.error) {
|
|
2735
|
-
|
|
2736
|
-
|
|
2736
|
+
if (!original.fromSession) {
|
|
2737
|
+
console.error(`Channel reply failed: ${rr.error}`);
|
|
2738
|
+
process.exit(1);
|
|
2739
|
+
}
|
|
2740
|
+
} else {
|
|
2741
|
+
channelDelivered = true;
|
|
2742
|
+
console.log(`Reply queued to "${original.from}" on channel ${original.channelId} (correlation ${original.correlationId}).`);
|
|
2743
|
+
}
|
|
2744
|
+
}
|
|
2745
|
+
if (original.fromSession) {
|
|
2746
|
+
try {
|
|
2747
|
+
const hop = computeOutboundHop(process.env.SVAMP_SESSION_ID || fullId);
|
|
2748
|
+
const reply = {
|
|
2749
|
+
messageId: shortId(),
|
|
2750
|
+
body,
|
|
2751
|
+
timestamp: Date.now(),
|
|
2752
|
+
read: false,
|
|
2753
|
+
from: process.env.SVAMP_SESSION_HANDLE || `session:${fullId}`,
|
|
2754
|
+
fromSession: fullId,
|
|
2755
|
+
to: original.fromSession,
|
|
2756
|
+
subject: original.subject ? `Re: ${original.subject}` : void 0,
|
|
2757
|
+
urgency: "normal",
|
|
2758
|
+
hopCount: hop.hopCount,
|
|
2759
|
+
replyTo: original.messageId,
|
|
2760
|
+
threadId: original.threadId || original.messageId
|
|
2761
|
+
};
|
|
2762
|
+
const sendResult = await machine.sessionRPC(original.fromSession, "sendInboxMessage", { message: reply });
|
|
2763
|
+
console.log(`Reply sent to session ${original.fromSession.slice(0, 8)} (id: ${sendResult.messageId.slice(0, 8)})`);
|
|
2764
|
+
} catch (err) {
|
|
2765
|
+
if (!channelDelivered) {
|
|
2766
|
+
console.error(`Reply failed: ${err?.message || err}`);
|
|
2767
|
+
process.exit(1);
|
|
2768
|
+
}
|
|
2737
2769
|
}
|
|
2738
|
-
console.log(`Reply queued to "${original.from}" on channel ${original.channelId} (correlation ${original.correlationId}).`);
|
|
2739
2770
|
return;
|
|
2740
2771
|
}
|
|
2741
|
-
if (!
|
|
2772
|
+
if (!channelDelivered) {
|
|
2742
2773
|
console.error("Cannot reply: original message has no fromSession (and not a channel message).");
|
|
2743
2774
|
process.exit(1);
|
|
2744
2775
|
}
|
|
2745
|
-
const hop = computeOutboundHop(process.env.SVAMP_SESSION_ID || fullId);
|
|
2746
|
-
const reply = {
|
|
2747
|
-
messageId: shortId(),
|
|
2748
|
-
body,
|
|
2749
|
-
timestamp: Date.now(),
|
|
2750
|
-
read: false,
|
|
2751
|
-
from: process.env.SVAMP_SESSION_HANDLE || `session:${fullId}`,
|
|
2752
|
-
fromSession: fullId,
|
|
2753
|
-
to: original.fromSession,
|
|
2754
|
-
subject: original.subject ? `Re: ${original.subject}` : void 0,
|
|
2755
|
-
urgency: "normal",
|
|
2756
|
-
hopCount: hop.hopCount,
|
|
2757
|
-
replyTo: original.messageId,
|
|
2758
|
-
threadId: original.threadId || original.messageId
|
|
2759
|
-
};
|
|
2760
|
-
const sendResult = await machine.sessionRPC(original.fromSession, "sendInboxMessage", { message: reply });
|
|
2761
|
-
console.log(`Reply sent to session ${original.fromSession.slice(0, 8)} (id: ${sendResult.messageId.slice(0, 8)})`);
|
|
2762
2776
|
} finally {
|
|
2763
2777
|
await server.disconnect();
|
|
2764
2778
|
}
|
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
import { existsSync, readFileSync, unlinkSync, mkdirSync, writeFileSync, renameSync, readdirSync } from 'node:fs';
|
|
2
|
+
import { join, dirname } from 'node:path';
|
|
3
|
+
import { execFileSync } from 'node:child_process';
|
|
4
|
+
|
|
5
|
+
const FIELD_ORDER = ["id", "title", "status", "scope", "labels", "verify", "branch", "session", "created", "closed"];
|
|
6
|
+
function resolveProjectRoot(start = process.cwd()) {
|
|
7
|
+
let dir = start;
|
|
8
|
+
for (let i = 0; i < 40; i++) {
|
|
9
|
+
if (existsSync(join(dir, ".git")) || existsSync(join(dir, ".svamp"))) return dir;
|
|
10
|
+
const parent = dirname(dir);
|
|
11
|
+
if (parent === dir) break;
|
|
12
|
+
dir = parent;
|
|
13
|
+
}
|
|
14
|
+
return start;
|
|
15
|
+
}
|
|
16
|
+
function issuesDir(projectRoot) {
|
|
17
|
+
return join(projectRoot, ".svamp", "issues");
|
|
18
|
+
}
|
|
19
|
+
function archiveDir(projectRoot) {
|
|
20
|
+
return join(issuesDir(projectRoot), "archive");
|
|
21
|
+
}
|
|
22
|
+
function issuePath(projectRoot, id, archived = false) {
|
|
23
|
+
return join(archived ? archiveDir(projectRoot) : issuesDir(projectRoot), `${id}.md`);
|
|
24
|
+
}
|
|
25
|
+
function serializeIssue(issue) {
|
|
26
|
+
const lines = ["---"];
|
|
27
|
+
for (const k of FIELD_ORDER) {
|
|
28
|
+
const v = issue[k];
|
|
29
|
+
if (v === void 0) continue;
|
|
30
|
+
lines.push(`${k}: ${JSON.stringify(v)}`);
|
|
31
|
+
}
|
|
32
|
+
lines.push("---", "");
|
|
33
|
+
return lines.join("\n") + (issue.body ? issue.body.replace(/\s+$/, "") + "\n" : "");
|
|
34
|
+
}
|
|
35
|
+
function parseIssue(content) {
|
|
36
|
+
const m = content.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
|
|
37
|
+
if (!m) return null;
|
|
38
|
+
const fm = {};
|
|
39
|
+
for (const line of m[1].split("\n")) {
|
|
40
|
+
const idx = line.indexOf(": ");
|
|
41
|
+
if (idx === -1) continue;
|
|
42
|
+
const key = line.slice(0, idx).trim();
|
|
43
|
+
const raw = line.slice(idx + 2).trim();
|
|
44
|
+
try {
|
|
45
|
+
fm[key] = JSON.parse(raw);
|
|
46
|
+
} catch {
|
|
47
|
+
fm[key] = raw;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (!fm.id) return null;
|
|
51
|
+
return {
|
|
52
|
+
id: String(fm.id),
|
|
53
|
+
title: String(fm.title ?? ""),
|
|
54
|
+
status: fm.status ?? "backlog",
|
|
55
|
+
scope: fm.scope ?? "session",
|
|
56
|
+
labels: Array.isArray(fm.labels) ? fm.labels.map(String) : [],
|
|
57
|
+
verify: fm.verify ?? null,
|
|
58
|
+
branch: fm.branch ?? null,
|
|
59
|
+
session: fm.session ?? null,
|
|
60
|
+
created: String(fm.created ?? (/* @__PURE__ */ new Date()).toISOString()),
|
|
61
|
+
closed: fm.closed ?? null,
|
|
62
|
+
body: (m[2] || "").trim() || void 0
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function readDir(dir) {
|
|
66
|
+
if (!existsSync(dir)) return [];
|
|
67
|
+
const out = [];
|
|
68
|
+
for (const name of readdirSync(dir)) {
|
|
69
|
+
if (!name.endsWith(".md")) continue;
|
|
70
|
+
try {
|
|
71
|
+
const issue = parseIssue(readFileSync(join(dir, name), "utf-8"));
|
|
72
|
+
if (issue) out.push(issue);
|
|
73
|
+
} catch {
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return out;
|
|
77
|
+
}
|
|
78
|
+
function listIssues(projectRoot, opts = {}) {
|
|
79
|
+
let items = readDir(issuesDir(projectRoot));
|
|
80
|
+
if (opts.includeArchived) items = items.concat(readDir(archiveDir(projectRoot)));
|
|
81
|
+
if (opts.status) items = items.filter((i) => i.status === opts.status);
|
|
82
|
+
if (opts.label) items = items.filter((i) => i.labels.includes(opts.label));
|
|
83
|
+
if (opts.scope) items = items.filter((i) => i.scope === opts.scope);
|
|
84
|
+
return items.sort((a, b) => Number(a.id) - Number(b.id));
|
|
85
|
+
}
|
|
86
|
+
function getIssue(projectRoot, id) {
|
|
87
|
+
const padded = /^\d+$/.test(id) ? id.padStart(4, "0") : id;
|
|
88
|
+
for (const p of [issuePath(projectRoot, padded), issuePath(projectRoot, padded, true)]) {
|
|
89
|
+
if (existsSync(p)) {
|
|
90
|
+
try {
|
|
91
|
+
return parseIssue(readFileSync(p, "utf-8"));
|
|
92
|
+
} catch {
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
function atomicWrite(path, content) {
|
|
100
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
101
|
+
const tmp = `${path}.tmp-${process.pid}`;
|
|
102
|
+
writeFileSync(tmp, content);
|
|
103
|
+
renameSync(tmp, path);
|
|
104
|
+
}
|
|
105
|
+
function nextId(projectRoot) {
|
|
106
|
+
const all = listIssues(projectRoot, { includeArchived: true });
|
|
107
|
+
const max = all.reduce((acc, i) => Math.max(acc, Number(i.id) || 0), 0);
|
|
108
|
+
return String(max + 1).padStart(4, "0");
|
|
109
|
+
}
|
|
110
|
+
function addIssue(projectRoot, fields) {
|
|
111
|
+
const issue = {
|
|
112
|
+
id: nextId(projectRoot),
|
|
113
|
+
title: fields.title.trim(),
|
|
114
|
+
status: fields.status ?? "backlog",
|
|
115
|
+
scope: fields.scope ?? "session",
|
|
116
|
+
labels: fields.labels ?? [],
|
|
117
|
+
verify: fields.verify ?? null,
|
|
118
|
+
branch: null,
|
|
119
|
+
session: fields.session ?? null,
|
|
120
|
+
created: (/* @__PURE__ */ new Date()).toISOString(),
|
|
121
|
+
closed: null,
|
|
122
|
+
body: fields.body
|
|
123
|
+
};
|
|
124
|
+
atomicWrite(issuePath(projectRoot, issue.id), serializeIssue(issue));
|
|
125
|
+
return issue;
|
|
126
|
+
}
|
|
127
|
+
function updateIssue(projectRoot, id, patch) {
|
|
128
|
+
const cur = getIssue(projectRoot, id);
|
|
129
|
+
if (!cur) return null;
|
|
130
|
+
const wasArchived = cur.status === "archived";
|
|
131
|
+
const next = { ...cur, ...patch, id: cur.id };
|
|
132
|
+
const nowArchived = next.status === "archived";
|
|
133
|
+
if ((next.status === "done" || nowArchived) && !next.closed) next.closed = (/* @__PURE__ */ new Date()).toISOString();
|
|
134
|
+
if (next.status !== "done" && !nowArchived) next.closed = null;
|
|
135
|
+
atomicWrite(issuePath(projectRoot, next.id, nowArchived), serializeIssue(next));
|
|
136
|
+
if (wasArchived !== nowArchived) {
|
|
137
|
+
const oldPath = issuePath(projectRoot, cur.id, wasArchived);
|
|
138
|
+
try {
|
|
139
|
+
if (existsSync(oldPath)) unlinkSync(oldPath);
|
|
140
|
+
} catch {
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return next;
|
|
144
|
+
}
|
|
145
|
+
function addComment(projectRoot, id, text) {
|
|
146
|
+
const cur = getIssue(projectRoot, id);
|
|
147
|
+
if (!cur || !text.trim()) return cur;
|
|
148
|
+
const entry = `
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
**Follow-up \xB7 ${(/* @__PURE__ */ new Date()).toISOString()}**
|
|
152
|
+
|
|
153
|
+
${text.trim()}`;
|
|
154
|
+
const body = (cur.body ? cur.body.replace(/\s+$/, "") : "") + entry;
|
|
155
|
+
return updateIssue(projectRoot, id, { body });
|
|
156
|
+
}
|
|
157
|
+
function searchIssues(projectRoot, query) {
|
|
158
|
+
const q = query.trim();
|
|
159
|
+
if (!q) return [];
|
|
160
|
+
try {
|
|
161
|
+
const out = execFileSync("rg", ["-l", "-i", "--no-messages", q, issuesDir(projectRoot)], { encoding: "utf-8" });
|
|
162
|
+
const files = out.split("\n").filter(Boolean);
|
|
163
|
+
const issues = [];
|
|
164
|
+
for (const f of files) {
|
|
165
|
+
try {
|
|
166
|
+
const i = parseIssue(readFileSync(f, "utf-8"));
|
|
167
|
+
if (i) issues.push(i);
|
|
168
|
+
} catch {
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return issues.sort((a, b) => Number(a.id) - Number(b.id));
|
|
172
|
+
} catch {
|
|
173
|
+
const ql = q.toLowerCase();
|
|
174
|
+
return listIssues(projectRoot, { includeArchived: true }).filter((i) => i.title.toLowerCase().includes(ql) || (i.body || "").toLowerCase().includes(ql) || i.labels.some((l) => l.toLowerCase().includes(ql)));
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
function summarize(issues) {
|
|
178
|
+
const by = (s) => issues.filter((i) => i.status === s).length;
|
|
179
|
+
return { total: issues.length, backlog: by("backlog"), ready: by("ready"), in_progress: by("in_progress"), done: by("done"), archived: by("archived") };
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const STATUS_GLYPH = {
|
|
183
|
+
backlog: "\u25CB",
|
|
184
|
+
ready: "\u25C9",
|
|
185
|
+
in_progress: "\u25D0",
|
|
186
|
+
done: "\u2713",
|
|
187
|
+
archived: "\u25A3"
|
|
188
|
+
};
|
|
189
|
+
function flag(args, name) {
|
|
190
|
+
const i = args.indexOf(name);
|
|
191
|
+
return i !== -1 && i + 1 < args.length ? args[i + 1] : void 0;
|
|
192
|
+
}
|
|
193
|
+
function has(args, name) {
|
|
194
|
+
return args.includes(name);
|
|
195
|
+
}
|
|
196
|
+
function positional(args) {
|
|
197
|
+
const out = [];
|
|
198
|
+
for (let i = 0; i < args.length; i++) {
|
|
199
|
+
const a = args[i];
|
|
200
|
+
if (a.startsWith("--")) {
|
|
201
|
+
if (a !== "--json" && a !== "--ready") i++;
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
out.push(a);
|
|
205
|
+
}
|
|
206
|
+
return out;
|
|
207
|
+
}
|
|
208
|
+
function fmtIssue(i) {
|
|
209
|
+
const label = i.labels.length ? ` [${i.labels.join(", ")}]` : "";
|
|
210
|
+
const v = i.verify ? ` (verify:${i.verify.type})` : "";
|
|
211
|
+
const br = i.branch ? ` {branch:${i.branch}}` : "";
|
|
212
|
+
return `#${i.id} ${STATUS_GLYPH[i.status]} ${i.title}${label}${v}${br}`;
|
|
213
|
+
}
|
|
214
|
+
function buildVerify(args) {
|
|
215
|
+
const cmd = flag(args, "--verify-cmd");
|
|
216
|
+
if (cmd) return { type: "command", text: cmd };
|
|
217
|
+
const agent = flag(args, "--verify");
|
|
218
|
+
if (agent) return { type: "agent", text: agent };
|
|
219
|
+
if (has(args, "--manual")) return { type: "manual" };
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
222
|
+
async function issueCommand(args) {
|
|
223
|
+
const sub = args[0];
|
|
224
|
+
const rest = args.slice(1);
|
|
225
|
+
const root = resolveProjectRoot();
|
|
226
|
+
const json = has(args, "--json");
|
|
227
|
+
const sessionId = process.env.SVAMP_SESSION_ID || null;
|
|
228
|
+
const out = (text) => console.log(text);
|
|
229
|
+
const ok = (obj, text) => {
|
|
230
|
+
if (json) console.log(JSON.stringify(obj));
|
|
231
|
+
else out(text);
|
|
232
|
+
};
|
|
233
|
+
switch (sub) {
|
|
234
|
+
case "add": {
|
|
235
|
+
const title = positional(rest)[0];
|
|
236
|
+
if (!title) {
|
|
237
|
+
console.error('usage: svamp issue add "<title>" [--ready] [--label x] [--verify-cmd "npm test"] [--scope project|session] [--body "\u2026"]');
|
|
238
|
+
process.exit(1);
|
|
239
|
+
}
|
|
240
|
+
const labels = rest.filter((a, idx) => rest[idx - 1] === "--label");
|
|
241
|
+
const scope = flag(rest, "--scope") || (sessionId ? "session" : "project");
|
|
242
|
+
const issue = addIssue(root, {
|
|
243
|
+
title,
|
|
244
|
+
status: has(rest, "--ready") ? "ready" : "backlog",
|
|
245
|
+
scope,
|
|
246
|
+
labels,
|
|
247
|
+
verify: buildVerify(rest),
|
|
248
|
+
session: scope === "session" ? sessionId : null,
|
|
249
|
+
body: flag(rest, "--body")
|
|
250
|
+
});
|
|
251
|
+
ok(issue, `Created #${issue.id} (${issue.status}): ${issue.title}`);
|
|
252
|
+
break;
|
|
253
|
+
}
|
|
254
|
+
case "list":
|
|
255
|
+
case "ls": {
|
|
256
|
+
const status = flag(rest, "--status");
|
|
257
|
+
const opts = { includeArchived: status === "all" || status === "archived" || has(rest, "--all") };
|
|
258
|
+
if (status && status !== "all") opts.status = status;
|
|
259
|
+
if (flag(rest, "--label")) opts.label = flag(rest, "--label");
|
|
260
|
+
if (flag(rest, "--scope")) opts.scope = flag(rest, "--scope");
|
|
261
|
+
const items = listIssues(root, opts);
|
|
262
|
+
if (json) {
|
|
263
|
+
console.log(JSON.stringify(items));
|
|
264
|
+
break;
|
|
265
|
+
}
|
|
266
|
+
if (!items.length) {
|
|
267
|
+
out("No issues.");
|
|
268
|
+
break;
|
|
269
|
+
}
|
|
270
|
+
for (const i of items) out(fmtIssue(i));
|
|
271
|
+
const s = summarize(listIssues(root, { includeArchived: true }));
|
|
272
|
+
out(`
|
|
273
|
+
${s.ready} ready \xB7 ${s.in_progress} in-progress \xB7 ${s.backlog} backlog \xB7 ${s.done} done \xB7 ${s.archived} archived`);
|
|
274
|
+
break;
|
|
275
|
+
}
|
|
276
|
+
case "show": {
|
|
277
|
+
const id = positional(rest)[0];
|
|
278
|
+
const issue = id ? getIssue(root, id) : null;
|
|
279
|
+
if (!issue) {
|
|
280
|
+
console.error(`Issue not found: ${id}`);
|
|
281
|
+
process.exit(1);
|
|
282
|
+
}
|
|
283
|
+
if (json) {
|
|
284
|
+
console.log(JSON.stringify(issue));
|
|
285
|
+
break;
|
|
286
|
+
}
|
|
287
|
+
out(fmtIssue(issue));
|
|
288
|
+
out(`status: ${issue.status} \xB7 scope: ${issue.scope} \xB7 created: ${issue.created}${issue.closed ? ` \xB7 closed: ${issue.closed}` : ""}`);
|
|
289
|
+
if (issue.body) out(`
|
|
290
|
+
${issue.body}`);
|
|
291
|
+
break;
|
|
292
|
+
}
|
|
293
|
+
case "ready":
|
|
294
|
+
case "start":
|
|
295
|
+
case "close":
|
|
296
|
+
case "done":
|
|
297
|
+
case "reopen":
|
|
298
|
+
case "archive":
|
|
299
|
+
case "backlog": {
|
|
300
|
+
const id = positional(rest)[0];
|
|
301
|
+
if (!id) {
|
|
302
|
+
console.error(`usage: svamp issue ${sub} <id>`);
|
|
303
|
+
process.exit(1);
|
|
304
|
+
}
|
|
305
|
+
const map = {
|
|
306
|
+
ready: "ready",
|
|
307
|
+
start: "in_progress",
|
|
308
|
+
close: "done",
|
|
309
|
+
done: "done",
|
|
310
|
+
reopen: "ready",
|
|
311
|
+
archive: "archived",
|
|
312
|
+
backlog: "backlog"
|
|
313
|
+
};
|
|
314
|
+
const updated = updateIssue(root, id, { status: map[sub] });
|
|
315
|
+
if (!updated) {
|
|
316
|
+
console.error(`Issue not found: ${id}`);
|
|
317
|
+
process.exit(1);
|
|
318
|
+
}
|
|
319
|
+
ok(updated, `#${updated.id} \u2192 ${updated.status}: ${updated.title}`);
|
|
320
|
+
break;
|
|
321
|
+
}
|
|
322
|
+
case "edit": {
|
|
323
|
+
const id = positional(rest)[0];
|
|
324
|
+
if (!id) {
|
|
325
|
+
console.error("usage: svamp issue edit <id> [--title \u2026] [--label x] [--verify-cmd \u2026] [--scope \u2026] [--body \u2026]");
|
|
326
|
+
process.exit(1);
|
|
327
|
+
}
|
|
328
|
+
const patch = {};
|
|
329
|
+
if (flag(rest, "--title")) patch.title = flag(rest, "--title");
|
|
330
|
+
const labels = rest.filter((a, idx) => rest[idx - 1] === "--label");
|
|
331
|
+
if (labels.length) patch.labels = labels;
|
|
332
|
+
const v = buildVerify(rest);
|
|
333
|
+
if (v || has(rest, "--no-verify")) patch.verify = has(rest, "--no-verify") ? null : v;
|
|
334
|
+
if (flag(rest, "--scope")) patch.scope = flag(rest, "--scope");
|
|
335
|
+
if (flag(rest, "--body")) patch.body = flag(rest, "--body");
|
|
336
|
+
if (flag(rest, "--status")) patch.status = flag(rest, "--status");
|
|
337
|
+
const updated = updateIssue(root, id, patch);
|
|
338
|
+
if (!updated) {
|
|
339
|
+
console.error(`Issue not found: ${id}`);
|
|
340
|
+
process.exit(1);
|
|
341
|
+
}
|
|
342
|
+
ok(updated, `Updated #${updated.id}: ${updated.title}`);
|
|
343
|
+
break;
|
|
344
|
+
}
|
|
345
|
+
case "comment": {
|
|
346
|
+
const id = positional(rest)[0];
|
|
347
|
+
const text = positional(rest)[1];
|
|
348
|
+
if (!id || !text) {
|
|
349
|
+
console.error('usage: svamp issue comment <id> "<text>"');
|
|
350
|
+
process.exit(1);
|
|
351
|
+
}
|
|
352
|
+
const updated = addComment(root, id, text);
|
|
353
|
+
if (!updated) {
|
|
354
|
+
console.error(`Issue not found: ${id}`);
|
|
355
|
+
process.exit(1);
|
|
356
|
+
}
|
|
357
|
+
ok(updated, `Commented on #${updated.id}`);
|
|
358
|
+
break;
|
|
359
|
+
}
|
|
360
|
+
case "search": {
|
|
361
|
+
const q = positional(rest)[0] || "";
|
|
362
|
+
const items = searchIssues(root, q);
|
|
363
|
+
if (json) {
|
|
364
|
+
console.log(JSON.stringify(items));
|
|
365
|
+
break;
|
|
366
|
+
}
|
|
367
|
+
if (!items.length) {
|
|
368
|
+
out(`No issues match "${q}".`);
|
|
369
|
+
break;
|
|
370
|
+
}
|
|
371
|
+
for (const i of items) out(fmtIssue(i));
|
|
372
|
+
break;
|
|
373
|
+
}
|
|
374
|
+
case "help":
|
|
375
|
+
case void 0:
|
|
376
|
+
case "--help":
|
|
377
|
+
case "-h":
|
|
378
|
+
out([
|
|
379
|
+
"svamp issue \u2014 the session backlog (folder of .svamp/issues/<id>.md)",
|
|
380
|
+
"",
|
|
381
|
+
' add "<title>" [--ready] [--label x] [--verify-cmd "cmd"] [--scope project|session] [--body "\u2026"]',
|
|
382
|
+
" list [--status ready|backlog|in_progress|done|archived|all] [--label x] [--scope \u2026] [--json]",
|
|
383
|
+
" show <id> [--json]",
|
|
384
|
+
" ready <id> | start <id> | close <id> | reopen <id> | backlog <id> | archive <id>",
|
|
385
|
+
" edit <id> [--title \u2026] [--label x] [--verify-cmd \u2026] [--no-verify] [--status \u2026] [--body \u2026]",
|
|
386
|
+
' comment <id> "<text>" # append a follow-up to the issue',
|
|
387
|
+
' search "<query>" [--json]'
|
|
388
|
+
].join("\n"));
|
|
389
|
+
break;
|
|
390
|
+
default:
|
|
391
|
+
console.error(`Unknown: svamp issue ${sub}. Try: svamp issue help`);
|
|
392
|
+
process.exit(1);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
export { issueCommand };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs';
|
|
2
|
-
import { connectAndGetMachine, resolveSessionId, createWorktree, connectAndResolveSession } from './commands-
|
|
2
|
+
import { connectAndGetMachine, resolveSessionId, createWorktree, connectAndResolveSession } from './commands-Ch1QWOw5.mjs';
|
|
3
3
|
import { execSync } from 'node:child_process';
|
|
4
|
-
import { m as shortId } from './run-
|
|
4
|
+
import { m as shortId } from './run-C_xwiN7C.mjs';
|
|
5
5
|
import 'node:path';
|
|
6
6
|
import 'node:os';
|
|
7
7
|
import 'os';
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { writeFileSync, readFileSync } from 'fs';
|
|
2
2
|
import { resolve } from 'path';
|
|
3
|
-
import { connectAndGetMachine } from './commands-
|
|
3
|
+
import { connectAndGetMachine } from './commands-Ch1QWOw5.mjs';
|
|
4
4
|
import 'node:fs';
|
|
5
5
|
import 'node:child_process';
|
|
6
6
|
import 'node:path';
|
|
7
7
|
import 'node:os';
|
|
8
|
-
import './run-
|
|
8
|
+
import './run-C_xwiN7C.mjs';
|
|
9
9
|
import 'os';
|
|
10
10
|
import 'fs/promises';
|
|
11
11
|
import 'url';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import os from 'os';
|
|
2
2
|
import fs__default from 'fs';
|
|
3
3
|
import { resolve, join, relative } from 'path';
|
|
4
|
-
import { p as parseFrontmatter, n as getSkillsServer, o as getSkillsWorkspaceName, q as getSkillsCollectionName, t as fetchWithTimeout, u as searchSkills, v as SKILLS_DIR, w as getSkillInfo, x as downloadSkillFile, y as listSkillFiles } from './run-
|
|
4
|
+
import { p as parseFrontmatter, n as getSkillsServer, o as getSkillsWorkspaceName, q as getSkillsCollectionName, t as fetchWithTimeout, u as searchSkills, v as SKILLS_DIR, w as getSkillInfo, x as downloadSkillFile, y as listSkillFiles } from './run-C_xwiN7C.mjs';
|
|
5
5
|
import 'fs/promises';
|
|
6
6
|
import 'url';
|
|
7
7
|
import 'child_process';
|
|
@@ -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-C_xwiN7C.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-C_xwiN7C.mjs';
|
|
8
8
|
import 'fs/promises';
|
|
9
9
|
import 'url';
|
|
10
10
|
import 'node:crypto';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { D as resolveModel, Y as describeMisconfiguration, Z as buildMachineDeps } from './run-
|
|
2
|
-
import { handleRealtimeEvent, initMachineVoiceSession } from './sideband-
|
|
1
|
+
import { D as resolveModel, Y as describeMisconfiguration, Z as buildMachineDeps } from './run-C_xwiN7C.mjs';
|
|
2
|
+
import { handleRealtimeEvent, initMachineVoiceSession } from './sideband-xxUkkrOq.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-C_xwiN7C.mjs';
|
|
2
2
|
import 'os';
|
|
3
3
|
import 'fs/promises';
|
|
4
4
|
import 'fs';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
var name = "svamp-cli";
|
|
2
|
-
var version = "0.2.
|
|
2
|
+
var version = "0.2.145";
|
|
3
3
|
var description = "Svamp CLI — AI workspace daemon on Hypha Cloud";
|
|
4
4
|
var author = "Amun AI AB";
|
|
5
5
|
var license = "SEE LICENSE IN LICENSE";
|
|
@@ -19,7 +19,7 @@ var exports$1 = {
|
|
|
19
19
|
var scripts = {
|
|
20
20
|
build: "rm -rf dist bin/skills && mkdir -p bin/skills && cp -r ../../skills/artifact bin/skills/artifact && cp -r ../../skills/loop bin/skills/loop && cp -r ../../skills/crew bin/skills/crew && tsc --noEmit && pkgroll",
|
|
21
21
|
typecheck: "tsc --noEmit",
|
|
22
|
-
test: "npx tsx test/test-context-window.mjs && npx tsx test/test-ratelimit-retry.mjs && npx tsx test/test-instance-config.mjs && npx tsx test/test-authorize.mjs && npx tsx test/test-normalize-allowed-user.mjs && npx tsx test/test-share-url.mjs && npx tsx test/test-update-sharing-normalization.mjs && npx tsx test/test-staged-homes-sweep.mjs && npx tsx test/test-session-helpers.mjs && npx tsx test/test-cli-routing.mjs && npx tsx test/test-security-context.mjs && npx tsx test/test-isolation-decision.mjs && npx tsx test/test-loop-activation.mjs && npx tsx test/test-message-helpers.mjs && npx tsx test/test-agent-config.mjs && npx tsx test/test-wrap-command.mjs && npx tsx test/test-credential-staging.mjs && npx tsx test/test-claude-auth.mjs && npx tsx test/test-output-formatters.mjs && npx tsx test/test-inbox-guard.mjs && npx tsx test/test-auto-topic.mjs && npx tsx test/test-project-info.mjs && npx tsx test/test-agent-types.mjs && npx tsx test/test-transport.mjs && npx tsx test/test-session-update-handlers.mjs && npx tsx test/test-session-scanner.mjs && npx tsx test/test-hypha-client.mjs && npx tsx test/test-hook-settings.mjs && npx tsx test/test-session-service-logic.mjs && npx tsx test/test-daemon-persistence.mjs && npx tsx test/test-detect-isolation.mjs && npx tsx test/test-machine-service-logic.mjs && npx tsx test/test-interactive-helpers.mjs && npx tsx test/test-codex-backend.mjs && npx tsx test/test-acp-backend.mjs && npx tsx test/test-acp-bridge.mjs && npx tsx test/test-hook-server.mjs && npx tsx test/test-session-commands.mjs && npx tsx test/test-interactive-console.mjs && npx tsx test/test-session-messages.mjs && npx tsx test/test-session-send-query.mjs && npx tsx test/test-skills.mjs && npx tsx test/test-agent-grouping.mjs && npx tsx test/test-machine-list-directory.mjs && npx tsx test/test-service-commands.mjs && npx tsx test/test-supervisor.mjs && npx tsx test/test-supervisor-lock.mjs && node test/test-supervisor-restart.mjs && npx tsx test/test-clear-detection.mjs && npx tsx test/test-session-consolidation.mjs && npx tsx test/test-inbox.mjs && npx tsx test/test-inbox-cross-machine.mjs && npx tsx test/test-checklist.mjs && npx tsx test/test-checklist-cli.mjs && npx tsx test/test-serve-link-subdomain.mjs && npx tsx test/test-short-id.mjs && npx tsx test/test-transcript-edit.mjs && npx tsx test/test-edit-history.mjs && npx tsx test/test-friendly-name.mjs && npx tsx test/test-session-rpc-dispatch.mjs && npx tsx test/test-sandbox-cli.mjs && npx tsx test/test-serve-manager.mjs && npx tsx test/test-serve-stability.mjs && npx tsx test/test-frpc-e2e.mjs --unit-only && npx tsx test/test-frpc-status.mjs && node test/pinnedClaudeCode.test.mjs && node test/fleet.test.mjs && npx tsx test/test-routine.mjs && npx tsx test/test-routine-rpc.mjs && npx tsx test/test-checklist-watchdog.mjs && npx tsx test/test-session-file.mjs && npx tsx test/test-channel-rpc.mjs && npx tsx test/test-wise-agent.mjs && npx tsx test/test-channel-agent.mjs && npx tsx test/test-channels-service.mjs && npx tsx test/test-channel-async-reply.mjs && npx tsx test/test-channel-binding.mjs && npx tsx test/test-channel-identity.mjs && npx tsx test/test-shared-session-identity.mjs && npx tsx test/test-wise-agent-auth.mjs && npx tsx test/test-channel-http.mjs && npx tsx test/test-wise-voice.mjs && npx tsx test/test-wise-headless.mjs && npx tsx test/test-wise-machine.mjs && npx tsx test/test-crew-merge.mjs",
|
|
22
|
+
test: "npx tsx test/test-context-window.mjs && npx tsx test/test-ratelimit-retry.mjs && npx tsx test/test-instance-config.mjs && npx tsx test/test-authorize.mjs && npx tsx test/test-normalize-allowed-user.mjs && npx tsx test/test-share-url.mjs && npx tsx test/test-update-sharing-normalization.mjs && npx tsx test/test-staged-homes-sweep.mjs && npx tsx test/test-session-helpers.mjs && npx tsx test/test-cli-routing.mjs && npx tsx test/test-security-context.mjs && npx tsx test/test-isolation-decision.mjs && npx tsx test/test-loop-activation.mjs && npx tsx test/test-message-helpers.mjs && npx tsx test/test-agent-config.mjs && npx tsx test/test-wrap-command.mjs && npx tsx test/test-credential-staging.mjs && npx tsx test/test-claude-auth.mjs && npx tsx test/test-output-formatters.mjs && npx tsx test/test-inbox-guard.mjs && npx tsx test/test-auto-topic.mjs && npx tsx test/test-project-info.mjs && npx tsx test/test-agent-types.mjs && npx tsx test/test-transport.mjs && npx tsx test/test-session-update-handlers.mjs && npx tsx test/test-session-scanner.mjs && npx tsx test/test-hypha-client.mjs && npx tsx test/test-hook-settings.mjs && npx tsx test/test-session-service-logic.mjs && npx tsx test/test-daemon-persistence.mjs && npx tsx test/test-detect-isolation.mjs && npx tsx test/test-machine-service-logic.mjs && npx tsx test/test-interactive-helpers.mjs && npx tsx test/test-codex-backend.mjs && npx tsx test/test-acp-backend.mjs && npx tsx test/test-acp-bridge.mjs && npx tsx test/test-hook-server.mjs && npx tsx test/test-session-commands.mjs && npx tsx test/test-interactive-console.mjs && npx tsx test/test-session-messages.mjs && npx tsx test/test-session-send-query.mjs && npx tsx test/test-skills.mjs && npx tsx test/test-agent-grouping.mjs && npx tsx test/test-machine-list-directory.mjs && npx tsx test/test-service-commands.mjs && npx tsx test/test-supervisor.mjs && npx tsx test/test-supervisor-lock.mjs && node test/test-supervisor-restart.mjs && npx tsx test/test-clear-detection.mjs && npx tsx test/test-session-consolidation.mjs && npx tsx test/test-inbox.mjs && npx tsx test/test-inbox-cross-machine.mjs && npx tsx test/test-checklist.mjs && npx tsx test/test-checklist-cli.mjs && npx tsx test/test-issue-store.mjs && npx tsx test/test-serve-link-subdomain.mjs && npx tsx test/test-short-id.mjs && npx tsx test/test-transcript-edit.mjs && npx tsx test/test-edit-history.mjs && npx tsx test/test-friendly-name.mjs && npx tsx test/test-session-rpc-dispatch.mjs && npx tsx test/test-sandbox-cli.mjs && npx tsx test/test-serve-manager.mjs && npx tsx test/test-serve-stability.mjs && npx tsx test/test-frpc-e2e.mjs --unit-only && npx tsx test/test-frpc-status.mjs && node test/pinnedClaudeCode.test.mjs && node test/fleet.test.mjs && npx tsx test/test-routine.mjs && npx tsx test/test-routine-rpc.mjs && npx tsx test/test-checklist-watchdog.mjs && npx tsx test/test-session-file.mjs && npx tsx test/test-channel-rpc.mjs && npx tsx test/test-wise-agent.mjs && npx tsx test/test-channel-agent.mjs && npx tsx test/test-channels-service.mjs && npx tsx test/test-channel-async-reply.mjs && npx tsx test/test-channel-binding.mjs && npx tsx test/test-channel-identity.mjs && npx tsx test/test-shared-session-identity.mjs && npx tsx test/test-wise-agent-auth.mjs && npx tsx test/test-channel-http.mjs && npx tsx test/test-wise-voice.mjs && npx tsx test/test-wise-headless.mjs && npx tsx test/test-wise-machine.mjs && npx tsx test/test-crew-merge.mjs",
|
|
23
23
|
"test:hypha": "node --no-warnings test/test-hypha-service.mjs",
|
|
24
24
|
dev: "tsx src/cli.ts",
|
|
25
25
|
"dev:daemon": "tsx src/cli.ts daemon start-sync",
|