@arnilo/prism 0.0.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/CHANGELOG.md +31 -0
- package/LICENSE +21 -0
- package/README.md +139 -0
- package/dist/agents.d.ts +5 -0
- package/dist/agents.js +439 -0
- package/dist/cli-runner.d.ts +33 -0
- package/dist/cli-runner.js +167 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +10 -0
- package/dist/compaction.d.ts +9 -0
- package/dist/compaction.js +67 -0
- package/dist/config.d.ts +17 -0
- package/dist/config.js +69 -0
- package/dist/contracts.d.ts +670 -0
- package/dist/contracts.js +2 -0
- package/dist/contributions.d.ts +35 -0
- package/dist/contributions.js +47 -0
- package/dist/credentials.d.ts +22 -0
- package/dist/credentials.js +63 -0
- package/dist/extensions.d.ts +25 -0
- package/dist/extensions.js +131 -0
- package/dist/index.d.ts +47 -0
- package/dist/index.js +28 -0
- package/dist/input.d.ts +57 -0
- package/dist/input.js +225 -0
- package/dist/manifests.d.ts +28 -0
- package/dist/manifests.js +108 -0
- package/dist/middleware.d.ts +15 -0
- package/dist/middleware.js +49 -0
- package/dist/mock-provider.d.ts +6 -0
- package/dist/mock-provider.js +14 -0
- package/dist/models.d.ts +8 -0
- package/dist/models.js +25 -0
- package/dist/node/config.d.ts +9 -0
- package/dist/node/config.js +51 -0
- package/dist/node/session-store-jsonl.d.ts +17 -0
- package/dist/node/session-store-jsonl.js +134 -0
- package/dist/node/settings.d.ts +7 -0
- package/dist/node/settings.js +26 -0
- package/dist/node/trust.d.ts +13 -0
- package/dist/node/trust.js +56 -0
- package/dist/provider-events.d.ts +15 -0
- package/dist/provider-events.js +30 -0
- package/dist/provider-packages.d.ts +4 -0
- package/dist/provider-packages.js +12 -0
- package/dist/provider-request-policy.d.ts +9 -0
- package/dist/provider-request-policy.js +49 -0
- package/dist/providers/openai-compatible.d.ts +9 -0
- package/dist/providers/openai-compatible.js +197 -0
- package/dist/providers.d.ts +8 -0
- package/dist/providers.js +25 -0
- package/dist/redaction.d.ts +11 -0
- package/dist/redaction.js +68 -0
- package/dist/resources.d.ts +5 -0
- package/dist/resources.js +30 -0
- package/dist/retry.d.ts +11 -0
- package/dist/retry.js +48 -0
- package/dist/rpc.d.ts +18 -0
- package/dist/rpc.js +187 -0
- package/dist/security.d.ts +51 -0
- package/dist/security.js +60 -0
- package/dist/session-stores.d.ts +25 -0
- package/dist/session-stores.js +116 -0
- package/dist/settings.d.ts +3 -0
- package/dist/settings.js +26 -0
- package/dist/skills.d.ts +8 -0
- package/dist/skills.js +34 -0
- package/dist/system-prompts.d.ts +6 -0
- package/dist/system-prompts.js +47 -0
- package/dist/testing/provider-conformance.d.ts +36 -0
- package/dist/testing/provider-conformance.js +164 -0
- package/dist/tools.d.ts +25 -0
- package/dist/tools.js +109 -0
- package/docs/agent-session-runtime.md +167 -0
- package/docs/api-page-template.md +32 -0
- package/docs/cli-rpc.md +140 -0
- package/docs/compaction-and-retry.md +177 -0
- package/docs/compaction-llm.md +108 -0
- package/docs/compaction-observational-memory.md +123 -0
- package/docs/configuration-and-manifests.md +142 -0
- package/docs/context-and-skills.md +113 -0
- package/docs/contribution-registries.md +118 -0
- package/docs/credentials-and-redaction.md +122 -0
- package/docs/extensions.md +139 -0
- package/docs/index.md +56 -0
- package/docs/input-and-prompt-assembly.md +168 -0
- package/docs/middleware-hooks.md +123 -0
- package/docs/node-filesystem-config.md +85 -0
- package/docs/node-jsonl-session-store.md +81 -0
- package/docs/provider-conformance.md +109 -0
- package/docs/provider-layer.md +172 -0
- package/docs/provider-packages.md +171 -0
- package/docs/providers/kimi.md +110 -0
- package/docs/providers/openai-compatible.md +125 -0
- package/docs/providers/openai.md +131 -0
- package/docs/providers/opencode-go.md +103 -0
- package/docs/providers/openrouter.md +105 -0
- package/docs/providers/zai.md +108 -0
- package/docs/public-contracts.md +375 -0
- package/docs/release-and-install.md +141 -0
- package/docs/resource-loading.md +97 -0
- package/docs/session-stores-and-branching.md +119 -0
- package/docs/settings-auth-trust-security.md +73 -0
- package/docs/system-prompts.md +116 -0
- package/docs/tools.md +151 -0
- package/package.json +93 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# Provider layer
|
|
2
|
+
|
|
3
|
+
## What it does
|
|
4
|
+
|
|
5
|
+
The provider layer contains the small runtime pieces Prism already ships for host-owned model access:
|
|
6
|
+
|
|
7
|
+
- `createProviderRegistry()` / `ProviderRegistry`: register and resolve `AIProvider` instances by id.
|
|
8
|
+
- `createModelRegistry()` / `ModelRegistry`: register and resolve `ModelConfig` values by provider/model key.
|
|
9
|
+
- `ModelConfig` metadata fields for display names, capabilities, limits, cost/cache pricing, opaque provider compat data, and host metadata.
|
|
10
|
+
- Provider event helpers: create normalized `ProviderEvent` values for text, thinking, tool calls, usage, done, and errors, including optional cache read/write usage fields.
|
|
11
|
+
- `toolCallContent()`: create a `ToolCallContent` block.
|
|
12
|
+
- `createMockProvider()` / `MockProviderOptions`: create a deterministic scripted `AIProvider` for tests and examples.
|
|
13
|
+
- `@arnilo/prism/testing/provider-conformance`: optional network-free assertion helpers for provider adapter tests.
|
|
14
|
+
|
|
15
|
+
These APIs are exported from the root `@arnilo/prism` package. `ProviderRegistry` and `ModelRegistry` are public runtime API types that live beside their factory implementations, not in the type-only `contracts.ts` file.
|
|
16
|
+
|
|
17
|
+
## When to use it
|
|
18
|
+
|
|
19
|
+
Use this layer when a host app, extension package, or test needs to:
|
|
20
|
+
|
|
21
|
+
- Keep an explicit provider/model registry instead of hidden globals.
|
|
22
|
+
- Fail closed before any provider call when a provider or model is unknown.
|
|
23
|
+
- Emit provider events without hand-writing event objects.
|
|
24
|
+
- Test agent/provider flows without timers, credentials, SDKs, or network calls.
|
|
25
|
+
|
|
26
|
+
Do not use this layer for credential storage, settings loading, tool dispatch, agent loops, package discovery, cache stores, or provider SDK configuration. Those stay host-owned or belong to provider packages.
|
|
27
|
+
|
|
28
|
+
## Inputs / request
|
|
29
|
+
|
|
30
|
+
### Provider registry
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
createProviderRegistry(providers?: readonly AIProvider[]): ProviderRegistry
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
`ProviderRegistry` methods:
|
|
37
|
+
|
|
38
|
+
| Method | Input | Result |
|
|
39
|
+
| --- | --- | --- |
|
|
40
|
+
| `register(provider)` | `AIProvider` | Stores provider by `provider.id`. |
|
|
41
|
+
| `get(id)` | provider id string | Returns provider or `undefined`. |
|
|
42
|
+
| `resolve(model)` | provider id string or `{ provider: string }` | Returns provider or throws `Unknown provider: <id>`. |
|
|
43
|
+
| `list()` | none | Returns registered providers in insertion order. |
|
|
44
|
+
|
|
45
|
+
### Model registry
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
createModelRegistry(models?: readonly ModelConfig[]): ModelRegistry
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
`ModelRegistry` methods:
|
|
52
|
+
|
|
53
|
+
| Method | Input | Result |
|
|
54
|
+
| --- | --- | --- |
|
|
55
|
+
| `register(model)` | `ModelConfig` | Stores model by provider/model key, preserving inert metadata. |
|
|
56
|
+
| `get(provider, model)` | provider id and model id | Returns model config or `undefined`. |
|
|
57
|
+
| `resolve(provider, model)` | provider id and model id | Returns model config or throws `Unknown model: <provider>/<model>`. |
|
|
58
|
+
| `list()` | none | Returns registered model configs in insertion order. |
|
|
59
|
+
|
|
60
|
+
### Provider event helpers
|
|
61
|
+
|
|
62
|
+
```ts
|
|
63
|
+
providerTextDelta(text: string): ProviderEvent
|
|
64
|
+
providerThinkingDelta(text: string, signature?: string): ProviderEvent
|
|
65
|
+
providerContentDelta(content: ContentBlock): ProviderEvent
|
|
66
|
+
providerToolCallDelta(delta: { index: number; id?: string; name?: string; argumentsText?: string }): ProviderEvent
|
|
67
|
+
providerToolCall(call: ToolCallContent): ProviderEvent
|
|
68
|
+
providerUsage(usage: Usage): ProviderEvent
|
|
69
|
+
providerDone(usage?: Usage): ProviderEvent
|
|
70
|
+
providerError(error: unknown, secrets?: readonly (string | undefined)[]): ProviderEvent
|
|
71
|
+
toolCallContent(id: string, name: string, args?: JsonObject): ToolCallContent
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Mock provider
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
createMockProvider(events?: readonly ProviderEvent[], options?: MockProviderOptions): AIProvider
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
`MockProviderOptions`:
|
|
81
|
+
|
|
82
|
+
| Field | Type | Purpose |
|
|
83
|
+
| --- | --- | --- |
|
|
84
|
+
| `id` | `string` | Optional provider id. Defaults to `mock`. |
|
|
85
|
+
| `onRequest` | `(request: ProviderRequest) => void` | Optional request observer for tests. |
|
|
86
|
+
|
|
87
|
+
## Outputs / response / events
|
|
88
|
+
|
|
89
|
+
- Registry `resolve()` returns the matching provider/model or throws before any provider `generate()` call.
|
|
90
|
+
- Provider event helpers return plain `ProviderEvent` objects.
|
|
91
|
+
- `providerError()` converts unknown errors to redacted `ErrorInfo` through `errorToErrorInfo()` and preserves safe string/number `code` fields for retry classification.
|
|
92
|
+
- `createMockProvider()` returns an `AIProvider` whose `generate()` yields the scripted events in order and checks `request.signal?.aborted` before each event.
|
|
93
|
+
- The agent/session runtime passes its per-run abort signal as `ProviderRequest.signal`.
|
|
94
|
+
|
|
95
|
+
## Request/response example
|
|
96
|
+
|
|
97
|
+
```json
|
|
98
|
+
{
|
|
99
|
+
"provider": "mock",
|
|
100
|
+
"model": "demo"
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Example provider events:
|
|
105
|
+
|
|
106
|
+
```json
|
|
107
|
+
[
|
|
108
|
+
{ "type": "content_delta", "content": { "type": "text", "text": "Hello" } },
|
|
109
|
+
{ "type": "done" }
|
|
110
|
+
]
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Implementation example
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
import {
|
|
117
|
+
createModelRegistry,
|
|
118
|
+
createMockProvider,
|
|
119
|
+
createProviderRegistry,
|
|
120
|
+
providerDone,
|
|
121
|
+
providerTextDelta,
|
|
122
|
+
providerToolCall,
|
|
123
|
+
toolCallContent,
|
|
124
|
+
} from "@arnilo/prism";
|
|
125
|
+
|
|
126
|
+
const provider = createMockProvider([
|
|
127
|
+
providerTextDelta("Hello"),
|
|
128
|
+
providerToolCall(toolCallContent("call_1", "lookup", { id: "1" })),
|
|
129
|
+
providerDone(),
|
|
130
|
+
]);
|
|
131
|
+
|
|
132
|
+
const providers = createProviderRegistry([provider]);
|
|
133
|
+
const models = createModelRegistry([{ provider: "mock", model: "demo" }]);
|
|
134
|
+
|
|
135
|
+
const resolvedProvider = providers.resolve("mock");
|
|
136
|
+
const resolvedModel = models.resolve("mock", "demo");
|
|
137
|
+
|
|
138
|
+
for await (const event of resolvedProvider.generate({
|
|
139
|
+
model: resolvedModel,
|
|
140
|
+
messages: [{ role: "user", content: [{ type: "text", text: "Hi" }] }],
|
|
141
|
+
options: { sessionId: "session-1", cacheRetention: "short" },
|
|
142
|
+
})) {
|
|
143
|
+
console.log(event.type);
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Extension and configuration notes
|
|
148
|
+
|
|
149
|
+
- Registries are explicit objects returned by factories. Prism does not create a hidden global provider/model registry.
|
|
150
|
+
- Extension packages can contribute `AIProvider` and `ModelConfig` values by registering them with host-owned registries.
|
|
151
|
+
- Model resolution and provider resolution are separate on purpose: hosts can validate a model exists before selecting a provider.
|
|
152
|
+
- Credential resolvers stay outside these registries; pass credentials directly to the provider adapter or runtime edge that needs them.
|
|
153
|
+
- Mock provider is for deterministic tests/examples. Real providers should implement `AIProvider` directly or through adapter packages.
|
|
154
|
+
|
|
155
|
+
## Security and performance notes
|
|
156
|
+
|
|
157
|
+
- Provider/model registries are `Map`-backed and perform O(1) lookup.
|
|
158
|
+
- Registries store providers and model metadata only. Do not store API keys, credential resolvers, headers, tokens, or secret-bearing settings in them.
|
|
159
|
+
- Unknown provider/model resolution fails before provider execution or network I/O.
|
|
160
|
+
- `createMockProvider()` uses scripted events only: no timers, credentials, SDKs, or network.
|
|
161
|
+
- Do not hide real secrets in mock event fixtures. If an error event must include secret-like text, use fake placeholders and redaction helpers.
|
|
162
|
+
- `providerError(error, secrets)` only redacts the provided secret values. It is not a general secret scanner.
|
|
163
|
+
- Providers may set safe `ErrorInfo.code` values such as `429`, `503`, or `ETIMEDOUT`; retry policy code treats them as classification hints, not trusted provider metadata.
|
|
164
|
+
|
|
165
|
+
## Related APIs
|
|
166
|
+
|
|
167
|
+
- [Agent/session runtime](agent-session-runtime.md): passes abort signals to providers, maps provider errors to session `error` events, and can retry configured transient provider-turn failures before output.
|
|
168
|
+
- [Provider packages](provider-packages.md): explicit package primitive for registering providers, models, auth descriptors, request/cache policies, and prompt contributions.
|
|
169
|
+
- [Public contracts](public-contracts.md): `AIProvider`, `ProviderRequest`, `ProviderEvent`, `ModelConfig`, `Usage`, and content/tool-call contracts.
|
|
170
|
+
- [Credentials and redaction](credentials-and-redaction.md): credential and redaction helpers used by provider adapters.
|
|
171
|
+
- [OpenAI-compatible provider](providers/openai-compatible.md): optional provider adapter that emits these normalized provider events.
|
|
172
|
+
- [Provider conformance](provider-conformance.md): reusable network-free provider adapter checks, including content-preservation canaries for text/thinking/tool-call/tool-result/image blocks and secret-leak assertions.
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# Provider packages
|
|
2
|
+
|
|
3
|
+
## What it does
|
|
4
|
+
|
|
5
|
+
Provider package primitives let a host or extension register provider-related contributions explicitly:
|
|
6
|
+
|
|
7
|
+
- `defineProviderPackage()`: validates and returns an inert provider package definition.
|
|
8
|
+
- `ProviderPackage`: package metadata plus a `setup(api)` callback.
|
|
9
|
+
- `ModelConfig` metadata: `displayName`, `capabilities`, `limits`, `cost`, opaque `compat`, and `metadata`.
|
|
10
|
+
- New contribution registries and `ExtensionAPI` methods for provider packages, auth methods, provider request policies, and system prompt contributions.
|
|
11
|
+
- Auth method descriptors for API-key, OAuth, and custom provider auth flows.
|
|
12
|
+
|
|
13
|
+
These primitives do not load packages, discover manifests, read credentials, refresh OAuth tokens, or call providers.
|
|
14
|
+
|
|
15
|
+
## When to use it
|
|
16
|
+
|
|
17
|
+
Use provider packages when a host wants to bundle model metadata, provider adapters, auth descriptors, cache/request policies, or prompt contributions behind one explicit setup call.
|
|
18
|
+
|
|
19
|
+
Do not use provider packages as a package manager, credential store, env loader, provider-specific cache implementation, or live integration runner.
|
|
20
|
+
|
|
21
|
+
## Inputs / request
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
import { defineProviderPackage } from "@arnilo/prism";
|
|
25
|
+
|
|
26
|
+
export default defineProviderPackage({
|
|
27
|
+
name: "demo-provider",
|
|
28
|
+
setup(api) {
|
|
29
|
+
api.registerProvider(provider);
|
|
30
|
+
api.registerModel({
|
|
31
|
+
provider: "demo",
|
|
32
|
+
model: "demo-large",
|
|
33
|
+
displayName: "Demo Large",
|
|
34
|
+
capabilities: { input: ["text"], reasoning: true, tools: true },
|
|
35
|
+
limits: { contextWindow: 128_000, maxOutputTokens: 8_192 },
|
|
36
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, currency: "USD" },
|
|
37
|
+
compat: { vendorSpecific: true },
|
|
38
|
+
});
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
`compat` is provider-owned inert JSON. Core does not branch on provider names or interpret vendor-specific fields.
|
|
44
|
+
|
|
45
|
+
Provider packages can also contribute auth descriptors and request policies without resolving credentials:
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
import { createSessionCachePolicy } from "@arnilo/prism";
|
|
49
|
+
|
|
50
|
+
api.registerAuthMethod({ provider: "demo", kind: "api_key", credentialName: "apiKey" });
|
|
51
|
+
api.registerAuthMethod({ provider: "demo", kind: "oauth", oauth: demoOAuthProvider });
|
|
52
|
+
api.registerProviderRequestPolicy(createSessionCachePolicy({ retention: "short" }));
|
|
53
|
+
api.registerSystemPromptContribution({ id: "demo-prompt", source: "package", mode: "append", text: "Use demo provider rules." });
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Hosts decide which credential resolvers, env objects, OAuth stores, request policies, and prompt contributions become active. Request policies can set generic `ProviderRequest.options` such as `sessionId`, `cacheRetention`, `headers`, retry/timeouts, and opaque `extra`; provider adapters decide how to map those options to provider payloads.
|
|
57
|
+
|
|
58
|
+
## First-party provider package skeletons
|
|
59
|
+
|
|
60
|
+
Phase 12 adds explicit npm workspaces for [`@arnilo/prism-provider-openai`](providers/openai.md), [`@arnilo/prism-provider-opencode-go`](providers/opencode-go.md), [`@arnilo/prism-provider-openrouter`](providers/openrouter.md), [`@arnilo/prism-provider-zai`](providers/zai.md), and [`@arnilo/prism-provider-kimi`](providers/kimi.md). Each package starts with a side-effect-free `create*ProviderPackage()` export, README, TypeScript build, network-free default tests, and an env-gated live-test placeholder.
|
|
61
|
+
|
|
62
|
+
These workspaces still follow the same rule as external packages: no provider SDK dependency, catalog fetch, env scan, keychain/file credential lookup, shell auth command, OAuth login, or live provider call runs by default. `@arnilo/prism-provider-openai` now registers OpenAI Responses and OpenAI Codex providers from caller-supplied credentials only. `@arnilo/prism-provider-opencode-go` now registers static OpenCode Go metadata and package-local OpenAI/Anthropic-compatible routes from caller-supplied credentials only. `@arnilo/prism-provider-openrouter` now registers an app-controlled OpenRouter catalog with routing/reasoning/cache passthrough and no setup catalog fetch. `@arnilo/prism-provider-zai` now registers static GLM metadata with Z.AI thinking/reasoning/tool-stream request mapping. `@arnilo/prism-provider-kimi` now registers Kimi Coding Anthropic-compatible behavior by default and optional Moonshot metadata only when requested.
|
|
63
|
+
|
|
64
|
+
## Outputs / response / events
|
|
65
|
+
|
|
66
|
+
`defineProviderPackage()` returns the same package object or throws when `name` is blank. A package contributes only when a host passes it to an extension/kernel/setup flow and calls `setup()` explicitly.
|
|
67
|
+
|
|
68
|
+
## Request/response example
|
|
69
|
+
|
|
70
|
+
Provider package manifest contribution and the generic request options a provider request policy can set:
|
|
71
|
+
|
|
72
|
+
```json
|
|
73
|
+
{
|
|
74
|
+
"manifest": {
|
|
75
|
+
"name": "demo-provider-manifest",
|
|
76
|
+
"contributions": [
|
|
77
|
+
{ "kind": "providerPackage", "name": "demo-provider" },
|
|
78
|
+
{ "kind": "providerRequestPolicy", "name": "demo.cache" }
|
|
79
|
+
]
|
|
80
|
+
},
|
|
81
|
+
"providerRequest.options": {
|
|
82
|
+
"sessionId": "sess_123",
|
|
83
|
+
"cacheKey": "demo",
|
|
84
|
+
"cacheRetention": "short",
|
|
85
|
+
"headers": { "x-demo": "1" }
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Implementation example
|
|
91
|
+
|
|
92
|
+
Wire a provider package with model metadata plus a session cache policy through the extension kernel:
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
import { createExtensionKernel, defineProviderPackage, createSessionCachePolicy } from "@arnilo/prism";
|
|
96
|
+
|
|
97
|
+
const pkg = defineProviderPackage({
|
|
98
|
+
name: "demo-provider",
|
|
99
|
+
setup(api) {
|
|
100
|
+
api.registerProvider(/* host-owned AIProvider */ null as never);
|
|
101
|
+
api.registerModel({
|
|
102
|
+
provider: "demo",
|
|
103
|
+
model: "demo-large",
|
|
104
|
+
displayName: "Demo Large",
|
|
105
|
+
capabilities: { input: ["text"], reasoning: true, tools: true },
|
|
106
|
+
limits: { contextWindow: 128_000, maxOutputTokens: 8_192 },
|
|
107
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, currency: "USD" },
|
|
108
|
+
compat: { vendorSpecific: true },
|
|
109
|
+
});
|
|
110
|
+
api.registerProviderRequestPolicy(createSessionCachePolicy({ retention: "short" }));
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
const kernel = createExtensionKernel();
|
|
115
|
+
await kernel.load([pkg]);
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Extension and configuration notes
|
|
119
|
+
|
|
120
|
+
- Hosts decide which credential resolvers, env objects, OAuth stores, request
|
|
121
|
+
policies, and prompt contributions become active; the package only *declares*
|
|
122
|
+
them.
|
|
123
|
+
- `createSessionCachePolicy()` acts as a concrete cache policy hook
|
|
124
|
+
(`provider_request`) that sets generic `ProviderRequest.options`
|
|
125
|
+
(`sessionId`, `cacheKey`, `cacheRetention`, `headers`, opaque `extra`) before
|
|
126
|
+
`AIProvider.generate()`; provider adapters map those options to provider payloads.
|
|
127
|
+
- `ModelConfig.compat` is provider-owned inert JSON: cache policy overrides,
|
|
128
|
+
reasoning/thinking formats, and provider-specific usage mapping live there
|
|
129
|
+
rather than in core, so Prism never branches on provider names.
|
|
130
|
+
- A package contributes auth methods and request policies without resolving
|
|
131
|
+
credentials; OAuth/api-key resolution runs only when the host wires the
|
|
132
|
+
matching credential resolver.
|
|
133
|
+
- Packages can also be declared as inert manifest contributions and resolved
|
|
134
|
+
later through registries (see the Manifest declarations section below).
|
|
135
|
+
|
|
136
|
+
## Security and performance notes
|
|
137
|
+
|
|
138
|
+
- Keep resolved credential values out of `ModelConfig`, provider package metadata, docs metadata, auth method metadata, and registries.
|
|
139
|
+
- Registration is in-memory only and does no filesystem, network, env, OAuth refresh, or command access.
|
|
140
|
+
- Provider-specific behavior belongs in provider packages, not Prism core.
|
|
141
|
+
- Adapter serializers should preserve Prism content blocks (text, thinking, tool_call, tool_result, and image when the model declares image input) in provider-native request shape, or fail explicitly when a block is unsupported.
|
|
142
|
+
|
|
143
|
+
## Manifest declarations
|
|
144
|
+
|
|
145
|
+
Provider packages, auth methods, provider request policies, and system prompt contributions can also be declared in data-only Prism manifests:
|
|
146
|
+
|
|
147
|
+
```ts
|
|
148
|
+
import { definePrismManifest } from "@arnilo/prism";
|
|
149
|
+
|
|
150
|
+
export default definePrismManifest({
|
|
151
|
+
name: "demo-provider-manifest",
|
|
152
|
+
contributions: [
|
|
153
|
+
{ kind: "providerPackage", name: "demo-provider" },
|
|
154
|
+
{ kind: "authMethod", name: "demo.api-key", metadata: { credentialName: "apiKey" } },
|
|
155
|
+
{ kind: "providerRequestPolicy", name: "demo.cache" },
|
|
156
|
+
{ kind: "systemPromptContribution", name: "demo.prompt" },
|
|
157
|
+
],
|
|
158
|
+
});
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Manifest declarations are inert. The host must later resolve them through registries or extension setup and make explicit trust decisions before activating any package, auth flow, request policy, or prompt contribution.
|
|
162
|
+
|
|
163
|
+
## Related APIs
|
|
164
|
+
|
|
165
|
+
- [Provider layer](provider-layer.md): provider/model registries and provider events.
|
|
166
|
+
- [Provider conformance](provider-conformance.md): reusable network-free checks for provider adapters.
|
|
167
|
+
- [Contribution registries](contribution-registries.md): registry bundle and extension contribution points.
|
|
168
|
+
- [Configuration and manifests](configuration-and-manifests.md): data-only manifest `kind` values.
|
|
169
|
+
- [System prompts](system-prompts.md): composing selected package/app/user/run prompt layers.
|
|
170
|
+
- [Credentials and redaction](credentials-and-redaction.md): host-owned credential helpers.
|
|
171
|
+
- [Public contracts](public-contracts.md): public type inventory.
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Kimi provider package
|
|
2
|
+
|
|
3
|
+
## What it does
|
|
4
|
+
|
|
5
|
+
`@arnilo/prism-provider-kimi` provides explicit, side-effect-free setup for Kimi For
|
|
6
|
+
Coding using an Anthropic-compatible `/messages` endpoint with
|
|
7
|
+
`User-Agent: KimiCLI/1.5` (unless overridden). Moonshot/Open Platform model
|
|
8
|
+
metadata is optional.
|
|
9
|
+
|
|
10
|
+
The package registers the `kimi-coding` provider, default Kimi Coding model
|
|
11
|
+
metadata, and an `api_key` auth method through `createExtensionKernel().load([...])`.
|
|
12
|
+
|
|
13
|
+
## When to use it
|
|
14
|
+
|
|
15
|
+
Use it when a host app wants the Kimi For Coding endpoint through Prism's
|
|
16
|
+
`AgentSession` runtime with Kimi-specific serializer behavior.
|
|
17
|
+
|
|
18
|
+
Do not use it for Moonshot Open Platform default registration, automatic
|
|
19
|
+
credential discovery, catalog fetches, or real-network tests.
|
|
20
|
+
|
|
21
|
+
## Inputs / request
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
import { createKimiProviderPackage } from "@arnilo/prism-provider-kimi";
|
|
25
|
+
|
|
26
|
+
createKimiProviderPackage(options: KimiProviderPackageOptions): ProviderPackage
|
|
27
|
+
defineKimiModel(config: KimiModelConfig): KimiModelConfig
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
| Field | Type | Purpose |
|
|
31
|
+
| --- | --- | --- |
|
|
32
|
+
| `kimiApiKey` | `CredentialValueSource` | Direct/callback/resolver API-key source for Kimi. |
|
|
33
|
+
| `fetch` | `typeof fetch` | Optional fetch implementation for tests/hosts. |
|
|
34
|
+
| `baseUrl` | `string` | Overrides the Kimi base URL. |
|
|
35
|
+
| `id` | `string` | Overrides the provider id (default `kimi-coding`). |
|
|
36
|
+
| `userAgent` | `string` | Overrides `User-Agent: KimiCLI/1.5`. |
|
|
37
|
+
| `models` | `readonly ModelConfig[]` | Overrides `kimiCodingModels` defaults. |
|
|
38
|
+
| `includeMoonshotModels` | `boolean` | Registers Moonshot models when `true` (default off). |
|
|
39
|
+
| `moonshotModels` | `readonly ModelConfig[]` | Overrides `moonshotKimiModels` when included. |
|
|
40
|
+
|
|
41
|
+
## Outputs / response / events
|
|
42
|
+
|
|
43
|
+
| Surface | Behavior |
|
|
44
|
+
| --- | --- |
|
|
45
|
+
| Provider stream | Prism text, thinking (preserved only when `model.compat.preserveThinking` is true, otherwise downgraded to text), tool-call delta/final, `usage`, `done`, redacted `error`. |
|
|
46
|
+
| Block preservation | Text, thinking, assistant `tool_call` → `tool_use`, `tool_result` → `tool_result`, images when `capabilities.input` includes `"image"`. |
|
|
47
|
+
| Auth method | `api_key` for `kimi-coding`, credential name `apiKey`. |
|
|
48
|
+
|
|
49
|
+
Unsupported block placements or unclaimed images fail before fetch.
|
|
50
|
+
|
|
51
|
+
## Request/response example
|
|
52
|
+
|
|
53
|
+
Example request (Anthropic-compatible `/messages` shape):
|
|
54
|
+
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"model": "kimi-latest",
|
|
58
|
+
"messages": [{ "role": "user", "content": "Hello" }],
|
|
59
|
+
"stream": true
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Implementation example
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
import { createExtensionKernel } from "@arnilo/prism";
|
|
67
|
+
import { createKimiProviderPackage } from "@arnilo/prism-provider-kimi";
|
|
68
|
+
|
|
69
|
+
const kernel = createExtensionKernel();
|
|
70
|
+
await kernel.load([
|
|
71
|
+
createKimiProviderPackage({ kimiApiKey: "fake-kimi-key", includeMoonshotModels: false }),
|
|
72
|
+
]);
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Register Moonshot/Open Platform metadata explicitly:
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
import { createKimiProviderPackage } from "@arnilo/prism-provider-kimi";
|
|
79
|
+
|
|
80
|
+
await kernel.load([
|
|
81
|
+
createKimiProviderPackage({ kimiApiKey: "fake", includeMoonshotModels: true }),
|
|
82
|
+
]);
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Extension and configuration notes
|
|
86
|
+
|
|
87
|
+
- Hosts choose base URL, provider id, `User-Agent`, model list, credential source,
|
|
88
|
+
and `fetch` impl.
|
|
89
|
+
- Moonshot/Open Platform metadata is registered only with
|
|
90
|
+
`includeMoonshotModels: true`; it is not core behavior.
|
|
91
|
+
- Package contributes models via the extension `api` and an `api_key` auth method.
|
|
92
|
+
|
|
93
|
+
## Security and performance notes
|
|
94
|
+
|
|
95
|
+
- No network calls during import, setup, build, or default tests.
|
|
96
|
+
- No automatic environment, file, keychain, or shell credential lookup.
|
|
97
|
+
- Kimi credentials are resolved per request from caller-supplied values or resolvers
|
|
98
|
+
and redacted from errors.
|
|
99
|
+
- Live tests stay opt-in behind `PRISM_LIVE_PROVIDER_TESTS=1` plus fake-safe
|
|
100
|
+
provider-specific env names; default tests are network-free.
|
|
101
|
+
|
|
102
|
+
## Related APIs
|
|
103
|
+
|
|
104
|
+
- [Provider packages](../provider-packages.md): `defineProviderPackage`,
|
|
105
|
+
`ModelConfig`/`compat`, Anthropic-compatible routes.
|
|
106
|
+
- [Credentials and redaction](../credentials-and-redaction.md):
|
|
107
|
+
`resolveCredentialValue`, `redactSecrets`.
|
|
108
|
+
- [Provider layer](../provider-layer.md): `ProviderRequest.options` and usage
|
|
109
|
+
mapping.
|
|
110
|
+
- [Provider conformance](../provider-conformance.md): network-free adapter tests.
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# OpenAI-compatible provider
|
|
2
|
+
|
|
3
|
+
## What it does
|
|
4
|
+
|
|
5
|
+
`@arnilo/prism/providers/openai-compatible` exports `createOpenAICompatibleProvider()` and `OpenAICompatibleProviderOptions`.
|
|
6
|
+
|
|
7
|
+
The adapter implements `AIProvider` for OpenAI-compatible Chat Completions streaming APIs using native or injected `fetch`. It maps streaming Server-Sent Events into Prism `ProviderEvent` values for text, thinking, tool-call fragments, final tool calls, usage, done, and errors.
|
|
8
|
+
|
|
9
|
+
It has no provider SDK dependency.
|
|
10
|
+
|
|
11
|
+
## When to use it
|
|
12
|
+
|
|
13
|
+
Use this adapter when a host app or extension package wants to connect a Prism provider to an OpenAI-compatible `/chat/completions` endpoint.
|
|
14
|
+
|
|
15
|
+
Do not use it for the OpenAI Responses API, provider-specific non-streaming APIs, automatic credential discovery, or real-network tests. Inject `fetch` in tests.
|
|
16
|
+
|
|
17
|
+
## Inputs / request
|
|
18
|
+
|
|
19
|
+
Import from the subpath:
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
import { createOpenAICompatibleProvider } from "@arnilo/prism/providers/openai-compatible";
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Options:
|
|
26
|
+
|
|
27
|
+
| Field | Type | Purpose |
|
|
28
|
+
| --- | --- | --- |
|
|
29
|
+
| `id` | `string` | Optional provider id. Defaults to `openai-compatible`. |
|
|
30
|
+
| `baseUrl` | `string` | Base API URL; `/chat/completions` is appended. |
|
|
31
|
+
| `apiKey` | `CredentialValueSource` | Optional direct/callback/resolver credential source. |
|
|
32
|
+
| `fetch` | `typeof fetch` | Optional fetch implementation for tests or custom hosts. |
|
|
33
|
+
|
|
34
|
+
Provider requests use the standard `ProviderRequest` shape: `model`, `messages`, optional `tools`, `metadata`, and `signal`.
|
|
35
|
+
|
|
36
|
+
## Outputs / response / events
|
|
37
|
+
|
|
38
|
+
The returned provider emits normalized `ProviderEvent` values:
|
|
39
|
+
|
|
40
|
+
| Stream input | Prism output |
|
|
41
|
+
| --- | --- |
|
|
42
|
+
| `delta.content` | `content_delta` with text content. |
|
|
43
|
+
| `delta.reasoning_content` | `content_delta` with thinking content. |
|
|
44
|
+
| streamed `tool_calls` fragments | `tool_call_delta` events. |
|
|
45
|
+
| complete accumulated tool call | final `tool_call` event. |
|
|
46
|
+
| `usage` | `usage` event. |
|
|
47
|
+
| `[DONE]` or stream end | `done` event. |
|
|
48
|
+
| HTTP/stream/parsing error | `error` event with redacted `ErrorInfo`. |
|
|
49
|
+
|
|
50
|
+
The adapter passes `request.signal` to `fetch` for abort propagation.
|
|
51
|
+
|
|
52
|
+
## Request/response example
|
|
53
|
+
|
|
54
|
+
Example request body sent to an OpenAI-compatible endpoint:
|
|
55
|
+
|
|
56
|
+
```json
|
|
57
|
+
{
|
|
58
|
+
"model": "demo-model",
|
|
59
|
+
"messages": [
|
|
60
|
+
{ "role": "user", "content": "Hello" }
|
|
61
|
+
],
|
|
62
|
+
"stream": true,
|
|
63
|
+
"stream_options": { "include_usage": true }
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Example Prism events:
|
|
68
|
+
|
|
69
|
+
```json
|
|
70
|
+
[
|
|
71
|
+
{ "type": "content_delta", "content": { "type": "text", "text": "Hel" } },
|
|
72
|
+
{ "type": "content_delta", "content": { "type": "text", "text": "lo" } },
|
|
73
|
+
{ "type": "done" }
|
|
74
|
+
]
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Implementation example
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
import { createOpenAICompatibleProvider } from "@arnilo/prism/providers/openai-compatible";
|
|
81
|
+
|
|
82
|
+
const provider = createOpenAICompatibleProvider({
|
|
83
|
+
baseUrl: "https://api.openai.com/v1",
|
|
84
|
+
apiKey: () => process.env.OPENAI_API_KEY,
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
for await (const event of provider.generate({
|
|
88
|
+
model: { provider: provider.id, model: "demo-model" },
|
|
89
|
+
messages: [{ role: "user", content: [{ type: "text", text: "Hello" }] }],
|
|
90
|
+
})) {
|
|
91
|
+
console.log(event.type);
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Test with injected fetch, not the network:
|
|
96
|
+
|
|
97
|
+
```ts
|
|
98
|
+
const provider = createOpenAICompatibleProvider({
|
|
99
|
+
baseUrl: "https://example.test/v1",
|
|
100
|
+
fetch: async () => new Response("data: [DONE]\\n\\n", { status: 200 }),
|
|
101
|
+
});
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Extension and configuration notes
|
|
105
|
+
|
|
106
|
+
- Extension packages can create this provider and register it with a host-owned provider registry.
|
|
107
|
+
- Hosts choose the provider id, base URL, model configs, credential source, and fetch implementation.
|
|
108
|
+
- The adapter resolves `apiKey` per request through `resolveCredentialValue()`.
|
|
109
|
+
- This adapter currently targets Chat Completions streaming only.
|
|
110
|
+
- The serializer preserves text, thinking (downgraded to text), assistant `tool_call` blocks as `tool_calls`, `tool_result` blocks as role `tool` messages, and image blocks when the model declares `capabilities.input` includes `"image"`. Unsupported block placements or unclaimed images fail before fetch.
|
|
111
|
+
|
|
112
|
+
## Security and performance notes
|
|
113
|
+
|
|
114
|
+
- Credentials are host-owned and resolved only when `generate()` runs.
|
|
115
|
+
- Resolved API keys are used for the HTTP `Authorization` header and passed to error redaction; they are not stored in registries or events.
|
|
116
|
+
- Redaction only removes known values supplied to the helper. Avoid logging raw provider requests/responses.
|
|
117
|
+
- `fetch` receives the request `AbortSignal`.
|
|
118
|
+
- Tests should use injected `fetch` and never make real network calls.
|
|
119
|
+
- Tool-call arguments are accumulated as streamed text, parsed as JSON only when the final tool call is emitted, and default to `{}` for empty argument text.
|
|
120
|
+
|
|
121
|
+
## Related APIs
|
|
122
|
+
|
|
123
|
+
- [Provider layer](../provider-layer.md): registries, provider events, tool-call helpers, and mock provider.
|
|
124
|
+
- [Credentials and redaction](../credentials-and-redaction.md): `resolveCredentialValue()`, `CredentialValueSource`, `redactSecrets()`, and `errorToErrorInfo()`.
|
|
125
|
+
- [Public contracts](../public-contracts.md): `AIProvider`, `ProviderRequest`, `ProviderEvent`, `ToolDefinition`, `ToolCallContent`, and `Usage`.
|