@arnilo/prism 0.0.96 → 0.1.0
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 +285 -2
- package/README.md +17 -3
- package/dist/agent-definitions.js +2 -3
- package/dist/agent-event-source.d.ts +11 -0
- package/dist/agent-event-source.js +512 -0
- package/dist/agent-loops.d.ts +5 -0
- package/dist/agent-loops.js +99 -14
- package/dist/agent-run-lifecycle.d.ts +5 -2
- package/dist/agent-run-lifecycle.js +18 -2
- package/dist/agent-run-state.d.ts +27 -1
- package/dist/agent-run-state.js +113 -7
- package/dist/agents.d.ts +3 -1
- package/dist/agents.js +1255 -129
- package/dist/artifacts.d.ts +132 -0
- package/dist/artifacts.js +44 -0
- package/dist/cache-helpers.js +18 -9
- package/dist/checkpoints.d.ts +4 -0
- package/dist/checkpoints.js +17 -9
- package/dist/cli-init.js +3 -7
- package/dist/cli-runner.d.ts +2 -6
- package/dist/cli-runner.js +71 -33
- package/dist/compaction.js +5 -4
- package/dist/config.js +7 -4
- package/dist/content.js +26 -24
- package/dist/context-budget.d.ts +67 -0
- package/dist/context-budget.js +288 -0
- package/dist/contracts.d.ts +590 -8
- package/dist/contracts.js +142 -1
- package/dist/contribution-parsing.js +6 -2
- package/dist/contributions.d.ts +2 -0
- package/dist/contributions.js +3 -0
- package/dist/conversations.d.ts +50 -0
- package/dist/conversations.js +98 -0
- package/dist/credentials.d.ts +22 -2
- package/dist/credentials.js +18 -3
- package/dist/devices.d.ts +94 -0
- package/dist/devices.js +138 -0
- package/dist/event-multiplexer.js +18 -4
- package/dist/extensions.d.ts +18 -1
- package/dist/extensions.js +79 -6
- package/dist/feedback.js +12 -10
- package/dist/guardrails.d.ts +1 -1
- package/dist/guardrails.js +26 -17
- package/dist/identity.d.ts +92 -0
- package/dist/identity.js +265 -0
- package/dist/index.d.ts +94 -72
- package/dist/index.js +48 -36
- package/dist/input.d.ts +10 -1
- package/dist/input.js +152 -52
- package/dist/instruction-injection.d.ts +1 -1
- package/dist/middleware.js +9 -1
- package/dist/models.d.ts +2 -0
- package/dist/models.js +3 -0
- package/dist/node/agent-definitions.js +16 -8
- package/dist/node/contribution-discovery.d.ts +1 -2
- package/dist/node/contribution-discovery.js +3 -3
- package/dist/node/session-store-jsonl.js +13 -7
- package/dist/node/settings.d.ts +1 -1
- package/dist/node/settings.js +1 -1
- package/dist/node/system-project-prompts.js +2 -4
- package/dist/node/trust.js +1 -1
- package/dist/persistence-lifecycle.d.ts +103 -0
- package/dist/persistence-lifecycle.js +202 -0
- package/dist/provider-events.d.ts +1 -0
- package/dist/provider-events.js +6 -1
- package/dist/provider-request-policy.js +3 -4
- package/dist/providers/media.d.ts +1 -1
- package/dist/providers/openai-compatible.d.ts +46 -1
- package/dist/providers/openai-compatible.js +123 -53
- package/dist/providers/openai-primitives.js +10 -7
- package/dist/providers/transport.d.ts +6 -0
- package/dist/providers/transport.js +21 -0
- package/dist/providers.d.ts +2 -0
- package/dist/providers.js +3 -0
- package/dist/redaction.d.ts +1 -0
- package/dist/redaction.js +26 -9
- package/dist/resources.d.ts +2 -2
- package/dist/resources.js +2 -2
- package/dist/retry.d.ts +5 -0
- package/dist/retry.js +8 -1
- package/dist/rpc.js +55 -11
- package/dist/run-ledger.d.ts +6 -0
- package/dist/run-ledger.js +16 -13
- package/dist/run-limits.js +49 -10
- package/dist/secure-agent.js +8 -2
- package/dist/security.js +7 -2
- package/dist/session-stores.d.ts +7 -2
- package/dist/session-stores.js +195 -21
- package/dist/skill-disclosure.d.ts +35 -0
- package/dist/skill-disclosure.js +101 -0
- package/dist/skill-load.d.ts +25 -0
- package/dist/skill-load.js +112 -0
- package/dist/structured-output.d.ts +5 -1
- package/dist/structured-output.js +20 -2
- package/dist/system-prompts.js +7 -2
- package/dist/testing/agent-event-source-conformance.d.ts +4 -0
- package/dist/testing/agent-event-source-conformance.js +54 -0
- package/dist/testing/compaction-conformance.js +5 -1
- package/dist/testing/extension-conformance.js +15 -3
- package/dist/testing/feedback.d.ts +1 -3
- package/dist/testing/feedback.js +1 -1
- package/dist/testing/persistence-schema.d.ts +2 -2
- package/dist/testing/persistence-schema.js +280 -35
- package/dist/testing/provider-conformance.js +3 -3
- package/dist/testing/run-ledger-conformance.js +1 -1
- package/dist/testing/session-store-conformance.d.ts +6 -0
- package/dist/testing/session-store-conformance.js +37 -2
- package/dist/testing/tool-conformance.js +30 -5
- package/dist/testing/tool-effect-store-conformance.d.ts +9 -0
- package/dist/testing/tool-effect-store-conformance.js +85 -0
- package/dist/thinking.js +4 -1
- package/dist/tool-effects.d.ts +15 -0
- package/dist/tool-effects.js +352 -0
- package/dist/tool-result-fold.d.ts +40 -0
- package/dist/tool-result-fold.js +176 -0
- package/dist/tools.d.ts +8 -3
- package/dist/tools.js +248 -13
- package/docs/0.1.0-readiness.md +202 -0
- package/docs/a2a.md +33 -2
- package/docs/acp.md +126 -0
- package/docs/ag-ui-adoption.md +77 -0
- package/docs/ag-ui.md +225 -0
- package/docs/agent-events.md +34 -3
- package/docs/agent-identity.md +144 -0
- package/docs/agent-loops.md +17 -2
- package/docs/agent-session-runtime.md +21 -4
- package/docs/browser-automation.md +5 -0
- package/docs/caveman.md +129 -0
- package/docs/cli-rpc.md +3 -6
- package/docs/coding-agent-tools.md +229 -25
- package/docs/coding-security.md +77 -11
- package/docs/compaction-and-retry.md +5 -2
- package/docs/compaction-llm.md +20 -1
- package/docs/compaction-observational-memory.md +52 -8
- package/docs/context-and-skills.md +94 -7
- package/docs/contribution-registries.md +1 -0
- package/docs/conversations.md +135 -0
- package/docs/credential-storage.md +34 -1
- package/docs/credentials-and-redaction.md +11 -1
- package/docs/database-persistence.md +27 -7
- package/docs/device-adapters.md +97 -0
- package/docs/enterprise-postgres-state.md +178 -0
- package/docs/evaluations.md +14 -1
- package/docs/extensions.md +4 -1
- package/docs/forge-integration.md +113 -0
- package/docs/guardrails.md +16 -2
- package/docs/host-security.md +35 -4
- package/docs/index.md +69 -37
- package/docs/input-and-prompt-assembly.md +8 -7
- package/docs/language-intelligence.md +162 -0
- package/docs/mcp-tools.md +62 -5
- package/docs/middleware-hooks.md +2 -2
- package/docs/migration.md +423 -2
- package/docs/model-routing.md +111 -0
- package/docs/multimodal-content.md +8 -5
- package/docs/node-jsonl-session-store.md +1 -1
- package/docs/observability.md +2 -0
- package/docs/openapi-tools.md +56 -0
- package/docs/performance.md +282 -0
- package/docs/policy-and-audit.md +171 -0
- package/docs/ponytail.md +127 -0
- package/docs/postgres-persistence.md +8 -4
- package/docs/process-sessions.md +147 -0
- package/docs/provider-caching.md +13 -1
- package/docs/provider-conformance.md +29 -5
- package/docs/provider-packages.md +43 -2
- package/docs/provider-request-policies.md +2 -0
- package/docs/providers/ai-sdk.md +24 -7
- package/docs/providers/alibaba.md +179 -0
- package/docs/providers/anthropic.md +93 -0
- package/docs/providers/azure.md +74 -0
- package/docs/providers/bedrock.md +72 -0
- package/docs/providers/google.md +89 -0
- package/docs/providers/ollama.md +166 -0
- package/docs/providers/openai-compatible.md +31 -2
- package/docs/providers/openai.md +24 -5
- package/docs/providers/openrouter.md +2 -0
- package/docs/providers/vertex.md +71 -0
- package/docs/public-contracts.md +61 -4
- package/docs/rag.md +41 -12
- package/docs/release-and-install.md +323 -206
- package/docs/resource-loading.md +3 -0
- package/docs/runs-and-usage.md +3 -0
- package/docs/server.md +44 -6
- package/docs/session-store-conformance.md +2 -0
- package/docs/session-stores.md +41 -2
- package/docs/sqlite-persistence.md +11 -3
- package/docs/structured-output.md +7 -1
- package/docs/supervisors.md +8 -0
- package/docs/tool-effects.md +95 -0
- package/docs/tools.md +5 -0
- package/docs/work-artifacts-and-review.md +102 -0
- package/docs/work-connectors.md +32 -0
- package/docs/work-tools.md +137 -0
- package/docs/workflows.md +6 -0
- package/docs/working-and-semantic-memory.md +40 -7
- package/package.json +30 -8
- package/templates/init/providers.json +22 -0
- package/docs/review-coverage-2026-07-14.md +0 -260
- package/docs/review-coverage-2026-07-15.md +0 -193
- package/docs/review-coverage-2026-07-17-provider-validation.md +0 -192
- package/docs/review-coverage-2026-07-19-phase-3.md +0 -174
- package/docs/review-coverage-2026-07-20-phase-4.md +0 -175
|
@@ -110,12 +110,13 @@ export function mapOpenAIChatUsage(usage) {
|
|
|
110
110
|
if (!usage || typeof usage !== "object" || Array.isArray(usage))
|
|
111
111
|
return undefined;
|
|
112
112
|
const wire = usage;
|
|
113
|
-
if (wire.prompt_tokens === undefined
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
113
|
+
if (wire.prompt_tokens === undefined &&
|
|
114
|
+
wire.completion_tokens === undefined &&
|
|
115
|
+
wire.total_tokens === undefined &&
|
|
116
|
+
wire.prompt_cache_hit_tokens === undefined &&
|
|
117
|
+
wire.prompt_tokens_details?.cached_tokens === undefined &&
|
|
118
|
+
wire.prompt_tokens_details?.cache_write_tokens === undefined &&
|
|
119
|
+
wire.prompt_tokens_details?.cache_creation_input_tokens === undefined) {
|
|
119
120
|
return undefined;
|
|
120
121
|
}
|
|
121
122
|
return {
|
|
@@ -123,7 +124,9 @@ export function mapOpenAIChatUsage(usage) {
|
|
|
123
124
|
outputTokens: wire.completion_tokens,
|
|
124
125
|
totalTokens: wire.total_tokens,
|
|
125
126
|
cacheReadTokens: wire.prompt_tokens_details?.cached_tokens ?? wire.prompt_cache_hit_tokens,
|
|
126
|
-
|
|
127
|
+
// Some OpenAI-compatible vendors report cache writes as `cache_write_tokens`,
|
|
128
|
+
// others as the `cache_creation_input_tokens` variant; accept both.
|
|
129
|
+
cacheWriteTokens: wire.prompt_tokens_details?.cache_write_tokens ?? wire.prompt_tokens_details?.cache_creation_input_tokens,
|
|
127
130
|
};
|
|
128
131
|
}
|
|
129
132
|
//# sourceMappingURL=openai-primitives.js.map
|
|
@@ -20,6 +20,12 @@ export declare class ProviderTransportError extends Error {
|
|
|
20
20
|
readonly limitBytes?: number;
|
|
21
21
|
constructor(code: ProviderTransportErrorCode, message: string, limitBytes?: number);
|
|
22
22
|
}
|
|
23
|
+
/** HTTP failure error carrying the status as numeric `code` plus any `Retry-After`
|
|
24
|
+
* hint as `retryAfterMs`, so retry policies classify transience and pace retries
|
|
25
|
+
* without parsing message text. Both fields flow into `ErrorInfo` via errorToErrorInfo. */
|
|
26
|
+
export declare function httpStatusError(prefix: string, response: Response, bodyText: string): Error;
|
|
27
|
+
/** Parse a `Retry-After` header (delay-seconds or HTTP-date) into milliseconds. */
|
|
28
|
+
export declare function parseRetryAfterMs(value: string | null, now?: number): number | undefined;
|
|
23
29
|
export interface ReadSseEventsOptions extends BoundedStreamLimits {
|
|
24
30
|
readonly signal?: AbortSignal;
|
|
25
31
|
}
|
|
@@ -13,6 +13,27 @@ export class ProviderTransportError extends Error {
|
|
|
13
13
|
this.limitBytes = limitBytes;
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
|
+
/** HTTP failure error carrying the status as numeric `code` plus any `Retry-After`
|
|
17
|
+
* hint as `retryAfterMs`, so retry policies classify transience and pace retries
|
|
18
|
+
* without parsing message text. Both fields flow into `ErrorInfo` via errorToErrorInfo. */
|
|
19
|
+
export function httpStatusError(prefix, response, bodyText) {
|
|
20
|
+
const error = new Error(`${prefix}: ${response.status} ${bodyText}`);
|
|
21
|
+
error.code = response.status;
|
|
22
|
+
const hint = parseRetryAfterMs(response.headers.get("retry-after"));
|
|
23
|
+
if (hint !== undefined)
|
|
24
|
+
error.retryAfterMs = hint;
|
|
25
|
+
return error;
|
|
26
|
+
}
|
|
27
|
+
/** Parse a `Retry-After` header (delay-seconds or HTTP-date) into milliseconds. */
|
|
28
|
+
export function parseRetryAfterMs(value, now = Date.now()) {
|
|
29
|
+
if (!value)
|
|
30
|
+
return undefined;
|
|
31
|
+
const seconds = Number(value);
|
|
32
|
+
if (Number.isFinite(seconds) && seconds >= 0)
|
|
33
|
+
return seconds * 1000;
|
|
34
|
+
const date = Date.parse(value);
|
|
35
|
+
return Number.isNaN(date) ? undefined : Math.max(0, date - now);
|
|
36
|
+
}
|
|
16
37
|
function resolveLimits(options) {
|
|
17
38
|
return {
|
|
18
39
|
maxEventBytes: options?.maxEventBytes ?? DEFAULT_MAX_EVENT_BYTES,
|
package/dist/providers.d.ts
CHANGED
|
@@ -2,6 +2,8 @@ import type { AIProvider, ModelConfig, ProviderResolver } from "./contracts.js";
|
|
|
2
2
|
import { type DuplicateRegistrationOptions } from "./registry-options.js";
|
|
3
3
|
export interface ProviderRegistry {
|
|
4
4
|
register(provider: AIProvider): void;
|
|
5
|
+
/** Remove a provider; returns false when the id was not registered. */
|
|
6
|
+
unregister(id: string): boolean;
|
|
5
7
|
get(id: string): AIProvider | undefined;
|
|
6
8
|
resolve(model: Pick<ModelConfig, "provider"> | string): AIProvider;
|
|
7
9
|
list(): readonly AIProvider[];
|
package/dist/providers.js
CHANGED
|
@@ -6,6 +6,9 @@ export function createProviderRegistry(providers = [], options = {}) {
|
|
|
6
6
|
assertCanRegister(byId, provider.id, "provider", provider.id, options.duplicate);
|
|
7
7
|
byId.set(provider.id, provider);
|
|
8
8
|
},
|
|
9
|
+
unregister(id) {
|
|
10
|
+
return byId.delete(id);
|
|
11
|
+
},
|
|
9
12
|
get(id) {
|
|
10
13
|
return byId.get(id);
|
|
11
14
|
},
|
package/dist/redaction.d.ts
CHANGED
|
@@ -8,5 +8,6 @@ export declare function redactAgentEvent(event: AgentEvent, redactor?: SecretRed
|
|
|
8
8
|
export declare function redactSessionEntry(entry: SessionEntry, redactor?: SecretRedactor): SessionEntry;
|
|
9
9
|
export declare function redactProviderRequest(request: ProviderRequest, redactor?: SecretRedactor): ProviderRequest;
|
|
10
10
|
export declare function redactRunLedgerRecord<T extends RunLedgerRecord>(record: T, redactor?: SecretRedactor): T;
|
|
11
|
+
export declare function resolveRedactor(redactor?: SecretRedactor, secrets?: readonly (string | undefined)[]): SecretRedactor | undefined;
|
|
11
12
|
export declare function redactSecrets<T>(value: T, secrets: readonly (string | undefined)[]): T;
|
|
12
13
|
export declare function errorToErrorInfo(error: unknown, secrets?: readonly (string | undefined)[]): ErrorInfo;
|
package/dist/redaction.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
const REDACTED = "[REDACTED]";
|
|
2
|
+
// Depth bound matching agent-run-state.ts; hostile deep structures yield a placeholder
|
|
3
|
+
// instead of a stack overflow.
|
|
4
|
+
const MAX_REDACT_DEPTH = 32;
|
|
2
5
|
export function createSecretRedactor(secrets) {
|
|
3
6
|
return { redact: (value) => redactSecrets(value, secrets) };
|
|
4
7
|
}
|
|
@@ -17,6 +20,9 @@ export function redactProviderRequest(request, redactor) {
|
|
|
17
20
|
export function redactRunLedgerRecord(record, redactor) {
|
|
18
21
|
return redactor?.redact(record) ?? record;
|
|
19
22
|
}
|
|
23
|
+
export function resolveRedactor(redactor, secrets) {
|
|
24
|
+
return redactor ?? (secrets?.some((secret) => Boolean(secret)) ? createSecretRedactor(secrets) : undefined);
|
|
25
|
+
}
|
|
20
26
|
export function redactSecrets(value, secrets) {
|
|
21
27
|
const needles = secrets.filter((secret) => Boolean(secret));
|
|
22
28
|
if (needles.length === 0)
|
|
@@ -28,23 +34,25 @@ export function redactSecrets(value, secrets) {
|
|
|
28
34
|
return String(key);
|
|
29
35
|
};
|
|
30
36
|
const assignKey = (target, key, value) => {
|
|
31
|
-
if (!Object.
|
|
37
|
+
if (!Object.hasOwn(target, key)) {
|
|
32
38
|
target[key] = value;
|
|
33
39
|
return;
|
|
34
40
|
}
|
|
35
41
|
let suffix = 2;
|
|
36
|
-
while (Object.
|
|
42
|
+
while (Object.hasOwn(target, `${key}__${suffix}`))
|
|
37
43
|
suffix += 1;
|
|
38
44
|
target[`${key}__${suffix}`] = value;
|
|
39
45
|
};
|
|
40
46
|
// ponytail: active-path WeakSet marks only ancestor cycles as [Circular]; shared
|
|
41
47
|
// references (diamonds) are visited again on separate branches. Map/Set normalize
|
|
42
48
|
// to JSON-shaped output; string keys are redacted like values.
|
|
43
|
-
const redact = (input, active = new WeakSet()) => {
|
|
49
|
+
const redact = (input, active = new WeakSet(), depth = 0) => {
|
|
44
50
|
if (typeof input === "string")
|
|
45
51
|
return redactString(input);
|
|
46
52
|
if (input === null || typeof input !== "object")
|
|
47
53
|
return input;
|
|
54
|
+
if (depth >= MAX_REDACT_DEPTH)
|
|
55
|
+
return "[MaxDepth]";
|
|
48
56
|
if (input instanceof Date || input instanceof RegExp)
|
|
49
57
|
return input;
|
|
50
58
|
if (ArrayBuffer.isView(input) || input instanceof ArrayBuffer)
|
|
@@ -54,18 +62,18 @@ export function redactSecrets(value, secrets) {
|
|
|
54
62
|
active.add(input);
|
|
55
63
|
try {
|
|
56
64
|
if (Array.isArray(input))
|
|
57
|
-
return input.map((item) => redact(item, active));
|
|
65
|
+
return input.map((item) => redact(item, active, depth + 1));
|
|
58
66
|
if (input instanceof Map) {
|
|
59
67
|
const out = {};
|
|
60
68
|
for (const [key, item] of input)
|
|
61
|
-
assignKey(out, redactKey(key), redact(item, active));
|
|
69
|
+
assignKey(out, redactKey(key), redact(item, active, depth + 1));
|
|
62
70
|
return out;
|
|
63
71
|
}
|
|
64
72
|
if (input instanceof Set)
|
|
65
|
-
return [...input].map((item) => redact(item, active));
|
|
73
|
+
return [...input].map((item) => redact(item, active, depth + 1));
|
|
66
74
|
const out = {};
|
|
67
75
|
for (const [key, item] of Object.entries(input))
|
|
68
|
-
assignKey(out, redactKey(key), redact(item, active));
|
|
76
|
+
assignKey(out, redactKey(key), redact(item, active, depth + 1));
|
|
69
77
|
return out;
|
|
70
78
|
}
|
|
71
79
|
finally {
|
|
@@ -76,18 +84,21 @@ export function redactSecrets(value, secrets) {
|
|
|
76
84
|
}
|
|
77
85
|
export function errorToErrorInfo(error, secrets = []) {
|
|
78
86
|
const code = readErrorCode(error);
|
|
87
|
+
const retry = readRetryAfterMs(error);
|
|
88
|
+
const retryAfter = retry !== undefined ? { retryAfterMs: retry } : {};
|
|
79
89
|
if (error instanceof Error) {
|
|
80
90
|
return {
|
|
81
91
|
name: error.name,
|
|
82
92
|
message: redactSecrets(error.message, secrets),
|
|
83
93
|
code,
|
|
94
|
+
...retryAfter,
|
|
84
95
|
cause: error.cause ? redactSecrets(String(error.cause), secrets) : undefined,
|
|
85
96
|
};
|
|
86
97
|
}
|
|
87
98
|
if (error && typeof error === "object" && "message" in error) {
|
|
88
|
-
return { message: redactSecrets(String(error.message), secrets), code };
|
|
99
|
+
return { message: redactSecrets(String(error.message), secrets), code, ...retryAfter };
|
|
89
100
|
}
|
|
90
|
-
return { message: redactSecrets(String(error), secrets), code };
|
|
101
|
+
return { message: redactSecrets(String(error), secrets), code, ...retryAfter };
|
|
91
102
|
}
|
|
92
103
|
function readErrorCode(error) {
|
|
93
104
|
if (!error || typeof error !== "object" || !("code" in error))
|
|
@@ -95,4 +106,10 @@ function readErrorCode(error) {
|
|
|
95
106
|
const code = error.code;
|
|
96
107
|
return typeof code === "string" || typeof code === "number" ? code : undefined;
|
|
97
108
|
}
|
|
109
|
+
function readRetryAfterMs(error) {
|
|
110
|
+
if (!error || typeof error !== "object" || !("retryAfterMs" in error))
|
|
111
|
+
return undefined;
|
|
112
|
+
const value = error.retryAfterMs;
|
|
113
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : undefined;
|
|
114
|
+
}
|
|
98
115
|
//# sourceMappingURL=redaction.js.map
|
package/dist/resources.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { type PrismManifest } from "./manifests.js";
|
|
2
|
-
import type { JsonObject, ResourceLoader, ResourceLoadContext } from "./contracts.js";
|
|
3
1
|
import { type MediaContentBounds } from "./content.js";
|
|
2
|
+
import type { JsonObject, ResourceLoadContext, ResourceLoader } from "./contracts.js";
|
|
3
|
+
import { type PrismManifest } from "./manifests.js";
|
|
4
4
|
export declare function loadTextResource(loader: ResourceLoader, uri: string, context?: ResourceLoadContext): Promise<string>;
|
|
5
5
|
export declare function loadJsonResource(loader: ResourceLoader, uri: string, context?: ResourceLoadContext): Promise<JsonObject>;
|
|
6
6
|
export declare function loadManifestResource(loader: ResourceLoader, uri: string, context?: ResourceLoadContext): Promise<PrismManifest>;
|
package/dist/resources.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { parsePrismManifest } from "./manifests.js";
|
|
2
1
|
import { assertJsonObject } from "./config.js";
|
|
3
|
-
import { DEFAULT_MAX_MEDIA_ITEM_BYTES, loadBoundedBinaryResource
|
|
2
|
+
import { DEFAULT_MAX_MEDIA_ITEM_BYTES, loadBoundedBinaryResource } from "./content.js";
|
|
3
|
+
import { parsePrismManifest } from "./manifests.js";
|
|
4
4
|
import { assertPermission, assertTrusted } from "./security.js";
|
|
5
5
|
export async function loadTextResource(loader, uri, context) {
|
|
6
6
|
await assertTrusted(context?.trust, { kind: "resource", target: uri, capability: "load", metadata: context?.metadata });
|
package/dist/retry.d.ts
CHANGED
|
@@ -5,6 +5,11 @@ export interface DefaultRetryPolicyOptions {
|
|
|
5
5
|
readonly baseDelayMs?: number;
|
|
6
6
|
readonly maxDelayMs?: number;
|
|
7
7
|
readonly transientCodes?: readonly (string | number)[];
|
|
8
|
+
/** Symmetric jitter fraction applied to computed delays (default 0.25 → ±25%).
|
|
9
|
+
* Prevents thundering-herd retries under a shared outage. Set 0 to disable. */
|
|
10
|
+
readonly jitter?: number;
|
|
11
|
+
/** Random source for jitter (tests); defaults to Math.random. */
|
|
12
|
+
readonly random?: () => number;
|
|
8
13
|
}
|
|
9
14
|
export declare function createDefaultRetryPolicy(options?: DefaultRetryPolicyOptions): RetryPolicy;
|
|
10
15
|
export declare function isTransientErrorInfo(error: ErrorInfo, transientCodes?: ReadonlySet<string | number>): boolean;
|
package/dist/retry.js
CHANGED
|
@@ -22,13 +22,20 @@ export function createDefaultRetryPolicy(options = {}) {
|
|
|
22
22
|
const maxAttempts = Math.max(1, options.maxAttempts ?? 3);
|
|
23
23
|
const baseDelayMs = Math.max(0, options.baseDelayMs ?? 100);
|
|
24
24
|
const maxDelayMs = Math.max(baseDelayMs, options.maxDelayMs ?? 1000);
|
|
25
|
+
const jitter = Math.min(1, Math.max(0, options.jitter ?? 0.25));
|
|
26
|
+
const random = options.random ?? Math.random;
|
|
25
27
|
const transientCodes = new Set([...TRANSIENT_CODES, ...(options.transientCodes ?? [])]);
|
|
26
28
|
return {
|
|
27
29
|
name: options.name ?? "default-retry",
|
|
28
30
|
decide(context) {
|
|
29
31
|
if (context.signal?.aborted || context.attempt >= maxAttempts || !isTransientErrorInfo(context.error, transientCodes))
|
|
30
32
|
return { retry: false };
|
|
31
|
-
|
|
33
|
+
// Provider backpressure hint (Retry-After) wins over computed backoff, always
|
|
34
|
+
// capped at maxDelayMs so a hostile/huge hint cannot pin a run.
|
|
35
|
+
const hint = context.error.retryAfterMs;
|
|
36
|
+
const base = Math.min(hint !== undefined && Number.isFinite(hint) && hint >= 0 ? hint : baseDelayMs * 2 ** Math.max(0, context.attempt - 1), maxDelayMs);
|
|
37
|
+
const delayMs = jitter > 0 ? Math.round(base * (1 - jitter + random() * 2 * jitter)) : base;
|
|
38
|
+
return { retry: true, delayMs };
|
|
32
39
|
},
|
|
33
40
|
};
|
|
34
41
|
}
|
package/dist/rpc.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createInterface } from "node:readline";
|
|
2
|
-
import { errorToErrorInfo } from "./redaction.js";
|
|
3
2
|
import { resolveInstructionInjectors } from "./instruction-injection.js";
|
|
3
|
+
import { errorToErrorInfo } from "./redaction.js";
|
|
4
4
|
export async function runRpcServer(options) {
|
|
5
5
|
const first = options.createSession();
|
|
6
6
|
const state = {
|
|
@@ -58,7 +58,11 @@ async function handleRequest(request, state, stdout, activeRuns) {
|
|
|
58
58
|
const session = state.current;
|
|
59
59
|
const existing = activeRuns.get(session.id);
|
|
60
60
|
if (existing) {
|
|
61
|
-
write(stdout, {
|
|
61
|
+
write(stdout, {
|
|
62
|
+
id: request.id,
|
|
63
|
+
ok: false,
|
|
64
|
+
error: errorToErrorInfo(new Error(`Session ${session.id} already has an active run for request ${existing.requestId}`)),
|
|
65
|
+
});
|
|
62
66
|
return;
|
|
63
67
|
}
|
|
64
68
|
// ponytail: Phase 30 — resolve run options (incl. instructionInjectors names) BEFORE opening the
|
|
@@ -74,31 +78,52 @@ async function handleRequest(request, state, stdout, activeRuns) {
|
|
|
74
78
|
await events;
|
|
75
79
|
}
|
|
76
80
|
write(stdout, { id: request.id, ok: true, result: { sessionId: session.id } });
|
|
77
|
-
})()
|
|
81
|
+
})()
|
|
82
|
+
.catch((error) => {
|
|
78
83
|
write(stdout, { id: request.id, ok: false, error: errorToErrorInfo(error) });
|
|
79
|
-
})
|
|
84
|
+
})
|
|
85
|
+
.finally(() => {
|
|
80
86
|
activeRuns.delete(session.id);
|
|
81
87
|
});
|
|
82
88
|
activeRuns.set(session.id, { requestId: request.id, promise });
|
|
83
89
|
break;
|
|
84
90
|
}
|
|
85
|
-
case "steer":
|
|
86
|
-
|
|
91
|
+
case "steer": {
|
|
92
|
+
const input = stringParam(request.params, "input") ?? stringParam(request.params, "prompt");
|
|
93
|
+
if (!input)
|
|
94
|
+
throw new Error("steer requires params.input");
|
|
95
|
+
const softInterrupt = request.params?.softInterrupt === true;
|
|
96
|
+
state.current.steer(input, softInterrupt ? { softInterrupt: true } : undefined);
|
|
97
|
+
write(stdout, {
|
|
98
|
+
id: request.id,
|
|
99
|
+
ok: true,
|
|
100
|
+
result: { sessionId: state.current.id },
|
|
101
|
+
});
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
87
104
|
case "abort":
|
|
88
105
|
state.current.abort(stringParam(request.params, "reason"));
|
|
89
106
|
write(stdout, { id: request.id, ok: true, result: { sessionId: state.current.id } });
|
|
90
107
|
break;
|
|
91
108
|
case "state":
|
|
92
|
-
write(stdout, {
|
|
109
|
+
write(stdout, {
|
|
110
|
+
id: request.id,
|
|
111
|
+
ok: true,
|
|
112
|
+
result: {
|
|
93
113
|
sessionId: state.current.id,
|
|
94
114
|
leafId: state.current.leafId,
|
|
95
115
|
handleId: state.currentHandleId,
|
|
96
116
|
// ponytail: `sessions` kept as a backward-compatible handle-id string list (== sessionId
|
|
97
117
|
// for the initial session and clones); `handles` is the branch-handle detail view.
|
|
98
118
|
sessions: [...state.sessions.keys()],
|
|
99
|
-
handles: [...state.sessions.entries()].map(([handleId, session]) => ({
|
|
119
|
+
handles: [...state.sessions.entries()].map(([handleId, session]) => ({
|
|
120
|
+
handleId,
|
|
121
|
+
sessionId: session.id,
|
|
122
|
+
leafId: session.leafId,
|
|
123
|
+
})),
|
|
100
124
|
model: state.model,
|
|
101
|
-
}
|
|
125
|
+
},
|
|
126
|
+
});
|
|
102
127
|
break;
|
|
103
128
|
case "messages":
|
|
104
129
|
write(stdout, { id: request.id, ok: true, result: { sessionId: state.current.id, entries: await state.current.entries() } });
|
|
@@ -141,7 +166,11 @@ async function handleRequest(request, state, stdout, activeRuns) {
|
|
|
141
166
|
if (!leafId)
|
|
142
167
|
throw new Error("checkout requires params.leafId");
|
|
143
168
|
await state.current.checkout(leafId);
|
|
144
|
-
write(stdout, {
|
|
169
|
+
write(stdout, {
|
|
170
|
+
id: request.id,
|
|
171
|
+
ok: true,
|
|
172
|
+
result: { sessionId: state.current.id, leafId: state.current.leafId, handleId: state.currentHandleId },
|
|
173
|
+
});
|
|
145
174
|
break;
|
|
146
175
|
}
|
|
147
176
|
case "command": {
|
|
@@ -234,7 +263,22 @@ function isObject(value) {
|
|
|
234
263
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
235
264
|
}
|
|
236
265
|
function isCommand(value) {
|
|
237
|
-
return typeof value === "string" &&
|
|
266
|
+
return (typeof value === "string" &&
|
|
267
|
+
[
|
|
268
|
+
"prompt",
|
|
269
|
+
"steer",
|
|
270
|
+
"followUp",
|
|
271
|
+
"abort",
|
|
272
|
+
"state",
|
|
273
|
+
"messages",
|
|
274
|
+
"setModel",
|
|
275
|
+
"compact",
|
|
276
|
+
"switchSession",
|
|
277
|
+
"forkSession",
|
|
278
|
+
"cloneSession",
|
|
279
|
+
"checkout",
|
|
280
|
+
"command",
|
|
281
|
+
].includes(value));
|
|
238
282
|
}
|
|
239
283
|
function readRequestId(value) {
|
|
240
284
|
return isObject(value) && (typeof value.id === "string" || typeof value.id === "number") ? value.id : null;
|
package/dist/run-ledger.d.ts
CHANGED
|
@@ -6,9 +6,15 @@ export declare const HARD_LEDGER_BATCH_BYTES: number;
|
|
|
6
6
|
export declare const DEFAULT_LEDGER_BATCH_DELAY_MS = 25;
|
|
7
7
|
export declare const HARD_LEDGER_BATCH_DELAY_MS = 60000;
|
|
8
8
|
export interface BatchedRunLedgerOptions {
|
|
9
|
+
/** Flush triggers, not write grouping: a pending flush fires once the buffer reaches
|
|
10
|
+
* this many entries. Writes still go to the target one at a time (RunLedger has no
|
|
11
|
+
* batch append); these bounds shape flush *timing*, not per-write coalescing. */
|
|
9
12
|
readonly maxBatchEntries?: number;
|
|
13
|
+
/** Flush trigger: pending flush fires once buffered bytes reach this bound. */
|
|
10
14
|
readonly maxBatchBytes?: number;
|
|
15
|
+
/** Backpressure bound: enqueue flushes synchronously before exceeding this. */
|
|
11
16
|
readonly maxBufferedEntries?: number;
|
|
17
|
+
/** Backpressure bound (bytes): enqueue flushes synchronously before exceeding this. */
|
|
12
18
|
readonly maxBufferedBytes?: number;
|
|
13
19
|
readonly maxDelayMs?: number;
|
|
14
20
|
readonly durability?: RunLedgerDurability;
|
package/dist/run-ledger.js
CHANGED
|
@@ -32,12 +32,18 @@ export function createBatchedRunLedger(target, options = {}) {
|
|
|
32
32
|
let flushChain = Promise.resolve();
|
|
33
33
|
let disposed = false;
|
|
34
34
|
const status = () => ({ accepted, flushed, buffered: queue.length });
|
|
35
|
-
const cancelTimer = () => {
|
|
36
|
-
|
|
35
|
+
const cancelTimer = () => {
|
|
36
|
+
if (timer)
|
|
37
|
+
clearTimeout(timer);
|
|
38
|
+
timer = undefined;
|
|
39
|
+
};
|
|
37
40
|
const schedule = () => {
|
|
38
41
|
if (timer || disposed || queue.length === 0)
|
|
39
42
|
return;
|
|
40
|
-
timer = setTimeout(() => {
|
|
43
|
+
timer = setTimeout(() => {
|
|
44
|
+
timer = undefined;
|
|
45
|
+
void flush().catch(() => undefined);
|
|
46
|
+
}, maxDelayMs);
|
|
41
47
|
timer.unref?.();
|
|
42
48
|
};
|
|
43
49
|
const write = (item) => {
|
|
@@ -52,20 +58,14 @@ export function createBatchedRunLedger(target, options = {}) {
|
|
|
52
58
|
const flush = () => {
|
|
53
59
|
cancelTimer();
|
|
54
60
|
const operation = flushChain.then(async () => {
|
|
55
|
-
|
|
56
|
-
|
|
61
|
+
// One write per record — RunLedger has no batch append API. maxBatchEntries/
|
|
62
|
+
// maxBatchBytes only decide when a flush fires (see enqueue), never how writes group.
|
|
57
63
|
while (queue.length) {
|
|
58
64
|
const item = queue[0];
|
|
59
|
-
|
|
60
|
-
entries = 0;
|
|
61
|
-
bytes = 0;
|
|
62
|
-
}
|
|
63
|
-
await write(item);
|
|
65
|
+
await write(item); // shifts only after success — a failed write stays buffered for retry
|
|
64
66
|
queue.shift();
|
|
65
67
|
bufferedBytes -= item.bytes;
|
|
66
68
|
flushed += 1;
|
|
67
|
-
entries += 1;
|
|
68
|
-
bytes += item.bytes;
|
|
69
69
|
}
|
|
70
70
|
return status();
|
|
71
71
|
});
|
|
@@ -83,7 +83,10 @@ export function createBatchedRunLedger(target, options = {}) {
|
|
|
83
83
|
queue.push({ ...item, bytes });
|
|
84
84
|
bufferedBytes += bytes;
|
|
85
85
|
accepted += 1;
|
|
86
|
-
if (durability === "write_through" ||
|
|
86
|
+
if (durability === "write_through" ||
|
|
87
|
+
queue.length >= maxBatchEntries ||
|
|
88
|
+
bufferedBytes >= maxBatchBytes ||
|
|
89
|
+
(item.kind === "run" && terminal(item.record) && durability === "flush_on_terminal"))
|
|
87
90
|
await flush();
|
|
88
91
|
else
|
|
89
92
|
schedule();
|
package/dist/run-limits.js
CHANGED
|
@@ -58,9 +58,23 @@ export function resolveRunLimits(agent, run) {
|
|
|
58
58
|
resolved[name] = base ? Math.min(resolved[name], override[name]) : override[name];
|
|
59
59
|
}
|
|
60
60
|
const maxCost = override?.maxCost ?? base?.maxCost;
|
|
61
|
-
return Object.freeze({
|
|
61
|
+
return Object.freeze({
|
|
62
|
+
...resolved,
|
|
63
|
+
...(maxCost
|
|
64
|
+
? {
|
|
65
|
+
maxCost: base?.maxCost && override?.maxCost
|
|
66
|
+
? {
|
|
67
|
+
amount: Math.min(base.maxCost.amount, override.maxCost.amount),
|
|
68
|
+
currency: base.maxCost.currency === override.maxCost.currency ? base.maxCost.currency : failCurrency(),
|
|
69
|
+
}
|
|
70
|
+
: maxCost,
|
|
71
|
+
}
|
|
72
|
+
: {}),
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
function failCurrency() {
|
|
76
|
+
throw new TypeError("Run limit currencies must match when narrowed");
|
|
62
77
|
}
|
|
63
|
-
function failCurrency() { throw new TypeError("Run limit currencies must match when narrowed"); }
|
|
64
78
|
function validateLimits(input) {
|
|
65
79
|
for (const name of LIMIT_NAMES) {
|
|
66
80
|
const value = input[name];
|
|
@@ -88,7 +102,20 @@ export class RunLimitTracker {
|
|
|
88
102
|
constructor(limits, options = {}) {
|
|
89
103
|
this.options = options;
|
|
90
104
|
this.limits = limits;
|
|
91
|
-
this.counters = {
|
|
105
|
+
this.counters = {
|
|
106
|
+
turns: 0,
|
|
107
|
+
providerAttempts: 0,
|
|
108
|
+
toolRounds: 0,
|
|
109
|
+
toolCalls: 0,
|
|
110
|
+
wallTimeMs: 0,
|
|
111
|
+
requestBytes: 0,
|
|
112
|
+
responseBytes: 0,
|
|
113
|
+
inputTokens: 0,
|
|
114
|
+
outputTokens: 0,
|
|
115
|
+
totalTokens: 0,
|
|
116
|
+
cost: 0,
|
|
117
|
+
...options.snapshot,
|
|
118
|
+
};
|
|
92
119
|
for (const [key, value] of Object.entries(this.counters)) {
|
|
93
120
|
if (!Number.isFinite(value) || value < 0 || (key !== "cost" && !Number.isSafeInteger(value))) {
|
|
94
121
|
throw new TypeError("Run limit snapshot must contain finite non-negative counters");
|
|
@@ -104,10 +131,17 @@ export class RunLimitTracker {
|
|
|
104
131
|
if (remaining === 0)
|
|
105
132
|
this.exceed("maxWallTimeMs", limits.maxWallTimeMs);
|
|
106
133
|
}
|
|
107
|
-
get breach() {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
134
|
+
get breach() {
|
|
135
|
+
return this.exceeded;
|
|
136
|
+
}
|
|
137
|
+
snapshot() {
|
|
138
|
+
return { ...this.counters, wallTimeMs: Math.min(this.limits.maxWallTimeMs, Math.ceil(performance.now() - this.startedAt)) };
|
|
139
|
+
}
|
|
140
|
+
dispose() {
|
|
141
|
+
if (this.timer)
|
|
142
|
+
clearTimeout(this.timer);
|
|
143
|
+
this.timer = undefined;
|
|
144
|
+
}
|
|
111
145
|
charge(limit, delta = 1) {
|
|
112
146
|
if (!Number.isSafeInteger(delta) || delta < 0)
|
|
113
147
|
throw new TypeError("Run limit delta must be a non-negative safe integer");
|
|
@@ -130,7 +164,7 @@ export class RunLimitTracker {
|
|
|
130
164
|
if (value !== undefined && (!Number.isSafeInteger(value) || value < 0))
|
|
131
165
|
throw new TypeError(`Provider usage ${key} must be a non-negative safe integer`);
|
|
132
166
|
}
|
|
133
|
-
const total = usage.totalTokens ?? (
|
|
167
|
+
const total = usage.totalTokens ?? (usage.inputTokens ?? 0) + (usage.outputTokens ?? 0);
|
|
134
168
|
if (!Number.isSafeInteger(total))
|
|
135
169
|
throw new TypeError("Provider usage totalTokens is invalid");
|
|
136
170
|
this.charge("maxInputTokens", usage.inputTokens ?? 0);
|
|
@@ -149,8 +183,13 @@ export class RunLimitTracker {
|
|
|
149
183
|
}
|
|
150
184
|
exceed(limit, observed) {
|
|
151
185
|
if (!this.exceeded) {
|
|
152
|
-
const maximum = limit === "maxCost" ? this.limits.maxCost?.amount ?? 0 : this.limits[limit];
|
|
153
|
-
this.exceeded = {
|
|
186
|
+
const maximum = limit === "maxCost" ? (this.limits.maxCost?.amount ?? 0) : this.limits[limit];
|
|
187
|
+
this.exceeded = {
|
|
188
|
+
limit,
|
|
189
|
+
maximum,
|
|
190
|
+
observed,
|
|
191
|
+
...(limit === "maxCost" && this.limits.maxCost ? { currency: this.limits.maxCost.currency } : {}),
|
|
192
|
+
};
|
|
154
193
|
this.options.onExceeded?.(this.exceeded);
|
|
155
194
|
}
|
|
156
195
|
if (limit !== "maxWallTimeMs")
|
package/dist/secure-agent.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { createAgent } from "./agents.js";
|
|
2
1
|
import { validateRunStateOptions } from "./agent-run-state.js";
|
|
2
|
+
import { createAgent } from "./agents.js";
|
|
3
|
+
import { assertIdentityActive, assertIdentityMatchesOwnership } from "./identity.js";
|
|
3
4
|
import { resolveRunLimits } from "./run-limits.js";
|
|
4
5
|
import { createToolParameterValidator, createToolRegistry } from "./tools.js";
|
|
5
6
|
/** Build an opt-in agent whose security-critical defaults cannot be replaced per run. */
|
|
@@ -27,6 +28,10 @@ export function createSecureAgent(options) {
|
|
|
27
28
|
throw new TypeError(`Secure agent tool ${tool.name} requires a non-empty parameters schema`);
|
|
28
29
|
}
|
|
29
30
|
resolveRunLimits(options.limits);
|
|
31
|
+
if (options.identity) {
|
|
32
|
+
assertIdentityActive(options.identity);
|
|
33
|
+
assertIdentityMatchesOwnership(options.identity, options.ownership);
|
|
34
|
+
}
|
|
30
35
|
const runState = Object.freeze({ ...options.runState, definitionRevision: options.definitionRevision, interruptBeforeTool: true });
|
|
31
36
|
validateRunStateOptions(runState);
|
|
32
37
|
const config = Object.freeze({
|
|
@@ -38,6 +43,7 @@ export function createSecureAgent(options) {
|
|
|
38
43
|
permission: options.permission,
|
|
39
44
|
trust: options.trust,
|
|
40
45
|
ownership: Object.freeze({ ...options.ownership }),
|
|
46
|
+
...(options.identity ? { identity: Object.freeze({ ...options.identity, scopes: Object.freeze([...options.identity.scopes]) }) } : {}),
|
|
41
47
|
limits: Object.freeze({ ...options.limits }),
|
|
42
48
|
guardrails: freezeGuardrails(options.guardrails),
|
|
43
49
|
runState,
|
|
@@ -46,7 +52,7 @@ export function createSecureAgent(options) {
|
|
|
46
52
|
return createAgent(config);
|
|
47
53
|
}
|
|
48
54
|
function withoutSecureFields(options) {
|
|
49
|
-
const { tools: _tools, toolArgumentValidator: _validator, redactor: _redactor, permission: _permission, trust: _trust, ownership: _ownership, limits: _limits, guardrails: _guardrails, definitionRevision: _revision, runState: _runState, ...config } = options;
|
|
55
|
+
const { tools: _tools, toolArgumentValidator: _validator, redactor: _redactor, permission: _permission, trust: _trust, ownership: _ownership, identity: _identity, limits: _limits, guardrails: _guardrails, definitionRevision: _revision, runState: _runState, ...config } = options;
|
|
50
56
|
return config;
|
|
51
57
|
}
|
|
52
58
|
function freezeGuardrails(guardrails) {
|
package/dist/security.js
CHANGED
|
@@ -50,11 +50,16 @@ export function createStaticPermissionPolicy(options) {
|
|
|
50
50
|
const key = `${request.kind}:${request.target}:${request.action}`;
|
|
51
51
|
if (deny.has(key))
|
|
52
52
|
return { allowed: false, reason: `Permission denied: ${key}` };
|
|
53
|
-
return {
|
|
53
|
+
return {
|
|
54
|
+
allowed: allow.size === 0 || allow.has(key),
|
|
55
|
+
reason: allow.size && !allow.has(key) ? `Permission not allowed: ${key}` : undefined,
|
|
56
|
+
};
|
|
54
57
|
},
|
|
55
58
|
};
|
|
56
59
|
}
|
|
57
60
|
export function denialToErrorInfo(error) {
|
|
58
|
-
return error instanceof Error
|
|
61
|
+
return error instanceof Error
|
|
62
|
+
? { name: error.name, message: error.message, code: error.code }
|
|
63
|
+
: { message: String(error) };
|
|
59
64
|
}
|
|
60
65
|
//# sourceMappingURL=security.js.map
|
package/dist/session-stores.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type BranchReader, type Message, type SessionBranchRead, type SessionEntry, type SessionStore } from "./contracts.js";
|
|
2
2
|
export interface CreateSessionEntryOptions extends Omit<SessionEntry, "id" | "timestamp"> {
|
|
3
3
|
readonly id?: string;
|
|
4
4
|
readonly timestamp?: string;
|
|
@@ -24,4 +24,9 @@ export declare function getSessionBranchEntries(entries: readonly SessionEntry[]
|
|
|
24
24
|
export declare function listSessionBranches(entries: readonly SessionEntry[]): readonly SessionBranch[];
|
|
25
25
|
export declare function rebuildSessionContext(reader: BranchReader, query: SessionBranchRead): Promise<SessionContextSnapshot>;
|
|
26
26
|
export declare function rebuildSessionContext(entries: readonly SessionEntry[], options?: SessionBranchOptions): SessionContextSnapshot;
|
|
27
|
-
export
|
|
27
|
+
export type MemorySessionSearchMode = "linear" | "unsupported";
|
|
28
|
+
export interface CreateMemorySessionStoreOptions {
|
|
29
|
+
/** Default `"linear"`: capped in-process scan. `"unsupported"`: typed throw. */
|
|
30
|
+
readonly sessionSearchMode?: MemorySessionSearchMode;
|
|
31
|
+
}
|
|
32
|
+
export declare function createMemorySessionStore(initialEntries?: readonly SessionEntry[], options?: CreateMemorySessionStoreOptions): SessionStore;
|