@fayegram-ai/decision-bridge 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/.env.example +10 -0
  2. package/CHANGELOG.md +75 -0
  3. package/CONTRIBUTING.md +57 -0
  4. package/LICENSE +21 -0
  5. package/README.md +307 -2
  6. package/SECURITY.md +88 -0
  7. package/bin/decision.mjs +15 -0
  8. package/docs/README.md +58 -0
  9. package/docs/development/ARCHITECTURE.md +118 -0
  10. package/docs/development/DESIGN.md +66 -0
  11. package/docs/development/README.md +12 -0
  12. package/docs/development/RELEASING.md +100 -0
  13. package/docs/development/REPOSITORY_LAYOUT.md +33 -0
  14. package/docs/development/TESTING.md +131 -0
  15. package/docs/guides/BROWSER.md +43 -0
  16. package/docs/guides/CLOUDFLARE_DECISIONS.md +374 -0
  17. package/docs/guides/CUSTOMIZATION.md +141 -0
  18. package/docs/guides/CUSTOM_DECISION.md +66 -0
  19. package/docs/guides/CUSTOM_GENERATIVE.md +164 -0
  20. package/docs/guides/CUSTOM_PROVIDERS.md +81 -0
  21. package/docs/guides/GETTING_STARTED.md +252 -0
  22. package/docs/guides/OPENAI_DECISIONS.md +210 -0
  23. package/docs/guides/PLATFORMS.md +107 -0
  24. package/docs/guides/SWITCHING_MODELS.md +202 -0
  25. package/docs/guides/TROUBLESHOOTING.md +82 -0
  26. package/docs/reference/CLI.md +202 -0
  27. package/docs/reference/CONFIGURATION.md +168 -0
  28. package/docs/reference/ERRORS.md +82 -0
  29. package/docs/reference/PROVIDERS.md +113 -0
  30. package/docs/reference/SDK.md +388 -0
  31. package/docs/reference/SOURCES.md +51 -0
  32. package/examples/basic.mjs +17 -0
  33. package/examples/batch.mjs +13 -0
  34. package/examples/cloudflare-decisions.mjs +22 -0
  35. package/examples/cloudflare-omni.mjs +32 -0
  36. package/examples/cloudflare-worker.mjs +21 -0
  37. package/examples/cloudflare.native.json +28 -0
  38. package/examples/configs/anthropic.json +9 -0
  39. package/examples/configs/cloudflare-decisions.json +8 -0
  40. package/examples/configs/custom-decision.json +9 -0
  41. package/examples/configs/custom-generative.json +14 -0
  42. package/examples/configs/jev.json +7 -0
  43. package/examples/configs/local.json +12 -0
  44. package/examples/configs/openai-decisions.json +7 -0
  45. package/examples/configs/openai.json +10 -0
  46. package/examples/configs/openrouter.json +10 -0
  47. package/examples/custom/decision-provider.mjs +15 -0
  48. package/examples/custom/generative-provider.mjs +13 -0
  49. package/examples/custom/openrouter.mjs +13 -0
  50. package/examples/customize.mjs +23 -0
  51. package/examples/decisions.native.json +19 -0
  52. package/examples/extended.mjs +43 -0
  53. package/examples/openai-decisions.mjs +20 -0
  54. package/examples/request.json +31 -0
  55. package/examples/requests.jsonl +2 -0
  56. package/package.json +87 -4
  57. package/schemas/decision.config.schema.json +553 -0
  58. package/src/async.mjs +63 -0
  59. package/src/batch.mjs +38 -0
  60. package/src/bridge.mjs +184 -0
  61. package/src/capabilities.mjs +95 -0
  62. package/src/cli/config-validation.mjs +89 -0
  63. package/src/cli/config.mjs +84 -0
  64. package/src/cli/decisions.mjs +19 -0
  65. package/src/cli/initialize.mjs +79 -0
  66. package/src/cli/io.mjs +171 -0
  67. package/src/cli/main.mjs +280 -0
  68. package/src/cli/ordered.mjs +43 -0
  69. package/src/cli/provider-loader.mjs +58 -0
  70. package/src/cloudflare-decisions.d.mts +78 -0
  71. package/src/custom/decision.d.mts +5 -0
  72. package/src/custom/decision.mjs +6 -0
  73. package/src/custom/definition.mjs +19 -0
  74. package/src/custom/generative/anthropic.mjs +75 -0
  75. package/src/custom/generative/index.d.mts +42 -0
  76. package/src/custom/generative/index.mjs +29 -0
  77. package/src/custom/generative/openai-compatible.mjs +101 -0
  78. package/src/custom/generative/schema.mjs +95 -0
  79. package/src/custom/generative/shared.mjs +39 -0
  80. package/src/decisions.d.mts +45 -0
  81. package/src/embedded.mjs +24 -0
  82. package/src/errors.mjs +49 -0
  83. package/src/index.d.mts +229 -0
  84. package/src/index.mjs +7 -0
  85. package/src/input.mjs +37 -0
  86. package/src/options.mjs +15 -0
  87. package/src/policy.mjs +44 -0
  88. package/src/probabilities.mjs +27 -0
  89. package/src/provider-contract.mjs +42 -0
  90. package/src/providers/cloudflare-audio.mjs +83 -0
  91. package/src/providers/cloudflare-codec.mjs +39 -0
  92. package/src/providers/cloudflare-decisions.mjs +81 -0
  93. package/src/providers/cloudflare-images.mjs +95 -0
  94. package/src/providers/cloudflare-media.mjs +36 -0
  95. package/src/providers/cloudflare-preflight.mjs +92 -0
  96. package/src/providers/cloudflare-profile.mjs +102 -0
  97. package/src/providers/cloudflare-transport.mjs +63 -0
  98. package/src/providers/cloudflare-validation.mjs +48 -0
  99. package/src/providers/cloudflare-video.mjs +84 -0
  100. package/src/providers/decisions-codec.mjs +61 -0
  101. package/src/providers/decisions-preflight.mjs +20 -0
  102. package/src/providers/decisions-validation.mjs +150 -0
  103. package/src/providers/index.mjs +26 -0
  104. package/src/providers/jev.mjs +51 -0
  105. package/src/providers/media-binary.mjs +51 -0
  106. package/src/providers/openai-decisions.mjs +51 -0
  107. package/src/questions.mjs +15 -0
  108. package/src/response-transport.mjs +176 -0
  109. package/src/runtime-env.mjs +4 -0
  110. package/src/transport.mjs +51 -0
  111. package/src/validation.mjs +245 -0
  112. package/src/version.mjs +2 -0
package/.env.example ADDED
@@ -0,0 +1,10 @@
1
+ # Set only the keys for providers you actually use. Never commit the populated .env.
2
+ TYPESAFE_API_KEY=replace_with_your_typesafe_api_key
3
+ # JEV_MODEL=jev-latest
4
+ # OPENAI_API_KEY=replace_with_your_openai_api_key
5
+ # CLOUDFLARE_ACCOUNT_ID=replace_with_your_cloudflare_account_id
6
+ # CLOUDFLARE_API_TOKEN=replace_with_your_cloudflare_api_token
7
+ # Custom generative preset credentials (opt-in custom/generative).
8
+ # The OpenAI-compatible preset shares OPENAI_API_KEY at the official OpenAI origin.
9
+ # OPENROUTER_API_KEY=replace_with_your_openrouter_api_key
10
+ # ANTHROPIC_API_KEY=replace_with_your_anthropic_api_key
package/CHANGELOG.md ADDED
@@ -0,0 +1,75 @@
1
+ # Changelog
2
+
3
+ Notable user-facing changes by version.
4
+
5
+ ## 0.1.0
6
+
7
+ Initial release of Decision Bridge as `@fayegram-ai/decision-bridge`.
8
+
9
+ ### SDK and providers
10
+
11
+ - Provider-neutral `createBridge` interface with explicit provider selection,
12
+ immutable requests/results, typed questions, capability preflight, context
13
+ preparation, bounded observations, and ordered batch evaluation.
14
+ - Native Jev, OpenAI Decisions, and Cloudflare Clef/Clef-flash/Clef-omni providers, alongside
15
+ explicit custom decision and generative paths. General-purpose adapters are
16
+ retained as maintained OpenAI-compatible, OpenRouter, and Anthropic presets in
17
+ `custom/generative`; the root factory and exports are native-only.
18
+ - Required decision/generative provider classification, authoritative
19
+ `providerKind` metadata, definition helpers, and generative provenance validation.
20
+ - Explicit CLI custom kinds with preset/module selection, initialization templates,
21
+ editor JSON Schema, and structure-only module validation without execution.
22
+ - Common/native OpenAI and Cloudflare access, ordered embedded images, typed
23
+ string/boolean choices, labelled score rubrics, and preserved native values.
24
+ - Clef-omni common/native WAV/MP3 audio and MP4/WebM video, grouped media ordering,
25
+ bounded container/duration inspection, and audio/video result schema version 3.
26
+ Omni defaults to a 36 MiB client request budget, configurable through 64 MiB;
27
+ older Clef models retain 13 MiB. Effective request models select their own
28
+ budgets without enlarging explicit smaller ceilings.
29
+ - Cloudflare REST and Workers AI binding transports, binding capacity rejection,
30
+ optional AI Gateway controls on both transports, and provider-selected
31
+ four-decimal probability allowance.
32
+ Enabled Clef/Clef-flash/Clef-omni REST busy options fail local preflight with
33
+ `UNSUPPORTED_CAPABILITY`, preventing predictably rejected inference requests; see the
34
+ [Cloudflare compatibility notes](docs/guides/CLOUDFLARE_DECISIONS.md#capacity-rejection-and-ai-gateway).
35
+ - Shared Cloudflare Gateway validation enforces 64-character names, cache TTL
36
+ from 60 seconds through 30 days, and at most five metadata entries without
37
+ caller-supplied `cf.*` keys. Invalid settings fail before dispatch; metadata
38
+ is never silently truncated or stripped.
39
+ - Choice policies accept explicit provider probability precision; OpenAI Decisions
40
+ preflight enforces its documented 2–255 choice-option range.
41
+ - Explicit native/elicited probability provenance and reported token accounting;
42
+ missing common usage remains null and generative confidence is not fabricated.
43
+ - Generative presets reserve tool/function controls, including legacy `functions`
44
+ and `function_call`, with matching CLI editor and runtime validation.
45
+ - Invalid async capability hooks raise configuration errors without leaving
46
+ rejected promises unobserved or dispatching inference.
47
+ - Custom decision provenance labels are validated as nonempty strings, while
48
+ preserving service-specific labels and provider defaults.
49
+ - Exported generative prompt and normalization helpers validate their complete
50
+ request profile, rejecting unsupported input instead of discarding it.
51
+ - Bounded requests/responses, cancellation, end-to-end deadlines, conservative
52
+ retries, strict response validation, and safe structured DecisionError details.
53
+ - Response-body deadlines also cover continuously ready streams; fragmented
54
+ responses use bounded byte storage. Model-list snapshots reject accessors
55
+ before reading their values.
56
+ - Choice policies reject sparse abstention arrays and accessor entries before
57
+ applying thresholds or abstention rules.
58
+
59
+ ### CLI and distribution
60
+
61
+ - `decision-bridge`, `decision`, and `faye-decision` commands for initialization, evaluation,
62
+ offline validation, generative schemas, supported model listing, and ordered
63
+ JSONL batches with common/native decision dispatch.
64
+ - CLI settings retain flags, environment, explicit JSON config, and default
65
+ precedence, including custom module request models and resolved module identity.
66
+ Its built-in provider default is Jev.
67
+ - JSONL record limits remain consistent when CRLF delimiters arrive in separate
68
+ chunks, without expanding the per-record or total input ceilings.
69
+ - Cloudflare CLI reads within 64 MiB, then uses model-specific SDK preflight for
70
+ embedded media, per-request overrides, and mixed-model batches. The JSONL total
71
+ cap remains 64 MiB and the configuration schema remains version 1.
72
+ - ESM source, browser-safe SDK imports, TypeScript declarations, Node.js 22.16+,
73
+ MIT licensing, and zero runtime dependencies.
74
+ - Consumer/provider guides, examples, cross-platform CI, functional/type checks,
75
+ and verification by offline installation of the exact npm tarball.
@@ -0,0 +1,57 @@
1
+ # Contributing
2
+
3
+ ## Report an issue or propose a change
4
+
5
+ Search [existing issues](https://github.com/Fayegram-AI/decision-bridge/issues) before
6
+ opening a new one. For a bug, include the bridge version, Node.js version,
7
+ operating system, a minimal reproducible request with synthetic data, expected
8
+ behavior, and actual behavior. For a feature proposal, describe the use case and
9
+ how it fits the provider-independent contract. Report vulnerabilities through the
10
+ private route in [SECURITY.md](SECURITY.md), not in an issue.
11
+
12
+ Use a source checkout with Node.js 22.16 or newer. No build step or runtime
13
+ dependencies are required. `npm ci --ignore-scripts` installs the pinned
14
+ development-only TypeScript compiler, official Workers declarations, and Ajv
15
+ configuration-schema validator from the lockfile. See the
16
+ [testing guide](docs/development/TESTING.md).
17
+
18
+ ## Understand the design
19
+
20
+ Start with the [architecture](docs/development/ARCHITECTURE.md),
21
+ [design rationale](docs/development/DESIGN.md), and
22
+ [repository layout](docs/development/REPOSITORY_LAYOUT.md).
23
+ Preserve the provider-independent contract of `state` or ordered `input` plus
24
+ `questions`, and explicit probability provenance. Add focused regression tests for bug fixes and wire-level
25
+ tests for protocol changes. Fixtures must not contain credentials or live-account
26
+ data; label synthetic responses as synthetic.
27
+
28
+ ## Make and verify a change
29
+
30
+ Work on a focused branch. Use ESM JavaScript, four-space indentation for new code,
31
+ LF line endings, and a final newline. Avoid unrelated reformatting of existing
32
+ files. Update `.d.mts` declarations and compile-time regressions when public APIs
33
+ change. Document user-visible changes in the changelog.
34
+
35
+ ```text
36
+ npm run verify
37
+ ```
38
+
39
+ Verification includes syntax/JSON/doc-link checks, functional tests, strict public
40
+ type contracts, and a clean offline installation of the npm tarball. Coverage is
41
+ a separate command. Tests use fixtures and local servers; they do not contact
42
+ model accounts. Package checks require npm. Run `npm run test:coverage` when
43
+ reviewing coverage; it reruns the same functional suite.
44
+
45
+ Keep generated files and credentials out of commits. Maintained contributor
46
+ documentation belongs in `docs/development/`.
47
+
48
+ ## Review and release
49
+
50
+ Keep commits focused and explain behavior changes and the checks performed.
51
+ Open a pull request with a short description of the behavior change and the
52
+ verification you ran; link the relevant issue when one exists.
53
+ Inspect `git diff` and `git diff --cached` before committing. Respect existing
54
+ authorship and use the project identity configured for the repository.
55
+
56
+ Follow the [packaging guide](docs/development/RELEASING.md) for the coordinated
57
+ source and npm release. The project is licensed under [MIT](LICENSE).
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Fayegram AI
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,308 @@
1
- # Temporary Holding Version
1
+ # Decision Bridge
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ [![MIT license](https://img.shields.io/badge/license-MIT-blue)](LICENSE)
4
+ [![Zero runtime dependencies](https://img.shields.io/badge/runtime%20dependencies-0-brightgreen)](package.json)
5
+
6
+ A JavaScript SDK that turns supplied information into structured decisions inside
7
+ your application. An optional Node command runner is included for evaluating files.
8
+ Give it a `state` (text or JSON to assess) and one or more `questions`; it returns
9
+ validated choices, probabilities for yes/no (`noul`) questions, or rubric-based
10
+ scores.
11
+ For example, pass a failed test log to classify the failure and estimate whether
12
+ a missing dependency caused it. Your application decides what to do with the result.
13
+
14
+ Try the [Decision Playground](https://decision-pg.fayegram.com/).
15
+
16
+ The main SDK supports native decision models: Jev through TypeSafe, OpenAI
17
+ Decisions, and Cloudflare Clef. Custom decision services use the explicit
18
+ `custom/decision` entry point. General-purpose models remain available through
19
+ the opt-in `custom/generative` entry point, with maintained OpenAI-compatible,
20
+ OpenRouter, and Anthropic presets. The bridge handles the shared request and result
21
+ contract; each provider handles its API protocol and model capabilities.
22
+
23
+ [OpenAI Decisions](docs/guides/OPENAI_DECISIONS.md) also supports ordered text/image
24
+ input, typed string/boolean choices, labelled scores, and dedicated native access.
25
+ [Cloudflare Clef, Clef-flash, and Clef-omni](docs/guides/CLOUDFLARE_DECISIONS.md) provide
26
+ common/native access, embedded images, typed choices, labelled scores, REST,
27
+ Workers AI bindings, and optional AI Gateway routing. Omni additionally supports
28
+ embedded WAV/MP3 audio and MP4/WebM video, ordered images → audio → videos → text.
29
+ The common API checks provider/model capabilities before dispatch; refusals are
30
+ errors.
31
+
32
+ **Version 0.1.0 · Node.js 22.16+ or modern browsers (SDK) · ESM · zero runtime dependencies**
33
+
34
+ The npm package is
35
+ [@fayegram-ai/decision-bridge](https://www.npmjs.com/package/@fayegram-ai/decision-bridge).
36
+ Source and issue reports are maintained at
37
+ [Fayegram-AI/decision-bridge](https://github.com/Fayegram-AI/decision-bridge).
38
+ Report security issues privately as described in [SECURITY.md](SECURITY.md).
39
+
40
+ This is an independent project. The custom generative presets identify their
41
+ probabilities as elicited model outputs.
42
+ Changing providers does **not** make their accuracy or calibration equivalent.
43
+
44
+ ## Supported models
45
+
46
+ The built-in decision providers support these model selectors in this release:
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` | — |
55
+
56
+ `jev-latest` is Jev's default alias. Jev also accepts explicit model IDs available through your TypeSafe account;
57
+ use `bridge.listModels()` or the CLI `models` command to inspect that catalog.
58
+ The bridge does not maintain a static list of Jev versions. A moving alias or a
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.
62
+ Model discovery is unsupported for OpenAI Decisions and Cloudflare.
63
+
64
+ Additional decision protocols use [custom decision providers](docs/guides/CUSTOM_DECISION.md).
65
+ General-purpose models use the separate [custom generative](docs/guides/CUSTOM_GENERATIVE.md)
66
+ entry point, with `openai-compatible`, `openrouter`, or `anthropic` presets, or
67
+ an explicit provider module. Those presets require a model ID supported by your
68
+ configured service and have no default model or fixed model catalog.
69
+
70
+ ## Choose a provider
71
+
72
+ All native providers support shared state and the common `choice`, `noul`, and
73
+ `score` questions. Additional input and question forms depend on the provider:
74
+
75
+ | Provider | Additional supported features | Guide |
76
+ | --- | --- | --- |
77
+ | Jev | Native decisions through the TypeSafe API | [Provider reference](docs/reference/PROVIDERS.md#native-jev) |
78
+ | OpenAI Decisions | Ordered text/images, typed choices, labelled scores, safety identifiers, native access | [OpenAI Decisions](docs/guides/OPENAI_DECISIONS.md) |
79
+ | 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
+ | 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) |
81
+ | Custom decision service | Explicit decision provider contract | [Custom decision providers](docs/guides/CUSTOM_DECISION.md) |
82
+ | Custom generative presets / modules | General-purpose output mapped into decisions; explicit opt-in | [Custom generative providers](docs/guides/CUSTOM_GENERATIVE.md) |
83
+
84
+ For Cloudflare REST, provide an account ID and API token. Workers binding and
85
+ Gateway are optional paths with their own configured resources. Enabled
86
+ `rejectIfBusy` currently requires the binding path for all three Clef models.
87
+ Enabling it for REST fails local preflight with `UNSUPPORTED_CAPABILITY`; see the
88
+ [service compatibility note](docs/guides/CLOUDFLARE_DECISIONS.md#capacity-rejection-and-ai-gateway).
89
+ Use [provider capabilities](docs/reference/PROVIDERS.md#common-request-capabilities)
90
+ and `bridge.validate()` to check a request before inference. Capability support
91
+ does not establish account access or model quality.
92
+
93
+ ## Use in your application
94
+
95
+ For this server-side example, use Node.js **22.16 or newer**. Install the package
96
+ in your application's directory:
97
+
98
+ ```bash
99
+ npm install @fayegram-ai/decision-bridge
100
+ ```
101
+
102
+ The installed SDK runs without a compilation step. See
103
+ [getting started](docs/guides/GETTING_STARTED.md) for source and archive setup.
104
+
105
+ Create `.env` in your application's directory and set your TypeSafe API key:
106
+
107
+ ```dotenv
108
+ TYPESAFE_API_KEY=your_real_key_here
109
+ ```
110
+
111
+ Add `.env` to your application's `.gitignore`. The SDK reads the process
112
+ environment; the Node command below explicitly loads this file before startup.
113
+
114
+ Save this complete example as `app.mjs` beside `.env`. The `.mjs` extension enables
115
+ ESM imports without changing your application's `package.json`:
116
+
117
+ ```javascript
118
+ import { createBridge, choice, noul, publicError } from '@fayegram-ai/decision-bridge';
119
+
120
+ try {
121
+ const bridge = createBridge({ jev: {} }); // TYPESAFE_API_KEY; model defaults to jev-latest.
122
+ const result = await bridge.evaluate({
123
+ state: { log: "ModuleNotFoundError: No module named 'pytest'" },
124
+ questions: {
125
+ category: choice('Classify the failure using only the evidence.', {
126
+ dependency: 'A required package or module is unavailable.',
127
+ network: 'A network operation failed.',
128
+ unknown: 'The evidence is insufficient.',
129
+ }),
130
+ missing_package: noul('Does the error indicate a missing package?'),
131
+ },
132
+ });
133
+ console.log(result.answers.category.choice);
134
+ console.log(result.answers.missing_package.noul);
135
+ console.log(result.meta.probabilitySource);
136
+ } catch (error) {
137
+ console.error(publicError(error));
138
+ process.exitCode = 1;
139
+ }
140
+ ```
141
+
142
+ ```bash
143
+ node --env-file=.env app.mjs
144
+ ```
145
+
146
+ This makes one real Jev evaluation and may incur charges. The first output is one
147
+ of your category labels. The second is a probability between 0 and 1; `noul` does
148
+ not turn it into a boolean. For Jev, `probabilitySource` is `native`. Answers depend
149
+ on the model; the example does not assume a particular prediction.
150
+
151
+ Edit `state` and the question definitions for each call. No saved prompt
152
+ registration is required. `publicError()` exposes a stable error code and safe
153
+ message, with HTTP diagnostics when available; see [errors](docs/reference/ERRORS.md).
154
+
155
+ The example explicitly selects Jev using the `jev` shortcut. For a native provider,
156
+ construct it with `createProvider({ type: 'YOUR_PROVIDER', ...options })` or a
157
+ built-in provider class, then pass it to `createBridge({ provider })`.
158
+ `createBridge()` and `createBridge({})` reject missing provider selection.
159
+
160
+ Continue with [getting started](docs/guides/GETTING_STARTED.md) for TypeScript,
161
+ CommonJS, and optional command-runner usage, or the [SDK reference](docs/reference/SDK.md)
162
+ for the complete request and result contracts.
163
+
164
+ ## Browser use
165
+
166
+ The same SDK import works in modern browser applications. Supply credentials
167
+ explicitly; browsers do not have Node's process environment. Direct requests work
168
+ only when the provider permits your web origin through CORS, including the
169
+ authorization and content-type headers. The default Jev endpoint needs TypeSafe
170
+ to allow the app's origin before a browser can call it. A browser-visible API key
171
+ is accessible to users of that app, so use only credentials intended for client
172
+ exposure. See [browser integration](docs/guides/BROWSER.md) for the boundary and
173
+ an example. The optional command runner remains Node-only.
174
+
175
+ ## Change the backend, not the request
176
+
177
+ [Switching models](docs/guides/SWITCHING_MODELS.md) provides a complete SDK example
178
+ for changing native providers. To elicit decisions from a locally served general-purpose
179
+ model, explicitly opt into the maintained custom generative preset:
180
+
181
+ ```javascript
182
+ import { createBridge } from '@fayegram-ai/decision-bridge';
183
+ import { OpenAICompatibleProvider } from '@fayegram-ai/decision-bridge/custom/generative';
184
+
185
+ const provider = new OpenAICompatibleProvider({
186
+ baseURL: 'http://127.0.0.1:8000/v1',
187
+ apiKey: null, // Explicitly allowed only for loopback.
188
+ model: process.env.LOCAL_MODEL, // Your locally served model ID.
189
+ responseFormat: 'json_schema', // Must be supported by that endpoint.
190
+ tokenParameter: 'max_tokens',
191
+ });
192
+ const bridge = createBridge({ provider });
193
+ // await bridge.evaluate(theSameRequest);
194
+ ```
195
+
196
+ The `custom/generative` entry point also exports the other presets. For OpenRouter, use `new OpenRouterProvider({ model: 'your-provider/your-model' })`
197
+ with `OPENROUTER_API_KEY`. For Anthropic, use
198
+ `new AnthropicProvider({ model: 'your-account-model-id' })` with
199
+ `ANTHROPIC_API_KEY`. Substitute real available model IDs; the bridge does not
200
+ choose an arbitrary remote model on your behalf.
201
+
202
+ A server may implement only JSON-object or text output. Select that mode explicitly
203
+ with `responseFormat: 'json_object'` or `'text'`; the client still validates every
204
+ answer. It never silently downgrades formats, repairs JSON, or changes models.
205
+
206
+ ## Optional command runner
207
+
208
+ The installed package includes `decision-bridge` for working with request files.
209
+ The `decision` and `faye-decision` aliases run the same CLI with the same options.
210
+ Run it through npm from your application directory:
211
+
212
+ ```bash
213
+ npm exec -- decision-bridge init ./my-decisions
214
+ npm exec -- decision-bridge validate ./my-decisions/request.json
215
+ ```
216
+
217
+ These two commands are offline. To evaluate with a real account, copy the generated
218
+ `.env.example` to `.env` inside `my-decisions`, set the key, then run:
219
+
220
+ ```bash
221
+ npm exec -- decision-bridge evaluate ./my-decisions/request.json --config ./my-decisions/decision.config.json --env-file ./my-decisions/.env
222
+ ```
223
+
224
+ The runner uses explicit environment/configuration paths. See the
225
+ [command reference](docs/reference/CLI.md) for flags, streams, and exit codes.
226
+ Its built-in provider default is Jev; SDK construction requires explicit selection.
227
+
228
+ ## What this repository produces
229
+
230
+ | Component | What you get |
231
+ | --- | --- |
232
+ | JavaScript SDK | Import `@fayegram-ai/decision-bridge` in your application; TypeScript declarations are included |
233
+ | Optional command runner | `decision-bridge`, `decision`, and `faye-decision`, all backed by `bin/decision.mjs` |
234
+ | npm package artifact | `npm run build` creates and verifies `release/fayegram-ai-decision-bridge-VERSION.tgz` |
235
+
236
+ For maintainers, `npm run build` archives the ESM source and verifies an offline
237
+ install of the exact tarball used for the npm release. See
238
+ [packaging and release](docs/development/RELEASING.md).
239
+
240
+ For running the source examples, see [source setup](docs/guides/GETTING_STARTED.md#run-from-a-source-checkout).
241
+ See [platform setup](docs/guides/PLATFORMS.md) for Windows/macOS/Linux details.
242
+
243
+ ## What is included
244
+
245
+ The source checkout includes these runtime features and development tools. The npm
246
+ tarball contains the SDK, Node command, small examples, and maintained docs; it excludes the
247
+ test suite and development scripts.
248
+
249
+ | Area | Implementation |
250
+ | --- | --- |
251
+ | Stable contract | Runtime-defined [questions](docs/reference/SDK.md#question-builders), structured state or ordered input, typed answers, immutable results |
252
+ | Native providers | Jev, OpenAI Decisions, Cloudflare Clef/Clef-flash/Clef-omni |
253
+ | Custom providers | Separate decision and generative contracts; opt-in Chat Completions, OpenRouter, and Anthropic presets |
254
+ | SDK | Provider factory, [capability preflight](docs/reference/SDK.md#bridgegetcapabilitiesmodel-and-bridgevalidaterequest), [cancellation](docs/reference/SDK.md#cancellation-and-deadlines), and [ordered batch evaluation](docs/reference/SDK.md#sdk-batch-evaluation) |
255
+ | Application extensions | [State/input preparation and result observation](docs/guides/CUSTOMIZATION.md), plus [choice thresholds and abstention policies](docs/guides/CUSTOMIZATION.md#application-policy-is-a-separate-stage) |
256
+ | Node command | [Initialize, evaluate, validate, schema, models, and ordered JSONL batches](docs/reference/CLI.md#commands), with [explicit JSON profiles](docs/reference/CONFIGURATION.md) |
257
+ | Reliability | [Transport byte limits and fetch injection](docs/reference/SDK.md#provider-transport-options), deadlines, [limited retries and safe errors](docs/reference/ERRORS.md), strict response validation, atomic output |
258
+ | Development | Functional tests, coverage, TypeScript and Workers binding contracts, offline tarball-install checks, cross-platform CI configuration |
259
+
260
+ ## Result semantics
261
+
262
+ `result` contains `answers`, `model`, `usage`, and `meta`. Native provider confidence is
263
+ preserved. `bridge.providerKind` and `result.meta.providerKind` distinguish
264
+ `'decision'` from `'generative'`; the bridge takes this classification from the
265
+ provider contract. Generative backends **do not invent confidence**; missing token counts
266
+ are `null`, not zero. Their choices and scores are derived from the returned
267
+ probability distributions. See [SDK reference](docs/reference/SDK.md) and
268
+ [provider compatibility](docs/reference/PROVIDERS.md).
269
+
270
+ This library does not execute the selected action, operate an agent loop, train a
271
+ model, enforce user authorization, or guarantee decision correctness. It is the
272
+ integration layer on which you can build those policies explicitly.
273
+
274
+ ## Documentation
275
+
276
+ Start with the [documentation index](docs/README.md), including:
277
+
278
+ - [Getting started](docs/guides/GETTING_STARTED.md), [customization](docs/guides/CUSTOMIZATION.md), and [custom providers](docs/guides/CUSTOM_PROVIDERS.md), including [generative presets](docs/guides/CUSTOM_GENERATIVE.md).
279
+ - [SDK](docs/reference/SDK.md), [configuration](docs/reference/CONFIGURATION.md), [errors](docs/reference/ERRORS.md), and the optional [command runner](docs/reference/CLI.md).
280
+ - [Contributor documentation](docs/development/README.md) and [security](SECURITY.md).
281
+
282
+ ## Project origins
283
+
284
+ Decision Bridge builds on the original
285
+ [Jev Adapter repository](https://github.com/Fayegram-AI/jev-adapter).
286
+ It carries forward the structured-decision SDK and CLI, with Jev supported
287
+ alongside the other providers.
288
+
289
+ ## Contributing and verification
290
+
291
+ Start with [CONTRIBUTING.md](CONTRIBUTING.md). User guides and API references live
292
+ under `docs/guides/` and `docs/reference/`; maintained contributor documentation
293
+ lives under `docs/development/`. See the [repository layout](docs/development/REPOSITORY_LAYOUT.md)
294
+ for the source and package contents.
295
+
296
+ From a source checkout, run `npm run verify` for routine code, contract, and
297
+ package checks. `npm run test:coverage` reruns the functional suite with coverage
298
+ floors; the [release guide](docs/development/RELEASING.md) gives a single-pass
299
+ verification sequence. These software checks use synthetic fixtures and local
300
+ HTTP servers; they do not measure model quality. The
301
+ [testing guide](docs/development/TESTING.md) covers code and package checks plus
302
+ an optional live integration smoke check. Package preparation is described in the
303
+ [release guide](docs/development/RELEASING.md).
304
+ Public behavior changes are recorded in the [changelog](CHANGELOG.md).
305
+
306
+ ## License
307
+
308
+ This project is licensed under the [MIT License](LICENSE).
package/SECURITY.md ADDED
@@ -0,0 +1,88 @@
1
+ # Security and operational boundaries
2
+
3
+ ## Credentials and data
4
+
5
+ Keep keys in the process environment or an explicitly loaded local environment
6
+ file. Never place them in request JSON, committed profiles, command-line arguments,
7
+ or shared logs. The package contains no key, telemetry client, or background job.
8
+ By design it sends the supplied state and question definitions to the selected
9
+ provider when evaluation is explicitly requested. Review data-sharing requirements
10
+ before sending private repository content or documents.
11
+ Optional Cloudflare Gateway routing can cache requests/responses or collect logs
12
+ according to explicit options and the Gateway's configuration. Review that
13
+ configuration as part of your data-handling policy; Gateway is disabled until
14
+ selected. See the [Cloudflare guide](docs/guides/CLOUDFLARE_DECISIONS.md#capacity-rejection-and-ai-gateway).
15
+
16
+ Built-in constructors do not forward ambient credentials to unrelated custom
17
+ origins. The CLI requires explicit credential selection for custom URLs. URL
18
+ credentials/query/fragment are rejected; HTTP is limited to loopback and redirects
19
+ are not followed. These controls do not authenticate an arbitrary configured host,
20
+ resolve all DNS-rebinding risks, or sandbox untrusted URLs. An embedding server
21
+ must impose its own allowlist and network controls.
22
+
23
+ ## Safe errors, not a universal secret scanner
24
+
25
+ HTTP failure bodies/headers and unknown exception stacks are not copied into public
26
+ errors. Known keys are removed from request IDs and CLI error string values.
27
+ Model outputs, requested labels, state, and arbitrary application logs are not
28
+ universally scrubbed. Do not deliberately include secrets in prompts. A custom
29
+ provider constructing DecisionError is responsible for a safe message. Never add a
30
+ verbose HTTP logger that prints Authorization or x-api-key headers.
31
+
32
+ ## Input and output
33
+
34
+ Strict plain-JSON checks reject accessors, cycles, non-finite numbers, lossy objects,
35
+ and unknown fields. Bytes, nesting, nodes, retries, concurrency, and waiting time
36
+ are bounded. These checks do not establish decision accuracy or resist every
37
+ adversarial semantic input. Question instructions are trusted configuration;
38
+ state is untrusted evidence. Prompt separation is a mitigation, not a guarantee.
39
+
40
+ Output files use exclusive temporary files and mode 0600 where supported, then
41
+ same-directory finalization. Existing output requires explicit --force. Atomicity
42
+ and permissions depend on the filesystem/OS; there is no power-loss-proof
43
+ transaction across model billing, stdout, and filesystem writes.
44
+
45
+ ## Plugins and cancellation
46
+
47
+ Custom provider modules execute ordinary trusted JavaScript with process access.
48
+ They are not sandboxed and are never auto-discovered. Extensions can perform I/O
49
+ and log data by their own design. Honor supplied AbortSignals and close resources;
50
+ the bridge can stop awaiting a non-cooperative promise, not terminate arbitrary
51
+ code or undo side effects. A provider timeout or cancellation does not prove remote
52
+ inference stopped before billing.
53
+
54
+ ## Dependencies and CI
55
+
56
+ There are zero runtime dependencies. This reduces dependency surface but is not a
57
+ security certification. Maintain Node.js security updates. The pinned TypeScript
58
+ compiler, official Workers declarations, and Ajv configuration-schema validator
59
+ are development-only dependencies; none is required by the installed SDK or CLI.
60
+ The supplied CI uses read-only repository permissions, no model
61
+ keys, and no publishing. Review third-party action updates and pin audited action
62
+ commits under your organization's policy before using CI in a privileged setting.
63
+
64
+ ## Reporting
65
+
66
+ For a hosted public repository, use its **Security** tab and **Report a
67
+ vulnerability** to submit a private report. The repository owner must enable
68
+ private vulnerability reporting when making the repository public, before
69
+ announcing the release; this source tree has no dedicated security inbox or other
70
+ private contact channel. If the reporting button is absent, ask the maintainer
71
+ for a private contact method without
72
+ including vulnerability details in a public issue.
73
+
74
+ Include the affected version, impact, and a minimal redacted reproduction. Do
75
+ not publish credentials, confidential inputs, or exploit details in an issue.
76
+
77
+ ## Release assurance
78
+
79
+ Automated tests and package verification are engineering checks, not an
80
+ independent security audit. Consult CI results for the specific commit or
81
+ release. Ordinary tests do not establish authenticated vendor
82
+ compatibility. See [Testing](docs/development/TESTING.md) for the verification scope.
83
+
84
+ The input-overwrite guard resolves known path/file aliases; it does not lock the
85
+ whole filesystem against concurrent changes. File-output cancellation is honored
86
+ until atomic finalization is submitted. It cannot retract an OS operation already
87
+ submitted. Parameter objects are validated before inspection/spreading so accessors
88
+ are rejected without being invoked by the provider constructors.
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env node
2
+ import { runCli } from '../src/cli/main.mjs';
3
+
4
+ const controller = new AbortController();
5
+ const interrupt = () => controller.abort();
6
+ process.once('SIGINT', interrupt);
7
+ process.once('SIGTERM', interrupt);
8
+ // Stream errors are handled by write callbacks; avoid unhandled EPIPE events.
9
+ process.stdout.on('error', () => {});
10
+ process.stderr.on('error', () => {});
11
+ process.exitCode = await runCli(process.argv.slice(2), { signal: controller.signal });
12
+ // An interrupted, backpressured pipe must not keep the process alive.
13
+ if (controller.signal.aborted) { process.stdin.destroy(); process.stdout.destroy(); }
14
+ process.removeListener('SIGINT', interrupt);
15
+ process.removeListener('SIGTERM', interrupt);
package/docs/README.md ADDED
@@ -0,0 +1,58 @@
1
+ # Documentation
2
+
3
+ Start with [using the SDK in your application](../README.md#use-in-your-application)
4
+ for installation and a complete first call. This index separates usage guides,
5
+ API reference, and contributor documentation.
6
+ Install `@fayegram-ai/decision-bridge` with npm; the
7
+ [getting started guide](guides/GETTING_STARTED.md#install-into-your-application)
8
+ also covers installation from a verified archive.
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.
12
+
13
+ Decision Bridge is a JavaScript SDK with an optional command runner. It evaluates
14
+ supplied `state` or ordered `input`, plus `questions`, with an explicitly selected
15
+ provider and returns
16
+ validated, structured decisions.
17
+ For provider-specific input forms, consult the
18
+ [capability comparison](reference/PROVIDERS.md#common-request-capabilities).
19
+ The common bridge API and dedicated native APIs have separate request shapes;
20
+ the OpenAI and Cloudflare guides cover both.
21
+
22
+ ## Use the bridge
23
+
24
+ | Guide | Purpose |
25
+ | --- | --- |
26
+ | [Getting started](guides/GETTING_STARTED.md) | Package installation, credentials, JavaScript/TypeScript integration, and first evaluation |
27
+ | [Browser integration](guides/BROWSER.md) | Direct browser use, CORS requirements, and credential exposure |
28
+ | [Platforms](guides/PLATFORMS.md) | Windows, macOS, and Linux setup |
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 |
31
+ | [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
+ | [Customization](guides/CUSTOMIZATION.md) | Questions, templates, extensions, and policies |
33
+ | [Custom providers](guides/CUSTOM_PROVIDERS.md) | Common classified contract and explicit CLI module loading |
34
+ | [Custom decision](guides/CUSTOM_DECISION.md) | Extend a native decision model protocol |
35
+ | [Custom generative](guides/CUSTOM_GENERATIVE.md) | Opt-in OpenAI-compatible, OpenRouter, Anthropic presets, strategy helpers, and new protocols |
36
+ | [Troubleshooting](guides/TROUBLESHOOTING.md) | Configuration, network, model, and output errors |
37
+
38
+ ## Reference
39
+
40
+ | Document | Purpose |
41
+ | --- | --- |
42
+ | [SDK](reference/SDK.md) | Questions/results, exports and types, transport options, validation, cancellation, batching, extensions, and policies |
43
+ | [Command runner](reference/CLI.md) | Optional commands, flags, streams, and exit codes |
44
+ | [Configuration](reference/CONFIGURATION.md) | Precedence, credentials, and profiles |
45
+ | [Providers](reference/PROVIDERS.md) | Protocols and probability provenance |
46
+ | [Errors](reference/ERRORS.md) | Error codes and retry behavior |
47
+ | [Sources](reference/SOURCES.md) | Primary protocol documentation |
48
+
49
+ ## Contribute
50
+
51
+ Read [CONTRIBUTING.md](../CONTRIBUTING.md), then the
52
+ [contributor documentation](development/README.md) for architecture, design
53
+ choices, testing, and packaging. The
54
+ [repository layout](development/REPOSITORY_LAYOUT.md) explains source and package
55
+ contents.
56
+
57
+ The [security policy](../SECURITY.md) and [changelog](../CHANGELOG.md) cover
58
+ operational boundaries and public compatibility history.