@fayegram-ai/decision-bridge 0.1.2 → 0.1.3

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 (72) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/CONTRIBUTING.md +5 -3
  3. package/README.md +24 -8
  4. package/SECURITY.md +18 -11
  5. package/docs/README.md +17 -4
  6. package/docs/development/ARCHITECTURE.md +32 -5
  7. package/docs/development/DESIGN.md +21 -3
  8. package/docs/development/RELEASING.md +7 -3
  9. package/docs/development/REPOSITORY_LAYOUT.md +2 -0
  10. package/docs/development/TESTING.md +31 -3
  11. package/docs/guides/BROWSER.md +5 -0
  12. package/docs/guides/CLOUDFLARE_DECISIONS.md +24 -46
  13. package/docs/guides/CUSTOMIZATION.md +8 -2
  14. package/docs/guides/CUSTOM_GENERATIVE.md +5 -3
  15. package/docs/guides/CUSTOM_PROVIDERS.md +5 -3
  16. package/docs/guides/EXTRACTION.md +125 -0
  17. package/docs/guides/GETTING_STARTED.md +8 -4
  18. package/docs/guides/JEV.md +13 -20
  19. package/docs/guides/LIVE_DECISIONS.md +163 -0
  20. package/docs/guides/OPENAI_DECISIONS.md +52 -24
  21. package/docs/guides/PLATFORMS.md +3 -3
  22. package/docs/guides/SWITCHING_MODELS.md +6 -2
  23. package/docs/guides/TROUBLESHOOTING.md +25 -0
  24. package/docs/reference/CLI.md +48 -10
  25. package/docs/reference/CONFIGURATION.md +31 -8
  26. package/docs/reference/ERRORS.md +41 -12
  27. package/docs/reference/PROVIDERS.md +19 -6
  28. package/docs/reference/SDK.md +62 -24
  29. package/docs/reference/SOURCES.md +7 -0
  30. package/examples/extraction.mjs +16 -0
  31. package/examples/live-decisions.mjs +24 -0
  32. package/package.json +11 -1
  33. package/schemas/decision.config.schema.json +88 -11
  34. package/src/bridge.mjs +9 -6
  35. package/src/capabilities.mjs +28 -4
  36. package/src/cli/config-validation.mjs +4 -4
  37. package/src/cli/config.mjs +4 -2
  38. package/src/cli/initialize.mjs +8 -4
  39. package/src/cli/live.mjs +63 -0
  40. package/src/cli/main.mjs +35 -12
  41. package/src/cli/provider-loader.mjs +3 -2
  42. package/src/cloudflare-decisions.d.mts +12 -5
  43. package/src/decisions.d.mts +28 -4
  44. package/src/errors.mjs +7 -1
  45. package/src/extraction/index.d.mts +66 -0
  46. package/src/extraction/index.mjs +78 -0
  47. package/src/extraction/validation.mjs +105 -0
  48. package/src/index.d.mts +18 -4
  49. package/src/input.mjs +21 -3
  50. package/src/live/index.d.mts +73 -0
  51. package/src/live/index.mjs +170 -0
  52. package/src/live/state.mjs +125 -0
  53. package/src/live/validation.mjs +122 -0
  54. package/src/providers/cloudflare-images.mjs +3 -9
  55. package/src/providers/cloudflare-media.mjs +5 -10
  56. package/src/providers/cloudflare-preflight.mjs +4 -3
  57. package/src/providers/cloudflare-profile.mjs +10 -14
  58. package/src/providers/cloudflare-transport.mjs +12 -5
  59. package/src/providers/cloudflare-validation.mjs +3 -1
  60. package/src/providers/decisions-codec.mjs +10 -5
  61. package/src/providers/decisions-input.mjs +120 -0
  62. package/src/providers/decisions-validation.mjs +37 -69
  63. package/src/providers/jev-images.mjs +2 -8
  64. package/src/providers/jev-preflight.mjs +1 -0
  65. package/src/providers/jev-profile.mjs +2 -2
  66. package/src/providers/media-binary.mjs +0 -7
  67. package/src/providers/openai-decisions.mjs +2 -1
  68. package/src/providers/openai-errors.mjs +23 -0
  69. package/src/providers/openai-profile.mjs +2 -1
  70. package/src/response-transport.mjs +84 -17
  71. package/src/validation.mjs +26 -14
  72. package/src/version.mjs +1 -1
@@ -72,8 +72,9 @@ or zero-based level indices. It checks probabilities, derives argmax/weighted
72
72
  scores and matching legends, and marks absent usage as unknown. It does not repair
73
73
  JSON, strip Markdown, or create confidence. `buildPrompt` and `normalizeGenerated`
74
74
  independently validate and snapshot the request. They require shared state and
75
- legacy questions, and reject ordered input, typed choices, labelled scores, and
76
- safety identifiers with `UNSUPPORTED_CAPABILITY`. Malformed request JSON raises
75
+ legacy questions, and reject ordered input, conversation/tool history, remote
76
+ images, prompt-cache controls, typed choices, labelled scores and safety
77
+ identifiers with `UNSUPPORTED_CAPABILITY`. Malformed request JSON raises
77
78
  `VALIDATION_ERROR`; unsupported input is never silently discarded. New modules
78
79
  implement their own encoding and normalization for richer capabilities.
79
80
 
@@ -110,7 +111,8 @@ provenance and `confidenceSource: 'unavailable'`, and rejects returned native
110
111
  confidence claims or answer confidence fields. Their output is an estimate elicited
111
112
  from a model, not a native probability, logprob, or calibration guarantee.
112
113
  Presets support shared state and legacy `choice`, `noul`, and `score`; ordered
113
- media, typed choices, labelled scores, and safety identifiers are unsupported.
114
+ media, conversation/tool history, remote images, prompt-cache controls, typed
115
+ choices, labelled scores and safety identifiers are unsupported.
114
116
  A new module may declare capabilities only after implementing and validating them.
115
117
 
116
118
  ## OpenAI-compatible servers
@@ -41,7 +41,9 @@ Internal transport helpers are not stable public exports. Delegate a maintained
41
41
  preset for a protocol already supported, or implement and test your own transport.
42
42
 
43
43
  Capability omissions retain the legacy shared-state and question profile. Audio
44
- and video additions default to false/zero. Declare richer forms only when their
44
+ and video additions default to false/zero; conversation, tool history, remote
45
+ images and prompt caching default to false. Explicit quantitative custom limits
46
+ are enforced; `null` leaves that admission limit to the service. Declare richer forms only when their
45
47
  encoding and validation are implemented. The bridge runs preflight again after
46
48
  preparation hooks. Unknown usage is null; no provider should invent token counts,
47
49
  confidence, or calibration. Generative native-provenance claims are rejected.
@@ -68,8 +70,8 @@ relative to that file; flag paths
68
70
  resolve relative to the working directory. Explicit modules execute trusted code;
69
71
  this extension point is not a sandbox. No module is discovered automatically.
70
72
 
71
- `init` creates an honest service implementation placeholder when no implementation
72
- is selected. When given an existing module, it references that module without
73
+ `init` creates a provider module with an unimplemented service call when no
74
+ implementation is selected. When given an existing module, it references that module without
73
75
  loading or overwriting it. Offline `validate` never imports custom modules or
74
76
  requires credentials; it reports structure-only validation for unknown protocols.
75
77
  `bridge.validate()` on an instantiated provider includes capabilities and preflight.
@@ -0,0 +1,125 @@
1
+ # Clairic extraction
2
+
3
+ Requires **0.1.3 or later**. See [version availability](../README.md#version-availability)
4
+ and [installation](GETTING_STARTED.md#install-into-your-application).
5
+
6
+ Import extraction from `@fayegram-ai/decision-bridge/extraction`. This operation
7
+ returns typed values and predictive statistics, using Cloudflare Clairic through
8
+ REST or an injected Workers AI binding. Its result is independent of the decision
9
+ bridge's question/answer contract.
10
+
11
+ ```javascript
12
+ import { CloudflareExtractionProvider } from '@fayegram-ai/decision-bridge/extraction';
13
+
14
+ const provider = new CloudflareExtractionProvider();
15
+ const { extraction, meta } = await provider.extract({
16
+ state: 'Invoice total: 1080 USD. Due date: 2026-11-01.',
17
+ reference_date: '2026-10-20',
18
+ fields: {
19
+ amount: { type: 'number', unit: 'USD' },
20
+ due_date: { type: 'date' },
21
+ payment_days: { type: 'estimate', min: 0, max: 90, step: 1 },
22
+ },
23
+ options: { include_quantiles: true, return_state_text: true },
24
+ });
25
+ console.log(extraction.answers.amount.value, extraction.truncated, meta.requestId);
26
+ ```
27
+
28
+ REST reads `CLOUDFLARE_API_TOKEN` and `CLOUDFLARE_ACCOUNT_ID` only for the official
29
+ origin, or accepts explicit `apiKey` and `accountId`. Custom origins require
30
+ explicit credentials. The default model is `clairic`; the full selector
31
+ `@cf/cloudflare/clairic` is also accepted. Requested, resolved and reported model
32
+ identities remain separate. There is no model-discovery request.
33
+
34
+ ## Fields and results
35
+
36
+ | Type | Definition | Returned value |
37
+ | --- | --- | --- |
38
+ | `text` | Instructions describing a text value | String or null |
39
+ | `number` | Optional unit, integer and decimal settings | Number or null |
40
+ | `date`, `time`, `datetime` | Instructions describing the temporal value | String or null; no implicit timezone conversion |
41
+ | `duration` | Unit: seconds, minutes, hours, days, weeks, months or years | Number or null |
42
+ | `list` | Required `items`: text, number or date | Ordered list, including an empty list, or null |
43
+ | `estimate` | Required numeric or ISO-date `min` and `max`; optional `step` and `scale` | Number, date string or null, plus available distribution summaries |
44
+ | `forecast` | Prediction bounds plus optional positive `horizon` and `interval` | Native value and ordered predictive `steps`, retained as JSON |
45
+
46
+ `instructions` and `null_threshold` describe individual fields. `null_threshold`
47
+ must be greater than zero and at most one. `number` and `duration` accept boolean
48
+ `integer` and nonnegative integer `decimals`; numeric lists also accept `decimals`.
49
+ Grids support positive numeric steps or `month`/`year`;
50
+ `scale` is `linear` or `log`. Forecast intervals are `step`, `minute`, `hour`,
51
+ `day`, `week`, `month`, `quarter`, or `year`. Server ceilings remain server-owned.
52
+
53
+ The immutable envelope is `{ extraction, meta }`. The native extraction retains
54
+ all returned fields: values, guesses, confidence, `p_null`, spans, means,
55
+ medians, `p10`/`p90`, bounds probabilities, quantiles, forecast steps, `truncated`,
56
+ optional `state_text`, and usage including optional pass counts. Unknown native
57
+ response fields are retained after safe JSON validation.
58
+
59
+ A null value can coexist with a guess and span. Typed output does not establish
60
+ factual accuracy. The adapter does not recalculate predictions or token totals.
61
+ Predictive substructures with an underspecified schema remain JSON values in the
62
+ types; span offsets are preserved without assuming JavaScript slicing units.
63
+
64
+ ## Images, binding and Gateway
65
+
66
+ Provide text `state`, embedded `images`, or both. Images accept PNG/JPEG/WebP data
67
+ URLs or `{ content_type, base64 }` objects. Remote images are not supported by
68
+ this operation. The adapter checks format and container structure, while the
69
+ service owns image-count, decoded-size, dimension and context admission.
70
+
71
+ ```javascript
72
+ const provider = new CloudflareExtractionProvider({
73
+ transport: 'binding',
74
+ ai: env.AI,
75
+ gateway: { id: 'existing-gateway', skipCache: true },
76
+ });
77
+ ```
78
+
79
+ `include_quantiles` and `return_state_text` stay in the model input's `options`.
80
+ `rejectIfBusy` is an execution setting, configurable on the provider or request
81
+ options; binding dispatch places it in the third `ai.run` argument. Gateway
82
+ settings use the same routing and diagnostics as the Clef provider. A service
83
+ rejection of an execution setting is reported without dropping the setting.
84
+
85
+ ## Validation, batching and errors
86
+
87
+ `validateExtractionRequest(request, options?)` is credential-free offline
88
+ validation. `provider.validate(request)` uses the configured provider settings.
89
+ Both check structure and client resource budgets, without promising admission.
90
+
91
+ Request/response budgets default to 8 MiB each and can be configured through
92
+ 64 MiB. Requests are checked before media decoding. `extract(request, { signal })`
93
+ accepts an `AbortSignal`. Set `timeoutMs` on the provider constructor to bound
94
+ validation, dispatch and response handling; extraction call options accept only
95
+ `signal` and have no per-call timeout override.
96
+ Retries default to zero. Billing/allocation errors are not retried even when
97
+ retries are enabled; temporary eligible failures use the shared error policy.
98
+ See [errors and recovery](../reference/ERRORS.md).
99
+
100
+ `extractBatch(provider, requests, { concurrency, signal, stopOnError })` validates
101
+ all array requests before dispatch and returns ordered `{ index, ok, result }`
102
+ or `{ index, ok, error }` records. Concurrency defaults to four and is a client
103
+ execution setting, independent of any service quota.
104
+ Batch results retain each caller's `requestedModel`, including the full
105
+ `@cf/cloudflare/clairic` alias, while `resolvedModel` and dispatched input use
106
+ `clairic`, just as for individual extraction calls.
107
+
108
+ ## CLI
109
+
110
+ ```shell
111
+ decision extraction init my-extraction
112
+ decision extraction validate request.json
113
+ decision extraction run request.json --env-file .env
114
+ decision extraction batch requests.jsonl --concurrency 4 --env-file .env
115
+ ```
116
+
117
+ The namespace defaults to `cloudflare-extraction`; incompatible explicit
118
+ providers are rejected. Configuration schema version remains 1. Use the existing
119
+ Cloudflare account, credential, Gateway, timeout and retry settings. Inference
120
+ options belong in request JSON. Validation is offline and reports `fieldCount`.
121
+ Streaming JSONL batches can complete valid rows before a later row fails.
122
+
123
+ See the [runnable extraction example](../../examples/extraction.mjs), the
124
+ [official model schema](https://developers.cloudflare.com/workers-ai/models/clairic/)
125
+ and [extraction concepts](https://developers.cloudflare.com/workers-ai/concepts/extraction-models/).
@@ -20,18 +20,22 @@ In your application's directory, install the package from npm:
20
20
  npm install @fayegram-ai/decision-bridge
21
21
  ```
22
22
 
23
- You can also install a verified local archive, replacing the path below. See
24
- [packaging and release](../development/RELEASING.md) to build and verify one from
25
- a source checkout:
23
+ You can also install a verified package archive. Replace the example archive
24
+ path with your own; see [packaging and release](../development/RELEASING.md) to
25
+ build and verify one from a source checkout:
26
26
 
27
27
  ```bash
28
- npm install /path/to/fayegram-ai-decision-bridge-0.1.2.tgz
28
+ npm install /path/to/fayegram-ai-decision-bridge-0.1.3.tgz
29
29
  ```
30
30
 
31
31
  The installed package contains the SDK, declarations, command runner, examples,
32
32
  and docs. It runs without compilation; source development scripts and tests are
33
33
  excluded.
34
34
 
35
+ Check the installed version with `npm exec -- decision-bridge --version`.
36
+ Use the documentation bundled with your installed package, or select the
37
+ matching [versioned documentation](../README.md#version-availability).
38
+
35
39
  ## Configure credentials
36
40
 
37
41
  Create `.env` in your application's directory and edit it locally:
@@ -114,25 +114,18 @@ choose your own presence/confidence thresholds using representative images.
114
114
  Jev token usage may be `null`; that means unknown, never zero. Native confidence
115
115
  and all other result checks remain enforced.
116
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.
117
+ ## Images and client budgets
118
+
119
+ PNG/JPEG formats, canonical base64, positive dimensions, still-image structure
120
+ and asset reference semantics are checked locally. Service image dimensions,
121
+ decoded/processed sizes and context admission remain upstream. The bridge does
122
+ not resize, rotate or re-encode images. Prepare upright pixels in the application.
123
+
124
+ Jev requests default to a 32 MiB client serialized-JSON budget. An explicit
125
+ `maxRequestBytes` can select a budget through 64 MiB. Responses default to 8 MiB.
126
+ General JSON processing retains a 100-level depth and 200,000-node safeguard;
127
+ reference-pattern safeguards bound local regex construction. These are client
128
+ resource controls, independent of service quotas.
136
129
 
137
130
  ## CLI
138
131
 
@@ -155,7 +148,7 @@ decision-bridge batch native.jsonl --native --config decision.config.json --env-
155
148
 
156
149
  Common/native validation is offline and uses the same preflight as inference.
157
150
  `--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;
151
+ `models` command. CLI JSON/JSONL input defaults to 32 MiB per record and permits a larger explicit client budget through 64 MiB;
159
152
  the actual serialized request must also fit the configured provider ceiling.
160
153
 
161
154
  `--jev-images` / `--no-jev-images` and `--jev-long-context` /
@@ -0,0 +1,163 @@
1
+ # Live Decisions
2
+
3
+ Requires **0.1.3 or later**. See [version availability](../README.md#version-availability)
4
+ and [installation](GETTING_STARTED.md#install-into-your-application).
5
+
6
+ `@fayegram-ai/decision-bridge/live` attaches Decisions handling to an existing
7
+ GPT-Live connection. Your application owns authentication, audio, connection
8
+ setup and reconnection. The controller owns Decisions commands, acknowledgements
9
+ and conservative result correlation. It does not issue additional HTTP inference.
10
+
11
+ ```javascript
12
+ import { createLiveDecisions } from '@fayegram-ai/decision-bridge/live';
13
+
14
+ const live = createLiveDecisions({ transport: {
15
+ send(event) { connection.send(JSON.stringify(event)); },
16
+ subscribe(listener) {
17
+ const message = event => listener({ kind: 'event', event: JSON.parse(event.data) });
18
+ const closed = () => listener({ kind: 'close' });
19
+ const failed = () => listener({ kind: 'error' });
20
+ connection.addEventListener('message', message);
21
+ connection.addEventListener('close', closed);
22
+ connection.addEventListener('error', failed);
23
+ return () => {
24
+ connection.removeEventListener('message', message);
25
+ connection.removeEventListener('close', closed);
26
+ connection.removeEventListener('error', failed);
27
+ };
28
+ },
29
+ } });
30
+
31
+ live.subscribe(event => {
32
+ if (event.type === 'decision') {
33
+ console.log(event.decision, event.correlation);
34
+ }
35
+ });
36
+ await live.configure({
37
+ delegation: { type: 'decisions', decisions: {
38
+ model: 'gpt-6-luna',
39
+ questions: [{ type: 'predicate', name: 'ready', instructions: 'Is the requested action fully specified?' }],
40
+ } },
41
+ });
42
+ ```
43
+
44
+ The connection must already support the required Live events and Decisions
45
+ permissions. Start the session with Decisions delegation if it will delegate to
46
+ Decisions; Live does not allow changing the delegation type after startup.
47
+ `transport.subscribe` receives a listener for `{ kind: 'event',
48
+ event }`, `{ kind: 'close' }`, and `{ kind: 'error' }` notifications and must
49
+ return an unsubscribe function. `send` may return a promise. Dispose the
50
+ controller before replacing a connection; disposal does not close the connection.
51
+
52
+ ## Commands and acknowledgements
53
+
54
+ | Method | Completion |
55
+ | --- | --- |
56
+ | `configure(configuration, options?)` | Matching `session.updated` acknowledgement |
57
+ | `createItem(item, options?)` | Matching `decision.item.created` acknowledgement |
58
+ | `deleteItem(itemId, options?)` | Matching `decision.item.deleted` acknowledgement |
59
+ | `requestDecision(options?)` | Submission receipt, not an inference-result promise |
60
+ | `appendCommentary(content, { delegationId, ...options }?)` | Submission receipt, not a speech-completion promise |
61
+ | `subscribe(observer)` | Returns an unsubscribe function |
62
+ | `dispose()` | Cancels pending waits and detaches owned listeners |
63
+
64
+ Configuration accepts Decisions `delegation` and transcript `triggers`. Each
65
+ trigger specifies `type: 'decisions'`, `event_type` as input or output transcript
66
+ delta, and `decisions: { questions }`. Trigger arrays replace the trigger list;
67
+ an empty list disables them. Omitted fields preserve server configuration.
68
+ Questions use the native predicate/choice/score representation.
69
+
70
+ Decision items are user messages containing text or embedded image parts. Live
71
+ items do not inherit the HTTP Decisions conversation, remote-image or cache
72
+ input extensions. Item creation appends evidence for later evaluations; it does
73
+ not itself request evaluation. IDs are generated uniquely for commands.
74
+
75
+ An application can execute a selected action, append its confirmed outcome with
76
+ `createItem`, wait for acknowledgement, then submit commentary. The controller
77
+ does not execute application actions. Commentary is forwarded with the explicit
78
+ delegation ID or null; any service rejection is reported as an error event.
79
+
80
+ ## Results and correlation
81
+
82
+ Completed native decisions arrive as `type: 'decision'` notifications containing
83
+ the full model, ordered answers and usage. Native refusal answers are preserved.
84
+ The controller does not fabricate partial common success from a refusal.
85
+
86
+ `correlation` contains `matched`, `stale`, source event ID/type, delegation ID,
87
+ trigger ID and a configuration generation when known. Match quality describes
88
+ available protocol evidence, not model accuracy.
89
+
90
+ - Transcript fragments are tracked in delivery order separately for input and
91
+ output. Results can arrive out of order; older/equal source results are stale.
92
+ A newer result from an observed source makes older results stale even when its
93
+ configuration cannot be matched. An unknown source or conflicting direction
94
+ cannot advance the observed order.
95
+ - Configuration becomes active after acknowledgement. Sources observed during
96
+ an in-flight or unresolved update remain unmatched.
97
+ - A rejected update preserves the last acknowledged configuration. If unresolved
98
+ update IDs are evicted from history, future sources stay unmatched for this
99
+ controller's lifetime. Attach a new controller with a known accepted snapshot
100
+ to restore correlation after losing that history.
101
+ - A known delegation or transcript source carries its question snapshot. Missing
102
+ or evicted source/configuration history remains observable and unmatched.
103
+ - Duplicate server event IDs produce `duplicate` notifications within retained
104
+ history. Delegation results consume their source snapshot; repeated results
105
+ cannot become newly matched work.
106
+ - Manual request IDs are not assumed to be echoed by completion events. A manual
107
+ submission receipt cannot be used as proof that a later result belongs to it.
108
+ - Unrelated events do not enter the Decisions state machine.
109
+
110
+ Only apply application actions when your own policy accepts the result and its
111
+ correlation. A supplied starting `configuration` asserts that the application
112
+ already knows the connection's accepted Decisions configuration.
113
+
114
+ ## Resources and failures
115
+
116
+ Defaults are a 30-second command deadline, 128 pending operations, 4096 retained
117
+ history entries per correlation map, and 8 MiB command/event budgets (configurable
118
+ through 64 MiB). These are local resource budgets, independent of server quotas.
119
+ History eviction can make late results unmatched. No service RPM/TPM enforcement,
120
+ automatic command replay or reconnect policy is introduced.
121
+
122
+ Call options accept `signal` and `timeoutMs`. Disconnect and disposal settle
123
+ pending operations. Invalid signal values fail with `CONFIGURATION_ERROR` before
124
+ dispatch. Application cleanup exceptions are isolated, including when the
125
+ connection closes synchronously during attachment.
126
+ A timed-out update may still be accepted upstream; a later
127
+ acknowledgement updates observed state without resolving an unrelated call.
128
+ Cancellation before dispatch preserves the accepted configuration. A correlated
129
+ item acknowledgement with the wrong item ID rejects that operation with
130
+ `INVALID_RESPONSE` immediately.
131
+ Observer failures emit safe `observer_error` notifications and do not repeat work.
132
+ Subscription changes during delivery apply to subsequent notifications; a
133
+ recipient is called at most once for the current notification.
134
+ Server errors are normalized without exposing their raw messages.
135
+ Malformed server events, including nested items and configuration snapshots,
136
+ report `INVALID_RESPONSE`. Unknown validation exceptions use a generic message.
137
+
138
+ ## Offline protocol tools
139
+
140
+ ```shell
141
+ decision live validate configuration.json --kind config
142
+ decision live validate command.json --kind command
143
+ decision live validate event.json --kind event
144
+ decision live replay session.jsonl
145
+ ```
146
+
147
+ Replay records are `{ "direction": "client" | "server", "event": ... }`.
148
+ The same correlation reducer processes them and emits ordered JSONL records.
149
+ No connection, audio device or credential is used. Malformed rows are reported
150
+ individually and make the final exit status nonzero.
151
+ Offline `live validate` treats malformed event files as caller input: it reports
152
+ `VALIDATION_ERROR` and exits 2. Replay retains `INVALID_RESPONSE` for malformed
153
+ server records, continues processing later records, and exits 1 if any row fails.
154
+ A replay represents one connection lifecycle. `session.closed` releases its
155
+ history; subsequent records report `CONNECTION_CLOSED` and make the exit status
156
+ nonzero. Use a separate replay for a replacement connection. Configuration
157
+ updates without event IDs are valid wire commands, but prevent trustworthy
158
+ configuration correlation for the rest of that replay. Controller-generated
159
+ commands always include unique IDs.
160
+
161
+ See the [connection adapter example](../../examples/live-decisions.mjs),
162
+ [OpenAI guide](https://developers.openai.com/api/docs/guides/decisions-voice) and
163
+ [Live protocol reference](https://developers.openai.com/api/reference/resources/live/primary-websocket).
@@ -1,5 +1,8 @@
1
1
  # OpenAI Decisions
2
2
 
3
+ Conversation/tool history, remote images and prompt caching require **0.1.3 or
4
+ later**. See [version availability](../README.md#version-availability).
5
+
3
6
  The `openai-decisions` provider implements the native `POST /v1/decisions` API.
4
7
  Its default model selector is `default`; `luna` selects the supported Luna-family
5
8
  model, and `gpt-6-luna` selects that explicit upstream ID. Decision Bridge resolves
@@ -80,8 +83,9 @@ That native choice's confidence is retained in provider metadata.
80
83
 
81
84
  ## Ordered text and images
82
85
 
83
- Provide exactly one of `state` or `input`. An existing JSON array supplied as
84
- `state` retains its original meaning. New `input` is a nonempty ordered array:
86
+ Choose exactly one of `state`, ordered `input` or `conversation`. An existing
87
+ JSON array supplied as `state` retains its original meaning. Ordered `input` is
88
+ a nonempty array:
85
89
 
86
90
  ```javascript
87
91
  const result = await bridge.evaluate({
@@ -95,9 +99,9 @@ const result = await bridge.evaluate({
95
99
  });
96
100
  ```
97
101
 
98
- Images must be nonempty inline base64 data URLs, such as
99
- `data:image/png;base64,...`. The bridge does not fetch image URLs or read files.
100
- Convert image bytes in your application. OpenAI permits at most 128 images.
102
+ Images accept inline base64 data URLs or an exclusive common `url` HTTP(S)
103
+ reference. Native images use `image_url` for either form. References are forwarded;
104
+ the bridge does not fetch URLs or read files. Image-count admission is server-owned.
101
105
  Detail accepts `low`, `high`, `auto`, `original`, or null; omission uses the service
102
106
  default. Text/image ordering is preserved.
103
107
 
@@ -105,9 +109,8 @@ The default transport request/response limits are 8 MiB each, including encoded
105
109
  images. Set `maxRequestBytes` explicitly for larger requests, up to the existing
106
110
  64 MiB ceiling. These local limits do not override service limits.
107
111
 
108
- `safetyIdentifier` is an optional per-request opaque string of at most 128
109
- Unicode characters, or null. It maps to `safety_identifier`; avoid private identity
110
- data. Character limits count Unicode code points rather than UTF-16 code units.
112
+ `safetyIdentifier` is an optional per-request opaque string or null. It maps
113
+ to `safety_identifier`; length admission remains upstream.
111
114
 
112
115
  ## Typed choices and labelled scores
113
116
 
@@ -130,35 +133,38 @@ coercion to object keys are not supported. TypeScript preserves literal unions.
130
133
  `scoreLevels` stores ordered `levels` instead of `criteria` and requires at least
131
134
  two `{ label, description? }` objects. Its answer retains the numeric score and
132
135
  index-keyed probability map, with the original level objects in the legend.
133
- OpenAI choice questions require 2–255 unique options in both common forms and
134
- native requests. Labelled scores do not inherit Jev's 10-level limit; legacy
135
- score criteria retain the 2–10-level limit. JSON snapshots and transport caps
136
- apply to all requests.
136
+ Choices require at least two distinct options for OpenAI. Service count ceilings
137
+ are not enforced locally. Both labelled and legacy scores retain ordered levels;
138
+ JSON safety and configured client wire budgets apply to all forms.
137
139
 
138
140
  ## Capabilities and preparation
139
141
 
140
142
  `bridge.getCapabilities(model?)` synchronously reports support and limits for
141
143
  ordered input, images, typed choices, labelled scores, and safety identifiers.
144
+ It also reports conversation/tool history, remote images and prompt caching.
142
145
  `bridge.validate(request)` resolves the model, snapshots/freezes the request,
143
146
  and checks capabilities without inference. Unsupported combinations fail before
144
147
  dispatch with `UNSUPPORTED_CAPABILITY`.
145
148
 
146
- Preflight also checks the encoded native field limits and the complete UTF-8 wire
149
+ Preflight also checks the encoded native structure and the complete UTF-8 wire
147
150
  body against `maxRequestBytes`. SDK array batches check every raw request before
148
151
  dispatching any entry. Prepared input is revalidated during each evaluation.
149
152
 
150
- Jev, OpenAI-compatible, OpenRouter, and Anthropic currently support the legacy
151
- common forms. Existing custom providers default to that profile; implement
153
+ Jev supports shared state and ordered text, with experimental images and boxes;
154
+ the maintained generative presets use legacy shared-state forms. Existing custom
155
+ providers default to the legacy profile; implement
152
156
  `getCapabilities(model)` and corresponding behavior to support new forms.
153
157
 
154
- Use `prepareInput(parts, context)` for ordered input and `prepareState` for state.
158
+ Use `prepareInput(parts, context)` for ordered input, `prepareState` for state,
159
+ and `prepareConversation(items, context)` for conversation history.
155
160
  A preparation extension must implement the hook for the form being used;
156
161
  incompatible extensions fail explicitly rather than being skipped. Extensions
157
- can implement both hooks. `onResult` works with either form and runs only after
162
+ can implement all three preparation hooks. `onResult` works with every form and runs only after
158
163
  success, with the existing isolated-failure policy.
159
164
 
160
165
  Legacy common requests retain `meta.schemaVersion: 1`. New input/question forms
161
- or safety identifiers use version 2.
166
+ or safety identifiers use version 2. Conversation, remote image URLs or cache
167
+ controls select version 5; see [conversation and prompt caching](#conversation-and-prompt-caching).
162
168
 
163
169
  ## Dedicated native access
164
170
 
@@ -178,11 +184,11 @@ const { decision, meta } = await provider.createDecision({
178
184
  }, { signal: controller.signal });
179
185
  ```
180
186
 
181
- An omitted model inherits the provider's configured selection. Native input accepts text or
182
- multiple user messages containing text or ordered `input_text`/`input_image`
183
- parts. Only user roles are supported. Files, external image URLs, audio, tools,
184
- and item references are rejected locally. Exported `NativeDecisionRequest` and
185
- related types describe this format.
187
+ An omitted model inherits the provider's configured selection. Native input accepts
188
+ text, role-aware messages, assistant output/refusal content and function/custom-tool
189
+ calls and outputs. Images may be embedded or remote HTTP(S) references. File IDs,
190
+ audio and item references remain unsupported. Exported native types describe the
191
+ Decisions-specific representation; tool payload strings remain verbatim.
186
192
 
187
193
  `decision` preserves native answer arrays, optional question names, probabilities,
188
194
  confidence, and full usage. `meta` has the exported `OpenAIDecisionsTransportMetadata`
@@ -239,7 +245,7 @@ OpenAI initialization stores the model selection in configuration and omits it
239
245
  from the generated request so later configuration changes apply. The default
240
246
  configuration uses `default`. Offline validation reports the selected value as
241
247
  `model` and the outgoing upstream ID as `resolvedModel`.
242
- Decisions offline validation also checks native field limits and the configured
248
+ Decisions offline validation also checks native structure and the configured
243
249
  request byte limit in both modes.
244
250
 
245
251
  The `schema` command remains a generative utility and rejects the new request
@@ -250,3 +256,25 @@ From a source checkout, the optional `npm run smoke:live -- --decisions --env-fi
250
256
  checks four bounded requests when `RUN_LIVE_TESTS=1` is explicitly set. It checks
251
257
  protocol behavior rather than prediction quality, disables retries, and prints
252
258
  only model identities and token usage. Normal verification never runs it.
259
+
260
+ ## Conversation and prompt caching
261
+
262
+ Common requests select exactly one of `state`, ordered `input` or `conversation`.
263
+ Conversation items use `NativeDecisionInputItem`: user/developer/system messages,
264
+ assistant messages with optional commentary/final_answer phase, function calls,
265
+ custom tool calls and their outputs. Tool outputs reference preceding call IDs.
266
+ System/developer content is text; assistant parts are output text or refusal.
267
+
268
+ `promptCacheKey` and `promptCacheOptions` map to native `prompt_cache_key` and
269
+ `prompt_cache_options`. Options support implicit/explicit mode and Decisions'
270
+ 30m TTL. Eligible common text/image parts accept `promptCacheBreakpoint` with
271
+ explicit mode or null; native content uses `prompt_cache_breakpoint`. The adapter
272
+ preserves breakpoints, omission and explicit nulls without selecting cache writes.
273
+
274
+ Use `prepareConversation(items, context)` to transform conversation input.
275
+ Transformations are snapshotted, frozen and revalidated before dispatch. Capability
276
+ flags are `conversation`, `toolHistory`, `remoteImages` and `promptCaching`;
277
+ existing custom providers default to false. New-feature requests use common
278
+ schema version 5; existing forms retain versions 1–4.
279
+
280
+ See [Live Decisions](LIVE_DECISIONS.md) for the separate connection lifecycle.
@@ -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.2"
25
+ cd "C:\path\to\decision-bridge"
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.2"
51
+ cd "/path/to/decision-bridge"
52
52
  node --version
53
53
  node bin/decision.mjs validate examples/request.json
54
54
  cp .env.example .env
@@ -73,7 +73,7 @@ Install the package with npm from your application's directory:
73
73
  npm install @fayegram-ai/decision-bridge
74
74
  ```
75
75
 
76
- For installation from a verified local archive, see
76
+ For version requirements and installation from a verified local archive, see
77
77
  [getting started](GETTING_STARTED.md#install-into-your-application).
78
78
 
79
79
  Import from `@fayegram-ai/decision-bridge` in ESM JavaScript, or invoke the installed
@@ -1,7 +1,8 @@
1
1
  # Switching models without rewriting the application
2
2
 
3
- The bridge's request contains `questions`, either `state` or ordered `input`, and
4
- optionally `model`. Ordered input and richer question types require provider capabilities.
3
+ The bridge's request contains `questions`, exactly one of `state`, ordered `input`
4
+ or `conversation`, and optionally `model`. Ordered input, conversation/tool history,
5
+ remote images, cache controls and richer questions require provider capabilities.
5
6
  The provider translates it into that service's wire protocol and validates the
6
7
  response. Select a provider when constructing your SDK bridge.
7
8
  See [model selectors and provider defaults](../../README.md#model-selectors).
@@ -15,6 +16,9 @@ entry point. A new decision protocol uses [custom decision](CUSTOM_DECISION.md).
15
16
  The example below demonstrates the opt-in generative path; native alternatives
16
17
  follow it.
17
18
 
19
+ Clairic [extraction](EXTRACTION.md) and [Live Decisions](LIVE_DECISIONS.md) use
20
+ dedicated APIs. They cannot replace a provider in an existing `createBridge` call.
21
+
18
22
  ## SDK: same request, different provider
19
23
 
20
24
  Install the package as described in [getting started](GETTING_STARTED.md).
@@ -1,5 +1,13 @@
1
1
  # Troubleshooting
2
2
 
3
+ ## An export or command from these guides is missing
4
+
5
+ Run `npm exec -- decision-bridge --version` in the consuming project and compare
6
+ it with [version availability](../README.md#version-availability). The `/extraction`
7
+ and `/live` exports, their CLI commands, and expanded OpenAI history/cache inputs
8
+ require 0.1.3 or later. See [installation options](GETTING_STARTED.md#install-into-your-application)
9
+ to install a compatible version.
10
+
3
11
  ## The command cannot find a key
4
12
 
5
13
  General `node bin/decision.mjs ...` calls need exported environment variables or an
@@ -81,6 +89,23 @@ file output is not finalized in that case; stdout can contain a completed prefix
81
89
  Some requests may already have been sent/billed. Retrying an entire prefix can
82
90
  repeat work, so retain completed records externally when designing resumability.
83
91
 
92
+ ## Extraction or Live does not behave like bridge evaluation
93
+
94
+ For Clairic, use `CloudflareExtractionProvider` from the `/extraction` export or
95
+ the `extraction` CLI namespace with `cloudflare-extraction`. The root decision
96
+ factory and `createBridge` do not accept extraction providers. An explicit
97
+ provider from config or environment overrides the namespace default and must
98
+ match the operation. A null value, empty list or `truncated: true` can be a valid
99
+ native result; inspect it according to your application's needs.
100
+
101
+ For Live, `requestDecision` and `appendCommentary` resolve on submission. Consume
102
+ completed decisions through `subscribe`. An unmatched result indicates missing or
103
+ ambiguous source/configuration history; a stale result refers to older observed
104
+ transcript order. Neither is proof of a current request result. Disposal and
105
+ connection closure cancel pending waits. Malformed offline event validation exits
106
+ 2, while failed replay rows produce exit 1 and processing continues. See
107
+ [Live lifecycle](LIVE_DECISIONS.md#results-and-correlation).
108
+
84
109
  ## Type checks fail because tsc is missing
85
110
 
86
111
  Runtime and tests have no TypeScript dependency. Development type checks require