devframe 0.9.20 → 0.10.0

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 (100) hide show
  1. package/dist/_shared-B2PZsp-J.mjs +191 -0
  2. package/dist/{_shared-BIUet_Jh.d.mts → _shared-Dy1UBMUN.d.mts} +13 -14
  3. package/dist/adapters/build.d.mts +3 -4
  4. package/dist/adapters/build.mjs +4 -5
  5. package/dist/adapters/cac.d.mts +3 -4
  6. package/dist/adapters/cac.mjs +3 -3
  7. package/dist/adapters/dev.d.mts +8 -8
  8. package/dist/adapters/dev.mjs +2 -2
  9. package/dist/adapters/embedded.d.mts +1 -1
  10. package/dist/adapters/initiate.d.mts +8 -8
  11. package/dist/adapters/initiate.mjs +1 -1
  12. package/dist/adapters/mcp.d.mts +4 -142
  13. package/dist/adapters/mcp.mjs +1 -597
  14. package/dist/agentic-D4QQQUjE.d.mts +30 -0
  15. package/dist/cli/main.mjs +12 -260
  16. package/dist/client/index.d.mts +6 -6
  17. package/dist/client/index.mjs +3 -4
  18. package/dist/constants.d.mts +2 -1
  19. package/dist/constants.mjs +2 -1
  20. package/dist/{context-BA5FPz7K.d.mts → context-B4BKPuaa.d.mts} +1 -1
  21. package/dist/{context-BLXXjoBW.mjs → context-C141q8H4.mjs} +5 -5
  22. package/dist/{context-jXO5vzjH.mjs → context-CHpyLX8W.mjs} +1 -1
  23. package/dist/{context-BLHBDQcZ.d.mts → context-CTAxz9ec.d.mts} +108 -47
  24. package/dist/{dev-BdKKOH8S.mjs → dev-DM1mIlgi.mjs} +16 -24
  25. package/dist/{diagnostics-DZA6KQ_Z.mjs → diagnostics-Cx4_VjlG.mjs} +11 -3
  26. package/dist/dist-Bw3EbMj4.mjs +305 -0
  27. package/dist/dist-CO98PBnQ.mjs +265 -0
  28. package/dist/{host-agent-C3MBpNCd.mjs → host-agent-ZSKgzMVu.mjs} +2 -7
  29. package/dist/import-runtime-module-BzlEQ9PI.mjs +24 -0
  30. package/dist/in-page-channel/index.d.mts +2 -7
  31. package/dist/in-page-channel/index.mjs +1 -4
  32. package/dist/index-Bia1vKjL.d.mts +218 -0
  33. package/dist/{index-r6NstVmM.d.mts → index-CcPSKbxb.d.mts} +2 -2
  34. package/dist/index-CeEtxDmK.d.mts +78 -0
  35. package/dist/{index-CiA6C705.d.mts → index-DuEm0sDH.d.mts} +1 -1
  36. package/dist/index.d.mts +4 -11
  37. package/dist/index.mjs +1 -10
  38. package/dist/{instance-registry-DCq762YJ.mjs → instance-registry-DtvYxc0Y.mjs} +1 -1
  39. package/dist/{instance-shell-C6Vg97lg.d.mts → instance-shell-DOZSxst6.d.mts} +31 -5
  40. package/dist/{instance-shell-yfrM3_vK.mjs → instance-shell-wC2sfEU_.mjs} +7 -7
  41. package/dist/interactive-auth-BCa_iamv.mjs +384 -0
  42. package/dist/internal/index.d.mts +66 -22
  43. package/dist/internal/index.mjs +143 -8
  44. package/dist/mrmime-40h5OOIp.mjs +448 -0
  45. package/dist/node/auth.d.mts +2 -2
  46. package/dist/node/hub-internals.d.mts +2 -2
  47. package/dist/node/hub-internals.mjs +2 -2
  48. package/dist/node/index.d.mts +2 -4
  49. package/dist/node/index.mjs +2 -2
  50. package/dist/{nostics-0sKe5HIj.d.mts → nostics-DWvukRwa.d.mts} +11 -2
  51. package/dist/{origin-D_eBKEzr.mjs → origin-DZit9g29.mjs} +1 -21
  52. package/dist/recipes/interactive-auth.d.mts +2 -2
  53. package/dist/recipes/interactive-auth.mjs +1 -231
  54. package/dist/{remote-assets-D0StJVLp.mjs → remote-assets-B9MeWmW6.mjs} +2 -2
  55. package/dist/rpc/client.d.mts +1 -1
  56. package/dist/rpc/client.mjs +1 -1
  57. package/dist/rpc/dump.d.mts +2 -1
  58. package/dist/rpc/index.d.mts +3 -2
  59. package/dist/rpc/server.d.mts +1 -1
  60. package/dist/rpc/server.mjs +1 -1
  61. package/dist/rpc/transports/sse-client.d.mts +1 -1
  62. package/dist/rpc/transports/sse-server.d.mts +3 -3
  63. package/dist/rpc/transports/sse-server.mjs +1 -1
  64. package/dist/rpc/transports/ws-bun.d.mts +2 -2
  65. package/dist/rpc/transports/ws-bun.mjs +1 -1
  66. package/dist/rpc/transports/ws-client.d.mts +1 -1
  67. package/dist/rpc/transports/ws-deno.d.mts +2 -2
  68. package/dist/rpc/transports/ws-deno.mjs +1 -1
  69. package/dist/rpc/transports/ws-server.d.mts +1 -1
  70. package/dist/rpc/transports/ws-server.mjs +1 -1
  71. package/dist/{rpc-core-CvkU23bQ.mjs → rpc-core-BXyMjbKG.mjs} +1 -1
  72. package/dist/{rpc-core-BlL-Ip8n.d.mts → rpc-core-rLrwFEcw.d.mts} +4 -4
  73. package/dist/{services-install-Ben4yh52.mjs → services-install-D5YUwFXW.mjs} +17 -1
  74. package/dist/{sse-client-BcbYwXdD.d.mts → sse-client-DNdscfu_.d.mts} +2 -2
  75. package/dist/{storage-B70AXK64.mjs → storage-CHD1IkqU.mjs} +1 -1
  76. package/dist/types/index.d.mts +4 -4
  77. package/dist/{types-D2vGd7-2.d.mts → types-BmDbfHCx.d.mts} +2 -3
  78. package/dist/utils/debounce.d.mts +50 -0
  79. package/dist/utils/debounce.mjs +88 -0
  80. package/dist/utils/events.d.mts +1 -1
  81. package/dist/utils/launch-editor.d.mts +8 -0
  82. package/dist/utils/launch-editor.mjs +36 -1
  83. package/dist/utils/nostics.d.mts +2 -2
  84. package/dist/utils/remote-assets.mjs +1 -1
  85. package/dist/utils/serve-static.mjs +1 -1
  86. package/dist/utils/shared-state.d.mts +1 -1
  87. package/dist/utils/simple-schema.d.mts +3 -2
  88. package/dist/utils/streaming-channel.d.mts +1 -1
  89. package/dist/utils/url.d.mts +31 -0
  90. package/dist/utils/url.mjs +58 -0
  91. package/dist/{ws-client-CNpP6Ium.d.mts → ws-client-6Mrz6eC4.d.mts} +2 -2
  92. package/dist/{ws-server-BB8jhxeT.d.mts → ws-server-y2R76aSW.d.mts} +2 -2
  93. package/package.json +10 -11
  94. package/dist/_shared-U8D-xzrp.mjs +0 -115
  95. package/dist/agent-tool-name-DGzeuWcO.mjs +0 -31
  96. package/dist/client-assets-DNdhagGm.mjs +0 -16
  97. package/dist/nostics-DD6gsDZA.mjs +0 -108
  98. package/dist/recipes/common-rpc-functions.d.mts +0 -70
  99. package/dist/recipes/common-rpc-functions.mjs +0 -115
  100. package/dist/simple-schema-Bi40l-P6.mjs +0 -154
@@ -0,0 +1,384 @@
1
+ import { s as colors } from "./nostics-D0PvLZsn.mjs";
2
+ import { n as defineRpcFunction } from "./define-BLWPsH6y.mjs";
3
+ import { isAnonymousRpcMethod } from "./constants.mjs";
4
+ import { a as getTempAuthCodeInfo, n as describeUA, o as refreshTempAuthCode, r as exchangeTempAuthCode, s as verifyAuthToken, t as buildOtpAuthUrl } from "./state-W4wI6X5X.mjs";
5
+ import { t as getInternalContext } from "./context-CHpyLX8W.mjs";
6
+ //#region src/utils/simple-schema.ts
7
+ function ok(value) {
8
+ return { value };
9
+ }
10
+ function fail(message, path) {
11
+ return { issues: [path ? {
12
+ message,
13
+ path
14
+ } : { message }] };
15
+ }
16
+ function make(type, validate, extra) {
17
+ return {
18
+ type,
19
+ ...extra,
20
+ "~standard": {
21
+ version: 1,
22
+ vendor: "devframe",
23
+ validate
24
+ }
25
+ };
26
+ }
27
+ /** Run a Standard Schema synchronously, rejecting async validators. */
28
+ function runSync(schema, value) {
29
+ const result = schema["~standard"].validate(value);
30
+ if (result instanceof Promise) throw new TypeError("[devframe/utils/simple-schema] async validators are not supported inside object()/optional()/nullable()");
31
+ return result;
32
+ }
33
+ /** Any string. */
34
+ function string() {
35
+ return make("string", (v) => typeof v === "string" ? ok(v) : fail("Expected a string"));
36
+ }
37
+ /** A finite number (rejects `NaN`). */
38
+ function number() {
39
+ return make("number", (v) => typeof v === "number" && !Number.isNaN(v) ? ok(v) : fail("Expected a number"));
40
+ }
41
+ /** A boolean. */
42
+ function boolean() {
43
+ return make("boolean", (v) => typeof v === "boolean" ? ok(v) : fail("Expected a boolean"));
44
+ }
45
+ /** `undefined`, mirroring valibot's `void`. */
46
+ function voidType() {
47
+ return make("void", (v) => v === void 0 ? ok(void 0) : fail("Expected undefined"));
48
+ }
49
+ /** `null`. */
50
+ function nullType() {
51
+ return make("null", (v) => v === null ? ok(null) : fail("Expected null"));
52
+ }
53
+ /** One of a fixed set of literal values. */
54
+ function picklist(values) {
55
+ const set = new Set(values);
56
+ return make("picklist", (v) => set.has(v) ? ok(v) : fail(`Expected one of: ${values.join(", ")}`), { values });
57
+ }
58
+ /** A single literal value (string / number / boolean). */
59
+ function literal(value) {
60
+ return make("literal", (v) => v === value ? ok(v) : fail(`Expected ${JSON.stringify(value)}`), { value });
61
+ }
62
+ /** A value matching any one of the given schemas. */
63
+ function union(options) {
64
+ return make("union", (v) => {
65
+ const issues = [];
66
+ for (const option of options) {
67
+ const result = runSync(option, v);
68
+ if (!result.issues) return ok(v);
69
+ issues.push(...result.issues);
70
+ }
71
+ return { issues };
72
+ }, { options });
73
+ }
74
+ /** A record with string keys whose values each satisfy the value schema. */
75
+ function record(_key, value) {
76
+ return make("record", (v) => {
77
+ if (typeof v !== "object" || v === null || Array.isArray(v)) return fail("Expected an object");
78
+ const obj = v;
79
+ const issues = [];
80
+ for (const key of Object.keys(obj)) {
81
+ const result = runSync(value, obj[key]);
82
+ if (result.issues) for (const issue of result.issues) issues.push({
83
+ message: issue.message,
84
+ path: [key, ...issue.path ?? []]
85
+ });
86
+ }
87
+ return issues.length ? { issues } : ok(v);
88
+ });
89
+ }
90
+ /** An array whose every element satisfies the item schema. */
91
+ function array(item) {
92
+ return make("array", (v) => {
93
+ if (!Array.isArray(v)) return fail("Expected an array");
94
+ const issues = [];
95
+ for (let i = 0; i < v.length; i++) {
96
+ const result = runSync(item, v[i]);
97
+ if (result.issues) for (const issue of result.issues) issues.push({
98
+ message: issue.message,
99
+ path: [i, ...issue.path ?? []]
100
+ });
101
+ }
102
+ return issues.length ? { issues } : ok(v);
103
+ });
104
+ }
105
+ /** An object whose known keys each satisfy their schema (extra keys are kept). */
106
+ function object(shape) {
107
+ const entries = Object.entries(shape);
108
+ return make("object", (v) => {
109
+ if (typeof v !== "object" || v === null || Array.isArray(v)) return fail("Expected an object");
110
+ const obj = v;
111
+ const issues = [];
112
+ for (const [key, schema] of entries) {
113
+ const result = runSync(schema, obj[key]);
114
+ if (result.issues) for (const issue of result.issues) issues.push({
115
+ message: issue.message,
116
+ path: [key, ...issue.path ?? []]
117
+ });
118
+ }
119
+ return issues.length ? { issues } : ok(v);
120
+ });
121
+ }
122
+ /** Allow `undefined` in addition to the inner schema. */
123
+ function optional(inner) {
124
+ return make("optional", (v) => v === void 0 ? ok(void 0) : runSync(inner, v), { wrapped: inner });
125
+ }
126
+ /** Allow `null` in addition to the inner schema. */
127
+ function nullable(inner) {
128
+ return make("nullable", (v) => v === null ? ok(null) : runSync(inner, v), { wrapped: inner });
129
+ }
130
+ /** Attach a human-readable description (used for CLI option help). */
131
+ function describe(schema, description) {
132
+ return {
133
+ ...schema,
134
+ description
135
+ };
136
+ }
137
+ /**
138
+ * Grouped access to every builder: `s.string()`, `s.object({ ... })`,
139
+ * `s.void()`, etc. Handy for a valibot-like `import { s } from
140
+ * 'devframe/utils/simple-schema'` call site.
141
+ */
142
+ const s = {
143
+ string,
144
+ number,
145
+ boolean,
146
+ void: voidType,
147
+ null: nullType,
148
+ literal,
149
+ picklist,
150
+ union,
151
+ record,
152
+ array,
153
+ object,
154
+ optional,
155
+ nullable,
156
+ describe
157
+ };
158
+ //#endregion
159
+ //#region src/recipes/interactive-auth.ts
160
+ /**
161
+ * Build a {@link AuthBannerFunction} that renders the auth code + magic-link
162
+ * URL as a small bordered box, its two rows label-aligned. `createInteractiveAuth`
163
+ * falls back to `createAuthBanner()` when no `banner` is given; call this
164
+ * yourself to rebrand the box (`title` / `colors`) and pass the result as
165
+ * `options.banner`.
166
+ */
167
+ function createAuthBanner(options = {}) {
168
+ const title = options.title ?? "Devframe";
169
+ const palette = {
170
+ border: colors.dim,
171
+ title: (x) => colors.gray(colors.bold(x)),
172
+ label: colors.dim,
173
+ code: (f) => colors.green(colors.bold(f)),
174
+ url: colors.cyan,
175
+ ...options.colors
176
+ };
177
+ return (info) => {
178
+ const rows = [
179
+ [
180
+ "auth code",
181
+ info.code,
182
+ palette.code
183
+ ],
184
+ [
185
+ "or open",
186
+ info.url,
187
+ palette.url
188
+ ],
189
+ [
190
+ "expires at",
191
+ new Date(info.expireAt).toLocaleTimeString(),
192
+ palette.label
193
+ ]
194
+ ];
195
+ if (info.requester) {
196
+ rows.push([
197
+ "ua",
198
+ info.requester.ua,
199
+ palette.label
200
+ ]);
201
+ rows.push([
202
+ "origin",
203
+ info.requester.origin,
204
+ palette.label
205
+ ]);
206
+ }
207
+ const labelWidth = Math.max(...rows.map(([label]) => label.length));
208
+ const contentWidth = Math.max(...rows.map(([, value]) => labelWidth + 2 + value.length));
209
+ const titleBarLength = title.length + 2;
210
+ const lineWidth = Math.max(contentWidth, titleBarLength - 2);
211
+ const top = [
212
+ palette.border(`╭`),
213
+ palette.title(title),
214
+ palette.border(`${"─".repeat(Math.max(lineWidth + 2 - titleBarLength, 0))}╮`)
215
+ ].join(" ");
216
+ const bottom = `╰${"─".repeat(lineWidth + 2)}╯`;
217
+ const body = rows.map(([label, value, color]) => {
218
+ const plain = `${label.padEnd(labelWidth)} ${value}`;
219
+ const pad = " ".repeat(lineWidth - plain.length);
220
+ return `${palette.border("│")} ${palette.label(label.padEnd(labelWidth))} ${color(value)}${pad} ${palette.border("│")}`;
221
+ });
222
+ console.log(`\n${palette.border(top)}\n${body.join("\n")}\n${palette.border(bottom)}\n`);
223
+ };
224
+ }
225
+ /**
226
+ * Package the interactive OTP auth protocol devframe's primitives
227
+ * (`exchangeTempAuthCode`, `verifyAuthToken`, `revokeAuthToken`,
228
+ * `getTempAuthCode`, `buildOtpAuthUrl`) implement into a ready-made
229
+ * {@link DevframeAuthHandler}: the handshake RPC functions, the resolver
230
+ * gate, the connect-time trust hook, and the startup banner.
231
+ *
232
+ * The auth storage stays internal to this handler; callers never reach into
233
+ * `devframe/node/hub-internals` themselves.
234
+ *
235
+ * ```ts
236
+ * import { createInteractiveAuth } from 'devframe/recipes/interactive-auth'
237
+ *
238
+ * const auth = createInteractiveAuth(ctx)
239
+ * auth.rpcFunctions.forEach(fn => ctx.rpc.register(fn))
240
+ * auth.printBanner()
241
+ *
242
+ * // wire `auth.authorize` / `auth.onConnect` into your transport, or pass
243
+ * // the whole handler to `initDevframe` / `initHub` via their `auth` option.
244
+ * ```
245
+ */
246
+ function createInteractiveAuth(context, options = {}) {
247
+ const internal = getInternalContext(context);
248
+ const storage = internal.storage.auth;
249
+ const staticTokens = new Set(options.clientAuthTokens ?? []);
250
+ function isStaticToken(token) {
251
+ return !!token && staticTokens.has(token);
252
+ }
253
+ function resolveServerUrl() {
254
+ return options.serverUrl?.() ?? context.host.resolveOrigin();
255
+ }
256
+ const banner = options.banner ?? createAuthBanner();
257
+ let bannerPrintedForCode;
258
+ function printBanner(info) {
259
+ const { code, expireAt } = getTempAuthCodeInfo();
260
+ if (code === bannerPrintedForCode) return;
261
+ bannerPrintedForCode = code;
262
+ const url = buildOtpAuthUrl(resolveServerUrl(), code);
263
+ banner({
264
+ code,
265
+ url,
266
+ expireAt,
267
+ ...info?.requester ? { requester: info.requester } : {}
268
+ });
269
+ }
270
+ const anonymousAuth = defineRpcFunction({
271
+ name: "anonymous:devframe:auth",
272
+ type: "action",
273
+ jsonSerializable: true,
274
+ args: [s.object({
275
+ authToken: s.string(),
276
+ ua: s.string(),
277
+ origin: s.string()
278
+ })],
279
+ returns: s.object({ isTrusted: s.boolean() }),
280
+ handler(params) {
281
+ const session = context.rpc.getCurrentRpcSession();
282
+ if (!session) return { isTrusted: false };
283
+ if (session.meta.isTrusted) return { isTrusted: true };
284
+ if (isStaticToken(params.authToken)) {
285
+ session.meta.clientAuthToken = params.authToken;
286
+ session.meta.isTrusted = true;
287
+ return { isTrusted: true };
288
+ }
289
+ return { isTrusted: verifyAuthToken(params.authToken, session, storage) };
290
+ }
291
+ });
292
+ const anonymousAuthExchange = defineRpcFunction({
293
+ name: "anonymous:devframe:auth:exchange",
294
+ type: "action",
295
+ jsonSerializable: true,
296
+ args: [s.object({
297
+ code: s.string(),
298
+ ua: s.string(),
299
+ origin: s.string()
300
+ })],
301
+ returns: s.object({ authToken: s.nullable(s.string()) }),
302
+ handler(params) {
303
+ const session = context.rpc.getCurrentRpcSession();
304
+ if (!session) return { authToken: null };
305
+ const authToken = exchangeTempAuthCode(params.code, session, params, storage);
306
+ if (authToken) options.onTrusted?.({
307
+ session,
308
+ authToken
309
+ });
310
+ return { authToken };
311
+ }
312
+ });
313
+ const anonymousAuthRequestCode = defineRpcFunction({
314
+ name: "anonymous:devframe:auth:request-code",
315
+ type: "action",
316
+ jsonSerializable: true,
317
+ args: [s.object({
318
+ ua: s.string(),
319
+ origin: s.string(),
320
+ reissue: s.optional(s.boolean())
321
+ })],
322
+ returns: s.void(),
323
+ handler(params) {
324
+ if (params.reissue) refreshTempAuthCode();
325
+ printBanner({ requester: {
326
+ ua: describeUA(params.ua),
327
+ origin: params.origin
328
+ } });
329
+ }
330
+ });
331
+ const revoke = defineRpcFunction({
332
+ name: "devframe:auth:revoke",
333
+ type: "action",
334
+ jsonSerializable: true,
335
+ args: [],
336
+ returns: s.void(),
337
+ async handler() {
338
+ const token = context.rpc.getCurrentRpcSession()?.meta.clientAuthToken;
339
+ if (token) await internal.revokeAuthToken(token);
340
+ }
341
+ });
342
+ function authorize(methodName, session) {
343
+ if (isAnonymousRpcMethod(methodName)) return true;
344
+ return !!session.meta.isTrusted;
345
+ }
346
+ function onConnect(connection, session) {
347
+ let token;
348
+ let requestOrigin;
349
+ try {
350
+ token = new URL(connection.request?.url ?? "", "http://localhost").searchParams.get("devframe_auth_token") ?? void 0;
351
+ } catch {}
352
+ try {
353
+ requestOrigin = connection.request?.headers?.get?.("origin") ?? void 0;
354
+ } catch {}
355
+ if (!token) return;
356
+ if (isStaticToken(token)) {
357
+ session.meta.clientAuthToken = token;
358
+ session.meta.isTrusted = true;
359
+ return;
360
+ }
361
+ if (verifyAuthToken(token, session, storage)) return;
362
+ if (internal.isRemoteTokenTrusted(token, requestOrigin)) {
363
+ session.meta.clientAuthToken = token;
364
+ session.meta.isTrusted = true;
365
+ }
366
+ }
367
+ function buildOpenUrl(url) {
368
+ return buildOtpAuthUrl(url);
369
+ }
370
+ return {
371
+ rpcFunctions: [
372
+ anonymousAuth,
373
+ anonymousAuthExchange,
374
+ anonymousAuthRequestCode,
375
+ revoke
376
+ ],
377
+ authorize,
378
+ onConnect,
379
+ printBanner,
380
+ buildOpenUrl
381
+ };
382
+ }
383
+ //#endregion
384
+ export { createInteractiveAuth as n, createAuthBanner as t };
@@ -1,21 +1,59 @@
1
- import { v as RpcFunctionDefinitionAny } from "../types-D2vGd7-2.mjs";
2
- import { At as AgentHandle, Bt as DevframeAgentHostEvents, F as DevframeDefinition, Ft as AgentTool, It as AgentToolInput, Lt as AgentToolProvider, Mt as AgentResource, Nt as AgentResourceContent, Pt as AgentResourceInput, Rt as AgentToolProviderHandle, Vt as EventEmitter, jt as AgentManifest, o as DevframeNodeContext, xt as DevframeHost, zt as DevframeAgentHost$1 } from "../context-BLHBDQcZ.mjs";
3
- import { a as RemoteAssetsStore, o as StaticAssetsSource } from "../remote-assets-eBvSKZMS.mjs";
4
- import { a as InstanceShellInit, c as StartedServer, d as samePath, f as DevframeInstanceRecord, h as registerDevframeInstance, i as InstanceShellApi, l as createInstanceShell, m as listLiveDevframeInstances, n as InstanceRegisterConfig, o as InstanceShellInternals, p as DevframeInstanceRegistration, r as InstanceShell, s as InstanceWsTier, t as CreateInstanceShellOptions, u as resolveInstanceRegister } from "../instance-shell-C6Vg97lg.mjs";
5
- import { a as resolveBasePath, i as normalizeBasePath, n as ResolvedMcpConfig, r as loadAutoMcpAdapter, s as resolveMcpConfig } from "../_shared-BIUet_Jh.mjs";
6
- import { n as CreateContextRpcServerOptions, r as createContextRpcServer, t as ContextRpcServer } from "../rpc-core-BlL-Ip8n.mjs";
7
- //#region src/client-assets.d.ts
1
+ import { t as StandardSchemaV1 } from "../index-CeEtxDmK.mjs";
2
+ import { g as RpcFunctionDefinitionAny } from "../types-BmDbfHCx.mjs";
3
+ import { Bt as AgentTool, Et as DevframeHost, Ft as AgentHandle, Gt as DevframeAgentHostEvents, Ht as AgentToolProvider, It as AgentManifest, Kt as EventEmitter, Lt as AgentResource, Rt as AgentResourceContent, Ut as AgentToolProviderHandle, Vt as AgentToolInput, Wt as DevframeAgentHost$1, o as DevframeNodeContext, zt as AgentResourceInput } from "../context-CTAxz9ec.mjs";
4
+ import { a as RemoteAssetsStore } from "../remote-assets-eBvSKZMS.mjs";
5
+ import { a as InstanceShellInit, c as StartedServer, d as samePath, f as DevframeInstanceRecord, g as registerDevframeInstance, h as probeDevframeOrigin, i as InstanceShellApi, l as createInstanceShell, m as listLiveDevframeInstances, n as InstanceRegisterConfig, o as InstanceShellInternals, p as DevframeInstanceRegistration, r as InstanceShell, s as InstanceWsTier, t as CreateInstanceShellOptions, u as resolveInstanceRegister } from "../instance-shell-DOZSxst6.mjs";
6
+ import { i as importAgenticMcp, n as MountMcpHttpOptions, r as MountedMcpHttp, t as AgenticMcpModule } from "../agentic-D4QQQUjE.mjs";
7
+ import { a as resolveBasePath, i as normalizeBasePath, n as ResolvedMcpConfig, r as loadAutoMcpAdapter, s as resolveMcpConfig } from "../_shared-Dy1UBMUN.mjs";
8
+ import { n as CreateContextRpcServerOptions, r as createContextRpcServer, t as ContextRpcServer } from "../rpc-core-rLrwFEcw.mjs";
9
+ //#region src/agent/stringify.d.ts
8
10
  /**
9
- * Resolve a definition's client assets source: the built SPA served as its
10
- * UI. Prefers the top-level {@link DevframeDefinition.clientAssets} and falls
11
- * back to the deprecated `cli.distDir`, so both the new and legacy shapes
12
- * resolve. Returns `undefined` when neither is set (bridge mode, where the SPA is
13
- * hosted elsewhere).
11
+ * JSON-coercing serializer for MCP text payloads.
14
12
  *
15
- * Internal: exposed to first-party integrations via `devframe/internal`, not
16
- * part of the stable public API.
13
+ * MCP carries tool results and resource reads as plain text over a
14
+ * JSON-RPC transport, so we cannot use the `s:`-prefixed structured-clone
15
+ * format the WS RPC transport falls back to for non-JSON values. Instead,
16
+ * we coerce common non-JSON types into JSON-friendly forms so the LLM
17
+ * client sees something useful instead of `[object Object]`.
18
+ *
19
+ * Coercions:
20
+ * - `BigInt` → `"123n"`
21
+ * - `Date` → ISO string (via the native `toJSON`)
22
+ * - `Map` → `{ __type: 'Map', entries: [[k, v], …] }`
23
+ * - `Set` → `{ __type: 'Set', entries: [v, …] }`
24
+ * - `Error` → `{ name, message, stack, cause? }` (cause recurses)
25
+ * - `Function` → `"[Function: name]"`
26
+ * - `Symbol` → `value.toString()`
27
+ * - cycles → `"[Circular]"`
17
28
  */
18
- export declare function resolveClientAssets(d: DevframeDefinition): StaticAssetsSource | undefined;
29
+ export declare function stringifyForMcp(value: unknown): string;
30
+ /**
31
+ * Format a thrown value for an MCP `isError` text payload.
32
+ *
33
+ * A nostics `Diagnostic` (every coded devframe error) becomes structured
34
+ * JSON (`{ error: { code, message, fix?, docs? } }`), so an agent receives
35
+ * the actionable next step (`fix`) and the docs URL instead of a bare
36
+ * message string. Other errors surface `Error.name`/`message`, plus one
37
+ * level of `cause.message` so context isn't dropped silently.
38
+ */
39
+ export declare function formatMcpError(error: unknown): string;
40
+ //#endregion
41
+ //#region src/agent/to-json-schema.d.ts
42
+ /**
43
+ * JSON Schema for an RPC return value on the agent/MCP surface.
44
+ * @internal
45
+ */
46
+ export declare function returnToJsonSchema(schema: StandardSchemaV1 | undefined): unknown;
47
+ /**
48
+ * JSON Schema for an RPC function's positional args on the agent/MCP
49
+ * surface. Each positional arg is advertised under `arg0` / `arg1` / …,
50
+ * matching how the agent bridge coerces the incoming object payload back
51
+ * into positional arguments.
52
+ *
53
+ * Returns `{ type: 'object', properties: {} }` when there are no args.
54
+ * @internal
55
+ */
56
+ export declare function argsToJsonSchema(args: readonly StandardSchemaV1[] | undefined): unknown;
19
57
  //#endregion
20
58
  //#region src/node/diagnostics.d.ts
21
59
  /**
@@ -147,7 +185,7 @@ export declare const diagnostics: import("nostics").Diagnostics<{
147
185
  readonly why: (p: {
148
186
  reason: string;
149
187
  }) => string;
150
- readonly fix: "Install it next to devframe (e.g. `npm install @modelcontextprotocol/client`) and run `devframe connect` again.";
188
+ readonly fix: "Install it next to devframe (e.g. `npm install @devframes/agentic`) and run `devframe connect` again.";
151
189
  };
152
190
  readonly DF0047: {
153
191
  readonly why: (p: {
@@ -177,7 +215,7 @@ export declare const diagnostics: import("nostics").Diagnostics<{
177
215
  readonly why: (p: {
178
216
  port: number;
179
217
  }) => string;
180
- readonly fix: "Restart the instance with the --mcp flag (or set `cli.mcp: true` on its definition) to expose its tools, then list instances again.";
218
+ readonly fix: "Restart the instance with the --mcp flag to expose its tools, then list instances again.";
181
219
  };
182
220
  readonly DF0052: {
183
221
  readonly why: (p: {
@@ -324,6 +362,16 @@ export declare const diagnostics: import("nostics").Diagnostics<{
324
362
  }) => string;
325
363
  readonly fix: "On Bun/Deno, serve the advertised `__ws` route from `Bun.serve` / `Deno.serve` with `attachBunWsTransport` / `attachDenoWsTransport` (see the hub-deno example), or connect over the SSE endpoint instead.";
326
364
  };
365
+ readonly DF0078: {
366
+ readonly why: "This devframe exposes agent tools, but the MCP endpoint stays off: the optional peer \"@devframes/agentic\" is not installed.";
367
+ readonly fix: "Install `@devframes/agentic` next to devframe to serve the MCP endpoint, or set `mcp: false` to opt out silently.";
368
+ };
369
+ readonly DF0079: {
370
+ readonly why: (p: {
371
+ reason: string;
372
+ }) => string;
373
+ readonly fix: "Install `@devframes/agentic` next to devframe (the MCP adapter and the MCP SDK live there), or remove the explicit `mcp` setting.";
374
+ };
327
375
  }, readonly [(d: import("nostics").Diagnostic, { method }?: {
328
376
  method?: "log" | "warn" | "error";
329
377
  }) => void]>;
@@ -453,9 +501,5 @@ export declare function peekRpcWireFrame(raw: string): {
453
501
  //#region src/tool-input.d.ts
454
502
  /** Convert tool input for a command, whose arguments must be declared. */
455
503
  export declare function toolInputToCommandArgs(input: unknown, argumentCount?: number): unknown[];
456
- /** @deprecated Use {@link toolInputToRpcArgs} or {@link toolInputToCommandArgs}. */
457
- type AgentArgsFallback = 'wrap' | 'drop';
458
- /** @deprecated Use {@link toolInputToRpcArgs} or {@link toolInputToCommandArgs}. */
459
- export declare function coerceAgentPositionalArgs(input: unknown, schemas: readonly unknown[] | undefined, fallback?: AgentArgsFallback): unknown[];
460
504
  //#endregion
461
- export { type AgentArgsFallback, type ContextRpcServer, type CreateContextRpcServerOptions, type CreateInstanceShellOptions, type DevframeInstanceRecord, type DevframeInstanceRegistration, type InstanceRegisterConfig, type InstanceShell, type InstanceShellApi, type InstanceShellInit, type InstanceShellInternals, type InstanceWsTier, type ResolvedMcpConfig, type RpcWireCodec, type StartedServer, createContextRpcServer, createInstanceShell, listLiveDevframeInstances, loadAutoMcpAdapter, normalizeBasePath, registerDevframeInstance, resolveBasePath, resolveInstanceRegister, resolveMcpConfig, samePath };
505
+ export { type AgenticMcpModule, type ContextRpcServer, type CreateContextRpcServerOptions, type CreateInstanceShellOptions, type DevframeInstanceRecord, type DevframeInstanceRegistration, type InstanceRegisterConfig, type InstanceShell, type InstanceShellApi, type InstanceShellInit, type InstanceShellInternals, type InstanceWsTier, type MountMcpHttpOptions, type MountedMcpHttp, type ResolvedMcpConfig, type RpcWireCodec, type StartedServer, createContextRpcServer, createInstanceShell, importAgenticMcp, listLiveDevframeInstances, loadAutoMcpAdapter, normalizeBasePath, probeDevframeOrigin, registerDevframeInstance, resolveBasePath, resolveInstanceRegister, resolveMcpConfig, samePath };
@@ -1,10 +1,145 @@
1
- import { t as resolveClientAssets } from "../client-assets-DNdhagGm.mjs";
1
+ import { t as Diagnostic } from "../nostics-D0PvLZsn.mjs";
2
2
  import { n as peekRpcWireFrame, t as createRpcWireCodec } from "../wire-codec-B1W3zH3L.mjs";
3
- import { t as diagnostics } from "../diagnostics-DZA6KQ_Z.mjs";
4
- import { n as coerceAgentPositionalArgs, r as toolInputToCommandArgs, t as DevframeAgentHost } from "../host-agent-C3MBpNCd.mjs";
5
- import { a as resolveMcpConfig, n as normalizeBasePath, r as resolveBasePath, s as importRuntimeModule, t as loadAutoMcpAdapter } from "../_shared-U8D-xzrp.mjs";
3
+ import { t as diagnostics } from "../diagnostics-Cx4_VjlG.mjs";
4
+ import { n as toolInputToCommandArgs, t as DevframeAgentHost } from "../host-agent-ZSKgzMVu.mjs";
5
+ import { a as resolveMcpConfig, n as normalizeBasePath, r as resolveBasePath, s as importAgenticMcp, t as loadAutoMcpAdapter } from "../_shared-B2PZsp-J.mjs";
6
+ import { t as importRuntimeModule } from "../import-runtime-module-BzlEQ9PI.mjs";
6
7
  import { t as createH3DevframeHost } from "../host-h3-BROI6SQ4.mjs";
7
- import { i as registerDevframeInstance, n as listLiveDevframeInstances } from "../instance-registry-DCq762YJ.mjs";
8
- import { i as normalizeHttpServerUrl, n as resolveInstanceRegister, r as samePath, t as createInstanceShell } from "../instance-shell-yfrM3_vK.mjs";
9
- import { t as createContextRpcServer } from "../rpc-core-CvkU23bQ.mjs";
10
- export { DevframeAgentHost, coerceAgentPositionalArgs, createContextRpcServer, createH3DevframeHost, createInstanceShell, createRpcWireCodec, diagnostics, importRuntimeModule, listLiveDevframeInstances, loadAutoMcpAdapter, normalizeBasePath, normalizeHttpServerUrl, peekRpcWireFrame, registerDevframeInstance, resolveBasePath, resolveClientAssets, resolveInstanceRegister, resolveMcpConfig, samePath, toolInputToCommandArgs };
8
+ import { i as registerDevframeInstance, n as listLiveDevframeInstances, r as probeDevframeOrigin } from "../instance-registry-DtvYxc0Y.mjs";
9
+ import { i as normalizeHttpServerUrl, n as resolveInstanceRegister, r as samePath, t as createInstanceShell } from "../instance-shell-wC2sfEU_.mjs";
10
+ import { t as createContextRpcServer } from "../rpc-core-BXyMjbKG.mjs";
11
+ //#region src/agent/stringify.ts
12
+ /**
13
+ * JSON-coercing serializer for MCP text payloads.
14
+ *
15
+ * MCP carries tool results and resource reads as plain text over a
16
+ * JSON-RPC transport, so we cannot use the `s:`-prefixed structured-clone
17
+ * format the WS RPC transport falls back to for non-JSON values. Instead,
18
+ * we coerce common non-JSON types into JSON-friendly forms so the LLM
19
+ * client sees something useful instead of `[object Object]`.
20
+ *
21
+ * Coercions:
22
+ * - `BigInt` → `"123n"`
23
+ * - `Date` → ISO string (via the native `toJSON`)
24
+ * - `Map` → `{ __type: 'Map', entries: [[k, v], …] }`
25
+ * - `Set` → `{ __type: 'Set', entries: [v, …] }`
26
+ * - `Error` → `{ name, message, stack, cause? }` (cause recurses)
27
+ * - `Function` → `"[Function: name]"`
28
+ * - `Symbol` → `value.toString()`
29
+ * - cycles → `"[Circular]"`
30
+ */
31
+ function stringifyForMcp(value) {
32
+ if (value === void 0) return "undefined";
33
+ if (typeof value === "string") return value;
34
+ const seen = /* @__PURE__ */ new WeakSet();
35
+ return JSON.stringify(value, (_key, val) => {
36
+ if (typeof val === "bigint") return `${val}n`;
37
+ if (val instanceof Error) {
38
+ const out = {
39
+ name: val.name,
40
+ message: val.message,
41
+ stack: val.stack
42
+ };
43
+ if (val.cause !== void 0) out.cause = val.cause;
44
+ return out;
45
+ }
46
+ if (val instanceof Map) return {
47
+ __type: "Map",
48
+ entries: [...val.entries()]
49
+ };
50
+ if (val instanceof Set) return {
51
+ __type: "Set",
52
+ entries: [...val]
53
+ };
54
+ if (typeof val === "function") return `[Function: ${val.name || "anonymous"}]`;
55
+ if (typeof val === "symbol") return val.toString();
56
+ if (val !== null && typeof val === "object") {
57
+ if (seen.has(val)) return "[Circular]";
58
+ seen.add(val);
59
+ }
60
+ return val;
61
+ }, 2);
62
+ }
63
+ /**
64
+ * Format a thrown value for an MCP `isError` text payload.
65
+ *
66
+ * A nostics `Diagnostic` (every coded devframe error) becomes structured
67
+ * JSON (`{ error: { code, message, fix?, docs? } }`), so an agent receives
68
+ * the actionable next step (`fix`) and the docs URL instead of a bare
69
+ * message string. Other errors surface `Error.name`/`message`, plus one
70
+ * level of `cause.message` so context isn't dropped silently.
71
+ */
72
+ function formatMcpError(error) {
73
+ if (error instanceof Diagnostic) return JSON.stringify({ error: {
74
+ code: error.code,
75
+ message: error.message,
76
+ ...error.fix ? { fix: error.fix } : {},
77
+ ...error.docs ? { docs: error.docs } : {}
78
+ } }, null, 2);
79
+ if (!(error instanceof Error)) return String(error);
80
+ const cause = error.cause;
81
+ const causeText = cause instanceof Error ? ` (cause: ${cause.message})` : cause !== void 0 ? ` (cause: ${String(cause)})` : "";
82
+ return `${error.name}: ${error.message}${causeText}`;
83
+ }
84
+ //#endregion
85
+ //#region src/agent/to-json-schema.ts
86
+ const FALLBACK_OBJECT_SCHEMA = Object.freeze({
87
+ type: "object",
88
+ additionalProperties: true
89
+ });
90
+ /**
91
+ * Convert a Standard Schema to JSON Schema for the agent/MCP surface.
92
+ *
93
+ * Devframe stays validator-neutral, so conversion uses the schema's own
94
+ * [Standard JSON Schema](https://standardschema.dev/) converter
95
+ * (`~standard.jsonSchema`) when the validator provides one; zod 4 does,
96
+ * for example. Validators without a native converter (e.g. valibot) degrade
97
+ * to a permissive object schema rather than pulling in a converter library.
98
+ */
99
+ function safeToJsonSchema(schema) {
100
+ const standard = schema["~standard"];
101
+ if (standard.jsonSchema) try {
102
+ return standard.jsonSchema.input({ target: "draft-2020-12" });
103
+ } catch {
104
+ return FALLBACK_OBJECT_SCHEMA;
105
+ }
106
+ return FALLBACK_OBJECT_SCHEMA;
107
+ }
108
+ /**
109
+ * JSON Schema for an RPC return value on the agent/MCP surface.
110
+ * @internal
111
+ */
112
+ function returnToJsonSchema(schema) {
113
+ if (!schema) return void 0;
114
+ return safeToJsonSchema(schema);
115
+ }
116
+ /**
117
+ * JSON Schema for an RPC function's positional args on the agent/MCP
118
+ * surface. Each positional arg is advertised under `arg0` / `arg1` / …,
119
+ * matching how the agent bridge coerces the incoming object payload back
120
+ * into positional arguments.
121
+ *
122
+ * Returns `{ type: 'object', properties: {} }` when there are no args.
123
+ * @internal
124
+ */
125
+ function argsToJsonSchema(args) {
126
+ if (!args || args.length === 0) return {
127
+ type: "object",
128
+ properties: {}
129
+ };
130
+ const properties = {};
131
+ const required = [];
132
+ for (let i = 0; i < args.length; i++) {
133
+ const key = `arg${i}`;
134
+ properties[key] = safeToJsonSchema(args[i]);
135
+ required.push(key);
136
+ }
137
+ return {
138
+ type: "object",
139
+ properties,
140
+ required,
141
+ additionalProperties: false
142
+ };
143
+ }
144
+ //#endregion
145
+ export { DevframeAgentHost, argsToJsonSchema, createContextRpcServer, createH3DevframeHost, createInstanceShell, createRpcWireCodec, diagnostics, formatMcpError, importAgenticMcp, importRuntimeModule, listLiveDevframeInstances, loadAutoMcpAdapter, normalizeBasePath, normalizeHttpServerUrl, peekRpcWireFrame, probeDevframeOrigin, registerDevframeInstance, resolveBasePath, resolveInstanceRegister, resolveMcpConfig, returnToJsonSchema, samePath, stringifyForMcp, toolInputToCommandArgs };