svamp-cli 0.2.151 → 0.2.153

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.
Files changed (24) hide show
  1. package/dist/{agentCommands-CtOE-AFD.mjs → agentCommands-BA6vfwBe.mjs} +5 -5
  2. package/dist/{auth-DR4WJJdh.mjs → auth-DDGQNcgj.mjs} +1 -1
  3. package/dist/cli.mjs +64 -60
  4. package/dist/{commands-DRFQ4tEC.mjs → commands-0OqnzYM4.mjs} +2 -2
  5. package/dist/{commands-C80GsDpQ.mjs → commands-6o8EfiTm.mjs} +1 -1
  6. package/dist/commands-C5NCV1-2.mjs +206 -0
  7. package/dist/{commands-5huYGEJA.mjs → commands-DFV7sIED.mjs} +2 -2
  8. package/dist/{commands-DR_g13_S.mjs → commands-DGrSL-zP.mjs} +5 -5
  9. package/dist/{commands-CraNY95y.mjs → commands-DTkbPUBJ.mjs} +2 -2
  10. package/dist/{commands--9dm2tSB.mjs → commands-GYM5Mj8d.mjs} +4 -180
  11. package/dist/{commands-sruHTsVh.mjs → commands-zix9Pnz-.mjs} +1 -1
  12. package/dist/{fleet-BM08pkb9.mjs → fleet-Bnn3afbQ.mjs} +1 -1
  13. package/dist/{frpc-BQ9Dta1o.mjs → frpc-DNTYlFA6.mjs} +1 -1
  14. package/dist/{headlessCli-D5m-1YmS.mjs → headlessCli-BziHStSj.mjs} +2 -2
  15. package/dist/{httpServer-CWn3F-0t.mjs → httpServer-DwhcH2T9.mjs} +10 -3
  16. package/dist/index.mjs +1 -1
  17. package/dist/{package-JMm_HlGt.mjs → package-CcVsdUQQ.mjs} +2 -2
  18. package/dist/{run-H_4p9eNo.mjs → run-CCmmjoNa.mjs} +1 -1
  19. package/dist/{run-DhnZXHcu.mjs → run-DLOd6buN.mjs} +10 -6
  20. package/dist/{serveCommands-CUywdvCF.mjs → serveCommands-Cpca3ZIy.mjs} +5 -5
  21. package/dist/{serveManager-sZkIrZCW.mjs → serveManager-DqCyMxvg.mjs} +2 -2
  22. package/dist/{sideband-CKX3P035.mjs → sideband-BCt7MEtP.mjs} +1 -1
  23. package/dist/store-ChN9bgel.mjs +182 -0
  24. package/package.json +2 -2
@@ -0,0 +1,206 @@
1
+ import { spawnSync } from 'node:child_process';
2
+ import { r as resolveProjectRoot } from './store-ChN9bgel.mjs';
3
+ import { existsSync, unlinkSync, readFileSync, readdirSync, mkdirSync, writeFileSync, renameSync } from 'node:fs';
4
+ import { join } from 'node:path';
5
+ import { parse, stringify } from 'yaml';
6
+
7
+ function workflowsDir(projectRoot) {
8
+ return join(projectRoot, ".svamp", "workflows");
9
+ }
10
+ function workflowPath(projectRoot, name) {
11
+ return join(workflowsDir(projectRoot), `${name}.yaml`);
12
+ }
13
+ function parseWorkflow(content) {
14
+ try {
15
+ const o = parse(content);
16
+ if (!o || typeof o !== "object" || !o.name) return null;
17
+ const jobs = Array.isArray(o.jobs) ? o.jobs.map((j) => ({ run: String(j?.run ?? "") })).filter((j) => j.run) : [];
18
+ return { name: String(o.name), on: o.on && typeof o.on === "object" ? o.on : void 0, jobs };
19
+ } catch {
20
+ return null;
21
+ }
22
+ }
23
+ function serializeWorkflow(wf) {
24
+ const clean = { name: wf.name };
25
+ if (wf.on && Object.keys(wf.on).length) clean.on = wf.on;
26
+ clean.jobs = wf.jobs.map((j) => ({ run: j.run }));
27
+ return stringify(clean);
28
+ }
29
+ function listWorkflows(projectRoot) {
30
+ const dir = workflowsDir(projectRoot);
31
+ if (!existsSync(dir)) return [];
32
+ const out = [];
33
+ for (const name of readdirSync(dir)) {
34
+ if (!name.endsWith(".yaml") && !name.endsWith(".yml")) continue;
35
+ try {
36
+ const wf = parseWorkflow(readFileSync(join(dir, name), "utf-8"));
37
+ if (wf) out.push(wf);
38
+ } catch {
39
+ }
40
+ }
41
+ return out.sort((a, b) => a.name.localeCompare(b.name));
42
+ }
43
+ function getWorkflow(projectRoot, name) {
44
+ const p = workflowPath(projectRoot, name);
45
+ if (!existsSync(p)) return null;
46
+ try {
47
+ return parseWorkflow(readFileSync(p, "utf-8"));
48
+ } catch {
49
+ return null;
50
+ }
51
+ }
52
+ function rawWorkflow(projectRoot, name) {
53
+ const p = workflowPath(projectRoot, name);
54
+ return existsSync(p) ? readFileSync(p, "utf-8") : null;
55
+ }
56
+ function saveWorkflow(projectRoot, wf) {
57
+ const dir = workflowsDir(projectRoot);
58
+ mkdirSync(dir, { recursive: true });
59
+ const path = workflowPath(projectRoot, wf.name);
60
+ const tmp = `${path}.tmp-${process.pid}`;
61
+ writeFileSync(tmp, serializeWorkflow(wf));
62
+ renameSync(tmp, path);
63
+ }
64
+ function removeWorkflow(projectRoot, name) {
65
+ const p = workflowPath(projectRoot, name);
66
+ if (!existsSync(p)) return false;
67
+ try {
68
+ unlinkSync(p);
69
+ return true;
70
+ } catch {
71
+ return false;
72
+ }
73
+ }
74
+
75
+ function flag(args, name) {
76
+ const i = args.indexOf(name);
77
+ return i !== -1 && i + 1 < args.length ? args[i + 1] : void 0;
78
+ }
79
+ function allFlags(args, name) {
80
+ return args.filter((_a, idx) => args[idx - 1] === name);
81
+ }
82
+ function positional(args) {
83
+ const out = [];
84
+ for (let i = 0; i < args.length; i++) {
85
+ const a = args[i];
86
+ if (a.startsWith("--")) {
87
+ if (a !== "--json") i++;
88
+ continue;
89
+ }
90
+ out.push(a);
91
+ }
92
+ return out;
93
+ }
94
+ function describeOn(on) {
95
+ if (!on) return "manual";
96
+ const parts = [];
97
+ if (on.schedule) parts.push(`schedule(${on.schedule})`);
98
+ if (on.dispatch) parts.push("dispatch");
99
+ if (on.channel) parts.push(`channel(${on.channel})`);
100
+ if (on.issue?.length) parts.push(`issue(${on.issue.join("/")})`);
101
+ return parts.length ? parts.join(" ") : "manual";
102
+ }
103
+ async function workflowCommand(args) {
104
+ const sub = args[0];
105
+ const rest = args.slice(1);
106
+ const root = resolveProjectRoot();
107
+ const json = args.includes("--json");
108
+ switch (sub) {
109
+ case "add": {
110
+ const name = positional(rest)[0];
111
+ const runs = allFlags(rest, "--run");
112
+ if (!name || !runs.length) {
113
+ console.error('usage: svamp workflow add <name> --run "<cmd>" [--run "<cmd2>"] [--on schedule|dispatch|channel|issue] [--cron "* * * * *"] [--channel <name>] [--issue ready,closed,labeled]');
114
+ process.exit(1);
115
+ }
116
+ const onKinds = allFlags(rest, "--on");
117
+ const on = {};
118
+ if (onKinds.includes("schedule") || flag(rest, "--cron")) on.schedule = flag(rest, "--cron") || "0 * * * *";
119
+ if (onKinds.includes("dispatch")) on.dispatch = true;
120
+ if (onKinds.includes("channel") || flag(rest, "--channel")) on.channel = flag(rest, "--channel") || "default";
121
+ if (onKinds.includes("issue") || flag(rest, "--issue")) on.issue = (flag(rest, "--issue") || "ready").split(",").map((s) => s.trim()).filter(Boolean);
122
+ const wf = { name, on: Object.keys(on).length ? on : void 0, jobs: runs.map((r) => ({ run: r })) };
123
+ saveWorkflow(root, wf);
124
+ if (json) console.log(JSON.stringify(wf));
125
+ else console.log(`Saved workflow "${name}" (on: ${describeOn(wf.on)}, ${wf.jobs.length} step${wf.jobs.length === 1 ? "" : "s"}).`);
126
+ break;
127
+ }
128
+ case "list":
129
+ case "ls": {
130
+ const all = listWorkflows(root);
131
+ if (json) {
132
+ console.log(JSON.stringify(all));
133
+ break;
134
+ }
135
+ if (!all.length) {
136
+ console.log("No workflows.");
137
+ break;
138
+ }
139
+ for (const wf of all) console.log(`${wf.name} [${describeOn(wf.on)}] ${wf.jobs.length} step${wf.jobs.length === 1 ? "" : "s"}`);
140
+ break;
141
+ }
142
+ case "show": {
143
+ const name = positional(rest)[0];
144
+ const raw = name ? rawWorkflow(root, name) : null;
145
+ if (!raw) {
146
+ console.error(`Workflow not found: ${name}`);
147
+ process.exit(1);
148
+ }
149
+ if (json) console.log(JSON.stringify(getWorkflow(root, name)));
150
+ else process.stdout.write(raw);
151
+ break;
152
+ }
153
+ case "remove":
154
+ case "rm": {
155
+ const name = positional(rest)[0];
156
+ if (!name) {
157
+ console.error("usage: svamp workflow remove <name>");
158
+ process.exit(1);
159
+ }
160
+ console.log(removeWorkflow(root, name) ? `Removed workflow "${name}".` : `Workflow not found: ${name}`);
161
+ break;
162
+ }
163
+ case "run": {
164
+ const name = positional(rest)[0];
165
+ const wf = name ? getWorkflow(root, name) : null;
166
+ if (!wf) {
167
+ console.error(`Workflow not found: ${name}`);
168
+ process.exit(1);
169
+ }
170
+ console.log(`\u25B6 running workflow "${wf.name}" (${wf.jobs.length} step${wf.jobs.length === 1 ? "" : "s"})`);
171
+ for (let i = 0; i < wf.jobs.length; i++) {
172
+ const step = wf.jobs[i];
173
+ console.log(` [${i + 1}/${wf.jobs.length}] $ ${step.run}`);
174
+ const r = spawnSync("sh", ["-c", step.run], { cwd: root, stdio: "inherit" });
175
+ if (r.status !== 0) {
176
+ console.error(` \u2717 step ${i + 1} failed (exit ${r.status ?? "signal"}). Stopping.`);
177
+ process.exit(r.status ?? 1);
178
+ }
179
+ }
180
+ console.log(`\u2713 workflow "${wf.name}" completed.`);
181
+ break;
182
+ }
183
+ case "help":
184
+ case void 0:
185
+ case "--help":
186
+ case "-h":
187
+ console.log([
188
+ "svamp workflow \u2014 GitHub-Actions-style automation as .svamp/workflows/<name>.yaml",
189
+ "",
190
+ ' add <name> --run "<cmd>" [--run "<cmd2>"] [--on schedule|dispatch|channel|issue]',
191
+ ' [--cron "0 9 * * 1-5"] [--channel <name>] [--issue ready,closed,labeled]',
192
+ " list | show <name> | remove <name>",
193
+ " run <name> # execute the workflow's run-only steps now",
194
+ "",
195
+ "Each step is a shell command \u2014 every verb is a `svamp` CLI call, e.g.",
196
+ ' svamp workflow add nightly --on schedule --cron "0 2 * * *" \\',
197
+ ' --run "svamp session send . \\"Run the nightly checks and fix failures\\""'
198
+ ].join("\n"));
199
+ break;
200
+ default:
201
+ console.error(`Unknown: svamp workflow ${sub}. Try: svamp workflow help`);
202
+ process.exit(1);
203
+ }
204
+ }
205
+
206
+ export { workflowCommand };
@@ -1,11 +1,11 @@
1
1
  import { writeFileSync, readFileSync } from 'fs';
2
2
  import { resolve } from 'path';
3
- import { connectAndGetMachine } from './commands-sruHTsVh.mjs';
3
+ import { connectAndGetMachine } from './commands-zix9Pnz-.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-DhnZXHcu.mjs';
8
+ import './run-DLOd6buN.mjs';
9
9
  import 'os';
10
10
  import 'fs/promises';
11
11
  import 'url';
@@ -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-BQ9Dta1o.mjs');
61
+ const { runFrpcTunnel } = await import('./frpc-DNTYlFA6.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-sruHTsVh.mjs');
71
+ const { connectAndGetMachine } = await import('./commands-zix9Pnz-.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-BQ9Dta1o.mjs');
126
+ const { runFrpcTunnel } = await import('./frpc-DNTYlFA6.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-sruHTsVh.mjs');
135
+ const { connectAndGetMachine } = await import('./commands-zix9Pnz-.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-sruHTsVh.mjs');
175
+ const { connectAndGetMachine } = await import('./commands-zix9Pnz-.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 } from 'node:fs';
2
- import { connectAndGetMachine, resolveSessionId, createWorktree, connectAndResolveSession } from './commands-sruHTsVh.mjs';
2
+ import { connectAndGetMachine, resolveSessionId, createWorktree, connectAndResolveSession } from './commands-zix9Pnz-.mjs';
3
3
  import { execSync } from 'node:child_process';
4
- import { m as shortId } from './run-DhnZXHcu.mjs';
4
+ import { m as shortId } from './run-DLOd6buN.mjs';
5
5
  import 'node:path';
6
6
  import 'node:os';
7
7
  import 'os';
@@ -1,183 +1,7 @@
1
- import { existsSync, readFileSync, unlinkSync, readdirSync, mkdirSync, writeFileSync, renameSync } 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
- }
1
+ import { r as resolveProjectRoot, s as searchIssues, l as listIssues, a as addComment, u as updateIssue, b as summarize, c as addIssue, g as getIssue } from './store-ChN9bgel.mjs';
2
+ import 'node:fs';
3
+ import 'node:path';
4
+ import 'node:child_process';
181
5
 
182
6
  const STATUS_GLYPH = {
183
7
  backlog: "\u25CB",
@@ -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-DhnZXHcu.mjs';
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-DLOd6buN.mjs';
6
6
  import 'os';
7
7
  import 'fs/promises';
8
8
  import 'fs';
@@ -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-DhnZXHcu.mjs';
4
+ import { c as connectToHypha } from './run-DLOd6buN.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-DhnZXHcu.mjs';
7
+ import { h as getFrpsSubdomainHost, i as getFrpsServerPort, j as getFrpsServerAddr } from './run-DLOd6buN.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-DhnZXHcu.mjs';
2
- import { handleRealtimeEvent, initMachineVoiceSession } from './sideband-CKX3P035.mjs';
1
+ import { D as resolveModel, Y as describeMisconfiguration, Z as buildMachineDeps } from './run-DLOd6buN.mjs';
2
+ import { handleRealtimeEvent, initMachineVoiceSession } from './sideband-BCt7MEtP.mjs';
3
3
  import { WebSocket } from 'ws';
4
4
  import { execSync, spawn } from 'child_process';
5
5
  import 'os';
@@ -3,10 +3,17 @@ import { createServer } from 'node:http';
3
3
  async function findOwner(deps, channelId) {
4
4
  for (const sid of deps.getSessionIds()) {
5
5
  const rpc = deps.getSessionRPCHandlers(sid);
6
- if (!rpc?.channelList) continue;
6
+ if (!rpc) continue;
7
7
  try {
8
- const r = await rpc.channelList();
9
- if ((r?.channels || []).some((c) => c.id === channelId)) return rpc;
8
+ if (rpc.channelOwns) {
9
+ const r = await rpc.channelOwns(channelId);
10
+ if (r?.owned) return rpc;
11
+ continue;
12
+ }
13
+ if (rpc.channelList) {
14
+ const r = await rpc.channelList();
15
+ if ((r?.channels || []).some((c) => c.id === channelId)) return rpc;
16
+ }
10
17
  } catch {
11
18
  }
12
19
  }
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-DhnZXHcu.mjs';
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-DLOd6buN.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.151";
2
+ var version = "0.2.153";
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-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",
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-workflow-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",
@@ -1,4 +1,4 @@
1
- import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import { _ as composeSessionId, $ as generateFriendlyName, c as connectToHypha, a as createSessionStore, r as registerMachineService, a0 as generateHookSettings } from './run-DhnZXHcu.mjs';
1
+ import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import { _ as composeSessionId, $ as generateFriendlyName, c as connectToHypha, a as createSessionStore, r as registerMachineService, a0 as generateHookSettings } from './run-DLOd6buN.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';
@@ -2771,7 +2771,7 @@ async function registerMachineService(server, machineId, metadata, daemonState,
2771
2771
  const tunnels = handlers.tunnels;
2772
2772
  if (!tunnels) throw new Error("Tunnel management not available");
2773
2773
  if (tunnels.has(params.name)) throw new Error(`Tunnel '${params.name}' already running`);
2774
- const { FrpcTunnel } = await import('./frpc-BQ9Dta1o.mjs');
2774
+ const { FrpcTunnel } = await import('./frpc-DNTYlFA6.mjs');
2775
2775
  const tunnel = new FrpcTunnel({
2776
2776
  name: params.name,
2777
2777
  ports: params.ports,
@@ -3212,7 +3212,7 @@ QUESTION: ${params.question || "Summarize this concisely."}` }
3212
3212
  }
3213
3213
  const deps = buildSessionDeps(rpc, { cwd, ownerEmail: owner });
3214
3214
  const sender = { name: context?.user?.email || context?.user?.id || "user", kind: "user", verified: true };
3215
- const { toolsForRole } = await import('./sideband-CKX3P035.mjs');
3215
+ const { toolsForRole } = await import('./sideband-BCt7MEtP.mjs');
3216
3216
  const r2 = await runWiseAgent({ message: params.message, sender, config: { tools: toolsForRole(role2) }, deps, transport, model: resolved.model });
3217
3217
  return fmt(r2);
3218
3218
  }
@@ -3311,7 +3311,7 @@ QUESTION: ${params.question || "Summarize this concisely."}` }
3311
3311
  if (r.error || !r.sender) return { error: r.error || "unauthorized" };
3312
3312
  const callId = "call_" + Math.random().toString(16).slice(2, 12);
3313
3313
  const rendered = renderMessage(c, { sender: r.sender, body: { message: kwargs.message }, callId });
3314
- const { queryCore } = await import('./commands-sruHTsVh.mjs');
3314
+ const { queryCore } = await import('./commands-zix9Pnz-.mjs');
3315
3315
  const timeout = c.reply?.timeout_sec || 120;
3316
3316
  let result;
3317
3317
  try {
@@ -4347,6 +4347,10 @@ function createSessionStore(server, sessionId, initialMetadata, initialAgentStat
4347
4347
  channelList: async () => {
4348
4348
  return { channels: channelStore.list().filter((c) => c.enabled !== false && !c.system).map(channelPublicView) };
4349
4349
  },
4350
+ channelOwns: async (id) => {
4351
+ const c = channelStore.get(id);
4352
+ return { owned: !!c && c.enabled !== false };
4353
+ },
4350
4354
  channelDescribe: async (id) => {
4351
4355
  const c = channelStore.get(id);
4352
4356
  if (!c || c.enabled === false || c.system) return { error: "not found" };
@@ -11772,7 +11776,7 @@ async function startDaemon(options) {
11772
11776
  saveExposedTunnels(list);
11773
11777
  }
11774
11778
  async function createExposedTunnel(spec) {
11775
- const { FrpcTunnel } = await import('./frpc-BQ9Dta1o.mjs');
11779
+ const { FrpcTunnel } = await import('./frpc-DNTYlFA6.mjs');
11776
11780
  const tunnel = new FrpcTunnel({
11777
11781
  name: spec.name,
11778
11782
  ports: spec.ports,
@@ -11792,7 +11796,7 @@ async function startDaemon(options) {
11792
11796
  return tunnel;
11793
11797
  }
11794
11798
  const tunnelRecreateState = /* @__PURE__ */ new Map();
11795
- const { ServeManager } = await import('./serveManager-sZkIrZCW.mjs');
11799
+ const { ServeManager } = await import('./serveManager-DqCyMxvg.mjs');
11796
11800
  const serveManager = new ServeManager(SVAMP_HOME, (msg) => logger.log(`[SERVE] ${msg}`), hyphaServerUrl);
11797
11801
  ensureAutoInstalledSkills(logger).catch(() => {
11798
11802
  });
@@ -14571,7 +14575,7 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
14571
14575
  const channelHttpPort = Number(process.env.SVAMP_CHANNEL_HTTP_PORT) || 0;
14572
14576
  if (channelHttpPort > 0) {
14573
14577
  try {
14574
- const { createChannelHttpServer } = await import('./httpServer-CWn3F-0t.mjs');
14578
+ const { createChannelHttpServer } = await import('./httpServer-DwhcH2T9.mjs');
14575
14579
  const channelHttpServer = createChannelHttpServer({
14576
14580
  getSessionIds: () => {
14577
14581
  const ids = [];