@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,142 @@
|
|
|
1
|
+
# Configuration and manifests
|
|
2
|
+
|
|
3
|
+
## What it does
|
|
4
|
+
|
|
5
|
+
Configuration helpers merge host-provided JSON config layers in a deterministic order. Manifest helpers validate data-only package manifests that describe contribution/resource declarations and config defaults without importing or executing package code.
|
|
6
|
+
|
|
7
|
+
APIs:
|
|
8
|
+
|
|
9
|
+
- `mergeConfigLayers()` / `ConfigLayer`
|
|
10
|
+
- `loadConfigLayers()` / `ConfigProvider`
|
|
11
|
+
- `isJsonObject()` / `assertJsonObject()`
|
|
12
|
+
- `definePrismManifest()` / `parsePrismManifest()`
|
|
13
|
+
- `PrismManifest`, `ManifestContributionDeclaration`, `ManifestResourceDeclaration`
|
|
14
|
+
|
|
15
|
+
## When to use it
|
|
16
|
+
|
|
17
|
+
Use these APIs when a host or package needs an in-memory config merge or wants to publish a data-only Prism manifest.
|
|
18
|
+
|
|
19
|
+
Do not use them for package discovery, dynamic imports, executable plugin loading, credential storage, filesystem config loading, resource fetching, or agent/session runtime startup. Those are explicit host or later-phase choices.
|
|
20
|
+
|
|
21
|
+
## Inputs / request
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
mergeConfigLayers(layers: readonly ConfigLayer[]): JsonObject
|
|
25
|
+
loadConfigLayers(providers: readonly ConfigProvider[], context?: ConfigLoadContext): Promise<ConfigLayer[]>
|
|
26
|
+
definePrismManifest(manifest: PrismManifest): PrismManifest
|
|
27
|
+
parsePrismManifest(value: unknown): PrismManifest
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
`ConfigLayer`:
|
|
31
|
+
|
|
32
|
+
| Field | Type | Purpose |
|
|
33
|
+
| --- | --- | --- |
|
|
34
|
+
| `name` | `string` | Layer name used for diagnostics. |
|
|
35
|
+
| `config` | `JsonObject` | JSON config values for that layer. |
|
|
36
|
+
|
|
37
|
+
`PrismManifest`:
|
|
38
|
+
|
|
39
|
+
| Field | Type | Purpose |
|
|
40
|
+
| --- | --- | --- |
|
|
41
|
+
| `name` | `string` | Package/manifest name. |
|
|
42
|
+
| `version` | `string` | Optional package/manifest version. |
|
|
43
|
+
| `description` | `string` | Optional description. |
|
|
44
|
+
| `configDefaults` | `JsonObject` | Optional JSON defaults contributed by the manifest. |
|
|
45
|
+
| `contributions` | `ManifestContributionDeclaration[]` | Optional data-only contribution declarations. |
|
|
46
|
+
| `resources` | `ManifestResourceDeclaration[]` | Optional prompt/skill/package resource declarations by URI. |
|
|
47
|
+
| `metadata` | `JsonObject` | Optional JSON metadata. |
|
|
48
|
+
|
|
49
|
+
`ManifestContributionKind` values match `createContributionRegistries()` categories:
|
|
50
|
+
|
|
51
|
+
| Kind | Registry | Notes |
|
|
52
|
+
| --- | --- | --- |
|
|
53
|
+
| `provider` | `providers` | Provider adapter declaration. |
|
|
54
|
+
| `model` | `models` | Model metadata declaration. |
|
|
55
|
+
| `tool` | `tools` | Tool definition declaration. |
|
|
56
|
+
| `contextProvider` | `contextProviders` | Context provider declaration. |
|
|
57
|
+
| `skill` | `skills` | Skill declaration. |
|
|
58
|
+
| `command` | `commands` | RPC command declaration. |
|
|
59
|
+
| `agent` | `agents` | Agent definition declaration. |
|
|
60
|
+
| `inputBuilder` | `inputBuilders` | Input builder declaration. |
|
|
61
|
+
| `promptBuilder` | `promptBuilders` | Prompt builder declaration. |
|
|
62
|
+
| `compactionStrategy` | `compactionStrategies` | Compaction strategy declaration. |
|
|
63
|
+
| `retryPolicy` | `retryPolicies` | Retry policy declaration. |
|
|
64
|
+
| `storeFactory` | `storeFactories` | Session store factory declaration. |
|
|
65
|
+
| `resourceLoader` | `resourceLoaders` | Resource loader declaration. |
|
|
66
|
+
| `settingsProvider` | `settingsProviders` | Settings provider declaration. |
|
|
67
|
+
| `credentialResolver` | `credentialResolvers` | Credential resolver declaration. |
|
|
68
|
+
| `providerPackage` | `providerPackages` | Provider package declaration. |
|
|
69
|
+
| `authMethod` | `authMethods` | Auth method descriptor; uses `credentialName`, never a resolved credential value. |
|
|
70
|
+
| `providerRequestPolicy` | `providerRequestPolicies` | Provider request policy declaration. |
|
|
71
|
+
| `systemPromptContribution` | `systemPromptContributions` | System prompt contribution declaration. |
|
|
72
|
+
|
|
73
|
+
## Outputs / response / events
|
|
74
|
+
|
|
75
|
+
- `mergeConfigLayers()` returns a new JSON object and does not mutate inputs.
|
|
76
|
+
- Later config layers override earlier layers.
|
|
77
|
+
- Nested plain objects merge recursively.
|
|
78
|
+
- Arrays and primitives replace previous values.
|
|
79
|
+
- `parsePrismManifest()` returns a validated manifest or throws a field-specific validation error.
|
|
80
|
+
- No events are emitted and no registries are modified by these helpers.
|
|
81
|
+
|
|
82
|
+
## Request/response example
|
|
83
|
+
|
|
84
|
+
```json
|
|
85
|
+
{
|
|
86
|
+
"layers": ["built-in", "manifest", "host", "user", "runtime"],
|
|
87
|
+
"manifest": {
|
|
88
|
+
"name": "demo-package",
|
|
89
|
+
"configDefaults": { "demo": { "enabled": true } }
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Implementation example
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
import { definePrismManifest, mergeConfigLayers } from "@arnilo/prism";
|
|
98
|
+
|
|
99
|
+
const manifest = definePrismManifest({
|
|
100
|
+
name: "demo-package",
|
|
101
|
+
configDefaults: { demo: { enabled: true, tools: ["echo"] } },
|
|
102
|
+
contributions: [
|
|
103
|
+
{ kind: "tool", name: "demo.echo", module: "./tool.js", exportName: "tool" },
|
|
104
|
+
{ kind: "retryPolicy", name: "demo.retry", module: "./retry.js", exportName: "retry" },
|
|
105
|
+
{ kind: "providerPackage", name: "demo-provider" },
|
|
106
|
+
{ kind: "authMethod", name: "demo.api-key", metadata: { credentialName: "apiKey" } },
|
|
107
|
+
{ kind: "providerRequestPolicy", name: "demo.cache" },
|
|
108
|
+
{ kind: "systemPromptContribution", name: "demo.prompt" },
|
|
109
|
+
],
|
|
110
|
+
resources: [{ uri: "package://demo/prompt.md", purpose: "prompt" }],
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
const config = mergeConfigLayers([
|
|
114
|
+
{ name: "built-in", config: {} },
|
|
115
|
+
{ name: "manifest", config: manifest.configDefaults ?? {} },
|
|
116
|
+
{ name: "runtime", config: { demo: { enabled: false } } },
|
|
117
|
+
]);
|
|
118
|
+
|
|
119
|
+
console.log(config.demo);
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Extension and configuration notes
|
|
123
|
+
|
|
124
|
+
- Hosts choose the layer order. Prism documents `built-in -> manifest defaults -> host app -> optional user/global -> runtime overrides` but does not load those layers automatically.
|
|
125
|
+
- Manifest contribution declarations are data. Hosts may later choose to import the declared module/export and register it, but parsing the manifest never does that.
|
|
126
|
+
- Contribution `kind` values match `createContributionRegistries()` categories, including the Phase 14 provider primitives `providerPackage`, `authMethod`, `providerRequestPolicy`, and `systemPromptContribution`.
|
|
127
|
+
- Filesystem config loading is intentionally outside the root API and belongs to the optional [`@arnilo/prism/node/config`](node-filesystem-config.md) subpath.
|
|
128
|
+
- Manifest `resources` entries are URI declarations; use [resource loading](resource-loading.md) helpers with a host-provided loader to fetch them.
|
|
129
|
+
|
|
130
|
+
## Security and performance notes
|
|
131
|
+
|
|
132
|
+
- Config and manifest values must be JSON-compatible data.
|
|
133
|
+
- Do not put resolved credential values, tokens, headers, or executable code in config defaults, manifests, or metadata.
|
|
134
|
+
- Manifest parsing does not execute package code, dynamically import modules, resolve credentials, call providers/tools, or read resources.
|
|
135
|
+
- Config merging is dependency-free and proportional to the total number of JSON fields.
|
|
136
|
+
|
|
137
|
+
## Related APIs
|
|
138
|
+
|
|
139
|
+
- [Contribution registries](contribution-registries.md): manifest contribution `kind` values describe registry categories.
|
|
140
|
+
- [Extension kernel and event bus](extensions.md): hosts can load extensions after they decide to execute package code.
|
|
141
|
+
- [Resource loading](resource-loading.md): load manifest, prompt, skill, and package resources through host-provided loaders.
|
|
142
|
+
- [Credentials and redaction](credentials-and-redaction.md): credential values stay out of manifests and config layers.
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# Context and skills
|
|
2
|
+
|
|
3
|
+
## What it does
|
|
4
|
+
|
|
5
|
+
`resolveContextProviders()` runs host-selected `ContextProvider` objects in caller order and returns explicit `ContextBlock[]`. `createSkillRegistry()` stores host-selected `Skill` objects, and `resolveActiveSkills()` discloses only requested skills after checking their `toolNames` against host-active tools.
|
|
6
|
+
|
|
7
|
+
## When to use it
|
|
8
|
+
|
|
9
|
+
Use context resolution when a host wants project/session/context blocks resolved before prompt composition. Use the skill registry when a host wants explicit progressive skill disclosure.
|
|
10
|
+
|
|
11
|
+
Do not use these helpers as an agent loop, package discovery mechanism, context cache, token budgeter, retrier, credential resolver, semantic skill ranker, tool activator, or permission system.
|
|
12
|
+
|
|
13
|
+
## Inputs / request
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { resolveContextProviders } from "@arnilo/prism";
|
|
17
|
+
|
|
18
|
+
const context = await resolveContextProviders({
|
|
19
|
+
providers: [projectContext],
|
|
20
|
+
messages,
|
|
21
|
+
sessionId: "s1",
|
|
22
|
+
runId: "r1",
|
|
23
|
+
metadata: { requestId: "r1" },
|
|
24
|
+
signal,
|
|
25
|
+
});
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`ResolveContextOptions` accepts `providers`, `messages`, optional session/run ids, metadata, abort signal, and optional middleware.
|
|
29
|
+
|
|
30
|
+
Skill selection:
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
import { createSkillRegistry, resolveActiveSkills } from "@arnilo/prism";
|
|
34
|
+
|
|
35
|
+
const registry = createSkillRegistry([{ name: "brief", instructions: "Answer briefly.", toolNames: ["echo"] }]);
|
|
36
|
+
const active = resolveActiveSkills({
|
|
37
|
+
registry,
|
|
38
|
+
names: ["brief"],
|
|
39
|
+
tools: activeTools,
|
|
40
|
+
});
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
`ResolveActiveSkillsOptions` accepts a `SkillRegistry`, requested skill names, and host-active `ToolDefinition[]`.
|
|
44
|
+
|
|
45
|
+
## Outputs / response / events
|
|
46
|
+
|
|
47
|
+
`resolveContextProviders()` returns `readonly ContextBlock[]` in provider order. If a middleware registry is supplied, the `context` hook can transform the final block array.
|
|
48
|
+
|
|
49
|
+
`resolveActiveSkills()` returns requested skills in requested order. Unknown skills and skills that reference inactive tools throw before prompt composition.
|
|
50
|
+
|
|
51
|
+
## Request/response example
|
|
52
|
+
|
|
53
|
+
```json
|
|
54
|
+
{
|
|
55
|
+
"providers": ["project"],
|
|
56
|
+
"skills": ["brief"],
|
|
57
|
+
"activeTools": ["echo"],
|
|
58
|
+
"messages": [{ "role": "user", "content": [{ "type": "text", "text": "Explain" }] }]
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
```json
|
|
63
|
+
[
|
|
64
|
+
{ "title": "Project", "content": "Project context" }
|
|
65
|
+
]
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Implementation example
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
import { assembleProviderInput, createDefaultPromptBuilder, resolveActiveSkills, resolveContextProviders } from "@arnilo/prism";
|
|
72
|
+
|
|
73
|
+
const blocks = await resolveContextProviders({ providers, messages });
|
|
74
|
+
|
|
75
|
+
const activeSkills = resolveActiveSkills({ registry: skills, names: ["brief"], tools: activeTools });
|
|
76
|
+
const request = await assembleProviderInput({
|
|
77
|
+
model: { provider: "mock", model: "demo" },
|
|
78
|
+
input: "Explain this file",
|
|
79
|
+
contextProviders: providers,
|
|
80
|
+
promptBuilder: createDefaultPromptBuilder(),
|
|
81
|
+
skills: activeSkills,
|
|
82
|
+
tools: activeTools,
|
|
83
|
+
});
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Extension and configuration notes
|
|
87
|
+
|
|
88
|
+
Extensions can contribute context providers and skills with `registerContextProvider()` and `registerSkill()`, but those contributions stay inert until the host selects providers or registers/selects skills. The agent/session runtime uses the `context` and selected `skills` arrays passed on `AgentConfig`; it does not auto-select contributions.
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
const providers = [kernel.registries.contextProviders.resolve("project")];
|
|
92
|
+
const skillRegistry = createSkillRegistry([kernel.registries.skills.resolve("brief")]);
|
|
93
|
+
const skills = resolveActiveSkills({ registry: skillRegistry, names: ["brief"], tools: activeTools });
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
`context` middleware runs only when a middleware registry is supplied to the helper. Middleware transforms context data; it does not grant tool access. Skills can reference tool names, but only host-active tools satisfy those references.
|
|
97
|
+
|
|
98
|
+
## Security and performance notes
|
|
99
|
+
|
|
100
|
+
- Context providers run sequentially and deterministically in caller order.
|
|
101
|
+
- Skill registry lookup is `Map`-backed, and selection is linear in requested skills plus active tools.
|
|
102
|
+
- These helpers perform no provider calls, tool execution, resource loading, package discovery, filesystem/network access, retries, timers, or watchers by themselves.
|
|
103
|
+
- Context and skill output is host/extension data. Do not include secrets unless the host explicitly accepts that prompt exposure.
|
|
104
|
+
- Active tools remain host-supplied; skills and middleware do not activate tools or grant permissions.
|
|
105
|
+
|
|
106
|
+
## Related APIs
|
|
107
|
+
|
|
108
|
+
- [Agent/session runtime](agent-session-runtime.md): consumes host-selected context providers and skills from explicit agent config.
|
|
109
|
+
- [Input and prompt assembly](input-and-prompt-assembly.md): default prompt builder and provider-input assembly helper.
|
|
110
|
+
- [Public contracts](public-contracts.md): `ContextProvider`, `ContextResolutionContext`, `ContextBlock`, `Skill`, `SkillRegistry`, `PromptBuilder`, and `PromptBuildRequest`.
|
|
111
|
+
- [Middleware hooks](middleware-hooks.md): `context` and `prompt_build` hooks.
|
|
112
|
+
- [Contribution registries](contribution-registries.md): inert context provider and skill contributions.
|
|
113
|
+
- [Tools](tools.md): host-owned active tools and permissions.
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# Contribution registries
|
|
2
|
+
|
|
3
|
+
## What it does
|
|
4
|
+
|
|
5
|
+
Contribution registries are explicit, host-owned maps for extension/package contributions. They let hosts register and resolve providers, models, provider packages, auth methods, provider request policies, system prompt contributions, tools, context providers, skills, commands, agents, input builders, prompt builders, compaction strategies, retry policies, store factories, resource loaders, settings providers, and credential resolvers without hidden globals.
|
|
6
|
+
|
|
7
|
+
APIs:
|
|
8
|
+
|
|
9
|
+
- `createContributionRegistry<T>()` / `ContributionRegistry<T>`: generic string-keyed registry.
|
|
10
|
+
- `createContributionRegistries()` / `ContributionRegistries`: typed bundle for Phase 2 contribution categories.
|
|
11
|
+
|
|
12
|
+
## When to use it
|
|
13
|
+
|
|
14
|
+
Use these registries when a host app or extension kernel needs direct registration and fail-closed lookup before runtime behavior executes.
|
|
15
|
+
|
|
16
|
+
Do not use them as a dependency injection container, manifest loader, settings loader, credential store, active tool registry, tool dispatcher, or agent/session runtime. For tools, copy selected `registries.tools` entries into `createToolRegistry()` before dispatch.
|
|
17
|
+
|
|
18
|
+
## Inputs / request
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
createContributionRegistry<T>(options?: { label?: string }): ContributionRegistry<T>
|
|
22
|
+
createContributionRegistries(): ContributionRegistries
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
`ContributionRegistry<T>` methods:
|
|
26
|
+
|
|
27
|
+
| Method | Input | Result |
|
|
28
|
+
| --- | --- | --- |
|
|
29
|
+
| `register(key, contribution)` | string key and contribution | Stores or replaces the contribution for that key. |
|
|
30
|
+
| `get(key)` | string key | Returns the contribution or `undefined`. |
|
|
31
|
+
| `resolve(key)` | string key | Returns the contribution or throws `Unknown <label>: <key>`. |
|
|
32
|
+
| `list()` | none | Returns contributions in insertion order. |
|
|
33
|
+
|
|
34
|
+
`ContributionRegistries` includes existing `providers` and `models` registries plus generic registries for `providerPackages`, `authMethods`, `providerRequestPolicies`, `systemPromptContributions`, `tools`, `contextProviders`, `skills`, `commands`, `agents`, `inputBuilders`, `promptBuilders`, `compactionStrategies`, `retryPolicies`, `storeFactories`, `resourceLoaders`, `settingsProviders`, and `credentialResolvers`.
|
|
35
|
+
|
|
36
|
+
## Outputs / response / events
|
|
37
|
+
|
|
38
|
+
Registry calls return plain contribution objects. Unknown `resolve()` calls throw before provider, model, tool, credential, prompt, resource, or session behavior can run. `systemPromptContributions` are inert until a host passes selected values to `AgentConfig.systemPrompt` or `RunOptions.systemPrompt`.
|
|
39
|
+
|
|
40
|
+
Registering the same key replaces the contribution deterministically. Registries do not emit events by themselves; the extension kernel may emit events when it uses them.
|
|
41
|
+
|
|
42
|
+
## Request/response example
|
|
43
|
+
|
|
44
|
+
```json
|
|
45
|
+
{
|
|
46
|
+
"registered": "echo",
|
|
47
|
+
"resolved": "echo"
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Implementation example
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
import { createAgent, createContributionRegistries, type ToolDefinition } from "@arnilo/prism";
|
|
55
|
+
|
|
56
|
+
const tool: ToolDefinition = {
|
|
57
|
+
name: "echo",
|
|
58
|
+
execute(args, context) {
|
|
59
|
+
return { toolCallId: context.toolCallId, name: "echo", value: args };
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const registries = createContributionRegistries();
|
|
64
|
+
registries.tools.register(tool.name, tool);
|
|
65
|
+
registries.agents.register("demo", {
|
|
66
|
+
name: "demo",
|
|
67
|
+
create: () => createAgent({ model, provider, tools: [tool] }),
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
const resolved = registries.tools.resolve("echo");
|
|
71
|
+
console.log(resolved.name); // contributed only, not active for dispatch yet
|
|
72
|
+
|
|
73
|
+
const inputBuilder = registries.inputBuilders.get("custom-input");
|
|
74
|
+
const contextProviders = registries.contextProviders.get("project") ? [registries.contextProviders.resolve("project")] : [];
|
|
75
|
+
const promptBuilder = registries.promptBuilders.get("custom-prompt");
|
|
76
|
+
const skill = registries.skills.get("brief");
|
|
77
|
+
const agent = await registries.agents.resolve("demo").create();
|
|
78
|
+
void agent;
|
|
79
|
+
void inputBuilder;
|
|
80
|
+
void contextProviders;
|
|
81
|
+
void promptBuilder;
|
|
82
|
+
void skill;
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Extension and configuration notes
|
|
86
|
+
|
|
87
|
+
- Hosts can use contribution registries directly and skip extension loading entirely.
|
|
88
|
+
- Extension packages should register contributions through the host-provided extension API once the extension kernel is in use.
|
|
89
|
+
- Registry keys are explicit strings. Prefer stable ids/names such as `provider.id`, `tool.name`, `skill.name`, or package-qualified names when collisions matter.
|
|
90
|
+
- Manifest contribution `kind` values match these registry keys. For example, `authMethods` accepts `authMethod` manifest declarations, `providerPackages` accepts `providerPackage`, `providerRequestPolicies` accepts `providerRequestPolicy`, and `systemPromptContributions` accepts `systemPromptContribution`.
|
|
91
|
+
- Manifest and configuration loading are separate APIs; this page only covers in-memory registration.
|
|
92
|
+
- Tool contributions are inert. They are not executable until the host registers selected definitions in an active tool registry and passes that registry to `dispatchToolCall()`.
|
|
93
|
+
- Provider packages, auth methods, provider request policies, and system prompt contributions are inert until the host resolves them and explicitly calls setup or passes them to a runtime/helper that documents the call site.
|
|
94
|
+
- Input builders, prompt builders, context providers, skills, compaction strategies, and retry policies are inert until the host resolves them and calls, passes, registers, or selects them for runtime helpers.
|
|
95
|
+
- Agent definitions are inert until the host resolves one and calls `create()`. A definition may call `createAgent()` with explicit provider/tools/context/skills; registries are not hidden globals for the runtime.
|
|
96
|
+
|
|
97
|
+
## Security and performance notes
|
|
98
|
+
|
|
99
|
+
- Generic registries are `Map`-backed with O(1) lookup.
|
|
100
|
+
- Registries are explicit objects returned by factories. Prism does not create hidden global contribution registries.
|
|
101
|
+
- Registries must not store resolved credential values, tokens, headers, or secret-bearing settings.
|
|
102
|
+
- `credentialResolvers` may store resolver objects, but resolved credentials must stay at the edge that needs them.
|
|
103
|
+
- Registry operations do not perform network, filesystem, provider, credential, tool, or resource work.
|
|
104
|
+
- Resolving a tool contribution returns data/code supplied by the host or extension; it does not grant allow-list permission or execute the tool.
|
|
105
|
+
- Resolving Phase 5 builder/context/skill contributions only returns data/code. The host still chooses which builder, provider, or skill to pass into input/prompt assembly.
|
|
106
|
+
|
|
107
|
+
## Related APIs
|
|
108
|
+
|
|
109
|
+
- [Provider packages](provider-packages.md): provider package and model metadata contribution primitives.
|
|
110
|
+
- [Provider layer](provider-layer.md): existing provider/model registries reused by `ContributionRegistries`.
|
|
111
|
+
- [Agent/session runtime](agent-session-runtime.md): selected `AgentDefinition` values can create runtime agents with explicit config.
|
|
112
|
+
- [Input and prompt assembly](input-and-prompt-assembly.md): default builders and provider-input assembly for selected contributions.
|
|
113
|
+
- [System prompts](system-prompts.md): composing selected system prompt contributions.
|
|
114
|
+
- [Context and skills](context-and-skills.md): ordered resolution for selected context providers and progressive disclosure for selected skills.
|
|
115
|
+
- [Tools](tools.md): active host tool registry, filtering, and dispatch for selected tool definitions.
|
|
116
|
+
- [Compaction and retry policies](compaction-and-retry.md): selected compaction strategy and retry policy behavior.
|
|
117
|
+
- [Public contracts](public-contracts.md): contribution contract types stored in these registries.
|
|
118
|
+
- [Credentials and redaction](credentials-and-redaction.md): credential resolver and secret-redaction rules.
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# Credentials and redaction
|
|
2
|
+
|
|
3
|
+
## What it does
|
|
4
|
+
|
|
5
|
+
Prism provides small helpers for host-owned credentials and known-secret redaction:
|
|
6
|
+
|
|
7
|
+
- `resolveCredentialValue()`: resolves a credential from a direct string, callback, or `CredentialResolver`.
|
|
8
|
+
- `createExplicitCredentialResolver()`: tries named resolver sources in caller-provided order, such as runtime override → stored → env object → fallback.
|
|
9
|
+
- `createEnvCredentialResolver()`: reads only a caller-supplied env-like object and map.
|
|
10
|
+
- `refreshOAuthCredential()`: calls a provider OAuth refresh function and writes the result to a caller-owned store when supplied.
|
|
11
|
+
- `CredentialValueSource`: the accepted source type for `resolveCredentialValue()`.
|
|
12
|
+
- `redactSecrets()`: replaces known secret string values inside strings, arrays, and plain objects.
|
|
13
|
+
- `errorToErrorInfo()`: converts unknown errors into `ErrorInfo` and redacts known secret values from error text.
|
|
14
|
+
|
|
15
|
+
These helpers do not persist credentials, scan environment variables, execute commands, or load settings.
|
|
16
|
+
|
|
17
|
+
## When to use it
|
|
18
|
+
|
|
19
|
+
Use these helpers inside provider adapters or host integration code that needs to resolve a credential at request time and prevent known secret values from appearing in emitted errors or logs.
|
|
20
|
+
|
|
21
|
+
Do not use them as a credential manager, general secret scanner, vault, settings loader, or permission system.
|
|
22
|
+
|
|
23
|
+
## Inputs / request
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
resolveCredentialValue(
|
|
27
|
+
source: CredentialValueSource | undefined,
|
|
28
|
+
request: CredentialRequest,
|
|
29
|
+
): Promise<string | undefined>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
`CredentialValueSource` can be:
|
|
33
|
+
|
|
34
|
+
| Source | Behavior |
|
|
35
|
+
| --- | --- |
|
|
36
|
+
| `string` | Returned directly. |
|
|
37
|
+
| `() => string | undefined | Promise<string | undefined>` | Called when a credential is needed. |
|
|
38
|
+
| `CredentialResolver` | `resolve(request)` is called and `.value` is returned. |
|
|
39
|
+
|
|
40
|
+
```ts
|
|
41
|
+
createExplicitCredentialResolver(sources: readonly CredentialResolverSource[]): CredentialResolver
|
|
42
|
+
createEnvCredentialResolver(env: Readonly<Record<string, string | undefined>>, map: Readonly<Record<string, string>>): CredentialResolver
|
|
43
|
+
refreshOAuthCredential(options: { provider: OAuthProvider; credentials: OAuthCredentials; store?: OAuthCredentialStore }): Promise<OAuthCredentials>
|
|
44
|
+
redactSecrets<T>(value: T, secrets: readonly (string | undefined)[]): T
|
|
45
|
+
errorToErrorInfo(error: unknown, secrets?: readonly (string | undefined)[]): ErrorInfo
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
`secrets` must be the exact values to redact. Undefined and empty values are ignored.
|
|
49
|
+
|
|
50
|
+
## Outputs / response / events
|
|
51
|
+
|
|
52
|
+
- `resolveCredentialValue()` returns a credential string or `undefined`.
|
|
53
|
+
- `redactSecrets()` returns the same value shape with known string secrets replaced by `[REDACTED]`.
|
|
54
|
+
- `errorToErrorInfo()` returns `{ name?, message, code?, cause? }` with known secret values removed from message/cause text.
|
|
55
|
+
|
|
56
|
+
## Request/response example
|
|
57
|
+
|
|
58
|
+
```json
|
|
59
|
+
{
|
|
60
|
+
"request": { "name": "apiKey", "provider": "demo" },
|
|
61
|
+
"resolved": "<host-owned credential value>",
|
|
62
|
+
"redactedError": { "message": "bad key [REDACTED]" }
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Implementation example
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
import {
|
|
70
|
+
createEnvCredentialResolver,
|
|
71
|
+
createExplicitCredentialResolver,
|
|
72
|
+
errorToErrorInfo,
|
|
73
|
+
redactSecrets,
|
|
74
|
+
resolveCredentialValue,
|
|
75
|
+
} from "@arnilo/prism";
|
|
76
|
+
|
|
77
|
+
const runtime = { resolve: () => undefined };
|
|
78
|
+
const stored = { resolve: () => undefined };
|
|
79
|
+
const env = createEnvCredentialResolver({ DEMO_API_KEY: "fake-demo-key" }, { demo: "DEMO_API_KEY" });
|
|
80
|
+
const resolver = createExplicitCredentialResolver([
|
|
81
|
+
{ name: "runtime", resolver: runtime },
|
|
82
|
+
{ name: "stored", resolver: stored },
|
|
83
|
+
{ name: "env", resolver: env },
|
|
84
|
+
]);
|
|
85
|
+
|
|
86
|
+
const apiKey = await resolveCredentialValue(resolver, { name: "apiKey", provider: "demo" });
|
|
87
|
+
|
|
88
|
+
const message = redactSecrets(`request failed for ${apiKey}`, [apiKey]);
|
|
89
|
+
const error = errorToErrorInfo(new Error(`bad credential ${apiKey}`), [apiKey]);
|
|
90
|
+
|
|
91
|
+
console.log(message);
|
|
92
|
+
console.log(error.message);
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Extension and configuration notes
|
|
96
|
+
|
|
97
|
+
- Hosts and extension packages can implement `CredentialResolver` and pass it explicitly to code that needs credentials.
|
|
98
|
+
- Use `createExplicitCredentialResolver()` when documenting a fixed order such as runtime override, stored credential, caller-provided env object, then fallback resolver.
|
|
99
|
+
- Use `createEnvCredentialResolver()` only with an object supplied by the host; Prism does not read `process.env` for you.
|
|
100
|
+
- Provider adapters should resolve credentials as late as possible, per request.
|
|
101
|
+
- Keep resolved credential values local to the request path. Do not put them in registries, model configs, messages, provider events, agent events, session entries, compaction summaries, or logs.
|
|
102
|
+
- Future settings/config loaders may provide credential resolver instances, but core helpers remain storage-free.
|
|
103
|
+
|
|
104
|
+
## Security and performance notes
|
|
105
|
+
|
|
106
|
+
- Redaction only removes exact known secret values passed to the helper. It is not a general-purpose secret detector.
|
|
107
|
+
- Do not pass empty strings as secrets; they are ignored.
|
|
108
|
+
- `redactSecrets()` recursively walks arrays and object entries, so avoid using it on huge objects unless needed.
|
|
109
|
+
- Cycle and non-JSON value handling: `redactSecrets()` is cycle-safe via a `WeakSet` visited-set. Self-referential or mutually referenced objects render `"[Circular]"` at the back-reference instead of throwing. `Date` and `RegExp` values are passed through unchanged; `ArrayBuffer` and typed arrays are passed through unchanged; `Map` is normalized to a plain object and `Set` to an array so the output stays JSON-compatible. `errorToErrorInfo()` tolerates a cyclic `error.cause` (rendered via `String()`).
|
|
110
|
+
- Use placeholders in tests and docs. Never commit real tokens.
|
|
111
|
+
- Live provider/worker tests are gated behind explicit environment variables and skipped by default: `PRISM_LIVE_PROVIDER_TESTS`, `PRISM_LIVE_COMPACTION_TESTS`, `PRISM_LIVE_OBSERVATIONAL_MEMORY_TESTS`. Default `npm test` is network-free; do not add ungated network calls to default tests.
|
|
112
|
+
- `resolveCredentialValue()` and `createExplicitCredentialResolver()` do not cache values. Add host-side caching only if a real credential source needs it.
|
|
113
|
+
- `refreshOAuthCredential()` only calls the supplied OAuth provider and optional store; it has no built-in persistence or retry loop.
|
|
114
|
+
|
|
115
|
+
## Related APIs
|
|
116
|
+
|
|
117
|
+
- [Public contracts](public-contracts.md): `CredentialRequest`, `Credential`, `CredentialResolver`, `CredentialResolverSource`, `OAuthLoginCallbacks`, `OAuthCredentials`, `OAuthProvider`, and `ErrorInfo`.
|
|
118
|
+
- [Provider layer](provider-layer.md): `providerError()` uses `errorToErrorInfo()` for redacted provider error events.
|
|
119
|
+
- [LLM compaction package](compaction-llm.md): resolves optional summary-provider credentials per compaction call and redacts exact known values.
|
|
120
|
+
- [OpenAI-compatible provider](providers/openai-compatible.md): resolves API keys per request and redacts known values from adapter errors.
|
|
121
|
+
|
|
122
|
+
Phase 10 added `createMemoryCredentialStore()`, `createChainedCredentialResolver()`, and `createSecretRedactor()` for opt-in in-memory auth and runtime redaction. Phase 11 adds OAuth/API-key contracts plus explicit resolver order helpers. Core still has no persistent secret store and does not read environment variables or files for credentials. See [Security/auth/trust](settings-auth-trust-security.md).
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Extension kernel and event bus
|
|
2
|
+
|
|
3
|
+
## What it does
|
|
4
|
+
|
|
5
|
+
The extension kernel loads host-provided `Extension` objects in order and gives each extension a runtime `ExtensionAPI`. The API can register contributions into explicit registries, register middleware, subscribe to lifecycle events, and emit events.
|
|
6
|
+
|
|
7
|
+
APIs:
|
|
8
|
+
|
|
9
|
+
- `createExtensionKernel()` / `ExtensionKernel`
|
|
10
|
+
- `createExtensionEventBus()` / `ExtensionEventBus`
|
|
11
|
+
- `ExtensionAPI`, `ExtensionEvent`, and `extension_error` events
|
|
12
|
+
- Shared `MiddlewareRegistry` access and `api.use()` registration
|
|
13
|
+
|
|
14
|
+
## When to use it
|
|
15
|
+
|
|
16
|
+
Use the extension kernel when a host wants packages to contribute provider packages, providers, models, auth methods, provider request policies, system prompt contributions, tools, context providers, skills, commands, agents, builders, strategies, stores, resources, settings providers, or credential resolvers without editing Prism internals.
|
|
17
|
+
|
|
18
|
+
Skip the kernel and use contribution registries directly when the host does not need extension setup lifecycle or events.
|
|
19
|
+
|
|
20
|
+
## Inputs / request
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
createExtensionKernel(options?: ExtensionKernelOptions): ExtensionKernel
|
|
24
|
+
createExtensionEventBus(options?: { errorPolicy?: "event" | "throw"; secrets?: readonly string[] }): ExtensionEventBus
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
`ExtensionKernelOptions`:
|
|
28
|
+
|
|
29
|
+
| Field | Type | Purpose |
|
|
30
|
+
| --- | --- | --- |
|
|
31
|
+
| `registries` | `ContributionRegistries` | Optional host-created registry bundle. |
|
|
32
|
+
| `middleware` | `MiddlewareRegistry` | Optional host-created middleware registry. |
|
|
33
|
+
| `errorPolicy` | `"event" | "throw"` | Defaults to `"event"`; use `"throw"` for fail-fast setup/listener/middleware errors. |
|
|
34
|
+
| `secrets` | readonly strings | Known secret values to redact from extension error events. |
|
|
35
|
+
|
|
36
|
+
`ExtensionAPI` includes `registries`, `middleware`, `on()`, `emit()`, `use()`, and registration methods for all contribution categories, including provider packages, auth methods, provider request policies, and system prompt contributions.
|
|
37
|
+
|
|
38
|
+
## Outputs / response / events
|
|
39
|
+
|
|
40
|
+
- `kernel.load(extensions)` calls each extension's `setup(api)` in host-provided order.
|
|
41
|
+
- `kernel.registries` exposes the explicit contribution registry bundle.
|
|
42
|
+
- `kernel.events.on(type, handler)` registers ordered event handlers and returns an unsubscribe function.
|
|
43
|
+
- `kernel.events.emit(event)` calls matching handlers in registration order.
|
|
44
|
+
- `kernel.middleware.run(hook, value)` runs matching middleware in registration order.
|
|
45
|
+
- With default `errorPolicy: "event"`, setup/listener/middleware errors become `extension_error` events with redacted `ErrorInfo`.
|
|
46
|
+
- With `errorPolicy: "throw"`, setup/listener/middleware errors reject/throw.
|
|
47
|
+
|
|
48
|
+
## Request/response example
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"loaded": ["demo-extension"],
|
|
53
|
+
"events": [{ "type": "extension_error", "extension": "demo-extension" }]
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Implementation example
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
import { createAgent, createExtensionKernel, type Extension } from "@arnilo/prism";
|
|
61
|
+
|
|
62
|
+
const extension: Extension = {
|
|
63
|
+
name: "demo-extension",
|
|
64
|
+
setup(api) {
|
|
65
|
+
api.registerProviderPackage({ name: "demo-provider", setup: () => undefined });
|
|
66
|
+
api.registerModel({ provider: "mock", model: "demo", capabilities: { input: ["text"] } });
|
|
67
|
+
api.registerAuthMethod({ provider: "mock", kind: "api_key", credentialName: "apiKey" });
|
|
68
|
+
api.registerProviderRequestPolicy({ name: "cache", apply: ({ request }) => request });
|
|
69
|
+
api.registerSystemPromptContribution({ id: "demo-prompt", source: "package", mode: "append", text: "Use demo rules." });
|
|
70
|
+
api.registerTool({ name: "echo", execute: (args, ctx) => ({ toolCallId: ctx.toolCallId, name: "echo", value: args }) });
|
|
71
|
+
api.registerContextProvider({ name: "project", resolve: () => [{ title: "Project", content: "Context" }] });
|
|
72
|
+
api.registerInputBuilder({ name: "input", build: async () => [{ role: "user", content: [{ type: "text", text: "Hello" }] }] });
|
|
73
|
+
api.registerPromptBuilder({ name: "prompt", build: async (request) => request.messages });
|
|
74
|
+
api.registerSkill({ name: "brief", instructions: "Answer briefly.", toolNames: ["echo"] });
|
|
75
|
+
api.registerAgent({ name: "demo", create: () => createAgent({ model, provider }) });
|
|
76
|
+
api.registerCompactionStrategy({ name: "compact", compact: () => ({ summary: "summary" }) });
|
|
77
|
+
api.registerRetryPolicy({ name: "retry", decide: () => ({ retry: false }) });
|
|
78
|
+
api.on("session_start", (event) => {
|
|
79
|
+
console.log(event.type);
|
|
80
|
+
});
|
|
81
|
+
api.use("provider_request", (request) => request);
|
|
82
|
+
api.use("compaction", (payload) => payload);
|
|
83
|
+
api.use("retry", (payload) => payload);
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const kernel = createExtensionKernel({ errorPolicy: "event" });
|
|
88
|
+
await kernel.load([extension]);
|
|
89
|
+
|
|
90
|
+
console.log(kernel.registries.models.resolve("mock", "demo").model);
|
|
91
|
+
console.log(kernel.registries.tools.resolve("echo").name); // contributed only; host must activate before dispatch
|
|
92
|
+
console.log(kernel.registries.contextProviders.resolve("project").name); // contributed only; host must select before context resolution
|
|
93
|
+
console.log(kernel.registries.inputBuilders.resolve("input").name); // contributed only; host must pass it to assembly
|
|
94
|
+
console.log(kernel.registries.promptBuilders.resolve("prompt").name); // contributed only; host must pass it to assembly
|
|
95
|
+
console.log(kernel.registries.skills.resolve("brief").name); // contributed only; host must select before prompt use
|
|
96
|
+
console.log(kernel.registries.agents.resolve("demo").name); // contributed only; host must create/select before runtime use
|
|
97
|
+
console.log(kernel.registries.systemPromptContributions.resolve("demo-prompt").text); // contributed only; host must select before prompt use
|
|
98
|
+
await kernel.middleware.run("provider_request", { metadata: {} });
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Extension and configuration notes
|
|
102
|
+
|
|
103
|
+
- Extension loading is explicit. Prism does not discover packages, read manifests, or load filesystem config in the kernel.
|
|
104
|
+
- Setup order is the order provided by the host.
|
|
105
|
+
- The kernel writes only to explicit registries returned by `createContributionRegistries()` or provided by the host.
|
|
106
|
+
- `api.registerTool()` contributes an inert `ToolDefinition` to `registries.tools`; it does not add the tool to an active tool registry, allow list, or dispatch loop.
|
|
107
|
+
- `api.registerInputBuilder()`, `api.registerPromptBuilder()`, and `api.registerContextProvider()` contribute inert builders/providers; they do not replace defaults or run until the host passes selected entries to Phase 5 helpers.
|
|
108
|
+
- `api.registerSkill()` contributes an inert `Skill` to `registries.skills`; it does not disclose instructions, activate referenced tools, or grant permissions until the host selects it.
|
|
109
|
+
- `api.registerProviderPackage()`, `api.registerAuthMethod()`, `api.registerProviderRequestPolicy()`, and `api.registerSystemPromptContribution()` contribute inert provider-package data; they do not load packages, resolve credentials, mutate provider payloads, or change prompts until selected by a host/runtime helper that documents that behavior.
|
|
110
|
+
- `api.registerAgent()` contributes an inert `AgentDefinition`; its `create()` can call `createAgent()`, but the runtime is not started until host code resolves the definition and creates/runs a session.
|
|
111
|
+
- The kernel registers middleware only into the explicit registry returned by `createMiddlewareRegistry()` or provided by the host.
|
|
112
|
+
- `api.use("compaction", middleware)` and `api.use("retry", middleware)` observe or adjust runtime compaction/retry payloads only when the host passes that middleware registry to `createAgent({ middleware })`; compaction strategy and retry policy contributions remain inert until selected by the host.
|
|
113
|
+
- Manifest contribution `kind` values for provider packages, auth methods, provider request policies, and system prompt contributions match the registry keys populated by the extension API. See [Configuration and manifests](configuration-and-manifests.md) for data-only declaration examples.
|
|
114
|
+
|
|
115
|
+
## Security and performance notes
|
|
116
|
+
|
|
117
|
+
- No hidden global extension kernel, provider registry, credential resolver, settings provider, store, or resource loader is created.
|
|
118
|
+
- Error events use `ErrorInfo` and redact only known secret values passed in `secrets`.
|
|
119
|
+
- Do not put resolved credential values in extension events, registry metadata, docs, logs, prompts, or session stores.
|
|
120
|
+
- Event and middleware dispatch are ordered and dependency-free. They use no timers, background workers, filesystem discovery, network calls, provider calls, or tool execution.
|
|
121
|
+
- Extension middleware cannot bypass host tool permissions: tool dispatch re-checks active registry lookup, filters, and object arguments after `tool_call` middleware. Skills that reference `toolNames` are checked against host-active tools by `resolveActiveSkills()`.
|
|
122
|
+
|
|
123
|
+
## Related APIs
|
|
124
|
+
|
|
125
|
+
- [Middleware hooks](middleware-hooks.md): ordered hook registry populated by `ExtensionAPI.use()`.
|
|
126
|
+
- [Provider packages](provider-packages.md): provider package and model metadata registration through `ExtensionAPI`.
|
|
127
|
+
- [Contribution registries](contribution-registries.md): registry bundle populated by `ExtensionAPI`.
|
|
128
|
+
- [Tools](tools.md): host activation, filtering, and dispatch for contributed tool definitions.
|
|
129
|
+
- [Input and prompt assembly](input-and-prompt-assembly.md): host selection for contributed input/prompt builders.
|
|
130
|
+
- [System prompts](system-prompts.md): host selection for contributed system prompt layers.
|
|
131
|
+
- [Context and skills](context-and-skills.md): host selection and tool checks for contributed context providers and skills.
|
|
132
|
+
- [Agent/session runtime](agent-session-runtime.md): `AgentDefinition.create()` can return agents built with `createAgent()` from explicit host-selected config.
|
|
133
|
+
- [Compaction and retry policies](compaction-and-retry.md): compaction strategy/retry policy contributions and `compaction`/`retry` middleware runtime behavior.
|
|
134
|
+
- [LLM compaction package](compaction-llm.md): optional extension helper that registers a provider-backed compaction strategy.
|
|
135
|
+
- [Observational memory compaction package](compaction-observational-memory.md): optional extension helper that registers an inert fast memory compaction strategy.
|
|
136
|
+
- [Public contracts](public-contracts.md): `Extension`, `ExtensionAPI`, and contribution contract types.
|
|
137
|
+
- [Credentials and redaction](credentials-and-redaction.md): secret-redaction behavior used for extension errors.
|
|
138
|
+
|
|
139
|
+
`createExtensionKernel({ permission })` checks `extension:<name>:setup` before each extension `setup()`. Denied extensions do not run. Prism does not sandbox extension code or auto-load project-local extensions. See [Security/auth/trust](settings-auth-trust-security.md).
|