devframe 0.9.17 → 0.9.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/dist/{_shared-CkLpdx6I.d.mts → _shared-BIUet_Jh.d.mts} +1 -1
  2. package/dist/adapters/build.d.mts +1 -1
  3. package/dist/adapters/build.mjs +3 -3
  4. package/dist/adapters/cac.d.mts +1 -1
  5. package/dist/adapters/cac.mjs +1 -1
  6. package/dist/adapters/dev.d.mts +4 -4
  7. package/dist/adapters/dev.mjs +1 -1
  8. package/dist/adapters/embedded.d.mts +1 -1
  9. package/dist/adapters/initiate.d.mts +3 -3
  10. package/dist/adapters/initiate.mjs +1 -1
  11. package/dist/adapters/mcp.d.mts +1 -1
  12. package/dist/adapters/mcp.mjs +1 -1
  13. package/dist/client/index.d.mts +5 -5
  14. package/dist/client/index.mjs +66 -54
  15. package/dist/{context-3y_PeZKl.d.mts → context-BA5FPz7K.d.mts} +1 -1
  16. package/dist/{context-DLzIyQCZ.d.mts → context-BLHBDQcZ.d.mts} +2 -2
  17. package/dist/{context-Cdj9z9m2.mjs → context-BLXXjoBW.mjs} +3 -3
  18. package/dist/{dev-DpfkCVqo.mjs → dev-DbWecpjA.mjs} +2 -2
  19. package/dist/{host-agent-CKqSTEX9.mjs → host-agent-C3MBpNCd.mjs} +30 -31
  20. package/dist/in-page-channel/index.d.mts +4 -4
  21. package/dist/in-page-channel/index.mjs +32 -22
  22. package/dist/{index-pIVt92jP.d.mts → index-CiA6C705.d.mts} +2 -2
  23. package/dist/{index-Ces7aTOQ.d.mts → index-r6NstVmM.d.mts} +2 -2
  24. package/dist/index.d.mts +3 -3
  25. package/dist/{instance-shell-BQXr8n68.d.mts → instance-shell-C6Vg97lg.d.mts} +3 -3
  26. package/dist/internal/index.d.mts +13 -33
  27. package/dist/internal/index.mjs +3 -3
  28. package/dist/node/auth.d.mts +2 -2
  29. package/dist/node/hub-internals.d.mts +2 -2
  30. package/dist/node/index.d.mts +3 -3
  31. package/dist/node/index.mjs +1 -1
  32. package/dist/recipes/common-rpc-functions.d.mts +5 -62
  33. package/dist/recipes/interactive-auth.d.mts +2 -2
  34. package/dist/{remote-assets-DMFzLSoH.mjs → remote-assets-D0StJVLp.mjs} +17 -16
  35. package/dist/rpc/dump.d.mts +1 -1
  36. package/dist/rpc/dump.mjs +1 -1
  37. package/dist/rpc/index.d.mts +3 -3
  38. package/dist/rpc/index.mjs +8 -11
  39. package/dist/rpc/transports/sse-client.d.mts +1 -1
  40. package/dist/rpc/transports/sse-client.mjs +1 -1
  41. package/dist/rpc/transports/sse-server.d.mts +2 -2
  42. package/dist/rpc/transports/sse-server.mjs +1 -1
  43. package/dist/rpc/transports/ws-bun.d.mts +2 -2
  44. package/dist/rpc/transports/ws-client.d.mts +1 -1
  45. package/dist/rpc/transports/ws-client.mjs +1 -1
  46. package/dist/rpc/transports/ws-deno.d.mts +2 -2
  47. package/dist/rpc/transports/ws-server.d.mts +1 -1
  48. package/dist/rpc/transports/ws-server.mjs +1 -1
  49. package/dist/{rpc-core-Clo3kHfo.d.mts → rpc-core-BlL-Ip8n.d.mts} +3 -3
  50. package/dist/{serialization-DFg5sUt6.mjs → serialization-BhuOoL80.mjs} +2 -2
  51. package/dist/{sse-client-BQ4jS3eO.d.mts → sse-client-BcbYwXdD.d.mts} +1 -1
  52. package/dist/types/index.d.mts +2 -2
  53. package/dist/{types-Dq4i156u.d.mts → types-D2vGd7-2.d.mts} +52 -113
  54. package/dist/utils/events.d.mts +1 -1
  55. package/dist/utils/remote-assets.mjs +1 -1
  56. package/dist/utils/shared-state.d.mts +1 -1
  57. package/dist/utils/streaming-channel.d.mts +1 -1
  58. package/dist/{validation-CfV1s0SF.mjs → validation-BzxTTYaV.mjs} +15 -2
  59. package/dist/{wire-codec-BHGt0sSs.mjs → wire-codec-B1W3zH3L.mjs} +1 -1
  60. package/dist/{write-D2AJqVT8.mjs → write-DoXJzGUH.mjs} +3 -2
  61. package/dist/{ws-client-Xpxt0oPA.d.mts → ws-client-CNpP6Ium.d.mts} +1 -1
  62. package/dist/{ws-server-9ztvkeJ0.d.mts → ws-server-BB8jhxeT.d.mts} +1 -1
  63. package/package.json +3 -3
  64. package/skills/devframe/SKILL.md +1 -1
@@ -1,4 +1,4 @@
1
- import { F as DevframeDefinition, G as McpAuthorization, I as DevframeDeploymentKind, q as McpSetting, t as ConnectionMeta, zt as DevframeAgentHost } from "./context-DLzIyQCZ.mjs";
1
+ import { F as DevframeDefinition, G as McpAuthorization, I as DevframeDeploymentKind, q as McpSetting, t as ConnectionMeta, zt as DevframeAgentHost } from "./context-BLHBDQcZ.mjs";
2
2
  //#region src/adapters/_shared.d.ts
3
3
  /**
4
4
  * Resolve the mount base path for a devframe's SPA. Hosted adapters
@@ -1,4 +1,4 @@
1
- import { F as DevframeDefinition, V as DevframeSnapshotRpcEntry, o as DevframeNodeContext } from "../context-DLzIyQCZ.mjs";
1
+ import { F as DevframeDefinition, V as DevframeSnapshotRpcEntry, o as DevframeNodeContext } from "../context-BLHBDQcZ.mjs";
2
2
  import { o as StaticAssetsSource } from "../remote-assets-eBvSKZMS.mjs";
3
3
  //#region src/adapters/build.d.ts
4
4
  export interface CreateBuildOptions {
@@ -1,10 +1,10 @@
1
1
  import { s as colors } from "../nostics-D0PvLZsn.mjs";
2
2
  import { t as resolveClientAssets } from "../client-assets-DNdhagGm.mjs";
3
3
  import { DEVFRAME_CONNECTION_META_FILENAME, DEVFRAME_RPC_DUMP_MANIFEST_FILENAME } from "../constants.mjs";
4
- import { n as collectStaticRpcDump, t as writeStaticRpcDump } from "../write-D2AJqVT8.mjs";
4
+ import { n as collectStaticRpcDump, t as writeStaticRpcDump } from "../write-DoXJzGUH.mjs";
5
5
  import { t as diagnostics } from "../diagnostics-DZA6KQ_Z.mjs";
6
- import { t as createHostContext } from "../context-Cdj9z9m2.mjs";
7
- import { t as resolveStaticAssetsSource } from "../remote-assets-DMFzLSoH.mjs";
6
+ import { t as createHostContext } from "../context-BLXXjoBW.mjs";
7
+ import { t as resolveStaticAssetsSource } from "../remote-assets-D0StJVLp.mjs";
8
8
  import { t as createH3DevframeHost } from "../host-h3-BROI6SQ4.mjs";
9
9
  import fs from "node:fs/promises";
10
10
  import { resolve } from "pathe";
@@ -1,4 +1,4 @@
1
- import { Dt as InferCliFlags, Et as CliFlagsSchema, F as DevframeDefinition, Ot as defineCliFlags, kt as parseCliFlags, q as McpSetting } from "../context-DLzIyQCZ.mjs";
1
+ import { Dt as InferCliFlags, Et as CliFlagsSchema, F as DevframeDefinition, Ot as defineCliFlags, kt as parseCliFlags, q as McpSetting } from "../context-BLHBDQcZ.mjs";
2
2
  import { CAC } from "cac";
3
3
  import { H3 } from "h3";
4
4
  //#region src/adapters/cac.d.ts
@@ -1,7 +1,7 @@
1
1
  import { s as colors } from "../nostics-D0PvLZsn.mjs";
2
2
  import { i as resolveDevServerPort, s as importRuntimeModule } from "../_shared-U8D-xzrp.mjs";
3
3
  import { createBuild } from "./build.mjs";
4
- import { t as createDevServer } from "../dev-DpfkCVqo.mjs";
4
+ import { t as createDevServer } from "../dev-DbWecpjA.mjs";
5
5
  import process from "node:process";
6
6
  import cac$1 from "cac";
7
7
  //#region src/adapters/flags.ts
@@ -1,9 +1,9 @@
1
- import { F as DevframeDefinition, Tt as DevframeAuthHandler, U as DevframeSseOptions, W as DevframeWsOptions, q as McpSetting, s as DevframeNodeRpcSession } from "../context-DLzIyQCZ.mjs";
1
+ import { F as DevframeDefinition, Tt as DevframeAuthHandler, U as DevframeSseOptions, W as DevframeWsOptions, q as McpSetting, s as DevframeNodeRpcSession } from "../context-BLHBDQcZ.mjs";
2
2
  import { n as DevframeRpcConnection, t as DevframeNodeRpcSessionMeta } from "../session-r6PDixP6.mjs";
3
3
  import { o as StaticAssetsSource } from "../remote-assets-eBvSKZMS.mjs";
4
- import { n as WsOriginRegistry } from "../ws-server-9ztvkeJ0.mjs";
5
- import { c as StartedServer } from "../instance-shell-BQXr8n68.mjs";
6
- import { c as resolveMcpConnectionMeta, o as resolveDevServerPort, t as ResolveDevServerPortOptions } from "../_shared-CkLpdx6I.mjs";
4
+ import { n as WsOriginRegistry } from "../ws-server-BB8jhxeT.mjs";
5
+ import { c as StartedServer } from "../instance-shell-C6Vg97lg.mjs";
6
+ import { c as resolveMcpConnectionMeta, o as resolveDevServerPort, t as ResolveDevServerPortOptions } from "../_shared-BIUet_Jh.mjs";
7
7
  import { H3 } from "h3";
8
8
  //#region src/adapters/dev.d.ts
9
9
  export interface CreateDevServerOptions {
@@ -1,3 +1,3 @@
1
1
  import { i as resolveDevServerPort, o as resolveMcpConnectionMeta } from "../_shared-U8D-xzrp.mjs";
2
- import { t as createDevServer } from "../dev-DpfkCVqo.mjs";
2
+ import { t as createDevServer } from "../dev-DbWecpjA.mjs";
3
3
  export { createDevServer, resolveDevServerPort, resolveMcpConnectionMeta };
@@ -1,4 +1,4 @@
1
- import { F as DevframeDefinition, o as DevframeNodeContext } from "../context-DLzIyQCZ.mjs";
1
+ import { F as DevframeDefinition, o as DevframeNodeContext } from "../context-BLHBDQcZ.mjs";
2
2
  //#region src/adapters/embedded.d.ts
3
3
  export interface CreateEmbeddedOptions {
4
4
  /** Target context the devframe is registered into. Required. */
@@ -1,8 +1,8 @@
1
- import { F as DevframeDefinition, St as DevframeStorageScope, Tt as DevframeAuthHandler, U as DevframeSseOptions, W as DevframeWsOptions, o as DevframeNodeContext, q as McpSetting, s as DevframeNodeRpcSession, t as ConnectionMeta } from "../context-DLzIyQCZ.mjs";
1
+ import { F as DevframeDefinition, St as DevframeStorageScope, Tt as DevframeAuthHandler, U as DevframeSseOptions, W as DevframeWsOptions, o as DevframeNodeContext, q as McpSetting, s as DevframeNodeRpcSession, t as ConnectionMeta } from "../context-BLHBDQcZ.mjs";
2
2
  import { n as DevframeRpcConnection, t as DevframeNodeRpcSessionMeta } from "../session-r6PDixP6.mjs";
3
3
  import { o as StaticAssetsSource } from "../remote-assets-eBvSKZMS.mjs";
4
- import { n as WsOriginRegistry } from "../ws-server-9ztvkeJ0.mjs";
5
- import { c as StartedServer, f as DevframeInstanceRecord } from "../instance-shell-BQXr8n68.mjs";
4
+ import { n as WsOriginRegistry } from "../ws-server-BB8jhxeT.mjs";
5
+ import { c as StartedServer, f as DevframeInstanceRecord } from "../instance-shell-C6Vg97lg.mjs";
6
6
  import { H3 } from "h3";
7
7
  import { Buffer } from "node:buffer";
8
8
  import { IncomingMessage, Server, ServerResponse } from "node:http";
@@ -1,2 +1,2 @@
1
- import { n as getInstanceInternals, r as initDevframe } from "../dev-DpfkCVqo.mjs";
1
+ import { n as getInstanceInternals, r as initDevframe } from "../dev-DbWecpjA.mjs";
2
2
  export { getInstanceInternals, initDevframe };
@@ -1,4 +1,4 @@
1
- import { F as DevframeDefinition, G as McpAuthorization, o as DevframeNodeContext } from "../context-DLzIyQCZ.mjs";
1
+ import { F as DevframeDefinition, G as McpAuthorization, o as DevframeNodeContext } from "../context-BLHBDQcZ.mjs";
2
2
  import { H3 } from "h3";
3
3
  import "@modelcontextprotocol/server";
4
4
  //#region src/adapters/mcp/build-server.d.ts
@@ -3,7 +3,7 @@ import { t as DEVFRAME_EVENTS } from "../events-BV4Dj59a.mjs";
3
3
  import { t as isAllowedOrigin } from "../origin-DZit9g29.mjs";
4
4
  import { r as timingSafeEqual } from "../crypto-token-TVbGGFuj.mjs";
5
5
  import { t as diagnostics } from "../diagnostics-DZA6KQ_Z.mjs";
6
- import { t as createHostContext } from "../context-Cdj9z9m2.mjs";
6
+ import { t as createHostContext } from "../context-BLXXjoBW.mjs";
7
7
  import { t as toAgentToolName } from "../agent-tool-name-DGzeuWcO.mjs";
8
8
  import { join } from "pathe";
9
9
  import process from "node:process";
@@ -1,8 +1,8 @@
1
- import { f as RpcCacheManager, p as RpcCacheOptions } from "../index-pIVt92jP.mjs";
2
- import { _ as RpcFunctionDefinition, w as RpcFunctionsCollector } from "../types-Dq4i156u.mjs";
3
- import { Q as DevframeServiceMeta, Vt as EventEmitter, b as StreamSink, ct as DevframeSettings, d as RpcSharedStateHost, et as DevframeServiceScopeOf, gt as SettingsForNamespace, ht as ScopedSharedStates, it as DevframeServicesState, k as SharedState, mt as ScopedServerFunctions, pt as ScopedRpcFn, t as ConnectionMeta, u as RpcSharedStateGetOptions, vt as DevframeRpcClientFunctions, y as StreamReader, yt as DevframeRpcServerFunctions } from "../context-DLzIyQCZ.mjs";
4
- import { t as SseRpcChannelOptions } from "../sse-client-BQ4jS3eO.mjs";
5
- import { t as WsRpcChannelOptions } from "../ws-client-Xpxt0oPA.mjs";
1
+ import { f as RpcCacheManager, p as RpcCacheOptions } from "../index-CiA6C705.mjs";
2
+ import { E as RpcFunctionsCollector, _ as RpcFunctionDefinition } from "../types-D2vGd7-2.mjs";
3
+ import { Q as DevframeServiceMeta, Vt as EventEmitter, b as StreamSink, ct as DevframeSettings, d as RpcSharedStateHost, et as DevframeServiceScopeOf, gt as SettingsForNamespace, ht as ScopedSharedStates, it as DevframeServicesState, k as SharedState, mt as ScopedServerFunctions, pt as ScopedRpcFn, t as ConnectionMeta, u as RpcSharedStateGetOptions, vt as DevframeRpcClientFunctions, y as StreamReader, yt as DevframeRpcServerFunctions } from "../context-BLHBDQcZ.mjs";
4
+ import { t as SseRpcChannelOptions } from "../sse-client-BcbYwXdD.mjs";
5
+ import { t as WsRpcChannelOptions } from "../ws-client-CNpP6Ium.mjs";
6
6
  import { BirpcOptions, BirpcReturn } from "birpc";
7
7
  //#region src/client/connection.d.ts
8
8
  export interface DevframeConnection {
@@ -99,8 +99,8 @@ const diagnostics = defineDiagnostics({
99
99
  docsBase: "https://devfra.me/errors",
100
100
  codes: {
101
101
  DF0019: {
102
- why: (p) => `RPC function "${p.name}" has \`agent\` set but \`jsonSerializable\` is not \`true\`; MCP requires JSON-serializable data.`,
103
- fix: "Set `jsonSerializable: true` if the payload is JSON-safe, or remove `agent` to keep it RPC-only."
102
+ why: (p) => `RPC function "${p.name}" has \`agent\` set but \`jsonSerializable\` is \`false\`; MCP requires JSON-serializable data.`,
103
+ fix: "Remove `jsonSerializable: false`, or remove `agent` to keep it RPC-only."
104
104
  },
105
105
  DF0020: {
106
106
  why: (p) => `RPC function "${p.name}" declares \`jsonSerializable: true\` but the value at "${p.path}" is a ${p.type}.`,
@@ -131,6 +131,19 @@ const diagnostics = defineDiagnostics({
131
131
  }
132
132
  });
133
133
  //#endregion
134
+ //#region src/rpc/agent-json-serialization.ts
135
+ /**
136
+ * Prevents using a coding-agent-exposed RPC function that is explicitly
137
+ * marked as non-serializable, and marks these functions as serializable by
138
+ * default.
139
+ *
140
+ * @internal
141
+ */
142
+ function ensureAgentJsonSerializable(fnDef) {
143
+ if (fnDef.agent && fnDef.jsonSerializable === false) throw diagnostics.DF0019({ name: fnDef.name });
144
+ if (fnDef.agent && !fnDef.jsonSerializable) fnDef.jsonSerializable = true;
145
+ }
146
+ //#endregion
134
147
  //#region src/rpc/validate-io.ts
135
148
  /**
136
149
  * Run a single [Standard Schema](https://standardschema.dev) validator,
@@ -270,15 +283,15 @@ var RpcFunctionsCollectorBase = class {
270
283
  }
271
284
  });
272
285
  }
273
- register(fn, force = false) {
274
- if (this.definitions.has(fn.name) && !force) throw diagnostics.DF0021({ name: fn.name });
275
- assertAgentJsonSerializable(fn);
276
- this.definitions.set(fn.name, fn);
277
- this._onChanged.forEach((cb) => cb(fn.name));
286
+ register(fnDef, force = false) {
287
+ if (this.definitions.has(fnDef.name) && !force) throw diagnostics.DF0021({ name: fnDef.name });
288
+ ensureAgentJsonSerializable(fnDef);
289
+ this.definitions.set(fnDef.name, fnDef);
290
+ this._onChanged.forEach((cb) => cb(fnDef.name));
278
291
  }
279
292
  update(fn, force = false) {
280
293
  if (!this.definitions.has(fn.name) && !force) throw diagnostics.DF0022({ name: fn.name });
281
- assertAgentJsonSerializable(fn);
294
+ ensureAgentJsonSerializable(fn);
282
295
  this.definitions.set(fn.name, fn);
283
296
  this._onChanged.forEach((cb) => cb(fn.name));
284
297
  }
@@ -310,9 +323,6 @@ var RpcFunctionsCollectorBase = class {
310
323
  return Array.from(this.definitions.keys());
311
324
  }
312
325
  };
313
- function assertAgentJsonSerializable(fn) {
314
- if (fn.agent && fn.jsonSerializable !== true) throw diagnostics.DF0019({ name: fn.name });
315
- }
316
326
  //#endregion
317
327
  //#region src/rpc/serialization.ts
318
328
  /**
@@ -1089,14 +1099,17 @@ function createLiveRpcClientMode(options) {
1089
1099
  async function ensureTrusted(timeout = 6e4) {
1090
1100
  if (isTrusted) trustedPromise.resolve(true);
1091
1101
  if (timeout <= 0) return trustedPromise.promise;
1092
- let clear = () => {};
1093
- await Promise.race([trustedPromise.promise.then(clear), new Promise((resolve, reject) => {
1094
- const id = setTimeout(() => {
1095
- reject(/* @__PURE__ */ new Error("[devframe] Timeout waiting for rpc to be trusted"));
1096
- }, timeout);
1097
- clear = () => clearTimeout(id);
1098
- })]);
1099
- return isTrusted;
1102
+ let timer;
1103
+ try {
1104
+ await Promise.race([trustedPromise.promise, new Promise((_, reject) => {
1105
+ timer = setTimeout(() => {
1106
+ reject(/* @__PURE__ */ new Error("[devframe] Timeout waiting for rpc to be trusted"));
1107
+ }, timeout);
1108
+ })]);
1109
+ return isTrusted;
1110
+ } finally {
1111
+ clearTimeout(timer);
1112
+ }
1100
1113
  }
1101
1114
  return {
1102
1115
  transport,
@@ -1709,39 +1722,29 @@ function argsToJsonSchema(args) {
1709
1722
  };
1710
1723
  }
1711
1724
  //#endregion
1712
- //#region src/node/agent-args.ts
1725
+ //#region src/tool-input.ts
1713
1726
  /**
1714
- * Map the args payload an agent surface receives (MCP sends an object
1715
- * keyed `arg0`/`arg1`/…, matching the schema the adapter advertises) onto
1716
- * a handler's positional parameters. Shared by the agent host's RPC
1717
- * bridge and the hub's command-derived tools so the coercion cannot
1718
- * drift between them.
1727
+ * Convert an object-shaped tool input into positional arguments.
1719
1728
  *
1720
- * - an array passes through as-is
1721
- * - `null`/`undefined` become a zero-argument call
1722
- * - with declared schemas, each schema reads its own `argN` key, in order
1723
- * - without schemas, `arg0`/`arg1`/… keys are collected when present
1724
- * - an empty object becomes a zero-argument call
1725
- * - anything else follows the {@link AgentArgsFallback}
1729
+ * Tool schemas expose positional parameters as `arg0`, `arg1`, and so on.
1730
+ * Arrays pass through for callers that already provide positional arguments.
1726
1731
  */
1727
- function coerceAgentPositionalArgs(args, schemas, fallback = "wrap") {
1728
- if (Array.isArray(args)) return args;
1729
- if (args === void 0 || args === null) return [];
1730
- if (typeof args === "object") {
1731
- const obj = args;
1732
- if (schemas && schemas.length) return schemas.map((_, i) => obj[`arg${i}`]);
1733
- if ("arg0" in obj) {
1734
- const out = [];
1735
- let i = 0;
1736
- while (`arg${i}` in obj) {
1737
- out.push(obj[`arg${i}`]);
1738
- i++;
1739
- }
1740
- return out;
1741
- }
1742
- if (Object.keys(obj).length === 0) return [];
1743
- }
1744
- return fallback === "drop" ? [] : [args];
1732
+ function collectPositionalArgs(input, argumentCount) {
1733
+ if (Array.isArray(input)) return input;
1734
+ if (input === void 0 || input === null) return [];
1735
+ if (typeof input !== "object") return void 0;
1736
+ const record = input;
1737
+ if (argumentCount != null) return Array.from({ length: argumentCount }, (_, index) => record[`arg${index}`]);
1738
+ if ("arg0" in record) {
1739
+ const positional = [];
1740
+ while (`arg${positional.length}` in record) positional.push(record[`arg${positional.length}`]);
1741
+ return positional;
1742
+ }
1743
+ return Object.keys(record).length === 0 ? [] : void 0;
1744
+ }
1745
+ /** Convert tool input for an RPC, preserving an untyped payload as arg 0. */
1746
+ function toolInputToRpcArgs(input, argumentCount) {
1747
+ return collectPositionalArgs(input, argumentCount) ?? [input];
1745
1748
  }
1746
1749
  //#endregion
1747
1750
  //#region src/client/webmcp.ts
@@ -1828,7 +1831,7 @@ function resolveSafety(def, agent) {
1828
1831
  }
1829
1832
  async function executeRpcTool(def, context, args) {
1830
1833
  try {
1831
- const positional = coerceAgentPositionalArgs(args, def.args, "wrap");
1834
+ const positional = toolInputToRpcArgs(args, def.args?.length);
1832
1835
  return { content: [{
1833
1836
  type: "text",
1834
1837
  text: stringifyResult(await (await getRpcHandler(def, context))(...positional))
@@ -1952,6 +1955,18 @@ async function getDevframeRpcClient(options = {}) {
1952
1955
  return bootstrapAuthPromise.then(() => fn(...args));
1953
1956
  });
1954
1957
  }
1958
+ /** Release authentication and transport resources even if another disposer fails. */
1959
+ function closeRpcClient() {
1960
+ try {
1961
+ disposeWebMcp?.();
1962
+ } finally {
1963
+ try {
1964
+ authChannel?.close();
1965
+ } finally {
1966
+ mode.close?.();
1967
+ }
1968
+ }
1969
+ }
1955
1970
  const rpc = {
1956
1971
  events,
1957
1972
  get isTrusted() {
@@ -2006,10 +2021,7 @@ async function getDevframeRpcClient(options = {}) {
2006
2021
  streaming: void 0,
2007
2022
  cacheManager,
2008
2023
  scope: void 0,
2009
- close: () => {
2010
- disposeWebMcp?.();
2011
- mode.close?.();
2012
- }
2024
+ close: closeRpcClient
2013
2025
  };
2014
2026
  rpc.sharedState = createRpcSharedStateClientHost(rpc);
2015
2027
  rpc.streaming = createRpcStreamingClientHost(rpc);
@@ -1,4 +1,4 @@
1
- import { k as SharedState, o as DevframeNodeContext } from "./context-DLzIyQCZ.mjs";
1
+ import { k as SharedState, o as DevframeNodeContext } from "./context-BLHBDQcZ.mjs";
2
2
  //#region src/node/hub-internals/context.d.ts
3
3
  interface InternalAnonymousAuthStorage {
4
4
  trusted: Record<string, {
@@ -1,5 +1,5 @@
1
- import { d as RpcFunctionsCollectorBase } from "./index-pIVt92jP.mjs";
2
- import { _ as RpcFunctionDefinition, v as RpcFunctionDefinitionAny } from "./types-Dq4i156u.mjs";
1
+ import { d as RpcFunctionsCollectorBase } from "./index-CiA6C705.mjs";
2
+ import { _ as RpcFunctionDefinition, v as RpcFunctionDefinitionAny } from "./types-D2vGd7-2.mjs";
3
3
  import { n as DevframeRpcConnection, t as DevframeNodeRpcSessionMeta } from "./session-r6PDixP6.mjs";
4
4
  import { a as RemoteAssetsStore, o as StaticAssetsSource } from "./remote-assets-eBvSKZMS.mjs";
5
5
  import { m as defineDiagnostics } from "./nostics-0sKe5HIj.mjs";
@@ -1,12 +1,12 @@
1
1
  import { i as defineDiagnostics } from "./nostics-D0PvLZsn.mjs";
2
- import { r as diagnostics } from "./serialization-DFg5sUt6.mjs";
2
+ import { r as diagnostics } from "./serialization-BhuOoL80.mjs";
3
3
  import { RpcFunctionsCollectorBase } from "./rpc/index.mjs";
4
4
  import { defineRpcFunction } from "./index.mjs";
5
5
  import { t as DEVFRAME_EVENTS } from "./events-BV4Dj59a.mjs";
6
6
  import { DEVFRAME_SERVICES_STATE_KEY } from "./constants.mjs";
7
7
  import { t as diagnostics$1 } from "./diagnostics-DZA6KQ_Z.mjs";
8
- import { r as createEventEmitter, t as DevframeAgentHost } from "./host-agent-CKqSTEX9.mjs";
9
- import { n as createDebug, t as resolveStaticAssetsSource } from "./remote-assets-DMFzLSoH.mjs";
8
+ import { i as createEventEmitter, t as DevframeAgentHost } from "./host-agent-C3MBpNCd.mjs";
9
+ import { n as createDebug, t as resolveStaticAssetsSource } from "./remote-assets-D0StJVLp.mjs";
10
10
  import { i as satisfiesVersionRange, n as expandResolveFrom, r as importServicePackage, t as deepMergeOptionSets } from "./services-install-Ben4yh52.mjs";
11
11
  import { t as createStorage } from "./storage-B70AXK64.mjs";
12
12
  import { join } from "pathe";
@@ -1,8 +1,8 @@
1
1
  import { t as resolveClientAssets } from "./client-assets-DNdhagGm.mjs";
2
2
  import { DEVFRAME_CONNECTION_META_FILENAME } from "./constants.mjs";
3
3
  import { t as diagnostics } from "./diagnostics-DZA6KQ_Z.mjs";
4
- import { t as createHostContext } from "./context-Cdj9z9m2.mjs";
5
- import { t as resolveStaticAssetsSource } from "./remote-assets-DMFzLSoH.mjs";
4
+ import { t as createHostContext } from "./context-BLXXjoBW.mjs";
5
+ import { t as resolveStaticAssetsSource } from "./remote-assets-D0StJVLp.mjs";
6
6
  import { a as resolveMcpConfig, i as resolveDevServerPort, n as normalizeBasePath, r as resolveBasePath, s as importRuntimeModule, t as loadAutoMcpAdapter } from "./_shared-U8D-xzrp.mjs";
7
7
  import { t as createH3DevframeHost } from "./host-h3-BROI6SQ4.mjs";
8
8
  import { i as normalizeHttpServerUrl, n as resolveInstanceRegister, t as createInstanceShell } from "./instance-shell-370Oee9K.mjs";
@@ -39,39 +39,38 @@ function createEventEmitter() {
39
39
  };
40
40
  }
41
41
  //#endregion
42
- //#region src/node/agent-args.ts
42
+ //#region src/tool-input.ts
43
43
  /**
44
- * Map the args payload an agent surface receives (MCP sends an object
45
- * keyed `arg0`/`arg1`/…, matching the schema the adapter advertises) onto
46
- * a handler's positional parameters. Shared by the agent host's RPC
47
- * bridge and the hub's command-derived tools so the coercion cannot
48
- * drift between them.
44
+ * Convert an object-shaped tool input into positional arguments.
49
45
  *
50
- * - an array passes through as-is
51
- * - `null`/`undefined` become a zero-argument call
52
- * - with declared schemas, each schema reads its own `argN` key, in order
53
- * - without schemas, `arg0`/`arg1`/… keys are collected when present
54
- * - an empty object becomes a zero-argument call
55
- * - anything else follows the {@link AgentArgsFallback}
46
+ * Tool schemas expose positional parameters as `arg0`, `arg1`, and so on.
47
+ * Arrays pass through for callers that already provide positional arguments.
56
48
  */
57
- function coerceAgentPositionalArgs(args, schemas, fallback = "wrap") {
58
- if (Array.isArray(args)) return args;
59
- if (args === void 0 || args === null) return [];
60
- if (typeof args === "object") {
61
- const obj = args;
62
- if (schemas && schemas.length) return schemas.map((_, i) => obj[`arg${i}`]);
63
- if ("arg0" in obj) {
64
- const out = [];
65
- let i = 0;
66
- while (`arg${i}` in obj) {
67
- out.push(obj[`arg${i}`]);
68
- i++;
69
- }
70
- return out;
71
- }
72
- if (Object.keys(obj).length === 0) return [];
49
+ function collectPositionalArgs(input, argumentCount) {
50
+ if (Array.isArray(input)) return input;
51
+ if (input === void 0 || input === null) return [];
52
+ if (typeof input !== "object") return void 0;
53
+ const record = input;
54
+ if (argumentCount != null) return Array.from({ length: argumentCount }, (_, index) => record[`arg${index}`]);
55
+ if ("arg0" in record) {
56
+ const positional = [];
57
+ while (`arg${positional.length}` in record) positional.push(record[`arg${positional.length}`]);
58
+ return positional;
73
59
  }
74
- return fallback === "drop" ? [] : [args];
60
+ return Object.keys(record).length === 0 ? [] : void 0;
61
+ }
62
+ /** Convert tool input for an RPC, preserving an untyped payload as arg 0. */
63
+ function toolInputToRpcArgs(input, argumentCount) {
64
+ return collectPositionalArgs(input, argumentCount) ?? [input];
65
+ }
66
+ /** Convert tool input for a command, whose arguments must be declared. */
67
+ function toolInputToCommandArgs(input, argumentCount) {
68
+ return collectPositionalArgs(input, argumentCount) ?? [];
69
+ }
70
+ /** @deprecated Use {@link toolInputToRpcArgs} or {@link toolInputToCommandArgs}. */
71
+ function coerceAgentPositionalArgs(input, schemas, fallback = "wrap") {
72
+ const argumentCount = schemas?.length;
73
+ return fallback === "drop" ? toolInputToCommandArgs(input, argumentCount) : toolInputToRpcArgs(input, argumentCount);
75
74
  }
76
75
  //#endregion
77
76
  //#region src/node/host-agent.ts
@@ -192,7 +191,7 @@ var DevframeAgentHost = class {
192
191
  if (plain?.handler) return await plain.handler(args);
193
192
  const rpcDef = this._findRpcDefinition(id);
194
193
  if (rpcDef) {
195
- const positional = coerceAgentPositionalArgs(args, rpcDef.args, "wrap");
194
+ const positional = toolInputToRpcArgs(args, rpcDef.args?.length);
196
195
  return await this.context.rpc.invokeLocal(id, ...positional);
197
196
  }
198
197
  const provided = this._collectProviderTools().find((t) => t.tool.id === id);
@@ -274,4 +273,4 @@ function inferSafety(type) {
274
273
  return "action";
275
274
  }
276
275
  //#endregion
277
- export { coerceAgentPositionalArgs as n, createEventEmitter as r, DevframeAgentHost as t };
276
+ export { createEventEmitter as i, coerceAgentPositionalArgs as n, toolInputToCommandArgs as r, DevframeAgentHost as t };
@@ -1,5 +1,5 @@
1
- import { D as InferArgsType, E as Thenable, O as InferReturnType, T as RpcReturnSchema, i as RpcArgsSchema } from "../types-Dq4i156u.mjs";
2
- import { Vt as EventEmitter, k as SharedState } from "../context-DLzIyQCZ.mjs";
1
+ import { A as InferReturnType, D as RpcReturnSchema, O as Thenable, i as RpcArgsSchema, k as InferArgsType } from "../types-D2vGd7-2.mjs";
2
+ import { Vt as EventEmitter, k as SharedState } from "../context-BLHBDQcZ.mjs";
3
3
  import { BirpcReturn } from "birpc";
4
4
  //#region src/in-page-channel/types.d.ts
5
5
  /**
@@ -199,7 +199,7 @@ interface ConnectPanelChannelOptions<Protocol extends InPageChannelProtocol = In
199
199
  window?: Window | false;
200
200
  /**
201
201
  * Windows the hello is posted to. Defaults to the panel's ancestor chain
202
- * plus its `opener`, the places a same-tab page script can live. When
202
+ * plus those windows' openers, the places a page script can live. When
203
203
  * empty and no `transport` is given, the endpoint stays `connecting` and
204
204
  * warns once.
205
205
  */
@@ -363,7 +363,7 @@ export declare function createPageScriptChannel<P extends InPageChannelProtocol>
363
363
  * Connect the panel endpoint of an in-page channel.
364
364
  *
365
365
  * The panel initiates: it posts a versioned hello to every window a
366
- * same-tab page script can live in (its ancestor chain and its `opener`),
366
+ * page script can live in (its ancestor chain and those windows' openers),
367
367
  * retrying with backoff until one answers with a dedicated port, so boot
368
368
  * order never matters, and a reload of either side is just a re-handshake
369
369
  * (`WindowProxy` references survive navigations). While `connecting`,
@@ -60,8 +60,8 @@ function resolveAllowedOrigins(allowedOrigins, win) {
60
60
  return origin && origin !== "null" ? [origin] : ["*"];
61
61
  }
62
62
  /**
63
- * Default handshake targets of a panel: its ancestor chain plus its
64
- * `opener`, every same-tab window a page script can live in. `WindowProxy`
63
+ * Default handshake targets of a panel: its ancestor chain plus the
64
+ * `opener` of each window, including a popup containing the panel iframe. `WindowProxy`
65
65
  * references stay valid across navigations, so hellos posted to these reach
66
66
  * a page script even after the host page reloads.
67
67
  */
@@ -74,9 +74,9 @@ function defaultHandshakeTargets(win) {
74
74
  current = current.parent;
75
75
  }
76
76
  } catch {}
77
- try {
78
- const opener = win.opener;
79
- if (opener && opener !== win) targets.push(opener);
77
+ for (const current of [win, ...targets]) try {
78
+ const opener = current.opener;
79
+ if (opener && opener !== win && !targets.includes(opener)) targets.push(opener);
80
80
  } catch {}
81
81
  return targets;
82
82
  }
@@ -186,6 +186,12 @@ function createLocalFunctionRegistry(codec) {
186
186
  register(definition) {
187
187
  definitions.set(channelMethod(definition.type, definition.name), definition);
188
188
  },
189
+ registerInternal(method, handler) {
190
+ definitions.set(method, {
191
+ name: method,
192
+ handler
193
+ });
194
+ },
189
195
  on(name, listener) {
190
196
  const key = channelMethod("event", name);
191
197
  let registered = listeners.get(key);
@@ -202,12 +208,7 @@ function createLocalFunctionRegistry(codec) {
202
208
  resolve(name) {
203
209
  const definition = definitions.get(name);
204
210
  const registered = listeners.get(name);
205
- if (!definition && !registered?.size) {
206
- if (name.startsWith(FUNCTION_METHOD_PREFIX)) return () => {
207
- throw diagnostics.DF0077({ name: name.slice(FUNCTION_METHOD_PREFIX.length) });
208
- };
209
- return;
210
- }
211
+ if (!definition && !registered?.size) return void 0;
211
212
  return async (...rawArgs) => {
212
213
  const args = codec.deserialize ? rawArgs.map(codec.deserialize) : rawArgs;
213
214
  if (definition?.jsonSerializable) assertJsonSerializable(args, "its arguments", definition.name);
@@ -221,6 +222,21 @@ function createLocalFunctionRegistry(codec) {
221
222
  }
222
223
  };
223
224
  }
225
+ /**
226
+ * Consult each registry in order and, only once none owns the name, fall back
227
+ * to the coded "not registered" error for a `function:` call (events stay
228
+ * silent). The fallback lives here, after every registry, so chaining a
229
+ * state registry ahead of the user registry never masks a real handler.
230
+ */
231
+ function resolveLocalHandler(name, registries) {
232
+ for (const registry of registries) {
233
+ const handler = registry(name);
234
+ if (handler) return handler;
235
+ }
236
+ if (name.startsWith(FUNCTION_METHOD_PREFIX)) return () => {
237
+ throw diagnostics.DF0077({ name: name.slice(FUNCTION_METHOD_PREFIX.length) });
238
+ };
239
+ }
224
240
  function wrapPostError(error) {
225
241
  if (error instanceof DOMException && error.name === "DataCloneError") return new InPageChannelError("not-cloneable", `a payload could not be structured-cloned across the in-page channel: ${error.message}. Strip non-cloneable values (functions, DOM nodes, framework reactivity proxies) before sending: declare the function \`jsonSerializable: true\` for a precise error, or provide a \`serialize\` hook.`, { cause: error });
226
242
  return error;
@@ -539,12 +555,9 @@ function createPageScriptChannel(options) {
539
555
  }
540
556
  });
541
557
  const stateRegistry = createLocalFunctionRegistry(codec);
542
- for (const [name, handler] of Object.entries(internal.internalHandlers)) stateRegistry.register({
543
- name,
544
- handler
545
- });
558
+ for (const [method, handler] of Object.entries(internal.internalHandlers)) stateRegistry.registerInternal(method, handler);
546
559
  internal.attached = attachChannelPort(port, {
547
- resolveLocal: (fnName) => stateRegistry.resolve(fnName) ?? registry.resolve(fnName),
560
+ resolveLocal: (fnName) => resolveLocalHandler(fnName, [stateRegistry.resolve, registry.resolve]),
548
561
  onControl: (kind) => {
549
562
  if (kind === "ping") internal.attached.postControl("pong");
550
563
  },
@@ -643,7 +656,7 @@ const DEFAULT_EVENT_BUFFER_LIMIT = 64;
643
656
  * Connect the panel endpoint of an in-page channel.
644
657
  *
645
658
  * The panel initiates: it posts a versioned hello to every window a
646
- * same-tab page script can live in (its ancestor chain and its `opener`),
659
+ * page script can live in (its ancestor chain and those windows' openers),
647
660
  * retrying with backoff until one answers with a dedicated port, so boot
648
661
  * order never matters, and a reload of either side is just a re-handshake
649
662
  * (`WindowProxy` references survive navigations). While `connecting`,
@@ -697,10 +710,7 @@ function connectPanelChannel(options) {
697
710
  call: (method, args) => enqueueCall(method, serializeArgs(codec, args))
698
711
  });
699
712
  const stateRegistry = createLocalFunctionRegistry(codec);
700
- for (const [name, handler] of Object.entries(stateHost.handlers)) stateRegistry.register({
701
- name,
702
- handler
703
- });
713
+ for (const [method, handler] of Object.entries(stateHost.handlers)) stateRegistry.registerInternal(method, handler);
704
714
  function sendEventNow(method, args) {
705
715
  attached?.rpc.$callRaw({
706
716
  method,
@@ -746,7 +756,7 @@ function connectPanelChannel(options) {
746
756
  reason: "the panel adopted a newer port"
747
757
  });
748
758
  attached = attachChannelPort(port, {
749
- resolveLocal: (fnName) => stateRegistry.resolve(fnName) ?? registry.resolve(fnName),
759
+ resolveLocal: (fnName) => resolveLocalHandler(fnName, [stateRegistry.resolve, registry.resolve]),
750
760
  onControl: (kind) => {
751
761
  if (kind === "ping") attached?.postControl("pong");
752
762
  },
@@ -1,4 +1,4 @@
1
- import { C as RpcFunctionType, S as RpcFunctionSetupResult, T as RpcReturnSchema, _ as RpcFunctionDefinition, i as RpcArgsSchema, v as RpcFunctionDefinitionAny, w as RpcFunctionsCollector } from "./types-Dq4i156u.mjs";
1
+ import { D as RpcReturnSchema, E as RpcFunctionsCollector, T as RpcFunctionType, _ as RpcFunctionDefinition, i as RpcArgsSchema, v as RpcFunctionDefinitionAny, w as RpcFunctionSetupResult } from "./types-D2vGd7-2.mjs";
2
2
  //#region src/rpc/cache.d.ts
3
3
  interface RpcCacheOptions {
4
4
  functions: string[];
@@ -30,7 +30,7 @@ declare class RpcFunctionsCollectorBase<LocalFunctions extends Record<string, an
30
30
  readonly functions: LocalFunctions;
31
31
  private readonly _onChanged;
32
32
  constructor(context: SetupContext);
33
- register(fn: RpcFunctionDefinition<string, any, any, any, any, any, SetupContext>, force?: boolean): void;
33
+ register(fnDef: RpcFunctionDefinition<string, any, any, any, any, any, SetupContext>, force?: boolean): void;
34
34
  update(fn: RpcFunctionDefinition<string, any, any, any, any, any, SetupContext>, force?: boolean): void;
35
35
  onChanged(fn: (id?: string) => void): () => void;
36
36
  getHandler<T extends keyof LocalFunctions>(name: T): Promise<LocalFunctions[T]>;
@@ -1,5 +1,5 @@
1
- import { k as SharedState, o as DevframeNodeContext, s as DevframeNodeRpcSession } from "./context-DLzIyQCZ.mjs";
2
- import { n as InternalAnonymousAuthStorage } from "./context-3y_PeZKl.mjs";
1
+ import { k as SharedState, o as DevframeNodeContext, s as DevframeNodeRpcSession } from "./context-BLHBDQcZ.mjs";
2
+ import { n as InternalAnonymousAuthStorage } from "./context-BA5FPz7K.mjs";
3
3
  //#region src/node/auth/revoke.d.ts
4
4
  /**
5
5
  * Flip `isTrusted` to false on any live WS clients connected with `token`