@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
@@ -0,0 +1,118 @@
1
+ # Architecture
2
+
3
+ ## Bridge and provider responsibilities
4
+
5
+ Decision Bridge exposes one application contract for structured decisions. The
6
+ bridge owns request snapshots, common validation, extension sequencing, the total
7
+ deadline, final result validation, immutable results, and bounded observations.
8
+ A Provider owns its API encoding, transport, decoding, model defaults,
9
+ capabilities, and native operations. Multiple models sharing a protocol can use
10
+ one provider implementation.
11
+
12
+ `createBridge` requires an explicitly selected provider or the Jev shortcut.
13
+ `createProvider` requires an explicit native type. `custom/decision` and
14
+ `custom/generative` expose classified extension helpers; maintained generative
15
+ adapters are loaded only through their opt-in subpath. The CLI resolves its own configuration
16
+ and Jev default before constructing the SDK bridge.
17
+
18
+ ```text
19
+ Application / CLI
20
+ state or ordered input + question definitions + optional model
21
+ |
22
+ v
23
+ request snapshot, common validation, capabilities, provider preflight
24
+ |
25
+ ordered prepareState or prepareInput extensions + revalidation
26
+ |
27
+ Provider.evaluate (explicit decision/generative kind)
28
+ +-- Jev: native systemone
29
+ +-- OpenAI Decisions: native /v1/decisions
30
+ +-- Cloudflare Clef / Clef-flash / Clef-omni: REST or Workers AI binding
31
+ +-- custom/decision: new native decision protocol
32
+ +-- custom/generative: OpenAI-compatible / OpenRouter / Anthropic or new protocol
33
+ |
34
+ canonical result validation using provider precision policy
35
+ |
36
+ immutable result + bounded observation
37
+ |
38
+ application policy / storage / downstream action
39
+ ```
40
+
41
+ Native OpenAI and Cloudflare providers also expose `createDecision` directly.
42
+ Common and native paths share provider validation, codecs, and bounded transport.
43
+ Direct native calls use provider deadlines; bridge calls additionally enforce the
44
+ shared evaluation deadline and extension lifecycle.
45
+
46
+ Application policy decides whether a downstream action is permitted. The SDK
47
+ returns decisions without executing actions or maintaining an agent loop.
48
+
49
+ ## Module map
50
+
51
+ | Module | Responsibility |
52
+ | --- | --- |
53
+ | `src/index.mjs`, `src/index.d.mts` | Public runtime exports and TypeScript contract |
54
+ | `src/bridge.mjs` | Orchestration, extension lifecycle, total deadline, immutable results |
55
+ | `src/validation.mjs`, `src/input.mjs` | Lossless snapshots, common input and result invariants |
56
+ | `src/questions.mjs` | Immutable typed question builders, independent of inference selection |
57
+ | `src/capabilities.mjs` | Provider/model capability checks and common schema versions |
58
+ | `src/probabilities.mjs` | Provider-selected precision allowance without normalization |
59
+ | `src/provider-contract.mjs` | Required classification, authoritative metadata, and generative provenance |
60
+ | `src/custom/decision.mjs` | Explicit native decision definition helper |
61
+ | `src/custom/generative/` | Opt-in protocol presets, schema, prompts, and result derivation |
62
+ | `schemas/decision.config.schema.json` | Shipped CLI configuration structure and editor support |
63
+ | `src/providers/` | API orchestration, model profiles, preflight, codecs, bounded image/audio/video inspection, and transports |
64
+ | `src/embedded.mjs` | Shared embedded data URL and canonical base64 checks |
65
+ | `src/transport.mjs`, `src/response-transport.mjs` | Credential destinations, bounded bodies, safe errors, retries |
66
+ | `src/async.mjs` | Deadlines and cancellation races |
67
+ | `src/options.mjs` | Unknown-field/accessor rejection for options |
68
+ | `src/errors.mjs` | DecisionError and safe public diagnostics |
69
+ | `src/batch.mjs` | Ordered bounded-concurrency SDK arrays |
70
+ | `src/policy.mjs` | Explicit choice thresholds, without action execution |
71
+ | `src/cli/ordered.mjs` | Concurrent JSONL processing with a bounded ordered window |
72
+ | `src/cli/`, `bin/decision.mjs` | Configuration, input/output, commands, process signals |
73
+
74
+ ## Results and precision
75
+
76
+ Generative providers elicit distributions and derive argmax choices, weighted
77
+ scores, and rubric legends in code. Native decision providers validate and retain
78
+ their returned values, confidence, and reported usage. No path repairs malformed
79
+ distributions or invents confidence. The common shape preserves provenance without
80
+ claiming equivalent statistical semantics across models.
81
+
82
+ The bridge takes result-validation policy from the provider contract. Cloudflare
83
+ 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).
85
+ Application code passes that precision explicitly when using `decideChoice`; the
86
+ policy helper does not infer it from the answer or its metadata.
87
+
88
+ ## Reliability and configuration
89
+
90
+ Provider deadlines include dispatch, configured retries, backoff, and bounded body
91
+ reading. The bridge deadline additionally covers validation, preparation, provider
92
+ waiting, and result processing. Expired synchronous work cannot dispatch a call.
93
+ Cancellation bounds waiting for custom promises; custom code must honor signals
94
+ to release its own resources. Observations use a separate bounded budget.
95
+
96
+ Retries cover selected explicit transient responses. Ambiguous failures and failed
97
+ observers do not trigger another inference. CLI atomic files protect previous
98
+ output but cannot undo remote work or emitted stdout.
99
+
100
+ JSON configuration is explicit. Custom ESM executes only when selected. Custom
101
+ origins do not inherit unrelated ambient credentials. Gateway settings remain
102
+ provider configuration, and do not replace the bridge's total deadline.
103
+
104
+ ## Extension boundaries
105
+
106
+ Use preparation hooks for context, observation hooks for metrics, classified custom providers
107
+ for another API, and application code for policy. Ordered images and richer
108
+ questions require declared capabilities. Native provider guides document limits.
109
+ Cloudflare Omni supports grouped embedded images/audio/video before text. Model
110
+ profiles resolve request byte limits per call; transport instances share no
111
+ mutable request limit or response identifiers. Header/container inspection is
112
+ bounded and does not perform full media decoding.
113
+
114
+ The SDK does not host models or provide a server API, persistent state, autonomous
115
+ actions, streaming, transcription, transcoding, frame extraction,
116
+ provider-side asynchronous batch jobs, platform
117
+ management, automatic model search, or automatic provider failover. SDK arrays and
118
+ CLI JSONL batches provide bounded client-side concurrency.
@@ -0,0 +1,66 @@
1
+ # Design rationale
2
+
3
+ ## Native decisions as the application contract
4
+
5
+ Use shared state or ordered input and independent typed questions as the public
6
+ contract. The bridge owns orchestration; providers own their model API protocols.
7
+ This gives applications a stable decision interface and makes customization
8
+ explicit at each call. Native decision models are the main package scope;
9
+ generative protocols are opt-in custom strategies with their own public subpath.
10
+ Every provider declares its decision/generative kind. Consequence: not every model can satisfy this contract
11
+ reliably; compatibility and quality must be tested separately.
12
+
13
+ ## ESM JavaScript with declarations and no runtime dependencies
14
+
15
+ Use standard fetch, streams, and JSON in the SDK; keep Node's test runner,
16
+ argument parser, and filesystem APIs in development tools and the optional CLI.
17
+ Ship ESM source plus `.d.mts` types without a transpilation build. Consequence:
18
+ Node 22.16+ is required for Node use, while browser use depends on modern web
19
+ APIs and the provider's CORS policy. TypeScript declaration synchronization needs
20
+ its own tests. A CommonJS entry point is not claimed.
21
+
22
+ ## Provenance is part of the result
23
+
24
+ Native versus elicited probabilities are tagged. Native codecs preserve reported
25
+ probabilities, confidence, and scores. Generative strategies derive choice/score
26
+ from their elicited distributions and do not supply native confidence;
27
+ unreported token counts are null. Consequence: applications must handle optional
28
+ confidence/usage, and identical output schemas do not imply interchangeable
29
+ calibration or correctness.
30
+
31
+ ## Fail explicitly instead of silently repairing or falling back
32
+
33
+ Reject invalid JSON, extra fields, wrong labels, distributions outside the provider
34
+ precision allowance, explicit output truncation, and refusals. Require explicit
35
+ output modes and models. Services may truncate input without reporting it; local
36
+ byte limits do not guarantee token fit. Consequence:
37
+ some calls fail that a permissive wrapper might guess at, but failures remain
38
+ observable and cannot silently change budgets or decision policies.
39
+
40
+ ## Trusted extensions and explicit configuration
41
+
42
+ Read JSON config only when named. Load custom ESM only when explicitly selected.
43
+ Protect credential destinations and expose bounded callbacks. Consequence: plugins
44
+ are powerful and must be trusted; cancellation is not a JavaScript sandbox.
45
+
46
+ ## Conservative retries and independent observations
47
+
48
+ Retry selected explicit transient HTTP statuses within a deadline. Do not retry
49
+ ambiguous network failures, malformed decisions, or observer failures. Consequence:
50
+ users can choose manual retry policies, but exactly-once billing cannot be promised.
51
+
52
+ ## MIT licensing and coordinated distribution
53
+
54
+ Publish the maintained source under the MIT License, with the copyright notice
55
+ in `LICENSE` and matching SPDX identifiers in package metadata. Release the source
56
+ repository and npm package together. Consequence: source and package recipients
57
+ have the same MIT permissions and obligations; building an archive alone does not
58
+ publish a release.
59
+
60
+ ## Verified npm package artifact
61
+
62
+ Build a versioned npm tarball from the source package and retain it only after an
63
+ offline installation check of the exact archive. Publish that verified artifact
64
+ to the public npm registry as part of the coordinated source and package release;
65
+ building alone never publishes it. Consequence: consumers install the release from
66
+ npm, while maintainers verify the exact archive before publication.
@@ -0,0 +1,12 @@
1
+ # Contributor documentation
2
+
3
+ This directory contains maintained documentation for contributors to the public
4
+ repository. Start with [CONTRIBUTING.md](../../CONTRIBUTING.md).
5
+
6
+ | Document | Purpose |
7
+ | --- | --- |
8
+ | [Architecture](ARCHITECTURE.md) | Runtime ownership, evaluation flow, and boundaries |
9
+ | [Design rationale](DESIGN.md) | Public contract choices and their consequences |
10
+ | [Testing](TESTING.md) | Local tests, type checks, packaging checks, and live smoke tests |
11
+ | [Packaging and release](RELEASING.md) | Source/package verification and separate publication instructions |
12
+ | [Repository layout](REPOSITORY_LAYOUT.md) | Source and package boundaries |
@@ -0,0 +1,100 @@
1
+ # Packaging and release
2
+
3
+ The npm package build archives ESM source without compilation. The versioned
4
+ tarball contains the runtime, TypeScript declarations, examples, and maintained
5
+ docs. Tests and development scripts remain in the source repository.
6
+
7
+ ## Verify source and package contents
8
+
9
+ From a clean source checkout, verify the code and build the installable artifact:
10
+
11
+ ```text
12
+ npm run check
13
+ npm run test:coverage
14
+ npm run typecheck
15
+ npm run build
16
+ ```
17
+
18
+ `npm run build` packs the source with lifecycle scripts disabled, installs and
19
+ checks that exact tarball in a clean offline consumer, and retains it at
20
+ `release/fayegram-ai-decision-bridge-VERSION.tgz`. The `release/` directory is Git-ignored.
21
+ Packing and individual verification commands have 120-second bounds; the combined
22
+ installed-consumer verification stage has a separate 600-second bound and streams
23
+ its progress. This accommodates CLI startup across multiple verification commands.
24
+ To check that archive again, run:
25
+
26
+ ```text
27
+ node scripts/package-smoke.mjs --tarball release/fayegram-ai-decision-bridge-VERSION.tgz
28
+ ```
29
+
30
+ Check public documentation against the implementation, including supported API
31
+ shapes, examples, limits, errors, and service compatibility notes. Inspect the MIT
32
+ copyright notice and package contents. Complete hosted checks relevant to changed
33
+ features using an authorized account/runtime;
34
+ fixture and declaration checks do not establish hosted binding/Gateway behavior.
35
+ Keep completed verification evidence separate from maintained consumer guidance.
36
+ These content and verification checks do not depend on publication account setup.
37
+
38
+ ## Confirm publication prerequisites
39
+
40
+ Before publication, confirm the repository exists at the metadata destination and
41
+ inspect CI results for the exact release commit. Make sure the hosted repository
42
+ has a private vulnerability-reporting route as described in
43
+ [SECURITY.md](../../SECURITY.md). Confirm that the npm login can publish under
44
+ `@fayegram-ai`. Direct publication requires account 2FA or a granular token
45
+ permitted to bypass it; see [npm's requirements](https://docs.npmjs.com/creating-and-publishing-scoped-public-packages/).
46
+
47
+ Building only creates and checks the artifact; it does not publish it. The package
48
+ name and registry are `@fayegram-ai/decision-bridge` and the public npm registry.
49
+ Coordinate the GitHub source release and publication of the verified tarball to
50
+ npm as one release. The source release commit and archive must contain the same
51
+ intended files, including README and documentation. A packed or uploaded archive
52
+ is a snapshot: subsequent source edits do not change its contents.
53
+
54
+ The tracked `.npmrc` routes this scope to npm in this checkout without changing
55
+ the user's npm configuration. Keep credentials in the user configuration, never
56
+ in the repository. Verify the target with `npm config get @fayegram-ai:registry`
57
+ before staging or publishing. Replace `VERSION` and `STAGE_ID` below with the
58
+ package version and the returned stage identifier. The `./` prefix identifies a
59
+ local archive path to npm.
60
+
61
+ ## Stage, inspect, and approve an archive
62
+
63
+ With npm CLI 11.15.0+ and package write access, stage the verified archive:
64
+
65
+ ```text
66
+ npm stage publish ./release/fayegram-ai-decision-bridge-VERSION.tgz --access public --tag latest
67
+ npm stage view STAGE_ID --json
68
+ npm stage download STAGE_ID
69
+ ```
70
+
71
+ Compare the downloaded archive's checksum with the retained artifact, then verify
72
+ that exact download using `node scripts/package-smoke.mjs --tarball PATH_TO_DOWNLOAD`.
73
+ The staged version becomes publicly installable when a maintainer approves it
74
+ with 2FA:
75
+
76
+ ```text
77
+ npm stage approve STAGE_ID
78
+ ```
79
+
80
+ Approval publishes that version; no additional `npm publish` is needed. A first
81
+ stage for a new package creates a public `0.0.0-stage` placeholder, which is not
82
+ the staged SDK. See [npm's staged publishing guide](https://docs.npmjs.com/staged-publishing/).
83
+
84
+ If packaged files change before approval, build and verify a fresh archive.
85
+ Reject the old stage with `npm stage reject STAGE_ID` (requires 2FA), then stage
86
+ the new archive and repeat inspection. A pending stage reserves its version, so
87
+ remove it before staging a replacement with the same unpublished version. See
88
+ the [npm stage reference](https://docs.npmjs.com/cli/v12/commands/npm-stage/).
89
+
90
+ ## Direct publication alternative
91
+
92
+ For a version without a pending stage, publish the verified archive directly:
93
+
94
+ ```text
95
+ npm publish ./release/fayegram-ai-decision-bridge-VERSION.tgz --access public --tag latest
96
+ ```
97
+
98
+ After the coordinated release, confirm that the package page
99
+ links to the source repository and `npm install @fayegram-ai/decision-bridge` works.
100
+ Keep generated archives and verification logs outside tracked source.
@@ -0,0 +1,33 @@
1
+ # Repository layout
2
+
3
+ The source repository contains the SDK, CLI, examples, functional tests, CI, and
4
+ maintained documentation. The installable npm tarball contains the SDK and CLI
5
+ with declarations, examples, and docs; it excludes tests and development scripts.
6
+
7
+ ```text
8
+ README.md Product overview and quick start
9
+ CONTRIBUTING.md Contributor entry point
10
+ CHANGELOG.md User-visible changes
11
+ SECURITY.md Security boundaries and reporting guidance
12
+ LICENSE MIT license
13
+ package.json Package identity, exports, commands, and file allowlist
14
+ package-lock.json Pinned development dependency metadata
15
+ .env.example Provider credential placeholders
16
+ src/ Common SDK, native providers, CLI, declarations
17
+ src/custom/ Explicit decision definitions and generative presets
18
+ bin/ Node.js CLI entry point
19
+ examples/ Native SDK examples and request profiles
20
+ examples/custom/ Opt-in generative and native delegation examples
21
+ schemas/ Packaged CLI configuration JSON Schema
22
+ docs/guides/ User guides
23
+ docs/reference/ SDK, CLI, configuration, and provider contracts
24
+ docs/development/ Architecture, tests, and packaging guidance
25
+ test/ Functional and type-contract tests
26
+ scripts/ Source, type, and package checks
27
+ .github/ CI and dependency update configuration
28
+ ```
29
+
30
+ The `package.json` `files` allowlist defines the npm tarball.
31
+ `npm run test:package` verifies the installed files and offline CLI commands. `npm run build`
32
+ retains its verified tarball under the ignored `release/` directory. Credentials
33
+ belong in local environment files, not in source or package contents.
@@ -0,0 +1,131 @@
1
+ # Testing
2
+
3
+ Run these commands from a source checkout. An installed npm package contains
4
+ runtime code and documentation, but does not contain tests or development scripts.
5
+
6
+ ## Automated code and package checks
7
+
8
+ Use Node.js 22.16 or newer. Runtime code has zero npm dependencies. Run
9
+ `npm ci --ignore-scripts` to install the pinned development tools: TypeScript
10
+ 5.8.3, the official Workers declarations, and the configuration-schema validator.
11
+ Source and installed-consumer type checks use the same local compiler.
12
+
13
+ | Command | Verification |
14
+ | --- | --- |
15
+ | `npm run check` | Public-source layout, JavaScript syntax, JSON, formatting, local doc links, versions |
16
+ | `npm test` | SDK, CLI, provider, and file/transport behavior using fixtures and loopback servers |
17
+ | `npm run test:coverage` | The functional suite with production source/bin coverage floors |
18
+ | `npm run typecheck` | Positive and expected-negative TypeScript API contracts |
19
+ | `npm run test:package` | Pack, offline install, root/custom exports and types, browser-safe imports, presets/modules, contents and docs |
20
+ | `npm run build` | Retain a versioned npm tarball after checking its offline installation |
21
+ | `npm run verify` | Source checks, tests, type contracts, and package smoke check |
22
+
23
+ `verify` is a convenience command for routine changes. It already runs `npm test`
24
+ and `test:package`; running coverage and build immediately after it repeats
25
+ those checks. CI and the release guide run `check`, `test:coverage`,
26
+ `typecheck`, and `build` once each.
27
+
28
+ These commands validate code behavior and package integrity. Model-quality
29
+ evaluation is a separate activity, not part of the test suite: these commands do
30
+ not score model answers, measure provider speed, or use paid inference. Coverage
31
+ floors are 90% lines, 80% branches, and 85% functions. Coverage does not establish model
32
+ quality, correctness of every path, or current hosted compatibility.
33
+ The CI configuration targets Linux, Windows, and macOS on Node 22.16 and Node 24;
34
+ consult actual run results for a particular commit instead of treating the matrix
35
+ as evidence that every environment passed.
36
+
37
+ ## Suite ownership
38
+
39
+ - `contract.test.mjs`: request/result contracts, builders, decision policy, and JSON safety.
40
+ - `bridge.test.mjs`: SDK evaluation, extensions, observers, deadlines, and batches.
41
+ - `providers.test.mjs`: provider wire formats, response parsing, model listing, and configuration.
42
+ - `transport.test.mjs`: HTTP policy, limits, retries, cancellation, and deadlines.
43
+ - `deadlines.test.mjs`: synchronous preparation/dispatch/completion and inherited budgets.
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.
46
+ - `cloudflare*.test.mjs`: models, images, codecs, REST/binding/Gateway arguments, errors, and CLI limits.
47
+ - `custom-providers.test.mjs`, `custom-config.test.mjs`: classified SDK paths, provenance, presets/modules, schema and initialization.
48
+ - `generative-helpers.test.mjs`: exported prompt/normalization helper contracts and unsupported input rejection.
49
+ - `config.test.mjs`: file/environment/flag precedence and provider transitions.
50
+ - `cli.test.mjs`: commands, streams, exit codes, modules, and signals.
51
+ - `io.test.mjs`: atomic output, file aliases, and cancellation.
52
+ - `ordered.test.mjs`: ordered streaming and bounded concurrency.
53
+ - `support.mjs` and `fixtures.mjs`: local test setup and synthetic domain data.
54
+ - `types.mts`, `providers.types.mts`, `custom.types.mts`: public type inference and rejected API usage.
55
+ - `decisions.types.mts`, `cloudflare.types.mts`: richer questions, native APIs, and precision settings.
56
+ - `cloudflare-worker.types.mts`: compatibility with official Workers binding declarations.
57
+
58
+ Node's reported test count includes each row of a parameterized input table. It
59
+ is not a count of independent features; retain separate rows when they protect
60
+ different contract or protocol paths.
61
+
62
+ All model responses used by ordinary tests are synthetic. HTTP integration servers
63
+ listen on loopback. Tests do not require account keys or make paid model calls.
64
+ Test workspaces are temporary.
65
+
66
+ ## Optional authenticated provider smoke check
67
+
68
+ Live inference is explicitly opted in and can incur charges. Configure credentials
69
+ locally, then on POSIX shells:
70
+
71
+ ```bash
72
+ RUN_LIVE_TESTS=1 npm run smoke:live -- --env-file .env
73
+ ```
74
+
75
+ On PowerShell:
76
+
77
+ ```powershell
78
+ $env:RUN_LIVE_TESTS = '1'
79
+ npm run smoke:live -- --env-file .env
80
+ Remove-Item Env:RUN_LIVE_TESTS
81
+ ```
82
+
83
+ Forward provider/model/config options for the selected account. The helper refuses
84
+ to infer without the opt-in flag and returns real results or errors. It checks a
85
+ configured inference path, not model quality or throughput. For model listing
86
+ alone, use `node bin/decision.mjs models --env-file .env`.
87
+ Model listing is unsupported for OpenAI Decisions and Cloudflare Clef.
88
+
89
+ The OpenAI Decisions helper performs four bounded common/native requests when
90
+ invoked with `--decisions`. It includes a valid embedded PNG, typed choices, and
91
+ labelled scores. For example, after setting the same opt-in variable:
92
+
93
+ ```text
94
+ npm run smoke:live -- --decisions --env-file .env
95
+ ```
96
+
97
+ Cloudflare REST can use the ordinary smoke command with
98
+ `--provider cloudflare-decisions --model clef`, `--model clef-flash`, or
99
+ `--model clef-omni`, loading its
100
+ account/token environment explicitly. These invocations each check one common
101
+ request. Native, image, large-distribution, binding, and Gateway checks require
102
+ separate bounded cases; test the latter two in the intended existing runtime and
103
+ Gateway. REST busy rejection has a documented
104
+ [service limitation](../guides/CLOUDFLARE_DECISIONS.md#capacity-rejection-and-ai-gateway).
105
+ Test all three models and both access shapes when changing those paths. Include typed
106
+ string/boolean identity, labelled scores, reported confidence/usage, and distinct
107
+ request/Gateway IDs from concurrent calls. Enabling binding busy mode verifies
108
+ option acceptance; it does not establish behavior under exhausted capacity.
109
+ Header/dimension preflight does not fully decode images, so live image fixtures
110
+ must also contain valid encoded image data.
111
+ Omni fixtures must contain genuinely decodable WAV/MP3 and MP4/WebM media for
112
+ hosted tests. Local authored container fixtures verify inspection and protocol
113
+ behavior without claiming codec validity. Include grouped modalities, duration
114
+ and size boundaries, effective-model overrides, request bodies above 13 MiB,
115
+ and explicit smaller ceilings. Gateway caching/logging should be disabled for
116
+ test payloads, and each bounded run should have a request and total time budget.
117
+
118
+ The SDK, CLI, and ordinary checks do not create Workers or Gateways. Provisioning
119
+ and cleanup belong to the application's separately authorized environment setup.
120
+
121
+ ## Package verification
122
+
123
+ To test a specific local tarball against this source checkout:
124
+
125
+ ```text
126
+ node scripts/package-smoke.mjs --tarball /path/to/fayegram-ai-decision-bridge-VERSION.tgz
127
+ ```
128
+
129
+ The check installs the specified archive offline and compares installed bytes,
130
+ documentation links, exports, CLI shims, and the bundled sample. It also rejects
131
+ local archives and development-only files leaking into the runtime package.
@@ -0,0 +1,43 @@
1
+ # Browser integration
2
+
3
+ The SDK exports browser-compatible ESM. Follow the
4
+ [installation guide](GETTING_STARTED.md#install-into-your-application), then import
5
+ `@fayegram-ai/decision-bridge` through your browser application's module bundler. The
6
+ optional `decision-bridge` command still requires Node.js.
7
+ Omni's embedded audio/video validation is browser-safe and adds no runtime media
8
+ library. Build data URLs in the application; the SDK does not fetch remote media.
9
+
10
+ Built-in REST providers need explicitly supplied credentials in browser code;
11
+ Node environment-variable defaults and `.env` files are not available. Cloudflare
12
+ REST also needs `accountId`; its Workers AI binding is configured inside a Worker,
13
+ as described in the [Cloudflare guide](CLOUDFLARE_DECISIONS.md#workers-ai-binding).
14
+ A compatible loopback endpoint can explicitly use `apiKey: null`.
15
+ The following example requires TypeSafe to permit your application's origin and
16
+ provide a credential suitable for client exposure. `browserCredential` is supplied
17
+ by your application's credential flow:
18
+
19
+ ```javascript
20
+ import { createBridge, JevProvider, noul } from '@fayegram-ai/decision-bridge';
21
+
22
+ const bridge = createBridge({
23
+ provider: new JevProvider({ apiKey: browserCredential }),
24
+ });
25
+ const result = await bridge.evaluate({
26
+ state: 'A user-supplied statement',
27
+ questions: { relevant: noul('Is this relevant?') },
28
+ });
29
+ console.log(result.answers.relevant.noul);
30
+ ```
31
+
32
+ This sends the request **directly from the browser**. The provider's server must
33
+ accept the page's origin in its CORS preflight response and allow the method and
34
+ headers used by the SDK. For Jev evaluation those include `POST`, `Authorization`,
35
+ and `Content-Type`. If the preflight is rejected, the browser sends no evaluation
36
+ request; neither the SDK nor a browser setting can override that server policy.
37
+ Check your intended origin with TypeSafe before relying on direct Jev calls.
38
+
39
+ Any key delivered to browser JavaScript can be read by the app's users. Only use
40
+ a credential that the provider explicitly permits for browser exposure. If an
41
+ account key must remain private, keep the provider call in your own backend and
42
+ invoke that backend from the browser. This is a credential boundary, separate
43
+ from whether the SDK's modules can run in a browser.