theokit 0.12.0 → 0.13.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/dist/{actions-virtual-module-SQDY3V5X.js → actions-virtual-module-3CDQTWOC.js} +6 -6
- package/dist/{actions-virtual-module-PNPRCEOS.js → actions-virtual-module-EIPXX4ZB.js} +3 -3
- package/dist/adapters/web-shim.d.ts +67 -0
- package/dist/adapters/ws-shim.d.ts +55 -0
- package/dist/agent-events-DosDXkSV.d.ts +94 -0
- package/dist/agents-typed-client-SAWAAH7K.js +142 -0
- package/dist/agents-typed-client-SAWAAH7K.js.map +1 -0
- package/dist/agents-typed-client-UTEQUA63.js +143 -0
- package/dist/agents-typed-client-UTEQUA63.js.map +1 -0
- package/dist/{app-typed-client-5GYEOYP3.js → app-typed-client-7PBFWZUE.js} +3 -3
- package/dist/{app-typed-client-QG7BVZYW.js → app-typed-client-CSOK7NPC.js} +6 -6
- package/dist/audit-log-BQWM5YLG.d.ts +60 -0
- package/dist/body-parser-web-FV5HWCY3.js +71 -0
- package/dist/body-parser-web-FV5HWCY3.js.map +1 -0
- package/dist/boot/index.d.ts +39 -0
- package/dist/{build-QFRLSEZ4.js → build-HXND27XG.js} +11 -11
- package/dist/{chunk-223EFY5X.js → chunk-2J7XU3PW.js} +68 -27
- package/dist/chunk-2J7XU3PW.js.map +1 -0
- package/dist/{chunk-RESN62GB.js → chunk-2KZQPDYR.js} +5 -48
- package/dist/chunk-2KZQPDYR.js.map +1 -0
- package/dist/chunk-3S3BNW5K.js +445 -0
- package/dist/chunk-3S3BNW5K.js.map +1 -0
- package/dist/{chunk-6FYD34NX.js → chunk-BQDGES7C.js} +28 -28
- package/dist/{chunk-6FYD34NX.js.map → chunk-BQDGES7C.js.map} +1 -1
- package/dist/chunk-EXP56GFQ.js +52 -0
- package/dist/chunk-EXP56GFQ.js.map +1 -0
- package/dist/chunk-F4YUPDJ2.js +115 -0
- package/dist/chunk-F4YUPDJ2.js.map +1 -0
- package/dist/{chunk-NAZ4E2GT.js → chunk-KXA37ONC.js} +2 -2
- package/dist/chunk-NHJMZCAS.js +32 -0
- package/dist/chunk-NHJMZCAS.js.map +1 -0
- package/dist/{chunk-43D6XNDR.js → chunk-O62MW4MT.js} +91 -18
- package/dist/chunk-O62MW4MT.js.map +1 -0
- package/dist/chunk-RSVN727G.js +1 -0
- package/dist/{chunk-7CBRKNQA.js → chunk-RYTZYFSD.js} +198 -6
- package/dist/chunk-RYTZYFSD.js.map +1 -0
- package/dist/chunk-UNLA45FY.js +235 -0
- package/dist/chunk-UNLA45FY.js.map +1 -0
- package/dist/{chunk-GFMQJHXX.js → chunk-WR4F4EEZ.js} +1082 -1074
- package/dist/chunk-WR4F4EEZ.js.map +1 -0
- package/dist/{chunk-AD74EAK3.js → chunk-ZSTZXR2D.js} +1 -30
- package/dist/chunk-ZSTZXR2D.js.map +1 -0
- package/dist/cli/index.js +5 -5
- package/dist/client/index.d.ts +418 -0
- package/dist/client/index.js +84 -3
- package/dist/client/index.js.map +1 -1
- package/dist/csrf-BBrEZSBW.d.ts +107 -0
- package/dist/csrf-readiness-store-CjIoub3U.d.ts +43 -0
- package/dist/define-websocket-CdK94O-D.d.ts +64 -0
- package/dist/{dev-GBXOTXUP.js → dev-OWW4XVIH.js} +10 -10
- package/dist/{dev-emit-FEFEDLZF.js → dev-emit-5MDSBP5D.js} +3 -3
- package/dist/{dev-emit-O4EGOSNV.js → dev-emit-QH2YGZXN.js} +2 -2
- package/dist/devtools/entry.d.ts +5 -0
- package/dist/error-envelope-BsNzzAV5.d.ts +62 -0
- package/dist/health-route-C0hk64_U.d.ts +57 -0
- package/dist/index-B40qUSrQ.d.ts +575 -0
- package/dist/index.d.ts +361 -0
- package/dist/index.js +6 -4
- package/dist/index.js.map +1 -1
- package/dist/internal-api-4YTJDITC.js +83 -0
- package/dist/internal-api-EFKZWIYZ.js +66 -0
- package/dist/internal-api-EFKZWIYZ.js.map +1 -0
- package/dist/job-backend-CgC8Xf33.d.ts +68 -0
- package/dist/match-CfbEFRG4.d.ts +26 -0
- package/dist/{openapi-VR6AFBLJ.js → openapi-FHY6HC6I.js} +7 -7
- package/dist/plugin-runner-BGBkzgi0.d.ts +95 -0
- package/dist/plugin-types-DNJGxr4Z.d.ts +79 -0
- package/dist/rate-limit-BdNDZ3vt.d.ts +58 -0
- package/dist/rate-limit-store-BEJnhWdw.d.ts +72 -0
- package/dist/react-query/index.d.ts +33 -0
- package/dist/{registry-Q2TZQLUH.js → registry-34LL7NF4.js} +1 -1
- package/dist/{routes-LRYOIIAI.js → routes-EW7TP7NJ.js} +2 -2
- package/dist/schema-BpH6ivDY.d.ts +74 -0
- package/dist/server/agent/index.d.ts +229 -0
- package/dist/server/agent/index.js +2 -1
- package/dist/server/auth/index.d.ts +419 -0
- package/dist/server/cost/index.d.ts +177 -0
- package/dist/server/cron/index.d.ts +208 -0
- package/dist/server/define/index.d.ts +313 -0
- package/dist/server/define/index.js +4 -2
- package/dist/server/http/index.d.ts +11 -0
- package/dist/server/index.d.ts +848 -0
- package/dist/server/index.js +9 -294
- package/dist/server/index.js.map +1 -1
- package/dist/server/jobs/index.d.ts +348 -0
- package/dist/server/observability/index.d.ts +324 -0
- package/dist/server/plugins/index.d.ts +17 -0
- package/dist/server/rate-limit/index.d.ts +105 -0
- package/dist/server/realtime/index.d.ts +15 -0
- package/dist/server/scan/index.d.ts +126 -0
- package/dist/server/scan/index.js +1 -1
- package/dist/server/security/index.d.ts +193 -0
- package/dist/server/storage/index.d.ts +22 -0
- package/dist/server/webhook/index.d.ts +148 -0
- package/dist/{start-3ZHAXSJE.js → start-KIQ5TTLR.js} +76 -13
- package/dist/start-KIQ5TTLR.js.map +1 -0
- package/dist/storage-manager-C4jsO0Tp.d.ts +89 -0
- package/dist/storage-types-DsDTCPbp.d.ts +96 -0
- package/dist/vite-plugin/index.d.ts +115 -0
- package/dist/vite-plugin/index.js +6 -4
- package/dist/{vite-plugin-WO72VLYR.js → vite-plugin-RK66K26Z.js} +7 -7
- package/dist/vite-plugin-RK66K26Z.js.map +1 -0
- package/package.json +4 -4
- package/dist/chunk-223EFY5X.js.map +0 -1
- package/dist/chunk-3LVRAGAZ.js +0 -73
- package/dist/chunk-3LVRAGAZ.js.map +0 -1
- package/dist/chunk-43D6XNDR.js.map +0 -1
- package/dist/chunk-7CBRKNQA.js.map +0 -1
- package/dist/chunk-AD74EAK3.js.map +0 -1
- package/dist/chunk-GFMQJHXX.js.map +0 -1
- package/dist/chunk-PBEH6NXR.js +0 -44
- package/dist/chunk-PBEH6NXR.js.map +0 -1
- package/dist/chunk-PIVX3DYW.js +0 -142
- package/dist/chunk-PIVX3DYW.js.map +0 -1
- package/dist/chunk-PPPR5DGR.js +0 -1
- package/dist/chunk-RESN62GB.js.map +0 -1
- package/dist/start-3ZHAXSJE.js.map +0 -1
- /package/dist/{actions-virtual-module-SQDY3V5X.js.map → actions-virtual-module-3CDQTWOC.js.map} +0 -0
- /package/dist/{actions-virtual-module-PNPRCEOS.js.map → actions-virtual-module-EIPXX4ZB.js.map} +0 -0
- /package/dist/{app-typed-client-5GYEOYP3.js.map → app-typed-client-7PBFWZUE.js.map} +0 -0
- /package/dist/{app-typed-client-QG7BVZYW.js.map → app-typed-client-CSOK7NPC.js.map} +0 -0
- /package/dist/{build-QFRLSEZ4.js.map → build-HXND27XG.js.map} +0 -0
- /package/dist/{chunk-NAZ4E2GT.js.map → chunk-KXA37ONC.js.map} +0 -0
- /package/dist/{chunk-PPPR5DGR.js.map → chunk-RSVN727G.js.map} +0 -0
- /package/dist/{dev-GBXOTXUP.js.map → dev-OWW4XVIH.js.map} +0 -0
- /package/dist/{dev-emit-FEFEDLZF.js.map → dev-emit-5MDSBP5D.js.map} +0 -0
- /package/dist/{dev-emit-O4EGOSNV.js.map → dev-emit-QH2YGZXN.js.map} +0 -0
- /package/dist/{vite-plugin-WO72VLYR.js.map → internal-api-4YTJDITC.js.map} +0 -0
- /package/dist/{openapi-VR6AFBLJ.js.map → openapi-FHY6HC6I.js.map} +0 -0
- /package/dist/{registry-Q2TZQLUH.js.map → registry-34LL7NF4.js.map} +0 -0
- /package/dist/{routes-LRYOIIAI.js.map → routes-EW7TP7NJ.js.map} +0 -0
package/dist/client/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/client/theo-fetch.ts","../../src/client/batch.ts","../../src/client/batch-transport.ts","../../src/client/app-client.ts","../../src/client/use-agent-stream.ts","../../src/client/agent-stream-core.ts","../../src/client/agent-tool-cards.ts","../../src/client/use-agent-tool-cards.ts","../../src/client/link.tsx","../../src/client/metadata.tsx","../../src/client/image.tsx"],"sourcesContent":["import superjson from 'superjson'\nimport type { z } from 'zod'\n\nimport type { TheoErrorCode, TheoErrorEnvelope } from '../core/contracts/error-envelope.js'\n\nimport { getGlobalBatcher } from './batch-transport.js'\n\n// --- Transformer (T1.3) ---\n\n/**\n * Module-scoped flag preventing the transformer-mismatch warning from\n * firing more than once per session (EC-6).\n */\nlet mismatchWarned = false\n\n/** Test-only helper to reset the warned flag between assertions. */\nexport function __resetMismatchWarningForTests(): void {\n mismatchWarned = false\n}\n\n/**\n * Deserialize a fetch response body according to the negotiated transformer.\n *\n * `serverTransformerName` comes from the `x-theo-transformer` response header\n * (null when absent — server is using the default JSON path).\n * `clientTransformerName` is the transformer the client was built with\n * (typically injected via a Vite virtual module; falls back to `'json'`).\n *\n * Mismatch fires a single console.warn and falls back to JSON.parse (EC-5/EC-6).\n */\nexport function deserializeFetchResponse(\n raw: string,\n serverTransformerName: string | null,\n clientTransformerName: string,\n): unknown {\n // `raw` is typed `string`, but stay defensive: callers pass `await response.text()`\n // which can be empty.\n if (raw === '') {\n return null\n }\n\n const serverEffective = serverTransformerName ?? 'json'\n if (serverEffective !== clientTransformerName && !mismatchWarned) {\n mismatchWarned = true\n console.warn(\n `[theokit] transformer mismatch: server=${serverEffective}, client=${clientTransformerName}. Falling back to JSON.parse.`,\n )\n }\n\n if (serverEffective === 'superjson' && clientTransformerName === 'superjson') {\n const wrapped = JSON.parse(raw) as Parameters<typeof superjson.deserialize>[0]\n return superjson.deserialize(wrapped)\n }\n\n // Default path (json) or mismatch fallback\n return JSON.parse(raw)\n}\n\n// --- Utility Types ---\n\n/** Infer the response type from a route's handler return */\nexport type InferResponse<T> = T extends { handler: (...args: never[]) => infer R }\n ? Awaited<R>\n : unknown\n\n/** Extract the query Zod schema type, handling optional properties */\ntype ExtractQuery<T> = T extends { query?: infer Q } ? (Q extends z.ZodType ? Q : never) : never\n\n/** Extract the body Zod schema type, handling optional properties */\ntype ExtractBody<T> = T extends { body?: infer B } ? (B extends z.ZodType ? B : never) : never\n\n/** Infer query type from a route's query Zod schema */\nexport type InferQuery<T> = [ExtractQuery<T>] extends [never]\n ? undefined\n : ExtractQuery<T> extends z.ZodUndefined\n ? undefined\n : z.infer<ExtractQuery<T>>\n\n/** Infer body type from a route's body Zod schema */\nexport type InferBody<T> = [ExtractBody<T>] extends [never]\n ? undefined\n : ExtractBody<T> extends z.ZodUndefined\n ? undefined\n : z.infer<ExtractBody<T>>\n\n/** Build the options type based on what schemas the route has */\nexport type TheoFetchOptions<T> = Omit<RequestInit, 'body' | 'method'> &\n (InferQuery<T> extends undefined ? { query?: never } : { query: InferQuery<T> }) &\n (InferBody<T> extends undefined ? { body?: never } : { body: InferBody<T> })\n\n// --- Error Class ---\n\n/**\n * G5 T2.1 — extract a TheoErrorEnvelope from a response body. Supports both\n * the new envelope-at-root shape (`{ code, message, ext?, ... }`, blueprint\n * Recommendations § concrete shape) and the legacy nested shape\n * (`{ error: { code, message, issues? } }`, G3 SerializedActionResult).\n *\n * Falls back to `INTERNAL_SERVER_ERROR` with a synthetic message when the\n * body shape is unrecognized. Pure; no I/O.\n */\nfunction extractEnvelope(status: number, body: unknown): TheoErrorEnvelope {\n if (!body || typeof body !== 'object') {\n return { code: 'INTERNAL_SERVER_ERROR', message: `HTTP ${String(status)}` }\n }\n const obj = body as Record<string, unknown>\n // New shape — envelope at root\n if (typeof obj.code === 'string' && typeof obj.message === 'string') {\n return {\n code: obj.code as TheoErrorCode,\n message: obj.message,\n cause: obj.cause,\n meta: obj.meta as Record<string, unknown> | undefined,\n ext: obj.ext,\n }\n }\n // Legacy shape — { error: { code, message, ... } }\n if (obj.error && typeof obj.error === 'object') {\n const nested = obj.error as Record<string, unknown>\n return {\n code:\n typeof nested.code === 'string' ? (nested.code as TheoErrorCode) : 'INTERNAL_SERVER_ERROR',\n message: typeof nested.message === 'string' ? nested.message : `HTTP ${String(status)}`,\n }\n }\n return { code: 'INTERNAL_SERVER_ERROR', message: `HTTP ${String(status)}` }\n}\n\n/**\n * Pull a single string field from an object, returning undefined if missing\n * or non-string. Helper for `extractLegacyFields` to stay under the\n * complexity ceiling.\n */\nfunction strField(obj: Record<string, unknown> | null, key: string): string | undefined {\n const v = obj?.[key]\n return typeof v === 'string' ? v : undefined\n}\n\n/**\n * Pull the canonical {message, code, issues} from either an envelope-at-root\n * body or the legacy { error: {...} } body. Pure.\n */\nfunction extractLegacyFields(\n status: number,\n body: unknown,\n): { message: string; code?: string; issues?: unknown[] } {\n if (!body || typeof body !== 'object') {\n return { message: `HTTP ${String(status)}` }\n }\n const obj = body as Record<string, unknown>\n const nested =\n obj.error && typeof obj.error === 'object' ? (obj.error as Record<string, unknown>) : null\n const issues = Array.isArray(nested?.issues) ? nested.issues : undefined\n return {\n message: strField(obj, 'message') ?? strField(nested, 'message') ?? `HTTP ${String(status)}`,\n code: strField(obj, 'code') ?? strField(nested, 'code'),\n issues,\n }\n}\n\nexport class TheoFetchError extends Error {\n status: number\n code?: string\n issues?: unknown[]\n /**\n * G5 T2.1 — canonical envelope view of the server-side error. Use this in\n * consumer code that wants to switch on a typed TheoErrorCode instead of\n * coupling to the legacy `.status` / `.code` flat fields.\n */\n readonly envelope: TheoErrorEnvelope\n\n constructor(status: number, body?: unknown) {\n const legacy = extractLegacyFields(status, body)\n super(legacy.message)\n this.name = 'TheoFetchError'\n this.status = status\n this.code = legacy.code\n this.issues = legacy.issues\n this.envelope = extractEnvelope(status, body)\n }\n}\n\n/**\n * Serialize a query-param value to a string. Handles primitives, dates,\n * and falls back to JSON for arrays/objects. Avoids the\n * `[object Object]` foot-gun that `no-base-to-string` warns against.\n */\nfunction stringifyQueryValue(value: unknown): string {\n if (value === null) return 'null'\n if (value instanceof Date) return value.toISOString()\n switch (typeof value) {\n case 'string':\n return value\n case 'number':\n case 'boolean':\n case 'bigint':\n return String(value)\n default:\n return JSON.stringify(value)\n }\n}\n\n// --- Main Function ---\n\ninterface TheoFetchInternalOptions {\n method?: string\n query?: Record<string, unknown>\n body?: unknown\n headers?: HeadersInit\n signal?: AbortSignal\n}\n\n/**\n * Resolve the request origin per the documented fallback hierarchy. Pure\n * helper extracted to keep `theoFetch` under the complexity ceiling.\n * 1. `globalThis.location.origin` (browser)\n * 2. `globalThis.__THEO_ORIGIN__` (build-time literal)\n * 3. `process.env.THEO_ORIGIN` (escape hatch)\n * 4. `http://localhost` (placeholder for URL parsing — the URL is built\n * relative so only pathname+search ever flows to the wire)\n */\nfunction resolveRequestOrigin(): string {\n const g = globalThis as { location?: { origin?: string }; __THEO_ORIGIN__?: string }\n const fromEnv = typeof process !== 'undefined' ? process.env.THEO_ORIGIN : undefined\n return g.location?.origin ?? g.__THEO_ORIGIN__ ?? fromEnv ?? 'http://localhost'\n}\n\nfunction buildFetchUrl(path: string, query: Record<string, unknown> | undefined): URL {\n const fetchUrl = new URL(path, resolveRequestOrigin())\n if (!query) return fetchUrl\n for (const [k, v] of Object.entries(query)) {\n if (v !== undefined) {\n fetchUrl.searchParams.set(k, stringifyQueryValue(v))\n }\n }\n return fetchUrl\n}\n\n/**\n * Normalize `HeadersInit` (Headers / `[string, string][]` / Record) into a\n * single plain `Record<string, string>`. Plain-object output is required\n * by callers that introspect headers via index access (test fixtures use\n * `(init.headers as Record<string, string>)['Content-Type']`).\n */\nfunction normalizeHeaders(input: HeadersInit | undefined): Record<string, string> {\n const out: Record<string, string> = {}\n if (!input) return out\n if (input instanceof Headers) {\n input.forEach((value, key) => {\n out[key] = value\n })\n return out\n }\n if (Array.isArray(input)) {\n for (const [key, value] of input) out[key] = value\n return out\n }\n for (const [key, value] of Object.entries(input)) {\n out[key] = value\n }\n return out\n}\n\nfunction buildRequestInit(opts: TheoFetchInternalOptions): RequestInit {\n const init: RequestInit = {}\n if (opts.method !== undefined) init.method = opts.method\n if (opts.signal !== undefined) init.signal = opts.signal\n\n const headers = normalizeHeaders(opts.headers)\n init.headers = headers\n\n if (opts.body !== undefined) {\n init.body = JSON.stringify(opts.body)\n headers['Content-Type'] = 'application/json'\n }\n\n // Phase 5 — Auto-attach `X-Theo-Action: 1` for state-mutating methods so\n // the framework's CSRF check passes when servers run in `strict` mode.\n // Safe methods (GET/HEAD/OPTIONS) skip the header to keep them cacheable.\n const method = (opts.method ?? 'GET').toUpperCase()\n if (method !== 'GET' && method !== 'HEAD' && method !== 'OPTIONS') {\n headers['X-Theo-Action'] = '1'\n }\n return init\n}\n\nasync function tryBatcher(\n url: string,\n options: TheoFetchInternalOptions,\n): Promise<{ matched: true; result: unknown } | { matched: false }> {\n const batcher = getGlobalBatcher()\n if (!batcher) return { matched: false }\n try {\n const result = await batcher.dispatch({\n path: url,\n method: options.method ?? 'GET',\n query: options.query,\n body: options.body,\n })\n return { matched: true, result }\n } catch {\n // Batcher failure: fall through to direct fetch (graceful degrade).\n return { matched: false }\n }\n}\n\nexport async function theoFetch<T>(\n url: string,\n options?: TheoFetchOptions<T>,\n): Promise<InferResponse<T>> {\n const internal = (options ?? {}) as unknown as TheoFetchInternalOptions\n\n // T1.5 — Transparent batching when globalThis.__THEO_BATCHING__ is truthy.\n const batchAttempt = await tryBatcher(url, internal)\n if (batchAttempt.matched) {\n return batchAttempt.result as InferResponse<T>\n }\n\n const fetchUrl = buildFetchUrl(url, internal.query)\n const init = buildRequestInit(internal)\n const response = await fetch(fetchUrl.toString(), init)\n\n if (!response.ok) {\n let errorBody: unknown\n try {\n errorBody = await response.json()\n } catch {\n // Non-JSON error response\n }\n throw new TheoFetchError(response.status, errorBody)\n }\n\n // Handle 204 No Content (EC-1)\n if (response.status === 204) {\n return null as InferResponse<T>\n }\n\n // Check for empty body\n const contentLength = response.headers.get('content-length')\n if (contentLength === '0') {\n return null as InferResponse<T>\n }\n\n // T1.3 — transformer-aware deserialization\n const serverTransformerName = response.headers.get('x-theo-transformer')\n const clientTransformerName = resolveClientTransformerName()\n const text = await response.text()\n return deserializeFetchResponse(\n text,\n serverTransformerName,\n clientTransformerName,\n ) as InferResponse<T>\n}\n\n/**\n * Read the client-configured transformer name. Default `'json'`.\n *\n * In a Vite build, this is overridden by virtual module\n * `/@theo/runtime-config` which sets `globalThis.__THEO_TRANSFORMER__`.\n * Outside Vite (Node SSR, tests) the default applies.\n */\nfunction resolveClientTransformerName(): string {\n const g = globalThis as { __THEO_TRANSFORMER__?: string }\n return g.__THEO_TRANSFORMER__ ?? 'json'\n}\n","/**\n * T5.1 — client-side microtask batching.\n *\n * Collects all `dispatch` calls within the same microtask and sends them as a\n * single HTTP POST to the configured transport. Each caller's promise resolves\n * with its own result; one failed item does not break the others (per-item\n * error isolation).\n *\n * Designed as a transport-agnostic primitive so unit tests do not require\n * network access. The default transport (fetch to `/api/__theo_batch__`)\n * lives alongside this module but is created by the consumer (e.g., theoFetch).\n */\n\nexport interface BatchRequest {\n path: string\n method: string\n query?: Record<string, unknown>\n body?: unknown\n headers?: Record<string, string>\n}\n\nexport type BatchResponse =\n | { index: number; data: unknown }\n | { index: number; error: { message: string; code?: string } }\n\nexport type BatchTransport = (requests: BatchRequest[]) => Promise<BatchResponse[]>\n\nexport interface BatcherOptions {\n transport: BatchTransport\n /** Maximum batch size before flushing into multiple parallel batches. */\n max?: number\n}\n\nexport interface Batcher {\n dispatch(req: BatchRequest): Promise<unknown>\n}\n\ninterface PendingCall {\n req: BatchRequest\n resolve: (value: unknown) => void\n reject: (reason: unknown) => void\n}\n\nexport function createBatcher(options: BatcherOptions): Batcher {\n const max = options.max ?? 32\n let queue: PendingCall[] = []\n let flushScheduled = false\n\n function flush(): void {\n flushScheduled = false\n const current = queue\n queue = []\n if (current.length === 0) return\n\n // Split into chunks respecting max\n const chunks: PendingCall[][] = []\n for (let i = 0; i < current.length; i += max) {\n chunks.push(current.slice(i, i + max))\n }\n\n for (const chunk of chunks) {\n const payload: BatchRequest[] = chunk.map((p) => p.req)\n options\n .transport(payload)\n .then((results) => {\n for (let i = 0; i < chunk.length; i++) {\n // `results[i]` could be undefined at runtime when the transport\n // returns fewer entries than the chunk; TypeScript's strict\n // typing without `noUncheckedIndexedAccess` does not surface\n // this, so we hand-narrow.\n const result = results.length > i ? results[i] : undefined\n if (result === undefined) {\n chunk[i].reject(new Error(`Batch transport returned no result for index ${i}`))\n continue\n }\n if ('error' in result) {\n const err = new Error(result.error.message)\n ;(err as { code?: string }).code = result.error.code\n chunk[i].reject(err)\n } else {\n chunk[i].resolve(result.data)\n }\n }\n })\n .catch((err: unknown) => {\n for (const item of chunk) item.reject(err)\n })\n }\n }\n\n return {\n dispatch(req: BatchRequest): Promise<unknown> {\n return new Promise<unknown>((resolve, reject) => {\n queue.push({ req, resolve, reject })\n if (!flushScheduled) {\n flushScheduled = true\n queueMicrotask(flush)\n }\n })\n },\n }\n}\n","/**\n * T1.5 — Default HTTP transport for the client batcher.\n *\n * Wraps `fetch` to POST `/api/__theo_batch__` with the collected requests\n * and return the array of per-item results.\n */\n\nimport {\n createBatcher,\n type BatchTransport,\n type Batcher,\n type BatchRequest,\n type BatchResponse,\n} from './batch.js'\n\nconst BATCH_ENDPOINT = '/api/__theo_batch__'\n\nexport interface CreateBatchTransportOptions {\n /** Override fetch (default: globalThis.fetch). Used by tests. */\n fetchImpl?: typeof fetch\n /** Override endpoint (default '/api/__theo_batch__'). */\n endpoint?: string\n}\n\nexport function createBatchTransport(options: CreateBatchTransportOptions = {}): BatchTransport {\n const fetchImpl = options.fetchImpl ?? fetch\n const endpoint = options.endpoint ?? BATCH_ENDPOINT\n return async (requests: BatchRequest[]): Promise<BatchResponse[]> => {\n const response = await fetchImpl(endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ requests }),\n })\n if (!response.ok) {\n throw new Error(`Batch transport returned ${response.status}`)\n }\n const payload = (await response.json()) as { results?: BatchResponse[] }\n if (!Array.isArray(payload.results)) {\n throw new Error('Batch response missing results array')\n }\n // Map results to indexed BatchResponse shape (server already returns the right form)\n return payload.results.map((item, index) => {\n if ('error' in item) {\n return { index, error: (item as { error: { message: string; code?: string } }).error }\n }\n return { index, data: (item as { data: unknown }).data }\n })\n }\n}\n\n// --- EC-7: singleton batcher per page, lazy-instantiated ---\n\nlet globalBatcher: Batcher | undefined\n\n/** Test-only — reset the module-scope singleton between assertions. */\nexport function __resetGlobalBatcherForTests(): void {\n globalBatcher = undefined\n}\n\n/**\n * Returns the global batcher singleton when `globalThis.__THEO_BATCHING__` is\n * truthy; undefined otherwise. Lazy-instantiated on first call.\n */\nexport function getGlobalBatcher(): Batcher | undefined {\n const g = globalThis as { __THEO_BATCHING__?: boolean }\n if (!g.__THEO_BATCHING__) return undefined\n globalBatcher ??= createBatcher({ transport: createBatchTransport() })\n return globalBatcher\n}\n","/**\n * Phase 3 of G1 (g1-client-codegen-plan.md):\n *\n * `createAppClient(baseUrl?, fetchImpl?)` returns a Proxy that walks property\n * access (`client.posts.id.get(...)`) into a `theoFetch` invocation against\n * `{baseUrl}/posts/{params.id}` with method `GET`.\n *\n * Type safety is delivered by the `.d.ts` file emitted in Phase 2 — this\n * runtime is structurally untyped. Power users may use `theoFetch` directly\n * when they need to escape the Proxy facade.\n *\n * Edge cases absorbed:\n * - EC-1 (thenable trap): `then` / `catch` / `finally` / `toJSON` / `Symbol.*`\n * return `undefined` so that accidental `await client.posts` resolves to a\n * plain Proxy value (it is NOT thenable) instead of looping.\n * - EC-7 (abort signal): `opts.signal` is spread through to the underlying\n * fetchImpl unchanged — verified in unit tests.\n *\n * Bundle target: ≤ 2KB gzipped.\n */\n\nimport { theoFetch, TheoFetchError } from './theo-fetch.js'\nimport type { TheoFetchOptions } from './theo-fetch.js'\nimport { HTTP_METHOD_LOWERCASE } from '../core/contracts/http-methods.js'\n\nconst HTTP_METHODS_SET = new Set(HTTP_METHOD_LOWERCASE)\n\n/**\n * Keys that JavaScript runtime / inspectors / Promise resolution probe\n * unconditionally. Returning `undefined` for these keeps the Proxy from\n * pretending to be a thenable / iterable / serializable thing.\n */\nconst NON_INTERCEPT_KEYS = new Set([\n 'then',\n 'catch',\n 'finally',\n 'toJSON',\n 'toString',\n 'valueOf',\n 'constructor',\n 'prototype',\n])\n\ntype FetchImpl = typeof theoFetch\n\ninterface CallOptions {\n params?: Record<string, string | number>\n query?: Record<string, unknown>\n body?: unknown\n signal?: AbortSignal\n headers?: HeadersInit\n // arbitrary RequestInit fields (mode, credentials, cache, etc.)\n [k: string]: unknown\n}\n\nfunction injectParams(path: string, params?: Record<string, string | number>): string {\n if (!params) {\n if (/:(?:\\.\\.\\.)?[A-Za-z_]/.test(path)) {\n throw new TheoFetchError(0, {\n error: {\n code: 'MISSING_PARAM',\n message: `Route ${path} requires params but none were provided. Pass them via opts.params, e.g. client.posts.get({ params: { id: '123' } }).`,\n },\n })\n }\n return path\n }\n return path.replace(/:(?:\\.\\.\\.)?([A-Za-z_][A-Za-z0-9_]*)/g, (_match, key: string) => {\n const value = params[key]\n if (value === undefined || value === null || value === '') {\n throw new TheoFetchError(0, {\n error: {\n code: 'MISSING_PARAM',\n message: `Param '${key}' is required for path '${path}' but was missing/empty.`,\n },\n })\n }\n return encodeURIComponent(String(value))\n })\n}\n\ninterface ProxyContext {\n segments: string[]\n baseUrl: string\n fetchImpl: FetchImpl\n}\n\nfunction makeProxy(ctx: ProxyContext): unknown {\n const handler: ProxyHandler<() => void> = {\n get(_target, key) {\n if (typeof key !== 'string') return undefined\n if (NON_INTERCEPT_KEYS.has(key)) return undefined\n if (HTTP_METHODS_SET.has(key)) {\n return async (opts?: CallOptions) => {\n if (ctx.segments.length === 0) {\n throw new TheoFetchError(0, {\n error: {\n code: 'INVALID_PATH',\n message: `client.${key}() called without a route segment. Use client.<resource>.${key}(...) instead.`,\n },\n })\n }\n let finalPath = `${ctx.baseUrl}/${ctx.segments.join('/')}`\n if (opts?.params) {\n // Build a path with `:name` placeholders re-inserted from segments\n // whose name matches a key in opts.params (treat as dynamic).\n const segmentsWithDynamic = ctx.segments.map((seg) =>\n Object.prototype.hasOwnProperty.call(opts.params, seg) ? `:${seg}` : seg,\n )\n finalPath = injectParams(\n `${ctx.baseUrl}/${segmentsWithDynamic.join('/')}`,\n opts.params,\n )\n }\n const { params: _ignored, ...rest } = opts ?? {}\n const init = { method: key.toUpperCase(), ...rest } as unknown as TheoFetchOptions<unknown>\n return ctx.fetchImpl(finalPath, init)\n }\n }\n // Continue traversal — append segment to the path.\n return makeProxy({ ...ctx, segments: [...ctx.segments, key] })\n },\n apply() {\n return Promise.reject(\n new TheoFetchError(0, {\n error: {\n code: 'INVALID_CALL',\n message:\n 'client(...) is not callable. Use client.<resource>.<method>(opts?) — e.g. client.posts.get().',\n },\n }),\n )\n },\n }\n return new Proxy(() => undefined, handler)\n}\n\nexport interface CreateAppClientOptions {\n /** Base URL for the API. Defaults to `/api`. */\n baseUrl?: string\n /** Test-only fetch override. Production callers should not pass this. */\n fetchImpl?: FetchImpl\n}\n\nexport function createAppClient<TAppClient = unknown>(\n baseUrlOrOptions?: string | CreateAppClientOptions,\n legacyFetchImpl?: FetchImpl,\n): TAppClient {\n let baseUrl = '/api'\n let fetchImpl: FetchImpl = theoFetch\n if (typeof baseUrlOrOptions === 'string') {\n baseUrl = baseUrlOrOptions || '/api'\n } else if (baseUrlOrOptions && typeof baseUrlOrOptions === 'object') {\n if (baseUrlOrOptions.baseUrl) baseUrl = baseUrlOrOptions.baseUrl\n if (baseUrlOrOptions.fetchImpl) fetchImpl = baseUrlOrOptions.fetchImpl\n }\n // Legacy 2nd-arg fetchImpl overrides regardless of 1st-arg shape (test seam).\n if (legacyFetchImpl) fetchImpl = legacyFetchImpl\n // Strip trailing slash for predictable joining.\n if (baseUrl.length > 1 && baseUrl.endsWith('/')) baseUrl = baseUrl.slice(0, -1)\n return makeProxy({ segments: [], baseUrl, fetchImpl }) as TAppClient\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react'\n\nimport type { AgentErrorEvent, AgentEvent } from '../core/contracts/agent-events.js'\n\nimport { consumeAgentStream } from './agent-stream-core.js'\n\n/**\n * Accumulated assistant text (M5-1): the concatenation of every `message`\n * event's `content`. Pure. Assumes append/delta semantics — a server that\n * emits full-snapshot messages should read `events` directly.\n */\nexport function deriveLiveText(events: readonly AgentEvent[]): string {\n let text = ''\n for (const event of events) {\n if (event.type === 'message') text += event.content\n }\n return text\n}\n\n/**\n * The current error (M5-1): the last `error` event, or `undefined`. Surfaces\n * the full `AgentErrorEvent` (with `code`/`retriable`) so the UI can branch.\n * Pure.\n */\nexport function deriveError(events: readonly AgentEvent[]): AgentErrorEvent | undefined {\n let last: AgentErrorEvent | undefined\n for (const event of events) {\n if (event.type === 'error') last = event\n }\n return last\n}\n\n/**\n * T5.2 — useAgentStream\n *\n * React hook to consume an agent endpoint defined with `defineAgentEndpoint`.\n *\n * Transport (ADR D7, EC-3): fetch + ReadableStream — NOT EventSource.\n * EventSource is GET-only; agent endpoints need POST + body.\n *\n * Returns:\n * events — array of AgentEvents accumulated so far\n * send — call with a payload to (re)open a stream\n * status — 'idle' | 'streaming' | 'done' | 'error'\n * abort — manually cancel an in-flight stream\n *\n * Cleanup (EC-8): on unmount, the current AbortController fires .abort(),\n * which propagates to the underlying fetch and the ReadableStream reader.\n * Safe under React.StrictMode double-mount.\n */\n\nexport type AgentStreamStatus = 'idle' | 'streaming' | 'done' | 'error'\n\nexport interface UseAgentStreamReturn<TBody = unknown> {\n events: AgentEvent[]\n status: AgentStreamStatus\n /** Accumulated assistant text — concatenation of all `message` contents (M5-1). */\n liveText: string\n /** The last `error` event, or `undefined` (M5-1). */\n error: AgentErrorEvent | undefined\n send: (body: TBody) => void\n abort: () => void\n reset: () => void\n}\n\nexport interface UseAgentStreamOptions {\n /** Extra headers (e.g., auth). */\n headers?: Record<string, string>\n /** Override fetch (rare — primarily for tests). */\n fetch?: typeof fetch\n}\n\nexport function useAgentStream<TBody = unknown>(\n path: string,\n options: UseAgentStreamOptions = {},\n): UseAgentStreamReturn<TBody> {\n const [events, setEvents] = useState<AgentEvent[]>([])\n const [status, setStatus] = useState<AgentStreamStatus>('idle')\n const controllerRef = useRef<AbortController | null>(null)\n\n const abort = useCallback(() => {\n if (controllerRef.current) {\n controllerRef.current.abort()\n controllerRef.current = null\n }\n }, [])\n\n const reset = useCallback(() => {\n abort()\n setEvents([])\n setStatus('idle')\n }, [abort])\n\n const send = useCallback(\n (body: TBody) => {\n // Cancel any in-flight stream first.\n abort()\n const controller = new AbortController()\n controllerRef.current = controller\n setStatus('streaming')\n\n let sawError = false\n consumeAgentStream<TBody>(path, {\n body,\n fetch: options.fetch,\n headers: options.headers,\n signal: controller.signal,\n onEvent: (event) => {\n if (event.type === 'error') sawError = true\n setEvents((prev) => [...prev, event])\n },\n })\n .then(() => {\n if (controllerRef.current !== controller) return // superseded\n setStatus(sawError ? 'error' : 'done')\n })\n .catch(() => {\n if (controllerRef.current !== controller) return // superseded / aborted\n if (controller.signal.aborted) return\n setStatus('error')\n })\n },\n [abort, path, options.fetch, options.headers],\n )\n\n // EC-8: cleanup on unmount aborts in-flight stream.\n useEffect(() => {\n return () => {\n if (controllerRef.current) {\n controllerRef.current.abort()\n controllerRef.current = null\n }\n }\n }, [])\n\n // M5-1: derived views over the accumulated events.\n const liveText = useMemo(() => deriveLiveText(events), [events])\n const error = useMemo(() => deriveError(events), [events])\n\n return { events, status, liveText, error, send, abort, reset }\n}\n","import type { AgentEvent } from '../core/contracts/agent-events.js'\n\n/**\n * T5.2 — Pure SSE consumer used by useAgentStream.\n *\n * Split out from the React hook so the wire behavior can be tested\n * without a DOM. The hook is glue: useState + useEffect + this primitive.\n *\n * Transport (ADR D7, EC-3): fetch + ReadableStream — NOT EventSource.\n * EventSource is GET-only and cannot carry a body. Agent endpoints need\n * POST + JSON body, so we use fetch + manual SSE chunk parsing.\n */\n\nexport interface ConsumeOptions<TBody = unknown> {\n /** Request body — JSON-serialized into the POST. */\n body: TBody\n /** Called once per SSE event parsed off the stream. */\n onEvent: (event: AgentEvent) => void\n /** Optional fetch override (tests). */\n fetch?: typeof fetch\n /** Optional abort signal — passed through to fetch. */\n signal?: AbortSignal\n /** Extra headers (e.g., auth). */\n headers?: Record<string, string>\n}\n\n/**\n * Dispatch SSE events from a list of `\\n\\n`-separated chunk parts.\n * Extracted to keep the streaming loop under the max-depth ceiling.\n */\nfunction dispatchSseParts(parts: string[], onEvent: (event: AgentEvent) => void): void {\n for (const part of parts) {\n // A chunk may contain multiple lines; keep only the data: line.\n for (const line of part.split('\\n')) {\n const evt = parseSSEChunk(line)\n if (evt) onEvent(evt)\n }\n }\n}\n\n/**\n * Parse a single SSE line of the form `data: <json>`.\n * Returns null for non-data lines, comments, or malformed JSON.\n */\nexport function parseSSEChunk(line: string): AgentEvent | null {\n if (!line.startsWith('data:')) return null\n const raw = line.slice(5).trim()\n if (!raw) return null\n try {\n return JSON.parse(raw) as AgentEvent\n } catch {\n return null\n }\n}\n\n/**\n * POSTs to `path` with `body`, reads the SSE response, and invokes\n * `onEvent` for each parsed AgentEvent. Resolves when the server\n * closes the stream or the signal aborts.\n *\n * T1.1 — Attaches `X-Theo-Action: '1'` so 0.3.0 strict CSRF mode accepts\n * the request. The user can override (or suppress) by passing the header\n * in `options.headers` — spread order ensures their value wins.\n */\nexport async function consumeAgentStream<TBody = unknown>(\n path: string,\n options: ConsumeOptions<TBody>,\n): Promise<void> {\n const fetchImpl = options.fetch ?? globalThis.fetch\n const response = await fetchImpl(path, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n accept: 'text/event-stream',\n 'X-Theo-Action': '1',\n ...options.headers,\n },\n body: JSON.stringify(options.body),\n signal: options.signal,\n })\n\n if (!response.body) return\n\n const reader = response.body.getReader()\n const decoder = new TextDecoder()\n let buf = ''\n\n try {\n let done = false\n while (!done) {\n const chunk = await reader.read()\n done = chunk.done\n if (done) continue\n buf += decoder.decode(chunk.value, { stream: true })\n\n // SSE separates events with a blank line: `\\n\\n`.\n // Split, keep the trailing partial in buf.\n const parts = buf.split('\\n\\n')\n buf = parts.pop() ?? ''\n dispatchSseParts(parts, options.onEvent)\n }\n } finally {\n try {\n reader.releaseLock()\n } catch {\n // ignore — reader may already be released if the stream errored\n }\n }\n}\n","import type { AgentEvent } from '../core/contracts/agent-events.js'\n\n/**\n * A correlated, UI-facing view of one tool invocation (M5-2).\n *\n * `foldAgentToolCards` correlates a `tool_call` with its `tool_result` (by\n * `id`, falling back to FIFO-by-name) into a single card so consumers stop\n * hand-rolling `switch(event.type)`.\n */\nexport interface AgentToolCard {\n /** Correlation id (the event `id`, or a synthesized `tool-<index>`). */\n id: string\n name: string\n args: Record<string, unknown>\n status: 'running' | 'success' | 'error'\n /** The `tool_result.data` payload, once the result arrives. */\n result?: unknown\n}\n\n/**\n * Classifies a `tool_result.data` payload as success/error. Injectable so the\n * correlator is decoupled from any specific tool-result envelope shape.\n */\nexport type ToolEnvelopeResolver = (data: unknown) => { error: boolean }\n\nexport interface FoldAgentToolCardsOptions {\n /** Override the default envelope classifier. */\n resolveEnvelope?: ToolEnvelopeResolver\n}\n\n/**\n * Default envelope resolver: an object (or a JSON STRING parsing to an object)\n * with `ok === false` is an error; everything else is success (conservative).\n * sdk-tools handlers return a JSON STRING, so string parsing is intentional.\n */\nexport function defaultResolveEnvelope(data: unknown): { error: boolean } {\n return { error: coerceObject(data)?.ok === false }\n}\n\nfunction coerceObject(data: unknown): { ok?: unknown } | undefined {\n if (typeof data === 'object' && data !== null) return data\n if (typeof data === 'string') {\n try {\n const parsed: unknown = JSON.parse(data)\n if (typeof parsed === 'object' && parsed !== null) return parsed\n } catch {\n return undefined\n }\n }\n return undefined\n}\n\n/**\n * Fold an `AgentEvent[]` into correlated {@link AgentToolCard}s (M5-2). Pure.\n *\n * Correlation: a `tool_result` matches its `tool_call` by `id` when both carry\n * one; otherwise it matches the oldest still-`running` card with the same\n * `name` (FIFO). An unmatched `tool_result` becomes its own finished card.\n * A `tool_call` with no result stays `running`. The error status comes from\n * `options.resolveEnvelope` (default {@link defaultResolveEnvelope}).\n */\nexport function foldAgentToolCards(\n events: readonly AgentEvent[],\n options: FoldAgentToolCardsOptions = {},\n): AgentToolCard[] {\n const resolve = options.resolveEnvelope ?? defaultResolveEnvelope\n const cards: AgentToolCard[] = []\n const byId = new Map<string, AgentToolCard>()\n const runningByName = new Map<string, AgentToolCard[]>()\n\n events.forEach((event, index) => {\n if (event.type === 'tool_call') {\n const card: AgentToolCard = {\n id: event.id ?? `tool-${index}`,\n name: event.name,\n args: event.args,\n status: 'running',\n }\n cards.push(card)\n // Index by id (when present) AND by name FIFO — the two indexes overlap so\n // a result can correlate even when call/result disagree on carrying an id.\n if (event.id !== undefined) byId.set(event.id, card)\n pushRunning(runningByName, event.name, card)\n } else if (event.type === 'tool_result') {\n const card = matchResultCard(event, index, byId, runningByName, cards)\n card.result = event.data\n card.status = resolve(event.data).error ? 'error' : 'success'\n }\n })\n\n return cards\n}\n\nfunction pushRunning(\n runningByName: Map<string, AgentToolCard[]>,\n name: string,\n card: AgentToolCard,\n): void {\n const queue = runningByName.get(name)\n if (queue) queue.push(card)\n else runningByName.set(name, [card])\n}\n\nfunction removeRunning(\n runningByName: Map<string, AgentToolCard[]>,\n name: string,\n card: AgentToolCard,\n): void {\n const queue = runningByName.get(name)\n if (!queue) return\n const at = queue.indexOf(card)\n if (at >= 0) queue.splice(at, 1)\n}\n\nfunction matchResultCard(\n event: Extract<AgentEvent, { type: 'tool_result' }>,\n index: number,\n byId: Map<string, AgentToolCard>,\n runningByName: Map<string, AgentToolCard[]>,\n cards: AgentToolCard[],\n): AgentToolCard {\n // 1. Exact id match — consume from both indexes so it is matched at most once.\n if (event.id !== undefined) {\n const byIdCard = byId.get(event.id)\n if (byIdCard) {\n byId.delete(event.id)\n removeRunning(runningByName, byIdCard.name, byIdCard)\n return byIdCard\n }\n }\n // 2. FIFO-by-name fallback — works even if the call carried an id the result\n // omits (or vice-versa). Drop the matched card's id entry too.\n const fifo = runningByName.get(event.name)?.shift()\n if (fifo) {\n byId.delete(fifo.id)\n return fifo\n }\n // 3. Orphan result — surface it as its own finished card (never drop a result).\n const orphan: AgentToolCard = {\n id: event.id ?? `tool-${index}`,\n name: event.name,\n args: {},\n status: 'running',\n }\n cards.push(orphan)\n return orphan\n}\n","import { useMemo } from 'react'\n\nimport {\n type AgentToolCard,\n type FoldAgentToolCardsOptions,\n foldAgentToolCards,\n} from './agent-tool-cards.js'\nimport {\n type UseAgentStreamOptions,\n type UseAgentStreamReturn,\n useAgentStream,\n} from './use-agent-stream.js'\n\n/** {@link useAgentToolCards} return — the stream result plus correlated tool cards. */\nexport interface UseAgentToolCardsReturn<TBody = unknown> extends UseAgentStreamReturn<TBody> {\n /** Correlated tool cards folded from the stream events (M5-2). */\n toolCards: AgentToolCard[]\n}\n\n/**\n * `useAgentStream` + correlated tool cards (M5-2). Composes the stream hook with\n * the pure {@link foldAgentToolCards} reducer; pass `resolveEnvelope` to classify\n * tool-result payloads (default flags `{ ok: false }` envelopes as errors).\n */\nexport function useAgentToolCards<TBody = unknown>(\n path: string,\n options: UseAgentStreamOptions & FoldAgentToolCardsOptions = {},\n): UseAgentToolCardsReturn<TBody> {\n const { resolveEnvelope, ...streamOptions } = options\n const stream = useAgentStream<TBody>(path, streamOptions)\n const toolCards = useMemo(\n () => foldAgentToolCards(stream.events, { resolveEnvelope }),\n [stream.events, resolveEnvelope],\n )\n return { ...stream, toolCards }\n}\n","/**\n * <Link> — React Router Link with route prefetching.\n *\n * Wraps react-router's <Link> with prefetch behavior:\n * - `intent` (default): prefetch on hover + focus (~200ms before click)\n * - `viewport`: prefetch when visible (IntersectionObserver)\n * - `none`: no prefetch (same as plain react-router Link)\n *\n * Uses `<link rel=\"prefetch\">` (not modulepreload) because route paths\n * can be prefetched directly — no Vite manifest resolution needed (EC-1).\n */\nimport {\n Link as RouterLink,\n type LinkProps as RouterLinkProps,\n} from 'react-router'\nimport { useRef, useCallback, useEffect } from 'react'\n\nexport type PrefetchBehavior = 'none' | 'intent' | 'viewport'\n\nexport interface LinkProps extends RouterLinkProps {\n /** Prefetch strategy. Default: 'intent' (on hover + focus). */\n prefetch?: PrefetchBehavior\n}\n\n/** Deduplication — each URL prefetched at most once per session. */\nconst prefetched = new Set<string>()\n\nfunction injectPrefetch(href: string): void {\n // EC-2: SSR guard — document unavailable on server\n if (typeof document === 'undefined') return\n if (prefetched.has(href)) return\n prefetched.add(href)\n\n const link = document.createElement('link')\n link.rel = 'prefetch'\n link.href = href\n document.head.appendChild(link)\n}\n\nfunction resolveTo(to: LinkProps['to']): string {\n if (typeof to === 'string') return to\n return to?.pathname ?? ''\n}\n\n/**\n * TheoKit Link — drop-in replacement for react-router Link with prefetch.\n *\n * @example\n * ```tsx\n * import { Link } from 'theokit/client'\n *\n * <Link to=\"/contacts\">Contacts</Link>\n * <Link to=\"/dashboard\" prefetch=\"viewport\">Dashboard</Link>\n * <Link to=\"/settings\" prefetch=\"none\">Settings</Link>\n * ```\n */\nexport function Link({ prefetch = 'intent', to, onMouseEnter, onFocus, ...rest }: LinkProps) {\n const ref = useRef<HTMLAnchorElement>(null)\n\n const handleIntent = useCallback(\n (event: React.MouseEvent<HTMLAnchorElement> | React.FocusEvent<HTMLAnchorElement>) => {\n if (prefetch === 'intent') {\n injectPrefetch(resolveTo(to))\n }\n // Forward original handlers\n if (event.type === 'mouseenter' && onMouseEnter) {\n ;(onMouseEnter as React.MouseEventHandler<HTMLAnchorElement>)(event as React.MouseEvent<HTMLAnchorElement>)\n }\n if (event.type === 'focus' && onFocus) {\n ;(onFocus as React.FocusEventHandler<HTMLAnchorElement>)(event as React.FocusEvent<HTMLAnchorElement>)\n }\n },\n [prefetch, to, onMouseEnter, onFocus],\n )\n\n // Viewport mode: IntersectionObserver\n useEffect(() => {\n if (prefetch !== 'viewport' || !ref.current) return\n if (typeof IntersectionObserver === 'undefined') return // SSR guard\n\n const observer = new IntersectionObserver(\n ([entry]) => {\n if (entry.isIntersecting) {\n injectPrefetch(resolveTo(to))\n observer.disconnect()\n }\n },\n { rootMargin: '200px' }, // prefetch slightly before visible\n )\n observer.observe(ref.current)\n return () => observer.disconnect()\n }, [prefetch, to])\n\n return (\n <RouterLink\n ref={ref}\n to={to}\n onMouseEnter={handleIntent}\n onFocus={handleIntent}\n {...rest}\n />\n )\n}\n","/**\n * <Metadata> — SEO-ready head tags from a single component.\n *\n * Uses React 19's native <title>/<meta>/<link> hoisting to <head>.\n * No build-time extraction needed — works in SSR and client.\n *\n * @example\n * ```tsx\n * import { Metadata } from 'theokit/client'\n *\n * export default function ContactsPage() {\n * return (\n * <>\n * <Metadata\n * title=\"Contacts | My CRM\"\n * description=\"Manage your contacts\"\n * ogImage=\"/og/contacts.png\"\n * canonical=\"https://mycrm.com/contacts\"\n * />\n * <h1>Contacts</h1>\n * </>\n * )\n * }\n * ```\n */\n\nexport interface MetadataProps {\n title?: string\n description?: string\n canonical?: string\n ogTitle?: string\n ogDescription?: string\n ogImage?: string\n ogType?: string\n ogUrl?: string\n twitterCard?: 'summary' | 'summary_large_image'\n /** Custom meta tags rendered as children */\n children?: React.ReactNode\n}\n\nexport function Metadata(props: MetadataProps) {\n const ogTitle = props.ogTitle ?? props.title\n const ogDesc = props.ogDescription ?? props.description\n\n return (\n <>\n {props.title && <title>{props.title}</title>}\n {props.description && <meta name=\"description\" content={props.description} />}\n {props.canonical && <link rel=\"canonical\" href={props.canonical} />}\n {ogTitle && <meta property=\"og:title\" content={ogTitle} />}\n {ogDesc && <meta property=\"og:description\" content={ogDesc} />}\n {props.ogImage && <meta property=\"og:image\" content={props.ogImage} />}\n {props.ogType && <meta property=\"og:type\" content={props.ogType} />}\n {props.ogUrl && <meta property=\"og:url\" content={props.ogUrl} />}\n {props.twitterCard && <meta name=\"twitter:card\" content={props.twitterCard} />}\n {props.children}\n </>\n )\n}\n","/**\n * <Image> — optimized image component with lazy loading.\n *\n * Renders a standard <img> with:\n * - loading=\"lazy\" by default (eager with priority={true})\n * - decoding=\"async\" for non-blocking decode\n * - width/height for CLS prevention\n * - srcSet/sizes forwarded for responsive images\n *\n * No CDN, no Sharp, no build-time optimization — pure HTML attributes\n * that deliver 80% of the performance value at zero complexity.\n *\n * @example\n * ```tsx\n * import { Image } from 'theokit/client'\n *\n * <Image src=\"/team.jpg\" alt=\"Team photo\" width={800} height={600} />\n * <Image src=\"/hero.jpg\" alt=\"Hero\" priority />\n * <Image\n * src=\"/product.jpg\"\n * alt=\"Product\"\n * width={400}\n * height={300}\n * srcSet=\"/product-400.jpg 400w, /product-800.jpg 800w\"\n * sizes=\"(max-width: 768px) 100vw, 400px\"\n * />\n * ```\n */\n\nexport interface ImageProps extends React.ImgHTMLAttributes<HTMLImageElement> {\n /** Image source URL (required). */\n src: string\n /** Alt text for accessibility (required). */\n alt: string\n /** If true, loading=\"eager\" — use for above-the-fold images. */\n priority?: boolean\n}\n\nexport function Image({ priority, loading, decoding, ...props }: ImageProps) {\n return (\n <img\n loading={loading ?? (priority ? 'eager' : 'lazy')}\n decoding={decoding ?? 'async'}\n {...props}\n />\n )\n}\n"],"mappings":"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","names":["useMemo","useMemo","useRef","useCallback","useEffect","jsx","jsx"]}
|
|
1
|
+
{"version":3,"sources":["../../src/client/theo-fetch.ts","../../src/client/batch.ts","../../src/client/batch-transport.ts","../../src/client/app-client.ts","../../src/client/use-agent-stream.ts","../../src/client/agent-stream-core.ts","../../src/client/agent-tool-cards.ts","../../src/client/use-agent-tool-cards.ts","../../src/client/consume-ui-message-stream.ts","../../src/client/use-agent.ts","../../src/client/link.tsx","../../src/client/metadata.tsx","../../src/client/image.tsx"],"sourcesContent":["import superjson from 'superjson'\nimport type { z } from 'zod'\n\nimport type { TheoErrorCode, TheoErrorEnvelope } from '../core/contracts/error-envelope.js'\n\nimport { getGlobalBatcher } from './batch-transport.js'\n\n// --- Transformer (T1.3) ---\n\n/**\n * Module-scoped flag preventing the transformer-mismatch warning from\n * firing more than once per session (EC-6).\n */\nlet mismatchWarned = false\n\n/** Test-only helper to reset the warned flag between assertions. */\nexport function __resetMismatchWarningForTests(): void {\n mismatchWarned = false\n}\n\n/**\n * Deserialize a fetch response body according to the negotiated transformer.\n *\n * `serverTransformerName` comes from the `x-theo-transformer` response header\n * (null when absent — server is using the default JSON path).\n * `clientTransformerName` is the transformer the client was built with\n * (typically injected via a Vite virtual module; falls back to `'json'`).\n *\n * Mismatch fires a single console.warn and falls back to JSON.parse (EC-5/EC-6).\n */\nexport function deserializeFetchResponse(\n raw: string,\n serverTransformerName: string | null,\n clientTransformerName: string,\n): unknown {\n // `raw` is typed `string`, but stay defensive: callers pass `await response.text()`\n // which can be empty.\n if (raw === '') {\n return null\n }\n\n const serverEffective = serverTransformerName ?? 'json'\n if (serverEffective !== clientTransformerName && !mismatchWarned) {\n mismatchWarned = true\n console.warn(\n `[theokit] transformer mismatch: server=${serverEffective}, client=${clientTransformerName}. Falling back to JSON.parse.`,\n )\n }\n\n if (serverEffective === 'superjson' && clientTransformerName === 'superjson') {\n const wrapped = JSON.parse(raw) as Parameters<typeof superjson.deserialize>[0]\n return superjson.deserialize(wrapped)\n }\n\n // Default path (json) or mismatch fallback\n return JSON.parse(raw)\n}\n\n// --- Utility Types ---\n\n/** Infer the response type from a route's handler return */\nexport type InferResponse<T> = T extends { handler: (...args: never[]) => infer R }\n ? Awaited<R>\n : unknown\n\n/** Extract the query Zod schema type, handling optional properties */\ntype ExtractQuery<T> = T extends { query?: infer Q } ? (Q extends z.ZodType ? Q : never) : never\n\n/** Extract the body Zod schema type, handling optional properties */\ntype ExtractBody<T> = T extends { body?: infer B } ? (B extends z.ZodType ? B : never) : never\n\n/** Infer query type from a route's query Zod schema */\nexport type InferQuery<T> = [ExtractQuery<T>] extends [never]\n ? undefined\n : ExtractQuery<T> extends z.ZodUndefined\n ? undefined\n : z.infer<ExtractQuery<T>>\n\n/** Infer body type from a route's body Zod schema */\nexport type InferBody<T> = [ExtractBody<T>] extends [never]\n ? undefined\n : ExtractBody<T> extends z.ZodUndefined\n ? undefined\n : z.infer<ExtractBody<T>>\n\n/** Build the options type based on what schemas the route has */\nexport type TheoFetchOptions<T> = Omit<RequestInit, 'body' | 'method'> &\n (InferQuery<T> extends undefined ? { query?: never } : { query: InferQuery<T> }) &\n (InferBody<T> extends undefined ? { body?: never } : { body: InferBody<T> })\n\n// --- Error Class ---\n\n/**\n * G5 T2.1 — extract a TheoErrorEnvelope from a response body. Supports both\n * the new envelope-at-root shape (`{ code, message, ext?, ... }`, blueprint\n * Recommendations § concrete shape) and the legacy nested shape\n * (`{ error: { code, message, issues? } }`, G3 SerializedActionResult).\n *\n * Falls back to `INTERNAL_SERVER_ERROR` with a synthetic message when the\n * body shape is unrecognized. Pure; no I/O.\n */\nfunction extractEnvelope(status: number, body: unknown): TheoErrorEnvelope {\n if (!body || typeof body !== 'object') {\n return { code: 'INTERNAL_SERVER_ERROR', message: `HTTP ${String(status)}` }\n }\n const obj = body as Record<string, unknown>\n // New shape — envelope at root\n if (typeof obj.code === 'string' && typeof obj.message === 'string') {\n return {\n code: obj.code as TheoErrorCode,\n message: obj.message,\n cause: obj.cause,\n meta: obj.meta as Record<string, unknown> | undefined,\n ext: obj.ext,\n }\n }\n // Legacy shape — { error: { code, message, ... } }\n if (obj.error && typeof obj.error === 'object') {\n const nested = obj.error as Record<string, unknown>\n return {\n code:\n typeof nested.code === 'string' ? (nested.code as TheoErrorCode) : 'INTERNAL_SERVER_ERROR',\n message: typeof nested.message === 'string' ? nested.message : `HTTP ${String(status)}`,\n }\n }\n return { code: 'INTERNAL_SERVER_ERROR', message: `HTTP ${String(status)}` }\n}\n\n/**\n * Pull a single string field from an object, returning undefined if missing\n * or non-string. Helper for `extractLegacyFields` to stay under the\n * complexity ceiling.\n */\nfunction strField(obj: Record<string, unknown> | null, key: string): string | undefined {\n const v = obj?.[key]\n return typeof v === 'string' ? v : undefined\n}\n\n/**\n * Pull the canonical {message, code, issues} from either an envelope-at-root\n * body or the legacy { error: {...} } body. Pure.\n */\nfunction extractLegacyFields(\n status: number,\n body: unknown,\n): { message: string; code?: string; issues?: unknown[] } {\n if (!body || typeof body !== 'object') {\n return { message: `HTTP ${String(status)}` }\n }\n const obj = body as Record<string, unknown>\n const nested =\n obj.error && typeof obj.error === 'object' ? (obj.error as Record<string, unknown>) : null\n const issues = Array.isArray(nested?.issues) ? nested.issues : undefined\n return {\n message: strField(obj, 'message') ?? strField(nested, 'message') ?? `HTTP ${String(status)}`,\n code: strField(obj, 'code') ?? strField(nested, 'code'),\n issues,\n }\n}\n\nexport class TheoFetchError extends Error {\n status: number\n code?: string\n issues?: unknown[]\n /**\n * G5 T2.1 — canonical envelope view of the server-side error. Use this in\n * consumer code that wants to switch on a typed TheoErrorCode instead of\n * coupling to the legacy `.status` / `.code` flat fields.\n */\n readonly envelope: TheoErrorEnvelope\n\n constructor(status: number, body?: unknown) {\n const legacy = extractLegacyFields(status, body)\n super(legacy.message)\n this.name = 'TheoFetchError'\n this.status = status\n this.code = legacy.code\n this.issues = legacy.issues\n this.envelope = extractEnvelope(status, body)\n }\n}\n\n/**\n * Serialize a query-param value to a string. Handles primitives, dates,\n * and falls back to JSON for arrays/objects. Avoids the\n * `[object Object]` foot-gun that `no-base-to-string` warns against.\n */\nfunction stringifyQueryValue(value: unknown): string {\n if (value === null) return 'null'\n if (value instanceof Date) return value.toISOString()\n switch (typeof value) {\n case 'string':\n return value\n case 'number':\n case 'boolean':\n case 'bigint':\n return String(value)\n default:\n return JSON.stringify(value)\n }\n}\n\n// --- Main Function ---\n\ninterface TheoFetchInternalOptions {\n method?: string\n query?: Record<string, unknown>\n body?: unknown\n headers?: HeadersInit\n signal?: AbortSignal\n}\n\n/**\n * Resolve the request origin per the documented fallback hierarchy. Pure\n * helper extracted to keep `theoFetch` under the complexity ceiling.\n * 1. `globalThis.location.origin` (browser)\n * 2. `globalThis.__THEO_ORIGIN__` (build-time literal)\n * 3. `process.env.THEO_ORIGIN` (escape hatch)\n * 4. `http://localhost` (placeholder for URL parsing — the URL is built\n * relative so only pathname+search ever flows to the wire)\n */\nfunction resolveRequestOrigin(): string {\n const g = globalThis as { location?: { origin?: string }; __THEO_ORIGIN__?: string }\n const fromEnv = typeof process !== 'undefined' ? process.env.THEO_ORIGIN : undefined\n return g.location?.origin ?? g.__THEO_ORIGIN__ ?? fromEnv ?? 'http://localhost'\n}\n\nfunction buildFetchUrl(path: string, query: Record<string, unknown> | undefined): URL {\n const fetchUrl = new URL(path, resolveRequestOrigin())\n if (!query) return fetchUrl\n for (const [k, v] of Object.entries(query)) {\n if (v !== undefined) {\n fetchUrl.searchParams.set(k, stringifyQueryValue(v))\n }\n }\n return fetchUrl\n}\n\n/**\n * Normalize `HeadersInit` (Headers / `[string, string][]` / Record) into a\n * single plain `Record<string, string>`. Plain-object output is required\n * by callers that introspect headers via index access (test fixtures use\n * `(init.headers as Record<string, string>)['Content-Type']`).\n */\nfunction normalizeHeaders(input: HeadersInit | undefined): Record<string, string> {\n const out: Record<string, string> = {}\n if (!input) return out\n if (input instanceof Headers) {\n input.forEach((value, key) => {\n out[key] = value\n })\n return out\n }\n if (Array.isArray(input)) {\n for (const [key, value] of input) out[key] = value\n return out\n }\n for (const [key, value] of Object.entries(input)) {\n out[key] = value\n }\n return out\n}\n\nfunction buildRequestInit(opts: TheoFetchInternalOptions): RequestInit {\n const init: RequestInit = {}\n if (opts.method !== undefined) init.method = opts.method\n if (opts.signal !== undefined) init.signal = opts.signal\n\n const headers = normalizeHeaders(opts.headers)\n init.headers = headers\n\n if (opts.body !== undefined) {\n init.body = JSON.stringify(opts.body)\n headers['Content-Type'] = 'application/json'\n }\n\n // Phase 5 — Auto-attach `X-Theo-Action: 1` for state-mutating methods so\n // the framework's CSRF check passes when servers run in `strict` mode.\n // Safe methods (GET/HEAD/OPTIONS) skip the header to keep them cacheable.\n const method = (opts.method ?? 'GET').toUpperCase()\n if (method !== 'GET' && method !== 'HEAD' && method !== 'OPTIONS') {\n headers['X-Theo-Action'] = '1'\n }\n return init\n}\n\nasync function tryBatcher(\n url: string,\n options: TheoFetchInternalOptions,\n): Promise<{ matched: true; result: unknown } | { matched: false }> {\n const batcher = getGlobalBatcher()\n if (!batcher) return { matched: false }\n try {\n const result = await batcher.dispatch({\n path: url,\n method: options.method ?? 'GET',\n query: options.query,\n body: options.body,\n })\n return { matched: true, result }\n } catch {\n // Batcher failure: fall through to direct fetch (graceful degrade).\n return { matched: false }\n }\n}\n\nexport async function theoFetch<T>(\n url: string,\n options?: TheoFetchOptions<T>,\n): Promise<InferResponse<T>> {\n const internal = (options ?? {}) as unknown as TheoFetchInternalOptions\n\n // T1.5 — Transparent batching when globalThis.__THEO_BATCHING__ is truthy.\n const batchAttempt = await tryBatcher(url, internal)\n if (batchAttempt.matched) {\n return batchAttempt.result as InferResponse<T>\n }\n\n const fetchUrl = buildFetchUrl(url, internal.query)\n const init = buildRequestInit(internal)\n const response = await fetch(fetchUrl.toString(), init)\n\n if (!response.ok) {\n let errorBody: unknown\n try {\n errorBody = await response.json()\n } catch {\n // Non-JSON error response\n }\n throw new TheoFetchError(response.status, errorBody)\n }\n\n // Handle 204 No Content (EC-1)\n if (response.status === 204) {\n return null as InferResponse<T>\n }\n\n // Check for empty body\n const contentLength = response.headers.get('content-length')\n if (contentLength === '0') {\n return null as InferResponse<T>\n }\n\n // T1.3 — transformer-aware deserialization\n const serverTransformerName = response.headers.get('x-theo-transformer')\n const clientTransformerName = resolveClientTransformerName()\n const text = await response.text()\n return deserializeFetchResponse(\n text,\n serverTransformerName,\n clientTransformerName,\n ) as InferResponse<T>\n}\n\n/**\n * Read the client-configured transformer name. Default `'json'`.\n *\n * In a Vite build, this is overridden by virtual module\n * `/@theo/runtime-config` which sets `globalThis.__THEO_TRANSFORMER__`.\n * Outside Vite (Node SSR, tests) the default applies.\n */\nfunction resolveClientTransformerName(): string {\n const g = globalThis as { __THEO_TRANSFORMER__?: string }\n return g.__THEO_TRANSFORMER__ ?? 'json'\n}\n","/**\n * T5.1 — client-side microtask batching.\n *\n * Collects all `dispatch` calls within the same microtask and sends them as a\n * single HTTP POST to the configured transport. Each caller's promise resolves\n * with its own result; one failed item does not break the others (per-item\n * error isolation).\n *\n * Designed as a transport-agnostic primitive so unit tests do not require\n * network access. The default transport (fetch to `/api/__theo_batch__`)\n * lives alongside this module but is created by the consumer (e.g., theoFetch).\n */\n\nexport interface BatchRequest {\n path: string\n method: string\n query?: Record<string, unknown>\n body?: unknown\n headers?: Record<string, string>\n}\n\nexport type BatchResponse =\n | { index: number; data: unknown }\n | { index: number; error: { message: string; code?: string } }\n\nexport type BatchTransport = (requests: BatchRequest[]) => Promise<BatchResponse[]>\n\nexport interface BatcherOptions {\n transport: BatchTransport\n /** Maximum batch size before flushing into multiple parallel batches. */\n max?: number\n}\n\nexport interface Batcher {\n dispatch(req: BatchRequest): Promise<unknown>\n}\n\ninterface PendingCall {\n req: BatchRequest\n resolve: (value: unknown) => void\n reject: (reason: unknown) => void\n}\n\nexport function createBatcher(options: BatcherOptions): Batcher {\n const max = options.max ?? 32\n let queue: PendingCall[] = []\n let flushScheduled = false\n\n function flush(): void {\n flushScheduled = false\n const current = queue\n queue = []\n if (current.length === 0) return\n\n // Split into chunks respecting max\n const chunks: PendingCall[][] = []\n for (let i = 0; i < current.length; i += max) {\n chunks.push(current.slice(i, i + max))\n }\n\n for (const chunk of chunks) {\n const payload: BatchRequest[] = chunk.map((p) => p.req)\n options\n .transport(payload)\n .then((results) => {\n for (let i = 0; i < chunk.length; i++) {\n // `results[i]` could be undefined at runtime when the transport\n // returns fewer entries than the chunk; TypeScript's strict\n // typing without `noUncheckedIndexedAccess` does not surface\n // this, so we hand-narrow.\n const result = results.length > i ? results[i] : undefined\n if (result === undefined) {\n chunk[i].reject(new Error(`Batch transport returned no result for index ${i}`))\n continue\n }\n if ('error' in result) {\n const err = new Error(result.error.message)\n ;(err as { code?: string }).code = result.error.code\n chunk[i].reject(err)\n } else {\n chunk[i].resolve(result.data)\n }\n }\n })\n .catch((err: unknown) => {\n for (const item of chunk) item.reject(err)\n })\n }\n }\n\n return {\n dispatch(req: BatchRequest): Promise<unknown> {\n return new Promise<unknown>((resolve, reject) => {\n queue.push({ req, resolve, reject })\n if (!flushScheduled) {\n flushScheduled = true\n queueMicrotask(flush)\n }\n })\n },\n }\n}\n","/**\n * T1.5 — Default HTTP transport for the client batcher.\n *\n * Wraps `fetch` to POST `/api/__theo_batch__` with the collected requests\n * and return the array of per-item results.\n */\n\nimport {\n createBatcher,\n type BatchTransport,\n type Batcher,\n type BatchRequest,\n type BatchResponse,\n} from './batch.js'\n\nconst BATCH_ENDPOINT = '/api/__theo_batch__'\n\nexport interface CreateBatchTransportOptions {\n /** Override fetch (default: globalThis.fetch). Used by tests. */\n fetchImpl?: typeof fetch\n /** Override endpoint (default '/api/__theo_batch__'). */\n endpoint?: string\n}\n\nexport function createBatchTransport(options: CreateBatchTransportOptions = {}): BatchTransport {\n const fetchImpl = options.fetchImpl ?? fetch\n const endpoint = options.endpoint ?? BATCH_ENDPOINT\n return async (requests: BatchRequest[]): Promise<BatchResponse[]> => {\n const response = await fetchImpl(endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ requests }),\n })\n if (!response.ok) {\n throw new Error(`Batch transport returned ${response.status}`)\n }\n const payload = (await response.json()) as { results?: BatchResponse[] }\n if (!Array.isArray(payload.results)) {\n throw new Error('Batch response missing results array')\n }\n // Map results to indexed BatchResponse shape (server already returns the right form)\n return payload.results.map((item, index) => {\n if ('error' in item) {\n return { index, error: (item as { error: { message: string; code?: string } }).error }\n }\n return { index, data: (item as { data: unknown }).data }\n })\n }\n}\n\n// --- EC-7: singleton batcher per page, lazy-instantiated ---\n\nlet globalBatcher: Batcher | undefined\n\n/** Test-only — reset the module-scope singleton between assertions. */\nexport function __resetGlobalBatcherForTests(): void {\n globalBatcher = undefined\n}\n\n/**\n * Returns the global batcher singleton when `globalThis.__THEO_BATCHING__` is\n * truthy; undefined otherwise. Lazy-instantiated on first call.\n */\nexport function getGlobalBatcher(): Batcher | undefined {\n const g = globalThis as { __THEO_BATCHING__?: boolean }\n if (!g.__THEO_BATCHING__) return undefined\n globalBatcher ??= createBatcher({ transport: createBatchTransport() })\n return globalBatcher\n}\n","/**\n * Phase 3 of G1 (g1-client-codegen-plan.md):\n *\n * `createAppClient(baseUrl?, fetchImpl?)` returns a Proxy that walks property\n * access (`client.posts.id.get(...)`) into a `theoFetch` invocation against\n * `{baseUrl}/posts/{params.id}` with method `GET`.\n *\n * Type safety is delivered by the `.d.ts` file emitted in Phase 2 — this\n * runtime is structurally untyped. Power users may use `theoFetch` directly\n * when they need to escape the Proxy facade.\n *\n * Edge cases absorbed:\n * - EC-1 (thenable trap): `then` / `catch` / `finally` / `toJSON` / `Symbol.*`\n * return `undefined` so that accidental `await client.posts` resolves to a\n * plain Proxy value (it is NOT thenable) instead of looping.\n * - EC-7 (abort signal): `opts.signal` is spread through to the underlying\n * fetchImpl unchanged — verified in unit tests.\n *\n * Bundle target: ≤ 2KB gzipped.\n */\n\nimport { theoFetch, TheoFetchError } from './theo-fetch.js'\nimport type { TheoFetchOptions } from './theo-fetch.js'\nimport { HTTP_METHOD_LOWERCASE } from '../core/contracts/http-methods.js'\n\nconst HTTP_METHODS_SET = new Set(HTTP_METHOD_LOWERCASE)\n\n/**\n * Keys that JavaScript runtime / inspectors / Promise resolution probe\n * unconditionally. Returning `undefined` for these keeps the Proxy from\n * pretending to be a thenable / iterable / serializable thing.\n */\nconst NON_INTERCEPT_KEYS = new Set([\n 'then',\n 'catch',\n 'finally',\n 'toJSON',\n 'toString',\n 'valueOf',\n 'constructor',\n 'prototype',\n])\n\ntype FetchImpl = typeof theoFetch\n\ninterface CallOptions {\n params?: Record<string, string | number>\n query?: Record<string, unknown>\n body?: unknown\n signal?: AbortSignal\n headers?: HeadersInit\n // arbitrary RequestInit fields (mode, credentials, cache, etc.)\n [k: string]: unknown\n}\n\nfunction injectParams(path: string, params?: Record<string, string | number>): string {\n if (!params) {\n if (/:(?:\\.\\.\\.)?[A-Za-z_]/.test(path)) {\n throw new TheoFetchError(0, {\n error: {\n code: 'MISSING_PARAM',\n message: `Route ${path} requires params but none were provided. Pass them via opts.params, e.g. client.posts.get({ params: { id: '123' } }).`,\n },\n })\n }\n return path\n }\n return path.replace(/:(?:\\.\\.\\.)?([A-Za-z_][A-Za-z0-9_]*)/g, (_match, key: string) => {\n const value = params[key]\n if (value === undefined || value === null || value === '') {\n throw new TheoFetchError(0, {\n error: {\n code: 'MISSING_PARAM',\n message: `Param '${key}' is required for path '${path}' but was missing/empty.`,\n },\n })\n }\n return encodeURIComponent(String(value))\n })\n}\n\ninterface ProxyContext {\n segments: string[]\n baseUrl: string\n fetchImpl: FetchImpl\n}\n\nfunction makeProxy(ctx: ProxyContext): unknown {\n const handler: ProxyHandler<() => void> = {\n get(_target, key) {\n if (typeof key !== 'string') return undefined\n if (NON_INTERCEPT_KEYS.has(key)) return undefined\n if (HTTP_METHODS_SET.has(key)) {\n return async (opts?: CallOptions) => {\n if (ctx.segments.length === 0) {\n throw new TheoFetchError(0, {\n error: {\n code: 'INVALID_PATH',\n message: `client.${key}() called without a route segment. Use client.<resource>.${key}(...) instead.`,\n },\n })\n }\n let finalPath = `${ctx.baseUrl}/${ctx.segments.join('/')}`\n if (opts?.params) {\n // Build a path with `:name` placeholders re-inserted from segments\n // whose name matches a key in opts.params (treat as dynamic).\n const segmentsWithDynamic = ctx.segments.map((seg) =>\n Object.prototype.hasOwnProperty.call(opts.params, seg) ? `:${seg}` : seg,\n )\n finalPath = injectParams(\n `${ctx.baseUrl}/${segmentsWithDynamic.join('/')}`,\n opts.params,\n )\n }\n const { params: _ignored, ...rest } = opts ?? {}\n const init = { method: key.toUpperCase(), ...rest } as unknown as TheoFetchOptions<unknown>\n return ctx.fetchImpl(finalPath, init)\n }\n }\n // Continue traversal — append segment to the path.\n return makeProxy({ ...ctx, segments: [...ctx.segments, key] })\n },\n apply() {\n return Promise.reject(\n new TheoFetchError(0, {\n error: {\n code: 'INVALID_CALL',\n message:\n 'client(...) is not callable. Use client.<resource>.<method>(opts?) — e.g. client.posts.get().',\n },\n }),\n )\n },\n }\n return new Proxy(() => undefined, handler)\n}\n\nexport interface CreateAppClientOptions {\n /** Base URL for the API. Defaults to `/api`. */\n baseUrl?: string\n /** Test-only fetch override. Production callers should not pass this. */\n fetchImpl?: FetchImpl\n}\n\nexport function createAppClient<TAppClient = unknown>(\n baseUrlOrOptions?: string | CreateAppClientOptions,\n legacyFetchImpl?: FetchImpl,\n): TAppClient {\n let baseUrl = '/api'\n let fetchImpl: FetchImpl = theoFetch\n if (typeof baseUrlOrOptions === 'string') {\n baseUrl = baseUrlOrOptions || '/api'\n } else if (baseUrlOrOptions && typeof baseUrlOrOptions === 'object') {\n if (baseUrlOrOptions.baseUrl) baseUrl = baseUrlOrOptions.baseUrl\n if (baseUrlOrOptions.fetchImpl) fetchImpl = baseUrlOrOptions.fetchImpl\n }\n // Legacy 2nd-arg fetchImpl overrides regardless of 1st-arg shape (test seam).\n if (legacyFetchImpl) fetchImpl = legacyFetchImpl\n // Strip trailing slash for predictable joining.\n if (baseUrl.length > 1 && baseUrl.endsWith('/')) baseUrl = baseUrl.slice(0, -1)\n return makeProxy({ segments: [], baseUrl, fetchImpl }) as TAppClient\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react'\n\nimport type { AgentErrorEvent, AgentEvent } from '../core/contracts/agent-events.js'\n\nimport { consumeAgentStream } from './agent-stream-core.js'\n\n/**\n * Accumulated assistant text (M5-1): the concatenation of every `message`\n * event's `content`. Pure. Assumes append/delta semantics — a server that\n * emits full-snapshot messages should read `events` directly.\n */\nexport function deriveLiveText(events: readonly AgentEvent[]): string {\n let text = ''\n for (const event of events) {\n if (event.type === 'message') text += event.content\n }\n return text\n}\n\n/**\n * The current error (M5-1): the last `error` event, or `undefined`. Surfaces\n * the full `AgentErrorEvent` (with `code`/`retriable`) so the UI can branch.\n * Pure.\n */\nexport function deriveError(events: readonly AgentEvent[]): AgentErrorEvent | undefined {\n let last: AgentErrorEvent | undefined\n for (const event of events) {\n if (event.type === 'error') last = event\n }\n return last\n}\n\n/**\n * T5.2 — useAgentStream\n *\n * React hook to consume an agent endpoint defined with `defineAgentEndpoint`.\n *\n * Transport (ADR D7, EC-3): fetch + ReadableStream — NOT EventSource.\n * EventSource is GET-only; agent endpoints need POST + body.\n *\n * Returns:\n * events — array of AgentEvents accumulated so far\n * send — call with a payload to (re)open a stream\n * status — 'idle' | 'streaming' | 'done' | 'error'\n * abort — manually cancel an in-flight stream\n *\n * Cleanup (EC-8): on unmount, the current AbortController fires .abort(),\n * which propagates to the underlying fetch and the ReadableStream reader.\n * Safe under React.StrictMode double-mount.\n */\n\nexport type AgentStreamStatus = 'idle' | 'streaming' | 'done' | 'error'\n\nexport interface UseAgentStreamReturn<TBody = unknown> {\n events: AgentEvent[]\n status: AgentStreamStatus\n /** Accumulated assistant text — concatenation of all `message` contents (M5-1). */\n liveText: string\n /** The last `error` event, or `undefined` (M5-1). */\n error: AgentErrorEvent | undefined\n send: (body: TBody) => void\n abort: () => void\n reset: () => void\n}\n\nexport interface UseAgentStreamOptions {\n /** Extra headers (e.g., auth). */\n headers?: Record<string, string>\n /** Override fetch (rare — primarily for tests). */\n fetch?: typeof fetch\n}\n\nexport function useAgentStream<TBody = unknown>(\n path: string,\n options: UseAgentStreamOptions = {},\n): UseAgentStreamReturn<TBody> {\n const [events, setEvents] = useState<AgentEvent[]>([])\n const [status, setStatus] = useState<AgentStreamStatus>('idle')\n const controllerRef = useRef<AbortController | null>(null)\n\n const abort = useCallback(() => {\n if (controllerRef.current) {\n controllerRef.current.abort()\n controllerRef.current = null\n }\n }, [])\n\n const reset = useCallback(() => {\n abort()\n setEvents([])\n setStatus('idle')\n }, [abort])\n\n const send = useCallback(\n (body: TBody) => {\n // Cancel any in-flight stream first.\n abort()\n const controller = new AbortController()\n controllerRef.current = controller\n setStatus('streaming')\n\n let sawError = false\n consumeAgentStream<TBody>(path, {\n body,\n fetch: options.fetch,\n headers: options.headers,\n signal: controller.signal,\n onEvent: (event) => {\n if (event.type === 'error') sawError = true\n setEvents((prev) => [...prev, event])\n },\n })\n .then(() => {\n if (controllerRef.current !== controller) return // superseded\n setStatus(sawError ? 'error' : 'done')\n })\n .catch(() => {\n if (controllerRef.current !== controller) return // superseded / aborted\n if (controller.signal.aborted) return\n setStatus('error')\n })\n },\n [abort, path, options.fetch, options.headers],\n )\n\n // EC-8: cleanup on unmount aborts in-flight stream.\n useEffect(() => {\n return () => {\n if (controllerRef.current) {\n controllerRef.current.abort()\n controllerRef.current = null\n }\n }\n }, [])\n\n // M5-1: derived views over the accumulated events.\n const liveText = useMemo(() => deriveLiveText(events), [events])\n const error = useMemo(() => deriveError(events), [events])\n\n return { events, status, liveText, error, send, abort, reset }\n}\n","import type { AgentEvent } from '../core/contracts/agent-events.js'\n\n/**\n * T5.2 — Pure SSE consumer used by useAgentStream.\n *\n * Split out from the React hook so the wire behavior can be tested\n * without a DOM. The hook is glue: useState + useEffect + this primitive.\n *\n * Transport (ADR D7, EC-3): fetch + ReadableStream — NOT EventSource.\n * EventSource is GET-only and cannot carry a body. Agent endpoints need\n * POST + JSON body, so we use fetch + manual SSE chunk parsing.\n */\n\nexport interface ConsumeOptions<TBody = unknown> {\n /** Request body — JSON-serialized into the POST. */\n body: TBody\n /** Called once per SSE event parsed off the stream. */\n onEvent: (event: AgentEvent) => void\n /** Optional fetch override (tests). */\n fetch?: typeof fetch\n /** Optional abort signal — passed through to fetch. */\n signal?: AbortSignal\n /** Extra headers (e.g., auth). */\n headers?: Record<string, string>\n}\n\n/**\n * Dispatch SSE events from a list of `\\n\\n`-separated chunk parts.\n * Extracted to keep the streaming loop under the max-depth ceiling.\n */\nfunction dispatchSseParts(parts: string[], onEvent: (event: AgentEvent) => void): void {\n for (const part of parts) {\n // A chunk may contain multiple lines; keep only the data: line.\n for (const line of part.split('\\n')) {\n const evt = parseSSEChunk(line)\n if (evt) onEvent(evt)\n }\n }\n}\n\n/**\n * Parse a single SSE line of the form `data: <json>`.\n * Returns null for non-data lines, comments, or malformed JSON.\n */\nexport function parseSSEChunk(line: string): AgentEvent | null {\n if (!line.startsWith('data:')) return null\n const raw = line.slice(5).trim()\n if (!raw) return null\n try {\n return JSON.parse(raw) as AgentEvent\n } catch {\n return null\n }\n}\n\n/**\n * POSTs to `path` with `body`, reads the SSE response, and invokes\n * `onEvent` for each parsed AgentEvent. Resolves when the server\n * closes the stream or the signal aborts.\n *\n * T1.1 — Attaches `X-Theo-Action: '1'` so 0.3.0 strict CSRF mode accepts\n * the request. The user can override (or suppress) by passing the header\n * in `options.headers` — spread order ensures their value wins.\n */\nexport async function consumeAgentStream<TBody = unknown>(\n path: string,\n options: ConsumeOptions<TBody>,\n): Promise<void> {\n const fetchImpl = options.fetch ?? globalThis.fetch\n const response = await fetchImpl(path, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n accept: 'text/event-stream',\n 'X-Theo-Action': '1',\n ...options.headers,\n },\n body: JSON.stringify(options.body),\n signal: options.signal,\n })\n\n if (!response.body) return\n\n const reader = response.body.getReader()\n const decoder = new TextDecoder()\n let buf = ''\n\n try {\n let done = false\n while (!done) {\n const chunk = await reader.read()\n done = chunk.done\n if (done) continue\n buf += decoder.decode(chunk.value, { stream: true })\n\n // SSE separates events with a blank line: `\\n\\n`.\n // Split, keep the trailing partial in buf.\n const parts = buf.split('\\n\\n')\n buf = parts.pop() ?? ''\n dispatchSseParts(parts, options.onEvent)\n }\n } finally {\n try {\n reader.releaseLock()\n } catch {\n // ignore — reader may already be released if the stream errored\n }\n }\n}\n","import type { AgentEvent } from '../core/contracts/agent-events.js'\n\n/**\n * A correlated, UI-facing view of one tool invocation (M5-2).\n *\n * `foldAgentToolCards` correlates a `tool_call` with its `tool_result` (by\n * `id`, falling back to FIFO-by-name) into a single card so consumers stop\n * hand-rolling `switch(event.type)`.\n */\nexport interface AgentToolCard {\n /** Correlation id (the event `id`, or a synthesized `tool-<index>`). */\n id: string\n name: string\n args: Record<string, unknown>\n status: 'running' | 'success' | 'error'\n /** The `tool_result.data` payload, once the result arrives. */\n result?: unknown\n}\n\n/**\n * Classifies a `tool_result.data` payload as success/error. Injectable so the\n * correlator is decoupled from any specific tool-result envelope shape.\n */\nexport type ToolEnvelopeResolver = (data: unknown) => { error: boolean }\n\nexport interface FoldAgentToolCardsOptions {\n /** Override the default envelope classifier. */\n resolveEnvelope?: ToolEnvelopeResolver\n}\n\n/**\n * Default envelope resolver: an object (or a JSON STRING parsing to an object)\n * with `ok === false` is an error; everything else is success (conservative).\n * sdk-tools handlers return a JSON STRING, so string parsing is intentional.\n */\nexport function defaultResolveEnvelope(data: unknown): { error: boolean } {\n return { error: coerceObject(data)?.ok === false }\n}\n\nfunction coerceObject(data: unknown): { ok?: unknown } | undefined {\n if (typeof data === 'object' && data !== null) return data\n if (typeof data === 'string') {\n try {\n const parsed: unknown = JSON.parse(data)\n if (typeof parsed === 'object' && parsed !== null) return parsed\n } catch {\n return undefined\n }\n }\n return undefined\n}\n\n/**\n * Fold an `AgentEvent[]` into correlated {@link AgentToolCard}s (M5-2). Pure.\n *\n * Correlation: a `tool_result` matches its `tool_call` by `id` when both carry\n * one; otherwise it matches the oldest still-`running` card with the same\n * `name` (FIFO). An unmatched `tool_result` becomes its own finished card.\n * A `tool_call` with no result stays `running`. The error status comes from\n * `options.resolveEnvelope` (default {@link defaultResolveEnvelope}).\n */\nexport function foldAgentToolCards(\n events: readonly AgentEvent[],\n options: FoldAgentToolCardsOptions = {},\n): AgentToolCard[] {\n const resolve = options.resolveEnvelope ?? defaultResolveEnvelope\n const cards: AgentToolCard[] = []\n const byId = new Map<string, AgentToolCard>()\n const runningByName = new Map<string, AgentToolCard[]>()\n\n events.forEach((event, index) => {\n if (event.type === 'tool_call') {\n const card: AgentToolCard = {\n id: event.id ?? `tool-${index}`,\n name: event.name,\n args: event.args,\n status: 'running',\n }\n cards.push(card)\n // Index by id (when present) AND by name FIFO — the two indexes overlap so\n // a result can correlate even when call/result disagree on carrying an id.\n if (event.id !== undefined) byId.set(event.id, card)\n pushRunning(runningByName, event.name, card)\n } else if (event.type === 'tool_result') {\n const card = matchResultCard(event, index, byId, runningByName, cards)\n card.result = event.data\n card.status = resolve(event.data).error ? 'error' : 'success'\n }\n })\n\n return cards\n}\n\nfunction pushRunning(\n runningByName: Map<string, AgentToolCard[]>,\n name: string,\n card: AgentToolCard,\n): void {\n const queue = runningByName.get(name)\n if (queue) queue.push(card)\n else runningByName.set(name, [card])\n}\n\nfunction removeRunning(\n runningByName: Map<string, AgentToolCard[]>,\n name: string,\n card: AgentToolCard,\n): void {\n const queue = runningByName.get(name)\n if (!queue) return\n const at = queue.indexOf(card)\n if (at >= 0) queue.splice(at, 1)\n}\n\nfunction matchResultCard(\n event: Extract<AgentEvent, { type: 'tool_result' }>,\n index: number,\n byId: Map<string, AgentToolCard>,\n runningByName: Map<string, AgentToolCard[]>,\n cards: AgentToolCard[],\n): AgentToolCard {\n // 1. Exact id match — consume from both indexes so it is matched at most once.\n if (event.id !== undefined) {\n const byIdCard = byId.get(event.id)\n if (byIdCard) {\n byId.delete(event.id)\n removeRunning(runningByName, byIdCard.name, byIdCard)\n return byIdCard\n }\n }\n // 2. FIFO-by-name fallback — works even if the call carried an id the result\n // omits (or vice-versa). Drop the matched card's id entry too.\n const fifo = runningByName.get(event.name)?.shift()\n if (fifo) {\n byId.delete(fifo.id)\n return fifo\n }\n // 3. Orphan result — surface it as its own finished card (never drop a result).\n const orphan: AgentToolCard = {\n id: event.id ?? `tool-${index}`,\n name: event.name,\n args: {},\n status: 'running',\n }\n cards.push(orphan)\n return orphan\n}\n","import { useMemo } from 'react'\n\nimport {\n type AgentToolCard,\n type FoldAgentToolCardsOptions,\n foldAgentToolCards,\n} from './agent-tool-cards.js'\nimport {\n type UseAgentStreamOptions,\n type UseAgentStreamReturn,\n useAgentStream,\n} from './use-agent-stream.js'\n\n/** {@link useAgentToolCards} return — the stream result plus correlated tool cards. */\nexport interface UseAgentToolCardsReturn<TBody = unknown> extends UseAgentStreamReturn<TBody> {\n /** Correlated tool cards folded from the stream events (M5-2). */\n toolCards: AgentToolCard[]\n}\n\n/**\n * `useAgentStream` + correlated tool cards (M5-2). Composes the stream hook with\n * the pure {@link foldAgentToolCards} reducer; pass `resolveEnvelope` to classify\n * tool-result payloads (default flags `{ ok: false }` envelopes as errors).\n */\nexport function useAgentToolCards<TBody = unknown>(\n path: string,\n options: UseAgentStreamOptions & FoldAgentToolCardsOptions = {},\n): UseAgentToolCardsReturn<TBody> {\n const { resolveEnvelope, ...streamOptions } = options\n const stream = useAgentStream<TBody>(path, streamOptions)\n const toolCards = useMemo(\n () => foldAgentToolCards(stream.events, { resolveEnvelope }),\n [stream.events, resolveEnvelope],\n )\n return { ...stream, toolCards }\n}\n","import type { UIMessage, UIMessageChunk } from 'ai'\n\n/**\n * M2 (theokit-ai-first) — read a TheoKit agent endpoint's `UIMessageStream` SSE `Response`\n * into reconstructed assistant `UIMessage`s, reusing the `ai` package's own consumer\n * primitives (`parseJsonEventStream` + `readUIMessageStream`) — the exact path\n * `@ai-sdk/react`'s `useChat` runs internally. No reinvented wire parser (Rule 9).\n *\n * `ai` is an OPTIONAL peer dependency, so it is imported dynamically: an app that never\n * calls an agent never pays for it, and importing `theokit/client` does not hard-require\n * `ai` (mirrors how the agent runtime dynamically imports `@theokit/sdk`). An agent app\n * always has `ai` installed (it is the UIMessageStream consumer).\n *\n * `onMessage` is invoked on every reconstruction step with the latest snapshot of the\n * assistant message, so a caller (the `useAgent` hook) can render streaming updates.\n */\nexport async function consumeUIMessageStream(\n response: Response,\n onMessage: (message: UIMessage) => void,\n): Promise<void> {\n if (response.body === null) return\n\n const { parseJsonEventStream, readUIMessageStream, uiMessageChunkSchema } = await import('ai')\n\n // ai validates each SSE JSON frame against its own strict chunk schema (the exact\n // gate `useChat` runs), then yields `{ success, value }`; forward the valid chunks.\n const parsed = parseJsonEventStream({ stream: response.body, schema: uiMessageChunkSchema })\n const chunkStream = new ReadableStream<UIMessageChunk>({\n async start(controller) {\n for await (const result of parsed) {\n if (result.success) controller.enqueue(result.value)\n }\n controller.close()\n },\n })\n\n for await (const message of readUIMessageStream({ stream: chunkStream })) {\n onMessage(message)\n }\n}\n","import type { UIMessage } from 'ai'\nimport { useCallback, useRef, useState } from 'react'\n\nimport { consumeUIMessageStream } from './consume-ui-message-stream.js'\n\n/**\n * M2 (theokit-ai-first) — `useAgent`, the typed client hook for the `agents/*.ts` convention.\n *\n * A thin React hook over `consumeUIMessageStream` (which reuses `ai`'s own UIMessageStream\n * reader). `useAgent('support')` binds to `POST /api/agents/support`; the generated\n * `@theo/agents` module (`.theokit/agents.d.ts`) types `send` to the agent's `input` schema,\n * so the request shape is inferred end-to-end from the server `defineAgent({ input })` with\n * ZERO manual wiring (DoD line 2).\n *\n * Transport mirrors `useAgentStream`: fetch + ReadableStream (POST needs a body; EventSource\n * is GET-only). `ai` is loaded lazily by `consumeUIMessageStream` so non-agent apps never\n * pay for it.\n */\nexport type UseAgentStatus = 'idle' | 'streaming' | 'done' | 'error'\n\nexport interface UseAgentReturn<TInput = unknown> {\n /** Reconstructed assistant messages so far (ai `UIMessage[]`). */\n messages: UIMessage[]\n status: UseAgentStatus\n /** The last error, or `undefined`. */\n error: Error | undefined\n /** Send a request; opens a new stream. Typed to the agent's `input` schema. */\n send: (input: TInput) => void\n /** Abort an in-flight stream. */\n abort: () => void\n /** Clear messages + error, back to idle. */\n reset: () => void\n}\n\nexport interface UseAgentOptions {\n /** Extra request headers (e.g., auth). */\n headers?: Record<string, string>\n /** Override fetch (primarily for tests). */\n fetch?: typeof fetch\n}\n\n/**\n * Bind to the agent endpoint at `path` (`/api/agents/<name>`). Prefer the generated\n * `useAgent` from `@theo/agents` (typed by agent name); this base accepts an explicit path.\n */\nexport function useAgent<TInput = unknown>(\n path: string,\n options: UseAgentOptions = {},\n): UseAgentReturn<TInput> {\n const [messages, setMessages] = useState<UIMessage[]>([])\n const [status, setStatus] = useState<UseAgentStatus>('idle')\n const [error, setError] = useState<Error | undefined>(undefined)\n const controllerRef = useRef<AbortController | null>(null)\n\n const abort = useCallback(() => {\n controllerRef.current?.abort()\n controllerRef.current = null\n }, [])\n\n const reset = useCallback(() => {\n abort()\n setMessages([])\n setError(undefined)\n setStatus('idle')\n }, [abort])\n\n const send = useCallback(\n (input: TInput) => {\n abort()\n const controller = new AbortController()\n controllerRef.current = controller\n setMessages([])\n setError(undefined)\n setStatus('streaming')\n\n const fetchImpl = options.fetch ?? globalThis.fetch\n void (async () => {\n try {\n const response = await fetchImpl(path, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n accept: 'text/event-stream',\n 'X-Theo-Action': '1',\n ...options.headers,\n },\n body: JSON.stringify(input),\n signal: controller.signal,\n })\n await consumeUIMessageStream(response, (message) => {\n setMessages((prev) => {\n const next = [...prev]\n const idx = next.findIndex((m) => m.id === message.id)\n if (idx >= 0) next[idx] = message\n else next.push(message)\n return next\n })\n })\n setStatus('done')\n } catch (err) {\n if (controller.signal.aborted) return\n setError(err instanceof Error ? err : new Error(String(err)))\n setStatus('error')\n }\n })()\n },\n [abort, options.fetch, options.headers, path],\n )\n\n return { messages, status, error, send, abort, reset }\n}\n","/**\n * <Link> — React Router Link with route prefetching.\n *\n * Wraps react-router's <Link> with prefetch behavior:\n * - `intent` (default): prefetch on hover + focus (~200ms before click)\n * - `viewport`: prefetch when visible (IntersectionObserver)\n * - `none`: no prefetch (same as plain react-router Link)\n *\n * Uses `<link rel=\"prefetch\">` (not modulepreload) because route paths\n * can be prefetched directly — no Vite manifest resolution needed (EC-1).\n */\nimport {\n Link as RouterLink,\n type LinkProps as RouterLinkProps,\n} from 'react-router'\nimport { useRef, useCallback, useEffect } from 'react'\n\nexport type PrefetchBehavior = 'none' | 'intent' | 'viewport'\n\nexport interface LinkProps extends RouterLinkProps {\n /** Prefetch strategy. Default: 'intent' (on hover + focus). */\n prefetch?: PrefetchBehavior\n}\n\n/** Deduplication — each URL prefetched at most once per session. */\nconst prefetched = new Set<string>()\n\nfunction injectPrefetch(href: string): void {\n // EC-2: SSR guard — document unavailable on server\n if (typeof document === 'undefined') return\n if (prefetched.has(href)) return\n prefetched.add(href)\n\n const link = document.createElement('link')\n link.rel = 'prefetch'\n link.href = href\n document.head.appendChild(link)\n}\n\nfunction resolveTo(to: LinkProps['to']): string {\n if (typeof to === 'string') return to\n return to?.pathname ?? ''\n}\n\n/**\n * TheoKit Link — drop-in replacement for react-router Link with prefetch.\n *\n * @example\n * ```tsx\n * import { Link } from 'theokit/client'\n *\n * <Link to=\"/contacts\">Contacts</Link>\n * <Link to=\"/dashboard\" prefetch=\"viewport\">Dashboard</Link>\n * <Link to=\"/settings\" prefetch=\"none\">Settings</Link>\n * ```\n */\nexport function Link({ prefetch = 'intent', to, onMouseEnter, onFocus, ...rest }: LinkProps) {\n const ref = useRef<HTMLAnchorElement>(null)\n\n const handleIntent = useCallback(\n (event: React.MouseEvent<HTMLAnchorElement> | React.FocusEvent<HTMLAnchorElement>) => {\n if (prefetch === 'intent') {\n injectPrefetch(resolveTo(to))\n }\n // Forward original handlers\n if (event.type === 'mouseenter' && onMouseEnter) {\n ;(onMouseEnter as React.MouseEventHandler<HTMLAnchorElement>)(event as React.MouseEvent<HTMLAnchorElement>)\n }\n if (event.type === 'focus' && onFocus) {\n ;(onFocus as React.FocusEventHandler<HTMLAnchorElement>)(event as React.FocusEvent<HTMLAnchorElement>)\n }\n },\n [prefetch, to, onMouseEnter, onFocus],\n )\n\n // Viewport mode: IntersectionObserver\n useEffect(() => {\n if (prefetch !== 'viewport' || !ref.current) return\n if (typeof IntersectionObserver === 'undefined') return // SSR guard\n\n const observer = new IntersectionObserver(\n ([entry]) => {\n if (entry.isIntersecting) {\n injectPrefetch(resolveTo(to))\n observer.disconnect()\n }\n },\n { rootMargin: '200px' }, // prefetch slightly before visible\n )\n observer.observe(ref.current)\n return () => observer.disconnect()\n }, [prefetch, to])\n\n return (\n <RouterLink\n ref={ref}\n to={to}\n onMouseEnter={handleIntent}\n onFocus={handleIntent}\n {...rest}\n />\n )\n}\n","/**\n * <Metadata> — SEO-ready head tags from a single component.\n *\n * Uses React 19's native <title>/<meta>/<link> hoisting to <head>.\n * No build-time extraction needed — works in SSR and client.\n *\n * @example\n * ```tsx\n * import { Metadata } from 'theokit/client'\n *\n * export default function ContactsPage() {\n * return (\n * <>\n * <Metadata\n * title=\"Contacts | My CRM\"\n * description=\"Manage your contacts\"\n * ogImage=\"/og/contacts.png\"\n * canonical=\"https://mycrm.com/contacts\"\n * />\n * <h1>Contacts</h1>\n * </>\n * )\n * }\n * ```\n */\n\nexport interface MetadataProps {\n title?: string\n description?: string\n canonical?: string\n ogTitle?: string\n ogDescription?: string\n ogImage?: string\n ogType?: string\n ogUrl?: string\n twitterCard?: 'summary' | 'summary_large_image'\n /** Custom meta tags rendered as children */\n children?: React.ReactNode\n}\n\nexport function Metadata(props: MetadataProps) {\n const ogTitle = props.ogTitle ?? props.title\n const ogDesc = props.ogDescription ?? props.description\n\n return (\n <>\n {props.title && <title>{props.title}</title>}\n {props.description && <meta name=\"description\" content={props.description} />}\n {props.canonical && <link rel=\"canonical\" href={props.canonical} />}\n {ogTitle && <meta property=\"og:title\" content={ogTitle} />}\n {ogDesc && <meta property=\"og:description\" content={ogDesc} />}\n {props.ogImage && <meta property=\"og:image\" content={props.ogImage} />}\n {props.ogType && <meta property=\"og:type\" content={props.ogType} />}\n {props.ogUrl && <meta property=\"og:url\" content={props.ogUrl} />}\n {props.twitterCard && <meta name=\"twitter:card\" content={props.twitterCard} />}\n {props.children}\n </>\n )\n}\n","/**\n * <Image> — optimized image component with lazy loading.\n *\n * Renders a standard <img> with:\n * - loading=\"lazy\" by default (eager with priority={true})\n * - decoding=\"async\" for non-blocking decode\n * - width/height for CLS prevention\n * - srcSet/sizes forwarded for responsive images\n *\n * No CDN, no Sharp, no build-time optimization — pure HTML attributes\n * that deliver 80% of the performance value at zero complexity.\n *\n * @example\n * ```tsx\n * import { Image } from 'theokit/client'\n *\n * <Image src=\"/team.jpg\" alt=\"Team photo\" width={800} height={600} />\n * <Image src=\"/hero.jpg\" alt=\"Hero\" priority />\n * <Image\n * src=\"/product.jpg\"\n * alt=\"Product\"\n * width={400}\n * height={300}\n * srcSet=\"/product-400.jpg 400w, /product-800.jpg 800w\"\n * sizes=\"(max-width: 768px) 100vw, 400px\"\n * />\n * ```\n */\n\nexport interface ImageProps extends React.ImgHTMLAttributes<HTMLImageElement> {\n /** Image source URL (required). */\n src: string\n /** Alt text for accessibility (required). */\n alt: string\n /** If true, loading=\"eager\" — use for above-the-fold images. */\n priority?: boolean\n}\n\nexport function Image({ priority, loading, decoding, ...props }: ImageProps) {\n return (\n <img\n loading={loading ?? (priority ? 'eager' : 'lazy')}\n decoding={decoding ?? 'async'}\n {...props}\n />\n )\n}\n"],"mappings":"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","names":["useMemo","useMemo","useCallback","useRef","useState","useState","useRef","useCallback","useRef","useCallback","useEffect","jsx","jsx"]}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { IncomingMessage } from 'node:http';
|
|
2
|
+
import { A as AuditLogger } from './audit-log-BQWM5YLG.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* CSRF enforcement mode.
|
|
6
|
+
*
|
|
7
|
+
* - `off` — skip CSRF entirely. Use only when you have another defense
|
|
8
|
+
* (e.g. you don't ship session cookies, all auth is bearer).
|
|
9
|
+
* - `warn` — log a structured warning when the check would fail, but
|
|
10
|
+
* still serve the request. Default for 0.2.0. Migration mode.
|
|
11
|
+
* - `strict` — reject failing requests with 403 + code `CSRF_INVALID`.
|
|
12
|
+
* Will become the default in 0.3.0.
|
|
13
|
+
*/
|
|
14
|
+
type CsrfMode = 'off' | 'warn' | 'strict';
|
|
15
|
+
/**
|
|
16
|
+
* Per-request structured logger surface. Only `warn` is used by enforceCsrf;
|
|
17
|
+
* we don't require a full Logger here so callers can pass a mock or the
|
|
18
|
+
* console directly.
|
|
19
|
+
*/
|
|
20
|
+
interface CsrfLogger {
|
|
21
|
+
warn: (payload: CsrfWarnPayload) => void;
|
|
22
|
+
/** Optional path the request was destined for — used for log correlation. */
|
|
23
|
+
path?: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* T5.1 — Rails-inspired per-route escalation.
|
|
27
|
+
*
|
|
28
|
+
* `routes` accepts string (exact match) or RegExp entries. When a request
|
|
29
|
+
* path matches AND the request would otherwise emit a warning, the
|
|
30
|
+
* `behavior` field decides what happens:
|
|
31
|
+
*
|
|
32
|
+
* - `'warn'` → normal warn dispatch (no-op vs default)
|
|
33
|
+
* - `'raise'` → escalate to 403 regardless of global `csrf` mode
|
|
34
|
+
*
|
|
35
|
+
* `'raise'` never downgrades: when global mode is `'off'`, validation is
|
|
36
|
+
* skipped entirely and disallowed dispatch never runs.
|
|
37
|
+
*/
|
|
38
|
+
interface DisallowedConfig {
|
|
39
|
+
routes: (string | RegExp)[];
|
|
40
|
+
behavior: 'warn' | 'raise';
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Test whether `path` matches any of the supplied patterns. String
|
|
44
|
+
* patterns are EXACT (trailing slash matters — use RegExp for tolerance).
|
|
45
|
+
*
|
|
46
|
+
* EC-5: when a RegExp carries the `/g` flag, `.test()` mutates
|
|
47
|
+
* `lastIndex` and the next invocation may miss. We reset `lastIndex`
|
|
48
|
+
* before each test so the matcher is a pure function.
|
|
49
|
+
*/
|
|
50
|
+
declare function matchDisallowed(path: string, patterns: readonly (string | RegExp)[]): boolean;
|
|
51
|
+
/**
|
|
52
|
+
* T2.2 — Stable cutover identifier shipped with every csrf.warn payload.
|
|
53
|
+
*
|
|
54
|
+
* Convention borrowed from Vite's `deprecations.ts:74` — a `code` plus a
|
|
55
|
+
* `docsUrl` lets users (a) grep their logs for a single stable identifier
|
|
56
|
+
* to find every csrf.warn line, and (b) click through directly to the
|
|
57
|
+
* migration guide. Strings are exported constants so the analyzer (T2.3)
|
|
58
|
+
* and migration guide can reference the same source of truth.
|
|
59
|
+
*/
|
|
60
|
+
declare const CSRF_WARN_CODE: "CSRF_STRICT_CUTOVER";
|
|
61
|
+
declare const CSRF_WARN_DOCS_URL: "https://theokit.dev/upgrade/csrf-strict-cutover";
|
|
62
|
+
interface CsrfWarnPayload {
|
|
63
|
+
event: 'csrf.warn';
|
|
64
|
+
method: string;
|
|
65
|
+
path: string | undefined;
|
|
66
|
+
reason: string;
|
|
67
|
+
/**
|
|
68
|
+
* Stable identifier for the 0.2 → 0.3 CSRF strict cutover. Always
|
|
69
|
+
* `'CSRF_STRICT_CUTOVER'`. Grep-able from prod logs.
|
|
70
|
+
*/
|
|
71
|
+
code: string;
|
|
72
|
+
/**
|
|
73
|
+
* Link to the section of the migration guide explaining how to clear
|
|
74
|
+
* this specific warning class.
|
|
75
|
+
*/
|
|
76
|
+
docsUrl: string;
|
|
77
|
+
}
|
|
78
|
+
declare function validateCsrf(req: IncomingMessage): {
|
|
79
|
+
valid: true;
|
|
80
|
+
} | {
|
|
81
|
+
valid: false;
|
|
82
|
+
reason: string;
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* T5a.2 Phase B (slice 1/6) — Web-Standards-shaped CSRF validator.
|
|
86
|
+
*
|
|
87
|
+
* Mirror of `validateCsrf(req: IncomingMessage)` for the Web `Request`
|
|
88
|
+
* shape. Consumes `request.headers.get(name)` (native Web `Headers` API)
|
|
89
|
+
* instead of `req.headers[name]` (Node `IncomingMessage` indexer). Same
|
|
90
|
+
* CSRF policy + same return shape — the difference is only the input
|
|
91
|
+
* extraction.
|
|
92
|
+
*
|
|
93
|
+
* Used by `executeWebRequest` (T5a.2 Phase A) to enforce CSRF on the
|
|
94
|
+
* Web-Standards request handler entry-point.
|
|
95
|
+
*/
|
|
96
|
+
declare function validateCsrfRequest(request: Request): {
|
|
97
|
+
valid: true;
|
|
98
|
+
} | {
|
|
99
|
+
valid: false;
|
|
100
|
+
reason: string;
|
|
101
|
+
};
|
|
102
|
+
declare function enforceCsrf(req: IncomingMessage, mode: CsrfMode, logger?: CsrfLogger, disallowed?: DisallowedConfig, auditLogger?: AuditLogger): {
|
|
103
|
+
allow: boolean;
|
|
104
|
+
reason?: string;
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
export { CSRF_WARN_CODE as C, type DisallowedConfig as D, CSRF_WARN_DOCS_URL as a, type CsrfLogger as b, type CsrfMode as c, type CsrfWarnPayload as d, enforceCsrf as e, validateCsrfRequest as f, matchDisallowed as m, validateCsrf as v };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* T2.2 — In-memory bounded counter for CSRF warn events.
|
|
3
|
+
*
|
|
4
|
+
* Aggregates `csrf.warn` payloads by `(method, path, reason)` triple.
|
|
5
|
+
* Used by the `/__theo/csrf-readiness` endpoint to expose a summary the
|
|
6
|
+
* developer (or devtools tab) can inspect, so users do NOT need to grep
|
|
7
|
+
* stdout to know which endpoints will break under 0.3.0 strict CSRF.
|
|
8
|
+
*
|
|
9
|
+
* Bounded at 1000 distinct keys (EC-22). Eviction is LRU-by-insertion —
|
|
10
|
+
* when the cap is hit, the oldest key is dropped and a re-record of an
|
|
11
|
+
* evicted key starts fresh (count: 1).
|
|
12
|
+
*
|
|
13
|
+
* Single-threaded by virtue of the JS event loop; Map operations are
|
|
14
|
+
* atomic. NOT shared across processes — each worker has its own store.
|
|
15
|
+
*/
|
|
16
|
+
interface CsrfWarnRecord {
|
|
17
|
+
method: string;
|
|
18
|
+
path: string;
|
|
19
|
+
reason: string;
|
|
20
|
+
}
|
|
21
|
+
interface CsrfReadinessRouteSummary {
|
|
22
|
+
method: string;
|
|
23
|
+
path: string;
|
|
24
|
+
reason: string;
|
|
25
|
+
count: number;
|
|
26
|
+
firstSeen: string;
|
|
27
|
+
lastSeen: string;
|
|
28
|
+
}
|
|
29
|
+
interface CsrfReadinessSummary {
|
|
30
|
+
generatedAt: string;
|
|
31
|
+
totalEvents: number;
|
|
32
|
+
routes: CsrfReadinessRouteSummary[];
|
|
33
|
+
}
|
|
34
|
+
declare class CsrfReadinessStore {
|
|
35
|
+
static readonly MAX_ENTRIES = 1000;
|
|
36
|
+
private readonly entries;
|
|
37
|
+
private keyFor;
|
|
38
|
+
record(event: CsrfWarnRecord): void;
|
|
39
|
+
summary(): CsrfReadinessSummary;
|
|
40
|
+
reset(): void;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export { CsrfReadinessStore as C, type CsrfReadinessRouteSummary as a, type CsrfReadinessSummary as b, type CsrfWarnRecord as c };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { IncomingMessage } from 'node:http';
|
|
2
|
+
|
|
3
|
+
interface WebSocketLike {
|
|
4
|
+
send(data: string | Buffer): void;
|
|
5
|
+
close(code?: number, reason?: string): void;
|
|
6
|
+
}
|
|
7
|
+
interface WebSocketHandler {
|
|
8
|
+
onOpen?: (ws: WebSocketLike, req: IncomingMessage) => void;
|
|
9
|
+
onMessage?: (ws: WebSocketLike, data: string | Buffer) => void;
|
|
10
|
+
onClose?: (ws: WebSocketLike, code: number, reason: Buffer) => void;
|
|
11
|
+
onError?: (ws: WebSocketLike, error: Error) => void;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Define a WebSocket endpoint handler.
|
|
15
|
+
* Identity function — provides type inference for WebSocket handlers.
|
|
16
|
+
*/
|
|
17
|
+
declare function defineWebSocket(handler: WebSocketHandler): WebSocketHandler;
|
|
18
|
+
/**
|
|
19
|
+
* T5a.2 Phase F slice 3/3 — Web-Standards WebSocket endpoint handler.
|
|
20
|
+
*
|
|
21
|
+
* Mirror of `WebSocketHandler` for the Web `Request` shape. `onOpen`
|
|
22
|
+
* receives `request: Request` instead of `req: IncomingMessage`. The
|
|
23
|
+
* rest of the lifecycle (onMessage, onClose, onError) is shape-agnostic
|
|
24
|
+
* (`WebSocketLike` is already Web-standards-compatible per the existing
|
|
25
|
+
* design — `send(string | Buffer)` works on both Node `ws` and Web
|
|
26
|
+
* `WebSocket` instances; CF Workers / Bun / Deno coerce as needed at
|
|
27
|
+
* the adapter boundary).
|
|
28
|
+
*
|
|
29
|
+
* Per `docs/plans/t5a2-incoming-message-to-request-shape-refactor-plan.md`
|
|
30
|
+
* v1.0 § Phase F (closes Phase F).
|
|
31
|
+
*
|
|
32
|
+
* **Architectural note — WebSocket upgrade semantics differ across runtimes:**
|
|
33
|
+
* - Node + `ws`: `WebSocketServer.handleUpgrade(req, socket, head, cb)` —
|
|
34
|
+
* `req` is `IncomingMessage`. Use `WebSocketHandler`.
|
|
35
|
+
* - CF Workers: `new WebSocketPair()` + `request.headers` (the upgrade
|
|
36
|
+
* handshake IS a Web Request). Use `WebSocketHandlerWeb`.
|
|
37
|
+
* - Bun: `server.upgrade(request, { data })` — same Web Request shape.
|
|
38
|
+
* - Deno: `Deno.upgradeWebSocket(request)` — same Web Request shape.
|
|
39
|
+
*
|
|
40
|
+
* Cross-runtime WebSocket endpoints ship BOTH `WebSocketHandler` +
|
|
41
|
+
* `WebSocketHandlerWeb` exports; the runtime adapter picks the matching
|
|
42
|
+
* one. This is the canonical Hono / Nitric pattern.
|
|
43
|
+
*/
|
|
44
|
+
interface WebSocketHandlerWeb {
|
|
45
|
+
onOpen?: (ws: WebSocketLike, request: Request) => void;
|
|
46
|
+
onMessage?: (ws: WebSocketLike, data: string | Uint8Array) => void;
|
|
47
|
+
onClose?: (ws: WebSocketLike, code: number, reason: string) => void;
|
|
48
|
+
onError?: (ws: WebSocketLike, error: Error) => void;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Web-Standards `defineWebSocket` sibling. Identity function — provides
|
|
52
|
+
* type inference for Web WebSocket handlers.
|
|
53
|
+
*
|
|
54
|
+
* **Type difference note vs Node path:**
|
|
55
|
+
* - `onMessage` data is `string | Uint8Array` instead of `string | Buffer`
|
|
56
|
+
* (Web standards have no `Buffer`; Node's Buffer is a Uint8Array
|
|
57
|
+
* subclass so the Node path's Buffer values flow through unchanged
|
|
58
|
+
* when adapters wrap them).
|
|
59
|
+
* - `onClose` reason is `string` instead of `Buffer` (Web `CloseEvent`
|
|
60
|
+
* exposes the reason as a UTF-8 string natively).
|
|
61
|
+
*/
|
|
62
|
+
declare function defineWebSocketWeb(handler: WebSocketHandlerWeb): WebSocketHandlerWeb;
|
|
63
|
+
|
|
64
|
+
export { type WebSocketHandler as W, type WebSocketHandlerWeb as a, type WebSocketLike as b, defineWebSocketWeb as c, defineWebSocket as d };
|
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import "tsx/esm";
|
|
3
|
-
import {
|
|
4
|
-
preflightNodeAndBindings
|
|
5
|
-
} from "./chunk-HNBWZKIQ.js";
|
|
6
3
|
import {
|
|
7
4
|
validateProjectStructure
|
|
8
5
|
} from "./chunk-JQSFBJR5.js";
|
|
6
|
+
import {
|
|
7
|
+
preflightNodeAndBindings
|
|
8
|
+
} from "./chunk-HNBWZKIQ.js";
|
|
9
9
|
import {
|
|
10
10
|
theoPluginAsync
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import "./chunk-
|
|
11
|
+
} from "./chunk-O62MW4MT.js";
|
|
12
|
+
import "./chunk-UNLA45FY.js";
|
|
13
13
|
import {
|
|
14
14
|
loadConfig,
|
|
15
15
|
loadEnv
|
|
16
16
|
} from "./chunk-7YZHAQU7.js";
|
|
17
|
-
import "./chunk-NAZ4E2GT.js";
|
|
18
|
-
import "./chunk-GFMQJHXX.js";
|
|
19
17
|
import "./chunk-YJAUJXZS.js";
|
|
20
18
|
import {
|
|
21
19
|
orchestrateDev
|
|
22
20
|
} from "./chunk-45C3WUQ7.js";
|
|
23
21
|
import "./chunk-5ODOE6EF.js";
|
|
22
|
+
import "./chunk-KXA37ONC.js";
|
|
23
|
+
import "./chunk-WR4F4EEZ.js";
|
|
24
|
+
import "./chunk-F4YUPDJ2.js";
|
|
25
|
+
import "./chunk-BQDGES7C.js";
|
|
24
26
|
import "./chunk-HGZL5EOI.js";
|
|
25
27
|
import "./chunk-IEES3CHD.js";
|
|
26
|
-
import "./chunk-3LVRAGAZ.js";
|
|
27
|
-
import "./chunk-6FYD34NX.js";
|
|
28
28
|
|
|
29
29
|
// src/cli/commands/dev.ts
|
|
30
30
|
import react from "@vitejs/plugin-react";
|
|
@@ -99,4 +99,4 @@ export {
|
|
|
99
99
|
devCommand,
|
|
100
100
|
startDevServer
|
|
101
101
|
};
|
|
102
|
-
//# sourceMappingURL=dev-
|
|
102
|
+
//# sourceMappingURL=dev-OWW4XVIH.js.map
|
|
@@ -6,8 +6,8 @@ import {
|
|
|
6
6
|
} from "./chunk-JAIKGP3Q.js";
|
|
7
7
|
import {
|
|
8
8
|
generateManifest
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
9
|
+
} from "./chunk-F4YUPDJ2.js";
|
|
10
|
+
import "./chunk-BQDGES7C.js";
|
|
11
11
|
|
|
12
12
|
// src/vite-plugin/openapi-emit/dev-emit.ts
|
|
13
13
|
var inFlight = false;
|
|
@@ -39,4 +39,4 @@ export {
|
|
|
39
39
|
_resetInFlightForTests,
|
|
40
40
|
reEmitOpenApi
|
|
41
41
|
};
|
|
42
|
-
//# sourceMappingURL=dev-emit-
|
|
42
|
+
//# sourceMappingURL=dev-emit-5MDSBP5D.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
generateManifest
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-2J7XU3PW.js";
|
|
4
4
|
import "./chunk-WSJKACWB.js";
|
|
5
5
|
import "./chunk-X2VVCJ4V.js";
|
|
6
6
|
import "./chunk-DGUM43GV.js";
|
|
@@ -337,4 +337,4 @@ export {
|
|
|
337
337
|
_resetInFlightForTests,
|
|
338
338
|
reEmitOpenApi
|
|
339
339
|
};
|
|
340
|
-
//# sourceMappingURL=dev-emit-
|
|
340
|
+
//# sourceMappingURL=dev-emit-QH2YGZXN.js.map
|