svamp-cli 0.2.256 → 0.2.258

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 (27) hide show
  1. package/bin/skills/artifact/SKILL.md +1 -1
  2. package/dist/{agentCommands-DfTICQUR.mjs → agentCommands-CQ89BZon.mjs} +5 -5
  3. package/dist/{auth-CaFzUB-H.mjs → auth-CaFsKYbx.mjs} +1 -1
  4. package/dist/cli.mjs +61 -61
  5. package/dist/{commands-MopZEqZ7.mjs → commands--X8f4eSr.mjs} +24 -13
  6. package/dist/{commands-Dp4OLJ80.mjs → commands-B6eGMF5H.mjs} +1 -1
  7. package/dist/{commands-Cgi-GKQk.mjs → commands-BgX0W0uK.mjs} +1 -1
  8. package/dist/{commands-BrTyEX8u.mjs → commands-D8l74hsL.mjs} +1 -1
  9. package/dist/{commands-CRvH25K7.mjs → commands-Dd8xEIf0.mjs} +1 -1
  10. package/dist/{commands-C6_ClNDg.mjs → commands-DrfYv705.mjs} +2 -2
  11. package/dist/{commands-DPKRLSJZ.mjs → commands-DutfM3U7.mjs} +31 -15
  12. package/dist/{fleet-DT3LusNA.mjs → fleet-UvQnIWT1.mjs} +1 -1
  13. package/dist/{frpc--8kUn3Em.mjs → frpc-IXxyfgPn.mjs} +1 -1
  14. package/dist/{headlessCli-DJIDtYga.mjs → headlessCli-BK7WSS3D.mjs} +2 -2
  15. package/dist/index.mjs +1 -1
  16. package/dist/{package-CBpvrZJs.mjs → package-BdZX5mDv.mjs} +2 -2
  17. package/dist/{rpc-DPlerDzK.mjs → rpc-CyACkgY1.mjs} +1 -1
  18. package/dist/{rpc-BV_9jVwX.mjs → rpc-D7DB3XCH.mjs} +1 -1
  19. package/dist/{run-BDX-RaEm.mjs → run-C1Unk4Zx.mjs} +108 -84
  20. package/dist/{run-19FUjQ96.mjs → run-C1ufZjIW.mjs} +1 -1
  21. package/dist/{scheduler-CueRBYz_.mjs → scheduler-7wve0Fy3.mjs} +1 -1
  22. package/dist/{serveCommands-DRP03-lg.mjs → serveCommands-iQJJLsMJ.mjs} +5 -5
  23. package/dist/{serveManager-CQGY6nFz.mjs → serveManager-BszV0oIl.mjs} +62 -74
  24. package/dist/{sideband-BQ4pkLIQ.mjs → sideband-DMPZ-ZoR.mjs} +1 -1
  25. package/dist/staticFileServer-FCEOLIYH.mjs +239 -0
  26. package/package.json +2 -2
  27. package/dist/caddy-CuTbE3NY.mjs +0 -322
@@ -1,322 +0,0 @@
1
- import { spawn, execSync } from 'child_process';
2
- import { mkdirSync, existsSync, statSync, writeFileSync, chmodSync, unlinkSync } from 'fs';
3
- import { join } from 'path';
4
- import { homedir, platform, arch } from 'os';
5
-
6
- const CADDY_VERSION = "2.9.1";
7
- const BIN_DIR = join(homedir(), ".svamp", "bin");
8
- const CADDY_BIN = join(BIN_DIR, platform() === "win32" ? "caddy.exe" : "caddy");
9
- const ADMIN_PORT = 2019;
10
- const DEFAULT_LISTEN_PORT = 18080;
11
- function getCaddyDownloadUrl() {
12
- const os = platform();
13
- const a = arch();
14
- let osStr;
15
- let archStr;
16
- switch (os) {
17
- case "darwin":
18
- osStr = "mac";
19
- break;
20
- case "linux":
21
- osStr = "linux";
22
- break;
23
- case "win32":
24
- osStr = "windows";
25
- break;
26
- default:
27
- throw new Error(`Unsupported platform: ${os}`);
28
- }
29
- switch (a) {
30
- case "x64":
31
- archStr = "amd64";
32
- break;
33
- case "arm64":
34
- archStr = "arm64";
35
- break;
36
- default:
37
- throw new Error(`Unsupported architecture: ${a}`);
38
- }
39
- const ext = os === "win32" ? "zip" : "tar.gz";
40
- return `https://github.com/caddyserver/caddy/releases/download/v${CADDY_VERSION}/caddy_${CADDY_VERSION}_${osStr}_${archStr}.${ext}`;
41
- }
42
- async function ensureCaddy(log) {
43
- if (existsSync(CADDY_BIN)) return CADDY_BIN;
44
- const logger = log || console.log;
45
- mkdirSync(BIN_DIR, { recursive: true });
46
- const url = getCaddyDownloadUrl();
47
- logger(`Downloading Caddy ${CADDY_VERSION} from ${url}...`);
48
- const response = await fetch(url);
49
- if (!response.ok) {
50
- throw new Error(`Failed to download Caddy: ${response.status} ${response.statusText}`);
51
- }
52
- const buffer = Buffer.from(await response.arrayBuffer());
53
- if (platform() === "win32") {
54
- throw new Error("Windows ZIP extraction not implemented \u2014 please install caddy manually");
55
- }
56
- const tmpTar = join(BIN_DIR, `caddy-${CADDY_VERSION}.tar.gz`);
57
- writeFileSync(tmpTar, buffer);
58
- try {
59
- execSync(
60
- `tar -xzf "${tmpTar}" -C "${BIN_DIR}" caddy`,
61
- { stdio: "pipe" }
62
- );
63
- chmodSync(CADDY_BIN, 493);
64
- logger(`Caddy installed at ${CADDY_BIN}`);
65
- } finally {
66
- try {
67
- unlinkSync(tmpTar);
68
- } catch {
69
- }
70
- }
71
- return CADDY_BIN;
72
- }
73
- const CORS_HEADERS_HANDLER = {
74
- handler: "headers",
75
- response: {
76
- set: {
77
- "Access-Control-Allow-Origin": ["*"],
78
- "Access-Control-Allow-Methods": ["GET, POST, PUT, DELETE, OPTIONS"],
79
- "Access-Control-Allow-Headers": ["*"]
80
- }
81
- }
82
- };
83
- function generateCaddyConfig(listenPort, mounts, adminPort = ADMIN_PORT) {
84
- const routes = [];
85
- for (const mount of mounts) {
86
- if (mount.isFile) {
87
- const parentDir = mount.directory.replace(/[\\/][^\\/]+$/, "") || "/";
88
- const fileName = mount.directory.replace(/.*[\\/]/, "");
89
- routes.push({
90
- match: [{ path: [`/${mount.name}`] }],
91
- handle: [
92
- CORS_HEADERS_HANDLER,
93
- { handler: "rewrite", uri: `/${fileName}` },
94
- { handler: "file_server", root: parentDir }
95
- ]
96
- });
97
- } else {
98
- routes.push({
99
- match: [{ path: [`/${mount.name}`] }],
100
- handle: [
101
- {
102
- handler: "static_response",
103
- status_code: 302,
104
- headers: { Location: [`/${mount.name}/`] }
105
- }
106
- ]
107
- });
108
- const fileServerHandler = { handler: "file_server", root: mount.directory };
109
- if (mount.browse !== false) fileServerHandler.browse = {};
110
- routes.push({
111
- match: [{ path: [`/${mount.name}/*`, `/${mount.name}/`] }],
112
- handle: [
113
- CORS_HEADERS_HANDLER,
114
- { handler: "rewrite", strip_path_prefix: `/${mount.name}` },
115
- fileServerHandler
116
- ]
117
- });
118
- }
119
- }
120
- routes.push({
121
- match: [{ path: ["/"] }],
122
- handle: [
123
- CORS_HEADERS_HANDLER,
124
- {
125
- handler: "static_response",
126
- status_code: 200,
127
- headers: { "Content-Type": ["text/html; charset=utf-8"] },
128
- body: generateMountListHtml(mounts)
129
- }
130
- ]
131
- });
132
- routes.push({
133
- handle: [
134
- CORS_HEADERS_HANDLER,
135
- { handler: "static_response", status_code: 404, body: "Not Found" }
136
- ]
137
- });
138
- return {
139
- admin: {
140
- listen: `127.0.0.1:${adminPort}`
141
- },
142
- apps: {
143
- http: {
144
- servers: {
145
- srv0: {
146
- listen: [`127.0.0.1:${listenPort}`],
147
- routes
148
- }
149
- }
150
- }
151
- }
152
- };
153
- }
154
- function generateMountListHtml(mounts) {
155
- const items = mounts.map(
156
- (m) => `<li><a href="/${m.name}/">${m.name}</a> \u2014 ${m.directory}</li>`
157
- ).join("\n");
158
- return `<!DOCTYPE html>
159
- <html><head><meta charset="utf-8"><title>Svamp File Server</title>
160
- <style>
161
- body{font-family:system-ui,sans-serif;max-width:700px;margin:40px auto;padding:0 20px;color:#333}
162
- h1{font-size:1.3rem}
163
- ul{list-style:none;padding:0}
164
- li{padding:8px 0;border-bottom:1px solid #eee}
165
- a{color:#0969da;text-decoration:none;font-weight:500}
166
- a:hover{text-decoration:underline}
167
- </style>
168
- </head><body>
169
- <h1>Svamp File Server</h1>
170
- <ul>${items || "<li>No mounts registered.</li>"}</ul>
171
- </body></html>`;
172
- }
173
- class CaddyManager {
174
- process = null;
175
- mounts = /* @__PURE__ */ new Map();
176
- listenPort;
177
- adminPort;
178
- log;
179
- configPath;
180
- constructor(options = {}) {
181
- this.listenPort = options.listenPort || DEFAULT_LISTEN_PORT;
182
- this.adminPort = options.adminPort || ADMIN_PORT;
183
- this.log = options.log || ((msg) => console.log(`[CADDY] ${msg}`));
184
- const configDir = options.configDir || join(homedir(), ".svamp", "caddy");
185
- mkdirSync(configDir, { recursive: true });
186
- this.configPath = join(configDir, "config.json");
187
- }
188
- /** Start Caddy if not already running. */
189
- async start() {
190
- if (this.process) return;
191
- const caddyPath = await ensureCaddy(this.log);
192
- this.writeConfig();
193
- return new Promise((resolve, reject) => {
194
- const child = spawn(caddyPath, ["run", "--config", this.configPath], {
195
- stdio: ["ignore", "pipe", "pipe"],
196
- env: { ...process.env }
197
- });
198
- this.process = child;
199
- let resolved = false;
200
- const onOutput = (data) => {
201
- const text = data.toString().trim();
202
- if (!text) return;
203
- if (text.includes("serving initial configuration")) {
204
- if (!resolved) {
205
- resolved = true;
206
- this.log(`Caddy started on 127.0.0.1:${this.listenPort}`);
207
- resolve();
208
- }
209
- }
210
- if (text.includes('"level":"error"')) {
211
- this.log(`Caddy error: ${text}`);
212
- }
213
- };
214
- child.stdout?.on("data", onOutput);
215
- child.stderr?.on("data", onOutput);
216
- child.on("error", (err) => {
217
- if (!resolved) {
218
- resolved = true;
219
- reject(err);
220
- }
221
- });
222
- child.on("exit", (code) => {
223
- this.process = null;
224
- if (!resolved) {
225
- resolved = true;
226
- reject(new Error(`Caddy exited with code ${code}`));
227
- }
228
- });
229
- setTimeout(() => {
230
- if (!resolved) {
231
- resolved = true;
232
- resolve();
233
- }
234
- }, 1e4);
235
- });
236
- }
237
- /** Stop the Caddy process. */
238
- async stop() {
239
- if (!this.process) return;
240
- try {
241
- await fetch(`http://127.0.0.1:${this.adminPort}/stop`, { method: "POST" });
242
- } catch {
243
- this.process.kill("SIGTERM");
244
- }
245
- await new Promise((resolve) => {
246
- if (!this.process) {
247
- resolve();
248
- return;
249
- }
250
- const timeout = setTimeout(() => {
251
- try {
252
- this.process?.kill("SIGKILL");
253
- } catch {
254
- }
255
- resolve();
256
- }, 5e3);
257
- this.process.on("exit", () => {
258
- clearTimeout(timeout);
259
- resolve();
260
- });
261
- });
262
- this.process = null;
263
- this.log("Caddy stopped");
264
- }
265
- /** Add a mount and reload config. */
266
- async addMount(name, directory, browse = true) {
267
- const isFile = existsSync(directory) && statSync(directory).isFile();
268
- this.mounts.set(name, { name, directory, browse, isFile });
269
- await this.reloadConfig();
270
- this.log(`Mount added: ${name} \u2192 ${directory}`);
271
- }
272
- /** Remove a mount and reload config. */
273
- async removeMount(name) {
274
- if (!this.mounts.has(name)) {
275
- throw new Error(`Mount '${name}' not found`);
276
- }
277
- this.mounts.delete(name);
278
- await this.reloadConfig();
279
- this.log(`Mount removed: ${name}`);
280
- }
281
- /** Get all current mounts. */
282
- getMounts() {
283
- return Array.from(this.mounts.values());
284
- }
285
- /** Whether Caddy is running. */
286
- get isRunning() {
287
- return this.process !== null;
288
- }
289
- /** The port Caddy listens on. */
290
- get port() {
291
- return this.listenPort;
292
- }
293
- // ── Internal ─────────────────────────────────────────────────────
294
- writeConfig() {
295
- const config = generateCaddyConfig(this.listenPort, Array.from(this.mounts.values()), this.adminPort);
296
- writeFileSync(this.configPath, JSON.stringify(config, null, 2));
297
- }
298
- async reloadConfig() {
299
- this.writeConfig();
300
- if (!this.process) return;
301
- try {
302
- const config = generateCaddyConfig(this.listenPort, Array.from(this.mounts.values()), this.adminPort);
303
- const resp = await fetch(`http://127.0.0.1:${this.adminPort}/load`, {
304
- method: "POST",
305
- headers: { "Content-Type": "application/json" },
306
- body: JSON.stringify(config)
307
- });
308
- if (!resp.ok) {
309
- const body = await resp.text();
310
- this.log(`Config reload failed: ${resp.status} ${body}`);
311
- await this.stop();
312
- await this.start();
313
- }
314
- } catch (err) {
315
- this.log(`Config reload error: ${err.message} \u2014 restarting Caddy`);
316
- await this.stop();
317
- await this.start();
318
- }
319
- }
320
- }
321
-
322
- export { CaddyManager, ensureCaddy, generateCaddyConfig };