@adhd/apigen-engine-runtime 0.1.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.
package/README.md ADDED
@@ -0,0 +1,40 @@
1
+ # @adhd/apigen-engine-runtime
2
+
3
+ The apigen **dispatch runtime** — the single canonical call path every plugin and every
4
+ generated server uses to turn an inbound request into a function call. Pure TypeScript,
5
+ **platform: shared**.
6
+
7
+ Part of [apigen](../README.md). For end-to-end usage see [`../cli`](../cli).
8
+
9
+ ## Public API
10
+
11
+ ```ts
12
+ import { dispatch, buildFnTable, describeParams, needsEnvelopeField, dataParamNames, createLogger, defineMiddleware, createApiPackage, EventBus, wireObservers, buildContext } from '@adhd/apigen-engine-runtime';
13
+ import type { Logger, LogFormat, CreateLoggerOptions, ParamInfo, AnyFn } from '@adhd/apigen-engine-runtime';
14
+ ```
15
+
16
+ - **`dispatch(fns, ctx, schema, fnName, envelope, data)`** — the one dispatch path. No plugin
17
+ inlines this; all import it here.
18
+ - **`buildFnTable(mod)`** — normalize an imported module into a callable table, recursively
19
+ unwrapping `default` / CommonJS `module.exports` layers and keying functions by their
20
+ `.name` so default- and CJS-wrapped exports resolve (closes ledger finding F28).
21
+ - **`describeParams(schema)` → `ParamInfo[]`** — extract the parameter list for route/tool
22
+ logging and CLI flag generation.
23
+ - **`needsEnvelopeField` / `dataParamNames`** — envelope + param helpers (single source).
24
+ - **`createLogger({ level, format, destination })`** — pino-based logger; defaults to
25
+ **stderr** so MCP stdio stdout stays protocol-clean. `format: 'json' | 'pretty'`.
26
+ - **`defineMiddleware` / `createApiPackage` / `EventBus` / `wireObservers` / `buildContext`**
27
+ — middleware + observer wiring.
28
+
29
+ ## Request envelope
30
+
31
+ Inbound payloads are wrapped: `{ "data": { ...params }, ...envelope }`. `dispatch` validates
32
+ the envelope fields a function requires (e.g. a `session` added by middleware) and passes
33
+ `data` to the function.
34
+
35
+ ## Develop
36
+
37
+ ```bash
38
+ npx nx build apigen-engine-runtime
39
+ npx nx test apigen-engine-runtime
40
+ ```
package/index.d.ts ADDED
@@ -0,0 +1,28 @@
1
+ export { createInvoker, LayerContext } from './lib/invoke';
2
+ export type { Layer, LayerResult, Next, Call, InvokeOptions, InvokeFn, } from './lib/invoke';
3
+ export { defineMiddleware } from './lib/define-middleware';
4
+ export { EventBus, wireObservers } from './lib/event-bus';
5
+ export { buildContext } from './lib/build-context';
6
+ export { assertNoSelfSubscription, createApiPackage } from './lib/api-package';
7
+ export type { MiddlewareDef, MiddlewareEvent, ApiPackageOptions, ApiPackageResult, ConfigurationError, GeneratedSchemas, ComposedSchemas, } from './lib/types';
8
+ export { needsEnvelopeField, dataParamNames, dispatch } from './lib/dispatch';
9
+ export { createLogger } from './lib/logger';
10
+ export type { Logger, LogFormat, CreateLoggerOptions } from './lib/logger';
11
+ export { describeParams } from './lib/describe-params';
12
+ export type { ParamInfo } from './lib/describe-params';
13
+ export { coerceQueryParams } from './lib/coerce-query';
14
+ export { buildFnTable } from './lib/fn-table';
15
+ export type { AnyFn } from './lib/fn-table';
16
+ export { validateLayer, makeValidateLayer, ValidateSchemasToken, } from './lib/validate-layer';
17
+ export { InstanceRegistry } from './lib/instance-registry';
18
+ export type { InstanceRegistryOptions, CreateResult, AnyConstructor, } from './lib/instance-registry';
19
+ export { createStream, drainStream, collectWithPhase, isApiStream, } from './lib/stream';
20
+ export type { ApiStream, CreateStreamOptions, CollectResult, } from './lib/stream';
21
+ export { createUnionCodec, UnionCodecError } from './lib/logical/union-codec';
22
+ export type { UnionCodecOptions, UnionCodecErrorCode, } from './lib/logical/union-codec';
23
+ export { tsHostBinding, WELL_KNOWN_TS_CODECS } from './lib/logical/host-ts';
24
+ export type { HostBinding } from './lib/logical/host-ts';
25
+ export { buildToolDescription } from './lib/tool-description';
26
+ export type { ToolDescriptionSchema } from './lib/tool-description';
27
+ export { buildMcpOutputSchema, wrapMcpStructuredContent, } from './lib/mcp-output-schema';
28
+ export type { McpOutputAdapter } from './lib/mcp-output-schema';
package/index.js ADDED
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});require("ts-morph");require("node:fs");require("node:path");require("ts-json-schema-generator");const N=require("pino"),ge=require("ajv"),we=require("ajv-formats"),I="$apigen";class K extends Error{constructor(t){super(t),this.code="E_DUP_CODEC",this.name="CodecRegistryError"}}function be(e){const t=new Map;return{register(r,n){if(t.has(r.id)&&!(n!=null&&n.override))throw new K(`E_DUP_CODEC: a codec is already registered for id "${r.id}"`);t.set(r.id,r)},resolve(r){for(const n of t.values())if(n.matches(r))return n},get(r){return t.get(r)},ids(){return[...t.keys()]},freeze(){const r=new Map(t),n={register(){throw new K("E_DUP_CODEC: registry is frozen and cannot accept new codecs")},resolve(o){for(const i of r.values())if(i.matches(o))return i},get(o){return r.get(o)},ids(){return[...r.keys()]},freeze(){return n}};return n}}}const L="x-apigen-logical",U="x-apigen-codec",k="x-apigen-ctor",x="x-apigen-tojson",ve="0.1.0";function V(e,t){return{registry:e,resolve:r=>{throw new Error(`[apigen-logical] $ref "${r}" cannot be resolved in run-mode without a descriptor root. Supply a resolve() in the ctx override to handle $ref.`)},seen:new WeakSet,path:"",mode:"strict",...t}}function b(e,t,r){const n=r.registry.resolve(t);if(n)return n.encode(e,t,r);const o=t.$ref;if(typeof o=="string"){const s=r.resolve(o);return b(e,s,r)}const i=t.oneOf;if(Array.isArray(i)){const s=te(e,i,t);return b(e,s,r)}const a=t.type;if(a==="array"){if(!Array.isArray(e))return j(e,t,r);const s=t.items;if(!s)return e.map(c=>g(c));const f=r.path;return Array.isArray(s)?e.map((c,u)=>{const d=s[u];return d===void 0?g(c):b(c,d,{...r,path:`${f}/${u}`})}):e.map((c,u)=>b(c,s,{...r,path:`${f}/${u}`}))}if(a==="object"){if(e===null||typeof e!="object"||Array.isArray(e))return j(e,t,r);const s=t.properties;if(!s)return g(e);const f=r.path,c={};for(const[u,d]of Object.entries(s)){const p=e[u];p!==void 0&&(c[u]=b(p,d,{...r,path:`${f}/${u}`}))}return c}return a==null?j(e,t,r):g(e)}function v(e,t,r){const n=r.registry.resolve(t);if(n)return n.decode(e,t,r);const o=t.$ref;if(typeof o=="string"){const s=r.resolve(o);return v(e,s,r)}const i=t.oneOf;if(Array.isArray(i)){const s=te(e,i,t);return v(e,s,r)}const a=t.type;if(a==="array"){if(!Array.isArray(e))return e;const s=t.items;if(!s)return e;const f=r.path;return Array.isArray(s)?e.map((c,u)=>{const d=s[u];return d===void 0?c:v(c,d,{...r,path:`${f}/${u}`})}):e.map((c,u)=>v(c,s,{...r,path:`${f}/${u}`}))}if(a==="object"){if(e===null||typeof e!="object"||Array.isArray(e))return e;const s=t.properties;if(!s)return e;const f=r.path,c={};for(const[u,d]of Object.entries(s)){const p=e[u];p!==void 0&&(c[u]=v(p,d,{...r,path:`${f}/${u}`}))}return c}return a==null?$e(e,r):e}function te(e,t,r,n){const o=r.discriminator;if(o!=null&&o.propertyName){const i=e!==null&&typeof e=="object"?e[o.propertyName]:void 0;if(typeof i=="string"&&o.mapping){const a=o.mapping[i];if(a){const s=t.find(f=>f.$ref===a);if(s)return s}}}return t[0]??{}}function j(e,t,r){for(const n of r.registry.ids()){const o=r.registry.get(n);if(o)try{const i=o.encode(e,o.schema,r);return{[I]:n,v:i}}catch{}}return g(e)}function $e(e,t){if(e!==null&&typeof e=="object"&&!Array.isArray(e)&&I in e){const r=e,n=r[I],o=t.registry.get(n);if(o)return o.decode(r.v,o.schema,t)}return e}function g(e){if(e===null||typeof e=="string"||typeof e=="number"||typeof e=="boolean")return e;if(Array.isArray(e))return e.map(g);if(typeof e=="object"){const t={};for(const[r,n]of Object.entries(e))n!==void 0&&(t[r]=g(n));return t}return null}function Ne(e){return{encode(t,r,n){const o=V(e,n);return b(t,r,o)},decode(t,r,n){const o=V(e,n);return v(t,r,o)}}}const P={id:"date-time",kind:"scalar",schema:{type:"string",format:"date-time"},matches(e){return e.type==="string"&&e.format==="date-time"},encode(e,t,r){return e.toISOString()},decode(e,t,r){if(typeof e!="string"){if(r.mode==="strict")throw new TypeError(`[date-time] expected a string on the wire at "${r.path}", got ${typeof e}`);return new Date(String(e))}if(r.mode==="strict"&&Number.isNaN(new Date(e).getTime()))throw new TypeError(`[date-time] invalid date-time string at "${r.path}": ${JSON.stringify(e)}`);return new Date(e)}},R={id:"int64",kind:"scalar",schema:{type:"string",format:"int64"},matches(e){return e.type==="string"&&e.format==="int64"},encode(e,t,r){return String(e)},decode(e,t,r){if(typeof e!="string"){if(r.mode==="strict")throw new TypeError(`[int64] expected a string on the wire at "${r.path}", got ${typeof e}`);try{return BigInt(Math.trunc(Number(e)))}catch{return BigInt(0)}}if(r.mode==="strict")return BigInt(e);if(/^-?\d+$/.test(e))try{return BigInt(e)}catch{return BigInt(0)}return BigInt(0)}},q={id:"decimal",kind:"scalar",schema:{type:"string",format:"decimal"},matches(e){return e.type==="string"&&e.format==="decimal"},encode(e,t,r){return e},decode(e,t,r){if(typeof e!="string"){if(r.mode==="strict")throw new TypeError(`[decimal] expected a string on the wire at "${r.path}", got ${typeof e}`);return String(e)}if(r.mode==="strict"&&!/^-?\d+(\.\d+)?$/.test(e))throw new TypeError(`[decimal] wire value "${e}" at "${r.path}" is not a valid decimal string`);return e}},B={id:"byte",kind:"scalar",schema:{type:"string",format:"byte"},matches(e){return e.type==="string"&&e.format==="byte"},encode(e,t,r){return Buffer.from(e).toString("base64")},decode(e,t,r){if(typeof e!="string"){if(r.mode==="strict")throw new TypeError(`[byte] expected a base64 string on the wire at "${r.path}", got ${typeof e}`);return new Uint8Array(0)}if(r.mode==="strict"&&!/^[A-Za-z0-9+/]*={0,2}$/.test(e))throw new TypeError(`[byte] wire value at "${r.path}" is not standard base64 (format:byte): "${e}"`);return new Uint8Array(Buffer.from(e,"base64"))}},Oe=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/,W={id:"uuid",kind:"scalar",schema:{type:"string",format:"uuid"},matches(e){return e.type==="string"&&e.format==="uuid"},encode(e,t,r){return e.toLowerCase()},decode(e,t,r){if(typeof e!="string"){if(r.mode==="strict")throw new TypeError(`[uuid] expected a string on the wire at "${r.path}", got ${typeof e}`);return String(e).toLowerCase()}if(r.mode==="strict"&&!Oe.test(e))throw new TypeError(`[uuid] wire value "${e}" at "${r.path}" is not a lowercase-hyphenated RFC 4122 UUID`);return e}},C="NaN",T="Infinity",M="-Infinity",Ae=new Set([C,T,M]),F={id:"number-special",kind:"scalar",schema:{type:"number"},matches(e){return e.type==="number"&&e.format===void 0},encode(e,t,r){return Number.isNaN(e)?C:e===1/0?T:e===-1/0?M:e},decode(e,t,r){if(typeof e=="number")return e;if(typeof e=="string"){if(e===C)return NaN;if(e===T)return 1/0;if(e===M)return-1/0;const n=Number(e);if(!Number.isNaN(n))return n}if(r.mode==="strict")throw new TypeError(`[number-special] unrecognized wire value at "${r.path}": ${JSON.stringify(e)}. Expected a number or one of ${[...Ae].join(", ")}.`);return NaN}},je=[P,R,q,B,W,F];function _e(e,t={}){for(const r of je)e.register(r,{override:t.override??!1})}P.id,R.id,q.id,B.id,W.id,F.id;const re=be();_e(re);const ne=Ne(re.freeze());function oe(e,t){var n;const r=((n=e.input)==null?void 0:n.properties)??{};return t in r}function ie(e){var r,n;const t=(n=(r=e.input)==null?void 0:r.properties)==null?void 0:n.data;return Object.keys((t==null?void 0:t.properties)??{})}function Se(e,t){var o,i,a;const r=(a=(i=(o=e.input)==null?void 0:o.properties)==null?void 0:i.data)==null?void 0:a.properties,n=r==null?void 0:r[t];return n!==void 0?n:void 0}function Ee(e,t){return t===void 0||e===void 0?e:ne.decode(e,t)}function _(e,t){const r=t.output;return!r||Object.keys(r).length===0?e:ne.encode(e,r)}async function se(e,t,r,n,o,i){const s=ie(r).map(c=>Ee(i[c],Se(r,c)));if(oe(r,"session")&&t){const c=await t({session:o.session}),u=await e[n](c,...s);return _(u,r)}if(r.hasCtx){const c=t?await t(o):void 0,u=await e[n](c,...s);return _(u,r)}const f=await e[n](...s);return _(f,r)}class Ie{constructor(){this._map=new Map}set(t,r){this._map.set(t,r)}get(t){return this._map.get(t)}has(t){return this._map.has(t)}}function ke(e=[]){return async function(r,n,o){const i=o.schemas[r];if(!i)throw new Error(`apigen/invoke: no schema found for operation "${r}"`);const a=()=>se(o.fns,o.createClient,i,r,n.envelope,n.domainArgs);return e.reduceRight((f,c)=>()=>c(n,f),a)()}}function xe(e){return e}class ae{constructor(){this.handlers=new Map}on(t,r){const n=this.handlers.get(t)??[];return this.handlers.set(t,[...n,r]),()=>this.off(t,r)}off(t,r){const n=this.handlers.get(t);if(!n)return;const o=n.filter(i=>i!==r);o.length===0?this.handlers.delete(t):this.handlers.set(t,o)}clear(){this.handlers.clear()}async emit(t){for(const[r,n]of this.handlers)if(Ce(r,t))for(const o of n)await o(t)}}function Ce(e,t){const[r,n,o]=e.split(":");return!(r!=="*"&&r!==t.module||n&&n!=="*"&&n!==t.method||o&&o!=="*"&&o!==t.lifecycle)}function ce(e,t){for(const r of e)if(r.eventMapping)for(const[n,o]of Object.entries(r.eventMapping))t.on(n,o)}async function ue(e,t,r){let n={...t};for(const o of e)if(o.createContext){await r.emit({module:o.id,method:"createContext",lifecycle:"start",ctx:n});try{const i=await o.createContext(n);n={...n,...i},await r.emit({module:o.id,method:"createContext",lifecycle:"complete",ctx:n})}catch(i){throw await r.emit({module:o.id,method:"createContext",lifecycle:"error",ctx:n,error:i}),i}}return n}function J(e,t){const r=new Set,n=[e];for(;n.length>0;){const o=n.pop();if(!o||r.has(o))continue;r.add(o);const i=o.$ref;if(typeof i=="string"){if(t){const d=t[i];if(!d){const p=Object.keys(t).join(", ")||"(none)";throw new Error(`[apigen-logical] $ref "${i}" cannot be resolved. Available $defs: ${p}`)}n.push(d)}continue}const a=o.oneOf;if(Array.isArray(a))for(const d of a)typeof d=="object"&&d!==null&&n.push(d);const s=o.properties;if(s)for(const d of Object.values(s))n.push(d);const f=o.items;if(Array.isArray(f))for(const d of f)typeof d=="object"&&d!==null&&n.push(d);else typeof f=="object"&&f!==null&&n.push(f);const c=o.additionalProperties;typeof c=="object"&&c!==null&&n.push(c);const u=o.propertyNames;typeof u=="object"&&u!==null&&n.push(u)}}const H=new Set(["string","number","boolean","integer"]);function Te(e){if(typeof e!="object"||e===null)return!1;const t=e;if(t.$ref!==void 0||t.oneOf||t.anyOf||t.allOf)return!1;const{type:r}=t;return typeof r=="string"?H.has(r):Array.isArray(r)?r.every(n=>H.has(n)||n==="null"):Array.isArray(t.enum)&&t.enum.length>0?t.enum.every(n=>["string","number","boolean"].includes(typeof n)):!1}function Me(e){if(!e||typeof e!="object")return!1;const t=e.properties;return t===void 0||typeof t!="object"||t===null?!1:Object.values(t).every(Te)}function De(e){const t={},r=n=>{for(const o of["definitions","$defs"]){const i=n[o];if(i)for(const[a,s]of Object.entries(i)){const f=a.startsWith("#/")?a:`#/${o}/${a}`;t[f]=s}}};for(const n of Object.values(e.schemas))r(n.input),r(n.output);if(Object.keys(t).length!==0)for(const[n,o]of Object.entries(e.schemas))try{J(o.input,t),J(o.output,t)}catch(i){throw new Error(`[apigen-core-client] Schema validation failed for function "${n}": ${i.message}`)}}function Le(e,t){const r=['apigen calling convention: all domain parameters go inside a "data" envelope — e.g. { "data": { ... } }'+(t?".":" (an empty object for this zero-parameter tool).")];return e.length>0&&r.push(`Field(s) ${e.map(n=>`"${n}"`).join(", ")} are transport-level envelope metadata, NOT domain data — do not nest them under "data". Over MCP they are read from arguments._meta["x-<pluginId>-<field>"] (default pluginId "adhd"); see @adhd/apigen-naming's envelopeMetaKey/envelopeCliFlag/envelopeEnvVar for the HTTP-header / CLI-flag / env-var equivalents.`),r.join(" ")}function Ue(e,t,r){De(e);const n={};for(const[o,i]of Object.entries(e.schemas)){const a=(r==null?void 0:r[o])??{},s=i.input.properties??{},f=i.input.required??[],c={},u=[];for(const y of t)if(y.envelope&&a[y.id]!==!1)for(const[m,A]of Object.entries(y.envelope))c[m]=A,u.includes(m)||u.push(m);const d={type:"object",properties:s,additionalProperties:!1,...f.length>0?{required:f}:{}},p=i.safe===!0||Me(i.input),w=i.input.definitions,l=i.input.$defs;n[o]={input:{type:"object",properties:{...c,data:d},required:[...u,...f.length>0?["data"]:[]],additionalProperties:!1,description:Le(Object.keys(c),Object.keys(s).length>0),...w?{definitions:w}:{},...l?{$defs:l}:{}},output:i.output,...i.hasCtx?{hasCtx:!0}:{},"x-apigen-safe":p}}return n}const Pe={"decimal.js":"Decimal"};function Re(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}Object.entries(Pe).map(([e,t])=>({pattern:new RegExp(`import\\(["'][^"']*${Re(e)}[^"']*["']\\)\\.\\w+`,"g"),key:t}));class D extends Error{constructor(t){super(t),this.name="ConfigurationError"}}function fe(e){for(const t of e)for(const r of Object.keys(t.eventMapping??{})){const[n]=r.split(":");if(n!=="*"&&n===t.id)throw new D(`Middleware "${t.id}" subscribes to its own events via "${r}". This would cause infinite recursion.`)}}function qe(e){const{domainSchemas:t,middlewares:r,overrides:n={},strict:o=!1}=e;fe(r);for(const c of Object.keys(n))if(!(c in t.schemas)){const u=`Override key "${c}" not found in domain schemas.`;if(o)throw new D(u);console.warn("[apigen-runtime]",u)}const i=new Set(r.map(c=>c.id));for(const[c,u]of Object.entries(n))for(const d of Object.keys(u??{}))if(!i.has(d)){const p=`Override key "${c}.${d}" does not match any declared middleware id.`;if(o)throw new D(p);console.warn("[apigen-runtime]",p)}const a=Ue(t,r,n),s=new ae;return ce(r,s),{schemas:a,createClient:async c=>ue(r,c,s),dispose:()=>s.clear()}}function Be(e={}){const t=e.level??"info",r=typeof e.destination=="string"&&e.destination.length>0,n=!r&&!!process.stderr.isTTY,o=e.format??(n?"pretty":"json"),i={level:t};if(o==="pretty")return i.transport={target:"pino-pretty",options:{colorize:!r,translateTime:"SYS:HH:MM:ss.l",ignore:"pid,hostname",...r?{destination:e.destination,mkdir:!0}:{destination:2}}},N(i);const a=r?N.destination({dest:e.destination,mkdir:!0,sync:!0}):N.destination(2);return N(i,a)}function de(e){return e?e.type==="array"?`${de(e.items)}[]`:e.enum?"enum":e.$ref?String(e.$ref).split("/").pop()||"object":e.anyOf||e.oneOf?"union":e.type??"object":"unknown"}function We(e){var s;const r=(s=((e==null?void 0:e.input)??{}).properties)==null?void 0:s.data,n=(r==null?void 0:r.properties)??{},o=new Set((r==null?void 0:r.required)??[]),i=Object.entries(n).map(([f,c])=>({name:f,type:de(c),required:o.has(f)})),a=i.map(f=>`${f.name}${f.required?"":"?"}: ${f.type}`).join(", ");return{params:i,text:a}}function Fe(e){let t;return Array.isArray(e)?t=e:e?t=[e]:t=[],t.find(r=>r==="number"||r==="integer"||r==="boolean")}function ze(e,t){var i,a;const n=((a=(i=((t==null?void 0:t.input)??{}).properties)==null?void 0:i.data)==null?void 0:a.properties)??{},o={...e};for(const[s,f]of Object.entries(n)){const c=o[s];if(typeof c!="string")continue;const u=Fe(f==null?void 0:f.type);if(u==="number"||u==="integer"){const d=Number(c);!Number.isNaN(d)&&c.trim()!==""&&(o[s]=d)}else u==="boolean"&&(c==="true"?o[s]=!0:c==="false"&&(o[s]=!1))}return o}const G=new Set(["default","module.exports","__esModule"]);function Ke(e){const t={},r=(n,o)=>{for(const[i,a]of Object.entries(n))if(typeof a=="function"){!G.has(i)&&!(i in t)&&(t[i]=a);const s=a.name;s&&!(s in t)&&(t[s]=a)}else a&&typeof a=="object"&&o<2&&G.has(i)&&r(a,o+1)};return r(e,0),t}const Ve=["invalid_argument","unauthenticated","permission_denied","not_found","internal"];class z extends Error{constructor(t,r,n){super(r),this.name="ApiError",this.code=t,this.details=n,Object.setPrototypeOf(this,new.target.prototype)}toJSON(){const t={code:this.code,message:this.message};return this.details!==void 0&&(t.details=this.details),t}}function Je(e){return typeof e=="object"&&e!==null&&e.name==="ApiError"&&Ve.includes(e.code)&&typeof e.toJSON=="function"}function Y(e,t,r=0){return e==="before-first-chunk"?{phase:e,error:t}:{phase:e,error:t,chunksDelivered:r}}const $=new ge({allErrors:!0});we($);for(const e of[L,U,k,x,"discriminator"])$.addKeyword({keyword:e,valid:!0});$.addFormat("decimal",/^[+-]?(?:\d+(?:\.\d+)?|\.\d+)$/);function pe(e){return e.map(t=>`${t.instancePath||"(root)"} ${t.message??"failed schema check"}`).join("; ")}const He=async(e,t)=>{const r=e.ctx.get(le);if(r===void 0)return t();const n=e.operation.id,o=r[n];if(o===void 0)return t();const i={data:e.domainArgs,...e.envelope},a=$.compile(o.input);if(!a(i)){const f=a.errors??[];throw new z("invalid_argument",`Validation failed: ${pe(f)}`,f)}return t()},le=Symbol("ValidateSchemasToken");function Ge(e){return async function(r,n){const o=r.operation.id,i=e[o];if(i===void 0)return n();const a={data:r.domainArgs,...r.envelope},s=$.compile(i.input);if(!s(a)){const c=s.errors??[];throw new z("invalid_argument",`Validation failed: ${pe(c)}`,c)}return n()}}function Ye(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{const t=Math.random()*16|0;return(e==="x"?t:t&3|8).toString(16)})}class Qe{constructor(t={}){var n,o;this._store=new Map,this._sweeper=null,this._defaultTtlMs=t.defaultTtlMs;let r=null;t.sweepIntervalMs===0?r=null:t.sweepIntervalMs!==void 0?r=t.sweepIntervalMs:this._defaultTtlMs!==void 0?r=Math.max(1e3,Math.floor(this._defaultTtlMs/4)):r=null,r!==null&&r>0&&(this._sweeper=setInterval(()=>this._sweep(),r),(o=(n=this._sweeper).unref)==null||o.call(n))}create(t,r=[],n){const o=new t(...r),i=Ye(),a=n??this._defaultTtlMs,s=a!==void 0?Date.now()+a:null;return this._store.set(i,{instance:o,expiresAt:s}),{instanceId:i}}get(t){const r=this._store.get(t);if(!r)throw new Error(`[instance-registry] Unknown instanceId: "${t}"`);if(r.expiresAt!==null&&Date.now()>r.expiresAt)throw this._evict(t,r),new Error(`[instance-registry] Instance "${t}" has expired`);return r.instance}async dispatch(t,r,n=[]){const o=this.get(t),i=o[r];if(typeof i!="function")throw new Error(`[instance-registry] Method "${r}" not found on instance "${t}"`);return i.call(o,...n)}async dispose(t){const r=this._store.get(t);r&&(this._store.delete(t),await S(r.instance))}async disposeAll(){this._sweeper!==null&&(clearInterval(this._sweeper),this._sweeper=null);const t=[...this._store.entries()];this._store.clear(),await Promise.all(t.map(([,r])=>S(r.instance)))}get size(){return this._store.size}_sweep(){const t=Date.now();for(const[r,n]of this._store)n.expiresAt!==null&&t>n.expiresAt&&this._evict(r,n)}_evict(t,r){this._store.delete(t),S(r.instance)}}async function S(e){if(e!==null&&typeof e=="object"&&"dispose"in e){const t=e.dispose;typeof t=="function"&&await t.call(e)}}function Xe(e){const{produce:t,signal:r}=e,n=r??new AbortController().signal;return{[Symbol.asyncIterator](){const o=t(n);return{async next(){return n.aborted?(await o.return(void 0),{done:!0,value:void 0}):o.next()},async return(i){return await o.return(i),{done:!0,value:void 0}},async throw(i){return await o.throw(i),{done:!0,value:void 0}}}}}}async function Ze(e){const t=[];for await(const r of e)t.push(r);return t}async function et(e){const t=[];try{for await(const r of e)t.push(r);return{ok:!0,chunks:t}}catch(r){const n=Je(r)?r:new z("internal",r instanceof Error?r.message:String(r));return t.length===0?{ok:!1,carrier:Y("before-first-chunk",n)}:{ok:!1,carrier:Y("after-first-chunk",n,t.length)}}}function tt(e){return e!==null&&typeof e=="object"&&Symbol.asyncIterator in e}class h extends Error{constructor(t,r){super(r),this.name="UnionCodecError",this.code=t}}function E(e){const t=e.discriminator;if(t===null||typeof t!="object"||Array.isArray(t))return;const r=t;if(typeof r.propertyName!="string")return;const n=r.mapping;if(!(n===null||typeof n!="object"||Array.isArray(n)))return{propertyName:r.propertyName,mapping:n}}function ye(e,t){const r=e[U];if(typeof r=="string"){const n=t.registry.get(r);if(n)return n}return t.registry.resolve(e)}function rt(e,t,r){const n=ye(t,r);return n?n.encode(e,t,r):e}function nt(e,t,r){const n=ye(t,r);return n?n.decode(e,t,r):e}function he(e){const{id:t,schema:r}=e;return{id:t,kind:"union",schema:r,matches(n){if(n[L]==="union")return!0;const o=n.oneOf;return!Array.isArray(o)||o.length===0?!1:E(n)!==void 0},encode(n,o,i){const a=E(o);if(!a)throw new h("E_UNION_NO_DISCRIMINATOR",`[${t}] schema node at "${i.path}" has no discriminator.propertyName; cannot dispatch union branch.`);const{propertyName:s,mapping:f}=a,c=n[s];if(c==null)throw new h("E_UNION_NO_DISCRIMINATOR",`[${t}] value at "${i.path}" is missing the discriminator property "${s}".`);const u=String(c),d=f[u];if(!d)throw new h("E_UNION_UNKNOWN_TAG",`[${t}] discriminator tag "${u}" at "${i.path}" is not in the mapping (known: ${Object.keys(f).join(", ")}).`);const p=i.resolve(d);return rt(n,p,{...i,path:`${i.path}[${u}]`})},decode(n,o,i){if(n===null||typeof n!="object"||Array.isArray(n)){let l;throw n===null?l="null":Array.isArray(n)?l="array":l=typeof n,new h("E_UNION_INVALID_WIRE",`[${t}] expected a JSON object on the wire at "${i.path}", got ${l}.`)}const a=n,s=E(o);if(!s)throw new h("E_UNION_NO_DISCRIMINATOR",`[${t}] schema node at "${i.path}" has no discriminator.propertyName; cannot dispatch union branch.`);const{propertyName:f,mapping:c}=s,u=a[f];if(u==null)throw new h("E_UNION_NO_DISCRIMINATOR",`[${t}] wire object at "${i.path}" is missing the discriminator property "${f}".`);const d=String(u),p=c[d];if(!p)throw new h("E_UNION_UNKNOWN_TAG",`[${t}] discriminator tag "${d}" on the wire at "${i.path}" is not in the mapping (known: ${Object.keys(c).join(", ")}).`);const w=i.resolve(p);return nt(n,w,{...i,path:`${i.path}[${d}]`})}}}const ot="x-apigen-instances";class O extends Error{constructor(t,r){super(r),this.name="NominalCodecError",this.code=t}}function Q(e){const t=e.properties;return t&&typeof t=="object"&&!Array.isArray(t)?t:{}}function it(e){const t=e.required;return Array.isArray(t)?t.filter(r=>typeof r=="string"):[]}function X(e,t,r){if(t){const n=r.registry.resolve(t);if(n)return n.encode(e,t,r)}return e}function st(e,t,r){if(t){const n=r.registry.resolve(t);if(n)return n.decode(e,t,r)}return e}function at(e){const{id:t,schema:r,ctor:n}=e;return{id:t,kind:"nominal",schema:r,matches(o){return o[L]==="nominal"?!0:o[U]===t},encode(o,i,a){if(o===null||typeof o!="object")return o;if(a.seen.has(o)){if(a.mode==="strict")throw new O("E_NOMINAL_CYCLE",`[${t}] cycle detected at "${a.path}": a nominal instance references itself. Strict mode rejects cycles (DESIGN §8.3); break the cycle or use 'lossy' mode.`);return null}a.seen.add(o);try{const s=Q(i),f=typeof i[x]=="string"?i[x]:"toJSON",c=o[f];if(typeof c=="function"){const l=c.call(o);if(l!==null&&typeof l=="object"&&!Array.isArray(l)){const y={};for(const[m,A]of Object.entries(l))y[m]=X(A,s[m],{...a,path:`${a.path}/${m}`});return y}return l}const u={},d=Object.keys(s),p=o,w=d.length>0?d:Object.keys(p);for(const l of w){const y=p[l];y!==void 0&&(u[l]=X(y,s[l],{...a,path:`${a.path}/${l}`}))}return u}finally{a.seen.delete(o)}},decode(o,i,a){if(o===null||typeof o!="object"||Array.isArray(o)){let u;throw o===null?u="null":Array.isArray(o)?u="array":u=typeof o,new O("E_NOMINAL_INVALID_WIRE",`[${t}] expected a JSON object on the wire at "${a.path}", got ${u}.`)}const s=o;for(const u of it(i))if(!(u in s))throw new O("E_NOMINAL_INVALID_WIRE",`[${t}] required field "${u}" missing on the wire at "${a.path}".`);if(i[ot]===!1)throw new O("E_NOMINAL_NONRECONSTRUCTABLE",`[${t}] is encode-only: the extractor marked it non-reconstructable (x-apigen-instances:false). It cannot be decoded back to a live instance.`);const f=Q(i),c={};for(const[u,d]of Object.entries(s))c[u]=st(d,f[u],{...a,path:`${a.path}/${u}`});if(n){const u=typeof i[k]=="string"?i[k]:"fromJSON",d=n[u];if(typeof d=="function")return d.call(n,c);const p=n;return new p(c)}return c}}}const me=[P,R,q,B,W,F],ct={type:"object","x-apigen-logical":"nominal","x-apigen-codec":"ts.NominalSentinel"},Z=at({id:"ts.NominalSentinel",schema:ct}),ut={oneOf:[],discriminator:{propertyName:"kind",mapping:{}},"x-apigen-logical":"union","x-apigen-codec":"ts.UnionSentinel"},ee=he({id:"ts.UnionSentinel",schema:ut});function ft(){const e=[...me.map(t=>[t.id,t]),[Z.id,Z],[ee.id,ee]];return Object.freeze(new Map(e))}const dt=Object.freeze({host:"ts",logicalTypeVersion:ve,codecs:ft()});function pt(e,t,r){var i;const n=typeof((i=t==null?void 0:t.input)==null?void 0:i.description)=="string"?t.input.description:void 0,o=[r,n].filter(a=>typeof a=="string"&&a.length>0);return o.length>0?o.join(" — "):e}function lt(e){if(!e||typeof e!="object"||Array.isArray(e)||Object.keys(e).length===0)return{outputSchema:void 0,wrapped:!1};const t=e;return t.type==="object"?{outputSchema:t,wrapped:!1}:{outputSchema:{type:"object",properties:{result:t},required:["result"]},wrapped:!0}}function yt(e,t){return e?{result:t}:t&&typeof t=="object"&&!Array.isArray(t)?t:void 0}exports.EventBus=ae;exports.InstanceRegistry=Qe;exports.LayerContext=Ie;exports.UnionCodecError=h;exports.ValidateSchemasToken=le;exports.WELL_KNOWN_TS_CODECS=me;exports.assertNoSelfSubscription=fe;exports.buildContext=ue;exports.buildFnTable=Ke;exports.buildMcpOutputSchema=lt;exports.buildToolDescription=pt;exports.coerceQueryParams=ze;exports.collectWithPhase=et;exports.createApiPackage=qe;exports.createInvoker=ke;exports.createLogger=Be;exports.createStream=Xe;exports.createUnionCodec=he;exports.dataParamNames=ie;exports.defineMiddleware=xe;exports.describeParams=We;exports.dispatch=se;exports.drainStream=Ze;exports.isApiStream=tt;exports.makeValidateLayer=Ge;exports.needsEnvelopeField=oe;exports.tsHostBinding=dt;exports.validateLayer=He;exports.wireObservers=ce;exports.wrapMcpStructuredContent=yt;