@godspeedai/cognate-capabilities 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +127 -10
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -1,12 +1,129 @@
|
|
|
1
1
|
# @godspeedai/cognate-capabilities
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
3
|
+
Deterministic-first capability selection and the model provider contract for Cognate
|
|
4
|
+
applications. Given a requirement and a set of candidate providers, it decides — explainably
|
|
5
|
+
and durably — which provider to use, and it defines the plain-TypeScript `ModelProvider`
|
|
6
|
+
interface that model integrations implement.
|
|
7
|
+
|
|
8
|
+
**When to use this package:** you choose between multiple providers for the same capability
|
|
9
|
+
(for example several models) and need eligibility rules that always apply, ranking that can
|
|
10
|
+
never override policy, and a recorded explanation of every decision. Implementors of model
|
|
11
|
+
providers also need it for the `ModelProvider`, `ModelRequest`/`ModelResponse`, and
|
|
12
|
+
`ModelProviderError` types.
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```sh
|
|
17
|
+
bun add @godspeedai/cognate-capabilities
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Requires [Bun](https://bun.sh) >= 1.4.0. Recording selections needs any
|
|
21
|
+
[`@godspeedai/cognate-events`](https://www.npmjs.com/package/@godspeedai/cognate-events)
|
|
22
|
+
store. The SDK ships Bun-native TypeScript source, so add `@types/bun` and `@types/node` as
|
|
23
|
+
dev dependencies when typechecking your project.
|
|
24
|
+
|
|
25
|
+
## Quick start
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
import { createMemoryStore } from "@godspeedai/cognate-store-memory";
|
|
29
|
+
import {
|
|
30
|
+
compatibilityRule,
|
|
31
|
+
createSelector,
|
|
32
|
+
recordSelection,
|
|
33
|
+
} from "@godspeedai/cognate-capabilities";
|
|
34
|
+
|
|
35
|
+
const store = createMemoryStore();
|
|
36
|
+
|
|
37
|
+
const selector = createSelector({
|
|
38
|
+
rules: [
|
|
39
|
+
compatibilityRule, // contract id, major version, and attributes must satisfy the requirement
|
|
40
|
+
{
|
|
41
|
+
id: "policy.no-cloud",
|
|
42
|
+
evaluate: (candidate) =>
|
|
43
|
+
candidate.contract.attributes?.hosting === "cloud"
|
|
44
|
+
? { eligible: false, reason: "tenant forbids cloud models" }
|
|
45
|
+
: { eligible: true, reason: "hosting allowed" },
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
// ranker: optional; without one, eligible providers are picked in provider-id order
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
const decision = await selector.select({
|
|
52
|
+
requirement: { capability: "model.generate", version: "1.0", attributes: { structured_output: true } },
|
|
53
|
+
candidates: [
|
|
54
|
+
{ providerId: "cloud-a", contract: { id: "model.generate", version: "1.2.0", attributes: { structured_output: true, hosting: "cloud" } } },
|
|
55
|
+
{ providerId: "local-b", contract: { id: "model.generate", version: "1.0.0", attributes: { structured_output: true } } },
|
|
56
|
+
],
|
|
57
|
+
principal: { id: "alice", kind: "user" },
|
|
58
|
+
tenant: "tenant-a",
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
decision.eligible; // ["local-b"] — cloud-a failed the policy rule
|
|
62
|
+
decision.selected; // "local-b"
|
|
63
|
+
decision.filters; // every (provider, rule) result with its reason
|
|
64
|
+
|
|
65
|
+
// Make the decision a durable fact with its full explanation:
|
|
66
|
+
await recordSelection(store, decision, { tenant: "tenant-a", scopeId: "root", correlationId: "corr-1", runId: "run-1" });
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## How selection works
|
|
70
|
+
|
|
71
|
+
1. **Eligibility first.** Every `EligibilityRule` evaluates every candidate. Rules must be
|
|
72
|
+
pure and deterministic; a candidate is eligible only if all rules pass.
|
|
73
|
+
2. **Ranking second — and contained.** The optional `Ranker` sees only the eligible set and
|
|
74
|
+
can narrow it, never widen it. Ranker entries that are unknown, ineligible, duplicated, or
|
|
75
|
+
non-finite are dropped. A missing or throwing ranker falls back to deterministic
|
|
76
|
+
provider-id order, recorded in `decision.fallback`. With no eligible candidate, `selected`
|
|
77
|
+
is `null` and the ranker is never called.
|
|
78
|
+
3. **Durable feedback.** `recordSelection` appends a `capability.selected` event with the
|
|
79
|
+
full explanation; `recordOutcome` appends a `capability.outcome` for a recorded selection.
|
|
80
|
+
Run `outcomeProjection()` in your projection runner to derive per-capability success
|
|
81
|
+
counts, then pass `createOutcomeRanker(store)` as the selector's ranker: it scores
|
|
82
|
+
providers by an upper-confidence-bound rule over recorded outcomes, tries untried
|
|
83
|
+
providers first, and is deterministic — replaying the same outcomes yields the same
|
|
84
|
+
ranking. Feedback only influences ranking after it is committed and projected.
|
|
85
|
+
|
|
86
|
+
## The model provider contract
|
|
87
|
+
|
|
88
|
+
The package also defines the model integration contract every provider implements:
|
|
89
|
+
|
|
90
|
+
- `ModelProvider` — `id`, `model`, declared `features` (streaming, tool use, structured
|
|
91
|
+
output, multimodal input, context limit), `generate(request)` and `stream(request)`.
|
|
92
|
+
- `ModelRequest` / `ModelResponse` / `ModelDelta` — messages, tools, `responseFormat`, and
|
|
93
|
+
the streamed delta shapes (`text`, `tool_call_start`, `tool_call_args`, `tool_call_end`,
|
|
94
|
+
`tool_call`, `done`).
|
|
95
|
+
- `ModelProviderError` — typed failure kinds: `unauthorized`, `rate_limited`,
|
|
96
|
+
`invalid_request`, `unavailable`, `cancelled`, `malformed_response`.
|
|
97
|
+
- `modelContract(provider)` — the `CapabilityContract` a provider publishes (capability id
|
|
98
|
+
`model.generate`, features as attributes, never credentials).
|
|
99
|
+
|
|
100
|
+
Ready-made providers:
|
|
101
|
+
[`@godspeedai/cognate-provider-local`](https://www.npmjs.com/package/@godspeedai/cognate-provider-local)
|
|
102
|
+
(deterministic, offline) and
|
|
103
|
+
[`@godspeedai/cognate-provider-openai-compatible`](https://www.npmjs.com/package/@godspeedai/cognate-provider-openai-compatible)
|
|
104
|
+
(any OpenAI-compatible HTTP endpoint).
|
|
105
|
+
|
|
106
|
+
## Limitations
|
|
107
|
+
|
|
108
|
+
- Rules and rankers are yours to write; this package guarantees containment and honest
|
|
109
|
+
bookkeeping, not ranking quality.
|
|
110
|
+
- The built-in outcome ranker is a deterministic bandit heuristic over your own recorded
|
|
111
|
+
outcomes — not a trained model — and scores are only comparable within one capability.
|
|
112
|
+
- `recordSelection`/`recordOutcome` write to the store you give them; without a durable
|
|
113
|
+
store, feedback is lost on restart.
|
|
114
|
+
|
|
115
|
+
## Related packages
|
|
116
|
+
|
|
117
|
+
- [`@godspeedai/cognate-kernel-api`](https://www.npmjs.com/package/@godspeedai/cognate-kernel-api) —
|
|
118
|
+
`Requirement`, `CapabilityContract`, and the compatibility check used by `compatibilityRule`.
|
|
119
|
+
- [`@godspeedai/cognate-events`](https://www.npmjs.com/package/@godspeedai/cognate-events) —
|
|
120
|
+
the store contract for recording selections and outcomes.
|
|
121
|
+
- [`@godspeedai/cognate-projections`](https://www.npmjs.com/package/@godspeedai/cognate-projections) —
|
|
122
|
+
the projection runner that applies `outcomeProjection()`.
|
|
123
|
+
- [`@godspeedai/cognate-runtime-bun`](https://www.npmjs.com/package/@godspeedai/cognate-runtime-bun) —
|
|
124
|
+
the reference runtime, which wires selection and providers together.
|
|
125
|
+
- [`@godspeedai/cognate`](https://www.npmjs.com/package/@godspeedai/cognate) — the SDK umbrella.
|
|
126
|
+
|
|
127
|
+
## License
|
|
128
|
+
|
|
129
|
+
Apache-2.0
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@godspeedai/cognate-capabilities",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Two-phase capability selection: deterministic eligibility, then contained adaptive ranking with durable explanations (spec §8.2, §17, §30).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -22,9 +22,9 @@
|
|
|
22
22
|
".": "./src/index.ts"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@godspeedai/cognate-events": "^0.1.
|
|
26
|
-
"@godspeedai/cognate-kernel-api": "^0.1.
|
|
27
|
-
"@godspeedai/cognate-projections": "^0.1.
|
|
25
|
+
"@godspeedai/cognate-events": "^0.1.2",
|
|
26
|
+
"@godspeedai/cognate-kernel-api": "^0.1.2",
|
|
27
|
+
"@godspeedai/cognate-projections": "^0.1.2"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@godspeedai/cognate-store-memory": "workspace:*",
|