theokit 0.11.6 → 0.12.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/LICENSE +201 -0
- package/dist/actions-virtual-module-SQDY3V5X.js +0 -0
- package/dist/add-W6FNTAFS.js +0 -0
- package/dist/app-typed-client-QG7BVZYW.js +0 -0
- package/dist/aws-lambda-7GSCNLPY.js +0 -0
- package/dist/broadcast-LUMOJIJT.js +0 -0
- package/dist/build-QFRLSEZ4.js +0 -0
- package/dist/build-request-body-preview-QMWD2IXK.js +0 -0
- package/dist/bun-KP2KES6S.js +0 -0
- package/dist/check-PD2FTKMM.js +0 -0
- package/dist/chunk-3LVRAGAZ.js +0 -0
- package/dist/chunk-43D6XNDR.js +0 -0
- package/dist/chunk-45C3WUQ7.js +0 -0
- package/dist/chunk-5ODOE6EF.js +0 -0
- package/dist/chunk-6FYD34NX.js +0 -0
- package/dist/chunk-7YZHAQU7.js +0 -0
- package/dist/{chunk-GEEMNDPH.js → chunk-AD74EAK3.js} +30 -1
- package/dist/chunk-AD74EAK3.js.map +1 -0
- package/dist/chunk-FOZIR3TG.js +0 -0
- package/dist/chunk-GFMQJHXX.js +0 -0
- package/dist/chunk-HGZL5EOI.js +0 -0
- package/dist/chunk-HNBWZKIQ.js +0 -0
- package/dist/chunk-IEES3CHD.js +0 -0
- package/dist/chunk-JAIKGP3Q.js +0 -0
- package/dist/chunk-JQSFBJR5.js +0 -0
- package/dist/chunk-NAZ4E2GT.js +0 -0
- package/dist/chunk-PBEH6NXR.js +0 -0
- package/dist/chunk-YJAUJXZS.js +0 -0
- package/dist/cloudflare-C6E5SPAE.js +0 -0
- package/dist/configure-agent-registry-ZOBVU3MV.js +0 -0
- package/dist/db-3UNAMSFK.js +0 -0
- package/dist/deno-deploy-RFZN56X4.js +0 -0
- package/dist/dev-GBXOTXUP.js +0 -0
- package/dist/dev-emit-FEFEDLZF.js +0 -0
- package/dist/dispatcher-EJHL6JMJ.js +0 -0
- package/dist/docker-LZZB4D5E.js +0 -0
- package/dist/generate-OMKHQ7OM.js +0 -0
- package/dist/info-OUEUZOT7.js +0 -0
- package/dist/netlify-PMLHVPN4.js +0 -0
- package/dist/node-BPJ3Z4DT.js +0 -0
- package/dist/openapi-VR6AFBLJ.js +0 -0
- package/dist/registry-Q2TZQLUH.js +0 -0
- package/dist/router-TLEAOFID.js +0 -0
- package/dist/routes-LRYOIIAI.js +0 -0
- package/dist/scan-7MJC6PYU.js +0 -0
- package/dist/schema-7CAY6IZR.js +0 -0
- package/dist/server/define/index.js +5 -3
- package/dist/server/index.js +4 -2
- package/dist/server/index.js.map +1 -1
- package/dist/server-error-to-envelope-UUXDSLAZ.js +0 -0
- package/dist/server-routes-hmr-VZXOP5YT.js +0 -0
- package/dist/services-json-Y3XODNB5.js +0 -0
- package/dist/services-typed-client-32KMTTXR.js +0 -0
- package/dist/start-3ZHAXSJE.js +0 -0
- package/dist/static-55G3LX2I.js +0 -0
- package/dist/storage-manager-ZSQFLEYT.js +0 -0
- package/dist/theo-cloud-DQRP6S6M.js +0 -0
- package/dist/upgrade-readiness-ACGW44JC.js +0 -0
- package/dist/vercel-J6G7ZHYQ.js +0 -0
- package/dist/vite-plugin-WO72VLYR.js +0 -0
- package/package.json +13 -9
- package/dist/adapters/web-shim.d.ts +0 -67
- package/dist/adapters/ws-shim.d.ts +0 -55
- package/dist/agent-events-DosDXkSV.d.ts +0 -94
- package/dist/audit-log-BQWM5YLG.d.ts +0 -60
- package/dist/boot/index.d.ts +0 -39
- package/dist/chunk-GEEMNDPH.js.map +0 -1
- package/dist/client/index.d.ts +0 -362
- package/dist/csrf-BBrEZSBW.d.ts +0 -107
- package/dist/csrf-readiness-store-CjIoub3U.d.ts +0 -43
- package/dist/define-websocket-CdK94O-D.d.ts +0 -64
- package/dist/devtools/entry.d.ts +0 -5
- package/dist/error-envelope-BsNzzAV5.d.ts +0 -62
- package/dist/health-route-C0hk64_U.d.ts +0 -57
- package/dist/index-B40qUSrQ.d.ts +0 -575
- package/dist/index.d.ts +0 -361
- package/dist/job-backend-CgC8Xf33.d.ts +0 -68
- package/dist/match-CfbEFRG4.d.ts +0 -26
- package/dist/plugin-runner-BGBkzgi0.d.ts +0 -95
- package/dist/plugin-types-DNJGxr4Z.d.ts +0 -79
- package/dist/rate-limit-BdNDZ3vt.d.ts +0 -58
- package/dist/rate-limit-store-BEJnhWdw.d.ts +0 -72
- package/dist/react-query/index.d.ts +0 -33
- package/dist/schema-BpH6ivDY.d.ts +0 -74
- package/dist/server/agent/index.d.ts +0 -229
- package/dist/server/auth/index.d.ts +0 -419
- package/dist/server/cost/index.d.ts +0 -177
- package/dist/server/cron/index.d.ts +0 -208
- package/dist/server/define/index.d.ts +0 -310
- package/dist/server/http/index.d.ts +0 -11
- package/dist/server/index.d.ts +0 -847
- package/dist/server/jobs/index.d.ts +0 -348
- package/dist/server/observability/index.d.ts +0 -324
- package/dist/server/plugins/index.d.ts +0 -17
- package/dist/server/rate-limit/index.d.ts +0 -105
- package/dist/server/realtime/index.d.ts +0 -15
- package/dist/server/scan/index.d.ts +0 -106
- package/dist/server/security/index.d.ts +0 -193
- package/dist/server/storage/index.d.ts +0 -22
- package/dist/server/webhook/index.d.ts +0 -148
- package/dist/storage-manager-C4jsO0Tp.d.ts +0 -89
- package/dist/storage-types-DsDTCPbp.d.ts +0 -96
- package/dist/vite-plugin/index.d.ts +0 -115
|
File without changes
|
package/dist/start-3ZHAXSJE.js
CHANGED
|
File without changes
|
package/dist/static-55G3LX2I.js
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/dist/vercel-J6G7ZHYQ.js
CHANGED
|
File without changes
|
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "theokit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
|
-
"scripts": {
|
|
8
|
-
"build": "tsup",
|
|
9
|
-
"test": "echo 'theokit tests run from root: pnpm test'"
|
|
10
|
-
},
|
|
11
7
|
"bin": {
|
|
12
8
|
"theokit": "./dist/cli/index.js"
|
|
13
9
|
},
|
|
@@ -109,7 +105,7 @@
|
|
|
109
105
|
"dist"
|
|
110
106
|
],
|
|
111
107
|
"dependencies": {
|
|
112
|
-
"@theokit/agents": "^0.
|
|
108
|
+
"@theokit/agents": "^0.27.0",
|
|
113
109
|
"@theokit/http": "^0.5.4",
|
|
114
110
|
"@vitejs/plugin-react": "^4.7.0",
|
|
115
111
|
"busboy": "^1.6.0",
|
|
@@ -129,6 +125,7 @@
|
|
|
129
125
|
"peerDependencies": {
|
|
130
126
|
"@theokit/sdk": ">=2.9.0",
|
|
131
127
|
"@theokit/ui": "^0.14.0 || ^0.18.0 || ^0.19.0",
|
|
128
|
+
"ai": ">=7.0.0",
|
|
132
129
|
"db0": "^0.3.0",
|
|
133
130
|
"react": "^19.0.0",
|
|
134
131
|
"react-dom": "^19.0.0",
|
|
@@ -144,6 +141,9 @@
|
|
|
144
141
|
"@theokit/ui": {
|
|
145
142
|
"optional": true
|
|
146
143
|
},
|
|
144
|
+
"ai": {
|
|
145
|
+
"optional": true
|
|
146
|
+
},
|
|
147
147
|
"db0": {
|
|
148
148
|
"optional": true
|
|
149
149
|
},
|
|
@@ -155,8 +155,9 @@
|
|
|
155
155
|
}
|
|
156
156
|
},
|
|
157
157
|
"devDependencies": {
|
|
158
|
-
"@theokit/sdk": "^2.
|
|
158
|
+
"@theokit/sdk": "^2.13.0",
|
|
159
159
|
"@types/busboy": "^1.5.4",
|
|
160
|
+
"ai": "^7.0.14",
|
|
160
161
|
"@types/pg": "^8.20.0",
|
|
161
162
|
"@types/picomatch": "^4.0.3",
|
|
162
163
|
"better-sqlite3": "^12.11.1",
|
|
@@ -166,10 +167,13 @@
|
|
|
166
167
|
"unstorage": "^1.17.5"
|
|
167
168
|
},
|
|
168
169
|
"publishConfig": {
|
|
169
|
-
"provenance": true,
|
|
170
170
|
"access": "public"
|
|
171
171
|
},
|
|
172
172
|
"engines": {
|
|
173
173
|
"node": ">=22.12.0"
|
|
174
|
+
},
|
|
175
|
+
"scripts": {
|
|
176
|
+
"build": "tsup",
|
|
177
|
+
"test": "echo 'theokit tests run from root: pnpm test'"
|
|
174
178
|
}
|
|
175
|
-
}
|
|
179
|
+
}
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Web-to-Node bridge used by adapters whose runtimes provide a `Request`
|
|
3
|
-
* (Web Standard) but where TheoKit's `executeRoute` expects a Node-style
|
|
4
|
-
* IncomingMessage/ServerResponse pair.
|
|
5
|
-
*
|
|
6
|
-
* Used by adapters that target Node-compatible runtimes (Bun, Netlify
|
|
7
|
-
* Functions, AWS Lambda Node). Cloudflare uses an inline version of the same
|
|
8
|
-
* pattern — long-term it should consolidate here too.
|
|
9
|
-
*
|
|
10
|
-
* NOT used by Deno Deploy: Deno's stdlib does not have `Buffer`/`node:http`
|
|
11
|
-
* by default and forcing the shim there bloats the bundle. Deno wiring is
|
|
12
|
-
* tracked separately and will likely require executeRoute to accept Web
|
|
13
|
-
* Standard Request directly.
|
|
14
|
-
*/
|
|
15
|
-
interface ShimRequest {
|
|
16
|
-
method: string;
|
|
17
|
-
url: string;
|
|
18
|
-
headers: Record<string, string>;
|
|
19
|
-
socket: {
|
|
20
|
-
remoteAddress: string;
|
|
21
|
-
};
|
|
22
|
-
on: (event: 'data' | 'end' | 'error', cb: (chunk?: unknown) => void) => unknown;
|
|
23
|
-
}
|
|
24
|
-
interface ShimResponse {
|
|
25
|
-
statusCode: number;
|
|
26
|
-
headersSent: boolean;
|
|
27
|
-
writableEnded: boolean;
|
|
28
|
-
writeHead: (status: number, headers?: Record<string, string>) => void;
|
|
29
|
-
setHeader: (key: string, value: string) => void;
|
|
30
|
-
getHeader: (key: string) => string | undefined;
|
|
31
|
-
write: (chunk: Uint8Array | string) => boolean;
|
|
32
|
-
end: (body?: Uint8Array | string) => void;
|
|
33
|
-
}
|
|
34
|
-
interface ShimContext {
|
|
35
|
-
req: ShimRequest;
|
|
36
|
-
res: ShimResponse;
|
|
37
|
-
/** Resolves to a Web Standard Response once `res.end()` is called. */
|
|
38
|
-
toResponse: () => Promise<Response>;
|
|
39
|
-
}
|
|
40
|
-
interface CreateWebShimOptions {
|
|
41
|
-
/**
|
|
42
|
-
* CR-018 fix: how to resolve the client IP from forwarded headers.
|
|
43
|
-
*
|
|
44
|
-
* - `'platform'` (default for `cf-connecting-ip`): trust runtime-injected
|
|
45
|
-
* headers only (`cf-connecting-ip` on Cloudflare, `x-real-ip` on
|
|
46
|
-
* Netlify/Vercel when the platform writes it). Ignores
|
|
47
|
-
* `x-forwarded-for` because clients can spoof it.
|
|
48
|
-
* - `'trusted-proxy'`: read the **rightmost** entry of `x-forwarded-for`.
|
|
49
|
-
* Only safe when the request literally went through a trusted proxy
|
|
50
|
-
* that strips client-set headers and appends the real client IP last.
|
|
51
|
-
* - `'none'`: skip all forwarded-header lookups and report
|
|
52
|
-
* `'0.0.0.0'`. Force this when the adapter has no reliable way to
|
|
53
|
-
* identify the client (rate-limiters then must use a different key).
|
|
54
|
-
*
|
|
55
|
-
* Default: `'platform'`.
|
|
56
|
-
*/
|
|
57
|
-
trustedProxy?: 'platform' | 'trusted-proxy' | 'none';
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Build Node-style req/res objects around a Web Standard Request.
|
|
61
|
-
* `toResponse()` returns a Promise that resolves when `res.end()` has been
|
|
62
|
-
* invoked, materializing a Web Standard Response with the accumulated body
|
|
63
|
-
* + headers + status.
|
|
64
|
-
*/
|
|
65
|
-
declare function createWebShim(request: Request, options?: CreateWebShimOptions): ShimContext;
|
|
66
|
-
|
|
67
|
-
export { type CreateWebShimOptions, type ShimContext, type ShimRequest, type ShimResponse, createWebShim };
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* T3.1 — WebSocket cross-runtime bridges.
|
|
3
|
-
*
|
|
4
|
-
* Exports 4 bridges (Node `ws` package, Bun.serve, Deno.upgradeWebSocket,
|
|
5
|
-
* Cloudflare WebSocketPair) that adapt each runtime's native WebSocket API
|
|
6
|
-
* to a common `WebSocketLike` interface that user handlers (`defineWebSocket`)
|
|
7
|
-
* can consume uniformly.
|
|
8
|
-
*/
|
|
9
|
-
interface WebSocketLike {
|
|
10
|
-
send(data: string | Uint8Array | ArrayBuffer): void;
|
|
11
|
-
close(code?: number, reason?: string): void;
|
|
12
|
-
on(event: 'message' | 'close' | 'error', cb: (data?: unknown) => void): void;
|
|
13
|
-
}
|
|
14
|
-
interface WsHandler {
|
|
15
|
-
onOpen?: (ws: WebSocketLike) => void;
|
|
16
|
-
onMessage?: (ws: WebSocketLike, data: unknown) => void;
|
|
17
|
-
onClose?: (ws: WebSocketLike, code?: number, reason?: string) => void;
|
|
18
|
-
onError?: (ws: WebSocketLike, err: unknown) => void;
|
|
19
|
-
}
|
|
20
|
-
interface NodeWsLike {
|
|
21
|
-
on(event: string, cb: (arg?: unknown) => void): unknown;
|
|
22
|
-
send(data: unknown): void;
|
|
23
|
-
close(code?: number, reason?: string): void;
|
|
24
|
-
}
|
|
25
|
-
declare function createNodeWsBridge(handler: WsHandler): {
|
|
26
|
-
attach(nativeWs: NodeWsLike): WebSocketLike;
|
|
27
|
-
};
|
|
28
|
-
interface BunWsContext {
|
|
29
|
-
send(data: unknown): void;
|
|
30
|
-
close(code?: number, reason?: string): void;
|
|
31
|
-
}
|
|
32
|
-
interface BunWebSocketConfig {
|
|
33
|
-
open: (ws: BunWsContext) => void;
|
|
34
|
-
message: (ws: BunWsContext, message: unknown) => void;
|
|
35
|
-
close: (ws: BunWsContext, code?: number, reason?: string) => void;
|
|
36
|
-
}
|
|
37
|
-
declare function createBunWsBridge(handler: WsHandler): BunWebSocketConfig;
|
|
38
|
-
interface DenoLike {
|
|
39
|
-
upgradeWebSocket(req: Request): {
|
|
40
|
-
response: Response;
|
|
41
|
-
socket: {
|
|
42
|
-
send(data: unknown): void;
|
|
43
|
-
close(code?: number, reason?: string): void;
|
|
44
|
-
addEventListener(event: string, cb: (e: unknown) => void): void;
|
|
45
|
-
};
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
declare function createDenoWsBridge(handler: WsHandler, denoNs: DenoLike): {
|
|
49
|
-
handle(request: Request): Response;
|
|
50
|
-
};
|
|
51
|
-
declare function createCloudflareWsBridge(handler: WsHandler): {
|
|
52
|
-
handle(request: Request): Response;
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
export { type BunWebSocketConfig, type WebSocketLike, type WsHandler, createBunWsBridge, createCloudflareWsBridge, createDenoWsBridge, createNodeWsBridge };
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* core/contracts/agent-events.ts
|
|
3
|
-
*
|
|
4
|
-
* Canonical home for the AgentEvent wire-format contract (T2.2 of
|
|
5
|
-
* architecture-cleanup plan; ADR-0001 v3 invariant #3 exception).
|
|
6
|
-
*
|
|
7
|
-
* Server emits via SSE; client consumes. Discriminated union by `type`.
|
|
8
|
-
* Both `server/agent/*` and `client/*` import from here.
|
|
9
|
-
*
|
|
10
|
-
* Per ADR-0001 v3: `cache → core/contracts`, `client → core/contracts`,
|
|
11
|
-
* `devtools → core/contracts` are LEGAL direct imports (this is the
|
|
12
|
-
* documented exception to the `no-cross-module-deep-import` rule).
|
|
13
|
-
*/
|
|
14
|
-
/**
|
|
15
|
-
* Discriminated union for AgentRunError codes (Phase 1 — Production-Readiness #3).
|
|
16
|
-
*
|
|
17
|
-
* Mirrors `@theokit/sdk`'s `AgentRunErrorCode` without hard-importing the SDK
|
|
18
|
-
* type (D2 decoupling). EC-7 forward-compat: `(string & {})` fallback preserves
|
|
19
|
-
* autocompletion for the known codes while accepting future codes the SDK may
|
|
20
|
-
* introduce — autocomplete works AND TS doesn't reject unknown codes.
|
|
21
|
-
*/
|
|
22
|
-
type AgentRunErrorCode = 'auth' | 'rate_limit' | 'quota_exceeded' | 'invalid_model' | 'invalid_request' | 'invalid_input' | 'context_too_large' | 'safety_blocked' | 'provider_unreachable' | 'tool_runtime_error' | 'aborted' | 'unknown' | (string & {});
|
|
23
|
-
interface AgentMessageEvent {
|
|
24
|
-
type: 'message';
|
|
25
|
-
content: string;
|
|
26
|
-
/** Optional id for client-side dedup / animation keys. */
|
|
27
|
-
id?: string;
|
|
28
|
-
}
|
|
29
|
-
interface AgentToolCallEvent {
|
|
30
|
-
type: 'tool_call';
|
|
31
|
-
name: string;
|
|
32
|
-
args: Record<string, unknown>;
|
|
33
|
-
id?: string;
|
|
34
|
-
}
|
|
35
|
-
interface AgentToolResultEvent {
|
|
36
|
-
type: 'tool_result';
|
|
37
|
-
name: string;
|
|
38
|
-
data: unknown;
|
|
39
|
-
id?: string;
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Error event emitted via SSE.
|
|
43
|
-
*
|
|
44
|
-
* Phase 1 — Production-Readiness #3:
|
|
45
|
-
* New optional fields `code/provider/retriable/retryAfterMs` discriminate
|
|
46
|
-
* error classes for client-side handling (auth → sign-in CTA; rate_limit →
|
|
47
|
-
* countdown; quota_exceeded → upsell; etc.).
|
|
48
|
-
*
|
|
49
|
-
* Backward compat (D4): all new fields are optional. Existing clients that
|
|
50
|
-
* read only `event.message` keep working unchanged. New clients can safely
|
|
51
|
-
* `switch (event.code)` — `undefined` (legacy server) is a valid case.
|
|
52
|
-
*
|
|
53
|
-
* EC-15 (DOCUMENT): `message` is *trusted* to not contain secrets. SDK's
|
|
54
|
-
* `AgentRunError.message` is propagated verbatim. The SDK's `providerError`
|
|
55
|
-
* is NEVER serialized into this event — quarantined to prevent leakage.
|
|
56
|
-
*/
|
|
57
|
-
interface AgentErrorEvent {
|
|
58
|
-
type: 'error';
|
|
59
|
-
message: string;
|
|
60
|
-
id?: string;
|
|
61
|
-
/** Discriminated error class — see AgentRunErrorCode. */
|
|
62
|
-
code?: AgentRunErrorCode;
|
|
63
|
-
/** Provider id (e.g., 'openai', 'anthropic', 'openrouter'). */
|
|
64
|
-
provider?: string;
|
|
65
|
-
/** Whether the SAME request can be retried as-is. */
|
|
66
|
-
retriable?: boolean;
|
|
67
|
-
/** Hint from provider's Retry-After header (milliseconds). Zero is valid (immediate retry). */
|
|
68
|
-
retryAfterMs?: number;
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Extended thinking / reasoning event.
|
|
72
|
-
*
|
|
73
|
-
* Carries the model's reasoning text (when the model supports extended
|
|
74
|
-
* thinking). Mirrors the `@theokit/agents` stream-layer `ThinkingEvent`
|
|
75
|
-
* (`packages/agents/src/bridge/agent-stream-events.ts`) so the two layers
|
|
76
|
-
* agree on the wire form; defined here (not imported) to keep `core/contracts`
|
|
77
|
-
* free of a dependency on `@theokit/agents` (G1 dependency direction).
|
|
78
|
-
*
|
|
79
|
-
* Consumers that switch only on the other variants are unaffected (additive);
|
|
80
|
-
* a consumer that wants to surface reasoning opts in by handling `'thinking'`.
|
|
81
|
-
*/
|
|
82
|
-
interface AgentThinkingEvent {
|
|
83
|
-
type: 'thinking';
|
|
84
|
-
content: string;
|
|
85
|
-
/** Optional id for client-side dedup / animation keys. */
|
|
86
|
-
id?: string;
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Runtime AgentEvent — discriminated union of the 5 variants emitted by
|
|
90
|
-
* agent endpoints. Server produces; client consumes.
|
|
91
|
-
*/
|
|
92
|
-
type AgentEvent = AgentMessageEvent | AgentToolCallEvent | AgentToolResultEvent | AgentErrorEvent | AgentThinkingEvent;
|
|
93
|
-
|
|
94
|
-
export type { AgentEvent as A, AgentErrorEvent as a, AgentMessageEvent as b, AgentThinkingEvent as c, AgentToolCallEvent as d, AgentToolResultEvent as e, AgentRunErrorCode as f };
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* T4.1 — Audit logging interface + default JSON stdout sink.
|
|
3
|
-
*
|
|
4
|
-
* Per ADR D4: define the interface; ship a zero-dep default; reserve
|
|
5
|
-
* adapter shapes for Postgres, File, OpenTelemetry, Sentry as follow-up
|
|
6
|
-
* packages. Persistence has heavy deps (`pg`, `better-sqlite3`); we
|
|
7
|
-
* keep core dep-free and let users opt in.
|
|
8
|
-
*
|
|
9
|
-
* Compatibility:
|
|
10
|
-
* - Node / Bun / Deno / Vercel — console.log is sync, captured.
|
|
11
|
-
* - Edge runtimes (CF Workers, Vercel Edge) — console.log is captured
|
|
12
|
-
* but may be rate-limited by the platform. For high-volume edge audit,
|
|
13
|
-
* implement a custom sink writing to a queue / HTTP endpoint.
|
|
14
|
-
*/
|
|
15
|
-
interface AuditEvent {
|
|
16
|
-
/** Domain-qualified verb. Convention: `<domain>.<verb>` (e.g. csrf.warn, session.rotated). */
|
|
17
|
-
action: string;
|
|
18
|
-
/** Who triggered the event. Anonymous = no auth at time of event. */
|
|
19
|
-
actor?: {
|
|
20
|
-
type: 'user' | 'system' | 'anonymous';
|
|
21
|
-
id?: string;
|
|
22
|
-
};
|
|
23
|
-
/** What was operated on (optional). */
|
|
24
|
-
resource?: {
|
|
25
|
-
type: string;
|
|
26
|
-
id?: string;
|
|
27
|
-
};
|
|
28
|
-
/** Arbitrary event-specific metadata. JSON-serializable. */
|
|
29
|
-
metadata?: Record<string, unknown>;
|
|
30
|
-
/** ISO 8601 timestamp. If absent, sink fills in `new Date().toISOString()`. */
|
|
31
|
-
timestamp?: string;
|
|
32
|
-
/** Optional trace id (populated by middleware from `x-trace-id`). */
|
|
33
|
-
traceId?: string;
|
|
34
|
-
}
|
|
35
|
-
interface AuditLogger {
|
|
36
|
-
log(event: AuditEvent): void | Promise<void>;
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Default sink: one JSON line per event to stdout. Sync. Never throws.
|
|
40
|
-
*
|
|
41
|
-
* EC: circular refs / BigInt values fall back to a placeholder line so
|
|
42
|
-
* the event is still observable (action + traceId) without crashing the
|
|
43
|
-
* request lifecycle.
|
|
44
|
-
*/
|
|
45
|
-
declare class JsonStdoutSink implements AuditLogger {
|
|
46
|
-
log(event: AuditEvent): void;
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* No-op logger. Returned when `config.audit` is unset. Zero overhead;
|
|
50
|
-
* framework wiring sites null-check before calling.
|
|
51
|
-
*/
|
|
52
|
-
declare function createNoOpLogger(): AuditLogger;
|
|
53
|
-
/**
|
|
54
|
-
* T4.2 — Safe-emit wrapper. Used by framework wiring sites (csrf.ts,
|
|
55
|
-
* rate-limit.ts, session.ts) so a logger throw NEVER propagates into
|
|
56
|
-
* the request handler.
|
|
57
|
-
*/
|
|
58
|
-
declare function safeAudit(logger: AuditLogger | undefined, event: AuditEvent): void;
|
|
59
|
-
|
|
60
|
-
export { type AuditLogger as A, JsonStdoutSink as J, type AuditEvent as a, createNoOpLogger as c, safeAudit as s };
|
package/dist/boot/index.d.ts
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { R as ReservedRoutes } from '../health-route-C0hk64_U.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* M7-3 — `theokit/boot`: programmatic boot surface for the convention server.
|
|
5
|
-
*
|
|
6
|
-
* The programmatic surface is a Web `fetch` handler (the universal "fetch
|
|
7
|
-
* handler is the entry point" contract — see the hono reference in
|
|
8
|
-
* knowledge-base/discoveries/blueprints/m7-http-dual-surface-blueprint.md
|
|
9
|
-
* "Coverage Corner 4"). It composes M7-1 (typed 404 envelope) + M7-2 (reserved
|
|
10
|
-
* health/ready routes) and binds NO socket, so embedders + integration tests
|
|
11
|
-
* can fire requests in-process via `app.fetch(new Request(...))`.
|
|
12
|
-
*
|
|
13
|
-
* The CLI's `startDevServer`/`startCommand` (Vite/SSR machinery) intentionally
|
|
14
|
-
* stay in the `cli` module — `boot` must not depend on `cli` (architecture DAG:
|
|
15
|
-
* nothing depends on `cli`). The fetch handler IS the portable boot surface.
|
|
16
|
-
*
|
|
17
|
-
* @public
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
/** Options for {@link createConventionFetchHandler}. */
|
|
21
|
-
interface ConventionFetchHandlerOptions {
|
|
22
|
-
/** Reserved health/ready routes (M7-2). Liveness defaults to 200 even when omitted. */
|
|
23
|
-
readonly reservedRoutes?: ReservedRoutes;
|
|
24
|
-
}
|
|
25
|
-
/** A socketless convention-server handle. */
|
|
26
|
-
interface ConventionFetchHandle {
|
|
27
|
-
/** Serve a single request in-process (no socket). Reserved routes first, else a typed 404. */
|
|
28
|
-
fetch(request: Request): Promise<Response>;
|
|
29
|
-
/** Idempotent teardown. The in-process handler holds no socket, so this is a safe no-op. */
|
|
30
|
-
close(): Promise<void>;
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Build an in-process convention-server `fetch` handler. Reserved `/__theo/*`
|
|
34
|
-
* routes (health/ready) are served first; any other path yields a typed
|
|
35
|
-
* `NOT_FOUND` envelope (404) via the same translator the wire boundary uses.
|
|
36
|
-
*/
|
|
37
|
-
declare function createConventionFetchHandler(options?: ConventionFetchHandlerOptions): ConventionFetchHandle;
|
|
38
|
-
|
|
39
|
-
export { type ConventionFetchHandle, type ConventionFetchHandlerOptions, createConventionFetchHandler };
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server/define/define-route.ts","../src/server/define/define-action.ts","../src/server/define/define-middleware.ts","../src/server/define/define-agent-endpoint.ts","../src/server/define/define-agent-tool.ts","../src/server/define/define-websocket.ts","../src/server/define/define-channel.ts","../src/server/define/define-plugin.ts"],"sourcesContent":["import type { z } from 'zod'\n\n// T2.2 (architecture-cleanup) — RouteConfig type moved to core/contracts/\n// (canonical home per ADR-0001 v3). Re-export preserves the public path\n// `import { type RouteConfig } from 'theokit/server'`.\nexport type { RouteConfig } from '../../core/contracts/route-config.js'\n\nimport type { RouteConfig } from '../../core/contracts/route-config.js'\n\n/**\n * Define a typed HTTP route.\n * Identity function — provides type inference for route handlers.\n */\nexport function defineRoute<\n TQuery extends z.ZodType = z.ZodUndefined,\n TBody extends z.ZodType = z.ZodUndefined,\n TParams extends z.ZodType = z.ZodUndefined,\n TCtx = unknown,\n TResponse = unknown,\n>(\n config: RouteConfig<TQuery, TBody, TParams, TCtx, TResponse>,\n): RouteConfig<TQuery, TBody, TParams, TCtx, TResponse> {\n return config\n}\n","import type { z } from 'zod'\n\n/**\n * Action wire-protocol accept mode per plan g3-server-actions-and-useaction\n * v1.2 ADR D1. Default behavior (when omitted) is `'json'`. `'form'` opts the\n * action into FormData multipart parsing for progressive-enhancement forms;\n * the runtime in `server/http/action-execute.ts` will coerce FormData entries\n * against the `input` schema via `formDataToObject` (Astro pattern).\n */\nexport type ActionAccept = 'form' | 'json'\n\nexport interface ActionConfig<TInput extends z.ZodType, TCtx = unknown> {\n /**\n * Zod input schema. Required: every action declares its input contract via\n * Zod (architecture rule: zod-is-SSOT). The shape becomes the handler's\n * typed `input` parameter via `z.infer<TInput>`.\n */\n input: TInput\n /**\n * Wire-protocol accept mode. Defaults to `'json'` when omitted. Setting\n * `'form'` switches the runtime to FormData multipart parsing — the input\n * schema MUST be `z.object(...)` so field-by-field coercion can drive\n * boolean string / number / array coercion (Astro pattern).\n */\n accept?: ActionAccept\n /**\n * Opt OUT of CSRF enforcement for this action. Default (omitted) keeps the\n * multi-header CSRF gate active. Set `false` for endpoints intentionally\n * callable without the `X-Theo-Action` header (e.g. public webhooks). The\n * runtime in `server/http/action-execute.ts` reads this flag.\n */\n csrf?: false\n handler: (ctx: { input: z.infer<TInput>; ctx: TCtx }) => unknown\n}\n\n/**\n * Define a typed server action.\n *\n * Identity function — provides type inference for action handlers. The\n * runtime that consumes the config (validation + invocation + serialization)\n * lives in `server/http/action-execute.ts`.\n *\n * Per plan g3-server-actions-and-useaction v1.2 § Phase 1 / T1.2: the new\n * `accept?: 'form' | 'json'` field is the only contract change vs the\n * pre-G3 identity. Existing callsites (`defineAction({input, handler})`)\n * continue to compile — `accept` is opt-in.\n */\nexport function defineAction<TInput extends z.ZodType, TCtx = unknown>(\n config: ActionConfig<TInput, TCtx>,\n): ActionConfig<TInput, TCtx> {\n return config\n}\n","export type MiddlewareHandler = (\n request: Request,\n next: (request: Request) => Promise<Response>,\n) => Response | Promise<Response>\n\n/**\n * Define a middleware handler.\n * Identity function — provides type annotation for middleware.\n */\nexport function defineMiddleware(handler: MiddlewareHandler): MiddlewareHandler {\n return handler\n}\n","import type { z } from 'zod'\n\nimport type { AgentEvent } from '../agent/agent-types.js'\n\nimport type { RouteConfig } from './define-route.js'\n\n/**\n * T5.1 — defineAgentEndpoint\n *\n * Sugar over defineRoute (ADR D4). Accepts an async generator that yields\n * AgentEvents and produces a RouteConfig whose handler returns a Response\n * streaming Server-Sent Events (SSE).\n *\n * Wire format: `data: <JSON>\\n\\n` per event. Standards-compliant.\n *\n * The generator may throw — the wrapper catches and emits a final\n * `{ type: 'error', message }` event before closing the stream.\n *\n * The wrapper observes `request.signal` (EC-7) — when aborted, the\n * underlying generator is told to `return()` and the stream closes\n * promptly.\n *\n * Note (EC-12, Out of Scope): SSE backpressure (slow consumer) is not\n * handled here. For high-frequency token streaming consider a different\n * transport (WS) or a buffer policy. This MVP enqueues each event\n * immediately.\n */\n\nexport interface AgentEndpointHandlerArgs<\n TCtx = unknown,\n TBody = unknown,\n TParams extends z.ZodType = z.ZodUndefined,\n> {\n query: undefined\n body: TBody\n params: z.infer<TParams>\n request: Request\n ctx: TCtx\n /**\n * Mutable headers bag that the wrapper merges into the SSE response BEFORE\n * the stream starts. Used by `createConversationHistory` to issue a\n * conversation-id cookie on first request. Append entries via\n * `cookieHeaders.append('set-cookie', '<cookie-string>')`.\n *\n * Cookies appended AFTER the first yield are NOT applied — the response\n * headers commit when the wrapper constructs the Response, before the\n * async generator runs. This is per HTTP semantics, not a wrapper choice.\n */\n cookieHeaders: Headers\n /**\n * Phase 3 (Production-Readiness #5) — request abort signal.\n *\n * Fires when the SSE client disconnects (browser closes tab, abort fetch,\n * etc.). Thread this to `agent.send(msg, { signal })` so the SDK cancels\n * the in-flight provider call — STOPS TOKENS FROM CHARGING for output\n * the user will never receive.\n *\n * EC-1 (MUST FIX): the signal is derived via duck-type detection\n * (`'aborted' in r.signal && typeof r.signal.addEventListener === 'function'`)\n * to survive cross-realm scenarios (Node 18 polyfills, undici, Edge\n * runtimes with their own AbortSignal globals). `instanceof AbortSignal`\n * would fail in those cases.\n */\n signal: AbortSignal\n}\n\nexport interface AgentEndpointConfig<\n TCtx = unknown,\n TBody = unknown,\n TParams extends z.ZodType = z.ZodUndefined,\n> {\n /**\n * Optional Zod schema for path params (e.g. `z.object({ id: z.string() })`).\n * When present, the runner validates path params and returns 400 on mismatch\n * BEFORE the generator runs; the validated params are threaded to the\n * generator typed as `z.infer<TParams>` (D4).\n */\n params?: TParams\n handler: (\n args: AgentEndpointHandlerArgs<TCtx, TBody, TParams>,\n ) => AsyncGenerator<AgentEvent, void, unknown>\n}\n\nconst SSE_HEADERS = {\n 'content-type': 'text/event-stream',\n 'cache-control': 'no-cache, no-transform',\n connection: 'keep-alive',\n} as const\n\nfunction encodeSSE(event: AgentEvent): Uint8Array {\n return new TextEncoder().encode(`data: ${JSON.stringify(event)}\\n\\n`)\n}\n\n/**\n * Resolve an AbortSignal from either a Web `Request` (`.signal`) or a\n * Node `IncomingMessage` (`.socket` close + `'aborted'`/'close' events).\n *\n * The framework's `executeRoute` passes IncomingMessage to route handlers\n * today, but `defineAgentEndpoint` was designed for the Web Standards\n * `Request` shape. This helper bridges both — preventing a runtime crash\n * (`Cannot read properties of undefined (reading 'aborted')`) that would\n * otherwise abort the SSE stream silently before the first yield.\n *\n * Node ≥23 regression (empty-SSE-stream): Node 23 added\n * `http.IncomingMessage.prototype.signal` — a Web `AbortSignal` that fires\n * `abort` the instant the request body is fully received (`req.complete ===\n * true`), NOT when the client disconnects. The earlier duck-type\n * (\"has `.signal` with `aborted` + `addEventListener`\") matched a genuine Web\n * `Request` AND, on Node ≥23, the Node `IncomingMessage` — so the helper\n * returned the request-lifecycle signal, already aborted by the time the\n * handler primes, and EVERY agent stream produced 0 bytes on Node 24.\n *\n * Discriminator: a Node `IncomingMessage` is an `EventEmitter` (`typeof\n * r.on === 'function'`); a Web `Request` is not. So `r.signal` is trusted\n * directly ONLY when this is not a Node request. For the Node path the only\n * lifecycle event that means \"client disconnected\" (rather than \"request body\n * finished\") is the underlying SOCKET closing — `req`'s own `.signal`/`'close'`\n * fire at body-end on Node ≥23 and would kill a long-lived SSE response.\n */\nfunction resolveAbortSignal(request: unknown): AbortSignal {\n if (typeof request !== 'object' || request === null) {\n return new AbortController().signal\n }\n const r = request as {\n signal?: unknown\n aborted?: boolean\n complete?: boolean\n on?: (event: string, cb: () => void) => void\n socket?: { on?: (event: string, cb: () => void) => void }\n }\n\n // A genuine Web `Request` exposes `.signal` and is NOT a Node EventEmitter.\n const isNodeRequest = typeof r.on === 'function'\n if (\n !isNodeRequest &&\n typeof r.signal === 'object' &&\n r.signal !== null &&\n 'aborted' in r.signal &&\n typeof (r.signal as AbortSignal).addEventListener === 'function'\n ) {\n return r.signal as AbortSignal\n }\n\n const controller = new AbortController()\n const abort = () => {\n if (!controller.signal.aborted) controller.abort()\n }\n if (r.aborted === true) controller.abort()\n if (typeof r.on === 'function') {\n // Explicit client abort (request reset mid-flight).\n r.on('aborted', abort)\n // `req`'s own 'close' fires at request-completion on Node ≥23 (body fully\n // received), which is NOT a disconnect — guard with `complete`. A close\n // while the request already completed normally is body-end noise.\n r.on('close', () => {\n if (r.complete !== true) abort()\n })\n }\n // The underlying socket closes only on real connection teardown (client\n // gone), never at request-body-end — the correct disconnect signal for a\n // long-lived SSE response.\n const socket = r.socket\n if (socket && typeof socket.on === 'function') {\n socket.on('close', abort)\n }\n return controller.signal\n}\n\nexport function defineAgentEndpoint<\n TBody = unknown,\n TCtx = unknown,\n TParams extends z.ZodType = z.ZodUndefined,\n>(\n config: AgentEndpointConfig<TCtx, TBody, TParams>,\n): RouteConfig<z.ZodUndefined, z.ZodUndefined, TParams, TCtx, Response> {\n return {\n params: config.params,\n handler: async ({ request, ctx, body, query, params }) => {\n const cookieHeaders = new Headers()\n const signal = resolveAbortSignal(request)\n const generator = config.handler({\n request,\n ctx: ctx,\n body: body as TBody,\n query: query,\n params: params,\n cookieHeaders,\n signal,\n })\n\n // Prime the generator to its first yield. This forces the handler's\n // synchronous + async setup (including `createConversationHistory` if\n // used) to run BEFORE the Response headers commit, so any Set-Cookie\n // lines appended to `cookieHeaders` land in the actual response.\n //\n // First-byte latency cost: bounded by the work up to the first yield\n // (typically 100-500ms for an LLM chat with `agent.send`). Acceptable\n // for the use case; alternative (heuristic detection of cookie writes)\n // is brittle.\n let firstResult: IteratorResult<AgentEvent, void>\n let primeError: unknown\n try {\n firstResult = await generator.next()\n } catch (err) {\n primeError = err\n firstResult = { value: undefined, done: true }\n }\n\n // Merge any cookies the handler issued into the response headers.\n const responseHeaders = new Headers(SSE_HEADERS)\n for (const value of cookieHeaders.getSetCookie()) {\n responseHeaders.append('set-cookie', value)\n }\n\n const stream = new ReadableStream<Uint8Array>({\n async start(controller) {\n const onAbort = () => {\n void generator.return(undefined)\n }\n\n if (signal.aborted) {\n controller.close()\n return\n }\n signal.addEventListener('abort', onAbort, { once: true })\n\n try {\n // If priming threw, yield a final error event and close.\n if (primeError !== undefined) {\n let message: string\n if (primeError instanceof Error) {\n message = primeError.message\n } else if (typeof primeError === 'string') {\n message = primeError\n } else {\n message = 'agent handler failed during setup'\n }\n controller.enqueue(encodeSSE({ type: 'error', message }))\n return\n }\n // Enqueue the primed first value (if any).\n if (firstResult.done !== true) {\n controller.enqueue(encodeSSE(firstResult.value))\n } else {\n return\n }\n // Continue iterating remaining events.\n for await (const event of generator) {\n // `signal.aborted` can flip true asynchronously via the\n // listener registered above. ESLint's narrowing only sees\n // the false assertion at line 114; the dynamic abort is\n // legitimate and the guard prevents enqueue-after-close.\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (signal.aborted) break\n controller.enqueue(encodeSSE(event))\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n controller.enqueue(encodeSSE({ type: 'error', message }))\n } finally {\n signal.removeEventListener('abort', onAbort)\n controller.close()\n }\n },\n cancel() {\n void generator.return(undefined)\n },\n })\n\n return new Response(stream, { headers: responseHeaders })\n },\n }\n}\n","import { z } from 'zod'\n\n/**\n * Item #4 — `defineAgentTool`\n *\n * Sugar over the `@theokit/sdk` `CustomTool` contract. Takes a Zod schema +\n * handler and produces a structurally-compatible `CustomTool` that\n * `Agent.create({ tools: [...] })` accepts.\n *\n * Uses Zod v4's native `z.toJSONSchema()` to convert the input schema to\n * JSON Schema for LLM providers.\n *\n * Handler error propagation:\n * `defineAgentTool` parses the input via the Zod schema BEFORE calling the\n * user handler. Invalid input throws a `ZodError`, which the SDK's tool-\n * dispatcher (or the `streamAgentRun` adapter) sees as a tool failure and\n * surfaces as an `error` AgentEvent on the SSE wire (ADR D3).\n */\n\n/**\n * Local mirror of the SDK's `CustomTool` interface. We don't `import type`\n * from `@theokit/sdk` because the SDK is an optional peer (consumers who\n * never call `defineAgentTool` shouldn't need it installed). The shape is\n * the wire contract; any structurally-matching object is accepted by\n * `Agent.create({ tools })`.\n *\n * @public\n */\nexport interface CustomTool {\n name: string\n description: string\n inputSchema: Record<string, unknown>\n handler: (input: Record<string, unknown>) => string | Promise<string>\n}\n\n/**\n * Spec accepted by {@link defineAgentTool}. `inputSchema` is a Zod 3 schema\n * rooted in `z.object(...)`. The `handler` argument type is inferred via\n * `z.infer<T>`.\n *\n * @public\n */\nexport interface DefineAgentToolSpec<T extends z.ZodType> {\n /** Tool name surfaced to the LLM. Must match `^[a-zA-Z][a-zA-Z0-9_-]{0,63}$`. */\n name: string\n /** Description surfaced to the LLM. Required — drives tool-selection accuracy. */\n description: string\n /** Zod schema describing the input. Must be `z.object(...)` at the root. */\n inputSchema: T\n /** Handler invoked with the parsed input. */\n handler: (input: z.infer<T>) => string | Promise<string>\n}\n\nconst TOOL_NAME_REGEX = /^[a-zA-Z][a-zA-Z0-9_-]{0,63}$/\n\nfunction isZodObject(schema: z.ZodType): boolean {\n // Refinements (`.refine`), transforms (`.transform`), and defaults wrap the\n // underlying schema — walk the chain until we hit a ZodObject (or give up).\n // Supports both zod 4 (`instanceof z.ZodObject`, `def.type === 'object'`,\n // wrappers via `def.innerType` / pipe via `def.in`) and zod 3\n // (`_def.typeName === 'ZodObject'`, wrappers via `_def.schema`/`_def.innerType`).\n let current: unknown = schema\n for (let depth = 0; depth < 10; depth++) {\n if (current instanceof z.ZodObject) return true\n const z4 = (current as { def?: { type?: string; innerType?: unknown; in?: unknown } }).def\n if (z4?.type === 'object') return true\n const z3 = (current as { _def?: { typeName?: string; schema?: unknown; innerType?: unknown } })\n ._def\n if (z3?.typeName === 'ZodObject') return true\n const next = z4?.innerType ?? z4?.in ?? z3?.schema ?? z3?.innerType\n if (next !== undefined) {\n current = next\n continue\n }\n return false\n }\n return false\n}\n\n/**\n * Build a {@link CustomTool} from a Zod 3 schema + handler.\n *\n * Behavior:\n * - Validates `name` matches the LLM tool-name regex.\n * - Requires `inputSchema` to be a `ZodObject` (Anthropic + SDK contract).\n * - Warns (not throws) if `description` is empty — empty descriptions\n * degrade LLM tool selection.\n * - Converts the Zod schema to JSON Schema 7 inline (no `$ref`s — LLMs handle\n * inline schemas more reliably).\n * - Strips the top-level `$schema` field (Anthropic rejects schemas with\n * `$schema` at root in some provider modes).\n * - Wraps the handler to parse the input via the Zod schema BEFORE invoking\n * the user code — bad LLM-supplied input throws `ZodError`, which the SDK\n * converts to `tool_result(isError)`.\n *\n * @public\n */\nexport function defineAgentTool<T extends z.ZodType>(spec: DefineAgentToolSpec<T>): CustomTool {\n if (!TOOL_NAME_REGEX.test(spec.name)) {\n throw new Error(\n `defineAgentTool: name must match ${TOOL_NAME_REGEX.source}. Got: ${JSON.stringify(spec.name)}`,\n )\n }\n if (!isZodObject(spec.inputSchema)) {\n throw new Error('defineAgentTool: inputSchema must be a ZodObject (z.object({...}))')\n }\n if (spec.description.length === 0) {\n console.warn(\n `defineAgentTool(${JSON.stringify(spec.name)}): empty description degrades LLM tool selection — provide a one-sentence summary.`,\n )\n }\n\n // Zod v4 native JSON Schema conversion — replaces zod-to-json-schema dep.\n // Strip $schema (Anthropic + some providers reject it).\n const { $schema: _$schema, ...inputSchema } = z.toJSONSchema(spec.inputSchema) as Record<\n string,\n unknown\n > & {\n $schema?: unknown\n }\n\n return {\n name: spec.name,\n description: spec.description,\n inputSchema,\n handler: async (input: Record<string, unknown>): Promise<string> => {\n const parsed = spec.inputSchema.parse(input)\n return await spec.handler(parsed)\n },\n }\n}\n","import type { IncomingMessage } from 'node:http'\n\nexport interface WebSocketLike {\n send(data: string | Buffer): void\n close(code?: number, reason?: string): void\n}\n\nexport interface WebSocketHandler {\n onOpen?: (ws: WebSocketLike, req: IncomingMessage) => void\n onMessage?: (ws: WebSocketLike, data: string | Buffer) => void\n onClose?: (ws: WebSocketLike, code: number, reason: Buffer) => void\n onError?: (ws: WebSocketLike, error: Error) => void\n}\n\n/**\n * Define a WebSocket endpoint handler.\n * Identity function — provides type inference for WebSocket handlers.\n */\nexport function defineWebSocket(handler: WebSocketHandler): WebSocketHandler {\n return handler\n}\n\n/**\n * T5a.2 Phase F slice 3/3 — Web-Standards WebSocket endpoint handler.\n *\n * Mirror of `WebSocketHandler` for the Web `Request` shape. `onOpen`\n * receives `request: Request` instead of `req: IncomingMessage`. The\n * rest of the lifecycle (onMessage, onClose, onError) is shape-agnostic\n * (`WebSocketLike` is already Web-standards-compatible per the existing\n * design — `send(string | Buffer)` works on both Node `ws` and Web\n * `WebSocket` instances; CF Workers / Bun / Deno coerce as needed at\n * the adapter boundary).\n *\n * Per `docs/plans/t5a2-incoming-message-to-request-shape-refactor-plan.md`\n * v1.0 § Phase F (closes Phase F).\n *\n * **Architectural note — WebSocket upgrade semantics differ across runtimes:**\n * - Node + `ws`: `WebSocketServer.handleUpgrade(req, socket, head, cb)` —\n * `req` is `IncomingMessage`. Use `WebSocketHandler`.\n * - CF Workers: `new WebSocketPair()` + `request.headers` (the upgrade\n * handshake IS a Web Request). Use `WebSocketHandlerWeb`.\n * - Bun: `server.upgrade(request, { data })` — same Web Request shape.\n * - Deno: `Deno.upgradeWebSocket(request)` — same Web Request shape.\n *\n * Cross-runtime WebSocket endpoints ship BOTH `WebSocketHandler` +\n * `WebSocketHandlerWeb` exports; the runtime adapter picks the matching\n * one. This is the canonical Hono / Nitric pattern.\n */\nexport interface WebSocketHandlerWeb {\n onOpen?: (ws: WebSocketLike, request: Request) => void\n onMessage?: (ws: WebSocketLike, data: string | Uint8Array) => void\n onClose?: (ws: WebSocketLike, code: number, reason: string) => void\n onError?: (ws: WebSocketLike, error: Error) => void\n}\n\n/**\n * Web-Standards `defineWebSocket` sibling. Identity function — provides\n * type inference for Web WebSocket handlers.\n *\n * **Type difference note vs Node path:**\n * - `onMessage` data is `string | Uint8Array` instead of `string | Buffer`\n * (Web standards have no `Buffer`; Node's Buffer is a Uint8Array\n * subclass so the Node path's Buffer values flow through unchanged\n * when adapters wrap them).\n * - `onClose` reason is `string` instead of `Buffer` (Web `CloseEvent`\n * exposes the reason as a UTF-8 string natively).\n */\nexport function defineWebSocketWeb(handler: WebSocketHandlerWeb): WebSocketHandlerWeb {\n return handler\n}\n","import type { IncomingMessage } from 'node:http'\n\nimport type { WebSocketLike } from './define-websocket.js'\n\nexport interface ChannelHandler<TMessage = unknown> {\n onSubscribe?: (ws: WebSocketLike, room: string, req: IncomingMessage) => void\n onMessage?: (ws: WebSocketLike, room: string, data: TMessage) => void\n onUnsubscribe?: (ws: WebSocketLike, room: string) => void\n}\n\n/**\n * Define a channel handler for WebSocket rooms.\n * Identity function — provides type inference for channel handlers.\n */\nexport function defineChannel<TMessage = unknown>(\n handler: ChannelHandler<TMessage>,\n): ChannelHandler<TMessage> {\n return handler\n}\n\n/**\n * T5a.2 Phase F slice 2/3 — Web-Standards channel handler.\n *\n * Mirror of `ChannelHandler<TMessage>` for the Web `Request` shape.\n * `onSubscribe` receives `request: Request` instead of `req: IncomingMessage`\n * — the rest of the surface (onMessage, onUnsubscribe) is shape-agnostic\n * (WebSocketLike is already Web-standards-compatible per `define-websocket.ts`).\n *\n * Per `docs/plans/t5a2-incoming-message-to-request-shape-refactor-plan.md`\n * v1.0 § Phase F.\n *\n * **Architectural note:** WebSocket upgrade semantics differ across\n * runtimes:\n * - Node: `WebSocketServer.handleUpgrade(req, socket, head, cb)` —\n * hands you `req: IncomingMessage` at the upgrade handshake.\n * - CF Workers: `new WebSocketPair()` + `request.headers` (the upgrade\n * handshake IS a Web Request) — hands you `request: Request`.\n * - Bun: `server.upgrade(request, { data })` — same Web Request shape.\n * - Deno: `Deno.upgradeWebSocket(request)` — same Web Request shape.\n *\n * Channel handlers targeting CF/Bun/Deno use `WebChannelHandler`; legacy\n * Node consumers stay on `ChannelHandler`. Cross-runtime channels ship\n * both shapes.\n */\nexport interface WebChannelHandler<TMessage = unknown> {\n onSubscribe?: (ws: WebSocketLike, room: string, request: Request) => void\n onMessage?: (ws: WebSocketLike, room: string, data: TMessage) => void\n onUnsubscribe?: (ws: WebSocketLike, room: string) => void\n}\n\n/**\n * Web-Standards `defineChannel` sibling. Identity function — provides\n * type inference for Web channel handlers.\n */\nexport function defineWebChannel<TMessage = unknown>(\n handler: WebChannelHandler<TMessage>,\n): WebChannelHandler<TMessage> {\n return handler\n}\n","import type { TheoPlugin } from '../plugin-types.js'\n\n/**\n * Identity function for defining a Theo plugin.\n *\n * **Note:** Prefer `definePlugin` (shorter, canonical name per ADR-0008 D6).\n * Both functions are identical — `defineTheoPlugin` is kept as an alias for\n * existing in-tree consumers without forcing a migration sweep.\n */\nexport function defineTheoPlugin(plugin: TheoPlugin): TheoPlugin {\n return plugin\n}\n"],"mappings":"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","names":[]}
|