@fayegram-ai/decision-bridge 0.1.1 → 0.1.2
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/CHANGELOG.md +5 -0
- package/README.md +3 -3
- package/docs/README.md +2 -1
- package/docs/development/ARCHITECTURE.md +4 -2
- package/docs/guides/BROWSER.md +3 -0
- package/docs/guides/GETTING_STARTED.md +1 -1
- package/docs/guides/JEV.md +174 -0
- package/docs/guides/PLATFORMS.md +2 -2
- package/docs/reference/CLI.md +12 -1
- package/docs/reference/CONFIGURATION.md +6 -1
- package/docs/reference/PROVIDERS.md +12 -2
- package/docs/reference/SDK.md +13 -5
- package/docs/reference/SOURCES.md +4 -0
- package/package.json +1 -1
- package/schemas/decision.config.schema.json +15 -1
- package/src/capabilities.mjs +8 -2
- package/src/cli/config-validation.mjs +9 -1
- package/src/cli/config.mjs +15 -2
- package/src/cli/decisions.mjs +8 -0
- package/src/cli/main.mjs +15 -4
- package/src/index.d.mts +24 -5
- package/src/index.mjs +1 -1
- package/src/jev.d.mts +16 -0
- package/src/probabilities.mjs +6 -3
- package/src/providers/cloudflare-images.mjs +2 -58
- package/src/providers/image-header.mjs +59 -0
- package/src/providers/jev-images.mjs +90 -0
- package/src/providers/jev-preflight.mjs +61 -0
- package/src/providers/jev-profile.mjs +37 -0
- package/src/providers/jev.mjs +32 -13
- package/src/questions.mjs +2 -0
- package/src/validation.mjs +13 -6
- package/src/version.mjs +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
Notable user-facing changes by version.
|
|
4
4
|
|
|
5
|
+
## 0.1.2
|
|
6
|
+
|
|
7
|
+
- Add opt-in Jev images, typed bounding boxes, native JSON assets, and long context
|
|
8
|
+
across SDK and CLI, with capability preflight and nullable token usage.
|
|
9
|
+
|
|
5
10
|
## 0.1.1
|
|
6
11
|
|
|
7
12
|
- Add OpenAI `default`/`luna` selectors and requested/resolved model metadata; improve CLI configuration and documentation.
|
package/README.md
CHANGED
|
@@ -29,7 +29,7 @@ embedded WAV/MP3 audio and MP4/WebM video, ordered images → audio → videos
|
|
|
29
29
|
The common API checks provider/model capabilities before dispatch; refusals are
|
|
30
30
|
errors.
|
|
31
31
|
|
|
32
|
-
**Version 0.1.
|
|
32
|
+
**Version 0.1.2 · Node.js 22.16+ or modern browsers (SDK) · ESM · zero runtime dependencies**
|
|
33
33
|
|
|
34
34
|
The npm package is
|
|
35
35
|
[@fayegram-ai/decision-bridge](https://www.npmjs.com/package/@fayegram-ai/decision-bridge).
|
|
@@ -53,7 +53,7 @@ Use these model selectors with the built-in decision providers:
|
|
|
53
53
|
| Cloudflare (`cloudflare-decisions`) | `clef-flash`, `@cf/cloudflare/clef-flash` | — |
|
|
54
54
|
| Cloudflare (`cloudflare-decisions`) | `clef-omni`, `@cf/cloudflare/clef-omni` | — |
|
|
55
55
|
|
|
56
|
-
`jev-latest` is Jev's default alias. Jev also accepts explicit model IDs available through your TypeSafe account;
|
|
56
|
+
`jev-latest` is Jev's default alias. Jev also accepts `jev-preview` and explicit model IDs available through your TypeSafe account;
|
|
57
57
|
use `bridge.listModels()` or the CLI `models` command to inspect that catalog.
|
|
58
58
|
The bridge does not maintain a static list of Jev versions. A moving alias or a
|
|
59
59
|
catalog entry does not guarantee inference access or reproducible model quality.
|
|
@@ -80,7 +80,7 @@ All native providers support shared state and the common `choice`, `noul`, and
|
|
|
80
80
|
|
|
81
81
|
| Provider | Additional supported features | Guide |
|
|
82
82
|
| --- | --- | --- |
|
|
83
|
-
| Jev | Native decisions through
|
|
83
|
+
| Jev | Native decisions, opt-in images, boxes, and long context through TypeSafe | [Jev guide](docs/guides/JEV.md) |
|
|
84
84
|
| OpenAI Decisions | Ordered text/images, typed choices, labelled scores, safety identifiers, native access | [OpenAI Decisions](docs/guides/OPENAI_DECISIONS.md) |
|
|
85
85
|
| Cloudflare Clef / Clef-flash | Embedded images before text, typed choices, labelled scores, native access, Workers AI binding, optional Gateway | [Cloudflare decisions](docs/guides/CLOUDFLARE_DECISIONS.md) |
|
|
86
86
|
| Cloudflare Clef-omni | The same decision and transport features, plus embedded audio/video | [Omni media and limits](docs/guides/CLOUDFLARE_DECISIONS.md#omni-audio-and-video) |
|
package/docs/README.md
CHANGED
|
@@ -17,7 +17,7 @@ validated, structured decisions.
|
|
|
17
17
|
For provider-specific input forms, consult the
|
|
18
18
|
[capability comparison](reference/PROVIDERS.md#common-request-capabilities).
|
|
19
19
|
The common bridge API and dedicated native APIs have separate request shapes;
|
|
20
|
-
the OpenAI and Cloudflare guides cover both.
|
|
20
|
+
the Jev, OpenAI and Cloudflare guides cover both.
|
|
21
21
|
|
|
22
22
|
## Use the bridge
|
|
23
23
|
|
|
@@ -27,6 +27,7 @@ the OpenAI and Cloudflare guides cover both.
|
|
|
27
27
|
| [Browser integration](guides/BROWSER.md) | Direct browser use, CORS requirements, and credential exposure |
|
|
28
28
|
| [Platforms](guides/PLATFORMS.md) | Windows, macOS, and Linux setup |
|
|
29
29
|
| [Switching models](guides/SWITCHING_MODELS.md) | Backend and model selection |
|
|
30
|
+
| [Jev](guides/JEV.md) | Common/native images, boxes, experimental long context, model selection, and CLI opt-ins |
|
|
30
31
|
| [OpenAI Decisions](guides/OPENAI_DECISIONS.md) | Model selectors and upstream targets, selection metadata, common/native access, ordered images, and typed values |
|
|
31
32
|
| [Cloudflare Clef / Clef-flash / Clef-omni](guides/CLOUDFLARE_DECISIONS.md) | Common/native decisions, embedded images and Omni audio/video, REST and Workers AI binding, busy-mode compatibility, and optional Gateway |
|
|
32
33
|
| [Customization](guides/CUSTOMIZATION.md) | Questions, templates, extensions, and policies |
|
|
@@ -38,7 +38,7 @@ Application / CLI
|
|
|
38
38
|
application policy / storage / downstream action
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
-
Native OpenAI and Cloudflare providers also expose `createDecision` directly.
|
|
41
|
+
Native Jev, OpenAI and Cloudflare providers also expose `createDecision` directly.
|
|
42
42
|
Common and native paths share provider validation, codecs, and bounded transport.
|
|
43
43
|
Direct native calls use provider deadlines; bridge calls additionally enforce the
|
|
44
44
|
shared evaluation deadline and extension lifecycle.
|
|
@@ -82,6 +82,7 @@ See [OpenAI model selection](../guides/OPENAI_DECISIONS.md#model-selection).
|
|
|
82
82
|
| `schemas/decision.config.schema.json` | Shipped CLI configuration structure and editor support |
|
|
83
83
|
| `src/providers/` | API orchestration, model profiles, preflight, codecs, bounded image/audio/video inspection, and transports |
|
|
84
84
|
| `src/providers/openai-profile.mjs`, `src/providers/decisions-preflight.mjs` | Release-owned OpenAI selection, capabilities, and preparation of selected and outgoing requests |
|
|
85
|
+
| `src/providers/jev-profile.mjs`, `src/providers/jev-preflight.mjs`, `src/providers/jev-images.mjs` | Jev experimental policy, common/native assets, and image preflight |
|
|
85
86
|
| `src/embedded.mjs` | Shared embedded data URL and canonical base64 checks |
|
|
86
87
|
| `src/transport.mjs`, `src/response-transport.mjs` | Credential destinations, bounded bodies, safe errors, retries |
|
|
87
88
|
| `src/async.mjs` | Deadlines and cancellation races |
|
|
@@ -102,7 +103,8 @@ claiming equivalent statistical semantics across models.
|
|
|
102
103
|
|
|
103
104
|
The bridge takes result-validation policy from the provider contract. Cloudflare
|
|
104
105
|
uses an allowance for four-decimal distributions; other built-ins retain the
|
|
105
|
-
baseline.
|
|
106
|
+
baseline. Jev additionally permits explicitly unknown token counts while requiring
|
|
107
|
+
native confidence. Response metadata cannot relax validation. See the [SDK reference](../reference/SDK.md).
|
|
106
108
|
Application code passes that precision explicitly when using `decideChoice`; the
|
|
107
109
|
policy helper does not infer it from the answer or its metadata.
|
|
108
110
|
|
package/docs/guides/BROWSER.md
CHANGED
|
@@ -35,6 +35,9 @@ headers used by the SDK. For Jev evaluation those include `POST`, `Authorization
|
|
|
35
35
|
and `Content-Type`. If the preflight is rejected, the browser sends no evaluation
|
|
36
36
|
request; neither the SDK nor a browser setting can override that server policy.
|
|
37
37
|
Check your intended origin with TypeSafe before relying on direct Jev calls.
|
|
38
|
+
When Jev experimental features are enabled, CORS must also permit the selected
|
|
39
|
+
`TypeSafe-Danger-Zone-Images` and `TypeSafe-Danger-Zone-Long-Context` headers.
|
|
40
|
+
The [Jev guide](JEV.md) covers browser-safe embedded assets and boxes.
|
|
38
41
|
|
|
39
42
|
Any key delivered to browser JavaScript can be read by the app's users. Only use
|
|
40
43
|
a credential that the provider explicitly permits for browser exposure. If an
|
|
@@ -25,7 +25,7 @@ You can also install a verified local archive, replacing the path below. See
|
|
|
25
25
|
a source checkout:
|
|
26
26
|
|
|
27
27
|
```bash
|
|
28
|
-
npm install /path/to/fayegram-ai-decision-bridge-0.1.
|
|
28
|
+
npm install /path/to/fayegram-ai-decision-bridge-0.1.2.tgz
|
|
29
29
|
```
|
|
30
30
|
|
|
31
31
|
The installed package contains the SDK, declarations, command runner, examples,
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# Jev images, boxes, and long context
|
|
2
|
+
|
|
3
|
+
Jev uses TypeSafe's native `POST /v1/systemone` endpoint. The SDK defaults to
|
|
4
|
+
`jev-latest`; `jev-preview` and explicit version IDs are also accepted. Model
|
|
5
|
+
listing is account-specific and may list aliases without versioned IDs.
|
|
6
|
+
The returned `model` records the service-reported version independently of
|
|
7
|
+
`meta.requestedModel`.
|
|
8
|
+
|
|
9
|
+
## Experimental opt-ins
|
|
10
|
+
|
|
11
|
+
Jev images and long context are disabled by default. Enable each independently
|
|
12
|
+
in provider configuration. TypeSafe treats these capabilities as experimental;
|
|
13
|
+
their accuracy, formats, and limits can change.
|
|
14
|
+
|
|
15
|
+
```javascript
|
|
16
|
+
import { createBridge, JevProvider, box, noul } from '@fayegram-ai/decision-bridge';
|
|
17
|
+
|
|
18
|
+
const provider = new JevProvider({
|
|
19
|
+
model: 'jev-1.14.0',
|
|
20
|
+
dangerZone: { images: true, longContext: true },
|
|
21
|
+
});
|
|
22
|
+
const bridge = createBridge({ provider });
|
|
23
|
+
|
|
24
|
+
// imageBase64 is a caller-prepared PNG or JPEG, without a data URL prefix.
|
|
25
|
+
const result = await bridge.evaluate({
|
|
26
|
+
input: [
|
|
27
|
+
{ type: 'text', text: 'A photograph from the kitchen camera.' },
|
|
28
|
+
{ type: 'image', dataUrl: 'data:image/png;base64,' + imageBase64 },
|
|
29
|
+
],
|
|
30
|
+
questions: {
|
|
31
|
+
present: noul('Is there a coffee mug in the image?'),
|
|
32
|
+
mug: box('The coffee mug in the image'),
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
console.log(result.answers.present.noul, result.answers.mug.box);
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
`dangerZone.images` sends `TypeSafe-Danger-Zone-Images: true` and enables common
|
|
39
|
+
image input and boxes. It works with Jev 1.13 and 1.14 for images. Boxes require
|
|
40
|
+
`jev-preview` or a pinned Jev version of 1.14.0 or newer. Local box capability
|
|
41
|
+
lookup remains conservative for moving stable aliases and unknown model names;
|
|
42
|
+
use a supported pinned ID or `jev-preview` for boxes. Account access and hosted
|
|
43
|
+
model availability are still checked by the service.
|
|
44
|
+
|
|
45
|
+
`dangerZone.longContext` sends `TypeSafe-Danger-Zone-Long-Context: true`. TypeSafe
|
|
46
|
+
documents 262k tokens for both the per-request and per-question contexts with
|
|
47
|
+
this header, compared with default limits of 64k and 32k respectively. This
|
|
48
|
+
option works on Jev 1.13 and 1.14. It does not change the byte budget or estimate
|
|
49
|
+
token counts. Longer contexts are slower and less accurate.
|
|
50
|
+
|
|
51
|
+
Ordered common input becomes a state array in the same order. Text stays text;
|
|
52
|
+
each image becomes an asset reference. The SDK chooses references that do not
|
|
53
|
+
collide with the input or question text. Jev does not support image detail
|
|
54
|
+
controls: omit `detail`, or use `null` or `auto`. Audio/video, typed choices,
|
|
55
|
+
labelled scores, and safety identifiers remain unsupported by this provider.
|
|
56
|
+
|
|
57
|
+
## Native assets in instructions and criteria
|
|
58
|
+
|
|
59
|
+
Use `provider.createDecision()` when images belong inside structured state,
|
|
60
|
+
instructions, or criteria. It accepts the native JSON request shape and returns
|
|
61
|
+
`{ decision, meta }`. Native calls share validation, transport, cancellation,
|
|
62
|
+
and retry policy with common calls, and bypass bridge extensions and observers.
|
|
63
|
+
|
|
64
|
+
```javascript
|
|
65
|
+
const { decision, meta } = await provider.createDecision({
|
|
66
|
+
state: { photo: 'photo-unique-reference' },
|
|
67
|
+
assets: {
|
|
68
|
+
'photo-unique-reference': {
|
|
69
|
+
type: 'image', format: 'png', data_base64: imageBase64,
|
|
70
|
+
},
|
|
71
|
+
'example-unique-reference': {
|
|
72
|
+
type: 'image', format: 'jpg', data_base64: exampleBase64,
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
questions: {
|
|
76
|
+
same: noul('Does the object in `photo` match this picture: example-unique-reference?'),
|
|
77
|
+
target: box('The matching object in `photo`'),
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
console.log(decision.answers.target.box, meta.requestedModel);
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
References are substituted in string values, including inside sentences and
|
|
84
|
+
nested JSON. Object keys are not substituted. Every asset must be referenced.
|
|
85
|
+
Whole-value references are resolved first. In longer strings, matches are
|
|
86
|
+
consumed from left to right; when keys overlap at the same position, the current
|
|
87
|
+
API uses asset-map order. A reference hidden by another match does not count as
|
|
88
|
+
used. Preflight rejects unused assets before dispatch. Place references in
|
|
89
|
+
separate values when both images are intended.
|
|
90
|
+
Use long unique references (for example, fresh UUIDs) that cannot accidentally
|
|
91
|
+
match ordinary text. Each reference is at most 1024 UTF-8 bytes; all reference
|
|
92
|
+
keys together are at most 65536 bytes. A file is uploaded once, but repeating
|
|
93
|
+
its reference repeats the image in the model's expanded input.
|
|
94
|
+
|
|
95
|
+
The bridge uses the JSON/base64 transport supported by TypeSafe. It does not
|
|
96
|
+
accept multipart `part` assets, read local image files, fetch URLs, resize,
|
|
97
|
+
rotate, or re-encode images. Base64 overhead counts toward the request limit.
|
|
98
|
+
Native Jev assets are separate from the common request shape; use
|
|
99
|
+
`createDecision` for images embedded in instructions or criteria.
|
|
100
|
+
|
|
101
|
+
## Boxes and results
|
|
102
|
+
|
|
103
|
+
`box(instructions)` takes no criteria. Its answer has `type: 'box'`, `box`,
|
|
104
|
+
and native `confidence`. Coordinates are fractions measured from the top-left:
|
|
105
|
+
`left` and `right` scale with width; `top` and `bottom` scale with height.
|
|
106
|
+
All four values must be finite numbers in 0–1, with `left < right` and
|
|
107
|
+
`top < bottom`. Validation rejects malformed boxes rather than repairing them.
|
|
108
|
+
Common results containing box questions use result `meta.schemaVersion: 4`;
|
|
109
|
+
the CLI configuration schema version remains 1.
|
|
110
|
+
|
|
111
|
+
Each question returns one box. There is no absent-target result: a box is
|
|
112
|
+
returned even when the target is absent. Pair it with a presence `noul` and
|
|
113
|
+
choose your own presence/confidence thresholds using representative images.
|
|
114
|
+
Jev token usage may be `null`; that means unknown, never zero. Native confidence
|
|
115
|
+
and all other result checks remain enforced.
|
|
116
|
+
|
|
117
|
+
## Image and request limits
|
|
118
|
+
|
|
119
|
+
- PNG or JPEG (`png`, `jpg`, `jpeg`); still images only. Animated PNG is rejected.
|
|
120
|
+
- At most 16 MiB per decoded image file.
|
|
121
|
+
- Each dimension is 256–1568 pixels, and area is 78,400–2,458,624 pixels.
|
|
122
|
+
A 256 × 256 image fails the area minimum.
|
|
123
|
+
- Jev requests default to a 32 MiB serialized JSON ceiling. `maxRequestBytes`
|
|
124
|
+
can lower it, but cannot exceed 32 MiB. Response budgets remain independently
|
|
125
|
+
configurable, with an 8 MiB default.
|
|
126
|
+
- State, each instruction, and each criterion must fit 64 nested JSON levels.
|
|
127
|
+
General bridge snapshots also retain their 200,000-node limit.
|
|
128
|
+
|
|
129
|
+
Preflight checks base64, headers, dimensions, PNG animation, references, original
|
|
130
|
+
image bytes, and serialized request bytes. Full decoding, server re-encoding,
|
|
131
|
+
the 32 MiB processed-image and expanded-input limits, and token limits remain
|
|
132
|
+
service checks. Client header inspection cannot predict processed sizes.
|
|
133
|
+
Prepare upright pixels yourself: TypeSafe removes metadata and does not apply
|
|
134
|
+
EXIF orientation. No separate image-count cap is asserted by the bridge;
|
|
135
|
+
`maxImages: null` means size and context determine capacity.
|
|
136
|
+
|
|
137
|
+
## CLI
|
|
138
|
+
|
|
139
|
+
```json
|
|
140
|
+
{
|
|
141
|
+
"schemaVersion": 1,
|
|
142
|
+
"provider": "jev",
|
|
143
|
+
"model": "jev-1.14.0",
|
|
144
|
+
"apiKeyEnv": "TYPESAFE_API_KEY",
|
|
145
|
+
"dangerZone": { "images": true, "longContext": true }
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
```shell
|
|
150
|
+
decision-bridge validate request.json --config decision.config.json
|
|
151
|
+
decision-bridge evaluate request.json --config decision.config.json --env-file .env
|
|
152
|
+
decision-bridge validate native.json --native --model jev-preview --jev-images
|
|
153
|
+
decision-bridge batch native.jsonl --native --config decision.config.json --env-file .env
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Common/native validation is offline and uses the same preflight as inference.
|
|
157
|
+
`--native` works with `init`, `validate`, `evaluate`, and `batch`. Jev keeps its
|
|
158
|
+
`models` command. CLI JSON/JSONL input supports requests up to 32 MiB per record;
|
|
159
|
+
the actual serialized request must also fit the configured provider ceiling.
|
|
160
|
+
|
|
161
|
+
`--jev-images` / `--no-jev-images` and `--jev-long-context` /
|
|
162
|
+
`--no-jev-long-context` override independent fields in `dangerZone`.
|
|
163
|
+
`DECISION_JEV_IMAGES` and `DECISION_JEV_LONG_CONTEXT` accept exactly `true` or
|
|
164
|
+
`false`. Flags override environment, then JSON configuration, then defaults.
|
|
165
|
+
Switching providers discards Jev-specific settings; using these flags with
|
|
166
|
+
another provider is a configuration error.
|
|
167
|
+
|
|
168
|
+
## Protocol sources
|
|
169
|
+
|
|
170
|
+
- [TypeSafe release announcement](https://typesafe.ai/blog/jev-1-14)
|
|
171
|
+
- [Images, assets, limits, and experimental header](https://docs.typesafe.ai/images)
|
|
172
|
+
- [Box questions and absence behavior](https://docs.typesafe.ai/primitives/box)
|
|
173
|
+
- [Models, aliases, and context limits](https://docs.typesafe.ai/models)
|
|
174
|
+
- [JavaScript SDK compatibility changes](https://docs.typesafe.ai/sdk/javascript/changelog)
|
package/docs/guides/PLATFORMS.md
CHANGED
|
@@ -22,7 +22,7 @@ compatible native Node runtime. See [testing](../development/TESTING.md).
|
|
|
22
22
|
Open PowerShell at the cloned repository or extracted source directory:
|
|
23
23
|
|
|
24
24
|
```powershell
|
|
25
|
-
cd "C:\path\to\decision-bridge-0.1.
|
|
25
|
+
cd "C:\path\to\decision-bridge-0.1.2"
|
|
26
26
|
node --version
|
|
27
27
|
node bin/decision.mjs validate examples/request.json
|
|
28
28
|
Copy-Item .env.example .env
|
|
@@ -48,7 +48,7 @@ the archive rather than reusing generated `node_modules` or executable shims.
|
|
|
48
48
|
## macOS / Linux
|
|
49
49
|
|
|
50
50
|
```bash
|
|
51
|
-
cd "/path/to/decision-bridge-0.1.
|
|
51
|
+
cd "/path/to/decision-bridge-0.1.2"
|
|
52
52
|
node --version
|
|
53
53
|
node bin/decision.mjs validate examples/request.json
|
|
54
54
|
cp .env.example .env
|
package/docs/reference/CLI.md
CHANGED
|
@@ -51,6 +51,12 @@ there is no CLI binding selector. Gateway settings route the selected REST reque
|
|
|
51
51
|
| `models` | List the configured provider's models; may be paginated |
|
|
52
52
|
| `batch FILE\|-` | Stream JSONL inputs and ordered JSONL result/error records |
|
|
53
53
|
|
|
54
|
+
Jev supports both common and `--native` requests for evaluation, validation,
|
|
55
|
+
initialization, and ordered batches. Experimental images/boxes require
|
|
56
|
+
`--jev-images`, and longer context requires `--jev-long-context` (or matching
|
|
57
|
+
JSON configuration). Use `--no-jev-images` and `--no-jev-long-context` to
|
|
58
|
+
override enabled settings. See the [Jev guide](../guides/JEV.md).
|
|
59
|
+
|
|
54
60
|
No input filename on `evaluate`, `validate`, or `schema` selects the bundled sample,
|
|
55
61
|
not stdin. Use `-` explicitly for stdin. Empty invocation prints help. Configuration
|
|
56
62
|
and credential errors do not cause fallback to another backend.
|
|
@@ -91,6 +97,8 @@ later configuration changes to control selection.
|
|
|
91
97
|
| `--provider NAME` | `jev`, `openai-decisions`, `cloudflare-decisions`, `custom-decision`, `custom-generative` |
|
|
92
98
|
| `--preset NAME` | custom-generative preset: `openai-compatible`, `openrouter`, or `anthropic`; exclusive with module |
|
|
93
99
|
| `--native` | Explicit native Decisions input/output; init/evaluate/validate/batch only |
|
|
100
|
+
| `--jev-images`, `--no-jev-images` | Enable/disable experimental Jev images and boxes |
|
|
101
|
+
| `--jev-long-context`, `--no-jev-long-context` | Enable/disable experimental Jev 262k context |
|
|
94
102
|
| `--model SELECTOR` | Model selector or supported upstream ID; overrides input JSON model and configured default |
|
|
95
103
|
| `--base-url URL` | Custom endpoint; requires explicit credential selection |
|
|
96
104
|
| `--api-key-env NAME` | Environment variable name, never the key itself |
|
|
@@ -172,7 +180,10 @@ delivery needs separate validation.
|
|
|
172
180
|
|
|
173
181
|
## I/O and resource limits
|
|
174
182
|
|
|
175
|
-
Single JSON input
|
|
183
|
+
Single JSON input normally uses **8 MiB**. JSONL normally uses **8 MiB per line,
|
|
184
|
+
64 MiB total**. Jev permits **32 MiB** for a single JSON input or JSONL record,
|
|
185
|
+
then checks serialized requests against its configured ceiling (32 MiB by default).
|
|
186
|
+
Config:
|
|
176
187
|
**1 MiB**. Environment file: **64 KiB**. Provider request and response default to
|
|
177
188
|
8 MiB each, configurable to at most 64 MiB. Cloudflare reads single JSON inputs
|
|
178
189
|
and individual JSONL records within 64 MiB, then applies model-specific serialized
|
|
@@ -46,10 +46,11 @@ profile. Gateway configuration is optional for either SDK transport and for CLI
|
|
|
46
46
|
| `noAuth` | Boolean; true only for loopback OpenAI-compatible endpoints |
|
|
47
47
|
| `timeoutMs` | Positive integer up to 2,147,483,647 milliseconds |
|
|
48
48
|
| `maxRetries` | Integer 0–10; OpenAI/Cloudflare default 0; Jev and generative presets default 2 |
|
|
49
|
-
| `maxRequestBytes`, `maxResponseBytes` | Positive integer through 64 MiB; default 8 MiB. Cloudflare requests: Clef/Clef-flash default/cap 13 MiB; Omni default 36 MiB, configurable through 64 MiB |
|
|
49
|
+
| `maxRequestBytes`, `maxResponseBytes` | Positive integer through 64 MiB; default 8 MiB. Jev requests default/cap 32 MiB. Cloudflare requests: Clef/Clef-flash default/cap 13 MiB; Omni default 36 MiB, configurable through 64 MiB |
|
|
50
50
|
| `accountId` | Cloudflare REST account ID; otherwise `CLOUDFLARE_ACCOUNT_ID` |
|
|
51
51
|
| `rejectIfBusy` | Cloudflare boolean; default false, incompatible with retries. Effective true fails REST preflight with `UNSUPPORTED_CAPABILITY`; see the [binding support and REST limitation](../guides/CLOUDFLARE_DECISIONS.md#capacity-rejection-and-ai-gateway) |
|
|
52
52
|
| `gateway` | Cloudflare Gateway object; see the [Cloudflare guide](../guides/CLOUDFLARE_DECISIONS.md) |
|
|
53
|
+
| `dangerZone` | Jev-only `{ images?: boolean, longContext?: boolean }`; both default false; see the [Jev guide](../guides/JEV.md) |
|
|
53
54
|
| `maxTokens` | Generative output budget, 1–1,048,576; default 4096 |
|
|
54
55
|
| `responseFormat` | Compatible generative presets: `json_schema`, `json_object`, `text` |
|
|
55
56
|
| `tokenParameter` | Compatible generative presets: `max_completion_tokens` or `max_tokens` |
|
|
@@ -58,6 +59,10 @@ profile. Gateway configuration is optional for either SDK transport and for CLI
|
|
|
58
59
|
| `options` | Custom factory's JSON options, e.g. its own baseURL |
|
|
59
60
|
|
|
60
61
|
Upper numeric limits validate client configuration, not vendor model capabilities.
|
|
62
|
+
Jev requests default to and are capped at 32 MiB; a smaller `maxRequestBytes`
|
|
63
|
+
lowers that ceiling. `DECISION_JEV_IMAGES` and `DECISION_JEV_LONG_CONTEXT`
|
|
64
|
+
accept `true` or `false`; their CLI overrides are `--jev-images`,
|
|
65
|
+
`--no-jev-images`, `--jev-long-context`, and `--no-jev-long-context`.
|
|
61
66
|
Cloudflare selects its byte budget from the effective request model, including
|
|
62
67
|
per-call overrides. An explicit smaller `maxRequestBytes` remains the ceiling;
|
|
63
68
|
selecting Omni cannot enlarge it. Omni's default is a bridge policy, not a
|
|
@@ -44,7 +44,7 @@ contract. The following additional forms are checked before dispatch:
|
|
|
44
44
|
|
|
45
45
|
| Provider | Ordered text / embedded images | Typed string/boolean choices | Labelled score levels | Safety identifier | Model listing |
|
|
46
46
|
| --- | --- | --- | --- | --- | --- |
|
|
47
|
-
| Jev |
|
|
47
|
+
| Jev | Ordered text; images with explicit opt-in | Unsupported | Unsupported | Unsupported | Supported |
|
|
48
48
|
| OpenAI Decisions | Supported; up to 128 images, preserving order | Supported | Supported | Supported | Unsupported |
|
|
49
49
|
| Cloudflare Clef / Clef-flash | Supported; up to four images before text | Supported | Supported; 2–10 levels | Unsupported | Unsupported |
|
|
50
50
|
| Cloudflare Clef-omni | Supported; up to four images before audio/video/text | Supported | Supported; 2–10 levels | Unsupported | Unsupported |
|
|
@@ -62,7 +62,11 @@ capability fields `audio`, `videos`, `maxAudioClips`, and `maxVideos` normalize
|
|
|
62
62
|
false/zero when omitted, preserving legacy custom profiles. Cloudflare's older
|
|
63
63
|
models and all other shipped providers reject audio/video before inference.
|
|
64
64
|
|
|
65
|
-
|
|
65
|
+
Jev additionally supports `box` questions on `jev-preview` and pinned 1.14+ models
|
|
66
|
+
when `dangerZone.images` is enabled. Other built-ins reject box questions.
|
|
67
|
+
See the [Jev guide](../guides/JEV.md) for asset placement and experimental opt-ins.
|
|
68
|
+
|
|
69
|
+
Dedicated `createDecision()` access is available on Jev, OpenAI Decisions and
|
|
66
70
|
Cloudflare providers. It uses each service's native request/response shape and
|
|
67
71
|
bypasses bridge preparation and observation hooks.
|
|
68
72
|
|
|
@@ -74,6 +78,12 @@ intermediate language model, skill, portal prompt, or chat conversion is used.
|
|
|
74
78
|
`GET /v1/models` lists native models. A listed catalog can differ from valid aliases;
|
|
75
79
|
`jev-latest` is the documented stable alias.
|
|
76
80
|
|
|
81
|
+
`jev-preview` selects the preview release. Images and longer context require
|
|
82
|
+
explicit `dangerZone` settings. Common image input preserves ordering; native
|
|
83
|
+
`createDecision()` additionally accepts JSON assets referenced in state,
|
|
84
|
+
instructions, and criteria. Box outputs preserve normalized edges and confidence.
|
|
85
|
+
See the [Jev guide](../guides/JEV.md) for limits and absence handling.
|
|
86
|
+
|
|
77
87
|
Pin a version after evaluating it for your workload rather than assuming a moving
|
|
78
88
|
alias yields reproducible quality. Store the returned `model` along with the
|
|
79
89
|
requested model and your question-template revision.
|
package/docs/reference/SDK.md
CHANGED
|
@@ -48,7 +48,7 @@ guides. These are SDK options, not per-evaluation bridge options.
|
|
|
48
48
|
| --- | --- |
|
|
49
49
|
| `timeoutMs` | 30,000 ms; positive integer through 2,147,483,647; one transport budget for dispatch, retries, backoff, and response reading |
|
|
50
50
|
| `maxRetries` | Additional eligible attempts, 0–10; Jev and generative presets default to 2, native OpenAI and Cloudflare to 0 |
|
|
51
|
-
| `maxRequestBytes` | Complete serialized request ceiling; normally 8 MiB, configurable from 1 byte through 64 MiB; Cloudflare applies its [model-specific budgets](../guides/CLOUDFLARE_DECISIONS.md#embedded-images-and-limits) |
|
|
51
|
+
| `maxRequestBytes` | Complete serialized request ceiling; normally 8 MiB, configurable from 1 byte through 64 MiB; Jev defaults to and caps at 32 MiB; Cloudflare applies its [model-specific budgets](../guides/CLOUDFLARE_DECISIONS.md#embedded-images-and-limits) |
|
|
52
52
|
| `maxResponseBytes` | 8 MiB; configurable from 1 byte through 64 MiB; applies while reading the response body |
|
|
53
53
|
| `fetchImpl` | Optional `(url: string, init?: RequestInit) => Promise<Response>`; defaults to the runtime's `fetch` |
|
|
54
54
|
|
|
@@ -146,6 +146,10 @@ const q3 = score('How far did processing progress?', [
|
|
|
146
146
|
]);
|
|
147
147
|
```
|
|
148
148
|
|
|
149
|
+
`box(instructions)` returns a box question with no criteria; supported providers
|
|
150
|
+
must declare `boxes: true`. Jev supports it with experimental image opt-in and
|
|
151
|
+
a supported model; see [Jev images and boxes](../guides/JEV.md).
|
|
152
|
+
|
|
149
153
|
Builders return immutable question objects. `choice(instructions, criteria)` accepts
|
|
150
154
|
a label map containing 1 to 255 options. `noul(instructions, criteria?)` accepts an
|
|
151
155
|
optional criteria object,
|
|
@@ -201,7 +205,8 @@ rubric exactly. Generative providers calculate score and legend locally. Native
|
|
|
201
205
|
values are validated and preserved, not normalized or replaced.
|
|
202
206
|
|
|
203
207
|
**Usage:** `input_tokens` and `output_tokens` are nonnegative integers or null.
|
|
204
|
-
Jev
|
|
208
|
+
Jev accepts explicitly null counts as unknown; OpenAI Decisions and Cloudflare
|
|
209
|
+
require reported integer counts. OpenAI and
|
|
205
210
|
Anthropic cache creation/read counts are preserved separately when provided;
|
|
206
211
|
Cloudflare does not fabricate cache or total-token fields. No total price, inferred cache saving, or
|
|
207
212
|
estimated token count is fabricated.
|
|
@@ -231,7 +236,8 @@ unavailable metadata exists. Result objects and nested data returned by the brid
|
|
|
231
236
|
are immutable. Standalone validation functions return snapshots, not frozen values.
|
|
232
237
|
|
|
233
238
|
`schemaVersion` remains 1 for legacy requests and 2 for ordered images/text or
|
|
234
|
-
richer question forms. Audio/video requests use 3
|
|
239
|
+
richer question forms. Audio/video requests use 3; requests with boxes use 4.
|
|
240
|
+
This result version is separate
|
|
235
241
|
from the CLI configuration schema, which remains 1.
|
|
236
242
|
|
|
237
243
|
## Extensions
|
|
@@ -304,6 +310,8 @@ automatic model fallback. The CLI has a separate streaming JSONL implementation.
|
|
|
304
310
|
- `createProvider(config)`: factory requiring an explicit `type` equal to `jev`,
|
|
305
311
|
`openai-decisions`, or `cloudflare-decisions`.
|
|
306
312
|
- `JevProvider`, `OpenAIDecisionsProvider`, `CloudflareDecisionsProvider`: native provider classes.
|
|
313
|
+
- `box(instructions)` and `JevProvider.createDecision(request, options?)`:
|
|
314
|
+
bounding boxes and native JSON assets; see the [Jev guide](../guides/JEV.md).
|
|
307
315
|
- `scoreLevels(instructions, levels)` and the array overload of `choice`:
|
|
308
316
|
labelled rubrics and typed string/boolean options, with provider capability checks.
|
|
309
317
|
- `OpenAIDecisionsProvider.createDecision(request, options?)`: dedicated native
|
|
@@ -314,9 +322,9 @@ automatic model fallback. The CLI has a separate streaming JSONL implementation.
|
|
|
314
322
|
an own `input.model` property or an explicitly supplied default; inherited
|
|
315
323
|
models are ignored, and it never selects a Jev model.
|
|
316
324
|
Question builders and schema generation validate without selecting an inference model.
|
|
317
|
-
- `validateResult(input, questions, { native = false, probabilityDecimalPlaces })`: snapshot supplied
|
|
325
|
+
- `validateResult(input, questions, { native = false, nullableUsage = false, probabilityDecimalPlaces })`: snapshot supplied
|
|
318
326
|
questions and validate the canonical result; native mode requires confidence
|
|
319
|
-
and reported counts.
|
|
327
|
+
and reported counts unless the provider explicitly enables nullable usage.
|
|
320
328
|
- `decideChoice(answer, { minProbability, minMargin = 0, abstainOptions = [], probabilityDecimalPlaces })`:
|
|
321
329
|
returns a policy result, never executes an action. `minProbability` is required.
|
|
322
330
|
- `DecisionError`, `publicError(error)`: public structured failure handling.
|
|
@@ -11,6 +11,10 @@ reference does not imply that authenticated inference was run against its servic
|
|
|
11
11
|
| TypeSafe request/response API | https://docs.typesafe.ai/api |
|
|
12
12
|
| TypeSafe JavaScript examples | https://docs.typesafe.ai/sdk/javascript |
|
|
13
13
|
| Native model listing and aliases | https://docs.typesafe.ai/models |
|
|
14
|
+
| Jev image assets and experimental opt-in | https://docs.typesafe.ai/images |
|
|
15
|
+
| Jev bounding boxes | https://docs.typesafe.ai/primitives/box |
|
|
16
|
+
| Jev 1.14 release | https://typesafe.ai/blog/jev-1-14 |
|
|
17
|
+
| Jev nullable usage compatibility | https://docs.typesafe.ai/sdk/javascript/changelog |
|
|
14
18
|
| Choice decisions | https://docs.typesafe.ai/primitives/choice |
|
|
15
19
|
| Noul probabilities | https://docs.typesafe.ai/primitives/noul |
|
|
16
20
|
| Score rubric and weighted expectation | https://docs.typesafe.ai/primitives/score |
|
package/package.json
CHANGED
|
@@ -29,13 +29,27 @@
|
|
|
29
29
|
"$ref": "#/$defs/retries"
|
|
30
30
|
},
|
|
31
31
|
"maxRequestBytes": {
|
|
32
|
-
"
|
|
32
|
+
"type": "integer",
|
|
33
|
+
"minimum": 1,
|
|
34
|
+
"maximum": 33554432
|
|
33
35
|
},
|
|
34
36
|
"maxResponseBytes": {
|
|
35
37
|
"$ref": "#/$defs/bytes"
|
|
36
38
|
},
|
|
37
39
|
"provider": {
|
|
38
40
|
"const": "jev"
|
|
41
|
+
},
|
|
42
|
+
"dangerZone": {
|
|
43
|
+
"type": "object",
|
|
44
|
+
"additionalProperties": false,
|
|
45
|
+
"properties": {
|
|
46
|
+
"images": {
|
|
47
|
+
"type": "boolean"
|
|
48
|
+
},
|
|
49
|
+
"longContext": {
|
|
50
|
+
"type": "boolean"
|
|
51
|
+
}
|
|
52
|
+
}
|
|
39
53
|
}
|
|
40
54
|
}
|
|
41
55
|
},
|
package/src/capabilities.mjs
CHANGED
|
@@ -2,6 +2,7 @@ import { DecisionError, requireCondition as check } from './errors.mjs';
|
|
|
2
2
|
import { cloneJson, freezeJson, isRecord } from './validation.mjs';
|
|
3
3
|
import { CLOUDFLARE_MODELS } from './providers/cloudflare-profile.mjs';
|
|
4
4
|
import { openaiModelProfile } from './providers/openai-profile.mjs';
|
|
5
|
+
import { jevFeatures } from './providers/jev-profile.mjs';
|
|
5
6
|
|
|
6
7
|
/** Conservative defaults preserve the pre-existing custom-provider contract. */
|
|
7
8
|
export const LEGACY_CAPABILITIES = freezeJson({
|
|
@@ -9,6 +10,7 @@ export const LEGACY_CAPABILITIES = freezeJson({
|
|
|
9
10
|
labeledScores: false, safetyIdentifier: false,
|
|
10
11
|
maxImages: 0, maxChoiceOptions: 255, maxScoreLevels: 10,
|
|
11
12
|
audio: false, videos: false, maxAudioClips: 0, maxVideos: 0,
|
|
13
|
+
boxes: false,
|
|
12
14
|
});
|
|
13
15
|
|
|
14
16
|
const CLOUDFLARE_CAPABILITIES = freezeJson({
|
|
@@ -16,7 +18,9 @@ const CLOUDFLARE_CAPABILITIES = freezeJson({
|
|
|
16
18
|
labeledScores: true, safetyIdentifier: false, maxImages: 4, maxChoiceOptions: 255, maxScoreLevels: 10,
|
|
17
19
|
});
|
|
18
20
|
|
|
19
|
-
export function builtInCapabilities(type, model) {
|
|
21
|
+
export function builtInCapabilities(type, model, options = {}) {
|
|
22
|
+
if (type === 'jev') return freezeJson({ ...LEGACY_CAPABILITIES,
|
|
23
|
+
...jevFeatures(model, Object.hasOwn(options, 'dangerZone') ? options.dangerZone : undefined) });
|
|
20
24
|
if (type === 'cloudflare-decisions') {
|
|
21
25
|
const key = typeof model === 'string' ? model.trim().replace(/^@cf\/cloudflare\//, '') : '';
|
|
22
26
|
const profile = Object.hasOwn(CLOUDFLARE_MODELS, key) ? CLOUDFLARE_MODELS[key] : undefined;
|
|
@@ -45,7 +49,7 @@ export function providerCapabilities(provider, model) {
|
|
|
45
49
|
check(isRecord(profile) && Object.keys(profile).every(key => Object.hasOwn(LEGACY_CAPABILITIES, key)),
|
|
46
50
|
'Invalid capability profile.', 'CONFIGURATION_ERROR');
|
|
47
51
|
const result = { ...LEGACY_CAPABILITIES, ...profile };
|
|
48
|
-
for (const key of ['supported', 'orderedInput', 'images', 'typedChoices', 'labeledScores', 'safetyIdentifier', 'audio', 'videos']) {
|
|
52
|
+
for (const key of ['supported', 'orderedInput', 'images', 'typedChoices', 'labeledScores', 'safetyIdentifier', 'audio', 'videos', 'boxes']) {
|
|
49
53
|
check(typeof result[key] === 'boolean', 'Capability flags must be boolean.', 'CONFIGURATION_ERROR');
|
|
50
54
|
}
|
|
51
55
|
for (const key of ['maxImages', 'maxChoiceOptions', 'maxScoreLevels', 'maxAudioClips', 'maxVideos']) {
|
|
@@ -75,6 +79,7 @@ export function assertCapabilities(request, capabilities) {
|
|
|
75
79
|
}
|
|
76
80
|
if (Object.hasOwn(request, 'safetyIdentifier')) requireFeature(capabilities.safetyIdentifier, 'safetyIdentifier');
|
|
77
81
|
for (const q of Object.values(request.questions)) {
|
|
82
|
+
if (q.type === 'box') requireFeature(capabilities.boxes, 'box questions');
|
|
78
83
|
if (q.options) requireFeature(capabilities.typedChoices, 'typed choices');
|
|
79
84
|
if (q.levels) requireFeature(capabilities.labeledScores, 'labelled scores');
|
|
80
85
|
const choices = q.options?.length ?? (q.type === 'choice' ? Object.keys(q.criteria).length : 0);
|
|
@@ -86,6 +91,7 @@ export function assertCapabilities(request, capabilities) {
|
|
|
86
91
|
}
|
|
87
92
|
|
|
88
93
|
export function commonSchemaVersion(request) {
|
|
94
|
+
if (Object.values(request.questions).some(q => q.type === 'box')) return 4;
|
|
89
95
|
if (request.input?.some(part => ['audio', 'video'].includes(part.type))) return 3;
|
|
90
96
|
return Object.hasOwn(request, 'input') || Object.hasOwn(request, 'safetyIdentifier') ||
|
|
91
97
|
Object.values(request.questions).some(q => q.options || q.levels) ? 2 : 1;
|
|
@@ -2,13 +2,14 @@ import { requireCondition as check } from '../errors.mjs';
|
|
|
2
2
|
import { cloneJson, isRecord } from '../validation.mjs';
|
|
3
3
|
import { cloudflareGateway, validateCloudflareLimits } from '../providers/cloudflare-profile.mjs';
|
|
4
4
|
import { generationOptions } from '../custom/generative/shared.mjs';
|
|
5
|
+
import { jevDangerZone, jevRequestLimit } from '../providers/jev-profile.mjs';
|
|
5
6
|
|
|
6
7
|
export const PROVIDERS = ['jev', 'openai-decisions', 'cloudflare-decisions', 'custom-decision', 'custom-generative'];
|
|
7
8
|
export const PRESETS = ['openai-compatible', 'openrouter', 'anthropic'];
|
|
8
9
|
export const TRANSPORT = ['baseURL', 'maxRetries', 'maxRequestBytes', 'maxResponseBytes'];
|
|
9
10
|
export const GENERATION = ['maxTokens', 'responseFormat', 'tokenParameter', 'parameters', 'noAuth'];
|
|
10
11
|
export const PROVIDER_FIELDS = [...TRANSPORT, ...GENERATION, 'apiKeyEnv', 'model', 'preset', 'module',
|
|
11
|
-
'options', 'accountId', 'rejectIfBusy', 'gateway'];
|
|
12
|
+
'options', 'accountId', 'rejectIfBusy', 'gateway', 'dangerZone'];
|
|
12
13
|
const FIELDS = new Set(['$schema', 'schemaVersion', 'provider', 'timeoutMs', ...PROVIDER_FIELDS]);
|
|
13
14
|
export const NUMERIC = new Set(['timeoutMs', 'maxRetries', 'maxRequestBytes', 'maxResponseBytes', 'maxTokens']);
|
|
14
15
|
export const KEY_ENVS = { jev: 'TYPESAFE_API_KEY', 'openai-decisions': 'OPENAI_API_KEY',
|
|
@@ -56,7 +57,14 @@ export function validateConfig(input, { complete = false } = {}) {
|
|
|
56
57
|
check(config.module === undefined || ['custom-decision', 'custom-generative'].includes(config.provider),
|
|
57
58
|
'module requires custom-decision or custom-generative.', 'CONFIGURATION_ERROR');
|
|
58
59
|
check(config.options === undefined || isModule(config), 'options requires a custom provider module.', 'CONFIGURATION_ERROR');
|
|
60
|
+
// Validate nested shape even when a partial file omits its provider selector.
|
|
61
|
+
if (Object.hasOwn(config, 'dangerZone')) config.dangerZone = jevDangerZone(config.dangerZone);
|
|
59
62
|
if (config.provider !== undefined) {
|
|
63
|
+
if (config.provider !== 'jev') check(!Object.hasOwn(config, 'dangerZone'),
|
|
64
|
+
'dangerZone requires Jev.', 'CONFIGURATION_ERROR');
|
|
65
|
+
else {
|
|
66
|
+
jevRequestLimit(config.maxRequestBytes);
|
|
67
|
+
}
|
|
60
68
|
if (config.provider !== 'cloudflare-decisions') check(['accountId', 'rejectIfBusy', 'gateway'].every(key => config[key] === undefined),
|
|
61
69
|
'Cloudflare settings require cloudflare-decisions.', 'CONFIGURATION_ERROR');
|
|
62
70
|
else {
|