@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.
Files changed (106) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/LICENSE +21 -0
  3. package/README.md +139 -0
  4. package/dist/agents.d.ts +5 -0
  5. package/dist/agents.js +439 -0
  6. package/dist/cli-runner.d.ts +33 -0
  7. package/dist/cli-runner.js +167 -0
  8. package/dist/cli.d.ts +2 -0
  9. package/dist/cli.js +10 -0
  10. package/dist/compaction.d.ts +9 -0
  11. package/dist/compaction.js +67 -0
  12. package/dist/config.d.ts +17 -0
  13. package/dist/config.js +69 -0
  14. package/dist/contracts.d.ts +670 -0
  15. package/dist/contracts.js +2 -0
  16. package/dist/contributions.d.ts +35 -0
  17. package/dist/contributions.js +47 -0
  18. package/dist/credentials.d.ts +22 -0
  19. package/dist/credentials.js +63 -0
  20. package/dist/extensions.d.ts +25 -0
  21. package/dist/extensions.js +131 -0
  22. package/dist/index.d.ts +47 -0
  23. package/dist/index.js +28 -0
  24. package/dist/input.d.ts +57 -0
  25. package/dist/input.js +225 -0
  26. package/dist/manifests.d.ts +28 -0
  27. package/dist/manifests.js +108 -0
  28. package/dist/middleware.d.ts +15 -0
  29. package/dist/middleware.js +49 -0
  30. package/dist/mock-provider.d.ts +6 -0
  31. package/dist/mock-provider.js +14 -0
  32. package/dist/models.d.ts +8 -0
  33. package/dist/models.js +25 -0
  34. package/dist/node/config.d.ts +9 -0
  35. package/dist/node/config.js +51 -0
  36. package/dist/node/session-store-jsonl.d.ts +17 -0
  37. package/dist/node/session-store-jsonl.js +134 -0
  38. package/dist/node/settings.d.ts +7 -0
  39. package/dist/node/settings.js +26 -0
  40. package/dist/node/trust.d.ts +13 -0
  41. package/dist/node/trust.js +56 -0
  42. package/dist/provider-events.d.ts +15 -0
  43. package/dist/provider-events.js +30 -0
  44. package/dist/provider-packages.d.ts +4 -0
  45. package/dist/provider-packages.js +12 -0
  46. package/dist/provider-request-policy.d.ts +9 -0
  47. package/dist/provider-request-policy.js +49 -0
  48. package/dist/providers/openai-compatible.d.ts +9 -0
  49. package/dist/providers/openai-compatible.js +197 -0
  50. package/dist/providers.d.ts +8 -0
  51. package/dist/providers.js +25 -0
  52. package/dist/redaction.d.ts +11 -0
  53. package/dist/redaction.js +68 -0
  54. package/dist/resources.d.ts +5 -0
  55. package/dist/resources.js +30 -0
  56. package/dist/retry.d.ts +11 -0
  57. package/dist/retry.js +48 -0
  58. package/dist/rpc.d.ts +18 -0
  59. package/dist/rpc.js +187 -0
  60. package/dist/security.d.ts +51 -0
  61. package/dist/security.js +60 -0
  62. package/dist/session-stores.d.ts +25 -0
  63. package/dist/session-stores.js +116 -0
  64. package/dist/settings.d.ts +3 -0
  65. package/dist/settings.js +26 -0
  66. package/dist/skills.d.ts +8 -0
  67. package/dist/skills.js +34 -0
  68. package/dist/system-prompts.d.ts +6 -0
  69. package/dist/system-prompts.js +47 -0
  70. package/dist/testing/provider-conformance.d.ts +36 -0
  71. package/dist/testing/provider-conformance.js +164 -0
  72. package/dist/tools.d.ts +25 -0
  73. package/dist/tools.js +109 -0
  74. package/docs/agent-session-runtime.md +167 -0
  75. package/docs/api-page-template.md +32 -0
  76. package/docs/cli-rpc.md +140 -0
  77. package/docs/compaction-and-retry.md +177 -0
  78. package/docs/compaction-llm.md +108 -0
  79. package/docs/compaction-observational-memory.md +123 -0
  80. package/docs/configuration-and-manifests.md +142 -0
  81. package/docs/context-and-skills.md +113 -0
  82. package/docs/contribution-registries.md +118 -0
  83. package/docs/credentials-and-redaction.md +122 -0
  84. package/docs/extensions.md +139 -0
  85. package/docs/index.md +56 -0
  86. package/docs/input-and-prompt-assembly.md +168 -0
  87. package/docs/middleware-hooks.md +123 -0
  88. package/docs/node-filesystem-config.md +85 -0
  89. package/docs/node-jsonl-session-store.md +81 -0
  90. package/docs/provider-conformance.md +109 -0
  91. package/docs/provider-layer.md +172 -0
  92. package/docs/provider-packages.md +171 -0
  93. package/docs/providers/kimi.md +110 -0
  94. package/docs/providers/openai-compatible.md +125 -0
  95. package/docs/providers/openai.md +131 -0
  96. package/docs/providers/opencode-go.md +103 -0
  97. package/docs/providers/openrouter.md +105 -0
  98. package/docs/providers/zai.md +108 -0
  99. package/docs/public-contracts.md +375 -0
  100. package/docs/release-and-install.md +141 -0
  101. package/docs/resource-loading.md +97 -0
  102. package/docs/session-stores-and-branching.md +119 -0
  103. package/docs/settings-auth-trust-security.md +73 -0
  104. package/docs/system-prompts.md +116 -0
  105. package/docs/tools.md +151 -0
  106. 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`.