devframe 0.7.16 → 0.8.1

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 (80) hide show
  1. package/bin/devframe.mjs +8 -0
  2. package/dist/adapters/build.d.mts +1 -1
  3. package/dist/adapters/build.mjs +4 -4
  4. package/dist/adapters/cac.d.mts +1 -1
  5. package/dist/adapters/cac.mjs +1 -1
  6. package/dist/adapters/cli.d.mts +1 -1
  7. package/dist/adapters/cli.mjs +1 -1
  8. package/dist/adapters/dev.d.mts +2 -2
  9. package/dist/adapters/dev.mjs +1 -1
  10. package/dist/adapters/embedded.d.mts +1 -1
  11. package/dist/adapters/mcp.d.mts +51 -3
  12. package/dist/adapters/mcp.mjs +2 -2
  13. package/dist/agent-tool-name-C3b5vEwJ.mjs +34 -0
  14. package/dist/{cac-CPaOy3LD.mjs → cac-B1LM3zit.mjs} +18 -13
  15. package/dist/cli/main.d.mts +11 -0
  16. package/dist/cli/main.mjs +284 -0
  17. package/dist/client/index.d.mts +40 -11
  18. package/dist/client/index.mjs +129 -19
  19. package/dist/constants.d.mts +13 -6
  20. package/dist/constants.mjs +13 -6
  21. package/dist/{context-DY72brRI.mjs → context-CQefP2jR.mjs} +3 -2
  22. package/dist/{context-CzqPrJSz.d.mts → context-DFzmxCLa.d.mts} +1 -1
  23. package/dist/{revoke-BtQDKTp7.mjs → crypto-token-XCqTSMg9.mjs} +1 -35
  24. package/dist/{dev-BCeaQuGE.mjs → dev-BSHFZGZr.mjs} +22 -11
  25. package/dist/{devframe-Ckhf3kFw.d.mts → devframe-qgCKL683.d.mts} +77 -15
  26. package/dist/diagnostics-B5-qHeqD.mjs +94 -0
  27. package/dist/{diagnostics-BXwBQmoN.mjs → diagnostics-hwjXp_UV.mjs} +8 -0
  28. package/dist/{dump-Cz7yVvsB.mjs → dump-CgZShDRB.mjs} +82 -6
  29. package/dist/fetch-CK0S253E.mjs +534 -0
  30. package/dist/helpers/vite.d.mts +15 -14
  31. package/dist/helpers/vite.mjs +8 -8
  32. package/dist/{host-h3-CgOetlNE.mjs → host-h3-Kz7t5Xab.mjs} +83 -28
  33. package/dist/http-Dvgxujcu.mjs +38 -0
  34. package/dist/{index-8dndvIxR.d.mts → index-B7RgLw--.d.mts} +11 -6
  35. package/dist/{index-DgsLFhZg.d.mts → index-Dbw1p5ch.d.mts} +27 -3
  36. package/dist/{index-YDSJgsyG.d.mts → index-vAX6bYuc.d.mts} +1 -1
  37. package/dist/index.d.mts +5 -5
  38. package/dist/instance-registry-D6fxYu36.mjs +190 -0
  39. package/dist/node/auth.d.mts +2 -2
  40. package/dist/node/auth.mjs +2 -2
  41. package/dist/node/hub-internals.d.mts +2 -2
  42. package/dist/node/hub-internals.mjs +1 -1
  43. package/dist/node/index.d.mts +124 -6
  44. package/dist/node/index.mjs +5 -4
  45. package/dist/recipes/common-rpc-functions.d.mts +33 -33
  46. package/dist/recipes/common-rpc-functions.mjs +6 -6
  47. package/dist/recipes/interactive-auth.d.mts +2 -2
  48. package/dist/recipes/interactive-auth.mjs +23 -15
  49. package/dist/revoke-DZbJ7Cl0.mjs +35 -0
  50. package/dist/rpc/dump.d.mts +1 -1
  51. package/dist/rpc/dump.mjs +1 -1
  52. package/dist/rpc/index.d.mts +3 -3
  53. package/dist/rpc/index.mjs +4 -4
  54. package/dist/rpc/transports/ws-client.d.mts +1 -1
  55. package/dist/rpc/transports/ws-client.mjs +1 -1
  56. package/dist/rpc/transports/ws-server.d.mts +2 -2
  57. package/dist/rpc/transports/ws-server.mjs +50 -3
  58. package/dist/{serialization-DpLXCy13.mjs → serialization-C8Mnw9hK.mjs} +1 -1
  59. package/dist/{server-DykHCza_.mjs → server-CXaDDUl0.mjs} +2 -2
  60. package/dist/{server-B0wiP_Oi.d.mts → server-E9z4ZWbd.d.mts} +4 -3
  61. package/dist/simple-schema-BDzLeJDk.d.mts +102 -0
  62. package/dist/simple-schema-DQPZrAaZ.mjs +154 -0
  63. package/dist/{state-WX3HT5a3.mjs → state-BeUHDDjk.mjs} +13 -6
  64. package/dist/{storage-gEnj9ASQ.mjs → storage-Dzoc3NVC.mjs} +2 -66
  65. package/dist/{transports-BmDVn4SF.mjs → transports-vhizgqXM.mjs} +1 -1
  66. package/dist/types/index.d.mts +4 -4
  67. package/dist/{types-CrzNxXKq.d.mts → types-CnJSgRVa.d.mts} +33 -19
  68. package/dist/utils/agent-tool-name.d.mts +27 -0
  69. package/dist/utils/agent-tool-name.mjs +34 -0
  70. package/dist/utils/events.d.mts +1 -1
  71. package/dist/utils/shared-state.d.mts +1 -1
  72. package/dist/utils/simple-schema.d.mts +2 -0
  73. package/dist/utils/simple-schema.mjs +154 -0
  74. package/dist/utils/streaming-channel.d.mts +1 -1
  75. package/dist/{ws-client-DSXiI2h7.d.mts → ws-client-B6Tnr0ic.d.mts} +1 -1
  76. package/dist/{ws-server-9-wn7MNQ.d.mts → ws-server-J-zkiOyp.d.mts} +24 -3
  77. package/package.json +18 -7
  78. package/skills/devframe/SKILL.md +4 -3
  79. package/dist/build-server-C7vTKjiQ.mjs +0 -359
  80. package/dist/http-_pPbryTQ.mjs +0 -114
@@ -0,0 +1,94 @@
1
+ import { t as devframeReporter } from "./diagnostics-reporter-CsIG85Q5.mjs";
2
+ import { defineDiagnostics } from "nostics";
3
+ //#region src/node/diagnostics.ts
4
+ const diagnostics = defineDiagnostics({
5
+ docsBase: "https://devfra.me/errors",
6
+ reporters: [devframeReporter],
7
+ codes: {
8
+ DF0006: { why: (p) => `RPC function "${p.name}" is not registered` },
9
+ DF0007: { why: "AsyncLocalStorage is not set, it likely to be an internal bug of the Devframe foundation" },
10
+ DF0008: { why: (p) => `distDir ${p.distDir} does not exist` },
11
+ DF0012: { why: (p) => `Failed to parse storage file: ${p.filepath}, falling back to defaults.` },
12
+ DF0013: { why: (p) => `Shared state of "${p.key}" is not found, please provide an initial value for the first time` },
13
+ DF0014: {
14
+ why: (p) => `RPC function "${p.name}" has an invalid \`agent\` field — \`description\` must be a non-empty string.`,
15
+ fix: "Provide a short description (~1–3 sentences) explaining what the tool does and when agents should invoke it."
16
+ },
17
+ DF0015: {
18
+ why: (p) => `Agent tool "${p.id}" is already registered.`,
19
+ fix: "Tool ids must be unique across RPC functions with an `agent` field and tools registered via `ctx.agent.registerTool()`."
20
+ },
21
+ DF0016: { why: (p) => `Agent resource "${p.id}" is already registered.` },
22
+ DF0017: { why: (p) => `Failed to start MCP server (${p.transport}): ${p.reason}` },
23
+ DF0029: {
24
+ why: (p) => `Stream "${p.channel}#${p.id}" dropped ${p.dropped} chunk(s) after exceeding the client high-water mark.`,
25
+ fix: "The consumer is too slow for the producer. Raise `highWaterMark` on the subscription, slow the producer, or batch chunks."
26
+ },
27
+ DF0030: {
28
+ why: (p) => `Stream "${p.channel}#${p.id}" is unknown — no producer has called \`channel.start({ id: "${p.id}" })\`.`,
29
+ fix: "Ensure the server-side producer is running before clients subscribe, or check for typos in the stream id."
30
+ },
31
+ DF0031: {
32
+ why: (p) => `Cannot write to closed stream "${p.channel}#${p.id}".`,
33
+ fix: "Track the producer lifecycle — guard writes with the `stream.signal.aborted` flag."
34
+ },
35
+ DF0032: {
36
+ why: (p) => `Streaming channel "${p.channel}" is already registered.`,
37
+ fix: "Each channel name must be unique within a context. Pick a different name or reuse the existing channel handle."
38
+ },
39
+ DF0033: {
40
+ why: (p) => `Failed to start dev RPC bridge for "${p.id}": ${p.reason}`,
41
+ fix: "Verify the bridge port is free and the devframe setup function does not throw. Pin a port via `cli.port` / `cli.portRange` on the definition, or via `devMiddleware.port` on `viteDevBridge`."
42
+ },
43
+ DF0034: {
44
+ why: (p) => `Scoped RPC registration for namespace "${p.namespace}" received an already-namespaced function name "${p.name}".`,
45
+ fix: "A scoped context auto-namespaces ids. Pass a bare name without a \":\" separator (e.g. `register({ name: \"get-cwd\" })`), or use the unscoped `ctx.base.rpc.register` for a fully-qualified name."
46
+ },
47
+ DF0035: {
48
+ why: (p) => `Failed to persist storage file: ${p.filepath}`,
49
+ fix: "Check that the storage directory is writable and has free space."
50
+ },
51
+ DF0036: {
52
+ why: (p) => `RPC call to "${p.name}" was rejected: the caller is not authorized.`,
53
+ fix: "Complete the auth handshake (or connect with a static/pre-shared token) before calling a trusted method. Untrusted callers may only call `anonymous:`-prefixed methods — see `isAnonymousRpcMethod`."
54
+ },
55
+ DF0037: {
56
+ why: (p) => `A service is already provided under "${p.id}".`,
57
+ fix: "Service ids are unique per context. Revoke the existing provider first (the `provide()` call returns a revoke function), or namespace the id with your plugin id to avoid collisions."
58
+ },
59
+ DF0042: {
60
+ why: (p) => `"${p.id}" declares \`capabilities.build: false\` — its static export is not meaningful (writes are excluded and any live-served data won't be there).`,
61
+ fix: "Pass `{ force: true }` to `createBuild()` if the degraded export is still useful to you, or drop `capabilities.build: false` on the definition."
62
+ },
63
+ DF0045: {
64
+ why: (p) => `Failed to update the devframe instance registry at "${p.file}": ${p.reason}`,
65
+ fix: "Discovery tooling (`devframe connect`) will not see this instance. Check that the registry directory is writable, point `DEVFRAME_INSTANCES_DIR` at a writable directory, or set `DEVFRAME_DISABLE_INSTANCE_REGISTRY=1` to opt out of registration."
66
+ },
67
+ DF0046: {
68
+ why: (p) => `\`devframe connect\` requires the optional peer dependency @modelcontextprotocol/server: ${p.reason}`,
69
+ fix: "Install it next to devframe (e.g. `npm install @modelcontextprotocol/server`) and run `devframe connect` again."
70
+ },
71
+ DF0047: {
72
+ why: (p) => `Agent tool "${p.id}" is hidden from the MCP surface: its wire name "${p.name}" collides with the tool "${p.existing}".`,
73
+ fix: "Wire names derive from tool ids (characters outside [a-zA-Z0-9_-] become \"_\"). Rename one of the two ids so they sanitize to distinct names."
74
+ },
75
+ DF0048: {
76
+ why: (p) => `Unknown shared-state key "${p.key}".`,
77
+ fix: "Call the devframe_state_read tool without arguments to list the available keys, then retry with one of them."
78
+ },
79
+ DF0049: {
80
+ why: "The devframe_connect_call-tool tool requires { port: number, tool: string }.",
81
+ fix: "Call devframe_connect_list-instances to get the port and tool names, then retry."
82
+ },
83
+ DF0050: {
84
+ why: (p) => `No running devframe instance on port ${p.port}.`,
85
+ fix: "Call devframe_connect_list-instances for the current instance list — the instance may have stopped or changed port."
86
+ },
87
+ DF0051: {
88
+ why: (p) => `The devframe instance on port ${p.port} has no MCP endpoint.`,
89
+ fix: "Restart the instance with the --mcp flag (or set `cli.mcp: true` on its definition) to expose its tools, then list instances again."
90
+ }
91
+ }
92
+ });
93
+ //#endregion
94
+ export { diagnostics as t };
@@ -26,6 +26,14 @@ const diagnostics = defineDiagnostics({
26
26
  DF0028: {
27
27
  why: (p) => `Function "${p.name}" with type "${p.type}" cannot use \`snapshot: true\`. Only "query" functions support this sugar; "static" functions have equivalent default behavior already.`,
28
28
  fix: "Remove `snapshot: true`, or change the function type to `query`."
29
+ },
30
+ DF0043: {
31
+ why: (p) => `RPC function "${p.name}" received an invalid argument at position ${p.index}: ${p.issues}`,
32
+ fix: "Pass a value that satisfies the `args` schema declared for this function."
33
+ },
34
+ DF0044: {
35
+ why: (p) => `RPC function "${p.name}" returned a value that failed its \`returns\` schema: ${p.issues}`,
36
+ fix: "Make the handler return a value that satisfies the `returns` schema, or relax the schema."
29
37
  }
30
38
  }
31
39
  });
@@ -1,4 +1,4 @@
1
- import { t as diagnostics } from "./diagnostics-BXwBQmoN.mjs";
1
+ import { t as diagnostics } from "./diagnostics-hwjXp_UV.mjs";
2
2
  import { DEVFRAME_RPC_DUMP_DIRNAME } from "./constants.mjs";
3
3
  import { createHash } from "node:crypto";
4
4
  //#region ../../node_modules/.pnpm/ohash@2.0.11/node_modules/ohash/dist/shared/ohash.D__AXeF1.mjs
@@ -498,6 +498,70 @@ function getDefinitionsWithDumps(definitions) {
498
498
  return definitions.filter((def) => def.dump !== void 0);
499
499
  }
500
500
  //#endregion
501
+ //#region src/rpc/validate-io.ts
502
+ /**
503
+ * Run a single [Standard Schema](https://standardschema.dev) validator,
504
+ * awaiting the result when the validator is asynchronous.
505
+ */
506
+ async function runStandardSchema(schema, value) {
507
+ const result = schema["~standard"].validate(value);
508
+ return result instanceof Promise ? await result : result;
509
+ }
510
+ /**
511
+ * Render Standard Schema issues into a single human-readable line for a
512
+ * diagnostic message, prefixing each with its dotted path when present.
513
+ */
514
+ function formatIssues(issues) {
515
+ return issues.map((issue) => {
516
+ const path = issue.path?.map((segment) => typeof segment === "object" ? segment.key : segment).join(".");
517
+ return path ? `${path}: ${issue.message}` : issue.message;
518
+ }).join("; ");
519
+ }
520
+ /**
521
+ * Validate positional arguments against their declared schemas. Only
522
+ * indices with a schema are checked; extra arguments pass through
523
+ * untouched. Throws `DF0038` on the first failing argument.
524
+ *
525
+ * Validation guards the payload without rewriting it: the original values
526
+ * are handed to the handler unchanged, so a schema that describes a subset
527
+ * of an object never silently strips the sender's extra fields (and any
528
+ * declared transforms stay a purely type-level concern).
529
+ *
530
+ * @internal
531
+ */
532
+ async function validateRpcArgs(name, argsSchema, args) {
533
+ const original = args.slice();
534
+ if (!argsSchema || argsSchema.length === 0) return original;
535
+ for (let index = 0; index < argsSchema.length; index++) {
536
+ const schema = argsSchema[index];
537
+ if (!schema) continue;
538
+ const result = await runStandardSchema(schema, args[index]);
539
+ if (result.issues) throw diagnostics.DF0043({
540
+ name,
541
+ index,
542
+ issues: formatIssues(result.issues)
543
+ });
544
+ }
545
+ return original;
546
+ }
547
+ /**
548
+ * Validate a handler's resolved return value against its declared schema.
549
+ * Throws `DF0039` when the value fails the schema, otherwise returns the
550
+ * original value unchanged (guard-only, never rewriting the payload — see
551
+ * {@link validateRpcArgs}). Passes through when no return schema is set.
552
+ *
553
+ * @internal
554
+ */
555
+ async function validateRpcReturn(name, returnSchema, value) {
556
+ if (!returnSchema) return value;
557
+ const result = await runStandardSchema(returnSchema, value);
558
+ if (result.issues) throw diagnostics.DF0044({
559
+ name,
560
+ issues: formatIssues(result.issues)
561
+ });
562
+ return value;
563
+ }
564
+ //#endregion
501
565
  //#region src/rpc/handler.ts
502
566
  async function getRpcResolvedSetupResult(definition, context) {
503
567
  if (!definition.setup) return {};
@@ -524,10 +588,22 @@ async function getRpcResolvedSetupResult(definition, context) {
524
588
  return await definition.__promise;
525
589
  }
526
590
  async function getRpcHandler(definition, context) {
527
- if (definition.handler) return definition.handler;
528
- const result = await getRpcResolvedSetupResult(definition, context);
529
- if (!result.handler) throw diagnostics.DF0024({ name: definition.name });
530
- return result.handler;
591
+ let handler = definition.handler;
592
+ if (!handler) {
593
+ const result = await getRpcResolvedSetupResult(definition, context);
594
+ if (!result.handler) throw diagnostics.DF0024({ name: definition.name });
595
+ handler = result.handler;
596
+ }
597
+ const argsSchema = definition.args;
598
+ const returnSchema = definition.returns;
599
+ if (!argsSchema && !returnSchema) return handler;
600
+ const inner = handler;
601
+ const validating = async (...args) => {
602
+ const validatedArgs = await validateRpcArgs(definition.name, argsSchema, args);
603
+ const output = await inner(...validatedArgs);
604
+ return await validateRpcReturn(definition.name, returnSchema, output);
605
+ };
606
+ return validating;
531
607
  }
532
608
  //#endregion
533
609
  //#region src/rpc/dump/static.ts
@@ -607,4 +683,4 @@ async function collectStaticRpcDump(definitions, context) {
607
683
  };
608
684
  }
609
685
  //#endregion
610
- export { dumpFunctions as a, serializeDumpError as c, hash as d, createClientFromDump as i, validateDefinition as l, getRpcHandler as n, getDefinitionsWithDumps as o, getRpcResolvedSetupResult as r, reviveDumpError as s, collectStaticRpcDump as t, validateDefinitions as u };
686
+ export { validateRpcReturn as a, getDefinitionsWithDumps as c, validateDefinition as d, validateDefinitions as f, validateRpcArgs as i, reviveDumpError as l, getRpcHandler as n, createClientFromDump as o, hash as p, getRpcResolvedSetupResult as r, dumpFunctions as s, collectStaticRpcDump as t, serializeDumpError as u };