@arnilo/prism 0.0.3 → 0.0.4

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 (99) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +32 -20
  3. package/dist/agent-loops.d.ts +8 -1
  4. package/dist/agent-loops.js +57 -11
  5. package/dist/agents.js +70 -17
  6. package/dist/checkpoints.d.ts +11 -0
  7. package/dist/checkpoints.js +144 -0
  8. package/dist/compaction.js +9 -1
  9. package/dist/content.d.ts +102 -0
  10. package/dist/content.js +410 -0
  11. package/dist/contracts.d.ts +142 -2
  12. package/dist/event-multiplexer.d.ts +23 -0
  13. package/dist/event-multiplexer.js +136 -0
  14. package/dist/execution-policy.d.ts +28 -0
  15. package/dist/execution-policy.js +24 -0
  16. package/dist/index.d.ts +17 -5
  17. package/dist/index.js +11 -4
  18. package/dist/input.js +11 -1
  19. package/dist/leases.d.ts +8 -0
  20. package/dist/leases.js +111 -0
  21. package/dist/node/agent-definitions.js +3 -5
  22. package/dist/node/config.d.ts +1 -0
  23. package/dist/node/config.js +5 -3
  24. package/dist/node/contribution-discovery.js +5 -8
  25. package/dist/node/session-store-jsonl.js +8 -5
  26. package/dist/node/settings.js +2 -2
  27. package/dist/node/trust.js +2 -4
  28. package/dist/observability.d.ts +3 -0
  29. package/dist/observability.js +18 -0
  30. package/dist/providers/media.d.ts +42 -0
  31. package/dist/providers/media.js +116 -0
  32. package/dist/providers/openai-compatible.js +18 -119
  33. package/dist/providers/openai-primitives.d.ts +9 -0
  34. package/dist/providers/openai-primitives.js +129 -0
  35. package/dist/providers/transport.d.ts +40 -0
  36. package/dist/providers/transport.js +221 -0
  37. package/dist/redaction.js +40 -13
  38. package/dist/resources.d.ts +5 -0
  39. package/dist/resources.js +4 -0
  40. package/dist/structured-output.d.ts +11 -0
  41. package/dist/structured-output.js +59 -0
  42. package/dist/testing/persistence-schema.d.ts +102 -0
  43. package/dist/testing/persistence-schema.js +457 -0
  44. package/dist/testing/provider-conformance.js +10 -1
  45. package/dist/testing/run-ledger-conformance.d.ts +33 -0
  46. package/dist/testing/run-ledger-conformance.js +172 -0
  47. package/dist/testing/session-store-conformance.d.ts +16 -0
  48. package/dist/testing/session-store-conformance.js +73 -0
  49. package/dist/tools.d.ts +17 -0
  50. package/dist/tools.js +29 -2
  51. package/docs/agent-events.md +13 -4
  52. package/docs/agent-loops.md +10 -4
  53. package/docs/agent-session-runtime.md +1 -0
  54. package/docs/cli-rpc.md +3 -0
  55. package/docs/coding-agent-tools.md +41 -7
  56. package/docs/coding-security.md +84 -0
  57. package/docs/credential-storage.md +177 -0
  58. package/docs/credentials-and-redaction.md +2 -1
  59. package/docs/database-persistence.md +44 -2
  60. package/docs/host-security.md +15 -1
  61. package/docs/index.md +28 -12
  62. package/docs/input-and-prompt-assembly.md +6 -5
  63. package/docs/mcp-tools.md +139 -0
  64. package/docs/middleware-hooks.md +2 -0
  65. package/docs/migration.md +21 -28
  66. package/docs/model-registry.md +5 -3
  67. package/docs/multimodal-content.md +148 -0
  68. package/docs/observability.md +163 -0
  69. package/docs/performance.md +40 -1
  70. package/docs/persistence-credentials-multimodality-primitives.md +303 -0
  71. package/docs/postgres-persistence.md +141 -0
  72. package/docs/provider-conformance.md +17 -0
  73. package/docs/provider-layer.md +1 -1
  74. package/docs/provider-primitives.md +281 -0
  75. package/docs/providers/kimi.md +1 -0
  76. package/docs/providers/neuralwatt.md +1 -0
  77. package/docs/providers/openai-compatible.md +2 -1
  78. package/docs/providers/openai.md +8 -1
  79. package/docs/providers/opencode-go.md +1 -0
  80. package/docs/providers/openrouter.md +1 -0
  81. package/docs/providers/zai.md +1 -0
  82. package/docs/public-contracts.md +9 -2
  83. package/docs/release-and-install.md +209 -25
  84. package/docs/resource-loading.md +14 -4
  85. package/docs/review-coverage-2026-07-14.md +260 -0
  86. package/docs/run-ledger-conformance.md +96 -0
  87. package/docs/runs-and-usage.md +2 -0
  88. package/docs/session-store-conformance.md +16 -0
  89. package/docs/session-stores-and-branching.md +1 -0
  90. package/docs/settings-auth-trust-security.md +2 -1
  91. package/docs/sqlite-persistence.md +122 -0
  92. package/docs/structured-output.md +9 -0
  93. package/docs/tool-conformance.md +1 -0
  94. package/docs/tool-execution-primitives.md +374 -0
  95. package/docs/tools.md +39 -1
  96. package/docs/workflow-orchestration-primitives.md +565 -0
  97. package/docs/workflow-tui-primitives.md +5 -0
  98. package/docs/workflows.md +219 -0
  99. package/package.json +33 -5
@@ -5,6 +5,7 @@ import type { SecretRedactor } from "./redaction.js";
5
5
  import type { PermissionPolicy } from "./security.js";
6
6
  import type { ManifestContributionDeclaration } from "./manifests.js";
7
7
  import type { ToolValidator } from "./tools.js";
8
+ import type { AudioContent, DocumentContent, FileContent } from "./content.js";
8
9
  export type JsonPrimitive = string | number | boolean | null;
9
10
  export type JsonValue = JsonPrimitive | JsonObject | JsonValue[];
10
11
  export interface JsonObject {
@@ -16,7 +17,8 @@ export interface ErrorInfo {
16
17
  readonly code?: string | number;
17
18
  readonly cause?: unknown;
18
19
  }
19
- export type ContentBlock = TextContent | ImageContent | ThinkingContent | ToolCallDeltaContent | ToolCallContent | ToolResultContent;
20
+ export type { AudioContent, DocumentContent, FileContent } from "./content.js";
21
+ export type ContentBlock = TextContent | ImageContent | AudioContent | FileContent | DocumentContent | ThinkingContent | ToolCallDeltaContent | ToolCallContent | ToolResultContent;
20
22
  export interface TextContent {
21
23
  readonly type: "text";
22
24
  readonly text: string;
@@ -26,6 +28,9 @@ export interface ImageContent {
26
28
  readonly mimeType?: string;
27
29
  readonly data?: string;
28
30
  readonly url?: string;
31
+ readonly resourceUri?: string;
32
+ readonly name?: string;
33
+ readonly metadata?: Readonly<Record<string, unknown>>;
29
34
  }
30
35
  export interface ThinkingContent {
31
36
  readonly type: "thinking";
@@ -71,11 +76,14 @@ export interface ModelConfig {
71
76
  readonly metadata?: Readonly<Record<string, unknown>>;
72
77
  }
73
78
  export interface ModelCapabilities {
79
+ /** Known values include `text`, `image`, `audio`, `file`, and `document`. */
74
80
  readonly input?: readonly string[];
75
81
  readonly output?: readonly string[];
76
82
  readonly reasoning?: boolean;
77
83
  readonly tools?: boolean;
78
84
  readonly streaming?: boolean;
85
+ /** Native JSON-schema structured output support for this model. */
86
+ readonly structuredOutput?: boolean | "json_schema";
79
87
  }
80
88
  export interface ModelLimits {
81
89
  readonly contextWindow?: number;
@@ -121,6 +129,11 @@ export interface PromptCacheHints {
121
129
  readonly retention?: CacheRetention;
122
130
  readonly breakpoints?: readonly PromptCacheBreakpoint[];
123
131
  }
132
+ export interface StructuredOutputOptions {
133
+ readonly name: string;
134
+ readonly schema: JsonObject;
135
+ readonly strict?: boolean;
136
+ }
124
137
  export interface ProviderRequestOptions {
125
138
  readonly sessionId?: string;
126
139
  readonly cacheRetention?: CacheRetention;
@@ -135,6 +148,8 @@ export interface ProviderRequestOptions {
135
148
  readonly maxRetryDelayMs?: number;
136
149
  readonly compat?: JsonObject;
137
150
  readonly extra?: JsonObject;
151
+ /** Provider-neutral JSON-schema structured output request. Requires model `capabilities.structuredOutput`. */
152
+ readonly structuredOutput?: StructuredOutputOptions;
138
153
  }
139
154
  export interface ProviderRequest {
140
155
  readonly model: ModelConfig;
@@ -304,6 +319,20 @@ export interface AgentSession {
304
319
  fork(options?: AgentSessionForkOptions): AgentSession;
305
320
  clone(options?: AgentSessionCloneOptions): Promise<AgentSession>;
306
321
  }
322
+ export interface ProviderTurnMetadata {
323
+ readonly providerId: string;
324
+ readonly model: ModelConfig;
325
+ readonly requestId?: string;
326
+ readonly latencyMs?: number;
327
+ readonly attempt?: number;
328
+ readonly httpStatus?: number;
329
+ readonly rateLimitRemaining?: number;
330
+ readonly rateLimitResetMs?: number;
331
+ }
332
+ export interface ToolExecutionMetadata {
333
+ readonly durationMs: number;
334
+ readonly status: ToolCallStatus;
335
+ }
307
336
  export type AgentEvent = {
308
337
  readonly type: "agent_started";
309
338
  readonly sessionId: string;
@@ -323,6 +352,20 @@ export type AgentEvent = {
323
352
  readonly sessionId: string;
324
353
  readonly runId: string;
325
354
  readonly turn: number;
355
+ } | {
356
+ readonly type: "provider_turn_started";
357
+ readonly sessionId: string;
358
+ readonly runId: string;
359
+ readonly turn: number;
360
+ readonly metadata: ProviderTurnMetadata;
361
+ } | {
362
+ readonly type: "provider_turn_finished";
363
+ readonly sessionId: string;
364
+ readonly runId: string;
365
+ readonly turn: number;
366
+ readonly metadata: ProviderTurnMetadata;
367
+ readonly usage?: Usage;
368
+ readonly error?: ErrorInfo;
326
369
  } | {
327
370
  readonly type: "message_started";
328
371
  readonly sessionId: string;
@@ -356,12 +399,14 @@ export type AgentEvent = {
356
399
  readonly sessionId: string;
357
400
  readonly runId: string;
358
401
  readonly result: ToolResult;
402
+ readonly metadata: ToolExecutionMetadata;
359
403
  } | {
360
404
  readonly type: "tool_execution_error";
361
405
  readonly sessionId: string;
362
406
  readonly runId: string;
363
407
  readonly call: ToolCallContent;
364
408
  readonly error: ErrorInfo;
409
+ readonly metadata: ToolExecutionMetadata;
365
410
  } | {
366
411
  readonly type: "tool_execution_blocked";
367
412
  readonly sessionId: string;
@@ -370,6 +415,7 @@ export type AgentEvent = {
370
415
  readonly name: string;
371
416
  readonly reason: string;
372
417
  readonly error: ErrorInfo;
418
+ readonly metadata: ToolExecutionMetadata;
373
419
  } | {
374
420
  readonly type: "queue_updated";
375
421
  readonly sessionId: string;
@@ -442,6 +488,8 @@ export interface ToolDefinition {
442
488
  readonly name: string;
443
489
  readonly description?: string;
444
490
  readonly parameters?: JsonObject;
491
+ /** Force any provider turn containing this tool to dispatch sequentially. */
492
+ readonly exclusive?: boolean;
445
493
  execute(args: JsonObject, context: ToolExecutionContext): Promise<ToolResult> | ToolResult;
446
494
  }
447
495
  export interface ToolRegistry {
@@ -647,6 +695,8 @@ export interface OAuthLoginCallbacks {
647
695
  readonly message: string;
648
696
  readonly choices: readonly string[];
649
697
  }): string | undefined | Promise<string | undefined>;
698
+ /** Aborts OAuth login flows and device-code polling when signaled. */
699
+ readonly signal?: AbortSignal;
650
700
  }
651
701
  export interface OAuthCredentials {
652
702
  readonly access?: string;
@@ -832,6 +882,83 @@ export interface PersistenceQuery {
832
882
  readonly limit?: number;
833
883
  readonly order?: "asc" | "desc";
834
884
  }
885
+ /** Generic versioned checkpoint key. Namespaces prevent consumer collisions. */
886
+ export interface CheckpointKey extends OwnershipScope {
887
+ readonly namespace: string;
888
+ readonly key: string;
889
+ readonly signal?: AbortSignal;
890
+ }
891
+ /** Input for an optimistic checkpoint write. Versions must strictly increase. */
892
+ export interface CheckpointSaveInput extends CheckpointKey {
893
+ readonly version: number;
894
+ /** Exact current version required before update; use 0 for create-only. */
895
+ readonly expectedVersion?: number;
896
+ /** Monotonic lease fence. Lower or absent worker fences cannot replace a fenced record. */
897
+ readonly fencingToken?: number;
898
+ readonly value: unknown;
899
+ readonly category?: string;
900
+ readonly metadata?: Readonly<Record<string, unknown>>;
901
+ }
902
+ /** Durable generic checkpoint record. */
903
+ export interface CheckpointRecord extends OwnershipScope {
904
+ readonly namespace: string;
905
+ readonly key: string;
906
+ readonly version: number;
907
+ readonly fencingToken?: number;
908
+ readonly value: unknown;
909
+ readonly category?: string;
910
+ readonly createdAt: string;
911
+ readonly updatedAt: string;
912
+ readonly metadata?: Readonly<Record<string, unknown>>;
913
+ }
914
+ /** Bounded checkpoint query. */
915
+ export interface CheckpointQuery extends PersistenceQuery, OwnershipScope {
916
+ readonly namespace?: string;
917
+ readonly keyPrefix?: string;
918
+ readonly category?: string | readonly string[];
919
+ readonly signal?: AbortSignal;
920
+ }
921
+ /** Generic versioned checkpoint capability for persistence adapters. */
922
+ export interface CheckpointStore {
923
+ saveCheckpoint(input: CheckpointSaveInput): Promise<CheckpointRecord>;
924
+ loadCheckpoint(input: CheckpointKey): Promise<CheckpointRecord | null>;
925
+ listCheckpoints(query?: CheckpointQuery): Promise<PersistencePage<CheckpointRecord>>;
926
+ deleteCheckpoint(input: CheckpointKey): Promise<boolean>;
927
+ }
928
+ /** Generic lease key. Ownership fields are part of the trust boundary. */
929
+ export interface LeaseKey extends OwnershipScope {
930
+ readonly namespace: string;
931
+ readonly key: string;
932
+ readonly signal?: AbortSignal;
933
+ }
934
+ export interface LeaseAcquireInput extends LeaseKey {
935
+ readonly ownerId: string;
936
+ readonly ttlMs: number;
937
+ }
938
+ export interface LeaseClaimInput extends LeaseKey {
939
+ readonly ownerId: string;
940
+ readonly token: string;
941
+ readonly ttlMs?: number;
942
+ }
943
+ export interface LeaseRecord extends OwnershipScope {
944
+ readonly namespace: string;
945
+ readonly key: string;
946
+ readonly ownerId: string;
947
+ readonly token: string;
948
+ readonly fencingToken: number;
949
+ readonly acquiredAt: string;
950
+ readonly expiresAt: string;
951
+ readonly updatedAt: string;
952
+ }
953
+ /** Atomic distributed lease capability. Expired rows retain fencing counters. */
954
+ export interface LeaseStore {
955
+ tryAcquireLease(input: LeaseAcquireInput): Promise<LeaseRecord | null>;
956
+ renewLease(input: LeaseClaimInput & {
957
+ readonly ttlMs: number;
958
+ }): Promise<LeaseRecord | null>;
959
+ releaseLease(input: LeaseClaimInput): Promise<boolean>;
960
+ getLease(input: LeaseKey): Promise<LeaseRecord | null>;
961
+ }
835
962
  /** Stored session record. Does not include provider objects or credentials. */
836
963
  export interface SessionRecord extends OwnershipScope {
837
964
  readonly id: string;
@@ -1058,11 +1185,15 @@ export interface MigrationQuery extends PersistenceQuery {
1058
1185
  * Production database-neutral persistence store contract.
1059
1186
  * Hosts implement this interface to provide durable, paginated storage
1060
1187
  * for sessions, entries, runs, events, tool calls, usage, agent definitions,
1061
- * and migrations. No SQL client, ORM, host file storage, or network dependency is
1188
+ * and migrations, with optional generic checkpoint and atomic lease capabilities. No SQL client, ORM, host file storage, or network dependency is
1062
1189
  * required by the contract.
1063
1190
  */
1064
1191
  export interface ProductionPersistenceStore {
1065
1192
  readonly name?: string;
1193
+ /** Optional generic write capability for resumable consumers such as workflows. */
1194
+ readonly checkpoints?: CheckpointStore;
1195
+ /** Optional atomic distributed lease capability for coordinators and workers. */
1196
+ readonly leases?: LeaseStore;
1066
1197
  querySessions(query: SessionQuery): Promise<PersistencePage<SessionRecord>>;
1067
1198
  queryBranches(query: BranchQuery): Promise<PersistencePage<BranchRecord>>;
1068
1199
  queryEntries(query: SessionEntryQuery): Promise<PersistencePage<SessionEntry>>;
@@ -1201,9 +1332,12 @@ export interface LoopContext {
1201
1332
  readonly input: AgentInput;
1202
1333
  readonly inputMessages: readonly Message[];
1203
1334
  readonly maxToolRounds: number;
1335
+ /** Maximum independent tool calls dispatched concurrently per provider turn. Default `1`. */
1336
+ readonly toolConcurrency: number;
1204
1337
  assemble(nextInput: AgentInput, toolResults?: readonly ToolResult[], turn?: number): Promise<ProviderRequest>;
1205
1338
  generate(request: ProviderRequest): Promise<ProviderTurnResult>;
1206
1339
  dispatchToolCall(call: ToolCallContent): Promise<ToolResult>;
1340
+ isToolCallExclusive?(call: ToolCallContent): boolean;
1207
1341
  appendMessage(message: Message): Promise<void>;
1208
1342
  emit(event: AgentEvent): void;
1209
1343
  }
@@ -1213,12 +1347,18 @@ export interface AgentLoopStrategy {
1213
1347
  }
1214
1348
  export type AgentLoopOptions = {
1215
1349
  readonly strategy: "single-shot";
1350
+ /** Independent tool calls per turn run concurrently up to this limit. Default `1` (sequential). */
1351
+ readonly toolConcurrency?: number;
1216
1352
  } | {
1217
1353
  readonly strategy: "generate-validate-revise";
1218
1354
  readonly validator: ArtifactValidator<unknown>;
1219
1355
  readonly parser?: ArtifactParser<unknown>;
1220
1356
  readonly repairer?: ArtifactRepairer<unknown>;
1221
1357
  readonly maxRevisions?: number;
1358
+ /** Native provider JSON-schema output. Ignored when `structuredOutputMode` is `artifact-loop`. */
1359
+ readonly structuredOutput?: StructuredOutputOptions;
1360
+ /** `native` maps schema to capable providers; `artifact-loop` keeps repair turns only. */
1361
+ readonly structuredOutputMode?: "native" | "artifact-loop";
1222
1362
  };
1223
1363
  export interface ArtifactValidation {
1224
1364
  readonly ok: boolean;
@@ -0,0 +1,23 @@
1
+ export type EventOverflowPolicy = "close" | "drop_oldest" | "drop_newest";
2
+ export interface EventOverflowInfo {
3
+ readonly droppedEvents: number;
4
+ readonly maxQueuedEvents: number;
5
+ readonly policy: EventOverflowPolicy;
6
+ }
7
+ export interface EventMultiplexerOptions<T> {
8
+ readonly maxQueuedEvents?: number;
9
+ readonly overflow?: EventOverflowPolicy;
10
+ readonly overflowEvent?: (info: EventOverflowInfo) => T;
11
+ readonly compare?: (a: T, b: T) => number;
12
+ readonly signal?: AbortSignal;
13
+ }
14
+ export interface EventMultiplexer<T> {
15
+ publish(event: T): void;
16
+ observe<S>(source: AsyncIterable<S>, map: (event: S) => T): () => void;
17
+ subscribe(): AsyncIterable<T>;
18
+ close(): void;
19
+ readonly droppedEvents: number;
20
+ readonly closed: boolean;
21
+ }
22
+ /** Bounded single-consumer fan-in for arbitrary async event sources. */
23
+ export declare function createEventMultiplexer<T>(options?: EventMultiplexerOptions<T>): EventMultiplexer<T>;
@@ -0,0 +1,136 @@
1
+ /** Bounded single-consumer fan-in for arbitrary async event sources. */
2
+ export function createEventMultiplexer(options = {}) {
3
+ const maxQueuedEvents = Math.max(1, options.maxQueuedEvents ?? 1024);
4
+ const overflow = options.overflow ?? "close";
5
+ const queue = [];
6
+ const stops = new Set();
7
+ let waiter;
8
+ let isClosed = false;
9
+ let droppedEvents = 0;
10
+ let overflowNotified = false;
11
+ const abort = () => close();
12
+ if (options.signal?.aborted)
13
+ isClosed = true;
14
+ else
15
+ options.signal?.addEventListener("abort", abort, { once: true });
16
+ function publish(event) {
17
+ if (isClosed)
18
+ return;
19
+ if (waiter) {
20
+ const resolve = waiter;
21
+ waiter = undefined;
22
+ resolve({ value: event, done: false });
23
+ return;
24
+ }
25
+ if (queue.length < maxQueuedEvents) {
26
+ queue.push(event);
27
+ return;
28
+ }
29
+ droppedEvents += 1;
30
+ const notice = !overflowNotified && options.overflowEvent
31
+ ? options.overflowEvent({ droppedEvents, maxQueuedEvents, policy: overflow })
32
+ : undefined;
33
+ overflowNotified = true;
34
+ if (overflow === "close") {
35
+ queue.length = 0;
36
+ if (notice !== undefined)
37
+ queue.push(notice);
38
+ options.signal?.removeEventListener("abort", abort);
39
+ finishSources();
40
+ isClosed = true;
41
+ return;
42
+ }
43
+ if (overflow === "drop_newest") {
44
+ if (notice !== undefined)
45
+ queue[queue.length - 1] = notice;
46
+ return;
47
+ }
48
+ queue.shift();
49
+ if (notice !== undefined) {
50
+ queue.push(notice);
51
+ if (queue.length >= maxQueuedEvents)
52
+ queue.shift();
53
+ }
54
+ queue.push(event);
55
+ }
56
+ function observe(source, map) {
57
+ if (isClosed)
58
+ return () => undefined;
59
+ const iterator = source[Symbol.asyncIterator]();
60
+ let stopped = false;
61
+ const stop = () => {
62
+ if (stopped)
63
+ return;
64
+ stopped = true;
65
+ stops.delete(stop);
66
+ void iterator.return?.();
67
+ };
68
+ stops.add(stop);
69
+ void (async () => {
70
+ try {
71
+ while (!stopped && !isClosed) {
72
+ const next = await iterator.next();
73
+ if (next.done)
74
+ break;
75
+ publish(map(next.value));
76
+ }
77
+ }
78
+ catch {
79
+ // Source failure ends that source; owners surface source errors separately.
80
+ }
81
+ finally {
82
+ stop();
83
+ }
84
+ })();
85
+ return stop;
86
+ }
87
+ function finishSources() {
88
+ for (const stop of [...stops])
89
+ stop();
90
+ stops.clear();
91
+ }
92
+ function close() {
93
+ if (isClosed)
94
+ return;
95
+ isClosed = true;
96
+ options.signal?.removeEventListener("abort", abort);
97
+ finishSources();
98
+ queue.length = 0;
99
+ if (waiter) {
100
+ const resolve = waiter;
101
+ waiter = undefined;
102
+ resolve({ value: undefined, done: true });
103
+ }
104
+ }
105
+ async function* subscribe() {
106
+ while (true) {
107
+ if (queue.length > 0) {
108
+ if (options.compare)
109
+ queue.sort(options.compare);
110
+ yield queue.shift();
111
+ continue;
112
+ }
113
+ if (isClosed)
114
+ return;
115
+ const next = await new Promise((resolve) => {
116
+ waiter = resolve;
117
+ });
118
+ if (next.done)
119
+ return;
120
+ yield next.value;
121
+ }
122
+ }
123
+ return {
124
+ publish,
125
+ observe,
126
+ subscribe,
127
+ close,
128
+ get droppedEvents() {
129
+ return droppedEvents;
130
+ },
131
+ get closed() {
132
+ return isClosed;
133
+ },
134
+ };
135
+ }
136
+ //# sourceMappingURL=event-multiplexer.js.map
@@ -0,0 +1,28 @@
1
+ export type ExecutionRisk = "low" | "medium" | "high";
2
+ export interface ExecutionAction {
3
+ readonly kind: "shell" | "read" | "write" | "edit" | string;
4
+ readonly operation: string;
5
+ readonly paths?: readonly string[];
6
+ readonly command?: string;
7
+ readonly risk?: ExecutionRisk;
8
+ readonly metadata?: Readonly<Record<string, unknown>>;
9
+ }
10
+ export interface ExecutionDecision {
11
+ readonly allowed: boolean;
12
+ readonly reason?: string;
13
+ readonly modified?: Partial<ExecutionAction>;
14
+ /** When true, tool definitions should expose `exclusive: true` for pre-dispatch serialization. */
15
+ readonly exclusive?: boolean;
16
+ }
17
+ export interface ExecutionPolicy {
18
+ check(action: ExecutionAction): ExecutionDecision | Promise<ExecutionDecision>;
19
+ }
20
+ export declare class ExecutionDeniedError extends Error {
21
+ readonly action: ExecutionAction;
22
+ readonly decision: ExecutionDecision;
23
+ readonly code = "ERR_PRISM_EXECUTION_DENIED";
24
+ constructor(action: ExecutionAction, decision: ExecutionDecision);
25
+ }
26
+ export declare function checkExecution(policy: ExecutionPolicy | undefined, action: ExecutionAction): Promise<ExecutionDecision>;
27
+ export declare function applyExecutionDecision(action: ExecutionAction, decision: ExecutionDecision): ExecutionAction;
28
+ export declare function assertExecutionAllowed(policy: ExecutionPolicy | undefined, action: ExecutionAction): Promise<ExecutionAction>;
@@ -0,0 +1,24 @@
1
+ export class ExecutionDeniedError extends Error {
2
+ action;
3
+ decision;
4
+ code = "ERR_PRISM_EXECUTION_DENIED";
5
+ constructor(action, decision) {
6
+ super(decision.reason ?? `Execution denied for ${action.kind}:${action.operation}`);
7
+ this.action = action;
8
+ this.decision = decision;
9
+ this.name = "ExecutionDeniedError";
10
+ }
11
+ }
12
+ export async function checkExecution(policy, action) {
13
+ return policy ? await policy.check(action) : { allowed: true };
14
+ }
15
+ export function applyExecutionDecision(action, decision) {
16
+ return decision.modified ? { ...action, ...decision.modified } : action;
17
+ }
18
+ export async function assertExecutionAllowed(policy, action) {
19
+ const decision = await checkExecution(policy, action);
20
+ if (!decision.allowed)
21
+ throw new ExecutionDeniedError(action, decision);
22
+ return applyExecutionDecision(action, decision);
23
+ }
24
+ //# sourceMappingURL=execution-policy.js.map
package/dist/index.d.ts CHANGED
@@ -1,6 +1,11 @@
1
1
  export type * from "./contracts.js";
2
2
  export { isSessionEntryKind, SESSION_APPEND_CONFLICT_CODE, SESSION_ENTRY_KINDS, SESSION_ENTRY_SCHEMA_VERSION, SessionAppendConflictError, isSessionAppendConflict } from "./contracts.js";
3
3
  export { createAgent, createAgentSession } from "./agents.js";
4
+ export { CHECKPOINT_CONFLICT_CODE, CheckpointConflictError, createMemoryCheckpointStore } from "./checkpoints.js";
5
+ export type { MemoryCheckpointStoreOptions } from "./checkpoints.js";
6
+ export { LEASE_CONFLICT_CODE, LeaseConflictError, createMemoryLeaseStore } from "./leases.js";
7
+ export { createEventMultiplexer } from "./event-multiplexer.js";
8
+ export type { EventMultiplexer, EventMultiplexerOptions, EventOverflowInfo, EventOverflowPolicy } from "./event-multiplexer.js";
4
9
  export { applyCacheControl, cacheHitRate, cacheSavings, cacheUsageReport, mapCacheRetention, sanitizeCacheKey } from "./cache-helpers.js";
5
10
  export type { ApplyCacheControlOptions, CacheControlledContentBlock, CacheControlledMessage, CacheControlValue, CacheUsageReport } from "./cache-helpers.js";
6
11
  export { resolveAgentDefinition } from "./agent-definitions.js";
@@ -19,6 +24,8 @@ export type { ExtensionErrorPolicy, ExtensionEventBus, ExtensionEventHandler, Ex
19
24
  export type { CredentialRecord, CredentialValueSource, MemoryCredentialStore } from "./credentials.js";
20
25
  export { createModelRegistry } from "./models.js";
21
26
  export { authMethodKey, defineProviderPackage, systemPromptContributionKey } from "./provider-packages.js";
27
+ export { assertStructuredOutputRequestSupported, DEFAULT_MAX_STRUCTURED_OUTPUT_NAME_LENGTH, DEFAULT_MAX_STRUCTURED_OUTPUT_SCHEMA_BYTES, modelSupportsStructuredOutput, resolveRunProviderOptions, StructuredOutputError, validateStructuredOutputOptions, } from "./structured-output.js";
28
+ export { createProviderTurnMetadata, readProviderHttpStatus } from "./observability.js";
22
29
  export { createProviderRequestPolicyChain, createSessionCachePolicy, mergeProviderRequestOptions } from "./provider-request-policy.js";
23
30
  export type { SessionCachePolicyOptions } from "./provider-request-policy.js";
24
31
  export { composeSystemPrompt, mergeSystemPromptConfig } from "./system-prompts.js";
@@ -26,7 +33,10 @@ export type { ComposeSystemPromptOptions } from "./system-prompts.js";
26
33
  export type { ModelRegistry, ModelRegistryOptions } from "./models.js";
27
34
  export { definePrismManifest, parsePrismManifest } from "./manifests.js";
28
35
  export type { ManifestContributionDeclaration, ManifestContributionKind, ManifestResourceDeclaration, PrismManifest } from "./manifests.js";
29
- export { loadJsonResource, loadManifestResource, loadTextResource } from "./resources.js";
36
+ export { assertDeclaredMediaTypeMatches, assertMediaBlocksWithinBounds, assertMessagesSupportModelCapabilities, assertModelSupportsContentBlocks, assertSsrfAllowedUrl, collectMessageContentBlocks, contentBlockInputModality, DEFAULT_MAX_AUDIO_DURATION_MS, DEFAULT_MAX_MEDIA_ITEM_BYTES, DEFAULT_MAX_MEDIA_ITEMS_PER_REQUEST, DEFAULT_MAX_MEDIA_REQUEST_BYTES, DEFAULT_MEDIA_FETCH_TIMEOUT_MS, loadBoundedBinaryResource, MediaContentError, MODEL_INPUT_CAPABILITIES, resolveMediaContentBlock, sniffMediaMimeType, UnsupportedModalityError, } from "./content.js";
37
+ export type { AudioContent, DocumentContent, FileContent, MediaContentBlock, MediaContentBounds, MediaMimePolicy, ModelInputCapability, ResolvedMediaContent, ResolveMediaContentOptions, SsrfPolicy, } from "./content.js";
38
+ export { loadBinaryResource, loadJsonResource, loadManifestResource, loadTextResource } from "./resources.js";
39
+ export type { LoadBinaryResourceOptions } from "./resources.js";
30
40
  export { createChainedSettingsProvider, createStaticSettingsProvider } from "./settings.js";
31
41
  export { createMiddlewareRegistry } from "./middleware.js";
32
42
  export type { Middleware, MiddlewareHookName, MiddlewareNext, MiddlewareRegistry, MiddlewareRegistryOptions } from "./middleware.js";
@@ -44,14 +54,16 @@ export { createSecretRedactor, errorToErrorInfo, redactAgentEvent, redactMessage
44
54
  export type { SecretRedactor } from "./redaction.js";
45
55
  export { assertPermission, assertTrusted, checkPermission, createStaticPermissionPolicy, createStaticTrustPolicy, denialToErrorInfo, isTrusted, PermissionDeniedError, TrustDeniedError } from "./security.js";
46
56
  export type { PermissionDecision, PermissionPolicy, PermissionRequest, TrustDecision, TrustPolicy, TrustRequest } from "./security.js";
57
+ export { applyExecutionDecision, assertExecutionAllowed, checkExecution, ExecutionDeniedError } from "./execution-policy.js";
58
+ export type { ExecutionAction, ExecutionDecision, ExecutionPolicy, ExecutionRisk } from "./execution-policy.js";
47
59
  export { createSkillRegistry, resolveActiveSkills } from "./skills.js";
48
60
  export type { ResolveActiveSkillsOptions, SkillRegistryOptions } from "./skills.js";
49
61
  export { resolveInstructionInjectors, runInstructionInjectors } from "./instruction-injection.js";
50
62
  export type { ResolveInstructionInjectorsOptions } from "./instruction-injection.js";
51
- export { createToolRegistry, dispatchToolCall, filterTools } from "./tools.js";
52
- export type { DispatchToolCallOptions, ToolFilter, ToolFilterInput, ToolRegistryOptions, ToolValidator } from "./tools.js";
63
+ export { createToolRegistry, dispatchToolCall, filterTools, createToolParameterValidator } from "./tools.js";
64
+ export type { DispatchToolCallOptions, ToolArgumentValidationError, ToolArgumentValidationResult, ToolArgumentValidator, ToolFilter, ToolFilterInput, ToolParameterValidatorOptions, ToolRegistryOptions, ToolValidator, } from "./tools.js";
53
65
  export type { DuplicateRegistrationOptions, DuplicateRegistrationPolicy } from "./registry-options.js";
54
- export { generateValidateReviseLoop, isAgentLoopOptions, resolveLoop, singleShotLoop } from "./agent-loops.js";
66
+ export { dispatchToolCallsInOrder, generateValidateReviseLoop, isAgentLoopOptions, resolveLoop, resolveToolConcurrency, singleShotLoop } from "./agent-loops.js";
55
67
  export declare const name = "prism";
56
- export declare const version = "0.0.3";
68
+ export declare const version = "0.0.4";
57
69
  export declare const description = "Agent harness for AI providers, agents, sessions, and tools.";
package/dist/index.js CHANGED
@@ -1,5 +1,8 @@
1
1
  export { isSessionEntryKind, SESSION_APPEND_CONFLICT_CODE, SESSION_ENTRY_KINDS, SESSION_ENTRY_SCHEMA_VERSION, SessionAppendConflictError, isSessionAppendConflict } from "./contracts.js";
2
2
  export { createAgent, createAgentSession } from "./agents.js";
3
+ export { CHECKPOINT_CONFLICT_CODE, CheckpointConflictError, createMemoryCheckpointStore } from "./checkpoints.js";
4
+ export { LEASE_CONFLICT_CODE, LeaseConflictError, createMemoryLeaseStore } from "./leases.js";
5
+ export { createEventMultiplexer } from "./event-multiplexer.js";
3
6
  export { applyCacheControl, cacheHitRate, cacheSavings, cacheUsageReport, mapCacheRetention, sanitizeCacheKey } from "./cache-helpers.js";
4
7
  export { resolveAgentDefinition } from "./agent-definitions.js";
5
8
  export { parseSkillFile, parseAgentFile } from "./contribution-parsing.js";
@@ -11,10 +14,13 @@ export { createChainedCredentialResolver, createEnvCredentialResolver, createExp
11
14
  export { createExtensionEventBus, createExtensionKernel } from "./extensions.js";
12
15
  export { createModelRegistry } from "./models.js";
13
16
  export { authMethodKey, defineProviderPackage, systemPromptContributionKey } from "./provider-packages.js";
17
+ export { assertStructuredOutputRequestSupported, DEFAULT_MAX_STRUCTURED_OUTPUT_NAME_LENGTH, DEFAULT_MAX_STRUCTURED_OUTPUT_SCHEMA_BYTES, modelSupportsStructuredOutput, resolveRunProviderOptions, StructuredOutputError, validateStructuredOutputOptions, } from "./structured-output.js";
18
+ export { createProviderTurnMetadata, readProviderHttpStatus } from "./observability.js";
14
19
  export { createProviderRequestPolicyChain, createSessionCachePolicy, mergeProviderRequestOptions } from "./provider-request-policy.js";
15
20
  export { composeSystemPrompt, mergeSystemPromptConfig } from "./system-prompts.js";
16
21
  export { definePrismManifest, parsePrismManifest } from "./manifests.js";
17
- export { loadJsonResource, loadManifestResource, loadTextResource } from "./resources.js";
22
+ export { assertDeclaredMediaTypeMatches, assertMediaBlocksWithinBounds, assertMessagesSupportModelCapabilities, assertModelSupportsContentBlocks, assertSsrfAllowedUrl, collectMessageContentBlocks, contentBlockInputModality, DEFAULT_MAX_AUDIO_DURATION_MS, DEFAULT_MAX_MEDIA_ITEM_BYTES, DEFAULT_MAX_MEDIA_ITEMS_PER_REQUEST, DEFAULT_MAX_MEDIA_REQUEST_BYTES, DEFAULT_MEDIA_FETCH_TIMEOUT_MS, loadBoundedBinaryResource, MediaContentError, MODEL_INPUT_CAPABILITIES, resolveMediaContentBlock, sniffMediaMimeType, UnsupportedModalityError, } from "./content.js";
23
+ export { loadBinaryResource, loadJsonResource, loadManifestResource, loadTextResource } from "./resources.js";
18
24
  export { createChainedSettingsProvider, createStaticSettingsProvider } from "./settings.js";
19
25
  export { createMiddlewareRegistry } from "./middleware.js";
20
26
  export { assembleProviderInput, createDefaultInputBuilder, createDefaultPromptBuilder, renderPromptTemplate, resolveContextProviders } from "./input.js";
@@ -24,11 +30,12 @@ export { providerContentDelta, providerDone, providerError, providerTextDelta, p
24
30
  export { createProviderRegistry, createProviderResolver } from "./providers.js";
25
31
  export { createSecretRedactor, errorToErrorInfo, redactAgentEvent, redactMessage, redactProviderRequest, redactRunLedgerRecord, redactSecrets, redactSessionEntry } from "./redaction.js";
26
32
  export { assertPermission, assertTrusted, checkPermission, createStaticPermissionPolicy, createStaticTrustPolicy, denialToErrorInfo, isTrusted, PermissionDeniedError, TrustDeniedError } from "./security.js";
33
+ export { applyExecutionDecision, assertExecutionAllowed, checkExecution, ExecutionDeniedError } from "./execution-policy.js";
27
34
  export { createSkillRegistry, resolveActiveSkills } from "./skills.js";
28
35
  export { resolveInstructionInjectors, runInstructionInjectors } from "./instruction-injection.js";
29
- export { createToolRegistry, dispatchToolCall, filterTools } from "./tools.js";
30
- export { generateValidateReviseLoop, isAgentLoopOptions, resolveLoop, singleShotLoop } from "./agent-loops.js";
36
+ export { createToolRegistry, dispatchToolCall, filterTools, createToolParameterValidator } from "./tools.js";
37
+ export { dispatchToolCallsInOrder, generateValidateReviseLoop, isAgentLoopOptions, resolveLoop, resolveToolConcurrency, singleShotLoop } from "./agent-loops.js";
31
38
  export const name = "prism";
32
- export const version = "0.0.3";
39
+ export const version = "0.0.4";
33
40
  export const description = "Agent harness for AI providers, agents, sessions, and tools.";
34
41
  //# sourceMappingURL=index.js.map
package/dist/input.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { redactMessage } from "./redaction.js";
2
+ import { assertMessagesSupportModelCapabilities } from "./content.js";
2
3
  import { loadTextResource } from "./resources.js";
3
4
  import { composeSystemPrompt } from "./system-prompts.js";
4
5
  import { runInstructionInjectors } from "./instruction-injection.js";
@@ -118,6 +119,7 @@ export async function assembleProviderInput(options) {
118
119
  signal: options.signal,
119
120
  };
120
121
  const providerMessages = await promptBuilder.build({ ...promptRequest, tools: options.tools });
122
+ assertMessagesSupportModelCapabilities(options.model, providerMessages);
121
123
  return {
122
124
  model: options.model,
123
125
  messages: providerMessages,
@@ -232,7 +234,15 @@ function blockText(block) {
232
234
  return `${part.name}(${JSON.stringify(part.arguments)})`;
233
235
  if (part.type === "tool_call_delta")
234
236
  return `${part.name ?? "tool"}(${part.argumentsText ?? ""})`;
235
- return part.url ?? part.mimeType ?? "[image]";
237
+ if (part.type === "image")
238
+ return part.url ?? part.resourceUri ?? part.mimeType ?? "[image]";
239
+ if (part.type === "audio")
240
+ return part.transcript ?? part.name ?? part.url ?? part.resourceUri ?? part.mediaType ?? "[audio]";
241
+ if (part.type === "file")
242
+ return part.name ?? part.url ?? part.resourceUri ?? part.mediaType ?? "[file]";
243
+ if (part.type === "document")
244
+ return part.transcript ?? part.name ?? part.url ?? part.resourceUri ?? part.mediaType ?? "[document]";
245
+ return "[content]";
236
246
  }).join("\n");
237
247
  }
238
248
  function templateValue(value) {
@@ -0,0 +1,8 @@
1
+ import type { LeaseStore } from "./contracts.js";
2
+ export declare const LEASE_CONFLICT_CODE = "ERR_PRISM_LEASE_CONFLICT";
3
+ export declare class LeaseConflictError extends Error {
4
+ readonly code = "ERR_PRISM_LEASE_CONFLICT";
5
+ constructor(message: string);
6
+ }
7
+ /** In-process reference implementation. Durable adapters provide cross-process exclusion. */
8
+ export declare function createMemoryLeaseStore(): LeaseStore;