@fayegram-ai/decision-bridge 0.1.0 → 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.
Files changed (49) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/README.md +20 -14
  3. package/docs/README.md +5 -4
  4. package/docs/development/ARCHITECTURE.md +26 -3
  5. package/docs/development/DESIGN.md +11 -0
  6. package/docs/development/TESTING.md +23 -1
  7. package/docs/guides/BROWSER.md +3 -0
  8. package/docs/guides/CLOUDFLARE_DECISIONS.md +2 -2
  9. package/docs/guides/CUSTOM_PROVIDERS.md +4 -2
  10. package/docs/guides/GETTING_STARTED.md +1 -1
  11. package/docs/guides/JEV.md +174 -0
  12. package/docs/guides/OPENAI_DECISIONS.md +46 -4
  13. package/docs/guides/PLATFORMS.md +2 -2
  14. package/docs/guides/SWITCHING_MODELS.md +10 -4
  15. package/docs/guides/TROUBLESHOOTING.md +14 -0
  16. package/docs/reference/CLI.md +26 -4
  17. package/docs/reference/CONFIGURATION.md +12 -5
  18. package/docs/reference/ERRORS.md +5 -2
  19. package/docs/reference/PROVIDERS.md +20 -7
  20. package/docs/reference/SDK.md +22 -8
  21. package/docs/reference/SOURCES.md +4 -0
  22. package/examples/configs/openai-decisions.json +1 -1
  23. package/examples/decisions.native.json +1 -1
  24. package/package.json +1 -1
  25. package/schemas/decision.config.schema.json +15 -1
  26. package/src/capabilities.mjs +11 -8
  27. package/src/cli/config-validation.mjs +9 -1
  28. package/src/cli/config.mjs +17 -3
  29. package/src/cli/decisions.mjs +10 -0
  30. package/src/cli/initialize.mjs +8 -2
  31. package/src/cli/main.mjs +16 -4
  32. package/src/decisions.d.mts +5 -0
  33. package/src/index.d.mts +30 -8
  34. package/src/index.mjs +1 -1
  35. package/src/jev.d.mts +16 -0
  36. package/src/probabilities.mjs +6 -3
  37. package/src/providers/cloudflare-images.mjs +2 -58
  38. package/src/providers/decisions-preflight.mjs +18 -7
  39. package/src/providers/decisions-validation.mjs +3 -2
  40. package/src/providers/image-header.mjs +59 -0
  41. package/src/providers/jev-images.mjs +90 -0
  42. package/src/providers/jev-preflight.mjs +61 -0
  43. package/src/providers/jev-profile.mjs +37 -0
  44. package/src/providers/jev.mjs +32 -13
  45. package/src/providers/openai-decisions.mjs +17 -10
  46. package/src/providers/openai-profile.mjs +24 -0
  47. package/src/questions.mjs +2 -0
  48. package/src/validation.mjs +13 -6
  49. package/src/version.mjs +1 -1
package/CHANGELOG.md CHANGED
@@ -2,6 +2,15 @@
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
+
10
+ ## 0.1.1
11
+
12
+ - Add OpenAI `default`/`luna` selectors and requested/resolved model metadata; improve CLI configuration and documentation.
13
+
5
14
  ## 0.1.0
6
15
 
7
16
  Initial release of Decision Bridge as `@fayegram-ai/decision-bridge`.
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.0 · Node.js 22.16+ or modern browsers (SDK) · ESM · zero runtime dependencies**
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).
@@ -41,24 +41,30 @@ This is an independent project. The custom generative presets identify their
41
41
  probabilities as elicited model outputs.
42
42
  Changing providers does **not** make their accuracy or calibration equivalent.
43
43
 
44
- ## Supported models
44
+ ## Model selectors
45
45
 
46
- The built-in decision providers support these model selectors in this release:
46
+ Use these model selectors with the built-in decision providers:
47
47
 
48
- | Decision provider | Model selector | Accepted alias | Provider default |
49
- | --- | --- | --- | --- |
50
- | Jev through TypeSafe (`jev`) | `jev-latest` | — | `jev-latest` |
51
- | OpenAI Decisions (`openai-decisions`) | `gpt-6-luna` | — | `gpt-6-luna` |
52
- | Cloudflare (`cloudflare-decisions`) | `clef` | `@cf/cloudflare/clef` | `clef` |
53
- | Cloudflare (`cloudflare-decisions`) | `clef-flash` | `@cf/cloudflare/clef-flash` | — |
54
- | Cloudflare (`cloudflare-decisions`) | `clef-omni` | `@cf/cloudflare/clef-omni` | — |
48
+ | Decision provider | Model selectors | Provider default |
49
+ | --- | --- | --- |
50
+ | Jev through TypeSafe (`jev`) | `jev-latest` | `jev-latest` |
51
+ | OpenAI Decisions (`openai-decisions`) | `default`, `luna` | `default` |
52
+ | Cloudflare (`cloudflare-decisions`) | `clef`, `@cf/cloudflare/clef` | `clef` |
53
+ | Cloudflare (`cloudflare-decisions`) | `clef-flash`, `@cf/cloudflare/clef-flash` | — |
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.
60
- OpenAI Decisions currently accepts only `gpt-6-luna` in this integration.
61
- Cloudflare accepts only the three models above, in short or full-alias form.
60
+ For OpenAI Decisions, `default` selects the provider default and `luna` selects
61
+ the supported Luna-family model. Decision Bridge resolves selectors to supported
62
+ upstream model IDs before calling the service. Mappings are fixed by the installed
63
+ Decision Bridge release. Explicit supported model IDs can also be selected; see
64
+ the [OpenAI model selection guide](docs/guides/OPENAI_DECISIONS.md#model-selection)
65
+ for details. Results retain the selected value in `meta.requestedModel`,
66
+ the outgoing ID in `meta.resolvedModel`, and the service-reported model in `model`.
67
+ Cloudflare accepts only the three models above, in short or full form.
62
68
  Model discovery is unsupported for OpenAI Decisions and Cloudflare.
63
69
 
64
70
  Additional decision protocols use [custom decision providers](docs/guides/CUSTOM_DECISION.md).
@@ -74,7 +80,7 @@ All native providers support shared state and the common `choice`, `noul`, and
74
80
 
75
81
  | Provider | Additional supported features | Guide |
76
82
  | --- | --- | --- |
77
- | Jev | Native decisions through the TypeSafe API | [Provider reference](docs/reference/PROVIDERS.md#native-jev) |
83
+ | Jev | Native decisions, opt-in images, boxes, and long context through TypeSafe | [Jev guide](docs/guides/JEV.md) |
78
84
  | OpenAI Decisions | Ordered text/images, typed choices, labelled scores, safety identifiers, native access | [OpenAI Decisions](docs/guides/OPENAI_DECISIONS.md) |
79
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) |
80
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
@@ -7,8 +7,8 @@ Install `@fayegram-ai/decision-bridge` with npm; the
7
7
  [getting started guide](guides/GETTING_STARTED.md#install-into-your-application)
8
8
  also covers installation from a verified archive.
9
9
  The hosted playground is [Decision Playground](https://decision-pg.fayegram.com/).
10
- The root README lists [supported model selectors and aliases](../README.md#supported-models),
11
- including the distinction between built-in decision models and custom generative presets.
10
+ See [model selectors and provider defaults](../README.md#model-selectors) for
11
+ built-in decision models and the separate custom generative presets.
12
12
 
13
13
  Decision Bridge is a JavaScript SDK with an optional command runner. It evaluates
14
14
  supplied `state` or ordered `input`, plus `questions`, with an explicitly selected
@@ -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,7 +27,8 @@ 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
- | [OpenAI Decisions](guides/OPENAI_DECISIONS.md) | Native/common decision access, ordered images, typed values, and capability checks |
30
+ | [Jev](guides/JEV.md) | Common/native images, boxes, experimental long context, model selection, and CLI opt-ins |
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 |
33
34
  | [Custom providers](guides/CUSTOM_PROVIDERS.md) | Common classified contract and explicit CLI module loading |
@@ -5,7 +5,7 @@
5
5
  Decision Bridge exposes one application contract for structured decisions. The
6
6
  bridge owns request snapshots, common validation, extension sequencing, the total
7
7
  deadline, final result validation, immutable results, and bounded observations.
8
- A Provider owns its API encoding, transport, decoding, model defaults,
8
+ A provider owns its API encoding, transport, decoding, model selection,
9
9
  capabilities, and native operations. Multiple models sharing a protocol can use
10
10
  one provider implementation.
11
11
 
@@ -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.
@@ -46,6 +46,26 @@ shared evaluation deadline and extension lifecycle.
46
46
  Application policy decides whether a downstream action is permitted. The SDK
47
47
  returns decisions without executing actions or maintaining an agent loop.
48
48
 
49
+ ## Model selection and request preparation
50
+
51
+ The bridge applies the provider's configured default when a request omits `model`.
52
+ Its validated request and extension context retain that selected string. A provider
53
+ may resolve a selection to an upstream ID while preparing its outgoing request;
54
+ the shared provider contract has no selector-resolution hook.
55
+
56
+ OpenAI's `openai-profile.mjs` owns the `default` selection, accepted selectors,
57
+ upstream targets, and capabilities. Common and native preparation retain the
58
+ validated selection separately from the resolved native request. Preflight returns
59
+ the selected request, while serialization and byte-limit checks use the resolved
60
+ request. Common evaluation and native `createDecision()` share dispatch, which
61
+ sends only that resolved request.
62
+
63
+ Successful OpenAI calls report the selected string in `meta.requestedModel` and
64
+ the outgoing ID in `meta.resolvedModel`. The response's `model` retains the
65
+ service-reported identity. CLI offline validation and execution use the same
66
+ preflight, and generated OpenAI requests inherit selection from configuration.
67
+ See [OpenAI model selection](../guides/OPENAI_DECISIONS.md#model-selection).
68
+
49
69
  ## Module map
50
70
 
51
71
  | Module | Responsibility |
@@ -61,6 +81,8 @@ returns decisions without executing actions or maintaining an agent loop.
61
81
  | `src/custom/generative/` | Opt-in protocol presets, schema, prompts, and result derivation |
62
82
  | `schemas/decision.config.schema.json` | Shipped CLI configuration structure and editor support |
63
83
  | `src/providers/` | API orchestration, model profiles, preflight, codecs, bounded image/audio/video inspection, and transports |
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 |
64
86
  | `src/embedded.mjs` | Shared embedded data URL and canonical base64 checks |
65
87
  | `src/transport.mjs`, `src/response-transport.mjs` | Credential destinations, bounded bodies, safe errors, retries |
66
88
  | `src/async.mjs` | Deadlines and cancellation races |
@@ -81,7 +103,8 @@ claiming equivalent statistical semantics across models.
81
103
 
82
104
  The bridge takes result-validation policy from the provider contract. Cloudflare
83
105
  uses an allowance for four-decimal distributions; other built-ins retain the
84
- baseline. Response metadata cannot relax validation. See the [SDK reference](../reference/SDK.md).
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).
85
108
  Application code passes that precision explicitly when using `decideChoice`; the
86
109
  policy helper does not infer it from the answer or its metadata.
87
110
 
@@ -43,6 +43,17 @@ Read JSON config only when named. Load custom ESM only when explicitly selected.
43
43
  Protect credential destinations and expose bounded callbacks. Consequence: plugins
44
44
  are powerful and must be trusted; cancellation is not a JavaScript sandbox.
45
45
 
46
+ ## Release-owned model selectors
47
+
48
+ OpenAI Decisions offers `default` for the provider's default supported model and
49
+ `luna` for the supported Luna-family model, alongside explicit supported upstream
50
+ IDs. The installed package fixes the target and capability profile for each
51
+ selector. The provider resolves it locally before serialization; no discovery,
52
+ automatic upgrade, or fallback occurs during a call. Consequence: applications can
53
+ use a stable selection string while inspecting selected, outgoing, and reported
54
+ model identities separately. A future target change requires an intentional
55
+ package update and verification of that model's protocol and capabilities.
56
+
46
57
  ## Conservative retries and independent observations
47
58
 
48
59
  Retry selected explicit transient HTTP statuses within a deadline. Do not retry
@@ -42,7 +42,7 @@ as evidence that every environment passed.
42
42
  - `transport.test.mjs`: HTTP policy, limits, retries, cancellation, and deadlines.
43
43
  - `deadlines.test.mjs`: synchronous preparation/dispatch/completion and inherited budgets.
44
44
  - `result-validation.test.mjs`: provider-selected precision and policy-hook boundaries.
45
- - `decisions*.test.mjs`: native/common OpenAI codecs, boundaries, preflight, CLI, and smoke-helper fixtures.
45
+ - `decisions*.test.mjs`: native/common OpenAI codecs, selectors and model identities, boundaries, preflight, CLI, and smoke-helper fixtures.
46
46
  - `cloudflare*.test.mjs`: models, images, codecs, REST/binding/Gateway arguments, errors, and CLI limits.
47
47
  - `custom-providers.test.mjs`, `custom-config.test.mjs`: classified SDK paths, provenance, presets/modules, schema and initialization.
48
48
  - `generative-helpers.test.mjs`: exported prompt/normalization helper contracts and unsupported input rejection.
@@ -63,6 +63,28 @@ All model responses used by ordinary tests are synthetic. HTTP integration serve
63
63
  listen on loopback. Tests do not require account keys or make paid model calls.
64
64
  Test workspaces are temporary.
65
65
 
66
+ ### OpenAI model-selector coverage
67
+
68
+ For changes to OpenAI selection or preparation, run the focused suites from the
69
+ source root:
70
+
71
+ ```text
72
+ node --test test/decisions-selectors.test.mjs test/decisions-preflight.test.mjs test/decisions-cli.test.mjs
73
+ ```
74
+
75
+ These cover omitted, `default`, `luna`, and explicit upstream selection; unsupported
76
+ and malformed values; independently selected, outgoing, and reported identities;
77
+ capabilities and extension context; immutable input; SDK batch preflight; resolved
78
+ wire-byte limits; CLI precedence and mixed-selector rows; and generated requests
79
+ that inherit later configuration changes. Existing Decisions suites also cover
80
+ revalidation after input preparation, refusals, retries, and deadlines.
81
+
82
+ Type and installed-package checks exercise metadata declarations, SDK/CLI
83
+ selection, and browser execution without Node globals. Use `npm run verify` for
84
+ the complete integration check. A selector mapping change must be verified against
85
+ the target model's protocol and capabilities; local fixtures alone do not establish
86
+ compatibility with a newly selected upstream model.
87
+
66
88
  ## Optional authenticated provider smoke check
67
89
 
68
90
  Live inference is explicitly opted in and can incur charges. Configure credentials
@@ -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
@@ -4,8 +4,8 @@ Use `cloudflare-decisions` for hosted inference with `clef` (the default),
4
4
  `clef-flash`, or `clef-omni`. All three support common bridge requests and the
5
5
  dedicated native API. Each accepts its full `@cf/cloudflare/<model>` alias.
6
6
  The provider normalizes the endpoint identifier and the required input selector together.
7
- See the root README's [model list](../../README.md#supported-models) for the exact
8
- short selectors and full aliases.
7
+ See the [model selector inventory](../../README.md#model-selectors) for supported
8
+ short selectors and full forms.
9
9
 
10
10
  | Model | Hosted context, in tokens | Default client request budget | Media |
11
11
  | --- | ---: | ---: | --- |
@@ -17,7 +17,7 @@ extension path.
17
17
  `Provider` requires a nonempty `name`, explicit `kind: 'decision' | 'generative'`,
18
18
  and `evaluate(request, { signal? })`. Optional fields and hooks are:
19
19
 
20
- - `defaultModel`: a nonempty model ID, otherwise the request must supply one.
20
+ - `defaultModel`: a nonempty selection string, otherwise the request must supply one.
21
21
  - `probabilitySource`: known provenance; generative providers use `elicited`.
22
22
  - `getCapabilities(model)`: a pure synchronous capability profile.
23
23
  - `validateRequest(request)`: pure synchronous provider preflight; no inference.
@@ -31,7 +31,9 @@ that implement this contract directly. Missing or invalid kinds fail at construc
31
31
  `bridge.providerKind` and `result.meta.providerKind` come from the contract and
32
32
  cannot be overridden by response metadata.
33
33
 
34
- The request is already snapshotted, validated, resolved to a model, and frozen.
34
+ The request is already snapshotted, validated, supplied with an effective model
35
+ selection, and frozen. Its model string retains the selection; any mapping to an
36
+ upstream ID belongs to the provider's preparation and transport.
35
37
  Return canonical `{ model, answers, usage, meta? }`; the bridge validates and
36
38
  freezes the result. Custom providers own API encoding, transport, response mapping,
37
39
  credential destinations, bounded bodies, safe errors, and cancellation cleanup.
@@ -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.0.tgz
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)
@@ -1,13 +1,50 @@
1
1
  # OpenAI Decisions
2
2
 
3
- The `openai-decisions` provider implements the native `POST /v1/decisions` API,
4
- supporting `gpt-6-luna` as its default and only accepted model in this release.
3
+ The `openai-decisions` provider implements the native `POST /v1/decisions` API.
4
+ Its default model selector is `default`; `luna` selects the supported Luna-family
5
+ model, and `gpt-6-luna` selects that explicit upstream ID. Decision Bridge resolves
6
+ all three selections to `gpt-6-luna` in this release before calling the service.
5
7
  This integration follows the official [Decisions guide](https://developers.openai.com/api/docs/guides/decisions)
6
8
  and [API reference](https://developers.openai.com/api/reference/resources/decisions/methods/create).
7
9
  Account access and remote limits still apply. Unknown models fail locally with
8
10
  `UNSUPPORTED_CAPABILITY`. The opt-in `openai-compatible` preset in `custom/generative` continues
9
11
  using Chat Completions.
10
12
 
13
+ ## Model selection
14
+
15
+ ```javascript
16
+ import { createProvider } from '@fayegram-ai/decision-bridge';
17
+
18
+ createProvider({ type: 'openai-decisions' }); // Selects default.
19
+ createProvider({ type: 'openai-decisions', model: 'luna' });
20
+ createProvider({ type: 'openai-decisions', model: 'gpt-6-luna' });
21
+ ```
22
+
23
+ These are alternative configurations. An omitted request `model` inherits the
24
+ provider's configured selection; an explicit request `model` overrides it.
25
+ With no provider or request model configured, the selection is `default`:
26
+
27
+ | Selection | Selected value | Current upstream target |
28
+ | --- | --- | --- |
29
+ | Omitted, with no configured model | `default` | `gpt-6-luna` |
30
+ | `default` | `default` | `gpt-6-luna` |
31
+ | `luna` | `luna` | `gpt-6-luna` |
32
+ | `gpt-6-luna` | `gpt-6-luna` | `gpt-6-luna` |
33
+
34
+ Mappings are fixed by the installed Decision Bridge release; there is
35
+ no runtime model discovery, automatic upgrading, or fallback after failure.
36
+ The `default` selector follows the provider default, while `luna` stays within
37
+ the Luna family. The resolved upstream model must have a supported capability
38
+ profile before a selector can target it.
39
+
40
+ `provider.defaultModel` and `bridge.defaultModel` expose the configured selection,
41
+ using `default` when provider configuration omits `model`. Validated requests and
42
+ extension context retain the effective selected value. Successful common
43
+ and native calls expose `meta.requestedModel` for that selection and
44
+ `meta.resolvedModel` for the upstream ID sent. The common `result.model` and native
45
+ `decision.model` preserve the service-reported identity, which may differ from
46
+ the outgoing ID. Byte limits apply to the resolved wire request.
47
+
11
48
  ## Common bridge access
12
49
 
13
50
  Set `OPENAI_API_KEY` in the process environment:
@@ -141,14 +178,15 @@ const { decision, meta } = await provider.createDecision({
141
178
  }, { signal: controller.signal });
142
179
  ```
143
180
 
144
- An omitted model resolves to the provider default. Native input accepts text or
181
+ An omitted model inherits the provider's configured selection. Native input accepts text or
145
182
  multiple user messages containing text or ordered `input_text`/`input_image`
146
183
  parts. Only user roles are supported. Files, external image URLs, audio, tools,
147
184
  and item references are rejected locally. Exported `NativeDecisionRequest` and
148
185
  related types describe this format.
149
186
 
150
187
  `decision` preserves native answer arrays, optional question names, probabilities,
151
- confidence, and full usage. `meta` contains transport duration, attempt count,
188
+ confidence, and full usage. `meta` has the exported `OpenAIDecisionsTransportMetadata`
189
+ shape: requested/resolved model identities, transport duration, attempt count,
152
190
  and request ID when available. Results are immutable. This method bypasses
153
191
  common bridge extensions.
154
192
 
@@ -197,6 +235,10 @@ provider. Native evaluation/validation/batch require an explicit file or `-`.
197
235
  Mode is never inferred from JSON. Initialization writes a native request, which
198
236
  must still be evaluated with `--native`. Offline validation checks built-in
199
237
  capabilities without credentials; custom capabilities are checked at evaluation.
238
+ OpenAI initialization stores the model selection in configuration and omits it
239
+ from the generated request so later configuration changes apply. The default
240
+ configuration uses `default`. Offline validation reports the selected value as
241
+ `model` and the outgoing upstream ID as `resolvedModel`.
200
242
  Decisions offline validation also checks native field limits and the configured
201
243
  request byte limit in both modes.
202
244
 
@@ -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.0"
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.0"
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
@@ -4,7 +4,7 @@ The bridge's request contains `questions`, either `state` or ordered `input`, an
4
4
  optionally `model`. Ordered input and richer question types require provider capabilities.
5
5
  The provider translates it into that service's wire protocol and validates the
6
6
  response. Select a provider when constructing your SDK bridge.
7
- The root README lists [supported model selectors and aliases](../../README.md#supported-models).
7
+ See [model selectors and provider defaults](../../README.md#model-selectors).
8
8
 
9
9
  ## Native and custom selection
10
10
 
@@ -72,7 +72,7 @@ example and provide that backend's credential in `.env`:
72
72
  | Native SDK `createProvider` type | Credential variable | Model selection |
73
73
  | --- | --- | --- |
74
74
  | `jev` | `TYPESAFE_API_KEY` | Defaults to `jev-latest`; an explicit model overrides it |
75
- | `openai-decisions` | `OPENAI_API_KEY` | Defaults to `gpt-6-luna` |
75
+ | `openai-decisions` | `OPENAI_API_KEY` | Defaults to `default`; also accepts `luna` and explicit `gpt-6-luna` |
76
76
  | `cloudflare-decisions` | `CLOUDFLARE_API_TOKEN` and `CLOUDFLARE_ACCOUNT_ID` for REST | Defaults to `clef`; also supports `clef-flash` and `clef-omni` |
77
77
 
78
78
  Custom generative presets use `createGenerativeProvider` instead. Their types are
@@ -83,7 +83,7 @@ using the following native alternatives:
83
83
 
84
84
  ```javascript
85
85
  createProvider({ type: 'jev', model: 'jev-latest' });
86
- createProvider({ type: 'openai-decisions', model: 'gpt-6-luna' });
86
+ createProvider({ type: 'openai-decisions', model: 'luna' });
87
87
  createProvider({ type: 'cloudflare-decisions', model: 'clef-flash' });
88
88
  createGenerativeProvider({ type: 'openai-compatible', model: process.env.DECISION_MODEL });
89
89
  createGenerativeProvider({ type: 'anthropic', model: process.env.DECISION_MODEL });
@@ -96,6 +96,12 @@ The SDK does not automatically read `DECISION_*` settings: this example passes
96
96
  `process.env.DECISION_MODEL` explicitly. The SDK factory property is **`type`**;
97
97
  a command-runner JSON profile uses **`provider`**.
98
98
 
99
+ OpenAI's `default` selector chooses the provider default and `luna` chooses the
100
+ supported Luna-family model. Both currently resolve to upstream `gpt-6-luna`
101
+ through Decision Bridge. Use `model: 'gpt-6-luna'` to select that explicit upstream
102
+ ID. Mappings are fixed by the installed package release; results expose the
103
+ selection in `meta.requestedModel` and outgoing ID in `meta.resolvedModel`.
104
+
99
105
  For Jev and the generative providers, list models with `await bridge.listModels()`.
100
106
  OpenAI Decisions and Cloudflare Clef do not implement model discovery and return
101
107
  `UNSUPPORTED_OPERATION`; their capability profiles do not prove account availability.
@@ -143,7 +149,7 @@ uppercase model placeholders with IDs available to your account/server:
143
149
 
144
150
  ```bash
145
151
  npm exec -- decision-bridge evaluate ./my-decisions/request.json --provider jev --model jev-latest --env-file .env
146
- npm exec -- decision-bridge evaluate ./my-decisions/request.json --provider openai-decisions --model gpt-6-luna --env-file .env
152
+ npm exec -- decision-bridge evaluate ./my-decisions/request.json --provider openai-decisions --model default --env-file .env
147
153
  npm exec -- decision-bridge evaluate ./my-decisions/request.json --provider cloudflare-decisions --model clef-flash --env-file .env
148
154
  npm exec -- decision-bridge evaluate ./my-decisions/request.json --provider custom-generative --preset openrouter --model VENDOR/MODEL_ID --env-file .env
149
155
  npm exec -- decision-bridge evaluate ./my-decisions/request.json --provider custom-generative --preset openai-compatible --model MODEL_ID --env-file .env
@@ -18,6 +18,20 @@ explicit config. A compatible base includes its version prefix, not the final
18
18
  `/chat/completions` path. Jev and the custom Anthropic preset require origins
19
19
  without a path. See [configuration](../reference/CONFIGURATION.md#precedence).
20
20
 
21
+ ## OpenAI reports a versioned model after I select default or luna
22
+
23
+ `default` and `luna` are Decision Bridge model selectors. Both currently resolve
24
+ to `gpt-6-luna`, which is the upstream ID sent to OpenAI. Successful common and
25
+ native calls expose the selection as `meta.requestedModel` and the outgoing ID
26
+ as `meta.resolvedModel`. `result.model` or native `decision.model` preserves the
27
+ service-reported identity, which may differ from the outgoing ID.
28
+
29
+ An omitted request model inherits the configured model. OpenAI initialization
30
+ omits `model` from its generated requests so later configuration edits apply.
31
+ If selection fails with `UNSUPPORTED_CAPABILITY`, check the
32
+ [accepted selectors](OPENAI_DECISIONS.md#model-selection); the bridge does not
33
+ discover another model or fall back after failure.
34
+
21
35
  ## Structured output is rejected
22
36
 
23
37
  Check that the selected endpoint/model supports the requested `json_schema` mode.