svamp-cli 0.2.195 → 0.2.197
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/bin/skills/loop/bin/stop-gate.mjs +31 -1
- package/bin/skills/loop/test/test-loop-gate.mjs +38 -0
- package/dist/{agentCommands-IdOiOg0f.mjs → agentCommands-Dxuc65V_.mjs} +5 -5
- package/dist/{auth-DmrnqTLo.mjs → auth-DweBQRAL.mjs} +1 -1
- package/dist/cli.mjs +60 -60
- package/dist/{commands-CbBOkn_G.mjs → commands-BF7fzTcc.mjs} +1 -1
- package/dist/{commands-DAYpMdgB.mjs → commands-BFZhHLhh.mjs} +2 -2
- package/dist/{commands-BlTV-jYX.mjs → commands-BItE-9OU.mjs} +1 -1
- package/dist/{commands-DHI31wAh.mjs → commands-BJ3G0VVJ.mjs} +1 -1
- package/dist/{commands-DZhCJXnB.mjs → commands-BWD_a3hE.mjs} +2 -2
- package/dist/{commands-B3uk2hcj.mjs → commands-Bxb8oEBa.mjs} +1 -1
- package/dist/{commands-DjT7M2al.mjs → commands-C1V3SEF9.mjs} +5 -5
- package/dist/{fleet-BtwsNKuT.mjs → fleet-C-2EKVda.mjs} +1 -1
- package/dist/{frpc-WpRu5zE_.mjs → frpc-BgabHfqV.mjs} +1 -1
- package/dist/{headlessCli-Dy049YdV.mjs → headlessCli-CtTe4oJ4.mjs} +2 -2
- package/dist/{httpServer-Cf54pQ77.mjs → httpServer-B1KVQJfm.mjs} +38 -0
- package/dist/index.mjs +1 -1
- package/dist/{package-ARvCEkBY.mjs → package-PTsbpBGF.mjs} +2 -2
- package/dist/{rpc-DgV6_G_Q.mjs → rpc-C35Y8Vto.mjs} +1 -1
- package/dist/{rpc-CvpwmghB.mjs → rpc-DlM7ml1e.mjs} +1 -1
- package/dist/{run-DiCtjIs5.mjs → run-B3fosGEs.mjs} +335 -36
- package/dist/{run-D79u_Ud4.mjs → run-DtTnHqcs.mjs} +1 -1
- package/dist/{scheduler-D8Xj2_vB.mjs → scheduler-B3hBIkt8.mjs} +1 -1
- package/dist/{serveCommands-Bc9DXaQv.mjs → serveCommands-Bj2aEfKX.mjs} +5 -5
- package/dist/{serveManager-C2ykbnxd.mjs → serveManager-CCslS9Yt.mjs} +2 -2
- package/dist/{sideband-B9uONcBg.mjs → sideband-BtZMx9Af.mjs} +1 -1
- package/package.json +2 -2
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import os$1, { homedir as homedir$1 } from 'os';
|
|
2
2
|
import fs, { mkdir as mkdir$1, readdir as readdir$1, readFile, writeFile as writeFile$1, rename, unlink } from 'fs/promises';
|
|
3
|
-
import { readFileSync as readFileSync$1, mkdirSync as mkdirSync$1, writeFileSync as writeFileSync$1, renameSync as renameSync$1, existsSync as existsSync$1, realpathSync, rmSync as rmSync$1, copyFileSync, unlinkSync as unlinkSync$1, readdirSync as readdirSync$1, watch, rmdirSync } from 'fs';
|
|
4
|
-
import path__default, { join as join$1, resolve, dirname as dirname$1, basename as basename$1 } from 'path';
|
|
3
|
+
import { readFileSync as readFileSync$1, mkdirSync as mkdirSync$1, writeFileSync as writeFileSync$1, renameSync as renameSync$1, existsSync as existsSync$1, realpathSync as realpathSync$1, rmSync as rmSync$1, copyFileSync, unlinkSync as unlinkSync$1, readdirSync as readdirSync$1, watch, rmdirSync } from 'fs';
|
|
4
|
+
import path__default, { join as join$1, resolve as resolve$1, dirname as dirname$1, basename as basename$1 } from 'path';
|
|
5
5
|
import { fileURLToPath } from 'url';
|
|
6
6
|
import { execFile, spawn as spawn$1, execSync as execSync$1, spawnSync } from 'child_process';
|
|
7
7
|
import { randomUUID as randomUUID$1 } from 'crypto';
|
|
8
8
|
import { randomBytes, createHash, randomUUID } from 'node:crypto';
|
|
9
|
-
import { existsSync, readFileSync,
|
|
9
|
+
import { existsSync, readFileSync, realpathSync, readdirSync, statSync, mkdirSync, writeFileSync, renameSync, rmSync, appendFileSync, unlinkSync } from 'node:fs';
|
|
10
10
|
import { exec, execSync, spawn, execFile as execFile$1, execFileSync } from 'node:child_process';
|
|
11
11
|
import { promisify } from 'util';
|
|
12
|
-
import { join, basename, dirname } from 'node:path';
|
|
12
|
+
import { extname, resolve, join, sep, basename, dirname } from 'node:path';
|
|
13
13
|
import { EventEmitter } from 'node:events';
|
|
14
14
|
import os, { homedir, platform } from 'node:os';
|
|
15
15
|
import { ndJsonStream, ClientSideConnection } from '@agentclientprotocol/sdk';
|
|
@@ -1233,6 +1233,155 @@ function renderTemplate(template, ctx) {
|
|
|
1233
1233
|
});
|
|
1234
1234
|
}
|
|
1235
1235
|
|
|
1236
|
+
const HARD_MAX_BYTES = 25 * 1024 * 1024;
|
|
1237
|
+
const DEFAULT_MAX_BYTES = 5 * 1024 * 1024;
|
|
1238
|
+
const DEFAULT_MAX_COUNT = 100;
|
|
1239
|
+
const DEFAULT_ALLOWED_EXT = [
|
|
1240
|
+
".png",
|
|
1241
|
+
".jpg",
|
|
1242
|
+
".jpeg",
|
|
1243
|
+
".gif",
|
|
1244
|
+
".webp",
|
|
1245
|
+
".bmp",
|
|
1246
|
+
".svg",
|
|
1247
|
+
".pdf",
|
|
1248
|
+
".txt",
|
|
1249
|
+
".md",
|
|
1250
|
+
".csv",
|
|
1251
|
+
".json",
|
|
1252
|
+
".log",
|
|
1253
|
+
".yaml",
|
|
1254
|
+
".yml"
|
|
1255
|
+
];
|
|
1256
|
+
function uploadEnabled(c) {
|
|
1257
|
+
return !!(c && c.upload && c.upload.enabled === true);
|
|
1258
|
+
}
|
|
1259
|
+
function effectiveUploadConfig(c) {
|
|
1260
|
+
const u = c.upload || {};
|
|
1261
|
+
const maxBytes = Math.min(
|
|
1262
|
+
typeof u.maxBytes === "number" && u.maxBytes > 0 ? u.maxBytes : DEFAULT_MAX_BYTES,
|
|
1263
|
+
HARD_MAX_BYTES
|
|
1264
|
+
);
|
|
1265
|
+
const maxCount = typeof u.maxCount === "number" && u.maxCount > 0 ? Math.floor(u.maxCount) : DEFAULT_MAX_COUNT;
|
|
1266
|
+
const allowedExt = Array.isArray(u.allowedExt) ? u.allowedExt.map((e) => String(e).toLowerCase().trim()).filter(Boolean) : DEFAULT_ALLOWED_EXT;
|
|
1267
|
+
return { ...u, maxBytes, maxCount, allowedExt };
|
|
1268
|
+
}
|
|
1269
|
+
function validateUploadConfig(c) {
|
|
1270
|
+
const u = c.upload;
|
|
1271
|
+
if (u == null) return [];
|
|
1272
|
+
if (typeof u !== "object") return ["upload must be an object"];
|
|
1273
|
+
const errs = [];
|
|
1274
|
+
if (u.enabled != null && typeof u.enabled !== "boolean") errs.push("upload.enabled must be a boolean");
|
|
1275
|
+
if (u.maxBytes != null && (typeof u.maxBytes !== "number" || u.maxBytes <= 0)) errs.push("upload.maxBytes must be a positive number");
|
|
1276
|
+
if (u.maxCount != null && (typeof u.maxCount !== "number" || u.maxCount <= 0)) errs.push("upload.maxCount must be a positive number");
|
|
1277
|
+
if (u.allowedExt != null && !Array.isArray(u.allowedExt)) errs.push("upload.allowedExt must be an array of extensions");
|
|
1278
|
+
if (u.allowedMime != null && !Array.isArray(u.allowedMime)) errs.push("upload.allowedMime must be an array of mime types");
|
|
1279
|
+
if (u.dir != null) {
|
|
1280
|
+
if (typeof u.dir !== "string") errs.push("upload.dir must be a string");
|
|
1281
|
+
else if (u.dir.startsWith("/") || u.dir.startsWith("\\") || /(^|[\\/])\.\.([\\/]|$)/.test(u.dir) || u.dir.includes("\0"))
|
|
1282
|
+
errs.push('upload.dir must be a project-relative path without ".." traversal');
|
|
1283
|
+
}
|
|
1284
|
+
return errs;
|
|
1285
|
+
}
|
|
1286
|
+
const CONTROL_CHARS = /[\x00-\x1f\x7f]/;
|
|
1287
|
+
function sanitizeFilename(raw) {
|
|
1288
|
+
const input = String(raw ?? "").trim();
|
|
1289
|
+
if (!input) return { error: "filename required" };
|
|
1290
|
+
if (input.length > 200) return { error: "filename too long (max 200 chars)" };
|
|
1291
|
+
if (CONTROL_CHARS.test(input)) return { error: "filename contains control characters" };
|
|
1292
|
+
if (input.includes("\0")) return { error: "filename contains null byte" };
|
|
1293
|
+
if (input.includes("/") || input.includes("\\")) return { error: "filename must not contain path separators" };
|
|
1294
|
+
if (input.includes("..")) return { error: 'filename must not contain ".."' };
|
|
1295
|
+
const name = basename(input);
|
|
1296
|
+
if (!name || name === "." || name === "..") return { error: "invalid filename" };
|
|
1297
|
+
if (name.startsWith(".")) return { error: "filename must not start with a dot" };
|
|
1298
|
+
if (!/^[A-Za-z0-9 ._-]+$/.test(name)) return { error: "filename has disallowed characters (use letters, digits, space, . _ -)" };
|
|
1299
|
+
return { name };
|
|
1300
|
+
}
|
|
1301
|
+
function validateUpload(input) {
|
|
1302
|
+
const { projectDir, channel, bytes, contentType } = input;
|
|
1303
|
+
if (!uploadEnabled(channel)) return { error: "uploads are not enabled on this channel" };
|
|
1304
|
+
const cfg = effectiveUploadConfig(channel);
|
|
1305
|
+
const fn = sanitizeFilename(input.filename);
|
|
1306
|
+
if (fn.error || !fn.name) return { error: fn.error || "invalid filename" };
|
|
1307
|
+
const name = fn.name;
|
|
1308
|
+
if (!Number.isFinite(bytes) || bytes < 0) return { error: "invalid file size" };
|
|
1309
|
+
if (bytes === 0) return { error: "empty file" };
|
|
1310
|
+
if (bytes > cfg.maxBytes) return { error: `file too large (${bytes} bytes > ${cfg.maxBytes} limit)` };
|
|
1311
|
+
const ext = extname(name).toLowerCase();
|
|
1312
|
+
if (!ext) return { error: "file has no extension" };
|
|
1313
|
+
if (!cfg.allowedExt.includes(ext)) return { error: `file type not allowed: ${ext} (allowed: ${cfg.allowedExt.join(", ") || "none"})` };
|
|
1314
|
+
if (Array.isArray(cfg.allowedMime) && cfg.allowedMime.length) {
|
|
1315
|
+
const ct = String(contentType || "").toLowerCase().split(";")[0].trim();
|
|
1316
|
+
if (!ct) return { error: "content-type required (channel restricts MIME types)" };
|
|
1317
|
+
if (!cfg.allowedMime.map((m) => String(m).toLowerCase().trim()).includes(ct))
|
|
1318
|
+
return { error: `mime type not allowed: ${ct}` };
|
|
1319
|
+
}
|
|
1320
|
+
let projectReal;
|
|
1321
|
+
try {
|
|
1322
|
+
projectReal = realpathSync(projectDir);
|
|
1323
|
+
} catch {
|
|
1324
|
+
projectReal = resolve(projectDir);
|
|
1325
|
+
}
|
|
1326
|
+
const relDir = cfg.dir && String(cfg.dir).trim() ? String(cfg.dir).trim() : join(".svamp", "channels", "uploads", String(channel.id || "unknown"));
|
|
1327
|
+
const destDir = resolve(projectReal, relDir);
|
|
1328
|
+
if (destDir !== projectReal && !destDir.startsWith(projectReal + sep))
|
|
1329
|
+
return { error: "upload destination escapes the project folder" };
|
|
1330
|
+
const fullPath = join(destDir, name);
|
|
1331
|
+
if (fullPath !== destDir && !fullPath.startsWith(destDir + sep))
|
|
1332
|
+
return { error: "upload path escapes the destination directory" };
|
|
1333
|
+
try {
|
|
1334
|
+
if (existsSync(destDir)) {
|
|
1335
|
+
const count = readdirSync(destDir).filter((f) => {
|
|
1336
|
+
try {
|
|
1337
|
+
return statSync(join(destDir, f)).isFile();
|
|
1338
|
+
} catch {
|
|
1339
|
+
return false;
|
|
1340
|
+
}
|
|
1341
|
+
}).length;
|
|
1342
|
+
if (count >= cfg.maxCount) return { error: `upload limit reached (${cfg.maxCount} files)` };
|
|
1343
|
+
}
|
|
1344
|
+
} catch {
|
|
1345
|
+
}
|
|
1346
|
+
return { target: { destDir, name, fullPath } };
|
|
1347
|
+
}
|
|
1348
|
+
function writeUpload(projectDir, target, data) {
|
|
1349
|
+
mkdirSync(target.destDir, { recursive: true });
|
|
1350
|
+
let finalName = target.name;
|
|
1351
|
+
let finalPath = target.fullPath;
|
|
1352
|
+
if (existsSync(finalPath)) {
|
|
1353
|
+
const ext = extname(target.name);
|
|
1354
|
+
const stem = target.name.slice(0, target.name.length - ext.length);
|
|
1355
|
+
finalName = `${stem}-${randomBytes(3).toString("hex")}${ext}`;
|
|
1356
|
+
finalPath = join(target.destDir, finalName);
|
|
1357
|
+
}
|
|
1358
|
+
const tmp = finalPath + ".tmp-" + randomBytes(4).toString("hex");
|
|
1359
|
+
writeFileSync(tmp, data);
|
|
1360
|
+
renameSync(tmp, finalPath);
|
|
1361
|
+
let projectReal;
|
|
1362
|
+
try {
|
|
1363
|
+
projectReal = realpathSync(projectDir);
|
|
1364
|
+
} catch {
|
|
1365
|
+
projectReal = resolve(projectDir);
|
|
1366
|
+
}
|
|
1367
|
+
const relPath = finalPath.startsWith(projectReal + sep) ? finalPath.slice(projectReal.length + 1) : finalPath;
|
|
1368
|
+
return { name: finalName, relPath, fullPath: finalPath, bytes: data.length };
|
|
1369
|
+
}
|
|
1370
|
+
function decodeBase64Capped(b64, maxBytes) {
|
|
1371
|
+
const s = String(b64 ?? "");
|
|
1372
|
+
if (!s) return { error: "empty file content" };
|
|
1373
|
+
if (s.length > Math.ceil(maxBytes / 3) * 4 + 16) return { error: `file too large (exceeds ${maxBytes} byte limit)` };
|
|
1374
|
+
let data;
|
|
1375
|
+
try {
|
|
1376
|
+
data = Buffer.from(s, "base64");
|
|
1377
|
+
} catch {
|
|
1378
|
+
return { error: "invalid base64 content" };
|
|
1379
|
+
}
|
|
1380
|
+
if (!data.length) return { error: "invalid or empty base64 content" };
|
|
1381
|
+
if (data.length > maxBytes) return { error: `file too large (${data.length} bytes > ${maxBytes} limit)` };
|
|
1382
|
+
return { data };
|
|
1383
|
+
}
|
|
1384
|
+
|
|
1236
1385
|
const genId = () => "c_" + randomBytes(5).toString("hex");
|
|
1237
1386
|
const genKey = () => "ck_" + randomBytes(18).toString("base64url");
|
|
1238
1387
|
const DEFAULT_TEMPLATE = `<inbound-message from="\${sender.name}" sender-type="\${sender.kind}" verified="\${sender.verified}" channel="\${channel.name}" call-id="\${call.id}" at="\${now}">
|
|
@@ -1268,6 +1417,7 @@ function validateChannel(c) {
|
|
|
1268
1417
|
if (c.skill?.description && unsafe.test(c.skill.description)) errs.push(`skill.description must be single-line and not contain < > " ' &`);
|
|
1269
1418
|
if (m === "fixed" && c.identity.fixed?.name && unsafe.test(c.identity.fixed.name)) errs.push(`identity.fixed.name must not contain < > " ' & or newlines`);
|
|
1270
1419
|
for (const cl of c.identity?.callers || []) if (unsafe.test(cl.name || "")) errs.push(`caller name "${cl.name}" must not contain < > " ' & or newlines`);
|
|
1420
|
+
errs.push(...validateUploadConfig(c));
|
|
1271
1421
|
return errs;
|
|
1272
1422
|
}
|
|
1273
1423
|
function normalizeBind(c) {
|
|
@@ -1377,6 +1527,7 @@ function generateSkillBody(channel, ctx) {
|
|
|
1377
1527
|
const gw = ctx?.channelsServiceId ? gatewayBase(svc, base) : `${base}/<workspace>/services/<machine>:channels`;
|
|
1378
1528
|
const skillUrl = `${gw}/skill?channel=${channel.id}`;
|
|
1379
1529
|
const sendUrl = `${gw}/send`;
|
|
1530
|
+
const uploadUrl = `${gw}/upload`;
|
|
1380
1531
|
const key = ctx?.key || "<your-key>";
|
|
1381
1532
|
const isAgent = channel.action?.kind === "agent";
|
|
1382
1533
|
const isQueue = channel.reply?.mode === "queue";
|
|
@@ -1422,6 +1573,47 @@ to \`send()\`. The reply is then delivered straight to **your session's inbox**
|
|
|
1422
1573
|
channel's outbox and you must poll \`receive()\` (above) for it \u2014 it will **not** appear
|
|
1423
1574
|
in your inbox.` : "";
|
|
1424
1575
|
const rpcAuthNote = hyphaOpen ? `Your verified Hypha identity is accepted \u2014 no key needed.` : `Uses your verified Hypha identity.`;
|
|
1576
|
+
const uploadSection = uploadEnabled(channel) ? (() => {
|
|
1577
|
+
const u = effectiveUploadConfig(channel);
|
|
1578
|
+
const mb = (u.maxBytes / (1024 * 1024)).toFixed(u.maxBytes % (1024 * 1024) === 0 ? 0 : 1);
|
|
1579
|
+
const exts = u.allowedExt.join(", ") || "(none)";
|
|
1580
|
+
const mimeLine = Array.isArray(u.allowedMime) && u.allowedMime.length ? `
|
|
1581
|
+
- **Allowed MIME types:** ${u.allowedMime.join(", ")}` : "";
|
|
1582
|
+
return `
|
|
1583
|
+
|
|
1584
|
+
## Uploading a file
|
|
1585
|
+
This channel **accepts file uploads** (server-validated, deny-by-default elsewhere).
|
|
1586
|
+
Send the file base64-encoded; the server validates it and saves it into the session's
|
|
1587
|
+
project folder, returning the saved relative path. Reference that path in a follow-up
|
|
1588
|
+
\`send()\` so the agent knows what you uploaded.
|
|
1589
|
+
|
|
1590
|
+
**Limits (enforced server-side):**
|
|
1591
|
+
- **Max size:** ${mb} MiB per file
|
|
1592
|
+
- **Max files retained:** ${u.maxCount}
|
|
1593
|
+
- **Allowed extensions:** ${exts}${mimeLine}
|
|
1594
|
+
- Filenames are sanitized to a safe basename \u2014 no paths, no \`..\` traversal.
|
|
1595
|
+
|
|
1596
|
+
### Hypha RPC
|
|
1597
|
+
\`\`\`js
|
|
1598
|
+
const res = await get_service("${svc}").upload({
|
|
1599
|
+
channel: "${channel.id}",
|
|
1600
|
+
filename: "report.pdf",
|
|
1601
|
+
content_base64: "<base64 of the file bytes>",
|
|
1602
|
+
content_type: "application/pdf",
|
|
1603
|
+
from: "your-name"${rSession ? `,
|
|
1604
|
+
session: "${rSession}"` : ""}${hyphaOpen ? "" : `,
|
|
1605
|
+
key: "${key}"`}
|
|
1606
|
+
});
|
|
1607
|
+
// \u2192 { ok: true, name, path, bytes }
|
|
1608
|
+
\`\`\`
|
|
1609
|
+
|
|
1610
|
+
### HTTP
|
|
1611
|
+
\`\`\`bash
|
|
1612
|
+
curl -X POST "${uploadUrl}" \\
|
|
1613
|
+
-H 'Content-Type: application/json' \\
|
|
1614
|
+
-d '{"kwargs": {"channel": "${channel.id}", "filename": "report.pdf", "content_base64": "<base64>", "content_type": "application/pdf", "from": "your-name", "key": "${key}"}}'
|
|
1615
|
+
\`\`\``;
|
|
1616
|
+
})() : "";
|
|
1425
1617
|
return `---
|
|
1426
1618
|
name: ${name}
|
|
1427
1619
|
description: ${desc}
|
|
@@ -1454,7 +1646,7 @@ curl -X POST "${sendUrl}" \\
|
|
|
1454
1646
|
-d '{"kwargs": {"channel": "${channel.id}", "message": "your message here", "from": "your-name", "key": "${key}"${sessionKv}}}'
|
|
1455
1647
|
\`\`\`
|
|
1456
1648
|
|
|
1457
|
-
Always-current copy of this skill (all ids filled in): ${skillUrl}${queueSection}`;
|
|
1649
|
+
Always-current copy of this skill (all ids filled in): ${skillUrl}${uploadSection}${queueSection}`;
|
|
1458
1650
|
}
|
|
1459
1651
|
|
|
1460
1652
|
function resolveSender(channel, input = {}) {
|
|
@@ -2720,7 +2912,7 @@ async function registerMachineService(server, machineId, metadata, daemonState,
|
|
|
2720
2912
|
const tunnels = handlers.tunnels;
|
|
2721
2913
|
if (!tunnels) throw new Error("Tunnel management not available");
|
|
2722
2914
|
if (tunnels.has(params.name)) throw new Error(`Tunnel '${params.name}' already running`);
|
|
2723
|
-
const { FrpcTunnel } = await import('./frpc-
|
|
2915
|
+
const { FrpcTunnel } = await import('./frpc-BgabHfqV.mjs');
|
|
2724
2916
|
const tunnel = new FrpcTunnel({
|
|
2725
2917
|
name: params.name,
|
|
2726
2918
|
ports: params.ports,
|
|
@@ -3167,7 +3359,7 @@ QUESTION: ${params.question || "Summarize this concisely."}` }
|
|
|
3167
3359
|
}
|
|
3168
3360
|
const deps = buildSessionDeps(rpc, { cwd, ownerEmail: owner });
|
|
3169
3361
|
const sender = { name: context?.user?.email || context?.user?.id || "user", kind: "user", verified: true };
|
|
3170
|
-
const { toolsForRole } = await import('./sideband-
|
|
3362
|
+
const { toolsForRole } = await import('./sideband-BtZMx9Af.mjs');
|
|
3171
3363
|
const r2 = await runWiseAgent({ message: params.message, sender, config: { tools: toolsForRole(role2) }, deps, transport, model: resolved.model });
|
|
3172
3364
|
return fmt(r2);
|
|
3173
3365
|
}
|
|
@@ -3266,7 +3458,7 @@ QUESTION: ${params.question || "Summarize this concisely."}` }
|
|
|
3266
3458
|
if (r.error || !r.sender) return { error: r.error || "unauthorized" };
|
|
3267
3459
|
const callId = "call_" + Math.random().toString(16).slice(2, 12);
|
|
3268
3460
|
const rendered = renderMessage(c, { sender: r.sender, body: { message: kwargs.message }, callId });
|
|
3269
|
-
const { queryCore } = await import('./commands-
|
|
3461
|
+
const { queryCore } = await import('./commands-Bxb8oEBa.mjs');
|
|
3270
3462
|
const timeout = c.reply?.timeout_sec || 120;
|
|
3271
3463
|
let result;
|
|
3272
3464
|
try {
|
|
@@ -3371,6 +3563,44 @@ ${d?.error || "not found"}`;
|
|
|
3371
3563
|
}
|
|
3372
3564
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
3373
3565
|
}
|
|
3566
|
+
},
|
|
3567
|
+
// Safety-restricted file upload (#0093). Deny-by-default: only channels whose
|
|
3568
|
+
// config sets upload.enabled accept files. The upload is a pure, validated file
|
|
3569
|
+
// write into the channel's project folder — no agent run — so we do NOT spawn a
|
|
3570
|
+
// stateless one-shot; we resolve the channel + dir from disk and write directly,
|
|
3571
|
+
// which works whether or not a live session hosts the channel. All safety checks
|
|
3572
|
+
// (filename/size/extension/MIME/count/path-confinement) live in channel/upload.ts.
|
|
3573
|
+
upload: async (kwargs = {}, context) => {
|
|
3574
|
+
trackInbound();
|
|
3575
|
+
if (!kwargs.channel) return { error: MISSING_CHANNEL_HINT };
|
|
3576
|
+
const found = readChannelFromDisk(kwargs.channel);
|
|
3577
|
+
if (!found) return { error: "channel not found" };
|
|
3578
|
+
const { c, dir } = found;
|
|
3579
|
+
if (!uploadEnabled(c)) return { error: "uploads are not enabled on this channel" };
|
|
3580
|
+
const u = context?.user;
|
|
3581
|
+
const r = resolveSender(c, {
|
|
3582
|
+
key: kwargs.key,
|
|
3583
|
+
from: kwargs.from,
|
|
3584
|
+
hyphaUser: u && u.is_anonymous !== true ? u.email || u.id : void 0,
|
|
3585
|
+
hyphaAnonymous: u?.is_anonymous === true,
|
|
3586
|
+
hyphaWorkspace: u?.scope?.current_workspace
|
|
3587
|
+
});
|
|
3588
|
+
if (r.error || !r.sender) return { error: r.error || "unauthorized" };
|
|
3589
|
+
const cfg = effectiveUploadConfig(c);
|
|
3590
|
+
const dec = decodeBase64Capped(kwargs.content_base64, cfg.maxBytes);
|
|
3591
|
+
if (dec.error || !dec.data) return { error: dec.error || "invalid content" };
|
|
3592
|
+
const v = validateUpload({ projectDir: dir, channel: c, filename: kwargs.filename, bytes: dec.data.length, contentType: kwargs.content_type });
|
|
3593
|
+
if (v.error || !v.target) return { error: v.error || "upload rejected" };
|
|
3594
|
+
try {
|
|
3595
|
+
const saved = writeUpload(dir, v.target, dec.data);
|
|
3596
|
+
try {
|
|
3597
|
+
new ChannelStore(dir).recordCall(c.id, { sender: r.sender.name, verified: r.sender.verified, callId: "up_" + Math.random().toString(16).slice(2, 10), outcome: "uploaded" });
|
|
3598
|
+
} catch {
|
|
3599
|
+
}
|
|
3600
|
+
return { ok: true, name: saved.name, path: saved.relPath, bytes: saved.bytes };
|
|
3601
|
+
} catch (e) {
|
|
3602
|
+
return { ok: false, error: e?.message || String(e) };
|
|
3603
|
+
}
|
|
3374
3604
|
}
|
|
3375
3605
|
},
|
|
3376
3606
|
{ overwrite: true }
|
|
@@ -3536,6 +3766,32 @@ function applyInboxClear(inbox, opts) {
|
|
|
3536
3766
|
return { kept, removed: inbox.length - kept.length };
|
|
3537
3767
|
}
|
|
3538
3768
|
|
|
3769
|
+
function inboxFilePath(projectDir, sessionId) {
|
|
3770
|
+
return join(projectDir, ".svamp", sessionId, "inbox.json");
|
|
3771
|
+
}
|
|
3772
|
+
function loadInbox(projectDir, sessionId) {
|
|
3773
|
+
try {
|
|
3774
|
+
const p = inboxFilePath(projectDir, sessionId);
|
|
3775
|
+
if (!existsSync(p)) return [];
|
|
3776
|
+
const data = JSON.parse(readFileSync(p, "utf8"));
|
|
3777
|
+
if (Array.isArray(data)) return data;
|
|
3778
|
+
if (data && Array.isArray(data.messages)) return data.messages;
|
|
3779
|
+
return [];
|
|
3780
|
+
} catch {
|
|
3781
|
+
return [];
|
|
3782
|
+
}
|
|
3783
|
+
}
|
|
3784
|
+
function saveInbox(projectDir, sessionId, inbox) {
|
|
3785
|
+
try {
|
|
3786
|
+
const p = inboxFilePath(projectDir, sessionId);
|
|
3787
|
+
mkdirSync(dirname(p), { recursive: true });
|
|
3788
|
+
const tmp = `${p}.tmp-${process.pid}`;
|
|
3789
|
+
writeFileSync(tmp, JSON.stringify(inbox));
|
|
3790
|
+
renameSync(tmp, p);
|
|
3791
|
+
} catch {
|
|
3792
|
+
}
|
|
3793
|
+
}
|
|
3794
|
+
|
|
3539
3795
|
function envInt(name, fallback) {
|
|
3540
3796
|
const raw = process.env[name];
|
|
3541
3797
|
if (raw === void 0 || raw === "") return fallback;
|
|
@@ -3760,7 +4016,9 @@ var claudeAuth = /*#__PURE__*/Object.freeze({
|
|
|
3760
4016
|
|
|
3761
4017
|
const PARTICIPANTS_CHANNEL_ID = "sys-participants";
|
|
3762
4018
|
function channelPublicView(c) {
|
|
3763
|
-
|
|
4019
|
+
const u = c.upload;
|
|
4020
|
+
const upload = u && u.enabled === true ? { enabled: true, ...typeof u.maxBytes === "number" ? { maxBytes: u.maxBytes } : {}, ...Array.isArray(u.allowedExt) ? { allowedExt: u.allowedExt } : {} } : void 0;
|
|
4021
|
+
return { id: c.id, name: c.name, description: c.description, identity: { mode: c.identity?.mode }, action: c.action?.kind, bind: c.bind, ...upload ? { upload } : {} };
|
|
3764
4022
|
}
|
|
3765
4023
|
function isStructuredMessage(msg) {
|
|
3766
4024
|
return !!(msg.from || msg.fromSession || msg.subject || msg.replyTo || msg.threadId || msg.channel);
|
|
@@ -3933,9 +4191,16 @@ function createSessionStore(server, sessionId, initialMetadata, initialAgentStat
|
|
|
3933
4191
|
mode: "remote",
|
|
3934
4192
|
time: Date.now()
|
|
3935
4193
|
};
|
|
3936
|
-
const inbox =
|
|
4194
|
+
const inbox = loadInbox(metadata.path || process.cwd(), sessionId);
|
|
3937
4195
|
const INBOX_MAX = 100;
|
|
4196
|
+
const persistInbox = () => {
|
|
4197
|
+
try {
|
|
4198
|
+
saveInbox(metadata.path || process.cwd(), sessionId, inbox);
|
|
4199
|
+
} catch {
|
|
4200
|
+
}
|
|
4201
|
+
};
|
|
3938
4202
|
const syncInboxToMetadata = () => {
|
|
4203
|
+
persistInbox();
|
|
3939
4204
|
metadata.inbox = inbox.map((m) => ({
|
|
3940
4205
|
messageId: m.messageId,
|
|
3941
4206
|
body: m.body,
|
|
@@ -4554,6 +4819,40 @@ function createSessionStore(server, sessionId, initialMetadata, initialAgentStat
|
|
|
4554
4819
|
return { ok: false, call_id: callId, status: "error", error: e?.message || String(e) };
|
|
4555
4820
|
}
|
|
4556
4821
|
},
|
|
4822
|
+
// Safety-restricted file upload (#0093). Deny-by-default: a channel accepts
|
|
4823
|
+
// uploads ONLY when its config sets upload.enabled. Auth = the channel's OWN
|
|
4824
|
+
// identity policy (resolveSender), same as channelSend. All validation is
|
|
4825
|
+
// server-side (channel/upload.ts): filename sanitization (no traversal),
|
|
4826
|
+
// size cap, extension/MIME allowlist, file-count cap, path confinement.
|
|
4827
|
+
channelUpload: async (params, context) => {
|
|
4828
|
+
const c = channelStore.get(params.channel);
|
|
4829
|
+
if (!c || c.enabled === false) return { error: "channel not found" };
|
|
4830
|
+
if (!uploadEnabled(c)) return { error: "uploads are not enabled on this channel" };
|
|
4831
|
+
const u = context?.user;
|
|
4832
|
+
const r = resolveSender(c, {
|
|
4833
|
+
key: params.key,
|
|
4834
|
+
from: params.from,
|
|
4835
|
+
hyphaUser: u && u.is_anonymous !== true ? u.email || u.id : void 0,
|
|
4836
|
+
hyphaAnonymous: u?.is_anonymous === true,
|
|
4837
|
+
hyphaWorkspace: u?.scope?.current_workspace
|
|
4838
|
+
});
|
|
4839
|
+
if (r.error || !r.sender) return { error: r.error || "unauthorized" };
|
|
4840
|
+
const cfg2 = effectiveUploadConfig(c);
|
|
4841
|
+
const dec = decodeBase64Capped(params.content_base64, cfg2.maxBytes);
|
|
4842
|
+
if (dec.error || !dec.data) return { error: dec.error || "invalid content" };
|
|
4843
|
+
const v = validateUpload({ projectDir: metadata.path, channel: c, filename: params.filename, bytes: dec.data.length, contentType: params.content_type });
|
|
4844
|
+
if (v.error || !v.target) return { error: v.error || "upload rejected" };
|
|
4845
|
+
const callId = "call_" + randomUUID().slice(0, 10);
|
|
4846
|
+
try {
|
|
4847
|
+
const saved = writeUpload(metadata.path, v.target, dec.data);
|
|
4848
|
+
channelStore.recordCall(c.id, { sender: r.sender.name, verified: r.sender.verified, callId, outcome: "uploaded" });
|
|
4849
|
+
syncChannelsToMetadata();
|
|
4850
|
+
return { ok: true, name: saved.name, path: saved.relPath, bytes: saved.bytes };
|
|
4851
|
+
} catch (e) {
|
|
4852
|
+
channelStore.recordCall(c.id, { sender: r.sender.name, verified: r.sender.verified, callId, outcome: "error" });
|
|
4853
|
+
return { ok: false, error: e?.message || String(e) };
|
|
4854
|
+
}
|
|
4855
|
+
},
|
|
4557
4856
|
// Agent/owner answers a queued (async) channel message → channel outbox, addressed
|
|
4558
4857
|
// to the original external caller. Routed here by `inbox reply` for channel-origin
|
|
4559
4858
|
// inbox messages (which carry channelId + correlationId + from). Owner-gated since
|
|
@@ -8047,9 +8346,9 @@ var GeminiTransport$1 = /*#__PURE__*/Object.freeze({
|
|
|
8047
8346
|
function resolveTranscriptPath(cwd, claudeSessionId) {
|
|
8048
8347
|
let real;
|
|
8049
8348
|
try {
|
|
8050
|
-
real = realpathSync(cwd);
|
|
8349
|
+
real = realpathSync$1(cwd);
|
|
8051
8350
|
} catch {
|
|
8052
|
-
real = resolve(cwd);
|
|
8351
|
+
real = resolve$1(cwd);
|
|
8053
8352
|
}
|
|
8054
8353
|
const projectId = real.replace(/[^a-zA-Z0-9-]/g, "-");
|
|
8055
8354
|
const claudeConfigDir = process.env.CLAUDE_CONFIG_DIR || join$1(os$1.homedir(), ".claude");
|
|
@@ -11631,7 +11930,7 @@ async function startDaemon(options) {
|
|
|
11631
11930
|
saveExposedTunnels(list);
|
|
11632
11931
|
}
|
|
11633
11932
|
async function createExposedTunnel(spec) {
|
|
11634
|
-
const { FrpcTunnel } = await import('./frpc-
|
|
11933
|
+
const { FrpcTunnel } = await import('./frpc-BgabHfqV.mjs');
|
|
11635
11934
|
const tunnel = new FrpcTunnel({
|
|
11636
11935
|
name: spec.name,
|
|
11637
11936
|
ports: spec.ports,
|
|
@@ -11651,7 +11950,7 @@ async function startDaemon(options) {
|
|
|
11651
11950
|
return tunnel;
|
|
11652
11951
|
}
|
|
11653
11952
|
const tunnelRecreateState = /* @__PURE__ */ new Map();
|
|
11654
|
-
const { ServeManager } = await import('./serveManager-
|
|
11953
|
+
const { ServeManager } = await import('./serveManager-CCslS9Yt.mjs');
|
|
11655
11954
|
const serveManager = new ServeManager(SVAMP_HOME, (msg) => logger.log(`[SERVE] ${msg}`), hyphaServerUrl);
|
|
11656
11955
|
ensureAutoInstalledSkills(logger).catch(() => {
|
|
11657
11956
|
});
|
|
@@ -13516,11 +13815,11 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
|
|
|
13516
13815
|
});
|
|
13517
13816
|
},
|
|
13518
13817
|
onIssue: async (params) => {
|
|
13519
|
-
const { issueRpc } = await import('./rpc-
|
|
13818
|
+
const { issueRpc } = await import('./rpc-C35Y8Vto.mjs');
|
|
13520
13819
|
return issueRpc(params?.cwd || directory, params || {}, { notifySession: notifyIssueOwner });
|
|
13521
13820
|
},
|
|
13522
13821
|
onWorkflow: async (params) => {
|
|
13523
|
-
const { workflowRpc } = await import('./rpc-
|
|
13822
|
+
const { workflowRpc } = await import('./rpc-DlM7ml1e.mjs');
|
|
13524
13823
|
return workflowRpc(params?.cwd || directory, params || {});
|
|
13525
13824
|
},
|
|
13526
13825
|
onRipgrep: async (args, cwd) => {
|
|
@@ -13537,23 +13836,23 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
|
|
|
13537
13836
|
});
|
|
13538
13837
|
},
|
|
13539
13838
|
onReadFile: async (path) => {
|
|
13540
|
-
const resolvedPath = resolve(directory, path);
|
|
13541
|
-
if (sessionMetadata.securityContext && resolvedPath !== resolve(directory) && !resolvedPath.startsWith(resolve(directory) + "/")) {
|
|
13839
|
+
const resolvedPath = resolve$1(directory, path);
|
|
13840
|
+
if (sessionMetadata.securityContext && resolvedPath !== resolve$1(directory) && !resolvedPath.startsWith(resolve$1(directory) + "/")) {
|
|
13542
13841
|
throw new Error("Path outside working directory");
|
|
13543
13842
|
}
|
|
13544
13843
|
return await readSessionFileBase64(resolvedPath);
|
|
13545
13844
|
},
|
|
13546
13845
|
onWriteFile: async (path, content) => {
|
|
13547
|
-
const resolvedPath = resolve(directory, path);
|
|
13548
|
-
if (sessionMetadata.securityContext && resolvedPath !== resolve(directory) && !resolvedPath.startsWith(resolve(directory) + "/")) {
|
|
13846
|
+
const resolvedPath = resolve$1(directory, path);
|
|
13847
|
+
if (sessionMetadata.securityContext && resolvedPath !== resolve$1(directory) && !resolvedPath.startsWith(resolve$1(directory) + "/")) {
|
|
13549
13848
|
throw new Error("Path outside working directory");
|
|
13550
13849
|
}
|
|
13551
13850
|
await fs.mkdir(dirname$1(resolvedPath), { recursive: true });
|
|
13552
13851
|
await fs.writeFile(resolvedPath, Buffer.from(content, "base64"));
|
|
13553
13852
|
},
|
|
13554
13853
|
onListDirectory: async (path) => {
|
|
13555
|
-
const resolvedDir = resolve(directory, path || ".");
|
|
13556
|
-
if (sessionMetadata.securityContext && resolvedDir !== resolve(directory) && !resolvedDir.startsWith(resolve(directory) + "/")) {
|
|
13854
|
+
const resolvedDir = resolve$1(directory, path || ".");
|
|
13855
|
+
if (sessionMetadata.securityContext && resolvedDir !== resolve$1(directory) && !resolvedDir.startsWith(resolve$1(directory) + "/")) {
|
|
13557
13856
|
throw new Error("Path outside working directory");
|
|
13558
13857
|
}
|
|
13559
13858
|
const entries = await fs.readdir(resolvedDir, { withFileTypes: true });
|
|
@@ -13591,8 +13890,8 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
|
|
|
13591
13890
|
return null;
|
|
13592
13891
|
}
|
|
13593
13892
|
}
|
|
13594
|
-
const resolvedPath = resolve(directory, treePath);
|
|
13595
|
-
if (sessionMetadata.securityContext && resolvedPath !== resolve(directory) && !resolvedPath.startsWith(resolve(directory) + "/")) {
|
|
13893
|
+
const resolvedPath = resolve$1(directory, treePath);
|
|
13894
|
+
if (sessionMetadata.securityContext && resolvedPath !== resolve$1(directory) && !resolvedPath.startsWith(resolve$1(directory) + "/")) {
|
|
13596
13895
|
throw new Error("Path outside working directory");
|
|
13597
13896
|
}
|
|
13598
13897
|
const tree = await buildTree(resolvedPath, basename$1(resolvedPath), 0);
|
|
@@ -14030,11 +14329,11 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
|
|
|
14030
14329
|
});
|
|
14031
14330
|
},
|
|
14032
14331
|
onIssue: async (params) => {
|
|
14033
|
-
const { issueRpc } = await import('./rpc-
|
|
14332
|
+
const { issueRpc } = await import('./rpc-C35Y8Vto.mjs');
|
|
14034
14333
|
return issueRpc(params?.cwd || directory, params || {}, { notifySession: notifyIssueOwner });
|
|
14035
14334
|
},
|
|
14036
14335
|
onWorkflow: async (params) => {
|
|
14037
|
-
const { workflowRpc } = await import('./rpc-
|
|
14336
|
+
const { workflowRpc } = await import('./rpc-DlM7ml1e.mjs');
|
|
14038
14337
|
return workflowRpc(params?.cwd || directory, params || {});
|
|
14039
14338
|
},
|
|
14040
14339
|
onRipgrep: async (args, cwd) => {
|
|
@@ -14051,23 +14350,23 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
|
|
|
14051
14350
|
});
|
|
14052
14351
|
},
|
|
14053
14352
|
onReadFile: async (path) => {
|
|
14054
|
-
const resolvedPath = resolve(directory, path);
|
|
14055
|
-
if (sessionMetadata.securityContext && resolvedPath !== resolve(directory) && !resolvedPath.startsWith(resolve(directory) + "/")) {
|
|
14353
|
+
const resolvedPath = resolve$1(directory, path);
|
|
14354
|
+
if (sessionMetadata.securityContext && resolvedPath !== resolve$1(directory) && !resolvedPath.startsWith(resolve$1(directory) + "/")) {
|
|
14056
14355
|
throw new Error("Path outside working directory");
|
|
14057
14356
|
}
|
|
14058
14357
|
return await readSessionFileBase64(resolvedPath);
|
|
14059
14358
|
},
|
|
14060
14359
|
onWriteFile: async (path, content) => {
|
|
14061
|
-
const resolvedPath = resolve(directory, path);
|
|
14062
|
-
if (sessionMetadata.securityContext && resolvedPath !== resolve(directory) && !resolvedPath.startsWith(resolve(directory) + "/")) {
|
|
14360
|
+
const resolvedPath = resolve$1(directory, path);
|
|
14361
|
+
if (sessionMetadata.securityContext && resolvedPath !== resolve$1(directory) && !resolvedPath.startsWith(resolve$1(directory) + "/")) {
|
|
14063
14362
|
throw new Error("Path outside working directory");
|
|
14064
14363
|
}
|
|
14065
14364
|
await fs.mkdir(dirname$1(resolvedPath), { recursive: true });
|
|
14066
14365
|
await fs.writeFile(resolvedPath, Buffer.from(content, "base64"));
|
|
14067
14366
|
},
|
|
14068
14367
|
onListDirectory: async (path) => {
|
|
14069
|
-
const resolvedDir = resolve(directory, path || ".");
|
|
14070
|
-
if (sessionMetadata.securityContext && resolvedDir !== resolve(directory) && !resolvedDir.startsWith(resolve(directory) + "/")) {
|
|
14368
|
+
const resolvedDir = resolve$1(directory, path || ".");
|
|
14369
|
+
if (sessionMetadata.securityContext && resolvedDir !== resolve$1(directory) && !resolvedDir.startsWith(resolve$1(directory) + "/")) {
|
|
14071
14370
|
throw new Error("Path outside working directory");
|
|
14072
14371
|
}
|
|
14073
14372
|
const entries = await fs.readdir(resolvedDir, { withFileTypes: true });
|
|
@@ -14105,8 +14404,8 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
|
|
|
14105
14404
|
return null;
|
|
14106
14405
|
}
|
|
14107
14406
|
}
|
|
14108
|
-
const resolvedPath = resolve(directory, treePath);
|
|
14109
|
-
if (sessionMetadata.securityContext && resolvedPath !== resolve(directory) && !resolvedPath.startsWith(resolve(directory) + "/")) {
|
|
14407
|
+
const resolvedPath = resolve$1(directory, treePath);
|
|
14408
|
+
if (sessionMetadata.securityContext && resolvedPath !== resolve$1(directory) && !resolvedPath.startsWith(resolve$1(directory) + "/")) {
|
|
14110
14409
|
throw new Error("Path outside working directory");
|
|
14111
14410
|
}
|
|
14112
14411
|
const tree = await buildTree(resolvedPath, basename$1(resolvedPath), 0);
|
|
@@ -14524,7 +14823,7 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
|
|
|
14524
14823
|
const channelHttpPort = Number(process.env.SVAMP_CHANNEL_HTTP_PORT) || 0;
|
|
14525
14824
|
if (channelHttpPort > 0) {
|
|
14526
14825
|
try {
|
|
14527
|
-
const { createChannelHttpServer } = await import('./httpServer-
|
|
14826
|
+
const { createChannelHttpServer } = await import('./httpServer-B1KVQJfm.mjs');
|
|
14528
14827
|
const channelHttpServer = createChannelHttpServer({
|
|
14529
14828
|
getSessionIds: () => {
|
|
14530
14829
|
const ids = [];
|
|
@@ -14789,7 +15088,7 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
|
|
|
14789
15088
|
const PING_TIMEOUT_MS = 15e3;
|
|
14790
15089
|
const POST_RECONNECT_GRACE_MS = 2e4;
|
|
14791
15090
|
const RECONNECT_JITTER_MS = 2500;
|
|
14792
|
-
const { WorkflowScheduler } = await import('./scheduler-
|
|
15091
|
+
const { WorkflowScheduler } = await import('./scheduler-B3hBIkt8.mjs');
|
|
14793
15092
|
const workflowScheduler = new WorkflowScheduler({
|
|
14794
15093
|
projectRoots: () => {
|
|
14795
15094
|
const dirs = /* @__PURE__ */ new Set();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import { a1 as applyClaudeProxyEnv, a2 as composeSessionId, a3 as generateFriendlyName, c as connectToHypha, a as createSessionStore, r as registerMachineService, a4 as generateHookSettings } from './run-
|
|
1
|
+
import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import { a1 as applyClaudeProxyEnv, a2 as composeSessionId, a3 as generateFriendlyName, c as connectToHypha, a as createSessionStore, r as registerMachineService, a4 as generateHookSettings } from './run-B3fosGEs.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';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { spawn } from 'node:child_process';
|
|
2
|
-
import { m as resolveProjectRoot, w as cronMatches } from './run-
|
|
2
|
+
import { m as resolveProjectRoot, w as cronMatches } from './run-B3fosGEs.mjs';
|
|
3
3
|
import { l as listWorkflows, i as isWorkflowEnabled, c as workflowCrons, w as workflowSteps } from './store-DEZ8e-uE.mjs';
|
|
4
4
|
import 'os';
|
|
5
5
|
import 'fs/promises';
|
|
@@ -54,7 +54,7 @@ async function handleServeCommand() {
|
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
async function serveAdd(args, machineId) {
|
|
57
|
-
const { connectAndGetMachine } = await import('./commands-
|
|
57
|
+
const { connectAndGetMachine } = await import('./commands-Bxb8oEBa.mjs');
|
|
58
58
|
const pos = positionalArgs(args);
|
|
59
59
|
const name = pos[0];
|
|
60
60
|
if (!name) {
|
|
@@ -93,7 +93,7 @@ async function serveAdd(args, machineId) {
|
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
95
|
async function serveApply(args, machineId) {
|
|
96
|
-
const { connectAndGetMachine } = await import('./commands-
|
|
96
|
+
const { connectAndGetMachine } = await import('./commands-Bxb8oEBa.mjs');
|
|
97
97
|
const fs = await import('fs');
|
|
98
98
|
const yaml = await import('yaml');
|
|
99
99
|
const file = positionalArgs(args)[0];
|
|
@@ -182,7 +182,7 @@ async function serveApply(args, machineId) {
|
|
|
182
182
|
}
|
|
183
183
|
}
|
|
184
184
|
async function serveRemove(args, machineId) {
|
|
185
|
-
const { connectAndGetMachine } = await import('./commands-
|
|
185
|
+
const { connectAndGetMachine } = await import('./commands-Bxb8oEBa.mjs');
|
|
186
186
|
const pos = positionalArgs(args);
|
|
187
187
|
const name = pos[0];
|
|
188
188
|
if (!name) {
|
|
@@ -202,7 +202,7 @@ async function serveRemove(args, machineId) {
|
|
|
202
202
|
}
|
|
203
203
|
}
|
|
204
204
|
async function serveList(args, machineId) {
|
|
205
|
-
const { connectAndGetMachine } = await import('./commands-
|
|
205
|
+
const { connectAndGetMachine } = await import('./commands-Bxb8oEBa.mjs');
|
|
206
206
|
const all = hasFlag(args, "--all", "-a");
|
|
207
207
|
const json = hasFlag(args, "--json");
|
|
208
208
|
const sessionId = getFlag(args, "--session");
|
|
@@ -235,7 +235,7 @@ async function serveList(args, machineId) {
|
|
|
235
235
|
}
|
|
236
236
|
}
|
|
237
237
|
async function serveInfo(machineId) {
|
|
238
|
-
const { connectAndGetMachine } = await import('./commands-
|
|
238
|
+
const { connectAndGetMachine } = await import('./commands-Bxb8oEBa.mjs');
|
|
239
239
|
const { machine, server } = await connectAndGetMachine(machineId);
|
|
240
240
|
try {
|
|
241
241
|
const info = await machine.serveInfo();
|
|
@@ -4,7 +4,7 @@ import * as fs from 'fs';
|
|
|
4
4
|
import * as http from 'http';
|
|
5
5
|
import * as net from 'net';
|
|
6
6
|
import * as path from 'path';
|
|
7
|
-
import { k as getHyphaServerUrl, S as ServeAuth, l as hasCookieToken } from './run-
|
|
7
|
+
import { k as getHyphaServerUrl, S as ServeAuth, l as hasCookieToken } from './run-B3fosGEs.mjs';
|
|
8
8
|
import 'os';
|
|
9
9
|
import 'fs/promises';
|
|
10
10
|
import 'url';
|
|
@@ -733,7 +733,7 @@ class ServeManager {
|
|
|
733
733
|
const mount = this.mounts.get(mountName);
|
|
734
734
|
const subdomainOverride = mount?.access === "link" && mount.linkToken ? /* @__PURE__ */ new Map([[this.port, buildLinkSubdomain(subdomainSafe, mount.linkToken)]]) : void 0;
|
|
735
735
|
try {
|
|
736
|
-
const { FrpcTunnel } = await import('./frpc-
|
|
736
|
+
const { FrpcTunnel } = await import('./frpc-BgabHfqV.mjs');
|
|
737
737
|
let tunnel;
|
|
738
738
|
tunnel = new FrpcTunnel({
|
|
739
739
|
name: tunnelName,
|