svamp-cli 0.2.100 → 0.2.102
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{agentCommands-muy26BZI.mjs → agentCommands-Cm-Cu_9Z.mjs} +17 -3
- package/dist/{auth-RVq9wRhV.mjs → auth-BwHB9Upd.mjs} +2 -1
- package/dist/cli.mjs +51 -50
- package/dist/{commands-Cu96nDGv.mjs → commands-Clj_0eV6.mjs} +3 -2
- package/dist/{commands-ChzeHFd3.mjs → commands-DNxxgy4V.mjs} +2 -1
- package/dist/{commands-rSREfaQg.mjs → commands-DpRXzSr9.mjs} +2 -1
- package/dist/{commands-lSqc48Ib.mjs → commands-h6yGJuJw.mjs} +5 -5
- package/dist/{commands-EwE87XNi.mjs → commands-x1wznXLf.mjs} +2 -1
- package/dist/{fleet-qN96q6Qb.mjs → fleet-Cilkj57K.mjs} +2 -1
- package/dist/{frpc-CIkmTNdJ.mjs → frpc-cJUGFtWY.mjs} +2 -1
- package/dist/{headlessCli-BVcAcLr1.mjs → headlessCli-CZEbwp47.mjs} +3 -2
- package/dist/{httpServer-wwHHk1EM.mjs → httpServer-D9qLS8ed.mjs} +56 -0
- package/dist/index.mjs +2 -1
- package/dist/{package-B7S5w1VE.mjs → package-BsbKsOb_.mjs} +2 -2
- package/dist/{run-CdtYIBbd.mjs → run-B_FyvS11.mjs} +306 -10
- package/dist/{run-zXRdkYtk.mjs → run-CW6bkzDX.mjs} +2 -1
- package/dist/{serveCommands-BZd0reEj.mjs → serveCommands-O2px1za0.mjs} +5 -5
- package/dist/{serveManager-lmPtmRnR.mjs → serveManager-B757hHGd.mjs} +3 -2
- package/dist/{sideband-JeID_jF-.mjs → sideband-DYhbiCEA.mjs} +2 -1
- package/package.json +2 -2
|
@@ -52,6 +52,62 @@ function createChannelHttpServer(deps) {
|
|
|
52
52
|
res.writeHead(200, { "content-type": "text/markdown" }).end(d.skill?.body || "");
|
|
53
53
|
return;
|
|
54
54
|
}
|
|
55
|
+
const keyOf = () => (req.headers.authorization || "").replace(/^Bearer\s+/i, "") || u.searchParams.get("key") || void 0;
|
|
56
|
+
m = u.pathname.match(/^\/channel\/([\w.-]+)\/receive$/);
|
|
57
|
+
if (m) {
|
|
58
|
+
const rpc2 = await findOwner(deps, m[1]);
|
|
59
|
+
if (!rpc2?.channelReceive) {
|
|
60
|
+
json(404, { error: "channel not found" });
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const out = await rpc2.channelReceive({
|
|
64
|
+
channel: m[1],
|
|
65
|
+
key: keyOf(),
|
|
66
|
+
from: u.searchParams.get("from") || void 0,
|
|
67
|
+
cursor: Number(u.searchParams.get("cursor") || 0),
|
|
68
|
+
correlationId: u.searchParams.get("correlationId") || void 0,
|
|
69
|
+
wait: u.searchParams.get("wait") != null ? Number(u.searchParams.get("wait")) : void 0
|
|
70
|
+
});
|
|
71
|
+
json(out?.error ? out.error === "channel not found" ? 404 : 401 : 200, out);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
m = u.pathname.match(/^\/channel\/([\w.-]+)\/events$/);
|
|
75
|
+
if (m) {
|
|
76
|
+
const rpc2 = await findOwner(deps, m[1]);
|
|
77
|
+
if (!rpc2?.channelReceive) {
|
|
78
|
+
res.writeHead(404).end("not found");
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const key = keyOf();
|
|
82
|
+
const from = u.searchParams.get("from") || void 0;
|
|
83
|
+
let cursor = Number(u.searchParams.get("cursor") || 0);
|
|
84
|
+
res.writeHead(200, { "content-type": "text/event-stream", "cache-control": "no-cache", connection: "keep-alive", "x-accel-buffering": "no" });
|
|
85
|
+
res.write(": connected\n\n");
|
|
86
|
+
let closed = false;
|
|
87
|
+
req.on("close", () => {
|
|
88
|
+
closed = true;
|
|
89
|
+
});
|
|
90
|
+
while (!closed) {
|
|
91
|
+
const out = await rpc2.channelReceive({ channel: m[1], key, from, cursor, wait: 25 });
|
|
92
|
+
if (out?.error) {
|
|
93
|
+
res.write(`event: error
|
|
94
|
+
data: ${JSON.stringify({ error: out.error })}
|
|
95
|
+
|
|
96
|
+
`);
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
for (const reply of out.replies || []) res.write(`data: ${JSON.stringify(reply)}
|
|
100
|
+
|
|
101
|
+
`);
|
|
102
|
+
cursor = out.cursor ?? cursor;
|
|
103
|
+
if (!(out.replies || []).length) res.write(": keepalive\n\n");
|
|
104
|
+
}
|
|
105
|
+
try {
|
|
106
|
+
res.end();
|
|
107
|
+
} catch {
|
|
108
|
+
}
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
55
111
|
m = u.pathname.match(/^\/channel\/([\w.-]+)$/);
|
|
56
112
|
if (!m) {
|
|
57
113
|
json(404, { error: "not found" });
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { c as connectToHypha, a as createSessionStore, d as daemonStatus, g as getHyphaServerUrl, r as registerMachineService, s as startDaemon, b as stopDaemon } from './run-
|
|
1
|
+
export { c as connectToHypha, a as createSessionStore, d as daemonStatus, g as getHyphaServerUrl, r as registerMachineService, s as startDaemon, b as stopDaemon } from './run-B_FyvS11.mjs';
|
|
2
2
|
import 'os';
|
|
3
3
|
import 'fs/promises';
|
|
4
4
|
import 'fs';
|
|
@@ -12,6 +12,7 @@ import 'util';
|
|
|
12
12
|
import 'node:crypto';
|
|
13
13
|
import 'node:path';
|
|
14
14
|
import 'node:os';
|
|
15
|
+
import 'node:events';
|
|
15
16
|
import '@agentclientprotocol/sdk';
|
|
16
17
|
import '@modelcontextprotocol/sdk/client/index.js';
|
|
17
18
|
import '@modelcontextprotocol/sdk/client/stdio.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
var name = "svamp-cli";
|
|
2
|
-
var version = "0.2.
|
|
2
|
+
var version = "0.2.102";
|
|
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 && tsc --noEmit && pkgroll",
|
|
21
21
|
typecheck: "tsc --noEmit",
|
|
22
|
-
test: "npx tsx test/test-context-window.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-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-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 && 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-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-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",
|
|
22
|
+
test: "npx tsx test/test-context-window.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-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-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 && 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-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-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",
|
|
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",
|
|
@@ -11,6 +11,7 @@ import { promisify } from 'util';
|
|
|
11
11
|
import { randomBytes, randomUUID, createHash } from 'node:crypto';
|
|
12
12
|
import { join as join$1 } from 'node:path';
|
|
13
13
|
import os, { homedir, platform } from 'node:os';
|
|
14
|
+
import { EventEmitter } from 'node:events';
|
|
14
15
|
import { ndJsonStream, ClientSideConnection } from '@agentclientprotocol/sdk';
|
|
15
16
|
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
16
17
|
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
|
|
@@ -433,6 +434,75 @@ function buildTools(deps, skills) {
|
|
|
433
434
|
}
|
|
434
435
|
return "(sent to the coding agent)";
|
|
435
436
|
}
|
|
437
|
+
},
|
|
438
|
+
// Create routine / loop / channel. ONLY call after the caller confirmed the
|
|
439
|
+
// proposed config (see the propose-then-confirm instruction in context.ts).
|
|
440
|
+
{
|
|
441
|
+
name: "create_routine",
|
|
442
|
+
readOnly: false,
|
|
443
|
+
description: "Create a session-scoped routine (cron schedule or webhook \u2192 message or loop). ONLY after the caller confirmed the proposal.",
|
|
444
|
+
parameters: { type: "object", properties: {
|
|
445
|
+
name: { type: "string", description: "Short human name." },
|
|
446
|
+
cron: { type: "string", description: 'Cron for a schedule trigger, e.g. "0 9 * * 1-5". Omit for a webhook.' },
|
|
447
|
+
tz: { type: "string", description: "IANA timezone for the schedule." },
|
|
448
|
+
action_kind: { type: "string", enum: ["message", "loop"], description: '"message" sends text to this session; "loop" starts a self-verifying loop.' },
|
|
449
|
+
message: { type: "string", description: "For message action: the text/template to deliver." },
|
|
450
|
+
task: { type: "string", description: "For loop action: the loop task." },
|
|
451
|
+
oracle: { type: "string", description: "For loop action: optional pass/fail command." }
|
|
452
|
+
}, required: ["name", "action_kind"], additionalProperties: false },
|
|
453
|
+
run: async (a) => {
|
|
454
|
+
const cron = a?.cron ? str$1(a.cron) : "";
|
|
455
|
+
const routine = {
|
|
456
|
+
name: str$1(a?.name),
|
|
457
|
+
enabled: true,
|
|
458
|
+
trigger: cron ? { type: "schedule", cron, ...a?.tz ? { tz: str$1(a.tz) } : {} } : { type: "webhook" },
|
|
459
|
+
action: str$1(a?.action_kind) === "loop" ? { kind: "loop", task_template: str$1(a?.task), loop: { task: str$1(a?.task), ...a?.oracle ? { oracle: str$1(a.oracle) } : {} } } : { kind: "message", template: str$1(a?.message) }
|
|
460
|
+
};
|
|
461
|
+
const r = await deps.saveRoutine(routine);
|
|
462
|
+
return r.success ? `Created routine "${str$1(a?.name)}" (${r.routine?.id || "saved"}).` : `Could not create routine: ${r.error || "unknown error"}.`;
|
|
463
|
+
}
|
|
464
|
+
},
|
|
465
|
+
{
|
|
466
|
+
name: "create_loop",
|
|
467
|
+
readOnly: false,
|
|
468
|
+
description: "Start a self-verifying loop in the bound session (iterates until an evaluator + optional oracle confirm done). ONLY after the caller confirmed the proposal.",
|
|
469
|
+
parameters: { type: "object", properties: {
|
|
470
|
+
task: { type: "string", description: "What the loop should accomplish." },
|
|
471
|
+
criteria: { type: "string", description: "How we know it is genuinely done." },
|
|
472
|
+
oracle: { type: "string", description: 'Optional pass/fail command (e.g. "npm test").' },
|
|
473
|
+
max_iterations: { type: "number", description: "Iteration ceiling (default 20)." }
|
|
474
|
+
}, required: ["task"], additionalProperties: false },
|
|
475
|
+
run: async (a) => {
|
|
476
|
+
await deps.startLoop({
|
|
477
|
+
task: str$1(a?.task),
|
|
478
|
+
criteria: a?.criteria ? str$1(a.criteria) : void 0,
|
|
479
|
+
oracle: a?.oracle ? str$1(a.oracle) : void 0,
|
|
480
|
+
maxIterations: typeof a?.max_iterations === "number" ? a.max_iterations : void 0
|
|
481
|
+
});
|
|
482
|
+
return `Started a loop: "${str$1(a?.task).slice(0, 80)}".`;
|
|
483
|
+
}
|
|
484
|
+
},
|
|
485
|
+
{
|
|
486
|
+
name: "create_channel",
|
|
487
|
+
readOnly: false,
|
|
488
|
+
description: "Create an inbound channel so other users/agents can message this session (identity-tagged). ONLY after the caller confirmed the proposal.",
|
|
489
|
+
parameters: { type: "object", properties: {
|
|
490
|
+
name: { type: "string", description: "Short channel name." },
|
|
491
|
+
description: { type: "string", description: "What this channel is for." },
|
|
492
|
+
identity_mode: { type: "string", enum: ["per-key", "caller-supplied", "fixed"], description: 'How callers are identified (default "per-key").' }
|
|
493
|
+
}, required: ["name"], additionalProperties: false },
|
|
494
|
+
run: async (a) => {
|
|
495
|
+
const mode = a?.identity_mode ? str$1(a.identity_mode) : "per-key";
|
|
496
|
+
const channel = {
|
|
497
|
+
name: str$1(a?.name),
|
|
498
|
+
...a?.description ? { description: str$1(a.description) } : {},
|
|
499
|
+
enabled: true,
|
|
500
|
+
identity: mode === "fixed" ? { mode, fixed: { name: "caller", kind: "agent" } } : { mode },
|
|
501
|
+
action: { kind: "message" }
|
|
502
|
+
};
|
|
503
|
+
const r = await deps.saveChannel(channel);
|
|
504
|
+
return r.success ? `Created channel "${str$1(a?.name)}" (${r.channel?.id || "saved"}).` : `Could not create channel: ${r.error || "unknown error"}.`;
|
|
505
|
+
}
|
|
436
506
|
}
|
|
437
507
|
];
|
|
438
508
|
}
|
|
@@ -560,10 +630,12 @@ You are WISE Agent, a fast, text-mode companion to the deep coding agent (Claude
|
|
|
560
630
|
- use_skill \u2014 load a project skill's full steps by name, then carry them out with run_bash.
|
|
561
631
|
- run_bash \u2014 run a shell command on the session's machine (when granted).
|
|
562
632
|
- send_to_session \u2014 hand a clear, reformulated instruction to the deep coding agent (when granted); pass wait=true to block for its reply.
|
|
633
|
+
- create_routine / create_loop / create_channel \u2014 set up a scheduled/triggered routine, a self-verifying loop, or an inbound channel for this session (when granted). ALWAYS propose first and confirm before calling these (see below).
|
|
563
634
|
|
|
564
635
|
# Instructions
|
|
565
636
|
- Answer general questions and questions about yourself directly. Use tools only to act on the machine/session.
|
|
566
637
|
- Take the cheap path: read state directly; delegate anything LONG to summarize_session \u2014 keep your own context small.
|
|
638
|
+
- To create a routine, loop, or channel: first restate the resolved config in one line and ask the caller to reply "confirm" to proceed. Only call create_routine / create_loop / create_channel after they confirm in a follow-up message. Never create without confirmation.
|
|
567
639
|
- For destructive actions (deleting, stopping, killing), require a verified caller and confirm intent; for safe reads, just do it.
|
|
568
640
|
- If a tool fails or returns nothing useful, say so plainly \u2014 never fabricate a result.
|
|
569
641
|
- Report the outcome in one line.`;
|
|
@@ -936,6 +1008,23 @@ function buildSessionDeps(rpc, opts = {}) {
|
|
|
936
1008
|
recentMessageCount: messages.length,
|
|
937
1009
|
latestMessage: latestText
|
|
938
1010
|
};
|
|
1011
|
+
},
|
|
1012
|
+
async saveRoutine(routine) {
|
|
1013
|
+
return await rpc.saveRoutine(routine, ctx);
|
|
1014
|
+
},
|
|
1015
|
+
async startLoop(cfg) {
|
|
1016
|
+
await rpc.updateConfig({
|
|
1017
|
+
loop: {
|
|
1018
|
+
task: cfg.task,
|
|
1019
|
+
...cfg.criteria ? { criteria: cfg.criteria } : {},
|
|
1020
|
+
...cfg.oracle ? { oracle: cfg.oracle } : {},
|
|
1021
|
+
max_iterations: cfg.maxIterations ?? 20,
|
|
1022
|
+
evaluator: true
|
|
1023
|
+
}
|
|
1024
|
+
}, ctx);
|
|
1025
|
+
},
|
|
1026
|
+
async saveChannel(channel) {
|
|
1027
|
+
return await rpc.saveChannel(channel, ctx);
|
|
939
1028
|
}
|
|
940
1029
|
};
|
|
941
1030
|
}
|
|
@@ -2077,7 +2166,7 @@ async function registerMachineService(server, machineId, metadata, daemonState,
|
|
|
2077
2166
|
const tunnels = handlers.tunnels;
|
|
2078
2167
|
if (!tunnels) throw new Error("Tunnel management not available");
|
|
2079
2168
|
if (tunnels.has(params.name)) throw new Error(`Tunnel '${params.name}' already running`);
|
|
2080
|
-
const { FrpcTunnel } = await import('./frpc-
|
|
2169
|
+
const { FrpcTunnel } = await import('./frpc-cJUGFtWY.mjs');
|
|
2081
2170
|
const tunnel = new FrpcTunnel({
|
|
2082
2171
|
name: params.name,
|
|
2083
2172
|
ports: params.ports,
|
|
@@ -2338,7 +2427,7 @@ QUESTION: ${params.question || "Summarize this concisely."}` }
|
|
|
2338
2427
|
}
|
|
2339
2428
|
const deps = buildSessionDeps(rpc, { cwd, ownerEmail: owner });
|
|
2340
2429
|
const sender = { name: context?.user?.email || context?.user?.id || "user", kind: "user", verified: true };
|
|
2341
|
-
const { toolsForRole } = await import('./sideband-
|
|
2430
|
+
const { toolsForRole } = await import('./sideband-DYhbiCEA.mjs');
|
|
2342
2431
|
const r2 = await runWiseAgent({ message: params.message, sender, config: { tools: toolsForRole(role2) }, deps, transport, model: resolved.model });
|
|
2343
2432
|
return fmt(r2);
|
|
2344
2433
|
}
|
|
@@ -2414,7 +2503,15 @@ ${d?.error || "not found"}`;
|
|
|
2414
2503
|
trackInbound();
|
|
2415
2504
|
const rpc = await findChannelOwner(kwargs.channel);
|
|
2416
2505
|
if (!rpc?.channelSend) return { error: "channel not found" };
|
|
2417
|
-
return rpc.channelSend({ channel: kwargs.channel, message: kwargs.message, from: kwargs.from, key: kwargs.key }, context);
|
|
2506
|
+
return rpc.channelSend({ channel: kwargs.channel, message: kwargs.message, from: kwargs.from, key: kwargs.key, reply_to: kwargs.reply_to }, context);
|
|
2507
|
+
},
|
|
2508
|
+
// Async reply retrieval for queue-mode channels — long-poll the channel outbox
|
|
2509
|
+
// for replies addressed to the caller. Channel-identity auth (key/from).
|
|
2510
|
+
receive: async (kwargs = {}, context) => {
|
|
2511
|
+
trackInbound();
|
|
2512
|
+
const rpc = await findChannelOwner(kwargs.channel);
|
|
2513
|
+
if (!rpc?.channelReceive) return { error: "channel not found" };
|
|
2514
|
+
return rpc.channelReceive({ channel: kwargs.channel, key: kwargs.key, from: kwargs.from, cursor: kwargs.cursor, correlationId: kwargs.correlationId, wait: kwargs.wait }, context);
|
|
2418
2515
|
}
|
|
2419
2516
|
},
|
|
2420
2517
|
{ overwrite: true }
|
|
@@ -2872,10 +2969,27 @@ function generateSkillBody(channel, ctx) {
|
|
|
2872
2969
|
const sendUrl = `${gw}/send`;
|
|
2873
2970
|
const key = ctx?.key || "<your-key>";
|
|
2874
2971
|
const isAgent = channel.action?.kind === "agent";
|
|
2972
|
+
const isQueue = channel.reply?.mode === "queue";
|
|
2973
|
+
const recvUrl = `${gw}/receive`;
|
|
2875
2974
|
const hyphaOpen = (channel.identity?.hypha_allow || []).length > 0;
|
|
2876
2975
|
const name = channel.skill?.name || channel.name;
|
|
2877
2976
|
const desc = channel.skill?.description || channel.description || `Send a message to the "${channel.name}" channel.`;
|
|
2878
|
-
const replyNote = isAgent ? `This is a **WISE Agent** channel: \`send()\` runs a fast assistant against the session's tools/skills and returns its answer synchronously in the result \`reply\`.` : `Delivery is fire-and-forget \u2014 the message lands in the agent's inbox, tagged with your verified identity (\`from\`).`;
|
|
2977
|
+
const replyNote = isAgent ? `This is a **WISE Agent** channel: \`send()\` runs a fast assistant against the session's tools/skills and returns its answer synchronously in the result \`reply\`.` : isQueue ? `This is an **async** channel: \`send()\` returns a \`correlationId\` and the agent replies later \u2014 poll \`receive()\` (or GET /receive \xB7 /events) for replies addressed to you.` : `Delivery is fire-and-forget \u2014 the message lands in the agent's inbox, tagged with your verified identity (\`from\`).`;
|
|
2978
|
+
const queueSection = isQueue ? `
|
|
2979
|
+
|
|
2980
|
+
## Getting the reply (async)
|
|
2981
|
+
\`send()\` returns \`{ correlationId }\`. The agent answers later; retrieve replies addressed
|
|
2982
|
+
to you by **long-polling** \`receive\` with a cursor you advance each call:
|
|
2983
|
+
\`\`\`js
|
|
2984
|
+
const { correlationId } = await get_service("${svc}").send({ channel: "${channel.id}", message: "\u2026", from: "your-name" });
|
|
2985
|
+
let cursor = 0;
|
|
2986
|
+
while (true) {
|
|
2987
|
+
const r = await get_service("${svc}").receive({ channel: "${channel.id}", key: "${key}", cursor, wait: 25 });
|
|
2988
|
+
cursor = r.cursor;
|
|
2989
|
+
for (const reply of r.replies) if (reply.correlationId === correlationId) return reply.body;
|
|
2990
|
+
}
|
|
2991
|
+
\`\`\`
|
|
2992
|
+
**HTTP:** \`POST ${recvUrl}\` with \`{"kwargs": {"channel": "${channel.id}", "key": "${key}", "cursor": 0, "wait": 25}}\` (long-poll), or stream \`GET <channel-http>/channel/${channel.id}/events?key=${key}\` (SSE).` : "";
|
|
2879
2993
|
const rpcLine = hyphaOpen ? `**Hypha RPC** \u2014 preferred. Your verified Hypha identity is accepted, no key needed:` : `**Hypha RPC** \u2014 verified identity:`;
|
|
2880
2994
|
return `---
|
|
2881
2995
|
name: ${name}
|
|
@@ -2903,7 +3017,139 @@ POST ${sendUrl}
|
|
|
2903
3017
|
Content-Type: application/json
|
|
2904
3018
|
|
|
2905
3019
|
{"kwargs": {"channel": "${channel.id}", "message": "your message here", "from": "your-name", "key": "${key}"}}
|
|
2906
|
-
|
|
3020
|
+
\`\`\`${queueSection}`;
|
|
3021
|
+
}
|
|
3022
|
+
|
|
3023
|
+
const MAX_PER_CHANNEL = 200;
|
|
3024
|
+
const TTL_MS = 60 * 60 * 1e3;
|
|
3025
|
+
class ChannelOutbox {
|
|
3026
|
+
file;
|
|
3027
|
+
byChannel = /* @__PURE__ */ new Map();
|
|
3028
|
+
seqByChannel = /* @__PURE__ */ new Map();
|
|
3029
|
+
emitter = new EventEmitter();
|
|
3030
|
+
constructor(projectDir) {
|
|
3031
|
+
const dir = join$1(projectDir, ".svamp", "channels");
|
|
3032
|
+
this.file = join$1(dir, "_outbox.jsonl");
|
|
3033
|
+
this.emitter.setMaxListeners(0);
|
|
3034
|
+
try {
|
|
3035
|
+
mkdirSync$1(dir, { recursive: true });
|
|
3036
|
+
} catch {
|
|
3037
|
+
}
|
|
3038
|
+
this._load();
|
|
3039
|
+
}
|
|
3040
|
+
_load() {
|
|
3041
|
+
if (!existsSync(this.file)) return;
|
|
3042
|
+
const cutoff = Date.now() - TTL_MS;
|
|
3043
|
+
try {
|
|
3044
|
+
for (const line of readFileSync(this.file, "utf8").split("\n")) {
|
|
3045
|
+
if (!line.trim()) continue;
|
|
3046
|
+
let rec = null;
|
|
3047
|
+
try {
|
|
3048
|
+
rec = JSON.parse(line);
|
|
3049
|
+
} catch {
|
|
3050
|
+
continue;
|
|
3051
|
+
}
|
|
3052
|
+
if (!rec || rec.ts < cutoff) continue;
|
|
3053
|
+
const { channelId, ...reply } = rec;
|
|
3054
|
+
const arr = this.byChannel.get(channelId) || [];
|
|
3055
|
+
arr.push(reply);
|
|
3056
|
+
this.byChannel.set(channelId, arr);
|
|
3057
|
+
this.seqByChannel.set(channelId, Math.max(this.seqByChannel.get(channelId) || 0, reply.seq));
|
|
3058
|
+
}
|
|
3059
|
+
for (const [ch, arr] of this.byChannel) if (arr.length > MAX_PER_CHANNEL) this.byChannel.set(ch, arr.slice(-MAX_PER_CHANNEL));
|
|
3060
|
+
} catch {
|
|
3061
|
+
}
|
|
3062
|
+
}
|
|
3063
|
+
_evict(channelId) {
|
|
3064
|
+
const cutoff = Date.now() - TTL_MS;
|
|
3065
|
+
let arr = this.byChannel.get(channelId);
|
|
3066
|
+
if (!arr) return;
|
|
3067
|
+
if (arr.some((r) => r.ts < cutoff)) arr = arr.filter((r) => r.ts >= cutoff);
|
|
3068
|
+
if (arr.length > MAX_PER_CHANNEL) arr = arr.slice(-MAX_PER_CHANNEL);
|
|
3069
|
+
this.byChannel.set(channelId, arr);
|
|
3070
|
+
}
|
|
3071
|
+
/** Append a reply addressed to `to`. Assigns seq + ts, persists, and wakes waiters. */
|
|
3072
|
+
append(channelId, r) {
|
|
3073
|
+
const seq = (this.seqByChannel.get(channelId) || 0) + 1;
|
|
3074
|
+
this.seqByChannel.set(channelId, seq);
|
|
3075
|
+
const reply = { seq, ts: Date.now(), to: r.to, body: r.body, ...r.correlationId ? { correlationId: r.correlationId } : {} };
|
|
3076
|
+
const arr = this.byChannel.get(channelId) || [];
|
|
3077
|
+
arr.push(reply);
|
|
3078
|
+
this.byChannel.set(channelId, arr);
|
|
3079
|
+
this._evict(channelId);
|
|
3080
|
+
try {
|
|
3081
|
+
appendFileSync(this.file, JSON.stringify({ channelId, ...reply }) + "\n");
|
|
3082
|
+
} catch {
|
|
3083
|
+
try {
|
|
3084
|
+
mkdirSync$1(join$1(this.file, ".."), { recursive: true });
|
|
3085
|
+
appendFileSync(this.file, JSON.stringify({ channelId, ...reply }) + "\n");
|
|
3086
|
+
} catch {
|
|
3087
|
+
}
|
|
3088
|
+
}
|
|
3089
|
+
this.emitter.emit(channelId, reply);
|
|
3090
|
+
return reply;
|
|
3091
|
+
}
|
|
3092
|
+
/** Replies for `to` on `channelId` with seq > cursor (optionally one correlationId). */
|
|
3093
|
+
since(channelId, cursor, to, correlationId) {
|
|
3094
|
+
this._evict(channelId);
|
|
3095
|
+
return (this.byChannel.get(channelId) || []).filter((r) => r.seq > cursor && r.to === to && (!correlationId || r.correlationId === correlationId));
|
|
3096
|
+
}
|
|
3097
|
+
/** Highest seq on a channel (the cursor a caller gets back). */
|
|
3098
|
+
cursor(channelId) {
|
|
3099
|
+
return this.seqByChannel.get(channelId) || 0;
|
|
3100
|
+
}
|
|
3101
|
+
/**
|
|
3102
|
+
* Long-poll: resolve immediately if there are replies after `cursor`, else wait for
|
|
3103
|
+
* the next append (filtered to this channel + `to`) or `timeoutMs`, then return.
|
|
3104
|
+
*/
|
|
3105
|
+
wait(channelId, cursor, to, timeoutMs, correlationId) {
|
|
3106
|
+
const ready = this.since(channelId, cursor, to, correlationId);
|
|
3107
|
+
if (ready.length) return Promise.resolve({ replies: ready, cursor: this.cursor(channelId) });
|
|
3108
|
+
return new Promise((resolve) => {
|
|
3109
|
+
const onReply = (r) => {
|
|
3110
|
+
if (r.to !== to || correlationId && r.correlationId !== correlationId) return;
|
|
3111
|
+
cleanup();
|
|
3112
|
+
resolve({ replies: this.since(channelId, cursor, to, correlationId), cursor: this.cursor(channelId) });
|
|
3113
|
+
};
|
|
3114
|
+
const timer = setTimeout(() => {
|
|
3115
|
+
cleanup();
|
|
3116
|
+
resolve({ replies: [], cursor: this.cursor(channelId) });
|
|
3117
|
+
}, Math.max(0, timeoutMs));
|
|
3118
|
+
const cleanup = () => {
|
|
3119
|
+
clearTimeout(timer);
|
|
3120
|
+
this.emitter.off(channelId, onReply);
|
|
3121
|
+
};
|
|
3122
|
+
this.emitter.on(channelId, onReply);
|
|
3123
|
+
});
|
|
3124
|
+
}
|
|
3125
|
+
/** Push subscription for SSE: calls onReply for each new reply addressed to `to`. */
|
|
3126
|
+
subscribe(channelId, to, onReply) {
|
|
3127
|
+
const handler = (r) => {
|
|
3128
|
+
if (r.to === to) onReply(r);
|
|
3129
|
+
};
|
|
3130
|
+
this.emitter.on(channelId, handler);
|
|
3131
|
+
return () => this.emitter.off(channelId, handler);
|
|
3132
|
+
}
|
|
3133
|
+
/** Drop a channel's outbox (on channel delete) — best-effort rewrite of the log. */
|
|
3134
|
+
purge(channelId) {
|
|
3135
|
+
this.byChannel.delete(channelId);
|
|
3136
|
+
this.seqByChannel.delete(channelId);
|
|
3137
|
+
if (!existsSync(this.file)) return;
|
|
3138
|
+
try {
|
|
3139
|
+
const kept = readFileSync(this.file, "utf8").split("\n").filter((l) => {
|
|
3140
|
+
if (!l.trim()) return false;
|
|
3141
|
+
try {
|
|
3142
|
+
return JSON.parse(l).channelId !== channelId;
|
|
3143
|
+
} catch {
|
|
3144
|
+
return false;
|
|
3145
|
+
}
|
|
3146
|
+
});
|
|
3147
|
+
const tmp = this.file + ".tmp";
|
|
3148
|
+
writeFileSync$1(tmp, kept.join("\n") + (kept.length ? "\n" : ""));
|
|
3149
|
+
renameSync$1(tmp, this.file);
|
|
3150
|
+
} catch {
|
|
3151
|
+
}
|
|
3152
|
+
}
|
|
2907
3153
|
}
|
|
2908
3154
|
|
|
2909
3155
|
function resolveSender(channel, input = {}) {
|
|
@@ -3181,6 +3427,7 @@ function createSessionStore(server, sessionId, initialMetadata, initialAgentStat
|
|
|
3181
3427
|
callbacks.onMetadataUpdate?.(metadata);
|
|
3182
3428
|
};
|
|
3183
3429
|
const channelStore = new ChannelStore(initialMetadata.path);
|
|
3430
|
+
const channelOutbox = new ChannelOutbox(initialMetadata.path);
|
|
3184
3431
|
const cfg = server?.config || {};
|
|
3185
3432
|
const channelsServiceId = cfg.workspace && cfg.client_id ? `${cfg.workspace}/${cfg.client_id}:channels` : void 0;
|
|
3186
3433
|
const channelsBaseUrl = cfg.public_base_url || process.env.HYPHA_SERVER_URL || "https://hypha.aicell.io";
|
|
@@ -3388,6 +3635,7 @@ function createSessionStore(server, sessionId, initialMetadata, initialAgentStat
|
|
|
3388
3635
|
removeChannel: async (id, context) => {
|
|
3389
3636
|
authorizeRequest(context, metadata.sharing, "admin");
|
|
3390
3637
|
const ok = channelStore.remove(id);
|
|
3638
|
+
channelOutbox.purge(id);
|
|
3391
3639
|
syncChannelsToMetadata();
|
|
3392
3640
|
return { success: ok };
|
|
3393
3641
|
},
|
|
@@ -3458,6 +3706,8 @@ function createSessionStore(server, sessionId, initialMetadata, initialAgentStat
|
|
|
3458
3706
|
return { ok: result.status === "completed", call_id: callId, status: result.status, reply: result.reply, tool_calls: result.toolCalls, error: result.error };
|
|
3459
3707
|
}
|
|
3460
3708
|
if (c.action?.kind === "loop") return { error: "loop channels are served by the channel server, not channelSend" };
|
|
3709
|
+
const queue = c.reply?.mode === "queue";
|
|
3710
|
+
const replySession = queue ? params.reply_to?.session : void 0;
|
|
3461
3711
|
const inboxMsg = {
|
|
3462
3712
|
messageId: callId,
|
|
3463
3713
|
body: xmlEscape(String(params.message ?? "").slice(0, 16 * 1024)),
|
|
@@ -3466,17 +3716,56 @@ function createSessionStore(server, sessionId, initialMetadata, initialAgentStat
|
|
|
3466
3716
|
from: r.sender.name,
|
|
3467
3717
|
verified: r.sender.verified,
|
|
3468
3718
|
channel: c.name,
|
|
3469
|
-
subject: c.name
|
|
3719
|
+
subject: c.name,
|
|
3720
|
+
...replySession ? { fromSession: replySession, threadId: callId } : {},
|
|
3721
|
+
...queue && !replySession ? { channelId: c.id, correlationId: callId } : {}
|
|
3470
3722
|
};
|
|
3471
3723
|
await rpcHandlers.sendInboxMessage(inboxMsg, ownerCtx);
|
|
3472
3724
|
channelStore.recordCall(c.id, { sender: r.sender.name, verified: r.sender.verified, callId, outcome: "delivered" });
|
|
3473
3725
|
syncChannelsToMetadata();
|
|
3474
|
-
return { ok: true, call_id: callId, status: "accepted" };
|
|
3726
|
+
return { ok: true, call_id: callId, status: queue ? "queued" : "accepted", ...queue ? { correlationId: callId } : {} };
|
|
3475
3727
|
} catch (e) {
|
|
3476
3728
|
channelStore.recordCall(c.id, { sender: r.sender.name, verified: r.sender.verified, callId, outcome: "error" });
|
|
3477
3729
|
return { ok: false, call_id: callId, status: "error", error: e?.message || String(e) };
|
|
3478
3730
|
}
|
|
3479
3731
|
},
|
|
3732
|
+
// Agent/owner answers a queued (async) channel message → channel outbox, addressed
|
|
3733
|
+
// to the original external caller. Routed here by `inbox reply` for channel-origin
|
|
3734
|
+
// inbox messages (which carry channelId + correlationId + from). Owner-gated since
|
|
3735
|
+
// it's the session speaking on its own behalf.
|
|
3736
|
+
channelReply: async (params, context) => {
|
|
3737
|
+
authorizeRequest(context, metadata.sharing, "interact");
|
|
3738
|
+
const c = channelStore.get(params.channel);
|
|
3739
|
+
if (!c) return { ok: false, error: "channel not found" };
|
|
3740
|
+
if (!params.to || !params.body) return { ok: false, error: "to and body are required" };
|
|
3741
|
+
const reply = channelOutbox.append(c.id, {
|
|
3742
|
+
correlationId: params.correlationId,
|
|
3743
|
+
to: String(params.to),
|
|
3744
|
+
body: String(params.body).slice(0, 16 * 1024)
|
|
3745
|
+
});
|
|
3746
|
+
channelStore.recordCall(c.id, { sender: String(params.to), verified: true, callId: params.correlationId || `seq_${reply.seq}`, outcome: "replied" });
|
|
3747
|
+
return { ok: true, seq: reply.seq };
|
|
3748
|
+
},
|
|
3749
|
+
// External caller retrieves async replies addressed to it. Channel-identity auth
|
|
3750
|
+
// (key/from) — NOT session sharing. Long-polls up to `wait` seconds for new replies
|
|
3751
|
+
// after `cursor`; the caller advances `cursor` each call (ack-by-cursor).
|
|
3752
|
+
channelReceive: async (params, context) => {
|
|
3753
|
+
const c = channelStore.get(params.channel);
|
|
3754
|
+
if (!c || c.enabled === false) return { error: "channel not found" };
|
|
3755
|
+
const u = context?.user;
|
|
3756
|
+
const r = resolveSender(c, {
|
|
3757
|
+
key: params.key,
|
|
3758
|
+
from: params.from,
|
|
3759
|
+
hyphaUser: u && u.is_anonymous !== true ? u.email || u.id : void 0,
|
|
3760
|
+
hyphaAnonymous: u?.is_anonymous === true,
|
|
3761
|
+
hyphaWorkspace: u?.scope?.current_workspace
|
|
3762
|
+
});
|
|
3763
|
+
if (r.error || !r.sender) return { error: r.error || "unauthorized" };
|
|
3764
|
+
const cursor = Math.max(0, Number(params.cursor) || 0);
|
|
3765
|
+
const waitMs = Math.min(Math.max(0, Number(params.wait ?? 25) * 1e3), 6e4);
|
|
3766
|
+
const out = await channelOutbox.wait(c.id, cursor, r.sender.name, waitMs, params.correlationId);
|
|
3767
|
+
return { ok: true, replies: out.replies, cursor: out.cursor };
|
|
3768
|
+
},
|
|
3480
3769
|
// ── Agent State ──
|
|
3481
3770
|
getAgentState: async (context) => {
|
|
3482
3771
|
authorizeRequest(context, metadata.sharing, "view");
|
|
@@ -3821,6 +4110,9 @@ function createSessionStore(server, sessionId, initialMetadata, initialAgentStat
|
|
|
3821
4110
|
const child = spawn("claude", args, {
|
|
3822
4111
|
cwd,
|
|
3823
4112
|
timeout: 6e4,
|
|
4113
|
+
// Ignore stdin: --print otherwise waits ~3s for piped input ("no stdin
|
|
4114
|
+
// data received in 3s, proceeding without it") — pure latency per /btw.
|
|
4115
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
3824
4116
|
env: { ...process.env, CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: "1" }
|
|
3825
4117
|
});
|
|
3826
4118
|
let stdout = "";
|
|
@@ -9834,7 +10126,7 @@ async function startDaemon(options) {
|
|
|
9834
10126
|
const list = loadExposedTunnels().filter((t) => t.name !== name);
|
|
9835
10127
|
saveExposedTunnels(list);
|
|
9836
10128
|
}
|
|
9837
|
-
const { ServeManager } = await import('./serveManager-
|
|
10129
|
+
const { ServeManager } = await import('./serveManager-B757hHGd.mjs');
|
|
9838
10130
|
const serveManager = new ServeManager(SVAMP_HOME, (msg) => logger.log(`[SERVE] ${msg}`), hyphaServerUrl);
|
|
9839
10131
|
ensureAutoInstalledSkills(logger).catch(() => {
|
|
9840
10132
|
});
|
|
@@ -10494,6 +10786,10 @@ async function startDaemon(options) {
|
|
|
10494
10786
|
}
|
|
10495
10787
|
if (msg.session_id) {
|
|
10496
10788
|
claudeResumeId = msg.session_id;
|
|
10789
|
+
if (sessionMetadata.claudeSessionId !== msg.session_id) {
|
|
10790
|
+
sessionMetadata = { ...sessionMetadata, claudeSessionId: msg.session_id };
|
|
10791
|
+
sessionService.updateMetadata(sessionMetadata);
|
|
10792
|
+
}
|
|
10497
10793
|
}
|
|
10498
10794
|
signalProcessing(false);
|
|
10499
10795
|
sessionWasProcessing = false;
|
|
@@ -12124,7 +12420,7 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
|
|
|
12124
12420
|
const channelHttpPort = Number(process.env.SVAMP_CHANNEL_HTTP_PORT) || 0;
|
|
12125
12421
|
if (channelHttpPort > 0) {
|
|
12126
12422
|
try {
|
|
12127
|
-
const { createChannelHttpServer } = await import('./httpServer-
|
|
12423
|
+
const { createChannelHttpServer } = await import('./httpServer-D9qLS8ed.mjs');
|
|
12128
12424
|
const channelHttpServer = createChannelHttpServer({
|
|
12129
12425
|
getSessionIds: () => {
|
|
12130
12426
|
const ids = [];
|
|
@@ -12145,7 +12441,7 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
|
|
|
12145
12441
|
const specs = loadExposedTunnels();
|
|
12146
12442
|
if (specs.length === 0) return;
|
|
12147
12443
|
logger.log(`[exposed-tunnels] Restoring ${specs.length} tunnel(s) from ${EXPOSED_TUNNELS_FILE}`);
|
|
12148
|
-
const { FrpcTunnel } = await import('./frpc-
|
|
12444
|
+
const { FrpcTunnel } = await import('./frpc-cJUGFtWY.mjs');
|
|
12149
12445
|
for (const spec of specs) {
|
|
12150
12446
|
if (tunnels.has(spec.name)) continue;
|
|
12151
12447
|
try {
|
|
@@ -2,7 +2,7 @@ import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(im
|
|
|
2
2
|
import os from 'node:os';
|
|
3
3
|
import { resolve, join } from 'node:path';
|
|
4
4
|
import { existsSync, readFileSync, watch } from 'node:fs';
|
|
5
|
-
import { c as connectToHypha, a as createSessionStore, r as registerMachineService, P as generateHookSettings } from './run-
|
|
5
|
+
import { c as connectToHypha, a as createSessionStore, r as registerMachineService, P as generateHookSettings } from './run-B_FyvS11.mjs';
|
|
6
6
|
import { createServer } from 'node:http';
|
|
7
7
|
import { spawn } from 'node:child_process';
|
|
8
8
|
import { createInterface } from 'node:readline';
|
|
@@ -14,6 +14,7 @@ import 'url';
|
|
|
14
14
|
import 'child_process';
|
|
15
15
|
import 'crypto';
|
|
16
16
|
import 'util';
|
|
17
|
+
import 'node:events';
|
|
17
18
|
import '@agentclientprotocol/sdk';
|
|
18
19
|
import '@modelcontextprotocol/sdk/client/index.js';
|
|
19
20
|
import '@modelcontextprotocol/sdk/client/stdio.js';
|
|
@@ -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-DpRXzSr9.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-DpRXzSr9.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-DpRXzSr9.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-DpRXzSr9.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-DpRXzSr9.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-B_FyvS11.mjs';
|
|
8
8
|
import 'os';
|
|
9
9
|
import 'fs/promises';
|
|
10
10
|
import 'url';
|
|
@@ -14,6 +14,7 @@ import 'util';
|
|
|
14
14
|
import 'node:crypto';
|
|
15
15
|
import 'node:path';
|
|
16
16
|
import 'node:os';
|
|
17
|
+
import 'node:events';
|
|
17
18
|
import '@agentclientprotocol/sdk';
|
|
18
19
|
import '@modelcontextprotocol/sdk/client/index.js';
|
|
19
20
|
import '@modelcontextprotocol/sdk/client/stdio.js';
|
|
@@ -712,7 +713,7 @@ class ServeManager {
|
|
|
712
713
|
const mount = this.mounts.get(mountName);
|
|
713
714
|
const subdomainOverride = mount?.access === "link" && mount.linkToken ? /* @__PURE__ */ new Map([[this.port, `static-${subdomainSafe}-${mount.linkToken}`]]) : void 0;
|
|
714
715
|
try {
|
|
715
|
-
const { FrpcTunnel } = await import('./frpc-
|
|
716
|
+
const { FrpcTunnel } = await import('./frpc-cJUGFtWY.mjs');
|
|
716
717
|
let tunnel;
|
|
717
718
|
tunnel = new FrpcTunnel({
|
|
718
719
|
name: tunnelName,
|