svamp-cli 0.2.284 → 0.2.290
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/{adminCommands-DPZaByla.mjs → adminCommands-BVvpkVsG.mjs} +22 -3
- package/dist/{agentCommands-B23M4vER.mjs → agentCommands-fY4keaFA.mjs} +5 -5
- package/dist/{auth-DPZSnISj.mjs → auth-SR7v-8nf.mjs} +1 -1
- package/dist/{cli-D8tJd71c.mjs → cli-Re14H3q0.mjs} +76 -69
- package/dist/cli.mjs +2 -2
- package/dist/{commands-CDFhSKgn.mjs → commands-BC-T6wDo.mjs} +2 -2
- package/dist/{commands-BHO7rzSh.mjs → commands-Bv5EcsN_.mjs} +1 -1
- package/dist/{commands-DDf0W30g.mjs → commands-CBsV6z9K.mjs} +2 -2
- package/dist/commands-CIyv2Qt-.mjs +258 -0
- package/dist/{commands-BABblJRp.mjs → commands-Dc9t_OeY.mjs} +1 -1
- package/dist/{commands-BqaOHWym.mjs → commands-Dd-6WXYJ.mjs} +9 -9
- package/dist/{commands-Cp8G-iuw.mjs → commands-Dwf-ntY-.mjs} +2 -2
- package/dist/{commands-DqsoW-S0.mjs → commands-zagci6-n.mjs} +1 -1
- package/dist/{fleet-BxhHefua.mjs → fleet-DlRlerEG.mjs} +1 -1
- package/dist/{frpc-BsR6aGNJ.mjs → frpc-B8zTErxt.mjs} +45 -27
- package/dist/{headlessCli-B-aMhdKx.mjs → headlessCli-D22LyDyO.mjs} +2 -2
- package/dist/index.mjs +1 -1
- package/dist/{notifyCommands-CfnthGpX.mjs → notifyCommands-5PueOg8Q.mjs} +1 -1
- package/dist/package-CpmmajAP.mjs +64 -0
- package/dist/{rpc-BjrKqEib.mjs → rpc-D3Hg4y67.mjs} +1 -1
- package/dist/{rpc-B5BRaVsS.mjs → rpc-olai-LcU.mjs} +1 -1
- package/dist/{run-DWJenrBe.mjs → run-B6V1wuT6.mjs} +1 -1
- package/dist/{run-CRTzyKbn.mjs → run-BNiSOlBf.mjs} +164 -30
- package/dist/{scheduler-QYMtbUDe.mjs → scheduler--MbVadb0.mjs} +1 -1
- package/dist/{serveCommands-Cj3MLbZb.mjs → serveCommands-BONMg_af.mjs} +5 -5
- package/dist/{sideband-CKmZxwY6.mjs → sideband-Dnuy9-IL.mjs} +1 -1
- package/package.json +46 -46
- package/dist/package-Br4fCS7J.mjs +0 -64
|
@@ -2973,7 +2973,7 @@ Connection: close\r
|
|
|
2973
2973
|
const mount = this.mounts.get(mountName);
|
|
2974
2974
|
const subdomainOverride = mount?.access === "link" && mount.linkToken ? /* @__PURE__ */ new Map([[this.port, buildLinkSubdomain(subdomainSafe, mount.linkToken)]]) : void 0;
|
|
2975
2975
|
try {
|
|
2976
|
-
const { FrpcTunnel } = await import('./frpc-
|
|
2976
|
+
const { FrpcTunnel } = await import('./frpc-B8zTErxt.mjs');
|
|
2977
2977
|
let tunnel;
|
|
2978
2978
|
tunnel = new FrpcTunnel({
|
|
2979
2979
|
name: tunnelName,
|
|
@@ -3269,11 +3269,17 @@ function buildCodexProviderArgs(cfg) {
|
|
|
3269
3269
|
if (cfg.model) configArgs.push("-c", `model=${JSON.stringify(cfg.model)}`);
|
|
3270
3270
|
return { configArgs, env: { [CODEX_PROVIDER_KEY_ENV]: cfg.apiKey }, model: cfg.model };
|
|
3271
3271
|
}
|
|
3272
|
+
function codexForcedModel(env = process.env) {
|
|
3273
|
+
const f = (env.SVAMP_CODEX_FORCE_MODEL || "").toLowerCase();
|
|
3274
|
+
if (!f || f === "0" || f === "false" || f === "no" || f === "off") return void 0;
|
|
3275
|
+
return env.SVAMP_CODEX_MODEL || env.LLM_MODEL || void 0;
|
|
3276
|
+
}
|
|
3272
3277
|
|
|
3273
3278
|
var codexProvider = /*#__PURE__*/Object.freeze({
|
|
3274
3279
|
__proto__: null,
|
|
3275
3280
|
CODEX_PROVIDER_KEY_ENV: CODEX_PROVIDER_KEY_ENV,
|
|
3276
3281
|
buildCodexProviderArgs: buildCodexProviderArgs,
|
|
3282
|
+
codexForcedModel: codexForcedModel,
|
|
3277
3283
|
codexPermissionSettings: codexPermissionSettings,
|
|
3278
3284
|
hasCustomProvider: hasCustomProvider,
|
|
3279
3285
|
resolveCodexProvider: resolveCodexProvider
|
|
@@ -4361,6 +4367,48 @@ function renderMessage(channel, { sender = {}, body = {}, query = {}, callId, no
|
|
|
4361
4367
|
return renderTemplate(channel.template || DEFAULT_TEMPLATE, ctx);
|
|
4362
4368
|
}
|
|
4363
4369
|
|
|
4370
|
+
class StatelessDispatchLimiter {
|
|
4371
|
+
constructor(maxConcurrent, maxPerSender) {
|
|
4372
|
+
this.maxConcurrent = maxConcurrent;
|
|
4373
|
+
this.maxPerSender = maxPerSender;
|
|
4374
|
+
}
|
|
4375
|
+
inflight = 0;
|
|
4376
|
+
perSender = /* @__PURE__ */ new Map();
|
|
4377
|
+
/** Try to reserve a dispatch slot for `sender`. Returns false (reserve nothing) if either cap
|
|
4378
|
+
* is already at its limit. On true, the caller MUST call release(sender) exactly once. */
|
|
4379
|
+
tryAcquire(sender) {
|
|
4380
|
+
const key = sender || "anonymous";
|
|
4381
|
+
if (this.inflight >= this.maxConcurrent) return false;
|
|
4382
|
+
const s = this.perSender.get(key) || 0;
|
|
4383
|
+
if (s >= this.maxPerSender) return false;
|
|
4384
|
+
this.inflight++;
|
|
4385
|
+
this.perSender.set(key, s + 1);
|
|
4386
|
+
return true;
|
|
4387
|
+
}
|
|
4388
|
+
/** Release a slot previously reserved by tryAcquire. Clamped so a double-release can't drive
|
|
4389
|
+
* the counters negative. */
|
|
4390
|
+
release(sender) {
|
|
4391
|
+
const key = sender || "anonymous";
|
|
4392
|
+
if (this.inflight > 0) this.inflight--;
|
|
4393
|
+
const s = (this.perSender.get(key) || 0) - 1;
|
|
4394
|
+
if (s > 0) this.perSender.set(key, s);
|
|
4395
|
+
else this.perSender.delete(key);
|
|
4396
|
+
}
|
|
4397
|
+
/** Current total in-flight dispatches (for diagnostics/tests). */
|
|
4398
|
+
get active() {
|
|
4399
|
+
return this.inflight;
|
|
4400
|
+
}
|
|
4401
|
+
}
|
|
4402
|
+
function statelessDispatchCaps(env = process.env) {
|
|
4403
|
+
const num = (v, dflt) => {
|
|
4404
|
+
const n = Number(v);
|
|
4405
|
+
return Number.isFinite(n) && n > 0 ? Math.floor(n) : dflt;
|
|
4406
|
+
};
|
|
4407
|
+
const concurrent = num(env.SVAMP_CHANNEL_MAX_CONCURRENT, 6);
|
|
4408
|
+
const perSender = Math.min(num(env.SVAMP_CHANNEL_MAX_PER_SENDER, 2), concurrent);
|
|
4409
|
+
return { concurrent, perSender };
|
|
4410
|
+
}
|
|
4411
|
+
|
|
4364
4412
|
const MAX_PER_CHANNEL = 200;
|
|
4365
4413
|
const TTL_MS = 60 * 60 * 1e3;
|
|
4366
4414
|
const COMPACT_EVERY = 500;
|
|
@@ -4588,6 +4636,11 @@ class ChannelOutbox {
|
|
|
4588
4636
|
}
|
|
4589
4637
|
}
|
|
4590
4638
|
|
|
4639
|
+
var outbox = /*#__PURE__*/Object.freeze({
|
|
4640
|
+
__proto__: null,
|
|
4641
|
+
ChannelOutbox: ChannelOutbox
|
|
4642
|
+
});
|
|
4643
|
+
|
|
4591
4644
|
function getParamNames(fn) {
|
|
4592
4645
|
const src = fn.toString();
|
|
4593
4646
|
const match = src.match(/^(?:async\s+)?(?:function\s*\w*)?\s*\(([^)]*)\)/);
|
|
@@ -5816,7 +5869,7 @@ async function registerMachineService(server, machineId, metadata, daemonState,
|
|
|
5816
5869
|
const tunnels = handlers.tunnels;
|
|
5817
5870
|
if (!tunnels) throw new Error("Tunnel management not available");
|
|
5818
5871
|
if (tunnels.has(params.name)) throw new Error(`Tunnel '${params.name}' already running`);
|
|
5819
|
-
const { FrpcTunnel } = await import('./frpc-
|
|
5872
|
+
const { FrpcTunnel } = await import('./frpc-B8zTErxt.mjs');
|
|
5820
5873
|
const tunnel = new FrpcTunnel({
|
|
5821
5874
|
name: params.name,
|
|
5822
5875
|
ports: params.ports,
|
|
@@ -6292,7 +6345,7 @@ QUESTION: ${params.question || "Summarize this concisely."}` }
|
|
|
6292
6345
|
}
|
|
6293
6346
|
const deps = buildSessionDeps(rpc, { cwd, ownerEmail: owner });
|
|
6294
6347
|
const sender = { name: context?.user?.email || context?.user?.id || "user", kind: "user", verified: true };
|
|
6295
|
-
const { toolsForRole } = await import('./sideband-
|
|
6348
|
+
const { toolsForRole } = await import('./sideband-Dnuy9-IL.mjs');
|
|
6296
6349
|
const r2 = await runWiseAgent({ message: params.message, sender, config: { tools: toolsForRole(role2) }, deps, transport, model: resolved.model });
|
|
6297
6350
|
return fmt(r2);
|
|
6298
6351
|
}
|
|
@@ -6379,6 +6432,8 @@ QUESTION: ${params.question || "Summarize this concisely."}` }
|
|
|
6379
6432
|
return handler(...callArgs);
|
|
6380
6433
|
}
|
|
6381
6434
|
};
|
|
6435
|
+
const _caps = statelessDispatchCaps();
|
|
6436
|
+
const statelessLimiter = new StatelessDispatchLimiter(_caps.concurrent, _caps.perSender);
|
|
6382
6437
|
const dispatchStateless = async (c, dir, kwargs, context) => {
|
|
6383
6438
|
const u = context?.user;
|
|
6384
6439
|
const r = resolveSender(c, {
|
|
@@ -6390,8 +6445,12 @@ QUESTION: ${params.question || "Summarize this concisely."}` }
|
|
|
6390
6445
|
});
|
|
6391
6446
|
if (r.error || !r.sender) return { error: r.error || "unauthorized" };
|
|
6392
6447
|
const callId = "call_" + Math.random().toString(16).slice(2, 12);
|
|
6448
|
+
const senderKey = (r.sender.name || "anonymous").toLowerCase();
|
|
6449
|
+
if (!statelessLimiter.tryAcquire(senderKey)) {
|
|
6450
|
+
return { ok: false, call_id: callId, status: "busy", error: "channel is busy (too many concurrent requests) \u2014 retry shortly" };
|
|
6451
|
+
}
|
|
6393
6452
|
const rendered = renderMessage(c, { sender: r.sender, body: { message: kwargs.message }, callId });
|
|
6394
|
-
const { queryCore } = await import('./commands-
|
|
6453
|
+
const { queryCore } = await import('./commands-Dc9t_OeY.mjs');
|
|
6395
6454
|
const timeout = c.reply?.timeout_sec || 120;
|
|
6396
6455
|
let result;
|
|
6397
6456
|
try {
|
|
@@ -6399,6 +6458,7 @@ QUESTION: ${params.question || "Summarize this concisely."}` }
|
|
|
6399
6458
|
} catch (e) {
|
|
6400
6459
|
return { ok: false, call_id: callId, status: "error", error: e?.message || String(e) };
|
|
6401
6460
|
} finally {
|
|
6461
|
+
statelessLimiter.release(senderKey);
|
|
6402
6462
|
if (result?.sessionId) {
|
|
6403
6463
|
try {
|
|
6404
6464
|
handlers.deleteSession?.(result.sessionId);
|
|
@@ -6723,7 +6783,9 @@ function recordWake(now) {
|
|
|
6723
6783
|
}
|
|
6724
6784
|
function senderIsHuman(message) {
|
|
6725
6785
|
const f = message.from || "";
|
|
6726
|
-
|
|
6786
|
+
if (!(f.startsWith("cli:") || f.startsWith("user:"))) return false;
|
|
6787
|
+
if (message.verified === false) return false;
|
|
6788
|
+
return true;
|
|
6727
6789
|
}
|
|
6728
6790
|
function senderKey(message) {
|
|
6729
6791
|
return message.fromSession || message.from || "unknown";
|
|
@@ -9388,10 +9450,27 @@ class SessionArtifactSync {
|
|
|
9388
9450
|
async listRemoteSessions() {
|
|
9389
9451
|
if (!this.initialized || !this.artifactManager || !this.collectionId) return [];
|
|
9390
9452
|
try {
|
|
9391
|
-
const
|
|
9392
|
-
|
|
9393
|
-
|
|
9394
|
-
|
|
9453
|
+
const PAGE = 100;
|
|
9454
|
+
const children = [];
|
|
9455
|
+
const seen = /* @__PURE__ */ new Set();
|
|
9456
|
+
for (let offset = 0; ; offset += PAGE) {
|
|
9457
|
+
const page = await this.artifactManager.list({
|
|
9458
|
+
parent_id: this.collectionId,
|
|
9459
|
+
offset,
|
|
9460
|
+
limit: PAGE,
|
|
9461
|
+
_rkwargs: true
|
|
9462
|
+
});
|
|
9463
|
+
if (!Array.isArray(page) || page.length === 0) break;
|
|
9464
|
+
let fresh = 0;
|
|
9465
|
+
for (const c of page) {
|
|
9466
|
+
const k = String(c?.id ?? c?.manifest?.id ?? c?.alias ?? `${offset}:${fresh}`);
|
|
9467
|
+
if (seen.has(k)) continue;
|
|
9468
|
+
seen.add(k);
|
|
9469
|
+
children.push(c);
|
|
9470
|
+
fresh++;
|
|
9471
|
+
}
|
|
9472
|
+
if (page.length < PAGE || fresh === 0) break;
|
|
9473
|
+
}
|
|
9395
9474
|
return (children || []).map((child) => ({
|
|
9396
9475
|
sessionId: child.manifest?.sessionId || child.alias?.replace("session-", ""),
|
|
9397
9476
|
machineId: child.manifest?.machineId,
|
|
@@ -9624,22 +9703,63 @@ class SharingNotificationSync {
|
|
|
9624
9703
|
this.log(`[USER EVENT] Failed to publish ${event.type} for ${event.recipientEmail}: ${err.message}`);
|
|
9625
9704
|
}
|
|
9626
9705
|
}
|
|
9706
|
+
/**
|
|
9707
|
+
* List ALL children of a collection, paginating past hypha's default page cap (`limit=100`,
|
|
9708
|
+
* server hypha/artifact.py list_children). The svamp-user-events / svamp-shared-sessions
|
|
9709
|
+
* collections are GLOBAL across every deployment user, so a single unpaginated list() would
|
|
9710
|
+
* return only the newest ~100 rows across ALL recipients — silently hiding a given user's
|
|
9711
|
+
* events past that page. We page offset+=100 until a short/empty/duplicate page.
|
|
9712
|
+
*/
|
|
9713
|
+
async listAllChildren(parentId) {
|
|
9714
|
+
const PAGE = 100;
|
|
9715
|
+
const all = [];
|
|
9716
|
+
const seen = /* @__PURE__ */ new Set();
|
|
9717
|
+
for (let offset = 0; ; offset += PAGE) {
|
|
9718
|
+
const page = await this.artifactManager.list({ parent_id: parentId, offset, limit: PAGE, _rkwargs: true });
|
|
9719
|
+
if (!Array.isArray(page) || page.length === 0) break;
|
|
9720
|
+
let fresh = 0;
|
|
9721
|
+
for (const c of page) {
|
|
9722
|
+
const k = String(c?.id ?? c?.manifest?.id ?? c?.alias ?? `${offset}:${fresh}`);
|
|
9723
|
+
if (seen.has(k)) continue;
|
|
9724
|
+
seen.add(k);
|
|
9725
|
+
all.push(c);
|
|
9726
|
+
fresh++;
|
|
9727
|
+
}
|
|
9728
|
+
if (page.length < PAGE || fresh === 0) break;
|
|
9729
|
+
}
|
|
9730
|
+
return all;
|
|
9731
|
+
}
|
|
9627
9732
|
/**
|
|
9628
9733
|
* List user events addressed to `recipientEmail` (the bell inbox), newest first, excluding
|
|
9629
9734
|
* expired ones. Reuses the global svamp-user-events collection — cross-workspace by design.
|
|
9630
|
-
* Mirrors the webapp's fetchUserEvents so the CLI reads the same source of truth.
|
|
9735
|
+
* Mirrors the webapp's fetchUserEvents so the CLI reads the same source of truth. Paginated
|
|
9736
|
+
* so a recipient's events past the first 100 global rows are not silently dropped; expired
|
|
9737
|
+
* events the caller owns are best-effort pruned (a no-op until the collection's
|
|
9738
|
+
* recipient_can_delete is active — swallowed on PermissionError).
|
|
9631
9739
|
*/
|
|
9632
9740
|
async listUserEvents(recipientEmail) {
|
|
9633
9741
|
if (!this.initialized || !this.eventCollectionId) return [];
|
|
9634
9742
|
const normalized = recipientEmail.toLowerCase();
|
|
9635
9743
|
try {
|
|
9636
|
-
const children = await this.
|
|
9637
|
-
parent_id: this.eventCollectionId,
|
|
9638
|
-
_rkwargs: true
|
|
9639
|
-
});
|
|
9744
|
+
const children = await this.listAllChildren(this.eventCollectionId);
|
|
9640
9745
|
if (!Array.isArray(children)) return [];
|
|
9641
9746
|
const now = Date.now();
|
|
9642
|
-
|
|
9747
|
+
const live = [];
|
|
9748
|
+
const expiredOwnedIds = [];
|
|
9749
|
+
for (const c of children) {
|
|
9750
|
+
const m = c?.manifest;
|
|
9751
|
+
if (!m || typeof m.recipientEmail !== "string" || m.recipientEmail.toLowerCase() !== normalized) continue;
|
|
9752
|
+
if (m.expiresAt && m.expiresAt <= now) {
|
|
9753
|
+
if (c?.id) expiredOwnedIds.push(c.id);
|
|
9754
|
+
continue;
|
|
9755
|
+
}
|
|
9756
|
+
live.push(m);
|
|
9757
|
+
}
|
|
9758
|
+
for (const id of expiredOwnedIds) {
|
|
9759
|
+
this.artifactManager.delete({ artifact_id: id, _rkwargs: true }).catch(() => {
|
|
9760
|
+
});
|
|
9761
|
+
}
|
|
9762
|
+
return live.sort((a, b) => (b.createdAt || 0) - (a.createdAt || 0));
|
|
9643
9763
|
} catch (err) {
|
|
9644
9764
|
this.log(`[USER EVENT] listUserEvents failed for ${recipientEmail}: ${err.message}`);
|
|
9645
9765
|
return [];
|
|
@@ -9654,7 +9774,7 @@ class SharingNotificationSync {
|
|
|
9654
9774
|
if (!this.initialized || !this.eventCollectionId) return false;
|
|
9655
9775
|
const normalized = recipientEmail.toLowerCase();
|
|
9656
9776
|
try {
|
|
9657
|
-
const children = await this.
|
|
9777
|
+
const children = await this.listAllChildren(this.eventCollectionId);
|
|
9658
9778
|
if (!Array.isArray(children)) return false;
|
|
9659
9779
|
const short = eventId.slice(0, 8);
|
|
9660
9780
|
const match = children.find((c) => {
|
|
@@ -9944,6 +10064,7 @@ function startToolCall(toolCallId, toolKind, update, ctx, source) {
|
|
|
9944
10064
|
ctx.activeToolCalls.delete(toolCallId);
|
|
9945
10065
|
ctx.toolCallStartTimes.delete(toolCallId);
|
|
9946
10066
|
ctx.toolCallTimeouts.delete(toolCallId);
|
|
10067
|
+
ctx.toolCallIdToNameMap.delete(toolCallId);
|
|
9947
10068
|
ctx.log(`Tool call TIMEOUT: ${toolCallId} (${toolKind}) after ${(timeoutMs / 1e3).toFixed(0)}s`);
|
|
9948
10069
|
if (ctx.activeToolCalls.size === 0) {
|
|
9949
10070
|
ctx.emitIdleStatus();
|
|
@@ -12455,6 +12576,13 @@ function shouldIsolate(input) {
|
|
|
12455
12576
|
return input.optionsSecurityContext !== null && input.optionsSecurityContext !== void 0;
|
|
12456
12577
|
}
|
|
12457
12578
|
|
|
12579
|
+
function classifyRestoreContinuation(opts) {
|
|
12580
|
+
if (opts.isOrphaned) return "none";
|
|
12581
|
+
if (opts.loopActive) return "loop-resume";
|
|
12582
|
+
if (opts.wasProcessing && opts.hasResumeId) return "auto-continue";
|
|
12583
|
+
return "none";
|
|
12584
|
+
}
|
|
12585
|
+
|
|
12458
12586
|
function getShareBaseUrl() {
|
|
12459
12587
|
return getSvampWebBaseUrl();
|
|
12460
12588
|
}
|
|
@@ -14409,7 +14537,7 @@ You are running inside a Svamp session (id: ${sessionId}${handle ? `, handle: ${
|
|
|
14409
14537
|
- \`svamp session link add "<url>" --label "<label>" [--icon "\u{1F517}"]\` \u2014 surface viewable artifacts (dashboards, reports, apps) as buttons in the composer "Launch Pad". Manage many: \`link list\` \xB7 \`link update <id> [--url|--label|--icon]\` \xB7 \`link remove <id>\`. Adding the same URL again UPDATES that entry (URL is the dedup key \u2014 no duplicates). Tunnel/exposed URLs from \`svamp service expose\` are added to the Launch Pad AUTOMATICALLY, so do NOT \`session link add\` a URL you just exposed. A session can have MANY links (the Launch Pad); \`session set-link "<url>" "<label>"\` also appends + dedupes by URL (alias of \`link add\`).
|
|
14410
14538
|
- \`svamp session notify "<msg>" [--level info|warning|error]\` \u2014 send a user notification
|
|
14411
14539
|
|
|
14412
|
-
**Artifacts (rich inline output):** Write HTML to a file (\`.svamp/<sessionId>/outputs/\` for disposable, \`./outputs/\` for persistent) and emit \`<artifact src="./outputs/viz.html" title="..." />\` \u2014 the Svamp client renders it inline as a sandboxed iframe with theme CSS vars, auto-resize, file inlining, and a header with Reload/Fullscreen/\u22EE menu. Modes: \`default\`, \`bare\` (controls on hover), \`immersive\` (no chrome), \`card\` (click-to-open preview with \`description\`+\`poster\`). Use \`<artifact src="https://..." height="540" />\` to embed a live server.
|
|
14540
|
+
**Artifacts (rich inline output):** Write HTML to a file (\`.svamp/<sessionId>/outputs/\` for disposable, \`./outputs/\` for persistent) and emit \`<artifact src="./outputs/viz.html" title="..." />\` \u2014 the Svamp client renders it inline as a sandboxed iframe with theme CSS vars, auto-resize, file inlining, and a header with Reload/Fullscreen/\u22EE menu. Modes: \`default\`, \`bare\` (controls on hover), \`immersive\` (no chrome), \`card\` (click-to-open preview with \`description\`+\`poster\`). Use \`<artifact src="https://..." height="540" />\` to embed a live server. To share it as a link, DEFAULT to a persistent, lazy mount \u2014 \`svamp serve apply <yaml>\` (a static dir, or a \`process:\` block with \`wake_on_request: true\` + \`idle_timeout_sec\` for a dynamic server): it survives daemon restarts, idles to near-zero memory, and wakes on the next visit (the serverless pattern users expect). Reserve ad-hoc \`svamp serve <name> <dir>\` / \`svamp service expose\` for genuinely throwaway demos ONLY \u2014 those vanish on restart, which confuses users who revisit. **Inline artifacts (\`<artifact>\u2026HTML\u2026</artifact>\` with a body) are for SMALL self-contained HTML only \u2014 anything large (images, datasets, big reports, base64) MUST be written to a file and referenced via \`<artifact src="./outputs/<file>" />\`, never pasted inline. An inline body over 512 KB is rejected (error card + stripped) because it bloats stored history.** See the \`artifact\` skill.
|
|
14413
14541
|
|
|
14414
14542
|
## Shared environment
|
|
14415
14543
|
|
|
@@ -16145,7 +16273,7 @@ async function startDaemon(options) {
|
|
|
16145
16273
|
try {
|
|
16146
16274
|
const dir = loadSessionIndex()[sessionId]?.directory;
|
|
16147
16275
|
if (!dir) return;
|
|
16148
|
-
const { reconcileServiceLinks } = await import('./agentCommands-
|
|
16276
|
+
const { reconcileServiceLinks } = await import('./agentCommands-fY4keaFA.mjs');
|
|
16149
16277
|
const configPath = getSvampConfigPath(dir, sessionId);
|
|
16150
16278
|
const config = readSvampConfig(configPath);
|
|
16151
16279
|
const entries = Array.from(urls.entries());
|
|
@@ -16163,7 +16291,7 @@ async function startDaemon(options) {
|
|
|
16163
16291
|
}
|
|
16164
16292
|
}
|
|
16165
16293
|
async function createExposedTunnel(spec) {
|
|
16166
|
-
const { FrpcTunnel } = await import('./frpc-
|
|
16294
|
+
const { FrpcTunnel } = await import('./frpc-B8zTErxt.mjs');
|
|
16167
16295
|
const tunnel = new FrpcTunnel({
|
|
16168
16296
|
name: spec.name,
|
|
16169
16297
|
ports: spec.ports,
|
|
@@ -18379,11 +18507,11 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
|
|
|
18379
18507
|
});
|
|
18380
18508
|
},
|
|
18381
18509
|
onIssue: async (params) => {
|
|
18382
|
-
const { issueRpc } = await import('./rpc-
|
|
18510
|
+
const { issueRpc } = await import('./rpc-olai-LcU.mjs');
|
|
18383
18511
|
return issueRpc(params?.cwd || directory, params || {}, { notifySession: notifyIssueOwner, rekickLoopOwner });
|
|
18384
18512
|
},
|
|
18385
18513
|
onWorkflow: async (params) => {
|
|
18386
|
-
const { workflowRpc } = await import('./rpc-
|
|
18514
|
+
const { workflowRpc } = await import('./rpc-D3Hg4y67.mjs');
|
|
18387
18515
|
return workflowRpc(params?.cwd || directory, params || {});
|
|
18388
18516
|
},
|
|
18389
18517
|
onRipgrep: async (args, cwd) => {
|
|
@@ -18755,7 +18883,8 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
|
|
|
18755
18883
|
logger.log(`[${agentName} Session ${sessionId}] Ignoring meta.permissionMode='${msgMeta.permissionMode}' from sendMessage (current: ${currentPermissionMode}; use switchMode to change)`);
|
|
18756
18884
|
}
|
|
18757
18885
|
{
|
|
18758
|
-
const
|
|
18886
|
+
const forcedModel = agentName === "codex" ? codexForcedModel() : void 0;
|
|
18887
|
+
const rawModel = forcedModel || (typeof msgMeta?.model === "string" && msgMeta.model ? msgMeta.model : void 0);
|
|
18759
18888
|
const desiredModel = rawModel || agentConfig?.default_model || void 0;
|
|
18760
18889
|
if (desiredModel !== appliedAgentModel) {
|
|
18761
18890
|
agentBackend?.setModel?.(desiredModel);
|
|
@@ -18995,11 +19124,11 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
|
|
|
18995
19124
|
});
|
|
18996
19125
|
},
|
|
18997
19126
|
onIssue: async (params) => {
|
|
18998
|
-
const { issueRpc } = await import('./rpc-
|
|
19127
|
+
const { issueRpc } = await import('./rpc-olai-LcU.mjs');
|
|
18999
19128
|
return issueRpc(params?.cwd || directory, params || {}, { notifySession: notifyIssueOwner, rekickLoopOwner });
|
|
19000
19129
|
},
|
|
19001
19130
|
onWorkflow: async (params) => {
|
|
19002
|
-
const { workflowRpc } = await import('./rpc-
|
|
19131
|
+
const { workflowRpc } = await import('./rpc-D3Hg4y67.mjs');
|
|
19003
19132
|
return workflowRpc(params?.cwd || directory, params || {});
|
|
19004
19133
|
},
|
|
19005
19134
|
onRipgrep: async (args, cwd) => {
|
|
@@ -19175,7 +19304,7 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
|
|
|
19175
19304
|
}
|
|
19176
19305
|
}
|
|
19177
19306
|
}
|
|
19178
|
-
const codexModel = options2.model || agentConfig?.default_model || provider.model || void 0;
|
|
19307
|
+
const codexModel = codexForcedModel() || options2.model || agentConfig?.default_model || provider.model || void 0;
|
|
19179
19308
|
const codexPerm = codexPermissionSettings(currentPermissionMode);
|
|
19180
19309
|
logger.log(`[Agent Session ${sessionId}] Codex backend: app-server (model=${codexModel ?? "default"}${provider.apiBase ? `, provider=${provider.apiBase}` : ""}${accountDesc ? `, account=${accountDesc}` : ""}, mode=${currentPermissionMode} \u2192 approval=${codexPerm.approvalPolicy}/sandbox=${codexPerm.sandbox})`);
|
|
19181
19310
|
if (acpResumeThreadId) logger.log(`[Agent Session ${sessionId}] Resuming Codex thread ${acpResumeThreadId} (restart recovery)`);
|
|
@@ -19950,10 +20079,15 @@ ${oracle.output.trim().slice(0, 500)}`, "\u{1F501} Continuing loop");
|
|
|
19950
20079
|
break;
|
|
19951
20080
|
}
|
|
19952
20081
|
}
|
|
19953
|
-
|
|
20082
|
+
const _restoreAction = classifyRestoreContinuation({
|
|
20083
|
+
wasProcessing: !!persisted.wasProcessing,
|
|
20084
|
+
hasResumeId: !!persisted.claudeResumeId,
|
|
20085
|
+
isOrphaned: !!isOrphaned,
|
|
20086
|
+
loopActive: isLoopActiveForSession(persisted.directory, persisted.sessionId)
|
|
20087
|
+
});
|
|
20088
|
+
if (_restoreAction === "auto-continue") {
|
|
19954
20089
|
sessionsToAutoContinue.push(persisted.sessionId);
|
|
19955
|
-
}
|
|
19956
|
-
if (!isOrphaned && !persisted.wasProcessing && isLoopActiveForSession(persisted.directory, persisted.sessionId)) {
|
|
20090
|
+
} else if (_restoreAction === "loop-resume") {
|
|
19957
20091
|
sessionsToLoopResume.push({ sessionId: persisted.sessionId, directory: persisted.directory });
|
|
19958
20092
|
}
|
|
19959
20093
|
} else {
|
|
@@ -20114,7 +20248,7 @@ ${oracle.output.trim().slice(0, 500)}`, "\u{1F501} Continuing loop");
|
|
|
20114
20248
|
const PING_TIMEOUT_MS = 15e3;
|
|
20115
20249
|
const POST_RECONNECT_GRACE_MS = 2e4;
|
|
20116
20250
|
const RECONNECT_JITTER_MS = 2500;
|
|
20117
|
-
const { WorkflowScheduler } = await import('./scheduler
|
|
20251
|
+
const { WorkflowScheduler } = await import('./scheduler--MbVadb0.mjs');
|
|
20118
20252
|
const workflowScheduler = new WorkflowScheduler({
|
|
20119
20253
|
projectRoots: () => {
|
|
20120
20254
|
const dirs = /* @__PURE__ */ new Set();
|
|
@@ -20737,4 +20871,4 @@ var run = /*#__PURE__*/Object.freeze({
|
|
|
20737
20871
|
writeStopMarker: writeStopMarker
|
|
20738
20872
|
});
|
|
20739
20873
|
|
|
20740
|
-
export { listSkillFiles as $, removeWorkflow as A, saveWorkflow as B, rawWorkflow as C, listWorkflows as D, isWorkflowEnabled as E, workflowCrons as F, cronMatches as G, summarize as H, workflowSteps as I, parseJwtEmail as J, computeCollectionConfigUpdate as K, SYSTEM_COLLECTION_CONFIG as L, loadMachineContext as M, buildMachineInstructions as N, machineToolsForRole as O, buildMachineTools as P, parseFrontmatter as Q, READ_ONLY_TOOLS as R, SharingNotificationSync as S, getSkillsServer as T, getSkillsWorkspaceName as U, getSkillsCollectionName as V, fetchWithTimeout as W, searchSkills as X, SKILLS_DIR as Y, getSkillInfo as Z, downloadSkillFile as _, createSessionStore as a, resolveModel as a0, clearStopMarker as a1, stopMarkerExists as a2,
|
|
20874
|
+
export { listSkillFiles as $, removeWorkflow as A, saveWorkflow as B, rawWorkflow as C, listWorkflows as D, isWorkflowEnabled as E, workflowCrons as F, cronMatches as G, summarize as H, workflowSteps as I, parseJwtEmail as J, computeCollectionConfigUpdate as K, SYSTEM_COLLECTION_CONFIG as L, loadMachineContext as M, buildMachineInstructions as N, machineToolsForRole as O, buildMachineTools as P, parseFrontmatter as Q, READ_ONLY_TOOLS as R, SharingNotificationSync as S, getSkillsServer as T, getSkillsWorkspaceName as U, getSkillsCollectionName as V, fetchWithTimeout as W, searchSkills as X, SKILLS_DIR as Y, getSkillInfo as Z, downloadSkillFile as _, createSessionStore as a, resolveModel as a0, clearStopMarker as a1, stopMarkerExists as a2, ChannelStore as a3, gatewayBase as a4, genKey as a5, formatHandle as a6, normalizeAllowedUser as a7, loadSecurityContextConfig as a8, resolveSecurityContext as a9, run as aA, buildSecurityContextFromFlags as aa, mergeSecurityContexts as ab, buildSessionShareUrl as ac, computeOutboundHop as ad, registerAwaitingReply as ae, buildMachineShareUrl as af, parseHandle as ag, handleMatchesMetadata as ah, describeMisconfiguration as ai, buildMachineDeps as aj, applyClaudeProxyEnv as ak, composeSessionId as al, generateFriendlyName as am, generateHookSettings as an, staticFileServer as ao, instanceConfig as ap, claudeAuth as aq, codexProvider as ar, outbox as as, projectInfo as at, DefaultTransport$1 as au, acpBackend as av, acpAgentConfig as aw, codexAppServerBackend as ax, GeminiTransport$1 as ay, api as az, stopDaemon as b, connectToHypha as c, daemonStatus as d, getFrpsSubdomainHost as e, getFrpsServerPort as f, getHyphaServerUrl$1 as g, getFrpsServerAddr as h, shortId as i, resolveProjectRoot as j, getIssue as k, resumeIssue as l, addComment as m, addIssue as n, listIssues as o, pauseIssue as p, searchIssues as q, registerMachineService as r, startDaemon as s, isVisibleTo as t, updateIssue as u, getRun as v, listRuns as w, getWorkflow as x, runWorkflow as y, setWorkflowEnabled as z };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { j as resolveProjectRoot, D as listWorkflows, E as isWorkflowEnabled, F as workflowCrons, y as runWorkflow, G as cronMatches } from './run-
|
|
1
|
+
import { j as resolveProjectRoot, D as listWorkflows, E as isWorkflowEnabled, F as workflowCrons, y as runWorkflow, G as cronMatches } from './run-BNiSOlBf.mjs';
|
|
2
2
|
import 'os';
|
|
3
3
|
import 'fs/promises';
|
|
4
4
|
import 'fs';
|
|
@@ -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-Dc9t_OeY.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-Dc9t_OeY.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-Dc9t_OeY.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-Dc9t_OeY.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-Dc9t_OeY.mjs');
|
|
239
239
|
const { machine, server } = await connectAndGetMachine(machineId);
|
|
240
240
|
try {
|
|
241
241
|
const info = await machine.serveInfo();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { R as READ_ONLY_TOOLS, M as loadMachineContext, N as buildMachineInstructions, O as machineToolsForRole, P as buildMachineTools } from './run-
|
|
1
|
+
import { R as READ_ONLY_TOOLS, M as loadMachineContext, N as buildMachineInstructions, O as machineToolsForRole, P as buildMachineTools } from './run-BNiSOlBf.mjs';
|
|
2
2
|
import 'node:child_process';
|
|
3
3
|
import 'os';
|
|
4
4
|
import 'fs/promises';
|
package/package.json
CHANGED
|
@@ -1,48 +1,48 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
2
|
+
"name": "svamp-cli",
|
|
3
|
+
"version": "0.2.290",
|
|
4
|
+
"description": "Svamp CLI — AI workspace daemon on Hypha Cloud",
|
|
5
|
+
"author": "Amun AI AB",
|
|
6
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"bin": {
|
|
9
|
+
"svamp": "./bin/svamp.mjs"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist",
|
|
13
|
+
"bin"
|
|
14
|
+
],
|
|
15
|
+
"main": "./dist/index.mjs",
|
|
16
|
+
"exports": {
|
|
17
|
+
".": "./dist/index.mjs",
|
|
18
|
+
"./cli": "./dist/cli.mjs"
|
|
19
|
+
},
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "rm -rf dist bin/skills bin/commands && mkdir -p bin/skills && cp -r ../../skills/artifact bin/skills/artifact && cp -r ../../skills/crew bin/skills/crew && cp -r ../../commands bin/commands && tsc --noEmit && pkgroll",
|
|
22
|
+
"typecheck": "tsc --noEmit",
|
|
23
|
+
"test": "npx tsx test/test-context-window.mjs && npx tsx test/test-ratelimit-retry.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-sharing-notify-sync.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-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-backend-accounts.mjs && npx tsx test/test-codex-force-model.mjs && npx tsx test/test-backend-oauth.mjs && npx tsx test/test-btw-proxy-env.mjs && npx tsx test/test-output-formatters.mjs && npx tsx test/test-inbox-guard.mjs && npx tsx test/test-user-events.mjs && npx tsx test/test-migrate-children.mjs && npx tsx test/test-outpost-install.mjs && npx tsx test/test-inbox-reconcile.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-isolation-disable.mjs && npx tsx test/test-machine-service-logic.mjs && npx tsx test/test-session-access-fallback.mjs && npx tsx test/test-interactive-helpers.mjs && npx tsx test/test-codex-app-server.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-compact-detect.mjs && npx tsx test/test-session-consolidation.mjs && npx tsx test/test-inbox-store.mjs && npx tsx test/test-inbox.mjs && npx tsx test/test-inbox-cross-machine.mjs && npx tsx test/test-issue-store.mjs && npx tsx test/test-issue-close-gate.mjs && npx tsx test/test-loop-verify.mjs && npx tsx test/test-restore-decision.mjs && npx tsx test/test-issue-rpc.mjs && npx tsx test/test-issue-pause.mjs && npx tsx test/test-workflow-store.mjs && npx tsx test/test-workflow-rpc.mjs && npx tsx test/test-workflow-scheduler.mjs && npx tsx test/test-cron.mjs && npx tsx test/test-workflow-runs.mjs && npx tsx test/test-workflow-idle.mjs && npx tsx test/test-serve-link-subdomain.mjs && npx tsx test/test-short-id.mjs && npx tsx test/test-transcript-edit.mjs && npx tsx test/test-edit-history.mjs && npx tsx test/test-friendly-name.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-ws-upgrade.mjs && npx tsx test/test-serve-auth.mjs && npx tsx test/test-static-file-server.mjs && npx tsx test/test-serve-stability.mjs && npx tsx test/test-frpc-e2e.mjs --unit-only && npx tsx test/test-frpc-status.mjs && node test/pinnedClaudeCode.test.mjs && node test/fleet.test.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-hotreload-seam.mjs && npx tsx test/test-hot-reload.mjs && npx tsx test/test-hot-reload-live.mjs && npx tsx test/test-session-core.mjs && npx tsx test/test-channel-async-reply.mjs && npx tsx test/test-outbox-reload.mjs && npx tsx test/test-channel-binding.mjs && npx tsx test/test-channel-identity.mjs && npx tsx test/test-stateless-dispatch-limiter.mjs && npx tsx test/test-shared-session-identity.mjs && npx tsx test/test-wise-agent-auth.mjs && npx tsx test/test-channel-http.mjs && npx tsx test/test-channel-upload.mjs && npx tsx test/test-wise-voice.mjs && npx tsx test/test-wise-headless.mjs && npx tsx test/test-wise-machine.mjs && npx tsx test/test-crew-merge.mjs && npx tsx test/test-crew-verdict-routing.mjs && npx tsx test/test-crew-standalone.mjs && npx tsx test/test-session-links.mjs && npx tsx test/test-issue-loop-pause-guard.mjs && npx tsx test/test-artifact-guard.mjs && npx tsx test/test-artifact-sync-pagination.mjs && npx tsx test/test-graceful-restart.mjs && npx tsx test/test-flush-exit.mjs",
|
|
24
|
+
"test:hypha": "node --no-warnings test/test-hypha-service.mjs",
|
|
25
|
+
"dev": "tsx src/cli.ts",
|
|
26
|
+
"dev:daemon": "tsx src/cli.ts daemon start-sync",
|
|
27
|
+
"test:e2e": "node --no-warnings test/e2e-session-tests.mjs",
|
|
28
|
+
"test:frpc": "npx tsx test/test-frpc-e2e.mjs",
|
|
29
|
+
"prepublishOnly": "yarn build"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@agentclientprotocol/sdk": "^0.14.1",
|
|
33
|
+
"@modelcontextprotocol/sdk": "^1.25.3",
|
|
34
|
+
"hypha-rpc": "0.21.42",
|
|
35
|
+
"node-pty": "1.2.0-beta.11",
|
|
36
|
+
"ws": "^8.18.0",
|
|
37
|
+
"yaml": "^2.8.2",
|
|
38
|
+
"zod": "^3.24.4"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@types/node": ">=20",
|
|
42
|
+
"@types/ws": "^8.5.14",
|
|
43
|
+
"pkgroll": "^2.14.2",
|
|
44
|
+
"tsx": "^4.20.6",
|
|
45
|
+
"typescript": "5.9.3"
|
|
46
|
+
},
|
|
47
|
+
"packageManager": "yarn@1.22.22"
|
|
48
48
|
}
|