@fayegram-ai/decision-bridge 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +10 -0
- package/CHANGELOG.md +79 -0
- package/CONTRIBUTING.md +57 -0
- package/LICENSE +21 -0
- package/README.md +313 -2
- package/SECURITY.md +88 -0
- package/bin/decision.mjs +15 -0
- package/docs/README.md +58 -0
- package/docs/development/ARCHITECTURE.md +139 -0
- package/docs/development/DESIGN.md +77 -0
- package/docs/development/README.md +12 -0
- package/docs/development/RELEASING.md +100 -0
- package/docs/development/REPOSITORY_LAYOUT.md +33 -0
- package/docs/development/TESTING.md +153 -0
- package/docs/guides/BROWSER.md +43 -0
- package/docs/guides/CLOUDFLARE_DECISIONS.md +374 -0
- package/docs/guides/CUSTOMIZATION.md +141 -0
- package/docs/guides/CUSTOM_DECISION.md +66 -0
- package/docs/guides/CUSTOM_GENERATIVE.md +164 -0
- package/docs/guides/CUSTOM_PROVIDERS.md +83 -0
- package/docs/guides/GETTING_STARTED.md +252 -0
- package/docs/guides/OPENAI_DECISIONS.md +252 -0
- package/docs/guides/PLATFORMS.md +107 -0
- package/docs/guides/SWITCHING_MODELS.md +208 -0
- package/docs/guides/TROUBLESHOOTING.md +96 -0
- package/docs/reference/CLI.md +213 -0
- package/docs/reference/CONFIGURATION.md +170 -0
- package/docs/reference/ERRORS.md +85 -0
- package/docs/reference/PROVIDERS.md +116 -0
- package/docs/reference/SDK.md +394 -0
- package/docs/reference/SOURCES.md +51 -0
- package/examples/basic.mjs +17 -0
- package/examples/batch.mjs +13 -0
- package/examples/cloudflare-decisions.mjs +22 -0
- package/examples/cloudflare-omni.mjs +32 -0
- package/examples/cloudflare-worker.mjs +21 -0
- package/examples/cloudflare.native.json +28 -0
- package/examples/configs/anthropic.json +9 -0
- package/examples/configs/cloudflare-decisions.json +8 -0
- package/examples/configs/custom-decision.json +9 -0
- package/examples/configs/custom-generative.json +14 -0
- package/examples/configs/jev.json +7 -0
- package/examples/configs/local.json +12 -0
- package/examples/configs/openai-decisions.json +7 -0
- package/examples/configs/openai.json +10 -0
- package/examples/configs/openrouter.json +10 -0
- package/examples/custom/decision-provider.mjs +15 -0
- package/examples/custom/generative-provider.mjs +13 -0
- package/examples/custom/openrouter.mjs +13 -0
- package/examples/customize.mjs +23 -0
- package/examples/decisions.native.json +19 -0
- package/examples/extended.mjs +43 -0
- package/examples/openai-decisions.mjs +20 -0
- package/examples/request.json +31 -0
- package/examples/requests.jsonl +2 -0
- package/package.json +87 -4
- package/schemas/decision.config.schema.json +553 -0
- package/src/async.mjs +63 -0
- package/src/batch.mjs +38 -0
- package/src/bridge.mjs +184 -0
- package/src/capabilities.mjs +92 -0
- package/src/cli/config-validation.mjs +89 -0
- package/src/cli/config.mjs +85 -0
- package/src/cli/decisions.mjs +21 -0
- package/src/cli/initialize.mjs +85 -0
- package/src/cli/io.mjs +171 -0
- package/src/cli/main.mjs +281 -0
- package/src/cli/ordered.mjs +43 -0
- package/src/cli/provider-loader.mjs +58 -0
- package/src/cloudflare-decisions.d.mts +78 -0
- package/src/custom/decision.d.mts +5 -0
- package/src/custom/decision.mjs +6 -0
- package/src/custom/definition.mjs +19 -0
- package/src/custom/generative/anthropic.mjs +75 -0
- package/src/custom/generative/index.d.mts +42 -0
- package/src/custom/generative/index.mjs +29 -0
- package/src/custom/generative/openai-compatible.mjs +101 -0
- package/src/custom/generative/schema.mjs +95 -0
- package/src/custom/generative/shared.mjs +39 -0
- package/src/decisions.d.mts +50 -0
- package/src/embedded.mjs +24 -0
- package/src/errors.mjs +49 -0
- package/src/index.d.mts +232 -0
- package/src/index.mjs +7 -0
- package/src/input.mjs +37 -0
- package/src/options.mjs +15 -0
- package/src/policy.mjs +44 -0
- package/src/probabilities.mjs +27 -0
- package/src/provider-contract.mjs +42 -0
- package/src/providers/cloudflare-audio.mjs +83 -0
- package/src/providers/cloudflare-codec.mjs +39 -0
- package/src/providers/cloudflare-decisions.mjs +81 -0
- package/src/providers/cloudflare-images.mjs +95 -0
- package/src/providers/cloudflare-media.mjs +36 -0
- package/src/providers/cloudflare-preflight.mjs +92 -0
- package/src/providers/cloudflare-profile.mjs +102 -0
- package/src/providers/cloudflare-transport.mjs +63 -0
- package/src/providers/cloudflare-validation.mjs +48 -0
- package/src/providers/cloudflare-video.mjs +84 -0
- package/src/providers/decisions-codec.mjs +61 -0
- package/src/providers/decisions-preflight.mjs +31 -0
- package/src/providers/decisions-validation.mjs +151 -0
- package/src/providers/index.mjs +26 -0
- package/src/providers/jev.mjs +51 -0
- package/src/providers/media-binary.mjs +51 -0
- package/src/providers/openai-decisions.mjs +58 -0
- package/src/providers/openai-profile.mjs +24 -0
- package/src/questions.mjs +15 -0
- package/src/response-transport.mjs +176 -0
- package/src/runtime-env.mjs +4 -0
- package/src/transport.mjs +51 -0
- package/src/validation.mjs +245 -0
- package/src/version.mjs +2 -0
|
@@ -0,0 +1,139 @@
|
|
|
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 selection,
|
|
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
|
+
## Model selection and request preparation
|
|
50
|
+
|
|
51
|
+
The bridge applies the provider's configured default when a request omits `model`.
|
|
52
|
+
Its validated request and extension context retain that selected string. A provider
|
|
53
|
+
may resolve a selection to an upstream ID while preparing its outgoing request;
|
|
54
|
+
the shared provider contract has no selector-resolution hook.
|
|
55
|
+
|
|
56
|
+
OpenAI's `openai-profile.mjs` owns the `default` selection, accepted selectors,
|
|
57
|
+
upstream targets, and capabilities. Common and native preparation retain the
|
|
58
|
+
validated selection separately from the resolved native request. Preflight returns
|
|
59
|
+
the selected request, while serialization and byte-limit checks use the resolved
|
|
60
|
+
request. Common evaluation and native `createDecision()` share dispatch, which
|
|
61
|
+
sends only that resolved request.
|
|
62
|
+
|
|
63
|
+
Successful OpenAI calls report the selected string in `meta.requestedModel` and
|
|
64
|
+
the outgoing ID in `meta.resolvedModel`. The response's `model` retains the
|
|
65
|
+
service-reported identity. CLI offline validation and execution use the same
|
|
66
|
+
preflight, and generated OpenAI requests inherit selection from configuration.
|
|
67
|
+
See [OpenAI model selection](../guides/OPENAI_DECISIONS.md#model-selection).
|
|
68
|
+
|
|
69
|
+
## Module map
|
|
70
|
+
|
|
71
|
+
| Module | Responsibility |
|
|
72
|
+
| --- | --- |
|
|
73
|
+
| `src/index.mjs`, `src/index.d.mts` | Public runtime exports and TypeScript contract |
|
|
74
|
+
| `src/bridge.mjs` | Orchestration, extension lifecycle, total deadline, immutable results |
|
|
75
|
+
| `src/validation.mjs`, `src/input.mjs` | Lossless snapshots, common input and result invariants |
|
|
76
|
+
| `src/questions.mjs` | Immutable typed question builders, independent of inference selection |
|
|
77
|
+
| `src/capabilities.mjs` | Provider/model capability checks and common schema versions |
|
|
78
|
+
| `src/probabilities.mjs` | Provider-selected precision allowance without normalization |
|
|
79
|
+
| `src/provider-contract.mjs` | Required classification, authoritative metadata, and generative provenance |
|
|
80
|
+
| `src/custom/decision.mjs` | Explicit native decision definition helper |
|
|
81
|
+
| `src/custom/generative/` | Opt-in protocol presets, schema, prompts, and result derivation |
|
|
82
|
+
| `schemas/decision.config.schema.json` | Shipped CLI configuration structure and editor support |
|
|
83
|
+
| `src/providers/` | API orchestration, model profiles, preflight, codecs, bounded image/audio/video inspection, and transports |
|
|
84
|
+
| `src/providers/openai-profile.mjs`, `src/providers/decisions-preflight.mjs` | Release-owned OpenAI selection, capabilities, and preparation of selected and outgoing requests |
|
|
85
|
+
| `src/embedded.mjs` | Shared embedded data URL and canonical base64 checks |
|
|
86
|
+
| `src/transport.mjs`, `src/response-transport.mjs` | Credential destinations, bounded bodies, safe errors, retries |
|
|
87
|
+
| `src/async.mjs` | Deadlines and cancellation races |
|
|
88
|
+
| `src/options.mjs` | Unknown-field/accessor rejection for options |
|
|
89
|
+
| `src/errors.mjs` | DecisionError and safe public diagnostics |
|
|
90
|
+
| `src/batch.mjs` | Ordered bounded-concurrency SDK arrays |
|
|
91
|
+
| `src/policy.mjs` | Explicit choice thresholds, without action execution |
|
|
92
|
+
| `src/cli/ordered.mjs` | Concurrent JSONL processing with a bounded ordered window |
|
|
93
|
+
| `src/cli/`, `bin/decision.mjs` | Configuration, input/output, commands, process signals |
|
|
94
|
+
|
|
95
|
+
## Results and precision
|
|
96
|
+
|
|
97
|
+
Generative providers elicit distributions and derive argmax choices, weighted
|
|
98
|
+
scores, and rubric legends in code. Native decision providers validate and retain
|
|
99
|
+
their returned values, confidence, and reported usage. No path repairs malformed
|
|
100
|
+
distributions or invents confidence. The common shape preserves provenance without
|
|
101
|
+
claiming equivalent statistical semantics across models.
|
|
102
|
+
|
|
103
|
+
The bridge takes result-validation policy from the provider contract. Cloudflare
|
|
104
|
+
uses an allowance for four-decimal distributions; other built-ins retain the
|
|
105
|
+
baseline. Response metadata cannot relax validation. See the [SDK reference](../reference/SDK.md).
|
|
106
|
+
Application code passes that precision explicitly when using `decideChoice`; the
|
|
107
|
+
policy helper does not infer it from the answer or its metadata.
|
|
108
|
+
|
|
109
|
+
## Reliability and configuration
|
|
110
|
+
|
|
111
|
+
Provider deadlines include dispatch, configured retries, backoff, and bounded body
|
|
112
|
+
reading. The bridge deadline additionally covers validation, preparation, provider
|
|
113
|
+
waiting, and result processing. Expired synchronous work cannot dispatch a call.
|
|
114
|
+
Cancellation bounds waiting for custom promises; custom code must honor signals
|
|
115
|
+
to release its own resources. Observations use a separate bounded budget.
|
|
116
|
+
|
|
117
|
+
Retries cover selected explicit transient responses. Ambiguous failures and failed
|
|
118
|
+
observers do not trigger another inference. CLI atomic files protect previous
|
|
119
|
+
output but cannot undo remote work or emitted stdout.
|
|
120
|
+
|
|
121
|
+
JSON configuration is explicit. Custom ESM executes only when selected. Custom
|
|
122
|
+
origins do not inherit unrelated ambient credentials. Gateway settings remain
|
|
123
|
+
provider configuration, and do not replace the bridge's total deadline.
|
|
124
|
+
|
|
125
|
+
## Extension boundaries
|
|
126
|
+
|
|
127
|
+
Use preparation hooks for context, observation hooks for metrics, classified custom providers
|
|
128
|
+
for another API, and application code for policy. Ordered images and richer
|
|
129
|
+
questions require declared capabilities. Native provider guides document limits.
|
|
130
|
+
Cloudflare Omni supports grouped embedded images/audio/video before text. Model
|
|
131
|
+
profiles resolve request byte limits per call; transport instances share no
|
|
132
|
+
mutable request limit or response identifiers. Header/container inspection is
|
|
133
|
+
bounded and does not perform full media decoding.
|
|
134
|
+
|
|
135
|
+
The SDK does not host models or provide a server API, persistent state, autonomous
|
|
136
|
+
actions, streaming, transcription, transcoding, frame extraction,
|
|
137
|
+
provider-side asynchronous batch jobs, platform
|
|
138
|
+
management, automatic model search, or automatic provider failover. SDK arrays and
|
|
139
|
+
CLI JSONL batches provide bounded client-side concurrency.
|
|
@@ -0,0 +1,77 @@
|
|
|
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
|
+
## Release-owned model selectors
|
|
47
|
+
|
|
48
|
+
OpenAI Decisions offers `default` for the provider's default supported model and
|
|
49
|
+
`luna` for the supported Luna-family model, alongside explicit supported upstream
|
|
50
|
+
IDs. The installed package fixes the target and capability profile for each
|
|
51
|
+
selector. The provider resolves it locally before serialization; no discovery,
|
|
52
|
+
automatic upgrade, or fallback occurs during a call. Consequence: applications can
|
|
53
|
+
use a stable selection string while inspecting selected, outgoing, and reported
|
|
54
|
+
model identities separately. A future target change requires an intentional
|
|
55
|
+
package update and verification of that model's protocol and capabilities.
|
|
56
|
+
|
|
57
|
+
## Conservative retries and independent observations
|
|
58
|
+
|
|
59
|
+
Retry selected explicit transient HTTP statuses within a deadline. Do not retry
|
|
60
|
+
ambiguous network failures, malformed decisions, or observer failures. Consequence:
|
|
61
|
+
users can choose manual retry policies, but exactly-once billing cannot be promised.
|
|
62
|
+
|
|
63
|
+
## MIT licensing and coordinated distribution
|
|
64
|
+
|
|
65
|
+
Publish the maintained source under the MIT License, with the copyright notice
|
|
66
|
+
in `LICENSE` and matching SPDX identifiers in package metadata. Release the source
|
|
67
|
+
repository and npm package together. Consequence: source and package recipients
|
|
68
|
+
have the same MIT permissions and obligations; building an archive alone does not
|
|
69
|
+
publish a release.
|
|
70
|
+
|
|
71
|
+
## Verified npm package artifact
|
|
72
|
+
|
|
73
|
+
Build a versioned npm tarball from the source package and retain it only after an
|
|
74
|
+
offline installation check of the exact archive. Publish that verified artifact
|
|
75
|
+
to the public npm registry as part of the coordinated source and package release;
|
|
76
|
+
building alone never publishes it. Consequence: consumers install the release from
|
|
77
|
+
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,153 @@
|
|
|
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, selectors and model identities, 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
|
+
### OpenAI model-selector coverage
|
|
67
|
+
|
|
68
|
+
For changes to OpenAI selection or preparation, run the focused suites from the
|
|
69
|
+
source root:
|
|
70
|
+
|
|
71
|
+
```text
|
|
72
|
+
node --test test/decisions-selectors.test.mjs test/decisions-preflight.test.mjs test/decisions-cli.test.mjs
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
These cover omitted, `default`, `luna`, and explicit upstream selection; unsupported
|
|
76
|
+
and malformed values; independently selected, outgoing, and reported identities;
|
|
77
|
+
capabilities and extension context; immutable input; SDK batch preflight; resolved
|
|
78
|
+
wire-byte limits; CLI precedence and mixed-selector rows; and generated requests
|
|
79
|
+
that inherit later configuration changes. Existing Decisions suites also cover
|
|
80
|
+
revalidation after input preparation, refusals, retries, and deadlines.
|
|
81
|
+
|
|
82
|
+
Type and installed-package checks exercise metadata declarations, SDK/CLI
|
|
83
|
+
selection, and browser execution without Node globals. Use `npm run verify` for
|
|
84
|
+
the complete integration check. A selector mapping change must be verified against
|
|
85
|
+
the target model's protocol and capabilities; local fixtures alone do not establish
|
|
86
|
+
compatibility with a newly selected upstream model.
|
|
87
|
+
|
|
88
|
+
## Optional authenticated provider smoke check
|
|
89
|
+
|
|
90
|
+
Live inference is explicitly opted in and can incur charges. Configure credentials
|
|
91
|
+
locally, then on POSIX shells:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
RUN_LIVE_TESTS=1 npm run smoke:live -- --env-file .env
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
On PowerShell:
|
|
98
|
+
|
|
99
|
+
```powershell
|
|
100
|
+
$env:RUN_LIVE_TESTS = '1'
|
|
101
|
+
npm run smoke:live -- --env-file .env
|
|
102
|
+
Remove-Item Env:RUN_LIVE_TESTS
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Forward provider/model/config options for the selected account. The helper refuses
|
|
106
|
+
to infer without the opt-in flag and returns real results or errors. It checks a
|
|
107
|
+
configured inference path, not model quality or throughput. For model listing
|
|
108
|
+
alone, use `node bin/decision.mjs models --env-file .env`.
|
|
109
|
+
Model listing is unsupported for OpenAI Decisions and Cloudflare Clef.
|
|
110
|
+
|
|
111
|
+
The OpenAI Decisions helper performs four bounded common/native requests when
|
|
112
|
+
invoked with `--decisions`. It includes a valid embedded PNG, typed choices, and
|
|
113
|
+
labelled scores. For example, after setting the same opt-in variable:
|
|
114
|
+
|
|
115
|
+
```text
|
|
116
|
+
npm run smoke:live -- --decisions --env-file .env
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Cloudflare REST can use the ordinary smoke command with
|
|
120
|
+
`--provider cloudflare-decisions --model clef`, `--model clef-flash`, or
|
|
121
|
+
`--model clef-omni`, loading its
|
|
122
|
+
account/token environment explicitly. These invocations each check one common
|
|
123
|
+
request. Native, image, large-distribution, binding, and Gateway checks require
|
|
124
|
+
separate bounded cases; test the latter two in the intended existing runtime and
|
|
125
|
+
Gateway. REST busy rejection has a documented
|
|
126
|
+
[service limitation](../guides/CLOUDFLARE_DECISIONS.md#capacity-rejection-and-ai-gateway).
|
|
127
|
+
Test all three models and both access shapes when changing those paths. Include typed
|
|
128
|
+
string/boolean identity, labelled scores, reported confidence/usage, and distinct
|
|
129
|
+
request/Gateway IDs from concurrent calls. Enabling binding busy mode verifies
|
|
130
|
+
option acceptance; it does not establish behavior under exhausted capacity.
|
|
131
|
+
Header/dimension preflight does not fully decode images, so live image fixtures
|
|
132
|
+
must also contain valid encoded image data.
|
|
133
|
+
Omni fixtures must contain genuinely decodable WAV/MP3 and MP4/WebM media for
|
|
134
|
+
hosted tests. Local authored container fixtures verify inspection and protocol
|
|
135
|
+
behavior without claiming codec validity. Include grouped modalities, duration
|
|
136
|
+
and size boundaries, effective-model overrides, request bodies above 13 MiB,
|
|
137
|
+
and explicit smaller ceilings. Gateway caching/logging should be disabled for
|
|
138
|
+
test payloads, and each bounded run should have a request and total time budget.
|
|
139
|
+
|
|
140
|
+
The SDK, CLI, and ordinary checks do not create Workers or Gateways. Provisioning
|
|
141
|
+
and cleanup belong to the application's separately authorized environment setup.
|
|
142
|
+
|
|
143
|
+
## Package verification
|
|
144
|
+
|
|
145
|
+
To test a specific local tarball against this source checkout:
|
|
146
|
+
|
|
147
|
+
```text
|
|
148
|
+
node scripts/package-smoke.mjs --tarball /path/to/fayegram-ai-decision-bridge-VERSION.tgz
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
The check installs the specified archive offline and compares installed bytes,
|
|
152
|
+
documentation links, exports, CLI shims, and the bundled sample. It also rejects
|
|
153
|
+
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.
|