system-one 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Luke Ramsden
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,172 @@
1
+ # system-one
2
+
3
+ Typed decisions from System-1-style models — TypeSafe **Jev** (directly or via **Cloudflare AI Gateway**) and **Laya** (via a bridge you run) — with a plain Promise client and an **Effect-native** service that share one set of question definitions.
4
+
5
+ `system-one` is a decision API, not a chat SDK. You send **state** and **typed questions**; you get back **typed answers with probabilities**; your code decides what to do. The library never invents a probability, a threshold, a selected level, or a model version it was not given.
6
+
7
+ ```
8
+ pnpm add system-one # Promise API, zero runtime deps
9
+ pnpm add effect @effect/platform # optional, only for system-one/effect
10
+ ```
11
+
12
+ Node ≥ 22.18, ESM only.
13
+
14
+ ## Define questions once
15
+
16
+ ```ts
17
+ import { Question, defineQuestions } from "system-one";
18
+
19
+ const triage = defineQuestions({
20
+ urgent: Question.boolean({
21
+ instructions: "Does this need urgent attention?",
22
+ criteria: { true: "Time-sensitive harm or an ongoing outage", false: "Routine request" },
23
+ }),
24
+ department: Question.choice({
25
+ instructions: "Which department should handle this?",
26
+ options: {
27
+ billing: "Payments, refunds, invoices",
28
+ technical: "Bugs, outages",
29
+ sales: "Pricing",
30
+ },
31
+ }),
32
+ frustration: Question.ordinal({
33
+ instructions: "How frustrated is the customer?",
34
+ levels: ["Calm", "Frustrated", "Very angry"],
35
+ }),
36
+ });
37
+ ```
38
+
39
+ Definitions are validated, deep-copied, and frozen. Literal keys are preserved: `answers.department.value` is `"billing" | "technical" | "sales"`.
40
+
41
+ ## Promise API
42
+
43
+ ```ts
44
+ import { createClient } from "system-one";
45
+ import { jev } from "system-one/adapters/typesafe";
46
+
47
+ const client = createClient({
48
+ model: jev({ apiKey: process.env.TYPESAFE_API_KEY!, model: "jev-1.13.0" }),
49
+ });
50
+
51
+ const result = await client.evaluate(
52
+ { state: { message: "My payouts have failed for three days!" }, questions: triage },
53
+ { signal: controller.signal, timeoutMs: 10_000 }, // both optional
54
+ );
55
+
56
+ result.answers.department.value; // "billing" | "technical" | "sales"
57
+ result.answers.department.probabilities; // { billing: 0.87, technical: 0.13, sales: 0 } | undefined
58
+ result.answers.urgent.probabilityTrue; // 0.95 | undefined — you pick the threshold
59
+ result.answers.frustration.expectedIndex; // 1.04 — a position on your scale, NOT a selected level
60
+ result.model; // { adapter: "typesafe", requestedModel: "jev-1.13.0", resolvedModel: "jev-1.13.0" }
61
+ result.usage; // { inputTokens: 426, outputTokens: 73 } | undefined
62
+ ```
63
+
64
+ Need distributions guaranteed? Ask, and the type tightens:
65
+
66
+ ```ts
67
+ const r = await client.evaluate({
68
+ state,
69
+ questions: triage,
70
+ requirements: { probabilities: "required" },
71
+ });
72
+ r.answers.urgent.probabilityTrue; // number (not number | undefined)
73
+ ```
74
+
75
+ If the adapter cannot deliver that, you get `UnsupportedCapability` **before** any network call.
76
+
77
+ One attempt per `evaluate`, no hidden retries, redirects refused. Cancellation via `AbortSignal` reaches the HTTP request.
78
+
79
+ ## Effect API
80
+
81
+ ```ts
82
+ import { Effect } from "effect";
83
+ import { FetchHttpClient } from "@effect/platform";
84
+ import { System1, layer } from "system-one/effect";
85
+ import { jev } from "system-one/adapters/typesafe";
86
+
87
+ const program = Effect.gen(function* () {
88
+ const system1 = yield* System1;
89
+ return yield* system1.evaluate({ state: { message: "…" }, questions: triage });
90
+ });
91
+
92
+ const runnable = program.pipe(
93
+ Effect.provide(layer(jev({ apiKey: "…" }))),
94
+ Effect.provide(FetchHttpClient.layer), // or any HttpClient — tests inject their own
95
+ );
96
+ ```
97
+
98
+ - Lazy; interruption cancels the in-flight HTTP request.
99
+ - `System1Error` in the error channel; adapter bugs stay defects.
100
+ - Span `system1.evaluate` with `system1.adapter` / `system1.model` attributes.
101
+ - `testLayer({ capabilities, evaluate })` for fixtures — still runs full validation, so tests cannot make invalid shapes look typed.
102
+
103
+ Swap the model by swapping the layer; the program does not change.
104
+
105
+ ## Adapters
106
+
107
+ | Import | Constructor | Notes |
108
+ | -------------------------------- | ------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
109
+ | `system-one/adapters/typesafe` | `jev({ apiKey, model?: "jev-latest", endpoint? })` | Direct `POST https://api.typesafe.ai/v1/systemone`. Confidence definition `typesafe:distribution-confidence`. |
110
+ | `system-one/adapters/cloudflare` | `cloudflare({ accountId, apiToken, gatewayId?, model?: "typesafe/jev" })` | Universal `POST …/ai/run` envelope; `gatewayId` → `cf-aig-gateway-id`. Token needs **Workers AI** permission. Classifies code `2021` (no credits/BYOK) as `QuotaExceeded`. **Routing verified; a funded success response has not been observed yet** — see [specs](specs/2026-09-19-cloudflare-route-status.md). |
111
+ | `system-one/adapters/laya` | `laya({ endpoint, model, apiKey? })` | Talks to **your own bridge** speaking the `system1-laya-v1` contract around `laya.predict()`. There is no public Laya HTTP API — see [specs](specs/2026-09-19-laya-bridge-contract.md). |
112
+
113
+ All endpoints must be HTTPS (HTTP allowed on loopback only). Credentials live in closures; `JSON.stringify(adapter)` never contains them.
114
+
115
+ Write your own: [docs/writing-an-adapter.md](docs/writing-an-adapter.md).
116
+
117
+ ## Errors
118
+
119
+ Everything operational is a `System1Error` with a `_tag`:
120
+
121
+ | `_tag` | When |
122
+ | ----------------------- | --------------------------------------------------------- |
123
+ | `InvalidRequest` | bad state/definitions/requirements, or provider 400/422 |
124
+ | `UnsupportedCapability` | adapter cannot meet the requested contract |
125
+ | `AuthenticationError` | 401/403, Cloudflare `10000` |
126
+ | `QuotaExceeded` | 402, Cloudflare `2021` |
127
+ | `RateLimited` | 429/529 — `details.retryAfterMs` when the header is valid |
128
+ | `ContextLimitExceeded` | 413 |
129
+ | `TransportError` | fetch failure or timeout (fixed message, no leak) |
130
+ | `InvalidResponse` | provider output violates the answer contract |
131
+ | `ProviderError` | anything else upstream |
132
+
133
+ Messages are fixed strings; `details` never contains headers, bodies, state, or tokens. Low confidence is a **result**, not an error. Retries are yours to compose (e.g. `Effect.retry` keyed on `_tag`) — repeating inference can be billed again.
134
+
135
+ ## What it deliberately does not do
136
+
137
+ No chat, streaming, tool calling, batching, caching, routing, or LLM fallback. No truncation, question dropping, or request splitting. No calibration guarantee. No label→probability or probability→label conversion. No cross-provider confidence normalisation. Details: [docs/semantics.md](docs/semantics.md).
138
+
139
+ ## Repository
140
+
141
+ ```
142
+ packages/system1 the published package
143
+ examples/triage runnable example: same questions through Promise and Effect (`pnpm example`)
144
+ docs/ writing-an-adapter.md, semantics.md, snippets.ts (type-checked)
145
+ specs/ dated design decisions (YYYY-MM-DD-*.md)
146
+ scripts/smoke.mjs packs the tarball and imports it from a fresh consumer, with and without Effect
147
+ ```
148
+
149
+ ```
150
+ pnpm install
151
+ pnpm verify # check + typecheck + test + build + example + smoke
152
+ ```
153
+
154
+ ### Publishing
155
+
156
+ Releases are tag-driven via [`.github/workflows/publish.yml`](.github/workflows/publish.yml). From a clean, green `master`:
157
+
158
+ ```
159
+ # 1. bump packages/system1/package.json version and add a CHANGELOG.md entry, commit
160
+ # 2. tag with the same semver, prefixed v
161
+ git tag v0.1.0 && git push origin master v0.1.0
162
+ ```
163
+
164
+ The workflow checks the tag matches `package.json`, runs `pnpm verify`, publishes `system-one` to npm with provenance (pre-release tags → `next` dist-tag), and creates a GitHub Release from the matching CHANGELOG section.
165
+
166
+ Auth is npm **trusted publishing** (OIDC; configure the repo/workflow as a trusted publisher on npmjs.com), or a repository secret `NPM_TOKEN` as fallback.
167
+
168
+ ### Live checks
169
+
170
+ Tests are offline. Live inference against TypeSafe (needs `TYPESAFE_API_KEY`) and Cloudflare (needs Unified Billing credits or a BYOK key) has **not** been run in this repository and is tracked as blocked, not passed.
171
+
172
+ MIT © Luke Ramsden
@@ -0,0 +1,30 @@
1
+ import { a as Capabilities, d as EvaluationRequest, l as DecodedEvaluation } from "./core-DwacbzM7.mjs";
2
+ //#region src/adapter.d.ts
3
+ interface PreparedRequest {
4
+ readonly url: string;
5
+ readonly method: "POST";
6
+ readonly headers: Readonly<Record<string, string>>;
7
+ readonly body: string;
8
+ }
9
+ interface ReceivedResponse {
10
+ readonly status: number;
11
+ readonly headers: Readonly<Record<string, string>>;
12
+ readonly body: unknown;
13
+ }
14
+ /** Trusted adapter code may throw System1Error; unexpected exceptions remain defects. */
15
+ interface ModelProtocol {
16
+ readonly id: string;
17
+ readonly model: string;
18
+ readonly capabilities: Capabilities;
19
+ encode(request: EvaluationRequest): PreparedRequest;
20
+ decode(response: ReceivedResponse, request: EvaluationRequest): DecodedEvaluation;
21
+ }
22
+ declare function defineAdapter(protocol: ModelProtocol): ModelProtocol;
23
+ /** Sanitized generic HTTP classification. Adapters may classify documented provider codes first. */
24
+ declare function checkHttp(response: ReceivedResponse): void;
25
+ /** Reject accidental credential forwarding through redirects and non-HTTP URLs. */
26
+ declare function endpoint(value: string): string;
27
+ declare function bearer(value: string): string;
28
+ //#endregion
29
+ export { checkHttp as a, bearer as i, PreparedRequest as n, defineAdapter as o, ReceivedResponse as r, endpoint as s, ModelProtocol as t };
30
+ //# sourceMappingURL=adapter-DndZN8Se.d.mts.map
@@ -0,0 +1,3 @@
1
+ import { E as record, a as Capabilities, d as EvaluationRequest, j as System1Error, l as DecodedEvaluation } from "./core-DwacbzM7.mjs";
2
+ import { a as checkHttp, i as bearer, n as PreparedRequest, o as defineAdapter, r as ReceivedResponse, s as endpoint, t as ModelProtocol } from "./adapter-DndZN8Se.mjs";
3
+ export { type Capabilities, type DecodedEvaluation, type EvaluationRequest, ModelProtocol, PreparedRequest, ReceivedResponse, System1Error, bearer, checkHttp, defineAdapter, endpoint, record };
@@ -0,0 +1,43 @@
1
+ import { l as System1Error, o as record } from "./core-D7i-WVU7.mjs";
2
+ //#region src/adapter.ts
3
+ function defineAdapter(protocol) {
4
+ if (!protocol.id.trim() || !protocol.model.trim()) throw new System1Error("InvalidRequest", "Adapter and model identifiers are required");
5
+ return Object.freeze(protocol);
6
+ }
7
+ /** Sanitized generic HTTP classification. Adapters may classify documented provider codes first. */
8
+ function checkHttp(response) {
9
+ const { status, headers } = response;
10
+ if (status >= 200 && status < 300) return;
11
+ const retry = headers["retry-after"];
12
+ const seconds = retry === void 0 ? NaN : Number(retry);
13
+ const delay = retry === void 0 ? NaN : Number.isFinite(seconds) ? seconds * 1e3 : Date.parse(retry) - Date.now();
14
+ const details = {
15
+ status,
16
+ ...Number.isFinite(delay) ? { retryAfterMs: Math.max(0, delay) } : {}
17
+ };
18
+ throw new System1Error(status === 401 || status === 403 ? "AuthenticationError" : status === 402 ? "QuotaExceeded" : status === 429 || status === 529 ? "RateLimited" : status === 413 ? "ContextLimitExceeded" : status === 400 || status === 422 ? "InvalidRequest" : "ProviderError", `Provider returned HTTP ${status}`, details);
19
+ }
20
+ /** Reject accidental credential forwarding through redirects and non-HTTP URLs. */
21
+ function endpoint(value) {
22
+ let url;
23
+ try {
24
+ url = new URL(value);
25
+ } catch {
26
+ throw new System1Error("InvalidRequest", "Invalid endpoint URL");
27
+ }
28
+ if (!["https:", "http:"].includes(url.protocol) || url.username || url.password || url.hash) throw new System1Error("InvalidRequest", "Endpoint must be an HTTP URL without embedded credentials or fragment");
29
+ if (url.protocol === "http:" && ![
30
+ "localhost",
31
+ "127.0.0.1",
32
+ "[::1]"
33
+ ].includes(url.hostname)) throw new System1Error("InvalidRequest", "Use HTTPS except for loopback development servers");
34
+ return url.toString();
35
+ }
36
+ function bearer(value) {
37
+ if (!value.trim() || /[\r\n]/.test(value)) throw new System1Error("AuthenticationError", "A valid API credential is required");
38
+ return `Bearer ${value}`;
39
+ }
40
+ //#endregion
41
+ export { System1Error, bearer, checkHttp, defineAdapter, endpoint, record };
42
+
43
+ //# sourceMappingURL=adapter.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.mjs","names":[],"sources":["../src/adapter.ts"],"sourcesContent":["import type { Capabilities, DecodedEvaluation, EvaluationRequest } from \"./core.js\";\nimport { System1Error } from \"./errors.js\";\nexport type { Capabilities, DecodedEvaluation, EvaluationRequest } from \"./core.js\";\nexport { record } from \"./core.js\";\nexport { System1Error } from \"./errors.js\";\n\nexport interface PreparedRequest {\n readonly url: string;\n readonly method: \"POST\";\n readonly headers: Readonly<Record<string, string>>;\n readonly body: string;\n}\nexport interface ReceivedResponse {\n readonly status: number;\n readonly headers: Readonly<Record<string, string>>;\n readonly body: unknown;\n}\n/** Trusted adapter code may throw System1Error; unexpected exceptions remain defects. */\nexport interface ModelProtocol {\n readonly id: string;\n readonly model: string;\n readonly capabilities: Capabilities;\n encode(request: EvaluationRequest): PreparedRequest;\n decode(response: ReceivedResponse, request: EvaluationRequest): DecodedEvaluation;\n}\nexport function defineAdapter(protocol: ModelProtocol): ModelProtocol {\n if (!protocol.id.trim() || !protocol.model.trim())\n throw new System1Error(\"InvalidRequest\", \"Adapter and model identifiers are required\");\n return Object.freeze(protocol);\n}\n\n/** Sanitized generic HTTP classification. Adapters may classify documented provider codes first. */\nexport function checkHttp(response: ReceivedResponse): void {\n const { status, headers } = response;\n if (status >= 200 && status < 300) return;\n const retry = headers[\"retry-after\"];\n const seconds = retry === undefined ? NaN : Number(retry);\n const delay =\n retry === undefined\n ? NaN\n : Number.isFinite(seconds)\n ? seconds * 1000\n : Date.parse(retry) - Date.now();\n const details = {\n status,\n ...(Number.isFinite(delay) ? { retryAfterMs: Math.max(0, delay) } : {}),\n };\n const tag =\n status === 401 || status === 403\n ? \"AuthenticationError\"\n : status === 402\n ? \"QuotaExceeded\"\n : status === 429 || status === 529\n ? \"RateLimited\"\n : status === 413\n ? \"ContextLimitExceeded\"\n : status === 400 || status === 422\n ? \"InvalidRequest\"\n : \"ProviderError\";\n throw new System1Error(tag, `Provider returned HTTP ${status}`, details);\n}\n\n/** Reject accidental credential forwarding through redirects and non-HTTP URLs. */\nexport function endpoint(value: string): string {\n let url: URL;\n try {\n url = new URL(value);\n } catch {\n throw new System1Error(\"InvalidRequest\", \"Invalid endpoint URL\");\n }\n if (![\"https:\", \"http:\"].includes(url.protocol) || url.username || url.password || url.hash)\n throw new System1Error(\n \"InvalidRequest\",\n \"Endpoint must be an HTTP URL without embedded credentials or fragment\",\n );\n if (url.protocol === \"http:\" && ![\"localhost\", \"127.0.0.1\", \"[::1]\"].includes(url.hostname))\n throw new System1Error(\"InvalidRequest\", \"Use HTTPS except for loopback development servers\");\n return url.toString();\n}\n\nexport function bearer(value: string): string {\n if (!value.trim() || /[\\r\\n]/.test(value))\n throw new System1Error(\"AuthenticationError\", \"A valid API credential is required\");\n return `Bearer ${value}`;\n}\n"],"mappings":";;AAyBA,SAAgB,cAAc,UAAwC;CACpE,IAAI,CAAC,SAAS,GAAG,KAAK,KAAK,CAAC,SAAS,MAAM,KAAK,GAC9C,MAAM,IAAI,aAAa,kBAAkB,4CAA4C;CACvF,OAAO,OAAO,OAAO,QAAQ;AAC/B;;AAGA,SAAgB,UAAU,UAAkC;CAC1D,MAAM,EAAE,QAAQ,YAAY;CAC5B,IAAI,UAAU,OAAO,SAAS,KAAK;CACnC,MAAM,QAAQ,QAAQ;CACtB,MAAM,UAAU,UAAU,KAAA,IAAY,MAAM,OAAO,KAAK;CACxD,MAAM,QACJ,UAAU,KAAA,IACN,MACA,OAAO,SAAS,OAAO,IACrB,UAAU,MACV,KAAK,MAAM,KAAK,IAAI,KAAK,IAAI;CACrC,MAAM,UAAU;EACd;EACA,GAAI,OAAO,SAAS,KAAK,IAAI,EAAE,cAAc,KAAK,IAAI,GAAG,KAAK,EAAE,IAAI,CAAC;CACvE;CAaA,MAAM,IAAI,aAXR,WAAW,OAAO,WAAW,MACzB,wBACA,WAAW,MACT,kBACA,WAAW,OAAO,WAAW,MAC3B,gBACA,WAAW,MACT,yBACA,WAAW,OAAO,WAAW,MAC3B,mBACA,iBACc,0BAA0B,UAAU,OAAO;AACzE;;AAGA,SAAgB,SAAS,OAAuB;CAC9C,IAAI;CACJ,IAAI;EACF,MAAM,IAAI,IAAI,KAAK;CACrB,QAAQ;EACN,MAAM,IAAI,aAAa,kBAAkB,sBAAsB;CACjE;CACA,IAAI,CAAC,CAAC,UAAU,OAAO,CAAC,CAAC,SAAS,IAAI,QAAQ,KAAK,IAAI,YAAY,IAAI,YAAY,IAAI,MACrF,MAAM,IAAI,aACR,kBACA,uEACF;CACF,IAAI,IAAI,aAAa,WAAW,CAAC;EAAC;EAAa;EAAa;CAAO,CAAC,CAAC,SAAS,IAAI,QAAQ,GACxF,MAAM,IAAI,aAAa,kBAAkB,mDAAmD;CAC9F,OAAO,IAAI,SAAS;AACtB;AAEA,SAAgB,OAAO,OAAuB;CAC5C,IAAI,CAAC,MAAM,KAAK,KAAK,SAAS,KAAK,KAAK,GACtC,MAAM,IAAI,aAAa,uBAAuB,oCAAoC;CACpF,OAAO,UAAU;AACnB"}
@@ -0,0 +1,12 @@
1
+ import { t as ModelProtocol } from "../adapter-DndZN8Se.mjs";
2
+ //#region src/adapters/cloudflare.d.ts
3
+ export interface CloudflareOptions {
4
+ readonly accountId: string;
5
+ readonly apiToken: string;
6
+ readonly gatewayId?: string;
7
+ readonly model?: "typesafe/jev";
8
+ }
9
+ /** The gateway envelope supports many models; this adapter only claims Jev semantics. */
10
+ export declare function cloudflare(options: CloudflareOptions): ModelProtocol;
11
+ //#endregion
12
+ //# sourceMappingURL=cloudflare.d.mts.map
@@ -0,0 +1,67 @@
1
+ import { l as System1Error, o as record } from "../core-D7i-WVU7.mjs";
2
+ import { bearer, checkHttp, defineAdapter, endpoint } from "../adapter.mjs";
3
+ import { n as encodeQuestions, r as typedCapabilities, t as decodeTyped } from "../typed-decisions-W30cNQUJ.mjs";
4
+ //#region src/adapters/cloudflare.ts
5
+ /** The gateway envelope supports many models; this adapter only claims Jev semantics. */
6
+ function cloudflare(options) {
7
+ if (!/^[a-f\d]{32}$/i.test(options.accountId)) throw new System1Error("InvalidRequest", "Cloudflare accountId must be 32 hexadecimal characters");
8
+ if (options.gatewayId !== void 0 && !/^[a-zA-Z0-9_-]+$/.test(options.gatewayId)) throw new System1Error("InvalidRequest", "Invalid gateway identifier");
9
+ const url = endpoint(`https://api.cloudflare.com/client/v4/accounts/${options.accountId}/ai/run`);
10
+ const authorization = bearer(options.apiToken);
11
+ const model = options.model ?? "typesafe/jev";
12
+ if (model !== "typesafe/jev") throw new System1Error("UnsupportedCapability", "Cloudflare adapter currently supports typesafe/jev only");
13
+ const headers = {
14
+ authorization,
15
+ "content-type": "application/json",
16
+ ...options.gatewayId ? { "cf-aig-gateway-id": options.gatewayId } : {}
17
+ };
18
+ return defineAdapter({
19
+ id: "cloudflare",
20
+ model,
21
+ capabilities: typedCapabilities,
22
+ encode: (request) => ({
23
+ url,
24
+ method: "POST",
25
+ headers,
26
+ body: JSON.stringify({
27
+ model,
28
+ input: {
29
+ state: request.state,
30
+ questions: encodeQuestions(request)
31
+ }
32
+ })
33
+ }),
34
+ decode: (response, request) => {
35
+ const body = response.body;
36
+ if (body !== null && typeof body === "object" && !Array.isArray(body)) {
37
+ const envelope = record(body);
38
+ if (envelope.success === false) {
39
+ const codes = (Array.isArray(envelope.errors) ? envelope.errors : []).map((e) => e && typeof e === "object" ? String(e.code) : "");
40
+ if (codes.includes("2021")) throw new System1Error("QuotaExceeded", "Cloudflare requires credits or provider credentials", {
41
+ providerCode: "2021",
42
+ status: response.status
43
+ });
44
+ if (codes.includes("10000")) throw new System1Error("AuthenticationError", "Cloudflare authentication or permissions failed", {
45
+ providerCode: "10000",
46
+ status: response.status
47
+ });
48
+ checkHttp(response);
49
+ throw new System1Error("ProviderError", "Cloudflare reported an unsuccessful evaluation", { status: response.status });
50
+ }
51
+ }
52
+ checkHttp(response);
53
+ const envelope = record(body);
54
+ const payload = Object.hasOwn(envelope, "result") ? envelope.success === true ? envelope.result : void 0 : envelope;
55
+ const decoded = decodeTyped(payload, request, "typesafe:distribution-confidence");
56
+ const requestId = response.headers["cf-aig-log-id"] ?? response.headers["cf-ray"];
57
+ return {
58
+ ...decoded,
59
+ ...requestId ? { requestId } : {}
60
+ };
61
+ }
62
+ });
63
+ }
64
+ //#endregion
65
+ export { cloudflare };
66
+
67
+ //# sourceMappingURL=cloudflare.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloudflare.mjs","names":[],"sources":["../../src/adapters/cloudflare.ts"],"sourcesContent":["import { bearer, checkHttp, defineAdapter, endpoint } from \"../adapter.js\";\nimport { record } from \"../core.js\";\nimport { System1Error } from \"../errors.js\";\nimport { decodeTyped, encodeQuestions, typedCapabilities } from \"./typed-decisions.js\";\n\nexport interface CloudflareOptions {\n readonly accountId: string;\n readonly apiToken: string;\n readonly gatewayId?: string;\n readonly model?: \"typesafe/jev\";\n}\n/** The gateway envelope supports many models; this adapter only claims Jev semantics. */\nexport function cloudflare(options: CloudflareOptions) {\n if (!/^[a-f\\d]{32}$/i.test(options.accountId))\n throw new System1Error(\n \"InvalidRequest\",\n \"Cloudflare accountId must be 32 hexadecimal characters\",\n );\n if (options.gatewayId !== undefined && !/^[a-zA-Z0-9_-]+$/.test(options.gatewayId))\n throw new System1Error(\"InvalidRequest\", \"Invalid gateway identifier\");\n const url = endpoint(`https://api.cloudflare.com/client/v4/accounts/${options.accountId}/ai/run`);\n const authorization = bearer(options.apiToken);\n const model = options.model ?? \"typesafe/jev\";\n if (model !== \"typesafe/jev\")\n throw new System1Error(\n \"UnsupportedCapability\",\n \"Cloudflare adapter currently supports typesafe/jev only\",\n );\n const headers = {\n authorization,\n \"content-type\": \"application/json\",\n ...(options.gatewayId ? { \"cf-aig-gateway-id\": options.gatewayId } : {}),\n };\n return defineAdapter({\n id: \"cloudflare\",\n model,\n capabilities: typedCapabilities,\n encode: (request) => ({\n url,\n method: \"POST\",\n headers,\n body: JSON.stringify({\n model,\n input: { state: request.state, questions: encodeQuestions(request) },\n }),\n }),\n decode: (response, request) => {\n const body = response.body;\n if (body !== null && typeof body === \"object\" && !Array.isArray(body)) {\n const envelope = record(body);\n if (envelope.success === false) {\n const errors = Array.isArray(envelope.errors) ? envelope.errors : [];\n const codes = errors.map((e) =>\n e && typeof e === \"object\" ? String((e as Record<string, unknown>).code) : \"\",\n );\n if (codes.includes(\"2021\"))\n throw new System1Error(\n \"QuotaExceeded\",\n \"Cloudflare requires credits or provider credentials\",\n { providerCode: \"2021\", status: response.status },\n );\n if (codes.includes(\"10000\"))\n throw new System1Error(\n \"AuthenticationError\",\n \"Cloudflare authentication or permissions failed\",\n { providerCode: \"10000\", status: response.status },\n );\n checkHttp(response);\n throw new System1Error(\n \"ProviderError\",\n \"Cloudflare reported an unsuccessful evaluation\",\n { status: response.status },\n );\n }\n }\n checkHttp(response);\n const envelope = record(body);\n // Cloudflare documents model-native output and also uses API result envelopes.\n const payload = Object.hasOwn(envelope, \"result\")\n ? envelope.success === true\n ? envelope.result\n : undefined\n : envelope;\n const decoded = decodeTyped(payload, request, \"typesafe:distribution-confidence\");\n const requestId = response.headers[\"cf-aig-log-id\"] ?? response.headers[\"cf-ray\"];\n return { ...decoded, ...(requestId ? { requestId } : {}) };\n },\n });\n}\n"],"mappings":";;;;;AAYA,SAAgB,WAAW,SAA4B;CACrD,IAAI,CAAC,iBAAiB,KAAK,QAAQ,SAAS,GAC1C,MAAM,IAAI,aACR,kBACA,wDACF;CACF,IAAI,QAAQ,cAAc,KAAA,KAAa,CAAC,mBAAmB,KAAK,QAAQ,SAAS,GAC/E,MAAM,IAAI,aAAa,kBAAkB,4BAA4B;CACvE,MAAM,MAAM,SAAS,iDAAiD,QAAQ,UAAU,QAAQ;CAChG,MAAM,gBAAgB,OAAO,QAAQ,QAAQ;CAC7C,MAAM,QAAQ,QAAQ,SAAS;CAC/B,IAAI,UAAU,gBACZ,MAAM,IAAI,aACR,yBACA,yDACF;CACF,MAAM,UAAU;EACd;EACA,gBAAgB;EAChB,GAAI,QAAQ,YAAY,EAAE,qBAAqB,QAAQ,UAAU,IAAI,CAAC;CACxE;CACA,OAAO,cAAc;EACnB,IAAI;EACJ;EACA,cAAc;EACd,SAAS,aAAa;GACpB;GACA,QAAQ;GACR;GACA,MAAM,KAAK,UAAU;IACnB;IACA,OAAO;KAAE,OAAO,QAAQ;KAAO,WAAW,gBAAgB,OAAO;IAAE;GACrE,CAAC;EACH;EACA,SAAS,UAAU,YAAY;GAC7B,MAAM,OAAO,SAAS;GACtB,IAAI,SAAS,QAAQ,OAAO,SAAS,YAAY,CAAC,MAAM,QAAQ,IAAI,GAAG;IACrE,MAAM,WAAW,OAAO,IAAI;IAC5B,IAAI,SAAS,YAAY,OAAO;KAE9B,MAAM,SADS,MAAM,QAAQ,SAAS,MAAM,IAAI,SAAS,SAAS,CAAC,EAAA,CAC9C,KAAK,MACxB,KAAK,OAAO,MAAM,WAAW,OAAQ,EAA8B,IAAI,IAAI,EAC7E;KACA,IAAI,MAAM,SAAS,MAAM,GACvB,MAAM,IAAI,aACR,iBACA,uDACA;MAAE,cAAc;MAAQ,QAAQ,SAAS;KAAO,CAClD;KACF,IAAI,MAAM,SAAS,OAAO,GACxB,MAAM,IAAI,aACR,uBACA,mDACA;MAAE,cAAc;MAAS,QAAQ,SAAS;KAAO,CACnD;KACF,UAAU,QAAQ;KAClB,MAAM,IAAI,aACR,iBACA,kDACA,EAAE,QAAQ,SAAS,OAAO,CAC5B;IACF;GACF;GACA,UAAU,QAAQ;GAClB,MAAM,WAAW,OAAO,IAAI;GAE5B,MAAM,UAAU,OAAO,OAAO,UAAU,QAAQ,IAC5C,SAAS,YAAY,OACnB,SAAS,SACT,KAAA,IACF;GACJ,MAAM,UAAU,YAAY,SAAS,SAAS,kCAAkC;GAChF,MAAM,YAAY,SAAS,QAAQ,oBAAoB,SAAS,QAAQ;GACxE,OAAO;IAAE,GAAG;IAAS,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC;GAAG;EAC3D;CACF,CAAC;AACH"}
@@ -0,0 +1,12 @@
1
+ import { t as ModelProtocol } from "../adapter-DndZN8Se.mjs";
2
+ //#region src/adapters/laya.d.ts
3
+ export interface LayaOptions {
4
+ /** Full URL of your explicitly compatible bridge, not a Hugging Face inference URL. */
5
+ readonly endpoint: string;
6
+ readonly model: string;
7
+ readonly apiKey?: string;
8
+ }
9
+ /** Opt-in system1 Laya bridge v1 contract. No public hosted Laya API is assumed. */
10
+ export declare function laya(options: LayaOptions): ModelProtocol;
11
+ //#endregion
12
+ //# sourceMappingURL=laya.d.mts.map
@@ -0,0 +1,36 @@
1
+ import { bearer, checkHttp, defineAdapter, endpoint } from "../adapter.mjs";
2
+ import { n as encodeQuestions, r as typedCapabilities, t as decodeTyped } from "../typed-decisions-W30cNQUJ.mjs";
3
+ //#region src/adapters/laya.ts
4
+ /** Opt-in system1 Laya bridge v1 contract. No public hosted Laya API is assumed. */
5
+ function laya(options) {
6
+ const url = endpoint(options.endpoint);
7
+ const headers = {
8
+ "content-type": "application/json",
9
+ ...options.apiKey ? { authorization: bearer(options.apiKey) } : {}
10
+ };
11
+ const model = options.model;
12
+ return defineAdapter({
13
+ id: "laya-bridge-v1",
14
+ model,
15
+ capabilities: typedCapabilities,
16
+ encode: (request) => ({
17
+ url,
18
+ method: "POST",
19
+ headers,
20
+ body: JSON.stringify({
21
+ protocol: "system1-laya-v1",
22
+ model,
23
+ state: request.state,
24
+ questions: encodeQuestions(request)
25
+ })
26
+ }),
27
+ decode: (response, request) => {
28
+ checkHttp(response);
29
+ return decodeTyped(response.body, request, "laya:reported-confidence");
30
+ }
31
+ });
32
+ }
33
+ //#endregion
34
+ export { laya };
35
+
36
+ //# sourceMappingURL=laya.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"laya.mjs","names":[],"sources":["../../src/adapters/laya.ts"],"sourcesContent":["import { bearer, checkHttp, defineAdapter, endpoint } from \"../adapter.js\";\nimport { decodeTyped, encodeQuestions, typedCapabilities } from \"./typed-decisions.js\";\n\nexport interface LayaOptions {\n /** Full URL of your explicitly compatible bridge, not a Hugging Face inference URL. */\n readonly endpoint: string;\n readonly model: string;\n readonly apiKey?: string;\n}\n/** Opt-in system1 Laya bridge v1 contract. No public hosted Laya API is assumed. */\nexport function laya(options: LayaOptions) {\n const url = endpoint(options.endpoint);\n const headers = {\n \"content-type\": \"application/json\",\n ...(options.apiKey ? { authorization: bearer(options.apiKey) } : {}),\n };\n const model = options.model;\n return defineAdapter({\n id: \"laya-bridge-v1\",\n model,\n capabilities: typedCapabilities,\n encode: (request) => ({\n url,\n method: \"POST\",\n headers,\n body: JSON.stringify({\n protocol: \"system1-laya-v1\",\n model,\n state: request.state,\n questions: encodeQuestions(request),\n }),\n }),\n decode: (response, request) => {\n checkHttp(response);\n return decodeTyped(response.body, request, \"laya:reported-confidence\");\n },\n });\n}\n"],"mappings":";;;;AAUA,SAAgB,KAAK,SAAsB;CACzC,MAAM,MAAM,SAAS,QAAQ,QAAQ;CACrC,MAAM,UAAU;EACd,gBAAgB;EAChB,GAAI,QAAQ,SAAS,EAAE,eAAe,OAAO,QAAQ,MAAM,EAAE,IAAI,CAAC;CACpE;CACA,MAAM,QAAQ,QAAQ;CACtB,OAAO,cAAc;EACnB,IAAI;EACJ;EACA,cAAc;EACd,SAAS,aAAa;GACpB;GACA,QAAQ;GACR;GACA,MAAM,KAAK,UAAU;IACnB,UAAU;IACV;IACA,OAAO,QAAQ;IACf,WAAW,gBAAgB,OAAO;GACpC,CAAC;EACH;EACA,SAAS,UAAU,YAAY;GAC7B,UAAU,QAAQ;GAClB,OAAO,YAAY,SAAS,MAAM,SAAS,0BAA0B;EACvE;CACF,CAAC;AACH"}
@@ -0,0 +1,11 @@
1
+ import { t as ModelProtocol } from "../adapter-DndZN8Se.mjs";
2
+ //#region src/adapters/typesafe.d.ts
3
+ export interface JevOptions {
4
+ readonly apiKey: string;
5
+ readonly model?: string;
6
+ /** Full native endpoint, for explicitly trusted compatible services. */
7
+ readonly endpoint?: string;
8
+ }
9
+ export declare function jev(options: JevOptions): ModelProtocol;
10
+ //#endregion
11
+ //# sourceMappingURL=typesafe.d.mts.map
@@ -0,0 +1,39 @@
1
+ import { bearer, checkHttp, defineAdapter, endpoint } from "../adapter.mjs";
2
+ import { n as encodeQuestions, r as typedCapabilities, t as decodeTyped } from "../typed-decisions-W30cNQUJ.mjs";
3
+ //#region src/adapters/typesafe.ts
4
+ function jev(options) {
5
+ const url = endpoint(options.endpoint ?? "https://api.typesafe.ai/v1/systemone");
6
+ const authorization = bearer(options.apiKey);
7
+ const model = options.model ?? "jev-latest";
8
+ return defineAdapter({
9
+ id: "typesafe",
10
+ model,
11
+ capabilities: typedCapabilities,
12
+ encode: (request) => ({
13
+ url,
14
+ method: "POST",
15
+ headers: {
16
+ authorization,
17
+ "content-type": "application/json"
18
+ },
19
+ body: JSON.stringify({
20
+ model,
21
+ state: request.state,
22
+ questions: encodeQuestions(request)
23
+ })
24
+ }),
25
+ decode: (response, request) => {
26
+ checkHttp(response);
27
+ const result = decodeTyped(response.body, request, "typesafe:distribution-confidence");
28
+ const requestId = response.headers["x-request-id"];
29
+ return {
30
+ ...result,
31
+ ...requestId ? { requestId } : {}
32
+ };
33
+ }
34
+ });
35
+ }
36
+ //#endregion
37
+ export { jev };
38
+
39
+ //# sourceMappingURL=typesafe.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typesafe.mjs","names":[],"sources":["../../src/adapters/typesafe.ts"],"sourcesContent":["import { bearer, checkHttp, defineAdapter, endpoint } from \"../adapter.js\";\nimport { decodeTyped, encodeQuestions, typedCapabilities } from \"./typed-decisions.js\";\n\nexport interface JevOptions {\n readonly apiKey: string;\n readonly model?: string;\n /** Full native endpoint, for explicitly trusted compatible services. */\n readonly endpoint?: string;\n}\nexport function jev(options: JevOptions) {\n const url = endpoint(options.endpoint ?? \"https://api.typesafe.ai/v1/systemone\");\n const authorization = bearer(options.apiKey);\n const model = options.model ?? \"jev-latest\";\n return defineAdapter({\n id: \"typesafe\",\n model,\n capabilities: typedCapabilities,\n encode: (request) => ({\n url,\n method: \"POST\",\n headers: { authorization, \"content-type\": \"application/json\" },\n body: JSON.stringify({ model, state: request.state, questions: encodeQuestions(request) }),\n }),\n decode: (response, request) => {\n checkHttp(response);\n const result = decodeTyped(response.body, request, \"typesafe:distribution-confidence\");\n const requestId = response.headers[\"x-request-id\"];\n return { ...result, ...(requestId ? { requestId } : {}) };\n },\n });\n}\n"],"mappings":";;;AASA,SAAgB,IAAI,SAAqB;CACvC,MAAM,MAAM,SAAS,QAAQ,YAAY,sCAAsC;CAC/E,MAAM,gBAAgB,OAAO,QAAQ,MAAM;CAC3C,MAAM,QAAQ,QAAQ,SAAS;CAC/B,OAAO,cAAc;EACnB,IAAI;EACJ;EACA,cAAc;EACd,SAAS,aAAa;GACpB;GACA,QAAQ;GACR,SAAS;IAAE;IAAe,gBAAgB;GAAmB;GAC7D,MAAM,KAAK,UAAU;IAAE;IAAO,OAAO,QAAQ;IAAO,WAAW,gBAAgB,OAAO;GAAE,CAAC;EAC3F;EACA,SAAS,UAAU,YAAY;GAC7B,UAAU,QAAQ;GAClB,MAAM,SAAS,YAAY,SAAS,MAAM,SAAS,kCAAkC;GACrF,MAAM,YAAY,SAAS,QAAQ;GACnC,OAAO;IAAE,GAAG;IAAQ,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC;GAAG;EAC1D;CACF,CAAC;AACH"}