svamp-cli 0.2.176 → 0.2.178

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 (31) hide show
  1. package/bin/skills/loop/SKILL.md +1 -1
  2. package/dist/{agentCommands-kchQlyIS.mjs → agentCommands-BIn9btot.mjs} +5 -5
  3. package/dist/{auth-oH2upjHc.mjs → auth-DY_tcgLY.mjs} +1 -1
  4. package/dist/cli.mjs +60 -64
  5. package/dist/{commands-CbrJ16x7.mjs → commands-BTyp-k7w.mjs} +5 -5
  6. package/dist/{commands-Cu6nPOsD.mjs → commands-BfdkS7Iy.mjs} +10 -10
  7. package/dist/{commands-USG2Z4XP.mjs → commands-CdMEMD_c.mjs} +1 -1
  8. package/dist/{commands-CXtkDntj.mjs → commands-J9WOCzDG.mjs} +2 -2
  9. package/dist/{commands-DGkX7Kcr.mjs → commands-MjIkmrmC.mjs} +1 -1
  10. package/dist/{commands-DHbv5qMP.mjs → commands-WgUO8QeK.mjs} +1 -1
  11. package/dist/{commands-9LT5p45A.mjs → commands-kepmDOXD.mjs} +2 -2
  12. package/dist/{fleet-BcS8xNkk.mjs → fleet-CDllUpMj.mjs} +1 -1
  13. package/dist/{frpc-Bm7BrLan.mjs → frpc-D4x74mG6.mjs} +1 -1
  14. package/dist/{headlessCli-B4CVNI7S.mjs → headlessCli-CmBCGmNV.mjs} +2 -2
  15. package/dist/index.mjs +1 -1
  16. package/dist/{package-DndVS0ln.mjs → package-B-yM7SvY.mjs} +2 -2
  17. package/dist/{rpc-BbaS0cLh.mjs → rpc-2TJ6ipXZ.mjs} +7 -7
  18. package/dist/{rpc-DVNDMfl8.mjs → rpc-DBH2bo8s.mjs} +1 -1
  19. package/dist/{run-BmpyfykC.mjs → run-B-1WDymr.mjs} +31 -409
  20. package/dist/{run-Cr1yt_tm.mjs → run-BVNBqt1C.mjs} +1 -1
  21. package/dist/{scheduler-BusuolPD.mjs → scheduler-C3j8Tghm.mjs} +1 -1
  22. package/dist/{serveCommands-Crb8ENkv.mjs → serveCommands-BFWBxK8L.mjs} +5 -5
  23. package/dist/{serveManager-DQByExEO.mjs → serveManager-DXm1bdoU.mjs} +2 -2
  24. package/dist/{sideband-B4L2zR2U.mjs → sideband-Da1VG2iq.mjs} +1 -1
  25. package/package.json +2 -2
  26. package/bin/skills/loop/bin/routine-cli.mjs +0 -121
  27. package/bin/skills/loop/bin/routine-runner.mjs +0 -125
  28. package/bin/skills/loop/bin/routine-store.mjs +0 -49
  29. package/bin/skills/loop/routines.process.yaml +0 -20
  30. package/bin/skills/loop/test/test-routine-engine.mjs +0 -122
  31. package/dist/commands-DBi7fxGX.mjs +0 -223
@@ -1,223 +0,0 @@
1
- import { execFileSync } from 'node:child_process';
2
- import { randomUUID } from 'node:crypto';
3
- import { createServer } from 'node:http';
4
- import { R as RoutineStore, x as RoutineRunner } from './run-BmpyfykC.mjs';
5
- import 'os';
6
- import 'fs/promises';
7
- import 'fs';
8
- import 'path';
9
- import 'url';
10
- import 'child_process';
11
- import 'crypto';
12
- import 'node:fs';
13
- import 'util';
14
- import 'node:path';
15
- import 'node:events';
16
- import 'node:os';
17
- import '@agentclientprotocol/sdk';
18
- import '@modelcontextprotocol/sdk/client/index.js';
19
- import '@modelcontextprotocol/sdk/client/stdio.js';
20
- import '@modelcontextprotocol/sdk/types.js';
21
- import 'zod';
22
- import 'node:fs/promises';
23
- import 'node:util';
24
-
25
- function parseArgs(argv) {
26
- const a = { _: [] };
27
- for (let i = 0; i < argv.length; i++) {
28
- const t = argv[i];
29
- if (t.startsWith("--")) a[t.slice(2)] = argv[i + 1] && !argv[i + 1].startsWith("--") ? argv[++i] : true;
30
- else a._.push(t);
31
- }
32
- return a;
33
- }
34
- function isSessionLive(sid) {
35
- try {
36
- const out = execFileSync("svamp", ["session", "list", "--json"], { stdio: ["ignore", "pipe", "ignore"], timeout: 15e3 }).toString();
37
- const list = JSON.parse(out);
38
- return Array.isArray(list) && list.some((s) => s?.sessionId === sid);
39
- } catch {
40
- return false;
41
- }
42
- }
43
- async function cliDeliver({ routine, resolved }) {
44
- if (resolved.kind === "verify") {
45
- const dir = routine.dir;
46
- if (!dir) {
47
- console.error(`[trigger] skip ${routine.id || routine.name}: verify action has no dir`);
48
- return { skipped: "verify: no dir" };
49
- }
50
- const target = routine.action.verify?.target_session || routine.session_id;
51
- const reportTo = routine.action.verify?.report_to || routine.session_id;
52
- if (!isSessionLive(reportTo)) {
53
- console.error(`[trigger] skip ${routine.id || routine.name}: report session ${reportTo} not live (inbox is in-memory)`);
54
- return { skipped: "verify: report session not live" };
55
- }
56
- let res;
57
- try {
58
- const out = execFileSync("svamp", ["issue", "pending"], { cwd: dir, encoding: "utf8" });
59
- res = { verdict: "approved", guidance: out.trim() || "No pending issues.", criteria: "svamp issue pending" };
60
- } catch (e) {
61
- res = { verdict: "rework", guidance: (String(e?.stdout || "") + String(e?.stderr || "")).trim() || "Pending issues remain.", criteria: "svamp issue pending" };
62
- }
63
- const message = {
64
- messageId: randomUUID(),
65
- from: `watchdog:${routine.name || routine.id}`,
66
- fromSession: target,
67
- to: reportTo,
68
- subject: `watchdog: ${res.verdict} \u2014 ${routine.name || routine.id}`,
69
- body: `<supervision-verdict source="watchdog" session="${target}" verdict="${res.verdict}" judge="oracle" round="0">
70
- ${res.guidance}
71
- Criteria: ${res.criteria || "(none)"}
72
- </supervision-verdict>`,
73
- timestamp: Date.now(),
74
- read: false,
75
- urgency: "normal",
76
- hopCount: 1
77
- };
78
- const { connectAndGetMachine } = await import('./commands-DGkX7Kcr.mjs');
79
- const { server, machine } = await connectAndGetMachine();
80
- try {
81
- await machine.sessionRPC(reportTo, "sendInboxMessage", { message });
82
- } finally {
83
- await server.disconnect();
84
- }
85
- return;
86
- }
87
- if (routine.bind === "stateless") {
88
- const dir = routine.dir;
89
- if (!dir) {
90
- console.error(`[routine] skip ${routine.id || routine.name}: stateless routine has no dir`);
91
- return { skipped: "stateless: no dir" };
92
- }
93
- execFileSync("svamp", ["session", "query", dir, resolved.text || resolved.task || "run"], { stdio: "pipe" });
94
- return;
95
- }
96
- const sid = routine.session_id;
97
- if (!isSessionLive(sid)) {
98
- console.error(`[routine] skip ${routine.id || routine.name}: session ${sid} is stopped/archived`);
99
- return { skipped: "session stopped/archived" };
100
- }
101
- if (resolved.kind === "message") {
102
- execFileSync("svamp", ["session", "send", sid, resolved.text || ""], { stdio: "pipe" });
103
- return;
104
- }
105
- execFileSync("svamp", [
106
- "session",
107
- "send",
108
- sid,
109
- `Begin the loop (LOOP MODE). Task: ${resolved.task}. Iterate until the gate lets you stop.`
110
- ], { stdio: "pipe" });
111
- }
112
- function buildRoutineFromArgs(a) {
113
- const r = { session_id: a.session, name: a.name || "routine", overlap: a.overlap || "queue" };
114
- if (a.schedule) r.trigger = { type: "schedule", cron: a.schedule, missed: a.missed || "skip", tz: a.tz };
115
- else if (a.webhook || a.api) r.trigger = { type: a.api ? "api" : "webhook", methods: a.get ? ["GET"] : ["GET", "POST"], public: !!a.public };
116
- else r.trigger = { type: "manual" };
117
- if (a.verify) r.action = { kind: "verify", verify: { target_session: a["target-session"], report_to: a["report-to"] } };
118
- else if (a.loop) r.action = { kind: "loop", task_template: a.task || "", loop: { dir: a.dir, oracle: a.oracle, evaluator: a.evaluator || "off" } };
119
- else r.action = { kind: "message", template: a.message || a.task || "run" };
120
- if (a.dir) r.dir = a.dir;
121
- if (a.stateless) r.bind = "stateless";
122
- return r;
123
- }
124
- async function routineCommand(args) {
125
- const a = parseArgs(args);
126
- const cmd = a._[0];
127
- const store = new RoutineStore();
128
- const runner = new RoutineRunner({ store, deliver: cliDeliver, log: console.error });
129
- switch (cmd) {
130
- case "add": {
131
- if (!a.session) {
132
- console.error("--session <id> required");
133
- process.exit(1);
134
- }
135
- const r = store.save(buildRoutineFromArgs(a));
136
- console.log(`\u2705 added trigger ${r.id} (${r.name}) source=${r.trigger.type} action=${r.action.kind} session=${r.session_id}`);
137
- if (r.trigger.key) console.log(` webhook key: ${r.trigger.key}`);
138
- break;
139
- }
140
- case "list": {
141
- const rs = store.list(typeof a.session === "string" ? a.session : void 0);
142
- if (a.json) {
143
- console.log(JSON.stringify(rs, null, 2));
144
- break;
145
- }
146
- if (!rs.length) {
147
- console.log("(no triggers)");
148
- break;
149
- }
150
- for (const r of rs) console.log(`${r.enabled ? "\u25CF" : "\u25CB"} ${r.id} ${r.name} [${r.trigger.type}${r.trigger.cron ? " " + r.trigger.cron : ""}] -> ${r.action.kind} ${r.bind === "stateless" ? `stateless(${r.dir || "?"})` : `session=${r.session_id}`}`);
151
- break;
152
- }
153
- case "remove":
154
- console.log(store.remove(a._[1]) ? `removed ${a._[1]}` : "not found");
155
- break;
156
- case "enable":
157
- store.setEnabled(a._[1], true);
158
- console.log(`enabled ${a._[1]}`);
159
- break;
160
- case "disable":
161
- store.setEnabled(a._[1], false);
162
- console.log(`disabled ${a._[1]}`);
163
- break;
164
- case "run-now":
165
- console.log(JSON.stringify(await runner.runNow(a._[1], {}), null, 2));
166
- break;
167
- case "serve":
168
- await serve(runner, Number(a.port) || 8722);
169
- break;
170
- default:
171
- console.log(`usage: svamp trigger <add|list|remove|enable|disable|run-now|serve> (alias: svamp routine)
172
- add --session <id> --name <n> [--schedule "*/5 * * * *" [--missed catchup]] [--webhook|--api [--get] [--public]] [--stateless --dir <path>] (--message "..." | --loop --dir <path> --task "..." [--oracle "cmd"])
173
- list [--session <id>] [--json]
174
- serve [--port 8722]`);
175
- }
176
- }
177
- async function serve(runner, port) {
178
- await runner.catchUp(new Date(Date.now() - 24 * 3600 * 1e3), /* @__PURE__ */ new Date());
179
- const timer = setInterval(() => {
180
- runner.tick(/* @__PURE__ */ new Date()).catch((e) => console.error("tick error", e));
181
- }, 2e4);
182
- const server = createServer((req, res) => {
183
- const u = new URL(req.url || "/", `http://localhost:${port}`);
184
- if (u.pathname === "/" || u.pathname === "/health") {
185
- res.writeHead(200).end("routines ok");
186
- return;
187
- }
188
- const m = u.pathname.match(/^\/routine\/([\w.-]+)$/);
189
- if (!m) {
190
- res.writeHead(404).end("not found");
191
- return;
192
- }
193
- const id = m[1];
194
- const key = u.searchParams.get("key");
195
- const query = Object.fromEntries(u.searchParams.entries());
196
- let chunks = "";
197
- req.on("data", (c) => {
198
- chunks += c;
199
- if (chunks.length > 1e6) req.destroy();
200
- });
201
- req.on("end", async () => {
202
- let body = {};
203
- try {
204
- body = chunks ? JSON.parse(chunks) : {};
205
- } catch {
206
- }
207
- const result = await runner.webhook(id, { key, method: req.method, body, query });
208
- res.writeHead(result.status || 200, { "content-type": "application/json" }).end(JSON.stringify(result));
209
- });
210
- });
211
- server.listen(port, () => {
212
- console.log(`\u{1FA9D} trigger server on http://localhost:${port}`);
213
- console.log(` webhook URL: http://localhost:${port}/routine/<id>?key=<key>`);
214
- console.log(` expose: svamp service expose triggers --port ${port}`);
215
- });
216
- process.on("SIGINT", () => {
217
- clearInterval(timer);
218
- server.close();
219
- process.exit(0);
220
- });
221
- }
222
-
223
- export { routineCommand };