gemi 0.106.0 → 0.108.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/ai/Agent.d.ts +88 -10
- package/dist/ai/Agent.d.ts.map +1 -1
- package/dist/ai/AgentController.d.ts +29 -1
- package/dist/ai/AgentController.d.ts.map +1 -1
- package/dist/ai/Schema.d.ts +26 -3
- package/dist/ai/Schema.d.ts.map +1 -1
- package/dist/ai/client/index.js +86 -25
- package/dist/ai/client/index.js.map +1 -1
- package/dist/ai/client/reducer.d.ts.map +1 -1
- package/dist/ai/contextWindow.d.ts +122 -0
- package/dist/ai/contextWindow.d.ts.map +1 -0
- package/dist/ai/index.d.ts +3 -1
- package/dist/ai/index.d.ts.map +1 -1
- package/dist/ai/index.js +14 -14
- package/dist/ai/index.js.map +7 -6
- package/dist/ai/types.d.ts +9 -0
- package/dist/ai/types.d.ts.map +1 -1
- package/dist/ai/useChat.d.ts +47 -1
- package/dist/ai/useChat.d.ts.map +1 -1
- package/dist/app/index.js +2 -2
- package/dist/app/index.js.map +1 -1
- package/dist/bin/gemi.js +171 -20
- package/dist/bin/gemi.js.map +8 -7
- package/dist/bun/customRequestParser.d.ts +9 -0
- package/dist/bun/customRequestParser.d.ts.map +1 -0
- package/dist/bun/plugin.js +2 -2
- package/dist/bun/plugin.js.map +1 -1
- package/dist/bun/preload.js +2 -2
- package/dist/bun/preload.js.map +2 -2
- package/dist/{chunk-rjcmbwcc.js → chunk-00y49jcf.js} +2 -2
- package/dist/{chunk-rjcmbwcc.js.map → chunk-00y49jcf.js.map} +1 -1
- package/dist/{chunk-22k4b395.js → chunk-1npdp1w2.js} +2 -2
- package/dist/{chunk-22k4b395.js.map → chunk-1npdp1w2.js.map} +1 -1
- package/dist/{chunk-j6e99sra.js → chunk-1rs13253.js} +75 -75
- package/dist/{chunk-j6e99sra.js.map → chunk-1rs13253.js.map} +4 -5
- package/dist/{chunk-0fney17e.js → chunk-2gmgd05c.js} +2 -2
- package/dist/{chunk-0fney17e.js.map → chunk-2gmgd05c.js.map} +1 -1
- package/dist/{chunk-k6rd1nd4.js → chunk-2mhx4e4g.js} +3 -3
- package/dist/{chunk-k6rd1nd4.js.map → chunk-2mhx4e4g.js.map} +1 -1
- package/dist/{chunk-4f7n1r02.js → chunk-2q7m8a16.js} +2 -2
- package/dist/{chunk-4f7n1r02.js.map → chunk-2q7m8a16.js.map} +1 -1
- package/dist/{chunk-cbywzv21.js → chunk-2xqrh6d0.js} +1 -1
- package/dist/{chunk-gyareq03.js → chunk-331s9wqr.js} +3 -3
- package/dist/{chunk-gyareq03.js.map → chunk-331s9wqr.js.map} +1 -1
- package/dist/{chunk-1xzdexbq.js → chunk-3s3awh38.js} +2 -2
- package/dist/{chunk-1xzdexbq.js.map → chunk-3s3awh38.js.map} +1 -1
- package/dist/{chunk-v4exgqbp.js → chunk-47rgq59q.js} +2 -2
- package/dist/{chunk-v4exgqbp.js.map → chunk-47rgq59q.js.map} +1 -1
- package/dist/{chunk-fcsq613t.js → chunk-4rr9wmh8.js} +2 -2
- package/dist/{chunk-fcsq613t.js.map → chunk-4rr9wmh8.js.map} +1 -1
- package/dist/{chunk-9a8qz3s7.js → chunk-564zfdd1.js} +2 -2
- package/dist/{chunk-9a8qz3s7.js.map → chunk-564zfdd1.js.map} +1 -1
- package/dist/{chunk-st0d3ndv.js → chunk-5wt25tyd.js} +2 -2
- package/dist/{chunk-st0d3ndv.js.map → chunk-5wt25tyd.js.map} +1 -1
- package/dist/{chunk-gy6d6jeg.js → chunk-661wezaf.js} +2 -2
- package/dist/{chunk-gy6d6jeg.js.map → chunk-661wezaf.js.map} +1 -1
- package/dist/{chunk-yxh4xs3k.js → chunk-6rz8kyqb.js} +2 -2
- package/dist/{chunk-yxh4xs3k.js.map → chunk-6rz8kyqb.js.map} +1 -1
- package/dist/{chunk-18aqqrev.js → chunk-6wrhc9bq.js} +3 -3
- package/dist/{chunk-18aqqrev.js.map → chunk-6wrhc9bq.js.map} +1 -1
- package/dist/{chunk-3m93v7bt.js → chunk-82hpq0bq.js} +2 -2
- package/dist/{chunk-3m93v7bt.js.map → chunk-82hpq0bq.js.map} +1 -1
- package/dist/{chunk-ee92kx8s.js → chunk-8pynv9rw.js} +2 -2
- package/dist/{chunk-ee92kx8s.js.map → chunk-8pynv9rw.js.map} +1 -1
- package/dist/{chunk-7kedxtbp.js → chunk-9hbwvcxn.js} +2 -2
- package/dist/{chunk-7kedxtbp.js.map → chunk-9hbwvcxn.js.map} +1 -1
- package/dist/{chunk-47dqttnk.js → chunk-9jz4rggd.js} +2 -2
- package/dist/{chunk-47dqttnk.js.map → chunk-9jz4rggd.js.map} +1 -1
- package/dist/{chunk-xnggfm0s.js → chunk-9mqqr05d.js} +3 -3
- package/dist/{chunk-xnggfm0s.js.map → chunk-9mqqr05d.js.map} +1 -1
- package/dist/{chunk-gvkydx8r.js → chunk-9r3znmqq.js} +2 -2
- package/dist/{chunk-gvkydx8r.js.map → chunk-9r3znmqq.js.map} +1 -1
- package/dist/{chunk-zq5m4scz.js → chunk-a1g0bahx.js} +2 -2
- package/dist/{chunk-zq5m4scz.js.map → chunk-a1g0bahx.js.map} +1 -1
- package/dist/{chunk-5ngv175h.js → chunk-anp4kv3w.js} +1 -1
- package/dist/{chunk-tnp1sc4j.js → chunk-b9av1sgb.js} +2 -2
- package/dist/{chunk-tnp1sc4j.js.map → chunk-b9av1sgb.js.map} +1 -1
- package/dist/chunk-cewyag0d.js +6 -0
- package/dist/{chunk-qxg2dnnr.js.map → chunk-cewyag0d.js.map} +2 -2
- package/dist/{chunk-214av8am.js → chunk-cfsscms3.js} +4 -4
- package/dist/{chunk-214av8am.js.map → chunk-cfsscms3.js.map} +1 -1
- package/dist/{chunk-q8r9mvzx.js → chunk-eytdyahy.js} +2 -2
- package/dist/{chunk-q8r9mvzx.js.map → chunk-eytdyahy.js.map} +1 -1
- package/dist/{chunk-j041a7ej.js → chunk-ffagkj3x.js} +2 -2
- package/dist/{chunk-j041a7ej.js.map → chunk-ffagkj3x.js.map} +1 -1
- package/dist/{chunk-gvv2trvz.js → chunk-fq3sb3xt.js} +3 -3
- package/dist/{chunk-gvv2trvz.js.map → chunk-fq3sb3xt.js.map} +1 -1
- package/dist/{chunk-b1dqx3b9.js → chunk-ftgd68se.js} +3 -3
- package/dist/{chunk-b1dqx3b9.js.map → chunk-ftgd68se.js.map} +1 -1
- package/dist/{chunk-j9deswmn.js → chunk-fwympxqk.js} +2 -2
- package/dist/{chunk-j9deswmn.js.map → chunk-fwympxqk.js.map} +1 -1
- package/dist/{chunk-5dwtmkk8.js → chunk-gqpge54c.js} +2 -2
- package/dist/{chunk-5dwtmkk8.js.map → chunk-gqpge54c.js.map} +1 -1
- package/dist/chunk-h2hdpm70.js +24 -0
- package/dist/{chunk-70e5fypb.js.map → chunk-h2hdpm70.js.map} +6 -5
- package/dist/{chunk-r5pnz4nn.js → chunk-h3t4n0bn.js} +2 -2
- package/dist/{chunk-r5pnz4nn.js.map → chunk-h3t4n0bn.js.map} +1 -1
- package/dist/{chunk-zm00crsx.js → chunk-h4x7cba0.js} +3 -3
- package/dist/{chunk-zm00crsx.js.map → chunk-h4x7cba0.js.map} +1 -1
- package/dist/{chunk-b0jpvp5t.js → chunk-h7pafjej.js} +3 -3
- package/dist/{chunk-b0jpvp5t.js.map → chunk-h7pafjej.js.map} +1 -1
- package/dist/{chunk-63hvh35x.js → chunk-hdhahvd4.js} +2 -2
- package/dist/{chunk-63hvh35x.js.map → chunk-hdhahvd4.js.map} +1 -1
- package/dist/{chunk-zytmxty5.js → chunk-hyfzw1fk.js} +2 -2
- package/dist/{chunk-zytmxty5.js.map → chunk-hyfzw1fk.js.map} +1 -1
- package/dist/{chunk-zmag8k0z.js → chunk-jnw73s8c.js} +2 -2
- package/dist/{chunk-zmag8k0z.js.map → chunk-jnw73s8c.js.map} +1 -1
- package/dist/{chunk-bsq80942.js → chunk-k17prwhx.js} +3 -3
- package/dist/{chunk-bsq80942.js.map → chunk-k17prwhx.js.map} +1 -1
- package/dist/{chunk-xxkk60aw.js → chunk-k9qmr2wa.js} +3 -3
- package/dist/{chunk-xxkk60aw.js.map → chunk-k9qmr2wa.js.map} +1 -1
- package/dist/chunk-kda25fn4.js +5 -0
- package/dist/chunk-kda25fn4.js.map +10 -0
- package/dist/{chunk-cw7qfcvt.js → chunk-kh273hj0.js} +2 -2
- package/dist/{chunk-cw7qfcvt.js.map → chunk-kh273hj0.js.map} +1 -1
- package/dist/{chunk-kwkbzswm.js → chunk-kqff894s.js} +2 -2
- package/dist/{chunk-kwkbzswm.js.map → chunk-kqff894s.js.map} +1 -1
- package/dist/{chunk-ma5rmcbe.js → chunk-kqz8jp6v.js} +2 -2
- package/dist/{chunk-ma5rmcbe.js.map → chunk-kqz8jp6v.js.map} +1 -1
- package/dist/{chunk-dtybftkq.js → chunk-kstvyvr0.js} +2 -2
- package/dist/{chunk-dtybftkq.js.map → chunk-kstvyvr0.js.map} +1 -1
- package/dist/{chunk-h945tg0r.js → chunk-m31pfz1s.js} +2 -2
- package/dist/{chunk-h945tg0r.js.map → chunk-m31pfz1s.js.map} +1 -1
- package/dist/{chunk-4p752vk2.js → chunk-mhq2bd9c.js} +3 -3
- package/dist/{chunk-4p752vk2.js.map → chunk-mhq2bd9c.js.map} +1 -1
- package/dist/chunk-mrvcaakf.js +5 -0
- package/dist/{chunk-f2n21fef.js.map → chunk-mrvcaakf.js.map} +1 -1
- package/dist/chunk-ncfxmtd5.js +17 -0
- package/dist/{chunk-48wh5mbp.js.map → chunk-ncfxmtd5.js.map} +13 -8
- package/dist/{chunk-ayss2f8c.js → chunk-njkk498k.js} +2 -2
- package/dist/{chunk-ayss2f8c.js.map → chunk-njkk498k.js.map} +1 -1
- package/dist/{chunk-hwc8gt4n.js → chunk-pj2e1p07.js} +2 -2
- package/dist/{chunk-hwc8gt4n.js.map → chunk-pj2e1p07.js.map} +1 -1
- package/dist/{chunk-5k3rm4b6.js → chunk-q2fyp44f.js} +2 -2
- package/dist/{chunk-5k3rm4b6.js.map → chunk-q2fyp44f.js.map} +1 -1
- package/dist/{chunk-53we503k.js → chunk-q7y9v2v5.js} +3 -3
- package/dist/{chunk-53we503k.js.map → chunk-q7y9v2v5.js.map} +1 -1
- package/dist/chunk-rh9j8cwv.js +9 -0
- package/dist/chunk-rh9j8cwv.js.map +31 -0
- package/dist/{chunk-sedwjgvf.js → chunk-rjernda5.js} +2 -2
- package/dist/{chunk-sedwjgvf.js.map → chunk-rjernda5.js.map} +1 -1
- package/dist/{chunk-2baxmae9.js → chunk-rn2kgbg4.js} +2 -2
- package/dist/{chunk-2baxmae9.js.map → chunk-rn2kgbg4.js.map} +1 -1
- package/dist/{chunk-8nkdvgd9.js → chunk-sbyqs03h.js} +2 -2
- package/dist/{chunk-8nkdvgd9.js.map → chunk-sbyqs03h.js.map} +1 -1
- package/dist/{chunk-wc46df4w.js → chunk-t26n9vzw.js} +2 -2
- package/dist/{chunk-wc46df4w.js.map → chunk-t26n9vzw.js.map} +1 -1
- package/dist/{chunk-8z37k28d.js → chunk-tvy2fqza.js} +2 -2
- package/dist/{chunk-8z37k28d.js.map → chunk-tvy2fqza.js.map} +1 -1
- package/dist/{chunk-zhk3z9zk.js → chunk-tyhrrnp5.js} +3 -3
- package/dist/{chunk-zhk3z9zk.js.map → chunk-tyhrrnp5.js.map} +1 -1
- package/dist/{chunk-vh1hxm9y.js → chunk-v52dyw0q.js} +3 -3
- package/dist/{chunk-vh1hxm9y.js.map → chunk-v52dyw0q.js.map} +1 -1
- package/dist/{chunk-p2jn4bnx.js → chunk-vj2t77x1.js} +2 -2
- package/dist/{chunk-p2jn4bnx.js.map → chunk-vj2t77x1.js.map} +1 -1
- package/dist/{chunk-mnctdd8r.js → chunk-we2sj339.js} +2 -2
- package/dist/{chunk-mnctdd8r.js.map → chunk-we2sj339.js.map} +1 -1
- package/dist/{chunk-szrgwggb.js → chunk-wedwkqe7.js} +3 -3
- package/dist/{chunk-szrgwggb.js.map → chunk-wedwkqe7.js.map} +1 -1
- package/dist/{chunk-pfjr510h.js → chunk-wsftnxzs.js} +2 -2
- package/dist/{chunk-pfjr510h.js.map → chunk-wsftnxzs.js.map} +1 -1
- package/dist/{chunk-62cv9vjt.js → chunk-wzqkdmjd.js} +2 -2
- package/dist/{chunk-62cv9vjt.js.map → chunk-wzqkdmjd.js.map} +1 -1
- package/dist/{chunk-rkre6bqc.js → chunk-xg9vye7c.js} +1 -1
- package/dist/{chunk-vqvdptx4.js → chunk-xpyhmg45.js} +2 -2
- package/dist/{chunk-vqvdptx4.js.map → chunk-xpyhmg45.js.map} +1 -1
- package/dist/{chunk-hzmnqe4x.js → chunk-ydkjf626.js} +2 -2
- package/dist/{chunk-hzmnqe4x.js.map → chunk-ydkjf626.js.map} +1 -1
- package/dist/{chunk-jfnhzza6.js → chunk-yebaheh7.js} +3 -3
- package/dist/{chunk-jfnhzza6.js.map → chunk-yebaheh7.js.map} +1 -1
- package/dist/{chunk-dyew1yf7.js → chunk-zrdbytx4.js} +2 -2
- package/dist/{chunk-dyew1yf7.js.map → chunk-zrdbytx4.js.map} +1 -1
- package/dist/client/ClientRouter.d.ts +2 -0
- package/dist/client/ClientRouter.d.ts.map +1 -1
- package/dist/client/index.js +4 -3
- package/dist/client/index.js.map +1 -1
- package/dist/config/index.js +1 -1
- package/dist/console/run.js +2 -2
- package/dist/console/run.js.map +1 -1
- package/dist/container/index.js +2 -2
- package/dist/container/index.js.map +1 -1
- package/dist/database/index.js +2 -2
- package/dist/database/index.js.map +1 -1
- package/dist/email/index.js +2 -2
- package/dist/email/index.js.map +1 -1
- package/dist/facades/index.js +2 -2
- package/dist/facades/index.js.map +1 -1
- package/dist/foundation/index.js +2 -2
- package/dist/foundation/index.js.map +1 -1
- package/dist/http/ApiRouter.d.ts.map +1 -1
- package/dist/http/BodyLimitMiddleware.d.ts +27 -0
- package/dist/http/BodyLimitMiddleware.d.ts.map +1 -0
- package/dist/http/HttpRequest.d.ts.map +1 -1
- package/dist/http/bodyLimit.d.ts +45 -0
- package/dist/http/bodyLimit.d.ts.map +1 -0
- package/dist/http/index.d.ts +3 -0
- package/dist/http/index.d.ts.map +1 -1
- package/dist/http/index.js +2 -2
- package/dist/http/index.js.map +1 -1
- package/dist/http/middleware-config.d.ts +8 -0
- package/dist/http/middleware-config.d.ts.map +1 -1
- package/dist/http/safeFetch/addresses.d.ts +60 -0
- package/dist/http/safeFetch/addresses.d.ts.map +1 -0
- package/dist/http/safeFetch/errors.d.ts +78 -0
- package/dist/http/safeFetch/errors.d.ts.map +1 -0
- package/dist/http/safeFetch/index.d.ts +4 -0
- package/dist/http/safeFetch/index.d.ts.map +1 -0
- package/dist/http/safeFetch/safeFetch.d.ts +82 -0
- package/dist/http/safeFetch/safeFetch.d.ts.map +1 -0
- package/dist/i18n/dictionaryRuntime.js +2 -2
- package/dist/i18n/dictionaryRuntime.js.map +1 -1
- package/dist/i18n/index.js +2 -2
- package/dist/i18n/index.js.map +1 -1
- package/dist/kernel/index.js +2 -2
- package/dist/kernel/index.js.map +1 -1
- package/dist/orm/index.js +2 -2
- package/dist/orm/index.js.map +1 -1
- package/dist/server/httpProd.d.ts.map +1 -1
- package/dist/server/index.js +2 -2
- package/dist/server/index.js.map +1 -1
- package/dist/server/staticFile.d.ts +20 -1
- package/dist/server/staticFile.d.ts.map +1 -1
- package/dist/services/index.js +2 -2
- package/dist/services/index.js.map +1 -1
- package/dist/services/middleware/MiddlewareRegistry.d.ts +8 -0
- package/dist/services/middleware/MiddlewareRegistry.d.ts.map +1 -1
- package/dist/services/queue/work.js +2 -2
- package/dist/services/queue/work.js.map +1 -1
- package/dist/services/router/ApiRouteDispatcher.d.ts.map +1 -1
- package/dist/services/router/createComponentTree.d.ts.map +1 -1
- package/dist/support/index.js +2 -2
- package/dist/support/index.js.map +1 -1
- package/dist/vitest/index.d.ts +27 -0
- package/dist/vitest/index.d.ts.map +1 -0
- package/dist/vitest/index.js +4 -0
- package/dist/vitest/index.js.map +10 -0
- package/package.json +3 -2
- package/dist/chunk-3cxbvrts.js +0 -9
- package/dist/chunk-3cxbvrts.js.map +0 -31
- package/dist/chunk-48wh5mbp.js +0 -17
- package/dist/chunk-70e5fypb.js +0 -24
- package/dist/chunk-f2n21fef.js +0 -5
- package/dist/chunk-qxg2dnnr.js +0 -6
- /package/dist/{chunk-cbywzv21.js.map → chunk-2xqrh6d0.js.map} +0 -0
- /package/dist/{chunk-5ngv175h.js.map → chunk-anp4kv3w.js.map} +0 -0
- /package/dist/{chunk-rkre6bqc.js.map → chunk-xg9vye7c.js.map} +0 -0
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../http/Controller.ts", "../http/getCookies.ts", "../http/range.ts", "../http/Router.ts", "../http/validate.ts", "../ai/Schema.ts", "../http/mediaType.ts", "../http/modelOriginated.ts", "../http/requestDomain.ts", "../http/HttpRequest.ts", "../http/errors.ts", "../facades/Facade.ts", "../services/file-storage/drivers/FileStorageDriver.ts", "../services/file-storage/drivers/abortableBody.ts", "../services/file-storage/drivers/FileSystemDriver.ts", "../services/file-storage/config.ts", "../services/file-storage/FilesystemManager.ts", "../facades/Storage.ts", "../support/sharp.ts", "../services/logging/LogManager.ts", "../facades/Log.ts", "../services/redis/RedisManager.ts"],
|
|
4
|
-
"sourcesContent": [
|
|
5
|
-
"import type { HttpRequest } from \"./HttpRequest\";\n\nexport class Controller {\n static kind = \"controller\" as const;\n\n constructor() {}\n}\n\ntype PromiseOrData<T> = T | Promise<T>;\n\nexport abstract class ResourceController extends Controller {\n abstract store(req: HttpRequest<any, any>): PromiseOrData<any>;\n abstract update(req: HttpRequest<any, any>): PromiseOrData<any>;\n abstract delete(req: HttpRequest<any, any>): PromiseOrData<any>;\n abstract list(req: HttpRequest<any, any>): PromiseOrData<any>;\n abstract show(req: HttpRequest<any, any>): PromiseOrData<any>;\n}\n\nexport type ControllerMethods<\n T extends new () => Controller | ResourceController,\n> = {\n [K in keyof InstanceType<T>]: InstanceType<T>[K] extends Function ? K : never;\n}[keyof InstanceType<T>];\n",
|
|
6
|
-
"/**\n * Parses a `Cookie` request header into name -> value.\n *\n * Splits each pair on its *first* `=`: base64 padding and JWTs put `=` inside\n * the value, and splitting on every one would cut them off. A segment with no\n * `=` or an empty name is skipped rather than thrown on, since browsers and\n * proxies do send `flag;`-style pairs and the client may not control them.\n * A repeated name keeps its last value.\n *\n * Values are not percent-decoded: server-written cookies (`createCookie`) are\n * unencoded, so decoding here would change any value that happens to contain\n * a `%`. A cookie the browser writes may be encoded — `useLocale` encodes\n * `i18n-locale` — and its reader decodes it if it needs to.\n */\nexport function parseCookieHeader(header: string | null | undefined): Map<string, string> {\n const cookies = new Map<string, string>();\n if (!header) {\n return cookies;\n }\n for (const pair of header.split(\";\")) {\n const eq = pair.indexOf(\"=\");\n if (eq === -1) continue;\n const name = pair.slice(0, eq).trim();\n if (!name) continue;\n cookies.set(name, pair.slice(eq + 1).trim());\n }\n return cookies;\n}\n\nexport function getCookies(req: Request): Map<string, string> {\n return parseCookieHeader(req.headers.get(\"cookie\"));\n}\n",
|
|
7
|
-
"/**\n * RFC 7233 byte-range parsing and resolution.\n *\n * Deliberately dependency-free: the file storage drivers import `ByteRange`\n * from here, and drivers otherwise import nothing out of `http/`.\n */\n\n/**\n * A parsed but *unresolved* `Range` header. The suffix form carries no absolute\n * offsets — resolving it needs the total size of the object.\n */\nexport type ByteRange =\n | { kind: \"offset\"; start: number; end: number | null }\n | { kind: \"suffix\"; suffixLength: number };\n\n/** Absolute, inclusive, clamped-to-the-object byte offsets. */\nexport type ResolvedRange = { start: number; end: number; length: number };\n\n/** A parsed response `Content-Range` of the `bytes S-E/TOTAL` form. */\nexport type ContentRange = { start: number; end: number; total: number };\n\nfunction parseInteger(raw: string): number | null {\n // Reject anything that isn't a run of ASCII digits. `Number()` would happily\n // take \"0x10\", \" 5\", \"1e3\" and \"+5\", none of which are valid byte-pos.\n if (!/^\\d+$/.test(raw)) {\n return null;\n }\n const value = Number(raw);\n return Number.isSafeInteger(value) ? value : null;\n}\n\n/**\n * Parses a request `Range` header.\n *\n * Returns `null` for anything we cannot or will not serve as a partial\n * response. That is not an error path: RFC 7233 §3.1 requires a recipient to\n * ignore a `Range` it does not understand, and §4.1 lets a server ignore one it\n * does. Every `null` here means \"serve the complete representation with 200\".\n *\n * Only a single range is supported — we never emit `multipart/byteranges`, so a\n * multi-range request is ignored rather than partially honoured.\n */\nexport function parseRangeHeader(\n header: string | null | undefined,\n): ByteRange | null {\n if (!header) {\n return null;\n }\n\n const trimmed = header.trim();\n if (!/^bytes=/i.test(trimmed)) {\n return null;\n }\n\n const specs = trimmed\n .slice(\"bytes=\".length)\n .split(\",\")\n .map((spec) => spec.trim());\n\n // A single trailing comma is tolerated (\"bytes=0-9,\") because some clients\n // emit it. More than one *non-empty* spec is a genuine multi-range request.\n const present = specs.filter((spec) => spec !== \"\");\n if (present.length !== 1) {\n return null;\n }\n\n const spec = present[0];\n const separator = spec.indexOf(\"-\");\n if (separator === -1) {\n return null;\n }\n\n const rawStart = spec.slice(0, separator);\n const rawEnd = spec.slice(separator + 1);\n\n if (rawStart === \"\") {\n // Suffix form: `bytes=-N`, the last N bytes.\n const suffixLength = parseInteger(rawEnd);\n if (suffixLength === null) {\n return null;\n }\n // `bytes=-0` parses cleanly and resolves to unsatisfiable (416). Collapsing\n // it to `null` here would serve the whole file instead, which the spec does\n // not allow. Satisfiability is `resolveRange`'s job alone.\n return { kind: \"suffix\", suffixLength };\n }\n\n const start = parseInteger(rawStart);\n if (start === null) {\n return null;\n }\n\n if (rawEnd === \"\") {\n return { kind: \"offset\", start, end: null };\n }\n\n const end = parseInteger(rawEnd);\n if (end === null || end < start) {\n return null;\n }\n\n return { kind: \"offset\", start, end };\n}\n\n/**\n * Resolves a parsed range against a known total size.\n *\n * Returns `null` when the range is unsatisfiable, which the caller must turn\n * into a 416 rather than a full response.\n */\nexport function resolveRange(\n range: ByteRange,\n total: number,\n): ResolvedRange | null {\n // An empty (or unknown-length) representation has no satisfiable range at\n // all. Handling it here is what keeps `bytes 0--1/0` from ever being built.\n if (!Number.isFinite(total) || total <= 0) {\n return null;\n }\n\n let start: number;\n let end: number;\n\n if (range.kind === \"suffix\") {\n if (range.suffixLength <= 0) {\n return null;\n }\n start = Math.max(0, total - range.suffixLength);\n end = total - 1;\n } else {\n if (range.start >= total) {\n return null;\n }\n start = range.start;\n // An end past the last byte is clamped, not rejected — Chrome routinely\n // asks for `bytes=0-2147483647` when loading a <video>.\n end = range.end === null ? total - 1 : Math.min(range.end, total - 1);\n if (end < start) {\n return null;\n }\n }\n\n return { start, end, length: end - start + 1 };\n}\n\n/** Renders a range back into a `Range` request header for a storage backend. */\nexport function toRangeHeaderValue(range: ByteRange): string {\n if (range.kind === \"suffix\") {\n return `bytes=-${range.suffixLength}`;\n }\n return range.end === null\n ? `bytes=${range.start}-`\n : `bytes=${range.start}-${range.end}`;\n}\n\n/**\n * Parses a response `Content-Range`. Storage backends report the authoritative\n * total size of the object here on a ranged read, which is what lets a driver\n * answer a range without a second round trip for the size.\n *\n * The unsatisfied form used on a 416 has no offsets and returns `null`.\n */\nexport function parseContentRange(\n value: string | null | undefined,\n): ContentRange | null {\n if (!value) {\n return null;\n }\n const match = /^bytes\\s+(\\d+)-(\\d+)\\/(\\d+)$/i.exec(value.trim());\n if (!match) {\n return null;\n }\n const start = parseInteger(match[1]);\n const end = parseInteger(match[2]);\n const total = parseInteger(match[3]);\n if (start === null || end === null || total === null || end < start) {\n return null;\n }\n return { start, end, total };\n}\n\nexport function formatContentRange(\n start: number,\n end: number,\n total: number,\n): string {\n return `bytes ${start}-${end}/${total}`;\n}\n\n/** The `Content-Range` of a 416: no offsets, just the current total size. */\nexport function formatUnsatisfiedContentRange(total: number): string {\n return `bytes */${total}`;\n}\n",
|
|
8
|
-
"import { RequestBreakerError } from \"./Error\";\nimport type { HttpRequest } from \"./HttpRequest\";\n\ntype MiddlewareResult = Partial<{\n headers: Record<string, string>;\n cookies: Record<string, string>;\n}>;\n\nexport type MiddlewareReturnType =\n | void\n | Promise<MiddlewareResult>\n | MiddlewareResult;\n\nexport type RouterMiddleware = (\n req: HttpRequest,\n ctx: any,\n) => MiddlewareReturnType;\n\nexport class ValidationError extends RequestBreakerError {\n errors: Record<string, string[]> = {};\n constructor(errors: Record<string, string[]>) {\n super(\"Validation error\");\n this.name = \"ValidationError\";\n this.errors = errors;\n this.payload = {\n api: {\n status: 400,\n data: {\n error: {\n kind: \"validation_error\",\n messages: errors,\n status: 400,\n },\n },\n headers: {\n \"Content-Type\": \"application/json\",\n },\n },\n view: {\n status: 400,\n },\n };\n }\n}\n",
|
|
9
|
-
"/**\n * The validation rule table: a rule name in, a predicate out.\n *\n * ITS OWN MODULE SO THE TEST DOES NOT NEED A HOOK. This lived in\n * `HttpRequest.ts` and was reached from `validate.test.ts` through\n * `export const __validateForTests = validate`, which is a name that exists\n * only because the thing it aliases was in the wrong file. Two costs, and the\n * second is the one that bites:\n *\n * - `tsc` emits a declaration per source file, so `dist/http/HttpRequest.d.ts`\n * shipped `__validateForTests` to every installed copy of the framework. The\n * JS build bundles, so there is no `dist/http/HttpRequest.js` behind it —\n * the declaration announced an export the tarball could not produce.\n * - A test-only alias is a second name for the same function, so the test\n * reads as if it were poking at something private. It is not: this is the\n * code path every request body goes through. Importing `validate` says so.\n *\n * Nothing outside `HttpRequest` should build predicates by hand — rules are\n * named in a route's schema — but \"internal\" is what an unexported name in an\n * unexported module already means, and it does not need a warning label.\n */\n\n// Formats B KB MB GB TB\n// e.g parseFileSizeString(\"1MB\") => 1024 * 1024\nfunction parseFileSizeString(size: string) {\n const [number, unit] = size.match(/\\d+|\\D+/g) ?? [];\n if (!number || !unit) {\n return 0;\n }\n const fileSize = Number.parseInt(number);\n switch (unit) {\n case \"B\":\n return fileSize;\n case \"KB\":\n return fileSize * 1024;\n case \"MB\":\n return fileSize * 1024 * 1024;\n case \"GB\":\n return fileSize * 1024 * 1024 * 1024;\n case \"TB\":\n return fileSize * 1024 * 1024 * 1024 * 1024;\n default:\n return 0;\n }\n}\n\n// Formats png, jpg, ttf, excel, csv, word, pdf, json\n// Eg. png => image/png\nfunction parseFileTypeString(type: string) {\n switch (type) {\n case \"image\":\n return \"image\";\n case \"png\":\n return \"image/png\";\n case \"jpg\":\n return \"image/jpeg\";\n case \"jpeg\":\n return \"image/jpeg\";\n case \"ttf\":\n return \"font/ttf\";\n case \"excel\":\n return \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\";\n case \"csv\":\n return \"text/csv\";\n case \"word\":\n return \"application/vnd.openxmlformats-officedocument.wordprocessingml.document\";\n case \"pdf\":\n return \"application/pdf\";\n case \"json\":\n return \"application/json\";\n default:\n return type;\n }\n}\n\n/** The length of the things that have one — `undefined` for everything else,\n * rather than the `undefined` that arithmetic silently turns into `false`. */\nfunction lengthOf(value: any): number | undefined {\n if (typeof value === \"string\" || Array.isArray(value)) return value.length;\n return undefined;\n}\n\nfunction isNumber(value: any): value is number {\n return typeof value === \"number\" && !Number.isNaN(value);\n}\n\n/** Every rule `validate` implements. `SchemaKey` in `HttpRequest.ts` offers\n * these and only these: `validate.test-d.ts` checks the two lists agree, and\n * `validate.test.ts` that each one has a case. */\nexport const RULES = [\n \"required\",\n \"string\",\n \"boolean\",\n \"number\",\n \"email\",\n \"password\",\n \"min\",\n \"max\",\n \"gte\",\n \"lte\",\n \"file\",\n \"fileType\",\n \"fileSize\",\n \"array\",\n \"object\",\n \"in\",\n] as const;\n\n/**\n * A schema names a rule `validate` does not have, or gives one a parameter it\n * cannot use. Thrown when the request is validated, not when the body is bad:\n * it is a bug in the schema, so it is a 500 and not a 400.\n */\nexport class InvalidValidationRuleError extends Error {\n name = \"InvalidValidationRuleError\";\n}\n\n/** `min:3` → 3. A parameter that is not a number throws, instead of becoming\n * `NaN` and quietly failing every value. */\nfunction numericParam(rule: string, param: string | undefined): number {\n const n = param === undefined || param.trim() === \"\" ? Number.NaN : Number(param);\n if (Number.isNaN(n)) {\n throw new InvalidValidationRuleError(\n `Validation rule \"${rule}:${param ?? \"\"}\" needs a number, e.g. \"${rule}:3\"`,\n );\n }\n return n;\n}\n\nexport function validate(ruleName: string) {\n // Split at the first colon only, so a parameter may hold one.\n const colon = ruleName.indexOf(\":\");\n const rule = colon === -1 ? ruleName : ruleName.slice(0, colon);\n const param = colon === -1 ? undefined : ruleName.slice(colon + 1);\n switch (rule) {\n /**\n * Present. Not \"non-empty for the two types that happen to have `.length`\".\n *\n * This used to end in `value?.length > 0`, which is `undefined > 0` — so\n * `false` — for every value that is not a string, an array or a Blob. A\n * number failed it. A boolean failed it. A plain object failed it, which on\n * a typed `HttpRequest<{ theme: { … } }>` is the ordinary case, and the app\n * saw a 400 on a request that was correct.\n *\n * `0` and `false` PASS. They are values someone sent, and a rule called\n * `required` asks whether the field is there, not whether it is truthy —\n * conflating those is how a checkbox set to \"no\" and a quantity of zero get\n * rejected as missing. Emptiness is still emptiness where the concept\n * applies: `\"\"` and `[]` fail, as they did before, and so does a zero-byte\n * upload.\n *\n * `{}` passes. It is an object that was sent; whether its contents are\n * adequate is a question for the rules on its fields, not for this one.\n */\n case \"required\":\n return (value: any) => {\n if (value instanceof Blob) {\n return value.size > 0;\n }\n if (value === null || value === undefined) {\n return false;\n }\n if (typeof value === \"string\" || Array.isArray(value)) {\n return value.length > 0;\n }\n return true;\n };\n /**\n * The JSON types, checked with `typeof` like `number`. No coercion: `\"true\"`\n * is not a boolean and `42` is not a string. A form-encoded or multipart\n * body only ever carries strings (and files), so `boolean` and `number` are\n * rules for JSON bodies.\n */\n case \"string\":\n return (value: any) => typeof value === \"string\";\n case \"boolean\":\n return (value: any) => typeof value === \"boolean\";\n case \"number\":\n return (value: any) => isNumber(value);\n /**\n * `RegExp.prototype.test` stringifies its argument, so without the `typeof`\n * check `[\"a@b.co\"]` passed `email` and an array holding a strong password\n * passed `password`.\n */\n case \"password\":\n return (value: any) => {\n // min 8 characters\n // at least one uppercase letter,\n // at least one lowercase letter and one number\n // at least one special character\n const passwordRegex = /^(?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z0-9]).{8,}$/;\n return typeof value === \"string\" && passwordRegex.test(value);\n };\n /**\n * Length, and only length. `min:3` is \"at least three characters\", never\n * \"at least three\".\n *\n * ONE NAME, ONE COMPARISON, deliberately. The tempting fix was to overload\n * these by runtime type — length for a string, magnitude for a number — and\n * that is the shape `required` was already in: a rule whose meaning depends\n * on what it is handed, which reads fine until the value's type is not the\n * one the author pictured. `gte` / `lte` below say which comparison they\n * make in their names, so nothing has to be inferred.\n *\n * Written out rather than left as `value?.length >= n` so that a number\n * fails here for a stated reason instead of by arithmetic on `undefined`.\n */\n case \"min\": {\n const min = numericParam(rule, param);\n return (value: any) => {\n const length = lengthOf(value);\n return length !== undefined && length >= min;\n };\n }\n case \"max\": {\n const max = numericParam(rule, param);\n return (value: any) => {\n const length = lengthOf(value);\n return length !== undefined && length <= max;\n };\n }\n /** Magnitude, for numbers. The counterpart `min` / `max` deliberately are not. */\n case \"gte\": {\n const bound = numericParam(rule, param);\n return (value: any) => isNumber(value) && value >= bound;\n }\n case \"lte\": {\n const bound = numericParam(rule, param);\n return (value: any) => isNumber(value) && value <= bound;\n }\n case \"email\":\n return (value: any) => {\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n return typeof value === \"string\" && emailRegex.test(value);\n };\n case \"file\":\n return (value: any) => {\n return value instanceof Blob;\n };\n case \"fileType\": {\n if (!param) {\n throw new InvalidValidationRuleError(\n `Validation rule \"fileType\" needs a type, e.g. \"fileType:png\" or \"fileType:image\"`,\n );\n }\n const parsedType = parseFileTypeString(param);\n return (value: any) => value instanceof Blob && value.type.startsWith(parsedType);\n }\n case \"fileSize\": {\n // `parseFileSizeString` answers 0 for anything it cannot read, and a\n // 0-byte ceiling rejects every upload — so `fileSize:5mb` or\n // `fileSize:1.5MB` looked like a limit and was a wall.\n const absoluteSize = parseFileSizeString(param ?? \"\");\n if (absoluteSize === 0 && !/^0+(B|KB|MB|GB|TB)$/.test(param ?? \"\")) {\n throw new InvalidValidationRuleError(\n `Validation rule \"fileSize:${param ?? \"\"}\" needs a whole size in B, KB, MB, GB or TB, e.g. \"fileSize:5MB\"`,\n );\n }\n return (value: any) => value instanceof Blob && value.size <= absoluteSize;\n }\n /**\n * The JSON container types, for the parent of a nested rule\n * (`rounds: { array: … }` next to `\"rounds.*.prompt\": { … }`, #711). An\n * object is a plain one: not an array, not `null`, not an upload.\n */\n case \"array\":\n return (value: any) => Array.isArray(value);\n case \"object\":\n return (value: any) =>\n typeof value === \"object\" &&\n value !== null &&\n !Array.isArray(value) &&\n !(value instanceof Blob);\n /**\n * One of a fixed list: `in:question,choice`. Compared as strings and\n * exactly, so it is a rule for string fields; a number is not \"in\" `1,2`.\n */\n case \"in\": {\n const allowed = (param ?? \"\").split(\",\").filter((item) => item !== \"\");\n if (allowed.length === 0) {\n throw new InvalidValidationRuleError(\n `Validation rule \"in\" needs a comma-separated list, e.g. \"in:draft,published\"`,\n );\n }\n return (value: any) => typeof value === \"string\" && allowed.includes(value);\n }\n /**\n * Not `() => true`. That default is how `string` and `boolean` shipped in\n * `SchemaKey` checking nothing (#609): a rule the table does not\n * know looks, from the schema, exactly like one it does. A typo'd or\n * unimplemented rule is a bug in the schema, so it throws.\n */\n default:\n throw new InvalidValidationRuleError(\n `Unknown validation rule \"${ruleName}\". Known rules: ${RULES.join(\", \")}`,\n );\n }\n}\n",
|
|
10
|
-
"/**\n * The schema layer for tool inputs, tool outputs and structured final answers.\n *\n * Two things have to come out of one declaration: a TypeScript type, so\n * `execute(input)` is typed at the call site and the result is typed in the\n * browser, and a JSON Schema, because that is what the model is actually shown.\n * A phantom `Schema<T>` gives the first and nothing of the second, and a\n * hand-written JSON Schema next to a hand-written type gives both and lets them\n * drift. So the builder below is the single source, and `Infer` reads the type\n * back off it.\n *\n * Everything here is deliberately narrower than JSON Schema. OpenAI's strict\n * structured output only accepts a subset — every property listed in\n * `required`, `additionalProperties: false` on every object, no patterns, no\n * `oneOf` at the root — and a builder that cannot express the rejected parts is\n * better than one that lets you write a schema the API refuses at runtime.\n *\n * `json()` is the one deliberate hole in that, for the formats strict mode\n * cannot describe at all: a record with arbitrary keys, a mixed-type tuple. It\n * does not widen the subset — it turns strict mode off for the schema containing\n * it, which `supportsStrict` reads back off the tree so that no caller has to\n * remember to.\n *\n * A document that nests into itself is NOT one of those: strict mode accepts\n * `$defs` + `$ref`, and `recursive()` emits exactly that (#745).\n */\n\nexport type JSONSchema = {\n type?: string | string[];\n description?: string;\n enum?: readonly (string | number)[];\n const?: string | number | boolean;\n properties?: Record<string, JSONSchema>;\n required?: readonly string[];\n additionalProperties?: false;\n items?: JSONSchema;\n anyOf?: readonly JSONSchema[];\n /**\n * `#/$defs/<name>`, pointing at an entry of the root's `$defs`. Emitted by\n * `s.recursive` and never with a sibling keyword: OpenAI's strict mode\n * refuses `{ $ref, description }`, so a described or nullable reference is\n * wrapped in an `anyOf` instead.\n */\n $ref?: string;\n /** Only ever on the root: every `s.recursive` the schema reaches, by name. */\n $defs?: Record<string, JSONSchema>;\n};\n\n/**\n * Any value JSON can carry. The default output type of `json()`, and the\n * annotation an app reaches for when it hands one of those values on.\n */\nexport type JsonValue =\n | string\n | number\n | boolean\n | null\n | JsonValue[]\n | { [key: string]: JsonValue };\n\ndeclare const OUTPUT: unique symbol;\ndeclare const OPTIONAL: unique symbol;\n\n/**\n * `T` is carried in a phantom property rather than a real one: it exists only\n * for inference, and a real field would show up on the object the app writes.\n */\nexport interface Schema<T> {\n readonly [OUTPUT]: T;\n /** The JSON Schema handed to the provider. */\n toJSONSchema(): JSONSchema;\n /**\n * Parses a value coming back from the model. Tool arguments arrive as a JSON\n * string the model generated, so they are untrusted in exactly the way a\n * request body is: shape-checked before `execute` ever sees them.\n */\n parse(value: unknown): T;\n safeParse(value: unknown): { ok: true; value: T } | { ok: false; errors: string[] };\n}\n\n/**\n * A schema whose key may be left out of the object containing it.\n *\n * Marked with a property rather than detected from the output type, because\n * `undefined extends T` — the obvious test — is true of *everything* when\n * `strictNullChecks` is off, which is how this package and plenty of apps\n * compile. That version made every field of every tool optional, and did it\n * quietly: the JSON Schema was still right, so only the TypeScript types lied.\n */\nexport interface OptionalSchema<T> extends Schema<T | undefined> {\n readonly [OPTIONAL]: true;\n}\n\nexport type AnySchema = Schema<any>;\n\nexport type Infer<S> = S extends Schema<infer T> ? T : never;\n\n/**\n * Collapses a type into one flat object.\n *\n * `ShapeOutput` builds its result as an intersection of two mapped types, one\n * required and one optional, and that intersection is what every hover, every\n * error message and every type assertion would otherwise show. The difference\n * is between an app reading `{ command: string; cwd?: string }` and reading two\n * mapped types joined by an ampersand.\n *\n * It also drops `readonly`, which the mapped types copy from the shape literal\n * — `s.object({ ... })` infers that literal as `const` to keep the keys, and a\n * tool has no reason to receive an immutable input because of how its schema\n * was written down.\n */\ntype Flatten<T> = { -readonly [K in keyof T]: T[K] };\n\ntype ShapeOutput<S extends Record<string, AnySchema>> = Flatten<\n {\n [K in keyof S as S[K] extends OptionalSchema<any> ? never : K]: Infer<S[K]>;\n } & {\n [K in keyof S as S[K] extends OptionalSchema<any> ? K : never]?: Infer<S[K]>;\n }\n>;\n\ninterface SchemaBuilder<T> extends Schema<T> {\n /**\n * The description is not documentation — it is the only prose the model gets\n * about a field, and it is the difference between a tool that is called\n * correctly and one that is not.\n */\n describe(description: string): this;\n /**\n * Strict mode has no notion of an omitted key: every property must appear in\n * `required`. So `optional()` emits a nullable union and the model is told to\n * send `null`, while the TypeScript type says `| undefined` and the parsed\n * value drops the key. The asymmetry is the point — it is what lets an app\n * write ordinary optional fields against an API that forbids them.\n */\n optional(): OptionalSchemaBuilder<T>;\n nullable(): SchemaBuilder<T | null>;\n /**\n * `safeParse` with the failures as structured issues rather than sentences:\n * each one names the path it is about, a JSON Schema keyword as its `code`\n * and the keyword's argument in `params`. For an app that validates a value\n * against a schema itself — a form, a stored record — and wants to word or\n * group the problems per field. All failures are reported, not the first.\n */\n validate(value: unknown): { ok: true; value: T } | { ok: false; issues: SchemaIssue[] };\n}\n\n/**\n * One reason a value failed `validate`.\n *\n * `code` is the JSON Schema keyword the value broke — the same names Ajv puts\n * on its `keyword` — so a mapping written against one reads the other:\n *\n * - `required`: the key is missing (`path` ends in it).\n * - `type`: the wrong kind of value, an integer that isn't whole, or a value\n * that isn't JSON at all.\n * - `const`, `enum`: a literal or a choice that didn't match (`params.allowedValues`).\n * - `minLength`, `maxLength`, `minimum`, `maximum`, `exclusiveMinimum`,\n * `exclusiveMaximum`, `minItems`, `maxItems`: `params.limit` is the bound.\n * - `format`: `params.format` names the format the string failed.\n * - `anyOf`: no union member matched; `message` names the closest one's problems.\n *\n * `message` is the sentence `safeParse` reports for it, without the path.\n */\nexport type SchemaIssueCode =\n | \"required\"\n | \"type\"\n | \"const\"\n | \"enum\"\n | \"anyOf\"\n | \"minLength\"\n | \"maxLength\"\n | \"minimum\"\n | \"maximum\"\n | \"exclusiveMinimum\"\n | \"exclusiveMaximum\"\n | \"minItems\"\n | \"maxItems\"\n | \"format\";\n\nexport type SchemaIssue = {\n /** Keys and array indices from the root, `[]` for the root itself. */\n path: (string | number)[];\n code: SchemaIssueCode;\n message: string;\n params: Record<string, unknown>;\n};\n\ninterface OptionalSchemaBuilder<T> extends SchemaBuilder<T | undefined>, OptionalSchema<T> {}\n\n// --- the runtime ---------------------------------------------------------\n\n/**\n * What a builder actually is. `optional` and `nullable` are flags rather than\n * wrapper nodes so that `.nullable().optional()` cannot nest into something\n * whose emitted shape depends on which order they were called in.\n */\ntype Definition = {\n node: SchemaNode;\n description?: string;\n optional: boolean;\n nullable: boolean;\n};\n\n/**\n * The constraints `s.fromJSONSchema` can carry over from a JSON Schema. None of\n * the builders set them; they exist so that a schema read from data validates\n * what it says it does.\n *\n * They are CHECKED, NOT EMITTED as keywords. Strict structured output refuses\n * most of them (`minLength`, `maxLength`, `minimum` on Anthropic; any `format`\n * outside a short list on both), so the model is told them in the field's\n * description instead, and `parse` enforces them — a model that ignores the\n * prose gets an `invalid_tool_input` it can correct, the same as a wrong type.\n */\ntype StringChecks = {\n minLength?: number;\n maxLength?: number;\n format?: { name: string; test: (value: string) => boolean };\n};\n\ntype NumberChecks = {\n integer?: boolean;\n minimum?: number;\n maximum?: number;\n exclusiveMinimum?: number;\n exclusiveMaximum?: number;\n};\n\ntype ArrayChecks = { minItems?: number; maxItems?: number };\n\ntype SchemaNode =\n | { kind: \"string\"; checks?: StringChecks }\n | { kind: \"number\"; checks?: NumberChecks }\n | { kind: \"boolean\" }\n | { kind: \"literal\"; value: string | number | boolean }\n | { kind: \"enum\"; values: readonly string[]; checks?: StringChecks }\n | { kind: \"object\"; shape: Record<string, Definition> }\n | { kind: \"array\"; item: Definition; checks?: ArrayChecks }\n | { kind: \"union\"; members: readonly Definition[] }\n /** Constrains nothing. The node strict mode has no spelling for. */\n | { kind: \"json\" }\n /**\n * A use of an `s.recursive` schema — its `self`, or the builder it returned.\n * Emitted as a `$ref` into the root's `$defs`, read by following the cell.\n */\n | { kind: \"ref\"; cell: RecursiveCell };\n\n/**\n * One `s.recursive` declaration. `definition` is filled in once the callback\n * returns; until then `self` is a reference to something that does not exist\n * yet, which is the whole trick.\n *\n * `active` is the set of values being read through this cell right now, the\n * cycle guard for a JavaScript value that contains itself (a tool output an app\n * built). Per cell rather than global, so that one value read through two\n * different recursive schemas in a row is not mistaken for a cycle.\n */\ntype RecursiveCell = {\n name: string;\n definition?: Definition;\n active: Set<object>;\n};\n\nfunction bodyOf(cell: RecursiveCell): Definition {\n if (!cell.definition) {\n throw new Error(\n `gemi/ai: the recursive schema \"${cell.name}\" was used before its definition returned; \\`self\\` can be nested into the schema, but not parsed or emitted inside the callback`,\n );\n }\n return cell.definition;\n}\n\ntype ParseResult = { ok: true; value: unknown } | { ok: false; errors: string[] };\n\ntype Path = (string | number)[];\n\n/** The public interface with the phantoms and the generic taken off. */\ninterface RuntimeSchema {\n toJSONSchema(): JSONSchema;\n parse(value: unknown): unknown;\n safeParse(value: unknown): ParseResult;\n validate(value: unknown): { ok: true; value: unknown } | { ok: false; issues: SchemaIssue[] };\n describe(description: string): RuntimeSchema;\n optional(): RuntimeSchema;\n nullable(): RuntimeSchema;\n}\n\n/**\n * Definitions hang off the builders here rather than on the builders\n * themselves: a property, however obscurely named, is a property an app can\n * see, serialise or accidentally depend on, and `Schema<T>` promises exactly\n * three methods.\n */\nconst definitions = new WeakMap<object, Definition>();\n\n/**\n * Whether `value` is a schema built with `s`. How `HttpRequest` tells an `s`\n * body schema from a map of rules (#711), without a property on the builder.\n */\nexport function isSchema(value: unknown): value is SchemaBuilder<unknown> {\n return typeof value === \"object\" && value !== null && definitions.has(value);\n}\n\nfunction definitionOf(schema: AnySchema): Definition {\n const definition = definitions.get(schema);\n if (!definition) {\n throw new Error(\"gemi/ai: expected a schema built with `s`, got a foreign object\");\n }\n return definition;\n}\n\n// --- emitting ------------------------------------------------------------\n\n/**\n * What one `toJSONSchema()` call collects on its way down: the `$defs` the\n * root will carry, and which cell owns each name in them.\n */\ntype EmitContext = {\n defs: Record<string, JSONSchema>;\n cells: Map<string, RecursiveCell>;\n};\n\n/**\n * The schema as the provider sees it: the tree, plus `$defs` at the root when\n * an `s.recursive` is anywhere in it.\n *\n * A recursive schema used AS the root is inlined there, and its `$defs` entry\n * is a second copy of the same body. Pointing the root at itself with\n * `\"$ref\": \"#\"` would be shorter, and OpenAI accepts it, but `#` means \"the\n * whole document\" — and a document that gets merged into (MCP's\n * `combineSchemas` adds properties to an input's root) would then demand the\n * merged-in fields at every level of the tree.\n */\nfunction emitRoot(definition: Definition): JSONSchema {\n const context: EmitContext = { defs: {}, cells: new Map() };\n let root = definition;\n if (definition.node.kind === \"ref\") {\n const body = bodyOf(definition.node.cell);\n root = {\n ...body,\n ...(definition.description ? { description: definition.description } : {}),\n optional: definition.optional,\n nullable: definition.nullable || body.nullable,\n };\n }\n const schema = emit(root, context);\n return Object.keys(context.defs).length > 0 ? { ...schema, $defs: context.defs } : schema;\n}\n\nfunction emit(definition: Definition, context: EmitContext): JSONSchema {\n // A `json` node already admits every value there is, null included, so\n // widening it would only add an `anyOf` for the model to read past — and one\n // whose second branch is a strictly narrower repeat of its first.\n const widen = (definition.optional || definition.nullable) && definition.node.kind !== \"json\";\n let body = allowNull(emitNode(definition.node, context), widen);\n const description = [definition.description, hint(definition.node)].filter(Boolean).join(\" \");\n // `$ref` takes no siblings under strict mode, so a described reference\n // becomes a one-member `anyOf` that can carry the description beside it.\n if (description && body.$ref !== undefined) body = { anyOf: [body] };\n return description ? { description, ...body } : body;\n}\n\n/**\n * The checks a node carries, in words, for the description — the one place a\n * strict-mode provider lets them through. See `StringChecks`.\n */\nfunction hint(node: SchemaNode): string {\n const said: string[] = [];\n if (node.kind === \"string\" || node.kind === \"enum\") {\n const checks = node.checks;\n if (checks?.format) said.push(`Format: ${checks.format.name}.`);\n if (checks?.minLength !== undefined) said.push(`At least ${checks.minLength} characters.`);\n if (checks?.maxLength !== undefined) said.push(`At most ${checks.maxLength} characters.`);\n } else if (node.kind === \"number\") {\n const checks = node.checks;\n if (checks?.minimum !== undefined) said.push(`Minimum ${checks.minimum}.`);\n if (checks?.exclusiveMinimum !== undefined) {\n said.push(`Greater than ${checks.exclusiveMinimum}.`);\n }\n if (checks?.maximum !== undefined) said.push(`Maximum ${checks.maximum}.`);\n if (checks?.exclusiveMaximum !== undefined) said.push(`Less than ${checks.exclusiveMaximum}.`);\n } else if (node.kind === \"array\") {\n const checks = node.checks;\n if (checks?.minItems !== undefined) said.push(`At least ${checks.minItems} items.`);\n if (checks?.maxItems !== undefined) said.push(`At most ${checks.maxItems} items.`);\n }\n // A `ref` says nothing of its own: its body's hints are in its `$defs` entry.\n return said.join(\" \");\n}\n\nfunction emitNode(node: SchemaNode, context: EmitContext): JSONSchema {\n switch (node.kind) {\n case \"string\":\n return { type: \"string\" };\n case \"number\":\n // `integer` is in the strict subset of every provider gemi speaks to.\n return { type: node.checks?.integer ? \"integer\" : \"number\" };\n case \"boolean\":\n return { type: \"boolean\" };\n // `const` rather than a one-member `enum`, because a boolean literal has no\n // `enum` form and one branch that works for all three beats two that\n // disagree about what a literal is.\n case \"literal\":\n return { type: typeof node.value, const: node.value };\n case \"enum\":\n return { type: \"string\", enum: node.values };\n case \"array\":\n return { type: \"array\", items: emit(node.item, context) };\n case \"object\":\n return {\n type: \"object\",\n properties: Object.fromEntries(\n Object.entries(node.shape).map(([key, child]) => [key, emit(child, context)]),\n ),\n // Every declared property, optional ones included. This is the whole of\n // strict mode's bargain: the model is never allowed to omit a key, so\n // \"may be absent\" has to be spelled as \"may be null\" instead.\n required: Object.keys(node.shape),\n additionalProperties: false,\n };\n case \"union\":\n return { anyOf: node.members.map((member) => emit(member, context)) };\n // The empty schema, which is JSON Schema's own way of saying \"any value\" —\n // no `type` listing all seven, which reads as a constraint the model then\n // has to check itself. What the field actually is gets said in\n // `description`, the one channel a model reads either way.\n case \"json\":\n return {};\n case \"ref\": {\n const { cell } = node;\n const owner = context.cells.get(cell.name);\n if (owner && owner !== cell) {\n throw new Error(\n `gemi/ai: two different recursive schemas are named \"${cell.name}\" in one schema; give each s.recursive(...) its own name`,\n );\n }\n if (!owner) {\n // Claimed BEFORE the body is emitted: the body refers to itself, and\n // that inner reference has to find the name taken and stop here.\n context.cells.set(cell.name, cell);\n context.defs[cell.name] = {};\n context.defs[cell.name] = emit(bodyOf(cell), context);\n }\n return { $ref: `#/$defs/${cell.name}` };\n }\n }\n}\n\n/**\n * Widens a schema to admit `null` — for a `nullable()` field, and for the null\n * an `optional()` field tells the model to send in place of omitting the key.\n */\nfunction allowNull(base: JSONSchema, on: boolean): JSONSchema {\n if (!on) return base;\n // A union is already a list of alternatives; appending to it is flatter than\n // nesting an `anyOf` inside an `anyOf`, and reads the same to the model.\n if (base.anyOf) return { ...base, anyOf: [...base.anyOf, { type: \"null\" }] };\n // `enum` and `const` cannot carry the null themselves — `enum` here is\n // strings and numbers by declaration — so those get wrapped rather than\n // widened.\n if (base.enum || base.const !== undefined) return { anyOf: [base, { type: \"null\" }] };\n if (typeof base.type === \"string\") return { ...base, type: [base.type, \"null\"] };\n return { anyOf: [base, { type: \"null\" }] };\n}\n\n// --- parsing -------------------------------------------------------------\n\nfunction typeName(value: unknown): string {\n if (value === null) return \"null\";\n if (Array.isArray(value)) return \"array\";\n return typeof value;\n}\n\n/**\n * What the value looked like. For a literal or an enum the *type* is usually\n * right and the value is wrong, and \"expected \\\"refund\\\", got string\" tells\n * whoever is reading the failed tool call nothing they did not know.\n */\nfunction saw(node: SchemaNode, value: unknown): string {\n if (typeof value === \"number\" && !Number.isFinite(value)) return String(value);\n if (node.kind === \"literal\" || node.kind === \"enum\") {\n const primitive =\n typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\";\n if (primitive) return JSON.stringify(value);\n }\n return typeName(value);\n}\n\nfunction wanted(definition: Definition): string {\n const node = definition.node;\n const base = (() => {\n switch (node.kind) {\n case \"number\":\n return node.checks?.integer ? \"integer\" : \"number\";\n case \"string\":\n case \"boolean\":\n return node.kind;\n case \"literal\":\n return JSON.stringify(node.value);\n case \"enum\":\n return `one of ${node.values.map((v) => JSON.stringify(v)).join(\" | \")}`;\n case \"array\":\n return \"array\";\n case \"object\":\n return \"object\";\n case \"union\":\n return \"one of the variants\";\n case \"json\":\n return \"a JSON value\";\n case \"ref\":\n return wanted({ ...bodyOf(node.cell), optional: false, nullable: false });\n }\n })();\n return definition.optional || definition.nullable ? `${base} or null` : base;\n}\n\n/** `orders[2].total` — keys joined with dots, indices in brackets. */\nfunction formatPath(path: Path): string {\n let out = \"\";\n for (const segment of path) {\n out += typeof segment === \"number\" ? `[${segment}]` : out ? `.${segment}` : segment;\n }\n return out;\n}\n\n/** `orders[2].total: ` — empty at the root, where a prefix would be noise. */\nfunction at(path: Path): string {\n const text = formatPath(path);\n return text ? `${text}: ` : \"\";\n}\n\n/** The sentence `safeParse` reports for an issue. */\nfunction render(issue: SchemaIssue): string {\n return `${at(issue.path)}${issue.message}`;\n}\n\n/**\n * How well a value matches, used only to pick which union variant to blame.\n * A literal or an enum hit counts for far more than an ordinary field, because\n * that is what a discriminated union turns on: the variant whose `kind` matched\n * is the one the model meant, whatever else it got wrong.\n */\nfunction score(definition: Definition, value: unknown): number {\n if (value === null || value === undefined) {\n return definition.optional || definition.nullable ? 1 : 0;\n }\n const node = definition.node;\n switch (node.kind) {\n case \"string\":\n return typeof value === \"string\" ? 1 : 0;\n case \"number\":\n return typeof value === \"number\" ? 1 : 0;\n case \"boolean\":\n return typeof value === \"boolean\" ? 1 : 0;\n case \"literal\":\n return value === node.value ? 10 : 0;\n case \"enum\":\n return typeof value === \"string\" && node.values.includes(value) ? 10 : 0;\n case \"array\":\n return Array.isArray(value) ? 1 : 0;\n case \"object\": {\n if (typeof value !== \"object\" || Array.isArray(value)) return 0;\n const source = value as Record<string, unknown>;\n let total = 1;\n for (const [key, child] of Object.entries(node.shape)) {\n total += score(child, source[key]);\n }\n return total;\n }\n case \"union\":\n return node.members.reduce((best, member) => Math.max(best, score(member, value)), 0);\n // Matches, because it matches everything — but at the score of a plain\n // scalar, so a sibling variant that pinned its discriminant still wins the\n // blame.\n //\n // Reached only when no member parsed, which for a `json` member means the\n // value is not JSON at all: a function, a bigint, a cycle. Then this is\n // what makes the report name the reason the value was refused rather than\n // the discriminant of a variant the model was never aiming at.\n case \"json\":\n return 1;\n case \"ref\":\n return through(\n node.cell,\n value,\n () => 1,\n () => score(bodyOf(node.cell), value),\n );\n }\n}\n\n/**\n * Runs `walk` with `value` marked as being read through `cell`, or `cycle` when\n * it already is. A value can only meet the same cell again further down by\n * containing itself — `s.recursive` refuses a body that reaches `self` without\n * an object or array in between — so this is exactly the cycle guard, and a\n * value that merely appears twice side by side is read twice.\n */\nfunction through<R>(cell: RecursiveCell, value: unknown, cycle: () => R, walk: () => R): R {\n if (typeof value !== \"object\" || value === null) return walk();\n if (cell.active.has(value)) return cycle();\n cell.active.add(value);\n try {\n return walk();\n } finally {\n cell.active.delete(value);\n }\n}\n\n/** `drop` is a key that should not appear in the parsed object at all. */\ntype Reading = { drop: boolean; value: unknown };\n\nfunction read(definition: Definition, value: unknown, path: Path, issues: SchemaIssue[]): Reading {\n // `optional` is checked before `nullable`, so a schema that is both treats\n // null as \"absent\". They are not distinguishable on the wire: strict mode\n // gives the model one spelling for \"nothing\", and pretending otherwise would\n // mean `.nullable().optional()` silently kept a key the type says is\n // optional. What that trades away is the ability to say \"present and null\" on\n // a field that may also be absent — a distinction no model can express here.\n if (definition.optional && (value === null || value === undefined)) {\n return { drop: true, value: undefined };\n }\n if (definition.nullable && value === null) return { drop: false, value: null };\n return { drop: false, value: readNode(definition, value, path, issues) };\n}\n\nfunction readNode(\n definition: Definition,\n value: unknown,\n path: Path,\n issues: SchemaIssue[],\n): unknown {\n const node = definition.node;\n const fail = () => {\n const code: SchemaIssueCode =\n value === undefined\n ? \"required\"\n : node.kind === \"literal\"\n ? \"const\"\n : node.kind === \"enum\" && typeof value === \"string\"\n ? \"enum\"\n : \"type\";\n const params =\n code === \"const\"\n ? { allowedValue: (node as { value: unknown }).value }\n : code === \"enum\"\n ? { allowedValues: (node as { values: readonly string[] }).values }\n : {};\n issues.push({\n path,\n code,\n message: `expected ${wanted(definition)}, got ${saw(node, value)}`,\n params,\n });\n return undefined;\n };\n\n switch (node.kind) {\n case \"string\":\n if (typeof value !== \"string\") return fail();\n checkString(node.checks, value, path, issues);\n return value;\n case \"number\":\n // NaN and Infinity do not survive `JSON.stringify`, so a tool that\n // returns one produces a body the provider cannot be sent.\n if (typeof value !== \"number\" || !Number.isFinite(value)) return fail();\n if (node.checks?.integer && !Number.isInteger(value)) return fail();\n checkNumber(node.checks, value, path, issues);\n return value;\n case \"boolean\":\n return typeof value === \"boolean\" ? value : fail();\n case \"literal\":\n return value === node.value ? value : fail();\n case \"enum\":\n if (typeof value !== \"string\" || !node.values.includes(value)) return fail();\n checkString(node.checks, value, path, issues);\n return value;\n case \"array\": {\n if (!Array.isArray(value)) return fail();\n const items = value.map((item, index) => {\n const element = read(node.item, item, [...path, index], issues);\n return element.drop ? undefined : element.value;\n });\n const { minItems, maxItems } = node.checks ?? {};\n if (minItems !== undefined && value.length < minItems) {\n issues.push({\n path,\n code: \"minItems\",\n message: `expected at least ${minItems} items, got ${value.length}`,\n params: { limit: minItems },\n });\n }\n if (maxItems !== undefined && value.length > maxItems) {\n issues.push({\n path,\n code: \"maxItems\",\n message: `expected at most ${maxItems} items, got ${value.length}`,\n params: { limit: maxItems },\n });\n }\n return items;\n }\n case \"object\": {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) return fail();\n const source = value as Record<string, unknown>;\n const output: Record<string, unknown> = {};\n for (const [key, child] of Object.entries(node.shape)) {\n const element = read(child, source[key], [...path, key], issues);\n if (!element.drop) output[key] = element.value;\n }\n // Unknown keys are DROPPED, not rejected. `additionalProperties: false`\n // has already told the model not to send them, so one arriving anyway is\n // a slip rather than an attack, and failing a whole tool call over a\n // stray field costs a turn to fix nothing. Dropping is also what keeps\n // `execute` from ever seeing a field its input type says cannot be there.\n return output;\n }\n case \"union\": {\n let best: { issues: SchemaIssue[]; score: number } | undefined;\n for (const member of node.members) {\n const attempt: SchemaIssue[] = [];\n const element = read(member, value, path, attempt);\n if (attempt.length === 0) return element.drop ? undefined : element.value;\n const points = score(member, value);\n if (!best || points > best.score) best = { issues: attempt, score: points };\n }\n // \"no match\" is useless when one field of a five-field variant was wrong.\n // Naming the closest variant and why it stopped is the difference between\n // a debuggable bad tool call and a shrug.\n issues.push({\n path,\n code: \"anyOf\",\n message: `no matching variant; closest: ${best!.issues.map(render).join(\"; \")}`,\n params: { closest: best!.issues },\n });\n return undefined;\n }\n // Passed through by reference, not rebuilt. Two reasons beyond the obvious\n // one: a rebuild would turn a `Date` into `{}` by copying own properties\n // that a `toJSON` was going to replace anyway, and the agent loop signs the\n // *parsed* input and later verifies the signature against it — a parse that\n // is exactly the identity cannot disagree with itself.\n case \"json\":\n if (value === undefined) return fail();\n checkJson(value, path, issues, new Set());\n return value;\n // The reference's own `optional`/`nullable` were settled by `read` above;\n // the body's are its own business, settled by the `read` below.\n case \"ref\":\n return through(\n node.cell,\n value,\n () => {\n issues.push({\n path,\n code: \"type\",\n message: \"expected a finite tree, got a circular reference\",\n params: {},\n });\n return undefined;\n },\n () => read(bodyOf(node.cell), value, path, issues).value,\n );\n }\n}\n\n/**\n * Length in code points, not UTF-16 units — what JSON Schema (and Ajv) count,\n * so an emoji is one character against a `maxLength` either way.\n */\nfunction length(value: string): number {\n let count = 0;\n for (const _ of value) count++;\n return count;\n}\n\nfunction checkString(\n checks: StringChecks | undefined,\n value: string,\n path: Path,\n issues: SchemaIssue[],\n): void {\n if (!checks) return;\n const { minLength, maxLength, format } = checks;\n if (minLength !== undefined || maxLength !== undefined) {\n const size = length(value);\n if (minLength !== undefined && size < minLength) {\n issues.push({\n path,\n code: \"minLength\",\n message: `expected at least ${minLength} characters, got ${size}`,\n params: { limit: minLength },\n });\n }\n if (maxLength !== undefined && size > maxLength) {\n issues.push({\n path,\n code: \"maxLength\",\n message: `expected at most ${maxLength} characters, got ${size}`,\n params: { limit: maxLength },\n });\n }\n }\n if (format) {\n let ok = false;\n try {\n ok = format.test(value) === true;\n } catch {\n // A check that throws has not said yes.\n }\n if (!ok) {\n issues.push({\n path,\n code: \"format\",\n message: `expected a string in format \"${format.name}\"`,\n params: { format: format.name },\n });\n }\n }\n}\n\nfunction checkNumber(\n checks: NumberChecks | undefined,\n value: number,\n path: Path,\n issues: SchemaIssue[],\n): void {\n if (!checks) return;\n const bound = (\n code: SchemaIssueCode,\n limit: number | undefined,\n passes: (limit: number) => boolean,\n words: string,\n ) => {\n if (limit === undefined || passes(limit)) return;\n issues.push({\n path,\n code,\n message: `expected ${words} ${limit}, got ${value}`,\n params: { limit },\n });\n };\n bound(\"minimum\", checks.minimum, (limit) => value >= limit, \"at least\");\n bound(\"exclusiveMinimum\", checks.exclusiveMinimum, (limit) => value > limit, \"more than\");\n bound(\"maximum\", checks.maximum, (limit) => value <= limit, \"at most\");\n bound(\"exclusiveMaximum\", checks.exclusiveMaximum, (limit) => value < limit, \"less than\");\n}\n\n/**\n * Checks that a value is JSON, which is the only check a `json()` node makes.\n *\n * Tool arguments arrive through `JSON.parse`, so this never fires on model\n * input. It fires on a tool *output* or a structured answer an app built, where\n * a `bigint` or a cycle throws inside `JSON.stringify` and a function or a\n * `symbol` is dropped without a word — one turn later, with the provider's\n * request body to debug instead of the value.\n *\n * `undefined` and non-plain objects are deliberately allowed below the root:\n * `JSON.stringify` drops an `undefined` property, writes `null` for an\n * `undefined` element, and calls `toJSON` where there is one. Those are JSON's\n * own answers, and rejecting a `Date` to catch a `Map` is a bad trade.\n *\n * `toJSON` is honoured rather than assumed harmless: the walk checks what it\n * returns and never the object behind it, because that is all `JSON.stringify`\n * will look at.\n */\nfunction checkJson(\n value: unknown,\n path: Path,\n issues: SchemaIssue[],\n seen: Set<object>,\n // False for the value a `toJSON` just returned: `JSON.stringify` applies\n // `toJSON` once per position, and re-applying it is how a pair of them\n // returning each other became an infinite loop.\n applyToJSON = true,\n): void {\n const reject = (what: string) => {\n issues.push({ path, code: \"type\", message: `expected a JSON value, got ${what}`, params: {} });\n };\n\n switch (typeof value) {\n case \"undefined\":\n case \"string\":\n case \"boolean\":\n return;\n case \"number\":\n if (!Number.isFinite(value)) reject(String(value));\n return;\n case \"bigint\":\n return reject(\"a bigint\");\n case \"function\":\n return reject(\"a function\");\n case \"symbol\":\n return reject(\"a symbol\");\n }\n\n if (value === null) return;\n const object = value as object;\n\n // The cycle guard comes FIRST, above `toJSON`, and that ordering is the whole\n // of it: a `toJSON` is arbitrary code that can hand back another object with a\n // `toJSON` of its own, so two of them returning each other is a cycle that\n // `seen` catches and an identity test cannot. Below the guard, that pair hung\n // `safeParse` forever — and a `toJSON` returning a fresh object each time threw\n // `RangeError` out of a function documented to return `{ ok: false, errors }`.\n if (seen.has(object)) return reject(\"a circular reference\");\n seen.add(object);\n try {\n // `JSON.stringify` asks `toJSON` what to write and never looks at the object\n // itself, so that answer is what has to be checked. Without this the walk\n // descended into the wrapper's own fields and refused values `stringify`\n // serializes without complaint — a `toJSON` returning a string off a `bigint`\n // field being the archetype, since writing a `toJSON` is exactly what one\n // does about a field JSON cannot carry. `Date` passed only by having no own\n // enumerable properties to trip over.\n const toJSON = applyToJSON ? (object as { toJSON?: unknown }).toJSON : undefined;\n if (typeof toJSON === \"function\") {\n let replaced: unknown;\n try {\n replaced = (toJSON as (key?: string) => unknown).call(object);\n } catch {\n return reject(\"a toJSON that threw\");\n }\n // `JSON.stringify` applies `toJSON` once per value position, not until it\n // stops changing, so the replacement is checked with it switched off here\n // — its nested values get their own.\n if (replaced === undefined) return reject(\"a toJSON that returns undefined\");\n return checkJson(replaced, path, issues, seen, false);\n }\n if (Array.isArray(value)) {\n value.forEach((item, index) => checkJson(item, [...path, index], issues, seen));\n } else {\n for (const [key, child] of Object.entries(object)) {\n checkJson(child, [...path, key], issues, seen);\n }\n }\n } finally {\n // Removed rather than left in: `seen` is the path currently being walked, and\n // keeping it would call the same object appearing twice side by side — which\n // `JSON.stringify` writes out twice quite happily — a cycle. In a `finally`\n // so the `toJSON` returns above cannot leave it marked.\n seen.delete(object);\n }\n}\n\n/**\n * The one cast in this file, and the reason it has to exist: `OUTPUT` and\n * `OPTIONAL` are `declare const` unique symbols. They have no runtime\n * counterpart — they are inference channels — so no object that can actually be\n * constructed satisfies `Schema<T>` structurally. Funnelling every builder\n * through here means the lie is told once, in one place, and everything else in\n * the module is checked against the real declarations.\n */\nfunction make<T>(definition: Definition): SchemaBuilder<T> {\n return build(definition) as unknown as SchemaBuilder<T>;\n}\n\n/**\n * Builders are immutable: `describe`, `optional` and `nullable` each build a\n * fresh one from a copied definition. Mutating in place is the obvious\n * implementation and it is wrong — `const id = s.string()` reused in two\n * objects, described in one of them, would carry that description into the\n * other, and the only symptom is a model being told the wrong thing about a\n * field somewhere else.\n */\nfunction build(definition: Definition): RuntimeSchema {\n const runtime: RuntimeSchema = {\n toJSONSchema: () => emitRoot(definition),\n parse(value) {\n const issues: SchemaIssue[] = [];\n const result = read(definition, value, [], issues);\n if (issues.length > 0) throw new Error(issues.map(render).join(\"; \"));\n return result.drop ? undefined : result.value;\n },\n safeParse(value) {\n const issues: SchemaIssue[] = [];\n const result = read(definition, value, [], issues);\n if (issues.length > 0) return { ok: false, errors: issues.map(render) };\n return { ok: true, value: result.drop ? undefined : result.value };\n },\n validate(value) {\n const issues: SchemaIssue[] = [];\n const result = read(definition, value, [], issues);\n if (issues.length > 0) return { ok: false, issues };\n return { ok: true, value: result.drop ? undefined : result.value };\n },\n describe: (description) => build({ ...definition, description }),\n optional: () => build({ ...definition, optional: true }),\n // Clearing `optional` is not tidiness. `nullable()` returns a\n // `SchemaBuilder`, not an `OptionalSchemaBuilder`, so the key it describes\n // is required again in `ShapeOutput` — and a parse that still dropped it\n // would hand back an object missing a key its own type declares.\n nullable: () => build({ ...definition, nullable: true, optional: false }),\n };\n definitions.set(runtime, definition);\n return runtime;\n}\n\nfunction leaf(node: SchemaNode): Definition {\n return { node, optional: false, nullable: false };\n}\n\n// --- reading a JSON Schema ---------------------------------------------------\n\n/**\n * How `s.fromJSONSchema` checks a `format`. `true` accepts any string (a format\n * that is only a hint, like `markdown`); a `RegExp` or a function decides.\n */\nexport type JSONSchemaFormat = true | RegExp | ((value: string) => boolean);\n\nexport type FromJSONSchemaOptions = {\n /**\n * The formats the schema may name. A `format` not listed here is refused, not\n * ignored: gemi ships no format checks of its own, and a format that quietly\n * checked nothing would be a constraint that only looks enforced.\n */\n formats?: Record<string, JSONSchemaFormat>;\n /**\n * Keywords to skip as annotations, on top of the ones always skipped:\n * `title`, `$schema`, `$id`, `$comment`, `examples`, `default`,\n * `deprecated`, `readOnly`, `writeOnly`, and every `x-` keyword.\n */\n ignoreKeywords?: readonly string[];\n};\n\n/**\n * Thrown by `s.fromJSONSchema` for a schema outside the subset `s` models.\n * `problems` lists every one found, each starting with the path into the\n * schema (`properties.price.type: ...`), so a schema written by a user or a\n * model can be sent back with all of them at once.\n */\nexport class JSONSchemaError extends Error {\n readonly problems: string[];\n constructor(problems: string[]) {\n super(\n `gemi/ai: s.fromJSONSchema cannot model this schema:\\n${problems.map((p) => `- ${p}`).join(\"\\n\")}`,\n );\n this.name = \"JSONSchemaError\";\n this.problems = problems;\n }\n}\n\nconst ANNOTATIONS = new Set([\n \"title\",\n \"$schema\",\n \"$id\",\n \"$comment\",\n \"examples\",\n \"default\",\n \"deprecated\",\n \"readOnly\",\n \"writeOnly\",\n]);\n\n/** The keywords each type may carry, beyond `type`, `description`, `enum` and `const`. */\nconst KEYWORDS: Record<string, readonly string[]> = {\n string: [\"minLength\", \"maxLength\", \"format\"],\n number: [\"minimum\", \"maximum\", \"exclusiveMinimum\", \"exclusiveMaximum\"],\n integer: [\"minimum\", \"maximum\", \"exclusiveMinimum\", \"exclusiveMaximum\"],\n boolean: [],\n object: [\"properties\", \"required\", \"additionalProperties\"],\n array: [\"items\", \"minItems\", \"maxItems\"],\n};\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/**\n * Reads a JSON Schema into a definition, collecting every problem rather than\n * stopping at the first. Returns `undefined` where a node could not be read;\n * the caller throws once the walk is done.\n */\nfunction fromJSON(\n schema: unknown,\n options: FromJSONSchemaOptions,\n where: string,\n problems: string[],\n): Definition | undefined {\n const problem = (message: string, at = where) => {\n problems.push(at ? `${at}: ${message}` : message);\n return undefined;\n };\n const child = (key: string) => (where ? `${where}.${key}` : key);\n if (!isPlainObject(schema)) return problem(\"expected a schema object\");\n\n const ignored = new Set(options.ignoreKeywords ?? []);\n const skip = (key: string) => ANNOTATIONS.has(key) || key.startsWith(\"x-\") || ignored.has(key);\n\n // `type: [T, \"null\"]`, `enum` with a null in it and an `anyOf` with a\n // `{ type: \"null\" }` member all mean the same: T, nullable.\n let nullable = false;\n let type = schema.type;\n if (Array.isArray(type)) {\n const rest = type.filter((t) => t !== \"null\");\n if (rest.length !== 1) {\n return problem(\n `type ${JSON.stringify(type)} is not supported; only one type, optionally with \"null\". Use anyOf for alternatives`,\n child(\"type\"),\n );\n }\n nullable = rest.length < type.length;\n type = rest[0];\n }\n if (type !== undefined && (typeof type !== \"string\" || !(type in KEYWORDS))) {\n return problem(\n `type ${JSON.stringify(type)} is not supported; expected one of ${Object.keys(KEYWORDS).join(\", \")}`,\n child(\"type\"),\n );\n }\n\n const allowed = new Set([\n \"type\",\n \"description\",\n \"enum\",\n \"const\",\n \"anyOf\",\n ...(type ? KEYWORDS[type as string] : []),\n ]);\n let unknown = false;\n for (const key of Object.keys(schema)) {\n if (allowed.has(key) || skip(key)) continue;\n unknown = true;\n const owner = Object.entries(KEYWORDS).find(([, keys]) => keys.includes(key));\n problem(\n owner && owner[0] !== type\n ? `\"${key}\" applies to type ${owner[0]}, and this schema is ${type ? `type ${type}` : \"untyped\"}`\n : `\"${key}\" is not supported by s.fromJSONSchema`,\n child(key),\n );\n }\n if (unknown) return undefined;\n\n if (schema.description !== undefined && typeof schema.description !== \"string\") {\n return problem(\"expected a string\", child(\"description\"));\n }\n const description = schema.description as string | undefined;\n const finish = (node: SchemaNode): Definition => ({\n node,\n optional: false,\n nullable,\n ...(description ? { description } : {}),\n });\n\n if (schema.anyOf !== undefined) {\n if (type !== undefined || schema.enum !== undefined || schema.const !== undefined) {\n return problem(\"anyOf cannot be combined with type, enum or const here\", child(\"anyOf\"));\n }\n if (!Array.isArray(schema.anyOf) || schema.anyOf.length === 0) {\n return problem(\"expected a non-empty array\", child(\"anyOf\"));\n }\n const members: Definition[] = [];\n let failed = false;\n schema.anyOf.forEach((member, index) => {\n if (isPlainObject(member) && member.type === \"null\" && Object.keys(member).length === 1) {\n nullable = true;\n return;\n }\n const read = fromJSON(member, options, child(`anyOf[${index}]`), problems);\n if (read) members.push(read);\n else failed = true;\n });\n if (failed) return undefined;\n if (members.length === 0) return problem(\"anyOf has only null in it\", child(\"anyOf\"));\n if (members.length === 1) {\n const only = members[0]!;\n return {\n ...only,\n nullable: only.nullable || nullable,\n ...(description ? { description } : {}),\n };\n }\n return finish({ kind: \"union\", members });\n }\n\n if (schema.const !== undefined) {\n const value = schema.const;\n if (typeof value !== \"string\" && typeof value !== \"number\" && typeof value !== \"boolean\") {\n return problem(\"only a string, number or boolean const is supported\", child(\"const\"));\n }\n if (type !== undefined && typeof value !== (type === \"integer\" ? \"number\" : type)) {\n return problem(`const ${JSON.stringify(value)} is not of type ${type}`, child(\"const\"));\n }\n return finish({ kind: \"literal\", value });\n }\n\n let stringChecks: StringChecks | undefined;\n if (type === \"string\") {\n stringChecks = readStringChecks(schema, options, child, problems);\n if (stringChecks === null) return undefined;\n }\n\n if (schema.enum !== undefined) {\n if (!Array.isArray(schema.enum) || schema.enum.length === 0) {\n return problem(\"expected a non-empty array\", child(\"enum\"));\n }\n const values = schema.enum.filter((value) => value !== null);\n if (values.length < schema.enum.length) nullable = true;\n const bad = values.find(\n (value) =>\n !(typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\") ||\n (type !== undefined && typeof value !== (type === \"integer\" ? \"number\" : type)),\n );\n if (bad !== undefined || values.length === 0) {\n return problem(\n type\n ? `every value must be of type ${type}${values.length === 0 ? \", and there must be one\" : `; ${JSON.stringify(bad)} is not`}`\n : \"only strings, numbers and booleans are supported\",\n child(\"enum\"),\n );\n }\n if (values.every((value) => typeof value === \"string\")) {\n return finish({\n kind: \"enum\",\n values: [...new Set(values as string[])],\n ...(stringChecks ? { checks: stringChecks } : {}),\n });\n }\n const literals = [...new Set(values as (string | number | boolean)[])];\n if (literals.length === 1) return finish({ kind: \"literal\", value: literals[0]! });\n return finish({\n kind: \"union\",\n members: literals.map((value) => leaf({ kind: \"literal\", value })),\n });\n }\n\n switch (type) {\n case undefined:\n return problem(\"a schema needs a type, an enum, a const or an anyOf\");\n case \"string\":\n return finish({ kind: \"string\", ...(stringChecks ? { checks: stringChecks } : {}) });\n case \"number\":\n case \"integer\": {\n const checks: NumberChecks = type === \"integer\" ? { integer: true } : {};\n let failed = false;\n for (const key of KEYWORDS.number!) {\n const value = schema[key];\n if (value === undefined) continue;\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n problem(\"expected a number\", child(key));\n failed = true;\n continue;\n }\n checks[key as \"minimum\"] = value;\n }\n if (failed) return undefined;\n return finish({ kind: \"number\", ...(Object.keys(checks).length > 0 ? { checks } : {}) });\n }\n case \"boolean\":\n return finish({ kind: \"boolean\" });\n case \"array\": {\n if (!isPlainObject(schema.items)) {\n return problem(\n 'an array needs \"items\" to be one schema (tuples are not supported)',\n child(\"items\"),\n );\n }\n const checks: ArrayChecks = {};\n let failed = false;\n for (const key of [\"minItems\", \"maxItems\"] as const) {\n const value = schema[key];\n if (value === undefined) continue;\n if (typeof value !== \"number\" || !Number.isInteger(value) || value < 0) {\n problem(\"expected a non-negative integer\", child(key));\n failed = true;\n continue;\n }\n checks[key] = value;\n }\n const item = fromJSON(schema.items, options, child(\"items\"), problems);\n if (!item || failed) return undefined;\n return finish({ kind: \"array\", item, ...(Object.keys(checks).length > 0 ? { checks } : {}) });\n }\n case \"object\": {\n const properties = schema.properties ?? {};\n if (!isPlainObject(properties)) return problem(\"expected an object\", child(\"properties\"));\n if (schema.additionalProperties !== undefined && schema.additionalProperties !== false) {\n return problem(\n \"only false is supported; a record with arbitrary keys has no strict-mode form (use s.json())\",\n child(\"additionalProperties\"),\n );\n }\n const required = schema.required ?? [];\n if (!Array.isArray(required) || !required.every((key) => typeof key === \"string\")) {\n return problem(\"expected an array of property names\", child(\"required\"));\n }\n const missing = required.filter((key) => !Object.hasOwn(properties, key));\n if (missing.length > 0) {\n return problem(\n `lists properties the schema doesn't have: ${missing.join(\", \")}`,\n child(\"required\"),\n );\n }\n const shape: Record<string, Definition> = {};\n let failed = false;\n for (const [key, value] of Object.entries(properties)) {\n const read = fromJSON(value, options, child(`properties.${key}`), problems);\n if (!read) {\n failed = true;\n continue;\n }\n // Not in `required` is \"may be left out\", which is `optional()`: the\n // model is told to send null, and a parse drops the key.\n shape[key] = required.includes(key) ? read : { ...read, optional: true };\n }\n if (failed) return undefined;\n return finish({ kind: \"object\", shape });\n }\n }\n return undefined;\n}\n\n/** `null` when a problem was reported. */\nfunction readStringChecks(\n schema: Record<string, unknown>,\n options: FromJSONSchemaOptions,\n child: (key: string) => string,\n problems: string[],\n): StringChecks | undefined | null {\n const checks: StringChecks = {};\n let failed = false;\n for (const key of [\"minLength\", \"maxLength\"] as const) {\n const value = schema[key];\n if (value === undefined) continue;\n if (typeof value !== \"number\" || !Number.isInteger(value) || value < 0) {\n problems.push(`${child(key)}: expected a non-negative integer`);\n failed = true;\n continue;\n }\n checks[key] = value;\n }\n if (schema.format !== undefined) {\n const name = schema.format;\n const format = typeof name === \"string\" ? options.formats?.[name] : undefined;\n if (typeof name !== \"string\") {\n problems.push(`${child(\"format\")}: expected a string`);\n failed = true;\n } else if (!format || !Object.hasOwn(options.formats!, name)) {\n problems.push(\n `${child(\"format\")}: unknown format ${JSON.stringify(name)}; pass a check for it in the formats option`,\n );\n failed = true;\n } else {\n checks.format = { name, test: formatTest(format) };\n }\n }\n if (failed) return null;\n return Object.keys(checks).length > 0 ? checks : undefined;\n}\n\nfunction formatTest(format: JSONSchemaFormat): (value: string) => boolean {\n if (format === true) return () => true;\n if (format instanceof RegExp) {\n // A `g` or `y` regex keeps `lastIndex` between calls, so the second value\n // tested would start halfway in. Reset it every time.\n return (value) => {\n format.lastIndex = 0;\n return format.test(value);\n };\n }\n return format;\n}\n\nexport const s: {\n string(): SchemaBuilder<string>;\n number(): SchemaBuilder<number>;\n boolean(): SchemaBuilder<boolean>;\n literal<const L extends string | number | boolean>(value: L): SchemaBuilder<L>;\n /** Modelled as a JSON Schema `enum`, which strict mode does support. */\n enum<const L extends readonly [string, ...string[]]>(values: L): SchemaBuilder<L[number]>;\n object<const S extends Record<string, AnySchema>>(shape: S): SchemaBuilder<ShapeOutput<S>>;\n array<const S extends AnySchema>(item: S): SchemaBuilder<Infer<S>[]>;\n /**\n * `anyOf` of object schemas, discriminated by a literal member. Left in\n * because tool outputs are frequently a success/failure pair, and modelling\n * that as one object with everything optional is worse for the model.\n */\n union<const S extends readonly [AnySchema, AnySchema, ...AnySchema[]]>(\n members: S,\n ): SchemaBuilder<Infer<S[number]>>;\n /**\n * Any JSON value, constrained by nothing — for a format the rest of this\n * builder cannot describe: a record with arbitrary keys, a mixed-type tuple,\n * a document whose shape is not known in advance. (A document that nests\n * into itself has a strict spelling: `s.recursive`.)\n *\n * A schema containing one cannot be sent under strict mode, so a tool whose\n * input uses it is sent with `strict: false` automatically. That is not an\n * option to pass anywhere; it is read back off the schema by\n * `supportsStrict`. The rest of the tool is unaffected, and so is streaming:\n * partial arguments are parsed from the raw text, never through a schema.\n *\n * `T` is an assertion, not a guarantee. The emitted schema constrains\n * nothing, so nothing checks the model's output against `T` — only that it is\n * JSON. Validate it in `execute` and hand the model back an error it can fix,\n * the way it would any other bad argument. `describe()` is where you tell it\n * the format; with no constraints to read, that prose is all it gets.\n *\n * TWO CALL SIGNATURES, NOT A DEFAULT TYPE PARAMETER, and that is load-bearing.\n * Written `json<T = JsonValue>()`, the default lost to the surrounding\n * contextual type in the position this is actually used: `s.object`'s shape is\n * constrained to `Record<string, AnySchema>` — `Schema<any>` — which supplies\n * `any` as an inference candidate, and a candidate beats a default. So\n * `s.object({ definition: s.json() })` inferred `{ definition: any }`, which is\n * type checking switched off around exactly the field this exists for, and the\n * opposite of what the default was written to prevent. An overload with no type\n * parameter has nothing to infer, so `s.json()` is `JsonValue` wherever it is\n * written.\n *\n * `ai:generate-client` maps it to the native `JSONValue` and says nothing about\n * it. `JsonValue` is a union of every JSON shape, so it used to reach the\n * generator's \"a union that is not told apart by one string member\" warning —\n * true, and a misdescription of a field that is free-form on purpose. The\n * extractor recognises it now.\n */\n json(): SchemaBuilder<JsonValue>;\n json<T>(): SchemaBuilder<T>;\n /**\n * A schema that contains itself — a tree of UI nodes, a comment thread, a\n * folder listing — and stays strict-mode safe, unlike `s.json()`.\n *\n * ```ts\n * type Node = { tag: string; text?: string; children: Node[] };\n *\n * const node = s.recursive<Node>(\"Node\", (self) =>\n * s.object({\n * tag: s.enum([\"section\", \"heading\", \"text\"]),\n * text: s.string().optional(),\n * children: s.array(self),\n * }),\n * );\n * const output = s.object({ title: s.string(), root: node });\n * ```\n *\n * Emitted the way OpenAI's strict structured output spells recursion: the\n * body once under the root's `$defs[name]`, and `{ \"$ref\": \"#/$defs/<name>\" }`\n * wherever it is used. Used as the root itself, the body is also inlined at\n * the root, since a tool's parameters and an agent's output must be an\n * object there. `parse`, `safeParse` and `validate` follow the reference to\n * any depth.\n *\n * `T` has to be written out: TypeScript cannot infer a type from a value\n * that mentions itself. The callback's schema is checked against it, so a\n * field the type has and the schema lacks (or the reverse) is a type error.\n *\n * Rules, each an error when the schema is built:\n *\n * - `name` is the `$defs` key: letters, digits, `_` and `-`. Two different\n * recursive schemas in one tool or output need different names.\n * - `self` must be nested inside an `s.object` field or an `s.array` — a\n * body that is `self` again through a union describes no finite value.\n * - The body cannot be `optional()`; make the uses optional instead\n * (`children: s.array(self).optional()`, `next: self.optional()`).\n *\n * Strict mode limits the rest as usual: every node of the body is in the\n * strict subset or the whole schema is sent non-strict (`supportsStrict`).\n */\n recursive<T>(name: string, define: (self: SchemaBuilder<T>) => Schema<T>): SchemaBuilder<T>;\n /**\n * A schema read from a JSON Schema at runtime — for a shape that comes from\n * data rather than code, like a collection whose items a user defined.\n *\n * Only the subset `s` itself models is accepted, so the result stays\n * strict-mode safe and can be a tool's `inputSchema` like any other:\n *\n * - `type`: `string`, `number`, `integer`, `boolean`, `object`, `array`,\n * or one of them with `\"null\"` (`[\"string\", \"null\"]`).\n * - `enum` (strings become `s.enum`, numbers and booleans a union of\n * literals; a `null` in it makes the field nullable), `const`, `anyOf`.\n * - strings: `minLength`, `maxLength`, `format` (checked with\n * `options.formats`). Numbers: `minimum`, `maximum`, `exclusiveMinimum`,\n * `exclusiveMaximum`. Arrays: `items` (one schema), `minItems`, `maxItems`.\n * - objects: `properties`, `required`, `additionalProperties: false`. A\n * property not in `required` is `optional()`.\n * - `description`; annotations (`title`, `default`, `examples`, `$schema`,\n * `x-*`, … and `options.ignoreKeywords`) are skipped.\n *\n * Anything else — `pattern`, `oneOf`, `allOf`, `$ref`, a tuple, an open\n * `additionalProperties`, an unknown `format` — throws a `JSONSchemaError`\n * listing every problem with its path.\n *\n * The length, range, item-count and format constraints are enforced by\n * `parse`/`safeParse`/`validate` and told to the model in the field's\n * description, because strict structured output does not accept them as\n * keywords. Unlike Ajv, an unknown key in an object is dropped from the\n * parsed value rather than reported.\n *\n * The output type is `JsonValue` (or the `T` you assert). Validate a value\n * with `.validate(value)` for per-path issues, or `.safeParse(value)`.\n */\n fromJSONSchema(schema: unknown, options?: FromJSONSchemaOptions): SchemaBuilder<JsonValue>;\n fromJSONSchema<T>(schema: unknown, options?: FromJSONSchemaOptions): SchemaBuilder<T>;\n} = {\n string: () => make<string>(leaf({ kind: \"string\" })),\n number: () => make<number>(leaf({ kind: \"number\" })),\n boolean: () => make<boolean>(leaf({ kind: \"boolean\" })),\n literal: (value) => make<typeof value>(leaf({ kind: \"literal\", value })),\n enum: (values) => make<(typeof values)[number]>(leaf({ kind: \"enum\", values })),\n object: (shape) =>\n make<ShapeOutput<typeof shape>>(\n leaf({\n kind: \"object\",\n shape: Object.fromEntries(\n Object.entries(shape).map(([key, child]) => [key, definitionOf(child)]),\n ),\n }),\n ),\n array: (item) => make<Infer<typeof item>[]>(leaf({ kind: \"array\", item: definitionOf(item) })),\n // A union is legal wherever a property is, but not as the root of a tool's\n // input or an agent's structured output: the provider wants an object there.\n // `s` cannot know where a schema will be used, so `AgentTool.create` and\n // `Agent.create` are what reject it at the root.\n union: (members) =>\n make<Infer<(typeof members)[number]>>(\n leaf({ kind: \"union\", members: members.map(definitionOf) }),\n ),\n json: <T>() => make<T>(leaf({ kind: \"json\" })),\n recursive,\n fromJSONSchema: <T>(schema: unknown, options: FromJSONSchemaOptions = {}) => {\n const problems: string[] = [];\n const definition = fromJSON(schema, options, \"\", problems);\n if (!definition || problems.length > 0) {\n throw new JSONSchemaError(problems.length > 0 ? problems : [\"unreadable schema\"]);\n }\n return make<T>(definition);\n },\n};\n\n/**\n * Whether a schema can be sent under a provider's strict mode.\n *\n * False exactly when a `json()` node is somewhere inside it. Strict mode's\n * bargain is that every node constrains its value; an unconstrained one has no\n * spelling there, and sending it anyway is a 400 naming a path.\n *\n * Derived from the tree rather than declared alongside it, because the two\n * would drift: a field added to a tool's input a year from now would need\n * whoever adds it to know that a flag somewhere else describes it. Adding the\n * field is the whole of turning strict off.\n */\nexport function supportsStrict(schema: AnySchema): boolean {\n const definition = definitions.get(schema);\n if (definition) return strictNode(definition.node);\n // A schema built by hand rather than with `s`: `questionSchema` in\n // `ai/Agent.ts`, and the merged one `services/mcp` casts together.\n //\n // Answering `true` here was wrong, and not harmlessly. `McpRegistry`'s\n // `combineSchemas` spreads `meta.input.toJSONSchema()` into its own object,\n // so an `s.json()` field an app declared on an `mcp` route survives into the\n // emitted schema while the *tree* that would have reported it is discarded.\n // Every MCP-projected tool was therefore sent `strict: true` with an empty\n // subschema inside it — a 400 on every turn, from the one path this function\n // exists to get right.\n //\n // So the emitted schema is read instead. It is the same question asked of the\n // artifact rather than the source, which is the only thing a foreign schema\n // has to offer.\n return strictJSONSchema(schema.toJSONSchema());\n}\n\n/**\n * Whether an already-emitted JSON Schema constrains every value it describes.\n *\n * Only for schemas with no definition tree. It answers a narrower question than\n * `strictNode` — it cannot see optionality or a builder's intent, just whether\n * some node says nothing about its value — but that is exactly the property\n * strict mode rejects, and it is visible in the artifact.\n */\nfunction strictJSONSchema(schema: JSONSchema): boolean {\n // `description` is prose, not a constraint. A node carrying only that — which\n // is what `s.json().describe(...)` emits — says nothing about its value.\n const constrained =\n schema.$ref !== undefined ||\n schema.type !== undefined ||\n schema.enum !== undefined ||\n schema.const !== undefined ||\n schema.anyOf !== undefined ||\n schema.properties !== undefined ||\n schema.items !== undefined;\n if (!constrained) return false;\n\n for (const child of Object.values(schema.properties ?? {})) {\n if (!strictJSONSchema(child)) return false;\n }\n if (schema.items && !strictJSONSchema(schema.items)) return false;\n for (const member of schema.anyOf ?? []) {\n if (!strictJSONSchema(member)) return false;\n }\n // A `$ref` is answered for by the `$defs` entry it points at, which is\n // checked here once rather than followed — following it is a cycle.\n for (const definition of Object.values(schema.$defs ?? {})) {\n if (!strictJSONSchema(definition)) return false;\n }\n return true;\n}\n\n/**\n * Enumerated rather than defaulted, so that a node kind added later cannot\n * inherit \"strict\" by omission — which is the failure that shows up as a 400\n * from the provider rather than as a type error here.\n *\n * The one cycle in a definition tree is an `s.recursive` reaching itself, so\n * `seen` holds the cells already being answered for: a body that is strict\n * apart from its references to itself is strict.\n */\nfunction strictNode(node: SchemaNode, seen = new Set<RecursiveCell>()): boolean {\n switch (node.kind) {\n case \"string\":\n case \"number\":\n case \"boolean\":\n case \"literal\":\n case \"enum\":\n return true;\n case \"object\":\n return Object.values(node.shape).every((child) => strictNode(child.node, seen));\n case \"array\":\n return strictNode(node.item.node, seen);\n case \"union\":\n return node.members.every((member) => strictNode(member.node, seen));\n case \"json\":\n return false;\n case \"ref\":\n if (seen.has(node.cell)) return true;\n seen.add(node.cell);\n return strictNode(bodyOf(node.cell).node, seen);\n }\n}\n\n/**\n * Whether `definition` can reach `cell` without an object property or an\n * array item in between — through a union member, or another recursive\n * schema's body. Such a schema describes no finite value (`Self = Self |\n * string` is just `string`), and reading one would recurse forever on a\n * primitive, where no object is there to catch the cycle with.\n */\nfunction reachesUnguarded(\n definition: Definition,\n cell: RecursiveCell,\n seen = new Set<RecursiveCell>(),\n): boolean {\n const node = definition.node;\n if (node.kind === \"union\") {\n return node.members.some((member) => reachesUnguarded(member, cell, seen));\n }\n if (node.kind !== \"ref\") return false;\n if (node.cell === cell) return true;\n if (seen.has(node.cell) || !node.cell.definition) return false;\n seen.add(node.cell);\n return reachesUnguarded(node.cell.definition, cell, seen);\n}\n\nconst RECURSIVE_NAME = /^[A-Za-z_][A-Za-z0-9_-]{0,63}$/;\n\nfunction recursive<T>(\n name: string,\n define: (self: SchemaBuilder<T>) => Schema<T>,\n): SchemaBuilder<T> {\n if (typeof name !== \"string\" || !RECURSIVE_NAME.test(name)) {\n throw new Error(\n `gemi/ai: s.recursive needs a name of letters, digits, \"_\" and \"-\" (starting with a letter or \"_\", at most 64), got ${JSON.stringify(name)}`,\n );\n }\n const cell: RecursiveCell = { name, active: new Set() };\n const reference = (): Definition => leaf({ kind: \"ref\", cell });\n const body = definitionOf(define(make<T>(reference())));\n if (body.optional) {\n throw new Error(\n `gemi/ai: the recursive schema \"${name}\" is optional() as a whole; mark the places that use it optional instead`,\n );\n }\n if (reachesUnguarded(body, cell)) {\n throw new Error(\n `gemi/ai: the recursive schema \"${name}\" refers to itself outside any object or array, so it describes no finite value; nest \\`self\\` in an s.object(...) field or an s.array(...)`,\n );\n }\n cell.definition = body;\n return make<T>(reference());\n}\n",
|
|
11
|
-
"/**\n * The media type of a `Content-Type` header: lowercased, with its parameters\n * (`; charset=utf-8`, `; boundary=…`) cut off. `null` when there is no header\n * or nothing before the first `;`.\n *\n * Media types compare case-insensitively (RFC 9110 §8.3.1), so\n * `Application/JSON; charset=UTF-8` is `application/json`.\n */\nexport function mediaType(header: string | null | undefined): string | null {\n if (typeof header !== \"string\") return null;\n const [type] = header.split(\";\", 1);\n const normalized = type.trim().toLowerCase();\n return normalized === \"\" ? null : normalized;\n}\n\n/**\n * `application/json`, or a structured `+json` type such as\n * `application/vnd.api+json` or `application/merge-patch+json` (RFC 6839).\n * Not a prefix match: `application/json-seq` is not JSON.\n */\nexport function isJsonMediaType(type: string | null): boolean {\n if (type === null) return false;\n if (type === \"application/json\") return true;\n const slash = type.indexOf(\"/\");\n return slash > 0 && type.endsWith(\"+json\") && type.length > slash + 1 + \"+json\".length;\n}\n",
|
|
12
|
-
"/**\n * The requests the api dispatcher built itself, on a model's behalf, rather\n * than received from a client.\n *\n * Keyed on the `Request` object, not carried in it. A header was the obvious\n * alternative and it is forgeable by construction: anything the synthetic\n * request can carry, a real client can send. Only a module holding this set can\n * add to it, and it is deliberately not re-exported from `http/index.ts`, so no\n * inbound request can put itself here. The only writer is\n * `ApiRouteDispatcher.dispatchAs`, and it marks only the requests it built.\n * App code can call `dispatchAs` — it is trusted — but cannot mark a request of\n * its own.\n *\n * The object, rather than a flag on the request context, because the two\n * places an app asks the question sit on either side of `RequestContext.run`:\n * `onRequestStart` fires before the dispatcher opens the request's store, and a\n * handler's `new SomeRequest()` builds a second `HttpRequest` from inside it.\n * Both wrap the same raw `Request`, so both get the same answer, and nothing has\n * to remember to copy a field from one to the other.\n *\n * A `WeakMap`, so a dispatched request is forgotten with the request. The\n * value is the initiator's client address; see `dispatchedClientAddress`.\n */\nconst dispatched = new WeakMap<Request, { clientAddress: string }>();\n\n/**\n * `clientAddress` is required so the one writer cannot mark a request without\n * saying whose rate-limit budget it spends.\n */\nexport function markModelOriginated(req: Request, clientAddress: string) {\n dispatched.set(req, { clientAddress });\n}\n\nexport function isModelOriginated(req: Request): boolean {\n return dispatched.has(req);\n}\n\n/**\n * The client address `clientIp` resolved from the initiator, for a request the\n * dispatcher built; `undefined` for any other.\n *\n * It rides here for the same reason the marker does. The synthetic request\n * carries credentials only, so it has no `x-forwarded-for`, and\n * `RateLimitMiddleware` would key every tool call from every user on\n * `unknown:<route>`: one budget, which one user's agent loop can spend for\n * everyone. Copying the initiator's `x-forwarded-for` instead would move a\n * client-written header onto a request the server built. Carrying the value\n * `clientIp` already derived from the initiator gives a tool call exactly the\n * address the user's own direct request gets, and nothing more.\n */\nexport function dispatchedClientAddress(req: Request): string | undefined {\n return dispatched.get(req)?.clientAddress;\n}\n",
|
|
13
|
-
"// Type-only: `services/router` imports from `http`, so a runtime import here\n// would be circular.\nimport type { ResolvedDomain } from \"../services/router/DomainResolver\";\n\n// Keyed by the raw Request, so the domain `App.fetch` resolved reaches the\n// dispatcher, and every `HttpRequest` built over that Request, without a\n// second AsyncLocalStorage that a streaming render would step outside of.\nconst domains = new WeakMap<Request, ResolvedDomain>();\n\nexport function setRequestDomain(req: Request, domain: ResolvedDomain) {\n domains.set(req, domain);\n}\n\n/** The host group `req` was routed by, or `null` when `route.domains` is not configured. */\nexport function requestDomain(req: Request): ResolvedDomain | null {\n return domains.get(req) ?? null;\n}\n\n// Headers meant for this app alone — `route.domains.trustProxy.secret` — that\n// a `proxy()` route must not forward upstream with the rest of the client's.\nconst withheld = new WeakMap<Request, string[]>();\n\nexport function withholdFromUpstream(req: Request, header: string) {\n const headers = withheld.get(req) ?? [];\n if (!headers.includes(header)) {\n withheld.set(req, [...headers, header]);\n }\n}\n\n/** The lowercased header names a `proxy()` route drops from `req` before forwarding it. */\nexport function withheldFromUpstream(req: Request): readonly string[] {\n return withheld.get(req) ?? [];\n}\n",
|
|
14
|
-
"import { RequestBreakerError } from \"./Error\";\nimport { parseCookieHeader } from \"./getCookies\";\nimport { isJsonMediaType, mediaType } from \"./mediaType\";\nimport { isModelOriginated } from \"./modelOriginated\";\nimport { parseRangeHeader } from \"./range\";\nimport { RequestContext } from \"./requestContext\";\nimport { requestDomain } from \"./requestDomain\";\nimport { ValidationError } from \"./Router\";\nimport { InvalidValidationRuleError, validate } from \"./validate\";\nimport type { ResolvedDomain } from \"../services/router/DomainResolver\";\nimport { isSchema, type SchemaIssue } from \"../ai/Schema\";\n\nclass Input<T> {\n constructor(private data: T) {}\n\n public get<K extends keyof T>(key: K): T[K] {\n return this.data[key];\n }\n\n public has(key: keyof T) {\n return this.data[key] !== undefined;\n }\n\n public toJSON(): T {\n return this.data;\n }\n}\n\ntype StringType = \"string\";\ntype NumberType = \"number\";\ntype BooleanType = \"boolean\";\ntype MinLengthType = `min:${number}`;\ntype MaxLengthType = `max:${number}`;\n/** Magnitude, for numbers — see `validate`'s `min` case for why these are not\n * the same rule wearing different names. */\ntype GreaterOrEqualType = `gte:${number}`;\ntype LessOrEqualType = `lte:${number}`;\ntype RequiredType = \"required\";\ntype FileType = \"file\";\n// Backticks, not quotes. These two were written with double quotes, which makes\n// them the *literal text* `fileType:${string}` rather than a template literal\n// type — so `fileType:image/png`, the only way anyone would ever write the rule,\n// did not typecheck, while the runtime handled it perfectly well.\ntype FileTypeType = `fileType:${string}`;\ntype FileSizeType = `fileSize:${string}`;\ntype EmailType = \"email\";\ntype PasswordType = \"password\";\ntype ArrayType = \"array\";\ntype ObjectType = \"object\";\ntype InType = `in:${string}`;\n/** One entry per rule in `validate`'s `RULES`; `validate.test-d.ts` holds them\n * to each other, so an offered rule cannot go unimplemented again (#609). */\nexport type SchemaKey =\n | StringType\n | NumberType\n | BooleanType\n | MinLengthType\n | MaxLengthType\n | GreaterOrEqualType\n | LessOrEqualType\n | RequiredType\n | FileType\n | FileTypeType\n | FileSizeType\n | EmailType\n | PasswordType\n | ArrayType\n | ObjectType\n | InType;\n\ntype FieldRules = Partial<Record<SchemaKey, string>>;\n\n/**\n * A field's rules by its key, plus nested ones by dotted path: `\"address.city\"`\n * for a nested object, `\"rounds.*.prompt\"` for every item of an array (#711).\n */\nexport type Schema<T extends Body> = Record<keyof T, FieldRules> & {\n [path: `${string}.${string}`]: FieldRules;\n};\n\ntype PathSegment = string | number;\n\nfunction isContainer(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !(value instanceof Blob);\n}\n\n/**\n * The values a schema key names, each with its concrete path.\n *\n * A key without a dot, or one the body has as a key of its own (a form field\n * named `user.name`), is a plain field, as it always was. Otherwise it is a\n * path: `address.city` steps into an object, a number steps into an array, and\n * `*` stands for every item of an array (or every key of an object). A `*`\n * over anything else, a missing parent included, names nothing, so only the\n * parent's own rules decide whether it had to be there. The path is reported\n * as `SchemaIssue[\"path\"]` is: keys as strings, array indices as numbers.\n */\nfunction resolvePath(data: Body, key: string): { path: PathSegment[]; value: unknown }[] {\n if (!key.includes(\".\") || Object.hasOwn(data, key)) {\n return [{ path: [key], value: data[key] }];\n }\n let found: { path: PathSegment[]; value: unknown }[] = [{ path: [], value: data }];\n for (const segment of key.split(\".\")) {\n const next: typeof found = [];\n for (const { path, value } of found) {\n if (segment === \"*\") {\n if (Array.isArray(value)) {\n value.forEach((item, index) => next.push({ path: [...path, index], value: item }));\n } else if (isContainer(value)) {\n for (const [k, item] of Object.entries(value))\n next.push({ path: [...path, k], value: item });\n }\n continue;\n }\n if (Array.isArray(value) && /^\\d+$/.test(segment)) {\n next.push({ path: [...path, Number(segment)], value: value[Number(segment)] });\n continue;\n }\n next.push({\n path: [...path, segment],\n value: isContainer(value) && Object.hasOwn(value, segment) ? value[segment] : undefined,\n });\n }\n found = next;\n }\n return found;\n}\n\n/** `[\"rounds\", 2, \"prompt\"]` → `\"rounds.2.prompt\"`, the key a\n * `ValidationError` reports a nested field under. The root is `\"\"`. */\nfunction errorKey(path: PathSegment[]): string {\n return path.join(\".\");\n}\n\nexport type Body = Record<string, any>;\nexport type HttpRequestKind = \"view\" | \"api\";\n\nexport class HttpRequest<T extends Body = Record<string, never>, Params = Record<string, never>> {\n kind: HttpRequestKind;\n rawRequest: Request;\n headers: Omit<Headers, \"set\" | \"delete\">;\n cookies: Omit<Map<string, string>, \"set\" | \"delete\">;\n search: Input<any>;\n /**\n * What `input()` validates the body against: a map of field (or dotted\n * path, `\"rounds.*.prompt\"`) to `{ rule: message }`, or an `s` schema from\n * `gemi/ai` (#711). See `docs/controllers.md`.\n */\n schema: any = {};\n routePath: string;\n params: Params;\n /**\n * The `route.domains` group this request was routed by — `domain.params`\n * holds a `:param` subdomain's value, or what `custom.resolve` returned for\n * a custom domain. `null` when the app declares no `route.domains`.\n *\n * Kept apart from `params`, which are the path's alone.\n */\n domain: ResolvedDomain | null;\n\n constructor(req?: Request, params?: any, kind?: HttpRequestKind, routePath?: string) {\n if (!req) {\n const _req = RequestContext.getStore().req;\n this.params = _req.params as any;\n this.rawRequest = _req.rawRequest;\n this.kind = _req.kind;\n this.routePath = _req.routePath;\n this.domain = _req.domain ?? null;\n } else {\n this.params = params;\n this.rawRequest = req;\n this.routePath = routePath;\n this.kind = kind ?? \"api\";\n this.domain = requestDomain(req);\n }\n\n this.headers = this.rawRequest.headers;\n\n const cookies = parseCookieHeader(this.rawRequest.headers.get(\"Cookie\"));\n const url = new URL(this.rawRequest.url);\n const map = new Map<string, string | string[]>();\n for (const [key, value] of url.searchParams) {\n if (map.has(key)) {\n const currentValue = map.get(key);\n if (Array.isArray(currentValue)) {\n currentValue.push(value);\n map.set(key, currentValue);\n } else {\n map.set(key, [currentValue, value]);\n }\n } else {\n map.set(key, value);\n }\n }\n const _params = Object.fromEntries(map.entries());\n this.search = new Input(_params);\n this.cookies = cookies;\n }\n\n locale() {\n return RequestContext.getStore().locale;\n }\n\n ctx() {\n return RequestContext.getStore();\n }\n\n /**\n * Whether the framework dispatched this request in-process for a model — a\n * tool call — rather than a client sending it. Readable in `onRequestStart`,\n * in middleware and in the handler alike.\n *\n * No header or cookie can make this true; see `http/modelOriginated.ts`.\n */\n isModelOriginated(): boolean {\n return isModelOriginated(this.rawRequest);\n }\n\n /**\n * Aborts when the client goes away before the response is sent: the\n * browser closed the connection, or `useQuery` gave up on a request nobody\n * renders any more (#659). Hand it to slow work — a model call, an upstream\n * `fetch` — so it stops instead of running to completion for no one:\n *\n * ```ts\n * const reply = await fetch(upstream, { signal: req.signal });\n * if (req.signal.aborted) return null;\n * ```\n *\n * During a server render, an in-process query shares the page request's\n * signal.\n */\n get signal(): AbortSignal {\n return this.rawRequest.signal;\n }\n\n /**\n * The parsed `Range` header, or `null` when absent or unusable. Pass it to\n * `FileStorage.read(name, { range })` to range explicitly; inside a\n * `this.stream()` route `read()` already picks it up on its own.\n */\n range() {\n return parseRangeHeader(this.rawRequest.headers.get(\"Range\"));\n }\n\n refine(_input: any): any {\n return {};\n }\n\n /**\n * The body, by its media type: JSON (`application/json` or any `+json`\n * type), a urlencoded form, or a multipart form. The type is read without\n * its parameters and case-insensitively, so `application/json;\n * charset=utf-8` is JSON (#699). Any other type, or none, reads as `{}`.\n *\n * An empty JSON body is no body, and reads as `{}` like a request without\n * one. A body that is not JSON, or is JSON but not an object, is the\n * client's mistake: a 400 refusal (`form_error`), never a 500 (#700).\n */\n private async parseBody() {\n const type = mediaType(this.rawRequest.headers.get(\"Content-Type\"));\n\n if (isJsonMediaType(type)) {\n return new Input<T>((await this.parseJsonBody()) as T);\n }\n\n if (type === \"application/x-www-form-urlencoded\" || type === \"multipart/form-data\") {\n let body: FormData;\n try {\n body = await this.rawRequest.formData();\n } catch {\n throw new RequestBreakerError(\"The request body could not be read as a form.\");\n }\n const _inputMap = new Map<string, any>();\n for (const [key, value] of body.entries()) {\n if (_inputMap.has(key)) {\n const currentValue = _inputMap.get(key);\n if (Array.isArray(currentValue)) {\n currentValue.push(value);\n } else {\n _inputMap.set(key, [currentValue, value]);\n }\n } else {\n _inputMap.set(key, value);\n }\n }\n return new Input<T>(Object.fromEntries(_inputMap.entries()) as T);\n }\n\n return new Input<T>({} as T);\n }\n\n private async parseJsonBody(): Promise<Body> {\n if (!this.rawRequest.body) {\n return {};\n }\n let text: string;\n try {\n text = await this.rawRequest.text();\n } catch {\n throw new RequestBreakerError(\"The request body could not be read.\");\n }\n if (text.trim() === \"\") {\n return {};\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(text);\n } catch {\n throw new RequestBreakerError(\"The request body is not valid JSON.\");\n }\n // `null`, a number, a string: nothing a field could be read from. An\n // array is left alone, as it was before.\n if (parsed === null || typeof parsed !== \"object\") {\n throw new RequestBreakerError(\"The request body must be a JSON object.\");\n }\n return parsed as Body;\n }\n\n private validateInput(input: Input<T>): Input<T> {\n if (isSchema(this.schema)) {\n return this.validateWithSchema(input);\n }\n const data = (input.toJSON() ?? {}) as Body;\n const errors: Record<string, string[]> = {};\n const fields = Object.entries(this.schema as Record<string, Record<string, unknown>>).map(\n ([key, rules]) => ({\n key,\n // Every rule is looked up before any value is checked, so a schema that\n // names an unknown rule throws on every request, whatever the body —\n // not only on the ones whose earlier rules happened to pass. A function\n // is its own validator: its key is a label, and is not looked up.\n rules: Object.entries(rules).map(([rule, message]) => ({\n rule,\n message,\n check: typeof message === \"function\" ? null : this.ruleFor(key, rule),\n })),\n }),\n );\n\n for (const { key, rules } of fields) {\n for (const { path, value } of resolvePath(data, key)) {\n const messages = this.checkField(value, rules);\n if (messages.length > 0) {\n // `rounds.0.prompt` and `rounds.*.prompt` can name the same value;\n // its messages are merged, each once.\n const reported = (errors[errorKey(path)] ??= []);\n for (const message of messages) {\n if (!reported.includes(message)) reported.push(message);\n }\n }\n }\n }\n\n this.addRefinements(errors, data);\n if (Object.keys(errors).length > 0) {\n throw new ValidationError(errors);\n }\n\n return input;\n }\n\n private checkField(\n value: unknown,\n rules: { rule: string; message: unknown; check: ((value: unknown) => boolean) | null }[],\n ): string[] {\n const isRequired = rules.some(({ rule }) => rule === \"required\");\n // Absent: skipped unless `required`. `0` and `false` are values, and are\n // checked like any other — skipping every falsy value let `0` and `false` through a\n // `string` rule and `0` through a `boolean` one.\n const isAbsent = value === undefined || value === null || value === \"\";\n const messages: string[] = [];\n\n for (const { rule, message, check } of rules) {\n let _message = message;\n let _isValid = false;\n if (typeof message === \"function\") {\n _message = message(value);\n _isValid = typeof _message === \"undefined\";\n } else {\n _isValid = check!(value);\n }\n\n if (_isValid) {\n continue;\n }\n\n if (isAbsent && !isRequired) {\n continue;\n }\n\n if (rule === \"required\") {\n // A missing field reports that it is missing, and only that — not\n // also that `undefined` is not a string. Wherever `required` sits\n // among the field's rules.\n return [String(_message)];\n }\n\n // Two rules can share a message (`string` and `email` both saying\n // \"Invalid email\"); the field reports it once (#675).\n if (!messages.includes(String(_message))) {\n messages.push(String(_message));\n }\n }\n return messages;\n }\n\n /**\n * An `s` schema as the body's validator (#711). Each `SchemaIssue` is\n * reported under its path joined with dots, the same key a dotted rule uses,\n * and its `message`. A valid body is replaced by the parsed value, so what\n * the handler reads is what the schema's type says: unknown keys dropped, an\n * optional field sent as `null` left out.\n */\n private validateWithSchema(input: Input<T>): Input<T> {\n const result = this.schema.validate(input.toJSON()) as\n | { ok: true; value: unknown }\n | { ok: false; issues: SchemaIssue[] };\n const errors: Record<string, string[]> = {};\n // `in`, not `!result.ok`: without `strictNullChecks` the union does not\n // narrow on its boolean tag.\n if (\"issues\" in result) {\n for (const issue of result.issues) {\n const key = errorKey(issue.path);\n const messages = (errors[key] ??= []);\n if (!messages.includes(issue.message)) messages.push(issue.message);\n }\n }\n const parsed = \"value\" in result ? new Input<T>(result.value as T) : input;\n this.addRefinements(errors, parsed.toJSON());\n if (Object.keys(errors).length > 0) {\n throw new ValidationError(errors);\n }\n return parsed;\n }\n\n private addRefinements(errors: Record<string, string[]>, data: unknown) {\n for (const [key, value] of Object.entries(this.refine(data) ?? {})) {\n const messages = errors[key] ?? [];\n // A `refine` message the rules already reported is not repeated (#675).\n errors[key] = messages.includes(value as string) ? messages : [...messages, value as string];\n }\n }\n\n private ruleFor(key: string, rule: string) {\n try {\n return validate(rule);\n } catch (err) {\n if (err instanceof InvalidValidationRuleError) {\n throw new InvalidValidationRuleError(\n `${this.constructor.name}.schema.${key}: ${err.message}`,\n );\n }\n throw err;\n }\n }\n\n async input(): Promise<Input<T>> {\n return this.validateInput(await this.parseBody());\n }\n\n async safeInput(): Promise<{\n isValid: boolean;\n errors: Record<string, string[]>;\n input: Input<T>;\n }> {\n const input = await this.parseBody();\n try {\n return {\n isValid: true,\n errors: {},\n input: this.validateInput(input),\n };\n } catch (err) {\n if (!(err instanceof ValidationError)) {\n throw err;\n }\n return {\n isValid: false,\n errors: err.errors,\n input,\n };\n }\n }\n}\n",
|
|
15
|
-
"import { refusal, RequestBreakerError, stringEraRefusal } from \"./Error\";\nimport { formatUnsatisfiedContentRange } from \"./range\";\n\nexport class AuthorizationError extends RequestBreakerError {\n private error: string;\n constructor(error: string = \"Not authorized\") {\n super(error);\n this.name = \"AuthorizationError\";\n this.error = error;\n this.payload = {\n api: {\n status: 401,\n data: { error: stringEraRefusal(\"authorization\", this.error, 401) },\n },\n view: {},\n };\n }\n}\n\n/**\n * A signed-in user who is not allowed to do this. Thrown by `Auth.guard()`.\n *\n * 403, not 401: a 401 tells the client to re-authenticate, so a client that\n * sends a 401 to the sign-in page would loop a signed-in user without the role\n * straight back to where they started. A request with no user at all is\n * `AuthenticationError`, which stays 401.\n */\nexport class InsufficientPermissionsError extends RequestBreakerError {\n /**\n * The status of `payload.api`, which answers API routes and `.json` view\n * navigations alike. Before 0.63 it was 401, and a shipped native client may\n * still branch on that — it cannot be rolled forward in the same deploy as\n * the server. Such an app sets this back to 401 once at boot, and removes the\n * line when its clients handle 403:\n *\n * ```ts\n * InsufficientPermissionsError.apiStatus = 401;\n * ```\n *\n * A full page load answers 403 either way; before 0.63 it fell through to\n * the view dispatcher's 400 default, which no client could have relied on.\n */\n static apiStatus: 401 | 403 = 403;\n\n private error: string;\n constructor(error: string = \"Insufficient permissions\") {\n super(error);\n this.name = \"InsufficientPermissionsError\";\n this.error = error;\n this.payload = {\n api: {\n status: InsufficientPermissionsError.apiStatus,\n data: {\n error: stringEraRefusal(\"permission\", this.error, InsufficientPermissionsError.apiStatus),\n },\n },\n // Without a status a view request would fall through to the\n // dispatcher's 400 default.\n view: { status: 403 },\n };\n }\n}\n\n/**\n * A `Range` that cannot be satisfied against the object's current size.\n *\n * Extends `RequestBreakerError` so a bare `FileStorage.read()` inside an\n * ordinary route still produces a correct 416 — and, importantly, so it does\n * not trip `onRequestFail`. A 416 is the client's header being wrong about the\n * object, not a server failure.\n */\nexport class RangeNotSatisfiableError extends RequestBreakerError {\n constructor(public total: number) {\n super(\"Range not satisfiable\");\n this.name = \"RangeNotSatisfiableError\";\n this.payload = {\n api: {\n status: 416,\n data: { error: refusal(\"range_not_satisfiable\", \"Range not satisfiable\", 416) },\n headers: {\n \"Content-Range\": formatUnsatisfiedContentRange(total),\n \"Accept-Ranges\": \"bytes\",\n // Decided by the client's own Range against the object's current\n // length, so it must never be replayed from a cache to a request\n // that did not ask for that window.\n \"Cache-Control\": \"no-store\",\n },\n },\n view: {},\n };\n }\n}\n\nexport class FileNotFoundError extends RequestBreakerError {\n constructor(public fileName: string) {\n super(\"File not found\");\n this.name = \"FileNotFoundError\";\n this.payload = {\n api: {\n status: 404,\n data: { error: refusal(\"not_found\", \"Not found\", 404) },\n headers: { \"Cache-Control\": \"no-store\" },\n },\n view: {},\n };\n }\n}\n\n/**\n * No signed-in user. A 401 to an API client; a view request is sent to\n * `redirectTo` instead — a 302 for a page load, and a `Redirect` directive for\n * a `.json` navigation, so the client router follows it rather than leaving\n * the previous page on screen.\n *\n * `redirectTo` is the whole location, intended-URL parameter included.\n * `AuthenticationMiddleware` and `Auth.user()` build it from the request and\n * the `auth.signInPath` config; code throwing this by hand can pass its own.\n */\nexport class AuthenticationError extends RequestBreakerError {\n constructor(options: { redirectTo?: string } = {}) {\n super(\"Authentication error\");\n this.name = \"AuthenticationError\";\n const location = options.redirectTo ?? \"/auth/sign-in\";\n this.payload = {\n api: {\n status: 401,\n data: { error: stringEraRefusal(\"authentication\", \"Authentication error\", 401) },\n },\n viewData: {\n status: 200,\n data: {},\n // A refusal is per-visitor, and this one answers 200 so that\n // `loadRoutePayload` reads it at all — which makes it exactly the\n // shape a shared cache would happily store and replay to the next\n // visitor. The `view` payload below says the same thing.\n headers: {\n \"Cache-Control\": \"private, no-cache, no-store, max-age=0, must-revalidate\",\n },\n directive: { kind: \"Redirect\", path: location },\n },\n view: {\n status: 302,\n headers: {\n \"Cache-Control\":\n \"private, no-cache, no-store, max-age=0, must-revalidate\",\n Location: location,\n },\n },\n };\n }\n}\n",
|
|
16
|
-
"import type { ServiceToken } from \"../container/Container\";\nimport { app } from \"../foundation/app\";\n\n/**\n * Base for the facades that front a container binding. A subclass names the\n * service it proxies with `getFacadeAccessor()` and reaches the live instance\n * through `this.getFacadeRoot()`, so the binding is resolved per call against\n * the Application for the current async context — never captured at module\n * load, which is what makes a facade swappable in tests.\n *\n * Two deliberate divergences from `Illuminate\\Support\\Facades\\Facade`:\n *\n * 1. No `__callStatic`. TypeScript has no typed equivalent, and a Proxy would\n * erase the very signatures that make these facades worth having. Subclasses\n * therefore declare explicit statics that forward to `getFacadeRoot()`.\n *\n * 2. `getFacadeAccessor()` is public, not protected. `getFacadeRoot()` types\n * its `this` structurally in order to infer the service type from the\n * accessor's return, and a protected static is not structurally assignable\n * to that.\n *\n * Facades that resolve nothing from the container — Cookie, Redirect, Url,\n * Meta — do not extend this class.\n */\nexport abstract class Facade {\n static getFacadeAccessor(): ServiceToken<any> {\n throw new Error(\n `Facade [${this.name}] does not implement getFacadeAccessor().`,\n );\n }\n\n static getFacadeRoot<T>(this: {\n getFacadeAccessor(): ServiceToken<T>;\n }): T {\n return app(this.getFacadeAccessor());\n }\n}\n",
|
|
17
|
-
"import { FileNotFoundError } from \"../../../http/errors\";\nimport type {\n DeleteFileParams,\n FetchFileOptions,\n IFileStorageDriver,\n PutFileOptions,\n PutFileParams,\n ReadFileParams,\n ReadResult,\n} from \"./types\";\n\nexport abstract class FileStorageDriver implements IFileStorageDriver {\n abstract fetch(\n params: ReadFileParams | string,\n options?: FetchFileOptions,\n ): Promise<Response>;\n abstract put(\n params: PutFileParams | Blob,\n options?: PutFileOptions,\n ): Promise<string>;\n abstract list(folder: string): Promise<any>;\n\n /**\n * Removes an object. A missing object is not an error: the promise resolves,\n * so cleanup can run twice, or after a write that never landed.\n *\n * Not abstract, for the same reason `read()` is not: a custom driver written\n * before `delete()` existed keeps compiling. It must not keep *working* as if\n * it deleted, though — silently resolving here is exactly the bug `delete()`\n * used to have (#608) — so the default throws and names the driver.\n */\n async delete(_params: DeleteFileParams | string): Promise<void> {\n throw new Error(\n `${this.constructor.name} does not implement delete(). Override it to remove objects from this backend.`,\n );\n }\n\n /**\n * Default `read()` for drivers that only implement `fetch()`.\n *\n * Deliberately not abstract: every driver written before `read()` existed\n * keeps compiling and gains working range support for free. It is not\n * *efficient* though — to serve a range it buffers the whole object so the\n * framework can slice it, which saves no bandwidth from the backend. Any\n * driver whose backend can range natively should override this.\n */\n async read(input: ReadFileParams | string): Promise<ReadResult> {\n const params = typeof input === \"string\" ? { name: input } : input;\n const response = await this.fetch({\n name: params.name,\n bucket: params.bucket,\n });\n\n if (!response.ok) {\n throw new FileNotFoundError(params.name);\n }\n\n const type =\n response.headers.get(\"Content-Type\") ?? \"application/octet-stream\";\n const etag = response.headers.get(\"ETag\") ?? undefined;\n const lastModifiedHeader = response.headers.get(\"Last-Modified\");\n const lastModified = lastModifiedHeader\n ? new Date(lastModifiedHeader)\n : undefined;\n\n if (params.range) {\n const blob = await response.blob();\n return {\n body: blob,\n start: 0,\n end: blob.size - 1,\n total: blob.size,\n // The range was not applied by the backend. Reporting `false` hands\n // the slicing to `createStreamResponse`, which has the total in hand.\n partial: false,\n type,\n etag,\n lastModified,\n name: params.name,\n };\n }\n\n const contentLength = Number(response.headers.get(\"Content-Length\"));\n const total = Number.isFinite(contentLength) ? contentLength : 0;\n\n return {\n body: response.body,\n start: 0,\n end: total - 1,\n total,\n partial: false,\n type,\n etag,\n lastModified,\n name: params.name,\n };\n }\n\n /**\n * Total size of an object. Used to resolve suffix ranges on backends without\n * native suffix support, and to report the total on a 416. Override with a\n * HEAD-style request wherever one is available.\n */\n async size(params: ReadFileParams | string): Promise<number> {\n const name = typeof params === \"string\" ? params : params.name;\n const bucket = typeof params === \"string\" ? undefined : params.bucket;\n const response = await this.fetch({ name, bucket });\n if (!response.ok) {\n throw new FileNotFoundError(name);\n }\n const contentLength = Number(response.headers.get(\"Content-Length\"));\n if (Number.isFinite(contentLength)) {\n await response.body?.cancel();\n return contentLength;\n }\n return (await response.blob()).size;\n }\n}\n",
|
|
18
|
-
"/**\n * Ties a response body to an `AbortSignal`, so aborting after `fetch()` has\n * resolved still reaches a caller that is reading the body.\n *\n * Handing the signal to the SDK is not enough on its own: once the headers are\n * back, whether an abort also errors the body stream depends on the SDK and\n * the runtime, and a caller parked in `arrayBuffer()` must not hang. So on\n * abort the returned stream errors with the signal's reason, and the source\n * stream is cancelled, which releases the file handle or the connection.\n *\n * The abort listener is removed once the body finishes, errors or is\n * cancelled, so a long-lived signal (a request's, say) does not collect one\n * listener per read.\n */\nexport function abortableBody(\n body: ReadableStream<Uint8Array>,\n signal: AbortSignal | undefined,\n): ReadableStream<Uint8Array> {\n if (!signal) {\n return body;\n }\n\n const reader = body.getReader();\n let settled = false;\n let onAbort: (() => void) | undefined;\n\n const detach = () => {\n settled = true;\n if (onAbort) {\n signal.removeEventListener(\"abort\", onAbort);\n }\n };\n\n return new ReadableStream<Uint8Array>(\n {\n start(controller) {\n onAbort = () => {\n if (settled) return;\n detach();\n controller.error(signal.reason);\n reader.cancel(signal.reason).catch(() => {});\n };\n if (signal.aborted) {\n onAbort();\n } else {\n signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n },\n async pull(controller) {\n let chunk: Awaited<ReturnType<typeof reader.read>>;\n try {\n chunk = await reader.read();\n } catch (err) {\n if (settled) return;\n detach();\n controller.error(err);\n return;\n }\n // An abort that landed while the read was pending has already\n // errored the stream, and a cancelled reader resolves `done`.\n if (settled) return;\n if (chunk.done) {\n detach();\n controller.close();\n return;\n }\n controller.enqueue(chunk.value);\n },\n cancel(reason) {\n detach();\n return reader.cancel(reason);\n },\n },\n // Pull only on demand, so nothing is read ahead of the consumer.\n { highWaterMark: 0 },\n );\n}\n",
|
|
19
|
-
"import type {\n DeleteFileParams,\n FetchFileOptions,\n PutFileOptions,\n PutFileParams,\n ReadFileParams,\n ReadResult,\n} from \"./types\";\nimport { FileStorageDriver } from \"./FileStorageDriver\";\nimport { abortableBody } from \"./abortableBody\";\nimport { readdir, unlink } from \"fs/promises\";\nimport { isAbsolute, relative, resolve, sep } from \"node:path\";\nimport { resolveRange } from \"../../../http/range\";\nimport { FileNotFoundError, RangeNotSatisfiableError } from \"../../../http/errors\";\nimport { projectRoot } from \"../../../support/discover\";\n\nexport class FileSystemDriver extends FileStorageDriver {\n private readonly configured?: string;\n\n constructor(folderPath?: string) {\n super();\n this.configured = folderPath;\n }\n\n /**\n * Computed per read, not baked into a constructor default.\n *\n * This is the second time this exact bug has been written in this repository,\n * and `LogManager.logsDirPath` carries the first one's post-mortem: a driver\n * is constructed when `app/config/filesystem.ts` is evaluated, and that\n * happens *before* the http layer sets `ROOT_DIR`. So the old default,\n * `` `${process.env.ROOT_DIR}/storage` ``, interpolated `undefined` and froze\n * it — measured, `new FileSystemDriver().folderPath` was `\"undefined/storage\"`\n * with `ROOT_DIR` unset, and stayed `\"undefined/storage\"` after the server set\n * it a moment later.\n *\n * It fails quietly, which is what makes it worth a comment rather than a\n * one-line fix: reads and writes both used the same wrong folder, so nothing\n * threw and nothing 404'd. Files simply accumulated in a stray `undefined/`\n * directory beside the project, and the only way to notice was to look.\n *\n * `projectRoot()` is the same rule `httpProd` computes `ROOT_DIR` from, so an\n * explicit folder still wins and an app that configured nothing now gets the\n * directory it always meant.\n */\n private get folderPath(): string {\n return this.configured ?? `${projectRoot()}/storage`;\n }\n\n async put(params: PutFileParams | Blob, { signal }: PutFileOptions = {}) {\n signal?.throwIfAborted();\n\n let body: Blob | File | Buffer;\n let name: string;\n\n if (params instanceof Blob) {\n body = params;\n name = `${Bun.randomUUIDv7()}.${params.type.split(\"/\")[1].split(\";\")[0]}`;\n } else {\n body = params.body;\n name = params.name;\n }\n\n const buffer =\n body instanceof Buffer\n ? body\n : body instanceof Blob || body instanceof File\n ? Buffer.from(await body.arrayBuffer())\n : \"\";\n\n const path = `${this.folderPath}/${name}`;\n\n // `Bun.write` takes no signal, and a local write is not worth interrupting\n // halfway, so the last chance to abort is once the body has been read.\n signal?.throwIfAborted();\n await Bun.write(path, buffer as any);\n\n return name;\n }\n\n async fetch(\n params: ReadFileParams | string,\n { signal }: FetchFileOptions = {},\n ) {\n signal?.throwIfAborted();\n\n let bucket = process.env.BUCKET_NAME;\n let name: string | undefined;\n\n if (typeof params === \"string\") {\n name = params;\n } else {\n bucket = params.bucket ?? bucket;\n name = params.name;\n }\n\n if (!name) {\n throw new Error(\"Object name has to be specified\");\n }\n\n const path = `${this.folderPath}/${name}`;\n const file = Bun.file(path);\n // The disk read has no signal of its own. The body is wrapped instead, so\n // an abort stops the stream and closes the file mid-read.\n const result = abortableBody(Bun.file(path).stream(), signal);\n const date = new Date(file.lastModified).toUTCString();\n\n return new Response(result, {\n headers: {\n \"Content-Type\": file.type,\n \"Content-Length\": String(file.size),\n \"Cache-Control\": \"private, max-age=12000, must-revalidate\",\n // TODO: fix this.\n \"Last-Modified\": date,\n },\n });\n }\n\n async read(input: ReadFileParams | string): Promise<ReadResult> {\n const params = typeof input === \"string\" ? { name: input } : input;\n const { name, range = null } = params;\n\n if (!name) {\n throw new Error(\"Object name has to be specified\");\n }\n\n const file = Bun.file(`${this.folderPath}/${name}`);\n\n // `Bun.file()` is lazy. Without this the response commits with a 200 and\n // the ENOENT only surfaces once the stream is pulled, as an unhandled\n // rejection with the status already on the wire.\n if (!(await file.exists())) {\n throw new FileNotFoundError(name);\n }\n\n const total = file.size;\n const resolved = range ? resolveRange(range, total) : null;\n\n if (range && !resolved) {\n throw new RangeNotSatisfiableError(total);\n }\n\n const start = resolved?.start ?? 0;\n const end = resolved ? resolved.end : total - 1;\n\n return {\n // A BunFile slice stays lazy and keeps a known size, so Bun can send it\n // with a real Content-Length instead of falling back to chunked.\n body: resolved ? file.slice(start, end + 1) : file,\n start,\n end,\n total,\n partial: Boolean(resolved),\n type: file.type || \"application/octet-stream\",\n lastModified: new Date(file.lastModified),\n name,\n };\n }\n\n async size(params: ReadFileParams | string) {\n const name = typeof params === \"string\" ? params : params.name;\n const file = Bun.file(`${this.folderPath}/${name}`);\n if (!(await file.exists())) {\n throw new FileNotFoundError(name);\n }\n return file.size;\n }\n\n async delete(params: DeleteFileParams | string) {\n const name = typeof params === \"string\" ? params : params.name;\n\n if (!name) {\n throw new Error(\"Object name has to be specified\");\n }\n\n // A bucket key cannot climb out of its bucket, but a path can: refuse a\n // name that resolves outside the storage folder rather than unlink it.\n const root = resolve(this.folderPath);\n const path = resolve(root, name);\n const rel = relative(root, path);\n if (!rel || rel === \"..\" || rel.startsWith(`..${sep}`) || isAbsolute(rel)) {\n throw new Error(`Refusing to delete \"${name}\": it is outside the storage folder`);\n }\n\n try {\n await unlink(path);\n } catch (err: any) {\n // Already gone is the outcome the caller asked for.\n if (err?.code === \"ENOENT\") {\n return;\n }\n throw err;\n }\n }\n\n async list() {\n const files = await readdir(this.folderPath);\n\n return files;\n }\n}\n",
|
|
20
|
-
"import type { FileStorageDriver } from \"./drivers/FileStorageDriver\";\nimport { FileSystemDriver } from \"./drivers/FileSystemDriver\";\n\n// Config key: `filesystem`. Derived from `FileStorageServiceProvider`.\nexport interface FilesystemConfig {\n driver?: FileStorageDriver;\n}\n\nexport function defineFilesystemConfig(\n config: FilesystemConfig,\n): FilesystemConfig {\n return config;\n}\n\nexport function filesystemConfigDefaults(): Required<FilesystemConfig> {\n return {\n driver: new FileSystemDriver(),\n };\n}\n",
|
|
21
|
-
"import type { FileStorageDriver } from \"./drivers/FileStorageDriver\";\nimport { filesystemConfigDefaults, type FilesystemConfig } from \"./config\";\n\nexport class FilesystemManager {\n static token = \"filesystem\";\n\n readonly driver: FileStorageDriver;\n\n constructor(config: FilesystemConfig = {}) {\n this.driver = config.driver ?? filesystemConfigDefaults().driver;\n }\n}\n",
|
|
22
|
-
"//@ts-ignore - type-only; the module itself is loaded on first use by `metadata()`.\nimport type sharp from \"sharp\";\n\nimport { Buffer } from \"node:buffer\";\nimport { loadSharp } from \"../support/sharp\";\nimport type { Prettify } from \"../utils/type\";\n\nimport { RequestContext } from \"../http/requestContext\";\nimport type { ByteRange } from \"../http/range\";\nimport type {\n DeleteFileParams,\n FetchFileOptions,\n PutFileOptions,\n PutFileParams,\n ReadFileParams,\n ReadResult,\n} from \"../services/file-storage/drivers/types\";\nimport { FilesystemManager } from \"../services/file-storage/FilesystemManager\";\nimport { Facade } from \"./Facade\";\n\ntype Metadata = Prettify<sharp.Metadata>;\n\nexport class Storage extends Facade {\n static getFacadeAccessor() {\n return FilesystemManager;\n }\n\n /**\n * Stores a file and returns its object name. Pass `{ signal }` to cancel the\n * upload, e.g. with the incoming request's signal or `AbortSignal.timeout()`.\n */\n static async put(params: PutFileParams | Blob, options: PutFileOptions = {}) {\n return this.getFacadeRoot().driver.put(params, options);\n }\n\n static async metadata(obj: Blob | File): Promise<Partial<Metadata>> {\n const buffer = Buffer.from(await obj.arrayBuffer());\n // Outside the catch: the empty object below means \"this blob is not an\n // image sharp can read\", and a missing `sharp` install must not be able to\n // hide behind it.\n const sharp = await loadSharp(\"Storage.metadata()\");\n try {\n return await sharp(buffer).metadata();\n } catch {\n return {};\n }\n }\n\n /**\n * Reads an object as a streamed `Response`. Pass `{ signal }` to cancel the\n * read, e.g. with the incoming request's signal or `AbortSignal.timeout()`:\n * an abort rejects `fetch()` itself, or errors the body if it lands after\n * `fetch()` resolved.\n */\n static async fetch(\n params: ReadFileParams | string,\n options: FetchFileOptions = {},\n ) {\n // Checked here too, so a custom driver that predates the option still\n // refuses an already-aborted read.\n options.signal?.throwIfAborted();\n return this.getFacadeRoot().driver.fetch(params, options);\n }\n\n /**\n * Reads an object as bytes plus metadata, pushing any byte range down to the\n * storage backend so a seek transfers one window rather than the whole file.\n *\n * The range is resolved in this order: an explicit `options.range`, then a\n * `range` on `params`, then the in-flight request's `Range` header when this\n * is called inside a `this.stream()` route. Pass `{ range: null }` to force a\n * full read inside a stream route.\n */\n static async read(\n params: ReadFileParams | string,\n options: { range?: ByteRange | null } = {},\n ): Promise<ReadResult> {\n const base: ReadFileParams =\n typeof params === \"string\" ? { name: params } : { ...params };\n\n const range =\n \"range\" in options\n ? (options.range ?? null)\n : base.range !== undefined\n ? base.range\n : (RequestContext.getStore()?.rangeRequest ?? null);\n\n return this.getFacadeRoot().driver.read({\n ...base,\n range,\n });\n }\n static list(folder: string) {\n return this.getFacadeRoot().driver.list(folder);\n }\n\n /**\n * Removes a stored object. Deleting one that does not exist resolves without\n * throwing, so a cleanup path can retry safely.\n */\n static async delete(params: DeleteFileParams | string): Promise<void> {\n return this.getFacadeRoot().driver.delete(params);\n }\n}\n",
|
|
23
|
-
"// @ts-ignore - `sharp` is a peer dependency; only its types are wanted here.\nimport type sharpNamespace from \"sharp\";\n\n/**\n * `sharp`, imported on first use rather than at module load.\n *\n * Three modules need it — the `Sharp` optimization driver, the `Storage` facade\n * and the OG-image branch of `ViewRouteDispatcher` — and all three are reachable\n * from the `gemi/services` and `gemi/facades` barrels, which are also the only\n * door an application has to `CronJob`, `Job`, `DB` and `Lang`. A static import\n * made every one of those imports load a native binary (#403).\n *\n * `sharp` is the only one of the four that can be genuinely absent — it is a\n * peer dependency, so an install can skip its platform binary — which is why\n * the failure gets a message naming the caller rather than a bare resolution\n * error. `usedBy` is that name, written as the caller reads in a stack trace.\n *\n * No memo: the module registry already caches a resolved `import()`, and\n * caching the *failure* would make every later call report the first call's\n * stack instead of its own.\n */\nexport async function loadSharp(usedBy: string): Promise<typeof sharpNamespace> {\n try {\n // @ts-ignore - peer dependency, resolved out of the application's own tree\n return (await import(\"sharp\")).default;\n } catch (error) {\n throw new Error(\n `${usedBy} requires the 'sharp' package. Install it with \\`bun add sharp\\`.`,\n { cause: error },\n );\n }\n}\n",
|
|
24
|
-
"import type { FileSink } from \"bun\";\nimport { mkdir, readdir, access } from \"fs/promises\";\n\nasync function exists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\nimport { RequestContext } from \"../../http/requestContext\";\nimport { projectRoot } from \"../../support/discover\";\nimport type { LogConfig } from \"./config\";\nimport type { LogEntry, LogLevel } from \"./types\";\n\nexport class LogManager {\n static token = \"log\";\n\n writer: FileSink;\n isReady: boolean = false;\n\n private flushTimeout: Timer;\n private fileSize: number = 0;\n private writerSize: number = 0;\n private isCreatingFile: boolean = false;\n private bootPromise: Promise<void> | null = null;\n public currentLogFilePath: string;\n\n /**\n * Computed per read, not once in the constructor: `Server.start` awaits\n * `waitForBoot()` — where `LogServiceProvider.boot()` builds this directory —\n * and only *then* imports the http layer that sets `ROOT_DIR`. A field\n * initializer (or any `process.env.ROOT_DIR` read here) resolves to\n * `undefined/storage/logs` at boot, which is how every `Log.info()` ended up\n * throwing on an undefined writer. `projectRoot()` is the same rule\n * `httpProd` sets `ROOT_DIR` from, a moment later.\n */\n private get logsDirPath(): string {\n return `${projectRoot()}/storage/logs`;\n }\n\n constructor(public config: Required<LogConfig>) {}\n\n /**\n * Idempotent. `LogServiceProvider.boot()` calls this so the storage\n * directory exists before the first request; a lazy first `log()` triggers\n * it too, so the manager still works when it is resolved on its own.\n */\n boot(): Promise<void> {\n if (!this.bootPromise) {\n this.bootPromise = this.createStorage()\n .catch((err) => {\n // A logger that rejects turns every `Log.info()` into the caller's\n // error. Report the storage failure once and carry on without a file\n // sink — `log()` still feeds `onLogCreated`.\n console.error(\"Log storage unavailable, file logging disabled\", err);\n })\n .then(() => {\n this.isReady = true;\n });\n }\n return this.bootPromise;\n }\n\n private async createStorage() {\n const storageDirPath = `${projectRoot()}/storage`;\n if (!(await exists(storageDirPath))) {\n await mkdir(storageDirPath);\n }\n if (!(await exists(this.logsDirPath))) {\n await mkdir(this.logsDirPath);\n }\n await this.newLogFile();\n }\n\n async newLogFile() {\n if (!(await exists(this.logsDirPath))) {\n await mkdir(this.logsDirPath);\n }\n this.isCreatingFile = true;\n if (this.currentLogFilePath) {\n this.writer.flush();\n this.writer.end();\n this.writer = null;\n const file = new File(\n [await Bun.file(this.currentLogFilePath).arrayBuffer()],\n this.currentLogFilePath.split(\"/\").pop(),\n { type: \"text/plain\" },\n );\n this.config.onLogFileClosed(file);\n this.fileSize = 0;\n this.writerSize = 0;\n }\n\n const logFiles = await readdir(this.logsDirPath);\n\n const lastLogFile = logFiles.sort().reverse()[0];\n\n if (lastLogFile) {\n const _file = Bun.file(`${this.logsDirPath}/${lastLogFile}`);\n if (_file.size < this.config.maxFileSize) {\n this.currentLogFilePath = `${this.logsDirPath}/${lastLogFile}`;\n\n this.writer = _file.writer();\n this.writer.write(await _file.text());\n this.writer.write(\"\\n\");\n this.writer.flush();\n this.fileSize = _file.size;\n }\n }\n\n if (!this.writer) {\n const logFileName =\n `${new Date(Date.now()).toISOString()}.log`.replaceAll(\":\", \"-\");\n this.currentLogFilePath = `${this.logsDirPath}/${logFileName}`;\n const file = Bun.file(`${this.logsDirPath}/${logFileName}`);\n this.writer = file.writer();\n this.fileSize = 0;\n this.writerSize = 0;\n }\n this.isCreatingFile = false;\n }\n\n async log(\n level: LogLevel,\n message: string,\n metadata: Record<string, any> = {},\n ) {\n if (!this.isReady) {\n await this.boot();\n }\n\n const reqCtx = RequestContext.getStore();\n let requestMetadata = {};\n if (reqCtx) {\n requestMetadata = {\n url: reqCtx.req.rawRequest.url,\n method: reqCtx.req.rawRequest.method,\n headers: reqCtx.req.rawRequest.headers,\n body: reqCtx.req.rawRequest.body,\n };\n }\n\n const logObject: LogEntry = {\n timestamp: new Date(Date.now()).toISOString(),\n env: process.env.NODE_ENV,\n level,\n message,\n metadata: { ...requestMetadata, ...metadata },\n };\n\n let log = \"\";\n try {\n log = JSON.stringify(logObject);\n } catch (err) {\n console.log(\"Error parsing log object\", err);\n }\n // Contained, because this is an app-supplied hook and every facade method\n // calls `log()` without awaiting it: a hook that throws would otherwise\n // leave a floating `Log.info()` as an unhandled rejection, which is the\n // failure this method exists to not have. A rejected promise from an async\n // hook is the same thing arriving later, so it is caught too — what is not\n // done is *awaiting* it, which would put the app's transport in front of\n // the file write.\n try {\n const handled = this.config.onLogCreated(logObject);\n if (handled instanceof Promise) {\n handled.catch((err) => console.error(\"Error in onLogCreated\", err));\n }\n } catch (err) {\n console.error(\"Error in onLogCreated\", err);\n }\n\n // No writer means `createStorage` failed (or a rotation is mid-flight);\n // either way the entry has already been handed to `onLogCreated`, so drop\n // the file copy rather than throwing at the call site.\n if (!this.writer) {\n return;\n }\n\n this.writerSize += log.length;\n this.fileSize += log.length;\n\n try {\n this.writer.write(log);\n this.writer.write(\"\\n\");\n this.tryFlush();\n } catch (err) {\n console.error(\"Error writing log\", err);\n // Do something\n }\n }\n\n async tryFlush() {\n if (this.fileSize > this.config.maxFileSize) {\n if (!this.isCreatingFile) {\n await this.newLogFile();\n }\n }\n if (this.writerSize > this.config.maxFileSize / 2) {\n await this.writer.flush();\n this.writerSize = 0;\n await this.newLogFile();\n } else {\n clearTimeout(this.flushTimeout);\n this.flushTimeout = setTimeout(async () => {\n await this.writer.flush();\n this.writerSize = 0;\n }, 100);\n }\n }\n}\n",
|
|
25
|
-
"import { LogManager } from \"../services/logging/LogManager\";\nimport { Facade } from \"./Facade\";\n\nexport class Log extends Facade {\n static getFacadeAccessor() {\n return LogManager;\n }\n\n static debug(message: string, metadata?: Record<string, any>) {\n this.getFacadeRoot().log(\"debug\", message, metadata);\n }\n\n static info(message: string, metadata?: Record<string, any>) {\n this.getFacadeRoot().log(\"info\", message, metadata);\n }\n\n static notice(message: string, metadata?: Record<string, any>) {\n this.getFacadeRoot().log(\"notice\", message, metadata);\n }\n\n static warning(message: string, metadata?: Record<string, any>) {\n this.getFacadeRoot().log(\"warning\", message, metadata);\n }\n\n static error(message: string, metadata?: Record<string, any>) {\n this.getFacadeRoot().log(\"error\", message, metadata);\n }\n\n static critical(message: string, metadata?: Record<string, any>) {\n this.getFacadeRoot().log(\"critical\", message, metadata);\n }\n\n static alert(message: string, metadata?: Record<string, any>) {\n this.getFacadeRoot().log(\"alert\", message, metadata);\n }\n\n static emergency(message: string, metadata?: Record<string, any>) {\n this.getFacadeRoot().log(\"emergency\", message, metadata);\n }\n}\n",
|
|
26
|
-
"import type { RedisClient, RedisOptions } from \"bun\";\nimport type { RedisConfig } from \"./config\";\n\n/**\n * The constructor `Bun.RedisClient` is, described structurally.\n *\n * Reached through the `Bun` global rather than `import { RedisClient } from\n * \"bun\"`, which is what this module used to do. That was a **value** import of\n * a specifier only the Bun runtime can resolve, and this class is re-exported\n * from `gemi/services` and reached from `gemi/facades` through the `Redis`\n * facade — the two barrels that are also the only door to `CronJob`, `Job`,\n * `DB` and `Lang`. So the specifier landed in the graph of every app and every\n * test that imported either one, and under a browser-targeted runner the whole\n * barrel simply failed to resolve (#396, #403).\n *\n * The global carries no specifier for a bundler or a test runner to resolve, so\n * the cost is paid only by code that actually asks for a client.\n */\ntype RedisClientConstructor = new (\n url?: string,\n options?: RedisOptions,\n) => RedisClient;\n\nexport class RedisManager {\n static token = \"redis\";\n\n private instance: RedisClient | null = null;\n\n constructor(public config: RedisConfig = {}) {}\n\n /**\n * Bun's Redis client. Built on first access and memoized.\n *\n * It connects lazily on the first command, so building it here is safe even\n * when Redis isn't running or configured — nothing connects until something\n * actually issues a command.\n */\n get client(): RedisClient {\n return (this.instance ??= new (redisClientConstructor())(\n this.config.url,\n this.config.options,\n ));\n }\n\n /**\n * `client` was a plain public property before it was a getter, and\n * overwriting a manager's client is how this repo fakes one —\n * `S3Driver.test.ts` does exactly that, and the `S3Driver` half of #403 kept\n * that seam working on purpose. An accessor with no setter would have turned\n * `manager.client = fake` into `TypeError: Attempted to assign to readonly\n * property` instead, which is not a change this was meant to make.\n */\n set client(client: RedisClient) {\n this.instance = client;\n }\n\n /**\n * Closes the client, when one was built; a later `client` builds a new one.\n * Does not build one to close it.\n */\n close(): void {\n const client = this.instance;\n this.instance = null;\n client?.close();\n }\n}\n\nfunction redisClientConstructor(): RedisClientConstructor {\n const ctor = (globalThis as any).Bun?.RedisClient as\n | RedisClientConstructor\n | undefined;\n\n if (typeof ctor !== \"function\") {\n throw new Error(\n \"Redis requires Bun's built-in Redis client, which this runtime does not provide. Run the app under Bun, or bind your own client for the 'redis' token.\",\n );\n }\n\n return ctor;\n}\n"
|
|
27
|
-
],
|
|
28
|
-
"mappings": "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",
|
|
29
|
-
"debugId": "369AC27CA155427064756E2164756E21",
|
|
30
|
-
"names": []
|
|
31
|
-
}
|