@arnilo/prism 0.0.22 → 0.0.24
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 +36 -2
- package/dist/agent-event-source.d.ts +11 -0
- package/dist/agent-event-source.js +512 -0
- package/dist/agent-run-state.js +6 -1
- package/dist/agents.js +7 -2
- package/dist/contracts.d.ts +157 -0
- package/dist/index.d.ts +7 -2
- package/dist/index.js +4 -1
- package/dist/testing/agent-event-source-conformance.d.ts +4 -0
- package/dist/testing/agent-event-source-conformance.js +54 -0
- package/dist/testing/persistence-schema.d.ts +2 -2
- package/dist/testing/persistence-schema.js +58 -21
- package/dist/testing/tool-effect-store-conformance.d.ts +9 -0
- package/dist/testing/tool-effect-store-conformance.js +85 -0
- package/dist/tool-effects.d.ts +15 -0
- package/dist/tool-effects.js +338 -0
- package/dist/tools.d.ts +3 -1
- package/dist/tools.js +204 -9
- package/docs/0.1.0-readiness.md +10 -9
- package/docs/a2a.md +6 -2
- package/docs/ag-ui-adoption.md +77 -0
- package/docs/ag-ui.md +39 -42
- package/docs/agent-events.md +5 -1
- package/docs/browser-automation.md +2 -0
- package/docs/coding-agent-tools.md +2 -0
- package/docs/database-persistence.md +5 -0
- package/docs/enterprise-postgres-state.md +177 -0
- package/docs/evaluations.md +13 -0
- package/docs/host-security.md +11 -1
- package/docs/index.md +17 -14
- package/docs/mcp-tools.md +17 -2
- package/docs/migration.md +41 -0
- package/docs/model-routing.md +17 -8
- package/docs/performance.md +38 -0
- package/docs/policy-and-audit.md +12 -0
- package/docs/postgres-persistence.md +7 -3
- package/docs/public-contracts.md +2 -0
- package/docs/release-and-install.md +67 -680
- package/docs/server.md +9 -6
- package/docs/sqlite-persistence.md +10 -2
- package/docs/supervisors.md +2 -0
- package/docs/tool-effects.md +95 -0
- package/docs/tools.md +4 -0
- package/docs/work-tools.md +21 -1
- package/package.json +11 -2
package/dist/contracts.d.ts
CHANGED
|
@@ -365,6 +365,8 @@ export interface RunOptions {
|
|
|
365
365
|
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
366
366
|
readonly redactor?: SecretRedactor;
|
|
367
367
|
readonly runLedger?: RunLedger;
|
|
368
|
+
/** Optional durable recovery store. Per-run value overrides this agent default. */
|
|
369
|
+
readonly effectStore?: ToolEffectStore;
|
|
368
370
|
readonly ownership?: OwnershipScope;
|
|
369
371
|
/** Host-verified identity; when set, must project onto `ownership` without widening. */
|
|
370
372
|
readonly identity?: import("./identity.js").AgentIdentity;
|
|
@@ -444,6 +446,8 @@ export interface AgentConfig {
|
|
|
444
446
|
readonly systemPrompt?: SystemPromptConfig;
|
|
445
447
|
readonly redactor?: SecretRedactor;
|
|
446
448
|
readonly runLedger?: RunLedger;
|
|
449
|
+
/** Optional durable recovery store. */
|
|
450
|
+
readonly effectStore?: ToolEffectStore;
|
|
447
451
|
readonly ownership?: OwnershipScope;
|
|
448
452
|
/** Host-verified identity default for sessions created from this agent. */
|
|
449
453
|
readonly identity?: import("./identity.js").AgentIdentity;
|
|
@@ -834,12 +838,23 @@ export type AgentEvent = {
|
|
|
834
838
|
readonly attempt: number;
|
|
835
839
|
readonly result: ArtifactValidation;
|
|
836
840
|
};
|
|
841
|
+
export type ToolEffectKind = "none" | "local_mutation" | "external_mutation";
|
|
842
|
+
export type ToolEffectIdempotency = "none" | "optional" | "required" | "tool_managed" | "unsupported";
|
|
843
|
+
/** Static or validated-argument classification of one tool call's side-effect behavior. */
|
|
844
|
+
export interface ToolEffectDeclaration {
|
|
845
|
+
readonly kind: ToolEffectKind;
|
|
846
|
+
readonly idempotency: ToolEffectIdempotency;
|
|
847
|
+
}
|
|
848
|
+
/** Runs after argument validation. It must be synchronous, deterministic, bounded, and side-effect-free. */
|
|
849
|
+
export type ToolEffectClassifier = (args: JsonObject, context: ToolExecutionContext) => ToolEffectDeclaration;
|
|
837
850
|
export interface ToolDefinition {
|
|
838
851
|
readonly name: string;
|
|
839
852
|
readonly description?: string;
|
|
840
853
|
readonly parameters?: JsonObject;
|
|
841
854
|
/** Force any provider turn containing this tool to dispatch sequentially. */
|
|
842
855
|
readonly exclusive?: boolean;
|
|
856
|
+
/** Optional side-effect declaration. Omitted tools retain legacy unmanaged dispatch. */
|
|
857
|
+
readonly effect?: ToolEffectDeclaration | ToolEffectClassifier;
|
|
843
858
|
execute(args: JsonObject, context: ToolExecutionContext): Promise<ToolResult> | ToolResult;
|
|
844
859
|
}
|
|
845
860
|
export interface ToolRegistry {
|
|
@@ -856,6 +871,8 @@ export interface ToolExecutionContext {
|
|
|
856
871
|
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
857
872
|
/** Host-verified identity for this tool invocation, when enterprise identity is active. */
|
|
858
873
|
readonly identity?: import("./identity.js").AgentIdentity;
|
|
874
|
+
/** Core-derived stable effect key. Never accept a model-supplied key as authority. */
|
|
875
|
+
readonly idempotencyKey?: string;
|
|
859
876
|
progress?(progress?: unknown, metadata?: Readonly<Record<string, unknown>>): void | Promise<void>;
|
|
860
877
|
}
|
|
861
878
|
export interface ToolResult {
|
|
@@ -866,6 +883,90 @@ export interface ToolResult {
|
|
|
866
883
|
readonly error?: ErrorInfo;
|
|
867
884
|
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
868
885
|
}
|
|
886
|
+
export type ToolEffectStatus = "pending" | "dispatched" | "completed" | "failed_retryable" | "failed_terminal" | "unknown";
|
|
887
|
+
export interface ToolEffectRecord extends OwnershipScope {
|
|
888
|
+
readonly key: string;
|
|
889
|
+
readonly sessionId: string;
|
|
890
|
+
readonly runId: string;
|
|
891
|
+
readonly toolCallId: string;
|
|
892
|
+
readonly toolName: string;
|
|
893
|
+
readonly argumentsHash: string;
|
|
894
|
+
readonly status: ToolEffectStatus;
|
|
895
|
+
readonly attempt: number;
|
|
896
|
+
readonly version: number;
|
|
897
|
+
readonly claimToken?: string;
|
|
898
|
+
readonly result?: ToolResult;
|
|
899
|
+
readonly resultRef?: string;
|
|
900
|
+
readonly failure?: {
|
|
901
|
+
readonly code: string;
|
|
902
|
+
readonly reference?: string;
|
|
903
|
+
};
|
|
904
|
+
readonly createdAt: string;
|
|
905
|
+
readonly updatedAt: string;
|
|
906
|
+
readonly expiresAt?: string;
|
|
907
|
+
}
|
|
908
|
+
export interface ToolEffectKey {
|
|
909
|
+
readonly identity: import("./identity.js").AgentIdentity;
|
|
910
|
+
readonly ownership: OwnershipScope;
|
|
911
|
+
readonly key: string;
|
|
912
|
+
readonly sessionId: string;
|
|
913
|
+
readonly runId: string;
|
|
914
|
+
readonly toolCallId: string;
|
|
915
|
+
readonly toolName: string;
|
|
916
|
+
readonly argumentsHash: string;
|
|
917
|
+
readonly signal?: AbortSignal;
|
|
918
|
+
}
|
|
919
|
+
export interface ToolEffectTransition extends ToolEffectKey {
|
|
920
|
+
readonly claimToken: string;
|
|
921
|
+
readonly expectedVersion: number;
|
|
922
|
+
}
|
|
923
|
+
/** Durable claim/CAS store for recoverable tool effects. */
|
|
924
|
+
export interface ToolEffectStore {
|
|
925
|
+
get(input: ToolEffectKey): Promise<ToolEffectRecord | undefined>;
|
|
926
|
+
begin(input: ToolEffectKey & {
|
|
927
|
+
readonly claimTtlMs?: number;
|
|
928
|
+
readonly maxAttempts?: number;
|
|
929
|
+
}): Promise<{
|
|
930
|
+
readonly outcome: "acquired" | "existing";
|
|
931
|
+
readonly record: ToolEffectRecord;
|
|
932
|
+
}>;
|
|
933
|
+
markDispatched(input: ToolEffectTransition): Promise<ToolEffectRecord>;
|
|
934
|
+
complete(input: ToolEffectTransition & {
|
|
935
|
+
readonly result?: ToolResult;
|
|
936
|
+
readonly resultRef?: string;
|
|
937
|
+
}): Promise<ToolEffectRecord>;
|
|
938
|
+
fail(input: ToolEffectTransition & {
|
|
939
|
+
readonly status: "failed_retryable" | "failed_terminal";
|
|
940
|
+
readonly failure: {
|
|
941
|
+
readonly code: string;
|
|
942
|
+
readonly reference?: string;
|
|
943
|
+
};
|
|
944
|
+
}): Promise<ToolEffectRecord>;
|
|
945
|
+
markUnknown(input: ToolEffectTransition & {
|
|
946
|
+
readonly failure?: {
|
|
947
|
+
readonly code: string;
|
|
948
|
+
readonly reference?: string;
|
|
949
|
+
};
|
|
950
|
+
}): Promise<ToolEffectRecord>;
|
|
951
|
+
resolveUnknown(input: ToolEffectKey & {
|
|
952
|
+
readonly expectedVersion: number;
|
|
953
|
+
readonly status: "completed" | "failed_retryable" | "failed_terminal";
|
|
954
|
+
readonly result?: ToolResult;
|
|
955
|
+
readonly resultRef?: string;
|
|
956
|
+
readonly failure?: {
|
|
957
|
+
readonly code: string;
|
|
958
|
+
readonly reference?: string;
|
|
959
|
+
};
|
|
960
|
+
}): Promise<ToolEffectRecord>;
|
|
961
|
+
cleanup(input: {
|
|
962
|
+
readonly ownership: OwnershipScope;
|
|
963
|
+
readonly before: string;
|
|
964
|
+
readonly limit?: number;
|
|
965
|
+
readonly signal?: AbortSignal;
|
|
966
|
+
}): Promise<{
|
|
967
|
+
readonly deleted: number;
|
|
968
|
+
}>;
|
|
969
|
+
}
|
|
869
970
|
export interface CommandDefinition {
|
|
870
971
|
readonly name: string;
|
|
871
972
|
readonly description?: string;
|
|
@@ -1446,6 +1547,8 @@ export interface AgentEventRecord extends OwnershipScope {
|
|
|
1446
1547
|
readonly id: string;
|
|
1447
1548
|
readonly sessionId: string;
|
|
1448
1549
|
readonly runId?: string;
|
|
1550
|
+
/** Durable sources allocate positive, strictly increasing per-run positions. */
|
|
1551
|
+
readonly sequence?: number;
|
|
1449
1552
|
readonly entryId?: string;
|
|
1450
1553
|
readonly type: AgentEventType;
|
|
1451
1554
|
readonly timestamp: string;
|
|
@@ -1453,6 +1556,58 @@ export interface AgentEventRecord extends OwnershipScope {
|
|
|
1453
1556
|
readonly redacted: boolean;
|
|
1454
1557
|
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
1455
1558
|
}
|
|
1559
|
+
/** An event record returned by an {@link AgentEventSource}. */
|
|
1560
|
+
export interface DurableAgentEventRecord extends AgentEventRecord {
|
|
1561
|
+
readonly runId: string;
|
|
1562
|
+
readonly sequence: number;
|
|
1563
|
+
}
|
|
1564
|
+
export interface AgentEventEnvelope {
|
|
1565
|
+
readonly record: DurableAgentEventRecord;
|
|
1566
|
+
/** Opaque cursor immediately after `record`. */
|
|
1567
|
+
readonly cursor: string;
|
|
1568
|
+
}
|
|
1569
|
+
export interface AgentEventSourcePage {
|
|
1570
|
+
readonly items: readonly AgentEventEnvelope[];
|
|
1571
|
+
readonly nextCursor?: string;
|
|
1572
|
+
/** True only after every event preceding a terminal event has been returned. */
|
|
1573
|
+
readonly terminal: boolean;
|
|
1574
|
+
}
|
|
1575
|
+
/** Exact-owned, per-run durable event read. `after` is exclusive. */
|
|
1576
|
+
export interface AgentEventSourceRead {
|
|
1577
|
+
readonly ownership: OwnershipScope;
|
|
1578
|
+
readonly sessionId: string;
|
|
1579
|
+
readonly runId: string;
|
|
1580
|
+
readonly after?: string;
|
|
1581
|
+
readonly limit?: number;
|
|
1582
|
+
readonly signal?: AbortSignal;
|
|
1583
|
+
}
|
|
1584
|
+
export interface AgentEventSourceCleanup {
|
|
1585
|
+
readonly ownership: OwnershipScope;
|
|
1586
|
+
readonly before: string;
|
|
1587
|
+
readonly limit?: number;
|
|
1588
|
+
readonly signal?: AbortSignal;
|
|
1589
|
+
}
|
|
1590
|
+
export interface AgentEventSourceOptions {
|
|
1591
|
+
readonly maxEventBytes?: number;
|
|
1592
|
+
readonly maxPageSize?: number;
|
|
1593
|
+
readonly maxCursorBytes?: number;
|
|
1594
|
+
readonly maxQueuedEvents?: number;
|
|
1595
|
+
readonly maxSubscribers?: number;
|
|
1596
|
+
readonly pollIntervalMs?: number;
|
|
1597
|
+
readonly reconnectInitialMs?: number;
|
|
1598
|
+
readonly reconnectMaxMs?: number;
|
|
1599
|
+
readonly maxRetainedEventsPerRun?: number;
|
|
1600
|
+
readonly maxRetentionAgeMs?: number;
|
|
1601
|
+
}
|
|
1602
|
+
/** Optional durable event capability. `RunLedger` remains a write-only contract. */
|
|
1603
|
+
export interface AgentEventSource {
|
|
1604
|
+
append(record: AgentEventRecord): Promise<DurableAgentEventRecord>;
|
|
1605
|
+
page(input: AgentEventSourceRead): Promise<AgentEventSourcePage>;
|
|
1606
|
+
subscribe(input: AgentEventSourceRead): AsyncIterable<AgentEventEnvelope>;
|
|
1607
|
+
cleanup(input: AgentEventSourceCleanup): Promise<{
|
|
1608
|
+
readonly deleted: number;
|
|
1609
|
+
}>;
|
|
1610
|
+
}
|
|
1456
1611
|
export type ToolCallStatus = "started" | "finished" | "error" | "blocked";
|
|
1457
1612
|
/** Stored tool-call row. The `result` payload should be redacted before storage when secrets are present. */
|
|
1458
1613
|
export interface ToolCallRecord extends OwnershipScope {
|
|
@@ -1715,6 +1870,8 @@ export interface ProductionPersistenceStore {
|
|
|
1715
1870
|
readonly leases?: LeaseStore;
|
|
1716
1871
|
/** Optional immutable run/trace feedback storage capability. */
|
|
1717
1872
|
readonly feedback?: RunFeedbackStore;
|
|
1873
|
+
/** Optional durable, cross-replica-capable event source. */
|
|
1874
|
+
readonly events?: AgentEventSource;
|
|
1718
1875
|
querySessions(query: SessionQuery): Promise<PersistencePage<SessionRecord>>;
|
|
1719
1876
|
queryBranches(query: BranchQuery): Promise<PersistencePage<BranchRecord>>;
|
|
1720
1877
|
queryEntries(query: SessionEntryQuery): Promise<PersistencePage<SessionEntry>>;
|
package/dist/index.d.ts
CHANGED
|
@@ -20,7 +20,7 @@ export { assertDeclaredMediaTypeMatches, assertMediaBlocksWithinBounds, assertMe
|
|
|
20
20
|
export type { ContextBudget, ContextBudgetMessageGroups, ContextBudgetOmission, ContextBudgetOmissionKind, ContextBudgetReport, } from "./context-budget.js";
|
|
21
21
|
export { applyContextBudget, CONTEXT_BUDGET_ERROR_CODE, CONTEXT_BUDGET_REPORT_METADATA_KEY, ContextBudgetError, DEFAULT_MAX_CONTEXT_BUDGET_OMISSIONS, estimateAssemblyTokens, estimateMessageBytes, estimateMessageTokens, estimateTextBytes, estimateTextTokens, getContextBudgetReport, HARD_MAX_CONTEXT_BUDGET_BYTES, HARD_MAX_CONTEXT_BUDGET_OMISSIONS, HARD_MAX_CONTEXT_BUDGET_TOKENS, isContextBudgetError, resolveContextBudget, } from "./context-budget.js";
|
|
22
22
|
export type * from "./contracts.js";
|
|
23
|
-
export type { ProviderResolver, RealtimeCaps, RealtimeEvent, RealtimeSession, RealtimeSessionFactory, RealtimeSessionOptions, RunLimitCounters, RunLimitName, SecureAgentOptions, ToolCallAuthority, } from "./contracts.js";
|
|
23
|
+
export type { ProviderResolver, RealtimeCaps, RealtimeEvent, RealtimeSession, RealtimeSessionFactory, RealtimeSessionOptions, RunLimitCounters, RunLimitName, SecureAgentOptions, ToolCallAuthority, ToolEffectClassifier, ToolEffectDeclaration, ToolEffectIdempotency, ToolEffectKey, ToolEffectKind, ToolEffectRecord, ToolEffectStatus, ToolEffectStore, ToolEffectTransition, } from "./contracts.js";
|
|
24
24
|
export { AgentRunError, AgentRunStateError, assertSessionMetadataKey, DEFAULT_MAX_PENDING_STEER_BYTES, DEFAULT_MAX_PENDING_STEERS, DEFAULT_MAX_SESSION_SEARCH_CURSOR_BYTES, DEFAULT_MAX_SESSION_SEARCH_FTS_CANDIDATES, DEFAULT_MAX_SESSION_SEARCH_LINEAR_BYTES, DEFAULT_MAX_SESSION_SEARCH_LINEAR_ENTRIES, DEFAULT_MAX_SESSION_SEARCH_LINEAR_SESSIONS, DEFAULT_MAX_SESSION_SEARCH_QUERY_BYTES, DEFAULT_MAX_SESSION_SEARCH_SNIPPET_BYTES, DEFAULT_SESSION_SEARCH_LIMIT, HARD_MAX_PENDING_STEER_BYTES, HARD_MAX_PENDING_STEERS, HARD_MAX_SESSION_SEARCH_CURSOR_BYTES, HARD_MAX_SESSION_SEARCH_FTS_CANDIDATES, HARD_MAX_SESSION_SEARCH_LIMIT, HARD_MAX_SESSION_SEARCH_LINEAR_BYTES, HARD_MAX_SESSION_SEARCH_LINEAR_ENTRIES, HARD_MAX_SESSION_SEARCH_LINEAR_SESSIONS, HARD_MAX_SESSION_SEARCH_QUERY_BYTES, HARD_MAX_SESSION_SEARCH_SNIPPET_BYTES, isSessionAppendConflict, isSessionEntryKind, isSessionSearchUnsupported, resolveSessionSearchQuery, SESSION_APPEND_CONFLICT_CODE, SESSION_ENTRY_KINDS, SESSION_ENTRY_SCHEMA_VERSION, SESSION_SEARCH_UNSUPPORTED_CODE, SESSION_SEARCH_WORKSPACE_METADATA_KEY, SessionAppendConflictError, SessionSearchUnsupportedError, } from "./contracts.js";
|
|
25
25
|
export { parseAgentFile, parseSkillFile } from "./contribution-parsing.js";
|
|
26
26
|
export type { ContributionRegistries, ContributionRegistriesOptions, ContributionRegistry, ContributionRegistryOptions, } from "./contributions.js";
|
|
@@ -31,6 +31,9 @@ export type { CredentialRecord, CredentialValueSource, MemoryCredentialStore, Re
|
|
|
31
31
|
export { createChainedCredentialResolver, createEnvCredentialResolver, createExplicitCredentialResolver, createMemoryCredentialStore, refreshOAuthCredential, resolveCredentialValue, revokeOAuthCredential, } from "./credentials.js";
|
|
32
32
|
export type { DeviceAdapter, DeviceAdmitRequest, DeviceChunkResult, DeviceConformanceResult, DeviceKind, DevicePolicyErrorCode, DevicePolicyOptions, DeviceStreamLimits, ResolvedDevicePolicy, } from "./devices.js";
|
|
33
33
|
export { acceptDeviceChunk, assertDeviceAdmit, DEFAULT_DEVICE_MAX_CHUNK_BYTES, DEFAULT_DEVICE_MAX_CONCURRENT_SESSIONS, DevicePolicyError, HARD_DEVICE_MAX_CHUNK_BYTES, HARD_DEVICE_MAX_CONCURRENT_SESSIONS, redactDeviceTelemetry, resolveDevicePolicy, runDevicePolicyConformance, } from "./devices.js";
|
|
34
|
+
export type { AgentEventSourceErrorCode } from "./agent-event-source.js";
|
|
35
|
+
export { AgentEventSourceError, createMemoryAgentEventSource } from "./agent-event-source.js";
|
|
36
|
+
export { assertAgentEventSourceConforms } from "./testing/agent-event-source-conformance.js";
|
|
34
37
|
export type { EventMultiplexer, EventMultiplexerOptions, EventOverflowInfo, EventOverflowPolicy } from "./event-multiplexer.js";
|
|
35
38
|
export { createEventMultiplexer } from "./event-multiplexer.js";
|
|
36
39
|
export type { ExecutionAction, ExecutionDecision, ExecutionPolicy, ExecutionRisk } from "./execution-policy.js";
|
|
@@ -97,8 +100,10 @@ export type { ThinkingCompatFamily, ThinkingLevel } from "./thinking.js";
|
|
|
97
100
|
export { applyThinkingLevel, isThinkingLevel, normalizeThinkingLevel, THINKING_LEVELS, thinkingCompatFor, thinkingFamilyForModel, } from "./thinking.js";
|
|
98
101
|
export type { DispatchToolCallOptions, ToolArgumentValidationError, ToolArgumentValidationResult, ToolArgumentValidator, ToolFilter, ToolFilterInput, ToolParameterValidatorOptions, ToolRegistryOptions, ToolValidator, } from "./tools.js";
|
|
99
102
|
export { createToolParameterValidator, createToolRegistry, dispatchToolCall, filterTools } from "./tools.js";
|
|
103
|
+
export { createMemoryToolEffectStore, ToolEffectError } from "./tool-effects.js";
|
|
104
|
+
export type { ToolEffectErrorCode } from "./tool-effects.js";
|
|
100
105
|
export type { ResolvedUseCaseModel, ResolveUseCaseModelInput, UseCaseModelBinding, } from "./use-case-model.js";
|
|
101
106
|
export { resolveUseCaseModel, resolveUseCaseModelBinding, useCaseCredentialProviderId, } from "./use-case-model.js";
|
|
102
107
|
export declare const name = "prism";
|
|
103
|
-
export declare const version = "0.0.
|
|
108
|
+
export declare const version = "0.0.24";
|
|
104
109
|
export declare const description = "Agent harness for AI providers, agents, sessions, and tools.";
|
package/dist/index.js
CHANGED
|
@@ -16,6 +16,8 @@ export { createContributionRegistries, createContributionRegistry, registerDisco
|
|
|
16
16
|
export { CONVERSATION_METADATA_KEY, ConversationError, conversationMarkerMetadata, conversationThreadFromRecord, DEFAULT_MAX_CONVERSATION_CURSOR_BYTES, decodeConversationReplayCursor, encodeConversationReplayCursor, HARD_MAX_CONVERSATION_CURSOR_BYTES, } from "./conversations.js";
|
|
17
17
|
export { createChainedCredentialResolver, createEnvCredentialResolver, createExplicitCredentialResolver, createMemoryCredentialStore, refreshOAuthCredential, resolveCredentialValue, revokeOAuthCredential, } from "./credentials.js";
|
|
18
18
|
export { acceptDeviceChunk, assertDeviceAdmit, DEFAULT_DEVICE_MAX_CHUNK_BYTES, DEFAULT_DEVICE_MAX_CONCURRENT_SESSIONS, DevicePolicyError, HARD_DEVICE_MAX_CHUNK_BYTES, HARD_DEVICE_MAX_CONCURRENT_SESSIONS, redactDeviceTelemetry, resolveDevicePolicy, runDevicePolicyConformance, } from "./devices.js";
|
|
19
|
+
export { AgentEventSourceError, createMemoryAgentEventSource } from "./agent-event-source.js";
|
|
20
|
+
export { assertAgentEventSourceConforms } from "./testing/agent-event-source-conformance.js";
|
|
19
21
|
export { createEventMultiplexer } from "./event-multiplexer.js";
|
|
20
22
|
export { applyExecutionDecision, assertExecutionAllowed, checkExecution, ExecutionDeniedError } from "./execution-policy.js";
|
|
21
23
|
export { createExtensionEventBus, createExtensionKernel } from "./extensions.js";
|
|
@@ -52,8 +54,9 @@ export { artifactStructuredOutputRequest, assertStructuredOutputRequestSupported
|
|
|
52
54
|
export { composeSystemPrompt, mergeSystemPromptConfig } from "./system-prompts.js";
|
|
53
55
|
export { applyThinkingLevel, isThinkingLevel, normalizeThinkingLevel, THINKING_LEVELS, thinkingCompatFor, thinkingFamilyForModel, } from "./thinking.js";
|
|
54
56
|
export { createToolParameterValidator, createToolRegistry, dispatchToolCall, filterTools } from "./tools.js";
|
|
57
|
+
export { createMemoryToolEffectStore, ToolEffectError } from "./tool-effects.js";
|
|
55
58
|
export { resolveUseCaseModel, resolveUseCaseModelBinding, useCaseCredentialProviderId, } from "./use-case-model.js";
|
|
56
59
|
export const name = "prism";
|
|
57
|
-
export const version = "0.0.
|
|
60
|
+
export const version = "0.0.24";
|
|
58
61
|
export const description = "Agent harness for AI providers, agents, sessions, and tools.";
|
|
59
62
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { AgentEventSource } from "../contracts.js";
|
|
2
|
+
export type AgentEventSourceConformanceFactory = () => AgentEventSource | Promise<AgentEventSource>;
|
|
3
|
+
/** Assert durable append/page/replay ownership and cursor behavior without a database dependency. */
|
|
4
|
+
export declare function assertAgentEventSourceConforms(factory: AgentEventSourceConformanceFactory): Promise<void>;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// ponytail: runner-free durable-event contract probe for database adapters.
|
|
2
|
+
/** Assert durable append/page/replay ownership and cursor behavior without a database dependency. */
|
|
3
|
+
export async function assertAgentEventSourceConforms(factory) {
|
|
4
|
+
const source = await factory();
|
|
5
|
+
const ownership = { tenantId: "tenant-a", accountId: "account-a", userId: "user-a" };
|
|
6
|
+
const input = { ownership, sessionId: "session-a", runId: "run-a" };
|
|
7
|
+
const first = event("event-a", "agent_started", input);
|
|
8
|
+
const second = event("event-b", "turn_started", input, "2026-01-01T00:00:01.000Z");
|
|
9
|
+
const storedFirst = await source.append(first);
|
|
10
|
+
const storedSecond = await source.append(second);
|
|
11
|
+
equal(storedFirst.sequence, 1, "first durable event must receive sequence 1");
|
|
12
|
+
equal(storedSecond.sequence, 2, "durable sequence must increase per run");
|
|
13
|
+
equal((await source.append(first)).sequence, 1, "identical duplicate append must be idempotent");
|
|
14
|
+
await rejects(() => source.append({ ...first, timestamp: "2026-01-01T00:00:02.000Z" }), "changed duplicate append must fail");
|
|
15
|
+
const page = await source.page({ ...input, limit: 1 });
|
|
16
|
+
equal(page.items.length, 1, "page limit must be honored");
|
|
17
|
+
equal(page.items[0].record.id, first.id, "page order must follow sequence");
|
|
18
|
+
if (!page.nextCursor)
|
|
19
|
+
throw new Error("truncated page must include a cursor");
|
|
20
|
+
const secondPage = await source.page({ ...input, after: page.nextCursor, limit: 1 });
|
|
21
|
+
equal(secondPage.items[0]?.record.id, second.id, "cursor must be exclusive");
|
|
22
|
+
const iterator = source.subscribe({ ...input, after: secondPage.items[0].cursor })[Symbol.asyncIterator]();
|
|
23
|
+
const pending = iterator.next();
|
|
24
|
+
const third = await source.append(event("event-c", "turn_started", input, "2026-01-01T00:00:02.000Z"));
|
|
25
|
+
equal((await pending).value?.record.id, third.id, "replay/live handoff dropped an event");
|
|
26
|
+
await iterator.return?.();
|
|
27
|
+
const terminal = await source.append(event("event-d", "agent_finished", input, "2026-01-01T00:00:03.000Z"));
|
|
28
|
+
const final = await source.page({ ...input, after: secondPage.items[0].cursor, limit: 10 });
|
|
29
|
+
equal(final.items.at(-1)?.record.id, terminal.id, "terminal page must include its terminal event");
|
|
30
|
+
equal(final.terminal, true, "terminal event must close only after prior events are delivered");
|
|
31
|
+
await rejects(() => source.page({ ...input, ownership: { ...ownership, tenantId: "tenant-b" }, after: page.nextCursor }), "foreign cursor must fail closed");
|
|
32
|
+
await rejects(() => source.append({ ...event("event-unredacted", "turn_started", input), redacted: false }), "unredacted append must fail");
|
|
33
|
+
await rejects(() => source.page({ ...input, limit: 0 }), "invalid page limit must fail");
|
|
34
|
+
}
|
|
35
|
+
function event(id, type, input, timestamp = "2026-01-01T00:00:00.000Z") {
|
|
36
|
+
const event = type === "turn_started"
|
|
37
|
+
? { type, sessionId: input.sessionId, runId: input.runId, turn: 1 }
|
|
38
|
+
: { type, sessionId: input.sessionId, runId: input.runId };
|
|
39
|
+
return { id, ...input.ownership, sessionId: input.sessionId, runId: input.runId, type, timestamp, event, redacted: true };
|
|
40
|
+
}
|
|
41
|
+
function equal(actual, expected, message) {
|
|
42
|
+
if (actual !== expected)
|
|
43
|
+
throw new Error(`${message}; expected ${String(expected)}, received ${String(actual)}`);
|
|
44
|
+
}
|
|
45
|
+
async function rejects(action, message) {
|
|
46
|
+
try {
|
|
47
|
+
await action();
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
throw new Error(message);
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=agent-event-source-conformance.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { PersistencePage, SessionEntry, SessionEntryQuery } from "../contracts.js";
|
|
2
2
|
/** Current shared persistence schema version for production database adapters. */
|
|
3
|
-
export declare const PERSISTENCE_SCHEMA_VERSION =
|
|
4
|
-
export type PersistenceTableName = "prism_tenants" | "prism_accounts" | "prism_users" | "prism_agent_definitions" | "prism_sessions" | "prism_branches" | "prism_session_entries" | "prism_session_append_idempotency" | "prism_runs" | "prism_agent_events" | "prism_tool_calls" | "prism_usage" | "prism_run_feedback" | "prism_retention_policies" | "prism_legal_holds" | "prism_tenant_quotas" | "prism_migrations";
|
|
3
|
+
export declare const PERSISTENCE_SCHEMA_VERSION = 7;
|
|
4
|
+
export type PersistenceTableName = "prism_tenants" | "prism_accounts" | "prism_users" | "prism_agent_definitions" | "prism_sessions" | "prism_branches" | "prism_session_entries" | "prism_session_append_idempotency" | "prism_runs" | "prism_agent_events" | "prism_agent_event_streams" | "prism_tool_calls" | "prism_usage" | "prism_run_feedback" | "prism_retention_policies" | "prism_legal_holds" | "prism_tenant_quotas" | "prism_migrations";
|
|
5
5
|
export type PersistenceColumnType = "text" | "integer" | "number" | "boolean" | "json" | "timestamp";
|
|
6
6
|
export interface PersistenceColumnDefinition {
|
|
7
7
|
readonly name: string;
|
|
@@ -4,7 +4,7 @@ import { createHash } from "node:crypto";
|
|
|
4
4
|
// this module defines the shared table/index/pagination/migration expectations
|
|
5
5
|
// adapter authors implement and test against before shipping dialect-specific DDL.
|
|
6
6
|
/** Current shared persistence schema version for production database adapters. */
|
|
7
|
-
export const PERSISTENCE_SCHEMA_VERSION =
|
|
7
|
+
export const PERSISTENCE_SCHEMA_VERSION = 7;
|
|
8
8
|
/** Guidance adapters must follow: values are bound parameters, never interpolated. */
|
|
9
9
|
export const PARAMETERIZED_QUERY_GUIDANCE = "Bind every user-supplied value (session ids, idempotency keys, tenant ids, timestamps, JSON payloads) as a query parameter. Quote/validate schema and table identifiers only; never interpolate untrusted strings into SQL text.";
|
|
10
10
|
const TENANT_COLUMNS = [
|
|
@@ -177,6 +177,17 @@ export function createPersistenceSchemaModel() {
|
|
|
177
177
|
],
|
|
178
178
|
foreignKeys: [{ columns: ["session_id"], referencesTable: "prism_sessions", referencesColumns: ["id"] }],
|
|
179
179
|
},
|
|
180
|
+
{
|
|
181
|
+
name: "prism_agent_event_streams",
|
|
182
|
+
primaryKey: ["session_id", "run_id"],
|
|
183
|
+
columns: [
|
|
184
|
+
{ name: "session_id", type: "text" },
|
|
185
|
+
{ name: "run_id", type: "text" },
|
|
186
|
+
{ name: "next_sequence", type: "integer" },
|
|
187
|
+
{ name: "updated_at", type: "timestamp" },
|
|
188
|
+
],
|
|
189
|
+
foreignKeys: [{ columns: ["session_id"], referencesTable: "prism_sessions", referencesColumns: ["id"] }],
|
|
190
|
+
},
|
|
180
191
|
{
|
|
181
192
|
name: "prism_tool_calls",
|
|
182
193
|
primaryKey: ["id"],
|
|
@@ -369,6 +380,7 @@ export function createPersistenceSchemaModel() {
|
|
|
369
380
|
name: "prism_agent_events_run_sequence_idx",
|
|
370
381
|
table: "prism_agent_events",
|
|
371
382
|
columns: ["run_id", "sequence"],
|
|
383
|
+
unique: true,
|
|
372
384
|
purpose: "stable per-run event timeline pagination",
|
|
373
385
|
},
|
|
374
386
|
{
|
|
@@ -377,6 +389,12 @@ export function createPersistenceSchemaModel() {
|
|
|
377
389
|
columns: ["session_id", "timestamp", "id"],
|
|
378
390
|
purpose: "event stream pagination",
|
|
379
391
|
},
|
|
392
|
+
{
|
|
393
|
+
name: "prism_agent_events_owner_timestamp_sequence_idx",
|
|
394
|
+
table: "prism_agent_events",
|
|
395
|
+
columns: ["tenant_id", "account_id", "user_id", "timestamp", "sequence", "id"],
|
|
396
|
+
purpose: "owned durable event retention cleanup",
|
|
397
|
+
},
|
|
380
398
|
{
|
|
381
399
|
name: "prism_tool_calls_session_name_started_idx",
|
|
382
400
|
table: "prism_tool_calls",
|
|
@@ -463,34 +481,51 @@ function migrationStep(version, name, description) {
|
|
|
463
481
|
const content = version === 1
|
|
464
482
|
? {
|
|
465
483
|
tables: model.tables
|
|
466
|
-
.filter((table) => table.name !== "prism_run_feedback")
|
|
484
|
+
.filter((table) => table.name !== "prism_run_feedback" && table.name !== "prism_agent_event_streams")
|
|
467
485
|
.map((table) => table.name === "prism_usage"
|
|
468
486
|
? { ...table, columns: table.columns.filter((column) => !["scope", "turn", "attempt"].includes(column.name)) }
|
|
469
487
|
: table),
|
|
470
|
-
indexes: model.indexes
|
|
488
|
+
indexes: model.indexes
|
|
489
|
+
.filter((index) => !index.name.startsWith("prism_usage_session_scope_") &&
|
|
490
|
+
!index.name.startsWith("prism_run_feedback_") &&
|
|
491
|
+
!index.name.startsWith("prism_agent_event_streams_") &&
|
|
492
|
+
!index.name.startsWith("prism_agent_events_owner_timestamp_"))
|
|
493
|
+
.map((index) => index.name === "prism_agent_events_run_sequence_idx"
|
|
494
|
+
? (() => {
|
|
495
|
+
const { unique: _unique, ...legacy } = index;
|
|
496
|
+
return legacy;
|
|
497
|
+
})()
|
|
498
|
+
: index),
|
|
471
499
|
}
|
|
472
|
-
: version ===
|
|
473
|
-
? {
|
|
474
|
-
: version ===
|
|
500
|
+
: version === 7
|
|
501
|
+
? { indexes: ["prism_agent_events_owner_timestamp_sequence_idx"] }
|
|
502
|
+
: version === 6
|
|
475
503
|
? {
|
|
476
|
-
tables: ["
|
|
477
|
-
indexes:
|
|
504
|
+
tables: ["prism_agent_event_streams"],
|
|
505
|
+
indexes: ["prism_agent_events_run_sequence_idx"],
|
|
478
506
|
}
|
|
479
|
-
: version ===
|
|
480
|
-
?
|
|
481
|
-
|
|
482
|
-
: version === 5
|
|
507
|
+
: version === 2
|
|
508
|
+
? { table: "prism_usage", columns: ["scope", "turn", "attempt"], indexes: ["prism_usage_session_scope_recorded_idx"] }
|
|
509
|
+
: version === 3
|
|
483
510
|
? {
|
|
484
|
-
tables: ["
|
|
485
|
-
indexes:
|
|
486
|
-
"prism_legal_holds_owner_resource_idx",
|
|
487
|
-
"prism_legal_holds_created_id_idx",
|
|
488
|
-
"prism_tenant_quotas_owner_kind_idx",
|
|
489
|
-
],
|
|
511
|
+
tables: ["prism_run_feedback"],
|
|
512
|
+
indexes: model.indexes.filter((index) => index.name.startsWith("prism_run_feedback_")).map((index) => index.name),
|
|
490
513
|
}
|
|
491
|
-
:
|
|
492
|
-
|
|
493
|
-
|
|
514
|
+
: version === 4
|
|
515
|
+
? // Adapter-local FTS objects (SQLite FTS5 / Postgres tsvector) map to this canonical name.
|
|
516
|
+
{ search: ["prism_session_search"], indexes: ["prism_sessions_updated_id_idx"] }
|
|
517
|
+
: version === 5
|
|
518
|
+
? {
|
|
519
|
+
tables: ["prism_legal_holds", "prism_tenant_quotas"],
|
|
520
|
+
indexes: [
|
|
521
|
+
"prism_legal_holds_owner_resource_idx",
|
|
522
|
+
"prism_legal_holds_created_id_idx",
|
|
523
|
+
"prism_tenant_quotas_owner_kind_idx",
|
|
524
|
+
],
|
|
525
|
+
}
|
|
526
|
+
: (() => {
|
|
527
|
+
throw new Error(`Unknown migration version ${version}`);
|
|
528
|
+
})();
|
|
494
529
|
return {
|
|
495
530
|
version,
|
|
496
531
|
name,
|
|
@@ -509,6 +544,8 @@ export function createPersistenceMigrationContract() {
|
|
|
509
544
|
migrationStep(3, "003_run_feedback", "Add immutable ownership-scoped run/trace feedback and evaluation links."),
|
|
510
545
|
migrationStep(4, "004_session_search", "Add bounded session search indexes and adapter-local FTS objects."),
|
|
511
546
|
migrationStep(5, "005_lifecycle_hold_quota", "Add legal-hold and tenant-quota tables for retention lifecycle."),
|
|
547
|
+
migrationStep(6, "006_agent_event_source", "Add transactional per-run event counters and unique durable event sequencing."),
|
|
548
|
+
migrationStep(7, "007_agent_event_retention_index", "Add an exact-owner durable-event retention cleanup index."),
|
|
512
549
|
],
|
|
513
550
|
lockGuidance: "Acquire a dialect-specific migration lock before applying steps (PostgreSQL advisory lock; SQLite exclusive transaction). Only one process should migrate at a time.",
|
|
514
551
|
leastPrivilegeGuidance: "Run migrations with a DDL-capable role; use a separate least-privilege runtime role limited to INSERT/SELECT/UPDATE on adapter tables. Never grant migration credentials to the agent runtime.",
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { AgentIdentity, ToolEffectKey, ToolEffectStore } from "../contracts.js";
|
|
2
|
+
export interface ToolEffectStoreConformanceOptions {
|
|
3
|
+
readonly identity?: AgentIdentity;
|
|
4
|
+
readonly ownership?: ToolEffectKey["ownership"];
|
|
5
|
+
readonly key?: string;
|
|
6
|
+
}
|
|
7
|
+
/** Assert core claim/CAS, duplicate, reconciliation, and cleanup semantics without a test framework. */
|
|
8
|
+
export declare function assertToolEffectStoreConforms(factory: () => ToolEffectStore | Promise<ToolEffectStore>, options?: ToolEffectStoreConformanceOptions): Promise<void>;
|
|
9
|
+
export declare function runToolEffectStoreConformance(factory: () => ToolEffectStore | Promise<ToolEffectStore>, options?: ToolEffectStoreConformanceOptions): Promise<void>;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/** Assert core claim/CAS, duplicate, reconciliation, and cleanup semantics without a test framework. */
|
|
2
|
+
export async function assertToolEffectStoreConforms(factory, options = {}) {
|
|
3
|
+
const store = await factory();
|
|
4
|
+
const identity = options.identity ?? testIdentity();
|
|
5
|
+
const ownership = options.ownership ?? { tenantId: identity.tenantId };
|
|
6
|
+
const base = key(identity, ownership, options.key ?? "prism:tool-effect:v1:conformance");
|
|
7
|
+
const first = await store.begin(base);
|
|
8
|
+
if (first.outcome !== "acquired" || first.record.status !== "pending" || !first.record.claimToken) {
|
|
9
|
+
throw new Error("store must acquire an absent tool effect as pending with a claim token");
|
|
10
|
+
}
|
|
11
|
+
const duplicate = await store.begin(base);
|
|
12
|
+
if (duplicate.outcome !== "existing" || duplicate.record.status !== "pending") {
|
|
13
|
+
throw new Error("store must return existing pending effects without a second claim");
|
|
14
|
+
}
|
|
15
|
+
const dispatched = await store.markDispatched(transition(base, first.record));
|
|
16
|
+
if (dispatched.status !== "dispatched" || dispatched.version !== first.record.version + 1) {
|
|
17
|
+
throw new Error("store must transition a claimed pending effect to dispatched");
|
|
18
|
+
}
|
|
19
|
+
const result = { toolCallId: base.toolCallId, name: base.toolName, value: { ok: true } };
|
|
20
|
+
const completed = await store.complete({ ...transition(base, dispatched), result });
|
|
21
|
+
if (completed.status !== "completed" || completed.result?.toolCallId !== base.toolCallId) {
|
|
22
|
+
throw new Error("store must retain a completed bounded result");
|
|
23
|
+
}
|
|
24
|
+
const replay = await store.begin(base);
|
|
25
|
+
if (replay.outcome !== "existing" || replay.record.status !== "completed") {
|
|
26
|
+
throw new Error("store must preserve completed duplicate state");
|
|
27
|
+
}
|
|
28
|
+
await expectReject(() => store.markDispatched(transition(base, dispatched)), "store must reject stale claim/version transitions");
|
|
29
|
+
const unknownKey = key(identity, ownership, `${base.key}:unknown`, "call-unknown");
|
|
30
|
+
const unknownPending = await store.begin(unknownKey);
|
|
31
|
+
const unknownDispatched = await store.markDispatched(transition(unknownKey, unknownPending.record));
|
|
32
|
+
const unknown = await store.markUnknown({ ...transition(unknownKey, unknownDispatched), failure: { code: "test" } });
|
|
33
|
+
if (unknown.status !== "unknown")
|
|
34
|
+
throw new Error("store must mark dispatched effects unknown");
|
|
35
|
+
const resolved = await store.resolveUnknown({
|
|
36
|
+
...unknownKey,
|
|
37
|
+
expectedVersion: unknown.version,
|
|
38
|
+
status: "failed_terminal",
|
|
39
|
+
failure: { code: "test" },
|
|
40
|
+
});
|
|
41
|
+
if (resolved.status !== "failed_terminal")
|
|
42
|
+
throw new Error("store must CAS-resolve unknown effects");
|
|
43
|
+
const cleanup = await store.cleanup({ ownership, before: new Date(Date.now() + 60_000).toISOString(), limit: 100 });
|
|
44
|
+
if (cleanup.deleted < 1)
|
|
45
|
+
throw new Error("store cleanup must remove terminal effects");
|
|
46
|
+
}
|
|
47
|
+
export async function runToolEffectStoreConformance(factory, options = {}) {
|
|
48
|
+
await assertToolEffectStoreConforms(factory, options);
|
|
49
|
+
}
|
|
50
|
+
function key(identity, ownership, value, toolCallId = "call") {
|
|
51
|
+
return {
|
|
52
|
+
identity,
|
|
53
|
+
ownership,
|
|
54
|
+
key: value,
|
|
55
|
+
sessionId: "session",
|
|
56
|
+
runId: "run",
|
|
57
|
+
toolCallId,
|
|
58
|
+
toolName: "effect.tool",
|
|
59
|
+
argumentsHash: "a".repeat(64),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function transition(base, record) {
|
|
63
|
+
if (!record.claimToken)
|
|
64
|
+
throw new Error("store transition record lacks claim token");
|
|
65
|
+
return { ...base, claimToken: record.claimToken, expectedVersion: record.version };
|
|
66
|
+
}
|
|
67
|
+
async function expectReject(run, message) {
|
|
68
|
+
try {
|
|
69
|
+
await run();
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
throw new Error(message);
|
|
75
|
+
}
|
|
76
|
+
function testIdentity() {
|
|
77
|
+
return {
|
|
78
|
+
tenantId: "tenant",
|
|
79
|
+
principal: { kind: "service", id: "conformance" },
|
|
80
|
+
scopes: ["tools:execute"],
|
|
81
|
+
issuedAt: "2026-01-01T00:00:00.000Z",
|
|
82
|
+
verified: true,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=tool-effect-store-conformance.js.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { JsonObject, ToolEffectKey, ToolEffectStore } from "./contracts.js";
|
|
2
|
+
export type ToolEffectErrorCode = "ERR_PRISM_TOOL_EFFECT_REQUIRED" | "ERR_PRISM_TOOL_EFFECT_CONFLICT" | "ERR_PRISM_TOOL_EFFECT_UNKNOWN" | "ERR_PRISM_TOOL_EFFECT_COMPLETED" | "ERR_PRISM_TOOL_EFFECT_LIMIT";
|
|
3
|
+
export declare class ToolEffectError extends Error {
|
|
4
|
+
readonly code: ToolEffectErrorCode;
|
|
5
|
+
constructor(code: ToolEffectErrorCode, message: string);
|
|
6
|
+
}
|
|
7
|
+
/** Stable JSON representation for an already-validated tool arguments object. */
|
|
8
|
+
export declare function canonicalToolEffectJson(value: unknown): string;
|
|
9
|
+
export declare function toolEffectArgumentsHash(argumentsValue: JsonObject): string;
|
|
10
|
+
/** Derives the only core-authoritative key. Callers never supply this from model input. */
|
|
11
|
+
export declare function deriveToolEffectKey(input: Omit<ToolEffectKey, "key" | "signal">): string;
|
|
12
|
+
/** In-process reference. Use a durable adapter for cross-replica claims. */
|
|
13
|
+
export declare function createMemoryToolEffectStore(options?: {
|
|
14
|
+
readonly now?: () => number;
|
|
15
|
+
}): ToolEffectStore;
|