svamp-cli 0.2.112 → 0.2.114
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-Dowbc5o1.mjs → agentCommands-D53qtjbo.mjs} +4 -4
- package/dist/{auth-Jpc28_of.mjs → auth-Ykv_kVPM.mjs} +2 -2
- package/dist/cli.mjs +52 -52
- package/dist/{commands-Bz2we3Hc.mjs → commands-1DLUHWZ5.mjs} +2 -2
- package/dist/{commands-ZmD0iGNp.mjs → commands-BBQI_6EM.mjs} +2 -2
- package/dist/{commands-CSLkIxLd.mjs → commands-BYBzqLJZ.mjs} +5 -5
- package/dist/{commands-BqTwxEGl.mjs → commands-BcIz9gl2.mjs} +2 -2
- package/dist/{commands-P9-75WDZ.mjs → commands-C29ciVUe.mjs} +10 -7
- package/dist/{fleet-4t-L6BVT.mjs → fleet--CAdje9C.mjs} +1 -1
- package/dist/{frpc-BoPlePa3.mjs → frpc-BjWZ129L.mjs} +2 -2
- package/dist/{headlessCli-BBCGDutU.mjs → headlessCli-C6MzdWRW.mjs} +3 -3
- package/dist/index.mjs +2 -2
- package/dist/{package-BX6NFLve.mjs → package-PUmSILNZ.mjs} +2 -2
- package/dist/{run-BGvBeuA4.mjs → run-CiiUhPNf.mjs} +1 -1
- package/dist/{run-Bs_f2KsC.mjs → run-aNUfTpRW.mjs} +209 -170
- package/dist/{serveCommands-BgSqTBrB.mjs → serveCommands-BoFSdzkv.mjs} +5 -5
- package/dist/{serveManager-D3sMgApm.mjs → serveManager-DrPFeC2o.mjs} +3 -3
- package/dist/{sideband-D1f0_8ao.mjs → sideband-BCKpph51.mjs} +2 -2
- package/package.json +2 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { F as resolveModel, O as describeMisconfiguration, P as buildMachineDeps } from './run-
|
|
2
|
-
import { handleRealtimeEvent, initMachineVoiceSession } from './sideband-
|
|
1
|
+
import { F as resolveModel, O as describeMisconfiguration, P as buildMachineDeps } from './run-aNUfTpRW.mjs';
|
|
2
|
+
import { handleRealtimeEvent, initMachineVoiceSession } from './sideband-BCKpph51.mjs';
|
|
3
3
|
import { WebSocket } from 'ws';
|
|
4
4
|
import { execSync, spawn } from 'child_process';
|
|
5
5
|
import 'os';
|
|
@@ -13,8 +13,8 @@ import 'node:fs';
|
|
|
13
13
|
import 'node:child_process';
|
|
14
14
|
import 'util';
|
|
15
15
|
import 'node:path';
|
|
16
|
-
import 'node:os';
|
|
17
16
|
import 'node:events';
|
|
17
|
+
import 'node:os';
|
|
18
18
|
import '@agentclientprotocol/sdk';
|
|
19
19
|
import '@modelcontextprotocol/sdk/client/index.js';
|
|
20
20
|
import '@modelcontextprotocol/sdk/client/stdio.js';
|
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-aNUfTpRW.mjs';
|
|
2
2
|
import 'os';
|
|
3
3
|
import 'fs/promises';
|
|
4
4
|
import 'fs';
|
|
@@ -11,8 +11,8 @@ import 'node:fs';
|
|
|
11
11
|
import 'node:child_process';
|
|
12
12
|
import 'util';
|
|
13
13
|
import 'node:path';
|
|
14
|
-
import 'node:os';
|
|
15
14
|
import 'node:events';
|
|
15
|
+
import 'node:os';
|
|
16
16
|
import '@agentclientprotocol/sdk';
|
|
17
17
|
import '@modelcontextprotocol/sdk/client/index.js';
|
|
18
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.114";
|
|
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-auto-topic.mjs && npx tsx test/test-project-info.mjs && npx tsx test/test-agent-types.mjs && npx tsx test/test-transport.mjs && npx tsx test/test-session-update-handlers.mjs && npx tsx test/test-session-scanner.mjs && npx tsx test/test-hypha-client.mjs && npx tsx test/test-hook-settings.mjs && npx tsx test/test-session-service-logic.mjs && npx tsx test/test-daemon-persistence.mjs && npx tsx test/test-detect-isolation.mjs && npx tsx test/test-machine-service-logic.mjs && npx tsx test/test-interactive-helpers.mjs && npx tsx test/test-codex-backend.mjs && npx tsx test/test-acp-backend.mjs && npx tsx test/test-acp-bridge.mjs && npx tsx test/test-hook-server.mjs && npx tsx test/test-session-commands.mjs && npx tsx test/test-interactive-console.mjs && npx tsx test/test-session-messages.mjs && npx tsx test/test-session-send-query.mjs && npx tsx test/test-skills.mjs && npx tsx test/test-agent-grouping.mjs && npx tsx test/test-machine-list-directory.mjs && npx tsx test/test-service-commands.mjs && npx tsx test/test-supervisor.mjs && npx tsx test/test-supervisor-lock.mjs && node test/test-supervisor-restart.mjs && npx tsx test/test-clear-detection.mjs && npx tsx test/test-session-consolidation.mjs && npx tsx test/test-inbox.mjs && npx tsx test/test-short-id.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-channel-binding.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-auto-topic.mjs && npx tsx test/test-project-info.mjs && npx tsx test/test-agent-types.mjs && npx tsx test/test-transport.mjs && npx tsx test/test-session-update-handlers.mjs && npx tsx test/test-session-scanner.mjs && npx tsx test/test-hypha-client.mjs && npx tsx test/test-hook-settings.mjs && npx tsx test/test-session-service-logic.mjs && npx tsx test/test-daemon-persistence.mjs && npx tsx test/test-detect-isolation.mjs && npx tsx test/test-machine-service-logic.mjs && npx tsx test/test-interactive-helpers.mjs && npx tsx test/test-codex-backend.mjs && npx tsx test/test-acp-backend.mjs && npx tsx test/test-acp-bridge.mjs && npx tsx test/test-hook-server.mjs && npx tsx test/test-session-commands.mjs && npx tsx test/test-interactive-console.mjs && npx tsx test/test-session-messages.mjs && npx tsx test/test-session-send-query.mjs && npx tsx test/test-skills.mjs && npx tsx test/test-agent-grouping.mjs && npx tsx test/test-machine-list-directory.mjs && npx tsx test/test-service-commands.mjs && npx tsx test/test-supervisor.mjs && npx tsx test/test-supervisor-lock.mjs && node test/test-supervisor-restart.mjs && npx tsx test/test-clear-detection.mjs && npx tsx test/test-session-consolidation.mjs && npx tsx test/test-inbox.mjs && npx tsx test/test-short-id.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-channel-binding.mjs && npx tsx test/test-channel-identity.mjs && npx tsx test/test-wise-agent-auth.mjs && npx tsx test/test-channel-http.mjs && npx tsx test/test-wise-voice.mjs && npx tsx test/test-wise-headless.mjs && npx tsx test/test-wise-machine.mjs",
|
|
23
23
|
"test:hypha": "node --no-warnings test/test-hypha-service.mjs",
|
|
24
24
|
dev: "tsx src/cli.ts",
|
|
25
25
|
"dev:daemon": "tsx src/cli.ts daemon start-sync",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import { n as shortId, c as connectToHypha, a as createSessionStore, r as registerMachineService, Q as generateHookSettings } from './run-
|
|
1
|
+
import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import { n as shortId, c as connectToHypha, a as createSessionStore, r as registerMachineService, Q as generateHookSettings } from './run-aNUfTpRW.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';
|
|
@@ -10,8 +10,8 @@ import { existsSync, readFileSync, mkdirSync, readdirSync, writeFileSync, rename
|
|
|
10
10
|
import { exec, execSync, spawn, execFile as execFile$1, execFileSync } from 'node:child_process';
|
|
11
11
|
import { promisify } from 'util';
|
|
12
12
|
import { join, basename, dirname } from 'node:path';
|
|
13
|
-
import os, { homedir, platform } from 'node:os';
|
|
14
13
|
import { EventEmitter } from 'node:events';
|
|
14
|
+
import os, { homedir, platform } from 'node:os';
|
|
15
15
|
import { ndJsonStream, ClientSideConnection } from '@agentclientprotocol/sdk';
|
|
16
16
|
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
17
17
|
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
|
|
@@ -1388,22 +1388,36 @@ function generateSkillBody(channel, ctx) {
|
|
|
1388
1388
|
const bindNote = mode === "stateless" ? `**Stateless channel** \u2014 each call spawns a fresh, isolated one-shot session (cold-start: a few seconds), runs, replies, and closes. No shared memory between calls.` : mode === "fixed" ? `Routes to a **fixed session** (\`${rSession}\`); reachable only while that session is live.` : rSession ? `Routes to **session \`${rSession}\`** (the one this instruction was copied from); reachable only while it is live, else a fresh stateless run answers.` : `**Dynamic channel** \u2014 pass \`session: "<id>"\` to target a specific live session, else a fresh stateless run answers.`;
|
|
1389
1389
|
const name = channel.skill?.name || channel.name;
|
|
1390
1390
|
const desc = channel.skill?.description || channel.description || `Send a message to the "${channel.name}" channel.`;
|
|
1391
|
-
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
|
|
1391
|
+
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()\` usually returns \`{ status: "queued", correlationId }\` and the agent replies later \u2014 poll \`receive()\` (or GET /receive \xB7 /events) for replies addressed to you. **But it may also answer synchronously** with \`{ status: "completed", reply }\` (e.g. when the target session is gone and a fresh one-shot run handles the call) \u2014 always check \`status\` first and use \`reply\` directly when present; \`receive()\` has nothing to return for a one-shot.` : `Delivery is fire-and-forget \u2014 the message lands in the agent's inbox, tagged with your verified identity (\`from\`).`;
|
|
1392
1392
|
const queueSection = isQueue ? `
|
|
1393
1393
|
|
|
1394
|
-
## Getting the reply
|
|
1395
|
-
\`send()\` returns
|
|
1396
|
-
|
|
1394
|
+
## Getting the reply
|
|
1395
|
+
\`send()\` returns one of two shapes \u2014 **check \`status\` first**:
|
|
1396
|
+
- \`{ status: "completed", reply, correlationId }\` \u2014 answered synchronously (e.g. a
|
|
1397
|
+
dynamic channel whose target session is gone falls back to a fresh one-shot run).
|
|
1398
|
+
Use \`reply\` directly; do **not** poll \`receive()\` \u2014 there is no persistent session
|
|
1399
|
+
to poll and it will return an error.
|
|
1400
|
+
- \`{ status: "queued", correlationId }\` \u2014 a live session will answer later; long-poll
|
|
1401
|
+
\`receive\` for replies addressed to you, advancing \`cursor\` each call:
|
|
1397
1402
|
\`\`\`js
|
|
1398
|
-
const
|
|
1399
|
-
|
|
1403
|
+
const res = await get_service("${svc}").send({ channel: "${channel.id}", message: "\u2026", from: "your-name" });
|
|
1404
|
+
if (res.status === "completed") return res.reply; // answered now \u2014 done
|
|
1405
|
+
let cursor = 0; // else poll for the async reply
|
|
1400
1406
|
while (true) {
|
|
1401
1407
|
const r = await get_service("${svc}").receive({ channel: "${channel.id}", key: "${key}", cursor, wait: 25 });
|
|
1402
1408
|
cursor = r.cursor;
|
|
1403
|
-
for (const reply of r.replies) if (reply.correlationId === correlationId) return reply.body;
|
|
1409
|
+
for (const reply of r.replies) if (reply.correlationId === res.correlationId) return reply.body;
|
|
1404
1410
|
}
|
|
1405
1411
|
\`\`\`
|
|
1406
|
-
**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)
|
|
1412
|
+
**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).
|
|
1413
|
+
|
|
1414
|
+
### Agent-to-agent: get the reply in your own inbox
|
|
1415
|
+
If **you are a Svamp agent session**, pass \`reply_to: { session: "<your-session-id>" }\`
|
|
1416
|
+
to \`send()\`. The reply is then delivered straight to **your session's inbox**
|
|
1417
|
+
(\`inbox reply\`-able, persistent) \u2014 symmetric agent\u2194agent messaging. Without
|
|
1418
|
+
\`reply_to.session\` you are treated as an **external caller**: the reply goes to this
|
|
1419
|
+
channel's outbox and you must poll \`receive()\` (above) for it \u2014 it will **not** appear
|
|
1420
|
+
in your inbox.` : "";
|
|
1407
1421
|
const rpcLine = hyphaOpen ? `**Hypha RPC** \u2014 preferred. Your verified Hypha identity is accepted, no key needed:` : `**Hypha RPC** \u2014 verified identity:`;
|
|
1408
1422
|
return `---
|
|
1409
1423
|
name: ${name}
|
|
@@ -1449,7 +1463,10 @@ function resolveSender(channel, input = {}) {
|
|
|
1449
1463
|
}
|
|
1450
1464
|
if (id.mode === "per-key") {
|
|
1451
1465
|
const caller = (id.callers || []).find((c) => c.key && c.key === key);
|
|
1452
|
-
if (!caller)
|
|
1466
|
+
if (!caller) {
|
|
1467
|
+
const acceptsHypha = Array.isArray(id.hypha_allow) && id.hypha_allow.length > 0;
|
|
1468
|
+
return { error: acceptsHypha ? "invalid or missing key \u2014 supply a caller key issued by the channel owner, or call with an authenticated Hypha identity (this channel accepts hypha_allow callers; anonymous/keyless requests are rejected)" : "invalid or missing key \u2014 this channel requires a caller key issued by the channel owner" };
|
|
1469
|
+
}
|
|
1453
1470
|
return { sender: { name: caller.name, kind: caller.kind, verified: true } };
|
|
1454
1471
|
}
|
|
1455
1472
|
if (id.mode === "caller-supplied") {
|
|
@@ -1482,6 +1499,138 @@ function renderMessage(channel, { sender = {}, body = {}, query = {}, callId, no
|
|
|
1482
1499
|
return renderTemplate(channel.template || DEFAULT_TEMPLATE, ctx);
|
|
1483
1500
|
}
|
|
1484
1501
|
|
|
1502
|
+
const MAX_PER_CHANNEL = 200;
|
|
1503
|
+
const TTL_MS = 60 * 60 * 1e3;
|
|
1504
|
+
class ChannelOutbox {
|
|
1505
|
+
file;
|
|
1506
|
+
byChannel = /* @__PURE__ */ new Map();
|
|
1507
|
+
seqByChannel = /* @__PURE__ */ new Map();
|
|
1508
|
+
emitter = new EventEmitter();
|
|
1509
|
+
constructor(projectDir) {
|
|
1510
|
+
const dir = join(projectDir, ".svamp", "channels");
|
|
1511
|
+
this.file = join(dir, "_outbox.jsonl");
|
|
1512
|
+
this.emitter.setMaxListeners(0);
|
|
1513
|
+
try {
|
|
1514
|
+
mkdirSync(dir, { recursive: true });
|
|
1515
|
+
} catch {
|
|
1516
|
+
}
|
|
1517
|
+
this._load();
|
|
1518
|
+
}
|
|
1519
|
+
_load() {
|
|
1520
|
+
if (!existsSync(this.file)) return;
|
|
1521
|
+
const cutoff = Date.now() - TTL_MS;
|
|
1522
|
+
try {
|
|
1523
|
+
for (const line of readFileSync(this.file, "utf8").split("\n")) {
|
|
1524
|
+
if (!line.trim()) continue;
|
|
1525
|
+
let rec = null;
|
|
1526
|
+
try {
|
|
1527
|
+
rec = JSON.parse(line);
|
|
1528
|
+
} catch {
|
|
1529
|
+
continue;
|
|
1530
|
+
}
|
|
1531
|
+
if (!rec || rec.ts < cutoff) continue;
|
|
1532
|
+
const { channelId, ...reply } = rec;
|
|
1533
|
+
const arr = this.byChannel.get(channelId) || [];
|
|
1534
|
+
arr.push(reply);
|
|
1535
|
+
this.byChannel.set(channelId, arr);
|
|
1536
|
+
this.seqByChannel.set(channelId, Math.max(this.seqByChannel.get(channelId) || 0, reply.seq));
|
|
1537
|
+
}
|
|
1538
|
+
for (const [ch, arr] of this.byChannel) if (arr.length > MAX_PER_CHANNEL) this.byChannel.set(ch, arr.slice(-MAX_PER_CHANNEL));
|
|
1539
|
+
} catch {
|
|
1540
|
+
}
|
|
1541
|
+
}
|
|
1542
|
+
_evict(channelId) {
|
|
1543
|
+
const cutoff = Date.now() - TTL_MS;
|
|
1544
|
+
let arr = this.byChannel.get(channelId);
|
|
1545
|
+
if (!arr) return;
|
|
1546
|
+
if (arr.some((r) => r.ts < cutoff)) arr = arr.filter((r) => r.ts >= cutoff);
|
|
1547
|
+
if (arr.length > MAX_PER_CHANNEL) arr = arr.slice(-MAX_PER_CHANNEL);
|
|
1548
|
+
this.byChannel.set(channelId, arr);
|
|
1549
|
+
}
|
|
1550
|
+
/** Append a reply addressed to `to`. Assigns seq + ts, persists, and wakes waiters. */
|
|
1551
|
+
append(channelId, r) {
|
|
1552
|
+
const seq = (this.seqByChannel.get(channelId) || 0) + 1;
|
|
1553
|
+
this.seqByChannel.set(channelId, seq);
|
|
1554
|
+
const reply = { seq, ts: Date.now(), to: r.to, body: r.body, ...r.correlationId ? { correlationId: r.correlationId } : {} };
|
|
1555
|
+
const arr = this.byChannel.get(channelId) || [];
|
|
1556
|
+
arr.push(reply);
|
|
1557
|
+
this.byChannel.set(channelId, arr);
|
|
1558
|
+
this._evict(channelId);
|
|
1559
|
+
try {
|
|
1560
|
+
appendFileSync(this.file, JSON.stringify({ channelId, ...reply }) + "\n");
|
|
1561
|
+
} catch {
|
|
1562
|
+
try {
|
|
1563
|
+
mkdirSync(join(this.file, ".."), { recursive: true });
|
|
1564
|
+
appendFileSync(this.file, JSON.stringify({ channelId, ...reply }) + "\n");
|
|
1565
|
+
} catch {
|
|
1566
|
+
}
|
|
1567
|
+
}
|
|
1568
|
+
this.emitter.emit(channelId, reply);
|
|
1569
|
+
return reply;
|
|
1570
|
+
}
|
|
1571
|
+
/** Replies for `to` on `channelId` with seq > cursor (optionally one correlationId). */
|
|
1572
|
+
since(channelId, cursor, to, correlationId) {
|
|
1573
|
+
this._evict(channelId);
|
|
1574
|
+
return (this.byChannel.get(channelId) || []).filter((r) => r.seq > cursor && r.to === to && (!correlationId || r.correlationId === correlationId));
|
|
1575
|
+
}
|
|
1576
|
+
/** Highest seq on a channel (the cursor a caller gets back). */
|
|
1577
|
+
cursor(channelId) {
|
|
1578
|
+
return this.seqByChannel.get(channelId) || 0;
|
|
1579
|
+
}
|
|
1580
|
+
/**
|
|
1581
|
+
* Long-poll: resolve immediately if there are replies after `cursor`, else wait for
|
|
1582
|
+
* the next append (filtered to this channel + `to`) or `timeoutMs`, then return.
|
|
1583
|
+
*/
|
|
1584
|
+
wait(channelId, cursor, to, timeoutMs, correlationId) {
|
|
1585
|
+
const ready = this.since(channelId, cursor, to, correlationId);
|
|
1586
|
+
if (ready.length) return Promise.resolve({ replies: ready, cursor: this.cursor(channelId) });
|
|
1587
|
+
return new Promise((resolve) => {
|
|
1588
|
+
const onReply = (r) => {
|
|
1589
|
+
if (r.to !== to || correlationId && r.correlationId !== correlationId) return;
|
|
1590
|
+
cleanup();
|
|
1591
|
+
resolve({ replies: this.since(channelId, cursor, to, correlationId), cursor: this.cursor(channelId) });
|
|
1592
|
+
};
|
|
1593
|
+
const timer = setTimeout(() => {
|
|
1594
|
+
cleanup();
|
|
1595
|
+
resolve({ replies: [], cursor: this.cursor(channelId) });
|
|
1596
|
+
}, Math.max(0, timeoutMs));
|
|
1597
|
+
const cleanup = () => {
|
|
1598
|
+
clearTimeout(timer);
|
|
1599
|
+
this.emitter.off(channelId, onReply);
|
|
1600
|
+
};
|
|
1601
|
+
this.emitter.on(channelId, onReply);
|
|
1602
|
+
});
|
|
1603
|
+
}
|
|
1604
|
+
/** Push subscription for SSE: calls onReply for each new reply addressed to `to`. */
|
|
1605
|
+
subscribe(channelId, to, onReply) {
|
|
1606
|
+
const handler = (r) => {
|
|
1607
|
+
if (r.to === to) onReply(r);
|
|
1608
|
+
};
|
|
1609
|
+
this.emitter.on(channelId, handler);
|
|
1610
|
+
return () => this.emitter.off(channelId, handler);
|
|
1611
|
+
}
|
|
1612
|
+
/** Drop a channel's outbox (on channel delete) — best-effort rewrite of the log. */
|
|
1613
|
+
purge(channelId) {
|
|
1614
|
+
this.byChannel.delete(channelId);
|
|
1615
|
+
this.seqByChannel.delete(channelId);
|
|
1616
|
+
if (!existsSync(this.file)) return;
|
|
1617
|
+
try {
|
|
1618
|
+
const kept = readFileSync(this.file, "utf8").split("\n").filter((l) => {
|
|
1619
|
+
if (!l.trim()) return false;
|
|
1620
|
+
try {
|
|
1621
|
+
return JSON.parse(l).channelId !== channelId;
|
|
1622
|
+
} catch {
|
|
1623
|
+
return false;
|
|
1624
|
+
}
|
|
1625
|
+
});
|
|
1626
|
+
const tmp = this.file + ".tmp";
|
|
1627
|
+
writeFileSync(tmp, kept.join("\n") + (kept.length ? "\n" : ""));
|
|
1628
|
+
renameSync(tmp, this.file);
|
|
1629
|
+
} catch {
|
|
1630
|
+
}
|
|
1631
|
+
}
|
|
1632
|
+
}
|
|
1633
|
+
|
|
1485
1634
|
function getParamNames(fn) {
|
|
1486
1635
|
const src = fn.toString();
|
|
1487
1636
|
const match = src.match(/^(?:async\s+)?(?:function\s*\w*)?\s*\(([^)]*)\)/);
|
|
@@ -2527,7 +2676,7 @@ async function registerMachineService(server, machineId, metadata, daemonState,
|
|
|
2527
2676
|
const tunnels = handlers.tunnels;
|
|
2528
2677
|
if (!tunnels) throw new Error("Tunnel management not available");
|
|
2529
2678
|
if (tunnels.has(params.name)) throw new Error(`Tunnel '${params.name}' already running`);
|
|
2530
|
-
const { FrpcTunnel } = await import('./frpc-
|
|
2679
|
+
const { FrpcTunnel } = await import('./frpc-BjWZ129L.mjs');
|
|
2531
2680
|
const tunnel = new FrpcTunnel({
|
|
2532
2681
|
name: params.name,
|
|
2533
2682
|
ports: params.ports,
|
|
@@ -2788,7 +2937,7 @@ QUESTION: ${params.question || "Summarize this concisely."}` }
|
|
|
2788
2937
|
}
|
|
2789
2938
|
const deps = buildSessionDeps(rpc, { cwd, ownerEmail: owner });
|
|
2790
2939
|
const sender = { name: context?.user?.email || context?.user?.id || "user", kind: "user", verified: true };
|
|
2791
|
-
const { toolsForRole } = await import('./sideband-
|
|
2940
|
+
const { toolsForRole } = await import('./sideband-BCKpph51.mjs');
|
|
2792
2941
|
const r2 = await runWiseAgent({ message: params.message, sender, config: { tools: toolsForRole(role2) }, deps, transport, model: resolved.model });
|
|
2793
2942
|
return fmt(r2);
|
|
2794
2943
|
}
|
|
@@ -2887,7 +3036,7 @@ QUESTION: ${params.question || "Summarize this concisely."}` }
|
|
|
2887
3036
|
if (r.error || !r.sender) return { error: r.error || "unauthorized" };
|
|
2888
3037
|
const callId = "call_" + Math.random().toString(16).slice(2, 12);
|
|
2889
3038
|
const rendered = renderMessage(c, { sender: r.sender, body: { message: kwargs.message }, callId });
|
|
2890
|
-
const { queryCore } = await import('./commands-
|
|
3039
|
+
const { queryCore } = await import('./commands-C29ciVUe.mjs');
|
|
2891
3040
|
const timeout = c.reply?.timeout_sec || 120;
|
|
2892
3041
|
let result;
|
|
2893
3042
|
try {
|
|
@@ -2904,7 +3053,7 @@ QUESTION: ${params.question || "Summarize this concisely."}` }
|
|
|
2904
3053
|
}
|
|
2905
3054
|
if (result.status === "error") return { ok: false, call_id: callId, status: "error", error: result.error };
|
|
2906
3055
|
if (result.status === "permission-pending") return { ok: false, call_id: callId, status: "permission-pending", error: result.error };
|
|
2907
|
-
return { ok: true, call_id: callId, status: "completed", reply: result.response };
|
|
3056
|
+
return { ok: true, call_id: callId, correlationId: callId, status: "completed", reply: result.response };
|
|
2908
3057
|
};
|
|
2909
3058
|
const channelsServiceInfo = await server.registerService(
|
|
2910
3059
|
{
|
|
@@ -2925,10 +3074,16 @@ QUESTION: ${params.question || "Summarize this concisely."}` }
|
|
|
2925
3074
|
}
|
|
2926
3075
|
return out;
|
|
2927
3076
|
},
|
|
2928
|
-
|
|
2929
|
-
|
|
3077
|
+
// Accept a plain `?channel=<id>` GET (positional, like `skill`) AS WELL AS
|
|
3078
|
+
// the kwargs-wrapped form. The Hypha HTTP gateway only maps a `?channel=`
|
|
3079
|
+
// query onto a param literally named `channel`; a kwargs-only signature left
|
|
3080
|
+
// `channel` undefined on GET, so describe() 404'd on every channel that
|
|
3081
|
+
// list() returned. Normalize both the string and `{channel}` object shapes.
|
|
3082
|
+
describe: async (channel) => {
|
|
3083
|
+
const id = typeof channel === "string" ? channel : channel?.channel;
|
|
3084
|
+
const rpc = id ? await findChannelOwner(id) : void 0;
|
|
2930
3085
|
if (!rpc?.channelDescribe) return { error: "channel not found" };
|
|
2931
|
-
return rpc.channelDescribe(
|
|
3086
|
+
return rpc.channelDescribe(id);
|
|
2932
3087
|
},
|
|
2933
3088
|
// Clean GET endpoint for the self-contained skill markdown. Param is
|
|
2934
3089
|
// named `channel` (not `kwargs`) so the Hypha HTTP gateway maps a plain
|
|
@@ -2958,9 +3113,26 @@ ${d?.error || "not found"}`;
|
|
|
2958
3113
|
trackInbound();
|
|
2959
3114
|
const res = resolveChannel(kwargs.channel, kwargs.session);
|
|
2960
3115
|
if ("error" in res) return { error: res.error };
|
|
2961
|
-
if (res.tier === "
|
|
2962
|
-
|
|
2963
|
-
|
|
3116
|
+
if (res.tier === "session" && !("stopped" in res)) {
|
|
3117
|
+
return res.rpc.channelReceive({ channel: kwargs.channel, key: kwargs.key, from: kwargs.from, cursor: kwargs.cursor, correlationId: kwargs.correlationId, wait: kwargs.wait }, context);
|
|
3118
|
+
}
|
|
3119
|
+
const { c, dir } = res;
|
|
3120
|
+
if (c.reply?.mode !== "queue") {
|
|
3121
|
+
return { error: "this channel has no async replies (not a queue-mode channel)" };
|
|
3122
|
+
}
|
|
3123
|
+
const u = context?.user;
|
|
3124
|
+
const r = resolveSender(c, {
|
|
3125
|
+
key: kwargs.key,
|
|
3126
|
+
from: kwargs.from,
|
|
3127
|
+
hyphaUser: u && u.is_anonymous !== true ? u.email || u.id : void 0,
|
|
3128
|
+
hyphaAnonymous: u?.is_anonymous === true,
|
|
3129
|
+
hyphaWorkspace: u?.scope?.current_workspace
|
|
3130
|
+
});
|
|
3131
|
+
if (r.error || !r.sender) return { error: r.error || "unauthorized" };
|
|
3132
|
+
const cursor = Math.max(0, Number(kwargs.cursor) || 0);
|
|
3133
|
+
const outbox = new ChannelOutbox(dir);
|
|
3134
|
+
const replies = outbox.since(c.id, cursor, r.sender.name, kwargs.correlationId);
|
|
3135
|
+
return { ok: true, replies, cursor: outbox.cursor(c.id) };
|
|
2964
3136
|
}
|
|
2965
3137
|
},
|
|
2966
3138
|
{ overwrite: true }
|
|
@@ -3202,138 +3374,6 @@ class RoutineRunner {
|
|
|
3202
3374
|
}
|
|
3203
3375
|
}
|
|
3204
3376
|
|
|
3205
|
-
const MAX_PER_CHANNEL = 200;
|
|
3206
|
-
const TTL_MS = 60 * 60 * 1e3;
|
|
3207
|
-
class ChannelOutbox {
|
|
3208
|
-
file;
|
|
3209
|
-
byChannel = /* @__PURE__ */ new Map();
|
|
3210
|
-
seqByChannel = /* @__PURE__ */ new Map();
|
|
3211
|
-
emitter = new EventEmitter();
|
|
3212
|
-
constructor(projectDir) {
|
|
3213
|
-
const dir = join(projectDir, ".svamp", "channels");
|
|
3214
|
-
this.file = join(dir, "_outbox.jsonl");
|
|
3215
|
-
this.emitter.setMaxListeners(0);
|
|
3216
|
-
try {
|
|
3217
|
-
mkdirSync(dir, { recursive: true });
|
|
3218
|
-
} catch {
|
|
3219
|
-
}
|
|
3220
|
-
this._load();
|
|
3221
|
-
}
|
|
3222
|
-
_load() {
|
|
3223
|
-
if (!existsSync(this.file)) return;
|
|
3224
|
-
const cutoff = Date.now() - TTL_MS;
|
|
3225
|
-
try {
|
|
3226
|
-
for (const line of readFileSync(this.file, "utf8").split("\n")) {
|
|
3227
|
-
if (!line.trim()) continue;
|
|
3228
|
-
let rec = null;
|
|
3229
|
-
try {
|
|
3230
|
-
rec = JSON.parse(line);
|
|
3231
|
-
} catch {
|
|
3232
|
-
continue;
|
|
3233
|
-
}
|
|
3234
|
-
if (!rec || rec.ts < cutoff) continue;
|
|
3235
|
-
const { channelId, ...reply } = rec;
|
|
3236
|
-
const arr = this.byChannel.get(channelId) || [];
|
|
3237
|
-
arr.push(reply);
|
|
3238
|
-
this.byChannel.set(channelId, arr);
|
|
3239
|
-
this.seqByChannel.set(channelId, Math.max(this.seqByChannel.get(channelId) || 0, reply.seq));
|
|
3240
|
-
}
|
|
3241
|
-
for (const [ch, arr] of this.byChannel) if (arr.length > MAX_PER_CHANNEL) this.byChannel.set(ch, arr.slice(-MAX_PER_CHANNEL));
|
|
3242
|
-
} catch {
|
|
3243
|
-
}
|
|
3244
|
-
}
|
|
3245
|
-
_evict(channelId) {
|
|
3246
|
-
const cutoff = Date.now() - TTL_MS;
|
|
3247
|
-
let arr = this.byChannel.get(channelId);
|
|
3248
|
-
if (!arr) return;
|
|
3249
|
-
if (arr.some((r) => r.ts < cutoff)) arr = arr.filter((r) => r.ts >= cutoff);
|
|
3250
|
-
if (arr.length > MAX_PER_CHANNEL) arr = arr.slice(-MAX_PER_CHANNEL);
|
|
3251
|
-
this.byChannel.set(channelId, arr);
|
|
3252
|
-
}
|
|
3253
|
-
/** Append a reply addressed to `to`. Assigns seq + ts, persists, and wakes waiters. */
|
|
3254
|
-
append(channelId, r) {
|
|
3255
|
-
const seq = (this.seqByChannel.get(channelId) || 0) + 1;
|
|
3256
|
-
this.seqByChannel.set(channelId, seq);
|
|
3257
|
-
const reply = { seq, ts: Date.now(), to: r.to, body: r.body, ...r.correlationId ? { correlationId: r.correlationId } : {} };
|
|
3258
|
-
const arr = this.byChannel.get(channelId) || [];
|
|
3259
|
-
arr.push(reply);
|
|
3260
|
-
this.byChannel.set(channelId, arr);
|
|
3261
|
-
this._evict(channelId);
|
|
3262
|
-
try {
|
|
3263
|
-
appendFileSync(this.file, JSON.stringify({ channelId, ...reply }) + "\n");
|
|
3264
|
-
} catch {
|
|
3265
|
-
try {
|
|
3266
|
-
mkdirSync(join(this.file, ".."), { recursive: true });
|
|
3267
|
-
appendFileSync(this.file, JSON.stringify({ channelId, ...reply }) + "\n");
|
|
3268
|
-
} catch {
|
|
3269
|
-
}
|
|
3270
|
-
}
|
|
3271
|
-
this.emitter.emit(channelId, reply);
|
|
3272
|
-
return reply;
|
|
3273
|
-
}
|
|
3274
|
-
/** Replies for `to` on `channelId` with seq > cursor (optionally one correlationId). */
|
|
3275
|
-
since(channelId, cursor, to, correlationId) {
|
|
3276
|
-
this._evict(channelId);
|
|
3277
|
-
return (this.byChannel.get(channelId) || []).filter((r) => r.seq > cursor && r.to === to && (!correlationId || r.correlationId === correlationId));
|
|
3278
|
-
}
|
|
3279
|
-
/** Highest seq on a channel (the cursor a caller gets back). */
|
|
3280
|
-
cursor(channelId) {
|
|
3281
|
-
return this.seqByChannel.get(channelId) || 0;
|
|
3282
|
-
}
|
|
3283
|
-
/**
|
|
3284
|
-
* Long-poll: resolve immediately if there are replies after `cursor`, else wait for
|
|
3285
|
-
* the next append (filtered to this channel + `to`) or `timeoutMs`, then return.
|
|
3286
|
-
*/
|
|
3287
|
-
wait(channelId, cursor, to, timeoutMs, correlationId) {
|
|
3288
|
-
const ready = this.since(channelId, cursor, to, correlationId);
|
|
3289
|
-
if (ready.length) return Promise.resolve({ replies: ready, cursor: this.cursor(channelId) });
|
|
3290
|
-
return new Promise((resolve) => {
|
|
3291
|
-
const onReply = (r) => {
|
|
3292
|
-
if (r.to !== to || correlationId && r.correlationId !== correlationId) return;
|
|
3293
|
-
cleanup();
|
|
3294
|
-
resolve({ replies: this.since(channelId, cursor, to, correlationId), cursor: this.cursor(channelId) });
|
|
3295
|
-
};
|
|
3296
|
-
const timer = setTimeout(() => {
|
|
3297
|
-
cleanup();
|
|
3298
|
-
resolve({ replies: [], cursor: this.cursor(channelId) });
|
|
3299
|
-
}, Math.max(0, timeoutMs));
|
|
3300
|
-
const cleanup = () => {
|
|
3301
|
-
clearTimeout(timer);
|
|
3302
|
-
this.emitter.off(channelId, onReply);
|
|
3303
|
-
};
|
|
3304
|
-
this.emitter.on(channelId, onReply);
|
|
3305
|
-
});
|
|
3306
|
-
}
|
|
3307
|
-
/** Push subscription for SSE: calls onReply for each new reply addressed to `to`. */
|
|
3308
|
-
subscribe(channelId, to, onReply) {
|
|
3309
|
-
const handler = (r) => {
|
|
3310
|
-
if (r.to === to) onReply(r);
|
|
3311
|
-
};
|
|
3312
|
-
this.emitter.on(channelId, handler);
|
|
3313
|
-
return () => this.emitter.off(channelId, handler);
|
|
3314
|
-
}
|
|
3315
|
-
/** Drop a channel's outbox (on channel delete) — best-effort rewrite of the log. */
|
|
3316
|
-
purge(channelId) {
|
|
3317
|
-
this.byChannel.delete(channelId);
|
|
3318
|
-
this.seqByChannel.delete(channelId);
|
|
3319
|
-
if (!existsSync(this.file)) return;
|
|
3320
|
-
try {
|
|
3321
|
-
const kept = readFileSync(this.file, "utf8").split("\n").filter((l) => {
|
|
3322
|
-
if (!l.trim()) return false;
|
|
3323
|
-
try {
|
|
3324
|
-
return JSON.parse(l).channelId !== channelId;
|
|
3325
|
-
} catch {
|
|
3326
|
-
return false;
|
|
3327
|
-
}
|
|
3328
|
-
});
|
|
3329
|
-
const tmp = this.file + ".tmp";
|
|
3330
|
-
writeFileSync(tmp, kept.join("\n") + (kept.length ? "\n" : ""));
|
|
3331
|
-
renameSync(tmp, this.file);
|
|
3332
|
-
} catch {
|
|
3333
|
-
}
|
|
3334
|
-
}
|
|
3335
|
-
}
|
|
3336
|
-
|
|
3337
3377
|
function channelPublicView(c) {
|
|
3338
3378
|
return { id: c.id, name: c.name, description: c.description, identity: { mode: c.identity?.mode }, action: c.action?.kind, bind: c.bind };
|
|
3339
3379
|
}
|
|
@@ -3870,7 +3910,7 @@ function createSessionStore(server, sessionId, initialMetadata, initialAgentStat
|
|
|
3870
3910
|
const result = await dispatchAgentChannel({ channel: c, sender: r.sender, message: rendered, deps, env: process.env });
|
|
3871
3911
|
channelStore.recordCall(c.id, { sender: r.sender.name, verified: r.sender.verified, callId, outcome: result.status });
|
|
3872
3912
|
syncChannelsToMetadata();
|
|
3873
|
-
return { ok: result.status === "completed", call_id: callId, status: result.status, reply: result.reply, tool_calls: result.toolCalls, error: result.error };
|
|
3913
|
+
return { ok: result.status === "completed", call_id: callId, correlationId: callId, status: result.status, reply: result.reply, tool_calls: result.toolCalls, error: result.error };
|
|
3874
3914
|
}
|
|
3875
3915
|
if (c.action?.kind === "loop") return { error: "loop channels are served by the channel server, not channelSend" };
|
|
3876
3916
|
const queue = c.reply?.mode === "queue";
|
|
@@ -9950,26 +9990,25 @@ function createSvampConfigChecker(directory, sessionId, getMetadata, setMetadata
|
|
|
9950
9990
|
} catch {
|
|
9951
9991
|
}
|
|
9952
9992
|
};
|
|
9953
|
-
let
|
|
9993
|
+
let announcedLoopStart = (() => {
|
|
9954
9994
|
const s = readLoopState(directory, sessionId);
|
|
9955
|
-
return s
|
|
9995
|
+
return s && (s.phase === "done" || s.phase === "gave_up") ? s.started_at ?? "\u2205" : null;
|
|
9956
9996
|
})();
|
|
9957
9997
|
const loopChecker = () => {
|
|
9958
9998
|
try {
|
|
9959
9999
|
const s = readLoopState(directory, sessionId);
|
|
9960
|
-
|
|
9961
|
-
const
|
|
9962
|
-
if (
|
|
9963
|
-
|
|
9964
|
-
|
|
9965
|
-
|
|
9966
|
-
|
|
9967
|
-
|
|
9968
|
-
|
|
9969
|
-
|
|
9970
|
-
|
|
9971
|
-
}
|
|
9972
|
-
lastLoopPhase = phase;
|
|
10000
|
+
if (!s || s.phase !== "done" && s.phase !== "gave_up") return;
|
|
10001
|
+
const key = s.started_at ?? "\u2205";
|
|
10002
|
+
if (key === announcedLoopStart) return;
|
|
10003
|
+
announcedLoopStart = key;
|
|
10004
|
+
const iter = typeof s.iteration === "number" ? s.iteration : 0;
|
|
10005
|
+
const plural = iter === 1 ? "" : "s";
|
|
10006
|
+
const msg = s.phase === "done" ? `\u{1F501} Loop complete \u2705 \u2014 finished after ${iter} iteration${plural}.` : `\u{1F501} Loop stopped \u{1F6D1} \u2014 gave up after ${iter} iteration${plural}${s.gave_up_reason ? ` (${s.gave_up_reason})` : ""}.`;
|
|
10007
|
+
sessionService.pushMessage(
|
|
10008
|
+
s.phase === "gave_up" ? { type: "message", message: msg, level: "warning" } : { type: "message", message: msg },
|
|
10009
|
+
"event"
|
|
10010
|
+
);
|
|
10011
|
+
logger.log(`[svampConfig] ${s.phase === "done" ? "Loop complete" : "Loop gave up"} (iter ${iter})`);
|
|
9973
10012
|
} catch {
|
|
9974
10013
|
}
|
|
9975
10014
|
};
|
|
@@ -10452,7 +10491,7 @@ async function startDaemon(options) {
|
|
|
10452
10491
|
const list = loadExposedTunnels().filter((t) => t.name !== name);
|
|
10453
10492
|
saveExposedTunnels(list);
|
|
10454
10493
|
}
|
|
10455
|
-
const { ServeManager } = await import('./serveManager-
|
|
10494
|
+
const { ServeManager } = await import('./serveManager-DrPFeC2o.mjs');
|
|
10456
10495
|
const serveManager = new ServeManager(SVAMP_HOME, (msg) => logger.log(`[SERVE] ${msg}`), hyphaServerUrl);
|
|
10457
10496
|
ensureAutoInstalledSkills(logger).catch(() => {
|
|
10458
10497
|
});
|
|
@@ -12937,7 +12976,7 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
|
|
|
12937
12976
|
const specs = loadExposedTunnels();
|
|
12938
12977
|
if (specs.length === 0) return;
|
|
12939
12978
|
logger.log(`[exposed-tunnels] Restoring ${specs.length} tunnel(s) from ${EXPOSED_TUNNELS_FILE}`);
|
|
12940
|
-
const { FrpcTunnel } = await import('./frpc-
|
|
12979
|
+
const { FrpcTunnel } = await import('./frpc-BjWZ129L.mjs');
|
|
12941
12980
|
for (const spec of specs) {
|
|
12942
12981
|
if (tunnels.has(spec.name)) continue;
|
|
12943
12982
|
try {
|
|
@@ -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-C29ciVUe.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-C29ciVUe.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-C29ciVUe.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-C29ciVUe.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-C29ciVUe.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-aNUfTpRW.mjs';
|
|
8
8
|
import 'os';
|
|
9
9
|
import 'fs/promises';
|
|
10
10
|
import 'url';
|
|
@@ -13,8 +13,8 @@ import 'node:fs';
|
|
|
13
13
|
import 'node:child_process';
|
|
14
14
|
import 'util';
|
|
15
15
|
import 'node:path';
|
|
16
|
-
import 'node:os';
|
|
17
16
|
import 'node:events';
|
|
17
|
+
import 'node:os';
|
|
18
18
|
import '@agentclientprotocol/sdk';
|
|
19
19
|
import '@modelcontextprotocol/sdk/client/index.js';
|
|
20
20
|
import '@modelcontextprotocol/sdk/client/stdio.js';
|
|
@@ -713,7 +713,7 @@ class ServeManager {
|
|
|
713
713
|
const mount = this.mounts.get(mountName);
|
|
714
714
|
const subdomainOverride = mount?.access === "link" && mount.linkToken ? /* @__PURE__ */ new Map([[this.port, `static-${subdomainSafe}-${mount.linkToken}`]]) : void 0;
|
|
715
715
|
try {
|
|
716
|
-
const { FrpcTunnel } = await import('./frpc-
|
|
716
|
+
const { FrpcTunnel } = await import('./frpc-BjWZ129L.mjs');
|
|
717
717
|
let tunnel;
|
|
718
718
|
tunnel = new FrpcTunnel({
|
|
719
719
|
name: tunnelName,
|