@arnilo/prism 0.0.11 → 0.0.13
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 +24 -0
- package/dist/agent-run-lifecycle.d.ts +5 -1
- package/dist/agent-run-lifecycle.js +17 -1
- package/dist/agents.d.ts +3 -1
- package/dist/agents.js +98 -20
- package/dist/contracts.d.ts +29 -1
- package/dist/extensions.d.ts +11 -0
- package/dist/extensions.js +15 -0
- package/dist/identity.d.ts +92 -0
- package/dist/identity.js +257 -0
- package/dist/index.d.ts +8 -4
- package/dist/index.js +4 -2
- package/dist/persistence-lifecycle.d.ts +103 -0
- package/dist/persistence-lifecycle.js +204 -0
- package/dist/providers/openai-compatible.d.ts +5 -1
- package/dist/providers/openai-compatible.js +15 -6
- package/dist/secure-agent.js +7 -1
- package/dist/testing/persistence-schema.d.ts +2 -2
- package/dist/testing/persistence-schema.js +35 -2
- package/dist/tools.d.ts +2 -0
- package/dist/tools.js +6 -0
- package/docs/a2a.md +3 -0
- package/docs/ag-ui.md +123 -0
- package/docs/agent-events.md +2 -1
- package/docs/agent-identity.md +111 -0
- package/docs/agent-session-runtime.md +5 -1
- package/docs/coding-agent-tools.md +2 -0
- package/docs/compaction-and-retry.md +2 -1
- package/docs/compaction-llm.md +20 -1
- package/docs/credential-storage.md +5 -1
- package/docs/credentials-and-redaction.md +8 -0
- package/docs/database-persistence.md +18 -7
- package/docs/extensions.md +1 -0
- package/docs/guardrails.md +3 -0
- package/docs/host-security.md +7 -1
- package/docs/index.md +25 -14
- package/docs/mcp-tools.md +2 -0
- package/docs/migration.md +43 -0
- package/docs/model-routing.md +102 -0
- package/docs/observability.md +2 -0
- package/docs/performance.md +38 -0
- package/docs/policy-and-audit.md +127 -0
- package/docs/postgres-persistence.md +1 -1
- package/docs/provider-packages.md +17 -0
- package/docs/provider-request-policies.md +2 -0
- package/docs/providers/anthropic.md +3 -2
- package/docs/providers/azure.md +74 -0
- package/docs/providers/bedrock.md +72 -0
- package/docs/providers/google.md +4 -2
- package/docs/providers/openai-compatible.md +3 -1
- package/docs/providers/openai.md +2 -2
- package/docs/providers/openrouter.md +2 -0
- package/docs/providers/vertex.md +71 -0
- package/docs/public-contracts.md +5 -1
- package/docs/release-and-install.md +167 -17
- package/docs/review-coverage-2026-07-22-phase-7.md +173 -0
- package/docs/review-coverage-2026-07-23-phase-8.md +245 -0
- package/docs/runs-and-usage.md +3 -0
- package/docs/server.md +34 -4
- package/docs/sqlite-persistence.md +1 -1
- package/docs/supervisors.md +2 -0
- package/docs/work-connectors.md +28 -0
- package/docs/work-tools.md +114 -0
- package/package.json +5 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.0.13] - 2026-07-24
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Enterprise identity (`Principal` / `AgentIdentity`), optional `@arnilo/prism-policy`, `@arnilo/prism-model-router`, enterprise cloud providers (Azure/Bedrock/Vertex), server deployment seams, persistence schema v5 lifecycle hooks, and `@arnilo/prism-work-tools` (M365 + GWS).
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- Versioned all **41** first-party manifests and exact internal ranges to `0.0.13`; Phase 8 optional packages enroll in `@arnilo/prism-all` only.
|
|
12
|
+
- Network-free enterprise evidence: `scripts/benchmark-0.0.13.mjs`.
|
|
13
|
+
|
|
3
14
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
4
15
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
5
16
|
|
|
@@ -7,6 +18,19 @@ All notable changes to this project will be documented in this file.
|
|
|
7
18
|
|
|
8
19
|
## [Unreleased]
|
|
9
20
|
|
|
21
|
+
## [0.0.12] - 2026-07-22
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
|
|
25
|
+
- Optional `@arnilo/prism-ag-ui` package with bounded AG-UI mapper/authorized handler/replay and stable `./acp` sibling, built over shared durable resume streams.
|
|
26
|
+
- `createCodingCompactionStrategy()` preset for bounded coding-session handoff.
|
|
27
|
+
|
|
28
|
+
### Changed
|
|
29
|
+
|
|
30
|
+
- Versioned all 35 first-party manifests and exact internal ranges to `0.0.12`; `@arnilo/prism-all` includes AG-UI while `@arnilo/prism-code` and `@arnilo/prism-sdk` remain free of UI protocol dependencies.
|
|
31
|
+
- Added network-free interoperability/compaction evidence: `scripts/benchmark-0.0.12.mjs`.
|
|
32
|
+
|
|
33
|
+
|
|
10
34
|
## [0.0.11] - 2026-07-22
|
|
11
35
|
|
|
12
36
|
### Added
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Agent, AgentRunRef, AgentRunResult, AgentRunResume, AgentRunStatusResult, OwnershipScope } from "./contracts.js";
|
|
1
|
+
import type { Agent, AgentEvent, AgentRunRef, AgentRunResult, AgentRunResume, AgentRunStatusResult, OwnershipScope, SubscribeOptions } from "./contracts.js";
|
|
2
2
|
import type { CheckpointStore } from "./contracts.js";
|
|
3
3
|
export interface AgentRunLifecycleAgent {
|
|
4
4
|
readonly agent: Agent;
|
|
@@ -20,9 +20,13 @@ export interface AgentRunLifecycleRequest {
|
|
|
20
20
|
/** Adapter-selected capability; stored runs for another agent are non-enumerable. */
|
|
21
21
|
readonly agentId?: string;
|
|
22
22
|
}
|
|
23
|
+
/** Bounded live-event options for a durable lifecycle resume. */
|
|
24
|
+
export interface AgentRunLifecycleStreamRequest extends AgentRunLifecycleRequest, SubscribeOptions {
|
|
25
|
+
}
|
|
23
26
|
export interface AgentRunLifecycle {
|
|
24
27
|
status(ref: AgentRunRef, options?: AgentRunLifecycleRequest): Promise<AgentRunStatusResult>;
|
|
25
28
|
resume(ref: AgentRunRef, resume: AgentRunResume, options?: AgentRunLifecycleRequest): Promise<AgentRunResult>;
|
|
29
|
+
resumeStream(ref: AgentRunRef, resume: AgentRunResume, options?: AgentRunLifecycleStreamRequest): AsyncIterable<AgentEvent>;
|
|
26
30
|
}
|
|
27
31
|
/** Host capability for durable agent status/resume. Adapters supply authorized ownership only. */
|
|
28
32
|
export declare function createAgentRunLifecycle(options: AgentRunLifecycleOptions): AgentRunLifecycle;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AgentRunStateError } from "./contracts.js";
|
|
2
2
|
import { loadAgentRunState, publicState } from "./agent-run-state.js";
|
|
3
|
-
import { resumeAgentRun } from "./agents.js";
|
|
3
|
+
import { resumeAgentRun, resumeAgentRunStream } from "./agents.js";
|
|
4
4
|
function assertAgentId(actual, expected) {
|
|
5
5
|
if (expected !== undefined && actual !== expected)
|
|
6
6
|
throw new AgentRunStateError("Agent run capability mismatch");
|
|
@@ -28,6 +28,22 @@ export function createAgentRunLifecycle(options) {
|
|
|
28
28
|
definitionRevision: resolved.definitionRevision,
|
|
29
29
|
});
|
|
30
30
|
},
|
|
31
|
+
async *resumeStream(ref, resume, request = {}) {
|
|
32
|
+
request.signal?.throwIfAborted();
|
|
33
|
+
const { state } = await loadAgentRunState(options.checkpoints, ref, request.ownership);
|
|
34
|
+
assertAgentId(state.agentId, request.agentId);
|
|
35
|
+
const resolved = await options.resolveAgent({ agentId: state.agentId, ownership: request.ownership, signal: request.signal });
|
|
36
|
+
request.signal?.throwIfAborted();
|
|
37
|
+
yield* resumeAgentRunStream(resolved.agent, ref, resume, {
|
|
38
|
+
checkpoints: options.checkpoints,
|
|
39
|
+
ownership: request.ownership,
|
|
40
|
+
fencingToken: options.fencingToken,
|
|
41
|
+
definitionRevision: resolved.definitionRevision,
|
|
42
|
+
signal: request.signal,
|
|
43
|
+
maxQueuedEvents: request.maxQueuedEvents,
|
|
44
|
+
overflow: request.overflow,
|
|
45
|
+
});
|
|
46
|
+
},
|
|
31
47
|
};
|
|
32
48
|
}
|
|
33
49
|
//# sourceMappingURL=agent-run-lifecycle.js.map
|
package/dist/agents.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import type { Agent, AgentConfig, AgentRunResult, AgentRunResume, AgentRunResumeOptions, AgentRunRef, AgentSession, AgentSessionConfig } from "./contracts.js";
|
|
1
|
+
import type { Agent, AgentConfig, AgentEvent, AgentRunResult, AgentRunResume, AgentRunResumeOptions, AgentRunResumeStreamOptions, AgentRunRef, AgentSession, AgentSessionConfig } from "./contracts.js";
|
|
2
2
|
export declare function createAgent(config: AgentConfig): Agent;
|
|
3
3
|
export declare function createAgentSession(config: AgentSessionConfig & {
|
|
4
4
|
readonly agent: Agent;
|
|
5
5
|
}): AgentSession;
|
|
6
6
|
/** Resume a persisted built-in run. A claimed/dispatched tool is never replayed automatically. */
|
|
7
7
|
export declare function resumeAgentRun(agent: Agent, ref: AgentRunRef, resume: AgentRunResume, options: AgentRunResumeOptions): Promise<AgentRunResult>;
|
|
8
|
+
/** Subscribe before resuming one durable run. Early consumer return aborts that resumed execution. */
|
|
9
|
+
export declare function resumeAgentRunStream(agent: Agent, ref: AgentRunRef, resume: AgentRunResume, options: AgentRunResumeStreamOptions): AsyncGenerator<AgentEvent>;
|
package/dist/agents.js
CHANGED
|
@@ -17,6 +17,7 @@ import { createToolRegistry, dispatchToolCall } from "./tools.js";
|
|
|
17
17
|
import { RunLimitError, RunLimitTracker, resolveRunLimits } from "./run-limits.js";
|
|
18
18
|
import { agentFingerprint, initialAgentRunState, loadAgentRunState, publicState, saveAgentRunState, validateRunStateOptions } from "./agent-run-state.js";
|
|
19
19
|
import { resolveActiveSkills } from "./skills.js";
|
|
20
|
+
import { identityTelemetryAttributes, ownershipFromIdentity, resolveRunIdentity, } from "./identity.js";
|
|
20
21
|
export function createAgent(config) {
|
|
21
22
|
return {
|
|
22
23
|
config,
|
|
@@ -30,6 +31,32 @@ export function createAgentSession(config) {
|
|
|
30
31
|
}
|
|
31
32
|
/** Resume a persisted built-in run. A claimed/dispatched tool is never replayed automatically. */
|
|
32
33
|
export async function resumeAgentRun(agent, ref, resume, options) {
|
|
34
|
+
return executePreparedAgentRunResume(await prepareAgentRunResume(agent, ref, resume, options));
|
|
35
|
+
}
|
|
36
|
+
/** Subscribe before resuming one durable run. Early consumer return aborts that resumed execution. */
|
|
37
|
+
export async function* resumeAgentRunStream(agent, ref, resume, options) {
|
|
38
|
+
throwIfAbortedSignal(options.signal);
|
|
39
|
+
const prepared = await prepareAgentRunResume(agent, ref, resume, options, options.signal);
|
|
40
|
+
const subscription = prepared.session.subscribe(options);
|
|
41
|
+
let settled = false;
|
|
42
|
+
const runPromise = executePreparedAgentRunResume(prepared, options.signal).finally(() => { settled = true; });
|
|
43
|
+
try {
|
|
44
|
+
for await (const event of subscription) {
|
|
45
|
+
if ("runId" in event && event.runId !== ref.runId)
|
|
46
|
+
continue;
|
|
47
|
+
yield event;
|
|
48
|
+
}
|
|
49
|
+
await runPromise;
|
|
50
|
+
}
|
|
51
|
+
finally {
|
|
52
|
+
if (!settled) {
|
|
53
|
+
prepared.session.abort(new Error("resume stream consumer closed"));
|
|
54
|
+
await runPromise.catch(() => undefined);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
async function prepareAgentRunResume(agent, ref, resume, options, signal) {
|
|
59
|
+
throwIfAbortedSignal(signal);
|
|
33
60
|
const { record, state } = await loadAgentRunState(options.checkpoints, ref, options.ownership);
|
|
34
61
|
if (state.definitionRevision !== options.definitionRevision || state.agentId !== (agent.config.id ?? agent.config.name) || state.fingerprint !== agentFingerprint(agent, options.definitionRevision)) {
|
|
35
62
|
throw new AgentRunStateError("Agent definition revision or fingerprint mismatch on resume");
|
|
@@ -37,7 +64,9 @@ export async function resumeAgentRun(agent, ref, resume, options) {
|
|
|
37
64
|
if (record.version !== resume.expectedVersion || state.status !== "suspended") {
|
|
38
65
|
throw new AgentRunStateError("Stale or non-suspended agent run resume");
|
|
39
66
|
}
|
|
67
|
+
const session = new RuntimeAgentSession({ agent, id: state.sessionId, leafId: state.leafId });
|
|
40
68
|
if (resume.decision === "deny") {
|
|
69
|
+
throwIfAbortedSignal(signal);
|
|
41
70
|
const denied = await saveAgentRunState({
|
|
42
71
|
checkpoints: options.checkpoints,
|
|
43
72
|
state: { ...state, status: "denied" },
|
|
@@ -45,10 +74,23 @@ export async function resumeAgentRun(agent, ref, resume, options) {
|
|
|
45
74
|
ownership: options.ownership,
|
|
46
75
|
fencingToken: options.fencingToken,
|
|
47
76
|
});
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
77
|
+
return {
|
|
78
|
+
kind: "deny",
|
|
79
|
+
session,
|
|
80
|
+
interruption: state.interruption,
|
|
81
|
+
version: denied.record.version,
|
|
82
|
+
ownership: options.ownership,
|
|
83
|
+
result: {
|
|
84
|
+
sessionId: state.sessionId,
|
|
85
|
+
runId: state.runId,
|
|
86
|
+
status: "denied",
|
|
87
|
+
leafId: state.leafId,
|
|
88
|
+
text: "",
|
|
89
|
+
content: [],
|
|
90
|
+
runState: publicState(denied.state),
|
|
91
|
+
interruption: state.interruption,
|
|
92
|
+
},
|
|
93
|
+
};
|
|
52
94
|
}
|
|
53
95
|
if (state.pending?.status === "dispatched")
|
|
54
96
|
throw new AgentRunStateError("Ambiguous dispatched tool requires operator resolution");
|
|
@@ -56,6 +98,7 @@ export async function resumeAgentRun(agent, ref, resume, options) {
|
|
|
56
98
|
if (configured && (configured.checkpoints !== options.checkpoints || configured.definitionRevision !== options.definitionRevision)) {
|
|
57
99
|
throw new AgentRunStateError("Agent durable run-state configuration mismatch on resume");
|
|
58
100
|
}
|
|
101
|
+
throwIfAbortedSignal(signal);
|
|
59
102
|
const claimed = await saveAgentRunState({
|
|
60
103
|
checkpoints: options.checkpoints,
|
|
61
104
|
state: { ...state, status: "running", interruption: undefined },
|
|
@@ -63,13 +106,25 @@ export async function resumeAgentRun(agent, ref, resume, options) {
|
|
|
63
106
|
ownership: options.ownership,
|
|
64
107
|
fencingToken: options.fencingToken,
|
|
65
108
|
});
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
109
|
+
return {
|
|
110
|
+
kind: "approve",
|
|
111
|
+
session,
|
|
112
|
+
state: claimed.state,
|
|
113
|
+
ownership: options.ownership,
|
|
114
|
+
runState: configured ?? {
|
|
115
|
+
checkpoints: options.checkpoints,
|
|
116
|
+
definitionRevision: options.definitionRevision,
|
|
117
|
+
interruptBeforeTool: state.interruptBeforeTool,
|
|
118
|
+
fencingToken: options.fencingToken,
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
async function executePreparedAgentRunResume(prepared, signal) {
|
|
123
|
+
if (prepared.kind === "deny") {
|
|
124
|
+
await prepared.session.recordDurableDenial(prepared.result.runId, prepared.interruption, prepared.version, prepared.ownership);
|
|
125
|
+
return prepared.result;
|
|
126
|
+
}
|
|
127
|
+
return prepared.session.resumeDurable(prepared.state, prepared.runState, prepared.ownership, signal);
|
|
73
128
|
}
|
|
74
129
|
class AgentRunSuspended extends Error {
|
|
75
130
|
state;
|
|
@@ -100,6 +155,7 @@ class RuntimeAgentSession {
|
|
|
100
155
|
activeProvider;
|
|
101
156
|
activeLedger;
|
|
102
157
|
activeOwnership;
|
|
158
|
+
activeIdentity;
|
|
103
159
|
activeIdempotencyKey;
|
|
104
160
|
activeGuardrails;
|
|
105
161
|
activeMetadata;
|
|
@@ -154,18 +210,23 @@ class RuntimeAgentSession {
|
|
|
154
210
|
this.pendingSoftInterrupt = true;
|
|
155
211
|
}
|
|
156
212
|
}
|
|
157
|
-
async resumeDurable(state, runState, ownership) {
|
|
158
|
-
return this.runInternal(state.input ?? [], { runState, ownership }, state.runId, { options: runState, state, version: state.version });
|
|
213
|
+
async resumeDurable(state, runState, ownership, signal) {
|
|
214
|
+
return this.runInternal(state.input ?? [], { runState, ownership, signal }, state.runId, { options: runState, state, version: state.version });
|
|
159
215
|
}
|
|
160
216
|
async recordDurableDenial(runId, interruption, version, ownership) {
|
|
161
217
|
this.activeLedger = this.agent.config.runLedger;
|
|
162
218
|
this.activeOwnership = ownership ?? this.agent.config.ownership;
|
|
163
219
|
this.activeRedactor = this.agent.config.redactor;
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
220
|
+
try {
|
|
221
|
+
this.emit({ type: "agent_denied", sessionId: this.id, runId, interruption, version });
|
|
222
|
+
await this.drainLedger();
|
|
223
|
+
}
|
|
224
|
+
finally {
|
|
225
|
+
this.activeLedger = undefined;
|
|
226
|
+
this.activeOwnership = undefined;
|
|
227
|
+
this.activeRedactor = undefined;
|
|
228
|
+
this.closeSubscribers();
|
|
229
|
+
}
|
|
169
230
|
}
|
|
170
231
|
async runInternal(input, options, runId, resumed) {
|
|
171
232
|
if (this.agent.config.secure && (options.redactor !== undefined || options.ownership !== undefined || options.validate !== undefined || options.runState !== undefined)) {
|
|
@@ -202,6 +263,9 @@ class RuntimeAgentSession {
|
|
|
202
263
|
this.activeRedactor = options.redactor ?? this.agent.config.redactor;
|
|
203
264
|
this.activeLedger = options.runLedger ?? this.agent.config.runLedger;
|
|
204
265
|
this.activeOwnership = options.ownership ?? this.agent.config.ownership;
|
|
266
|
+
this.activeIdentity = resolveRunIdentity(options.identity, this.agent.config.identity, this.activeOwnership);
|
|
267
|
+
if (this.activeIdentity && !this.activeOwnership)
|
|
268
|
+
this.activeOwnership = ownershipFromIdentity(this.activeIdentity);
|
|
205
269
|
this.activeIdempotencyKey = options.idempotencyKey ?? this.agent.config.idempotencyKey;
|
|
206
270
|
this.activeGuardrails = mergeGuardrails(this.agent.config.guardrails, options.guardrails);
|
|
207
271
|
this.activeDurable = resumed ?? (durableOptions ? { options: durableOptions, version: 0 } : undefined);
|
|
@@ -213,7 +277,12 @@ class RuntimeAgentSession {
|
|
|
213
277
|
let runStatus = "succeeded";
|
|
214
278
|
const runUsage = createUsageAccumulator();
|
|
215
279
|
let usage;
|
|
216
|
-
const metadata = {
|
|
280
|
+
const metadata = {
|
|
281
|
+
...this.agent.config.metadata,
|
|
282
|
+
...this.metadata,
|
|
283
|
+
...options.metadata,
|
|
284
|
+
...(this.activeIdentity ? identityTelemetryAttributes(this.activeIdentity) : {}),
|
|
285
|
+
};
|
|
217
286
|
this.activeMetadata = metadata;
|
|
218
287
|
const limits = new RunLimitTracker(resolvedLimits, {
|
|
219
288
|
onExceeded: (breach) => {
|
|
@@ -375,7 +444,14 @@ class RuntimeAgentSession {
|
|
|
375
444
|
dispatchToolCall: (call) => dispatchToolCall({
|
|
376
445
|
call,
|
|
377
446
|
registry,
|
|
378
|
-
context: {
|
|
447
|
+
context: {
|
|
448
|
+
sessionId: this.id,
|
|
449
|
+
runId,
|
|
450
|
+
toolCallId: call.id,
|
|
451
|
+
signal: controller.signal,
|
|
452
|
+
metadata,
|
|
453
|
+
identity: this.activeIdentity,
|
|
454
|
+
},
|
|
379
455
|
middleware: this.agent.config.middleware,
|
|
380
456
|
emit: (event) => this.emit(event),
|
|
381
457
|
permission: this.agent.config.permission,
|
|
@@ -383,6 +459,7 @@ class RuntimeAgentSession {
|
|
|
383
459
|
redactor: this.activeRedactor,
|
|
384
460
|
ledger: this.activeLedger,
|
|
385
461
|
ownership: this.activeOwnership,
|
|
462
|
+
identity: this.activeIdentity,
|
|
386
463
|
guardrails: this.activeGuardrails,
|
|
387
464
|
limitTracker: limits,
|
|
388
465
|
beforeExecute: async (mediatedCall) => {
|
|
@@ -518,6 +595,7 @@ class RuntimeAgentSession {
|
|
|
518
595
|
finally {
|
|
519
596
|
this.activeLedger = undefined;
|
|
520
597
|
this.activeOwnership = undefined;
|
|
598
|
+
this.activeIdentity = undefined;
|
|
521
599
|
this.activeIdempotencyKey = undefined;
|
|
522
600
|
this.activeGuardrails = undefined;
|
|
523
601
|
this.activeMetadata = undefined;
|
package/dist/contracts.d.ts
CHANGED
|
@@ -287,6 +287,8 @@ export interface RunOptions {
|
|
|
287
287
|
readonly redactor?: SecretRedactor;
|
|
288
288
|
readonly runLedger?: RunLedger;
|
|
289
289
|
readonly ownership?: OwnershipScope;
|
|
290
|
+
/** Host-verified identity; when set, must project onto `ownership` without widening. */
|
|
291
|
+
readonly identity?: import("./identity.js").AgentIdentity;
|
|
290
292
|
readonly idempotencyKey?: string;
|
|
291
293
|
readonly validate?: ToolValidator;
|
|
292
294
|
readonly activeSkills?: readonly string[];
|
|
@@ -352,6 +354,8 @@ export interface AgentConfig {
|
|
|
352
354
|
readonly redactor?: SecretRedactor;
|
|
353
355
|
readonly runLedger?: RunLedger;
|
|
354
356
|
readonly ownership?: OwnershipScope;
|
|
357
|
+
/** Host-verified identity default for sessions created from this agent. */
|
|
358
|
+
readonly identity?: import("./identity.js").AgentIdentity;
|
|
355
359
|
readonly idempotencyKey?: string;
|
|
356
360
|
readonly compaction?: false | CompactionOptions;
|
|
357
361
|
readonly retry?: false | RetryOptions;
|
|
@@ -369,7 +373,7 @@ export interface AgentConfig {
|
|
|
369
373
|
readonly secure?: true;
|
|
370
374
|
}
|
|
371
375
|
/** Opt-in fail-closed composition over the normal explicit AgentConfig API. */
|
|
372
|
-
export interface SecureAgentOptions extends Omit<AgentConfig, "tools" | "validator" | "redactor" | "permission" | "trust" | "ownership" | "limits" | "runState" | "secure"> {
|
|
376
|
+
export interface SecureAgentOptions extends Omit<AgentConfig, "tools" | "validator" | "redactor" | "permission" | "trust" | "ownership" | "identity" | "limits" | "runState" | "secure"> {
|
|
373
377
|
readonly id: string;
|
|
374
378
|
readonly tools: readonly ToolDefinition[];
|
|
375
379
|
readonly toolArgumentValidator: import("./tools.js").ToolArgumentValidator;
|
|
@@ -377,6 +381,8 @@ export interface SecureAgentOptions extends Omit<AgentConfig, "tools" | "validat
|
|
|
377
381
|
readonly permission: PermissionPolicy;
|
|
378
382
|
readonly trust: TrustPolicy;
|
|
379
383
|
readonly ownership: OwnershipScope;
|
|
384
|
+
/** Optional host-verified identity; when set must match `ownership`. */
|
|
385
|
+
readonly identity?: import("./identity.js").AgentIdentity;
|
|
380
386
|
readonly limits: RunLimits;
|
|
381
387
|
readonly definitionRevision: string;
|
|
382
388
|
readonly runState: Omit<AgentRunStateOptions, "definitionRevision" | "interruptBeforeTool">;
|
|
@@ -449,6 +455,10 @@ export interface AgentRunResumeOptions {
|
|
|
449
455
|
readonly ownership?: OwnershipScope;
|
|
450
456
|
readonly fencingToken?: number;
|
|
451
457
|
}
|
|
458
|
+
/** Bounded, abortable options for `resumeAgentRunStream()`. */
|
|
459
|
+
export interface AgentRunResumeStreamOptions extends AgentRunResumeOptions, SubscribeOptions {
|
|
460
|
+
readonly signal?: AbortSignal;
|
|
461
|
+
}
|
|
452
462
|
export interface AgentRunRef {
|
|
453
463
|
readonly runId: string;
|
|
454
464
|
readonly sessionId?: string;
|
|
@@ -746,6 +756,8 @@ export interface ToolExecutionContext {
|
|
|
746
756
|
readonly toolCallId: string;
|
|
747
757
|
readonly signal?: AbortSignal;
|
|
748
758
|
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
759
|
+
/** Host-verified identity for this tool invocation, when enterprise identity is active. */
|
|
760
|
+
readonly identity?: import("./identity.js").AgentIdentity;
|
|
749
761
|
progress?(progress?: unknown, metadata?: Readonly<Record<string, unknown>>): void | Promise<void>;
|
|
750
762
|
}
|
|
751
763
|
export interface ToolResult {
|
|
@@ -896,6 +908,9 @@ export interface ExtensionEvent {
|
|
|
896
908
|
export interface Extension {
|
|
897
909
|
readonly name: string;
|
|
898
910
|
setup(api: ExtensionAPI): void | Promise<void>;
|
|
911
|
+
/** Host-attested signature/digest for `ExtensionLoadPolicy.verifySignature`. */
|
|
912
|
+
readonly signature?: string;
|
|
913
|
+
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
899
914
|
}
|
|
900
915
|
export interface ProviderPackage {
|
|
901
916
|
readonly name: string;
|
|
@@ -1601,6 +1616,11 @@ export interface ProductionPersistenceStore {
|
|
|
1601
1616
|
/** DB-friendly branch read (mirrors `SessionStore.readBranchPath`): one ancestor-chain
|
|
1602
1617
|
* query instead of `queryEntries({ sessionId })` + in-memory walk. Optional. */
|
|
1603
1618
|
readBranchPath?(query: SessionBranchRead): Promise<PersistencePage<SessionEntry>>;
|
|
1619
|
+
/**
|
|
1620
|
+
* Optional Phase 8 retention / legal-hold / export / tenant-quota lifecycle.
|
|
1621
|
+
* Prefer attaching `createMemoryPersistenceLifecycle()` or adapter-native methods.
|
|
1622
|
+
*/
|
|
1623
|
+
readonly lifecycle?: import("./persistence-lifecycle.js").PersistenceLifecycleStore;
|
|
1604
1624
|
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
1605
1625
|
}
|
|
1606
1626
|
export interface CompactionStrategy {
|
|
@@ -1792,3 +1812,11 @@ export interface ArtifactParseResult<T> {
|
|
|
1792
1812
|
export type ArtifactParser<T> = (text: string, ctx: ArtifactContext) => ArtifactParseResult<T> | Promise<ArtifactParseResult<T>>;
|
|
1793
1813
|
export type ArtifactValidator<T> = (value: T, ctx: ArtifactContext) => ArtifactValidation | Promise<ArtifactValidation>;
|
|
1794
1814
|
export type ArtifactRepairer<T> = (value: T | undefined, failure: ArtifactValidation, ctx: ArtifactContext) => AgentInput | Promise<AgentInput>;
|
|
1815
|
+
/** Alias re-exports so `dist/contracts.d.ts` exposes implementer contract names. */
|
|
1816
|
+
export type AgentIdentity = import("./identity.js").AgentIdentity;
|
|
1817
|
+
export type Principal = import("./identity.js").Principal;
|
|
1818
|
+
export type IdentityVerifier = import("./identity.js").IdentityVerifier;
|
|
1819
|
+
export type PersistenceLifecycleStore = import("./persistence-lifecycle.js").PersistenceLifecycleStore;
|
|
1820
|
+
export type LegalHoldRecord = import("./persistence-lifecycle.js").LegalHoldRecord;
|
|
1821
|
+
export type TenantQuota = import("./persistence-lifecycle.js").TenantQuota;
|
|
1822
|
+
export type PersistenceResourceKind = import("./persistence-lifecycle.js").PersistenceResourceKind;
|
package/dist/extensions.d.ts
CHANGED
|
@@ -4,12 +4,23 @@ import { type MiddlewareRegistry } from "./middleware.js";
|
|
|
4
4
|
import { type PermissionPolicy } from "./security.js";
|
|
5
5
|
export type ExtensionEventHandler = (event: ExtensionEvent) => void | Promise<void>;
|
|
6
6
|
export type ExtensionErrorPolicy = "event" | "throw";
|
|
7
|
+
export interface ExtensionLoadPolicy {
|
|
8
|
+
/** When set, only listed extension names may load. */
|
|
9
|
+
readonly allowList?: readonly string[];
|
|
10
|
+
/**
|
|
11
|
+
* Host signature / attestation check. Return false or throw to deny.
|
|
12
|
+
* Unsigned extensions fail closed when this callback is provided.
|
|
13
|
+
*/
|
|
14
|
+
readonly verifySignature?: (extension: Extension) => boolean | Promise<boolean>;
|
|
15
|
+
}
|
|
7
16
|
export interface ExtensionKernelOptions {
|
|
8
17
|
readonly registries?: ContributionRegistries;
|
|
9
18
|
readonly middleware?: MiddlewareRegistry;
|
|
10
19
|
readonly errorPolicy?: ExtensionErrorPolicy;
|
|
11
20
|
readonly secrets?: readonly (string | undefined)[];
|
|
12
21
|
readonly permission?: PermissionPolicy;
|
|
22
|
+
/** Optional allow-list / signature policy evaluated before `setup`. */
|
|
23
|
+
readonly loadPolicy?: ExtensionLoadPolicy;
|
|
13
24
|
}
|
|
14
25
|
export interface ExtensionEventBus {
|
|
15
26
|
on(type: ExtensionLifecycleEventName | string, handler: ExtensionEventHandler): () => void;
|
package/dist/extensions.js
CHANGED
|
@@ -120,6 +120,7 @@ export function createExtensionKernel(options = {}) {
|
|
|
120
120
|
for (const extension of extensions) {
|
|
121
121
|
try {
|
|
122
122
|
await assertPermission(options.permission, { kind: "extension", action: "setup", target: extension.name });
|
|
123
|
+
await assertExtensionLoadPolicy(options.loadPolicy, extension);
|
|
123
124
|
await extension.setup(api);
|
|
124
125
|
}
|
|
125
126
|
catch (error) {
|
|
@@ -131,4 +132,18 @@ export function createExtensionKernel(options = {}) {
|
|
|
131
132
|
},
|
|
132
133
|
};
|
|
133
134
|
}
|
|
135
|
+
async function assertExtensionLoadPolicy(policy, extension) {
|
|
136
|
+
if (!policy)
|
|
137
|
+
return;
|
|
138
|
+
if (policy.allowList && !policy.allowList.includes(extension.name)) {
|
|
139
|
+
throw new Error(`Extension "${extension.name}" is not allow-listed`);
|
|
140
|
+
}
|
|
141
|
+
if (policy.verifySignature) {
|
|
142
|
+
if (!extension.signature)
|
|
143
|
+
throw new Error(`Extension "${extension.name}" is unsigned`);
|
|
144
|
+
const ok = await policy.verifySignature(extension);
|
|
145
|
+
if (!ok)
|
|
146
|
+
throw new Error(`Extension "${extension.name}" failed signature verification`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
134
149
|
//# sourceMappingURL=extensions.js.map
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import type { OwnershipScope } from "./contracts.js";
|
|
2
|
+
/** Host-authenticated actor (user, service, or agent principal). */
|
|
3
|
+
export interface Principal {
|
|
4
|
+
readonly kind: "user" | "service" | "agent" | string;
|
|
5
|
+
readonly id: string;
|
|
6
|
+
readonly displayName?: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Host-verified identity context. Projects onto {@link OwnershipScope}.
|
|
10
|
+
* `verified: true` marks host-verifier output; trust boundaries must obtain this
|
|
11
|
+
* via {@link IdentityVerifier}, never by accepting caller-asserted claims alone.
|
|
12
|
+
*/
|
|
13
|
+
export interface AgentIdentity {
|
|
14
|
+
readonly tenantId: string;
|
|
15
|
+
readonly accountId?: string;
|
|
16
|
+
readonly userId?: string;
|
|
17
|
+
/** Acting principal for this run/tool/delegation. */
|
|
18
|
+
readonly principal: Principal;
|
|
19
|
+
/** Human sponsor accountable for the agent lifecycle (Entra-style). */
|
|
20
|
+
readonly sponsor?: Principal;
|
|
21
|
+
/** Resource owner when distinct from sponsor. */
|
|
22
|
+
readonly owner?: Principal;
|
|
23
|
+
/** Parent principal when this identity is a narrowed delegation. */
|
|
24
|
+
readonly delegatedFrom?: Principal;
|
|
25
|
+
readonly scopes: readonly string[];
|
|
26
|
+
/** Late-bound credential resolver keys — never secret material. */
|
|
27
|
+
readonly credentialRefs?: readonly string[];
|
|
28
|
+
readonly issuedAt: string;
|
|
29
|
+
readonly expiresAt?: string;
|
|
30
|
+
readonly revokedAt?: string;
|
|
31
|
+
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
32
|
+
readonly verified: true;
|
|
33
|
+
}
|
|
34
|
+
export interface IdentityVerifier {
|
|
35
|
+
verify(input: unknown): AgentIdentity | Promise<AgentIdentity>;
|
|
36
|
+
}
|
|
37
|
+
export interface AssertIdentityActiveOptions {
|
|
38
|
+
readonly now?: number;
|
|
39
|
+
/** When set, identity.tenantId must equal this value. */
|
|
40
|
+
readonly expectedTenantId?: string;
|
|
41
|
+
readonly limits?: IdentityLimits;
|
|
42
|
+
}
|
|
43
|
+
export interface NarrowIdentityOptions {
|
|
44
|
+
readonly scopes: readonly string[];
|
|
45
|
+
readonly principal?: Principal;
|
|
46
|
+
readonly credentialRefs?: readonly string[];
|
|
47
|
+
readonly expiresAt?: string;
|
|
48
|
+
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
49
|
+
readonly limits?: IdentityLimits;
|
|
50
|
+
}
|
|
51
|
+
export interface IdentityLimits {
|
|
52
|
+
readonly maxScopes?: number;
|
|
53
|
+
readonly maxScopeBytes?: number;
|
|
54
|
+
readonly maxMetadataBytes?: number;
|
|
55
|
+
readonly maxCredentialRefBytes?: number;
|
|
56
|
+
readonly maxPrincipalIdBytes?: number;
|
|
57
|
+
}
|
|
58
|
+
export interface ResolvedIdentityLimits {
|
|
59
|
+
readonly maxScopes: number;
|
|
60
|
+
readonly maxScopeBytes: number;
|
|
61
|
+
readonly maxMetadataBytes: number;
|
|
62
|
+
readonly maxCredentialRefBytes: number;
|
|
63
|
+
readonly maxPrincipalIdBytes: number;
|
|
64
|
+
}
|
|
65
|
+
export declare const DEFAULT_IDENTITY_LIMITS: ResolvedIdentityLimits;
|
|
66
|
+
export declare const HARD_IDENTITY_LIMITS: ResolvedIdentityLimits;
|
|
67
|
+
export declare class IdentityError extends Error {
|
|
68
|
+
readonly reason: string;
|
|
69
|
+
readonly code = "ERR_PRISM_IDENTITY";
|
|
70
|
+
constructor(message: string, reason: string);
|
|
71
|
+
}
|
|
72
|
+
export declare function resolveIdentityLimits(input?: IdentityLimits): ResolvedIdentityLimits;
|
|
73
|
+
/** Project verified identity onto ownership scope fields used by persistence/server. */
|
|
74
|
+
export declare function ownershipFromIdentity(identity: AgentIdentity): OwnershipScope;
|
|
75
|
+
/**
|
|
76
|
+
* Fail closed on shape/limits/expiry/revocation/tenant mismatch.
|
|
77
|
+
* Sync and network-free — host {@link IdentityVerifier} owns remote checks.
|
|
78
|
+
*/
|
|
79
|
+
export declare function assertIdentityActive(identity: AgentIdentity, options?: AssertIdentityActiveOptions): void;
|
|
80
|
+
/** Delegation may only narrow scopes; tenant and ownership ids stay immutable. */
|
|
81
|
+
export declare function narrowIdentity(parent: AgentIdentity, options: NarrowIdentityOptions): AgentIdentity;
|
|
82
|
+
/** Refuse ownership that widens or conflicts with a verified identity. */
|
|
83
|
+
export declare function assertIdentityMatchesOwnership(identity: AgentIdentity, ownership?: OwnershipScope): void;
|
|
84
|
+
/**
|
|
85
|
+
* Propagation check: child must share tenant, not widen scopes, and remain active.
|
|
86
|
+
* Used by supervisor/A2A/MCP/server when forwarding identity across a boundary.
|
|
87
|
+
*/
|
|
88
|
+
export declare function assertIdentityPropagation(parent: AgentIdentity, child: AgentIdentity, options?: AssertIdentityActiveOptions): void;
|
|
89
|
+
/** Redacted identity refs safe for telemetry/ledger metadata (no secrets, no raw JWT). */
|
|
90
|
+
export declare function identityTelemetryAttributes(identity: AgentIdentity): Readonly<Record<string, string>>;
|
|
91
|
+
/** Resolve run identity: explicit option wins; otherwise agent default. Assert when present. */
|
|
92
|
+
export declare function resolveRunIdentity(runIdentity: AgentIdentity | undefined, agentIdentity: AgentIdentity | undefined, ownership: OwnershipScope | undefined, options?: AssertIdentityActiveOptions): AgentIdentity | undefined;
|