@bastani/atomic 0.9.40 → 0.9.41-alpha.2
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 +75 -0
- package/README.md +1 -1
- package/dist/builtin/intercom/CHANGELOG.md +12 -0
- package/dist/builtin/intercom/README.md +1 -1
- package/dist/builtin/intercom/broker/broker.ts +24 -21
- package/dist/builtin/intercom/broker/client.ts +97 -6
- package/dist/builtin/intercom/broker/list-reply.ts +53 -0
- package/dist/builtin/intercom/index.bundle.mjs +278 -46
- package/dist/builtin/intercom/package.json +2 -2
- package/dist/builtin/intercom/recoverable-disconnect.ts +27 -1
- package/dist/builtin/intercom/types.ts +8 -1
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/CHANGELOG.md +14 -0
- package/dist/builtin/subagents/README.md +14 -0
- package/dist/builtin/subagents/package.json +3 -3
- package/dist/builtin/subagents/src/extension/index.bundle.mjs +99 -19
- package/dist/builtin/web-access/package.json +2 -2
- package/dist/builtin/workflows/CHANGELOG.md +33 -0
- package/dist/builtin/workflows/README.md +2 -0
- package/dist/builtin/workflows/builtin/adversarial-verification.js +2 -2
- package/dist/builtin/workflows/builtin/{chunk-qjqn389g.js → chunk-2jfst7e4.js} +72 -10
- package/dist/builtin/workflows/builtin/{chunk-4bwtzyjq.js → chunk-49kkbdpr.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-qdd897wm.js → chunk-apagcs4r.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-454hz1qt.js → chunk-dcxscfnb.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-bjva9j5k.js → chunk-hx8v4p97.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-85mx6wcf.js → chunk-k5q3t7je.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-8kkv04hz.js → chunk-n2gkzkty.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-y45tkftg.js → chunk-txbc93t6.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-x0vvjyzg.js → chunk-w4xp1w1f.js} +1 -1
- package/dist/builtin/workflows/builtin/{chunk-5eh0brtd.js → chunk-z3pajrfs.js} +1 -1
- package/dist/builtin/workflows/builtin/classify-and-act.js +2 -2
- package/dist/builtin/workflows/builtin/fan-out-and-synthesize.js +2 -2
- package/dist/builtin/workflows/builtin/generate-and-filter.js +2 -2
- package/dist/builtin/workflows/builtin/goal.js +2 -2
- package/dist/builtin/workflows/builtin/index.js +10 -10
- package/dist/builtin/workflows/builtin/loop-until-done.js +2 -2
- package/dist/builtin/workflows/builtin/open-claude-design.js +2 -2
- package/dist/builtin/workflows/builtin/ralph.js +2 -2
- package/dist/builtin/workflows/builtin/tournament.js +2 -2
- package/dist/builtin/workflows/package.json +2 -2
- package/dist/builtin/workflows/src/authoring.d.ts +1 -1
- package/dist/builtin/workflows/src/durable/journal/internal.d.ts +16 -0
- package/dist/builtin/workflows/src/durable/journal/legacy-journal-tables.d.ts +9 -0
- package/dist/builtin/workflows/src/durable/journal/sql-run-journal.d.ts +6 -0
- package/dist/builtin/workflows/src/extension/index.bundle.mjs +950 -116
- package/dist/builtin/workflows/src/index.js +806 -131
- package/dist/builtin/workflows/src/shared/authoring-contract-stage.d.ts +17 -1
- package/dist/cli/credential-print.d.ts.map +1 -1
- package/dist/cli/credential-print.js +1 -1
- package/dist/cli/credential-print.js.map +1 -1
- package/dist/config.d.ts +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session-extension-bindings.d.ts +2 -1
- package/dist/core/agent-session-extension-bindings.d.ts.map +1 -1
- package/dist/core/agent-session-extension-bindings.js +33 -18
- package/dist/core/agent-session-extension-bindings.js.map +1 -1
- package/dist/core/agent-session-methods.d.ts +2 -1
- package/dist/core/agent-session-methods.d.ts.map +1 -1
- package/dist/core/agent-session-methods.js.map +1 -1
- package/dist/core/agent-session-prompt.d.ts.map +1 -1
- package/dist/core/agent-session-prompt.js +114 -21
- package/dist/core/agent-session-prompt.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts +1 -1
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +6 -0
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session-state.d.ts +19 -1
- package/dist/core/agent-session-state.d.ts.map +1 -1
- package/dist/core/agent-session-state.js +41 -6
- package/dist/core/agent-session-state.js.map +1 -1
- package/dist/core/auth-storage-backends.d.ts +3 -1
- package/dist/core/auth-storage-backends.d.ts.map +1 -1
- package/dist/core/auth-storage-backends.js +79 -12
- package/dist/core/auth-storage-backends.js.map +1 -1
- package/dist/core/client-identity.d.ts +8 -0
- package/dist/core/client-identity.d.ts.map +1 -0
- package/dist/core/client-identity.js +16 -0
- package/dist/core/client-identity.js.map +1 -0
- package/dist/core/compaction/planner-outcome.d.ts.map +1 -1
- package/dist/core/compaction/planner-outcome.js +2 -1
- package/dist/core/compaction/planner-outcome.js.map +1 -1
- package/dist/core/execution-model-router.d.ts +18 -0
- package/dist/core/execution-model-router.d.ts.map +1 -1
- package/dist/core/execution-model-router.js +14 -8
- package/dist/core/execution-model-router.js.map +1 -1
- package/dist/core/extension-oauth-refresh-rejection.d.ts +12 -0
- package/dist/core/extension-oauth-refresh-rejection.d.ts.map +1 -0
- package/dist/core/extension-oauth-refresh-rejection.js +70 -0
- package/dist/core/extension-oauth-refresh-rejection.js.map +1 -0
- package/dist/core/extension-startup-failure.d.ts +30 -0
- package/dist/core/extension-startup-failure.d.ts.map +1 -0
- package/dist/core/extension-startup-failure.js +62 -0
- package/dist/core/extension-startup-failure.js.map +1 -0
- package/dist/core/extensions/context-types.d.ts +2 -0
- package/dist/core/extensions/context-types.d.ts.map +1 -1
- package/dist/core/extensions/context-types.js.map +1 -1
- package/dist/core/extensions/provider-types.d.ts +2 -0
- package/dist/core/extensions/provider-types.d.ts.map +1 -1
- package/dist/core/extensions/provider-types.js.map +1 -1
- package/dist/core/extensions/runner-context.d.ts +1 -0
- package/dist/core/extensions/runner-context.d.ts.map +1 -1
- package/dist/core/extensions/runner-context.js +8 -0
- package/dist/core/extensions/runner-context.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +1 -0
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +3 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/runtime-types.d.ts +1 -0
- package/dist/core/extensions/runtime-types.d.ts.map +1 -1
- package/dist/core/extensions/runtime-types.js.map +1 -1
- package/dist/core/extensions/workflow-run-control-hub.d.ts +1 -0
- package/dist/core/extensions/workflow-run-control-hub.d.ts.map +1 -1
- package/dist/core/extensions/workflow-run-control-hub.js +3 -0
- package/dist/core/extensions/workflow-run-control-hub.js.map +1 -1
- package/dist/core/extensions/workflow-run-control.d.ts +8 -0
- package/dist/core/extensions/workflow-run-control.d.ts.map +1 -1
- package/dist/core/extensions/workflow-run-control.js.map +1 -1
- package/dist/core/model-config.d.ts +28 -0
- package/dist/core/model-config.d.ts.map +1 -1
- package/dist/core/model-fallback-failures.d.ts.map +1 -1
- package/dist/core/model-fallback-failures.js +12 -0
- package/dist/core/model-fallback-failures.js.map +1 -1
- package/dist/core/model-resolver-defaults.js +1 -1
- package/dist/core/model-resolver-defaults.js.map +1 -1
- package/dist/core/model-runtime-streaming.d.ts.map +1 -1
- package/dist/core/model-runtime-streaming.js +9 -3
- package/dist/core/model-runtime-streaming.js.map +1 -1
- package/dist/core/model-runtime.d.ts +5 -0
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +6 -0
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/provider-composer-internal.d.ts +8 -6
- package/dist/core/provider-composer-internal.d.ts.map +1 -1
- package/dist/core/provider-composer-internal.js +21 -8
- package/dist/core/provider-composer-internal.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +12 -4
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/storage/session/sql-session-store.d.ts +35 -0
- package/dist/core/storage/session/sql-session-store.d.ts.map +1 -1
- package/dist/core/storage/session/sql-session-store.js +158 -42
- package/dist/core/storage/session/sql-session-store.js.map +1 -1
- package/dist/core/structured-output/deadline.d.ts +40 -0
- package/dist/core/structured-output/deadline.d.ts.map +1 -0
- package/dist/core/structured-output/deadline.js +110 -0
- package/dist/core/structured-output/deadline.js.map +1 -0
- package/dist/core/structured-output/index.d.ts.map +1 -1
- package/dist/core/structured-output/index.js +103 -47
- package/dist/core/structured-output/index.js.map +1 -1
- package/dist/core/structured-output/rejection-detail.d.ts +9 -0
- package/dist/core/structured-output/rejection-detail.d.ts.map +1 -0
- package/dist/core/structured-output/rejection-detail.js +129 -0
- package/dist/core/structured-output/rejection-detail.js.map +1 -0
- package/dist/core/structured-output/types.d.ts +8 -1
- package/dist/core/structured-output/types.d.ts.map +1 -1
- package/dist/core/structured-output/types.js.map +1 -1
- package/dist/core/tasks/completion.d.ts +7 -1
- package/dist/core/tasks/completion.d.ts.map +1 -1
- package/dist/core/tasks/completion.js +28 -6
- package/dist/core/tasks/completion.js.map +1 -1
- package/dist/core/tasks/contracts.d.ts +6 -1
- package/dist/core/tasks/contracts.d.ts.map +1 -1
- package/dist/core/tasks/contracts.js.map +1 -1
- package/dist/core/tasks/pause.d.ts +2 -1
- package/dist/core/tasks/pause.d.ts.map +1 -1
- package/dist/core/tasks/pause.js +3 -2
- package/dist/core/tasks/pause.js.map +1 -1
- package/dist/core/tools/bash-pty-native.d.ts.map +1 -1
- package/dist/core/tools/bash-pty-native.js +10 -5
- package/dist/core/tools/bash-pty-native.js.map +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +16 -32
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/grep.js +1 -1
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/kill.d.ts.map +1 -1
- package/dist/core/tools/kill.js +17 -3
- package/dist/core/tools/kill.js.map +1 -1
- package/dist/core/tools/shell-task-render.d.ts +55 -0
- package/dist/core/tools/shell-task-render.d.ts.map +1 -0
- package/dist/core/tools/shell-task-render.js +123 -0
- package/dist/core/tools/shell-task-render.js.map +1 -0
- package/dist/core/tools/shell-task-status.d.ts +52 -0
- package/dist/core/tools/shell-task-status.d.ts.map +1 -0
- package/dist/core/tools/shell-task-status.js +184 -0
- package/dist/core/tools/shell-task-status.js.map +1 -0
- package/dist/core/tools/structured-output.d.ts +5 -0
- package/dist/core/tools/structured-output.d.ts.map +1 -1
- package/dist/core/tools/structured-output.js +3 -0
- package/dist/core/tools/structured-output.js.map +1 -1
- package/dist/extensions/codemode/execute.d.ts.map +1 -1
- package/dist/extensions/codemode/execute.js +134 -57
- package/dist/extensions/codemode/execute.js.map +1 -1
- package/dist/extensions/mcp/config.d.ts.map +1 -1
- package/dist/extensions/mcp/config.js +3 -2
- package/dist/extensions/mcp/config.js.map +1 -1
- package/dist/index-extensions.d.ts +1 -0
- package/dist/index-extensions.d.ts.map +1 -1
- package/dist/index-extensions.js +3 -0
- package/dist/index-extensions.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +19 -6
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/task-row.d.ts.map +1 -1
- package/dist/modes/interactive/components/task-row.js +11 -1
- package/dist/modes/interactive/components/task-row.js.map +1 -1
- package/dist/modes/interactive/interactive-auth-routing.js +12 -10
- package/dist/modes/interactive/interactive-auth-routing.js.map +1 -1
- package/dist/modes/interactive/interactive-extension-custom-ui.js +20 -30
- package/dist/modes/interactive/interactive-extension-custom-ui.js.map +1 -1
- package/dist/modes/interactive/interactive-extension-dialogs.js +23 -96
- package/dist/modes/interactive/interactive-extension-dialogs.js.map +1 -1
- package/dist/modes/interactive/interactive-extension-runtime.js +7 -8
- package/dist/modes/interactive/interactive-extension-runtime.js.map +1 -1
- package/dist/modes/interactive/interactive-input-handling.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-input-handling.js +27 -4
- package/dist/modes/interactive/interactive-input-handling.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-base.d.ts +20 -10
- package/dist/modes/interactive/interactive-mode-base.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode-base.js +40 -5
- package/dist/modes/interactive/interactive-mode-base.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-deps.d.ts +1 -1
- package/dist/modes/interactive/interactive-mode-deps.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode-deps.js +1 -1
- package/dist/modes/interactive/interactive-mode-deps.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-surface.d.ts +2 -4
- package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode-surface.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-types.d.ts +4 -1
- package/dist/modes/interactive/interactive-mode-types.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode-types.js.map +1 -1
- package/dist/modes/interactive/interactive-prompt-restore.d.ts +3 -0
- package/dist/modes/interactive/interactive-prompt-restore.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-prompt-restore.js +9 -1
- package/dist/modes/interactive/interactive-prompt-restore.js.map +1 -1
- package/dist/modes/interactive/interactive-prompt-turn.js +30 -2
- package/dist/modes/interactive/interactive-prompt-turn.js.map +1 -1
- package/dist/modes/interactive/interactive-queueing.js +43 -8
- package/dist/modes/interactive/interactive-queueing.js.map +1 -1
- package/dist/modes/interactive/interactive-startup.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-startup.js +12 -3
- package/dist/modes/interactive/interactive-startup.js.map +1 -1
- package/dist/modes/interactive/theme/color-utils.d.ts +6 -1
- package/dist/modes/interactive/theme/color-utils.d.ts.map +1 -1
- package/dist/modes/interactive/theme/color-utils.js +39 -17
- package/dist/modes/interactive/theme/color-utils.js.map +1 -1
- package/dist/modes/interactive/theme/theme-class.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme-class.js +2 -2
- package/dist/modes/interactive/theme/theme-class.js.map +1 -1
- package/dist/modes/interactive/theme/theme-tokens.d.ts +6 -0
- package/dist/modes/interactive/theme/theme-tokens.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme-tokens.js +7 -3
- package/dist/modes/interactive/theme/theme-tokens.js.map +1 -1
- package/dist/modes/interactive-engine/isolated-auth.d.ts +3 -0
- package/dist/modes/interactive-engine/isolated-auth.d.ts.map +1 -1
- package/dist/modes/interactive-engine/isolated-auth.js +13 -1
- package/dist/modes/interactive-engine/isolated-auth.js.map +1 -1
- package/dist/modes/interactive-engine/isolated-runtime.d.ts.map +1 -1
- package/dist/modes/interactive-engine/isolated-runtime.js +11 -2
- package/dist/modes/interactive-engine/isolated-runtime.js.map +1 -1
- package/dist/modes/interactive-engine/remote-model-catalog.d.ts +8 -0
- package/dist/modes/interactive-engine/remote-model-catalog.d.ts.map +1 -1
- package/dist/modes/interactive-engine/remote-model-catalog.js +54 -0
- package/dist/modes/interactive-engine/remote-model-catalog.js.map +1 -1
- package/dist/modes/rpc/rpc-command-handler.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-command-handler.js +4 -13
- package/dist/modes/rpc/rpc-command-handler.js.map +1 -1
- package/dist/modes/rpc/rpc-model-catalog.d.ts +9 -0
- package/dist/modes/rpc/rpc-model-catalog.d.ts.map +1 -0
- package/dist/modes/rpc/rpc-model-catalog.js +19 -0
- package/dist/modes/rpc/rpc-model-catalog.js.map +1 -0
- package/dist/modes/rpc/rpc-provider-auth.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-provider-auth.js +2 -6
- package/dist/modes/rpc/rpc-provider-auth.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +6 -0
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/utils/changelog.d.ts +6 -0
- package/dist/utils/changelog.d.ts.map +1 -1
- package/dist/utils/changelog.js +11 -0
- package/dist/utils/changelog.js.map +1 -1
- package/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js +4 -0
- package/dist/utils/clipboard.js.map +1 -1
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +3 -2
- package/dist/utils/tools-manager.js.map +1 -1
- package/docs/background-tasks.md +5 -3
- package/docs/codemode.md +2 -2
- package/docs/custom-provider/oauth.md +42 -1
- package/docs/custom-provider/registration.md +2 -0
- package/docs/environment-variables.md +1 -0
- package/docs/extensions/api-reference.md +3 -4
- package/docs/extensions/authoring.md +1 -1
- package/docs/extensions/events.md +1 -1
- package/docs/models-configuration.md +9 -0
- package/docs/models.md +3 -1
- package/docs/providers.md +4 -4
- package/docs/rpc/protocol.md +4 -2
- package/docs/sdk/reference.md +2 -0
- package/docs/sdk/structured-decisions.md +7 -5
- package/docs/sdk.md +5 -2
- package/docs/settings.md +4 -2
- package/docs/subagents/reference.md +1 -1
- package/docs/subagents.md +15 -1
- package/docs/themes/reference.md +3 -1
- package/docs/usage.md +3 -1
- package/docs/workflows/api-reference.md +28 -0
- package/docs/workflows/authoring.md +1 -1
- package/docs/workflows/operations.md +2 -2
- package/npm-shrinkwrap.json +67 -54
- package/package.json +6 -6
- package/schemas/models.schema.json +21 -0
- package/dist/core/provider-attribution.d.ts +0 -4
- package/dist/core/provider-attribution.d.ts.map +0 -1
- package/dist/core/provider-attribution.js +0 -87
- package/dist/core/provider-attribution.js.map +0 -1
|
@@ -8,12 +8,23 @@ export declare const SESSION_TABLES: Readonly<{
|
|
|
8
8
|
entries: "entries";
|
|
9
9
|
searchTexts: "search_texts";
|
|
10
10
|
}>;
|
|
11
|
+
/** Rows whose search text is read per query; well under SQLite's bound-parameter limit. */
|
|
12
|
+
export declare const LISTING_FETCH_BATCH = 500;
|
|
11
13
|
export declare class SqlSessionStore implements SessionStore {
|
|
12
14
|
private readonly database;
|
|
13
15
|
private readonly tables;
|
|
14
16
|
private readonly prefix;
|
|
15
17
|
private closed;
|
|
16
18
|
private readonly cwdMatcher?;
|
|
19
|
+
/** Session ids of each recently listed scope, valid while the store's change token is unchanged. */
|
|
20
|
+
private readonly scopes;
|
|
21
|
+
/** Listed summaries of sessions that still exist at the cached version; never more than the store holds. */
|
|
22
|
+
private readonly summaries;
|
|
23
|
+
/**
|
|
24
|
+
* Settles when the latest listing has read and updated the caches. Listings take turns, so one listing's
|
|
25
|
+
* pruning never drops summaries that another has fetched but not yet recorded under its scope.
|
|
26
|
+
*/
|
|
27
|
+
private listing;
|
|
17
28
|
private constructor();
|
|
18
29
|
static open(database: SqliteDatabase, options?: {
|
|
19
30
|
readonly prefix?: string;
|
|
@@ -32,12 +43,36 @@ export declare class SqlSessionStore implements SessionStore {
|
|
|
32
43
|
load(sessionId: string): Promise<SessionSnapshot>;
|
|
33
44
|
readHeader(sessionId: string): Promise<SessionRecordHeader | undefined>;
|
|
34
45
|
delete(sessionId: string): Promise<void>;
|
|
46
|
+
/**
|
|
47
|
+
* Lists from a per-scope cache revalidated on every call. A cheap change token, which moves on any commit
|
|
48
|
+
* from this or another connection, decides whether the scope is re-read. A scope listed for the first time
|
|
49
|
+
* is read exactly as an uncached listing; afterwards only its light columns are re-read and search text is
|
|
50
|
+
* read only for sessions whose stored listing columns changed. Listings of the same store take turns
|
|
51
|
+
* reading and updating the caches; the yielding below runs outside that turn.
|
|
52
|
+
*/
|
|
35
53
|
list(query: SessionListQuery): AsyncIterable<SessionSummary>;
|
|
54
|
+
/** Revalidates one scope's cache and resolves its summaries; called for one listing at a time. */
|
|
55
|
+
private listScope;
|
|
36
56
|
findMostRecent(query: {
|
|
37
57
|
readonly cwd: string;
|
|
38
58
|
readonly includeInternal?: boolean;
|
|
39
59
|
}): Promise<SessionSummary | undefined>;
|
|
40
60
|
close(): Promise<void>;
|
|
61
|
+
/**
|
|
62
|
+
* `data_version` moves when another connection commits and `total_changes()` when this one writes, so
|
|
63
|
+
* together they cover writers in every process; the table aggregates also catch a change to the sessions
|
|
64
|
+
* table if the adapter does not serve every statement from one connection.
|
|
65
|
+
*/
|
|
66
|
+
private changeToken;
|
|
67
|
+
/** The scope's session ids in store order, with a current summary cached for each. */
|
|
68
|
+
private readScope;
|
|
69
|
+
/** Reads full listing rows, search text included, and caches their summaries. */
|
|
70
|
+
private readSummaries;
|
|
71
|
+
/**
|
|
72
|
+
* Keeps only summaries some cached scope still lists, so memory follows the live sessions. Runs in a
|
|
73
|
+
* listing's turn after it records its scope, when no other listing holds summaries it has not recorded.
|
|
74
|
+
*/
|
|
75
|
+
private pruneSummaries;
|
|
41
76
|
private assertOpen;
|
|
42
77
|
private assertListing;
|
|
43
78
|
private read;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sql-session-store.d.ts","sourceRoot":"","sources":["../../../../src/core/storage/session/sql-session-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,KAAK,EAAE,cAAc,
|
|
1
|
+
{"version":3,"file":"sql-session-store.d.ts","sourceRoot":"","sources":["../../../../src/core/storage/session/sql-session-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,KAAK,EAAE,cAAc,EAA0C,MAAM,gBAAgB,CAAC;AAkB7F,OAAO,KAAK,EACX,iBAAiB,EACjB,gBAAgB,EAChB,mBAAmB,EACnB,eAAe,EACf,YAAY,EACZ,cAAc,EACd,mBAAmB,EACnB,iBAAiB,EACjB,MAAM,YAAY,CAAC;AAGpB,eAAO,MAAM,sBAAsB,IAAI,CAAC;AACxC,eAAO,MAAM,cAAc;;;;;EAKzB,CAAC;AAuBH,2FAA2F;AAC3F,eAAO,MAAM,mBAAmB,MAAM,CAAC;AA6BvC,qBAAa,eAAgB,YAAW,YAAY;IACnD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiB;IAC1C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAoB;IAChD,oGAAoG;IACpG,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkF;IACzG,4GAA4G;IAC5G,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqF;IAC/G;;;OAGG;IACH,OAAO,CAAC,OAAO,CAAoC;IAEnD,OAAO,eAKN;IAED,OAAa,IAAI,CAChB,QAAQ,EAAE,cAAc,EACxB,OAAO,GAAE;QAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,iBAAiB,CAAA;KAAO,GACjF,OAAO,CAAC,eAAe,CAAC,CAwC1B;IAED,IAAI,UAAU,IAAI,iBAAiB,CAElC;IAEK,MAAM,CAAC,MAAM,EAAE,mBAAmB,EAAE,OAAO,EAAE,SAAS,YAAY,EAAE,GAAG,OAAO,CAAC;QAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAYjH;IAEK,MAAM,CACX,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,SAAS,YAAY,EAAE,EAChC,OAAO,EAAE,mBAAmB,GAC1B,OAAO,CAAC;QAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAgBvC;IAEK,OAAO,CACZ,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,mBAAmB,EAC3B,OAAO,EAAE,SAAS,YAAY,EAAE,EAChC,OAAO,EAAE,mBAAmB,GAC1B,OAAO,CAAC;QAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAcvC;IAEK,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAItD;IAEK,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,GAAG,SAAS,CAAC,CAQ5E;IAEK,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ7C;IAED;;;;;;OAMG;IACI,IAAI,CAAC,KAAK,EAAE,gBAAgB,GAAG,aAAa,CAAC,cAAc,CAAC,CAgBlE;IAED,kGAAkG;YACpF,SAAS;IAuBjB,cAAc,CAAC,KAAK,EAAE;QAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;KACnC,GAAG,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,CAMtC;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAK3B;IAED;;;;OAIG;YACW,WAAW;IAUzB,sFAAsF;YACxE,SAAS;IA6CvB,iFAAiF;YACnE,aAAa;IAe3B;;;OAGG;IACH,OAAO,CAAC,cAAc;IAKtB,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,aAAa;YAKP,IAAI;IAiBlB,OAAO,CAAC,QAAQ;YA8BF,WAAW;YAuCX,aAAa;IA0B3B,OAAO,CAAC,MAAM;CAOd"}
|
|
@@ -11,12 +11,50 @@ export const SESSION_TABLES = Object.freeze({
|
|
|
11
11
|
entries: "entries",
|
|
12
12
|
searchTexts: "search_texts",
|
|
13
13
|
});
|
|
14
|
+
/** Every listing column except search text, so an unchanged row keeps its cached summary. */
|
|
15
|
+
const LISTING_COLUMNS = "id, cwd, internal, header_json, last_seq, modified_at, message_count, first_message, name, has_name, summary, summarized_through_id, revision";
|
|
16
|
+
/** Rows whose search text is read per query; well under SQLite's bound-parameter limit. */
|
|
17
|
+
export const LISTING_FETCH_BATCH = 500;
|
|
18
|
+
/** Listing scopes (visibility and project) kept at once; the picker uses two. */
|
|
19
|
+
const LISTING_SCOPES = 8;
|
|
20
|
+
function summaryFromRow(row) {
|
|
21
|
+
const header = JSON.parse(row.header_json);
|
|
22
|
+
return {
|
|
23
|
+
id: header.id,
|
|
24
|
+
cwd: header.cwd,
|
|
25
|
+
...(header.parentSessionId !== undefined ? { parentSessionId: header.parentSessionId } : {}),
|
|
26
|
+
internal: header.internal === true,
|
|
27
|
+
...(header.workflow !== undefined ? { workflow: header.workflow } : {}),
|
|
28
|
+
...(row.name !== null ? { name: JSON.parse(row.name) } : {}),
|
|
29
|
+
hasName: row.has_name === 1,
|
|
30
|
+
createdAt: header.createdAt,
|
|
31
|
+
modifiedAt: row.modified_at,
|
|
32
|
+
messageCount: row.message_count,
|
|
33
|
+
firstMessage: JSON.parse(row.first_message),
|
|
34
|
+
...(row.summary !== null ? { summary: JSON.parse(row.summary) } : {}),
|
|
35
|
+
...(row.summarized_through_id !== null ? { summarizedThroughId: row.summarized_through_id } : {}),
|
|
36
|
+
searchText: JSON.parse(row.search_texts_json).join(" "),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/** Changes on every write: `revision` catches a rewrite that leaves every other listed column as it was. */
|
|
40
|
+
function listingVersion(row) {
|
|
41
|
+
return `${row.revision}\u0000${row.last_seq}\u0000${row.modified_at}\u0000${row.message_count}\u0000${row.has_name}\u0000${row.name}\u0000${row.summarized_through_id}\u0000${row.summary}\u0000${row.first_message}\u0000${row.header_json}`;
|
|
42
|
+
}
|
|
14
43
|
export class SqlSessionStore {
|
|
15
44
|
database;
|
|
16
45
|
tables;
|
|
17
46
|
prefix;
|
|
18
47
|
closed = false;
|
|
19
48
|
cwdMatcher;
|
|
49
|
+
/** Session ids of each recently listed scope, valid while the store's change token is unchanged. */
|
|
50
|
+
scopes = new Map();
|
|
51
|
+
/** Listed summaries of sessions that still exist at the cached version; never more than the store holds. */
|
|
52
|
+
summaries = new Map();
|
|
53
|
+
/**
|
|
54
|
+
* Settles when the latest listing has read and updated the caches. Listings take turns, so one listing's
|
|
55
|
+
* pruning never drops summaries that another has fetched but not yet recorded under its scope.
|
|
56
|
+
*/
|
|
57
|
+
listing = Promise.resolve();
|
|
20
58
|
constructor(database, tables, prefix = "", cwdMatcher) {
|
|
21
59
|
this.database = database;
|
|
22
60
|
this.tables = tables;
|
|
@@ -42,7 +80,7 @@ export class SqlSessionStore {
|
|
|
42
80
|
first_message TEXT NOT NULL CHECK(json_valid(first_message)),
|
|
43
81
|
name TEXT CHECK(name IS NULL OR json_valid(name)), has_name INTEGER NOT NULL,
|
|
44
82
|
summary TEXT CHECK(summary IS NULL OR json_valid(summary)), summarized_through_id TEXT,
|
|
45
|
-
summary_state TEXT NOT NULL CHECK(json_valid(summary_state))
|
|
83
|
+
summary_state TEXT NOT NULL CHECK(json_valid(summary_state)), revision TEXT NOT NULL DEFAULT ''
|
|
46
84
|
) STRICT;
|
|
47
85
|
CREATE TABLE IF NOT EXISTS ${tables.entries} (
|
|
48
86
|
session_id TEXT NOT NULL, seq INTEGER NOT NULL, entry_id TEXT NOT NULL,
|
|
@@ -53,6 +91,11 @@ export class SqlSessionStore {
|
|
|
53
91
|
text_json TEXT NOT NULL CHECK(json_valid(text_json)), PRIMARY KEY(session_id, seq)
|
|
54
92
|
) STRICT;
|
|
55
93
|
`);
|
|
94
|
+
// Sessions tables created before the write revision gain it; their rows pick one up on the next write.
|
|
95
|
+
const revision = await tx.get("SELECT name FROM pragma_table_info(?) WHERE name = 'revision'", tables.sessions);
|
|
96
|
+
if (!revision) {
|
|
97
|
+
await tx.exec(`ALTER TABLE ${tables.sessions} ADD COLUMN revision TEXT NOT NULL DEFAULT ''`);
|
|
98
|
+
}
|
|
56
99
|
});
|
|
57
100
|
return new SqlSessionStore(database, tables, options.prefix, options.cwdMatcher);
|
|
58
101
|
}
|
|
@@ -120,53 +163,52 @@ export class SqlSessionStore {
|
|
|
120
163
|
await tx.run(`DELETE FROM ${this.tables.sessions} WHERE id = ?`, sessionId);
|
|
121
164
|
});
|
|
122
165
|
}
|
|
166
|
+
/**
|
|
167
|
+
* Lists from a per-scope cache revalidated on every call. A cheap change token, which moves on any commit
|
|
168
|
+
* from this or another connection, decides whether the scope is re-read. A scope listed for the first time
|
|
169
|
+
* is read exactly as an uncached listing; afterwards only its light columns are re-read and search text is
|
|
170
|
+
* read only for sessions whose stored listing columns changed. Listings of the same store take turns
|
|
171
|
+
* reading and updating the caches; the yielding below runs outside that turn.
|
|
172
|
+
*/
|
|
123
173
|
async *list(query) {
|
|
124
174
|
this.assertListing(query);
|
|
125
175
|
// Validate the original query before binding only matching stored spellings below.
|
|
126
176
|
if (query.cwd?.includes("\0"))
|
|
127
177
|
throw new StorageInvalidTextError(0);
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
const projects = await this.database.all(`SELECT DISTINCT cwd FROM ${this.tables.sessions}`);
|
|
134
|
-
projectCwds = projects.map((project) => project.cwd).filter(matchesCwd);
|
|
178
|
+
const listed = this.listing.then(() => this.listScope(query));
|
|
179
|
+
this.listing = listed.then(() => { }, () => { });
|
|
180
|
+
// Resolve before yielding so a concurrent listing cannot change what this one returns.
|
|
181
|
+
const summaries = await listed;
|
|
182
|
+
for (const summary of summaries) {
|
|
135
183
|
this.assertListing(query);
|
|
136
|
-
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
const projectFilter = projectCwds ? ` AND cwd IN (${projectCwds.map(() => "?").join(", ")})` : "";
|
|
140
|
-
// Combine encoded strings only at read time, preserving NUL and lone surrogates verbatim.
|
|
141
|
-
const rows = await this.database.all(`SELECT s.*, (
|
|
142
|
-
SELECT COALESCE('[' || group_concat(text_json, ',') || ']', '[]')
|
|
143
|
-
FROM (SELECT text_json FROM ${this.tables.searchTexts} WHERE session_id = s.id ORDER BY seq)
|
|
144
|
-
) AS search_texts_json
|
|
145
|
-
FROM ${this.tables.sessions} AS s WHERE (? = 1 OR internal = 0)${projectFilter}`, query.includeInternal ? 1 : 0, ...(projectCwds ?? []));
|
|
146
|
-
for (const row of rows) {
|
|
147
|
-
this.assertListing(query);
|
|
148
|
-
const header = JSON.parse(row.header_json);
|
|
149
|
-
if (matchesCwd && !matchesCwd(header.cwd))
|
|
150
|
-
continue;
|
|
151
|
-
yield {
|
|
152
|
-
id: header.id,
|
|
153
|
-
cwd: header.cwd,
|
|
154
|
-
...(header.parentSessionId !== undefined ? { parentSessionId: header.parentSessionId } : {}),
|
|
155
|
-
internal: header.internal === true,
|
|
156
|
-
...(header.workflow !== undefined ? { workflow: header.workflow } : {}),
|
|
157
|
-
...(row.name !== null ? { name: JSON.parse(row.name) } : {}),
|
|
158
|
-
hasName: row.has_name === 1,
|
|
159
|
-
createdAt: header.createdAt,
|
|
160
|
-
modifiedAt: row.modified_at,
|
|
161
|
-
messageCount: row.message_count,
|
|
162
|
-
firstMessage: JSON.parse(row.first_message),
|
|
163
|
-
...(row.summary !== null ? { summary: JSON.parse(row.summary) } : {}),
|
|
164
|
-
...(row.summarized_through_id !== null ? { summarizedThroughId: row.summarized_through_id } : {}),
|
|
165
|
-
searchText: JSON.parse(row.search_texts_json).join(" "),
|
|
166
|
-
};
|
|
184
|
+
yield summary;
|
|
167
185
|
}
|
|
168
186
|
this.assertListing(query);
|
|
169
187
|
}
|
|
188
|
+
/** Revalidates one scope's cache and resolves its summaries; called for one listing at a time. */
|
|
189
|
+
async listScope(query) {
|
|
190
|
+
// The store may have closed, or the caller given up, while an earlier listing held the turn.
|
|
191
|
+
this.assertListing(query);
|
|
192
|
+
// Read the token first: a commit racing the reads below moves it again before the next call.
|
|
193
|
+
const token = await this.changeToken();
|
|
194
|
+
const key = JSON.stringify([query.includeInternal === true, query.cwd ?? null]);
|
|
195
|
+
const cached = this.scopes.get(key);
|
|
196
|
+
// A cached id without a summary is never expected; re-reading the scope repairs it instead of dropping it.
|
|
197
|
+
const scope = cached?.token === token && cached.ids.every((id) => this.summaries.has(id))
|
|
198
|
+
? cached
|
|
199
|
+
: { token, ids: await this.readScope(query, cached !== undefined) };
|
|
200
|
+
// Map order is recency order: re-inserting marks the scope as used, and the oldest scope is evicted first.
|
|
201
|
+
this.scopes.delete(key);
|
|
202
|
+
this.scopes.set(key, scope);
|
|
203
|
+
for (const oldest of this.scopes.keys()) {
|
|
204
|
+
if (this.scopes.size <= LISTING_SCOPES)
|
|
205
|
+
break;
|
|
206
|
+
this.scopes.delete(oldest);
|
|
207
|
+
}
|
|
208
|
+
if (scope !== cached)
|
|
209
|
+
this.pruneSummaries();
|
|
210
|
+
return scope.ids.flatMap((id) => this.summaries.get(id)?.summary ?? []);
|
|
211
|
+
}
|
|
170
212
|
async findMostRecent(query) {
|
|
171
213
|
let latest;
|
|
172
214
|
for await (const summary of this.list(query)) {
|
|
@@ -178,6 +220,80 @@ export class SqlSessionStore {
|
|
|
178
220
|
async close() {
|
|
179
221
|
this.assertOpen();
|
|
180
222
|
this.closed = true;
|
|
223
|
+
this.scopes.clear();
|
|
224
|
+
this.summaries.clear();
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* `data_version` moves when another connection commits and `total_changes()` when this one writes, so
|
|
228
|
+
* together they cover writers in every process; the table aggregates also catch a change to the sessions
|
|
229
|
+
* table if the adapter does not serve every statement from one connection.
|
|
230
|
+
*/
|
|
231
|
+
async changeToken() {
|
|
232
|
+
const row = await this.database.get(`SELECT data_version, total_changes() AS changes,
|
|
233
|
+
(SELECT count(*) FROM ${this.tables.sessions}) AS sessions,
|
|
234
|
+
(SELECT max(rowid) FROM ${this.tables.sessions}) AS last_row
|
|
235
|
+
FROM pragma_data_version`);
|
|
236
|
+
return JSON.stringify(Object.values(row ?? {}).map(String));
|
|
237
|
+
}
|
|
238
|
+
/** The scope's session ids in store order, with a current summary cached for each. */
|
|
239
|
+
async readScope(query, listedBefore) {
|
|
240
|
+
const matchesCwd = query.cwd === undefined
|
|
241
|
+
? undefined
|
|
242
|
+
: (this.cwdMatcher?.(query.cwd) ?? ((candidate) => candidate === query.cwd));
|
|
243
|
+
let projectCwds;
|
|
244
|
+
if (matchesCwd) {
|
|
245
|
+
const projects = await this.database.all(`SELECT DISTINCT cwd FROM ${this.tables.sessions}`);
|
|
246
|
+
projectCwds = projects.map((project) => project.cwd).filter(matchesCwd);
|
|
247
|
+
this.assertListing(query);
|
|
248
|
+
if (projectCwds.length === 0)
|
|
249
|
+
return [];
|
|
250
|
+
}
|
|
251
|
+
const scope = `(? = 1 OR internal = 0)${projectCwds ? ` AND cwd IN (${projectCwds.map(() => "?").join(", ")})` : ""}`;
|
|
252
|
+
const params = [query.includeInternal ? 1 : 0, ...(projectCwds ?? [])];
|
|
253
|
+
const inScope = (row) => !matchesCwd || matchesCwd(row.cwd);
|
|
254
|
+
if (listedBefore) {
|
|
255
|
+
const rows = (await this.database.all(`SELECT ${LISTING_COLUMNS} FROM ${this.tables.sessions} WHERE ${scope}`, ...params)).filter(inScope);
|
|
256
|
+
this.assertListing(query);
|
|
257
|
+
const stale = rows.filter((row) => this.summaries.get(row.id)?.version !== listingVersion(row));
|
|
258
|
+
// A few changed sessions are read by id; when most changed, one scan of the scope is cheaper.
|
|
259
|
+
if (stale.length <= rows.length / 4) {
|
|
260
|
+
for (let start = 0; start < stale.length; start += LISTING_FETCH_BATCH) {
|
|
261
|
+
const ids = stale.slice(start, start + LISTING_FETCH_BATCH).map((row) => row.id);
|
|
262
|
+
const fetched = new Set((await this.readSummaries(`id IN (${ids.map(() => "?").join(", ")})`, ids)).map((row) => row.id));
|
|
263
|
+
// A session deleted after the light read must not be listed from an older cached copy.
|
|
264
|
+
for (const id of ids)
|
|
265
|
+
if (!fetched.has(id))
|
|
266
|
+
this.summaries.delete(id);
|
|
267
|
+
this.assertListing(query);
|
|
268
|
+
}
|
|
269
|
+
return rows.flatMap((row) => (this.summaries.has(row.id) ? [row.id] : []));
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
const rows = (await this.readSummaries(scope, params)).filter(inScope);
|
|
273
|
+
this.assertListing(query);
|
|
274
|
+
return rows.map((row) => row.id);
|
|
275
|
+
}
|
|
276
|
+
/** Reads full listing rows, search text included, and caches their summaries. */
|
|
277
|
+
async readSummaries(where, params) {
|
|
278
|
+
// Combine encoded strings only at read time, preserving NUL and lone surrogates verbatim.
|
|
279
|
+
const rows = await this.database.all(`SELECT ${LISTING_COLUMNS}, (
|
|
280
|
+
SELECT COALESCE('[' || group_concat(text_json, ',') || ']', '[]')
|
|
281
|
+
FROM (SELECT text_json FROM ${this.tables.searchTexts} WHERE session_id = s.id ORDER BY seq)
|
|
282
|
+
) AS search_texts_json
|
|
283
|
+
FROM ${this.tables.sessions} AS s WHERE ${where}`, ...params);
|
|
284
|
+
for (const row of rows)
|
|
285
|
+
this.summaries.set(row.id, { version: listingVersion(row), summary: summaryFromRow(row) });
|
|
286
|
+
return rows;
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Keeps only summaries some cached scope still lists, so memory follows the live sessions. Runs in a
|
|
290
|
+
* listing's turn after it records its scope, when no other listing holds summaries it has not recorded.
|
|
291
|
+
*/
|
|
292
|
+
pruneSummaries() {
|
|
293
|
+
const listed = new Set([...this.scopes.values()].flatMap((scope) => scope.ids));
|
|
294
|
+
for (const id of this.summaries.keys())
|
|
295
|
+
if (!listed.has(id))
|
|
296
|
+
this.summaries.delete(id);
|
|
181
297
|
}
|
|
182
298
|
assertOpen() {
|
|
183
299
|
if (this.closed)
|
|
@@ -215,15 +331,15 @@ export class SqlSessionStore {
|
|
|
215
331
|
const summary = materializeSessionSummaryMetadata(header, state);
|
|
216
332
|
await tx.run(`INSERT INTO ${this.tables.sessions}
|
|
217
333
|
(id, cwd, created_at, header_json, internal, last_seq, modified_at, message_count,
|
|
218
|
-
first_message, name, has_name, summary, summarized_through_id, summary_state)
|
|
219
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
|
|
334
|
+
first_message, name, has_name, summary, summarized_through_id, summary_state, revision)
|
|
335
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, lower(hex(randomblob(16))))
|
|
220
336
|
ON CONFLICT(id) DO UPDATE SET
|
|
221
337
|
cwd = excluded.cwd, created_at = excluded.created_at, header_json = excluded.header_json,
|
|
222
338
|
internal = excluded.internal, last_seq = excluded.last_seq, modified_at = excluded.modified_at,
|
|
223
339
|
message_count = excluded.message_count, first_message = excluded.first_message, name = excluded.name,
|
|
224
340
|
has_name = excluded.has_name, summary = excluded.summary,
|
|
225
341
|
summarized_through_id = excluded.summarized_through_id,
|
|
226
|
-
summary_state = excluded.summary_state`, sessionId, header.cwd, header.createdAt, this.encode(header), header.internal ? 1 : 0, lastSeq, summary.modifiedAt, summary.messageCount, this.encode(summary.firstMessage), summary.name === undefined ? null : this.encode(summary.name), summary.hasName ? 1 : 0, summary.summary === undefined ? null : this.encode(summary.summary), summary.summarizedThroughId ?? null, this.encode(state));
|
|
342
|
+
summary_state = excluded.summary_state, revision = excluded.revision`, sessionId, header.cwd, header.createdAt, this.encode(header), header.internal ? 1 : 0, lastSeq, summary.modifiedAt, summary.messageCount, this.encode(summary.firstMessage), summary.name === undefined ? null : this.encode(summary.name), summary.hasName ? 1 : 0, summary.summary === undefined ? null : this.encode(summary.summary), summary.summarizedThroughId ?? null, this.encode(state));
|
|
227
343
|
return texts;
|
|
228
344
|
}
|
|
229
345
|
async insertEntries(tx, sessionId, entries, lastSeq, texts) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sql-session-store.js","sourceRoot":"","sources":["../../../../src/core/storage/session/sql-session-store.ts"],"names":[],"mappings":"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","sourcesContent":["import type { SessionEntry } from \"../../session-manager-types.ts\";\nimport type { SqliteDatabase, SqliteExecutor, SqliteRow } from \"../database.js\";\nimport { StorageInvalidTextError } from \"../errors.js\";\nimport { renderStorageIdentifiers } from \"../prefix.js\";\nimport { assertStorageSchemaVersion } from \"../schema.js\";\nimport {\n\tSessionConflictError,\n\tSessionExistsError,\n\tSessionIdMismatchError,\n\tSessionNotFoundError,\n\tStorageUnavailableError,\n\tStoreClosedError,\n} from \"./errors.js\";\nimport {\n\tapplySessionSummaryEntries,\n\tmaterializeSessionSummaryMetadata,\n\ttype SessionSummaryState,\n\ttype SessionSummaryText,\n} from \"./session-summary.js\";\nimport type {\n\tSessionCwdMatcher,\n\tSessionListQuery,\n\tSessionRecordHeader,\n\tSessionSnapshot,\n\tSessionStore,\n\tSessionSummary,\n\tSessionWriteOptions,\n\tStorageDescriptor,\n} from \"./types.js\";\nimport { validateSessionEntries, validateSessionHeader, validateSessionText } from \"./validation.js\";\n\nexport const SESSION_SCHEMA_VERSION = 1;\nexport const SESSION_TABLES = Object.freeze({\n\tmeta: \"meta\",\n\tsessions: \"sessions\",\n\tentries: \"entries\",\n\tsearchTexts: \"search_texts\",\n});\n\ntype Tables = Readonly<Record<keyof typeof SESSION_TABLES, string>>;\ntype HeaderRow = SqliteRow & { header_json: string; last_seq: number };\ntype SummaryStateRow = HeaderRow & { summary_state: string };\ntype SummaryRow = HeaderRow & {\n\tmodified_at: string;\n\tmessage_count: number;\n\tfirst_message: string;\n\tname: string | null;\n\thas_name: number;\n\tsummary: string | null;\n\tsummarized_through_id: string | null;\n\tsearch_texts_json: string;\n};\n\nexport class SqlSessionStore implements SessionStore {\n\tprivate readonly database: SqliteDatabase;\n\tprivate readonly tables: Tables;\n\tprivate readonly prefix: string;\n\tprivate closed = false;\n\tprivate readonly cwdMatcher?: SessionCwdMatcher;\n\n\tprivate constructor(database: SqliteDatabase, tables: Tables, prefix = \"\", cwdMatcher?: SessionCwdMatcher) {\n\t\tthis.database = database;\n\t\tthis.tables = tables;\n\t\tthis.prefix = prefix;\n\t\tthis.cwdMatcher = cwdMatcher;\n\t}\n\n\tstatic async open(\n\t\tdatabase: SqliteDatabase,\n\t\toptions: { readonly prefix?: string; readonly cwdMatcher?: SessionCwdMatcher } = {},\n\t): Promise<SqlSessionStore> {\n\t\tconst tables = renderStorageIdentifiers(\"sessions\", SESSION_TABLES, options.prefix);\n\t\tawait database.transaction(async (tx) => {\n\t\t\tawait tx.exec(`CREATE TABLE IF NOT EXISTS ${tables.meta} (schema_version INTEGER NOT NULL) STRICT`);\n\t\t\tconst versions = await tx.all(`SELECT schema_version FROM ${tables.meta}`);\n\t\t\tif (versions.length === 0) {\n\t\t\t\tawait tx.run(`INSERT INTO ${tables.meta} VALUES (?)`, SESSION_SCHEMA_VERSION);\n\t\t\t}\n\t\t\tfor (const version of versions) {\n\t\t\t\tassertStorageSchemaVersion(\"sessions\", version.schema_version!, SESSION_SCHEMA_VERSION);\n\t\t\t}\n\t\t\tawait tx.exec(`\n\t\t\t\tCREATE TABLE IF NOT EXISTS ${tables.sessions} (\n\t\t\t\t\tid TEXT PRIMARY KEY, cwd TEXT NOT NULL, created_at TEXT NOT NULL,\n\t\t\t\t\theader_json TEXT NOT NULL CHECK(json_valid(header_json)), internal INTEGER NOT NULL,\n\t\t\t\t\tlast_seq INTEGER NOT NULL, modified_at TEXT NOT NULL, message_count INTEGER NOT NULL,\n\t\t\t\t\tfirst_message TEXT NOT NULL CHECK(json_valid(first_message)),\n\t\t\t\t\tname TEXT CHECK(name IS NULL OR json_valid(name)), has_name INTEGER NOT NULL,\n\t\t\t\t\tsummary TEXT CHECK(summary IS NULL OR json_valid(summary)), summarized_through_id TEXT,\n\t\t\t\t\tsummary_state TEXT NOT NULL CHECK(json_valid(summary_state))\n\t\t\t\t) STRICT;\n\t\t\t\tCREATE TABLE IF NOT EXISTS ${tables.entries} (\n\t\t\t\t\tsession_id TEXT NOT NULL, seq INTEGER NOT NULL, entry_id TEXT NOT NULL,\n\t\t\t\t\tentry_json TEXT NOT NULL CHECK(json_valid(entry_json)), PRIMARY KEY(session_id, seq)\n\t\t\t\t) STRICT;\n\t\t\t\tCREATE TABLE IF NOT EXISTS ${tables.searchTexts} (\n\t\t\t\t\tsession_id TEXT NOT NULL, seq INTEGER NOT NULL,\n\t\t\t\t\ttext_json TEXT NOT NULL CHECK(json_valid(text_json)), PRIMARY KEY(session_id, seq)\n\t\t\t\t) STRICT;\n\t\t\t`);\n\t\t});\n\t\treturn new SqlSessionStore(database, tables, options.prefix, options.cwdMatcher);\n\t}\n\n\tget descriptor(): StorageDescriptor {\n\t\treturn { ...this.database.descriptor, ...(this.prefix === \"\" ? {} : { prefix: this.prefix }) };\n\t}\n\n\tasync create(header: SessionRecordHeader, entries: readonly SessionEntry[]): Promise<{ readonly lastSeq: number }> {\n\t\tthis.assertOpen();\n\t\tvalidateSessionHeader(header);\n\t\tvalidateSessionEntries(entries);\n\t\treturn this.database.transaction(async (tx) => {\n\t\t\tif (await tx.get(`SELECT id FROM ${this.tables.sessions} WHERE id = ?`, header.id)) {\n\t\t\t\tthrow new SessionExistsError(header.id);\n\t\t\t}\n\t\t\tconst texts = await this.saveSummary(tx, header.id, { header, entries, lastSeq: entries.length });\n\t\t\tawait this.insertEntries(tx, header.id, entries, 0, texts);\n\t\t\treturn { lastSeq: entries.length };\n\t\t});\n\t}\n\n\tasync append(\n\t\tsessionId: string,\n\t\tentries: readonly SessionEntry[],\n\t\toptions: SessionWriteOptions,\n\t): Promise<{ readonly lastSeq: number }> {\n\t\tthis.assertOpen();\n\t\tvalidateSessionText(\"sessionId\", sessionId);\n\t\treturn this.database.transaction(async (tx) => {\n\t\t\tconst previous = await this.forWrite(tx, sessionId, options, true);\n\t\t\tvalidateSessionEntries(entries);\n\t\t\tconst lastSeq = previous.last_seq + entries.length;\n\t\t\tconst texts = await this.saveSummary(\n\t\t\t\ttx,\n\t\t\t\tsessionId,\n\t\t\t\t{ header: JSON.parse(previous.header_json) as SessionRecordHeader, entries, lastSeq },\n\t\t\t\tJSON.parse(previous.summary_state) as SessionSummaryState,\n\t\t\t);\n\t\t\tawait this.insertEntries(tx, sessionId, entries, previous.last_seq, texts);\n\t\t\treturn { lastSeq };\n\t\t});\n\t}\n\n\tasync replace(\n\t\tsessionId: string,\n\t\theader: SessionRecordHeader,\n\t\tentries: readonly SessionEntry[],\n\t\toptions: SessionWriteOptions,\n\t): Promise<{ readonly lastSeq: number }> {\n\t\tthis.assertOpen();\n\t\tvalidateSessionText(\"sessionId\", sessionId);\n\t\treturn this.database.transaction(async (tx) => {\n\t\t\tawait this.forWrite(tx, sessionId, options);\n\t\t\tvalidateSessionHeader(header);\n\t\t\tvalidateSessionEntries(entries);\n\t\t\tif (header.id !== sessionId) throw new SessionIdMismatchError(sessionId, header.id);\n\t\t\tawait tx.run(`DELETE FROM ${this.tables.searchTexts} WHERE session_id = ?`, sessionId);\n\t\t\tawait tx.run(`DELETE FROM ${this.tables.entries} WHERE session_id = ?`, sessionId);\n\t\t\tconst texts = await this.saveSummary(tx, sessionId, { header, entries, lastSeq: entries.length });\n\t\t\tawait this.insertEntries(tx, sessionId, entries, 0, texts);\n\t\t\treturn { lastSeq: entries.length };\n\t\t});\n\t}\n\n\tasync load(sessionId: string): Promise<SessionSnapshot> {\n\t\tthis.assertOpen();\n\t\tvalidateSessionText(\"sessionId\", sessionId);\n\t\treturn this.database.transaction((tx) => this.read(tx, sessionId));\n\t}\n\n\tasync readHeader(sessionId: string): Promise<SessionRecordHeader | undefined> {\n\t\tthis.assertOpen();\n\t\tvalidateSessionText(\"sessionId\", sessionId);\n\t\tconst row = await this.database.get<HeaderRow>(\n\t\t\t`SELECT header_json FROM ${this.tables.sessions} WHERE id = ?`,\n\t\t\tsessionId,\n\t\t);\n\t\treturn row ? (JSON.parse(row.header_json) as SessionRecordHeader) : undefined;\n\t}\n\n\tasync delete(sessionId: string): Promise<void> {\n\t\tthis.assertOpen();\n\t\tvalidateSessionText(\"sessionId\", sessionId);\n\t\tawait this.database.transaction(async (tx) => {\n\t\t\tawait tx.run(`DELETE FROM ${this.tables.searchTexts} WHERE session_id = ?`, sessionId);\n\t\t\tawait tx.run(`DELETE FROM ${this.tables.entries} WHERE session_id = ?`, sessionId);\n\t\t\tawait tx.run(`DELETE FROM ${this.tables.sessions} WHERE id = ?`, sessionId);\n\t\t});\n\t}\n\n\tasync *list(query: SessionListQuery): AsyncIterable<SessionSummary> {\n\t\tthis.assertListing(query);\n\t\t// Validate the original query before binding only matching stored spellings below.\n\t\tif (query.cwd?.includes(\"\\0\")) throw new StorageInvalidTextError(0);\n\t\tconst matchesCwd =\n\t\t\tquery.cwd === undefined\n\t\t\t\t? undefined\n\t\t\t\t: (this.cwdMatcher?.(query.cwd) ?? ((candidate: string | undefined) => candidate === query.cwd));\n\t\tlet projectCwds: string[] | undefined;\n\t\tif (matchesCwd) {\n\t\t\tconst projects = await this.database.all<SqliteRow & { cwd: string }>(\n\t\t\t\t`SELECT DISTINCT cwd FROM ${this.tables.sessions}`,\n\t\t\t);\n\t\t\tprojectCwds = projects.map((project) => project.cwd).filter(matchesCwd);\n\t\t\tthis.assertListing(query);\n\t\t\tif (projectCwds.length === 0) return;\n\t\t}\n\t\tconst projectFilter = projectCwds ? ` AND cwd IN (${projectCwds.map(() => \"?\").join(\", \")})` : \"\";\n\t\t// Combine encoded strings only at read time, preserving NUL and lone surrogates verbatim.\n\t\tconst rows = await this.database.all<SummaryRow>(\n\t\t\t`SELECT s.*, (\n\t\t\t\tSELECT COALESCE('[' || group_concat(text_json, ',') || ']', '[]')\n\t\t\t\tFROM (SELECT text_json FROM ${this.tables.searchTexts} WHERE session_id = s.id ORDER BY seq)\n\t\t\t) AS search_texts_json\n\t\t\tFROM ${this.tables.sessions} AS s WHERE (? = 1 OR internal = 0)${projectFilter}`,\n\t\t\tquery.includeInternal ? 1 : 0,\n\t\t\t...(projectCwds ?? []),\n\t\t);\n\t\tfor (const row of rows) {\n\t\t\tthis.assertListing(query);\n\t\t\tconst header = JSON.parse(row.header_json) as SessionRecordHeader;\n\t\t\tif (matchesCwd && !matchesCwd(header.cwd)) continue;\n\t\t\tyield {\n\t\t\t\tid: header.id,\n\t\t\t\tcwd: header.cwd,\n\t\t\t\t...(header.parentSessionId !== undefined ? { parentSessionId: header.parentSessionId } : {}),\n\t\t\t\tinternal: header.internal === true,\n\t\t\t\t...(header.workflow !== undefined ? { workflow: header.workflow } : {}),\n\t\t\t\t...(row.name !== null ? { name: JSON.parse(row.name) as string } : {}),\n\t\t\t\thasName: row.has_name === 1,\n\t\t\t\tcreatedAt: header.createdAt,\n\t\t\t\tmodifiedAt: row.modified_at,\n\t\t\t\tmessageCount: row.message_count,\n\t\t\t\tfirstMessage: JSON.parse(row.first_message) as string,\n\t\t\t\t...(row.summary !== null ? { summary: JSON.parse(row.summary) as string } : {}),\n\t\t\t\t...(row.summarized_through_id !== null ? { summarizedThroughId: row.summarized_through_id } : {}),\n\t\t\t\tsearchText: (JSON.parse(row.search_texts_json) as string[]).join(\" \"),\n\t\t\t};\n\t\t}\n\t\tthis.assertListing(query);\n\t}\n\n\tasync findMostRecent(query: {\n\t\treadonly cwd: string;\n\t\treadonly includeInternal?: boolean;\n\t}): Promise<SessionSummary | undefined> {\n\t\tlet latest: SessionSummary | undefined;\n\t\tfor await (const summary of this.list(query)) {\n\t\t\tif (!latest || Date.parse(summary.modifiedAt) > Date.parse(latest.modifiedAt)) latest = summary;\n\t\t}\n\t\treturn latest;\n\t}\n\n\tasync close(): Promise<void> {\n\t\tthis.assertOpen();\n\t\tthis.closed = true;\n\t}\n\n\tprivate assertOpen(): void {\n\t\tif (this.closed) throw new StoreClosedError(this.descriptor);\n\t}\n\n\tprivate assertListing(query: SessionListQuery): void {\n\t\tthis.assertOpen();\n\t\tif (query.signal?.aborted) throw new DOMException(\"Session listing aborted\", \"AbortError\");\n\t}\n\n\tprivate async read(tx: SqliteExecutor, sessionId: string): Promise<SessionSnapshot> {\n\t\tconst row = await tx.get<HeaderRow>(\n\t\t\t`SELECT header_json, last_seq FROM ${this.tables.sessions} WHERE id = ?`,\n\t\t\tsessionId,\n\t\t);\n\t\tif (!row) throw new SessionNotFoundError(sessionId);\n\t\tconst entries = await tx.all<SqliteRow & { entry_json: string }>(\n\t\t\t`SELECT entry_json FROM ${this.tables.entries} WHERE session_id = ? ORDER BY seq`,\n\t\t\tsessionId,\n\t\t);\n\t\treturn {\n\t\t\theader: JSON.parse(row.header_json) as SessionRecordHeader,\n\t\t\tentries: entries.map((entry) => JSON.parse(entry.entry_json) as SessionEntry),\n\t\t\tlastSeq: row.last_seq,\n\t\t};\n\t}\n\n\tprivate forWrite(\n\t\ttx: SqliteExecutor,\n\t\tsessionId: string,\n\t\toptions: SessionWriteOptions,\n\t\tincludeSummaryState: true,\n\t): Promise<SummaryStateRow>;\n\tprivate forWrite(\n\t\ttx: SqliteExecutor,\n\t\tsessionId: string,\n\t\toptions: SessionWriteOptions,\n\t\tincludeSummaryState?: false,\n\t): Promise<HeaderRow>;\n\tprivate async forWrite(\n\t\ttx: SqliteExecutor,\n\t\tsessionId: string,\n\t\toptions: SessionWriteOptions,\n\t\tincludeSummaryState = false,\n\t): Promise<HeaderRow> {\n\t\tconst row = await tx.get<HeaderRow>(\n\t\t\t`SELECT header_json, last_seq${includeSummaryState ? \", summary_state\" : \"\"}\n\t\t\t FROM ${this.tables.sessions} WHERE id = ?`,\n\t\t\tsessionId,\n\t\t);\n\t\tif (!row) throw new SessionNotFoundError(sessionId);\n\t\tif (row.last_seq !== options.expectSeq) {\n\t\t\tthrow new SessionConflictError(sessionId, options.expectSeq, row.last_seq);\n\t\t}\n\t\treturn row;\n\t}\n\n\tprivate async saveSummary(\n\t\ttx: SqliteExecutor,\n\t\tsessionId: string,\n\t\tsnapshot: SessionSnapshot,\n\t\tprevious?: SessionSummaryState,\n\t): Promise<readonly SessionSummaryText[]> {\n\t\tconst { header, lastSeq } = snapshot;\n\t\tconst { state, texts } = applySessionSummaryEntries(previous, snapshot.entries);\n\t\tconst summary = materializeSessionSummaryMetadata(header, state);\n\t\tawait tx.run(\n\t\t\t`INSERT INTO ${this.tables.sessions}\n\t\t\t\t(id, cwd, created_at, header_json, internal, last_seq, modified_at, message_count,\n\t\t\t\t first_message, name, has_name, summary, summarized_through_id, summary_state)\n\t\t\t\tVALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n\t\t\t\tON CONFLICT(id) DO UPDATE SET\n\t\t\t\tcwd = excluded.cwd, created_at = excluded.created_at, header_json = excluded.header_json,\n\t\t\t\tinternal = excluded.internal, last_seq = excluded.last_seq, modified_at = excluded.modified_at,\n\t\t\t\tmessage_count = excluded.message_count, first_message = excluded.first_message, name = excluded.name,\n\t\t\t\thas_name = excluded.has_name, summary = excluded.summary,\n\t\t\t\tsummarized_through_id = excluded.summarized_through_id,\n\t\t\t\tsummary_state = excluded.summary_state`,\n\t\t\tsessionId,\n\t\t\theader.cwd,\n\t\t\theader.createdAt,\n\t\t\tthis.encode(header),\n\t\t\theader.internal ? 1 : 0,\n\t\t\tlastSeq,\n\t\t\tsummary.modifiedAt,\n\t\t\tsummary.messageCount,\n\t\t\tthis.encode(summary.firstMessage),\n\t\t\tsummary.name === undefined ? null : this.encode(summary.name),\n\t\t\tsummary.hasName ? 1 : 0,\n\t\t\tsummary.summary === undefined ? null : this.encode(summary.summary),\n\t\t\tsummary.summarizedThroughId ?? null,\n\t\t\tthis.encode(state),\n\t\t);\n\t\treturn texts;\n\t}\n\n\tprivate async insertEntries(\n\t\ttx: SqliteExecutor,\n\t\tsessionId: string,\n\t\tentries: readonly SessionEntry[],\n\t\tlastSeq: number,\n\t\ttexts: readonly SessionSummaryText[],\n\t): Promise<void> {\n\t\tfor (const [index, entry] of entries.entries()) {\n\t\t\tawait tx.run(\n\t\t\t\t`INSERT INTO ${this.tables.entries} (session_id, seq, entry_id, entry_json) VALUES (?, ?, ?, ?)`,\n\t\t\t\tsessionId,\n\t\t\t\tlastSeq + index + 1,\n\t\t\t\tentry.id,\n\t\t\t\tthis.encode(entry),\n\t\t\t);\n\t\t}\n\t\tfor (const { index, text } of texts) {\n\t\t\tawait tx.run(\n\t\t\t\t`INSERT INTO ${this.tables.searchTexts} (session_id, seq, text_json) VALUES (?, ?, ?)`,\n\t\t\t\tsessionId,\n\t\t\t\tlastSeq + index + 1,\n\t\t\t\tthis.encode(text),\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate encode(value: SessionRecordHeader | SessionEntry | SessionSummaryState | string): string {\n\t\ttry {\n\t\t\treturn JSON.stringify(value);\n\t\t} catch (cause) {\n\t\t\tthrow new StorageUnavailableError(this.descriptor, cause as Error);\n\t\t}\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"sql-session-store.js","sourceRoot":"","sources":["../../../../src/core/storage/session/sql-session-store.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EACN,oBAAoB,EACpB,kBAAkB,EAClB,sBAAsB,EACtB,oBAAoB,EACpB,uBAAuB,EACvB,gBAAgB,GAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,0BAA0B,EAC1B,iCAAiC,GAGjC,MAAM,sBAAsB,CAAC;AAW9B,OAAO,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAErG,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC;AACxC,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC;IAC3C,IAAI,EAAE,MAAM;IACZ,QAAQ,EAAE,UAAU;IACpB,OAAO,EAAE,SAAS;IAClB,WAAW,EAAE,cAAc;CAC3B,CAAC,CAAC;AAoBH,6FAA6F;AAC7F,MAAM,eAAe,GACpB,+IAA+I,CAAC;AACjJ,2FAA2F;AAC3F,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,CAAC;AACvC,iFAAiF;AACjF,MAAM,cAAc,GAAG,CAAC,CAAC;AAEzB,SAAS,cAAc,CAAC,GAAe;IACtC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,CAAwB,CAAC;IAClE,OAAO;QACN,EAAE,EAAE,MAAM,CAAC,EAAE;QACb,GAAG,EAAE,MAAM,CAAC,GAAG;QACf,GAAG,CAAC,MAAM,CAAC,eAAe,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,MAAM,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5F,QAAQ,EAAE,MAAM,CAAC,QAAQ,KAAK,IAAI;QAClC,GAAG,CAAC,MAAM,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvE,GAAG,CAAC,GAAG,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACtE,OAAO,EAAE,GAAG,CAAC,QAAQ,KAAK,CAAC;QAC3B,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,UAAU,EAAE,GAAG,CAAC,WAAW;QAC3B,YAAY,EAAE,GAAG,CAAC,aAAa;QAC/B,YAAY,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,aAAa,CAAW;QACrD,GAAG,CAAC,GAAG,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/E,GAAG,CAAC,GAAG,CAAC,qBAAqB,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,mBAAmB,EAAE,GAAG,CAAC,qBAAqB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACjG,UAAU,EAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAc,CAAC,IAAI,CAAC,GAAG,CAAC;KACrE,CAAC;AACH,CAAC;AAED,4GAA4G;AAC5G,SAAS,cAAc,CAAC,GAAe;IACtC,OAAO,GAAG,GAAG,CAAC,QAAQ,SAAS,GAAG,CAAC,QAAQ,SAAS,GAAG,CAAC,WAAW,SAAS,GAAG,CAAC,aAAa,SAAS,GAAG,CAAC,QAAQ,SAAS,GAAG,CAAC,IAAI,SAAS,GAAG,CAAC,qBAAqB,SAAS,GAAG,CAAC,OAAO,SAAS,GAAG,CAAC,aAAa,SAAS,GAAG,CAAC,WAAW,EAAE,CAAC;AAC/O,CAAC;AAED,MAAM,OAAO,eAAe;IACV,QAAQ,CAAiB;IACzB,MAAM,CAAS;IACf,MAAM,CAAS;IACxB,MAAM,GAAG,KAAK,CAAC;IACN,UAAU,CAAqB;IAChD,oGAAoG;IACnF,MAAM,GAAG,IAAI,GAAG,EAAuE,CAAC;IACzG,4GAA4G;IAC3F,SAAS,GAAG,IAAI,GAAG,EAA0E,CAAC;IAC/G;;;OAGG;IACK,OAAO,GAAkB,OAAO,CAAC,OAAO,EAAE,CAAC;IAEnD,YAAoB,QAAwB,EAAE,MAAc,EAAE,MAAM,GAAG,EAAE,EAAE,UAA8B;QACxG,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC9B,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,IAAI,CAChB,QAAwB,EACxB,OAAO,GAA0E,EAAE;QAEnF,MAAM,MAAM,GAAG,wBAAwB,CAAC,UAAU,EAAE,cAAc,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QACpF,MAAM,QAAQ,CAAC,WAAW,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;YACvC,MAAM,EAAE,CAAC,IAAI,CAAC,8BAA8B,MAAM,CAAC,IAAI,2CAA2C,CAAC,CAAC;YACpG,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC,GAAG,CAAC,8BAA8B,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;YAC3E,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC3B,MAAM,EAAE,CAAC,GAAG,CAAC,eAAe,MAAM,CAAC,IAAI,aAAa,EAAE,sBAAsB,CAAC,CAAC;YAC/E,CAAC;YACD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;gBAChC,0BAA0B,CAAC,UAAU,EAAE,OAAO,CAAC,cAAe,EAAE,sBAAsB,CAAC,CAAC;YACzF,CAAC;YACD,MAAM,EAAE,CAAC,IAAI,CAAC;iCACgB,MAAM,CAAC,QAAQ;;;;;;;;;iCASf,MAAM,CAAC,OAAO;;;;iCAId,MAAM,CAAC,WAAW;;;;IAI/C,CAAC,CAAC;YACH,uGAAuG;YACvG,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC,GAAG,CAC5B,+DAA+D,EAC/D,MAAM,CAAC,QAAQ,CACf,CAAC;YACF,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACf,MAAM,EAAE,CAAC,IAAI,CAAC,eAAe,MAAM,CAAC,QAAQ,+CAA+C,CAAC,CAAC;YAC9F,CAAC;QACF,CAAC,CAAC,CAAC;QACH,OAAO,IAAI,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAClF,CAAC;IAED,IAAI,UAAU;QACb,OAAO,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,GAAG,CAAC,IAAI,CAAC,MAAM,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC;IAChG,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,MAA2B,EAAE,OAAgC;QACzE,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,qBAAqB,CAAC,MAAM,CAAC,CAAC;QAC9B,sBAAsB,CAAC,OAAO,CAAC,CAAC;QAChC,OAAO,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;YAC7C,IAAI,MAAM,EAAE,CAAC,GAAG,CAAC,kBAAkB,IAAI,CAAC,MAAM,CAAC,QAAQ,eAAe,EAAE,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;gBACpF,MAAM,IAAI,kBAAkB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACzC,CAAC;YACD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;YAClG,MAAM,IAAI,CAAC,aAAa,CAAC,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;YAC3D,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;QACpC,CAAC,CAAC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,MAAM,CACX,SAAiB,EACjB,OAAgC,EAChC,OAA4B;QAE5B,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,mBAAmB,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;QAC5C,OAAO,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;YAC7C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;YACnE,sBAAsB,CAAC,OAAO,CAAC,CAAC;YAChC,MAAM,OAAO,GAAG,QAAQ,CAAC,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC;YACnD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,WAAW,CACnC,EAAE,EACF,SAAS,EACT,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAwB,EAAE,OAAO,EAAE,OAAO,EAAE,EACrF,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAwB,CACzD,CAAC;YACF,MAAM,IAAI,CAAC,aAAa,CAAC,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;YAC3E,OAAO,EAAE,OAAO,EAAE,CAAC;QACpB,CAAC,CAAC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,OAAO,CACZ,SAAiB,EACjB,MAA2B,EAC3B,OAAgC,EAChC,OAA4B;QAE5B,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,mBAAmB,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;QAC5C,OAAO,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;YAC7C,MAAM,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;YAC5C,qBAAqB,CAAC,MAAM,CAAC,CAAC;YAC9B,sBAAsB,CAAC,OAAO,CAAC,CAAC;YAChC,IAAI,MAAM,CAAC,EAAE,KAAK,SAAS;gBAAE,MAAM,IAAI,sBAAsB,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;YACpF,MAAM,EAAE,CAAC,GAAG,CAAC,eAAe,IAAI,CAAC,MAAM,CAAC,WAAW,uBAAuB,EAAE,SAAS,CAAC,CAAC;YACvF,MAAM,EAAE,CAAC,GAAG,CAAC,eAAe,IAAI,CAAC,MAAM,CAAC,OAAO,uBAAuB,EAAE,SAAS,CAAC,CAAC;YACnF,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;YAClG,MAAM,IAAI,CAAC,aAAa,CAAC,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;YAC3D,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;QACpC,CAAC,CAAC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,SAAiB;QAC3B,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,mBAAmB,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;QAC5C,OAAO,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC;IACpE,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,SAAiB;QACjC,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,mBAAmB,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;QAC5C,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,CAClC,2BAA2B,IAAI,CAAC,MAAM,CAAC,QAAQ,eAAe,EAC9D,SAAS,CACT,CAAC;QACF,OAAO,GAAG,CAAC,CAAC,CAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,CAAyB,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/E,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,SAAiB;QAC7B,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,mBAAmB,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;QAC5C,MAAM,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE;YAC5C,MAAM,EAAE,CAAC,GAAG,CAAC,eAAe,IAAI,CAAC,MAAM,CAAC,WAAW,uBAAuB,EAAE,SAAS,CAAC,CAAC;YACvF,MAAM,EAAE,CAAC,GAAG,CAAC,eAAe,IAAI,CAAC,MAAM,CAAC,OAAO,uBAAuB,EAAE,SAAS,CAAC,CAAC;YACnF,MAAM,EAAE,CAAC,GAAG,CAAC,eAAe,IAAI,CAAC,MAAM,CAAC,QAAQ,eAAe,EAAE,SAAS,CAAC,CAAC;QAC7E,CAAC,CAAC,CAAC;IACJ,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,CAAC,IAAI,CAAC,KAAuB;QAClC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAC1B,mFAAmF;QACnF,IAAI,KAAK,CAAC,GAAG,EAAE,QAAQ,CAAC,IAAI,CAAC;YAAE,MAAM,IAAI,uBAAuB,CAAC,CAAC,CAAC,CAAC;QACpE,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;QAC9D,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,IAAI,CACzB,GAAG,EAAE,GAAE,CAAC,EACR,GAAG,EAAE,GAAE,CAAC,CACR,CAAC;QACF,uFAAuF;QACvF,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC;QAC/B,KAAK,MAAM,OAAO,IAAI,SAAS,EAAE,CAAC;YACjC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;YAC1B,MAAM,OAAO,CAAC;QACf,CAAC;QACD,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC;IAED,kGAAkG;IAC1F,KAAK,CAAC,SAAS,CAAC,KAAuB;QAC9C,6FAA6F;QAC7F,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAC1B,6FAA6F;QAC7F,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;QACvC,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,eAAe,KAAK,IAAI,EAAE,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC;QAChF,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACpC,2GAA2G;QAC3G,MAAM,KAAK,GACV,MAAM,EAAE,KAAK,KAAK,KAAK,IAAI,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAC1E,CAAC,CAAC,MAAM;YACR,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,MAAM,KAAK,SAAS,CAAC,EAAE,CAAC;QACtE,2GAA2G;QAC3G,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACxB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC5B,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;YACzC,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,cAAc;gBAAE,MAAM;YAC9C,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC5B,CAAC;QACD,IAAI,KAAK,KAAK,MAAM;YAAE,IAAI,CAAC,cAAc,EAAE,CAAC;QAC5C,OAAO,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC;IACzE,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,KAGpB;QACA,IAAI,MAAkC,CAAC;QACvC,IAAI,KAAK,EAAE,MAAM,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YAC9C,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC;gBAAE,MAAM,GAAG,OAAO,CAAC;QACjG,CAAC;QACD,OAAO,MAAM,CAAC;IACf,CAAC;IAED,KAAK,CAAC,KAAK;QACV,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACpB,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,WAAW;QACxB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,CAClC;4BACyB,IAAI,CAAC,MAAM,CAAC,QAAQ;8BAClB,IAAI,CAAC,MAAM,CAAC,QAAQ;4BACtB,CACzB,CAAC;QACF,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IAC7D,CAAC;IAED,sFAAsF;IAC9E,KAAK,CAAC,SAAS,CAAC,KAAuB,EAAE,YAAqB;QACrE,MAAM,UAAU,GACf,KAAK,CAAC,GAAG,KAAK,SAAS;YACtB,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,SAA6B,EAAE,EAAE,CAAC,SAAS,KAAK,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;QACnG,IAAI,WAAiC,CAAC;QACtC,IAAI,UAAU,EAAE,CAAC;YAChB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,CACvC,4BAA4B,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAClD,CAAC;YACF,WAAW,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YACxE,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;YAC1B,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,EAAE,CAAC;QACzC,CAAC;QACD,MAAM,KAAK,GAAG,0BAA0B,WAAW,CAAC,CAAC,CAAC,gBAAgB,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QACtH,MAAM,MAAM,GAAG,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,CAAC;QACvE,MAAM,OAAO,GAAG,CAAC,GAAe,EAAE,EAAE,CAAC,CAAC,UAAU,IAAI,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACxE,IAAI,YAAY,EAAE,CAAC;YAClB,MAAM,IAAI,GAAG,CACZ,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,CACtB,UAAU,eAAe,SAAS,IAAI,CAAC,MAAM,CAAC,QAAQ,UAAU,KAAK,EAAE,EACvE,GAAG,MAAM,CACT,CACD,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAClB,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;YAC1B,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,OAAO,KAAK,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC;YAChG,8FAA8F;YAC9F,IAAI,KAAK,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACrC,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,KAAK,IAAI,mBAAmB,EAAE,CAAC;oBACxE,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,mBAAmB,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;oBACjF,MAAM,OAAO,GAAG,IAAI,GAAG,CACtB,CAAC,MAAM,IAAI,CAAC,aAAa,CAAC,UAAU,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAChG,CAAC;oBACF,uFAAuF;oBACvF,KAAK,MAAM,EAAE,IAAI,GAAG;wBAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;4BAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;oBACtE,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;gBAC3B,CAAC;gBACD,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAC5E,CAAC;QACF,CAAC;QACD,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACvE,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAC1B,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClC,CAAC;IAED,iFAAiF;IACzE,KAAK,CAAC,aAAa,CAAC,KAAa,EAAE,MAA8B;QACxE,0FAA0F;QAC1F,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,CACnC,UAAU,eAAe;;kCAEM,IAAI,CAAC,MAAM,CAAC,WAAW;;UAE/C,IAAI,CAAC,MAAM,CAAC,QAAQ,eAAe,KAAK,EAAE,EACjD,GAAG,MAAM,CACT,CAAC;QACF,KAAK,MAAM,GAAG,IAAI,IAAI;YACrB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,cAAc,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC5F,OAAO,IAAI,CAAC;IACb,CAAC;IAED;;;OAGG;IACK,cAAc;QACrB,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;QAChF,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE;YAAE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;gBAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACxF,CAAC;IAEO,UAAU;QACjB,IAAI,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,gBAAgB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC9D,CAAC;IAEO,aAAa,CAAC,KAAuB;QAC5C,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,IAAI,KAAK,CAAC,MAAM,EAAE,OAAO;YAAE,MAAM,IAAI,YAAY,CAAC,yBAAyB,EAAE,YAAY,CAAC,CAAC;IAC5F,CAAC;IAEO,KAAK,CAAC,IAAI,CAAC,EAAkB,EAAE,SAAiB;QACvD,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,GAAG,CACvB,qCAAqC,IAAI,CAAC,MAAM,CAAC,QAAQ,eAAe,EACxE,SAAS,CACT,CAAC;QACF,IAAI,CAAC,GAAG;YAAE,MAAM,IAAI,oBAAoB,CAAC,SAAS,CAAC,CAAC;QACpD,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,GAAG,CAC3B,0BAA0B,IAAI,CAAC,MAAM,CAAC,OAAO,oCAAoC,EACjF,SAAS,CACT,CAAC;QACF,OAAO;YACN,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,CAAwB;YAC1D,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,CAAiB,CAAC;YAC7E,OAAO,EAAE,GAAG,CAAC,QAAQ;SACrB,CAAC;IACH,CAAC;IAcO,KAAK,CAAC,QAAQ,CACrB,EAAkB,EAClB,SAAiB,EACjB,OAA4B,EAC5B,mBAAmB,GAAG,KAAK;QAE3B,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,GAAG,CACvB,+BAA+B,mBAAmB,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE;WACnE,IAAI,CAAC,MAAM,CAAC,QAAQ,eAAe,EAC3C,SAAS,CACT,CAAC;QACF,IAAI,CAAC,GAAG;YAAE,MAAM,IAAI,oBAAoB,CAAC,SAAS,CAAC,CAAC;QACpD,IAAI,GAAG,CAAC,QAAQ,KAAK,OAAO,CAAC,SAAS,EAAE,CAAC;YACxC,MAAM,IAAI,oBAAoB,CAAC,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC5E,CAAC;QACD,OAAO,GAAG,CAAC;IACZ,CAAC;IAEO,KAAK,CAAC,WAAW,CACxB,EAAkB,EAClB,SAAiB,EACjB,QAAyB,EACzB,QAA8B;QAE9B,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,QAAQ,CAAC;QACrC,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,0BAA0B,CAAC,QAAQ,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;QAChF,MAAM,OAAO,GAAG,iCAAiC,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACjE,MAAM,EAAE,CAAC,GAAG,CACX,eAAe,IAAI,CAAC,MAAM,CAAC,QAAQ;;;;;;;;;;yEAUmC,EACtE,SAAS,EACT,MAAM,CAAC,GAAG,EACV,MAAM,CAAC,SAAS,EAChB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EACnB,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EACvB,OAAO,EACP,OAAO,CAAC,UAAU,EAClB,OAAO,CAAC,YAAY,EACpB,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,EACjC,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAC7D,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EACvB,OAAO,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EACnE,OAAO,CAAC,mBAAmB,IAAI,IAAI,EACnC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAClB,CAAC;QACF,OAAO,KAAK,CAAC;IACd,CAAC;IAEO,KAAK,CAAC,aAAa,CAC1B,EAAkB,EAClB,SAAiB,EACjB,OAAgC,EAChC,OAAe,EACf,KAAoC;QAEpC,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;YAChD,MAAM,EAAE,CAAC,GAAG,CACX,eAAe,IAAI,CAAC,MAAM,CAAC,OAAO,8DAA8D,EAChG,SAAS,EACT,OAAO,GAAG,KAAK,GAAG,CAAC,EACnB,KAAK,CAAC,EAAE,EACR,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAClB,CAAC;QACH,CAAC;QACD,KAAK,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,KAAK,EAAE,CAAC;YACrC,MAAM,EAAE,CAAC,GAAG,CACX,eAAe,IAAI,CAAC,MAAM,CAAC,WAAW,gDAAgD,EACtF,SAAS,EACT,OAAO,GAAG,KAAK,GAAG,CAAC,EACnB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CACjB,CAAC;QACH,CAAC;IACF,CAAC;IAEO,MAAM,CAAC,KAAwE;QACtF,IAAI,CAAC;YACJ,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,MAAM,IAAI,uBAAuB,CAAC,IAAI,CAAC,UAAU,EAAE,KAAc,CAAC,CAAC;QACpE,CAAC;IACF,CAAC;CACD","sourcesContent":["import type { SessionEntry } from \"../../session-manager-types.ts\";\nimport type { SqliteDatabase, SqliteExecutor, SqliteRow, SqliteValue } from \"../database.js\";\nimport { StorageInvalidTextError } from \"../errors.js\";\nimport { renderStorageIdentifiers } from \"../prefix.js\";\nimport { assertStorageSchemaVersion } from \"../schema.js\";\nimport {\n\tSessionConflictError,\n\tSessionExistsError,\n\tSessionIdMismatchError,\n\tSessionNotFoundError,\n\tStorageUnavailableError,\n\tStoreClosedError,\n} from \"./errors.js\";\nimport {\n\tapplySessionSummaryEntries,\n\tmaterializeSessionSummaryMetadata,\n\ttype SessionSummaryState,\n\ttype SessionSummaryText,\n} from \"./session-summary.js\";\nimport type {\n\tSessionCwdMatcher,\n\tSessionListQuery,\n\tSessionRecordHeader,\n\tSessionSnapshot,\n\tSessionStore,\n\tSessionSummary,\n\tSessionWriteOptions,\n\tStorageDescriptor,\n} from \"./types.js\";\nimport { validateSessionEntries, validateSessionHeader, validateSessionText } from \"./validation.js\";\n\nexport const SESSION_SCHEMA_VERSION = 1;\nexport const SESSION_TABLES = Object.freeze({\n\tmeta: \"meta\",\n\tsessions: \"sessions\",\n\tentries: \"entries\",\n\tsearchTexts: \"search_texts\",\n});\n\ntype Tables = Readonly<Record<keyof typeof SESSION_TABLES, string>>;\ntype HeaderRow = SqliteRow & { header_json: string; last_seq: number };\ntype SummaryStateRow = HeaderRow & { summary_state: string };\ntype ListingRow = HeaderRow & {\n\tid: string;\n\tcwd: string;\n\tinternal: number;\n\tmodified_at: string;\n\tmessage_count: number;\n\tfirst_message: string;\n\tname: string | null;\n\thas_name: number;\n\tsummary: string | null;\n\tsummarized_through_id: string | null;\n\trevision: string;\n};\ntype SummaryRow = ListingRow & { search_texts_json: string };\n\n/** Every listing column except search text, so an unchanged row keeps its cached summary. */\nconst LISTING_COLUMNS =\n\t\"id, cwd, internal, header_json, last_seq, modified_at, message_count, first_message, name, has_name, summary, summarized_through_id, revision\";\n/** Rows whose search text is read per query; well under SQLite's bound-parameter limit. */\nexport const LISTING_FETCH_BATCH = 500;\n/** Listing scopes (visibility and project) kept at once; the picker uses two. */\nconst LISTING_SCOPES = 8;\n\nfunction summaryFromRow(row: SummaryRow): SessionSummary {\n\tconst header = JSON.parse(row.header_json) as SessionRecordHeader;\n\treturn {\n\t\tid: header.id,\n\t\tcwd: header.cwd,\n\t\t...(header.parentSessionId !== undefined ? { parentSessionId: header.parentSessionId } : {}),\n\t\tinternal: header.internal === true,\n\t\t...(header.workflow !== undefined ? { workflow: header.workflow } : {}),\n\t\t...(row.name !== null ? { name: JSON.parse(row.name) as string } : {}),\n\t\thasName: row.has_name === 1,\n\t\tcreatedAt: header.createdAt,\n\t\tmodifiedAt: row.modified_at,\n\t\tmessageCount: row.message_count,\n\t\tfirstMessage: JSON.parse(row.first_message) as string,\n\t\t...(row.summary !== null ? { summary: JSON.parse(row.summary) as string } : {}),\n\t\t...(row.summarized_through_id !== null ? { summarizedThroughId: row.summarized_through_id } : {}),\n\t\tsearchText: (JSON.parse(row.search_texts_json) as string[]).join(\" \"),\n\t};\n}\n\n/** Changes on every write: `revision` catches a rewrite that leaves every other listed column as it was. */\nfunction listingVersion(row: ListingRow): string {\n\treturn `${row.revision}\\u0000${row.last_seq}\\u0000${row.modified_at}\\u0000${row.message_count}\\u0000${row.has_name}\\u0000${row.name}\\u0000${row.summarized_through_id}\\u0000${row.summary}\\u0000${row.first_message}\\u0000${row.header_json}`;\n}\n\nexport class SqlSessionStore implements SessionStore {\n\tprivate readonly database: SqliteDatabase;\n\tprivate readonly tables: Tables;\n\tprivate readonly prefix: string;\n\tprivate closed = false;\n\tprivate readonly cwdMatcher?: SessionCwdMatcher;\n\t/** Session ids of each recently listed scope, valid while the store's change token is unchanged. */\n\tprivate readonly scopes = new Map<string, { readonly token: string; readonly ids: readonly string[] }>();\n\t/** Listed summaries of sessions that still exist at the cached version; never more than the store holds. */\n\tprivate readonly summaries = new Map<string, { readonly version: string; readonly summary: SessionSummary }>();\n\t/**\n\t * Settles when the latest listing has read and updated the caches. Listings take turns, so one listing's\n\t * pruning never drops summaries that another has fetched but not yet recorded under its scope.\n\t */\n\tprivate listing: Promise<void> = Promise.resolve();\n\n\tprivate constructor(database: SqliteDatabase, tables: Tables, prefix = \"\", cwdMatcher?: SessionCwdMatcher) {\n\t\tthis.database = database;\n\t\tthis.tables = tables;\n\t\tthis.prefix = prefix;\n\t\tthis.cwdMatcher = cwdMatcher;\n\t}\n\n\tstatic async open(\n\t\tdatabase: SqliteDatabase,\n\t\toptions: { readonly prefix?: string; readonly cwdMatcher?: SessionCwdMatcher } = {},\n\t): Promise<SqlSessionStore> {\n\t\tconst tables = renderStorageIdentifiers(\"sessions\", SESSION_TABLES, options.prefix);\n\t\tawait database.transaction(async (tx) => {\n\t\t\tawait tx.exec(`CREATE TABLE IF NOT EXISTS ${tables.meta} (schema_version INTEGER NOT NULL) STRICT`);\n\t\t\tconst versions = await tx.all(`SELECT schema_version FROM ${tables.meta}`);\n\t\t\tif (versions.length === 0) {\n\t\t\t\tawait tx.run(`INSERT INTO ${tables.meta} VALUES (?)`, SESSION_SCHEMA_VERSION);\n\t\t\t}\n\t\t\tfor (const version of versions) {\n\t\t\t\tassertStorageSchemaVersion(\"sessions\", version.schema_version!, SESSION_SCHEMA_VERSION);\n\t\t\t}\n\t\t\tawait tx.exec(`\n\t\t\t\tCREATE TABLE IF NOT EXISTS ${tables.sessions} (\n\t\t\t\t\tid TEXT PRIMARY KEY, cwd TEXT NOT NULL, created_at TEXT NOT NULL,\n\t\t\t\t\theader_json TEXT NOT NULL CHECK(json_valid(header_json)), internal INTEGER NOT NULL,\n\t\t\t\t\tlast_seq INTEGER NOT NULL, modified_at TEXT NOT NULL, message_count INTEGER NOT NULL,\n\t\t\t\t\tfirst_message TEXT NOT NULL CHECK(json_valid(first_message)),\n\t\t\t\t\tname TEXT CHECK(name IS NULL OR json_valid(name)), has_name INTEGER NOT NULL,\n\t\t\t\t\tsummary TEXT CHECK(summary IS NULL OR json_valid(summary)), summarized_through_id TEXT,\n\t\t\t\t\tsummary_state TEXT NOT NULL CHECK(json_valid(summary_state)), revision TEXT NOT NULL DEFAULT ''\n\t\t\t\t) STRICT;\n\t\t\t\tCREATE TABLE IF NOT EXISTS ${tables.entries} (\n\t\t\t\t\tsession_id TEXT NOT NULL, seq INTEGER NOT NULL, entry_id TEXT NOT NULL,\n\t\t\t\t\tentry_json TEXT NOT NULL CHECK(json_valid(entry_json)), PRIMARY KEY(session_id, seq)\n\t\t\t\t) STRICT;\n\t\t\t\tCREATE TABLE IF NOT EXISTS ${tables.searchTexts} (\n\t\t\t\t\tsession_id TEXT NOT NULL, seq INTEGER NOT NULL,\n\t\t\t\t\ttext_json TEXT NOT NULL CHECK(json_valid(text_json)), PRIMARY KEY(session_id, seq)\n\t\t\t\t) STRICT;\n\t\t\t`);\n\t\t\t// Sessions tables created before the write revision gain it; their rows pick one up on the next write.\n\t\t\tconst revision = await tx.get(\n\t\t\t\t\"SELECT name FROM pragma_table_info(?) WHERE name = 'revision'\",\n\t\t\t\ttables.sessions,\n\t\t\t);\n\t\t\tif (!revision) {\n\t\t\t\tawait tx.exec(`ALTER TABLE ${tables.sessions} ADD COLUMN revision TEXT NOT NULL DEFAULT ''`);\n\t\t\t}\n\t\t});\n\t\treturn new SqlSessionStore(database, tables, options.prefix, options.cwdMatcher);\n\t}\n\n\tget descriptor(): StorageDescriptor {\n\t\treturn { ...this.database.descriptor, ...(this.prefix === \"\" ? {} : { prefix: this.prefix }) };\n\t}\n\n\tasync create(header: SessionRecordHeader, entries: readonly SessionEntry[]): Promise<{ readonly lastSeq: number }> {\n\t\tthis.assertOpen();\n\t\tvalidateSessionHeader(header);\n\t\tvalidateSessionEntries(entries);\n\t\treturn this.database.transaction(async (tx) => {\n\t\t\tif (await tx.get(`SELECT id FROM ${this.tables.sessions} WHERE id = ?`, header.id)) {\n\t\t\t\tthrow new SessionExistsError(header.id);\n\t\t\t}\n\t\t\tconst texts = await this.saveSummary(tx, header.id, { header, entries, lastSeq: entries.length });\n\t\t\tawait this.insertEntries(tx, header.id, entries, 0, texts);\n\t\t\treturn { lastSeq: entries.length };\n\t\t});\n\t}\n\n\tasync append(\n\t\tsessionId: string,\n\t\tentries: readonly SessionEntry[],\n\t\toptions: SessionWriteOptions,\n\t): Promise<{ readonly lastSeq: number }> {\n\t\tthis.assertOpen();\n\t\tvalidateSessionText(\"sessionId\", sessionId);\n\t\treturn this.database.transaction(async (tx) => {\n\t\t\tconst previous = await this.forWrite(tx, sessionId, options, true);\n\t\t\tvalidateSessionEntries(entries);\n\t\t\tconst lastSeq = previous.last_seq + entries.length;\n\t\t\tconst texts = await this.saveSummary(\n\t\t\t\ttx,\n\t\t\t\tsessionId,\n\t\t\t\t{ header: JSON.parse(previous.header_json) as SessionRecordHeader, entries, lastSeq },\n\t\t\t\tJSON.parse(previous.summary_state) as SessionSummaryState,\n\t\t\t);\n\t\t\tawait this.insertEntries(tx, sessionId, entries, previous.last_seq, texts);\n\t\t\treturn { lastSeq };\n\t\t});\n\t}\n\n\tasync replace(\n\t\tsessionId: string,\n\t\theader: SessionRecordHeader,\n\t\tentries: readonly SessionEntry[],\n\t\toptions: SessionWriteOptions,\n\t): Promise<{ readonly lastSeq: number }> {\n\t\tthis.assertOpen();\n\t\tvalidateSessionText(\"sessionId\", sessionId);\n\t\treturn this.database.transaction(async (tx) => {\n\t\t\tawait this.forWrite(tx, sessionId, options);\n\t\t\tvalidateSessionHeader(header);\n\t\t\tvalidateSessionEntries(entries);\n\t\t\tif (header.id !== sessionId) throw new SessionIdMismatchError(sessionId, header.id);\n\t\t\tawait tx.run(`DELETE FROM ${this.tables.searchTexts} WHERE session_id = ?`, sessionId);\n\t\t\tawait tx.run(`DELETE FROM ${this.tables.entries} WHERE session_id = ?`, sessionId);\n\t\t\tconst texts = await this.saveSummary(tx, sessionId, { header, entries, lastSeq: entries.length });\n\t\t\tawait this.insertEntries(tx, sessionId, entries, 0, texts);\n\t\t\treturn { lastSeq: entries.length };\n\t\t});\n\t}\n\n\tasync load(sessionId: string): Promise<SessionSnapshot> {\n\t\tthis.assertOpen();\n\t\tvalidateSessionText(\"sessionId\", sessionId);\n\t\treturn this.database.transaction((tx) => this.read(tx, sessionId));\n\t}\n\n\tasync readHeader(sessionId: string): Promise<SessionRecordHeader | undefined> {\n\t\tthis.assertOpen();\n\t\tvalidateSessionText(\"sessionId\", sessionId);\n\t\tconst row = await this.database.get<HeaderRow>(\n\t\t\t`SELECT header_json FROM ${this.tables.sessions} WHERE id = ?`,\n\t\t\tsessionId,\n\t\t);\n\t\treturn row ? (JSON.parse(row.header_json) as SessionRecordHeader) : undefined;\n\t}\n\n\tasync delete(sessionId: string): Promise<void> {\n\t\tthis.assertOpen();\n\t\tvalidateSessionText(\"sessionId\", sessionId);\n\t\tawait this.database.transaction(async (tx) => {\n\t\t\tawait tx.run(`DELETE FROM ${this.tables.searchTexts} WHERE session_id = ?`, sessionId);\n\t\t\tawait tx.run(`DELETE FROM ${this.tables.entries} WHERE session_id = ?`, sessionId);\n\t\t\tawait tx.run(`DELETE FROM ${this.tables.sessions} WHERE id = ?`, sessionId);\n\t\t});\n\t}\n\n\t/**\n\t * Lists from a per-scope cache revalidated on every call. A cheap change token, which moves on any commit\n\t * from this or another connection, decides whether the scope is re-read. A scope listed for the first time\n\t * is read exactly as an uncached listing; afterwards only its light columns are re-read and search text is\n\t * read only for sessions whose stored listing columns changed. Listings of the same store take turns\n\t * reading and updating the caches; the yielding below runs outside that turn.\n\t */\n\tasync *list(query: SessionListQuery): AsyncIterable<SessionSummary> {\n\t\tthis.assertListing(query);\n\t\t// Validate the original query before binding only matching stored spellings below.\n\t\tif (query.cwd?.includes(\"\\0\")) throw new StorageInvalidTextError(0);\n\t\tconst listed = this.listing.then(() => this.listScope(query));\n\t\tthis.listing = listed.then(\n\t\t\t() => {},\n\t\t\t() => {},\n\t\t);\n\t\t// Resolve before yielding so a concurrent listing cannot change what this one returns.\n\t\tconst summaries = await listed;\n\t\tfor (const summary of summaries) {\n\t\t\tthis.assertListing(query);\n\t\t\tyield summary;\n\t\t}\n\t\tthis.assertListing(query);\n\t}\n\n\t/** Revalidates one scope's cache and resolves its summaries; called for one listing at a time. */\n\tprivate async listScope(query: SessionListQuery): Promise<readonly SessionSummary[]> {\n\t\t// The store may have closed, or the caller given up, while an earlier listing held the turn.\n\t\tthis.assertListing(query);\n\t\t// Read the token first: a commit racing the reads below moves it again before the next call.\n\t\tconst token = await this.changeToken();\n\t\tconst key = JSON.stringify([query.includeInternal === true, query.cwd ?? null]);\n\t\tconst cached = this.scopes.get(key);\n\t\t// A cached id without a summary is never expected; re-reading the scope repairs it instead of dropping it.\n\t\tconst scope =\n\t\t\tcached?.token === token && cached.ids.every((id) => this.summaries.has(id))\n\t\t\t\t? cached\n\t\t\t\t: { token, ids: await this.readScope(query, cached !== undefined) };\n\t\t// Map order is recency order: re-inserting marks the scope as used, and the oldest scope is evicted first.\n\t\tthis.scopes.delete(key);\n\t\tthis.scopes.set(key, scope);\n\t\tfor (const oldest of this.scopes.keys()) {\n\t\t\tif (this.scopes.size <= LISTING_SCOPES) break;\n\t\t\tthis.scopes.delete(oldest);\n\t\t}\n\t\tif (scope !== cached) this.pruneSummaries();\n\t\treturn scope.ids.flatMap((id) => this.summaries.get(id)?.summary ?? []);\n\t}\n\n\tasync findMostRecent(query: {\n\t\treadonly cwd: string;\n\t\treadonly includeInternal?: boolean;\n\t}): Promise<SessionSummary | undefined> {\n\t\tlet latest: SessionSummary | undefined;\n\t\tfor await (const summary of this.list(query)) {\n\t\t\tif (!latest || Date.parse(summary.modifiedAt) > Date.parse(latest.modifiedAt)) latest = summary;\n\t\t}\n\t\treturn latest;\n\t}\n\n\tasync close(): Promise<void> {\n\t\tthis.assertOpen();\n\t\tthis.closed = true;\n\t\tthis.scopes.clear();\n\t\tthis.summaries.clear();\n\t}\n\n\t/**\n\t * `data_version` moves when another connection commits and `total_changes()` when this one writes, so\n\t * together they cover writers in every process; the table aggregates also catch a change to the sessions\n\t * table if the adapter does not serve every statement from one connection.\n\t */\n\tprivate async changeToken(): Promise<string> {\n\t\tconst row = await this.database.get<SqliteRow>(\n\t\t\t`SELECT data_version, total_changes() AS changes,\n\t\t\t\t(SELECT count(*) FROM ${this.tables.sessions}) AS sessions,\n\t\t\t\t(SELECT max(rowid) FROM ${this.tables.sessions}) AS last_row\n\t\t\tFROM pragma_data_version`,\n\t\t);\n\t\treturn JSON.stringify(Object.values(row ?? {}).map(String));\n\t}\n\n\t/** The scope's session ids in store order, with a current summary cached for each. */\n\tprivate async readScope(query: SessionListQuery, listedBefore: boolean): Promise<readonly string[]> {\n\t\tconst matchesCwd =\n\t\t\tquery.cwd === undefined\n\t\t\t\t? undefined\n\t\t\t\t: (this.cwdMatcher?.(query.cwd) ?? ((candidate: string | undefined) => candidate === query.cwd));\n\t\tlet projectCwds: string[] | undefined;\n\t\tif (matchesCwd) {\n\t\t\tconst projects = await this.database.all<SqliteRow & { cwd: string }>(\n\t\t\t\t`SELECT DISTINCT cwd FROM ${this.tables.sessions}`,\n\t\t\t);\n\t\t\tprojectCwds = projects.map((project) => project.cwd).filter(matchesCwd);\n\t\t\tthis.assertListing(query);\n\t\t\tif (projectCwds.length === 0) return [];\n\t\t}\n\t\tconst scope = `(? = 1 OR internal = 0)${projectCwds ? ` AND cwd IN (${projectCwds.map(() => \"?\").join(\", \")})` : \"\"}`;\n\t\tconst params = [query.includeInternal ? 1 : 0, ...(projectCwds ?? [])];\n\t\tconst inScope = (row: ListingRow) => !matchesCwd || matchesCwd(row.cwd);\n\t\tif (listedBefore) {\n\t\t\tconst rows = (\n\t\t\t\tawait this.database.all<ListingRow>(\n\t\t\t\t\t`SELECT ${LISTING_COLUMNS} FROM ${this.tables.sessions} WHERE ${scope}`,\n\t\t\t\t\t...params,\n\t\t\t\t)\n\t\t\t).filter(inScope);\n\t\t\tthis.assertListing(query);\n\t\t\tconst stale = rows.filter((row) => this.summaries.get(row.id)?.version !== listingVersion(row));\n\t\t\t// A few changed sessions are read by id; when most changed, one scan of the scope is cheaper.\n\t\t\tif (stale.length <= rows.length / 4) {\n\t\t\t\tfor (let start = 0; start < stale.length; start += LISTING_FETCH_BATCH) {\n\t\t\t\t\tconst ids = stale.slice(start, start + LISTING_FETCH_BATCH).map((row) => row.id);\n\t\t\t\t\tconst fetched = new Set(\n\t\t\t\t\t\t(await this.readSummaries(`id IN (${ids.map(() => \"?\").join(\", \")})`, ids)).map((row) => row.id),\n\t\t\t\t\t);\n\t\t\t\t\t// A session deleted after the light read must not be listed from an older cached copy.\n\t\t\t\t\tfor (const id of ids) if (!fetched.has(id)) this.summaries.delete(id);\n\t\t\t\t\tthis.assertListing(query);\n\t\t\t\t}\n\t\t\t\treturn rows.flatMap((row) => (this.summaries.has(row.id) ? [row.id] : []));\n\t\t\t}\n\t\t}\n\t\tconst rows = (await this.readSummaries(scope, params)).filter(inScope);\n\t\tthis.assertListing(query);\n\t\treturn rows.map((row) => row.id);\n\t}\n\n\t/** Reads full listing rows, search text included, and caches their summaries. */\n\tprivate async readSummaries(where: string, params: readonly SqliteValue[]): Promise<readonly SummaryRow[]> {\n\t\t// Combine encoded strings only at read time, preserving NUL and lone surrogates verbatim.\n\t\tconst rows = await this.database.all<SummaryRow>(\n\t\t\t`SELECT ${LISTING_COLUMNS}, (\n\t\t\t\tSELECT COALESCE('[' || group_concat(text_json, ',') || ']', '[]')\n\t\t\t\tFROM (SELECT text_json FROM ${this.tables.searchTexts} WHERE session_id = s.id ORDER BY seq)\n\t\t\t) AS search_texts_json\n\t\t\tFROM ${this.tables.sessions} AS s WHERE ${where}`,\n\t\t\t...params,\n\t\t);\n\t\tfor (const row of rows)\n\t\t\tthis.summaries.set(row.id, { version: listingVersion(row), summary: summaryFromRow(row) });\n\t\treturn rows;\n\t}\n\n\t/**\n\t * Keeps only summaries some cached scope still lists, so memory follows the live sessions. Runs in a\n\t * listing's turn after it records its scope, when no other listing holds summaries it has not recorded.\n\t */\n\tprivate pruneSummaries(): void {\n\t\tconst listed = new Set([...this.scopes.values()].flatMap((scope) => scope.ids));\n\t\tfor (const id of this.summaries.keys()) if (!listed.has(id)) this.summaries.delete(id);\n\t}\n\n\tprivate assertOpen(): void {\n\t\tif (this.closed) throw new StoreClosedError(this.descriptor);\n\t}\n\n\tprivate assertListing(query: SessionListQuery): void {\n\t\tthis.assertOpen();\n\t\tif (query.signal?.aborted) throw new DOMException(\"Session listing aborted\", \"AbortError\");\n\t}\n\n\tprivate async read(tx: SqliteExecutor, sessionId: string): Promise<SessionSnapshot> {\n\t\tconst row = await tx.get<HeaderRow>(\n\t\t\t`SELECT header_json, last_seq FROM ${this.tables.sessions} WHERE id = ?`,\n\t\t\tsessionId,\n\t\t);\n\t\tif (!row) throw new SessionNotFoundError(sessionId);\n\t\tconst entries = await tx.all<SqliteRow & { entry_json: string }>(\n\t\t\t`SELECT entry_json FROM ${this.tables.entries} WHERE session_id = ? ORDER BY seq`,\n\t\t\tsessionId,\n\t\t);\n\t\treturn {\n\t\t\theader: JSON.parse(row.header_json) as SessionRecordHeader,\n\t\t\tentries: entries.map((entry) => JSON.parse(entry.entry_json) as SessionEntry),\n\t\t\tlastSeq: row.last_seq,\n\t\t};\n\t}\n\n\tprivate forWrite(\n\t\ttx: SqliteExecutor,\n\t\tsessionId: string,\n\t\toptions: SessionWriteOptions,\n\t\tincludeSummaryState: true,\n\t): Promise<SummaryStateRow>;\n\tprivate forWrite(\n\t\ttx: SqliteExecutor,\n\t\tsessionId: string,\n\t\toptions: SessionWriteOptions,\n\t\tincludeSummaryState?: false,\n\t): Promise<HeaderRow>;\n\tprivate async forWrite(\n\t\ttx: SqliteExecutor,\n\t\tsessionId: string,\n\t\toptions: SessionWriteOptions,\n\t\tincludeSummaryState = false,\n\t): Promise<HeaderRow> {\n\t\tconst row = await tx.get<HeaderRow>(\n\t\t\t`SELECT header_json, last_seq${includeSummaryState ? \", summary_state\" : \"\"}\n\t\t\t FROM ${this.tables.sessions} WHERE id = ?`,\n\t\t\tsessionId,\n\t\t);\n\t\tif (!row) throw new SessionNotFoundError(sessionId);\n\t\tif (row.last_seq !== options.expectSeq) {\n\t\t\tthrow new SessionConflictError(sessionId, options.expectSeq, row.last_seq);\n\t\t}\n\t\treturn row;\n\t}\n\n\tprivate async saveSummary(\n\t\ttx: SqliteExecutor,\n\t\tsessionId: string,\n\t\tsnapshot: SessionSnapshot,\n\t\tprevious?: SessionSummaryState,\n\t): Promise<readonly SessionSummaryText[]> {\n\t\tconst { header, lastSeq } = snapshot;\n\t\tconst { state, texts } = applySessionSummaryEntries(previous, snapshot.entries);\n\t\tconst summary = materializeSessionSummaryMetadata(header, state);\n\t\tawait tx.run(\n\t\t\t`INSERT INTO ${this.tables.sessions}\n\t\t\t\t(id, cwd, created_at, header_json, internal, last_seq, modified_at, message_count,\n\t\t\t\t first_message, name, has_name, summary, summarized_through_id, summary_state, revision)\n\t\t\t\tVALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, lower(hex(randomblob(16))))\n\t\t\t\tON CONFLICT(id) DO UPDATE SET\n\t\t\t\tcwd = excluded.cwd, created_at = excluded.created_at, header_json = excluded.header_json,\n\t\t\t\tinternal = excluded.internal, last_seq = excluded.last_seq, modified_at = excluded.modified_at,\n\t\t\t\tmessage_count = excluded.message_count, first_message = excluded.first_message, name = excluded.name,\n\t\t\t\thas_name = excluded.has_name, summary = excluded.summary,\n\t\t\t\tsummarized_through_id = excluded.summarized_through_id,\n\t\t\t\tsummary_state = excluded.summary_state, revision = excluded.revision`,\n\t\t\tsessionId,\n\t\t\theader.cwd,\n\t\t\theader.createdAt,\n\t\t\tthis.encode(header),\n\t\t\theader.internal ? 1 : 0,\n\t\t\tlastSeq,\n\t\t\tsummary.modifiedAt,\n\t\t\tsummary.messageCount,\n\t\t\tthis.encode(summary.firstMessage),\n\t\t\tsummary.name === undefined ? null : this.encode(summary.name),\n\t\t\tsummary.hasName ? 1 : 0,\n\t\t\tsummary.summary === undefined ? null : this.encode(summary.summary),\n\t\t\tsummary.summarizedThroughId ?? null,\n\t\t\tthis.encode(state),\n\t\t);\n\t\treturn texts;\n\t}\n\n\tprivate async insertEntries(\n\t\ttx: SqliteExecutor,\n\t\tsessionId: string,\n\t\tentries: readonly SessionEntry[],\n\t\tlastSeq: number,\n\t\ttexts: readonly SessionSummaryText[],\n\t): Promise<void> {\n\t\tfor (const [index, entry] of entries.entries()) {\n\t\t\tawait tx.run(\n\t\t\t\t`INSERT INTO ${this.tables.entries} (session_id, seq, entry_id, entry_json) VALUES (?, ?, ?, ?)`,\n\t\t\t\tsessionId,\n\t\t\t\tlastSeq + index + 1,\n\t\t\t\tentry.id,\n\t\t\t\tthis.encode(entry),\n\t\t\t);\n\t\t}\n\t\tfor (const { index, text } of texts) {\n\t\t\tawait tx.run(\n\t\t\t\t`INSERT INTO ${this.tables.searchTexts} (session_id, seq, text_json) VALUES (?, ?, ?)`,\n\t\t\t\tsessionId,\n\t\t\t\tlastSeq + index + 1,\n\t\t\t\tthis.encode(text),\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate encode(value: SessionRecordHeader | SessionEntry | SessionSummaryState | string): string {\n\t\ttry {\n\t\t\treturn JSON.stringify(value);\n\t\t} catch (cause) {\n\t\t\tthrow new StorageUnavailableError(this.descriptor, cause as Error);\n\t\t}\n\t}\n}\n"]}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export declare class StructuredOutputDeadlineError extends Error {
|
|
2
|
+
constructor(timeoutMs: number, attempts: string);
|
|
3
|
+
}
|
|
4
|
+
/** The failure for an aborted decision: the deadline error when the deadline fired, otherwise a plain cancellation. */
|
|
5
|
+
export declare function abortFailure(signal: AbortSignal): Error;
|
|
6
|
+
export declare function validateTimeoutOverride(value: number | undefined): void;
|
|
7
|
+
/**
|
|
8
|
+
* The wall-clock limit for one decision: an explicit `timeoutMs`, else the session's `httpIdleTimeoutMs`, else that
|
|
9
|
+
* setting's default. Like the provider clients, an idle timeout of `0` (disabled) becomes the largest timer delay.
|
|
10
|
+
*/
|
|
11
|
+
export declare function resolveDecisionDeadlineMs(timeoutMs: number | undefined, httpIdleTimeoutMs?: number): number;
|
|
12
|
+
/** One model request, from send to response; transport retries and their waits are not part of it. Records only the stop reason and timing, never content. */
|
|
13
|
+
export declare class DecisionAttempt {
|
|
14
|
+
readonly startedAt: number;
|
|
15
|
+
endedAt: number | undefined;
|
|
16
|
+
stopReason: string | undefined;
|
|
17
|
+
settle(stopReason?: string): void;
|
|
18
|
+
describe(now: number): string;
|
|
19
|
+
}
|
|
20
|
+
/** How every generation of one decision ended and how long it took, across repairs, retries and candidates. */
|
|
21
|
+
export declare class DecisionTrace {
|
|
22
|
+
private readonly attempts;
|
|
23
|
+
get size(): number;
|
|
24
|
+
begin(): DecisionAttempt;
|
|
25
|
+
/** Mark every generation still in flight as ended without a response. */
|
|
26
|
+
settleOpen(): void;
|
|
27
|
+
/** The attempts from `first` onward, numbered from 1, or an empty string when there are none. */
|
|
28
|
+
describe(first?: number): string;
|
|
29
|
+
}
|
|
30
|
+
export interface DecisionRun {
|
|
31
|
+
readonly signal: AbortSignal;
|
|
32
|
+
readonly trace: DecisionTrace;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Run a whole decision under one wall-clock limit. `run` receives a signal that aborts with the caller's reason when
|
|
36
|
+
* the caller aborts and with a {@link StructuredOutputDeadlineError} when the limit passes, so the existing abort
|
|
37
|
+
* plumbing cancels the in-flight generation. The timer is always released.
|
|
38
|
+
*/
|
|
39
|
+
export declare function withinDecisionDeadline<T>(callerSignal: AbortSignal | undefined, timeoutMs: number, run: (decision: DecisionRun) => Promise<T>): Promise<T>;
|
|
40
|
+
//# sourceMappingURL=deadline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deadline.d.ts","sourceRoot":"","sources":["../../../src/core/structured-output/deadline.ts"],"names":[],"mappings":"AAOA,qBAAa,6BAA8B,SAAQ,KAAK;IACvD,YAAY,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAK9C;CACD;AAED,uHAAuH;AACvH,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,KAAK,CAEvD;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAKvE;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE,iBAAiB,CAAC,EAAE,MAAM,GAAG,MAAM,CAI3G;AAcD,8JAA8J;AAC9J,qBAAa,eAAe;IAC3B,QAAQ,CAAC,SAAS,SAAqB;IACvC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAE/B,MAAM,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAGhC;IAED,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAQ5B;CACD;AAED,+GAA+G;AAC/G,qBAAa,aAAa;IACzB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAyB;IAElD,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,KAAK,IAAI,eAAe,CAIvB;IAED,yEAAyE;IACzE,UAAU,IAAI,IAAI,CAEjB;IAED,iGAAiG;IACjG,QAAQ,CAAC,KAAK,SAAI,GAAG,MAAM,CAK1B;CACD;AAED,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;CAC9B;AAED;;;;GAIG;AACH,wBAAsB,sBAAsB,CAAC,CAAC,EAC7C,YAAY,EAAE,WAAW,GAAG,SAAS,EACrC,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,CAAC,QAAQ,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,GACxC,OAAO,CAAC,CAAC,CAAC,CAgBZ"}
|