theokit 0.25.0 → 0.27.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/{agent-GXJNFW6N.js → agent-I5QEOMCN.js} +2 -2
- package/dist/{agents-typed-client-RIJVHSX4.js → agents-typed-client-5DCGDWFZ.js} +8 -2
- package/dist/agents-typed-client-5DCGDWFZ.js.map +1 -0
- package/dist/{agents-typed-client-DCPSXUU5.js → agents-typed-client-MAAILRI6.js} +8 -2
- package/dist/agents-typed-client-MAAILRI6.js.map +1 -0
- package/dist/{build-WD2PT5TA.js → build-V2QEBE7I.js} +2 -2
- package/dist/{chunk-2JNG3P4Y.js → chunk-R4VVXLKZ.js} +2 -2
- package/dist/{chunk-GG6H76GC.js → chunk-VRVNM3QL.js} +2 -2
- package/dist/{chunk-LVGDYTU2.js → chunk-Y4TOVMNC.js} +2 -2
- package/dist/cli/index.js +4 -4
- package/dist/client/index.d.ts +177 -19
- package/dist/client/index.js +314 -62
- package/dist/client/index.js.map +1 -1
- package/dist/{dev-63UNEUF6.js → dev-5ZQMWVFC.js} +2 -2
- package/dist/index.js +1 -1
- package/dist/{mcp-MIZFVNCL.js → mcp-VMKWB2BY.js} +2 -2
- package/dist/server/index.d.ts +10 -5
- package/dist/server/index.js +31 -7
- package/dist/server/index.js.map +1 -1
- package/dist/vite-plugin/index.js +1 -1
- package/dist/{vite-plugin-ST4JZQRJ.js → vite-plugin-BNI7YLCD.js} +2 -2
- package/package.json +1 -1
- package/dist/agents-typed-client-DCPSXUU5.js.map +0 -1
- package/dist/agents-typed-client-RIJVHSX4.js.map +0 -1
- /package/dist/{agent-GXJNFW6N.js.map → agent-I5QEOMCN.js.map} +0 -0
- /package/dist/{build-WD2PT5TA.js.map → build-V2QEBE7I.js.map} +0 -0
- /package/dist/{chunk-2JNG3P4Y.js.map → chunk-R4VVXLKZ.js.map} +0 -0
- /package/dist/{chunk-GG6H76GC.js.map → chunk-VRVNM3QL.js.map} +0 -0
- /package/dist/{chunk-LVGDYTU2.js.map → chunk-Y4TOVMNC.js.map} +0 -0
- /package/dist/{dev-63UNEUF6.js.map → dev-5ZQMWVFC.js.map} +0 -0
- /package/dist/{mcp-MIZFVNCL.js.map → mcp-VMKWB2BY.js.map} +0 -0
- /package/dist/{vite-plugin-ST4JZQRJ.js.map → vite-plugin-BNI7YLCD.js.map} +0 -0
|
@@ -3,7 +3,7 @@ import "tsx/esm";
|
|
|
3
3
|
import {
|
|
4
4
|
agentCommand,
|
|
5
5
|
createAgentSsrLoader
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-Y4TOVMNC.js";
|
|
7
7
|
import "./chunk-M6NMS5LR.js";
|
|
8
8
|
import "./chunk-GDN3PXFH.js";
|
|
9
9
|
import "./chunk-TERFLG67.js";
|
|
@@ -12,4 +12,4 @@ export {
|
|
|
12
12
|
agentCommand,
|
|
13
13
|
createAgentSsrLoader
|
|
14
14
|
};
|
|
15
|
-
//# sourceMappingURL=agent-
|
|
15
|
+
//# sourceMappingURL=agent-I5QEOMCN.js.map
|
|
@@ -48,13 +48,19 @@ ${entries.join("\n")}
|
|
|
48
48
|
return `${FILE_HEADER}
|
|
49
49
|
declare module '@theo/agents' {
|
|
50
50
|
import type { InferAgentInput, InferAgentToolNames } from '@theokit/agents'
|
|
51
|
-
import type { UseAgentReturn } from 'theokit/client'
|
|
51
|
+
import type { UseAgentReturn, AgentTransport } from 'theokit/client'
|
|
52
52
|
${importBlock}
|
|
53
53
|
export interface AppAgents ${body}
|
|
54
54
|
|
|
55
|
+
// Web (and any HTTP surface): bind by agent name \u2014 \`send\` is typed to the agent's \`input\` schema.
|
|
55
56
|
export function useAgent<K extends keyof AppAgents>(
|
|
56
57
|
name: K,
|
|
57
58
|
): UseAgentReturn<AppAgents[K]['input'], AppAgents[K]['tools']>
|
|
59
|
+
// M41 (ADR-0050) \u2014 terminal/desktop (and advanced): bind by an explicit AgentTransport
|
|
60
|
+
// (e.g. InProcessTransport). The SAME hook, one consumption shape across every surface.
|
|
61
|
+
export function useAgent<TInput = unknown>(
|
|
62
|
+
transport: AgentTransport,
|
|
63
|
+
): UseAgentReturn<TInput>
|
|
58
64
|
}
|
|
59
65
|
`;
|
|
60
66
|
}
|
|
@@ -145,4 +151,4 @@ export {
|
|
|
145
151
|
agentsTypedClientPlugin,
|
|
146
152
|
generateAgentsDts
|
|
147
153
|
};
|
|
148
|
-
//# sourceMappingURL=agents-typed-client-
|
|
154
|
+
//# sourceMappingURL=agents-typed-client-5DCGDWFZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/vite-plugin/agents-typed-client.ts"],"sourcesContent":["/* eslint-disable security/detect-non-literal-fs-filename --\n * Codegen-time fs ops: all paths derive from `opts.projectRoot` / `opts.distDir`\n * (vite plugin opts — trusted, set by the framework's CLI). Never serves HTTP input.\n */\n/**\n * M2 (theokit-ai-first) — end-to-end typed binding for the `agents/*.ts` convention.\n *\n * Sibling of `app-typed-client.ts` (kept separate so the `@theo/client` output stays\n * byte-unchanged). Two parts:\n *\n * 1. `generateAgentsDts({ manifest, dtsOutPath, projectRoot })` — pure function emitting\n * `.theokit/agents.d.ts` (the virtual `@theo/agents` module) with `AppAgents` mapping\n * each scanned agent to `InferAgentInput` of its `defineAgent({ input })` schema, plus a\n * typed `useAgent` signature — so the client binds to `/api/agents/<name>` with the right\n * request type and ZERO manual wiring (DoD line 2).\n * 2. `agentsTypedClientPlugin(opts)` — Vite plugin that emits (1), rewrites on `agents/*`\n * changes, and serves the virtual `@theo/agents` runtime (`useAgent` from `theokit/client`).\n */\nimport { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs'\nimport { dirname, posix } from 'node:path'\n\nimport type { Plugin, ViteDevServer } from 'vite'\n\nimport type { TheoManifest } from '../server/internal-api.js'\n\nconst FILE_HEADER = `// AUTO-GENERATED by theokit — do not edit.\n// Source: theokit/packages/theo/src/vite-plugin/agents-typed-client.ts (M2).\n// To refresh: \\`pnpm dev\\` or \\`pnpm build\\` regenerates this on every agents/ change.\n\n/* eslint-disable */\n`\n\n/** A safe TS identifier alias for an agent (name may contain path separators). */\nfunction aliasFor(name: string): string {\n return `_agent_${name.replace(/[^\\w$]/g, '_')}`\n}\n\n/** Relative `import type` path from the .d.ts dir to the agent source (extension stripped). */\nfunction importPath(dtsOutPath: string, projectRoot: string, filePath: string): string {\n const fromDir = dirname(dtsOutPath).replace(/\\\\/g, '/')\n const abs = posix.join(projectRoot.replace(/\\\\/g, '/'), filePath.replace(/\\\\/g, '/'))\n const noExt = abs.replace(/\\.[jt]sx?$/, '')\n let rel = posix.relative(fromDir, noExt)\n if (!rel.startsWith('.')) rel = `./${rel}`\n return rel\n}\n\nexport interface GenerateAgentsDtsOptions {\n manifest: TheoManifest\n /** Absolute path to the .d.ts that will be emitted (drives the import paths). */\n dtsOutPath: string\n /** Absolute project root — agents live at `<projectRoot>/agents`. */\n projectRoot: string\n}\n\nexport function generateAgentsDts({\n manifest,\n dtsOutPath,\n projectRoot,\n}: GenerateAgentsDtsOptions): string {\n const agents = manifest.agents ?? []\n const imports: string[] = []\n const entries: string[] = []\n for (const agent of agents) {\n const alias = aliasFor(agent.name)\n imports.push(\n ` import type ${alias} from '${importPath(dtsOutPath, projectRoot, agent.filePath)}'`,\n )\n entries.push(\n ` '${agent.name}': { input: InferAgentInput<${alias}>; tools: InferAgentToolNames<${alias}> }`,\n )\n }\n\n const body =\n entries.length > 0\n ? `{\\n${entries.join('\\n')}\\n }`\n : `{\\n // No agents detected — add \\`agents/*.ts\\` to populate this binding.\\n }`\n\n const importBlock = imports.length > 0 ? `${imports.join('\\n')}\\n` : ''\n\n return `${FILE_HEADER}\ndeclare module '@theo/agents' {\n import type { InferAgentInput, InferAgentToolNames } from '@theokit/agents'\n import type { UseAgentReturn, AgentTransport } from 'theokit/client'\n${importBlock}\n export interface AppAgents ${body}\n\n // Web (and any HTTP surface): bind by agent name — \\`send\\` is typed to the agent's \\`input\\` schema.\n export function useAgent<K extends keyof AppAgents>(\n name: K,\n ): UseAgentReturn<AppAgents[K]['input'], AppAgents[K]['tools']>\n // M41 (ADR-0050) — terminal/desktop (and advanced): bind by an explicit AgentTransport\n // (e.g. InProcessTransport). The SAME hook, one consumption shape across every surface.\n export function useAgent<TInput = unknown>(\n transport: AgentTransport,\n ): UseAgentReturn<TInput>\n}\n`\n}\n\n// ─── Vite plugin ─────────────────────────────────────────────────────────────\n\nconst VIRTUAL_AGENTS_ID = '@theo/agents'\nconst RESOLVED_AGENTS_ID = '\\0@theo/agents'\n\nexport interface AgentsTypedClientPluginOptions {\n /** Absolute project root (agents live at `<projectRoot>/<agentsDir>`). */\n projectRoot: string\n /** Agents dir name (config `agentsDir`, default \"agents\"), relative to projectRoot — the watch glob. */\n agentsDir?: string\n /** Absolute `.theokit/` output dir (where `agents.d.ts` lands). */\n distDir: string\n /** Injects the scanned agents; returns the current manifest-shaped agent list. */\n scanManifest: (projectRoot: string) => TheoManifest\n}\n\n/** Atomic write via tmp + rename; skips when content is unchanged. */\nfunction writeIfChanged(filePath: string, content: string): void {\n if (existsSync(filePath)) {\n try {\n if (readFileSync(filePath, 'utf-8') === content) return\n } catch {\n /* fall through to write */\n }\n }\n mkdirSync(dirname(filePath), { recursive: true })\n const tmp = `${filePath}.${process.pid}.tmp`\n writeFileSync(tmp, content)\n renameSync(tmp, filePath)\n}\n\nfunction emitAgentsDts(opts: AgentsTypedClientPluginOptions): string {\n const dtsOutPath = posix.join(opts.distDir.replace(/\\\\/g, '/'), 'agents.d.ts')\n const content = generateAgentsDts({\n manifest: opts.scanManifest(opts.projectRoot),\n dtsOutPath,\n projectRoot: opts.projectRoot,\n })\n writeIfChanged(dtsOutPath, content)\n return dtsOutPath\n}\n\nexport function agentsTypedClientPlugin(opts: AgentsTypedClientPluginOptions): Plugin {\n let debounce: NodeJS.Timeout | undefined\n let viteServer: ViteDevServer | undefined\n\n const scheduleEmit = (): void => {\n if (debounce) clearTimeout(debounce)\n debounce = setTimeout(() => {\n try {\n emitAgentsDts(opts)\n if (viteServer) {\n const mod = viteServer.moduleGraph.getModuleById(RESOLVED_AGENTS_ID)\n if (mod) viteServer.moduleGraph.invalidateModule(mod)\n }\n } catch (err) {\n console.error('[theokit:agents-typed-client] codegen error:', err)\n }\n }, 100)\n }\n\n return {\n name: 'theokit:agents-typed-client',\n enforce: 'post',\n configResolved() {\n try {\n emitAgentsDts(opts)\n } catch (err) {\n console.error('[theokit:agents-typed-client] initial codegen error:', err)\n }\n },\n buildEnd() {\n try {\n emitAgentsDts(opts)\n } catch (err) {\n console.error('[theokit:agents-typed-client] buildEnd codegen error:', err)\n }\n },\n configureServer(server) {\n viteServer = server\n const agentsGlob = posix.join(\n opts.projectRoot.replace(/\\\\/g, '/'),\n opts.agentsDir ?? 'agents',\n )\n const onFile = (file: string): void => {\n if (file.replace(/\\\\/g, '/').startsWith(agentsGlob)) scheduleEmit()\n }\n server.watcher.on('add', onFile)\n server.watcher.on('change', onFile)\n server.watcher.on('unlink', onFile)\n },\n resolveId(id) {\n return id === VIRTUAL_AGENTS_ID ? RESOLVED_AGENTS_ID : null\n },\n load(id) {\n if (id === RESOLVED_AGENTS_ID) {\n return `export { useAgent } from 'theokit/client'\\n`\n }\n return null\n },\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -47,13 +47,19 @@ ${entries.join("\n")}
|
|
|
47
47
|
return `${FILE_HEADER}
|
|
48
48
|
declare module '@theo/agents' {
|
|
49
49
|
import type { InferAgentInput, InferAgentToolNames } from '@theokit/agents'
|
|
50
|
-
import type { UseAgentReturn } from 'theokit/client'
|
|
50
|
+
import type { UseAgentReturn, AgentTransport } from 'theokit/client'
|
|
51
51
|
${importBlock}
|
|
52
52
|
export interface AppAgents ${body}
|
|
53
53
|
|
|
54
|
+
// Web (and any HTTP surface): bind by agent name \u2014 \`send\` is typed to the agent's \`input\` schema.
|
|
54
55
|
export function useAgent<K extends keyof AppAgents>(
|
|
55
56
|
name: K,
|
|
56
57
|
): UseAgentReturn<AppAgents[K]['input'], AppAgents[K]['tools']>
|
|
58
|
+
// M41 (ADR-0050) \u2014 terminal/desktop (and advanced): bind by an explicit AgentTransport
|
|
59
|
+
// (e.g. InProcessTransport). The SAME hook, one consumption shape across every surface.
|
|
60
|
+
export function useAgent<TInput = unknown>(
|
|
61
|
+
transport: AgentTransport,
|
|
62
|
+
): UseAgentReturn<TInput>
|
|
57
63
|
}
|
|
58
64
|
`;
|
|
59
65
|
}
|
|
@@ -144,4 +150,4 @@ export {
|
|
|
144
150
|
agentsTypedClientPlugin,
|
|
145
151
|
generateAgentsDts
|
|
146
152
|
};
|
|
147
|
-
//# sourceMappingURL=agents-typed-client-
|
|
153
|
+
//# sourceMappingURL=agents-typed-client-MAAILRI6.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/vite-plugin/agents-typed-client.ts"],"sourcesContent":["/* eslint-disable security/detect-non-literal-fs-filename --\n * Codegen-time fs ops: all paths derive from `opts.projectRoot` / `opts.distDir`\n * (vite plugin opts — trusted, set by the framework's CLI). Never serves HTTP input.\n */\n/**\n * M2 (theokit-ai-first) — end-to-end typed binding for the `agents/*.ts` convention.\n *\n * Sibling of `app-typed-client.ts` (kept separate so the `@theo/client` output stays\n * byte-unchanged). Two parts:\n *\n * 1. `generateAgentsDts({ manifest, dtsOutPath, projectRoot })` — pure function emitting\n * `.theokit/agents.d.ts` (the virtual `@theo/agents` module) with `AppAgents` mapping\n * each scanned agent to `InferAgentInput` of its `defineAgent({ input })` schema, plus a\n * typed `useAgent` signature — so the client binds to `/api/agents/<name>` with the right\n * request type and ZERO manual wiring (DoD line 2).\n * 2. `agentsTypedClientPlugin(opts)` — Vite plugin that emits (1), rewrites on `agents/*`\n * changes, and serves the virtual `@theo/agents` runtime (`useAgent` from `theokit/client`).\n */\nimport { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs'\nimport { dirname, posix } from 'node:path'\n\nimport type { Plugin, ViteDevServer } from 'vite'\n\nimport type { TheoManifest } from '../server/internal-api.js'\n\nconst FILE_HEADER = `// AUTO-GENERATED by theokit — do not edit.\n// Source: theokit/packages/theo/src/vite-plugin/agents-typed-client.ts (M2).\n// To refresh: \\`pnpm dev\\` or \\`pnpm build\\` regenerates this on every agents/ change.\n\n/* eslint-disable */\n`\n\n/** A safe TS identifier alias for an agent (name may contain path separators). */\nfunction aliasFor(name: string): string {\n return `_agent_${name.replace(/[^\\w$]/g, '_')}`\n}\n\n/** Relative `import type` path from the .d.ts dir to the agent source (extension stripped). */\nfunction importPath(dtsOutPath: string, projectRoot: string, filePath: string): string {\n const fromDir = dirname(dtsOutPath).replace(/\\\\/g, '/')\n const abs = posix.join(projectRoot.replace(/\\\\/g, '/'), filePath.replace(/\\\\/g, '/'))\n const noExt = abs.replace(/\\.[jt]sx?$/, '')\n let rel = posix.relative(fromDir, noExt)\n if (!rel.startsWith('.')) rel = `./${rel}`\n return rel\n}\n\nexport interface GenerateAgentsDtsOptions {\n manifest: TheoManifest\n /** Absolute path to the .d.ts that will be emitted (drives the import paths). */\n dtsOutPath: string\n /** Absolute project root — agents live at `<projectRoot>/agents`. */\n projectRoot: string\n}\n\nexport function generateAgentsDts({\n manifest,\n dtsOutPath,\n projectRoot,\n}: GenerateAgentsDtsOptions): string {\n const agents = manifest.agents ?? []\n const imports: string[] = []\n const entries: string[] = []\n for (const agent of agents) {\n const alias = aliasFor(agent.name)\n imports.push(\n ` import type ${alias} from '${importPath(dtsOutPath, projectRoot, agent.filePath)}'`,\n )\n entries.push(\n ` '${agent.name}': { input: InferAgentInput<${alias}>; tools: InferAgentToolNames<${alias}> }`,\n )\n }\n\n const body =\n entries.length > 0\n ? `{\\n${entries.join('\\n')}\\n }`\n : `{\\n // No agents detected — add \\`agents/*.ts\\` to populate this binding.\\n }`\n\n const importBlock = imports.length > 0 ? `${imports.join('\\n')}\\n` : ''\n\n return `${FILE_HEADER}\ndeclare module '@theo/agents' {\n import type { InferAgentInput, InferAgentToolNames } from '@theokit/agents'\n import type { UseAgentReturn, AgentTransport } from 'theokit/client'\n${importBlock}\n export interface AppAgents ${body}\n\n // Web (and any HTTP surface): bind by agent name — \\`send\\` is typed to the agent's \\`input\\` schema.\n export function useAgent<K extends keyof AppAgents>(\n name: K,\n ): UseAgentReturn<AppAgents[K]['input'], AppAgents[K]['tools']>\n // M41 (ADR-0050) — terminal/desktop (and advanced): bind by an explicit AgentTransport\n // (e.g. InProcessTransport). The SAME hook, one consumption shape across every surface.\n export function useAgent<TInput = unknown>(\n transport: AgentTransport,\n ): UseAgentReturn<TInput>\n}\n`\n}\n\n// ─── Vite plugin ─────────────────────────────────────────────────────────────\n\nconst VIRTUAL_AGENTS_ID = '@theo/agents'\nconst RESOLVED_AGENTS_ID = '\\0@theo/agents'\n\nexport interface AgentsTypedClientPluginOptions {\n /** Absolute project root (agents live at `<projectRoot>/<agentsDir>`). */\n projectRoot: string\n /** Agents dir name (config `agentsDir`, default \"agents\"), relative to projectRoot — the watch glob. */\n agentsDir?: string\n /** Absolute `.theokit/` output dir (where `agents.d.ts` lands). */\n distDir: string\n /** Injects the scanned agents; returns the current manifest-shaped agent list. */\n scanManifest: (projectRoot: string) => TheoManifest\n}\n\n/** Atomic write via tmp + rename; skips when content is unchanged. */\nfunction writeIfChanged(filePath: string, content: string): void {\n if (existsSync(filePath)) {\n try {\n if (readFileSync(filePath, 'utf-8') === content) return\n } catch {\n /* fall through to write */\n }\n }\n mkdirSync(dirname(filePath), { recursive: true })\n const tmp = `${filePath}.${process.pid}.tmp`\n writeFileSync(tmp, content)\n renameSync(tmp, filePath)\n}\n\nfunction emitAgentsDts(opts: AgentsTypedClientPluginOptions): string {\n const dtsOutPath = posix.join(opts.distDir.replace(/\\\\/g, '/'), 'agents.d.ts')\n const content = generateAgentsDts({\n manifest: opts.scanManifest(opts.projectRoot),\n dtsOutPath,\n projectRoot: opts.projectRoot,\n })\n writeIfChanged(dtsOutPath, content)\n return dtsOutPath\n}\n\nexport function agentsTypedClientPlugin(opts: AgentsTypedClientPluginOptions): Plugin {\n let debounce: NodeJS.Timeout | undefined\n let viteServer: ViteDevServer | undefined\n\n const scheduleEmit = (): void => {\n if (debounce) clearTimeout(debounce)\n debounce = setTimeout(() => {\n try {\n emitAgentsDts(opts)\n if (viteServer) {\n const mod = viteServer.moduleGraph.getModuleById(RESOLVED_AGENTS_ID)\n if (mod) viteServer.moduleGraph.invalidateModule(mod)\n }\n } catch (err) {\n console.error('[theokit:agents-typed-client] codegen error:', err)\n }\n }, 100)\n }\n\n return {\n name: 'theokit:agents-typed-client',\n enforce: 'post',\n configResolved() {\n try {\n emitAgentsDts(opts)\n } catch (err) {\n console.error('[theokit:agents-typed-client] initial codegen error:', err)\n }\n },\n buildEnd() {\n try {\n emitAgentsDts(opts)\n } catch (err) {\n console.error('[theokit:agents-typed-client] buildEnd codegen error:', err)\n }\n },\n configureServer(server) {\n viteServer = server\n const agentsGlob = posix.join(\n opts.projectRoot.replace(/\\\\/g, '/'),\n opts.agentsDir ?? 'agents',\n )\n const onFile = (file: string): void => {\n if (file.replace(/\\\\/g, '/').startsWith(agentsGlob)) scheduleEmit()\n }\n server.watcher.on('add', onFile)\n server.watcher.on('change', onFile)\n server.watcher.on('unlink', onFile)\n },\n resolveId(id) {\n return id === VIRTUAL_AGENTS_ID ? RESOLVED_AGENTS_ID : null\n },\n load(id) {\n if (id === RESOLVED_AGENTS_ID) {\n return `export { useAgent } from 'theokit/client'\\n`\n }\n return null\n },\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -531,7 +531,7 @@ async function buildCommand(options) {
|
|
|
531
531
|
`);
|
|
532
532
|
}
|
|
533
533
|
async function runAdapterBuild(target, config, cwd) {
|
|
534
|
-
const { theoPluginAsync } = await import("./vite-plugin-
|
|
534
|
+
const { theoPluginAsync } = await import("./vite-plugin-BNI7YLCD.js");
|
|
535
535
|
const { default: react } = await import("@vitejs/plugin-react");
|
|
536
536
|
const ctx = {
|
|
537
537
|
// `react()` may return Plugin or Plugin[] depending on version; spread the
|
|
@@ -616,4 +616,4 @@ function relativize3(absPath, root) {
|
|
|
616
616
|
export {
|
|
617
617
|
buildCommand
|
|
618
618
|
};
|
|
619
|
-
//# sourceMappingURL=build-
|
|
619
|
+
//# sourceMappingURL=build-V2QEBE7I.js.map
|
|
@@ -3353,7 +3353,7 @@ async function theoPluginAsync(rootOrOptions) {
|
|
|
3353
3353
|
serverDir: serverDirAbs,
|
|
3354
3354
|
distDir: resolve9(projectRoot, ".theokit")
|
|
3355
3355
|
});
|
|
3356
|
-
const { agentsTypedClientPlugin } = await import("./agents-typed-client-
|
|
3356
|
+
const { agentsTypedClientPlugin } = await import("./agents-typed-client-MAAILRI6.js");
|
|
3357
3357
|
const { generateManifest } = await import("./internal-api-KPULK7ZK.js");
|
|
3358
3358
|
const agentsClientPlugin = agentsTypedClientPlugin({
|
|
3359
3359
|
projectRoot,
|
|
@@ -3537,4 +3537,4 @@ export {
|
|
|
3537
3537
|
theoPluginAsync,
|
|
3538
3538
|
theoPlugin
|
|
3539
3539
|
};
|
|
3540
|
-
//# sourceMappingURL=chunk-
|
|
3540
|
+
//# sourceMappingURL=chunk-R4VVXLKZ.js.map
|
|
@@ -1928,7 +1928,7 @@ async function theoPluginAsync(rootOrOptions) {
|
|
|
1928
1928
|
serverDir: serverDirAbs,
|
|
1929
1929
|
distDir: resolve7(projectRoot, ".theokit")
|
|
1930
1930
|
});
|
|
1931
|
-
const { agentsTypedClientPlugin } = await import("./agents-typed-client-
|
|
1931
|
+
const { agentsTypedClientPlugin } = await import("./agents-typed-client-5DCGDWFZ.js");
|
|
1932
1932
|
const { generateManifest } = await import("./internal-api-Y5REPVUS.js");
|
|
1933
1933
|
const agentsClientPlugin = agentsTypedClientPlugin({
|
|
1934
1934
|
projectRoot,
|
|
@@ -2104,4 +2104,4 @@ export {
|
|
|
2104
2104
|
theoPluginAsync,
|
|
2105
2105
|
theoPlugin
|
|
2106
2106
|
};
|
|
2107
|
-
//# sourceMappingURL=chunk-
|
|
2107
|
+
//# sourceMappingURL=chunk-VRVNM3QL.js.map
|
|
@@ -178,7 +178,7 @@ async function agentCommand(name, message, deps = {}) {
|
|
|
178
178
|
async function createAgentSsrLoader(projectRoot) {
|
|
179
179
|
const { createServer } = await import("vite");
|
|
180
180
|
const react = (await import("@vitejs/plugin-react")).default;
|
|
181
|
-
const { theoPluginAsync } = await import("./vite-plugin-
|
|
181
|
+
const { theoPluginAsync } = await import("./vite-plugin-BNI7YLCD.js");
|
|
182
182
|
const { loadConfig } = await import("./load-config-3EAQTXPH.js");
|
|
183
183
|
const config = await loadConfig(projectRoot);
|
|
184
184
|
const theoPlugins = await theoPluginAsync({
|
|
@@ -212,4 +212,4 @@ export {
|
|
|
212
212
|
agentCommand,
|
|
213
213
|
createAgentSsrLoader
|
|
214
214
|
};
|
|
215
|
-
//# sourceMappingURL=chunk-
|
|
215
|
+
//# sourceMappingURL=chunk-Y4TOVMNC.js.map
|
package/dist/cli/index.js
CHANGED
|
@@ -5,12 +5,12 @@ import "tsx/esm";
|
|
|
5
5
|
import cac from "cac";
|
|
6
6
|
var cli = cac("theokit");
|
|
7
7
|
cli.command("dev", "Start development server").option("--port <port>", "Port number").action(async (options) => {
|
|
8
|
-
const { devCommand } = await import("../dev-
|
|
8
|
+
const { devCommand } = await import("../dev-5ZQMWVFC.js");
|
|
9
9
|
await devCommand({ port: options.port ? Number(options.port) : void 0 });
|
|
10
10
|
});
|
|
11
11
|
cli.command("build", "Build for production").option("--target <target>", "Deploy target (node, vercel, cloudflare)").action(async (options) => {
|
|
12
12
|
try {
|
|
13
|
-
const { buildCommand } = await import("../build-
|
|
13
|
+
const { buildCommand } = await import("../build-V2QEBE7I.js");
|
|
14
14
|
await buildCommand({ target: options.target });
|
|
15
15
|
} catch (err) {
|
|
16
16
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -52,7 +52,7 @@ cli.command(
|
|
|
52
52
|
"Run an agent in the terminal (stream + tool calls + approval)"
|
|
53
53
|
).action(async (name, message) => {
|
|
54
54
|
try {
|
|
55
|
-
const { agentCommand } = await import("../agent-
|
|
55
|
+
const { agentCommand } = await import("../agent-I5QEOMCN.js");
|
|
56
56
|
const { sawError } = await agentCommand(name, message);
|
|
57
57
|
if (sawError) process.exit(1);
|
|
58
58
|
} catch (err) {
|
|
@@ -65,7 +65,7 @@ cli.command(
|
|
|
65
65
|
});
|
|
66
66
|
cli.command("mcp <agent>", "Serve an agent as an MCP server over stdio (for desktop MCP clients)").action(async (agent) => {
|
|
67
67
|
try {
|
|
68
|
-
const { mcpCommand } = await import("../mcp-
|
|
68
|
+
const { mcpCommand } = await import("../mcp-VMKWB2BY.js");
|
|
69
69
|
await mcpCommand(agent);
|
|
70
70
|
} catch (err) {
|
|
71
71
|
const msg = err instanceof Error ? err.message : String(err);
|
package/dist/client/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { T as TheoErrorEnvelope } from '../error-envelope-BsNzzAV5.js';
|
|
3
3
|
export { FetchOptionsLike, Fetcher, QueryKey, UseTheoQueryConfig, buildUseTheoQueryConfig, stableQueryKey } from '../react-query/index.js';
|
|
4
|
-
import { UIMessage } from 'ai';
|
|
4
|
+
import { UIMessageChunk, UIMessage, ChatTransport } from 'ai';
|
|
5
5
|
import * as react from 'react';
|
|
6
6
|
import { LinkProps as LinkProps$1 } from 'react-router';
|
|
7
7
|
|
|
@@ -130,20 +130,85 @@ declare function createBatcher(options: BatcherOptions): Batcher;
|
|
|
130
130
|
* assistant message, so a caller (the `useAgent` hook) can render streaming updates.
|
|
131
131
|
*/
|
|
132
132
|
declare function consumeUIMessageStream(response: Response, onMessage: (message: UIMessage) => void): Promise<void>;
|
|
133
|
+
/**
|
|
134
|
+
* M41 (ADR-0050 D3) — the reusable middle piece: a UIMessageStream SSE `Response` →
|
|
135
|
+
* `ReadableStream<UIMessageChunk>`, reusing `ai`'s own `parseJsonEventStream` (the exact primitive
|
|
136
|
+
* `useChat` runs). This is precisely what a `ChatTransport.sendMessages` returns, so `HttpTransport`
|
|
137
|
+
* builds on it directly (no reinvented wire parser — Rule 9). A body-less response yields an empty stream.
|
|
138
|
+
*/
|
|
139
|
+
declare function responseToChunkStream(response: Response): Promise<ReadableStream<UIMessageChunk>>;
|
|
140
|
+
/**
|
|
141
|
+
* M41 (ADR-0050 D6) — read a `ReadableStream<UIMessageChunk>` into reconstructed assistant
|
|
142
|
+
* `UIMessage`s via `ai`'s `readUIMessageStream`. Shared by `consumeUIMessageStream` (Response path)
|
|
143
|
+
* and the framework-agnostic `AgentClient` store (transport path). `onMessage` fires on every
|
|
144
|
+
* reconstruction step so a caller can render streaming updates.
|
|
145
|
+
*/
|
|
146
|
+
declare function consumeChunkStream(stream: ReadableStream<UIMessageChunk>, onMessage: (message: UIMessage) => void): Promise<void>;
|
|
133
147
|
|
|
134
148
|
/**
|
|
135
|
-
*
|
|
149
|
+
* M41 (ADR-0050 D2) — a HITL approval decision sent to settle a paused gated-tool call. Mirrors the
|
|
150
|
+
* `POST /api/agents/<name>/approve/<id>` wire body (`approve-agent.ts` `parseApprovalBody`). Defined
|
|
151
|
+
* on the client side (not imported from `server/`) as the client's view of the boundary contract.
|
|
152
|
+
*/
|
|
153
|
+
interface ApprovalDecision {
|
|
154
|
+
/** Whether the paused gated tool may proceed. */
|
|
155
|
+
approved: boolean;
|
|
156
|
+
/** Optional reason surfaced to the model on denial. */
|
|
157
|
+
reason?: string;
|
|
158
|
+
/** Optional small structured note (edited args, a reviewer comment) — capped server-side at 16 KiB. */
|
|
159
|
+
payload?: unknown;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* M41 (ADR-0050 D1/D2) — the client transport seam.
|
|
136
163
|
*
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
*
|
|
141
|
-
*
|
|
164
|
+
* It IS `ai`'s `ChatTransport<UIMessage>` (the adopted SOTA interface — we do NOT invent a parallel
|
|
165
|
+
* one) plus ONE optional method, `approve`, for TheoKit's OUT-OF-BAND HITL (the server pauses the run;
|
|
166
|
+
* the client settles it via a separate call). `ai`'s `ChatTransport` has no `approve` because its HITL
|
|
167
|
+
* is in-band (a re-sent message part); ours is out-of-band, and the settle route differs per transport
|
|
168
|
+
* (HTTP `POST /approve/<id>` vs an inline callback), so it belongs on the transport. `approve` is
|
|
169
|
+
* optional — agents without gated tools never settle an approval.
|
|
142
170
|
*
|
|
143
|
-
*
|
|
144
|
-
* loaded lazily by `consumeUIMessageStream` so non-agent apps never pay for it.
|
|
171
|
+
* `HttpTransport` (web) and `InProcessTransport` (TUI/desktop) implement this; `useAgent` drives it.
|
|
145
172
|
*/
|
|
173
|
+
type AgentTransport = ChatTransport<UIMessage> & {
|
|
174
|
+
approve?(approvalId: string, decision: ApprovalDecision): Promise<void>;
|
|
175
|
+
};
|
|
176
|
+
|
|
146
177
|
type UseAgentStatus = 'idle' | 'streaming' | 'done' | 'error';
|
|
178
|
+
/** The observable state the store exposes (stable reference between emits — `useSyncExternalStore` contract). */
|
|
179
|
+
interface AgentClientState {
|
|
180
|
+
messages: UIMessage[];
|
|
181
|
+
status: UseAgentStatus;
|
|
182
|
+
error: Error | undefined;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* M41 (ADR-0050 D6) — the framework-agnostic agent client store.
|
|
186
|
+
*
|
|
187
|
+
* Holds `messages`/`status`/`error`, drives an {@link AgentTransport}, and notifies subscribers on
|
|
188
|
+
* change. It is the SINGLE consolidation point: web (`HttpTransport`) and terminal/desktop
|
|
189
|
+
* (`InProcessTransport`) run the SAME store. `useAgent` is a thin React binding over it via
|
|
190
|
+
* `useSyncExternalStore`; a standalone (no-React) client (M44) can subscribe directly. Being
|
|
191
|
+
* framework-agnostic, it is unit-tested without a DOM.
|
|
192
|
+
*/
|
|
193
|
+
declare class AgentClient<TInput = unknown> {
|
|
194
|
+
#private;
|
|
195
|
+
constructor(transport: AgentTransport);
|
|
196
|
+
/** Subscribe to state changes; returns an unsubscribe fn. */
|
|
197
|
+
subscribe: (listener: () => void) => (() => void);
|
|
198
|
+
/** The current immutable snapshot (stable reference until the next emit). */
|
|
199
|
+
getSnapshot: () => AgentClientState;
|
|
200
|
+
/** Send a typed input; opens a fresh stream (replaces prior messages). */
|
|
201
|
+
send: (input: TInput) => void;
|
|
202
|
+
/** Resume an interrupted stream via the transport's `reconnectToStream` (no-op when unavailable). */
|
|
203
|
+
reconnect: () => void;
|
|
204
|
+
/** Abort an in-flight stream (not an error — leaves messages as-is). */
|
|
205
|
+
abort: () => void;
|
|
206
|
+
/** Clear messages + error, back to idle. */
|
|
207
|
+
reset: () => void;
|
|
208
|
+
/** Settle a paused HITL approval via the transport's HITL path (HTTP POST or inline callback). */
|
|
209
|
+
approve: (approvalId: string, decision: ApprovalDecision) => Promise<void>;
|
|
210
|
+
}
|
|
211
|
+
|
|
147
212
|
interface UseAgentReturn<TInput = unknown, TToolNames extends string = string> {
|
|
148
213
|
/** Reconstructed assistant messages so far (ai `UIMessage[]`). */
|
|
149
214
|
messages: UIMessage[];
|
|
@@ -156,25 +221,118 @@ interface UseAgentReturn<TInput = unknown, TToolNames extends string = string> {
|
|
|
156
221
|
abort: () => void;
|
|
157
222
|
/** Clear messages + error, back to idle. */
|
|
158
223
|
reset: () => void;
|
|
224
|
+
/** Settle a paused HITL approval (HTTP `POST /approve/<id>` for web; the inline callback in-process). */
|
|
225
|
+
approve: (approvalId: string, decision: ApprovalDecision) => Promise<void>;
|
|
226
|
+
/** Resume an interrupted stream (M37 durable transport for web; a no-op in-process). */
|
|
227
|
+
reconnect: () => void;
|
|
159
228
|
/**
|
|
160
|
-
* The union of tool names this agent can emit (M8), carried end-to-end from the `agent()`
|
|
161
|
-
*
|
|
162
|
-
*
|
|
163
|
-
* to the literal union for builder agents (`'read_file' | 'count_lines'`), `string` otherwise.
|
|
229
|
+
* The union of tool names this agent can emit (M8), carried end-to-end from the `agent()` builder's
|
|
230
|
+
* accumulated tool-name type through the generated `@theo/agents` client. Type-only witness (never
|
|
231
|
+
* populated at runtime). Resolves to the literal union for builder agents, `string` otherwise.
|
|
164
232
|
*/
|
|
165
233
|
readonly __toolNames?: TToolNames;
|
|
166
234
|
}
|
|
167
235
|
interface UseAgentOptions {
|
|
168
|
-
/**
|
|
236
|
+
/**
|
|
237
|
+
* Extra request headers (e.g., auth) — applied when a string path builds an `HttpTransport`. Read on
|
|
238
|
+
* EVERY request, so a value that changes across renders (a rotating JWT) is never sent stale.
|
|
239
|
+
*/
|
|
169
240
|
headers?: Record<string, string>;
|
|
170
|
-
/** Override fetch (primarily for tests)
|
|
241
|
+
/** Override fetch (primarily for tests) — captured when a string path builds an `HttpTransport`. */
|
|
171
242
|
fetch?: typeof fetch;
|
|
172
243
|
}
|
|
173
244
|
/**
|
|
174
|
-
* Bind to
|
|
175
|
-
* `useAgent` from `@theo/agents` (typed by agent name); this base accepts
|
|
245
|
+
* Bind to an agent by endpoint path (`/api/agents/<name>`) or by an explicit {@link AgentTransport}.
|
|
246
|
+
* Prefer the generated `useAgent` from `@theo/agents` (typed by agent name); this base accepts a path
|
|
247
|
+
* or a transport. The store is created once per binding identity — memoize a transport before passing it.
|
|
248
|
+
*/
|
|
249
|
+
declare function useAgent<TInput = unknown>(pathOrTransport: string | AgentTransport, options?: UseAgentOptions): UseAgentReturn<TInput>;
|
|
250
|
+
|
|
251
|
+
/** Extra request headers — a static record OR a resolver called per request (for dynamic auth). */
|
|
252
|
+
type HeadersResolver = Record<string, string> | (() => Record<string, string> | undefined);
|
|
253
|
+
interface HttpTransportOptions {
|
|
254
|
+
/** Agent endpoint path or URL, e.g. `/api/agents/support`. */
|
|
255
|
+
api: string;
|
|
256
|
+
/**
|
|
257
|
+
* Extra request headers (e.g. auth). Static record OR a resolver evaluated on EVERY request — pass a
|
|
258
|
+
* resolver when the value is dynamic (a rotating JWT), so a stale header is never sent. Merged UNDER
|
|
259
|
+
* per-request headers.
|
|
260
|
+
*/
|
|
261
|
+
headers?: HeadersResolver;
|
|
262
|
+
/** Override fetch (primarily for tests / non-browser hosts) — static; resolved once at construction. */
|
|
263
|
+
fetch?: typeof fetch;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* M41 (ADR-0050 D3) — `ChatTransport` over the web agent path.
|
|
267
|
+
*
|
|
268
|
+
* - `sendMessages`: `POST <api>` with the UIMessageStream `accept` + the `X-Theo-Action` CSRF header
|
|
269
|
+
* (HTTP method + headers are identical to the pre-M41 `useAgent` fetch; the body shape is a superset —
|
|
270
|
+
* `{ ...input, messages: [UIMessage] }` — which the server's dual-path parser accepts, so no
|
|
271
|
+
* regression), captures the server-minted `x-theokit-run-id`, and returns `ReadableStream<UIMessageChunk>`
|
|
272
|
+
* via `ai`'s own SSE parser (`responseToChunkStream`).
|
|
273
|
+
* - `reconnectToStream`: `GET <api>/runs/<runId>/stream` (M37 durable transport); 404 → `null` (the run
|
|
274
|
+
* completed / was evicted). A caller may pass a `Last-Event-ID` header to resume only the tail; by
|
|
275
|
+
* default the server replays the run from the start and the client upserts by message id (idempotent).
|
|
276
|
+
* - `approve`: `POST <api>/approve/<id>` (out-of-band HITL settle).
|
|
277
|
+
*
|
|
278
|
+
* Implemented directly (not by subclassing `DefaultChatTransport`) because reconnect keys on our
|
|
279
|
+
* server-minted `runId` captured from a response header, which the base class does not expose — see
|
|
280
|
+
* ADR-0050 D3.
|
|
281
|
+
*/
|
|
282
|
+
declare class HttpTransport implements AgentTransport {
|
|
283
|
+
#private;
|
|
284
|
+
constructor(options: HttpTransportOptions);
|
|
285
|
+
sendMessages(options: Parameters<ChatTransport<UIMessage>['sendMessages']>[0]): Promise<ReadableStream<UIMessageChunk>>;
|
|
286
|
+
reconnectToStream(options: Parameters<ChatTransport<UIMessage>['reconnectToStream']>[0]): Promise<ReadableStream<UIMessageChunk> | null>;
|
|
287
|
+
approve(approvalId: string, decision: ApprovalDecision): Promise<void>;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/** An inline approval request handed to the transport's resolver (structural — no server import). */
|
|
291
|
+
interface InProcessApprovalRequestLike {
|
|
292
|
+
approvalId: string;
|
|
293
|
+
toolName: string;
|
|
294
|
+
opts: unknown;
|
|
295
|
+
}
|
|
296
|
+
/** Resolve one gated-tool approval inline (mirrors the SDK's `boolean | HitlDecision` return). */
|
|
297
|
+
type InProcessAwaitApproval = (req: InProcessApprovalRequestLike) => Promise<boolean | ApprovalDecision>;
|
|
298
|
+
/** The input the injected runner receives (structurally compatible with `StreamAgentTurnInProcessInput`). */
|
|
299
|
+
interface InProcessRunInput {
|
|
300
|
+
message: string;
|
|
301
|
+
sessionId?: string;
|
|
302
|
+
signal?: AbortSignal;
|
|
303
|
+
awaitApproval?: InProcessAwaitApproval;
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* The in-process turn runner. The consumer binds `streamAgentTurnInProcess(mod, apiKey, …)`:
|
|
307
|
+
* `new InProcessTransport({ run: (input) => streamAgentTurnInProcess(mod, apiKey, input) })`.
|
|
308
|
+
* Injecting it keeps this client module decoupled from `server/` and makes the transport testable.
|
|
176
309
|
*/
|
|
177
|
-
|
|
310
|
+
type InProcessRunner = (input: InProcessRunInput) => AsyncGenerator<UIMessageChunk>;
|
|
311
|
+
interface InProcessTransportOptions {
|
|
312
|
+
run: InProcessRunner;
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* M41 (ADR-0050 D4) — `ChatTransport` over the in-process seam (`streamAgentTurnInProcess`), for the
|
|
316
|
+
* terminal/desktop surfaces that run client + server in ONE process (no HTTP loopback).
|
|
317
|
+
*
|
|
318
|
+
* - `sendMessages`: bridge the injected runner's `AsyncGenerator<UIMessageChunk>` into a
|
|
319
|
+
* `ReadableStream<UIMessageChunk>` (honoring `abortSignal`, which the runner forwards to the SDK).
|
|
320
|
+
* - `reconnectToStream`: always `null` — a single process has no dropped server-side stream to resume
|
|
321
|
+
* (mirrors `ai`'s `DirectChatTransport`).
|
|
322
|
+
* - `approve`: resolve the pending inline approval by id (the run parks on `awaitApproval`). An unknown
|
|
323
|
+
* id rejects (fail-fast, Rule 8 — never a silent resolve).
|
|
324
|
+
*
|
|
325
|
+
* Error asymmetry vs `HttpTransport` (by design, matching the `ChatTransport` contract): a runner that
|
|
326
|
+
* throws SYNCHRONOUSLY surfaces the error when the stream is READ (via `controller.error`), not from the
|
|
327
|
+
* `sendMessages` promise — whereas `HttpTransport` throws from `sendMessages` on a non-2xx response.
|
|
328
|
+
*/
|
|
329
|
+
declare class InProcessTransport implements AgentTransport {
|
|
330
|
+
#private;
|
|
331
|
+
constructor(options: InProcessTransportOptions);
|
|
332
|
+
sendMessages(options: Parameters<ChatTransport<UIMessage>['sendMessages']>[0]): Promise<ReadableStream<UIMessageChunk>>;
|
|
333
|
+
reconnectToStream(): Promise<ReadableStream<UIMessageChunk> | null>;
|
|
334
|
+
approve(approvalId: string, decision: ApprovalDecision): Promise<void>;
|
|
335
|
+
}
|
|
178
336
|
|
|
179
337
|
type PrefetchBehavior = 'none' | 'intent' | 'viewport';
|
|
180
338
|
interface LinkProps extends LinkProps$1 {
|
|
@@ -323,4 +481,4 @@ declare function mountMcpApp(container: HTMLElement, resource: {
|
|
|
323
481
|
html: string;
|
|
324
482
|
}, opts: McpAppHostOptions): McpAppHandle;
|
|
325
483
|
|
|
326
|
-
export { type BatchRequest, type BatchResponse, type BatchTransport, type Batcher, type BatcherOptions, type CreateAppClientOptions, type GuestMessage, Image, type ImageProps, type InferBody, type InferQuery, type InferResponse, Link, type LinkProps, MCP_APP_SANDBOX, type McpAppHandle, type McpAppHostOptions, Metadata, type MetadataProps, type PrefetchBehavior, TheoFetchError, type TheoFetchOptions, type UseAgentOptions, type UseAgentReturn, type UseAgentStatus, consumeUIMessageStream, createAppClient, createBatcher, createGuestMessageHandler, mountMcpApp, theoFetch, useAgent };
|
|
484
|
+
export { AgentClient, type AgentClientState, type AgentTransport, type ApprovalDecision, type BatchRequest, type BatchResponse, type BatchTransport, type Batcher, type BatcherOptions, type CreateAppClientOptions, type GuestMessage, HttpTransport, type HttpTransportOptions, Image, type ImageProps, type InProcessApprovalRequestLike, type InProcessAwaitApproval, type InProcessRunInput, type InProcessRunner, InProcessTransport, type InProcessTransportOptions, type InferBody, type InferQuery, type InferResponse, Link, type LinkProps, MCP_APP_SANDBOX, type McpAppHandle, type McpAppHostOptions, Metadata, type MetadataProps, type PrefetchBehavior, TheoFetchError, type TheoFetchOptions, type UseAgentOptions, type UseAgentReturn, type UseAgentStatus, consumeChunkStream, consumeUIMessageStream, createAppClient, createBatcher, createGuestMessageHandler, mountMcpApp, responseToChunkStream, theoFetch, useAgent };
|