@arnilo/prism 0.0.3 → 0.0.5

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 (131) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/README.md +62 -26
  3. package/dist/agent-loops.d.ts +8 -1
  4. package/dist/agent-loops.js +57 -11
  5. package/dist/agents.js +212 -32
  6. package/dist/checkpoints.d.ts +11 -0
  7. package/dist/checkpoints.js +144 -0
  8. package/dist/cli-init.d.ts +41 -0
  9. package/dist/cli-init.js +390 -0
  10. package/dist/cli-runner.d.ts +7 -1
  11. package/dist/cli-runner.js +13 -1
  12. package/dist/compaction.js +9 -1
  13. package/dist/content.d.ts +121 -0
  14. package/dist/content.js +538 -0
  15. package/dist/contracts.d.ts +236 -11
  16. package/dist/contracts.js +8 -0
  17. package/dist/event-multiplexer.d.ts +23 -0
  18. package/dist/event-multiplexer.js +136 -0
  19. package/dist/execution-policy.d.ts +28 -0
  20. package/dist/execution-policy.js +24 -0
  21. package/dist/feedback.d.ts +48 -0
  22. package/dist/feedback.js +230 -0
  23. package/dist/index.d.ts +20 -6
  24. package/dist/index.js +13 -5
  25. package/dist/input.js +11 -1
  26. package/dist/leases.d.ts +8 -0
  27. package/dist/leases.js +111 -0
  28. package/dist/node/agent-definitions.js +3 -5
  29. package/dist/node/config.d.ts +1 -0
  30. package/dist/node/config.js +5 -3
  31. package/dist/node/contribution-discovery.js +5 -8
  32. package/dist/node/session-store-jsonl.js +8 -5
  33. package/dist/node/settings.js +2 -2
  34. package/dist/node/trust.js +2 -4
  35. package/dist/observability.d.ts +3 -0
  36. package/dist/observability.js +18 -0
  37. package/dist/providers/media.d.ts +44 -0
  38. package/dist/providers/media.js +126 -0
  39. package/dist/providers/openai-compatible.js +18 -119
  40. package/dist/providers/openai-primitives.d.ts +9 -0
  41. package/dist/providers/openai-primitives.js +129 -0
  42. package/dist/providers/transport.d.ts +40 -0
  43. package/dist/providers/transport.js +221 -0
  44. package/dist/redaction.js +40 -13
  45. package/dist/resources.d.ts +5 -0
  46. package/dist/resources.js +4 -0
  47. package/dist/structured-output.d.ts +11 -0
  48. package/dist/structured-output.js +59 -0
  49. package/dist/testing/feedback.d.ts +6 -0
  50. package/dist/testing/feedback.js +37 -0
  51. package/dist/testing/persistence-schema.d.ts +102 -0
  52. package/dist/testing/persistence-schema.js +487 -0
  53. package/dist/testing/provider-conformance.js +10 -1
  54. package/dist/testing/run-ledger-conformance.d.ts +33 -0
  55. package/dist/testing/run-ledger-conformance.js +178 -0
  56. package/dist/testing/session-store-conformance.d.ts +16 -0
  57. package/dist/testing/session-store-conformance.js +73 -0
  58. package/dist/tools.d.ts +17 -0
  59. package/dist/tools.js +29 -2
  60. package/docs/a2a.md +73 -0
  61. package/docs/agent-events.md +17 -10
  62. package/docs/agent-loops.md +11 -5
  63. package/docs/agent-session-runtime.md +15 -16
  64. package/docs/cli-rpc.md +36 -5
  65. package/docs/coding-agent-tools.md +43 -9
  66. package/docs/coding-security.md +88 -0
  67. package/docs/compaction-observational-memory.md +2 -0
  68. package/docs/context-and-skills.md +1 -0
  69. package/docs/credential-storage.md +177 -0
  70. package/docs/credentials-and-redaction.md +4 -3
  71. package/docs/database-persistence.md +52 -7
  72. package/docs/evaluations.md +122 -0
  73. package/docs/extensions.md +2 -2
  74. package/docs/host-security.md +33 -2
  75. package/docs/index.md +46 -18
  76. package/docs/input-and-prompt-assembly.md +6 -5
  77. package/docs/mcp-tools.md +184 -0
  78. package/docs/middleware-hooks.md +2 -0
  79. package/docs/migration.md +51 -28
  80. package/docs/model-registry.md +5 -3
  81. package/docs/multimodal-content.md +156 -0
  82. package/docs/observability.md +171 -0
  83. package/docs/performance.md +249 -1
  84. package/docs/persistence-credentials-multimodality-primitives.md +303 -0
  85. package/docs/postgres-persistence.md +143 -0
  86. package/docs/provider-conformance.md +18 -0
  87. package/docs/provider-layer.md +1 -1
  88. package/docs/provider-packages.md +2 -0
  89. package/docs/provider-primitives.md +281 -0
  90. package/docs/providers/ai-sdk.md +113 -0
  91. package/docs/providers/kimi.md +1 -0
  92. package/docs/providers/neuralwatt.md +1 -0
  93. package/docs/providers/openai-compatible.md +2 -1
  94. package/docs/providers/openai.md +8 -1
  95. package/docs/providers/opencode-go.md +1 -0
  96. package/docs/providers/openrouter.md +1 -0
  97. package/docs/providers/zai.md +1 -0
  98. package/docs/public-contracts.md +13 -5
  99. package/docs/rag.md +113 -0
  100. package/docs/release-and-install.md +237 -30
  101. package/docs/resource-loading.md +14 -4
  102. package/docs/review-coverage-2026-07-14.md +260 -0
  103. package/docs/review-coverage-2026-07-15.md +193 -0
  104. package/docs/run-ledger-conformance.md +96 -0
  105. package/docs/runs-and-usage.md +43 -4
  106. package/docs/server.md +139 -0
  107. package/docs/session-store-conformance.md +16 -0
  108. package/docs/session-stores-and-branching.md +1 -0
  109. package/docs/settings-auth-trust-security.md +6 -5
  110. package/docs/sqlite-persistence.md +123 -0
  111. package/docs/structured-output.md +9 -0
  112. package/docs/supervisors.md +71 -0
  113. package/docs/tool-conformance.md +1 -0
  114. package/docs/tool-execution-primitives.md +374 -0
  115. package/docs/tools.md +39 -1
  116. package/docs/workflow-orchestration-primitives.md +581 -0
  117. package/docs/workflow-tui-primitives.md +5 -0
  118. package/docs/workflows.md +293 -0
  119. package/docs/working-and-semantic-memory.md +169 -0
  120. package/package.json +43 -5
  121. package/templates/init/README.md.tmpl +28 -0
  122. package/templates/init/env.example.tmpl +1 -0
  123. package/templates/init/gitignore.tmpl +11 -0
  124. package/templates/init/optional/evals-example.ts.tmpl +17 -0
  125. package/templates/init/optional/workflows-example.ts.tmpl +27 -0
  126. package/templates/init/package.json.tmpl +22 -0
  127. package/templates/init/providers.json +76 -0
  128. package/templates/init/src/agent.ts.tmpl +10 -0
  129. package/templates/init/src/index.ts.tmpl +12 -0
  130. package/templates/init/src/tests/agent.test.ts.tmpl +24 -0
  131. package/templates/init/tsconfig.json.tmpl +15 -0
@@ -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;
@@ -241,13 +256,7 @@ export interface AgentConfig {
241
256
  readonly promptBuilder?: PromptBuilder;
242
257
  readonly middleware?: MiddlewareRegistry;
243
258
  readonly resourceLoader?: ResourceLoader;
244
- /** Host-owned metadata only: createAgent/session.run do not load or run these extensions. */
245
- readonly extensions?: readonly Extension[];
246
259
  readonly store?: SessionStore;
247
- /** Host-owned metadata only: createAgent/session.run do not read settings. */
248
- readonly settings?: SettingsProvider;
249
- /** Host-owned metadata only: createAgent/session.run do not resolve credentials. Pass resolvers to provider edges explicitly. */
250
- readonly credentials?: CredentialResolver;
251
260
  readonly permission?: PermissionPolicy;
252
261
  readonly providerOptions?: ProviderRequestOptions;
253
262
  readonly providerRequestPolicies?: ProviderRequestPolicy | readonly ProviderRequestPolicy[];
@@ -289,13 +298,42 @@ export interface SubscribeOptions {
289
298
  /** What to do when `maxQueuedEvents` is reached. Defaults to `close`. */
290
299
  readonly overflow?: SubscriberOverflowPolicy;
291
300
  }
301
+ export type AgentRunStatus = "succeeded" | "failed" | "aborted";
302
+ /** Terminal result of `session.run()` / `session.prompt()`. Failed and aborted runs throw {@link AgentRunError} with this shape attached. */
303
+ export interface AgentRunResult {
304
+ readonly sessionId: string;
305
+ readonly runId: string;
306
+ readonly status: AgentRunStatus;
307
+ /** Branch leaf after the run settles. */
308
+ readonly leafId?: string;
309
+ /** Concatenated text blocks from the final assistant message, or `""` when none. */
310
+ readonly text: string;
311
+ /** Content blocks from the final assistant message, or `[]` when none. */
312
+ readonly content: readonly ContentBlock[];
313
+ /** Final assistant message when the run produced one. */
314
+ readonly message?: Message;
315
+ /** Aggregate usage across provider turns (`run_total` scope). */
316
+ readonly usage?: Usage;
317
+ /** Present when `status` is `"failed"` or when a failed attempt still produced partial output. */
318
+ readonly error?: ErrorInfo;
319
+ /** String form of the abort reason when `status` is `"aborted"`. */
320
+ readonly abortReason?: string;
321
+ }
322
+ export declare class AgentRunError extends Error {
323
+ readonly result: AgentRunResult;
324
+ constructor(result: AgentRunResult, options?: {
325
+ readonly cause?: unknown;
326
+ });
327
+ }
292
328
  export interface AgentSession {
293
329
  readonly id: string;
294
330
  /** Current branch leaf entry id; advances on every append/run and is re-pointed by `checkout`.
295
331
  * Undefined until the first entry lands (a fresh session with no history). */
296
332
  readonly leafId: string | undefined;
297
- run(input: string | Message | readonly Message[], options?: RunOptions): Promise<void>;
298
- prompt(input: string, options?: RunOptions): Promise<void>;
333
+ run(input: string | Message | readonly Message[], options?: RunOptions): Promise<AgentRunResult>;
334
+ prompt(input: string, options?: RunOptions): Promise<AgentRunResult>;
335
+ /** Subscribe first, then start exactly one run and yield only that run's events until it terminates. */
336
+ stream(input: string | Message | readonly Message[], options?: RunOptions & SubscribeOptions): AsyncIterable<AgentEvent>;
299
337
  compact(options?: CompactionOptions): Promise<CompactionResult>;
300
338
  subscribe(options?: SubscribeOptions): AsyncIterable<AgentEvent>;
301
339
  abort(reason?: unknown): void;
@@ -304,6 +342,20 @@ export interface AgentSession {
304
342
  fork(options?: AgentSessionForkOptions): AgentSession;
305
343
  clone(options?: AgentSessionCloneOptions): Promise<AgentSession>;
306
344
  }
345
+ export interface ProviderTurnMetadata {
346
+ readonly providerId: string;
347
+ readonly model: ModelConfig;
348
+ readonly requestId?: string;
349
+ readonly latencyMs?: number;
350
+ readonly attempt?: number;
351
+ readonly httpStatus?: number;
352
+ readonly rateLimitRemaining?: number;
353
+ readonly rateLimitResetMs?: number;
354
+ }
355
+ export interface ToolExecutionMetadata {
356
+ readonly durationMs: number;
357
+ readonly status: ToolCallStatus;
358
+ }
307
359
  export type AgentEvent = {
308
360
  readonly type: "agent_started";
309
361
  readonly sessionId: string;
@@ -323,6 +375,20 @@ export type AgentEvent = {
323
375
  readonly sessionId: string;
324
376
  readonly runId: string;
325
377
  readonly turn: number;
378
+ } | {
379
+ readonly type: "provider_turn_started";
380
+ readonly sessionId: string;
381
+ readonly runId: string;
382
+ readonly turn: number;
383
+ readonly metadata: ProviderTurnMetadata;
384
+ } | {
385
+ readonly type: "provider_turn_finished";
386
+ readonly sessionId: string;
387
+ readonly runId: string;
388
+ readonly turn: number;
389
+ readonly metadata: ProviderTurnMetadata;
390
+ readonly usage?: Usage;
391
+ readonly error?: ErrorInfo;
326
392
  } | {
327
393
  readonly type: "message_started";
328
394
  readonly sessionId: string;
@@ -356,12 +422,14 @@ export type AgentEvent = {
356
422
  readonly sessionId: string;
357
423
  readonly runId: string;
358
424
  readonly result: ToolResult;
425
+ readonly metadata: ToolExecutionMetadata;
359
426
  } | {
360
427
  readonly type: "tool_execution_error";
361
428
  readonly sessionId: string;
362
429
  readonly runId: string;
363
430
  readonly call: ToolCallContent;
364
431
  readonly error: ErrorInfo;
432
+ readonly metadata: ToolExecutionMetadata;
365
433
  } | {
366
434
  readonly type: "tool_execution_blocked";
367
435
  readonly sessionId: string;
@@ -370,6 +438,7 @@ export type AgentEvent = {
370
438
  readonly name: string;
371
439
  readonly reason: string;
372
440
  readonly error: ErrorInfo;
441
+ readonly metadata: ToolExecutionMetadata;
373
442
  } | {
374
443
  readonly type: "queue_updated";
375
444
  readonly sessionId: string;
@@ -442,6 +511,8 @@ export interface ToolDefinition {
442
511
  readonly name: string;
443
512
  readonly description?: string;
444
513
  readonly parameters?: JsonObject;
514
+ /** Force any provider turn containing this tool to dispatch sequentially. */
515
+ readonly exclusive?: boolean;
445
516
  execute(args: JsonObject, context: ToolExecutionContext): Promise<ToolResult> | ToolResult;
446
517
  }
447
518
  export interface ToolRegistry {
@@ -647,6 +718,8 @@ export interface OAuthLoginCallbacks {
647
718
  readonly message: string;
648
719
  readonly choices: readonly string[];
649
720
  }): string | undefined | Promise<string | undefined>;
721
+ /** Aborts OAuth login flows and device-code polling when signaled. */
722
+ readonly signal?: AbortSignal;
650
723
  }
651
724
  export interface OAuthCredentials {
652
725
  readonly access?: string;
@@ -832,6 +905,83 @@ export interface PersistenceQuery {
832
905
  readonly limit?: number;
833
906
  readonly order?: "asc" | "desc";
834
907
  }
908
+ /** Generic versioned checkpoint key. Namespaces prevent consumer collisions. */
909
+ export interface CheckpointKey extends OwnershipScope {
910
+ readonly namespace: string;
911
+ readonly key: string;
912
+ readonly signal?: AbortSignal;
913
+ }
914
+ /** Input for an optimistic checkpoint write. Versions must strictly increase. */
915
+ export interface CheckpointSaveInput extends CheckpointKey {
916
+ readonly version: number;
917
+ /** Exact current version required before update; use 0 for create-only. */
918
+ readonly expectedVersion?: number;
919
+ /** Monotonic lease fence. Lower or absent worker fences cannot replace a fenced record. */
920
+ readonly fencingToken?: number;
921
+ readonly value: unknown;
922
+ readonly category?: string;
923
+ readonly metadata?: Readonly<Record<string, unknown>>;
924
+ }
925
+ /** Durable generic checkpoint record. */
926
+ export interface CheckpointRecord extends OwnershipScope {
927
+ readonly namespace: string;
928
+ readonly key: string;
929
+ readonly version: number;
930
+ readonly fencingToken?: number;
931
+ readonly value: unknown;
932
+ readonly category?: string;
933
+ readonly createdAt: string;
934
+ readonly updatedAt: string;
935
+ readonly metadata?: Readonly<Record<string, unknown>>;
936
+ }
937
+ /** Bounded checkpoint query. */
938
+ export interface CheckpointQuery extends PersistenceQuery, OwnershipScope {
939
+ readonly namespace?: string;
940
+ readonly keyPrefix?: string;
941
+ readonly category?: string | readonly string[];
942
+ readonly signal?: AbortSignal;
943
+ }
944
+ /** Generic versioned checkpoint capability for persistence adapters. */
945
+ export interface CheckpointStore {
946
+ saveCheckpoint(input: CheckpointSaveInput): Promise<CheckpointRecord>;
947
+ loadCheckpoint(input: CheckpointKey): Promise<CheckpointRecord | null>;
948
+ listCheckpoints(query?: CheckpointQuery): Promise<PersistencePage<CheckpointRecord>>;
949
+ deleteCheckpoint(input: CheckpointKey): Promise<boolean>;
950
+ }
951
+ /** Generic lease key. Ownership fields are part of the trust boundary. */
952
+ export interface LeaseKey extends OwnershipScope {
953
+ readonly namespace: string;
954
+ readonly key: string;
955
+ readonly signal?: AbortSignal;
956
+ }
957
+ export interface LeaseAcquireInput extends LeaseKey {
958
+ readonly ownerId: string;
959
+ readonly ttlMs: number;
960
+ }
961
+ export interface LeaseClaimInput extends LeaseKey {
962
+ readonly ownerId: string;
963
+ readonly token: string;
964
+ readonly ttlMs?: number;
965
+ }
966
+ export interface LeaseRecord extends OwnershipScope {
967
+ readonly namespace: string;
968
+ readonly key: string;
969
+ readonly ownerId: string;
970
+ readonly token: string;
971
+ readonly fencingToken: number;
972
+ readonly acquiredAt: string;
973
+ readonly expiresAt: string;
974
+ readonly updatedAt: string;
975
+ }
976
+ /** Atomic distributed lease capability. Expired rows retain fencing counters. */
977
+ export interface LeaseStore {
978
+ tryAcquireLease(input: LeaseAcquireInput): Promise<LeaseRecord | null>;
979
+ renewLease(input: LeaseClaimInput & {
980
+ readonly ttlMs: number;
981
+ }): Promise<LeaseRecord | null>;
982
+ releaseLease(input: LeaseClaimInput): Promise<boolean>;
983
+ getLease(input: LeaseKey): Promise<LeaseRecord | null>;
984
+ }
835
985
  /** Stored session record. Does not include provider objects or credentials. */
836
986
  export interface SessionRecord extends OwnershipScope {
837
987
  readonly id: string;
@@ -908,12 +1058,16 @@ export interface ToolCallRecord extends OwnershipScope {
908
1058
  readonly redacted: boolean;
909
1059
  readonly metadata?: Readonly<Record<string, unknown>>;
910
1060
  }
911
- /** Stored usage row. */
1061
+ export type UsageScope = "provider_turn" | "run_total";
1062
+ /** Stored usage row. `scope` prevents provider-turn and aggregate totals from being summed together. */
912
1063
  export interface UsageRecord extends OwnershipScope {
913
1064
  readonly id: string;
914
1065
  readonly sessionId: string;
915
1066
  readonly runId?: string;
916
1067
  readonly entryId?: string;
1068
+ readonly scope: UsageScope;
1069
+ readonly turn?: number;
1070
+ readonly attempt?: number;
917
1071
  readonly usage: Usage;
918
1072
  readonly recordedAt: string;
919
1073
  readonly metadata?: Readonly<Record<string, unknown>>;
@@ -927,6 +1081,59 @@ export interface RunLedger {
927
1081
  }
928
1082
  /** Union of records that may be handed to a {@link RunLedger}. */
929
1083
  export type RunLedgerRecord = RunRecord | AgentEventRecord | ToolCallRecord | UsageRecord;
1084
+ /** Immutable human feedback linked to an existing owned run/trace and optional evaluations. */
1085
+ export interface RunFeedbackRecord extends OwnershipScope {
1086
+ readonly id: string;
1087
+ readonly runId: string;
1088
+ readonly sessionId: string;
1089
+ readonly traceId?: string;
1090
+ readonly rating?: number;
1091
+ readonly comment?: string;
1092
+ readonly tags: readonly string[];
1093
+ readonly scorerIds: readonly string[];
1094
+ readonly evaluationIds: readonly string[];
1095
+ readonly createdAt: string;
1096
+ readonly createdBy?: string;
1097
+ readonly metadata?: Readonly<Record<string, unknown>>;
1098
+ }
1099
+ export interface AppendRunFeedbackInput extends OwnershipScope {
1100
+ readonly id: string;
1101
+ readonly runId: string;
1102
+ readonly sessionId?: string;
1103
+ readonly traceId?: string;
1104
+ readonly rating?: number;
1105
+ readonly comment?: string;
1106
+ readonly tags?: readonly string[];
1107
+ readonly scorerIds?: readonly string[];
1108
+ readonly evaluationIds?: readonly string[];
1109
+ readonly createdAt?: string;
1110
+ readonly createdBy?: string;
1111
+ readonly metadata?: Readonly<Record<string, unknown>>;
1112
+ readonly signal?: AbortSignal;
1113
+ }
1114
+ /** Cursor-paginated, ownership-scoped feedback query. */
1115
+ export interface RunFeedbackQuery extends PersistenceQuery, OwnershipScope {
1116
+ readonly runId?: string;
1117
+ readonly sessionId?: string;
1118
+ readonly traceId?: string;
1119
+ readonly rating?: number;
1120
+ readonly scorerId?: string;
1121
+ readonly evaluationId?: string;
1122
+ readonly tag?: string;
1123
+ readonly fromCreatedAt?: string;
1124
+ readonly toCreatedAt?: string;
1125
+ readonly signal?: AbortSignal;
1126
+ }
1127
+ export interface DeleteRunFeedbackInput extends OwnershipScope {
1128
+ readonly id: string;
1129
+ readonly signal?: AbortSignal;
1130
+ }
1131
+ /** Feedback storage seam. Records are append-only; correction uses a new record and deletion is explicit. */
1132
+ export interface RunFeedbackStore {
1133
+ append(input: AppendRunFeedbackInput): Promise<RunFeedbackRecord>;
1134
+ query(query: RunFeedbackQuery): Promise<PersistencePage<RunFeedbackRecord>>;
1135
+ delete(input: DeleteRunFeedbackInput): Promise<boolean>;
1136
+ }
930
1137
  /** Stored agent definition version. Does not include provider credentials/resolvers/provider instances. */
931
1138
  export interface AgentDefinitionRecord extends OwnershipScope {
932
1139
  readonly id: string;
@@ -1031,6 +1238,9 @@ export interface UsageQuery extends PersistenceQuery, OwnershipScope {
1031
1238
  readonly sessionId?: string;
1032
1239
  readonly runId?: string;
1033
1240
  readonly entryId?: string;
1241
+ readonly scope?: UsageScope;
1242
+ readonly turn?: number;
1243
+ readonly attempt?: number;
1034
1244
  readonly fromRecordedAt?: string;
1035
1245
  readonly toRecordedAt?: string;
1036
1246
  }
@@ -1058,11 +1268,17 @@ export interface MigrationQuery extends PersistenceQuery {
1058
1268
  * Production database-neutral persistence store contract.
1059
1269
  * Hosts implement this interface to provide durable, paginated storage
1060
1270
  * for sessions, entries, runs, events, tool calls, usage, agent definitions,
1061
- * and migrations. No SQL client, ORM, host file storage, or network dependency is
1271
+ * and migrations, with optional generic checkpoint and atomic lease capabilities. No SQL client, ORM, host file storage, or network dependency is
1062
1272
  * required by the contract.
1063
1273
  */
1064
1274
  export interface ProductionPersistenceStore {
1065
1275
  readonly name?: string;
1276
+ /** Optional generic write capability for resumable consumers such as workflows. */
1277
+ readonly checkpoints?: CheckpointStore;
1278
+ /** Optional atomic distributed lease capability for coordinators and workers. */
1279
+ readonly leases?: LeaseStore;
1280
+ /** Optional immutable run/trace feedback storage capability. */
1281
+ readonly feedback?: RunFeedbackStore;
1066
1282
  querySessions(query: SessionQuery): Promise<PersistencePage<SessionRecord>>;
1067
1283
  queryBranches(query: BranchQuery): Promise<PersistencePage<BranchRecord>>;
1068
1284
  queryEntries(query: SessionEntryQuery): Promise<PersistencePage<SessionEntry>>;
@@ -1201,9 +1417,12 @@ export interface LoopContext {
1201
1417
  readonly input: AgentInput;
1202
1418
  readonly inputMessages: readonly Message[];
1203
1419
  readonly maxToolRounds: number;
1420
+ /** Maximum independent tool calls dispatched concurrently per provider turn. Default `1`. */
1421
+ readonly toolConcurrency: number;
1204
1422
  assemble(nextInput: AgentInput, toolResults?: readonly ToolResult[], turn?: number): Promise<ProviderRequest>;
1205
1423
  generate(request: ProviderRequest): Promise<ProviderTurnResult>;
1206
1424
  dispatchToolCall(call: ToolCallContent): Promise<ToolResult>;
1425
+ isToolCallExclusive?(call: ToolCallContent): boolean;
1207
1426
  appendMessage(message: Message): Promise<void>;
1208
1427
  emit(event: AgentEvent): void;
1209
1428
  }
@@ -1213,12 +1432,18 @@ export interface AgentLoopStrategy {
1213
1432
  }
1214
1433
  export type AgentLoopOptions = {
1215
1434
  readonly strategy: "single-shot";
1435
+ /** Independent tool calls per turn run concurrently up to this limit. Default `1` (sequential). */
1436
+ readonly toolConcurrency?: number;
1216
1437
  } | {
1217
1438
  readonly strategy: "generate-validate-revise";
1218
1439
  readonly validator: ArtifactValidator<unknown>;
1219
1440
  readonly parser?: ArtifactParser<unknown>;
1220
1441
  readonly repairer?: ArtifactRepairer<unknown>;
1221
1442
  readonly maxRevisions?: number;
1443
+ /** Native provider JSON-schema output. Ignored when `structuredOutputMode` is `artifact-loop`. */
1444
+ readonly structuredOutput?: StructuredOutputOptions;
1445
+ /** `native` maps schema to capable providers; `artifact-loop` keeps repair turns only. */
1446
+ readonly structuredOutputMode?: "native" | "artifact-loop";
1222
1447
  };
1223
1448
  export interface ArtifactValidation {
1224
1449
  readonly ok: boolean;
package/dist/contracts.js CHANGED
@@ -1,3 +1,11 @@
1
+ export class AgentRunError extends Error {
2
+ result;
3
+ constructor(result, options) {
4
+ super(result.error?.message ?? (result.status === "aborted" ? "Agent run aborted" : "Agent run failed"), options);
5
+ this.name = "AgentRunError";
6
+ this.result = result;
7
+ }
8
+ }
1
9
  export const SESSION_ENTRY_KINDS = [
2
10
  "message",
3
11
  "event",
@@ -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