From 5d5b4f4f3db20a91b2c75c64ef4e741058748ece Mon Sep 17 00:00:00 2001 From: Neil <4138956+nwparker@users.noreply.github.com> Date: Tue, 3 Nov 2026 01:05:52 -0800 Subject: [PATCH] refactor(ai-vault): organize provider scanners and history owners (#37742) --- .../workflows/zcode-transcript-contract.yml | 9 +- .../build-plugins/main-build-entry-points.ts | 4 +- config/flaky-test-pattern-baseline.txt | 32 +-- config/knip.json | 4 +- config/path-literal-baseline.txt | 2 + .../process-host-direct-import-baseline.txt | 6 +- config/reliability-gates.jsonc | 15 +- config/scripts/build-wsl-guest.mjs | 2 +- config/scripts/ci-shard-timings.json | 216 +++++++++--------- config/scripts/orcad-entry-build.mjs | 2 +- .../pr-codex-unit-only-selection.test.mjs | 2 +- .../scripts/session-scanner-service-smoke.mjs | 2 +- .../scripts/session-search-pass-benchmark.ts | 4 +- .../scripts/session-search-query-benchmark.ts | 8 +- .../scripts/session-search-scope-benchmark.ts | 8 +- .../scripts/session-search-write-benchmark.ts | 10 +- config/scripts/vitest-node-runtime-files.mjs | 14 +- src/main/acp/acp-conversation-copy.ts | 2 +- .../session-search-child-service.ts | 2 +- .../session-search-content-hash.ts | 2 +- .../session-search-cursor-timestamps.test.ts | 12 +- .../session-search-deleted-sources.test.ts | 2 +- ...ssion-search-dependent-transcripts.test.ts | 10 +- .../session-search-enablement.ts | 2 +- .../session-search-engine-test-fixture.ts | 2 +- .../session-search-engine-types.ts | 2 +- .../ai-vault-search/session-search-engine.ts | 2 +- .../session-search-file-records.ts | 2 +- .../session-search-file-write.test.ts | 2 +- .../session-search-host-registration.test.ts | 6 +- .../session-search-index-consumer.test.ts | 2 +- .../session-search-index-consumer.ts | 2 +- .../session-search-index-generation.test.ts | 4 +- .../session-search-index-pass.test.ts | 4 +- .../session-search-index-pass.ts | 2 +- .../session-search-index-test-fixture.ts | 4 +- .../session-search-index-writer.ts | 2 +- .../session-search-indexer.test.ts | 4 +- .../session-search-instance.test.ts | 4 +- .../session-search-lifecycle-matrix.test.ts | 4 +- .../session-search-list-reparse.test.ts | 2 +- .../session-search-live-transcript.test.ts | 6 +- .../session-search-merged-roots.test.ts | 4 +- .../session-search-message-rows.test.ts | 2 +- .../session-search-message-rows.ts | 2 +- ...ession-search-native-chat-indexing.test.ts | 4 +- .../session-search-opencode-index.test.ts | 64 +++--- .../ai-vault-search/session-search-pass.ts | 2 +- .../session-search-read-decision.ts | 2 +- .../session-search-restart-reindex.test.ts | 4 +- .../session-search-root-refresh.test.ts | 4 +- .../session-search-service-init.ts | 2 +- .../session-search-store-is-memory.test.ts | 4 +- .../ai-vault-search/session-search-store.ts | 2 +- .../session-search-synthetic-corpus.test.ts | 4 +- .../session-search-synthetic-sources.ts | 2 +- ...ion-search-transcript-dependencies.test.ts | 8 +- .../session-search-transcript-fixtures.ts | 2 +- .../session-search-write-buffer.ts | 2 +- .../session-search-write-lifetime.test.ts | 2 +- .../ai-vault/ai-vault-local-scan-progress.ts | 2 +- .../ai-vault-scan-progress-flow.test.ts | 38 +-- .../ai-vault/ai-vault-scan-progress.test.ts | 2 +- src/main/ai-vault/ai-vault-scan-tally.ts | 2 +- .../cached-session-list-wsl-probe.test.ts | 4 +- src/main/ai-vault/cached-session-list.test.ts | 2 +- src/main/ai-vault/cached-session-list.ts | 4 +- src/main/ai-vault/host-session-delete.ts | 4 +- ...on-parse-cache-antigravity-upgrade.test.ts | 16 +- .../session-parse-cache-database.ts | 12 +- .../session-parse-cache-devin-upgrade.test.ts | 12 +- .../session-parse-cache-large-scan.test.ts | 4 +- .../session-parse-cache-legacy-json.ts | 0 ...on-parse-cache-metadata-checkpoint.test.ts | 21 +- .../session-parse-cache-persistence.test.ts | 21 +- .../session-parse-cache-persistence.ts | 2 +- ...ession-parse-cache-preview-upgrade.test.ts | 12 +- .../session-parse-cache-store.ts | 8 +- .../session-parse-file-lane.ts | 0 ...session-scanner-parse-cache-agents.test.ts | 15 +- .../session-scanner-parse-cache.test.ts | 18 +- .../session-scanner-parse-cache.ts | 41 ++-- .../session-scanner-sidecar-enrichment.ts | 15 +- .../session-scope-cwds-table.ts | 2 +- .../session-sidecar-stat.test.ts | 0 .../{ => parse-cache}/session-sidecar-stat.ts | 0 src/main/ai-vault/runtime-session-scanner.ts | 2 +- .../session-scanner-background.ts | 12 +- ...ssion-scanner-service-cancellation.test.ts | 9 +- .../session-scanner-service-client-state.ts | 4 +- .../session-scanner-service-client.test.ts | 0 .../session-scanner-service-client.ts | 4 +- ...session-scanner-service-entry-path.test.ts | 0 .../session-scanner-service-entry-path.ts | 2 +- ...on-scanner-service-entry-subagents.test.ts | 8 +- .../session-scanner-service-entry.test.ts | 10 +- .../session-scanner-service-entry.ts | 24 +- .../session-scanner-service-env.test.ts | 0 .../session-scanner-service-env.ts | 0 .../session-scanner-service-priority.ts | 0 .../session-scanner-service-protocol.ts | 20 +- ...n-scanner-service-request-deadline.test.ts | 0 ...ession-scanner-service-request-deadline.ts | 2 +- ...ion-scanner-service-restart-policy.test.ts | 0 .../session-scanner-service-restart-policy.ts | 0 .../session-scanner-service-root-answer.ts | 0 ...ssion-scanner-service-root-request.test.ts | 0 .../session-scanner-service-root-request.ts | 2 +- ...sion-scanner-service-root-response.test.ts | 0 ...ssion-scanner-service-search-roots.test.ts | 10 +- .../session-scanner-service-search.test.ts | 7 +- .../session-scanner-service-search.ts | 12 +- .../session-scanner-service-spawn.test.ts | 0 .../session-scanner-service-spawn.ts | 20 +- .../session-scanner-service-test-child.ts | 0 .../session-scanner-service-wsl-notes.ts | 2 +- .../antigravity-history-prompt.ts | 2 +- .../antigravity-ide-history.test.ts | 6 +- .../antigravity-index-file-admission.test.ts | 2 +- ...tigravity-opening-prompt-workspace.test.ts | 2 +- .../antigravity-recorded-history.test.ts | 6 +- .../antigravity-transcript-candidates.ts | 10 +- .../session-scanner-antigravity-fixtures.ts | 2 +- .../session-scanner-antigravity-history.ts | 17 +- .../session-scanner-antigravity-metadata.ts | 2 +- ...session-scanner-antigravity-parser.test.ts | 4 +- .../session-scanner-antigravity-parser.ts | 21 +- .../session-scanner-antigravity-paths.ts | 0 ...session-scanner-antigravity-source.test.ts | 8 +- .../session-scanner-antigravity-sources.ts | 10 +- .../claude-project-dir-encoding.test.ts | 0 .../claude}/claude-project-dir-encoding.ts | 2 +- .../session-scanner-claude-cwd-drift.test.ts | 4 +- ...sion-scanner-claude-subagent-prune.test.ts | 4 +- .../session-scanner-claude-subagents.test.ts | 0 .../session-scanner-claude-subagents.ts | 21 +- .../session-scanner-claude-title.test.ts | 4 +- ...ssion-scanner-claude-unicode-scope.test.ts | 6 +- .../session-scanner-primary-parsers.ts | 32 ++- .../session-scanner-subagent-transcripts.ts | 2 +- .../session-scanner-cline-parser.test.ts | 4 +- .../cline}/session-scanner-cline-parser.ts | 38 ++- .../session-scanner-codebuddy-parser.ts | 25 +- .../session-scanner-codebuddy-scope.test.ts | 6 +- .../session-scanner-codebuddy-source.test.ts | 4 +- .../codex}/codex-session-collection.test.ts | 6 +- .../codex}/codex-session-root-dedup.test.ts | 4 +- .../codex}/codex-session-root-dedup.ts | 12 +- .../session-scanner-codex-cached-title.ts | 4 +- .../session-scanner-codex-dual-root.test.ts | 4 +- .../session-scanner-codex-fast-path.test.ts | 8 +- .../codex}/session-scanner-codex-fixtures.ts | 2 +- .../session-scanner-codex-message-records.ts | 12 +- ...sion-scanner-codex-non-user-origin.test.ts | 0 .../session-scanner-codex-non-user-origin.ts | 3 +- .../session-scanner-codex-parser.test.ts | 2 +- .../codex}/session-scanner-codex-parser.ts | 24 +- .../codex}/session-scanner-codex-paths.ts | 0 .../session-scanner-codex-record-fast-path.ts | 0 .../session-scanner-codex-session-meta.ts | 3 +- .../session-scanner-codex-title-index.test.ts | 0 .../session-scanner-codex-title-index.ts | 15 +- ...session-scanner-codex-tool-records.test.ts | 2 +- .../session-scanner-codex-tool-records.ts | 8 +- .../session-scanner-codex-workers.test.ts | 4 +- ...sion-scanner-copilot-cache-upgrade.test.ts | 26 +-- .../session-scanner-copilot-parser.test.ts | 2 +- .../session-scanner-copilot-parser.ts | 27 +-- .../session-scanner-cursor-chat-meta.test.ts | 27 +-- .../session-scanner-cursor-chat-meta.ts | 13 +- .../cursor}/session-scanner-cursor-parser.ts | 26 +-- .../session-scanner-devin-contention.test.ts | 10 +- .../devin}/session-scanner-devin-db.test.ts | 12 +- .../devin}/session-scanner-devin-db.ts | 20 +- .../session-scanner-devin-dedup.test.ts | 6 +- .../session-scanner-devin-parser.test.ts | 4 +- .../devin}/session-scanner-devin-parser.ts | 30 +-- .../session-scanner-droid-parser.test.ts | 2 +- .../droid}/session-scanner-droid-parser.ts | 26 +-- .../gemini}/session-scanner-gemini-parsers.ts | 28 +-- .../grok}/session-scanner-grok-parser.test.ts | 4 +- .../grok}/session-scanner-grok-parser.ts | 30 +-- .../session-scanner-grok-user-text.test.ts | 0 .../grok}/session-scanner-grok-user-text.ts | 0 .../hermes}/session-scanner-hermes-parser.ts | 27 +-- .../session-scanner-jcode-parser.test.ts | 0 .../jcode}/session-scanner-jcode-parser.ts | 26 +-- .../session-scanner-kimi-index-cache.test.ts | 0 .../kimi}/session-scanner-kimi-index-cache.ts | 0 .../kimi}/session-scanner-kimi-parser.test.ts | 6 +- .../kimi}/session-scanner-kimi-parser.ts | 33 +-- .../kimi}/session-scanner-kimi-paths.ts | 18 +- .../kiro}/session-scanner-kiro-fixtures.ts | 2 +- .../kiro}/session-scanner-kiro-parser.test.ts | 2 +- .../kiro}/session-scanner-kiro-parser.ts | 36 ++- .../muse}/session-scanner-muse-parser.ts | 28 ++- .../muse}/session-scanner-muse-paths.ts | 2 - .../muse}/session-scanner-muse.test.ts | 6 +- .../omp}/omp-session-root.test.ts | 6 +- .../{ => scanners/omp}/omp-session-root.ts | 2 +- ...ssion-scanner-omp-subagent-listing.test.ts | 0 .../session-scanner-omp-subagent-listing.ts | 12 +- ...session-scanner-omp-subagent-prune.test.ts | 4 +- ...n-scanner-omp-subagent-transcripts.test.ts | 2 +- ...ession-scanner-omp-subagent-transcripts.ts | 8 +- .../omp}/session-scanner-omp-title.test.ts | 2 +- .../omp}/session-scanner-omp-title.ts | 3 +- .../session-scanner-omp-written-record.ts | 3 +- .../openclaw}/openclaw-session-layout.test.ts | 4 +- .../openclaw}/openclaw-session-layout.ts | 6 +- .../opencode-wsl-runtime-preparation.test.ts | 12 +- .../opencode-wsl-runtime-preparation.ts | 32 +-- ...scanner-opencode-native-page-limit.test.ts | 0 ...ion-scanner-opencode-native-worker.test.ts | 8 +- ...scanner-opencode-process-admission.test.ts | 0 ...ession-scanner-opencode-sqlite-dispatch.ts | 16 +- ...-scanner-opencode-sqlite-process-client.ts | 4 +- ...n-scanner-opencode-sqlite-process-entry.ts | 0 ...scanner-opencode-sqlite-process-framing.ts | 2 +- ...on-scanner-opencode-sqlite-process.test.ts | 13 +- ...nner-opencode-sqlite-worker-client.test.ts | 4 +- ...n-scanner-opencode-sqlite-worker-client.ts | 14 +- ...scanner-opencode-sqlite-worker-protocol.ts | 8 +- ...scanner-opencode-sqlite-worker-response.ts | 6 +- ...anner-opencode-sqlite-worker-spawn.test.ts | 6 +- ...on-scanner-opencode-sqlite-worker-spawn.ts | 20 +- ...ession-scanner-opencode-wsl-client.test.ts | 8 +- .../session-scanner-opencode-wsl-client.ts | 25 +- ...ssion-scanner-opencode-wsl-routing.test.ts | 8 +- .../session-scanner-opencode-wsl-runtime.ts | 0 ...sion-scanner-opencode-cancellation.test.ts | 20 +- .../session-scanner-opencode-parser.test.ts | 6 +- .../session-scanner-opencode-parser.ts | 24 +- ...scanner-opencode-sources-wsl-stall.test.ts | 6 +- .../session-scanner-opencode-sources.test.ts | 6 +- .../session-scanner-opencode-sources.ts | 20 +- .../opencode-transcript-capture-limits.ts | 0 ...ion-scanner-opencode-sqlite-bounds.test.ts | 6 +- ...session-scanner-opencode-sqlite-capture.ts | 22 +- ...canner-opencode-sqlite-coexistence.test.ts | 9 +- ...ssion-scanner-opencode-sqlite-discovery.ts | 14 +- ...session-scanner-opencode-sqlite-fixture.ts | 2 +- .../session-scanner-opencode-sqlite-list.ts | 12 +- ...ssion-scanner-opencode-sqlite-open.test.ts | 4 +- .../session-scanner-opencode-sqlite-open.ts | 12 +- ...sion-scanner-opencode-sqlite-paths.test.ts | 2 +- .../session-scanner-opencode-sqlite-rows.ts | 2 +- ...scanner-opencode-sqlite-scan-scope.test.ts | 0 ...sion-scanner-opencode-sqlite-scan-scope.ts | 4 +- .../session-scanner-opencode-sqlite-schema.ts | 4 +- .../session-scanner-opencode-sqlite.test.ts | 10 +- .../session-scanner-opencode-sqlite.ts | 25 +- .../session-scanner-opencode2-message.test.ts | 2 +- .../session-scanner-opencode2-message.ts | 11 +- .../session-scanner-opencode2-sqlite-list.ts | 14 +- .../session-scanner-opencode2-sqlite.test.ts | 8 +- .../session-scanner-opencode2-sqlite.ts | 26 ++- ...session-scanner-pi-omp-shared-root.test.ts | 4 +- .../pi}/session-scanner-pi-scope.test.ts | 6 +- .../qoder-1.1.64-generated-resumed.jsonl | 0 .../qoder}/session-scanner-qoder-parser.ts | 17 +- .../qoder}/session-scanner-qoder.test.ts | 4 +- .../session-scanner-graph-parsers.test.ts | 4 +- .../session-scanner-graph-parsers.ts | 38 +-- .../session-scanner-sqlite-scope-rows.ts | 2 +- .../zcode}/session-scanner-zcode-order.ts | 4 +- .../session-scanner-zcode-sources.test.ts | 6 +- .../zcode}/session-scanner-zcode-sources.ts | 14 +- .../session-scanner-zcode-visibility.ts | 0 .../zcode}/session-scanner-zcode.test.ts | 8 +- .../ai-vault/session-cwd-bucket-layouts.ts | 5 +- src/main/ai-vault/session-delete-target.ts | 2 +- .../session-first-user-prompt-handler.ts | 2 +- ...session-first-user-prompt-opencode.test.ts | 11 +- .../session-first-user-prompt-read.ts | 8 +- src/main/ai-vault/session-root-dedup.ts | 5 +- .../ai-vault/session-scanner-accumulator.ts | 2 +- .../ai-vault/session-scanner-agent-parser.ts | 49 ++-- .../ai-vault/session-scanner-agent-sources.ts | 25 +- .../session-scanner-candidate-parse.ts | 8 +- .../ai-vault/session-scanner-candidates.ts | 8 +- ...sion-scanner-core-parser-wsl-stall.test.ts | 6 +- .../ai-vault/session-scanner-cutoff.test.ts | 4 +- .../ai-vault/session-scanner-discovery.ts | 2 +- .../session-scanner-every-agent-fixture.ts | 4 +- .../session-scanner-first-user-prompt.ts | 2 +- .../session-scanner-incremental-fixtures.ts | 4 +- ...sion-scanner-index-cache-wsl-stall.test.ts | 4 +- ...ssion-scanner-json-document-memory.test.ts | 8 +- .../session-scanner-jsonl-reader.test.ts | 2 +- .../ai-vault/session-scanner-jsonl-reader.ts | 2 +- .../ai-vault/session-scanner-messages.test.ts | 4 +- src/main/ai-vault/session-scanner-messages.ts | 7 +- .../session-scanner-opencode-sqlite-paths.ts | 5 - .../session-scanner-parse-wsl-stall.test.ts | 6 +- ...sion-scanner-parser-stream-cleanup.test.ts | 12 +- .../session-scanner-record-budget.test.ts | 22 +- .../session-scanner-recoverable-empty.test.ts | 4 +- src/main/ai-vault/session-scanner-roots.ts | 2 +- .../session-scanner-scope-cwd-facts.test.ts | 8 +- .../session-scanner-scope-walk.test.ts | 13 +- .../ai-vault/session-scanner-scope-walk.ts | 10 +- .../session-scanner-source-discovery.ts | 8 +- src/main/ai-vault/session-scanner-types.ts | 6 +- .../session-scanner-unlimited-dedup.test.ts | 2 +- .../session-scanner-wsl-stop-gaps.test.ts | 26 ++- src/main/ai-vault/session-scanner.test.ts | 55 ++--- src/main/ai-vault/session-scanner.ts | 13 +- src/main/ai-vault/session-scope-cwd.ts | 15 +- src/main/ai-vault/session-subagent-reader.ts | 6 +- ...ession-title-file-reader-wsl-stall.test.ts | 4 +- .../session-title-file-reader.test.ts | 2 +- .../session-title-file-reader.ts | 6 +- .../session-title-request-paths.ts | 6 +- .../session-title-resolver.ts | 6 +- .../session-title-result-validation.ts | 2 +- .../local-log-tail-reader.test.ts | 2 +- .../local-log-tail-reader.ts | 4 +- .../remote-session-content-lines.test.ts | 0 .../remote-session-content-lines.ts | 4 +- .../remote-session-file-stat.ts | 2 +- .../session-decoded-message.ts | 4 +- ...sion-document-consumer-replacement.test.ts | 4 +- ...n-document-discarded-scalar-memory.test.ts | 0 ...session-document-stream-boundaries.test.ts | 4 +- .../session-document-stream-contract.test.ts | 0 .../session-document-stream-parity.test.ts | 11 +- ...session-document-stream-projection.test.ts | 5 +- .../session-document-stream.ts | 4 +- .../session-transcript-channel.ts | 0 .../session-transcript-consumers.test.ts | 31 +-- .../session-transcript-consumers.ts | 4 +- ...ion-transcript-every-agent-capture.test.ts | 90 ++++---- ...session-transcript-message-content.test.ts | 0 .../session-transcript-message-content.ts | 4 +- .../session-transcript-reader.ts | 14 +- .../session-transcript-record-budget.test.ts | 0 .../session-transcript-record-budget.ts | 0 src/main/claude/claude-transcript-catch-up.ts | 2 +- .../codex/codex-legacy-session-resume.test.ts | 2 +- .../foreign-sqlite-reader-entry.ts | 4 +- .../readers/opencode-binder-sessions.ts | 2 +- .../readers/opencode-prompt-failure.ts | 2 +- src/main/ipc/ai-vault-scan-coalescing.test.ts | 2 +- ...-vault-search-all-hosts-real-index.test.ts | 4 +- src/main/ipc/ai-vault-search.test.ts | 2 +- src/main/ipc/ai-vault-search.ts | 2 +- .../ipc/ai-vault-session-title-routing.ts | 2 +- src/main/ipc/ai-vault-subagent-list.ts | 2 +- .../ipc/ai-vault-unresolved-owner.test.ts | 2 +- src/main/ipc/ai-vault.test.ts | 8 +- .../filesystem-file-content-inspection.ts | 2 +- src/main/ipc/local-log-tail.test.ts | 2 +- src/main/ipc/local-log-tail.ts | 2 +- .../adopted-directory-probe.ts | 5 +- .../adopted-transcript-source.ts | 2 +- ...tured-agent-session-adopted-import.test.ts | 25 +- ...ent-session-create-adoption-budget.test.ts | 21 +- ...n-create-adoption-contract-test-fixture.ts | 19 +- ...nt-session-create-adoption-restart.test.ts | 19 +- ...ured-agent-session-create-adoption.test.ts | 19 +- .../native-chat/session-file-id-layouts.ts | 2 +- src/main/native-chat/session-file-resolver.ts | 2 +- ...ed-agent-cli-conversation-adoption.test.ts | 25 +- ...structured-chat-naming-publication.test.ts | 2 +- .../transcript-opencode-database.test.ts | 24 +- .../transcript-opencode-database.ts | 6 +- .../transcript-opencode-sqlite-query.ts | 6 +- src/main/native-chat/transcript-opencode.ts | 4 +- src/main/native-chat/transcript-zcode.test.ts | 2 +- .../wsl-transcript-fs-process-spawn.ts | 5 +- src/main/omp/omp-transcript-import.ts | 2 +- .../scanner-windows-data-directory.test.ts | 23 +- .../opencode/opencode-transcript-import.ts | 2 +- .../orcad/orcad-forked-child-paths.test.ts | 2 +- src/main/orcad/orcad-session-scanner-idle.ts | 2 +- src/main/qoder/real-cli.test.ts | 2 +- ...ructured-agent-session-held-signal.test.ts | 2 +- src/main/runtime/rpc/methods/ai-vault.test.ts | 4 +- src/main/runtime/runtime-ai-vault-commands.ts | 2 +- ...rowser-process-user-agent-ordering.test.ts | 2 +- src/main/startup/main-process-preflight.ts | 2 +- .../worktree-retirement-discovery.ts | 2 +- .../wsl-move/wsl-move-storage-dispositions.ts | 7 +- tests/tools/omp-history-title-smoke.mjs | 4 +- .../tools/omp-session-root-upstream-smoke.mjs | 2 +- 386 files changed, 1702 insertions(+), 1591 deletions(-) rename src/main/ai-vault/{ => parse-cache}/session-parse-cache-antigravity-upgrade.test.ts (88%) rename src/main/ai-vault/{ => parse-cache}/session-parse-cache-database.ts (96%) rename src/main/ai-vault/{ => parse-cache}/session-parse-cache-devin-upgrade.test.ts (89%) rename src/main/ai-vault/{ => parse-cache}/session-parse-cache-large-scan.test.ts (96%) rename src/main/ai-vault/{ => parse-cache}/session-parse-cache-legacy-json.ts (100%) rename src/main/ai-vault/{ => parse-cache}/session-parse-cache-metadata-checkpoint.test.ts (92%) rename src/main/ai-vault/{ => parse-cache}/session-parse-cache-persistence.test.ts (97%) rename src/main/ai-vault/{ => parse-cache}/session-parse-cache-persistence.ts (98%) rename src/main/ai-vault/{ => parse-cache}/session-parse-cache-preview-upgrade.test.ts (90%) rename src/main/ai-vault/{ => parse-cache}/session-parse-cache-store.ts (96%) rename src/main/ai-vault/{ => parse-cache}/session-parse-file-lane.ts (100%) rename src/main/ai-vault/{ => parse-cache}/session-scanner-parse-cache-agents.test.ts (95%) rename src/main/ai-vault/{ => parse-cache}/session-scanner-parse-cache.test.ts (96%) rename src/main/ai-vault/{ => parse-cache}/session-scanner-parse-cache.ts (84%) rename src/main/ai-vault/{ => parse-cache}/session-scanner-sidecar-enrichment.ts (88%) rename src/main/ai-vault/{ => parse-cache}/session-scope-cwds-table.ts (98%) rename src/main/ai-vault/{ => parse-cache}/session-sidecar-stat.test.ts (100%) rename src/main/ai-vault/{ => parse-cache}/session-sidecar-stat.ts (100%) rename src/main/ai-vault/{ => scan-service}/session-scanner-background.ts (86%) rename src/main/ai-vault/{ => scan-service}/session-scanner-service-cancellation.test.ts (95%) rename src/main/ai-vault/{ => scan-service}/session-scanner-service-client-state.ts (98%) rename src/main/ai-vault/{ => scan-service}/session-scanner-service-client.test.ts (100%) rename src/main/ai-vault/{ => scan-service}/session-scanner-service-client.ts (98%) rename src/main/ai-vault/{ => scan-service}/session-scanner-service-entry-path.test.ts (100%) rename src/main/ai-vault/{ => scan-service}/session-scanner-service-entry-path.ts (95%) rename src/main/ai-vault/{ => scan-service}/session-scanner-service-entry-subagents.test.ts (90%) rename src/main/ai-vault/{ => scan-service}/session-scanner-service-entry.test.ts (93%) rename src/main/ai-vault/{ => scan-service}/session-scanner-service-entry.ts (88%) rename src/main/ai-vault/{ => scan-service}/session-scanner-service-env.test.ts (100%) rename src/main/ai-vault/{ => scan-service}/session-scanner-service-env.ts (100%) rename src/main/ai-vault/{ => scan-service}/session-scanner-service-priority.ts (100%) rename src/main/ai-vault/{ => scan-service}/session-scanner-service-protocol.ts (88%) rename src/main/ai-vault/{ => scan-service}/session-scanner-service-request-deadline.test.ts (100%) rename src/main/ai-vault/{ => scan-service}/session-scanner-service-request-deadline.ts (95%) rename src/main/ai-vault/{ => scan-service}/session-scanner-service-restart-policy.test.ts (100%) rename src/main/ai-vault/{ => scan-service}/session-scanner-service-restart-policy.ts (100%) rename src/main/ai-vault/{ => scan-service}/session-scanner-service-root-answer.ts (100%) rename src/main/ai-vault/{ => scan-service}/session-scanner-service-root-request.test.ts (100%) rename src/main/ai-vault/{ => scan-service}/session-scanner-service-root-request.ts (93%) rename src/main/ai-vault/{ => scan-service}/session-scanner-service-root-response.test.ts (100%) rename src/main/ai-vault/{ => scan-service}/session-scanner-service-search-roots.test.ts (87%) rename src/main/ai-vault/{ => scan-service}/session-scanner-service-search.test.ts (97%) rename src/main/ai-vault/{ => scan-service}/session-scanner-service-search.ts (84%) rename src/main/ai-vault/{ => scan-service}/session-scanner-service-spawn.test.ts (100%) rename src/main/ai-vault/{ => scan-service}/session-scanner-service-spawn.ts (89%) rename src/main/ai-vault/{ => scan-service}/session-scanner-service-test-child.ts (100%) rename src/main/ai-vault/{ => scan-service}/session-scanner-service-wsl-notes.ts (85%) rename src/main/ai-vault/{ => scanners/antigravity}/antigravity-history-prompt.ts (81%) rename src/main/ai-vault/{ => scanners/antigravity}/antigravity-ide-history.test.ts (97%) rename src/main/ai-vault/{ => scanners/antigravity}/antigravity-index-file-admission.test.ts (97%) rename src/main/ai-vault/{ => scanners/antigravity}/antigravity-opening-prompt-workspace.test.ts (99%) rename src/main/ai-vault/{ => scanners/antigravity}/antigravity-recorded-history.test.ts (91%) rename src/main/ai-vault/{ => scanners/antigravity}/antigravity-transcript-candidates.ts (89%) rename src/main/ai-vault/{ => scanners/antigravity}/session-scanner-antigravity-fixtures.ts (91%) rename src/main/ai-vault/{ => scanners/antigravity}/session-scanner-antigravity-history.ts (90%) rename src/main/ai-vault/{ => scanners/antigravity}/session-scanner-antigravity-metadata.ts (97%) rename src/main/ai-vault/{ => scanners/antigravity}/session-scanner-antigravity-parser.test.ts (96%) rename src/main/ai-vault/{ => scanners/antigravity}/session-scanner-antigravity-parser.ts (84%) rename src/main/ai-vault/{ => scanners/antigravity}/session-scanner-antigravity-paths.ts (100%) rename src/main/ai-vault/{ => scanners/antigravity}/session-scanner-antigravity-source.test.ts (95%) rename src/main/ai-vault/{ => scanners/antigravity}/session-scanner-antigravity-sources.ts (84%) rename src/main/ai-vault/{ => scanners/claude}/claude-project-dir-encoding.test.ts (100%) rename src/main/ai-vault/{ => scanners/claude}/claude-project-dir-encoding.ts (92%) rename src/main/ai-vault/{ => scanners/claude}/session-scanner-claude-cwd-drift.test.ts (92%) rename src/main/ai-vault/{ => scanners/claude}/session-scanner-claude-subagent-prune.test.ts (92%) rename src/main/ai-vault/{ => scanners/claude}/session-scanner-claude-subagents.test.ts (100%) rename src/main/ai-vault/{ => scanners/claude}/session-scanner-claude-subagents.ts (93%) rename src/main/ai-vault/{ => scanners/claude}/session-scanner-claude-title.test.ts (93%) rename src/main/ai-vault/{ => scanners/claude}/session-scanner-claude-unicode-scope.test.ts (94%) rename src/main/ai-vault/{ => scanners/claude}/session-scanner-primary-parsers.ts (88%) rename src/main/ai-vault/{ => scanners/claude}/session-scanner-subagent-transcripts.ts (93%) rename src/main/ai-vault/{ => scanners/cline}/session-scanner-cline-parser.test.ts (97%) rename src/main/ai-vault/{ => scanners/cline}/session-scanner-cline-parser.ts (81%) rename src/main/ai-vault/{ => scanners/codebuddy}/session-scanner-codebuddy-parser.ts (88%) rename src/main/ai-vault/{ => scanners/codebuddy}/session-scanner-codebuddy-scope.test.ts (94%) rename src/main/ai-vault/{ => scanners/codebuddy}/session-scanner-codebuddy-source.test.ts (94%) rename src/main/ai-vault/{ => scanners/codex}/codex-session-collection.test.ts (96%) rename src/main/ai-vault/{ => scanners/codex}/codex-session-root-dedup.test.ts (99%) rename src/main/ai-vault/{ => scanners/codex}/codex-session-root-dedup.ts (94%) rename src/main/ai-vault/{ => scanners/codex}/session-scanner-codex-cached-title.ts (84%) rename src/main/ai-vault/{ => scanners/codex}/session-scanner-codex-dual-root.test.ts (98%) rename src/main/ai-vault/{ => scanners/codex}/session-scanner-codex-fast-path.test.ts (97%) rename src/main/ai-vault/{ => scanners/codex}/session-scanner-codex-fixtures.ts (96%) rename src/main/ai-vault/{ => scanners/codex}/session-scanner-codex-message-records.ts (85%) rename src/main/ai-vault/{ => scanners/codex}/session-scanner-codex-non-user-origin.test.ts (100%) rename src/main/ai-vault/{ => scanners/codex}/session-scanner-codex-non-user-origin.ts (97%) rename src/main/ai-vault/{ => scanners/codex}/session-scanner-codex-parser.test.ts (99%) rename src/main/ai-vault/{ => scanners/codex}/session-scanner-codex-parser.ts (93%) rename src/main/ai-vault/{ => scanners/codex}/session-scanner-codex-paths.ts (100%) rename src/main/ai-vault/{ => scanners/codex}/session-scanner-codex-record-fast-path.ts (100%) rename src/main/ai-vault/{ => scanners/codex}/session-scanner-codex-session-meta.ts (69%) rename src/main/ai-vault/{ => scanners/codex}/session-scanner-codex-title-index.test.ts (100%) rename src/main/ai-vault/{ => scanners/codex}/session-scanner-codex-title-index.ts (92%) rename src/main/ai-vault/{ => scanners/codex}/session-scanner-codex-tool-records.test.ts (98%) rename src/main/ai-vault/{ => scanners/codex}/session-scanner-codex-tool-records.ts (89%) rename src/main/ai-vault/{ => scanners/codex}/session-scanner-codex-workers.test.ts (97%) rename src/main/ai-vault/{ => scanners/copilot}/session-scanner-copilot-cache-upgrade.test.ts (77%) rename src/main/ai-vault/{ => scanners/copilot}/session-scanner-copilot-parser.test.ts (98%) rename src/main/ai-vault/{ => scanners/copilot}/session-scanner-copilot-parser.ts (81%) rename src/main/ai-vault/{ => scanners/cursor}/session-scanner-cursor-chat-meta.test.ts (96%) rename src/main/ai-vault/{ => scanners/cursor}/session-scanner-cursor-chat-meta.ts (94%) rename src/main/ai-vault/{ => scanners/cursor}/session-scanner-cursor-parser.ts (77%) rename src/main/ai-vault/{ => scanners/devin}/session-scanner-devin-contention.test.ts (84%) rename src/main/ai-vault/{ => scanners/devin}/session-scanner-devin-db.test.ts (97%) rename src/main/ai-vault/{ => scanners/devin}/session-scanner-devin-db.ts (87%) rename src/main/ai-vault/{ => scanners/devin}/session-scanner-devin-dedup.test.ts (94%) rename src/main/ai-vault/{ => scanners/devin}/session-scanner-devin-parser.test.ts (98%) rename src/main/ai-vault/{ => scanners/devin}/session-scanner-devin-parser.ts (86%) rename src/main/ai-vault/{ => scanners/droid}/session-scanner-droid-parser.test.ts (92%) rename src/main/ai-vault/{ => scanners/droid}/session-scanner-droid-parser.ts (81%) rename src/main/ai-vault/{ => scanners/gemini}/session-scanner-gemini-parsers.ts (86%) rename src/main/ai-vault/{ => scanners/grok}/session-scanner-grok-parser.test.ts (96%) rename src/main/ai-vault/{ => scanners/grok}/session-scanner-grok-parser.ts (78%) rename src/main/ai-vault/{ => scanners/grok}/session-scanner-grok-user-text.test.ts (100%) rename src/main/ai-vault/{ => scanners/grok}/session-scanner-grok-user-text.ts (100%) rename src/main/ai-vault/{ => scanners/hermes}/session-scanner-hermes-parser.ts (80%) rename src/main/ai-vault/{ => scanners/jcode}/session-scanner-jcode-parser.test.ts (100%) rename src/main/ai-vault/{ => scanners/jcode}/session-scanner-jcode-parser.ts (81%) rename src/main/ai-vault/{ => scanners/kimi}/session-scanner-kimi-index-cache.test.ts (100%) rename src/main/ai-vault/{ => scanners/kimi}/session-scanner-kimi-index-cache.ts (100%) rename src/main/ai-vault/{ => scanners/kimi}/session-scanner-kimi-parser.test.ts (97%) rename src/main/ai-vault/{ => scanners/kimi}/session-scanner-kimi-parser.ts (84%) rename src/main/ai-vault/{ => scanners/kimi}/session-scanner-kimi-paths.ts (88%) rename src/main/ai-vault/{ => scanners/kiro}/session-scanner-kiro-fixtures.ts (94%) rename src/main/ai-vault/{ => scanners/kiro}/session-scanner-kiro-parser.test.ts (97%) rename src/main/ai-vault/{ => scanners/kiro}/session-scanner-kiro-parser.ts (82%) rename src/main/ai-vault/{ => scanners/muse}/session-scanner-muse-parser.ts (87%) rename src/main/ai-vault/{ => scanners/muse}/session-scanner-muse-paths.ts (77%) rename src/main/ai-vault/{ => scanners/muse}/session-scanner-muse.test.ts (93%) rename src/main/ai-vault/{ => scanners/omp}/omp-session-root.test.ts (96%) rename src/main/ai-vault/{ => scanners/omp}/omp-session-root.ts (97%) rename src/main/ai-vault/{ => scanners/omp}/session-scanner-omp-subagent-listing.test.ts (100%) rename src/main/ai-vault/{ => scanners/omp}/session-scanner-omp-subagent-listing.ts (89%) rename src/main/ai-vault/{ => scanners/omp}/session-scanner-omp-subagent-prune.test.ts (97%) rename src/main/ai-vault/{ => scanners/omp}/session-scanner-omp-subagent-transcripts.test.ts (98%) rename src/main/ai-vault/{ => scanners/omp}/session-scanner-omp-subagent-transcripts.ts (91%) rename src/main/ai-vault/{ => scanners/omp}/session-scanner-omp-title.test.ts (98%) rename src/main/ai-vault/{ => scanners/omp}/session-scanner-omp-title.ts (90%) rename src/main/ai-vault/{ => scanners/omp}/session-scanner-omp-written-record.ts (76%) rename src/main/ai-vault/{ => scanners/openclaw}/openclaw-session-layout.test.ts (92%) rename src/main/ai-vault/{ => scanners/openclaw}/openclaw-session-layout.ts (84%) rename src/main/ai-vault/{ => scanners/opencode/reader-transport}/opencode-wsl-runtime-preparation.test.ts (96%) rename src/main/ai-vault/{ => scanners/opencode/reader-transport}/opencode-wsl-runtime-preparation.ts (83%) rename src/main/ai-vault/{ => scanners/opencode/reader-transport}/session-scanner-opencode-native-page-limit.test.ts (100%) rename src/main/ai-vault/{ => scanners/opencode/reader-transport}/session-scanner-opencode-native-worker.test.ts (94%) rename src/main/ai-vault/{ => scanners/opencode/reader-transport}/session-scanner-opencode-process-admission.test.ts (100%) rename src/main/ai-vault/{ => scanners/opencode/reader-transport}/session-scanner-opencode-sqlite-dispatch.ts (80%) rename src/main/ai-vault/{ => scanners/opencode/reader-transport}/session-scanner-opencode-sqlite-process-client.ts (96%) rename src/main/ai-vault/{ => scanners/opencode/reader-transport}/session-scanner-opencode-sqlite-process-entry.ts (100%) rename src/main/ai-vault/{ => scanners/opencode/reader-transport}/session-scanner-opencode-sqlite-process-framing.ts (89%) rename src/main/ai-vault/{ => scanners/opencode/reader-transport}/session-scanner-opencode-sqlite-process.test.ts (96%) rename src/main/ai-vault/{ => scanners/opencode/reader-transport}/session-scanner-opencode-sqlite-worker-client.test.ts (98%) rename src/main/ai-vault/{ => scanners/opencode/reader-transport}/session-scanner-opencode-sqlite-worker-client.ts (92%) rename src/main/ai-vault/{ => scanners/opencode/reader-transport}/session-scanner-opencode-sqlite-worker-protocol.ts (84%) rename src/main/ai-vault/{ => scanners/opencode/reader-transport}/session-scanner-opencode-sqlite-worker-response.ts (84%) rename src/main/ai-vault/{ => scanners/opencode/reader-transport}/session-scanner-opencode-sqlite-worker-spawn.test.ts (91%) rename src/main/ai-vault/{ => scanners/opencode/reader-transport}/session-scanner-opencode-sqlite-worker-spawn.ts (92%) rename src/main/ai-vault/{ => scanners/opencode/reader-transport}/session-scanner-opencode-wsl-client.test.ts (94%) rename src/main/ai-vault/{ => scanners/opencode/reader-transport}/session-scanner-opencode-wsl-client.ts (77%) rename src/main/ai-vault/{ => scanners/opencode/reader-transport}/session-scanner-opencode-wsl-routing.test.ts (95%) rename src/main/ai-vault/{ => scanners/opencode/reader-transport}/session-scanner-opencode-wsl-runtime.ts (100%) rename src/main/ai-vault/{ => scanners/opencode}/session-scanner-opencode-cancellation.test.ts (90%) rename src/main/ai-vault/{ => scanners/opencode}/session-scanner-opencode-parser.test.ts (96%) rename src/main/ai-vault/{ => scanners/opencode}/session-scanner-opencode-parser.ts (83%) rename src/main/ai-vault/{ => scanners/opencode}/session-scanner-opencode-sources-wsl-stall.test.ts (94%) rename src/main/ai-vault/{ => scanners/opencode}/session-scanner-opencode-sources.test.ts (93%) rename src/main/ai-vault/{ => scanners/opencode}/session-scanner-opencode-sources.ts (83%) rename src/main/ai-vault/{ => scanners/opencode/sqlite}/opencode-transcript-capture-limits.ts (100%) rename src/main/ai-vault/{ => scanners/opencode/sqlite}/session-scanner-opencode-sqlite-bounds.test.ts (97%) rename src/main/ai-vault/{ => scanners/opencode/sqlite}/session-scanner-opencode-sqlite-capture.ts (91%) rename src/main/ai-vault/{ => scanners/opencode/sqlite}/session-scanner-opencode-sqlite-coexistence.test.ts (96%) rename src/main/ai-vault/{ => scanners/opencode/sqlite}/session-scanner-opencode-sqlite-discovery.ts (79%) rename src/main/ai-vault/{ => scanners/opencode/sqlite}/session-scanner-opencode-sqlite-fixture.ts (99%) rename src/main/ai-vault/{ => scanners/opencode/sqlite}/session-scanner-opencode-sqlite-list.ts (90%) rename src/main/ai-vault/{ => scanners/opencode/sqlite}/session-scanner-opencode-sqlite-open.test.ts (98%) rename src/main/ai-vault/{ => scanners/opencode/sqlite}/session-scanner-opencode-sqlite-open.ts (87%) rename src/main/ai-vault/{ => scanners/opencode/sqlite}/session-scanner-opencode-sqlite-paths.test.ts (93%) rename src/main/ai-vault/{ => scanners/opencode/sqlite}/session-scanner-opencode-sqlite-rows.ts (95%) rename src/main/ai-vault/{ => scanners/opencode/sqlite}/session-scanner-opencode-sqlite-scan-scope.test.ts (100%) rename src/main/ai-vault/{ => scanners/opencode/sqlite}/session-scanner-opencode-sqlite-scan-scope.ts (92%) rename src/main/ai-vault/{ => scanners/opencode/sqlite}/session-scanner-opencode-sqlite-schema.ts (84%) rename src/main/ai-vault/{ => scanners/opencode/sqlite}/session-scanner-opencode-sqlite.test.ts (98%) rename src/main/ai-vault/{ => scanners/opencode/sqlite}/session-scanner-opencode-sqlite.ts (93%) rename src/main/ai-vault/{ => scanners/opencode2}/session-scanner-opencode2-message.test.ts (92%) rename src/main/ai-vault/{ => scanners/opencode2}/session-scanner-opencode2-message.ts (84%) rename src/main/ai-vault/{ => scanners/opencode2}/session-scanner-opencode2-sqlite-list.ts (89%) rename src/main/ai-vault/{ => scanners/opencode2}/session-scanner-opencode2-sqlite.test.ts (97%) rename src/main/ai-vault/{ => scanners/opencode2}/session-scanner-opencode2-sqlite.ts (93%) rename src/main/ai-vault/{ => scanners/pi}/session-scanner-pi-omp-shared-root.test.ts (97%) rename src/main/ai-vault/{ => scanners/pi}/session-scanner-pi-scope.test.ts (94%) rename src/main/ai-vault/{ => scanners/qoder}/__fixtures__/qoder-1.1.64-generated-resumed.jsonl (100%) rename src/main/ai-vault/{ => scanners/qoder}/session-scanner-qoder-parser.ts (84%) rename src/main/ai-vault/{ => scanners/qoder}/session-scanner-qoder.test.ts (93%) rename src/main/ai-vault/{ => scanners}/session-scanner-graph-parsers.test.ts (90%) rename src/main/ai-vault/{ => scanners}/session-scanner-graph-parsers.ts (89%) rename src/main/ai-vault/{ => scanners}/session-scanner-sqlite-scope-rows.ts (87%) rename src/main/ai-vault/{ => scanners/zcode}/session-scanner-zcode-order.ts (83%) rename src/main/ai-vault/{ => scanners/zcode}/session-scanner-zcode-sources.test.ts (82%) rename src/main/ai-vault/{ => scanners/zcode}/session-scanner-zcode-sources.ts (77%) rename src/main/ai-vault/{ => scanners/zcode}/session-scanner-zcode-visibility.ts (100%) rename src/main/ai-vault/{ => scanners/zcode}/session-scanner-zcode.test.ts (96%) delete mode 100644 src/main/ai-vault/session-scanner-opencode-sqlite-paths.ts rename src/main/ai-vault/{ => session-titles}/session-title-file-reader-wsl-stall.test.ts (95%) rename src/main/ai-vault/{ => session-titles}/session-title-file-reader.test.ts (97%) rename src/main/ai-vault/{ => session-titles}/session-title-file-reader.ts (92%) rename src/main/ai-vault/{ => session-titles}/session-title-request-paths.ts (76%) rename src/main/ai-vault/{ => session-titles}/session-title-resolver.ts (85%) rename src/main/ai-vault/{ => session-titles}/session-title-result-validation.ts (96%) rename src/main/ai-vault/{ => transcripts}/local-log-tail-reader.test.ts (96%) rename src/main/ai-vault/{ => transcripts}/local-log-tail-reader.ts (94%) rename src/main/ai-vault/{ => transcripts}/remote-session-content-lines.test.ts (100%) rename src/main/ai-vault/{ => transcripts}/remote-session-content-lines.ts (94%) rename src/main/ai-vault/{ => transcripts}/remote-session-file-stat.ts (88%) rename src/main/ai-vault/{ => transcripts}/session-decoded-message.ts (95%) rename src/main/ai-vault/{ => transcripts}/session-document-consumer-replacement.test.ts (95%) rename src/main/ai-vault/{ => transcripts}/session-document-discarded-scalar-memory.test.ts (100%) rename src/main/ai-vault/{ => transcripts}/session-document-stream-boundaries.test.ts (97%) rename src/main/ai-vault/{ => transcripts}/session-document-stream-contract.test.ts (100%) rename src/main/ai-vault/{ => transcripts}/session-document-stream-parity.test.ts (92%) rename src/main/ai-vault/{ => transcripts}/session-document-stream-projection.test.ts (93%) rename src/main/ai-vault/{ => transcripts}/session-document-stream.ts (96%) rename src/main/ai-vault/{ => transcripts}/session-transcript-channel.ts (100%) rename src/main/ai-vault/{ => transcripts}/session-transcript-consumers.test.ts (92%) rename src/main/ai-vault/{ => transcripts}/session-transcript-consumers.ts (96%) rename src/main/ai-vault/{ => transcripts}/session-transcript-every-agent-capture.test.ts (55%) rename src/main/ai-vault/{ => transcripts}/session-transcript-message-content.test.ts (100%) rename src/main/ai-vault/{ => transcripts}/session-transcript-message-content.ts (96%) rename src/main/ai-vault/{ => transcripts}/session-transcript-reader.ts (94%) rename src/main/ai-vault/{ => transcripts}/session-transcript-record-budget.test.ts (100%) rename src/main/ai-vault/{ => transcripts}/session-transcript-record-budget.ts (100%) diff --git a/.github/workflows/zcode-transcript-contract.yml b/.github/workflows/zcode-transcript-contract.yml index 711df12e077..48f4b84ae84 100644 --- a/.github/workflows/zcode-transcript-contract.yml +++ b/.github/workflows/zcode-transcript-contract.yml @@ -3,9 +3,10 @@ on: pull_request: types: [opened, synchronize, reopened, ready_for_review, converted_to_draft] paths: - - 'src/main/ai-vault/session-scanner-zcode*' - - 'src/main/ai-vault/session-scanner-opencode*' - - 'src/main/ai-vault/opencode-wsl-runtime*' + - 'src/main/ai-vault/scanners/zcode/session-scanner-zcode*' + - 'src/main/ai-vault/scanners/opencode/**' + - 'src/main/ai-vault/scanners/opencode2/**' + - 'src/main/ai-vault/scanners/opencode/reader-transport/opencode-wsl-runtime*' - 'src/main/native-chat/transcript-opencode*' - 'src/main/native-chat/transcript-zcode*' - 'src/shared/native-chat/native-chat-types.ts' @@ -40,4 +41,4 @@ jobs: bun-version-file: config/.bun-version no-cache: true - name: Verify SQLite ordering, legacy readers, and host routing - run: pnpm test src/main/native-chat/transcript-zcode.test.ts src/main/native-chat/transcript-opencode.test.ts src/main/native-chat/transcript-opencode-sqlite-query.test.ts src/main/native-chat/transcript-opencode2-sqlite.test.ts src/main/native-chat/transcript-opencode-semantic-fidelity.test.ts src/main/native-chat/transcript-opencode-read-bounds.test.ts src/main/native-chat/transcript-opencode-subscribe.test.ts src/main/ai-vault/session-scanner-zcode.test.ts src/main/ai-vault/session-scanner-zcode-sources.test.ts src/main/ai-vault/opencode-wsl-runtime-preparation.test.ts src/main/ai-vault/session-scanner-opencode-wsl-routing.test.ts src/shared/native-chat/transcript/native-chat-transcript-projection.test.ts src/renderer/src/components/native-chat/structured-agent-session-transcript-order.test.ts + run: pnpm test src/main/native-chat/transcript-zcode.test.ts src/main/native-chat/transcript-opencode.test.ts src/main/native-chat/transcript-opencode-sqlite-query.test.ts src/main/native-chat/transcript-opencode2-sqlite.test.ts src/main/native-chat/transcript-opencode-semantic-fidelity.test.ts src/main/native-chat/transcript-opencode-read-bounds.test.ts src/main/native-chat/transcript-opencode-subscribe.test.ts src/main/ai-vault/scanners/zcode/session-scanner-zcode.test.ts src/main/ai-vault/scanners/zcode/session-scanner-zcode-sources.test.ts src/main/ai-vault/scanners/opencode/reader-transport/opencode-wsl-runtime-preparation.test.ts src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-wsl-routing.test.ts src/shared/native-chat/transcript/native-chat-transcript-projection.test.ts src/renderer/src/components/native-chat/structured-agent-session-transcript-order.test.ts diff --git a/config/build-plugins/main-build-entry-points.ts b/config/build-plugins/main-build-entry-points.ts index 38447ba9063..6e56cacd25b 100644 --- a/config/build-plugins/main-build-entry-points.ts +++ b/config/build-plugins/main-build-entry-points.ts @@ -24,7 +24,9 @@ export const MAIN_BUILD_ENTRY_POINTS: Record = { 'foreign-sqlite-reader-entry': resolve( 'src/main/foreign-sqlite-readers/foreign-sqlite-reader-entry.ts' ), - 'session-scanner-service-entry': resolve('src/main/ai-vault/session-scanner-service-entry.ts'), + 'session-scanner-service-entry': resolve( + 'src/main/ai-vault/scan-service/session-scanner-service-entry.ts' + ), 'wsl-transcript-fs-process-entry': resolve( 'src/main/native-chat/wsl-transcript-fs-process-entry.ts' ), diff --git a/config/flaky-test-pattern-baseline.txt b/config/flaky-test-pattern-baseline.txt index a8ffbeec290..8051d0d99f6 100644 --- a/config/flaky-test-pattern-baseline.txt +++ b/config/flaky-test-pattern-baseline.txt @@ -225,8 +225,8 @@ 1 test-no-real-time-wait:src/main/agent-hooks/server-turn-ended-at.test.ts 1 test-no-real-time-wait:src/main/agent-hooks/server-turn-started-at.test.ts 10 test-no-real-time-wait:src/main/agent-hooks/wsl-hook-relay-manager.test.ts -1 test-no-real-time-wait:src/main/ai-vault/session-scanner-opencode-sqlite-process.test.ts -2 test-no-real-time-wait:src/main/ai-vault/session-scanner-opencode-sqlite-scan-scope.test.ts +1 test-no-real-time-wait:src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-process.test.ts +2 test-no-real-time-wait:src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-scan-scope.test.ts 1 test-no-real-time-wait:src/main/antigravity/windows-hook-json-post.test.ts 1 test-no-real-time-wait:src/main/antigravity/windows-hook-payload-delivery.test.ts 2 test-no-real-time-wait:src/main/browser/browser-popup-compatibility.electron.test.ts @@ -727,19 +727,19 @@ 1 test-no-wall-clock:src/main/ai-vault-search/session-search-index-generation.test.ts 8 test-no-wall-clock:src/main/ai-vault-search/session-search-indexer.test.ts 1 test-no-wall-clock:src/main/ai-vault-search/session-search-store-is-memory.test.ts -1 test-no-wall-clock:src/main/ai-vault/session-parse-cache-metadata-checkpoint.test.ts -1 test-no-wall-clock:src/main/ai-vault/session-parse-cache-preview-upgrade.test.ts -3 test-no-wall-clock:src/main/ai-vault/session-scanner-claude-subagents.test.ts -1 test-no-wall-clock:src/main/ai-vault/session-scanner-copilot-cache-upgrade.test.ts -2 test-no-wall-clock:src/main/ai-vault/session-scanner-copilot-parser.test.ts -3 test-no-wall-clock:src/main/ai-vault/session-scanner-cursor-chat-meta.test.ts -1 test-no-wall-clock:src/main/ai-vault/session-scanner-devin-db.test.ts -4 test-no-wall-clock:src/main/ai-vault/session-scanner-devin-parser.test.ts -2 test-no-wall-clock:src/main/ai-vault/session-scanner-grok-parser.test.ts -3 test-no-wall-clock:src/main/ai-vault/session-scanner-jcode-parser.test.ts -1 test-no-wall-clock:src/main/ai-vault/session-scanner-kimi-parser.test.ts -2 test-no-wall-clock:src/main/ai-vault/session-scanner-opencode-parser.test.ts -1 test-no-wall-clock:src/main/ai-vault/session-scanner-opencode-sqlite-process.test.ts +1 test-no-wall-clock:src/main/ai-vault/parse-cache/session-parse-cache-metadata-checkpoint.test.ts +1 test-no-wall-clock:src/main/ai-vault/parse-cache/session-parse-cache-preview-upgrade.test.ts +3 test-no-wall-clock:src/main/ai-vault/scanners/claude/session-scanner-claude-subagents.test.ts +1 test-no-wall-clock:src/main/ai-vault/scanners/copilot/session-scanner-copilot-cache-upgrade.test.ts +2 test-no-wall-clock:src/main/ai-vault/scanners/copilot/session-scanner-copilot-parser.test.ts +3 test-no-wall-clock:src/main/ai-vault/scanners/cursor/session-scanner-cursor-chat-meta.test.ts +1 test-no-wall-clock:src/main/ai-vault/scanners/devin/session-scanner-devin-db.test.ts +4 test-no-wall-clock:src/main/ai-vault/scanners/devin/session-scanner-devin-parser.test.ts +2 test-no-wall-clock:src/main/ai-vault/scanners/grok/session-scanner-grok-parser.test.ts +3 test-no-wall-clock:src/main/ai-vault/scanners/jcode/session-scanner-jcode-parser.test.ts +1 test-no-wall-clock:src/main/ai-vault/scanners/kimi/session-scanner-kimi-parser.test.ts +2 test-no-wall-clock:src/main/ai-vault/scanners/opencode/session-scanner-opencode-parser.test.ts +1 test-no-wall-clock:src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-process.test.ts 2 test-no-wall-clock:src/main/antigravity/posix-hook-invocation.test.ts 2 test-no-wall-clock:src/main/browser/browser-session-registry.test.ts 2 test-no-wall-clock:src/main/browser/cdp-ws-proxy.test.ts @@ -1128,7 +1128,7 @@ 5 test-timeout-needs-reason:src/main/agent-hooks/server-transport-interference.test.ts 1 test-timeout-needs-reason:src/main/agent-hooks/wsl-hook-relay-live.integration.test.ts 1 test-timeout-needs-reason:src/main/agent-hooks/wsl-hook-relay-manager.test.ts -1 test-timeout-needs-reason:src/main/ai-vault/session-parse-cache-large-scan.test.ts +1 test-timeout-needs-reason:src/main/ai-vault/parse-cache/session-parse-cache-large-scan.test.ts 1 test-timeout-needs-reason:src/main/ai-vault/session-scanner-unlimited-dedup.test.ts 1 test-timeout-needs-reason:src/main/antigravity/native-macos-credentials.real.test.ts 2 test-timeout-needs-reason:src/main/antigravity/posix-hook-invocation.test.ts diff --git a/config/knip.json b/config/knip.json index 38409c4ba8f..97edb5ea89b 100644 --- a/config/knip.json +++ b/config/knip.json @@ -39,7 +39,7 @@ "src/preload/plugin-frame-guest.ts", "src/main/plugins/testing/plugin-test-hooks.ts", "src/main/plugins/testing/plugin-test-register.ts", - "src/main/ai-vault/session-scanner-service-entry.ts", + "src/main/ai-vault/scan-service/session-scanner-service-entry.ts", "src/main/native-chat/wsl-transcript-fs-process-entry.ts", "src/main/usage/usage-scan-worker-entry.ts", "src/main/workspaces/space-analysis/workspace-space-scan-worker-entry.ts", @@ -49,7 +49,7 @@ "src/main/orcad/orcad-local-serve-selection-entry.ts", "src/main/orcad/launcher.ts", "src/main/claude-accounts/claude-profile-wsl-entry.ts", - "src/main/ai-vault/session-scanner-opencode-sqlite-process-entry.ts", + "src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-process-entry.ts", "src/wsl-guest/wsl-browser-network-relay.ts", "src/renderer/src/space.tsx", "src/**/*.bench.ts", diff --git a/config/path-literal-baseline.txt b/config/path-literal-baseline.txt index 0007ace72f8..3a2c5ca033b 100644 --- a/config/path-literal-baseline.txt +++ b/config/path-literal-baseline.txt @@ -20,6 +20,8 @@ config/scripts/run-daemon-shutdown-descendants-docker.mjs src/main/windows-proce config/scripts/run-daemon-shutdown-descendants-docker.mjs src/main/windows-pty-root-identity.ts config/scripts/run-linux-lid-sleep-assertion-docker.mjs src/main/linux-lid-sleep-assertion.ts config/scripts/run-ssh-staged-upload-reliability.mjs src/main/ssh/ssh-relay-install-namespace.test.ts +config/scripts/session-search-file-id-e2e/run.ts src/main/ai-vault/session-scanner-service-entry.ts +config/scripts/session-search-tool-heavy-corpus.ts src/main/ai-vault/session-transcript-reader.ts config/tsconfig.node.json src/renderer/src/components/native-chat/native-chat-composer-primary-action.ts config/tsconfig.node.json src/renderer/src/components/native-chat/native-chat-resolution-receipt.ts config/tsconfig.node.json src/renderer/src/components/native-chat/structured-agent-question-projection.ts diff --git a/config/process-host-direct-import-baseline.txt b/config/process-host-direct-import-baseline.txt index d719e13e0d3..51c60f2434c 100644 --- a/config/process-host-direct-import-baseline.txt +++ b/config/process-host-direct-import-baseline.txt @@ -9,9 +9,9 @@ src/main/agent-hooks/managed-hook-owner-identity.ts src/main/agent-hooks/wsl-hook-relay-link.ts src/main/agent-hooks/wsl-hook-relay-manager.ts src/main/agent-hooks/wsl-hook-relay-sentinel.ts -src/main/ai-vault/session-scanner-service-client-state.ts -src/main/ai-vault/session-scanner-service-client.ts -src/main/ai-vault/session-scanner-service-spawn.ts +src/main/ai-vault/scan-service/session-scanner-service-client-state.ts +src/main/ai-vault/scan-service/session-scanner-service-client.ts +src/main/ai-vault/scan-service/session-scanner-service-spawn.ts src/main/window/desktop-integration/app-icon.ts src/main/automations/precheck-runner.ts src/main/browser/agent-browser/agent-browser-bridge-execution.ts diff --git a/config/reliability-gates.jsonc b/config/reliability-gates.jsonc index 1cba1e9f13d..c72c4d1e615 100644 --- a/config/reliability-gates.jsonc +++ b/config/reliability-gates.jsonc @@ -12441,7 +12441,7 @@ "invariant": "Typing, focus, terminal switch, workspace switch, visibility resume, resize, render, per-pane liveness, and tab-title synchronization must not call global pty:listSessions or aiVault.listSessions; they must use targeted APIs or cached provider-owned state.", "oracle": "The current executable slice asserts targeted visibility/first-input liveness, resize re-assertion after visibility resume, light tab/active-state resume, SSH/remote skip behavior, and a closed Resource Manager budget of one readiness seed plus one coalesced inventory read only for unknown spawn IDs. AI Vault title sync deterministically accepts only resolveSessionTitles, batches at most 64 exact identities, bounds scanner-service calls at sixteen, routes requests to the transcript-owning local/SSH/runtime host, and proves zero broad scans for unsupported hosts. The full hot-path oracle still needs instrumentation around raw focus, split focus, workspace switch, render ticks, and high-session PTY fixtures.", "commands": [ - "pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/lib/ai-vault-tab-title-sync.test.ts src/main/ai-vault/session-scanner-service-client.test.ts src/main/ai-vault/session-title-file-reader.test.ts src/main/ai-vault/session-parse-cache-persistence.test.ts src/main/ipc/ai-vault.test.ts src/main/runtime/rpc/methods/ai-vault.test.ts", + "pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/lib/ai-vault-tab-title-sync.test.ts src/main/ai-vault/scan-service/session-scanner-service-client.test.ts src/main/ai-vault/session-titles/session-title-file-reader.test.ts src/main/ai-vault/parse-cache/session-parse-cache-persistence.test.ts src/main/ipc/ai-vault.test.ts src/main/runtime/rpc/methods/ai-vault.test.ts", "ORCA_BACKGROUND_LAUNCH=1 pnpm exec vitest run --config config/vitest.config.ts src/main/ipc/pty/pty-startup-barrier-and-listing.test.ts src/renderer/src/components/status-bar/use-resource-session-inventory.test.tsx src/renderer/src/components/status-bar/resource-session-inventory.test.ts --maxWorkers=2 --reporter=dot" ], "testFiles": [ @@ -12449,9 +12449,9 @@ "src/renderer/src/components/status-bar/use-resource-session-inventory.test.tsx", "src/renderer/src/components/status-bar/resource-session-inventory.test.ts", "src/renderer/src/lib/ai-vault-tab-title-sync.test.ts", - "src/main/ai-vault/session-scanner-service-client.test.ts", - "src/main/ai-vault/session-title-file-reader.test.ts", - "src/main/ai-vault/session-parse-cache-persistence.test.ts", + "src/main/ai-vault/scan-service/session-scanner-service-client.test.ts", + "src/main/ai-vault/session-titles/session-title-file-reader.test.ts", + "src/main/ai-vault/parse-cache/session-parse-cache-persistence.test.ts", "src/main/ipc/ai-vault.test.ts", "src/main/runtime/rpc/methods/ai-vault.test.ts" ], @@ -12491,7 +12491,7 @@ ] }, { - "file": "src/main/ai-vault/session-scanner-service-client.test.ts", + "file": "src/main/ai-vault/scan-service/session-scanner-service-client.test.ts", "assertions": [ "the service waits for ready and runs the cache and interactive lanes independently", "active and queued calls are bounded together at sixteen", @@ -12500,7 +12500,7 @@ ] }, { - "file": "src/main/ai-vault/session-parse-cache-persistence.test.ts", + "file": "src/main/ai-vault/parse-cache/session-parse-cache-persistence.test.ts", "assertions": [ "the background scanner receives the configured persisted-cache identity", "unchanged transcripts remain reusable across process restarts" @@ -12522,7 +12522,8 @@ "command": "pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/lib/ai-vault-tab-title-sync.test.ts src/main/ai-vault/session-scanner-service-client.test.ts src/main/ai-vault/session-title-file-reader.test.ts src/main/ai-vault/session-parse-cache-persistence.test.ts src/main/ipc/ai-vault.test.ts src/main/runtime/rpc/methods/ai-vault.test.ts", "result": "passed", "durationSeconds": 5.3, - "summary": "The focused run passed 138 tests across 7 files, proving exact-title-only renderer requests, provider-isolated batching, per-lane scanner-service lifecycle and fault recovery, exact transcript identity, host routing, mixed-version degradation, and zero broad-scan fallback." + "summary": "The focused run passed 138 tests across 7 files, proving exact-title-only renderer requests, provider-isolated batching, per-lane scanner-service lifecycle and fault recovery, exact transcript identity, host routing, mixed-version degradation, and zero broad-scan fallback.", + "currentCommand": "pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/lib/ai-vault-tab-title-sync.test.ts src/main/ai-vault/scan-service/session-scanner-service-client.test.ts src/main/ai-vault/session-titles/session-title-file-reader.test.ts src/main/ai-vault/parse-cache/session-parse-cache-persistence.test.ts src/main/ipc/ai-vault.test.ts src/main/runtime/rpc/methods/ai-vault.test.ts" }, { "date": "2026-10-06", diff --git a/config/scripts/build-wsl-guest.mjs b/config/scripts/build-wsl-guest.mjs index e1ee2bd36e6..fff539fde4d 100644 --- a/config/scripts/build-wsl-guest.mjs +++ b/config/scripts/build-wsl-guest.mjs @@ -58,7 +58,7 @@ await bundle( WSL_CLAUDE_PROFILE_HELPER_FILENAME ) await bundle( - 'src/main/ai-vault/session-scanner-opencode-sqlite-process-entry.ts', + 'src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-process-entry.ts', OPENCODE_SQLITE_READER_FILENAME, { external: ['electron'] } ) diff --git a/config/scripts/ci-shard-timings.json b/config/scripts/ci-shard-timings.json index 74aa8694bd4..c98840d8dc0 100644 --- a/config/scripts/ci-shard-timings.json +++ b/config/scripts/ci-shard-timings.json @@ -1039,123 +1039,123 @@ "src/main/ai-vault/ai-vault-scan-progress-flow.test.ts": 835, "src/main/ai-vault/ai-vault-scan-progress.test.ts": 475, "src/main/ai-vault/ai-vault-wsl-session-carryover.test.ts": 46, - "src/main/ai-vault/antigravity-ide-history.test.ts": 525, - "src/main/ai-vault/antigravity-index-file-admission.test.ts": 170, - "src/main/ai-vault/antigravity-opening-prompt-workspace.test.ts": 204, - "src/main/ai-vault/antigravity-recorded-history.test.ts": 395, + "src/main/ai-vault/scanners/antigravity/antigravity-ide-history.test.ts": 525, + "src/main/ai-vault/scanners/antigravity/antigravity-index-file-admission.test.ts": 170, + "src/main/ai-vault/scanners/antigravity/antigravity-opening-prompt-workspace.test.ts": 204, + "src/main/ai-vault/scanners/antigravity/antigravity-recorded-history.test.ts": 395, "src/main/ai-vault/cached-session-list-wsl-probe.test.ts": 238, "src/main/ai-vault/cached-session-list.test.ts": 565, - "src/main/ai-vault/claude-project-dir-encoding.test.ts": 50, - "src/main/ai-vault/codex-session-collection.test.ts": 200, - "src/main/ai-vault/codex-session-root-dedup.test.ts": 183, - "src/main/ai-vault/local-log-tail-reader.test.ts": 59, - "src/main/ai-vault/omp-session-root.test.ts": 271, - "src/main/ai-vault/openclaw-session-layout.test.ts": 223, - "src/main/ai-vault/opencode-wsl-runtime-preparation.test.ts": 1230, - "src/main/ai-vault/remote-session-content-lines.test.ts": 66, + "src/main/ai-vault/scanners/claude/claude-project-dir-encoding.test.ts": 50, + "src/main/ai-vault/scanners/codex/codex-session-collection.test.ts": 200, + "src/main/ai-vault/scanners/codex/codex-session-root-dedup.test.ts": 183, + "src/main/ai-vault/transcripts/local-log-tail-reader.test.ts": 59, + "src/main/ai-vault/scanners/omp/omp-session-root.test.ts": 271, + "src/main/ai-vault/scanners/openclaw/openclaw-session-layout.test.ts": 223, + "src/main/ai-vault/scanners/opencode/reader-transport/opencode-wsl-runtime-preparation.test.ts": 1230, + "src/main/ai-vault/transcripts/remote-session-content-lines.test.ts": 66, "src/main/ai-vault/runtime-session-scanner.test.ts": 245, "src/main/ai-vault/runtime-session-search-call.test.ts": 48, "src/main/ai-vault/session-cwd-bucket-layouts.test.ts": 62, "src/main/ai-vault/session-delete-target.test.ts": 240, "src/main/ai-vault/session-delete.test.ts": 243, - "src/main/ai-vault/session-document-consumer-replacement.test.ts": 401, - "src/main/ai-vault/session-document-discarded-scalar-memory.test.ts": 441, - "src/main/ai-vault/session-document-stream-boundaries.test.ts": 214, - "src/main/ai-vault/session-document-stream-contract.test.ts": 279, - "src/main/ai-vault/session-document-stream-parity.test.ts": 237, - "src/main/ai-vault/session-document-stream-projection.test.ts": 183, + "src/main/ai-vault/transcripts/session-document-consumer-replacement.test.ts": 401, + "src/main/ai-vault/transcripts/session-document-discarded-scalar-memory.test.ts": 441, + "src/main/ai-vault/transcripts/session-document-stream-boundaries.test.ts": 214, + "src/main/ai-vault/transcripts/session-document-stream-contract.test.ts": 279, + "src/main/ai-vault/transcripts/session-document-stream-parity.test.ts": 237, + "src/main/ai-vault/transcripts/session-document-stream-projection.test.ts": 183, "src/main/ai-vault/session-first-user-prompt-opencode.test.ts": 244, "src/main/ai-vault/session-first-user-prompt-read.test.ts": 270, "src/main/ai-vault/session-list-fingerprint.test.ts": 49, "src/main/ai-vault/session-list-result-validation.test.ts": 118, "src/main/ai-vault/session-list-results.test.ts": 163, "src/main/ai-vault/session-newest-files.test.ts": 115, - "src/main/ai-vault/session-parse-cache-antigravity-upgrade.test.ts": 348, - "src/main/ai-vault/session-parse-cache-devin-upgrade.test.ts": 317, - "src/main/ai-vault/session-parse-cache-large-scan.test.ts": 4606, - "src/main/ai-vault/session-parse-cache-metadata-checkpoint.test.ts": 392, - "src/main/ai-vault/session-parse-cache-persistence.test.ts": 2723, - "src/main/ai-vault/session-parse-cache-preview-upgrade.test.ts": 341, + "src/main/ai-vault/parse-cache/session-parse-cache-antigravity-upgrade.test.ts": 348, + "src/main/ai-vault/parse-cache/session-parse-cache-devin-upgrade.test.ts": 317, + "src/main/ai-vault/parse-cache/session-parse-cache-large-scan.test.ts": 4606, + "src/main/ai-vault/parse-cache/session-parse-cache-metadata-checkpoint.test.ts": 392, + "src/main/ai-vault/parse-cache/session-parse-cache-persistence.test.ts": 2723, + "src/main/ai-vault/parse-cache/session-parse-cache-preview-upgrade.test.ts": 341, "src/main/ai-vault/session-scan-cutoff.test.ts": 172, "src/main/ai-vault/session-scanner-agent-root-overrides.test.ts": 887, - "src/main/ai-vault/session-scanner-antigravity-parser.test.ts": 181, - "src/main/ai-vault/session-scanner-antigravity-source.test.ts": 502, - "src/main/ai-vault/session-scanner-claude-cwd-drift.test.ts": 525, - "src/main/ai-vault/session-scanner-claude-subagent-prune.test.ts": 498, - "src/main/ai-vault/session-scanner-claude-subagents.test.ts": 205, - "src/main/ai-vault/session-scanner-claude-title.test.ts": 504, - "src/main/ai-vault/session-scanner-claude-unicode-scope.test.ts": 488, - "src/main/ai-vault/session-scanner-cline-parser.test.ts": 506, - "src/main/ai-vault/session-scanner-codebuddy-scope.test.ts": 488, - "src/main/ai-vault/session-scanner-codebuddy-source.test.ts": 465, - "src/main/ai-vault/session-scanner-codex-dual-root.test.ts": 517, - "src/main/ai-vault/session-scanner-codex-fast-path.test.ts": 392, - "src/main/ai-vault/session-scanner-codex-non-user-origin.test.ts": 153, - "src/main/ai-vault/session-scanner-codex-parser.test.ts": 195, - "src/main/ai-vault/session-scanner-codex-title-index.test.ts": 295, - "src/main/ai-vault/session-scanner-codex-tool-records.test.ts": 177, - "src/main/ai-vault/session-scanner-codex-workers.test.ts": 543, + "src/main/ai-vault/scanners/antigravity/session-scanner-antigravity-parser.test.ts": 181, + "src/main/ai-vault/scanners/antigravity/session-scanner-antigravity-source.test.ts": 502, + "src/main/ai-vault/scanners/claude/session-scanner-claude-cwd-drift.test.ts": 525, + "src/main/ai-vault/scanners/claude/session-scanner-claude-subagent-prune.test.ts": 498, + "src/main/ai-vault/scanners/claude/session-scanner-claude-subagents.test.ts": 205, + "src/main/ai-vault/scanners/claude/session-scanner-claude-title.test.ts": 504, + "src/main/ai-vault/scanners/claude/session-scanner-claude-unicode-scope.test.ts": 488, + "src/main/ai-vault/scanners/cline/session-scanner-cline-parser.test.ts": 506, + "src/main/ai-vault/scanners/codebuddy/session-scanner-codebuddy-scope.test.ts": 488, + "src/main/ai-vault/scanners/codebuddy/session-scanner-codebuddy-source.test.ts": 465, + "src/main/ai-vault/scanners/codex/session-scanner-codex-dual-root.test.ts": 517, + "src/main/ai-vault/scanners/codex/session-scanner-codex-fast-path.test.ts": 392, + "src/main/ai-vault/scanners/codex/session-scanner-codex-non-user-origin.test.ts": 153, + "src/main/ai-vault/scanners/codex/session-scanner-codex-parser.test.ts": 195, + "src/main/ai-vault/scanners/codex/session-scanner-codex-title-index.test.ts": 295, + "src/main/ai-vault/scanners/codex/session-scanner-codex-tool-records.test.ts": 177, + "src/main/ai-vault/scanners/codex/session-scanner-codex-workers.test.ts": 543, "src/main/ai-vault/session-scanner-conversation-name-requests.test.ts": 443, - "src/main/ai-vault/session-scanner-copilot-cache-upgrade.test.ts": 391, - "src/main/ai-vault/session-scanner-copilot-parser.test.ts": 173, + "src/main/ai-vault/scanners/copilot/session-scanner-copilot-cache-upgrade.test.ts": 391, + "src/main/ai-vault/scanners/copilot/session-scanner-copilot-parser.test.ts": 173, "src/main/ai-vault/session-scanner-core-parser-wsl-stall.test.ts": 344, - "src/main/ai-vault/session-scanner-cursor-chat-meta.test.ts": 745, + "src/main/ai-vault/scanners/cursor/session-scanner-cursor-chat-meta.test.ts": 745, "src/main/ai-vault/session-scanner-cutoff.test.ts": 778, "src/main/ai-vault/session-scanner-dedup-batches.test.ts": 556, - "src/main/ai-vault/session-scanner-devin-contention.test.ts": 586, - "src/main/ai-vault/session-scanner-devin-db.test.ts": 751, - "src/main/ai-vault/session-scanner-devin-dedup.test.ts": 501, - "src/main/ai-vault/session-scanner-devin-parser.test.ts": 283, + "src/main/ai-vault/scanners/devin/session-scanner-devin-contention.test.ts": 586, + "src/main/ai-vault/scanners/devin/session-scanner-devin-db.test.ts": 751, + "src/main/ai-vault/scanners/devin/session-scanner-devin-dedup.test.ts": 501, + "src/main/ai-vault/scanners/devin/session-scanner-devin-parser.test.ts": 283, "src/main/ai-vault/session-scanner-directory-reader.test.ts": 190, "src/main/ai-vault/session-scanner-discovery-pipeline.test.ts": 244, "src/main/ai-vault/session-scanner-discovery-wsl-gate.test.ts": 180, - "src/main/ai-vault/session-scanner-droid-parser.test.ts": 166, + "src/main/ai-vault/scanners/droid/session-scanner-droid-parser.test.ts": 166, "src/main/ai-vault/session-scanner-first-user-prompt.test.ts": 60, - "src/main/ai-vault/session-scanner-graph-parsers.test.ts": 176, - "src/main/ai-vault/session-scanner-grok-parser.test.ts": 199, - "src/main/ai-vault/session-scanner-grok-user-text.test.ts": 44, + "src/main/ai-vault/scanners/session-scanner-graph-parsers.test.ts": 176, + "src/main/ai-vault/scanners/grok/session-scanner-grok-parser.test.ts": 199, + "src/main/ai-vault/scanners/grok/session-scanner-grok-user-text.test.ts": 44, "src/main/ai-vault/session-scanner-index-cache-wsl-stall.test.ts": 204, "src/main/ai-vault/session-scanner-injected-title.test.ts": 500, - "src/main/ai-vault/session-scanner-jcode-parser.test.ts": 154, + "src/main/ai-vault/scanners/jcode/session-scanner-jcode-parser.test.ts": 154, "src/main/ai-vault/session-scanner-json-document-memory.test.ts": 2371, "src/main/ai-vault/session-scanner-jsonl-reader.test.ts": 278, - "src/main/ai-vault/session-scanner-kimi-index-cache.test.ts": 163, - "src/main/ai-vault/session-scanner-kimi-parser.test.ts": 262, - "src/main/ai-vault/session-scanner-kiro-parser.test.ts": 187, + "src/main/ai-vault/scanners/kimi/session-scanner-kimi-index-cache.test.ts": 163, + "src/main/ai-vault/scanners/kimi/session-scanner-kimi-parser.test.ts": 262, + "src/main/ai-vault/scanners/kiro/session-scanner-kiro-parser.test.ts": 187, "src/main/ai-vault/session-scanner-messages.test.ts": 175, - "src/main/ai-vault/session-scanner-muse.test.ts": 492, - "src/main/ai-vault/session-scanner-omp-subagent-listing.test.ts": 197, - "src/main/ai-vault/session-scanner-omp-subagent-prune.test.ts": 488, - "src/main/ai-vault/session-scanner-omp-subagent-transcripts.test.ts": 183, - "src/main/ai-vault/session-scanner-omp-title.test.ts": 183, - "src/main/ai-vault/session-scanner-opencode-cancellation.test.ts": 1032, - "src/main/ai-vault/session-scanner-opencode-native-page-limit.test.ts": 175, - "src/main/ai-vault/session-scanner-opencode-native-worker.test.ts": 1047, - "src/main/ai-vault/session-scanner-opencode-parser.test.ts": 182, - "src/main/ai-vault/session-scanner-opencode-process-admission.test.ts": 253, - "src/main/ai-vault/session-scanner-opencode-sources-wsl-stall.test.ts": 202, - "src/main/ai-vault/session-scanner-opencode-sources.test.ts": 198, - "src/main/ai-vault/session-scanner-opencode-sqlite-bounds.test.ts": 954, - "src/main/ai-vault/session-scanner-opencode-sqlite-coexistence.test.ts": 802, - "src/main/ai-vault/session-scanner-opencode-sqlite-open.test.ts": 3734, - "src/main/ai-vault/session-scanner-opencode-sqlite-paths.test.ts": 44, - "src/main/ai-vault/session-scanner-opencode-sqlite-process.test.ts": 3815, - "src/main/ai-vault/session-scanner-opencode-sqlite-scan-scope.test.ts": 54, - "src/main/ai-vault/session-scanner-opencode-sqlite-worker-client.test.ts": 181, - "src/main/ai-vault/session-scanner-opencode-sqlite-worker-spawn.test.ts": 180, - "src/main/ai-vault/session-scanner-opencode-sqlite.test.ts": 410, - "src/main/ai-vault/session-scanner-opencode-wsl-client.test.ts": 162, - "src/main/ai-vault/session-scanner-opencode-wsl-routing.test.ts": 200, - "src/main/ai-vault/session-scanner-opencode2-message.test.ts": 138, - "src/main/ai-vault/session-scanner-opencode2-sqlite.test.ts": 306, - "src/main/ai-vault/session-scanner-parse-cache-agents.test.ts": 544, - "src/main/ai-vault/session-scanner-parse-cache.test.ts": 413, + "src/main/ai-vault/scanners/muse/session-scanner-muse.test.ts": 492, + "src/main/ai-vault/scanners/omp/session-scanner-omp-subagent-listing.test.ts": 197, + "src/main/ai-vault/scanners/omp/session-scanner-omp-subagent-prune.test.ts": 488, + "src/main/ai-vault/scanners/omp/session-scanner-omp-subagent-transcripts.test.ts": 183, + "src/main/ai-vault/scanners/omp/session-scanner-omp-title.test.ts": 183, + "src/main/ai-vault/scanners/opencode/session-scanner-opencode-cancellation.test.ts": 1032, + "src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-native-page-limit.test.ts": 175, + "src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-native-worker.test.ts": 1047, + "src/main/ai-vault/scanners/opencode/session-scanner-opencode-parser.test.ts": 182, + "src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-process-admission.test.ts": 253, + "src/main/ai-vault/scanners/opencode/session-scanner-opencode-sources-wsl-stall.test.ts": 202, + "src/main/ai-vault/scanners/opencode/session-scanner-opencode-sources.test.ts": 198, + "src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-bounds.test.ts": 954, + "src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-coexistence.test.ts": 802, + "src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-open.test.ts": 3734, + "src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-paths.test.ts": 44, + "src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-process.test.ts": 3815, + "src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-scan-scope.test.ts": 54, + "src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-worker-client.test.ts": 181, + "src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-worker-spawn.test.ts": 180, + "src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite.test.ts": 410, + "src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-wsl-client.test.ts": 162, + "src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-wsl-routing.test.ts": 200, + "src/main/ai-vault/scanners/opencode2/session-scanner-opencode2-message.test.ts": 138, + "src/main/ai-vault/scanners/opencode2/session-scanner-opencode2-sqlite.test.ts": 306, + "src/main/ai-vault/parse-cache/session-scanner-parse-cache-agents.test.ts": 544, + "src/main/ai-vault/parse-cache/session-scanner-parse-cache.test.ts": 413, "src/main/ai-vault/session-scanner-parse-wsl-stall.test.ts": 296, "src/main/ai-vault/session-scanner-parser-stream-cleanup.test.ts": 184, - "src/main/ai-vault/session-scanner-pi-omp-shared-root.test.ts": 505, - "src/main/ai-vault/session-scanner-pi-scope.test.ts": 501, + "src/main/ai-vault/scanners/pi/session-scanner-pi-omp-shared-root.test.ts": 505, + "src/main/ai-vault/scanners/pi/session-scanner-pi-scope.test.ts": 501, "src/main/ai-vault/session-scanner-preview-window-truncation.test.ts": 150, - "src/main/ai-vault/session-scanner-qoder.test.ts": 289, + "src/main/ai-vault/scanners/qoder/session-scanner-qoder.test.ts": 289, "src/main/ai-vault/session-scanner-record-budget.test.ts": 734, "src/main/ai-vault/session-scanner-recoverable-empty.test.ts": 521, "src/main/ai-vault/session-scanner-roots.test.ts": 203, @@ -1163,34 +1163,34 @@ "src/main/ai-vault/session-scanner-scope-inventory.test.ts": 201, "src/main/ai-vault/session-scanner-scope-walk.test.ts": 5362, "src/main/ai-vault/session-scanner-scope.test.ts": 550, - "src/main/ai-vault/session-scanner-service-cancellation.test.ts": 391, - "src/main/ai-vault/session-scanner-service-client.test.ts": 327, - "src/main/ai-vault/session-scanner-service-entry-path.test.ts": 46, - "src/main/ai-vault/session-scanner-service-entry-subagents.test.ts": 870, - "src/main/ai-vault/session-scanner-service-entry.test.ts": 909, - "src/main/ai-vault/session-scanner-service-env.test.ts": 53, - "src/main/ai-vault/session-scanner-service-request-deadline.test.ts": 122, - "src/main/ai-vault/session-scanner-service-restart-policy.test.ts": 44, - "src/main/ai-vault/session-scanner-service-root-request.test.ts": 44, - "src/main/ai-vault/session-scanner-service-root-response.test.ts": 251, - "src/main/ai-vault/session-scanner-service-search-roots.test.ts": 825, - "src/main/ai-vault/session-scanner-service-search.test.ts": 1741, - "src/main/ai-vault/session-scanner-service-spawn.test.ts": 312, + "src/main/ai-vault/scan-service/session-scanner-service-cancellation.test.ts": 391, + "src/main/ai-vault/scan-service/session-scanner-service-client.test.ts": 327, + "src/main/ai-vault/scan-service/session-scanner-service-entry-path.test.ts": 46, + "src/main/ai-vault/scan-service/session-scanner-service-entry-subagents.test.ts": 870, + "src/main/ai-vault/scan-service/session-scanner-service-entry.test.ts": 909, + "src/main/ai-vault/scan-service/session-scanner-service-env.test.ts": 53, + "src/main/ai-vault/scan-service/session-scanner-service-request-deadline.test.ts": 122, + "src/main/ai-vault/scan-service/session-scanner-service-restart-policy.test.ts": 44, + "src/main/ai-vault/scan-service/session-scanner-service-root-request.test.ts": 44, + "src/main/ai-vault/scan-service/session-scanner-service-root-response.test.ts": 251, + "src/main/ai-vault/scan-service/session-scanner-service-search-roots.test.ts": 825, + "src/main/ai-vault/scan-service/session-scanner-service-search.test.ts": 1741, + "src/main/ai-vault/scan-service/session-scanner-service-spawn.test.ts": 312, "src/main/ai-vault/session-scanner-timeline.test.ts": 160, "src/main/ai-vault/session-scanner-unlimited-dedup.test.ts": 3933, "src/main/ai-vault/session-scanner-values.test.ts": 153, "src/main/ai-vault/session-scanner-wsl-stop-gaps.test.ts": 880, - "src/main/ai-vault/session-scanner-zcode-sources.test.ts": 196, - "src/main/ai-vault/session-scanner-zcode.test.ts": 515, + "src/main/ai-vault/scanners/zcode/session-scanner-zcode-sources.test.ts": 196, + "src/main/ai-vault/scanners/zcode/session-scanner-zcode.test.ts": 515, "src/main/ai-vault/session-scanner.test.ts": 731, "src/main/ai-vault/session-scope-real-paths.test.ts": 62, - "src/main/ai-vault/session-sidecar-stat.test.ts": 59, - "src/main/ai-vault/session-title-file-reader-wsl-stall.test.ts": 284, - "src/main/ai-vault/session-title-file-reader.test.ts": 173, - "src/main/ai-vault/session-transcript-consumers.test.ts": 562, - "src/main/ai-vault/session-transcript-every-agent-capture.test.ts": 856, - "src/main/ai-vault/session-transcript-message-content.test.ts": 76, - "src/main/ai-vault/session-transcript-record-budget.test.ts": 44, + "src/main/ai-vault/parse-cache/session-sidecar-stat.test.ts": 59, + "src/main/ai-vault/session-titles/session-title-file-reader-wsl-stall.test.ts": 284, + "src/main/ai-vault/session-titles/session-title-file-reader.test.ts": 173, + "src/main/ai-vault/transcripts/session-transcript-consumers.test.ts": 562, + "src/main/ai-vault/transcripts/session-transcript-every-agent-capture.test.ts": 856, + "src/main/ai-vault/transcripts/session-transcript-message-content.test.ts": 76, + "src/main/ai-vault/transcripts/session-transcript-record-budget.test.ts": 44, "src/main/ai-vault/shell-command-words.test.ts": 320, "src/main/ai-vault/structured-chat-cli-fork.test.ts": 1238, "src/main/ai-vault/structured-chat-conversation-copy.test.ts": 917, diff --git a/config/scripts/orcad-entry-build.mjs b/config/scripts/orcad-entry-build.mjs index ceaed3f22f2..b96601863f2 100644 --- a/config/scripts/orcad-entry-build.mjs +++ b/config/scripts/orcad-entry-build.mjs @@ -21,7 +21,7 @@ export const ORCAD_CHILD_ENTRY_POINTS = { foreignSqliteReader: 'src/main/foreign-sqlite-readers/foreign-sqlite-reader-entry.ts', portScanCommandWorker: 'src/main/ports/port-scan-command-worker-entry.ts', commandPathDirectoryWorker: 'src/main/ipc/command-path-directory-worker-entry.ts', - sessionScanner: 'src/main/ai-vault/session-scanner-service-entry.ts', + sessionScanner: 'src/main/ai-vault/scan-service/session-scanner-service-entry.ts', workerThreadChildProcess: 'src/main/worker-thread-child-process/worker-thread-child-process-entry.ts', claudeProfileSetup: 'src/main/claude-accounts/claude-profile-setup-worker-entry.ts', diff --git a/config/scripts/pr-codex-unit-only-selection.test.mjs b/config/scripts/pr-codex-unit-only-selection.test.mjs index 0a4ce3cc5ba..66c5448876e 100644 --- a/config/scripts/pr-codex-unit-only-selection.test.mjs +++ b/config/scripts/pr-codex-unit-only-selection.test.mjs @@ -25,7 +25,7 @@ describe('per-job path classification', () => { classifyPrJobs([ unit, 'config/scripts/process-host-build-dist.test.mjs', - 'src/main/ai-vault/session-parse-cache-persistence.test.ts', + 'src/main/ai-vault/parse-cache/session-parse-cache-persistence.test.ts', 'src/shared/worktree/id.test.ts' ]) ).toMatchObject(expected) diff --git a/config/scripts/session-scanner-service-smoke.mjs b/config/scripts/session-scanner-service-smoke.mjs index 7ab4a920300..1051a17d101 100644 --- a/config/scripts/session-scanner-service-smoke.mjs +++ b/config/scripts/session-scanner-service-smoke.mjs @@ -4,7 +4,7 @@ import { join, resolve } from 'node:path' import { runProcessSync } from '@orca/process-host' import { describeProcessFailure } from './process-failure-message.mjs' import { ORCAD_SESSION_SCANNER_SERVICE_ENTRY } from '../../src/shared/orcad-artifacts.ts' -import { AI_VAULT_SERVICE_PROTOCOL_VERSION } from '../../src/main/ai-vault/session-scanner-service-protocol.ts' +import { AI_VAULT_SERVICE_PROTOCOL_VERSION } from '../../src/main/ai-vault/scan-service/session-scanner-service-protocol.ts' // Probe forks with shipped runtime’s execPath; judge exit code, never matched output. const PROBE = ` diff --git a/config/scripts/session-search-pass-benchmark.ts b/config/scripts/session-search-pass-benchmark.ts index f91289d7f84..6c7fb413583 100644 --- a/config/scripts/session-search-pass-benchmark.ts +++ b/config/scripts/session-search-pass-benchmark.ts @@ -3,8 +3,8 @@ import { mkdir, mkdtemp, rename, rm } from 'node:fs/promises' import { tmpdir } from 'node:os' import { basename, join } from 'node:path' import { isolatedScanRoots } from '../../src/main/ai-vault/session-scanner-test-fixtures' -import { resetSessionParseCacheForTests } from '../../src/main/ai-vault/session-scanner-parse-cache' -import { resetTranscriptConsumersForTests } from '../../src/main/ai-vault/session-transcript-consumers' +import { resetSessionParseCacheForTests } from '../../src/main/ai-vault/parse-cache/session-parse-cache-store' +import { resetTranscriptConsumersForTests } from '../../src/main/ai-vault/transcripts/session-transcript-consumers' import { SessionSearchIndexer } from '../../src/main/ai-vault-search/session-search-indexer' import { writeSyntheticTranscriptCorpus } from '../../src/main/ai-vault-search/session-search-synthetic-corpus' diff --git a/config/scripts/session-search-query-benchmark.ts b/config/scripts/session-search-query-benchmark.ts index 242bc4a4af6..a4db62f8976 100644 --- a/config/scripts/session-search-query-benchmark.ts +++ b/config/scripts/session-search-query-benchmark.ts @@ -2,10 +2,10 @@ import { rm, writeFile } from 'node:fs/promises' import { join } from 'node:path' import { createSessionParseStats, - parseAgentSessionFileCached, - resetSessionParseCacheForTests -} from '../../src/main/ai-vault/session-scanner-parse-cache' -import { resetTranscriptConsumersForTests } from '../../src/main/ai-vault/session-transcript-consumers' + parseAgentSessionFileCached +} from '../../src/main/ai-vault/parse-cache/session-scanner-parse-cache' +import { resetSessionParseCacheForTests } from '../../src/main/ai-vault/parse-cache/session-parse-cache-store' +import { resetTranscriptConsumersForTests } from '../../src/main/ai-vault/transcripts/session-transcript-consumers' import { SessionSearchEngine } from '../../src/main/ai-vault-search/session-search-engine' import type { SessionSearchRequest, diff --git a/config/scripts/session-search-scope-benchmark.ts b/config/scripts/session-search-scope-benchmark.ts index cb2d42f5be6..97f91eaf4aa 100644 --- a/config/scripts/session-search-scope-benchmark.ts +++ b/config/scripts/session-search-scope-benchmark.ts @@ -2,10 +2,10 @@ import { rm, writeFile } from 'node:fs/promises' import { join } from 'node:path' import { createSessionParseStats, - parseAgentSessionFileCached, - resetSessionParseCacheForTests -} from '../../src/main/ai-vault/session-scanner-parse-cache' -import { resetTranscriptConsumersForTests } from '../../src/main/ai-vault/session-transcript-consumers' + parseAgentSessionFileCached +} from '../../src/main/ai-vault/parse-cache/session-scanner-parse-cache' +import { resetSessionParseCacheForTests } from '../../src/main/ai-vault/parse-cache/session-parse-cache-store' +import { resetTranscriptConsumersForTests } from '../../src/main/ai-vault/transcripts/session-transcript-consumers' import { SessionSearchEngine } from '../../src/main/ai-vault-search/session-search-engine' import type { SessionSearchRequest, diff --git a/config/scripts/session-search-write-benchmark.ts b/config/scripts/session-search-write-benchmark.ts index 9e1a5edf098..5a9ea9914bc 100644 --- a/config/scripts/session-search-write-benchmark.ts +++ b/config/scripts/session-search-write-benchmark.ts @@ -4,11 +4,11 @@ import { join } from 'node:path' import { setImmediate as yieldToEventLoop } from 'node:timers/promises' import { createSessionParseStats, - parseAgentSessionFileCached, - resetSessionParseCacheForTests -} from '../../src/main/ai-vault/session-scanner-parse-cache' -import { resetTranscriptConsumersForTests } from '../../src/main/ai-vault/session-transcript-consumers' -import { requestWholeTranscriptRead } from '../../src/main/ai-vault/session-transcript-reader' + parseAgentSessionFileCached +} from '../../src/main/ai-vault/parse-cache/session-scanner-parse-cache' +import { resetSessionParseCacheForTests } from '../../src/main/ai-vault/parse-cache/session-parse-cache-store' +import { resetTranscriptConsumersForTests } from '../../src/main/ai-vault/transcripts/session-transcript-consumers' +import { requestWholeTranscriptRead } from '../../src/main/ai-vault/transcripts/session-transcript-reader' import { registerSessionSearchIndexConsumer } from '../../src/main/ai-vault-search/session-search-index-consumer' import { SessionSearchStore } from '../../src/main/ai-vault-search/session-search-store' import { writeSyntheticTranscriptCorpus } from '../../src/main/ai-vault-search/session-search-synthetic-corpus' diff --git a/config/scripts/vitest-node-runtime-files.mjs b/config/scripts/vitest-node-runtime-files.mjs index c423f4f1568..8b6b07f89cb 100644 --- a/config/scripts/vitest-node-runtime-files.mjs +++ b/config/scripts/vitest-node-runtime-files.mjs @@ -18,11 +18,11 @@ const NODE_RUNTIME_INCLUDE = [ 'src/main/ai-vault-search/session-search-index-writer.test.ts', 'src/main/ai-vault/session-scanner-unlimited-dedup.test.ts', // The parse cache persists through node:sqlite. - 'src/main/ai-vault/session-parse-cache-antigravity-upgrade.test.ts', - 'src/main/ai-vault/session-parse-cache-devin-upgrade.test.ts', - 'src/main/ai-vault/session-parse-cache-large-scan.test.ts', - 'src/main/ai-vault/session-parse-cache-metadata-checkpoint.test.ts', - 'src/main/ai-vault/session-parse-cache-persistence.test.ts', + 'src/main/ai-vault/parse-cache/session-parse-cache-antigravity-upgrade.test.ts', + 'src/main/ai-vault/parse-cache/session-parse-cache-devin-upgrade.test.ts', + 'src/main/ai-vault/parse-cache/session-parse-cache-large-scan.test.ts', + 'src/main/ai-vault/parse-cache/session-parse-cache-metadata-checkpoint.test.ts', + 'src/main/ai-vault/parse-cache/session-parse-cache-persistence.test.ts', 'src/main/ai-vault/session-scanner-scope-cwd-facts.test.ts', 'src/main/ai-vault/session-scanner-scope-walk.test.ts', // Electron main bridges streams with Node's implementation. @@ -43,7 +43,7 @@ const NODE_RUNTIME_INCLUDE = [ 'src/main/claude/claude-transcript-catch-up.test.ts', 'src/main/claude/claude-transcript-duration.test.ts', 'tests/e2e/native-chat-startup-option-pickers.unit.test.ts', - 'src/main/ai-vault/session-document-consumer-replacement.test.ts', + 'src/main/ai-vault/transcripts/session-document-consumer-replacement.test.ts', 'src/main/ai-vault-search/session-search-dependent-transcripts.test.ts', 'src/main/ai-vault-search/session-search-list-reparse.test.ts', 'src/main/ai-vault-search/session-search-transcript-dependencies.test.ts', @@ -155,7 +155,7 @@ const NODE_RUNTIME_INCLUDE = [ 'src/main/browser/browser-popup-compatibility.electron.test.ts', 'src/main/browser/browser-popup-native-compatibility.electron.test.ts', 'src/main/browser/browser-popup-background-compatibility.electron.test.ts', - 'src/main/ai-vault/session-scanner-devin-db.test.ts', + 'src/main/ai-vault/scanners/devin/session-scanner-devin-db.test.ts', 'src/shared/workspace-session-salvage.test.ts', 'src/main/git/repo-detection.test.ts', 'src/renderer/src/components/browser-pane/annotate/browser-grab-toast-owner-cleanup.test.tsx', diff --git a/src/main/acp/acp-conversation-copy.ts b/src/main/acp/acp-conversation-copy.ts index c39105961cd..6ec7b21a3bb 100644 --- a/src/main/acp/acp-conversation-copy.ts +++ b/src/main/acp/acp-conversation-copy.ts @@ -8,7 +8,7 @@ import { import { waitForPromiseWithSignal } from '../../shared/abort-signal-reason' import type { AiVaultConversationCopy } from '../../shared/ai-vault-resume-preparation' import { resolveSessionFilePath } from '../native-chat/session-file-resolver' -import { resolveOmpSessionsDir } from '../ai-vault/omp-session-root' +import { resolveOmpSessionsDir } from '../ai-vault/scanners/omp/omp-session-root' import { AcpRpcError } from './acp-errors' import { acpAgentName } from './acp-structured-agent-definitions' import type { AcpStructuredConnection } from './acp-structured-connection' diff --git a/src/main/ai-vault-search/session-search-child-service.ts b/src/main/ai-vault-search/session-search-child-service.ts index b5493c4ccb0..6572a696300 100644 --- a/src/main/ai-vault-search/session-search-child-service.ts +++ b/src/main/ai-vault-search/session-search-child-service.ts @@ -4,7 +4,7 @@ import { reconcileSessionSearchInService, searchSessionsInService, sessionSearchStatusInService -} from '../ai-vault/session-scanner-service-spawn' +} from '../ai-vault/scan-service/session-scanner-service-spawn' import type { SessionSearchService } from './session-search-service' /** Forward to the database-owning child; failed searches return not-ready while logging the error. */ diff --git a/src/main/ai-vault-search/session-search-content-hash.ts b/src/main/ai-vault-search/session-search-content-hash.ts index 7bfa80e8767..286d90bf751 100644 --- a/src/main/ai-vault-search/session-search-content-hash.ts +++ b/src/main/ai-vault-search/session-search-content-hash.ts @@ -1,5 +1,5 @@ import { createHash } from 'node:crypto' -import type { TranscriptMessage } from '../ai-vault/session-transcript-consumers' +import type { TranscriptMessage } from '../ai-vault/transcripts/session-transcript-consumers' // Forked transcripts share an opening prefix even after their tails diverge. const CONTENT_HASH_MESSAGE_LIMIT = 8 diff --git a/src/main/ai-vault-search/session-search-cursor-timestamps.test.ts b/src/main/ai-vault-search/session-search-cursor-timestamps.test.ts index 8e6cb2ec4ed..6678ef2b52f 100644 --- a/src/main/ai-vault-search/session-search-cursor-timestamps.test.ts +++ b/src/main/ai-vault-search/session-search-cursor-timestamps.test.ts @@ -2,12 +2,10 @@ import { appendFile, mkdir, stat, utimes, writeFile } from 'node:fs/promises' import { dirname, join } from 'node:path' import { afterEach, beforeEach, expect, it } from 'vitest' import { isAiVaultScanCancelledError } from '../../shared/ai-vault-types' -import { - parseAgentSessionFileCached, - resetSessionParseCacheForTests -} from '../ai-vault/session-scanner-parse-cache' -import { resetTranscriptConsumersForTests } from '../ai-vault/session-transcript-consumers' -import { resetCursorChatMetaIndexCacheForTests } from '../ai-vault/session-scanner-cursor-chat-meta' +import { parseAgentSessionFileCached } from '../ai-vault/parse-cache/session-scanner-parse-cache' +import { resetSessionParseCacheForTests } from '../ai-vault/parse-cache/session-parse-cache-store' +import { resetTranscriptConsumersForTests } from '../ai-vault/transcripts/session-transcript-consumers' +import { resetCursorChatMetaIndexCacheForTests } from '../ai-vault/scanners/cursor/session-scanner-cursor-chat-meta' import { SessionSearchEngine } from './session-search-engine' import { registerSessionSearchIndexConsumer } from './session-search-index-consumer' import { @@ -16,7 +14,7 @@ import { } from './session-search-index-test-fixture' import { SessionSearchStore } from './session-search-store' import { sessionCandidate } from './session-search-transcript-fixtures' -import { readWholeTranscript } from '../ai-vault/session-transcript-reader' +import { readWholeTranscript } from '../ai-vault/transcripts/session-transcript-reader' let index: SessionSearchIndexFile let store: SessionSearchStore diff --git a/src/main/ai-vault-search/session-search-deleted-sources.test.ts b/src/main/ai-vault-search/session-search-deleted-sources.test.ts index 3dcfbadd559..ea695aa0211 100644 --- a/src/main/ai-vault-search/session-search-deleted-sources.test.ts +++ b/src/main/ai-vault-search/session-search-deleted-sources.test.ts @@ -1,7 +1,7 @@ import { chmod, mkdir, rm, writeFile } from 'node:fs/promises' import { join } from 'node:path' import { afterEach, beforeEach, expect, it } from 'vitest' -import { resetTranscriptConsumersForTests } from '../ai-vault/session-transcript-consumers' +import { resetTranscriptConsumersForTests } from '../ai-vault/transcripts/session-transcript-consumers' import { retireDeletedSessionSearchSources } from './session-search-deleted-sources' import { SessionSearchDirectoryListings, diff --git a/src/main/ai-vault-search/session-search-dependent-transcripts.test.ts b/src/main/ai-vault-search/session-search-dependent-transcripts.test.ts index daf8b38877a..abdf31707bc 100644 --- a/src/main/ai-vault-search/session-search-dependent-transcripts.test.ts +++ b/src/main/ai-vault-search/session-search-dependent-transcripts.test.ts @@ -1,13 +1,11 @@ import { mkdir, stat, unlink, writeFile } from 'node:fs/promises' import { dirname, join } from 'node:path' import { afterEach, beforeEach, expect, it } from 'vitest' -import { - parseAgentSessionFileCached, - resetSessionParseCacheForTests -} from '../ai-vault/session-scanner-parse-cache' -import { resetCodexSessionIndexTitleCacheForTests } from '../ai-vault/session-scanner-codex-title-index' +import { parseAgentSessionFileCached } from '../ai-vault/parse-cache/session-scanner-parse-cache' +import { resetSessionParseCacheForTests } from '../ai-vault/parse-cache/session-parse-cache-store' +import { resetCodexSessionIndexTitleCacheForTests } from '../ai-vault/scanners/codex/session-scanner-codex-title-index' import type { SessionFileCandidate } from '../ai-vault/session-scanner-types' -import { resetTranscriptConsumersForTests } from '../ai-vault/session-transcript-consumers' +import { resetTranscriptConsumersForTests } from '../ai-vault/transcripts/session-transcript-consumers' import { registerSessionSearchIndexConsumer } from './session-search-index-consumer' import { openSessionSearchIndexFile, diff --git a/src/main/ai-vault-search/session-search-enablement.ts b/src/main/ai-vault-search/session-search-enablement.ts index 8f0edb48f4b..acd9a75d3fa 100644 --- a/src/main/ai-vault-search/session-search-enablement.ts +++ b/src/main/ai-vault-search/session-search-enablement.ts @@ -1,6 +1,6 @@ import { changedAiVaultSearchSettings } from '../../shared/ai-vault-search-settings' import type { GlobalSettings } from '../../shared/global-settings-types' -import { updateSessionSearchInService } from '../ai-vault/session-scanner-service-spawn' +import { updateSessionSearchInService } from '../ai-vault/scan-service/session-scanner-service-spawn' import { createChildSessionSearchService } from './session-search-child-service' import { installSessionSearchPolicySource } from './session-search-policy' import { diff --git a/src/main/ai-vault-search/session-search-engine-test-fixture.ts b/src/main/ai-vault-search/session-search-engine-test-fixture.ts index adaabc107e0..e109989bffc 100644 --- a/src/main/ai-vault-search/session-search-engine-test-fixture.ts +++ b/src/main/ai-vault-search/session-search-engine-test-fixture.ts @@ -1,4 +1,4 @@ -import type { TranscriptMessageRole } from '../ai-vault/session-transcript-consumers' +import type { TranscriptMessageRole } from '../ai-vault/transcripts/session-transcript-consumers' import type SyncDatabase from '../sqlite/sync-database' import { SessionSearchEngine, type SessionSearchEngineOptions } from './session-search-engine' import { cwdKey } from './session-search-file-records' diff --git a/src/main/ai-vault-search/session-search-engine-types.ts b/src/main/ai-vault-search/session-search-engine-types.ts index 308a211d4e2..982ee996d95 100644 --- a/src/main/ai-vault-search/session-search-engine-types.ts +++ b/src/main/ai-vault-search/session-search-engine-types.ts @@ -1,5 +1,5 @@ import type { AiVaultAgent } from '../../shared/ai-vault-types' -import type { TranscriptMessageRole } from '../ai-vault/session-transcript-consumers' +import type { TranscriptMessageRole } from '../ai-vault/transcripts/session-transcript-consumers' export { SESSION_SEARCH_LIMIT_DEFAULT, diff --git a/src/main/ai-vault-search/session-search-engine.ts b/src/main/ai-vault-search/session-search-engine.ts index e64948a6698..a6b1790f2f8 100644 --- a/src/main/ai-vault-search/session-search-engine.ts +++ b/src/main/ai-vault-search/session-search-engine.ts @@ -1,5 +1,5 @@ import type SyncDatabase from '../sqlite/sync-database' -import type { TranscriptMessageRole } from '../ai-vault/session-transcript-consumers' +import type { TranscriptMessageRole } from '../ai-vault/transcripts/session-transcript-consumers' import { sliceAtCodeUnitLimit } from '../ai-vault/session-scanner-text-normalization' import { hasAiVaultSearchQueryOperators, diff --git a/src/main/ai-vault-search/session-search-file-records.ts b/src/main/ai-vault-search/session-search-file-records.ts index a6f97983554..1479d68cdb4 100644 --- a/src/main/ai-vault-search/session-search-file-records.ts +++ b/src/main/ai-vault-search/session-search-file-records.ts @@ -1,6 +1,6 @@ import { fileIdentity } from './session-search-file-cursor' import type { AiVaultSession } from '../../shared/ai-vault-types' -import type { TranscriptSessionIdentity } from '../ai-vault/session-transcript-consumers' +import type { TranscriptSessionIdentity } from '../ai-vault/transcripts/session-transcript-consumers' import type { SessionFileCandidate } from '../ai-vault/session-scanner-types' import type SyncDatabase from '../sqlite/sync-database' import { EMPTY_CONTENT_HASH, type SessionContentHash } from './session-search-content-hash' diff --git a/src/main/ai-vault-search/session-search-file-write.test.ts b/src/main/ai-vault-search/session-search-file-write.test.ts index fa62e914447..0e8acffa48a 100644 --- a/src/main/ai-vault-search/session-search-file-write.test.ts +++ b/src/main/ai-vault-search/session-search-file-write.test.ts @@ -1,5 +1,5 @@ import { afterEach, beforeEach, expect, it, vi } from 'vitest' -import { resetTranscriptConsumersForTests } from '../ai-vault/session-transcript-consumers' +import { resetTranscriptConsumersForTests } from '../ai-vault/transcripts/session-transcript-consumers' import SyncDatabase from '../sqlite/sync-database' import { registerSessionSearchIndexConsumer } from './session-search-index-consumer' import { cwdKey } from './session-search-file-records' diff --git a/src/main/ai-vault-search/session-search-host-registration.test.ts b/src/main/ai-vault-search/session-search-host-registration.test.ts index 62ff1639753..474262f9645 100644 --- a/src/main/ai-vault-search/session-search-host-registration.test.ts +++ b/src/main/ai-vault-search/session-search-host-registration.test.ts @@ -1,7 +1,7 @@ import { join } from 'node:path' import { afterEach, beforeEach, expect, it, vi } from 'vitest' -import { resetSessionParseCacheForTests } from '../ai-vault/session-scanner-parse-cache' -import { resetTranscriptConsumersForTests } from '../ai-vault/session-transcript-consumers' +import { resetSessionParseCacheForTests } from '../ai-vault/parse-cache/session-parse-cache-store' +import { resetTranscriptConsumersForTests } from '../ai-vault/transcripts/session-transcript-consumers' import type { AiVaultSearchSettings } from '../../shared/ai-vault-search-settings' import { installInProcessSessionSearchService } from './session-search-in-process-service' import { @@ -14,7 +14,7 @@ import { resetSessionSearchPolicyForTests } from './session-search-policy' import { resetSessionSearchServiceInitForTests } from './session-search-service-init' const updateSessionSearchInService = vi.hoisted(() => vi.fn()) -vi.mock('../ai-vault/session-scanner-service-spawn', async (importOriginal) => ({ +vi.mock('../ai-vault/scan-service/session-scanner-service-spawn', async (importOriginal) => ({ ...(await importOriginal()), updateSessionSearchInService })) diff --git a/src/main/ai-vault-search/session-search-index-consumer.test.ts b/src/main/ai-vault-search/session-search-index-consumer.test.ts index d808b9ef926..2b835af9533 100644 --- a/src/main/ai-vault-search/session-search-index-consumer.test.ts +++ b/src/main/ai-vault-search/session-search-index-consumer.test.ts @@ -1,5 +1,5 @@ import { afterEach, beforeEach, expect, it } from 'vitest' -import { resetTranscriptConsumersForTests } from '../ai-vault/session-transcript-consumers' +import { resetTranscriptConsumersForTests } from '../ai-vault/transcripts/session-transcript-consumers' import { registerSessionSearchIndexConsumer } from './session-search-index-consumer' import { openSessionSearchIndexFile, diff --git a/src/main/ai-vault-search/session-search-index-consumer.ts b/src/main/ai-vault-search/session-search-index-consumer.ts index d09217a3f08..6971a2cc1ff 100644 --- a/src/main/ai-vault-search/session-search-index-consumer.ts +++ b/src/main/ai-vault-search/session-search-index-consumer.ts @@ -6,7 +6,7 @@ import { type TranscriptReadConsumer, type TranscriptReadOutcome, type TranscriptReadStart -} from '../ai-vault/session-transcript-consumers' +} from '../ai-vault/transcripts/session-transcript-consumers' import type { SessionFileCandidate } from '../ai-vault/session-scanner-types' import { fileIdentity } from './session-search-file-cursor' import type { SessionSearchFileWrite } from './session-search-index-writer' diff --git a/src/main/ai-vault-search/session-search-index-generation.test.ts b/src/main/ai-vault-search/session-search-index-generation.test.ts index f5747ef4ba7..93be80b27e7 100644 --- a/src/main/ai-vault-search/session-search-index-generation.test.ts +++ b/src/main/ai-vault-search/session-search-index-generation.test.ts @@ -7,8 +7,8 @@ import type SyncDatabase from '../sqlite/sync-database' import { SessionSearchEngine } from './session-search-engine' import { readIndexGeneration, readIndexIncarnation } from './session-search-index-generation' import { registerSessionSearchIndexConsumer } from './session-search-index-consumer' -import { resetSessionParseCacheForTests } from '../ai-vault/session-scanner-parse-cache' -import { resetTranscriptConsumersForTests } from '../ai-vault/session-transcript-consumers' +import { resetSessionParseCacheForTests } from '../ai-vault/parse-cache/session-parse-cache-store' +import { resetTranscriptConsumersForTests } from '../ai-vault/transcripts/session-transcript-consumers' import type { SessionSearchCursorError } from './session-search-page-cursor' import { openSessionSearchDatabase } from './session-search-schema' import { SessionSearchStore } from './session-search-store' diff --git a/src/main/ai-vault-search/session-search-index-pass.test.ts b/src/main/ai-vault-search/session-search-index-pass.test.ts index e6ca2546bc0..a7124027cca 100644 --- a/src/main/ai-vault-search/session-search-index-pass.test.ts +++ b/src/main/ai-vault-search/session-search-index-pass.test.ts @@ -2,11 +2,11 @@ import { appendFile, rm, stat, utimes } from 'node:fs/promises' import { join } from 'node:path' import { afterEach, beforeEach, expect, it } from 'vitest' import { isAiVaultScanCancelledError } from '../../shared/ai-vault-types' -import { resetSessionParseCacheForTests } from '../ai-vault/session-scanner-parse-cache' +import { resetSessionParseCacheForTests } from '../ai-vault/parse-cache/session-parse-cache-store' import { registerTranscriptConsumer, resetTranscriptConsumersForTests -} from '../ai-vault/session-transcript-consumers' +} from '../ai-vault/transcripts/session-transcript-consumers' import { registerSessionSearchIndexConsumer } from './session-search-index-consumer' import { runSessionSearchIndexPass } from './session-search-index-pass' import { parseTranscript } from './session-search-transcript-fixtures' diff --git a/src/main/ai-vault-search/session-search-index-pass.ts b/src/main/ai-vault-search/session-search-index-pass.ts index c0c9689a32e..5ba71a668ca 100644 --- a/src/main/ai-vault-search/session-search-index-pass.ts +++ b/src/main/ai-vault-search/session-search-index-pass.ts @@ -3,7 +3,7 @@ import { createSessionParseStats, parseAgentSessionFileCached, type SessionParseStats -} from '../ai-vault/session-scanner-parse-cache' +} from '../ai-vault/parse-cache/session-scanner-parse-cache' import type { SessionFileCandidate } from '../ai-vault/session-scanner-types' import { fileIdentity } from './session-search-file-cursor' import { sessionSearchReadDecision } from './session-search-read-decision' diff --git a/src/main/ai-vault-search/session-search-index-test-fixture.ts b/src/main/ai-vault-search/session-search-index-test-fixture.ts index e34c95f7cc9..212edc9ea86 100644 --- a/src/main/ai-vault-search/session-search-index-test-fixture.ts +++ b/src/main/ai-vault-search/session-search-index-test-fixture.ts @@ -4,12 +4,12 @@ import { join } from 'node:path' import { removeTree } from '../../shared/windows-transient-lock-removal' import type { AiVaultSession } from '../../shared/ai-vault-types' import type { SessionFileCandidate } from '../ai-vault/session-scanner-types' -import { TranscriptMessageChannel } from '../ai-vault/session-transcript-channel' +import { TranscriptMessageChannel } from '../ai-vault/transcripts/session-transcript-channel' import type { TranscriptMessage, TranscriptReadOutcome, TranscriptReadStart -} from '../ai-vault/session-transcript-consumers' +} from '../ai-vault/transcripts/session-transcript-consumers' import type SyncDatabase from '../sqlite/sync-database' import { openSessionSearchDatabase } from './session-search-schema' diff --git a/src/main/ai-vault-search/session-search-index-writer.ts b/src/main/ai-vault-search/session-search-index-writer.ts index 257332b239f..cc2ef85cea1 100644 --- a/src/main/ai-vault-search/session-search-index-writer.ts +++ b/src/main/ai-vault-search/session-search-index-writer.ts @@ -4,7 +4,7 @@ import type { TranscriptMessage, TranscriptReadOutcome, TranscriptSessionIdentity -} from '../ai-vault/session-transcript-consumers' +} from '../ai-vault/transcripts/session-transcript-consumers' import { SessionSearchWriteBuffer } from './session-search-write-buffer' import { EMPTY_CONTENT_HASH, foldContentHash } from './session-search-content-hash' import type { diff --git a/src/main/ai-vault-search/session-search-indexer.test.ts b/src/main/ai-vault-search/session-search-indexer.test.ts index c051a0803f6..a9876a1d7e9 100644 --- a/src/main/ai-vault-search/session-search-indexer.test.ts +++ b/src/main/ai-vault-search/session-search-indexer.test.ts @@ -2,8 +2,8 @@ import { existsSync, mkdirSync, rmSync, utimesSync, writeFileSync } from 'node:f import { appendFile, chmod, mkdir, rm, stat, utimes } from 'node:fs/promises' import { dirname, join } from 'node:path' import { afterEach, beforeEach, expect, it } from 'vitest' -import { resetSessionParseCacheForTests } from '../ai-vault/session-scanner-parse-cache' -import { resetTranscriptConsumersForTests } from '../ai-vault/session-transcript-consumers' +import { resetSessionParseCacheForTests } from '../ai-vault/parse-cache/session-parse-cache-store' +import { resetTranscriptConsumersForTests } from '../ai-vault/transcripts/session-transcript-consumers' import type SyncDatabase from '../sqlite/sync-database' import { SessionSearchIndexer } from './session-search-indexer' import { removeSessionSearchDatabase } from './session-search-schema' diff --git a/src/main/ai-vault-search/session-search-instance.test.ts b/src/main/ai-vault-search/session-search-instance.test.ts index aed4d3dfdfe..1af5bb1e915 100644 --- a/src/main/ai-vault-search/session-search-instance.test.ts +++ b/src/main/ai-vault-search/session-search-instance.test.ts @@ -2,8 +2,8 @@ import { existsSync } from 'node:fs' import { utimes } from 'node:fs/promises' import { join } from 'node:path' import { afterEach, beforeEach, expect, it, vi } from 'vitest' -import { resetSessionParseCacheForTests } from '../ai-vault/session-scanner-parse-cache' -import { resetTranscriptConsumersForTests } from '../ai-vault/session-transcript-consumers' +import { resetSessionParseCacheForTests } from '../ai-vault/parse-cache/session-parse-cache-store' +import { resetTranscriptConsumersForTests } from '../ai-vault/transcripts/session-transcript-consumers' import { SessionSearchInstance } from './session-search-instance' import { openSessionSearchIndexerHarness, diff --git a/src/main/ai-vault-search/session-search-lifecycle-matrix.test.ts b/src/main/ai-vault-search/session-search-lifecycle-matrix.test.ts index 4b618f8adf2..a9e8cdb3900 100644 --- a/src/main/ai-vault-search/session-search-lifecycle-matrix.test.ts +++ b/src/main/ai-vault-search/session-search-lifecycle-matrix.test.ts @@ -1,8 +1,8 @@ import { chmod, mkdir, rename, rm } from 'node:fs/promises' import { delimiter, dirname, join } from 'node:path' import { afterEach, beforeEach, describe, expect, it } from 'vitest' -import { resetSessionParseCacheForTests } from '../ai-vault/session-scanner-parse-cache' -import { resetTranscriptConsumersForTests } from '../ai-vault/session-transcript-consumers' +import { resetSessionParseCacheForTests } from '../ai-vault/parse-cache/session-parse-cache-store' +import { resetTranscriptConsumersForTests } from '../ai-vault/transcripts/session-transcript-consumers' import type SyncDatabase from '../sqlite/sync-database' import { SessionSearchIndexer } from './session-search-indexer' import type { SessionSearchIndexerOptions } from './session-search-indexer-options' diff --git a/src/main/ai-vault-search/session-search-list-reparse.test.ts b/src/main/ai-vault-search/session-search-list-reparse.test.ts index 89180d444e7..a2ae6384da0 100644 --- a/src/main/ai-vault-search/session-search-list-reparse.test.ts +++ b/src/main/ai-vault-search/session-search-list-reparse.test.ts @@ -1,5 +1,5 @@ import { afterEach, beforeEach, expect, it } from 'vitest' -import { resetTranscriptConsumersForTests } from '../ai-vault/session-transcript-consumers' +import { resetTranscriptConsumersForTests } from '../ai-vault/transcripts/session-transcript-consumers' import { registerSessionSearchIndexConsumer } from './session-search-index-consumer' import { openSessionSearchIndexFile, diff --git a/src/main/ai-vault-search/session-search-live-transcript.test.ts b/src/main/ai-vault-search/session-search-live-transcript.test.ts index d620ca4e4f6..5d28c0b0ee3 100644 --- a/src/main/ai-vault-search/session-search-live-transcript.test.ts +++ b/src/main/ai-vault-search/session-search-live-transcript.test.ts @@ -2,13 +2,13 @@ import { mkdtemp, rm, writeFile, appendFile } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, beforeEach, expect, it } from 'vitest' -import { resetSessionParseCacheForTests } from '../ai-vault/session-scanner-parse-cache' +import { resetSessionParseCacheForTests } from '../ai-vault/parse-cache/session-parse-cache-store' import { registerTranscriptConsumer, resetTranscriptConsumersForTests, type TranscriptSessionIdentity -} from '../ai-vault/session-transcript-consumers' -import { requestWholeTranscriptRead } from '../ai-vault/session-transcript-reader' +} from '../ai-vault/transcripts/session-transcript-consumers' +import { requestWholeTranscriptRead } from '../ai-vault/transcripts/session-transcript-reader' import SyncDatabase from '../sqlite/sync-database' import { registerSessionSearchIndexConsumer } from './session-search-index-consumer' import { SessionSearchStore } from './session-search-store' diff --git a/src/main/ai-vault-search/session-search-merged-roots.test.ts b/src/main/ai-vault-search/session-search-merged-roots.test.ts index 53b15f27e81..242a475f7d5 100644 --- a/src/main/ai-vault-search/session-search-merged-roots.test.ts +++ b/src/main/ai-vault-search/session-search-merged-roots.test.ts @@ -1,8 +1,8 @@ import { chmod, rm } from 'node:fs/promises' import { delimiter, join } from 'node:path' import { afterEach, beforeEach, expect, it } from 'vitest' -import { resetSessionParseCacheForTests } from '../ai-vault/session-scanner-parse-cache' -import { resetTranscriptConsumersForTests } from '../ai-vault/session-transcript-consumers' +import { resetSessionParseCacheForTests } from '../ai-vault/parse-cache/session-parse-cache-store' +import { resetTranscriptConsumersForTests } from '../ai-vault/transcripts/session-transcript-consumers' import type SyncDatabase from '../sqlite/sync-database' import { SessionSearchIndexer } from './session-search-indexer' import { diff --git a/src/main/ai-vault-search/session-search-message-rows.test.ts b/src/main/ai-vault-search/session-search-message-rows.test.ts index 38f3ca5057f..86b2f5baa5c 100644 --- a/src/main/ai-vault-search/session-search-message-rows.test.ts +++ b/src/main/ai-vault-search/session-search-message-rows.test.ts @@ -1,5 +1,5 @@ import { expect, it } from 'vitest' -import type { TranscriptMessage } from '../ai-vault/session-transcript-consumers' +import type { TranscriptMessage } from '../ai-vault/transcripts/session-transcript-consumers' import { insertSearchMessage, searchMessageRows } from './session-search-message-rows' import { openSessionSearchIndexFile, diff --git a/src/main/ai-vault-search/session-search-message-rows.ts b/src/main/ai-vault-search/session-search-message-rows.ts index 26d1484cb47..d497bdd7a35 100644 --- a/src/main/ai-vault-search/session-search-message-rows.ts +++ b/src/main/ai-vault-search/session-search-message-rows.ts @@ -1,5 +1,5 @@ import type SyncDatabase from '../sqlite/sync-database' -import type { TranscriptMessage } from '../ai-vault/session-transcript-consumers' +import type { TranscriptMessage } from '../ai-vault/transcripts/session-transcript-consumers' import { sliceAtCodeUnitLimit } from '../ai-vault/session-scanner-text-normalization' import { identifierShadowText } from './session-search-identifier-split' diff --git a/src/main/ai-vault-search/session-search-native-chat-indexing.test.ts b/src/main/ai-vault-search/session-search-native-chat-indexing.test.ts index 60e43492e58..8b4248015c7 100644 --- a/src/main/ai-vault-search/session-search-native-chat-indexing.test.ts +++ b/src/main/ai-vault-search/session-search-native-chat-indexing.test.ts @@ -1,8 +1,8 @@ import { appendFile, mkdir, writeFile } from 'node:fs/promises' import { join } from 'node:path' import { afterEach, beforeEach, expect, it } from 'vitest' -import { resetSessionParseCacheForTests } from '../ai-vault/session-scanner-parse-cache' -import { resetTranscriptConsumersForTests } from '../ai-vault/session-transcript-consumers' +import { resetSessionParseCacheForTests } from '../ai-vault/parse-cache/session-parse-cache-store' +import { resetTranscriptConsumersForTests } from '../ai-vault/transcripts/session-transcript-consumers' import type SyncDatabase from '../sqlite/sync-database' import { SessionSearchIndexer } from './session-search-indexer' import { diff --git a/src/main/ai-vault-search/session-search-opencode-index.test.ts b/src/main/ai-vault-search/session-search-opencode-index.test.ts index 969fe6b86bb..36a1eae9b01 100644 --- a/src/main/ai-vault-search/session-search-opencode-index.test.ts +++ b/src/main/ai-vault-search/session-search-opencode-index.test.ts @@ -3,40 +3,46 @@ import { afterEach, beforeEach, expect, it, vi } from 'vitest' // Replace worker transport while exercising the real SQLite readers. export const openCodeReadCalls: string[] = [] -vi.mock('../ai-vault/session-scanner-opencode-sqlite-worker-spawn', async () => { - const list = await import('../ai-vault/session-scanner-opencode-sqlite-list') - const parse = await import('../ai-vault/session-scanner-opencode-sqlite') - const capture = await import('../ai-vault/session-scanner-opencode-sqlite-capture') - const own = await import('./session-search-opencode-index.test') - const { listOpenCode2SqliteSessions } = - await import('../ai-vault/session-scanner-opencode2-sqlite-list') - return { - listOpenCode2SqliteSessionsViaWorker: listOpenCode2SqliteSessions, - resolveOpenCodeSqliteWorkerEntryPath: () => null, - listOpenCodeSqliteSessionsViaWorker: ( - args: Parameters[0] - ) => list.listOpenCodeSqliteSessions(args), - parseOpenCodeSqliteSessionViaWorker: ( - args: Parameters[0] - ) => { - own.openCodeReadCalls.push(`parse:${args.sessionId}`) - return parse.parseOpenCodeSqliteSession(args) - }, - captureOpenCodeSqliteSessionViaWorker: ( - args: Parameters[0] - ) => { - own.openCodeReadCalls.push(`capture:${args.sessionId}`) - return capture.captureOpenCodeSqliteSession(args) +vi.mock( + '../ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-worker-spawn', + async () => { + const list = + await import('../ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-list') + const parse = + await import('../ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite') + const capture = + await import('../ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-capture') + const own = await import('./session-search-opencode-index.test') + const { listOpenCode2SqliteSessions } = + await import('../ai-vault/scanners/opencode2/session-scanner-opencode2-sqlite-list') + return { + listOpenCode2SqliteSessionsViaWorker: listOpenCode2SqliteSessions, + resolveOpenCodeSqliteWorkerEntryPath: () => null, + listOpenCodeSqliteSessionsViaWorker: ( + args: Parameters[0] + ) => list.listOpenCodeSqliteSessions(args), + parseOpenCodeSqliteSessionViaWorker: ( + args: Parameters[0] + ) => { + own.openCodeReadCalls.push(`parse:${args.sessionId}`) + return parse.parseOpenCodeSqliteSession(args) + }, + captureOpenCodeSqliteSessionViaWorker: ( + args: Parameters[0] + ) => { + own.openCodeReadCalls.push(`capture:${args.sessionId}`) + return capture.captureOpenCodeSqliteSession(args) + } } } -}) -import { resetSessionParseCacheForTests } from '../ai-vault/session-scanner-parse-cache' -import { resetTranscriptConsumersForTests } from '../ai-vault/session-transcript-consumers' -import { buildOpenCodeSqliteCandidatePath } from '../ai-vault/session-scanner-opencode-sqlite-paths' +) +import { resetSessionParseCacheForTests } from '../ai-vault/parse-cache/session-parse-cache-store' +import { resetTranscriptConsumersForTests } from '../ai-vault/transcripts/session-transcript-consumers' +import { buildOpenCodeSqliteCandidatePath } from '../../shared/opencode-sqlite-session-path' import { appendOpenCodeSqliteTurn, writeOpenCodeSqliteDatabase -} from '../ai-vault/session-scanner-opencode-sqlite-fixture' +} from '../ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-fixture' import type SyncDatabase from '../sqlite/sync-database' import { SessionSearchEngine } from './session-search-engine' import { SessionSearchIndexer } from './session-search-indexer' diff --git a/src/main/ai-vault-search/session-search-pass.ts b/src/main/ai-vault-search/session-search-pass.ts index a4e08269d49..ae53e685cbd 100644 --- a/src/main/ai-vault-search/session-search-pass.ts +++ b/src/main/ai-vault-search/session-search-pass.ts @@ -2,7 +2,7 @@ import type { AiVaultScanIssue } from '../../shared/ai-vault-types' import { cursorChatMetaRefusals, withCursorChatMetaScan -} from '../ai-vault/session-scanner-cursor-chat-meta' +} from '../ai-vault/scanners/cursor/session-scanner-cursor-chat-meta' import { recordSessionScanIssue } from '../ai-vault/session-scan-issues' import { mergeDegradedRoots, diff --git a/src/main/ai-vault-search/session-search-read-decision.ts b/src/main/ai-vault-search/session-search-read-decision.ts index f902c1391ad..f4c8b76f79d 100644 --- a/src/main/ai-vault-search/session-search-read-decision.ts +++ b/src/main/ai-vault-search/session-search-read-decision.ts @@ -1,5 +1,5 @@ import type { SessionFileCandidate } from '../ai-vault/session-scanner-types' -import type { SessionParseReadRequirement } from '../ai-vault/session-scanner-parse-cache' +import type { SessionParseReadRequirement } from '../ai-vault/parse-cache/session-scanner-parse-cache' import { requiresWholeRead, type SessionSearchIndexedFile } from './session-search-file-cursor' import type { SessionSearchFileRow } from './session-search-store' diff --git a/src/main/ai-vault-search/session-search-restart-reindex.test.ts b/src/main/ai-vault-search/session-search-restart-reindex.test.ts index ae5325066e4..82399d9540c 100644 --- a/src/main/ai-vault-search/session-search-restart-reindex.test.ts +++ b/src/main/ai-vault-search/session-search-restart-reindex.test.ts @@ -1,9 +1,9 @@ import { appendFile, chmod, mkdir, stat, writeFile } from 'node:fs/promises' import { dirname, join } from 'node:path' import { afterEach, beforeEach, expect, it } from 'vitest' -import { resetSessionParseCacheForTests } from '../ai-vault/session-scanner-parse-cache' +import { resetSessionParseCacheForTests } from '../ai-vault/parse-cache/session-parse-cache-store' import { asRecord } from '../ai-vault/session-scanner-record-value' -import { resetTranscriptConsumersForTests } from '../ai-vault/session-transcript-consumers' +import { resetTranscriptConsumersForTests } from '../ai-vault/transcripts/session-transcript-consumers' import type SyncDatabase from '../sqlite/sync-database' import { SessionSearchIndexer } from './session-search-indexer' import { diff --git a/src/main/ai-vault-search/session-search-root-refresh.test.ts b/src/main/ai-vault-search/session-search-root-refresh.test.ts index 43d57e19536..29db33f8747 100644 --- a/src/main/ai-vault-search/session-search-root-refresh.test.ts +++ b/src/main/ai-vault-search/session-search-root-refresh.test.ts @@ -7,8 +7,8 @@ import { writeClaudeTranscript, type SessionSearchIndexerHarness } from './session-search-indexer-test-fixture' -import { resetSessionParseCacheForTests } from '../ai-vault/session-scanner-parse-cache' -import { resetTranscriptConsumersForTests } from '../ai-vault/session-transcript-consumers' +import { resetSessionParseCacheForTests } from '../ai-vault/parse-cache/session-parse-cache-store' +import { resetTranscriptConsumersForTests } from '../ai-vault/transcripts/session-transcript-consumers' let harness: SessionSearchIndexerHarness let indexer: SessionSearchIndexer | undefined diff --git a/src/main/ai-vault-search/session-search-service-init.ts b/src/main/ai-vault-search/session-search-service-init.ts index 8d472036a1f..a3de3108cd3 100644 --- a/src/main/ai-vault-search/session-search-service-init.ts +++ b/src/main/ai-vault-search/session-search-service-init.ts @@ -1,5 +1,5 @@ import { LOCAL_EXECUTION_HOST_ID } from '../../shared/execution-host' -import type { AiVaultSessionSearchInit } from '../ai-vault/session-scanner-service-protocol' +import type { AiVaultSessionSearchInit } from '../ai-vault/scan-service/session-scanner-service-protocol' import { sessionSearchDatabasePath } from './session-search-database-path' import { sessionSearchPolicy } from './session-search-policy' diff --git a/src/main/ai-vault-search/session-search-store-is-memory.test.ts b/src/main/ai-vault-search/session-search-store-is-memory.test.ts index 7def91a1b54..426a8c0646d 100644 --- a/src/main/ai-vault-search/session-search-store-is-memory.test.ts +++ b/src/main/ai-vault-search/session-search-store-is-memory.test.ts @@ -1,8 +1,8 @@ import { chmod, rm, utimes } from 'node:fs/promises' import { join } from 'node:path' import { afterEach, beforeEach, expect, it } from 'vitest' -import { resetSessionParseCacheForTests } from '../ai-vault/session-scanner-parse-cache' -import { resetTranscriptConsumersForTests } from '../ai-vault/session-transcript-consumers' +import { resetSessionParseCacheForTests } from '../ai-vault/parse-cache/session-parse-cache-store' +import { resetTranscriptConsumersForTests } from '../ai-vault/transcripts/session-transcript-consumers' import type SyncDatabase from '../sqlite/sync-database' import { SessionSearchIndexer } from './session-search-indexer' import { diff --git a/src/main/ai-vault-search/session-search-store.ts b/src/main/ai-vault-search/session-search-store.ts index 1b4419b1322..0ce14166df1 100644 --- a/src/main/ai-vault-search/session-search-store.ts +++ b/src/main/ai-vault-search/session-search-store.ts @@ -1,7 +1,7 @@ import type SyncDatabase from '../sqlite/sync-database' import { asRecord } from '../ai-vault/session-scanner-record-value' import type { SessionFileCandidate } from '../ai-vault/session-scanner-types' -import type { TranscriptSessionIdentity } from '../ai-vault/session-transcript-consumers' +import type { TranscriptSessionIdentity } from '../ai-vault/transcripts/session-transcript-consumers' import { fileIdentity, type SessionSearchFileIdentity, diff --git a/src/main/ai-vault-search/session-search-synthetic-corpus.test.ts b/src/main/ai-vault-search/session-search-synthetic-corpus.test.ts index 9b6a48beb4e..c75fcb97196 100644 --- a/src/main/ai-vault-search/session-search-synthetic-corpus.test.ts +++ b/src/main/ai-vault-search/session-search-synthetic-corpus.test.ts @@ -1,8 +1,8 @@ import { rm } from 'node:fs/promises' import { join } from 'node:path' import { expect, it } from 'vitest' -import { resetSessionParseCacheForTests } from '../ai-vault/session-scanner-parse-cache' -import { resetTranscriptConsumersForTests } from '../ai-vault/session-transcript-consumers' +import { resetSessionParseCacheForTests } from '../ai-vault/parse-cache/session-parse-cache-store' +import { resetTranscriptConsumersForTests } from '../ai-vault/transcripts/session-transcript-consumers' import { registerSessionSearchIndexConsumer } from './session-search-index-consumer' import { SessionSearchStore } from './session-search-store' import { writeSyntheticTranscriptCorpus } from './session-search-synthetic-corpus' diff --git a/src/main/ai-vault-search/session-search-synthetic-sources.ts b/src/main/ai-vault-search/session-search-synthetic-sources.ts index 83ca37f07f0..5888e8aa0b9 100644 --- a/src/main/ai-vault-search/session-search-synthetic-sources.ts +++ b/src/main/ai-vault-search/session-search-synthetic-sources.ts @@ -1,5 +1,5 @@ import type { AiVaultScanIssue } from '../../shared/ai-vault-types' -import { splitOpenCodeSqliteCandidate } from '../ai-vault/session-scanner-opencode-sqlite-paths' +import { splitOpenCodeSqliteCandidate } from '../../shared/opencode-sqlite-session-path' import type { SessionFileCandidate } from '../ai-vault/session-scanner-types' /** A session inside a shared container rather than a standalone transcript file. */ diff --git a/src/main/ai-vault-search/session-search-transcript-dependencies.test.ts b/src/main/ai-vault-search/session-search-transcript-dependencies.test.ts index 7544390583d..889b39d4213 100644 --- a/src/main/ai-vault-search/session-search-transcript-dependencies.test.ts +++ b/src/main/ai-vault-search/session-search-transcript-dependencies.test.ts @@ -13,15 +13,13 @@ import { type EveryAgentVault } from '../ai-vault/session-scanner-every-agent-fixture' import { geminiJsonlFixture } from '../ai-vault/session-scanner-incremental-fixtures' -import { - parseAgentSessionFileCached, - resetSessionParseCacheForTests -} from '../ai-vault/session-scanner-parse-cache' +import { parseAgentSessionFileCached } from '../ai-vault/parse-cache/session-scanner-parse-cache' +import { resetSessionParseCacheForTests } from '../ai-vault/parse-cache/session-parse-cache-store' import { registerTranscriptConsumer, resetTranscriptConsumersForTests, type TranscriptMessage -} from '../ai-vault/session-transcript-consumers' +} from '../ai-vault/transcripts/session-transcript-consumers' import { SELF_CONTAINED_TRANSCRIPT_AGENTS } from './session-search-index-consumer' vi.mock('node:fs', async (importOriginal) => { diff --git a/src/main/ai-vault-search/session-search-transcript-fixtures.ts b/src/main/ai-vault-search/session-search-transcript-fixtures.ts index 8d27587d858..b8bf2968658 100644 --- a/src/main/ai-vault-search/session-search-transcript-fixtures.ts +++ b/src/main/ai-vault-search/session-search-transcript-fixtures.ts @@ -3,7 +3,7 @@ import { createSessionParseStats, parseAgentSessionFileCached, type SessionParseStats -} from '../ai-vault/session-scanner-parse-cache' +} from '../ai-vault/parse-cache/session-scanner-parse-cache' import type { SessionFileCandidate } from '../ai-vault/session-scanner-types' export const CLAUDE_SESSION_ID = 'aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee' diff --git a/src/main/ai-vault-search/session-search-write-buffer.ts b/src/main/ai-vault-search/session-search-write-buffer.ts index 8faedac7f73..a8b7e519d9b 100644 --- a/src/main/ai-vault-search/session-search-write-buffer.ts +++ b/src/main/ai-vault-search/session-search-write-buffer.ts @@ -1,5 +1,5 @@ import SyncDatabase from '../sqlite/sync-database' -import type { TranscriptMessage } from '../ai-vault/session-transcript-consumers' +import type { TranscriptMessage } from '../ai-vault/transcripts/session-transcript-consumers' import { ownRetainedString } from '../../shared/own-retained-string' /** Anonymous reads stay private until commit; large reads spill to a disposable SQLite file. */ diff --git a/src/main/ai-vault-search/session-search-write-lifetime.test.ts b/src/main/ai-vault-search/session-search-write-lifetime.test.ts index ef0007b58ce..5c9edc3d096 100644 --- a/src/main/ai-vault-search/session-search-write-lifetime.test.ts +++ b/src/main/ai-vault-search/session-search-write-lifetime.test.ts @@ -1,6 +1,6 @@ import { afterEach, beforeEach, expect, it, vi } from 'vitest' import { join } from 'node:path' -import { TranscriptMessageChannel } from '../ai-vault/session-transcript-channel' +import { TranscriptMessageChannel } from '../ai-vault/transcripts/session-transcript-channel' import { registerSessionSearchIndexConsumer } from './session-search-index-consumer' import { SessionSearchIndexWriter } from './session-search-index-writer' import { diff --git a/src/main/ai-vault/ai-vault-local-scan-progress.ts b/src/main/ai-vault/ai-vault-local-scan-progress.ts index 87d96f4b3de..8746114d463 100644 --- a/src/main/ai-vault/ai-vault-local-scan-progress.ts +++ b/src/main/ai-vault/ai-vault-local-scan-progress.ts @@ -3,7 +3,7 @@ import type { AiVaultScanProgressUpdate, AiVaultScanWork } from '../../shared/ai-vault-scan-progress' -import type { AiVaultServiceScanListener } from './session-scanner-service-request-deadline' +import type { AiVaultServiceScanListener } from './scan-service/session-scanner-service-request-deadline' type Listener = (update: AiVaultScanProgressUpdate) => void diff --git a/src/main/ai-vault/ai-vault-scan-progress-flow.test.ts b/src/main/ai-vault/ai-vault-scan-progress-flow.test.ts index 49ae366aed8..b37bd2eb44b 100644 --- a/src/main/ai-vault/ai-vault-scan-progress-flow.test.ts +++ b/src/main/ai-vault/ai-vault-scan-progress-flow.test.ts @@ -10,34 +10,40 @@ import { resetLocalAiVaultScanProgressForTests, startLocalAiVaultScanProgress } from './ai-vault-local-scan-progress' -import * as parseCache from './session-scanner-parse-cache' +import * as parseCache from './parse-cache/session-scanner-parse-cache' import * as transcriptFs from '../native-chat/wsl-transcript-fs-access' import { AiVaultScanTally } from './ai-vault-scan-tally' import { aiVaultScanWork, trackAiVaultScanProgress } from './ai-vault-scan-progress' -import { writeOpenCodeSqliteDatabase } from './session-scanner-opencode-sqlite-fixture' +import { writeOpenCodeSqliteDatabase } from './scanners/opencode/sqlite/session-scanner-opencode-sqlite-fixture' import { scanAiVaultSessions } from './session-scanner' -import { resetSessionParseCacheForTests } from './session-scanner-parse-cache' -import { AiVaultScannerServiceClient } from './session-scanner-service-client' +import { resetSessionParseCacheForTests } from './parse-cache/session-parse-cache-store' +import { AiVaultScannerServiceClient } from './scan-service/session-scanner-service-client' import { AiVaultServiceTestChild, aiVaultServiceRequestId, readyAiVaultServiceChild -} from './session-scanner-service-test-child' +} from './scan-service/session-scanner-service-test-child' import { isolatedScanRoots, writeJsonlFile } from './session-scanner-test-fixtures' // Source fixtures exercise the real SQLite readers without a packaged worker bundle. -vi.mock('./session-scanner-opencode-sqlite-worker-spawn', async () => { - const { listOpenCodeSqliteSessions } = await import('./session-scanner-opencode-sqlite-list') - const { listOpenCode2SqliteSessions } = await import('./session-scanner-opencode2-sqlite-list') - const { parseOpenCodeSqliteSession } = await import('./session-scanner-opencode-sqlite') - return { - listOpenCode2SqliteSessionsViaWorker: listOpenCode2SqliteSessions, - listOpenCodeSqliteSessionsViaWorker: listOpenCodeSqliteSessions, - listZcodeSqliteSessionsViaWorker: (args: Parameters[0]) => - listOpenCodeSqliteSessions({ ...args, agent: 'zcode' }), - parseOpenCodeSqliteSessionViaWorker: parseOpenCodeSqliteSession +vi.mock( + './scanners/opencode/reader-transport/session-scanner-opencode-sqlite-worker-spawn', + async () => { + const { listOpenCodeSqliteSessions } = + await import('./scanners/opencode/sqlite/session-scanner-opencode-sqlite-list') + const { listOpenCode2SqliteSessions } = + await import('./scanners/opencode2/session-scanner-opencode2-sqlite-list') + const { parseOpenCodeSqliteSession } = + await import('./scanners/opencode/sqlite/session-scanner-opencode-sqlite') + return { + listOpenCode2SqliteSessionsViaWorker: listOpenCode2SqliteSessions, + listOpenCodeSqliteSessionsViaWorker: listOpenCodeSqliteSessions, + listZcodeSqliteSessionsViaWorker: (args: Parameters[0]) => + listOpenCodeSqliteSessions({ ...args, agent: 'zcode' }), + parseOpenCodeSqliteSessionViaWorker: parseOpenCodeSqliteSession + } } -}) +) let tempRoot: string | null = null diff --git a/src/main/ai-vault/ai-vault-scan-progress.test.ts b/src/main/ai-vault/ai-vault-scan-progress.test.ts index 6d1dace1638..59dc24f5f14 100644 --- a/src/main/ai-vault/ai-vault-scan-progress.test.ts +++ b/src/main/ai-vault/ai-vault-scan-progress.test.ts @@ -12,7 +12,7 @@ import { trackAiVaultScanProgress } from './ai-vault-scan-progress' import { scanAiVaultSessions } from './session-scanner' -import { resetSessionParseCacheForTests } from './session-scanner-parse-cache' +import { resetSessionParseCacheForTests } from './parse-cache/session-parse-cache-store' import { isolatedScanRoots, writeJsonlFile } from './session-scanner-test-fixtures' let tempRoots: string[] = [] diff --git a/src/main/ai-vault/ai-vault-scan-tally.ts b/src/main/ai-vault/ai-vault-scan-tally.ts index edef342f5ef..ce528d10597 100644 --- a/src/main/ai-vault/ai-vault-scan-tally.ts +++ b/src/main/ai-vault/ai-vault-scan-tally.ts @@ -1,7 +1,7 @@ import { AI_VAULT_AGENTS, type AiVaultAgent } from '../../shared/ai-vault-types' import type { AiVaultScanWork } from '../../shared/ai-vault-scan-progress' import { AiVaultScanWorkload } from './ai-vault-scan-workload' -import { sessionFileExecutionNamespace } from './codex-session-root-dedup' +import { sessionFileExecutionNamespace } from '../../shared/ai-vault-scope-cwd-match' type AgentTally = { files: Set diff --git a/src/main/ai-vault/cached-session-list-wsl-probe.test.ts b/src/main/ai-vault/cached-session-list-wsl-probe.test.ts index daa81bf0f6b..738daf77fb7 100644 --- a/src/main/ai-vault/cached-session-list-wsl-probe.test.ts +++ b/src/main/ai-vault/cached-session-list-wsl-probe.test.ts @@ -11,11 +11,11 @@ vi.mock('@orca/process-host', async (importOriginal) => ({ ...(await importOriginal()), runProcess: runProcessMock })) -vi.mock('./session-scanner-service-spawn', async (importOriginal) => ({ +vi.mock('./scan-service/session-scanner-service-spawn', async (importOriginal) => ({ ...(await importOriginal()), scanAiVaultSessionsInService })) -vi.mock('./opencode-wsl-runtime-preparation', () => ({ +vi.mock('./scanners/opencode/reader-transport/opencode-wsl-runtime-preparation', () => ({ prepareOpenCodeWslReaders: vi.fn(async () => []) })) diff --git a/src/main/ai-vault/cached-session-list.test.ts b/src/main/ai-vault/cached-session-list.test.ts index 03a1e2724d3..aa672c93ff9 100644 --- a/src/main/ai-vault/cached-session-list.test.ts +++ b/src/main/ai-vault/cached-session-list.test.ts @@ -28,7 +28,7 @@ const { scanAiVaultSessionsInService: vi.fn() })) -vi.mock('./session-scanner-service-spawn', async (importOriginal) => ({ +vi.mock('./scan-service/session-scanner-service-spawn', async (importOriginal) => ({ ...(await importOriginal()), scanAiVaultSessionsInService })) diff --git a/src/main/ai-vault/cached-session-list.ts b/src/main/ai-vault/cached-session-list.ts index e354e05b5dc..3c1abe8bebb 100644 --- a/src/main/ai-vault/cached-session-list.ts +++ b/src/main/ai-vault/cached-session-list.ts @@ -5,7 +5,7 @@ import { clearAiVaultBackgroundRestartCircuit, resetAiVaultScannerBackgroundForTests, scanAiVaultSessionsInBackground -} from './session-scanner-background' +} from './scan-service/session-scanner-background' import { getCachedWslDistros, hasCachedWslDistros } from '../wsl/discovery/distro-catalog' import { listLastKnownRunningWslHomeDirs, @@ -24,7 +24,7 @@ import { import { aiVaultLocalScanKey, aiVaultLocalScanScopeKey } from '../../shared/ai-vault-local-scan-key' import type { AiVaultScanOptions } from './session-scanner-types' import { managedOpenCodeAccountDataDirs } from '../opencode/opencode-managed-account-data-dirs' -import { prepareOpenCodeWslReaders } from './opencode-wsl-runtime-preparation' +import { prepareOpenCodeWslReaders } from './scanners/opencode/reader-transport/opencode-wsl-runtime-preparation' import { LOCAL_EXECUTION_HOST_ID } from '../../shared/execution-host' import { AiVaultScanCoordinator } from './ai-vault-scan-coordinator' import { diff --git a/src/main/ai-vault/host-session-delete.ts b/src/main/ai-vault/host-session-delete.ts index 60de43c8e36..6ea8316b590 100644 --- a/src/main/ai-vault/host-session-delete.ts +++ b/src/main/ai-vault/host-session-delete.ts @@ -1,8 +1,8 @@ import { rm } from 'node:fs/promises' import { getAiVaultWslHomeDirs, invalidateAiVaultSessionListCache } from './cached-session-list' import { deleteAiVaultSessionFile, type AiVaultSessionPathRemover } from './session-delete' -import { invalidateSessionParseCacheEntry } from './session-scanner-parse-cache' -import { invalidateAiVaultBackgroundCache } from './session-scanner-background' +import { invalidateSessionParseCacheEntry } from './parse-cache/session-parse-cache-store' +import { invalidateAiVaultBackgroundCache } from './scan-service/session-scanner-background' import type { AiVaultAgent } from '../../shared/ai-vault-types' import { LOCAL_EXECUTION_HOST_ID } from '../../shared/execution-host' import type { diff --git a/src/main/ai-vault/session-parse-cache-antigravity-upgrade.test.ts b/src/main/ai-vault/parse-cache/session-parse-cache-antigravity-upgrade.test.ts similarity index 88% rename from src/main/ai-vault/session-parse-cache-antigravity-upgrade.test.ts rename to src/main/ai-vault/parse-cache/session-parse-cache-antigravity-upgrade.test.ts index dfdd81a4d36..5ebc173a6f3 100644 --- a/src/main/ai-vault/session-parse-cache-antigravity-upgrade.test.ts +++ b/src/main/ai-vault/parse-cache/session-parse-cache-antigravity-upgrade.test.ts @@ -7,15 +7,15 @@ import { initSessionParseCachePersistence, resetSessionParseCachePersistenceForTests } from './session-parse-cache-persistence' +import { createSessionParseStats, parseAgentSessionFileCached } from './session-scanner-parse-cache' import { - createSessionParseStats, - parseAgentSessionFileCached, - resetSessionParseCacheForTests -} from './session-scanner-parse-cache' -import { getSessionParseCacheEntry } from './session-parse-cache-store' -import { createAntigravityWorkspaceResolver } from './session-scanner-antigravity-history' -import { writeAntigravityTranscript } from './session-scanner-test-fixtures' -import type { SessionFileCandidate } from './session-scanner-types' + resetSessionParseCacheForTests, + getSessionParseCacheEntry +} from './session-parse-cache-store' + +import { createAntigravityWorkspaceResolver } from '../scanners/antigravity/session-scanner-antigravity-history' +import { writeAntigravityTranscript } from '../session-scanner-test-fixtures' +import type { SessionFileCandidate } from '../session-scanner-types' let root: string | undefined afterEach(async () => { diff --git a/src/main/ai-vault/session-parse-cache-database.ts b/src/main/ai-vault/parse-cache/session-parse-cache-database.ts similarity index 96% rename from src/main/ai-vault/session-parse-cache-database.ts rename to src/main/ai-vault/parse-cache/session-parse-cache-database.ts index 67c524589ec..c105c2e80c0 100644 --- a/src/main/ai-vault/session-parse-cache-database.ts +++ b/src/main/ai-vault/parse-cache/session-parse-cache-database.ts @@ -1,12 +1,12 @@ // Scanner-owned per-transcript rows persist changes without rewriting or capping the full working set. -import { isSqliteCorruption } from '../sqlite/sqlite-read-failure' -import { hardenSqliteDatabaseFiles } from '../sqlite/harden-database-files' -import type SyncDatabase from '../sqlite/sync-database' +import { isSqliteCorruption } from '../../sqlite/sqlite-read-failure' +import { hardenSqliteDatabaseFiles } from '../../sqlite/harden-database-files' +import type SyncDatabase from '../../sqlite/sync-database' import { openVersionedCacheDatabase, removeVersionedCacheDatabase -} from '../sqlite/versioned-cache-database' -import type { AiVaultSession } from '../../shared/ai-vault-types' +} from '../../sqlite/versioned-cache-database' +import type { AiVaultSession } from '../../../shared/ai-vault-types' import type { PersistedSessionParseCacheEntry, SessionScopeCwdLookup, @@ -21,7 +21,7 @@ import { parsePersistedSidecar } from './session-sidecar-stat' import { mergeSkippedTranscriptRecords, type SkippedTranscriptRecord -} from './session-transcript-record-budget' +} from '../transcripts/session-transcript-record-budget' // Bump for row-layout or cached-semantic changes; mismatched databases are discarded. export const SESSION_PARSE_CACHE_SCHEMA_VERSION = 9 diff --git a/src/main/ai-vault/session-parse-cache-devin-upgrade.test.ts b/src/main/ai-vault/parse-cache/session-parse-cache-devin-upgrade.test.ts similarity index 89% rename from src/main/ai-vault/session-parse-cache-devin-upgrade.test.ts rename to src/main/ai-vault/parse-cache/session-parse-cache-devin-upgrade.test.ts index 20cc71c7853..e4a2001ada3 100644 --- a/src/main/ai-vault/session-parse-cache-devin-upgrade.test.ts +++ b/src/main/ai-vault/parse-cache/session-parse-cache-devin-upgrade.test.ts @@ -6,13 +6,13 @@ import { initSessionParseCachePersistence, resetSessionParseCachePersistenceForTests } from './session-parse-cache-persistence' +import { createSessionParseStats, parseAgentSessionFileCached } from './session-scanner-parse-cache' import { - createSessionParseStats, - parseAgentSessionFileCached, - resetSessionParseCacheForTests -} from './session-scanner-parse-cache' -import { getSessionParseCacheEntry } from './session-parse-cache-store' -import type { SessionFileCandidate } from './session-scanner-types' + resetSessionParseCacheForTests, + getSessionParseCacheEntry +} from './session-parse-cache-store' + +import type { SessionFileCandidate } from '../session-scanner-types' let root: string | undefined diff --git a/src/main/ai-vault/session-parse-cache-large-scan.test.ts b/src/main/ai-vault/parse-cache/session-parse-cache-large-scan.test.ts similarity index 96% rename from src/main/ai-vault/session-parse-cache-large-scan.test.ts rename to src/main/ai-vault/parse-cache/session-parse-cache-large-scan.test.ts index bcf85aedd71..04e5a3abf6b 100644 --- a/src/main/ai-vault/session-parse-cache-large-scan.test.ts +++ b/src/main/ai-vault/parse-cache/session-parse-cache-large-scan.test.ts @@ -2,7 +2,7 @@ import { mkdtemp, rm, stat, writeFile } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, expect, it } from 'vitest' -import SyncDatabase from '../sqlite/sync-database' +import SyncDatabase from '../../sqlite/sync-database' import { flushSessionParseCachePersist, initSessionParseCachePersistence, @@ -17,7 +17,7 @@ import { storeSessionParseCacheEntry } from './session-parse-cache-store' import { createSessionParseStats, parseListedSessionFile } from './session-scanner-parse-cache' -import type { SessionFileCandidate } from './session-scanner-types' +import type { SessionFileCandidate } from '../session-scanner-types' const CANDIDATES = Math.max(MAX_RESUME_ENTRIES, MAX_UNLISTED_ENTRIES) + 178 let root: string | undefined diff --git a/src/main/ai-vault/session-parse-cache-legacy-json.ts b/src/main/ai-vault/parse-cache/session-parse-cache-legacy-json.ts similarity index 100% rename from src/main/ai-vault/session-parse-cache-legacy-json.ts rename to src/main/ai-vault/parse-cache/session-parse-cache-legacy-json.ts diff --git a/src/main/ai-vault/session-parse-cache-metadata-checkpoint.test.ts b/src/main/ai-vault/parse-cache/session-parse-cache-metadata-checkpoint.test.ts similarity index 92% rename from src/main/ai-vault/session-parse-cache-metadata-checkpoint.test.ts rename to src/main/ai-vault/parse-cache/session-parse-cache-metadata-checkpoint.test.ts index 100328d5ba8..e462d5ebaf5 100644 --- a/src/main/ai-vault/session-parse-cache-metadata-checkpoint.test.ts +++ b/src/main/ai-vault/parse-cache/session-parse-cache-metadata-checkpoint.test.ts @@ -7,17 +7,20 @@ import { initSessionParseCachePersistence, resetSessionParseCachePersistenceForTests } from './session-parse-cache-persistence' +import { createSessionParseStats, parseAgentSessionFileCached } from './session-scanner-parse-cache' import { - createSessionParseStats, - parseAgentSessionFileCached, - resetSessionParseCacheForTests -} from './session-scanner-parse-cache' -import { getSessionParseCacheEntry } from './session-parse-cache-store' + resetSessionParseCacheForTests, + getSessionParseCacheEntry +} from './session-parse-cache-store' + import { SessionParseCacheDatabase } from './session-parse-cache-database' -import { CODEX_FIXTURE_SESSION_ID, codexFixture } from './session-scanner-codex-fixtures' -import { resetCursorChatMetaIndexCacheForTests } from './session-scanner-cursor-chat-meta' -import { writeJsonlFile } from './session-scanner-test-fixtures' -import type { SessionFileCandidate } from './session-scanner-types' +import { + CODEX_FIXTURE_SESSION_ID, + codexFixture +} from '../scanners/codex/session-scanner-codex-fixtures' +import { resetCursorChatMetaIndexCacheForTests } from '../scanners/cursor/session-scanner-cursor-chat-meta' +import { writeJsonlFile } from '../session-scanner-test-fixtures' +import type { SessionFileCandidate } from '../session-scanner-types' let root: string let cacheFile: string diff --git a/src/main/ai-vault/session-parse-cache-persistence.test.ts b/src/main/ai-vault/parse-cache/session-parse-cache-persistence.test.ts similarity index 97% rename from src/main/ai-vault/session-parse-cache-persistence.test.ts rename to src/main/ai-vault/parse-cache/session-parse-cache-persistence.test.ts index 189ab89fb1b..1188a4ff294 100644 --- a/src/main/ai-vault/session-parse-cache-persistence.test.ts +++ b/src/main/ai-vault/parse-cache/session-parse-cache-persistence.test.ts @@ -4,7 +4,7 @@ import * as fsPromises from 'node:fs/promises' import { tmpdir } from 'node:os' import { dirname, join } from 'node:path' import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' -import SyncDatabase from '../sqlite/sync-database' +import SyncDatabase from '../../sqlite/sync-database' import { configureSessionParseCachePersistence, flushSessionParseCachePersist, @@ -16,27 +16,28 @@ import { SESSION_PARSE_CACHE_SCHEMA_VERSION, SessionParseCacheDatabase } from './session-parse-cache-database' -import { scanAiVaultSessions } from './session-scanner' +import { scanAiVaultSessions } from '../session-scanner' import { createSessionParseStats, - invalidateSessionParseCacheEntry, parseAgentSessionFileCached, - resetSessionParseCacheForTests, type SessionParseStats } from './session-scanner-parse-cache' -import type * as ParseCacheModule from './session-scanner-parse-cache' import { + invalidateSessionParseCacheEntry, + resetSessionParseCacheForTests, getSessionParseCacheEntry, storeSessionParseCacheEntry, storeSessionScopeCwd, type SessionScopeCwdStamp } from './session-parse-cache-store' +import type * as ParseCacheModule from './session-scanner-parse-cache' + import type { SessionSidecarObservation } from './session-sidecar-stat' -import { isolatedScanRoots } from './session-scanner-test-fixtures' -import { parseClaudeSessionFile } from './session-scanner-primary-parsers' -import { parseSessionCandidate } from './session-scanner-candidate-parse' -import { MAX_SESSION_TRANSCRIPT_RECORD_BYTES } from './session-transcript-record-budget' -import type { FileWithMtime, SessionFileCandidate } from './session-scanner-types' +import { isolatedScanRoots } from '../session-scanner-test-fixtures' +import { parseClaudeSessionFile } from '../scanners/claude/session-scanner-primary-parsers' +import { parseSessionCandidate } from '../session-scanner-candidate-parse' +import { MAX_SESSION_TRANSCRIPT_RECORD_BYTES } from '../transcripts/session-transcript-record-budget' +import type { FileWithMtime, SessionFileCandidate } from '../session-scanner-types' const hooks = vi.hoisted(() => { const state: { beforeParse: (() => Promise) | null } = { beforeParse: null } diff --git a/src/main/ai-vault/session-parse-cache-persistence.ts b/src/main/ai-vault/parse-cache/session-parse-cache-persistence.ts similarity index 98% rename from src/main/ai-vault/session-parse-cache-persistence.ts rename to src/main/ai-vault/parse-cache/session-parse-cache-persistence.ts index 21f175f81da..ab4e2bc3273 100644 --- a/src/main/ai-vault/session-parse-cache-persistence.ts +++ b/src/main/ai-vault/parse-cache/session-parse-cache-persistence.ts @@ -2,7 +2,7 @@ import { stat } from 'node:fs/promises' import { dirname, join } from 'node:path' import { setImmediate as yieldToEventLoop } from 'node:timers/promises' -import { splitOpenCodeSqliteCandidate } from '../../shared/opencode-sqlite-session-path' +import { splitOpenCodeSqliteCandidate } from '../../../shared/opencode-sqlite-session-path' import { SessionParseCacheDatabase } from './session-parse-cache-database' import { importLegacySessionParseCacheJson } from './session-parse-cache-legacy-json' import { diff --git a/src/main/ai-vault/session-parse-cache-preview-upgrade.test.ts b/src/main/ai-vault/parse-cache/session-parse-cache-preview-upgrade.test.ts similarity index 90% rename from src/main/ai-vault/session-parse-cache-preview-upgrade.test.ts rename to src/main/ai-vault/parse-cache/session-parse-cache-preview-upgrade.test.ts index b618dcdc8f2..7c8e834cd6c 100644 --- a/src/main/ai-vault/session-parse-cache-preview-upgrade.test.ts +++ b/src/main/ai-vault/parse-cache/session-parse-cache-preview-upgrade.test.ts @@ -2,19 +2,19 @@ import { mkdtemp, rm, stat, writeFile } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, expect, it } from 'vitest' -import SyncDatabase from '../sqlite/sync-database' +import SyncDatabase from '../../sqlite/sync-database' import { SessionParseCacheDatabase } from './session-parse-cache-database' import { initSessionParseCachePersistence, resetSessionParseCachePersistenceForTests } from './session-parse-cache-persistence' -import { getSessionParseCacheEntry } from './session-parse-cache-store' import { - createSessionParseStats, - parseAgentSessionFileCached, + getSessionParseCacheEntry, resetSessionParseCacheForTests -} from './session-scanner-parse-cache' -import type { SessionFileCandidate } from './session-scanner-types' +} from './session-parse-cache-store' +import { createSessionParseStats, parseAgentSessionFileCached } from './session-scanner-parse-cache' + +import type { SessionFileCandidate } from '../session-scanner-types' let root: string | undefined diff --git a/src/main/ai-vault/session-parse-cache-store.ts b/src/main/ai-vault/parse-cache/session-parse-cache-store.ts similarity index 96% rename from src/main/ai-vault/session-parse-cache-store.ts rename to src/main/ai-vault/parse-cache/session-parse-cache-store.ts index d02c9fd6762..a9720becf79 100644 --- a/src/main/ai-vault/session-parse-cache-store.ts +++ b/src/main/ai-vault/parse-cache/session-parse-cache-store.ts @@ -1,9 +1,9 @@ import type { Hash } from 'node:crypto' -import type { AiVaultAgent, AiVaultSession } from '../../shared/ai-vault-types' -import type { ResumableSessionParseState } from './session-scanner-types' +import type { AiVaultAgent, AiVaultSession } from '../../../shared/ai-vault-types' +import type { ResumableSessionParseState } from '../session-scanner-types' import type { SessionSidecarObservation } from './session-sidecar-stat' -import type { TranscriptMessageChannel } from './session-transcript-channel' -import type { SkippedTranscriptRecord } from './session-transcript-record-budget' +import type { TranscriptMessageChannel } from '../transcripts/session-transcript-channel' +import type { SkippedTranscriptRecord } from '../transcripts/session-transcript-record-budget' // Keep listed rows hot: unlimited scans must not evict their own next hits; only unlisted rows are count-bounded. export const MAX_UNLISTED_ENTRIES = 4096 diff --git a/src/main/ai-vault/session-parse-file-lane.ts b/src/main/ai-vault/parse-cache/session-parse-file-lane.ts similarity index 100% rename from src/main/ai-vault/session-parse-file-lane.ts rename to src/main/ai-vault/parse-cache/session-parse-file-lane.ts diff --git a/src/main/ai-vault/session-scanner-parse-cache-agents.test.ts b/src/main/ai-vault/parse-cache/session-scanner-parse-cache-agents.test.ts similarity index 95% rename from src/main/ai-vault/session-scanner-parse-cache-agents.test.ts rename to src/main/ai-vault/parse-cache/session-scanner-parse-cache-agents.test.ts index b5338149a32..049a68c78a2 100644 --- a/src/main/ai-vault/session-scanner-parse-cache-agents.test.ts +++ b/src/main/ai-vault/parse-cache/session-scanner-parse-cache-agents.test.ts @@ -2,19 +2,16 @@ import { appendFile, mkdir, mkdtemp, rm, stat, writeFile } from 'node:fs/promise import { tmpdir } from 'node:os' import { dirname, join } from 'node:path' import { afterEach, beforeEach, describe, expect, it } from 'vitest' -import { parseAgentSessionFile } from './session-scanner-agent-parser' +import { parseAgentSessionFile } from '../session-scanner-agent-parser' import { CODEX_FIXTURE_SESSION_ID, codexFixture, codexWorkerFixtureLines -} from './session-scanner-codex-fixtures' -import { allIncrementalAgentFixtures } from './session-scanner-incremental-fixtures' -import { - createSessionParseStats, - parseAgentSessionFileCached, - resetSessionParseCacheForTests -} from './session-scanner-parse-cache' -import type { SessionFileCandidate } from './session-scanner-types' +} from '../scanners/codex/session-scanner-codex-fixtures' +import { allIncrementalAgentFixtures } from '../session-scanner-incremental-fixtures' +import { createSessionParseStats, parseAgentSessionFileCached } from './session-scanner-parse-cache' +import { resetSessionParseCacheForTests } from './session-parse-cache-store' +import type { SessionFileCandidate } from '../session-scanner-types' let tempRoots: string[] = [] diff --git a/src/main/ai-vault/session-scanner-parse-cache.test.ts b/src/main/ai-vault/parse-cache/session-scanner-parse-cache.test.ts similarity index 96% rename from src/main/ai-vault/session-scanner-parse-cache.test.ts rename to src/main/ai-vault/parse-cache/session-scanner-parse-cache.test.ts index fd39f94c0ca..1d1ef075249 100644 --- a/src/main/ai-vault/session-scanner-parse-cache.test.ts +++ b/src/main/ai-vault/parse-cache/session-scanner-parse-cache.test.ts @@ -2,20 +2,20 @@ import { appendFile, mkdir, mkdtemp, rm, stat, writeFile } from 'node:fs/promise import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, beforeEach, describe, expect, it } from 'vitest' -import { isAiVaultScanCancelledError } from '../../shared/ai-vault-types' -import { getSessionParseCacheEntry } from './session-parse-cache-store' +import { isAiVaultScanCancelledError } from '../../../shared/ai-vault-types' import { - parseAgentSessionFileCached, - resetSessionParseCacheForTests, - createSessionParseStats -} from './session-scanner-parse-cache' -import { parseClaudeSessionFile } from './session-scanner-primary-parsers' -import type { FileWithMtime, SessionFileCandidate } from './session-scanner-types' + getSessionParseCacheEntry, + resetSessionParseCacheForTests +} from './session-parse-cache-store' +import { parseAgentSessionFileCached, createSessionParseStats } from './session-scanner-parse-cache' + +import { parseClaudeSessionFile } from '../scanners/claude/session-scanner-primary-parsers' +import type { FileWithMtime, SessionFileCandidate } from '../session-scanner-types' import { registerTranscriptConsumer, resetTranscriptConsumersForTests, type TranscriptReadOutcome -} from './session-transcript-consumers' +} from '../transcripts/session-transcript-consumers' let tempRoots: string[] = [] diff --git a/src/main/ai-vault/session-scanner-parse-cache.ts b/src/main/ai-vault/parse-cache/session-scanner-parse-cache.ts similarity index 84% rename from src/main/ai-vault/session-scanner-parse-cache.ts rename to src/main/ai-vault/parse-cache/session-scanner-parse-cache.ts index 711b05ba4a0..71f1272dfbc 100644 --- a/src/main/ai-vault/session-scanner-parse-cache.ts +++ b/src/main/ai-vault/parse-cache/session-scanner-parse-cache.ts @@ -1,19 +1,19 @@ -import { createQoderSessionResumeState } from './session-scanner-qoder-parser' -import type { AiVaultSession } from '../../shared/ai-vault-types' +import { createQoderSessionResumeState } from '../scanners/qoder/session-scanner-qoder-parser' +import type { AiVaultSession } from '../../../shared/ai-vault-types' import { inSessionParseFileLane } from './session-parse-file-lane' -import { createAntigravitySessionResumeState } from './session-scanner-antigravity-parser' -import { createCodexSessionResumeState } from './session-scanner-codex-parser' -import { createDroidSessionResumeState } from './session-scanner-droid-parser' -import { createMessageGraphSessionResumeState } from './session-scanner-graph-parsers' -import { createClaudeSessionResumeState } from './session-scanner-primary-parsers' -import { createCodebuddySessionResumeState } from './session-scanner-codebuddy-parser' -import { createGeminiJsonlSessionResumeState } from './session-scanner-gemini-parsers' -import { createCopilotSessionResumeState } from './session-scanner-copilot-parser' -import { createCursorSessionResumeState } from './session-scanner-cursor-parser' -import { countSubagentTranscripts } from './session-scanner-subagent-transcripts' -import { countOmpSubagentTranscripts } from './session-scanner-omp-subagent-transcripts' -import type { ResumableSessionParseState, SessionFileCandidate } from './session-scanner-types' -import { refreshCachedCodexTitle } from './session-scanner-codex-cached-title' +import { createAntigravitySessionResumeState } from '../scanners/antigravity/session-scanner-antigravity-parser' +import { createCodexSessionResumeState } from '../scanners/codex/session-scanner-codex-parser' +import { createDroidSessionResumeState } from '../scanners/droid/session-scanner-droid-parser' +import { createMessageGraphSessionResumeState } from '../scanners/session-scanner-graph-parsers' +import { createClaudeSessionResumeState } from '../scanners/claude/session-scanner-primary-parsers' +import { createCodebuddySessionResumeState } from '../scanners/codebuddy/session-scanner-codebuddy-parser' +import { createGeminiJsonlSessionResumeState } from '../scanners/gemini/session-scanner-gemini-parsers' +import { createCopilotSessionResumeState } from '../scanners/copilot/session-scanner-copilot-parser' +import { createCursorSessionResumeState } from '../scanners/cursor/session-scanner-cursor-parser' +import { countSubagentTranscripts } from '../scanners/claude/session-scanner-subagent-transcripts' +import { countOmpSubagentTranscripts } from '../scanners/omp/session-scanner-omp-subagent-transcripts' +import type { ResumableSessionParseState, SessionFileCandidate } from '../session-scanner-types' +import { refreshCachedCodexTitle } from '../scanners/codex/session-scanner-codex-cached-title' import { getSessionParseCacheEntry, noteSessionParseCacheListed, @@ -21,12 +21,12 @@ import { storeSessionParseCacheEntry, type SessionParseCacheEntry } from './session-parse-cache-store' -import type { TranscriptMessageSink } from './session-transcript-consumers' +import type { TranscriptMessageSink } from '../transcripts/session-transcript-consumers' import { sidecarUnchanged } from './session-sidecar-stat' import { mergeSkippedTranscriptRecords, type SkippedTranscriptRecord -} from './session-transcript-record-budget' +} from '../transcripts/session-transcript-record-budget' import { enrichSessionFromSidecar, reuseUnchangedSidecarSession, @@ -38,12 +38,7 @@ import { readWholeTranscript, requestWholeTranscriptRead, type TranscriptReadStats -} from './session-transcript-reader' - -export { - invalidateSessionParseCacheEntry, - resetSessionParseCacheForTests -} from './session-parse-cache-store' +} from '../transcripts/session-transcript-reader' // Resume only append-only folds; return factories so cached resumes avoid allocating throwaway state. function resumableStateFactoryFor( diff --git a/src/main/ai-vault/session-scanner-sidecar-enrichment.ts b/src/main/ai-vault/parse-cache/session-scanner-sidecar-enrichment.ts similarity index 88% rename from src/main/ai-vault/session-scanner-sidecar-enrichment.ts rename to src/main/ai-vault/parse-cache/session-scanner-sidecar-enrichment.ts index 99f3dc05fb0..56ceaa3f451 100644 --- a/src/main/ai-vault/session-scanner-sidecar-enrichment.ts +++ b/src/main/ai-vault/parse-cache/session-scanner-sidecar-enrichment.ts @@ -1,10 +1,13 @@ -import type { AiVaultSession } from '../../shared/ai-vault-types' -import { buildAiVaultResumeCommand } from '../../shared/ai-vault-resume-command' -import { generatedSessionTitle } from './session-scanner-accumulator' -import { readCursorChatMeta, wasCursorChatMetaRefused } from './session-scanner-cursor-chat-meta' -import { devinSessionsIndexForSidecar } from './session-scanner-devin-db' +import type { AiVaultSession } from '../../../shared/ai-vault-types' +import { buildAiVaultResumeCommand } from '../../../shared/ai-vault-resume-command' +import { generatedSessionTitle } from '../session-scanner-accumulator' +import { + readCursorChatMeta, + wasCursorChatMetaRefused +} from '../scanners/cursor/session-scanner-cursor-chat-meta' +import { devinSessionsIndexForSidecar } from '../scanners/devin/session-scanner-devin-db' import type { SessionSidecarObservation } from './session-sidecar-stat' -import type { SessionFileCandidate } from './session-scanner-types' +import type { SessionFileCandidate } from '../session-scanner-types' /** Reapply sibling metadata to the transcript fold so rewritten sidecars replace earlier enrichment. */ diff --git a/src/main/ai-vault/session-scope-cwds-table.ts b/src/main/ai-vault/parse-cache/session-scope-cwds-table.ts similarity index 98% rename from src/main/ai-vault/session-scope-cwds-table.ts rename to src/main/ai-vault/parse-cache/session-scope-cwds-table.ts index a718f4d5d83..02b471c7347 100644 --- a/src/main/ai-vault/session-scope-cwds-table.ts +++ b/src/main/ai-vault/parse-cache/session-scope-cwds-table.ts @@ -1,4 +1,4 @@ -import type SyncDatabase from '../sqlite/sync-database' +import type SyncDatabase from '../../sqlite/sync-database' import { parsePersistedSidecar } from './session-sidecar-stat' import type { SessionScopeCwdLookup, SessionScopeCwdStamp } from './session-parse-cache-store' diff --git a/src/main/ai-vault/session-sidecar-stat.test.ts b/src/main/ai-vault/parse-cache/session-sidecar-stat.test.ts similarity index 100% rename from src/main/ai-vault/session-sidecar-stat.test.ts rename to src/main/ai-vault/parse-cache/session-sidecar-stat.test.ts diff --git a/src/main/ai-vault/session-sidecar-stat.ts b/src/main/ai-vault/parse-cache/session-sidecar-stat.ts similarity index 100% rename from src/main/ai-vault/session-sidecar-stat.ts rename to src/main/ai-vault/parse-cache/session-sidecar-stat.ts diff --git a/src/main/ai-vault/runtime-session-scanner.ts b/src/main/ai-vault/runtime-session-scanner.ts index 087fc0a8d1b..75ca49b7c9d 100644 --- a/src/main/ai-vault/runtime-session-scanner.ts +++ b/src/main/ai-vault/runtime-session-scanner.ts @@ -20,7 +20,7 @@ import type { AiVaultSessionTitlesResult } from '../../shared/ai-vault-session-title' import { parseAiVaultListResult } from './session-list-result-validation' -import { parseAiVaultSessionTitlesResult } from './session-title-result-validation' +import { parseAiVaultSessionTitlesResult } from './session-titles/session-title-result-validation' import { isGatedOffWslHost } from '../wsl/host-lifecycle/wsl-host-gate' import type { AiVaultDeleteSessionArgs, diff --git a/src/main/ai-vault/session-scanner-background.ts b/src/main/ai-vault/scan-service/session-scanner-background.ts similarity index 86% rename from src/main/ai-vault/session-scanner-background.ts rename to src/main/ai-vault/scan-service/session-scanner-background.ts index 92f77004362..30a9d73e4ce 100644 --- a/src/main/ai-vault/session-scanner-background.ts +++ b/src/main/ai-vault/scan-service/session-scanner-background.ts @@ -1,12 +1,12 @@ -import type { AiVaultListResult, AiVaultSubagentListResult } from '../../shared/ai-vault-types' +import type { AiVaultListResult, AiVaultSubagentListResult } from '../../../shared/ai-vault-types' import type { AiVaultSessionTitleRequest, AiVaultSessionTitlesResult -} from '../../shared/ai-vault-session-title' +} from '../../../shared/ai-vault-session-title' import type { ReadAiVaultFirstUserPromptArgs, ReadAiVaultFirstUserPromptResult -} from './session-first-user-prompt-read' +} from '../session-first-user-prompt-read' import { clearAiVaultServiceRestartCircuit, invalidateAiVaultServiceCache, @@ -20,8 +20,8 @@ import type { AiVaultServiceScanOptions, AiVaultServiceSubagentRequest } from './session-scanner-service-protocol' -import { isWslUncPath } from '../../shared/wsl-paths' -import type { LocalAiVaultScanProgressHandle } from './ai-vault-local-scan-progress' +import { isWslUncPath } from '../../../shared/wsl-paths' +import type { LocalAiVaultScanProgressHandle } from '../ai-vault-local-scan-progress' // Let forced refreshes retry after a local service circuit opens. export function clearAiVaultBackgroundRestartCircuit(): void { @@ -53,7 +53,7 @@ export async function readAiVaultFirstUserPromptInBackground( request: ReadAiVaultFirstUserPromptArgs ): Promise { if (process.platform === 'win32' && isWslUncPath(request.filePath)) { - const { localAiVaultScanRoots } = await import('./cached-session-list') + const { localAiVaultScanRoots } = await import('../cached-session-list') const roots = await localAiVaultScanRoots() request = { ...request, wslOpenCodeReaders: roots.wslOpenCodeReaders ?? [] } } diff --git a/src/main/ai-vault/session-scanner-service-cancellation.test.ts b/src/main/ai-vault/scan-service/session-scanner-service-cancellation.test.ts similarity index 95% rename from src/main/ai-vault/session-scanner-service-cancellation.test.ts rename to src/main/ai-vault/scan-service/session-scanner-service-cancellation.test.ts index 92525900014..f9775ccb836 100644 --- a/src/main/ai-vault/session-scanner-service-cancellation.test.ts +++ b/src/main/ai-vault/scan-service/session-scanner-service-cancellation.test.ts @@ -9,9 +9,12 @@ const scanAiVaultSessions = vi.hoisted(() => vi.fn()) const flushSessionParseCachePersist = vi.hoisted(() => vi.fn(async () => undefined)) const closeSearch = vi.hoisted(() => vi.fn()) -vi.mock('./session-scanner', () => ({ scanAiVaultSessions })) -vi.mock('./session-scanner-parse-cache', () => ({ invalidateSessionParseCacheEntry: vi.fn() })) -vi.mock('./session-parse-cache-persistence', () => ({ +vi.mock('../session-scanner', () => ({ scanAiVaultSessions })) +vi.mock('../parse-cache/session-parse-cache-store', async (importOriginal) => ({ + ...(await importOriginal()), + invalidateSessionParseCacheEntry: vi.fn() +})) +vi.mock('../parse-cache/session-parse-cache-persistence', () => ({ flushSessionParseCachePersist, initSessionParseCachePersistence: vi.fn() })) diff --git a/src/main/ai-vault/session-scanner-service-client-state.ts b/src/main/ai-vault/scan-service/session-scanner-service-client-state.ts similarity index 98% rename from src/main/ai-vault/session-scanner-service-client-state.ts rename to src/main/ai-vault/scan-service/session-scanner-service-client-state.ts index b730d7a7f7d..851958757f9 100644 --- a/src/main/ai-vault/session-scanner-service-client-state.ts +++ b/src/main/ai-vault/scan-service/session-scanner-service-client-state.ts @@ -1,6 +1,6 @@ -import type { SessionSearchScanRoots } from '../ai-vault-search/session-search-scan-roots' +import type { SessionSearchScanRoots } from '../../ai-vault-search/session-search-scan-roots' import type { ChildProcess } from 'node:child_process' -import { createAiVaultScanCancelledError } from './ai-vault-scan-cancellation' +import { createAiVaultScanCancelledError } from '../ai-vault-scan-cancellation' import type { AiVaultServiceScanListener } from './session-scanner-service-request-deadline' import { AI_VAULT_SERVICE_PROTOCOL_VERSION, diff --git a/src/main/ai-vault/session-scanner-service-client.test.ts b/src/main/ai-vault/scan-service/session-scanner-service-client.test.ts similarity index 100% rename from src/main/ai-vault/session-scanner-service-client.test.ts rename to src/main/ai-vault/scan-service/session-scanner-service-client.test.ts diff --git a/src/main/ai-vault/session-scanner-service-client.ts b/src/main/ai-vault/scan-service/session-scanner-service-client.ts similarity index 98% rename from src/main/ai-vault/session-scanner-service-client.ts rename to src/main/ai-vault/scan-service/session-scanner-service-client.ts index e374e33b8c8..d84b951a665 100644 --- a/src/main/ai-vault/session-scanner-service-client.ts +++ b/src/main/ai-vault/scan-service/session-scanner-service-client.ts @@ -1,5 +1,5 @@ import type { ChildProcess } from 'node:child_process' -import { createAiVaultScanCancelledError } from './ai-vault-scan-cancellation' +import { createAiVaultScanCancelledError } from '../ai-vault-scan-cancellation' import { AI_VAULT_SERVICE_IDLE_TIMEOUT_MS, AI_VAULT_SERVICE_MAX_CALLS, @@ -318,5 +318,3 @@ export class AiVaultScannerServiceClient { retireAiVaultServiceChild(child) } } - -export type { AiVaultServiceProcessFactory } from './session-scanner-service-client-state' diff --git a/src/main/ai-vault/session-scanner-service-entry-path.test.ts b/src/main/ai-vault/scan-service/session-scanner-service-entry-path.test.ts similarity index 100% rename from src/main/ai-vault/session-scanner-service-entry-path.test.ts rename to src/main/ai-vault/scan-service/session-scanner-service-entry-path.test.ts diff --git a/src/main/ai-vault/session-scanner-service-entry-path.ts b/src/main/ai-vault/scan-service/session-scanner-service-entry-path.ts similarity index 95% rename from src/main/ai-vault/session-scanner-service-entry-path.ts rename to src/main/ai-vault/scan-service/session-scanner-service-entry-path.ts index 64909fd33c1..da7f0a70d32 100644 --- a/src/main/ai-vault/session-scanner-service-entry-path.ts +++ b/src/main/ai-vault/scan-service/session-scanner-service-entry-path.ts @@ -3,7 +3,7 @@ import { getForkedChildEntryPath, resolveForkedChildEntryPath, resolveForkedChildEntryPathWithoutApp -} from '../worker-threads/forked-child-entry-path' +} from '../../worker-threads/forked-child-entry-path' // orcad resolves this literal beside orcad.js; build-orcad.mjs emits it from ORCAD_CHILD_ENTRY_POINTS. export const AI_VAULT_SERVICE_ENTRY_FILENAME = 'session-scanner-service-entry.js' diff --git a/src/main/ai-vault/session-scanner-service-entry-subagents.test.ts b/src/main/ai-vault/scan-service/session-scanner-service-entry-subagents.test.ts similarity index 90% rename from src/main/ai-vault/session-scanner-service-entry-subagents.test.ts rename to src/main/ai-vault/scan-service/session-scanner-service-entry-subagents.test.ts index 0f9439bd9da..9de6bddbdb3 100644 --- a/src/main/ai-vault/session-scanner-service-entry-subagents.test.ts +++ b/src/main/ai-vault/scan-service/session-scanner-service-entry-subagents.test.ts @@ -4,9 +4,11 @@ import { AI_VAULT_SERVICE_PROTOCOL_VERSION } from './session-scanner-service-pro const listClaudeSubagentSessions = vi.hoisted(() => vi.fn()) const listOmpSubagentSessions = vi.hoisted(() => vi.fn()) -vi.mock('./session-scanner-claude-subagents', () => ({ listClaudeSubagentSessions })) -vi.mock('./session-scanner-omp-subagent-listing', () => ({ listOmpSubagentSessions })) -vi.mock('./session-parse-cache-persistence', () => ({ +vi.mock('../scanners/claude/session-scanner-claude-subagents', () => ({ + listClaudeSubagentSessions +})) +vi.mock('../scanners/omp/session-scanner-omp-subagent-listing', () => ({ listOmpSubagentSessions })) +vi.mock('../parse-cache/session-parse-cache-persistence', () => ({ flushSessionParseCachePersist: vi.fn(() => Promise.resolve()), initSessionParseCachePersistence: vi.fn() })) diff --git a/src/main/ai-vault/session-scanner-service-entry.test.ts b/src/main/ai-vault/scan-service/session-scanner-service-entry.test.ts similarity index 93% rename from src/main/ai-vault/session-scanner-service-entry.test.ts rename to src/main/ai-vault/scan-service/session-scanner-service-entry.test.ts index e952eff5271..93b3b139e87 100644 --- a/src/main/ai-vault/session-scanner-service-entry.test.ts +++ b/src/main/ai-vault/scan-service/session-scanner-service-entry.test.ts @@ -1,20 +1,20 @@ import { beforeAll, beforeEach, describe, expect, it, vi } from 'vitest' -import { noteAiVaultScanWorkChanged } from './ai-vault-scan-progress' +import { noteAiVaultScanWorkChanged } from '../ai-vault-scan-progress' import { AI_VAULT_SERVICE_PROTOCOL_VERSION } from './session-scanner-service-protocol' const invalidateSessionParseCacheEntry = vi.hoisted(() => vi.fn()) const scanAiVaultSessions = vi.hoisted(() => vi.fn()) -vi.mock('./session-scanner-parse-cache', async (importOriginal) => ({ +vi.mock('../parse-cache/session-parse-cache-store', async (importOriginal) => ({ ...(await importOriginal()), invalidateSessionParseCacheEntry })) -vi.mock('./session-scanner', () => ({ scanAiVaultSessions })) -vi.mock('./session-parse-cache-persistence', () => ({ +vi.mock('../session-scanner', () => ({ scanAiVaultSessions })) +vi.mock('../parse-cache/session-parse-cache-persistence', () => ({ flushSessionParseCachePersist: vi.fn(() => Promise.resolve()), initSessionParseCachePersistence: vi.fn() })) -vi.mock('./session-subagent-reader', () => ({ +vi.mock('../session-subagent-reader', () => ({ listLocalAiVaultSubagentSessions: vi.fn(() => Promise.resolve({ sessions: [], issues: [] })) })) diff --git a/src/main/ai-vault/session-scanner-service-entry.ts b/src/main/ai-vault/scan-service/session-scanner-service-entry.ts similarity index 88% rename from src/main/ai-vault/session-scanner-service-entry.ts rename to src/main/ai-vault/scan-service/session-scanner-service-entry.ts index d2f0a313c3a..91e65b6f141 100644 --- a/src/main/ai-vault/session-scanner-service-entry.ts +++ b/src/main/ai-vault/scan-service/session-scanner-service-entry.ts @@ -1,15 +1,15 @@ import { requestSessionSearchRoots } from './session-scanner-service-root-request' -import { aiVaultScanWork, trackAiVaultScanProgress } from './ai-vault-scan-progress' -import type { AiVaultScanWork } from '../../shared/ai-vault-scan-progress' -import type { AiVaultSessionTitle } from '../../shared/ai-vault-session-title' -import type { AiVaultListResult } from '../../shared/ai-vault-types' -import { readAiVaultFirstUserPrompt } from './session-first-user-prompt-read' +import { aiVaultScanWork, trackAiVaultScanProgress } from '../ai-vault-scan-progress' +import type { AiVaultScanWork } from '../../../shared/ai-vault-scan-progress' +import type { AiVaultSessionTitle } from '../../../shared/ai-vault-session-title' +import type { AiVaultListResult } from '../../../shared/ai-vault-types' +import { readAiVaultFirstUserPrompt } from '../session-first-user-prompt-read' import { flushSessionParseCachePersist, initSessionParseCachePersistence -} from './session-parse-cache-persistence' -import { scanAiVaultSessions } from './session-scanner' -import { invalidateSessionParseCacheEntry } from './session-scanner-parse-cache' +} from '../parse-cache/session-parse-cache-persistence' +import { scanAiVaultSessions } from '../session-scanner' +import { invalidateSessionParseCacheEntry } from '../parse-cache/session-parse-cache-store' import { SessionScannerServiceSearch } from './session-scanner-service-search' import { AI_VAULT_SERVICE_PROTOCOL_VERSION, @@ -21,13 +21,13 @@ import { type AiVaultServiceRequest, type AiVaultServiceResultValue } from './session-scanner-service-protocol' -import { readAiVaultSessionTitlesFromFiles } from './session-title-file-reader' -import { resolveHostReadableAiVaultTitleRequests } from './session-title-request-paths' -import { listLocalAiVaultSubagentSessions } from './session-subagent-reader' +import { readAiVaultSessionTitlesFromFiles } from '../session-titles/session-title-file-reader' +import { resolveHostReadableAiVaultTitleRequests } from '../session-titles/session-title-request-paths' +import { listLocalAiVaultSubagentSessions } from '../session-subagent-reader' import { noteWslDistroMayHaveStopped, noteWslDistroWoken -} from '../wsl/discovery/wsl-background-distro-gate' +} from '../../wsl/discovery/wsl-background-distro-gate' if (!process.send) { throw new Error('AI Vault service requires a parent IPC channel.') diff --git a/src/main/ai-vault/session-scanner-service-env.test.ts b/src/main/ai-vault/scan-service/session-scanner-service-env.test.ts similarity index 100% rename from src/main/ai-vault/session-scanner-service-env.test.ts rename to src/main/ai-vault/scan-service/session-scanner-service-env.test.ts diff --git a/src/main/ai-vault/session-scanner-service-env.ts b/src/main/ai-vault/scan-service/session-scanner-service-env.ts similarity index 100% rename from src/main/ai-vault/session-scanner-service-env.ts rename to src/main/ai-vault/scan-service/session-scanner-service-env.ts diff --git a/src/main/ai-vault/session-scanner-service-priority.ts b/src/main/ai-vault/scan-service/session-scanner-service-priority.ts similarity index 100% rename from src/main/ai-vault/session-scanner-service-priority.ts rename to src/main/ai-vault/scan-service/session-scanner-service-priority.ts diff --git a/src/main/ai-vault/session-scanner-service-protocol.ts b/src/main/ai-vault/scan-service/session-scanner-service-protocol.ts similarity index 88% rename from src/main/ai-vault/session-scanner-service-protocol.ts rename to src/main/ai-vault/scan-service/session-scanner-service-protocol.ts index 6feeabf9275..87fb92f0fda 100644 --- a/src/main/ai-vault/session-scanner-service-protocol.ts +++ b/src/main/ai-vault/scan-service/session-scanner-service-protocol.ts @@ -1,21 +1,21 @@ -import type { AiVaultListResult, AiVaultSubagentListResult } from '../../shared/ai-vault-types' +import type { AiVaultListResult, AiVaultSubagentListResult } from '../../../shared/ai-vault-types' import type { AiVaultSessionTitle, AiVaultSessionTitleRequest, AiVaultSessionTitlesResult -} from '../../shared/ai-vault-session-title' +} from '../../../shared/ai-vault-session-title' import type { AiVaultSearchRequest, AiVaultSearchResponse, AiVaultSearchStatus -} from '../../shared/ai-vault-search-types' -import type { AiVaultSearchSettings } from '../../shared/ai-vault-search-settings' -import type { SessionSearchHostScope } from '../ai-vault-search/session-search-service' -import type { SessionSearchScanRoots } from '../ai-vault-search/session-search-scan-roots' -import type { ReadAiVaultFirstUserPromptArgs } from './session-first-user-prompt-read' -import type { SessionParseCachePersistenceOptions } from './session-parse-cache-persistence' -import type { AiVaultScanOptions } from './session-scanner-types' -import type { AiVaultScanWork } from '../../shared/ai-vault-scan-progress' +} from '../../../shared/ai-vault-search-types' +import type { AiVaultSearchSettings } from '../../../shared/ai-vault-search-settings' +import type { SessionSearchHostScope } from '../../ai-vault-search/session-search-service' +import type { SessionSearchScanRoots } from '../../ai-vault-search/session-search-scan-roots' +import type { ReadAiVaultFirstUserPromptArgs } from '../session-first-user-prompt-read' +import type { SessionParseCachePersistenceOptions } from '../parse-cache/session-parse-cache-persistence' +import type { AiVaultScanOptions } from '../session-scanner-types' +import type { AiVaultScanWork } from '../../../shared/ai-vault-scan-progress' export const AI_VAULT_SERVICE_PROTOCOL_VERSION = 1 diff --git a/src/main/ai-vault/session-scanner-service-request-deadline.test.ts b/src/main/ai-vault/scan-service/session-scanner-service-request-deadline.test.ts similarity index 100% rename from src/main/ai-vault/session-scanner-service-request-deadline.test.ts rename to src/main/ai-vault/scan-service/session-scanner-service-request-deadline.test.ts diff --git a/src/main/ai-vault/session-scanner-service-request-deadline.ts b/src/main/ai-vault/scan-service/session-scanner-service-request-deadline.ts similarity index 95% rename from src/main/ai-vault/session-scanner-service-request-deadline.ts rename to src/main/ai-vault/scan-service/session-scanner-service-request-deadline.ts index 1868eb18c30..95105ac4399 100644 --- a/src/main/ai-vault/session-scanner-service-request-deadline.ts +++ b/src/main/ai-vault/scan-service/session-scanner-service-request-deadline.ts @@ -1,6 +1,6 @@ import type { AiVaultServicePendingCall } from './session-scanner-service-client-state' import type { AiVaultServiceRequest } from './session-scanner-service-protocol' -import type { AiVaultScanWork } from '../../shared/ai-vault-scan-progress' +import type { AiVaultScanWork } from '../../../shared/ai-vault-scan-progress' export const AI_VAULT_SERVICE_INTERACTIVE_TIMEOUT_MS = 15_000 diff --git a/src/main/ai-vault/session-scanner-service-restart-policy.test.ts b/src/main/ai-vault/scan-service/session-scanner-service-restart-policy.test.ts similarity index 100% rename from src/main/ai-vault/session-scanner-service-restart-policy.test.ts rename to src/main/ai-vault/scan-service/session-scanner-service-restart-policy.test.ts diff --git a/src/main/ai-vault/session-scanner-service-restart-policy.ts b/src/main/ai-vault/scan-service/session-scanner-service-restart-policy.ts similarity index 100% rename from src/main/ai-vault/session-scanner-service-restart-policy.ts rename to src/main/ai-vault/scan-service/session-scanner-service-restart-policy.ts diff --git a/src/main/ai-vault/session-scanner-service-root-answer.ts b/src/main/ai-vault/scan-service/session-scanner-service-root-answer.ts similarity index 100% rename from src/main/ai-vault/session-scanner-service-root-answer.ts rename to src/main/ai-vault/scan-service/session-scanner-service-root-answer.ts diff --git a/src/main/ai-vault/session-scanner-service-root-request.test.ts b/src/main/ai-vault/scan-service/session-scanner-service-root-request.test.ts similarity index 100% rename from src/main/ai-vault/session-scanner-service-root-request.test.ts rename to src/main/ai-vault/scan-service/session-scanner-service-root-request.test.ts diff --git a/src/main/ai-vault/session-scanner-service-root-request.ts b/src/main/ai-vault/scan-service/session-scanner-service-root-request.ts similarity index 93% rename from src/main/ai-vault/session-scanner-service-root-request.ts rename to src/main/ai-vault/scan-service/session-scanner-service-root-request.ts index 4d510dd2b73..bba7592ba13 100644 --- a/src/main/ai-vault/session-scanner-service-root-request.ts +++ b/src/main/ai-vault/scan-service/session-scanner-service-root-request.ts @@ -1,4 +1,4 @@ -import type { SessionSearchScanRoots } from '../ai-vault-search/session-search-scan-roots' +import type { SessionSearchScanRoots } from '../../ai-vault-search/session-search-scan-roots' import type { AiVaultServiceParentMessage } from './session-scanner-service-protocol' let nextId = 1 diff --git a/src/main/ai-vault/session-scanner-service-root-response.test.ts b/src/main/ai-vault/scan-service/session-scanner-service-root-response.test.ts similarity index 100% rename from src/main/ai-vault/session-scanner-service-root-response.test.ts rename to src/main/ai-vault/scan-service/session-scanner-service-root-response.test.ts diff --git a/src/main/ai-vault/session-scanner-service-search-roots.test.ts b/src/main/ai-vault/scan-service/session-scanner-service-search-roots.test.ts similarity index 87% rename from src/main/ai-vault/session-scanner-service-search-roots.test.ts rename to src/main/ai-vault/scan-service/session-scanner-service-search-roots.test.ts index d25e6415f9d..46dbd5d2a7b 100644 --- a/src/main/ai-vault/session-scanner-service-search-roots.test.ts +++ b/src/main/ai-vault/scan-service/session-scanner-service-search-roots.test.ts @@ -4,13 +4,13 @@ import { openSessionSearchIndexerHarness, writeMessageGraphTranscript, type SessionSearchIndexerHarness -} from '../ai-vault-search/session-search-indexer-test-fixture' -import { SessionSearchIndexer } from '../ai-vault-search/session-search-indexer' -import type { SessionSearchScanRoots } from '../ai-vault-search/session-search-scan-roots' -import { resetSessionParseCacheForTests } from './session-scanner-parse-cache' +} from '../../ai-vault-search/session-search-indexer-test-fixture' +import { SessionSearchIndexer } from '../../ai-vault-search/session-search-indexer' +import type { SessionSearchScanRoots } from '../../ai-vault-search/session-search-scan-roots' +import { resetSessionParseCacheForTests } from '../parse-cache/session-parse-cache-store' import type { AiVaultSessionSearchInit } from './session-scanner-service-protocol' import { SessionScannerServiceSearch } from './session-scanner-service-search' -import { resetTranscriptConsumersForTests } from './session-transcript-consumers' +import { resetTranscriptConsumersForTests } from '../transcripts/session-transcript-consumers' let harness: SessionSearchIndexerHarness let subject: SessionScannerServiceSearch diff --git a/src/main/ai-vault/session-scanner-service-search.test.ts b/src/main/ai-vault/scan-service/session-scanner-service-search.test.ts similarity index 97% rename from src/main/ai-vault/session-scanner-service-search.test.ts rename to src/main/ai-vault/scan-service/session-scanner-service-search.test.ts index 7d6883d967a..94d87da492c 100644 --- a/src/main/ai-vault/session-scanner-service-search.test.ts +++ b/src/main/ai-vault/scan-service/session-scanner-service-search.test.ts @@ -1,12 +1,15 @@ import { existsSync, rmSync } from 'node:fs' import { join } from 'node:path' import { afterAll, beforeAll, expect, it, vi } from 'vitest' -import type { AiVaultSearchResponse, AiVaultSearchStatus } from '../../shared/ai-vault-search-types' +import type { + AiVaultSearchResponse, + AiVaultSearchStatus +} from '../../../shared/ai-vault-search-types' import { openSessionSearchIndexerHarness, writeClaudeTranscript, type SessionSearchIndexerHarness -} from '../ai-vault-search/session-search-indexer-test-fixture' +} from '../../ai-vault-search/session-search-indexer-test-fixture' import { AI_VAULT_SERVICE_PROTOCOL_VERSION, type AiVaultServiceChildMessage, diff --git a/src/main/ai-vault/session-scanner-service-search.ts b/src/main/ai-vault/scan-service/session-scanner-service-search.ts similarity index 84% rename from src/main/ai-vault/session-scanner-service-search.ts rename to src/main/ai-vault/scan-service/session-scanner-service-search.ts index e373cb0e8e6..9432e8b4aaa 100644 --- a/src/main/ai-vault/session-scanner-service-search.ts +++ b/src/main/ai-vault/scan-service/session-scanner-service-search.ts @@ -1,12 +1,12 @@ -import type { SessionSearchIndexerOptions } from '../ai-vault-search/session-search-indexer-options' -import { unavailableSessionSearchStatus } from '../../shared/ai-vault-search-client' -import { AiVaultSearchRequestSchema } from '../../shared/ai-vault-search-contract' -import { SessionSearchInstance } from '../ai-vault-search/session-search-instance' +import type { SessionSearchIndexerOptions } from '../../ai-vault-search/session-search-indexer-options' +import { unavailableSessionSearchStatus } from '../../../shared/ai-vault-search-client' +import { AiVaultSearchRequestSchema } from '../../../shared/ai-vault-search-contract' +import { SessionSearchInstance } from '../../ai-vault-search/session-search-instance' import { sameSessionSearchRoots, type SessionSearchScanRoots -} from '../ai-vault-search/session-search-scan-roots' -import { sessionSearchSqliteAvailable } from '../ai-vault-search/session-search-sqlite-support' +} from '../../ai-vault-search/session-search-scan-roots' +import { sessionSearchSqliteAvailable } from '../../ai-vault-search/session-search-sqlite-support' import type { AiVaultServiceRequest, AiVaultServiceResultValue, diff --git a/src/main/ai-vault/session-scanner-service-spawn.test.ts b/src/main/ai-vault/scan-service/session-scanner-service-spawn.test.ts similarity index 100% rename from src/main/ai-vault/session-scanner-service-spawn.test.ts rename to src/main/ai-vault/scan-service/session-scanner-service-spawn.test.ts diff --git a/src/main/ai-vault/session-scanner-service-spawn.ts b/src/main/ai-vault/scan-service/session-scanner-service-spawn.ts similarity index 89% rename from src/main/ai-vault/session-scanner-service-spawn.ts rename to src/main/ai-vault/scan-service/session-scanner-service-spawn.ts index 58277ea4a71..57fe3353415 100644 --- a/src/main/ai-vault/session-scanner-service-spawn.ts +++ b/src/main/ai-vault/scan-service/session-scanner-service-spawn.ts @@ -1,24 +1,24 @@ -import { localAiVaultScanRoots } from './cached-session-list' -import type { SessionSearchHostScope } from '../ai-vault-search/session-search-service' +import { localAiVaultScanRoots } from '../cached-session-list' +import type { SessionSearchHostScope } from '../../ai-vault-search/session-search-service' import { fork, type ChildProcess } from 'node:child_process' import { existsSync } from 'node:fs' import type { AiVaultSearchRequest, AiVaultSearchResponse, AiVaultSearchStatus -} from '../../shared/ai-vault-search-types' -import type { AiVaultListResult, AiVaultSubagentListResult } from '../../shared/ai-vault-types' +} from '../../../shared/ai-vault-search-types' +import type { AiVaultListResult, AiVaultSubagentListResult } from '../../../shared/ai-vault-types' import type { AiVaultSessionTitleRequest, AiVaultSessionTitlesResult -} from '../../shared/ai-vault-session-title' -import { withSpan } from '../observability/tracer' +} from '../../../shared/ai-vault-session-title' +import { withSpan } from '../../observability/tracer' import type { ReadAiVaultFirstUserPromptArgs, ReadAiVaultFirstUserPromptResult -} from './session-first-user-prompt-read' -import { sessionSearchServiceInit } from '../ai-vault-search/session-search-service-init' -import { getSessionParseCachePersistenceOptions } from './session-parse-cache-persistence' +} from '../session-first-user-prompt-read' +import { sessionSearchServiceInit } from '../../ai-vault-search/session-search-service-init' +import { getSessionParseCachePersistenceOptions } from '../parse-cache/session-parse-cache-persistence' import { buildAiVaultServiceEnv } from './session-scanner-service-env' import { AiVaultScannerServiceClient } from './session-scanner-service-client' import { getAiVaultServiceEntryPath } from './session-scanner-service-entry-path' @@ -32,7 +32,7 @@ import type { import { requestLocalAiVaultScan, type LocalAiVaultScanProgressHandle -} from './ai-vault-local-scan-progress' +} from '../ai-vault-local-scan-progress' export function spawnAiVaultServiceProcess(): ChildProcess { const entryPath = getAiVaultServiceEntryPath() diff --git a/src/main/ai-vault/session-scanner-service-test-child.ts b/src/main/ai-vault/scan-service/session-scanner-service-test-child.ts similarity index 100% rename from src/main/ai-vault/session-scanner-service-test-child.ts rename to src/main/ai-vault/scan-service/session-scanner-service-test-child.ts diff --git a/src/main/ai-vault/session-scanner-service-wsl-notes.ts b/src/main/ai-vault/scan-service/session-scanner-service-wsl-notes.ts similarity index 85% rename from src/main/ai-vault/session-scanner-service-wsl-notes.ts rename to src/main/ai-vault/scan-service/session-scanner-service-wsl-notes.ts index 36ce6caac64..5a90efff331 100644 --- a/src/main/ai-vault/session-scanner-service-wsl-notes.ts +++ b/src/main/ai-vault/scan-service/session-scanner-service-wsl-notes.ts @@ -1,4 +1,4 @@ -import { onWslDistroGateNote } from '../wsl/discovery/wsl-background-distro-gate' +import { onWslDistroGateNote } from '../../wsl/discovery/wsl-background-distro-gate' type WslNoteChannel = { send(message: unknown, callback: (error: Error | null) => void): boolean diff --git a/src/main/ai-vault/antigravity-history-prompt.ts b/src/main/ai-vault/scanners/antigravity/antigravity-history-prompt.ts similarity index 81% rename from src/main/ai-vault/antigravity-history-prompt.ts rename to src/main/ai-vault/scanners/antigravity/antigravity-history-prompt.ts index cc40dd3010a..b619bbbb315 100644 --- a/src/main/ai-vault/antigravity-history-prompt.ts +++ b/src/main/ai-vault/scanners/antigravity/antigravity-history-prompt.ts @@ -1,5 +1,5 @@ import { createHash } from 'node:crypto' -import { normalizeTitleText } from './session-scanner-values' +import { normalizeTitleText } from '../../session-scanner-text-normalization' export function antigravityHistoryPromptHash(value: unknown): string | null { if (typeof value !== 'string' || value.length > 4096) { diff --git a/src/main/ai-vault/antigravity-ide-history.test.ts b/src/main/ai-vault/scanners/antigravity/antigravity-ide-history.test.ts similarity index 97% rename from src/main/ai-vault/antigravity-ide-history.test.ts rename to src/main/ai-vault/scanners/antigravity/antigravity-ide-history.test.ts index 626fe199668..7c1045f384d 100644 --- a/src/main/ai-vault/antigravity-ide-history.test.ts +++ b/src/main/ai-vault/scanners/antigravity/antigravity-ide-history.test.ts @@ -3,9 +3,9 @@ import { mkdtemp, mkdir, rm, writeFile, utimes } from 'node:fs/promises' import { tmpdir } from 'node:os' import { dirname, join } from 'node:path' import { afterEach, describe, expect, it } from 'vitest' -import { scanAiVaultSessions } from './session-scanner' -import { isolatedScanRoots, writeAntigravityTranscript } from './session-scanner-test-fixtures' -import { antigravitySessionOrigin } from '../../shared/antigravity-session-origin' +import { scanAiVaultSessions } from '../../session-scanner' +import { isolatedScanRoots, writeAntigravityTranscript } from '../../session-scanner-test-fixtures' +import { antigravitySessionOrigin } from '../../../../shared/antigravity-session-origin' import { readLocalAntigravityHistory } from './session-scanner-antigravity-history' import { ANTIGRAVITY_INDEX_MAX_BYTES } from './session-scanner-antigravity-metadata' diff --git a/src/main/ai-vault/antigravity-index-file-admission.test.ts b/src/main/ai-vault/scanners/antigravity/antigravity-index-file-admission.test.ts similarity index 97% rename from src/main/ai-vault/antigravity-index-file-admission.test.ts rename to src/main/ai-vault/scanners/antigravity/antigravity-index-file-admission.test.ts index e9a9b3e1eb4..4102f0fafb0 100644 --- a/src/main/ai-vault/antigravity-index-file-admission.test.ts +++ b/src/main/ai-vault/scanners/antigravity/antigravity-index-file-admission.test.ts @@ -21,7 +21,7 @@ vi.mock('node:fs/promises', async (original) => { } } }) -import { readNodeFileWithinLimit } from '../../shared/node-bounded-file-reader' +import { readNodeFileWithinLimit } from '../../../../shared/node-bounded-file-reader' import { readLocalAntigravityHistory } from './session-scanner-antigravity-history' const roots: string[] = [] diff --git a/src/main/ai-vault/antigravity-opening-prompt-workspace.test.ts b/src/main/ai-vault/scanners/antigravity/antigravity-opening-prompt-workspace.test.ts similarity index 99% rename from src/main/ai-vault/antigravity-opening-prompt-workspace.test.ts rename to src/main/ai-vault/scanners/antigravity/antigravity-opening-prompt-workspace.test.ts index 54f294124ab..512dd0552fe 100644 --- a/src/main/ai-vault/antigravity-opening-prompt-workspace.test.ts +++ b/src/main/ai-vault/scanners/antigravity/antigravity-opening-prompt-workspace.test.ts @@ -4,7 +4,7 @@ import { createAntigravitySessionResumeState, parseAntigravitySessionContent } from './session-scanner-antigravity-parser' -import { jsonLines } from './session-scanner-test-fixtures' +import { jsonLines } from '../../session-scanner-test-fixtures' const openingTime = '2026-07-15T11:39:10.000Z' const historyPath = '/home/ada/.gemini/antigravity-cli/history.jsonl' diff --git a/src/main/ai-vault/antigravity-recorded-history.test.ts b/src/main/ai-vault/scanners/antigravity/antigravity-recorded-history.test.ts similarity index 91% rename from src/main/ai-vault/antigravity-recorded-history.test.ts rename to src/main/ai-vault/scanners/antigravity/antigravity-recorded-history.test.ts index 64c7e8380c3..b474601475d 100644 --- a/src/main/ai-vault/antigravity-recorded-history.test.ts +++ b/src/main/ai-vault/scanners/antigravity/antigravity-recorded-history.test.ts @@ -2,9 +2,9 @@ import { homedir, tmpdir } from 'node:os' import { join } from 'node:path' import { mkdtemp, rm, stat, writeFile } from 'node:fs/promises' import { expect, it } from 'vitest' -import { scanAiVaultSessions } from './session-scanner' -import { isolatedScanRoots } from './session-scanner-test-fixtures' -import { antigravitySessionOrigin } from '../../shared/antigravity-session-origin' +import { scanAiVaultSessions } from '../../session-scanner' +import { isolatedScanRoots } from '../../session-scanner-test-fixtures' +import { antigravitySessionOrigin } from '../../../../shared/antigravity-session-origin' it.skipIf(process.env.ORCA_REAL_ANTIGRAVITY_HISTORY !== '1')( 'scans bounded existing official artifacts without publishing their content', diff --git a/src/main/ai-vault/antigravity-transcript-candidates.ts b/src/main/ai-vault/scanners/antigravity/antigravity-transcript-candidates.ts similarity index 89% rename from src/main/ai-vault/antigravity-transcript-candidates.ts rename to src/main/ai-vault/scanners/antigravity/antigravity-transcript-candidates.ts index 46c474fd2f7..6f3fc771cab 100644 --- a/src/main/ai-vault/antigravity-transcript-candidates.ts +++ b/src/main/ai-vault/scanners/antigravity/antigravity-transcript-candidates.ts @@ -1,9 +1,9 @@ import { dirname, join } from 'node:path' -import { wslGatedLstat } from '../native-chat/wsl-transcript-fs-access' -import { WslTranscriptFsError } from '../native-chat/wsl-transcript-fs-gate' -import type { AiVaultScanIssue } from '../../shared/ai-vault-types' -import { recordSessionScanIssue, scanIssueTextFromError } from './session-scan-issues' -import type { FileWithMtime, SessionFileDiscovery } from './session-scanner-types' +import { wslGatedLstat } from '../../../native-chat/wsl-transcript-fs-access' +import { WslTranscriptFsError } from '../../../native-chat/wsl-transcript-fs-error' +import type { AiVaultScanIssue } from '../../../../shared/ai-vault-types' +import { recordSessionScanIssue, scanIssueTextFromError } from '../../session-scan-issues' +import type { FileWithMtime, SessionFileDiscovery } from '../../session-scanner-types' function transcriptDirectory(file: FileWithMtime): string { return file.path diff --git a/src/main/ai-vault/session-scanner-antigravity-fixtures.ts b/src/main/ai-vault/scanners/antigravity/session-scanner-antigravity-fixtures.ts similarity index 91% rename from src/main/ai-vault/session-scanner-antigravity-fixtures.ts rename to src/main/ai-vault/scanners/antigravity/session-scanner-antigravity-fixtures.ts index cbcab494933..cf0f45ee971 100644 --- a/src/main/ai-vault/session-scanner-antigravity-fixtures.ts +++ b/src/main/ai-vault/scanners/antigravity/session-scanner-antigravity-fixtures.ts @@ -1,4 +1,4 @@ -import type { IncrementalAgentFixture } from './session-scanner-incremental-fixtures' +import type { IncrementalAgentFixture } from '../../session-scanner-incremental-fixtures' export function antigravityFixture(): IncrementalAgentFixture { const record = (source: string, type: string, content: string, createdAt: string) => diff --git a/src/main/ai-vault/session-scanner-antigravity-history.ts b/src/main/ai-vault/scanners/antigravity/session-scanner-antigravity-history.ts similarity index 90% rename from src/main/ai-vault/session-scanner-antigravity-history.ts rename to src/main/ai-vault/scanners/antigravity/session-scanner-antigravity-history.ts index 01d54496308..7a721e41995 100644 --- a/src/main/ai-vault/session-scanner-antigravity-history.ts +++ b/src/main/ai-vault/scanners/antigravity/session-scanner-antigravity-history.ts @@ -4,13 +4,16 @@ import { antigravityMetadataWorkspaces, readBoundedAntigravityIndex } from './session-scanner-antigravity-metadata' -import type { AiVaultSession } from '../../shared/ai-vault-types' -import { openTranscriptReadStream, wslGatedStat } from '../native-chat/wsl-transcript-fs-access' -import { readNodeFileWithinLimit } from '../../shared/node-bounded-file-reader' -import { isWslUncPath } from '../../shared/wsl-paths' -import { throwIfAiVaultScanCancelled } from './ai-vault-scan-cancellation' -import { WslTranscriptFsError } from '../native-chat/wsl-transcript-fs-gate' -import { parseJsonObject, timestampMs } from './session-scanner-values' +import type { AiVaultSession } from '../../../../shared/ai-vault-types' +import { + openTranscriptReadStream, + wslGatedStat +} from '../../../native-chat/wsl-transcript-fs-access' +import { readNodeFileWithinLimit } from '../../../../shared/node-bounded-file-reader' +import { isWslUncPath } from '../../../../shared/wsl-paths' +import { throwIfAiVaultScanCancelled } from '../../ai-vault-scan-cancellation' +import { WslTranscriptFsError } from '../../../native-chat/wsl-transcript-fs-error' +import { parseJsonObject, timestampMs } from '../../session-scanner-values' import { antigravityHistoryPromptHash } from './antigravity-history-prompt' const HISTORY_MATCH_WINDOW_MS = 2_000 diff --git a/src/main/ai-vault/session-scanner-antigravity-metadata.ts b/src/main/ai-vault/scanners/antigravity/session-scanner-antigravity-metadata.ts similarity index 97% rename from src/main/ai-vault/session-scanner-antigravity-metadata.ts rename to src/main/ai-vault/scanners/antigravity/session-scanner-antigravity-metadata.ts index 1f1c4263fd0..1ced4f014fa 100644 --- a/src/main/ai-vault/session-scanner-antigravity-metadata.ts +++ b/src/main/ai-vault/scanners/antigravity/session-scanner-antigravity-metadata.ts @@ -1,4 +1,4 @@ -import { parseJsonObject } from './session-scanner-values' +import { parseJsonObject } from '../../session-scanner-values' export const ANTIGRAVITY_INDEX_MAX_BYTES = 4 * 1024 * 1024 const MAX_INDEX_ENTRIES = 10_000 diff --git a/src/main/ai-vault/session-scanner-antigravity-parser.test.ts b/src/main/ai-vault/scanners/antigravity/session-scanner-antigravity-parser.test.ts similarity index 96% rename from src/main/ai-vault/session-scanner-antigravity-parser.test.ts rename to src/main/ai-vault/scanners/antigravity/session-scanner-antigravity-parser.test.ts index c8d037098ca..b9f2d15d623 100644 --- a/src/main/ai-vault/session-scanner-antigravity-parser.test.ts +++ b/src/main/ai-vault/scanners/antigravity/session-scanner-antigravity-parser.test.ts @@ -1,7 +1,7 @@ import { describe, expect, it } from 'vitest' import { parseAntigravitySessionContent } from './session-scanner-antigravity-parser' -import type { FileWithMtime } from './session-scanner-types' -import { jsonLines } from './session-scanner-test-fixtures' +import type { FileWithMtime } from '../../session-scanner-types' +import { jsonLines } from '../../session-scanner-test-fixtures' const SESSION_ID = 'aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee' diff --git a/src/main/ai-vault/session-scanner-antigravity-parser.ts b/src/main/ai-vault/scanners/antigravity/session-scanner-antigravity-parser.ts similarity index 84% rename from src/main/ai-vault/session-scanner-antigravity-parser.ts rename to src/main/ai-vault/scanners/antigravity/session-scanner-antigravity-parser.ts index e875d07a7b8..c41777dad81 100644 --- a/src/main/ai-vault/session-scanner-antigravity-parser.ts +++ b/src/main/ai-vault/scanners/antigravity/session-scanner-antigravity-parser.ts @@ -1,27 +1,28 @@ import { remoteSessionContentLines, type RemoteSessionContent -} from './remote-session-content-lines' -import { consumeCompleteJsonlLines } from './session-scanner-jsonl-reader' -import { MAX_SESSION_TRANSCRIPT_RECORD_BYTES } from './session-transcript-record-budget' -import type { AiVaultSession } from '../../shared/ai-vault-types' -import type { ExecutionHostId } from '../../shared/execution-host' +} from '../../transcripts/remote-session-content-lines' +import { consumeCompleteJsonlLines } from '../../session-scanner-jsonl-reader' +import { MAX_SESSION_TRANSCRIPT_RECORD_BYTES } from '../../transcripts/session-transcript-record-budget' +import type { AiVaultSession } from '../../../../shared/ai-vault-types' +import type { ExecutionHostId } from '../../../../shared/execution-host' import { accumulatorFoldResumeState, createAccumulator, timestampIso, updateTimeline -} from './session-scanner-accumulator' -import { addSessionText } from './session-scanner-messages' +} from '../../session-scanner-accumulator' +import { addSessionText } from '../../session-scanner-messages' import { antigravityConversationIdFromTranscriptPath } from './session-scanner-antigravity-paths' import { antigravityHistoryPromptHash } from './antigravity-history-prompt' import type { FileWithMtime, ResumableSessionParseState, SessionAccumulator -} from './session-scanner-types' -import type { TranscriptMessageSink } from './session-transcript-consumers' -import { extractString, normalizeTitleText, parseJsonObject } from './session-scanner-values' +} from '../../session-scanner-types' +import type { TranscriptMessageSink } from '../../transcripts/session-transcript-consumers' +import { extractString, parseJsonObject } from '../../session-scanner-values' +import { normalizeTitleText } from '../../session-scanner-text-normalization' type ParserSessionOptions = { executionHostId?: ExecutionHostId diff --git a/src/main/ai-vault/session-scanner-antigravity-paths.ts b/src/main/ai-vault/scanners/antigravity/session-scanner-antigravity-paths.ts similarity index 100% rename from src/main/ai-vault/session-scanner-antigravity-paths.ts rename to src/main/ai-vault/scanners/antigravity/session-scanner-antigravity-paths.ts diff --git a/src/main/ai-vault/session-scanner-antigravity-source.test.ts b/src/main/ai-vault/scanners/antigravity/session-scanner-antigravity-source.test.ts similarity index 95% rename from src/main/ai-vault/session-scanner-antigravity-source.test.ts rename to src/main/ai-vault/scanners/antigravity/session-scanner-antigravity-source.test.ts index 43e5526ae88..d7704befaa3 100644 --- a/src/main/ai-vault/session-scanner-antigravity-source.test.ts +++ b/src/main/ai-vault/scanners/antigravity/session-scanner-antigravity-source.test.ts @@ -2,14 +2,14 @@ import { mkdtemp, rm, writeFile } from 'node:fs/promises' import { tmpdir } from 'node:os' import { dirname, join } from 'node:path' import { afterEach, describe, expect, it } from 'vitest' -import { filterAiVaultSessions } from '../../shared/ai-vault-session-filters' -import { AI_VAULT_AGENTS } from '../../shared/ai-vault-types' -import { scanAiVaultSessions } from './session-scanner' +import { filterAiVaultSessions } from '../../../../shared/ai-vault-session-filters' +import { AI_VAULT_AGENTS } from '../../../../shared/ai-vault-types' +import { scanAiVaultSessions } from '../../session-scanner' import { isolatedScanRoots, writeAntigravityHistory, writeAntigravityTranscript -} from './session-scanner-test-fixtures' +} from '../../session-scanner-test-fixtures' const tempRoots: string[] = [] diff --git a/src/main/ai-vault/session-scanner-antigravity-sources.ts b/src/main/ai-vault/scanners/antigravity/session-scanner-antigravity-sources.ts similarity index 84% rename from src/main/ai-vault/session-scanner-antigravity-sources.ts rename to src/main/ai-vault/scanners/antigravity/session-scanner-antigravity-sources.ts index a7749255ec6..abcf9305163 100644 --- a/src/main/ai-vault/session-scanner-antigravity-sources.ts +++ b/src/main/ai-vault/scanners/antigravity/session-scanner-antigravity-sources.ts @@ -1,15 +1,15 @@ import { completeAntigravityTranscriptPairs } from './antigravity-transcript-candidates' -import { ANTIGRAVITY_HISTORY_ROOTS } from '../../shared/antigravity-session-origin' +import { ANTIGRAVITY_HISTORY_ROOTS } from '../../../../shared/antigravity-session-origin' import { homedir } from 'node:os' import { join } from 'node:path' -import type { AiVaultScanIssue } from '../../shared/ai-vault-types' +import type { AiVaultScanIssue } from '../../../../shared/ai-vault-types' import { isAntigravityTranscriptPath, shouldDescendAntigravityBrainDirectory } from './session-scanner-antigravity-paths' -import { discoverFiles } from './session-scanner-discovery' -import type { AiVaultScanOptions, SessionFileDiscovery } from './session-scanner-types' -import { scopeWalksAgentFiles } from './session-scope-cwd' +import { discoverFiles } from '../../session-scanner-discovery' +import type { AiVaultScanOptions, SessionFileDiscovery } from '../../session-scanner-types' +import { scopeWalksAgentFiles } from '../../session-scope-cwd' export function antigravityDiscoveries( options: AiVaultScanOptions, diff --git a/src/main/ai-vault/claude-project-dir-encoding.test.ts b/src/main/ai-vault/scanners/claude/claude-project-dir-encoding.test.ts similarity index 100% rename from src/main/ai-vault/claude-project-dir-encoding.test.ts rename to src/main/ai-vault/scanners/claude/claude-project-dir-encoding.test.ts diff --git a/src/main/ai-vault/claude-project-dir-encoding.ts b/src/main/ai-vault/scanners/claude/claude-project-dir-encoding.ts similarity index 92% rename from src/main/ai-vault/claude-project-dir-encoding.ts rename to src/main/ai-vault/scanners/claude/claude-project-dir-encoding.ts index 51b305c3fbb..6719a8a78ad 100644 --- a/src/main/ai-vault/claude-project-dir-encoding.ts +++ b/src/main/ai-vault/scanners/claude/claude-project-dir-encoding.ts @@ -1,4 +1,4 @@ -import { normalizeRuntimePathSeparators } from '../../shared/cross-platform-path' +import { normalizeRuntimePathSeparators } from '../../../../shared/cross-platform-path' /** Encode case-preserving raw paths and NFC variants; comparison keys lose Windows case and macOS can supply NFD. */ export function encodeClaudeProjectPaths(pathValue: string): string[] { diff --git a/src/main/ai-vault/session-scanner-claude-cwd-drift.test.ts b/src/main/ai-vault/scanners/claude/session-scanner-claude-cwd-drift.test.ts similarity index 92% rename from src/main/ai-vault/session-scanner-claude-cwd-drift.test.ts rename to src/main/ai-vault/scanners/claude/session-scanner-claude-cwd-drift.test.ts index 2ca2ec2ef11..2924f9a54ca 100644 --- a/src/main/ai-vault/session-scanner-claude-cwd-drift.test.ts +++ b/src/main/ai-vault/scanners/claude/session-scanner-claude-cwd-drift.test.ts @@ -2,8 +2,8 @@ import { mkdtemp, mkdir, rm, writeFile } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, describe, expect, it } from 'vitest' -import { scanAiVaultSessions } from './session-scanner' -import { isolatedScanRoots, jsonLines } from './session-scanner-test-fixtures' +import { scanAiVaultSessions } from '../../session-scanner' +import { isolatedScanRoots, jsonLines } from '../../session-scanner-test-fixtures' let tempRoots: string[] = [] diff --git a/src/main/ai-vault/session-scanner-claude-subagent-prune.test.ts b/src/main/ai-vault/scanners/claude/session-scanner-claude-subagent-prune.test.ts similarity index 92% rename from src/main/ai-vault/session-scanner-claude-subagent-prune.test.ts rename to src/main/ai-vault/scanners/claude/session-scanner-claude-subagent-prune.test.ts index 9e454baaf39..d709b3383f2 100644 --- a/src/main/ai-vault/session-scanner-claude-subagent-prune.test.ts +++ b/src/main/ai-vault/scanners/claude/session-scanner-claude-subagent-prune.test.ts @@ -2,8 +2,8 @@ import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, describe, expect, it } from 'vitest' -import { scanAiVaultSessions } from './session-scanner' -import { isolatedScanRoots, jsonLines } from './session-scanner-test-fixtures' +import { scanAiVaultSessions } from '../../session-scanner' +import { isolatedScanRoots, jsonLines } from '../../session-scanner-test-fixtures' let tempRoots: string[] = [] diff --git a/src/main/ai-vault/session-scanner-claude-subagents.test.ts b/src/main/ai-vault/scanners/claude/session-scanner-claude-subagents.test.ts similarity index 100% rename from src/main/ai-vault/session-scanner-claude-subagents.test.ts rename to src/main/ai-vault/scanners/claude/session-scanner-claude-subagents.test.ts diff --git a/src/main/ai-vault/session-scanner-claude-subagents.ts b/src/main/ai-vault/scanners/claude/session-scanner-claude-subagents.ts similarity index 93% rename from src/main/ai-vault/session-scanner-claude-subagents.ts rename to src/main/ai-vault/scanners/claude/session-scanner-claude-subagents.ts index 3ae64bac2fd..3c616d94eb4 100644 --- a/src/main/ai-vault/session-scanner-claude-subagents.ts +++ b/src/main/ai-vault/scanners/claude/session-scanner-claude-subagents.ts @@ -5,32 +5,29 @@ import type { AiVaultSession, AiVaultSubagentListResult, AiVaultSubagentRunStatus -} from '../../shared/ai-vault-types' +} from '../../../../shared/ai-vault-types' import { CLAUDE_TASK_NOTIFICATION_MARKER, readClaudeTaskNotification -} from '../../shared/claude-task-notification-text' +} from '../../../../shared/claude-task-notification-text' import { openTranscriptReadStream, wslGatedReaddir, wslGatedReadFile, wslGatedStat -} from '../native-chat/wsl-transcript-fs-access' -import { WslTranscriptFsError } from '../native-chat/wsl-transcript-fs-gate' -import { recordSessionScanIssue, scanIssueTextFromError } from './session-scan-issues' -import { sessionIdFromFileName, sessionSortTime } from './session-scanner-accumulator' +} from '../../../native-chat/wsl-transcript-fs-access' +import { WslTranscriptFsError } from '../../../native-chat/wsl-transcript-fs-error' +import { recordSessionScanIssue, scanIssueTextFromError } from '../../session-scan-issues' +import { sessionIdFromFileName, sessionSortTime } from '../../session-scanner-accumulator' import { parseClaudeSessionFile } from './session-scanner-primary-parsers' import { isSubagentTranscriptFileName, subagentTranscriptsDirFor, SUBAGENT_TRANSCRIPT_PREFIX } from './session-scanner-subagent-transcripts' -import { - asRecord, - extractString, - normalizeTitleText, - parseJsonObject -} from './session-scanner-values' +import { asRecord } from '../../session-scanner-record-value' +import { extractString, parseJsonObject } from '../../session-scanner-values' +import { normalizeTitleText } from '../../session-scanner-text-normalization' // Without a terminal report, old transcripts have unknown status rather than remaining running. const SUBAGENT_RUNNING_RECENCY_MS = 5 * 60_000 diff --git a/src/main/ai-vault/session-scanner-claude-title.test.ts b/src/main/ai-vault/scanners/claude/session-scanner-claude-title.test.ts similarity index 93% rename from src/main/ai-vault/session-scanner-claude-title.test.ts rename to src/main/ai-vault/scanners/claude/session-scanner-claude-title.test.ts index e1eef0df48a..41d0147fe4d 100644 --- a/src/main/ai-vault/session-scanner-claude-title.test.ts +++ b/src/main/ai-vault/scanners/claude/session-scanner-claude-title.test.ts @@ -2,8 +2,8 @@ import { mkdtemp, rm } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, describe, expect, it } from 'vitest' -import { scanAiVaultSessions } from './session-scanner' -import { isolatedScanRoots, writeJsonlFile } from './session-scanner-test-fixtures' +import { scanAiVaultSessions } from '../../session-scanner' +import { isolatedScanRoots, writeJsonlFile } from '../../session-scanner-test-fixtures' let tempRoots: string[] = [] diff --git a/src/main/ai-vault/session-scanner-claude-unicode-scope.test.ts b/src/main/ai-vault/scanners/claude/session-scanner-claude-unicode-scope.test.ts similarity index 94% rename from src/main/ai-vault/session-scanner-claude-unicode-scope.test.ts rename to src/main/ai-vault/scanners/claude/session-scanner-claude-unicode-scope.test.ts index 3ab168b0ee4..9f95aa1b0bf 100644 --- a/src/main/ai-vault/session-scanner-claude-unicode-scope.test.ts +++ b/src/main/ai-vault/scanners/claude/session-scanner-claude-unicode-scope.test.ts @@ -2,9 +2,9 @@ import { mkdtemp, mkdir, rm, writeFile } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, describe, expect, it } from 'vitest' -import { scanAiVaultSessions } from './session-scanner' -import { resetProjectDirCwdCacheForTests } from './session-scanner-scope-discovery' -import { isolatedScanRoots, jsonLines } from './session-scanner-test-fixtures' +import { scanAiVaultSessions } from '../../session-scanner' +import { resetProjectDirCwdCacheForTests } from '../../session-scanner-scope-discovery' +import { isolatedScanRoots, jsonLines } from '../../session-scanner-test-fixtures' let tempRoots: string[] = [] diff --git a/src/main/ai-vault/session-scanner-primary-parsers.ts b/src/main/ai-vault/scanners/claude/session-scanner-primary-parsers.ts similarity index 88% rename from src/main/ai-vault/session-scanner-primary-parsers.ts rename to src/main/ai-vault/scanners/claude/session-scanner-primary-parsers.ts index c3807f2e415..0c72549ab31 100644 --- a/src/main/ai-vault/session-scanner-primary-parsers.ts +++ b/src/main/ai-vault/scanners/claude/session-scanner-primary-parsers.ts @@ -1,19 +1,19 @@ import { remoteSessionContentLines, type RemoteSessionContent -} from './remote-session-content-lines' -import { openTranscriptReadStream } from '../native-chat/wsl-transcript-fs-access' +} from '../../transcripts/remote-session-content-lines' +import { openTranscriptReadStream } from '../../../native-chat/wsl-transcript-fs-access' import { createInterface } from 'node:readline' -import type { AiVaultSession } from '../../shared/ai-vault-types' -import { LOCAL_EXECUTION_HOST_ID, type ExecutionHostId } from '../../shared/execution-host' -import { isKnownHarnessInjectedUserTurnText } from '../../shared/harness-injected-user-turns' -import { normalizePromptField } from '../../shared/agent-status-field-normalization' +import type { AiVaultSession } from '../../../../shared/ai-vault-types' +import { LOCAL_EXECUTION_HOST_ID, type ExecutionHostId } from '../../../../shared/execution-host' +import { isKnownHarnessInjectedUserTurnText } from '../../../../shared/harness-injected-user-turns' +import { normalizePromptField } from '../../../../shared/agent-status-field-normalization' import type { FileWithMtime, ResumableSessionParseState, SessionAccumulator -} from './session-scanner-types' -import type { TranscriptMessageSink } from './session-transcript-consumers' +} from '../../session-scanner-types' +import type { TranscriptMessageSink } from '../../transcripts/session-transcript-consumers' import { accumulatorSessionIdentity, createAccumulator, @@ -21,17 +21,13 @@ import { sessionIdFromFileName, updateLatestLocation, updateTimeline -} from './session-scanner-accumulator' -import { addSessionContent } from './session-scanner-messages' +} from '../../session-scanner-accumulator' +import { addSessionContent } from '../../session-scanner-messages' import { countSubagentTranscripts } from './session-scanner-subagent-transcripts' -import { - asRecord, - claudeUsageTotal, - extractMessageText, - extractString, - normalizeTitleText, - parseJsonObject -} from './session-scanner-values' +import { asRecord } from '../../session-scanner-record-value' +import { claudeUsageTotal } from '../../session-scanner-token-values' +import { extractMessageText, normalizeTitleText } from '../../session-scanner-text-normalization' +import { extractString, parseJsonObject } from '../../session-scanner-values' type ParserSessionOptions = { executionHostId?: ExecutionHostId diff --git a/src/main/ai-vault/session-scanner-subagent-transcripts.ts b/src/main/ai-vault/scanners/claude/session-scanner-subagent-transcripts.ts similarity index 93% rename from src/main/ai-vault/session-scanner-subagent-transcripts.ts rename to src/main/ai-vault/scanners/claude/session-scanner-subagent-transcripts.ts index 2eb43e06375..adc9dc3bef0 100644 --- a/src/main/ai-vault/session-scanner-subagent-transcripts.ts +++ b/src/main/ai-vault/scanners/claude/session-scanner-subagent-transcripts.ts @@ -1,4 +1,4 @@ -import { wslGatedReaddir } from '../native-chat/wsl-transcript-fs-access' +import { wslGatedReaddir } from '../../../native-chat/wsl-transcript-fs-access' import { basename, dirname, extname, join } from 'node:path' export const SUBAGENT_DIR_NAME = 'subagents' diff --git a/src/main/ai-vault/session-scanner-cline-parser.test.ts b/src/main/ai-vault/scanners/cline/session-scanner-cline-parser.test.ts similarity index 97% rename from src/main/ai-vault/session-scanner-cline-parser.test.ts rename to src/main/ai-vault/scanners/cline/session-scanner-cline-parser.test.ts index 6d96bcb114f..564dc0f3bf1 100644 --- a/src/main/ai-vault/session-scanner-cline-parser.test.ts +++ b/src/main/ai-vault/scanners/cline/session-scanner-cline-parser.test.ts @@ -2,8 +2,8 @@ import { mkdtemp, mkdir, rm, writeFile } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, describe, expect, it } from 'vitest' -import { scanAiVaultSessions } from './session-scanner' -import { isolatedScanRoots } from './session-scanner-test-fixtures' +import { scanAiVaultSessions } from '../../session-scanner' +import { isolatedScanRoots } from '../../session-scanner-test-fixtures' let tempRoots: string[] = [] diff --git a/src/main/ai-vault/session-scanner-cline-parser.ts b/src/main/ai-vault/scanners/cline/session-scanner-cline-parser.ts similarity index 81% rename from src/main/ai-vault/session-scanner-cline-parser.ts rename to src/main/ai-vault/scanners/cline/session-scanner-cline-parser.ts index d7abcef0609..55050e423dc 100644 --- a/src/main/ai-vault/session-scanner-cline-parser.ts +++ b/src/main/ai-vault/scanners/cline/session-scanner-cline-parser.ts @@ -1,22 +1,22 @@ -import { isMissingRemoteSessionPathError } from './remote-session-file-stat' -import { BinarySessionTranscriptError } from './remote-session-content-lines' -import { readStreamedSessionDocument } from './session-document-stream' -import { openTranscriptReadStream } from '../native-chat/wsl-transcript-fs-access' -import { WslTranscriptFsError } from '../native-chat/wsl-transcript-fs-gate' -import type { AiVaultSession } from '../../shared/ai-vault-types' -import { clineMessagesPathForMetadata } from '../../shared/ai-vault-session-log-resource' -import type { ExecutionHostId } from '../../shared/execution-host' -import { createAccumulator, finalizeSession, updateTimeline } from './session-scanner-accumulator' -import { addSessionContent } from './session-scanner-messages' -import type { FileWithMtime, SessionAccumulator } from './session-scanner-types' -import type { TranscriptMessageSink } from './session-transcript-consumers' +import { isMissingRemoteSessionPathError } from '../../transcripts/remote-session-file-stat' +import { BinarySessionTranscriptError } from '../../transcripts/remote-session-content-lines' +import { readStreamedSessionDocument } from '../../transcripts/session-document-stream' +import { openTranscriptReadStream } from '../../../native-chat/wsl-transcript-fs-access' +import { WslTranscriptFsError } from '../../../native-chat/wsl-transcript-fs-error' +import type { AiVaultSession } from '../../../../shared/ai-vault-types' +import { clineMessagesPathForMetadata } from '../../../../shared/ai-vault-session-log-resource' +import type { ExecutionHostId } from '../../../../shared/execution-host' import { - arrayValue, - asRecord, - extractContentText, - extractString, - normalizeTitleText -} from './session-scanner-values' + createAccumulator, + finalizeSession, + updateTimeline +} from '../../session-scanner-accumulator' +import { addSessionContent } from '../../session-scanner-messages' +import type { FileWithMtime, SessionAccumulator } from '../../session-scanner-types' +import type { TranscriptMessageSink } from '../../transcripts/session-transcript-consumers' +import { arrayValue, extractString } from '../../session-scanner-values' +import { asRecord } from '../../session-scanner-record-value' +import { extractContentText, normalizeTitleText } from '../../session-scanner-text-normalization' type ParserSessionOptions = { executionHostId?: ExecutionHostId @@ -30,8 +30,6 @@ export function isClineSessionMetadataPath(filePath: string): boolean { return Boolean(fileName && sessionId && fileName === `${sessionId}.json`) } -export { clineMessagesPathForMetadata } - export async function parseClineSessionFile( file: FileWithMtime, platform: NodeJS.Platform = process.platform, diff --git a/src/main/ai-vault/session-scanner-codebuddy-parser.ts b/src/main/ai-vault/scanners/codebuddy/session-scanner-codebuddy-parser.ts similarity index 88% rename from src/main/ai-vault/session-scanner-codebuddy-parser.ts rename to src/main/ai-vault/scanners/codebuddy/session-scanner-codebuddy-parser.ts index 8d7f4fff553..723f32684ce 100644 --- a/src/main/ai-vault/session-scanner-codebuddy-parser.ts +++ b/src/main/ai-vault/scanners/codebuddy/session-scanner-codebuddy-parser.ts @@ -1,10 +1,10 @@ import { createInterface } from 'node:readline' -import { openTranscriptReadStream } from '../native-chat/wsl-transcript-fs-access' -import type { AiVaultSession } from '../../shared/ai-vault-types' -import type { ExecutionHostId } from '../../shared/execution-host' -import { isKnownHarnessInjectedUserTurnText } from '../../shared/harness-injected-user-turns' -import type { FileWithMtime, ResumableSessionParseState } from './session-scanner-types' -import type { TranscriptMessageSink } from './session-transcript-consumers' +import { openTranscriptReadStream } from '../../../native-chat/wsl-transcript-fs-access' +import type { AiVaultSession } from '../../../../shared/ai-vault-types' +import type { ExecutionHostId } from '../../../../shared/execution-host' +import { isKnownHarnessInjectedUserTurnText } from '../../../../shared/harness-injected-user-turns' +import type { FileWithMtime, ResumableSessionParseState } from '../../session-scanner-types' +import type { TranscriptMessageSink } from '../../transcripts/session-transcript-consumers' import { accumulatorSessionIdentity, createAccumulator, @@ -12,14 +12,11 @@ import { sessionIdFromFileName, updateLatestLocation, updateTimeline -} from './session-scanner-accumulator' -import { addSessionText } from './session-scanner-messages' -import { - asRecord, - extractString, - normalizeTitleText, - parseJsonObject -} from './session-scanner-values' +} from '../../session-scanner-accumulator' +import { addSessionText } from '../../session-scanner-messages' +import { asRecord } from '../../session-scanner-record-value' +import { extractString, parseJsonObject } from '../../session-scanner-values' +import { normalizeTitleText } from '../../session-scanner-text-normalization' type ParserSessionOptions = { executionHostId?: ExecutionHostId diff --git a/src/main/ai-vault/session-scanner-codebuddy-scope.test.ts b/src/main/ai-vault/scanners/codebuddy/session-scanner-codebuddy-scope.test.ts similarity index 94% rename from src/main/ai-vault/session-scanner-codebuddy-scope.test.ts rename to src/main/ai-vault/scanners/codebuddy/session-scanner-codebuddy-scope.test.ts index f3ccddf0d16..dc3dadba44c 100644 --- a/src/main/ai-vault/session-scanner-codebuddy-scope.test.ts +++ b/src/main/ai-vault/scanners/codebuddy/session-scanner-codebuddy-scope.test.ts @@ -2,9 +2,9 @@ import { mkdtemp, mkdir, rm, utimes, writeFile } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, describe, expect, it } from 'vitest' -import { scanAiVaultSessions } from './session-scanner' -import { resetProjectDirCwdCacheForTests } from './session-scanner-scope-discovery' -import { isolatedScanRoots, jsonLines } from './session-scanner-test-fixtures' +import { scanAiVaultSessions } from '../../session-scanner' +import { resetProjectDirCwdCacheForTests } from '../../session-scanner-scope-discovery' +import { isolatedScanRoots, jsonLines } from '../../session-scanner-test-fixtures' let tempRoots: string[] = [] diff --git a/src/main/ai-vault/session-scanner-codebuddy-source.test.ts b/src/main/ai-vault/scanners/codebuddy/session-scanner-codebuddy-source.test.ts similarity index 94% rename from src/main/ai-vault/session-scanner-codebuddy-source.test.ts rename to src/main/ai-vault/scanners/codebuddy/session-scanner-codebuddy-source.test.ts index a171ac6d671..1237f1f83e3 100644 --- a/src/main/ai-vault/session-scanner-codebuddy-source.test.ts +++ b/src/main/ai-vault/scanners/codebuddy/session-scanner-codebuddy-source.test.ts @@ -2,8 +2,8 @@ import { mkdtemp, mkdir, rm, writeFile } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, describe, expect, it } from 'vitest' -import { scanAiVaultSessions } from './session-scanner' -import { isolatedScanRoots, jsonLines } from './session-scanner-test-fixtures' +import { scanAiVaultSessions } from '../../session-scanner' +import { isolatedScanRoots, jsonLines } from '../../session-scanner-test-fixtures' let tempRoots: string[] = [] diff --git a/src/main/ai-vault/codex-session-collection.test.ts b/src/main/ai-vault/scanners/codex/codex-session-collection.test.ts similarity index 96% rename from src/main/ai-vault/codex-session-collection.test.ts rename to src/main/ai-vault/scanners/codex/codex-session-collection.test.ts index a20020f05ca..71fb8068057 100644 --- a/src/main/ai-vault/codex-session-collection.test.ts +++ b/src/main/ai-vault/scanners/codex/codex-session-collection.test.ts @@ -1,7 +1,7 @@ import { describe, expect, it } from 'vitest' -import type { AiVaultSession } from '../../shared/ai-vault-types' -import { ScannedSessionCollection, dedupeScannedSessions } from './session-root-dedup' -import { createAccumulator, finalizeSession } from './session-scanner-accumulator' +import type { AiVaultSession } from '../../../../shared/ai-vault-types' +import { ScannedSessionCollection, dedupeScannedSessions } from '../../session-root-dedup' +import { createAccumulator, finalizeSession } from '../../session-scanner-accumulator' function session(overrides: Partial = {}): AiVaultSession { const parsed = finalizeSession( diff --git a/src/main/ai-vault/codex-session-root-dedup.test.ts b/src/main/ai-vault/scanners/codex/codex-session-root-dedup.test.ts similarity index 99% rename from src/main/ai-vault/codex-session-root-dedup.test.ts rename to src/main/ai-vault/scanners/codex/codex-session-root-dedup.test.ts index fb7eba830c1..36c5de5cfe0 100644 --- a/src/main/ai-vault/codex-session-root-dedup.test.ts +++ b/src/main/ai-vault/scanners/codex/codex-session-root-dedup.test.ts @@ -1,10 +1,10 @@ import { describe, expect, it, vi } from 'vitest' -import type { AiVaultSession } from '../../shared/ai-vault-types' +import type { AiVaultSession } from '../../../../shared/ai-vault-types' import { dedupeCodexRolloutCopyAliases, dedupeCodexRolloutFileAliases } from './codex-session-root-dedup' -import { dedupeScannedSessions } from './session-root-dedup' +import { dedupeScannedSessions } from '../../session-root-dedup' const REAL_HOME_ROLLOUT = '/Users/ada/.codex/sessions/2026/07/01/rollout-2026-07-01T10-00-00-019f0000-1111-7222-8333-444444444444.jsonl' diff --git a/src/main/ai-vault/codex-session-root-dedup.ts b/src/main/ai-vault/scanners/codex/codex-session-root-dedup.ts similarity index 94% rename from src/main/ai-vault/codex-session-root-dedup.ts rename to src/main/ai-vault/scanners/codex/codex-session-root-dedup.ts index b50882a51ca..44e2b759276 100644 --- a/src/main/ai-vault/codex-session-root-dedup.ts +++ b/src/main/ai-vault/scanners/codex/codex-session-root-dedup.ts @@ -1,9 +1,9 @@ -import type { AiVaultSession } from '../../shared/ai-vault-types' -import { sessionFileExecutionNamespace } from '../../shared/ai-vault-scope-cwd-match' -export { sessionFileExecutionNamespace } from '../../shared/ai-vault-scope-cwd-match' -import { mapWithConcurrency } from '../../shared/map-with-concurrency' -import { throwIfAiVaultScanCancelled } from './ai-vault-scan-cancellation' -import { sessionSortTime } from './session-scanner-accumulator' +import type { AiVaultSession } from '../../../../shared/ai-vault-types' +import { sessionFileExecutionNamespace } from '../../../../shared/ai-vault-scope-cwd-match' + +import { mapWithConcurrency } from '../../../../shared/map-with-concurrency' +import { throwIfAiVaultScanCancelled } from '../../ai-vault-scan-cancellation' +import { sessionSortTime } from '../../session-scanner-accumulator' // Bridging and backfill expose one rollout through multiple roots; list only its canonical alias (#7521). diff --git a/src/main/ai-vault/session-scanner-codex-cached-title.ts b/src/main/ai-vault/scanners/codex/session-scanner-codex-cached-title.ts similarity index 84% rename from src/main/ai-vault/session-scanner-codex-cached-title.ts rename to src/main/ai-vault/scanners/codex/session-scanner-codex-cached-title.ts index e974f465324..1b2f180d843 100644 --- a/src/main/ai-vault/session-scanner-codex-cached-title.ts +++ b/src/main/ai-vault/scanners/codex/session-scanner-codex-cached-title.ts @@ -1,5 +1,5 @@ -import type { AiVaultSession } from '../../shared/ai-vault-types' -import type { SessionFileCandidate } from './session-scanner-types' +import type { AiVaultSession } from '../../../../shared/ai-vault-types' +import type { SessionFileCandidate } from '../../session-scanner-types' import { readCodexSessionIndexTitle } from './session-scanner-codex-title-index' /** Refresh cached titles independently: session_index.jsonl can change after the rollout stops growing. */ diff --git a/src/main/ai-vault/session-scanner-codex-dual-root.test.ts b/src/main/ai-vault/scanners/codex/session-scanner-codex-dual-root.test.ts similarity index 98% rename from src/main/ai-vault/session-scanner-codex-dual-root.test.ts rename to src/main/ai-vault/scanners/codex/session-scanner-codex-dual-root.test.ts index 0c55c5fd940..a9fad3be286 100644 --- a/src/main/ai-vault/session-scanner-codex-dual-root.test.ts +++ b/src/main/ai-vault/scanners/codex/session-scanner-codex-dual-root.test.ts @@ -2,8 +2,8 @@ import { copyFile, link, mkdtemp, mkdir, rm, utimes, writeFile } from 'node:fs/p import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, describe, expect, it } from 'vitest' -import { scanAiVaultSessions } from './session-scanner' -import { isolatedScanRoots, jsonLines } from './session-scanner-test-fixtures' +import { scanAiVaultSessions } from '../../session-scanner' +import { isolatedScanRoots, jsonLines } from '../../session-scanner-test-fixtures' let tempRoots: string[] = [] diff --git a/src/main/ai-vault/session-scanner-codex-fast-path.test.ts b/src/main/ai-vault/scanners/codex/session-scanner-codex-fast-path.test.ts similarity index 97% rename from src/main/ai-vault/session-scanner-codex-fast-path.test.ts rename to src/main/ai-vault/scanners/codex/session-scanner-codex-fast-path.test.ts index 17b72c8a4fb..711f1c5ddd7 100644 --- a/src/main/ai-vault/session-scanner-codex-fast-path.test.ts +++ b/src/main/ai-vault/scanners/codex/session-scanner-codex-fast-path.test.ts @@ -6,10 +6,10 @@ import { parseCodexSessionFile } from './session-scanner-codex-parser' import { readCodexTimelineOnlyRecord } from './session-scanner-codex-record-fast-path' import { createSessionParseStats, - parseAgentSessionFileCached, - resetSessionParseCacheForTests -} from './session-scanner-parse-cache' -import type { FileWithMtime, SessionFileCandidate } from './session-scanner-types' + parseAgentSessionFileCached +} from '../../parse-cache/session-scanner-parse-cache' +import { resetSessionParseCacheForTests } from '../../parse-cache/session-parse-cache-store' +import type { FileWithMtime, SessionFileCandidate } from '../../session-scanner-types' // Match serde field ordering: timestamp/type/payload, with payload type first. const PAD = 'x'.repeat(2048) diff --git a/src/main/ai-vault/session-scanner-codex-fixtures.ts b/src/main/ai-vault/scanners/codex/session-scanner-codex-fixtures.ts similarity index 96% rename from src/main/ai-vault/session-scanner-codex-fixtures.ts rename to src/main/ai-vault/scanners/codex/session-scanner-codex-fixtures.ts index 52e8841c3e9..2f5aa50ebf2 100644 --- a/src/main/ai-vault/session-scanner-codex-fixtures.ts +++ b/src/main/ai-vault/scanners/codex/session-scanner-codex-fixtures.ts @@ -1,4 +1,4 @@ -import type { IncrementalAgentFixture } from './session-scanner-incremental-fixtures' +import type { IncrementalAgentFixture } from '../../session-scanner-incremental-fixtures' const CODEX_SESSION_ID = '019f0000-1111-7222-8333-444444444444' diff --git a/src/main/ai-vault/session-scanner-codex-message-records.ts b/src/main/ai-vault/scanners/codex/session-scanner-codex-message-records.ts similarity index 85% rename from src/main/ai-vault/session-scanner-codex-message-records.ts rename to src/main/ai-vault/scanners/codex/session-scanner-codex-message-records.ts index 27a0b49189f..c5f6649e271 100644 --- a/src/main/ai-vault/session-scanner-codex-message-records.ts +++ b/src/main/ai-vault/scanners/codex/session-scanner-codex-message-records.ts @@ -2,10 +2,14 @@ import { publishCodexResponseTool, publishCodexCompletedTool } from './session-scanner-codex-tool-records' -import { normalizePromptField } from '../../shared/agent-status-field-normalization' -import { addSessionContent } from './session-scanner-messages' -import type { SessionAccumulator } from './session-scanner-types' -import { asRecord, extractContentText, extractPreviewContentText } from './session-scanner-values' +import { normalizePromptField } from '../../../../shared/agent-status-field-normalization' +import { addSessionContent } from '../../session-scanner-messages' +import type { SessionAccumulator } from '../../session-scanner-types' +import { asRecord } from '../../session-scanner-record-value' +import { + extractContentText, + extractPreviewContentText +} from '../../session-scanner-text-normalization' export function consumeCodexResponseMessage( accumulator: SessionAccumulator, diff --git a/src/main/ai-vault/session-scanner-codex-non-user-origin.test.ts b/src/main/ai-vault/scanners/codex/session-scanner-codex-non-user-origin.test.ts similarity index 100% rename from src/main/ai-vault/session-scanner-codex-non-user-origin.test.ts rename to src/main/ai-vault/scanners/codex/session-scanner-codex-non-user-origin.test.ts diff --git a/src/main/ai-vault/session-scanner-codex-non-user-origin.ts b/src/main/ai-vault/scanners/codex/session-scanner-codex-non-user-origin.ts similarity index 97% rename from src/main/ai-vault/session-scanner-codex-non-user-origin.ts rename to src/main/ai-vault/scanners/codex/session-scanner-codex-non-user-origin.ts index 7591511e958..75ed84d3417 100644 --- a/src/main/ai-vault/session-scanner-codex-non-user-origin.ts +++ b/src/main/ai-vault/scanners/codex/session-scanner-codex-non-user-origin.ts @@ -1,4 +1,5 @@ -import { asRecord, extractString } from './session-scanner-values' +import { asRecord } from '../../session-scanner-record-value' +import { extractString } from '../../session-scanner-values' /** Join by parentThreadId; agentPath is a label, and fork lineage does not establish spawn parentage. */ export type CodexSubagentParentage = { diff --git a/src/main/ai-vault/session-scanner-codex-parser.test.ts b/src/main/ai-vault/scanners/codex/session-scanner-codex-parser.test.ts similarity index 99% rename from src/main/ai-vault/session-scanner-codex-parser.test.ts rename to src/main/ai-vault/scanners/codex/session-scanner-codex-parser.test.ts index 83090a4e0d4..b38ed3a2a29 100644 --- a/src/main/ai-vault/session-scanner-codex-parser.test.ts +++ b/src/main/ai-vault/scanners/codex/session-scanner-codex-parser.test.ts @@ -6,7 +6,7 @@ import { createCodexSessionResumeState, parseCodexSessionFile } from './session-scanner-codex-parser' -import type { TranscriptMessage } from './session-transcript-consumers' +import type { TranscriptMessage } from '../../transcripts/session-transcript-consumers' let tempRoots: string[] = [] diff --git a/src/main/ai-vault/session-scanner-codex-parser.ts b/src/main/ai-vault/scanners/codex/session-scanner-codex-parser.ts similarity index 93% rename from src/main/ai-vault/session-scanner-codex-parser.ts rename to src/main/ai-vault/scanners/codex/session-scanner-codex-parser.ts index fb3633b9ad6..c03782509ed 100644 --- a/src/main/ai-vault/session-scanner-codex-parser.ts +++ b/src/main/ai-vault/scanners/codex/session-scanner-codex-parser.ts @@ -1,8 +1,8 @@ -import { openTranscriptReadStream } from '../native-chat/wsl-transcript-fs-access' +import { openTranscriptReadStream } from '../../../native-chat/wsl-transcript-fs-access' import { createInterface } from 'node:readline' -import type { AiVaultSession } from '../../shared/ai-vault-types' +import type { AiVaultSession } from '../../../../shared/ai-vault-types' import { readCodexSessionIndexTitle } from './session-scanner-codex-title-index' -import type { ExecutionHostId } from '../../shared/execution-host' +import type { ExecutionHostId } from '../../../../shared/execution-host' import { accumulatorSessionIdentity, cloneSessionAccumulator, @@ -10,7 +10,7 @@ import { finalizeSession, sessionIdFromFileName, updateTimeline -} from './session-scanner-accumulator' +} from '../../session-scanner-accumulator' import { consumeCodexCompletedMessage, consumeCodexLegacyEventMessage, @@ -22,18 +22,20 @@ import type { ResumableParseFinalizeOptions, ResumableSessionParseState, SessionAccumulator -} from './session-scanner-types' -import type { TranscriptMessageSink } from './session-transcript-consumers' +} from '../../session-scanner-types' +import type { TranscriptMessageSink } from '../../transcripts/session-transcript-consumers' import { addCodexUsage, - asRecord, + normalizeCodexUsage, + subtractCodexUsage +} from '../../session-scanner-token-values' +import { asRecord } from '../../session-scanner-record-value' +import { extractGitBranch, extractModel, extractString, - normalizeCodexUsage, - parseJsonObject, - subtractCodexUsage -} from './session-scanner-values' + parseJsonObject +} from '../../session-scanner-values' import { readCodexTimelineOnlyRecord } from './session-scanner-codex-record-fast-path' import { extractCodexSessionMetadataTitle } from './session-scanner-codex-session-meta' import { diff --git a/src/main/ai-vault/session-scanner-codex-paths.ts b/src/main/ai-vault/scanners/codex/session-scanner-codex-paths.ts similarity index 100% rename from src/main/ai-vault/session-scanner-codex-paths.ts rename to src/main/ai-vault/scanners/codex/session-scanner-codex-paths.ts diff --git a/src/main/ai-vault/session-scanner-codex-record-fast-path.ts b/src/main/ai-vault/scanners/codex/session-scanner-codex-record-fast-path.ts similarity index 100% rename from src/main/ai-vault/session-scanner-codex-record-fast-path.ts rename to src/main/ai-vault/scanners/codex/session-scanner-codex-record-fast-path.ts diff --git a/src/main/ai-vault/session-scanner-codex-session-meta.ts b/src/main/ai-vault/scanners/codex/session-scanner-codex-session-meta.ts similarity index 69% rename from src/main/ai-vault/session-scanner-codex-session-meta.ts rename to src/main/ai-vault/scanners/codex/session-scanner-codex-session-meta.ts index 015d1dd84fd..8b5fb208cb8 100644 --- a/src/main/ai-vault/session-scanner-codex-session-meta.ts +++ b/src/main/ai-vault/scanners/codex/session-scanner-codex-session-meta.ts @@ -1,4 +1,5 @@ -import { extractString, normalizeTitleText } from './session-scanner-values' +import { extractString } from '../../session-scanner-values' +import { normalizeTitleText } from '../../session-scanner-text-normalization' export function extractCodexSessionMetadataTitle(payload: Record): string | null { return ( diff --git a/src/main/ai-vault/session-scanner-codex-title-index.test.ts b/src/main/ai-vault/scanners/codex/session-scanner-codex-title-index.test.ts similarity index 100% rename from src/main/ai-vault/session-scanner-codex-title-index.test.ts rename to src/main/ai-vault/scanners/codex/session-scanner-codex-title-index.test.ts diff --git a/src/main/ai-vault/session-scanner-codex-title-index.ts b/src/main/ai-vault/scanners/codex/session-scanner-codex-title-index.ts similarity index 92% rename from src/main/ai-vault/session-scanner-codex-title-index.ts rename to src/main/ai-vault/scanners/codex/session-scanner-codex-title-index.ts index 8bb6850b311..2800fd3eec4 100644 --- a/src/main/ai-vault/session-scanner-codex-title-index.ts +++ b/src/main/ai-vault/scanners/codex/session-scanner-codex-title-index.ts @@ -1,9 +1,16 @@ import { basename, dirname, join } from 'node:path' import { createInterface } from 'node:readline' -import { InFlightPromiseDedupe, stableInFlightKey } from '../../shared/in-flight-promise-dedupe' -import { openTranscriptReadStream, wslGatedStat } from '../native-chat/wsl-transcript-fs-access' -import { WslTranscriptFsError } from '../native-chat/wsl-transcript-fs-gate' -import { extractString, normalizeTitleText, parseJsonObject } from './session-scanner-values' +import { + InFlightPromiseDedupe, + stableInFlightKey +} from '../../../../shared/in-flight-promise-dedupe' +import { + openTranscriptReadStream, + wslGatedStat +} from '../../../native-chat/wsl-transcript-fs-access' +import { WslTranscriptFsError } from '../../../native-chat/wsl-transcript-fs-error' +import { extractString, parseJsonObject } from '../../session-scanner-values' +import { normalizeTitleText } from '../../session-scanner-text-normalization' // Thread names may arrive here after the transcript was written. diff --git a/src/main/ai-vault/session-scanner-codex-tool-records.test.ts b/src/main/ai-vault/scanners/codex/session-scanner-codex-tool-records.test.ts similarity index 98% rename from src/main/ai-vault/session-scanner-codex-tool-records.test.ts rename to src/main/ai-vault/scanners/codex/session-scanner-codex-tool-records.test.ts index 1c57753c2ff..8066ec3aef9 100644 --- a/src/main/ai-vault/session-scanner-codex-tool-records.test.ts +++ b/src/main/ai-vault/scanners/codex/session-scanner-codex-tool-records.test.ts @@ -1,6 +1,6 @@ import { expect, it } from 'vitest' import { createCodexSessionResumeState } from './session-scanner-codex-parser' -import type { TranscriptMessage } from './session-transcript-consumers' +import type { TranscriptMessage } from '../../transcripts/session-transcript-consumers' import { readCodexTimelineOnlyRecord } from './session-scanner-codex-record-fast-path' const timestamp = '2026-05-01T10:00:00.000Z' diff --git a/src/main/ai-vault/session-scanner-codex-tool-records.ts b/src/main/ai-vault/scanners/codex/session-scanner-codex-tool-records.ts similarity index 89% rename from src/main/ai-vault/session-scanner-codex-tool-records.ts rename to src/main/ai-vault/scanners/codex/session-scanner-codex-tool-records.ts index 976d5eff36d..57d75cdb831 100644 --- a/src/main/ai-vault/session-scanner-codex-tool-records.ts +++ b/src/main/ai-vault/scanners/codex/session-scanner-codex-tool-records.ts @@ -1,7 +1,7 @@ -import { timestampIso } from './session-scanner-accumulator' -import { asRecord } from './session-scanner-record-value' -import type { SessionAccumulator } from './session-scanner-types' -import { transcriptMessagesFromContent } from './session-transcript-message-content' +import { timestampIso } from '../../session-scanner-accumulator' +import { asRecord } from '../../session-scanner-record-value' +import type { SessionAccumulator } from '../../session-scanner-types' +import { transcriptMessagesFromContent } from '../../transcripts/session-transcript-message-content' export const CODEX_TOOL_RESPONSE_TYPES = new Set([ 'function_call', diff --git a/src/main/ai-vault/session-scanner-codex-workers.test.ts b/src/main/ai-vault/scanners/codex/session-scanner-codex-workers.test.ts similarity index 97% rename from src/main/ai-vault/session-scanner-codex-workers.test.ts rename to src/main/ai-vault/scanners/codex/session-scanner-codex-workers.test.ts index e298ae864b1..2d9df02bafd 100644 --- a/src/main/ai-vault/session-scanner-codex-workers.test.ts +++ b/src/main/ai-vault/scanners/codex/session-scanner-codex-workers.test.ts @@ -2,8 +2,8 @@ import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, describe, expect, it } from 'vitest' -import { scanAiVaultSessions } from './session-scanner' -import { isolatedScanRoots, jsonLines } from './session-scanner-test-fixtures' +import { scanAiVaultSessions } from '../../session-scanner' +import { isolatedScanRoots, jsonLines } from '../../session-scanner-test-fixtures' let tempRoots: string[] = [] diff --git a/src/main/ai-vault/session-scanner-copilot-cache-upgrade.test.ts b/src/main/ai-vault/scanners/copilot/session-scanner-copilot-cache-upgrade.test.ts similarity index 77% rename from src/main/ai-vault/session-scanner-copilot-cache-upgrade.test.ts rename to src/main/ai-vault/scanners/copilot/session-scanner-copilot-cache-upgrade.test.ts index 9e388324545..dabb8cf1b5b 100644 --- a/src/main/ai-vault/session-scanner-copilot-cache-upgrade.test.ts +++ b/src/main/ai-vault/scanners/copilot/session-scanner-copilot-cache-upgrade.test.ts @@ -2,25 +2,25 @@ import { mkdtemp, rm, writeFile } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, expect, it } from 'vitest' -import { buildAiVaultResumeCommand } from '../../shared/ai-vault-resume-command' -import SyncDatabase from '../sqlite/sync-database' -import { registerSessionSearchIndexConsumer } from '../ai-vault-search/session-search-index-consumer' -import { replayTranscriptRead } from '../ai-vault-search/session-search-index-test-fixture' -import { SessionSearchStore } from '../ai-vault-search/session-search-store' -import { sessionCandidate } from '../ai-vault-search/session-search-transcript-fixtures' -import { SessionParseCacheDatabase } from './session-parse-cache-database' +import { buildAiVaultResumeCommand } from '../../../../shared/ai-vault-resume-command' +import SyncDatabase from '../../../sqlite/sync-database' +import { registerSessionSearchIndexConsumer } from '../../../ai-vault-search/session-search-index-consumer' +import { replayTranscriptRead } from '../../../ai-vault-search/session-search-index-test-fixture' +import { SessionSearchStore } from '../../../ai-vault-search/session-search-store' +import { sessionCandidate } from '../../../ai-vault-search/session-search-transcript-fixtures' +import { SessionParseCacheDatabase } from '../../parse-cache/session-parse-cache-database' import { initSessionParseCachePersistence, resetSessionParseCachePersistenceForTests -} from './session-parse-cache-persistence' +} from '../../parse-cache/session-parse-cache-persistence' import { createSessionParseStats, - parseAgentSessionFileCached, - resetSessionParseCacheForTests -} from './session-scanner-parse-cache' + parseAgentSessionFileCached +} from '../../parse-cache/session-scanner-parse-cache' +import { resetSessionParseCacheForTests } from '../../parse-cache/session-parse-cache-store' import { parseCopilotSessionFile } from './session-scanner-copilot-parser' -import { resetTranscriptConsumersForTests } from './session-transcript-consumers' -import type { PersistedSessionParseCacheEntry } from './session-parse-cache-store' +import { resetTranscriptConsumersForTests } from '../../transcripts/session-transcript-consumers' +import type { PersistedSessionParseCacheEntry } from '../../parse-cache/session-parse-cache-store' let root: string | undefined let store: SessionSearchStore | undefined diff --git a/src/main/ai-vault/session-scanner-copilot-parser.test.ts b/src/main/ai-vault/scanners/copilot/session-scanner-copilot-parser.test.ts similarity index 98% rename from src/main/ai-vault/session-scanner-copilot-parser.test.ts rename to src/main/ai-vault/scanners/copilot/session-scanner-copilot-parser.test.ts index e080031d2e9..1a335699a0c 100644 --- a/src/main/ai-vault/session-scanner-copilot-parser.test.ts +++ b/src/main/ai-vault/scanners/copilot/session-scanner-copilot-parser.test.ts @@ -2,7 +2,7 @@ import { mkdtemp, rm, writeFile } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, describe, expect, it } from 'vitest' -import type { AiVaultSession } from '../../shared/ai-vault-types' +import type { AiVaultSession } from '../../../../shared/ai-vault-types' import { parseCopilotSessionFile } from './session-scanner-copilot-parser' const DATETIME = '2026-10-19T18:40:06.682-03:00' diff --git a/src/main/ai-vault/session-scanner-copilot-parser.ts b/src/main/ai-vault/scanners/copilot/session-scanner-copilot-parser.ts similarity index 81% rename from src/main/ai-vault/session-scanner-copilot-parser.ts rename to src/main/ai-vault/scanners/copilot/session-scanner-copilot-parser.ts index 857ae02af47..ba34a2fb8d3 100644 --- a/src/main/ai-vault/session-scanner-copilot-parser.ts +++ b/src/main/ai-vault/scanners/copilot/session-scanner-copilot-parser.ts @@ -1,29 +1,24 @@ -import { openTranscriptReadStream } from '../native-chat/wsl-transcript-fs-access' +import { openTranscriptReadStream } from '../../../native-chat/wsl-transcript-fs-access' import { createInterface } from 'node:readline' -import type { AiVaultSession } from '../../shared/ai-vault-types' -import type { ExecutionHostId } from '../../shared/execution-host' +import type { AiVaultSession } from '../../../../shared/ai-vault-types' +import type { ExecutionHostId } from '../../../../shared/execution-host' import type { FileWithMtime, ResumableSessionParseState, SessionAccumulator -} from './session-scanner-types' -import type { TranscriptMessageSink } from './session-transcript-consumers' +} from '../../session-scanner-types' +import type { TranscriptMessageSink } from '../../transcripts/session-transcript-consumers' import { accumulatorFoldResumeState, createAccumulator, sessionIdFromFileName, updateTimeline -} from './session-scanner-accumulator' -import { addSessionText } from './session-scanner-messages' -import { - asRecord, - copilotModelMetricsTotal, - extractString, - extractTrustedFolder, - normalizeTitleText, - numberValue, - parseJsonObject -} from './session-scanner-values' +} from '../../session-scanner-accumulator' +import { addSessionText } from '../../session-scanner-messages' +import { asRecord } from '../../session-scanner-record-value' +import { copilotModelMetricsTotal, numberValue } from '../../session-scanner-token-values' +import { extractString, extractTrustedFolder, parseJsonObject } from '../../session-scanner-values' +import { normalizeTitleText } from '../../session-scanner-text-normalization' type ParserSessionOptions = { executionHostId?: ExecutionHostId diff --git a/src/main/ai-vault/session-scanner-cursor-chat-meta.test.ts b/src/main/ai-vault/scanners/cursor/session-scanner-cursor-chat-meta.test.ts similarity index 96% rename from src/main/ai-vault/session-scanner-cursor-chat-meta.test.ts rename to src/main/ai-vault/scanners/cursor/session-scanner-cursor-chat-meta.test.ts index 212efccdb7b..fe7e2c6f1c6 100644 --- a/src/main/ai-vault/session-scanner-cursor-chat-meta.test.ts +++ b/src/main/ai-vault/scanners/cursor/session-scanner-cursor-chat-meta.test.ts @@ -2,7 +2,7 @@ import { appendFile, mkdir, mkdtemp, rm, stat, utimes, writeFile } from 'node:fs import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, describe, expect, it, vi } from 'vitest' -import { WslTranscriptFsError } from '../native-chat/wsl-transcript-fs-error' +import { WslTranscriptFsError } from '../../../native-chat/wsl-transcript-fs-error' let failNextChatsReaddir = false let failNextChatsRootReaddir = false @@ -10,7 +10,7 @@ let failMetaJsonReads = false let failMetaJsonStats: false | true | 'eacces' = false let cancelMetaJsonReads: AbortController | null = null let chatsRootReads = 0 -vi.mock('../native-chat/wsl-transcript-fs-access', async (importOriginal) => { +vi.mock('../../../native-chat/wsl-transcript-fs-access', async (importOriginal) => { const actual = await importOriginal() return { ...actual, @@ -56,7 +56,7 @@ vi.mock('../native-chat/wsl-transcript-fs-access', async (importOriginal) => { } } }) -import type * as WslTranscriptFsAccess from '../native-chat/wsl-transcript-fs-access' +import type * as WslTranscriptFsAccess from '../../../native-chat/wsl-transcript-fs-access' import { cursorChatMetaPath, readCursorChatMeta, @@ -68,17 +68,17 @@ import { isAiVaultScanCancelledError, type AiVaultScanIssue, type AiVaultSession -} from '../../shared/ai-vault-types' -import { AI_VAULT_AGENT_SOURCES } from './session-scanner-agent-sources' -import { discoverFiles } from './session-scanner-discovery' -import { scanAiVaultSessions } from './session-scanner' +} from '../../../../shared/ai-vault-types' +import { AI_VAULT_AGENT_SOURCES } from '../../session-scanner-agent-sources' +import { discoverFiles } from '../../session-scanner-discovery' +import { scanAiVaultSessions } from '../../session-scanner' import { createSessionParseStats, parseAgentSessionFileCached, - resetSessionParseCacheForTests, type SessionParseStats -} from './session-scanner-parse-cache' +} from '../../parse-cache/session-scanner-parse-cache' import { + resetSessionParseCacheForTests, getSessionParseCacheEntry, lookupSessionScopeCwds, resolveSessionScopeCwd, @@ -86,10 +86,11 @@ import { peekSessionParseCacheEntry, type PersistedSessionParseCacheEntry, setSessionParseCacheColdTier -} from './session-parse-cache-store' -import { isolatedScanRoots } from './session-scanner-test-fixtures' -import type { FileWithMtime } from './session-scanner-types' -import type { SessionSidecarStat } from './session-sidecar-stat' +} from '../../parse-cache/session-parse-cache-store' + +import { isolatedScanRoots } from '../../session-scanner-test-fixtures' +import type { FileWithMtime } from '../../session-scanner-types' +import type { SessionSidecarStat } from '../../parse-cache/session-sidecar-stat' // Mirror Cursor meta.json keys (2026-09). type CursorMetaFixture = { diff --git a/src/main/ai-vault/session-scanner-cursor-chat-meta.ts b/src/main/ai-vault/scanners/cursor/session-scanner-cursor-chat-meta.ts similarity index 94% rename from src/main/ai-vault/session-scanner-cursor-chat-meta.ts rename to src/main/ai-vault/scanners/cursor/session-scanner-cursor-chat-meta.ts index 2ae24adecd2..20b5b7330e7 100644 --- a/src/main/ai-vault/session-scanner-cursor-chat-meta.ts +++ b/src/main/ai-vault/scanners/cursor/session-scanner-cursor-chat-meta.ts @@ -1,11 +1,12 @@ import { AsyncLocalStorage } from 'node:async_hooks' import { basename, dirname, join } from 'node:path' -import { wslGatedReaddir, wslGatedStat } from '../native-chat/wsl-transcript-fs-access' -import { WslTranscriptFsError } from '../native-chat/wsl-transcript-fs-gate' -import { timestampIso } from './session-scanner-accumulator' -import { scanIssueTextFromError } from './session-scan-issues' -import type { AiVaultScanIssueText } from '../../shared/ai-vault-scan-issue-copy' -import { extractString, normalizeTitleText, readJsonObjectIfExists } from './session-scanner-values' +import { wslGatedReaddir, wslGatedStat } from '../../../native-chat/wsl-transcript-fs-access' +import { WslTranscriptFsError } from '../../../native-chat/wsl-transcript-fs-error' +import { timestampIso } from '../../session-scanner-accumulator' +import { scanIssueTextFromError } from '../../session-scan-issues' +import type { AiVaultScanIssueText } from '../../../../shared/ai-vault-scan-issue-copy' +import { extractString, readJsonObjectIfExists } from '../../session-scanner-values' +import { normalizeTitleText } from '../../session-scanner-text-normalization' // Transcript paths cannot derive hashed metadata buckets; index the separate chats tree by chat ID. diff --git a/src/main/ai-vault/session-scanner-cursor-parser.ts b/src/main/ai-vault/scanners/cursor/session-scanner-cursor-parser.ts similarity index 77% rename from src/main/ai-vault/session-scanner-cursor-parser.ts rename to src/main/ai-vault/scanners/cursor/session-scanner-cursor-parser.ts index 8392348e075..6ddbcdd3693 100644 --- a/src/main/ai-vault/session-scanner-cursor-parser.ts +++ b/src/main/ai-vault/scanners/cursor/session-scanner-cursor-parser.ts @@ -1,31 +1,27 @@ import { remoteSessionContentLines, type RemoteSessionContent -} from './remote-session-content-lines' -import { openTranscriptReadStream } from '../native-chat/wsl-transcript-fs-access' +} from '../../transcripts/remote-session-content-lines' +import { openTranscriptReadStream } from '../../../native-chat/wsl-transcript-fs-access' import { createInterface } from 'node:readline' -import type { AiVaultSession } from '../../shared/ai-vault-types' -import type { ExecutionHostId } from '../../shared/execution-host' +import type { AiVaultSession } from '../../../../shared/ai-vault-types' +import type { ExecutionHostId } from '../../../../shared/execution-host' import type { FileWithMtime, ResumableSessionParseState, SessionAccumulator -} from './session-scanner-types' -import type { TranscriptMessageSink } from './session-transcript-consumers' +} from '../../session-scanner-types' +import type { TranscriptMessageSink } from '../../transcripts/session-transcript-consumers' import { accumulatorFoldResumeState, createAccumulator, sessionIdFromFileName, updateTimeline -} from './session-scanner-accumulator' -import { addSessionContent } from './session-scanner-messages' -import { - asRecord, - extractContentText, - extractMessageText, - extractString, - parseJsonObject -} from './session-scanner-values' +} from '../../session-scanner-accumulator' +import { addSessionContent } from '../../session-scanner-messages' +import { asRecord } from '../../session-scanner-record-value' +import { extractContentText, extractMessageText } from '../../session-scanner-text-normalization' +import { extractString, parseJsonObject } from '../../session-scanner-values' type ParserSessionOptions = { executionHostId?: ExecutionHostId diff --git a/src/main/ai-vault/session-scanner-devin-contention.test.ts b/src/main/ai-vault/scanners/devin/session-scanner-devin-contention.test.ts similarity index 84% rename from src/main/ai-vault/session-scanner-devin-contention.test.ts rename to src/main/ai-vault/scanners/devin/session-scanner-devin-contention.test.ts index b2c101dbff1..635e1b15807 100644 --- a/src/main/ai-vault/session-scanner-devin-contention.test.ts +++ b/src/main/ai-vault/scanners/devin/session-scanner-devin-contention.test.ts @@ -2,12 +2,12 @@ import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, expect, it, vi } from 'vitest' -import SyncDatabase from '../sqlite/sync-database' -import { scanAiVaultSessions } from './session-scanner' +import SyncDatabase from '../../../sqlite/sync-database' +import { scanAiVaultSessions } from '../../session-scanner' import { resetDevinSessionsIndexCacheForTests } from './session-scanner-devin-db' -import * as databaseReader from './session-scanner-opencode-sqlite-open' -import { resetSessionParseCacheForTests } from './session-scanner-parse-cache' -import { isolatedScanRoots } from './session-scanner-test-fixtures' +import * as databaseReader from '../opencode/sqlite/session-scanner-opencode-sqlite-open' +import { resetSessionParseCacheForTests } from '../../parse-cache/session-parse-cache-store' +import { isolatedScanRoots } from '../../session-scanner-test-fixtures' let root: string | undefined diff --git a/src/main/ai-vault/session-scanner-devin-db.test.ts b/src/main/ai-vault/scanners/devin/session-scanner-devin-db.test.ts similarity index 97% rename from src/main/ai-vault/session-scanner-devin-db.test.ts rename to src/main/ai-vault/scanners/devin/session-scanner-devin-db.test.ts index 64fc87673ac..741c83acade 100644 --- a/src/main/ai-vault/session-scanner-devin-db.test.ts +++ b/src/main/ai-vault/scanners/devin/session-scanner-devin-db.test.ts @@ -2,8 +2,8 @@ import { mkdir, mkdtemp, rm, stat, utimes, writeFile } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, describe, expect, it } from 'vitest' -import SyncDatabase from '../sqlite/sync-database' -import { scanAiVaultSessions } from './session-scanner' +import SyncDatabase from '../../../sqlite/sync-database' +import { scanAiVaultSessions } from '../../session-scanner' import { devinSessionsDbDependencyPath, devinSessionsDbPath, @@ -11,10 +11,10 @@ import { resetDevinSessionsIndexCacheForTests } from './session-scanner-devin-db' import { parseDevinSessionContent } from './session-scanner-devin-parser' -import { enrichSessionFromSidecar } from './session-scanner-sidecar-enrichment' -import { isolatedScanRoots } from './session-scanner-test-fixtures' -import type { FileWithMtime, SessionFileCandidate } from './session-scanner-types' -import type { SessionSidecarStat } from './session-sidecar-stat' +import { enrichSessionFromSidecar } from '../../parse-cache/session-scanner-sidecar-enrichment' +import { isolatedScanRoots } from '../../session-scanner-test-fixtures' +import type { FileWithMtime, SessionFileCandidate } from '../../session-scanner-types' +import type { SessionSidecarStat } from '../../parse-cache/session-sidecar-stat' // Mirror the Devin CLI 3000.10.x schema so every probed column exists. const DEVIN_SESSIONS_SCHEMA = ` diff --git a/src/main/ai-vault/session-scanner-devin-db.ts b/src/main/ai-vault/scanners/devin/session-scanner-devin-db.ts similarity index 87% rename from src/main/ai-vault/session-scanner-devin-db.ts rename to src/main/ai-vault/scanners/devin/session-scanner-devin-db.ts index c658164748f..8c54fab529b 100644 --- a/src/main/ai-vault/session-scanner-devin-db.ts +++ b/src/main/ai-vault/scanners/devin/session-scanner-devin-db.ts @@ -1,15 +1,15 @@ -import { parseWslUncPath } from '../../shared/wsl-paths' -import { wasWslDistroLastSeenRunningSettled } from '../wsl/discovery/wsl-background-distro-gate' -import { WSL_TRANSCRIPT_RUNNING_LEASE_MS } from '../native-chat/wsl-transcript-running-admission' +import { parseWslUncPath } from '../../../../shared/wsl-paths' +import { wasWslDistroLastSeenRunningSettled } from '../../../wsl/discovery/wsl-background-distro-gate' +import { WSL_TRANSCRIPT_RUNNING_LEASE_MS } from '../../../native-chat/wsl-transcript-running-admission' import { AsyncLocalStorage } from 'node:async_hooks' import { dirname, join } from 'node:path' -import { wslGatedStat } from '../native-chat/wsl-transcript-fs-access' -import { columnExists, tableExists } from '../opencode-usage/schema-helpers' -import { readOpenCodeDatabase } from './session-scanner-opencode-sqlite-open' -import type { SessionSidecarObservation } from './session-sidecar-stat' -import { asRecord } from './session-scanner-record-value' -import { numberValue } from './session-scanner-token-values' -import { extractString } from './session-scanner-values' +import { wslGatedStat } from '../../../native-chat/wsl-transcript-fs-access' +import { columnExists, tableExists } from '../../../opencode-usage/schema-helpers' +import { readOpenCodeDatabase } from '../opencode/sqlite/session-scanner-opencode-sqlite-open' +import type { SessionSidecarObservation } from '../../parse-cache/session-sidecar-stat' +import { asRecord } from '../../session-scanner-record-value' +import { numberValue } from '../../session-scanner-token-values' +import { extractString } from '../../session-scanner-values' // Devin stores workspace metadata absent from Windows transcripts in a sibling sessions.db. diff --git a/src/main/ai-vault/session-scanner-devin-dedup.test.ts b/src/main/ai-vault/scanners/devin/session-scanner-devin-dedup.test.ts similarity index 94% rename from src/main/ai-vault/session-scanner-devin-dedup.test.ts rename to src/main/ai-vault/scanners/devin/session-scanner-devin-dedup.test.ts index 2546937411e..ae22350c772 100644 --- a/src/main/ai-vault/session-scanner-devin-dedup.test.ts +++ b/src/main/ai-vault/scanners/devin/session-scanner-devin-dedup.test.ts @@ -2,9 +2,9 @@ import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, expect, it, vi } from 'vitest' -import { isolatedScanRoots } from './session-scanner-test-fixtures' +import { isolatedScanRoots } from '../../session-scanner-test-fixtures' import { parseDevinSessionContent } from './session-scanner-devin-parser' -import { dedupeScannedSessions, ScannedSessionCollection } from './session-root-dedup' +import { dedupeScannedSessions, ScannedSessionCollection } from '../../session-root-dedup' const roots: string[] = [] afterEach(async () => { @@ -34,7 +34,7 @@ it('lists a session in both default directories once and still fills the scan li join(root, 'transcripts', 'other.json'), transcript('other', '2026-09-18T00:00:00Z') ) - const { scanAiVaultSessions } = await import('./session-scanner') + const { scanAiVaultSessions } = await import('../../session-scanner') const { devinTranscriptsDir: _unused, ...options } = isolatedScanRoots(root) const result = await scanAiVaultSessions({ ...options, limit: 2 }) expect(result.sessions.map((session) => session.sessionId)).toEqual(['same', 'other']) diff --git a/src/main/ai-vault/session-scanner-devin-parser.test.ts b/src/main/ai-vault/scanners/devin/session-scanner-devin-parser.test.ts similarity index 98% rename from src/main/ai-vault/session-scanner-devin-parser.test.ts rename to src/main/ai-vault/scanners/devin/session-scanner-devin-parser.test.ts index 23d9b8ce5c7..fe7515eea00 100644 --- a/src/main/ai-vault/session-scanner-devin-parser.test.ts +++ b/src/main/ai-vault/scanners/devin/session-scanner-devin-parser.test.ts @@ -3,8 +3,8 @@ import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, describe, expect, it } from 'vitest' import { parseDevinSessionFile } from './session-scanner-devin-parser' -import { withFullFirstUserPromptCapture } from './session-scanner-first-user-prompt-capture' -import type { TranscriptMessage } from './session-transcript-consumers' +import { withFullFirstUserPromptCapture } from '../../session-scanner-first-user-prompt-capture' +import type { TranscriptMessage } from '../../transcripts/session-transcript-consumers' let tempDirs: string[] = [] diff --git a/src/main/ai-vault/session-scanner-devin-parser.ts b/src/main/ai-vault/scanners/devin/session-scanner-devin-parser.ts similarity index 86% rename from src/main/ai-vault/session-scanner-devin-parser.ts rename to src/main/ai-vault/scanners/devin/session-scanner-devin-parser.ts index 36c98a0d1cb..c40c1c0c396 100644 --- a/src/main/ai-vault/session-scanner-devin-parser.ts +++ b/src/main/ai-vault/scanners/devin/session-scanner-devin-parser.ts @@ -1,24 +1,24 @@ -import { readStreamedSessionDocument } from './session-document-stream' -import { openTranscriptReadStream } from '../native-chat/wsl-transcript-fs-access' -import type { AiVaultSession } from '../../shared/ai-vault-types' -import type { ExecutionHostId } from '../../shared/execution-host' -import type { FileWithMtime, SessionAccumulator } from './session-scanner-types' -import type { TranscriptMessageSink } from './session-transcript-consumers' +import { readStreamedSessionDocument } from '../../transcripts/session-document-stream' +import { openTranscriptReadStream } from '../../../native-chat/wsl-transcript-fs-access' +import type { AiVaultSession } from '../../../../shared/ai-vault-types' +import type { ExecutionHostId } from '../../../../shared/execution-host' +import type { FileWithMtime, SessionAccumulator } from '../../session-scanner-types' +import type { TranscriptMessageSink } from '../../transcripts/session-transcript-consumers' import { createAccumulator, finalizeSession, sessionIdFromFileName, updateTimeline -} from './session-scanner-accumulator' -import { addDecodedSessionMessage } from './session-scanner-messages' -import { decodeSessionMessage, type DecodedSessionMessage } from './session-decoded-message' +} from '../../session-scanner-accumulator' +import { addDecodedSessionMessage } from '../../session-scanner-messages' import { - arrayValue, - asRecord, - extractContentText, - extractString, - numberValue -} from './session-scanner-values' + decodeSessionMessage, + type DecodedSessionMessage +} from '../../transcripts/session-decoded-message' +import { arrayValue, extractString } from '../../session-scanner-values' +import { asRecord } from '../../session-scanner-record-value' +import { extractContentText } from '../../session-scanner-text-normalization' +import { numberValue } from '../../session-scanner-token-values' type ParserSessionOptions = { executionHostId?: ExecutionHostId diff --git a/src/main/ai-vault/session-scanner-droid-parser.test.ts b/src/main/ai-vault/scanners/droid/session-scanner-droid-parser.test.ts similarity index 92% rename from src/main/ai-vault/session-scanner-droid-parser.test.ts rename to src/main/ai-vault/scanners/droid/session-scanner-droid-parser.test.ts index c2e002daf67..5631040b99a 100644 --- a/src/main/ai-vault/session-scanner-droid-parser.test.ts +++ b/src/main/ai-vault/scanners/droid/session-scanner-droid-parser.test.ts @@ -1,6 +1,6 @@ import { expect, it } from 'vitest' import { createDroidSessionResumeState } from './session-scanner-droid-parser' -import type { TranscriptMessage } from './session-transcript-consumers' +import type { TranscriptMessage } from '../../transcripts/session-transcript-consumers' it.each([413, 256 * 1024 + 1])( 'publishes %i-character Droid content before preview limits', diff --git a/src/main/ai-vault/session-scanner-droid-parser.ts b/src/main/ai-vault/scanners/droid/session-scanner-droid-parser.ts similarity index 81% rename from src/main/ai-vault/session-scanner-droid-parser.ts rename to src/main/ai-vault/scanners/droid/session-scanner-droid-parser.ts index e9cb78ff4ee..7d5fb802083 100644 --- a/src/main/ai-vault/session-scanner-droid-parser.ts +++ b/src/main/ai-vault/scanners/droid/session-scanner-droid-parser.ts @@ -1,28 +1,24 @@ -import { openTranscriptReadStream } from '../native-chat/wsl-transcript-fs-access' +import { openTranscriptReadStream } from '../../../native-chat/wsl-transcript-fs-access' import { createInterface } from 'node:readline' -import type { AiVaultSession } from '../../shared/ai-vault-types' -import type { ExecutionHostId } from '../../shared/execution-host' +import type { AiVaultSession } from '../../../../shared/ai-vault-types' +import type { ExecutionHostId } from '../../../../shared/execution-host' import type { FileWithMtime, ResumableSessionParseState, SessionAccumulator -} from './session-scanner-types' -import type { TranscriptMessageSink } from './session-transcript-consumers' +} from '../../session-scanner-types' +import type { TranscriptMessageSink } from '../../transcripts/session-transcript-consumers' import { accumulatorFoldResumeState, createAccumulator, sessionIdFromFileName, updateTimeline -} from './session-scanner-accumulator' -import { addSessionContent, addSessionText } from './session-scanner-messages' -import { - asRecord, - extractMessageText, - extractString, - normalizeTitleText, - parseJsonObject, - tokenTotal -} from './session-scanner-values' +} from '../../session-scanner-accumulator' +import { addSessionContent, addSessionText } from '../../session-scanner-messages' +import { asRecord } from '../../session-scanner-record-value' +import { extractMessageText, normalizeTitleText } from '../../session-scanner-text-normalization' +import { extractString, parseJsonObject } from '../../session-scanner-values' +import { tokenTotal } from '../../session-scanner-token-values' type ParserSessionOptions = { executionHostId?: ExecutionHostId diff --git a/src/main/ai-vault/session-scanner-gemini-parsers.ts b/src/main/ai-vault/scanners/gemini/session-scanner-gemini-parsers.ts similarity index 86% rename from src/main/ai-vault/session-scanner-gemini-parsers.ts rename to src/main/ai-vault/scanners/gemini/session-scanner-gemini-parsers.ts index 9dfd75ff592..dd9c57a6814 100644 --- a/src/main/ai-vault/session-scanner-gemini-parsers.ts +++ b/src/main/ai-vault/scanners/gemini/session-scanner-gemini-parsers.ts @@ -1,31 +1,27 @@ -import { readStreamedSessionDocument } from './session-document-stream' -import { remoteSessionContentLines } from './remote-session-content-lines' -import { openTranscriptReadStream } from '../native-chat/wsl-transcript-fs-access' +import { readStreamedSessionDocument } from '../../transcripts/session-document-stream' +import { remoteSessionContentLines } from '../../transcripts/remote-session-content-lines' +import { openTranscriptReadStream } from '../../../native-chat/wsl-transcript-fs-access' import { createInterface } from 'node:readline' -import type { AiVaultSession } from '../../shared/ai-vault-types' +import type { AiVaultSession } from '../../../../shared/ai-vault-types' import type { FileWithMtime, ResumableParseFinalizeOptions, ResumableSessionParseState, SessionAccumulator -} from './session-scanner-types' -import type { TranscriptMessageSink } from './session-transcript-consumers' +} from '../../session-scanner-types' +import type { TranscriptMessageSink } from '../../transcripts/session-transcript-consumers' import { accumulatorFoldResumeState, createAccumulator, finalizeSession, sessionIdFromFileName, updateTimeline -} from './session-scanner-accumulator' -import { addSessionContent } from './session-scanner-messages' -import { - arrayValue, - asRecord, - extractContentText, - extractString, - parseJsonObject, - tokenTotal -} from './session-scanner-values' +} from '../../session-scanner-accumulator' +import { addSessionContent } from '../../session-scanner-messages' +import { arrayValue, extractString, parseJsonObject } from '../../session-scanner-values' +import { asRecord } from '../../session-scanner-record-value' +import { extractContentText } from '../../session-scanner-text-normalization' +import { tokenTotal } from '../../session-scanner-token-values' export async function parseGeminiSessionFile( file: FileWithMtime, diff --git a/src/main/ai-vault/session-scanner-grok-parser.test.ts b/src/main/ai-vault/scanners/grok/session-scanner-grok-parser.test.ts similarity index 96% rename from src/main/ai-vault/session-scanner-grok-parser.test.ts rename to src/main/ai-vault/scanners/grok/session-scanner-grok-parser.test.ts index 1bc5863fc90..fe16b289f68 100644 --- a/src/main/ai-vault/session-scanner-grok-parser.test.ts +++ b/src/main/ai-vault/scanners/grok/session-scanner-grok-parser.test.ts @@ -2,9 +2,9 @@ import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, describe, expect, it } from 'vitest' -import { withFullFirstUserPromptCapture } from './session-scanner-first-user-prompt-capture' +import { withFullFirstUserPromptCapture } from '../../session-scanner-first-user-prompt-capture' import { parseGrokSessionFile } from './session-scanner-grok-parser' -import type { TranscriptMessage } from './session-transcript-consumers' +import type { TranscriptMessage } from '../../transcripts/session-transcript-consumers' let tempRoots: string[] = [] diff --git a/src/main/ai-vault/session-scanner-grok-parser.ts b/src/main/ai-vault/scanners/grok/session-scanner-grok-parser.ts similarity index 78% rename from src/main/ai-vault/session-scanner-grok-parser.ts rename to src/main/ai-vault/scanners/grok/session-scanner-grok-parser.ts index 0f381d34a27..a67d0189adb 100644 --- a/src/main/ai-vault/session-scanner-grok-parser.ts +++ b/src/main/ai-vault/scanners/grok/session-scanner-grok-parser.ts @@ -1,29 +1,29 @@ -import { openTranscriptReadStream, wslGatedReadFile } from '../native-chat/wsl-transcript-fs-access' -import { WslTranscriptFsError } from '../native-chat/wsl-transcript-fs-gate' +import { + openTranscriptReadStream, + wslGatedReadFile +} from '../../../native-chat/wsl-transcript-fs-access' +import { WslTranscriptFsError } from '../../../native-chat/wsl-transcript-fs-error' import { dirname } from 'node:path' import { createInterface } from 'node:readline' -import type { AiVaultSession } from '../../shared/ai-vault-types' -import { grokTranscriptPathForMetadata } from '../../shared/ai-vault-session-log-resource' -import type { FileWithMtime, SessionAccumulator } from './session-scanner-types' -import type { TranscriptMessageSink } from './session-transcript-consumers' +import type { AiVaultSession } from '../../../../shared/ai-vault-types' +import { grokTranscriptPathForMetadata } from '../../../../shared/ai-vault-session-log-resource' +import type { FileWithMtime, SessionAccumulator } from '../../session-scanner-types' +import type { TranscriptMessageSink } from '../../transcripts/session-transcript-consumers' import { createAccumulator, finalizeSession, sessionIdFromFileName, updateTimeline -} from './session-scanner-accumulator' -import { addSessionContent, addSessionText } from './session-scanner-messages' +} from '../../session-scanner-accumulator' +import { addSessionContent, addSessionText } from '../../session-scanner-messages' import { extractGrokFirstUserPromptText, stripGrokUserQueryEnvelope } from './session-scanner-grok-user-text' -import { - asRecord, - extractString, - normalizeTitleText, - numberValue, - parseJsonObject -} from './session-scanner-values' +import { asRecord } from '../../session-scanner-record-value' +import { extractString, parseJsonObject } from '../../session-scanner-values' +import { normalizeTitleText } from '../../session-scanner-text-normalization' +import { numberValue } from '../../session-scanner-token-values' const GROK_PREVIEW_SCAN_LIMIT = 4096 diff --git a/src/main/ai-vault/session-scanner-grok-user-text.test.ts b/src/main/ai-vault/scanners/grok/session-scanner-grok-user-text.test.ts similarity index 100% rename from src/main/ai-vault/session-scanner-grok-user-text.test.ts rename to src/main/ai-vault/scanners/grok/session-scanner-grok-user-text.test.ts diff --git a/src/main/ai-vault/session-scanner-grok-user-text.ts b/src/main/ai-vault/scanners/grok/session-scanner-grok-user-text.ts similarity index 100% rename from src/main/ai-vault/session-scanner-grok-user-text.ts rename to src/main/ai-vault/scanners/grok/session-scanner-grok-user-text.ts diff --git a/src/main/ai-vault/session-scanner-hermes-parser.ts b/src/main/ai-vault/scanners/hermes/session-scanner-hermes-parser.ts similarity index 80% rename from src/main/ai-vault/session-scanner-hermes-parser.ts rename to src/main/ai-vault/scanners/hermes/session-scanner-hermes-parser.ts index d199f803f77..2fdddc0aa7f 100644 --- a/src/main/ai-vault/session-scanner-hermes-parser.ts +++ b/src/main/ai-vault/scanners/hermes/session-scanner-hermes-parser.ts @@ -1,23 +1,20 @@ -import { readStreamedSessionDocument } from './session-document-stream' -import { openTranscriptReadStream } from '../native-chat/wsl-transcript-fs-access' -import type { AiVaultSession } from '../../shared/ai-vault-types' -import type { ExecutionHostId } from '../../shared/execution-host' -import type { FileWithMtime, SessionAccumulator } from './session-scanner-types' -import type { TranscriptMessageSink } from './session-transcript-consumers' +import { readStreamedSessionDocument } from '../../transcripts/session-document-stream' +import { openTranscriptReadStream } from '../../../native-chat/wsl-transcript-fs-access' +import type { AiVaultSession } from '../../../../shared/ai-vault-types' +import type { ExecutionHostId } from '../../../../shared/execution-host' +import type { FileWithMtime, SessionAccumulator } from '../../session-scanner-types' +import type { TranscriptMessageSink } from '../../transcripts/session-transcript-consumers' import { createAccumulator, finalizeSession, sessionIdFromFileName, updateTimeline -} from './session-scanner-accumulator' -import { addSessionContent } from './session-scanner-messages' -import { - arrayValue, - asRecord, - extractContentText, - extractString, - numberValue -} from './session-scanner-values' +} from '../../session-scanner-accumulator' +import { addSessionContent } from '../../session-scanner-messages' +import { arrayValue, extractString } from '../../session-scanner-values' +import { asRecord } from '../../session-scanner-record-value' +import { extractContentText } from '../../session-scanner-text-normalization' +import { numberValue } from '../../session-scanner-token-values' type ParserSessionOptions = { executionHostId?: ExecutionHostId diff --git a/src/main/ai-vault/session-scanner-jcode-parser.test.ts b/src/main/ai-vault/scanners/jcode/session-scanner-jcode-parser.test.ts similarity index 100% rename from src/main/ai-vault/session-scanner-jcode-parser.test.ts rename to src/main/ai-vault/scanners/jcode/session-scanner-jcode-parser.test.ts diff --git a/src/main/ai-vault/session-scanner-jcode-parser.ts b/src/main/ai-vault/scanners/jcode/session-scanner-jcode-parser.ts similarity index 81% rename from src/main/ai-vault/session-scanner-jcode-parser.ts rename to src/main/ai-vault/scanners/jcode/session-scanner-jcode-parser.ts index 652fdae0105..efa67eaf53c 100644 --- a/src/main/ai-vault/session-scanner-jcode-parser.ts +++ b/src/main/ai-vault/scanners/jcode/session-scanner-jcode-parser.ts @@ -1,23 +1,19 @@ -import { wslGatedReadFile } from '../native-chat/wsl-transcript-fs-access' -import type { AiVaultSession } from '../../shared/ai-vault-types' -import type { ExecutionHostId } from '../../shared/execution-host' -import type { FileWithMtime } from './session-scanner-types' -import type { TranscriptMessageSink } from './session-transcript-consumers' +import { wslGatedReadFile } from '../../../native-chat/wsl-transcript-fs-access' +import type { AiVaultSession } from '../../../../shared/ai-vault-types' +import type { ExecutionHostId } from '../../../../shared/execution-host' +import type { FileWithMtime } from '../../session-scanner-types' +import type { TranscriptMessageSink } from '../../transcripts/session-transcript-consumers' import { createAccumulator, finalizeSession, sessionIdFromFileName, updateTimeline -} from './session-scanner-accumulator' -import { addSessionContent } from './session-scanner-messages' -import { - arrayValue, - asRecord, - extractContentText, - extractString, - normalizeTitleText -} from './session-scanner-values' -import { numberValue } from './session-scanner-token-values' +} from '../../session-scanner-accumulator' +import { addSessionContent } from '../../session-scanner-messages' +import { arrayValue, extractString } from '../../session-scanner-values' +import { asRecord } from '../../session-scanner-record-value' +import { extractContentText, normalizeTitleText } from '../../session-scanner-text-normalization' +import { numberValue } from '../../session-scanner-token-values' type ParserSessionOptions = { executionHostId?: ExecutionHostId diff --git a/src/main/ai-vault/session-scanner-kimi-index-cache.test.ts b/src/main/ai-vault/scanners/kimi/session-scanner-kimi-index-cache.test.ts similarity index 100% rename from src/main/ai-vault/session-scanner-kimi-index-cache.test.ts rename to src/main/ai-vault/scanners/kimi/session-scanner-kimi-index-cache.test.ts diff --git a/src/main/ai-vault/session-scanner-kimi-index-cache.ts b/src/main/ai-vault/scanners/kimi/session-scanner-kimi-index-cache.ts similarity index 100% rename from src/main/ai-vault/session-scanner-kimi-index-cache.ts rename to src/main/ai-vault/scanners/kimi/session-scanner-kimi-index-cache.ts diff --git a/src/main/ai-vault/session-scanner-kimi-parser.test.ts b/src/main/ai-vault/scanners/kimi/session-scanner-kimi-parser.test.ts similarity index 97% rename from src/main/ai-vault/session-scanner-kimi-parser.test.ts rename to src/main/ai-vault/scanners/kimi/session-scanner-kimi-parser.test.ts index 14c042a3511..26db11431bf 100644 --- a/src/main/ai-vault/session-scanner-kimi-parser.test.ts +++ b/src/main/ai-vault/scanners/kimi/session-scanner-kimi-parser.test.ts @@ -6,11 +6,11 @@ import { parseKimiSessionFile } from './session-scanner-kimi-parser' import { clearKimiSessionIndexCache, hasKimiSessionIndexCacheEntryForTests, - KIMI_WORK_DIR_CACHE_MAX_INDEX_PATHS, readKimiWorkDirBySessionId } from './session-scanner-kimi-paths' -import type { FileWithMtime } from './session-scanner-types' -import type { TranscriptMessage } from './session-transcript-consumers' +import { KIMI_WORK_DIR_CACHE_MAX_INDEX_PATHS } from './session-scanner-kimi-index-cache' +import type { FileWithMtime } from '../../session-scanner-types' +import type { TranscriptMessage } from '../../transcripts/session-transcript-consumers' let tempDirs: string[] = [] diff --git a/src/main/ai-vault/session-scanner-kimi-parser.ts b/src/main/ai-vault/scanners/kimi/session-scanner-kimi-parser.ts similarity index 84% rename from src/main/ai-vault/session-scanner-kimi-parser.ts rename to src/main/ai-vault/scanners/kimi/session-scanner-kimi-parser.ts index 13112c41835..c330014fbf9 100644 --- a/src/main/ai-vault/session-scanner-kimi-parser.ts +++ b/src/main/ai-vault/scanners/kimi/session-scanner-kimi-parser.ts @@ -1,25 +1,28 @@ -import { openTranscriptReadStream, wslGatedReadFile } from '../native-chat/wsl-transcript-fs-access' -import { WslTranscriptFsError } from '../native-chat/wsl-transcript-fs-gate' +import { + openTranscriptReadStream, + wslGatedReadFile +} from '../../../native-chat/wsl-transcript-fs-access' +import { WslTranscriptFsError } from '../../../native-chat/wsl-transcript-fs-error' import { createInterface } from 'node:readline' -import type { AiVaultSession } from '../../shared/ai-vault-types' -import { createAccumulator, finalizeSession, updateTimeline } from './session-scanner-accumulator' -import { addSessionContent, addSessionText } from './session-scanner-messages' +import type { AiVaultSession } from '../../../../shared/ai-vault-types' +import { + createAccumulator, + finalizeSession, + updateTimeline +} from '../../session-scanner-accumulator' +import { addSessionContent, addSessionText } from '../../session-scanner-messages' import { kimiPrimaryAgentWirePath, kimiSessionIdFromStatePath, kimiSessionIndexPathFromStatePath, readKimiWorkDirBySessionId } from './session-scanner-kimi-paths' -import type { FileWithMtime, SessionAccumulator } from './session-scanner-types' -import type { TranscriptMessageSink } from './session-transcript-consumers' -import { - asRecord, - extractContentText, - extractString, - normalizeTitleText, - numberValue, - parseJsonObject -} from './session-scanner-values' +import type { FileWithMtime, SessionAccumulator } from '../../session-scanner-types' +import type { TranscriptMessageSink } from '../../transcripts/session-transcript-consumers' +import { asRecord } from '../../session-scanner-record-value' +import { extractContentText, normalizeTitleText } from '../../session-scanner-text-normalization' +import { extractString, parseJsonObject } from '../../session-scanner-values' +import { numberValue } from '../../session-scanner-token-values' // State supplies metadata, session_index supplies cwd, and the wire transcript supplies messages and usage. export async function parseKimiSessionFile( diff --git a/src/main/ai-vault/session-scanner-kimi-paths.ts b/src/main/ai-vault/scanners/kimi/session-scanner-kimi-paths.ts similarity index 88% rename from src/main/ai-vault/session-scanner-kimi-paths.ts rename to src/main/ai-vault/scanners/kimi/session-scanner-kimi-paths.ts index 33176b6bb8c..ec8cffa90d1 100644 --- a/src/main/ai-vault/session-scanner-kimi-paths.ts +++ b/src/main/ai-vault/scanners/kimi/session-scanner-kimi-paths.ts @@ -1,17 +1,15 @@ import { homedir } from 'node:os' import { basename, dirname, join } from 'node:path' import { createInterface } from 'node:readline' -import { resolveAbsoluteDirOverride } from '../../shared/absolute-dir-override' -import { openTranscriptReadStream, wslGatedStat } from '../native-chat/wsl-transcript-fs-access' -import { WslTranscriptFsError } from '../native-chat/wsl-transcript-fs-gate' -import { asRecord, extractString } from './session-scanner-values' +import { resolveAbsoluteDirOverride } from '../../../../shared/absolute-dir-override' import { - KimiSessionIndexCache, - KIMI_WORK_DIR_CACHE_MAX_INDEX_PATHS, - KIMI_WORK_DIR_CACHE_TTL_MS -} from './session-scanner-kimi-index-cache' - -export { KIMI_WORK_DIR_CACHE_MAX_INDEX_PATHS, KIMI_WORK_DIR_CACHE_TTL_MS } + openTranscriptReadStream, + wslGatedStat +} from '../../../native-chat/wsl-transcript-fs-access' +import { WslTranscriptFsError } from '../../../native-chat/wsl-transcript-fs-error' +import { asRecord } from '../../session-scanner-record-value' +import { extractString } from '../../session-scanner-values' +import { KimiSessionIndexCache } from './session-scanner-kimi-index-cache' export function resolveKimiSessionsDir(override?: string): string { if (override?.trim()) { diff --git a/src/main/ai-vault/session-scanner-kiro-fixtures.ts b/src/main/ai-vault/scanners/kiro/session-scanner-kiro-fixtures.ts similarity index 94% rename from src/main/ai-vault/session-scanner-kiro-fixtures.ts rename to src/main/ai-vault/scanners/kiro/session-scanner-kiro-fixtures.ts index e29e55bdd1b..4cfb9992ad6 100644 --- a/src/main/ai-vault/session-scanner-kiro-fixtures.ts +++ b/src/main/ai-vault/scanners/kiro/session-scanner-kiro-fixtures.ts @@ -1,6 +1,6 @@ import { mkdir, writeFile } from 'node:fs/promises' import { join } from 'node:path' -import { type isolatedScanRoots, writeJsonlFile } from './session-scanner-test-fixtures' +import { type isolatedScanRoots, writeJsonlFile } from '../../session-scanner-test-fixtures' export const KIRO_FIXTURE_SESSION_ID = '0b5e1c2a-3d4f-4a5b-8c6d-7e8f9a0b1c2d' diff --git a/src/main/ai-vault/session-scanner-kiro-parser.test.ts b/src/main/ai-vault/scanners/kiro/session-scanner-kiro-parser.test.ts similarity index 97% rename from src/main/ai-vault/session-scanner-kiro-parser.test.ts rename to src/main/ai-vault/scanners/kiro/session-scanner-kiro-parser.test.ts index 3e238c513a1..f98b40e513d 100644 --- a/src/main/ai-vault/session-scanner-kiro-parser.test.ts +++ b/src/main/ai-vault/scanners/kiro/session-scanner-kiro-parser.test.ts @@ -4,10 +4,10 @@ import { join } from 'node:path' import { afterEach, describe, expect, it } from 'vitest' import { isKiroSessionMetadataPath, - kiroTranscriptPathForMetadata, parseKiroSessionContent, parseKiroSessionFile } from './session-scanner-kiro-parser' +import { kiroTranscriptPathForMetadata } from '../../../../shared/ai-vault-session-log-resource' const SESSION_ID = '0b5e1c2a-3d4f-4a5b-8c6d-7e8f9a0b1c2d' diff --git a/src/main/ai-vault/session-scanner-kiro-parser.ts b/src/main/ai-vault/scanners/kiro/session-scanner-kiro-parser.ts similarity index 82% rename from src/main/ai-vault/session-scanner-kiro-parser.ts rename to src/main/ai-vault/scanners/kiro/session-scanner-kiro-parser.ts index e22d72ad867..67228098ff4 100644 --- a/src/main/ai-vault/session-scanner-kiro-parser.ts +++ b/src/main/ai-vault/scanners/kiro/session-scanner-kiro-parser.ts @@ -1,22 +1,22 @@ import { basename } from 'node:path' -import { wslGatedReadFile } from '../native-chat/wsl-transcript-fs-access' -import { WslTranscriptFsError } from '../native-chat/wsl-transcript-fs-gate' -import type { AiVaultSession } from '../../shared/ai-vault-types' -import { kiroTranscriptPathForMetadata } from '../../shared/ai-vault-session-log-resource' -import type { ExecutionHostId } from '../../shared/execution-host' -import { createAccumulator, finalizeSession, updateTimeline } from './session-scanner-accumulator' -import { addSessionContent } from './session-scanner-messages' -import { consumeCompleteJsonlLines } from './session-scanner-jsonl-reader' -import type { FileWithMtime, SessionAccumulator } from './session-scanner-types' -import type { TranscriptMessageSink } from './session-transcript-consumers' -import type { SkippedTranscriptRecord } from './session-transcript-record-budget' +import { wslGatedReadFile } from '../../../native-chat/wsl-transcript-fs-access' +import { WslTranscriptFsError } from '../../../native-chat/wsl-transcript-fs-error' +import type { AiVaultSession } from '../../../../shared/ai-vault-types' +import { kiroTranscriptPathForMetadata } from '../../../../shared/ai-vault-session-log-resource' +import type { ExecutionHostId } from '../../../../shared/execution-host' import { - arrayValue, - asRecord, - extractString, - normalizeTitleText, - parseJsonObject -} from './session-scanner-values' + createAccumulator, + finalizeSession, + updateTimeline +} from '../../session-scanner-accumulator' +import { addSessionContent } from '../../session-scanner-messages' +import { consumeCompleteJsonlLines } from '../../session-scanner-jsonl-reader' +import type { FileWithMtime, SessionAccumulator } from '../../session-scanner-types' +import type { TranscriptMessageSink } from '../../transcripts/session-transcript-consumers' +import type { SkippedTranscriptRecord } from '../../transcripts/session-transcript-record-budget' +import { arrayValue, extractString, parseJsonObject } from '../../session-scanner-values' +import { asRecord } from '../../session-scanner-record-value' +import { normalizeTitleText } from '../../session-scanner-text-normalization' type ParserSessionOptions = { executionHostId?: ExecutionHostId @@ -32,8 +32,6 @@ export function isKiroSessionMetadataPath(filePath: string): boolean { return KIRO_SESSION_FILE_PATTERN.test(basename(filePath)) } -export { kiroTranscriptPathForMetadata } - /** Translate Kiro kind/data blocks into preview content blocks. */ function toPreviewBlocks(content: unknown): Record[] { const blocks: Record[] = [] diff --git a/src/main/ai-vault/session-scanner-muse-parser.ts b/src/main/ai-vault/scanners/muse/session-scanner-muse-parser.ts similarity index 87% rename from src/main/ai-vault/session-scanner-muse-parser.ts rename to src/main/ai-vault/scanners/muse/session-scanner-muse-parser.ts index 7e3f09c1f96..6cfb2f1f882 100644 --- a/src/main/ai-vault/session-scanner-muse-parser.ts +++ b/src/main/ai-vault/scanners/muse/session-scanner-muse-parser.ts @@ -1,21 +1,25 @@ -import { wslGatedReadFile } from '../native-chat/wsl-transcript-fs-access' -import type { AiVaultSession } from '../../shared/ai-vault-types' -import { unwrapMuseLogRecords } from '../../shared/muse-session-log' -import type { ExecutionHostId } from '../../shared/execution-host' -import type { FileWithMtime, SessionAccumulator } from './session-scanner-types' -import type { TranscriptMessageSink } from './session-transcript-consumers' -import { createAccumulator, finalizeSession, updateTimeline } from './session-scanner-accumulator' -import { addSessionContent } from './session-scanner-messages' +import { wslGatedReadFile } from '../../../native-chat/wsl-transcript-fs-access' +import type { AiVaultSession } from '../../../../shared/ai-vault-types' +import { unwrapMuseLogRecords } from '../../../../shared/muse-session-log' +import type { ExecutionHostId } from '../../../../shared/execution-host' +import type { FileWithMtime, SessionAccumulator } from '../../session-scanner-types' +import type { TranscriptMessageSink } from '../../transcripts/session-transcript-consumers' +import { + createAccumulator, + finalizeSession, + updateTimeline +} from '../../session-scanner-accumulator' +import { addSessionContent } from '../../session-scanner-messages' import { museSessionIdFromFilePath } from './session-scanner-muse-paths' import { arrayValue, - asRecord, extractString, - normalizeTitleText, - numberValue, parseJsonObject, timestampMs -} from './session-scanner-values' +} from '../../session-scanner-values' +import { asRecord } from '../../session-scanner-record-value' +import { normalizeTitleText } from '../../session-scanner-text-normalization' +import { numberValue } from '../../session-scanner-token-values' type ParserSessionOptions = { executionHostId?: ExecutionHostId diff --git a/src/main/ai-vault/session-scanner-muse-paths.ts b/src/main/ai-vault/scanners/muse/session-scanner-muse-paths.ts similarity index 77% rename from src/main/ai-vault/session-scanner-muse-paths.ts rename to src/main/ai-vault/scanners/muse/session-scanner-muse-paths.ts index 58cb9a470a8..e0e4cb795e9 100644 --- a/src/main/ai-vault/session-scanner-muse-paths.ts +++ b/src/main/ai-vault/scanners/muse/session-scanner-muse-paths.ts @@ -1,7 +1,5 @@ import { basename, dirname } from 'node:path' -export { resolveMuseSessionsDir } from '../../shared/muse-session-log' - // The UUID lives in the parent directory; every transcript basename is session.jsonl. export function museSessionIdFromFilePath(filePath: string): string { return basename(dirname(filePath)) diff --git a/src/main/ai-vault/session-scanner-muse.test.ts b/src/main/ai-vault/scanners/muse/session-scanner-muse.test.ts similarity index 93% rename from src/main/ai-vault/session-scanner-muse.test.ts rename to src/main/ai-vault/scanners/muse/session-scanner-muse.test.ts index 568f5c19e04..50a2e4e40cd 100644 --- a/src/main/ai-vault/session-scanner-muse.test.ts +++ b/src/main/ai-vault/scanners/muse/session-scanner-muse.test.ts @@ -2,14 +2,14 @@ import { mkdtemp, rm } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, describe, expect, it } from 'vitest' -import { scanAiVaultSessions } from './session-scanner' +import { scanAiVaultSessions } from '../../session-scanner' import { parseMuseSessionContent } from './session-scanner-muse-parser' import { isolatedScanRoots, jsonLines, writeMuseScannerFixture -} from './session-scanner-test-fixtures' -import type { TranscriptMessage } from './session-transcript-consumers' +} from '../../session-scanner-test-fixtures' +import type { TranscriptMessage } from '../../transcripts/session-transcript-consumers' let tempRoots: string[] = [] diff --git a/src/main/ai-vault/omp-session-root.test.ts b/src/main/ai-vault/scanners/omp/omp-session-root.test.ts similarity index 96% rename from src/main/ai-vault/omp-session-root.test.ts rename to src/main/ai-vault/scanners/omp/omp-session-root.test.ts index 6ef1214ba81..0230dc26e9a 100644 --- a/src/main/ai-vault/omp-session-root.test.ts +++ b/src/main/ai-vault/scanners/omp/omp-session-root.test.ts @@ -3,9 +3,9 @@ import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, describe, expect, it, vi } from 'vitest' import { resolveOmpSessionsDir } from './omp-session-root' -import { ompSessionsRootDirs } from './session-scanner-roots' -import { AI_VAULT_AGENT_SOURCES } from './session-scanner-agent-sources' -import { resolveSessionFilePath } from '../native-chat/session-file-resolver' +import { ompSessionsRootDirs } from '../../session-scanner-roots' +import { AI_VAULT_AGENT_SOURCES } from '../../session-scanner-agent-sources' +import { resolveSessionFilePath } from '../../../native-chat/session-file-resolver' const roots: string[] = [] function fixture() { diff --git a/src/main/ai-vault/omp-session-root.ts b/src/main/ai-vault/scanners/omp/omp-session-root.ts similarity index 97% rename from src/main/ai-vault/omp-session-root.ts rename to src/main/ai-vault/scanners/omp/omp-session-root.ts index ab834725bba..13dcfa3faac 100644 --- a/src/main/ai-vault/omp-session-root.ts +++ b/src/main/ai-vault/scanners/omp/omp-session-root.ts @@ -1,7 +1,7 @@ import { existsSync } from 'node:fs' import { homedir } from 'node:os' import { join, normalize, parse, resolve, win32 } from 'node:path' -import { normalizeAgentSessionsDir } from './session-scanner-values' +import { normalizeAgentSessionsDir } from '../../session-scanner-values' function normalizedProfile(value: string | undefined): string | undefined | null { const profile = value?.trim() diff --git a/src/main/ai-vault/session-scanner-omp-subagent-listing.test.ts b/src/main/ai-vault/scanners/omp/session-scanner-omp-subagent-listing.test.ts similarity index 100% rename from src/main/ai-vault/session-scanner-omp-subagent-listing.test.ts rename to src/main/ai-vault/scanners/omp/session-scanner-omp-subagent-listing.test.ts diff --git a/src/main/ai-vault/session-scanner-omp-subagent-listing.ts b/src/main/ai-vault/scanners/omp/session-scanner-omp-subagent-listing.ts similarity index 89% rename from src/main/ai-vault/session-scanner-omp-subagent-listing.ts rename to src/main/ai-vault/scanners/omp/session-scanner-omp-subagent-listing.ts index 47d424b9093..544f2fabd38 100644 --- a/src/main/ai-vault/session-scanner-omp-subagent-listing.ts +++ b/src/main/ai-vault/scanners/omp/session-scanner-omp-subagent-listing.ts @@ -3,12 +3,12 @@ import type { AiVaultScanIssue, AiVaultSession, AiVaultSubagentListResult -} from '../../shared/ai-vault-types' -import { wslGatedReaddir, wslGatedStat } from '../native-chat/wsl-transcript-fs-access' -import { WslTranscriptFsError } from '../native-chat/wsl-transcript-fs-gate' -import { recordSessionScanIssue, scanIssueTextFromError } from './session-scan-issues' -import { sessionIdFromFileName, sessionSortTime } from './session-scanner-accumulator' -import { parseMessageGraphSessionFile } from './session-scanner-graph-parsers' +} from '../../../../shared/ai-vault-types' +import { wslGatedReaddir, wslGatedStat } from '../../../native-chat/wsl-transcript-fs-access' +import { WslTranscriptFsError } from '../../../native-chat/wsl-transcript-fs-error' +import { recordSessionScanIssue, scanIssueTextFromError } from '../../session-scan-issues' +import { sessionIdFromFileName, sessionSortTime } from '../../session-scanner-accumulator' +import { parseMessageGraphSessionFile } from '../session-scanner-graph-parsers' import { isOmpSubagentTranscriptFileName, ompArtifactDirFor diff --git a/src/main/ai-vault/session-scanner-omp-subagent-prune.test.ts b/src/main/ai-vault/scanners/omp/session-scanner-omp-subagent-prune.test.ts similarity index 97% rename from src/main/ai-vault/session-scanner-omp-subagent-prune.test.ts rename to src/main/ai-vault/scanners/omp/session-scanner-omp-subagent-prune.test.ts index 042d2f17f4e..d69dde9c35b 100644 --- a/src/main/ai-vault/session-scanner-omp-subagent-prune.test.ts +++ b/src/main/ai-vault/scanners/omp/session-scanner-omp-subagent-prune.test.ts @@ -2,8 +2,8 @@ import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, describe, expect, it } from 'vitest' -import { scanAiVaultSessions } from './session-scanner' -import { isolatedScanRoots, jsonLines } from './session-scanner-test-fixtures' +import { scanAiVaultSessions } from '../../session-scanner' +import { isolatedScanRoots, jsonLines } from '../../session-scanner-test-fixtures' const SESSION_STEM = '2026-05-01T10-00-00-000Z_cccccccc-dddd-4eee-8fff-000000000000' const SESSION_ID = 'cccccccc-dddd-4eee-8fff-000000000000' diff --git a/src/main/ai-vault/session-scanner-omp-subagent-transcripts.test.ts b/src/main/ai-vault/scanners/omp/session-scanner-omp-subagent-transcripts.test.ts similarity index 98% rename from src/main/ai-vault/session-scanner-omp-subagent-transcripts.test.ts rename to src/main/ai-vault/scanners/omp/session-scanner-omp-subagent-transcripts.test.ts index 808ecce92bd..2ef27852dbf 100644 --- a/src/main/ai-vault/session-scanner-omp-subagent-transcripts.test.ts +++ b/src/main/ai-vault/scanners/omp/session-scanner-omp-subagent-transcripts.test.ts @@ -2,7 +2,7 @@ import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, describe, expect, it } from 'vitest' -import { parseMessageGraphSessionContent } from './session-scanner-graph-parsers' +import { parseMessageGraphSessionContent } from '../session-scanner-graph-parsers' import { countOmpSubagentTranscripts, isOmpConversationDirectory, diff --git a/src/main/ai-vault/session-scanner-omp-subagent-transcripts.ts b/src/main/ai-vault/scanners/omp/session-scanner-omp-subagent-transcripts.ts similarity index 91% rename from src/main/ai-vault/session-scanner-omp-subagent-transcripts.ts rename to src/main/ai-vault/scanners/omp/session-scanner-omp-subagent-transcripts.ts index 9ea00d8dbb3..bcc3a2476d9 100644 --- a/src/main/ai-vault/session-scanner-omp-subagent-transcripts.ts +++ b/src/main/ai-vault/scanners/omp/session-scanner-omp-subagent-transcripts.ts @@ -1,8 +1,8 @@ -import { wslGatedReaddir } from '../native-chat/wsl-transcript-fs-access' +import { wslGatedReaddir } from '../../../native-chat/wsl-transcript-fs-access' import { basename, dirname, extname, join } from 'node:path' -import { LOCAL_EXECUTION_HOST_ID } from '../../shared/execution-host' -import type { SubagentTranscriptPartition } from './session-scanner-subagent-transcripts' -import type { ResumableSessionParseState } from './session-scanner-types' +import { LOCAL_EXECUTION_HOST_ID } from '../../../../shared/execution-host' +import type { SubagentTranscriptPartition } from '../claude/session-scanner-subagent-transcripts' +import type { ResumableSessionParseState } from '../../session-scanner-types' // Infer lineage from stamp_UUID artifact directories: task transcripts are label-named and omit parentSession (#9330). const OMP_SESSION_DIR_NAME = String.raw`\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}-\d{3}Z_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}` diff --git a/src/main/ai-vault/session-scanner-omp-title.test.ts b/src/main/ai-vault/scanners/omp/session-scanner-omp-title.test.ts similarity index 98% rename from src/main/ai-vault/session-scanner-omp-title.test.ts rename to src/main/ai-vault/scanners/omp/session-scanner-omp-title.test.ts index 3e2d6a966cf..768740791a2 100644 --- a/src/main/ai-vault/session-scanner-omp-title.test.ts +++ b/src/main/ai-vault/scanners/omp/session-scanner-omp-title.test.ts @@ -2,7 +2,7 @@ import { describe, expect, it } from 'vitest' import { createMessageGraphSessionResumeState, parseMessageGraphSessionContent -} from './session-scanner-graph-parsers' +} from '../session-scanner-graph-parsers' const file = { path: '/tmp/omp-title.jsonl', mtimeMs: 1, modifiedAt: '2026-09-14T00:00:00.000Z' } const prompt = { type: 'message', message: { role: 'user', content: 'First prompt' } } diff --git a/src/main/ai-vault/session-scanner-omp-title.ts b/src/main/ai-vault/scanners/omp/session-scanner-omp-title.ts similarity index 90% rename from src/main/ai-vault/session-scanner-omp-title.ts rename to src/main/ai-vault/scanners/omp/session-scanner-omp-title.ts index e734350caad..32e9506297a 100644 --- a/src/main/ai-vault/session-scanner-omp-title.ts +++ b/src/main/ai-vault/scanners/omp/session-scanner-omp-title.ts @@ -1,4 +1,5 @@ -import { extractString, normalizeTitleText, timestampMs } from './session-scanner-values' +import { extractString, timestampMs } from '../../session-scanner-values' +import { normalizeTitleText } from '../../session-scanner-text-normalization' export type OmpTranscriptTitle = { title: string diff --git a/src/main/ai-vault/session-scanner-omp-written-record.ts b/src/main/ai-vault/scanners/omp/session-scanner-omp-written-record.ts similarity index 76% rename from src/main/ai-vault/session-scanner-omp-written-record.ts rename to src/main/ai-vault/scanners/omp/session-scanner-omp-written-record.ts index fed932ccfc4..79f5ab05ce7 100644 --- a/src/main/ai-vault/session-scanner-omp-written-record.ts +++ b/src/main/ai-vault/scanners/omp/session-scanner-omp-written-record.ts @@ -1,4 +1,5 @@ -import { asRecord, extractString } from './session-scanner-values' +import { asRecord } from '../../session-scanner-record-value' +import { extractString } from '../../session-scanner-values' // OMP inherits PI_CODING_AGENT_DIR, so Pi's folder can hold OMP transcripts; Pi never writes these. export function isOmpWrittenRecord(record: Record): boolean { diff --git a/src/main/ai-vault/openclaw-session-layout.test.ts b/src/main/ai-vault/scanners/openclaw/openclaw-session-layout.test.ts similarity index 92% rename from src/main/ai-vault/openclaw-session-layout.test.ts rename to src/main/ai-vault/scanners/openclaw/openclaw-session-layout.test.ts index c62b987dbc4..2a69251e397 100644 --- a/src/main/ai-vault/openclaw-session-layout.test.ts +++ b/src/main/ai-vault/scanners/openclaw/openclaw-session-layout.test.ts @@ -2,8 +2,8 @@ import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join, relative } from 'node:path' import { afterEach, beforeEach, describe, expect, it } from 'vitest' -import { AI_VAULT_AGENT_SOURCES } from './session-scanner-agent-sources' -import { walkSessionFiles } from './session-scanner-discovery' +import { AI_VAULT_AGENT_SOURCES } from '../../session-scanner-agent-sources' +import { walkSessionFiles } from '../../session-scanner-discovery' // The layout reported in #11394: canonical sessions beside an embedded Codex home. const CANONICAL = ['main', 'sessions', 'canonical.jsonl'] diff --git a/src/main/ai-vault/openclaw-session-layout.ts b/src/main/ai-vault/scanners/openclaw/openclaw-session-layout.ts similarity index 84% rename from src/main/ai-vault/openclaw-session-layout.ts rename to src/main/ai-vault/scanners/openclaw/openclaw-session-layout.ts index bb8adf604ab..42a64e1541c 100644 --- a/src/main/ai-vault/openclaw-session-layout.ts +++ b/src/main/ai-vault/scanners/openclaw/openclaw-session-layout.ts @@ -1,8 +1,8 @@ import { homedir } from 'node:os' import { basename, join } from 'node:path' -import { resolveAbsoluteDirOverride } from '../../shared/absolute-dir-override' -import type { AiVaultAgentSource } from './session-scanner-agent-sources' -import { pathSegments } from './session-file-discovery' +import { resolveAbsoluteDirOverride } from '../../../../shared/absolute-dir-override' +import type { AiVaultAgentSource } from '../../session-scanner-agent-sources' +import { pathSegments } from '../../session-file-discovery' /** At depth 1, enter only agent sessions directories, excluding embedded tools' histories (#11394). */ export function openClawSessionDirectoryPredicate(name: string, depth: number): boolean { diff --git a/src/main/ai-vault/opencode-wsl-runtime-preparation.test.ts b/src/main/ai-vault/scanners/opencode/reader-transport/opencode-wsl-runtime-preparation.test.ts similarity index 96% rename from src/main/ai-vault/opencode-wsl-runtime-preparation.test.ts rename to src/main/ai-vault/scanners/opencode/reader-transport/opencode-wsl-runtime-preparation.test.ts index dcac1c6e4e5..3ea6297dc36 100644 --- a/src/main/ai-vault/opencode-wsl-runtime-preparation.test.ts +++ b/src/main/ai-vault/scanners/opencode/reader-transport/opencode-wsl-runtime-preparation.test.ts @@ -2,7 +2,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join } from 'node:path' -import { NODE_RUNTIME_ASSETS } from '../../shared/node-runtime-pin' +import { NODE_RUNTIME_ASSETS } from '../../../../../shared/node-runtime-pin' import { runProcess } from '@orca/process-host' import type * as preparationModule from './opencode-wsl-runtime-preparation' @@ -16,25 +16,25 @@ const mocks = vi.hoisted(() => ({ bundles: vi.fn((platform: string) => [`C:/relay/${platform}`]) })) vi.mock('node:fs', () => ({ existsSync: mocks.exists })) -vi.mock('../../shared/app-environment', () => ({ +vi.mock('../../../../../shared/app-environment', () => ({ getAppEnvironment: () => ({ getAppPath: () => 'C:/app', getPath: () => 'C:/profile' }) })) -vi.mock('../wsl/execution/wsl-runner', () => ({ runWslProcess: mocks.run })) +vi.mock('../../../../wsl/execution/wsl-runner', () => ({ runWslProcess: mocks.run })) // The admission gate asks the running list for the path's distro; `running` stands in for it. -vi.mock('../native-chat/wsl-transcript-running-admission', () => ({ +vi.mock('../../../../native-chat/wsl-transcript-running-admission', () => ({ admitWslTranscriptPath: async (path: string) => { if ((await mocks.running([path], { requireConfirmed: true })).length === 0) { throw new Error('WSL distro is not running.') } } })) -vi.mock('../node-runtime/pinned-runtime-materializer', () => ({ +vi.mock('../../../../node-runtime/pinned-runtime-materializer', () => ({ materializeNodeRuntimeArchive: mocks.download })) -vi.mock('../ssh/relay-bundle-paths', () => ({ relayBundleCandidates: mocks.bundles })) +vi.mock('../../../../ssh/relay-bundle-paths', () => ({ relayBundleCandidates: mocks.bundles })) const home = String.raw`\\wsl.localhost\Ubuntu\home\ada` const success = (stdout: string) => ({ stdout, stderr: '', code: 0, timedOut: false }) diff --git a/src/main/ai-vault/opencode-wsl-runtime-preparation.ts b/src/main/ai-vault/scanners/opencode/reader-transport/opencode-wsl-runtime-preparation.ts similarity index 83% rename from src/main/ai-vault/opencode-wsl-runtime-preparation.ts rename to src/main/ai-vault/scanners/opencode/reader-transport/opencode-wsl-runtime-preparation.ts index 97953cf7e39..a966fb83935 100644 --- a/src/main/ai-vault/opencode-wsl-runtime-preparation.ts +++ b/src/main/ai-vault/scanners/opencode/reader-transport/opencode-wsl-runtime-preparation.ts @@ -1,27 +1,27 @@ import { randomBytes } from 'node:crypto' import { existsSync } from 'node:fs' import { basename, join } from 'node:path' -import { getAppEnvironment } from '../../shared/app-environment' -import { waitForPromiseWithSignal } from '../../shared/abort-signal-reason' -import type { ServerTarget } from '../../shared/node-runtime-pin' -import { OPENCODE_SQLITE_READER_FILENAME } from '../../shared/remote-bundle-artifacts' -import { parseWslUncPath, toWindowsWslUncPath } from '../../shared/wsl-paths' -import { NODE_SQLITE_READER_API_SOURCE } from '../sqlite/node-sqlite-reader-api' -import { relayBundleCandidates } from '../ssh/relay-bundle-paths' -import { materializeNodeRuntimeArchive } from '../node-runtime/pinned-runtime-materializer' -import { probeLinuxLibc } from '../node-runtime/linux-libc-probe' +import { getAppEnvironment } from '../../../../../shared/app-environment' +import { waitForPromiseWithSignal } from '../../../../../shared/abort-signal-reason' +import type { ServerTarget } from '../../../../../shared/node-runtime-pin' +import { OPENCODE_SQLITE_READER_FILENAME } from '../../../../../shared/remote-bundle-artifacts' +import { parseWslUncPath, toWindowsWslUncPath } from '../../../../../shared/wsl-paths' +import { NODE_SQLITE_READER_API_SOURCE } from '../../../../sqlite/node-sqlite-reader-api' +import { relayBundleCandidates } from '../../../../ssh/relay-bundle-paths' +import { materializeNodeRuntimeArchive } from '../../../../node-runtime/pinned-runtime-materializer' +import { probeLinuxLibc } from '../../../../node-runtime/linux-libc-probe' import { installNodeRuntimeFromHostArchiveCommand, nodeRuntimeStoreDir, posixNodeRuntimeExecutable, probeRemoteNodeRuntimeCommand -} from '../managed-server/install/orcad-remote-node-runtime' -import { REMOTE_NODE_RUNTIME_READY } from '../ssh/orcad-remote-node-runtime-report' -import { getRemoteHostPlatform } from '../ssh/ssh-remote-platform' -import { runWslProcess, type WslSpec } from '../wsl/execution/wsl-runner' -import { describeWslProcessFailure } from '../wsl/execution/wsl-process-failure' -import { admitWslTranscriptPath } from '../native-chat/wsl-transcript-running-admission' -import { AI_VAULT_SCAN_ISSUE_COPY } from '../../shared/ai-vault-scan-issue-copy' +} from '../../../../managed-server/install/orcad-remote-node-runtime' +import { REMOTE_NODE_RUNTIME_READY } from '../../../../ssh/orcad-remote-node-runtime-report' +import { getRemoteHostPlatform } from '../../../../ssh/ssh-remote-platform' +import { runWslProcess, type WslSpec } from '../../../../wsl/execution/wsl-runner' +import { describeWslProcessFailure } from '../../../../wsl/execution/wsl-process-failure' +import { admitWslTranscriptPath } from '../../../../native-chat/wsl-transcript-running-admission' +import { AI_VAULT_SCAN_ISSUE_COPY } from '../../../../../shared/ai-vault-scan-issue-copy' import type { OpenCodeWslRuntime } from './session-scanner-opencode-wsl-runtime' const preparation = new Map() diff --git a/src/main/ai-vault/session-scanner-opencode-native-page-limit.test.ts b/src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-native-page-limit.test.ts similarity index 100% rename from src/main/ai-vault/session-scanner-opencode-native-page-limit.test.ts rename to src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-native-page-limit.test.ts diff --git a/src/main/ai-vault/session-scanner-opencode-native-worker.test.ts b/src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-native-worker.test.ts similarity index 94% rename from src/main/ai-vault/session-scanner-opencode-native-worker.test.ts rename to src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-native-worker.test.ts index d1e284dd3dd..9de1b6c11f3 100644 --- a/src/main/ai-vault/session-scanner-opencode-native-worker.test.ts +++ b/src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-native-worker.test.ts @@ -4,12 +4,12 @@ import { tmpdir } from 'node:os' import { join } from 'node:path' import { Worker } from 'node:worker_threads' import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest' -import SyncDatabase from '../sqlite/sync-database' -import { writeOpenCodeSqliteDatabase } from './session-scanner-opencode-sqlite-fixture' +import SyncDatabase from '../../../../sqlite/sync-database' +import { writeOpenCodeSqliteDatabase } from '../sqlite/session-scanner-opencode-sqlite-fixture' import { OpenCodeSqliteWorkerClient } from './session-scanner-opencode-sqlite-worker-client' import { resolveOpenCodeSqliteWorkerEntryPath } from './session-scanner-opencode-sqlite-worker-spawn' -import type { AiVaultScanIssue } from '../../shared/ai-vault-types' -import { AGENT_SESSION_HOST_STATUS_COPY } from '../../shared/agent-session/view/agent-session-host-status-rows' +import type { AiVaultScanIssue } from '../../../../../shared/ai-vault-types' +import { AGENT_SESSION_HOST_STATUS_COPY } from '../../../../../shared/agent-session/view/agent-session-host-status-rows' const directory = mkdtempSync(join(tmpdir(), 'orca-opencode-native-worker-')) const entry = resolveOpenCodeSqliteWorkerEntryPath(directory) diff --git a/src/main/ai-vault/session-scanner-opencode-process-admission.test.ts b/src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-process-admission.test.ts similarity index 100% rename from src/main/ai-vault/session-scanner-opencode-process-admission.test.ts rename to src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-process-admission.test.ts diff --git a/src/main/ai-vault/session-scanner-opencode-sqlite-dispatch.ts b/src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-dispatch.ts similarity index 80% rename from src/main/ai-vault/session-scanner-opencode-sqlite-dispatch.ts rename to src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-dispatch.ts index fa0ce2743d3..b8b4b8539be 100644 --- a/src/main/ai-vault/session-scanner-opencode-sqlite-dispatch.ts +++ b/src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-dispatch.ts @@ -1,22 +1,22 @@ import { readOpenCodeTranscriptPage, readOpenCodeTranscriptSignal -} from '../native-chat/transcript-opencode-sqlite-query' -import type { AiVaultScanIssue } from '../../shared/ai-vault-types' -import { captureOpenCodeSqliteSession } from './session-scanner-opencode-sqlite-capture' -import { listOpenCodeSqliteSessions } from './session-scanner-opencode-sqlite-list' -import { parseOpenCodeSqliteSession } from './session-scanner-opencode-sqlite' -import { listOpenCode2SqliteSessions } from './session-scanner-opencode2-sqlite-list' +} from '../../../../native-chat/transcript-opencode-sqlite-query' +import type { AiVaultScanIssue } from '../../../../../shared/ai-vault-types' +import { captureOpenCodeSqliteSession } from '../sqlite/session-scanner-opencode-sqlite-capture' +import { listOpenCodeSqliteSessions } from '../sqlite/session-scanner-opencode-sqlite-list' +import { parseOpenCodeSqliteSession } from '../sqlite/session-scanner-opencode-sqlite' +import { listOpenCode2SqliteSessions } from '../../opencode2/session-scanner-opencode2-sqlite-list' import { captureOpenCode2SqliteSession, parseOpenCode2SqliteSession -} from './session-scanner-opencode2-sqlite' +} from '../../opencode2/session-scanner-opencode2-sqlite' import type { OpenCodeSqliteWorkerRequest, OpenCodeSqliteWorkerResponse } from './session-scanner-opencode-sqlite-worker-protocol' -import { withFullFirstUserPromptCapture } from './session-scanner-first-user-prompt-capture' +import { withFullFirstUserPromptCapture } from '../../../session-scanner-first-user-prompt-capture' export async function handleOpenCodeSqliteRequest( request: OpenCodeSqliteWorkerRequest diff --git a/src/main/ai-vault/session-scanner-opencode-sqlite-process-client.ts b/src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-process-client.ts similarity index 96% rename from src/main/ai-vault/session-scanner-opencode-sqlite-process-client.ts rename to src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-process-client.ts index 9cad97e03be..625b1926d02 100644 --- a/src/main/ai-vault/session-scanner-opencode-sqlite-process-client.ts +++ b/src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-process-client.ts @@ -1,7 +1,7 @@ import { EventEmitter } from 'node:events' import { spawnProcess } from '@orca/process-host' -import { waitForPromiseWithSignal } from '../../shared/abort-signal-reason' -import type { WorkerRequestTransport } from '../worker-threads/worker-thread-transport' +import { waitForPromiseWithSignal } from '../../../../../shared/abort-signal-reason' +import type { WorkerRequestTransport } from '../../../../worker-threads/worker-thread-transport' import { OpenCodeSqliteWorkerClient } from './session-scanner-opencode-sqlite-worker-client' import { createOpenCodeSqliteLineDecoder, diff --git a/src/main/ai-vault/session-scanner-opencode-sqlite-process-entry.ts b/src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-process-entry.ts similarity index 100% rename from src/main/ai-vault/session-scanner-opencode-sqlite-process-entry.ts rename to src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-process-entry.ts diff --git a/src/main/ai-vault/session-scanner-opencode-sqlite-process-framing.ts b/src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-process-framing.ts similarity index 89% rename from src/main/ai-vault/session-scanner-opencode-sqlite-process-framing.ts rename to src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-process-framing.ts index 9458456cd8d..98c1db63794 100644 --- a/src/main/ai-vault/session-scanner-opencode-sqlite-process-framing.ts +++ b/src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-process-framing.ts @@ -1,4 +1,4 @@ -import { SearchSubprocessLineAccumulator } from '../../shared/search-subprocess-lines' +import { SearchSubprocessLineAccumulator } from '../../../../../shared/search-subprocess-lines' export const OPENCODE_SQLITE_REQUEST_MAX_BYTES = 1024 * 1024 export const OPENCODE_SQLITE_RESPONSE_MAX_BYTES = 32 * 1024 * 1024 diff --git a/src/main/ai-vault/session-scanner-opencode-sqlite-process.test.ts b/src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-process.test.ts similarity index 96% rename from src/main/ai-vault/session-scanner-opencode-sqlite-process.test.ts rename to src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-process.test.ts index 7e0cd71db6d..f90be95ef7b 100644 --- a/src/main/ai-vault/session-scanner-opencode-sqlite-process.test.ts +++ b/src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-process.test.ts @@ -5,14 +5,17 @@ import { join } from 'node:path' import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest' import * as processRunner from '@orca/process-host' import { runProcess, spawnProcess } from '@orca/process-host' -import SyncDatabase from '../sqlite/sync-database' -import { appendTurns, writeOpenCodeSqliteDatabase } from './session-scanner-opencode-sqlite-fixture' +import SyncDatabase from '../../../../sqlite/sync-database' +import { + appendTurns, + writeOpenCodeSqliteDatabase +} from '../sqlite/session-scanner-opencode-sqlite-fixture' import { createOpenCodeSqliteProcessClient } from './session-scanner-opencode-sqlite-process-client' import { OPENCODE_SQLITE_REQUEST_MAX_BYTES, OPENCODE_SQLITE_RESPONSE_MAX_BYTES } from './session-scanner-opencode-sqlite-process-framing' -import type { AiVaultScanIssue } from '../../shared/ai-vault-types' +import type { AiVaultScanIssue } from '../../../../../shared/ai-vault-types' const executable = process.execPath const directory = mkdtempSync(join(tmpdir(), 'orca-opencode-process-')) @@ -24,7 +27,9 @@ let writer: SyncDatabase beforeAll(async () => { await build({ - entryPoints: ['src/main/ai-vault/session-scanner-opencode-sqlite-process-entry.ts'], + entryPoints: [ + 'src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-process-entry.ts' + ], bundle: true, platform: 'node', format: 'cjs', diff --git a/src/main/ai-vault/session-scanner-opencode-sqlite-worker-client.test.ts b/src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-worker-client.test.ts similarity index 98% rename from src/main/ai-vault/session-scanner-opencode-sqlite-worker-client.test.ts rename to src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-worker-client.test.ts index 9e8e229470e..0a0de3f9c93 100644 --- a/src/main/ai-vault/session-scanner-opencode-sqlite-worker-client.test.ts +++ b/src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-worker-client.test.ts @@ -11,8 +11,8 @@ import type { OpenCodeSqliteWorkerRequest, OpenCodeSqliteWorkerResponse } from './session-scanner-opencode-sqlite-worker-protocol' -import type { AiVaultScanIssue } from '../../shared/ai-vault-types' -import { withOpenCodeSqliteScanScope } from './session-scanner-opencode-sqlite-scan-scope' +import type { AiVaultScanIssue } from '../../../../../shared/ai-vault-types' +import { withOpenCodeSqliteScanScope } from '../sqlite/session-scanner-opencode-sqlite-scan-scope' class FakeWorker { postedRequests: OpenCodeSqliteWorkerRequest[] = [] diff --git a/src/main/ai-vault/session-scanner-opencode-sqlite-worker-client.ts b/src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-worker-client.ts similarity index 92% rename from src/main/ai-vault/session-scanner-opencode-sqlite-worker-client.ts rename to src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-worker-client.ts index b754f3ffa9e..e407ae072d5 100644 --- a/src/main/ai-vault/session-scanner-opencode-sqlite-worker-client.ts +++ b/src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-worker-client.ts @@ -1,7 +1,7 @@ -import type { WorkerThreadFactory } from '../worker-threads/worker-thread-transport' -import { aiVaultScanIssueText } from '../../shared/ai-vault-scan-issue-copy' -import { WorkerThreadRequestQueue } from '../worker-threads/worker-thread-request-queue' -import type { AiVaultScanIssue, AiVaultSession } from '../../shared/ai-vault-types' +import type { WorkerThreadFactory } from '../../../../worker-threads/worker-thread-transport' +import { aiVaultScanIssueText } from '../../../../../shared/ai-vault-scan-issue-copy' +import { WorkerThreadRequestQueue } from '../../../../worker-threads/worker-thread-request-queue' +import type { AiVaultScanIssue, AiVaultSession } from '../../../../../shared/ai-vault-types' import type { OpenCodeNativeChatReadRequest, OpenCodeNativeChatReadValue, @@ -11,9 +11,9 @@ import type { OpenCodeSqliteWorkerResponse } from './session-scanner-opencode-sqlite-worker-protocol' import { parseOpenCodeSqliteCaptureValue } from './session-scanner-opencode-sqlite-worker-response' -import type { SessionFileCandidate } from './session-scanner-types' -import { errorMessage } from './session-scanner-values' -import { runOpenCodeSqliteScanRequest } from './session-scanner-opencode-sqlite-scan-scope' +import type { SessionFileCandidate } from '../../../session-scanner-types' +import { errorMessage } from '../../../session-scanner-values' +import { runOpenCodeSqliteScanRequest } from '../sqlite/session-scanner-opencode-sqlite-scan-scope' // Adapt OpenCode reads to the shared worker queue and lazy host; spawning is wired in worker-spawn. diff --git a/src/main/ai-vault/session-scanner-opencode-sqlite-worker-protocol.ts b/src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-worker-protocol.ts similarity index 84% rename from src/main/ai-vault/session-scanner-opencode-sqlite-worker-protocol.ts rename to src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-worker-protocol.ts index a33fd5fb587..44c7d16352c 100644 --- a/src/main/ai-vault/session-scanner-opencode-sqlite-worker-protocol.ts +++ b/src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-worker-protocol.ts @@ -1,10 +1,10 @@ import type { OpenCodeTranscriptPage, OpenCodeTranscriptSignal -} from '../native-chat/transcript-opencode-sqlite-query' -import type { AiVaultScanIssue, AiVaultSession } from '../../shared/ai-vault-types' -import type { SessionFileCandidate } from './session-scanner-types' -import type { TranscriptMessage } from './session-transcript-consumers' +} from '../../../../native-chat/transcript-opencode-sqlite-query' +import type { AiVaultScanIssue, AiVaultSession } from '../../../../../shared/ai-vault-types' +import type { SessionFileCandidate } from '../../../session-scanner-types' +import type { TranscriptMessage } from '../../../transcripts/session-transcript-consumers' export type OpenCodeSqliteListRequest = { id: number diff --git a/src/main/ai-vault/session-scanner-opencode-sqlite-worker-response.ts b/src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-worker-response.ts similarity index 84% rename from src/main/ai-vault/session-scanner-opencode-sqlite-worker-response.ts rename to src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-worker-response.ts index 118d85388d6..ab130ae3349 100644 --- a/src/main/ai-vault/session-scanner-opencode-sqlite-worker-response.ts +++ b/src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-worker-response.ts @@ -1,7 +1,7 @@ -import type { AiVaultSession } from '../../shared/ai-vault-types' -import { asRecord } from './session-scanner-record-value' +import type { AiVaultSession } from '../../../../../shared/ai-vault-types' +import { asRecord } from '../../../session-scanner-record-value' import type { OpenCodeSqliteCaptureValue } from './session-scanner-opencode-sqlite-worker-protocol' -import type { TranscriptMessage } from './session-transcript-consumers' +import type { TranscriptMessage } from '../../../transcripts/session-transcript-consumers' function isTranscriptMessage(value: unknown): value is TranscriptMessage { const record = asRecord(value) diff --git a/src/main/ai-vault/session-scanner-opencode-sqlite-worker-spawn.test.ts b/src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-worker-spawn.test.ts similarity index 91% rename from src/main/ai-vault/session-scanner-opencode-sqlite-worker-spawn.test.ts rename to src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-worker-spawn.test.ts index 81f1b036606..ddac473b4fc 100644 --- a/src/main/ai-vault/session-scanner-opencode-sqlite-worker-spawn.test.ts +++ b/src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-worker-spawn.test.ts @@ -1,9 +1,9 @@ import { join } from 'node:path' import { describe, expect, it, vi } from 'vitest' -import { FOREIGN_SQLITE_READER_ENTRY_FILENAME as ENTRY } from '../foreign-sqlite-readers/foreign-sqlite-reader-entry-path' +import { FOREIGN_SQLITE_READER_ENTRY_FILENAME as ENTRY } from '../../../../foreign-sqlite-readers/foreign-sqlite-reader-entry-path' import type * as OpenCodeWslClient from './session-scanner-opencode-wsl-client' import type { OpenCodeSqliteWorkerClient } from './session-scanner-opencode-sqlite-worker-client' -import type { AiVaultScanIssue } from '../../shared/ai-vault-types' +import type { AiVaultScanIssue } from '../../../../../shared/ai-vault-types' import { resolveOpenCodeSqliteWorkerEntryPath, listOpenCodeSqliteSessionsViaWorker @@ -31,7 +31,7 @@ describe('resolveOpenCodeSqliteWorkerEntryPath', () => { const mocks = vi.hoisted(() => ({ list: vi.fn() })) vi.mock('./session-scanner-opencode-wsl-client', async (importOriginal) => { - const { parseWslUncPath } = await import('../../shared/wsl-paths') + const { parseWslUncPath } = await import('../../../../../shared/wsl-paths') return { ...(await importOriginal()), openCodeWslPath: parseWslUncPath, diff --git a/src/main/ai-vault/session-scanner-opencode-sqlite-worker-spawn.ts b/src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-worker-spawn.ts similarity index 92% rename from src/main/ai-vault/session-scanner-opencode-sqlite-worker-spawn.ts rename to src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-worker-spawn.ts index 6ee21938c86..fa14ac702c1 100644 --- a/src/main/ai-vault/session-scanner-opencode-sqlite-worker-spawn.ts +++ b/src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-worker-spawn.ts @@ -1,25 +1,25 @@ -import { aiVaultScopePathsForWslDistro } from '../../shared/ai-vault-scope-cwd-match' -import { recordSessionScanIssue, scanIssueTextFromError } from './session-scan-issues' +import { aiVaultScopePathsForWslDistro } from '../../../../../shared/ai-vault-scope-cwd-match' +import { recordSessionScanIssue, scanIssueTextFromError } from '../../../session-scan-issues' import { existsSync } from 'node:fs' import { Worker } from 'node:worker_threads' -import type { AiVaultScanIssue, AiVaultSession } from '../../shared/ai-vault-types' -import { throwIfSignalAborted } from '../../shared/abort-signal-reason' -import { openCodeTranscriptPageLimit } from '../../shared/opencode-transcript-page-limit' -import type { SessionFileCandidate } from './session-scanner-types' +import type { AiVaultScanIssue, AiVaultSession } from '../../../../../shared/ai-vault-types' +import { throwIfSignalAborted } from '../../../../../shared/abort-signal-reason' +import { openCodeTranscriptPageLimit } from '../../../../../shared/opencode-transcript-page-limit' +import type { SessionFileCandidate } from '../../../session-scanner-types' import type { OpenCodeSqliteCaptureValue } from './session-scanner-opencode-sqlite-worker-protocol' import { OpenCodeSqliteWorkerClient } from './session-scanner-opencode-sqlite-worker-client' import { buildOpenCodeSqliteCandidatePath, splitOpenCodeSqliteCandidate -} from './session-scanner-opencode-sqlite-paths' +} from '../../../../../shared/opencode-sqlite-session-path' import { mapOpenCodeWslSession, openCodeWslClient, openCodeWslPath } from './session-scanner-opencode-wsl-client' -import { findForeignSqliteReaderEntry } from '../foreign-sqlite-readers/foreign-sqlite-reader-entry-path' -import { runOpenCodeSqliteScanRequest } from './session-scanner-opencode-sqlite-scan-scope' -import { noteAiVaultScanDatabases, openAiVaultScanSource } from './ai-vault-scan-progress' +import { findForeignSqliteReaderEntry } from '../../../../foreign-sqlite-readers/foreign-sqlite-reader-entry-path' +import { runOpenCodeSqliteScanRequest } from '../sqlite/session-scanner-opencode-sqlite-scan-scope' +import { noteAiVaultScanDatabases, openAiVaultScanSource } from '../../../ai-vault-scan-progress' export function resolveOpenCodeSqliteWorkerEntryPath( runtimeDir = __dirname, diff --git a/src/main/ai-vault/session-scanner-opencode-wsl-client.test.ts b/src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-wsl-client.test.ts similarity index 94% rename from src/main/ai-vault/session-scanner-opencode-wsl-client.test.ts rename to src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-wsl-client.test.ts index c4f3aaf0a22..2d7f362efb5 100644 --- a/src/main/ai-vault/session-scanner-opencode-wsl-client.test.ts +++ b/src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-wsl-client.test.ts @@ -1,5 +1,5 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' -import { createAccumulator, finalizeSession } from './session-scanner-accumulator' +import { createAccumulator, finalizeSession } from '../../../session-scanner-accumulator' import type { OpenCodeSqliteProcessOptions } from './session-scanner-opencode-sqlite-process-client' const mocks = vi.hoisted(() => ({ @@ -9,7 +9,7 @@ const mocks = vi.hoisted(() => ({ create: vi.fn((_options: OpenCodeSqliteProcessOptions) => ({ dispose: vi.fn() })) })) // The admission gate asks the running list for the path's distro; `running` stands in for it. -vi.mock('../native-chat/wsl-transcript-running-admission', () => ({ +vi.mock('../../../../native-chat/wsl-transcript-running-admission', () => ({ admitWslTranscriptPath: async (path: string) => { if ((await mocks.running([path], { requireConfirmed: true })).length === 0) { throw new Error('WSL distro is not running.') @@ -19,10 +19,10 @@ vi.mock('../native-chat/wsl-transcript-running-admission', () => ({ vi.mock('./session-scanner-opencode-sqlite-process-client', () => ({ createOpenCodeSqliteProcessClient: mocks.create })) -vi.mock('../wsl/execution/wsl-executable-path', () => ({ +vi.mock('../../../../wsl/execution/wsl-executable-path', () => ({ resolveWslExecutablePath: () => 'C:\\Windows\\System32\\wsl.exe' })) -vi.mock('../wsl/execution/wsl-interop-spawn-directory', () => ({ +vi.mock('../../../../wsl/execution/wsl-interop-spawn-directory', () => ({ resolveWslInteropSpawnCwd: () => 'C:\\Windows' })) import { diff --git a/src/main/ai-vault/session-scanner-opencode-wsl-client.ts b/src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-wsl-client.ts similarity index 77% rename from src/main/ai-vault/session-scanner-opencode-wsl-client.ts rename to src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-wsl-client.ts index f377fc8cffd..4a2e70bb546 100644 --- a/src/main/ai-vault/session-scanner-opencode-wsl-client.ts +++ b/src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-wsl-client.ts @@ -1,20 +1,23 @@ -import type { AiVaultSession } from '../../shared/ai-vault-types' -import { waitForPromiseWithSignal, throwIfSignalAborted } from '../../shared/abort-signal-reason' -import { buildWslExecArgs } from '../../shared/wsl-login-shell-command' -import { parseWslUncPath } from '../../shared/wsl-paths' -import { resolveWslExecutablePath } from '../wsl/execution/wsl-executable-path' -import { resolveWslInteropSpawnCwd } from '../wsl/execution/wsl-interop-spawn-directory' -import { admitWslTranscriptPath } from '../native-chat/wsl-transcript-running-admission' -import { noteWslDistroMayHaveStopped } from '../wsl/discovery/wsl-background-distro-gate' +import type { AiVaultSession } from '../../../../../shared/ai-vault-types' +import { + waitForPromiseWithSignal, + throwIfSignalAborted +} from '../../../../../shared/abort-signal-reason' +import { buildWslExecArgs } from '../../../../../shared/wsl-login-shell-command' +import { parseWslUncPath } from '../../../../../shared/wsl-paths' +import { resolveWslExecutablePath } from '../../../../wsl/execution/wsl-executable-path' +import { resolveWslInteropSpawnCwd } from '../../../../wsl/execution/wsl-interop-spawn-directory' +import { admitWslTranscriptPath } from '../../../../native-chat/wsl-transcript-running-admission' +import { noteWslDistroMayHaveStopped } from '../../../../wsl/discovery/wsl-background-distro-gate' import { createOpenCodeSqliteProcessClient } from './session-scanner-opencode-sqlite-process-client' import type { OpenCodeSqliteWorkerClient } from './session-scanner-opencode-sqlite-worker-client' import type { OpenCodeWslRuntime } from './session-scanner-opencode-wsl-runtime' -import { buildRelayAiVaultServiceEnv } from './session-scanner-service-env' -import { AiVaultScanIssueError } from './session-scan-issues' +import { buildRelayAiVaultServiceEnv } from '../../../scan-service/session-scanner-service-env' +import { AiVaultScanIssueError } from '../../../session-scan-issues' import { AI_VAULT_SCAN_ISSUE_COPY, aiVaultScanIssueText -} from '../../shared/ai-vault-scan-issue-copy' +} from '../../../../../shared/ai-vault-scan-issue-copy' const runtimes = new Map() const clients = new Map() diff --git a/src/main/ai-vault/session-scanner-opencode-wsl-routing.test.ts b/src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-wsl-routing.test.ts similarity index 95% rename from src/main/ai-vault/session-scanner-opencode-wsl-routing.test.ts rename to src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-wsl-routing.test.ts index 9db4ba85e83..9bbeaefa23c 100644 --- a/src/main/ai-vault/session-scanner-opencode-wsl-routing.test.ts +++ b/src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-wsl-routing.test.ts @@ -1,9 +1,9 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' -import type { AiVaultScanIssue } from '../../shared/ai-vault-types' -import { createAccumulator, finalizeSession } from './session-scanner-accumulator' -import type { SessionFileCandidate } from './session-scanner-types' +import type { AiVaultScanIssue } from '../../../../../shared/ai-vault-types' +import { createAccumulator, finalizeSession } from '../../../session-scanner-accumulator' +import type { SessionFileCandidate } from '../../../session-scanner-types' import type * as wslClientModule from './session-scanner-opencode-wsl-client' -import { withOpenCodeSqliteScanScope } from './session-scanner-opencode-sqlite-scan-scope' +import { withOpenCodeSqliteScanScope } from '../sqlite/session-scanner-opencode-sqlite-scan-scope' const mocks = vi.hoisted(() => ({ native: { diff --git a/src/main/ai-vault/session-scanner-opencode-wsl-runtime.ts b/src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-wsl-runtime.ts similarity index 100% rename from src/main/ai-vault/session-scanner-opencode-wsl-runtime.ts rename to src/main/ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-wsl-runtime.ts diff --git a/src/main/ai-vault/session-scanner-opencode-cancellation.test.ts b/src/main/ai-vault/scanners/opencode/session-scanner-opencode-cancellation.test.ts similarity index 90% rename from src/main/ai-vault/session-scanner-opencode-cancellation.test.ts rename to src/main/ai-vault/scanners/opencode/session-scanner-opencode-cancellation.test.ts index 2ecf84dbccc..f05f3061074 100644 --- a/src/main/ai-vault/session-scanner-opencode-cancellation.test.ts +++ b/src/main/ai-vault/scanners/opencode/session-scanner-opencode-cancellation.test.ts @@ -2,32 +2,32 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { mkdtempSync, rmSync, writeFileSync } from 'node:fs' import { tmpdir } from 'node:os' import { join } from 'node:path' -import type * as workerSpawn from './session-scanner-opencode-sqlite-worker-spawn' -import type { SessionFileDiscovery } from './session-scanner-types' -import type { TranscriptReadOutcome } from './session-transcript-consumers' -import { createAccumulator, finalizeSession } from './session-scanner-accumulator' +import type * as workerSpawn from './reader-transport/session-scanner-opencode-sqlite-worker-spawn' +import type { SessionFileDiscovery } from '../../session-scanner-types' +import type { TranscriptReadOutcome } from '../../transcripts/session-transcript-consumers' +import { createAccumulator, finalizeSession } from '../../session-scanner-accumulator' const readers = vi.hoisted(() => ({ parse: vi.fn(), capture: vi.fn(), discover: vi.fn<() => Promise>() })) -vi.mock('./session-scanner-opencode-sqlite-worker-spawn', () => ({ +vi.mock('./reader-transport/session-scanner-opencode-sqlite-worker-spawn', () => ({ parseOpenCodeSqliteSessionViaWorker: readers.parse, parseOpenCode2SqliteSessionViaWorker: readers.parse, captureOpenCodeSqliteSessionViaWorker: readers.capture, captureOpenCode2SqliteSessionViaWorker: readers.capture })) -vi.mock('./session-scanner-source-discovery', () => ({ +vi.mock('../../session-scanner-source-discovery', () => ({ discoverAiVaultSessionSources: readers.discover })) -import { scanAiVaultSessions } from './session-scanner' -import { resetSessionParseCacheForTests } from './session-scanner-parse-cache' +import { scanAiVaultSessions } from '../../session-scanner' +import { resetSessionParseCacheForTests } from '../../parse-cache/session-parse-cache-store' import { registerTranscriptConsumer, resetTranscriptConsumersForTests -} from './session-transcript-consumers' -import { runOpenCodeSqliteScanRequest } from './session-scanner-opencode-sqlite-scan-scope' +} from '../../transcripts/session-transcript-consumers' +import { runOpenCodeSqliteScanRequest } from './sqlite/session-scanner-opencode-sqlite-scan-scope' const file = { path: '/fixture/opencode.db#session', diff --git a/src/main/ai-vault/session-scanner-opencode-parser.test.ts b/src/main/ai-vault/scanners/opencode/session-scanner-opencode-parser.test.ts similarity index 96% rename from src/main/ai-vault/session-scanner-opencode-parser.test.ts rename to src/main/ai-vault/scanners/opencode/session-scanner-opencode-parser.test.ts index 3ea3214765b..dece6746565 100644 --- a/src/main/ai-vault/session-scanner-opencode-parser.test.ts +++ b/src/main/ai-vault/scanners/opencode/session-scanner-opencode-parser.test.ts @@ -6,9 +6,9 @@ import { consumeOpenCodeMessages, parseOpenCodeSessionFile } from './session-scanner-opencode-parser' -import { createAccumulator } from './session-scanner-accumulator' -import { withFullFirstUserPromptCapture } from './session-scanner-first-user-prompt-capture' -import type { TranscriptMessage } from './session-transcript-consumers' +import { createAccumulator } from '../../session-scanner-accumulator' +import { withFullFirstUserPromptCapture } from '../../session-scanner-first-user-prompt-capture' +import type { TranscriptMessage } from '../../transcripts/session-transcript-consumers' let tempDirs: string[] = [] diff --git a/src/main/ai-vault/session-scanner-opencode-parser.ts b/src/main/ai-vault/scanners/opencode/session-scanner-opencode-parser.ts similarity index 83% rename from src/main/ai-vault/session-scanner-opencode-parser.ts rename to src/main/ai-vault/scanners/opencode/session-scanner-opencode-parser.ts index d979d237ed4..f6ecd26cc19 100644 --- a/src/main/ai-vault/session-scanner-opencode-parser.ts +++ b/src/main/ai-vault/scanners/opencode/session-scanner-opencode-parser.ts @@ -1,25 +1,25 @@ -import { wslGatedReaddir, wslGatedReadFile } from '../native-chat/wsl-transcript-fs-access' -import { WslTranscriptFsError } from '../native-chat/wsl-transcript-fs-gate' +import { wslGatedReaddir, wslGatedReadFile } from '../../../native-chat/wsl-transcript-fs-access' +import { WslTranscriptFsError } from '../../../native-chat/wsl-transcript-fs-error' import { join } from 'node:path' -import type { AiVaultSession } from '../../shared/ai-vault-types' -import type { FileWithMtime, SessionAccumulator } from './session-scanner-types' -import type { TranscriptMessageSink } from './session-transcript-consumers' +import type { AiVaultSession } from '../../../../shared/ai-vault-types' +import type { FileWithMtime, SessionAccumulator } from '../../session-scanner-types' +import type { TranscriptMessageSink } from '../../transcripts/session-transcript-consumers' import { createAccumulator, finalizeSession, sessionIdFromFileName, updateTimeline -} from './session-scanner-accumulator' -import { addSessionContent, addPreviewMessage } from './session-scanner-messages' +} from '../../session-scanner-accumulator' +import { addSessionContent, addPreviewMessage } from '../../session-scanner-messages' +import { asRecord } from '../../session-scanner-record-value' import { - asRecord, extractString, findOpenCodeStorageRoot, - normalizeTitleText, timeObjectValue, - timestampMs, - tokenTotal -} from './session-scanner-values' + timestampMs +} from '../../session-scanner-values' +import { normalizeTitleText } from '../../session-scanner-text-normalization' +import { tokenTotal } from '../../session-scanner-token-values' /** Scope discovery reads cwd without opening message files. */ export function openCodeSessionCwd(record: Record): string | null { diff --git a/src/main/ai-vault/session-scanner-opencode-sources-wsl-stall.test.ts b/src/main/ai-vault/scanners/opencode/session-scanner-opencode-sources-wsl-stall.test.ts similarity index 94% rename from src/main/ai-vault/session-scanner-opencode-sources-wsl-stall.test.ts rename to src/main/ai-vault/scanners/opencode/session-scanner-opencode-sources-wsl-stall.test.ts index 6511e6d4e8d..82dbc2d5a59 100644 --- a/src/main/ai-vault/session-scanner-opencode-sources-wsl-stall.test.ts +++ b/src/main/ai-vault/scanners/opencode/session-scanner-opencode-sources-wsl-stall.test.ts @@ -1,7 +1,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import type { Dirent } from 'node:fs' import type * as NodeFsPromisesModule from 'node:fs/promises' -import type { AiVaultScanIssue } from '../../shared/ai-vault-types' +import type { AiVaultScanIssue } from '../../../../shared/ai-vault-types' const WSL_HOME = '\\\\wsl.localhost\\Ubuntu\\home\\ada' const WSL_DATA_DIR = `${WSL_HOME}/.local/share/opencode` @@ -15,7 +15,7 @@ vi.mock('node:fs/promises', async (importOriginal) => ({ })) // The SQLite leg spawns a real worker thread, which fake timers cannot drive. -vi.mock('./session-scanner-opencode-sqlite-worker-spawn', () => ({ +vi.mock('./reader-transport/session-scanner-opencode-sqlite-worker-spawn', () => ({ listOpenCodeSqliteSessionsViaWorker: async () => [], listOpenCode2SqliteSessionsViaWorker: async () => [] })) @@ -24,7 +24,7 @@ import { opencodeDiscoveries } from './session-scanner-opencode-sources' import { resetWslTranscriptFsGateForTests, WSL_TRANSCRIPT_FS_SCAN_TIMEOUT_MS -} from '../native-chat/wsl-transcript-fs-gate' +} from '../../../native-chat/wsl-transcript-fs-gate' let releaseStall: (() => void) | undefined diff --git a/src/main/ai-vault/session-scanner-opencode-sources.test.ts b/src/main/ai-vault/scanners/opencode/session-scanner-opencode-sources.test.ts similarity index 93% rename from src/main/ai-vault/session-scanner-opencode-sources.test.ts rename to src/main/ai-vault/scanners/opencode/session-scanner-opencode-sources.test.ts index e1f5fa50be7..ecf17328562 100644 --- a/src/main/ai-vault/session-scanner-opencode-sources.test.ts +++ b/src/main/ai-vault/scanners/opencode/session-scanner-opencode-sources.test.ts @@ -14,15 +14,15 @@ const { listOpenCode2SessionsMock: vi.fn().mockResolvedValue([]) })) -vi.mock('./session-scanner-opencode-sqlite-worker-spawn', () => ({ +vi.mock('./reader-transport/session-scanner-opencode-sqlite-worker-spawn', () => ({ listOpenCode2SqliteSessionsViaWorker: listOpenCode2SessionsMock })) -vi.mock('./session-scanner-opencode-sqlite-discovery', () => ({ +vi.mock('./sqlite/session-scanner-opencode-sqlite-discovery', () => ({ discoverOpenCodeSessions: discoverOpenCodeSessionsMock })) -vi.mock('../opencode-usage/opencode-database-discovery', () => ({ +vi.mock('../../../opencode-usage/opencode-database-discovery', () => ({ listOpenCodeDatabases: listOpenCodeDatabasesMock, listOpenCodeDatabasesInDirectory: listOpenCodeDatabasesInDirectoryMock })) diff --git a/src/main/ai-vault/session-scanner-opencode-sources.ts b/src/main/ai-vault/scanners/opencode/session-scanner-opencode-sources.ts similarity index 83% rename from src/main/ai-vault/session-scanner-opencode-sources.ts rename to src/main/ai-vault/scanners/opencode/session-scanner-opencode-sources.ts index b71ff3d1148..9f2f4ecc138 100644 --- a/src/main/ai-vault/session-scanner-opencode-sources.ts +++ b/src/main/ai-vault/scanners/opencode/session-scanner-opencode-sources.ts @@ -1,17 +1,17 @@ import { basename, dirname, join } from 'node:path' -import type { AiVaultScanIssue } from '../../shared/ai-vault-types' -import type { WslTranscriptFsError } from '../native-chat/wsl-transcript-fs-gate' -import { resolveOpenCodeStorageDirectory } from '../opencode/opencode-data-directory' +import type { AiVaultScanIssue } from '../../../../shared/ai-vault-types' +import type { WslTranscriptFsError } from '../../../native-chat/wsl-transcript-fs-error' +import { resolveOpenCodeStorageDirectory } from '../../../opencode/opencode-data-directory' import { listOpenCodeDatabases, listOpenCodeDatabasesInDirectory -} from '../opencode-usage/opencode-database-discovery' -import { recordSessionScanIssue, scanIssueTextFromError } from './session-scan-issues' -import { discoverOpenCodeSessions } from './session-scanner-opencode-sqlite-discovery' -import { listOpenCode2SqliteSessionsViaWorker } from './session-scanner-opencode-sqlite-worker-spawn' -import { isOpenCodeV2DatabaseName } from '../../shared/opencode-database-name' -import type { AiVaultScanOptions, SessionFileDiscovery } from './session-scanner-types' -import { scopeWalksAgentFiles } from './session-scope-cwd' +} from '../../../opencode-usage/opencode-database-discovery' +import { recordSessionScanIssue, scanIssueTextFromError } from '../../session-scan-issues' +import { discoverOpenCodeSessions } from './sqlite/session-scanner-opencode-sqlite-discovery' +import { listOpenCode2SqliteSessionsViaWorker } from './reader-transport/session-scanner-opencode-sqlite-worker-spawn' +import { isOpenCodeV2DatabaseName } from '../../../../shared/opencode-database-name' +import type { AiVaultScanOptions, SessionFileDiscovery } from '../../session-scanner-types' +import { scopeWalksAgentFiles } from '../../session-scope-cwd' type OpenCodeSource = { storageDir: string diff --git a/src/main/ai-vault/opencode-transcript-capture-limits.ts b/src/main/ai-vault/scanners/opencode/sqlite/opencode-transcript-capture-limits.ts similarity index 100% rename from src/main/ai-vault/opencode-transcript-capture-limits.ts rename to src/main/ai-vault/scanners/opencode/sqlite/opencode-transcript-capture-limits.ts diff --git a/src/main/ai-vault/session-scanner-opencode-sqlite-bounds.test.ts b/src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-bounds.test.ts similarity index 97% rename from src/main/ai-vault/session-scanner-opencode-sqlite-bounds.test.ts rename to src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-bounds.test.ts index f4f29e0f9b4..6450d713d6d 100644 --- a/src/main/ai-vault/session-scanner-opencode-sqlite-bounds.test.ts +++ b/src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-bounds.test.ts @@ -2,9 +2,9 @@ import { mkdtempSync, rmSync } from 'node:fs' import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, describe, expect, it } from 'vitest' -import type { AiVaultScanIssue } from '../../shared/ai-vault-types' -import Database from '../sqlite/sync-database' -import { buildOpenCodeSqliteCandidatePath } from './session-scanner-opencode-sqlite-paths' +import type { AiVaultScanIssue } from '../../../../../shared/ai-vault-types' +import Database from '../../../../sqlite/sync-database' +import { buildOpenCodeSqliteCandidatePath } from '../../../../../shared/opencode-sqlite-session-path' import { listOpenCodeSqliteSessions } from './session-scanner-opencode-sqlite-list' import { parseOpenCodeSqliteSession } from './session-scanner-opencode-sqlite' diff --git a/src/main/ai-vault/session-scanner-opencode-sqlite-capture.ts b/src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-capture.ts similarity index 91% rename from src/main/ai-vault/session-scanner-opencode-sqlite-capture.ts rename to src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-capture.ts index 70f7e3c4276..d87a63f6396 100644 --- a/src/main/ai-vault/session-scanner-opencode-sqlite-capture.ts +++ b/src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-capture.ts @@ -2,17 +2,23 @@ import { OPENCODE_CAPTURE_RECORD_LIMIT, OPENCODE_CAPTURE_TEXT_LIMIT } from './opencode-transcript-capture-limits' -import type { AiVaultSession } from '../../shared/ai-vault-types' -import { timestampIso } from './session-scanner-accumulator' -import { asRecord } from './session-scanner-record-value' +import type { AiVaultSession } from '../../../../../shared/ai-vault-types' +import { timestampIso } from '../../../session-scanner-accumulator' +import { asRecord } from '../../../session-scanner-record-value' import { extractPartText, readOpenCodeSqliteSession } from './session-scanner-opencode-sqlite' import { readOpenCodeDatabase } from './session-scanner-opencode-sqlite-open' import { canReadOpenCodeMessageParts } from './session-scanner-opencode-sqlite-schema' -import type { TranscriptMessage, TranscriptMessageRole } from './session-transcript-consumers' -import { toolCallContent, transcriptMessageFromText } from './session-transcript-message-content' -import { zcodeVisibleMessageFilter } from './session-scanner-zcode-visibility' -import { zcodeTranscriptOrder } from './session-scanner-zcode-order' -import type SyncDatabase from '../sqlite/sync-database' +import type { + TranscriptMessage, + TranscriptMessageRole +} from '../../../transcripts/session-transcript-consumers' +import { + toolCallContent, + transcriptMessageFromText +} from '../../../transcripts/session-transcript-message-content' +import { zcodeVisibleMessageFilter } from '../../zcode/session-scanner-zcode-visibility' +import { zcodeTranscriptOrder } from '../../zcode/session-scanner-zcode-order' +import type SyncDatabase from '../../../../sqlite/sync-database' // Capture shares session decoding with listing but selects the full transcript instead of the preview window. diff --git a/src/main/ai-vault/session-scanner-opencode-sqlite-coexistence.test.ts b/src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-coexistence.test.ts similarity index 96% rename from src/main/ai-vault/session-scanner-opencode-sqlite-coexistence.test.ts rename to src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-coexistence.test.ts index a4f0d276208..a418fe79507 100644 --- a/src/main/ai-vault/session-scanner-opencode-sqlite-coexistence.test.ts +++ b/src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-coexistence.test.ts @@ -3,16 +3,17 @@ import { mkdtempSync, rmSync } from 'node:fs' import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, describe, expect, it, vi } from 'vitest' -import { scanAiVaultSessions } from './session-scanner' -import Database from '../sqlite/sync-database' +import { scanAiVaultSessions } from '../../../session-scanner' +import Database from '../../../../sqlite/sync-database' // Source tests lack a worker bundle; inline fixtures here while production still fails closed without it. -vi.mock('./session-scanner-opencode-sqlite-worker-spawn', async () => { +vi.mock('../reader-transport/session-scanner-opencode-sqlite-worker-spawn', async () => { const [{ listOpenCodeSqliteSessions }, { parseOpenCodeSqliteSession }] = await Promise.all([ import('./session-scanner-opencode-sqlite-list'), import('./session-scanner-opencode-sqlite') ]) - const { listOpenCode2SqliteSessions } = await import('./session-scanner-opencode2-sqlite-list') + const { listOpenCode2SqliteSessions } = + await import('../../opencode2/session-scanner-opencode2-sqlite-list') return { listOpenCode2SqliteSessionsViaWorker: listOpenCode2SqliteSessions, listOpenCodeSqliteSessionsViaWorker: listOpenCodeSqliteSessions, diff --git a/src/main/ai-vault/session-scanner-opencode-sqlite-discovery.ts b/src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-discovery.ts similarity index 79% rename from src/main/ai-vault/session-scanner-opencode-sqlite-discovery.ts rename to src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-discovery.ts index b87a4d7f14b..60e12e7d71d 100644 --- a/src/main/ai-vault/session-scanner-opencode-sqlite-discovery.ts +++ b/src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-discovery.ts @@ -1,12 +1,10 @@ import { basename, extname, join } from 'node:path' -import type { AiVaultScanIssue } from '../../shared/ai-vault-types' -import { discoverFiles } from './session-scanner-discovery' -import { splitOpenCodeSqliteCandidate } from './session-scanner-opencode-sqlite-paths' -import { listOpenCodeSqliteSessionsViaWorker } from './session-scanner-opencode-sqlite-worker-spawn' -import type { FileWithMtime, SessionFileDiscovery } from './session-scanner-types' -import { scopeWalksAgentFiles } from './session-scope-cwd' - -export { listOpenCodeSqliteSessions } from './session-scanner-opencode-sqlite-list' +import type { AiVaultScanIssue } from '../../../../../shared/ai-vault-types' +import { discoverFiles } from '../../../session-scanner-discovery' +import { splitOpenCodeSqliteCandidate } from '../../../../../shared/opencode-sqlite-session-path' +import { listOpenCodeSqliteSessionsViaWorker } from '../reader-transport/session-scanner-opencode-sqlite-worker-spawn' +import type { FileWithMtime, SessionFileDiscovery } from '../../../session-scanner-types' +import { scopeWalksAgentFiles } from '../../../session-scope-cwd' function sessionIdFromLegacyFilePath(filePath: string): string { return basename(filePath, extname(filePath)) diff --git a/src/main/ai-vault/session-scanner-opencode-sqlite-fixture.ts b/src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-fixture.ts similarity index 99% rename from src/main/ai-vault/session-scanner-opencode-sqlite-fixture.ts rename to src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-fixture.ts index 454730bfc91..ec52e5a88a0 100644 --- a/src/main/ai-vault/session-scanner-opencode-sqlite-fixture.ts +++ b/src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-fixture.ts @@ -1,6 +1,6 @@ import { mkdirSync } from 'node:fs' import { dirname } from 'node:path' -import SyncDatabase from '../sqlite/sync-database' +import SyncDatabase from '../../../../sqlite/sync-database' // Mirror the full OpenCode 1.17.x schema so column probes exercise real layouts. diff --git a/src/main/ai-vault/session-scanner-opencode-sqlite-list.ts b/src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-list.ts similarity index 90% rename from src/main/ai-vault/session-scanner-opencode-sqlite-list.ts rename to src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-list.ts index 548507f907d..1aabdf8286b 100644 --- a/src/main/ai-vault/session-scanner-opencode-sqlite-list.ts +++ b/src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-list.ts @@ -1,16 +1,16 @@ -import type { AiVaultScanIssue } from '../../shared/ai-vault-types' +import type { AiVaultScanIssue } from '../../../../../shared/ai-vault-types' import { buildOpenCodeSqliteCandidatePath, splitOpenCodeSqliteCandidate -} from './session-scanner-opencode-sqlite-paths' +} from '../../../../../shared/opencode-sqlite-session-path' import { openCodeDatabaseScanIssue, readOpenCodeDatabase } from './session-scanner-opencode-sqlite-open' -import type { SessionFileCandidate } from './session-scanner-types' -import type SyncDatabase from '../sqlite/sync-database' -import { scopedSessionRows } from './session-scanner-sqlite-scope-rows' -import { columnExists, tableExists } from '../opencode-usage/schema-helpers' +import type { SessionFileCandidate } from '../../../session-scanner-types' +import type SyncDatabase from '../../../../sqlite/sync-database' +import { scopedSessionRows } from '../../session-scanner-sqlite-scope-rows' +import { columnExists, tableExists } from '../../../../opencode-usage/schema-helpers' type SessionRow = { id: string diff --git a/src/main/ai-vault/session-scanner-opencode-sqlite-open.test.ts b/src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-open.test.ts similarity index 98% rename from src/main/ai-vault/session-scanner-opencode-sqlite-open.test.ts rename to src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-open.test.ts index bec9c994309..2c44eb9e9b7 100644 --- a/src/main/ai-vault/session-scanner-opencode-sqlite-open.test.ts +++ b/src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-open.test.ts @@ -3,8 +3,8 @@ import { tmpdir } from 'node:os' import { join } from 'node:path' import { Worker } from 'node:worker_threads' import { afterEach, describe, expect, it, vi } from 'vitest' -import type { AiVaultScanIssue } from '../../shared/ai-vault-types' -import Database from '../sqlite/sync-database' +import type { AiVaultScanIssue } from '../../../../../shared/ai-vault-types' +import Database from '../../../../sqlite/sync-database' import { listOpenCodeSqliteSessions } from './session-scanner-opencode-sqlite-list' import { openCodeBusyTimeoutMs, diff --git a/src/main/ai-vault/session-scanner-opencode-sqlite-open.ts b/src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-open.ts similarity index 87% rename from src/main/ai-vault/session-scanner-opencode-sqlite-open.ts rename to src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-open.ts index f95f3354536..a6104662605 100644 --- a/src/main/ai-vault/session-scanner-opencode-sqlite-open.ts +++ b/src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-open.ts @@ -1,13 +1,13 @@ import { basename } from 'node:path' -import type { AiVaultScanIssue } from '../../shared/ai-vault-types' -import { isWslUncPath } from '../../shared/wsl-paths' +import type { AiVaultScanIssue } from '../../../../../shared/ai-vault-types' +import { isWslUncPath } from '../../../../../shared/wsl-paths' import { aiVaultScanIssueText, type AiVaultScanIssueText -} from '../../shared/ai-vault-scan-issue-copy' -import SyncDatabase from '../sqlite/sync-database' -import { classifySqliteReadFailure } from '../sqlite/sqlite-read-failure' -import { errorMessage } from './session-scanner-values' +} from '../../../../../shared/ai-vault-scan-issue-copy' +import SyncDatabase from '../../../../sqlite/sync-database' +import { classifySqliteReadFailure } from '../../../../sqlite/sqlite-read-failure' +import { errorMessage } from '../../../session-scanner-values' // Allow bounded contention waits for native reads without adding retries atop SQLite’s busy handler (#15036). const OPENCODE_SQLITE_BUSY_TIMEOUT_MS = 1_500 diff --git a/src/main/ai-vault/session-scanner-opencode-sqlite-paths.test.ts b/src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-paths.test.ts similarity index 93% rename from src/main/ai-vault/session-scanner-opencode-sqlite-paths.test.ts rename to src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-paths.test.ts index 68dfcff90c3..3ec6677af86 100644 --- a/src/main/ai-vault/session-scanner-opencode-sqlite-paths.test.ts +++ b/src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-paths.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from 'vitest' -import { splitOpenCodeSqliteCandidate } from './session-scanner-opencode-sqlite-paths' +import { splitOpenCodeSqliteCandidate } from '../../../../../shared/opencode-sqlite-session-path' describe('splitOpenCodeSqliteCandidate', () => { it('splits a synthetic db#sessionId path', () => { diff --git a/src/main/ai-vault/session-scanner-opencode-sqlite-rows.ts b/src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-rows.ts similarity index 95% rename from src/main/ai-vault/session-scanner-opencode-sqlite-rows.ts rename to src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-rows.ts index 660426b2a6e..232cbbf8110 100644 --- a/src/main/ai-vault/session-scanner-opencode-sqlite-rows.ts +++ b/src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-rows.ts @@ -1,4 +1,4 @@ -import type { SqliteRow } from '../sqlite/sqlite-statement' +import type { SqliteRow } from '../../../../sqlite/sqlite-statement' import type { SQLOutputValue } from 'node:sqlite' type SessionRow = { diff --git a/src/main/ai-vault/session-scanner-opencode-sqlite-scan-scope.test.ts b/src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-scan-scope.test.ts similarity index 100% rename from src/main/ai-vault/session-scanner-opencode-sqlite-scan-scope.test.ts rename to src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-scan-scope.test.ts diff --git a/src/main/ai-vault/session-scanner-opencode-sqlite-scan-scope.ts b/src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-scan-scope.ts similarity index 92% rename from src/main/ai-vault/session-scanner-opencode-sqlite-scan-scope.ts rename to src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-scan-scope.ts index f123015f0b9..6a109b0c3dc 100644 --- a/src/main/ai-vault/session-scanner-opencode-sqlite-scan-scope.ts +++ b/src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-scan-scope.ts @@ -1,6 +1,6 @@ import { AsyncLocalStorage } from 'node:async_hooks' -import { throwIfSignalAborted } from '../../shared/abort-signal-reason' -import type { WorkerThreadRequestOwner } from '../worker-threads/worker-thread-request-queue' +import { throwIfSignalAborted } from '../../../../../shared/abort-signal-reason' +import type { WorkerThreadRequestOwner } from '../../../../worker-threads/worker-thread-request-queue' export const OPENCODE_SQLITE_SCAN_BUDGET_MS = 45_000 diff --git a/src/main/ai-vault/session-scanner-opencode-sqlite-schema.ts b/src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-schema.ts similarity index 84% rename from src/main/ai-vault/session-scanner-opencode-sqlite-schema.ts rename to src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-schema.ts index 77aba034bef..e2fa46acb99 100644 --- a/src/main/ai-vault/session-scanner-opencode-sqlite-schema.ts +++ b/src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-schema.ts @@ -1,5 +1,5 @@ -import type SyncDatabase from '../sqlite/sync-database' -import { columnExists, tableExists } from '../opencode-usage/schema-helpers' +import type SyncDatabase from '../../../../sqlite/sync-database' +import { columnExists, tableExists } from '../../../../opencode-usage/schema-helpers' // Centralize schema probes so readers tolerate release differences without inconsistent partial guards. diff --git a/src/main/ai-vault/session-scanner-opencode-sqlite.test.ts b/src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite.test.ts similarity index 98% rename from src/main/ai-vault/session-scanner-opencode-sqlite.test.ts rename to src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite.test.ts index 3ba2df82a6c..6ecb4285d67 100644 --- a/src/main/ai-vault/session-scanner-opencode-sqlite.test.ts +++ b/src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite.test.ts @@ -2,13 +2,13 @@ import { mkdtempSync, rmSync } from 'node:fs' import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, describe, expect, it } from 'vitest' -import Database from '../sqlite/sync-database' -import { buildOpenCodeSqliteCandidatePath } from './session-scanner-opencode-sqlite-paths' -import { listOpenCodeSqliteSessions } from './session-scanner-opencode-sqlite-discovery' +import Database from '../../../../sqlite/sync-database' +import { buildOpenCodeSqliteCandidatePath } from '../../../../../shared/opencode-sqlite-session-path' +import { listOpenCodeSqliteSessions } from './session-scanner-opencode-sqlite-list' import { parseOpenCodeSqliteSession } from './session-scanner-opencode-sqlite' import { captureOpenCodeSqliteSession } from './session-scanner-opencode-sqlite-capture' -import { withFullFirstUserPromptCapture } from './session-scanner-first-user-prompt-capture' -import type { AiVaultScanIssue } from '../../shared/ai-vault-types' +import { withFullFirstUserPromptCapture } from '../../../session-scanner-first-user-prompt-capture' +import type { AiVaultScanIssue } from '../../../../../shared/ai-vault-types' let tempDirs: string[] = [] diff --git a/src/main/ai-vault/session-scanner-opencode-sqlite.ts b/src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite.ts similarity index 93% rename from src/main/ai-vault/session-scanner-opencode-sqlite.ts rename to src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite.ts index 96a507bbe05..8331e46dcf8 100644 --- a/src/main/ai-vault/session-scanner-opencode-sqlite.ts +++ b/src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite.ts @@ -1,21 +1,28 @@ -import type { AiVaultSession, AiVaultSessionPreviewMessage } from '../../shared/ai-vault-types' -import { createAccumulator, finalizeSession, updateTimeline } from './session-scanner-accumulator' -import { addPreviewMessage } from './session-scanner-messages' +import type { + AiVaultSession, + AiVaultSessionPreviewMessage +} from '../../../../../shared/ai-vault-types' +import { + createAccumulator, + finalizeSession, + updateTimeline +} from '../../../session-scanner-accumulator' +import { addPreviewMessage } from '../../../session-scanner-messages' import { normalizeFullFirstUserPromptText, shouldCaptureFullFirstUserPrompt -} from './session-scanner-first-user-prompt' +} from '../../../session-scanner-first-user-prompt' import { readOpenCodeDatabase } from './session-scanner-opencode-sqlite-open' import { readPartDataRow, readSessionRow } from './session-scanner-opencode-sqlite-rows' import { canCountOpenCodeMessages, canReadOpenCodeMessageParts } from './session-scanner-opencode-sqlite-schema' -import { normalizeTitleText } from './session-scanner-values' -import { zcodeVisibleMessageFilter } from './session-scanner-zcode-visibility' -import { zcodeTranscriptOrder } from './session-scanner-zcode-order' -import type SyncDatabase from '../sqlite/sync-database' -import { columnExists, tableExists } from '../opencode-usage/schema-helpers' +import { normalizeTitleText } from '../../../session-scanner-text-normalization' +import { zcodeVisibleMessageFilter } from '../../zcode/session-scanner-zcode-visibility' +import { zcodeTranscriptOrder } from '../../zcode/session-scanner-zcode-order' +import type SyncDatabase from '../../../../sqlite/sync-database' +import { columnExists, tableExists } from '../../../../opencode-usage/schema-helpers' const OPENCODE_SQLITE_PREVIEW_LIMIT = 5 // Bound previews to recent messages to avoid scanning large historical tool blobs; worker timeout caps residual work. diff --git a/src/main/ai-vault/session-scanner-opencode2-message.test.ts b/src/main/ai-vault/scanners/opencode2/session-scanner-opencode2-message.test.ts similarity index 92% rename from src/main/ai-vault/session-scanner-opencode2-message.test.ts rename to src/main/ai-vault/scanners/opencode2/session-scanner-opencode2-message.test.ts index ca2e5adfa17..34bac27e65f 100644 --- a/src/main/ai-vault/session-scanner-opencode2-message.test.ts +++ b/src/main/ai-vault/scanners/opencode2/session-scanner-opencode2-message.test.ts @@ -1,4 +1,4 @@ -import { transcriptMessagesFromDecodedMessage } from './session-transcript-message-content' +import { transcriptMessagesFromDecodedMessage } from '../../transcripts/session-transcript-message-content' import { describe, expect, it } from 'vitest' import { decodeOpenCode2Message, diff --git a/src/main/ai-vault/session-scanner-opencode2-message.ts b/src/main/ai-vault/scanners/opencode2/session-scanner-opencode2-message.ts similarity index 84% rename from src/main/ai-vault/session-scanner-opencode2-message.ts rename to src/main/ai-vault/scanners/opencode2/session-scanner-opencode2-message.ts index 097f0f1c509..2f8f39d2ace 100644 --- a/src/main/ai-vault/session-scanner-opencode2-message.ts +++ b/src/main/ai-vault/scanners/opencode2/session-scanner-opencode2-message.ts @@ -1,7 +1,10 @@ -import type { AiVaultSessionPreviewMessage } from '../../shared/ai-vault-types' -import { asRecord } from './session-scanner-record-value' -import { parseJsonObject } from './session-scanner-values' -import { decodeSessionMessage, type SessionMessageDecodeOptions } from './session-decoded-message' +import type { AiVaultSessionPreviewMessage } from '../../../../shared/ai-vault-types' +import { asRecord } from '../../session-scanner-record-value' +import { parseJsonObject } from '../../session-scanner-values' +import { + decodeSessionMessage, + type SessionMessageDecodeOptions +} from '../../transcripts/session-decoded-message' export function extractOpenCode2MessageText(data: string): string | null { const record = parseJsonObject(data) diff --git a/src/main/ai-vault/session-scanner-opencode2-sqlite-list.ts b/src/main/ai-vault/scanners/opencode2/session-scanner-opencode2-sqlite-list.ts similarity index 89% rename from src/main/ai-vault/session-scanner-opencode2-sqlite-list.ts rename to src/main/ai-vault/scanners/opencode2/session-scanner-opencode2-sqlite-list.ts index 18bfd5f70ac..9538dbf6910 100644 --- a/src/main/ai-vault/session-scanner-opencode2-sqlite-list.ts +++ b/src/main/ai-vault/scanners/opencode2/session-scanner-opencode2-sqlite-list.ts @@ -1,13 +1,13 @@ -import type { AiVaultScanIssue } from '../../shared/ai-vault-types' +import type { AiVaultScanIssue } from '../../../../shared/ai-vault-types' import { buildOpenCodeSqliteCandidatePath, splitOpenCodeSqliteCandidate -} from './session-scanner-opencode-sqlite-paths' -import type { SessionFileCandidate } from './session-scanner-types' -import { errorMessage } from './session-scanner-values' -import SyncDatabase from '../sqlite/sync-database' -import { columnExists, tableExists } from '../opencode-usage/schema-helpers' -import { scopedSessionRows } from './session-scanner-sqlite-scope-rows' +} from '../../../../shared/opencode-sqlite-session-path' +import type { SessionFileCandidate } from '../../session-scanner-types' +import { errorMessage } from '../../session-scanner-values' +import SyncDatabase from '../../../sqlite/sync-database' +import { columnExists, tableExists } from '../../../opencode-usage/schema-helpers' +import { scopedSessionRows } from '../session-scanner-sqlite-scope-rows' // V2 uses session_v2/session_message tables; guard evolving schemas in shared and channel databases. diff --git a/src/main/ai-vault/session-scanner-opencode2-sqlite.test.ts b/src/main/ai-vault/scanners/opencode2/session-scanner-opencode2-sqlite.test.ts similarity index 97% rename from src/main/ai-vault/session-scanner-opencode2-sqlite.test.ts rename to src/main/ai-vault/scanners/opencode2/session-scanner-opencode2-sqlite.test.ts index c58db6c01f6..b6be05cbf8c 100644 --- a/src/main/ai-vault/session-scanner-opencode2-sqlite.test.ts +++ b/src/main/ai-vault/scanners/opencode2/session-scanner-opencode2-sqlite.test.ts @@ -2,15 +2,15 @@ import { mkdtempSync, rmSync } from 'node:fs' import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, describe, expect, it } from 'vitest' -import Database from '../sqlite/sync-database' -import { buildOpenCodeSqliteCandidatePath } from './session-scanner-opencode-sqlite-paths' +import Database from '../../../sqlite/sync-database' +import { buildOpenCodeSqliteCandidatePath } from '../../../../shared/opencode-sqlite-session-path' import { listOpenCode2SqliteSessions } from './session-scanner-opencode2-sqlite-list' import { parseOpenCode2SqliteSession, captureOpenCode2SqliteSession } from './session-scanner-opencode2-sqlite' -import { withFullFirstUserPromptCapture } from './session-scanner-first-user-prompt-capture' -import type { AiVaultScanIssue } from '../../shared/ai-vault-types' +import { withFullFirstUserPromptCapture } from '../../session-scanner-first-user-prompt-capture' +import type { AiVaultScanIssue } from '../../../../shared/ai-vault-types' let tempDirs: string[] = [] diff --git a/src/main/ai-vault/session-scanner-opencode2-sqlite.ts b/src/main/ai-vault/scanners/opencode2/session-scanner-opencode2-sqlite.ts similarity index 93% rename from src/main/ai-vault/session-scanner-opencode2-sqlite.ts rename to src/main/ai-vault/scanners/opencode2/session-scanner-opencode2-sqlite.ts index b004014ed35..b80009456cb 100644 --- a/src/main/ai-vault/session-scanner-opencode2-sqlite.ts +++ b/src/main/ai-vault/scanners/opencode2/session-scanner-opencode2-sqlite.ts @@ -1,29 +1,35 @@ import { OPENCODE_CAPTURE_RECORD_LIMIT, OPENCODE_CAPTURE_TEXT_LIMIT -} from './opencode-transcript-capture-limits' -import type { AiVaultSession, AiVaultSessionPreviewMessage } from '../../shared/ai-vault-types' +} from '../opencode/sqlite/opencode-transcript-capture-limits' +import type { + AiVaultSession, + AiVaultSessionPreviewMessage +} from '../../../../shared/ai-vault-types' import { createAccumulator, finalizeSession, updateTimeline, timestampIso -} from './session-scanner-accumulator' -import { addDecodedSessionMessage } from './session-scanner-messages' +} from '../../session-scanner-accumulator' +import { addDecodedSessionMessage } from '../../session-scanner-messages' import { normalizeFullFirstUserPromptText, shouldCaptureFullFirstUserPrompt -} from './session-scanner-first-user-prompt' -import { normalizeTitleText } from './session-scanner-values' -import { asRecord } from './session-scanner-record-value' +} from '../../session-scanner-first-user-prompt' +import { normalizeTitleText } from '../../session-scanner-text-normalization' +import { asRecord } from '../../session-scanner-record-value' import { extractOpenCode2MessageText, decodeOpenCode2Message, parseOpenCode2MessageRow } from './session-scanner-opencode2-message' -import SyncDatabase from '../sqlite/sync-database' -import { columnExists, tableExists } from '../opencode-usage/schema-helpers' -import type { TranscriptMessage, TranscriptMessageSink } from './session-transcript-consumers' +import SyncDatabase from '../../../sqlite/sync-database' +import { columnExists, tableExists } from '../../../opencode-usage/schema-helpers' +import type { + TranscriptMessage, + TranscriptMessageSink +} from '../../transcripts/session-transcript-consumers' // V2 stores tagged message JSON in session_message rather than v1 part rows; schemas vary by release. diff --git a/src/main/ai-vault/session-scanner-pi-omp-shared-root.test.ts b/src/main/ai-vault/scanners/pi/session-scanner-pi-omp-shared-root.test.ts similarity index 97% rename from src/main/ai-vault/session-scanner-pi-omp-shared-root.test.ts rename to src/main/ai-vault/scanners/pi/session-scanner-pi-omp-shared-root.test.ts index fec20bfab3a..0d514b81bd3 100644 --- a/src/main/ai-vault/session-scanner-pi-omp-shared-root.test.ts +++ b/src/main/ai-vault/scanners/pi/session-scanner-pi-omp-shared-root.test.ts @@ -2,8 +2,8 @@ import { mkdtemp, rm, utimes } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, describe, expect, it } from 'vitest' -import { scanAiVaultSessions } from './session-scanner' -import { isolatedScanRoots, writeJsonlFile } from './session-scanner-test-fixtures' +import { scanAiVaultSessions } from '../../session-scanner' +import { isolatedScanRoots, writeJsonlFile } from '../../session-scanner-test-fixtures' const OMP_STEM = '2026-05-01T10-00-00-000Z_0199a000-0000-7000-8000-000000000002' const runtime = { version: '18.12.2' } diff --git a/src/main/ai-vault/session-scanner-pi-scope.test.ts b/src/main/ai-vault/scanners/pi/session-scanner-pi-scope.test.ts similarity index 94% rename from src/main/ai-vault/session-scanner-pi-scope.test.ts rename to src/main/ai-vault/scanners/pi/session-scanner-pi-scope.test.ts index 31afd351164..b70ee26b78a 100644 --- a/src/main/ai-vault/session-scanner-pi-scope.test.ts +++ b/src/main/ai-vault/scanners/pi/session-scanner-pi-scope.test.ts @@ -2,9 +2,9 @@ import { mkdtemp, mkdir, rm, utimes, writeFile } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, describe, expect, it } from 'vitest' -import { scanAiVaultSessions } from './session-scanner' -import { resetProjectDirCwdCacheForTests } from './session-scanner-scope-discovery' -import { isolatedScanRoots, jsonLines } from './session-scanner-test-fixtures' +import { scanAiVaultSessions } from '../../session-scanner' +import { resetProjectDirCwdCacheForTests } from '../../session-scanner-scope-discovery' +import { isolatedScanRoots, jsonLines } from '../../session-scanner-test-fixtures' let tempRoots: string[] = [] diff --git a/src/main/ai-vault/__fixtures__/qoder-1.1.64-generated-resumed.jsonl b/src/main/ai-vault/scanners/qoder/__fixtures__/qoder-1.1.64-generated-resumed.jsonl similarity index 100% rename from src/main/ai-vault/__fixtures__/qoder-1.1.64-generated-resumed.jsonl rename to src/main/ai-vault/scanners/qoder/__fixtures__/qoder-1.1.64-generated-resumed.jsonl diff --git a/src/main/ai-vault/session-scanner-qoder-parser.ts b/src/main/ai-vault/scanners/qoder/session-scanner-qoder-parser.ts similarity index 84% rename from src/main/ai-vault/session-scanner-qoder-parser.ts rename to src/main/ai-vault/scanners/qoder/session-scanner-qoder-parser.ts index 4e04b163d5f..abc0105135c 100644 --- a/src/main/ai-vault/session-scanner-qoder-parser.ts +++ b/src/main/ai-vault/scanners/qoder/session-scanner-qoder-parser.ts @@ -1,21 +1,22 @@ import { createInterface } from 'node:readline' -import type { ExecutionHostId } from '../../shared/execution-host' -import { openTranscriptReadStream } from '../native-chat/wsl-transcript-fs-access' -import { accumulatorSessionIdentity, updateTimeline } from './session-scanner-accumulator' +import type { ExecutionHostId } from '../../../../shared/execution-host' +import { openTranscriptReadStream } from '../../../native-chat/wsl-transcript-fs-access' +import { accumulatorSessionIdentity, updateTimeline } from '../../session-scanner-accumulator' import { cloneClaudeSessionParseState, consumeClaudeSessionRecord, createClaudeSessionParseState, finalizeClaudeSessionParseState, type ClaudeSessionParseState -} from './session-scanner-primary-parsers' -import { asRecord, extractString, parseJsonObject } from './session-scanner-values' +} from '../claude/session-scanner-primary-parsers' +import { asRecord } from '../../session-scanner-record-value' +import { extractString, parseJsonObject } from '../../session-scanner-values' import { remoteSessionContentLines, type RemoteSessionContent -} from './remote-session-content-lines' -import type { FileWithMtime, ResumableSessionParseState } from './session-scanner-types' -import type { TranscriptMessageSink } from './session-transcript-consumers' +} from '../../transcripts/remote-session-content-lines' +import type { FileWithMtime, ResumableSessionParseState } from '../../session-scanner-types' +import type { TranscriptMessageSink } from '../../transcripts/session-transcript-consumers' type ParserOptions = { executionHostId?: ExecutionHostId diff --git a/src/main/ai-vault/session-scanner-qoder.test.ts b/src/main/ai-vault/scanners/qoder/session-scanner-qoder.test.ts similarity index 93% rename from src/main/ai-vault/session-scanner-qoder.test.ts rename to src/main/ai-vault/scanners/qoder/session-scanner-qoder.test.ts index 356a05e01dd..99369511fb1 100644 --- a/src/main/ai-vault/session-scanner-qoder.test.ts +++ b/src/main/ai-vault/scanners/qoder/session-scanner-qoder.test.ts @@ -5,8 +5,8 @@ import { createQoderSessionResumeState, parseQoderSessionContent } from './session-scanner-qoder-parser' -import { resetSessionParseCacheForTests } from './session-scanner-parse-cache' -import type { TranscriptMessage } from './session-transcript-consumers' +import { resetSessionParseCacheForTests } from '../../parse-cache/session-parse-cache-store' +import type { TranscriptMessage } from '../../transcripts/session-transcript-consumers' const roots: string[] = [] afterEach(async () => { diff --git a/src/main/ai-vault/session-scanner-graph-parsers.test.ts b/src/main/ai-vault/scanners/session-scanner-graph-parsers.test.ts similarity index 90% rename from src/main/ai-vault/session-scanner-graph-parsers.test.ts rename to src/main/ai-vault/scanners/session-scanner-graph-parsers.test.ts index 3e7b1e45cbc..0e74f1482cc 100644 --- a/src/main/ai-vault/session-scanner-graph-parsers.test.ts +++ b/src/main/ai-vault/scanners/session-scanner-graph-parsers.test.ts @@ -1,7 +1,7 @@ import { describe, expect, it } from 'vitest' -import { createAccumulator } from './session-scanner-accumulator' +import { createAccumulator } from '../session-scanner-accumulator' import { consumeRovoHistoryEntry } from './session-scanner-graph-parsers' -import type { TranscriptMessage } from './session-transcript-consumers' +import type { TranscriptMessage } from '../transcripts/session-transcript-consumers' function rovoAccumulator(messages?: TranscriptMessage[]) { return createAccumulator({ diff --git a/src/main/ai-vault/session-scanner-graph-parsers.ts b/src/main/ai-vault/scanners/session-scanner-graph-parsers.ts similarity index 89% rename from src/main/ai-vault/session-scanner-graph-parsers.ts rename to src/main/ai-vault/scanners/session-scanner-graph-parsers.ts index ace723bf0bf..1eeeb276178 100644 --- a/src/main/ai-vault/session-scanner-graph-parsers.ts +++ b/src/main/ai-vault/scanners/session-scanner-graph-parsers.ts @@ -1,22 +1,25 @@ -import { foldOmpTranscriptTitle, type OmpTranscriptTitle } from './session-scanner-omp-title' -import { isOmpWrittenRecord } from './session-scanner-omp-written-record' +import { foldOmpTranscriptTitle, type OmpTranscriptTitle } from './omp/session-scanner-omp-title' +import { isOmpWrittenRecord } from './omp/session-scanner-omp-written-record' import { remoteSessionContentLines, type RemoteSessionContent -} from './remote-session-content-lines' -import { openTranscriptReadStream, wslGatedReadFile } from '../native-chat/wsl-transcript-fs-access' +} from '../transcripts/remote-session-content-lines' +import { + openTranscriptReadStream, + wslGatedReadFile +} from '../../native-chat/wsl-transcript-fs-access' import { basename, dirname } from 'node:path' import { createInterface } from 'node:readline' -import type { AiVaultSession } from '../../shared/ai-vault-types' -import { rovoTranscriptPathForMetadata } from '../../shared/ai-vault-session-log-resource' -import type { ExecutionHostId } from '../../shared/execution-host' -import { withOmpSubagentTranscriptCount } from './session-scanner-omp-subagent-transcripts' +import type { AiVaultSession } from '../../../shared/ai-vault-types' +import { rovoTranscriptPathForMetadata } from '../../../shared/ai-vault-session-log-resource' +import type { ExecutionHostId } from '../../../shared/execution-host' +import { withOmpSubagentTranscriptCount } from './omp/session-scanner-omp-subagent-transcripts' import type { FileWithMtime, ResumableSessionParseState, SessionAccumulator -} from './session-scanner-types' -import type { TranscriptMessageSink } from './session-transcript-consumers' +} from '../session-scanner-types' +import type { TranscriptMessageSink } from '../transcripts/session-transcript-consumers' import { accumulatorSessionIdentity, cloneSessionAccumulator, @@ -24,19 +27,18 @@ import { finalizeSession, sessionIdFromFileName, updateTimeline -} from './session-scanner-accumulator' -import { addSessionContent } from './session-scanner-messages' +} from '../session-scanner-accumulator' +import { addSessionContent } from '../session-scanner-messages' import { arrayValue, - asRecord, - extractContentText, - extractMessageText, extractString, firstString, parseJsonObject, - readJsonObjectIfExists, - tokenTotal -} from './session-scanner-values' + readJsonObjectIfExists +} from '../session-scanner-values' +import { asRecord } from '../session-scanner-record-value' +import { extractContentText, extractMessageText } from '../session-scanner-text-normalization' +import { tokenTotal } from '../session-scanner-token-values' type ParserSessionOptions = { executionHostId?: ExecutionHostId diff --git a/src/main/ai-vault/session-scanner-sqlite-scope-rows.ts b/src/main/ai-vault/scanners/session-scanner-sqlite-scope-rows.ts similarity index 87% rename from src/main/ai-vault/session-scanner-sqlite-scope-rows.ts rename to src/main/ai-vault/scanners/session-scanner-sqlite-scope-rows.ts index a8ff93f2750..3052328876f 100644 --- a/src/main/ai-vault/session-scanner-sqlite-scope-rows.ts +++ b/src/main/ai-vault/scanners/session-scanner-sqlite-scope-rows.ts @@ -1,4 +1,4 @@ -import { createAiVaultScopeCwdMatcher } from '../../shared/ai-vault-scope-cwd-match' +import { createAiVaultScopeCwdMatcher } from '../../../shared/ai-vault-scope-cwd-match' /** Foreign databases need canonical descendant matching before output admission. */ export function scopedSessionRows( diff --git a/src/main/ai-vault/session-scanner-zcode-order.ts b/src/main/ai-vault/scanners/zcode/session-scanner-zcode-order.ts similarity index 83% rename from src/main/ai-vault/session-scanner-zcode-order.ts rename to src/main/ai-vault/scanners/zcode/session-scanner-zcode-order.ts index 958f73ff7ca..978a268ea7a 100644 --- a/src/main/ai-vault/session-scanner-zcode-order.ts +++ b/src/main/ai-vault/scanners/zcode/session-scanner-zcode-order.ts @@ -1,5 +1,5 @@ -import { columnExists } from '../opencode-usage/schema-helpers' -import type SyncDatabase from '../sqlite/sync-database' +import { columnExists } from '../../../opencode-usage/schema-helpers' +import type SyncDatabase from '../../../sqlite/sync-database' export function zcodeTranscriptOrder( db: SyncDatabase, diff --git a/src/main/ai-vault/session-scanner-zcode-sources.test.ts b/src/main/ai-vault/scanners/zcode/session-scanner-zcode-sources.test.ts similarity index 82% rename from src/main/ai-vault/session-scanner-zcode-sources.test.ts rename to src/main/ai-vault/scanners/zcode/session-scanner-zcode-sources.test.ts index 4ed6667342f..230e97353ef 100644 --- a/src/main/ai-vault/session-scanner-zcode-sources.test.ts +++ b/src/main/ai-vault/scanners/zcode/session-scanner-zcode-sources.test.ts @@ -1,9 +1,9 @@ import { afterEach, expect, it, vi } from 'vitest' -import type { AiVaultScanIssue } from '../../shared/ai-vault-types' -import { wslGatedAccess } from '../native-chat/wsl-transcript-fs-access' +import type { AiVaultScanIssue } from '../../../../shared/ai-vault-types' +import { wslGatedAccess } from '../../../native-chat/wsl-transcript-fs-access' import { zcodeDiscoveries } from './session-scanner-zcode-sources' -vi.mock('../native-chat/wsl-transcript-fs-access', () => ({ wslGatedAccess: vi.fn() })) +vi.mock('../../../native-chat/wsl-transcript-fs-access', () => ({ wslGatedAccess: vi.fn() })) const access = vi.mocked(wslGatedAccess) diff --git a/src/main/ai-vault/session-scanner-zcode-sources.ts b/src/main/ai-vault/scanners/zcode/session-scanner-zcode-sources.ts similarity index 77% rename from src/main/ai-vault/session-scanner-zcode-sources.ts rename to src/main/ai-vault/scanners/zcode/session-scanner-zcode-sources.ts index 96434dbb800..4500d6f532e 100644 --- a/src/main/ai-vault/session-scanner-zcode-sources.ts +++ b/src/main/ai-vault/scanners/zcode/session-scanner-zcode-sources.ts @@ -1,12 +1,12 @@ import { homedir } from 'node:os' import { join } from 'node:path' -import type { AiVaultScanIssue } from '../../shared/ai-vault-types' -import { throwIfSignalAborted } from '../../shared/abort-signal-reason' -import { wslGatedAccess } from '../native-chat/wsl-transcript-fs-access' -import { listZcodeSqliteSessionsViaWorker } from './session-scanner-opencode-sqlite-worker-spawn' -import { scanIssueTextFromError } from './session-scan-issues' -import type { AiVaultScanOptions, SessionFileDiscovery } from './session-scanner-types' -import { scopeWalksAgentFiles } from './session-scope-cwd' +import type { AiVaultScanIssue } from '../../../../shared/ai-vault-types' +import { throwIfSignalAborted } from '../../../../shared/abort-signal-reason' +import { wslGatedAccess } from '../../../native-chat/wsl-transcript-fs-access' +import { listZcodeSqliteSessionsViaWorker } from '../opencode/reader-transport/session-scanner-opencode-sqlite-worker-spawn' +import { scanIssueTextFromError } from '../../session-scan-issues' +import type { AiVaultScanOptions, SessionFileDiscovery } from '../../session-scanner-types' +import { scopeWalksAgentFiles } from '../../session-scope-cwd' // Keep ZCode discovery separate so OpenCode cannot absorb its database rows. export function zcodeDiscoveries( diff --git a/src/main/ai-vault/session-scanner-zcode-visibility.ts b/src/main/ai-vault/scanners/zcode/session-scanner-zcode-visibility.ts similarity index 100% rename from src/main/ai-vault/session-scanner-zcode-visibility.ts rename to src/main/ai-vault/scanners/zcode/session-scanner-zcode-visibility.ts diff --git a/src/main/ai-vault/session-scanner-zcode.test.ts b/src/main/ai-vault/scanners/zcode/session-scanner-zcode.test.ts similarity index 96% rename from src/main/ai-vault/session-scanner-zcode.test.ts rename to src/main/ai-vault/scanners/zcode/session-scanner-zcode.test.ts index f9e3705870c..ae831a480e0 100644 --- a/src/main/ai-vault/session-scanner-zcode.test.ts +++ b/src/main/ai-vault/scanners/zcode/session-scanner-zcode.test.ts @@ -2,10 +2,10 @@ import { mkdtempSync, rmSync } from 'node:fs' import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, describe, expect, it } from 'vitest' -import { handleOpenCodeSqliteRequest } from './session-scanner-opencode-sqlite-dispatch' -import { splitOpenCodeSqliteCandidate } from './session-scanner-opencode-sqlite-paths' -import { writeOpenCodeSqliteDatabase } from './session-scanner-opencode-sqlite-fixture' -import SyncDatabase from '../sqlite/sync-database' +import { handleOpenCodeSqliteRequest } from '../opencode/reader-transport/session-scanner-opencode-sqlite-dispatch' +import { splitOpenCodeSqliteCandidate } from '../../../../shared/opencode-sqlite-session-path' +import { writeOpenCodeSqliteDatabase } from '../opencode/sqlite/session-scanner-opencode-sqlite-fixture' +import SyncDatabase from '../../../sqlite/sync-database' function readCandidates(value: unknown): { agent: string; path: string }[] { if (typeof value !== 'object' || value === null || !('candidates' in value)) { diff --git a/src/main/ai-vault/session-cwd-bucket-layouts.ts b/src/main/ai-vault/session-cwd-bucket-layouts.ts index 6c621122b99..ad0a7d45e20 100644 --- a/src/main/ai-vault/session-cwd-bucket-layouts.ts +++ b/src/main/ai-vault/session-cwd-bucket-layouts.ts @@ -1,5 +1,8 @@ import type { AiVaultAgent } from '../../shared/ai-vault-types' -import { encodeClaudeProjectPaths, isClaudeProjectDirInScope } from './claude-project-dir-encoding' +import { + encodeClaudeProjectPaths, + isClaudeProjectDirInScope +} from './scanners/claude/claude-project-dir-encoding' export type CwdBucketLayout = { agent: Extract diff --git a/src/main/ai-vault/session-delete-target.ts b/src/main/ai-vault/session-delete-target.ts index e1aa970cb3e..13cf55ca256 100644 --- a/src/main/ai-vault/session-delete-target.ts +++ b/src/main/ai-vault/session-delete-target.ts @@ -19,7 +19,7 @@ import { isDiscoverableSessionFile, sessionRowRootDirs } from './session-scanner-agent-sources' -import { subagentTranscriptsDirFor } from './session-scanner-subagent-transcripts' +import { subagentTranscriptsDirFor } from './scanners/claude/session-scanner-subagent-transcripts' import type { AiVaultScanOptions } from './session-scanner-types' // These sessions own their containing directory, including companion files. diff --git a/src/main/ai-vault/session-first-user-prompt-handler.ts b/src/main/ai-vault/session-first-user-prompt-handler.ts index d20a3508202..9f8d6b78311 100644 --- a/src/main/ai-vault/session-first-user-prompt-handler.ts +++ b/src/main/ai-vault/session-first-user-prompt-handler.ts @@ -2,7 +2,7 @@ import type { AiVaultFirstUserPromptArgs, AiVaultFirstUserPromptResult } from '../../shared/ai-vault-types' -import { readAiVaultFirstUserPromptInBackground } from './session-scanner-background' +import { readAiVaultFirstUserPromptInBackground } from './scan-service/session-scanner-background' export function handleAiVaultGetFirstUserPrompt( args?: AiVaultFirstUserPromptArgs diff --git a/src/main/ai-vault/session-first-user-prompt-opencode.test.ts b/src/main/ai-vault/session-first-user-prompt-opencode.test.ts index c164f261516..4c1db95ce95 100644 --- a/src/main/ai-vault/session-first-user-prompt-opencode.test.ts +++ b/src/main/ai-vault/session-first-user-prompt-opencode.test.ts @@ -2,10 +2,13 @@ import { beforeEach, expect, it, vi } from 'vitest' import { readAiVaultFirstUserPrompt } from './session-first-user-prompt-read' const reader = vi.hoisted(() => ({ v1: vi.fn(), v2: vi.fn() })) -vi.mock('./session-scanner-opencode-sqlite-worker-spawn', () => ({ - parseOpenCodeSqliteSessionViaWorker: reader.v1, - parseOpenCode2SqliteSessionViaWorker: reader.v2 -})) +vi.mock( + './scanners/opencode/reader-transport/session-scanner-opencode-sqlite-worker-spawn', + () => ({ + parseOpenCodeSqliteSessionViaWorker: reader.v1, + parseOpenCode2SqliteSessionViaWorker: reader.v2 + }) +) beforeEach(() => { reader.v1.mockReset().mockResolvedValue({ firstUserPrompt: 'full first prompt' }) diff --git a/src/main/ai-vault/session-first-user-prompt-read.ts b/src/main/ai-vault/session-first-user-prompt-read.ts index 07c91e7da51..7371c401314 100644 --- a/src/main/ai-vault/session-first-user-prompt-read.ts +++ b/src/main/ai-vault/session-first-user-prompt-read.ts @@ -11,11 +11,11 @@ import { parseOpenCodeSqliteSessionViaWorker, parseOpenCode2SqliteSessionViaWorker, parseZcodeSqliteSessionViaWorker -} from './session-scanner-opencode-sqlite-worker-spawn' -import { splitOpenCodeSqliteCandidate } from './session-scanner-opencode-sqlite-paths' +} from './scanners/opencode/reader-transport/session-scanner-opencode-sqlite-worker-spawn' +import { splitOpenCodeSqliteCandidate } from '../../shared/opencode-sqlite-session-path' import type { FileWithMtime } from './session-scanner-types' -import type { OpenCodeWslRuntime } from './session-scanner-opencode-wsl-runtime' -import { configureOpenCodeWslReaders } from './session-scanner-opencode-wsl-client' +import type { OpenCodeWslRuntime } from './scanners/opencode/reader-transport/session-scanner-opencode-wsl-runtime' +import { configureOpenCodeWslReaders } from './scanners/opencode/reader-transport/session-scanner-opencode-wsl-client' export type ReadAiVaultFirstUserPromptArgs = { agent: AiVaultAgent diff --git a/src/main/ai-vault/session-root-dedup.ts b/src/main/ai-vault/session-root-dedup.ts index 063fb242324..c44192aabd7 100644 --- a/src/main/ai-vault/session-root-dedup.ts +++ b/src/main/ai-vault/session-root-dedup.ts @@ -1,6 +1,9 @@ import { antigravitySessionOrigin } from '../../shared/antigravity-session-origin' import type { AiVaultSession } from '../../shared/ai-vault-types' -import { codexSessionAliasKey, codexSessionAliasBeats } from './codex-session-root-dedup' +import { + codexSessionAliasKey, + codexSessionAliasBeats +} from './scanners/codex/codex-session-root-dedup' import { sessionSortTime } from './session-scanner-accumulator' function sessionAliasKey(session: AiVaultSession): string | null { diff --git a/src/main/ai-vault/session-scanner-accumulator.ts b/src/main/ai-vault/session-scanner-accumulator.ts index 8d0a32d4f19..7500ec505ed 100644 --- a/src/main/ai-vault/session-scanner-accumulator.ts +++ b/src/main/ai-vault/session-scanner-accumulator.ts @@ -16,7 +16,7 @@ import { NO_TRANSCRIPT_MESSAGES, type TranscriptMessageSink, type TranscriptSessionIdentity -} from './session-transcript-consumers' +} from './transcripts/session-transcript-consumers' export function createAccumulator(args: { agent: AiVaultAgent diff --git a/src/main/ai-vault/session-scanner-agent-parser.ts b/src/main/ai-vault/session-scanner-agent-parser.ts index 94e03bd542e..c06a07c1981 100644 --- a/src/main/ai-vault/session-scanner-agent-parser.ts +++ b/src/main/ai-vault/session-scanner-agent-parser.ts @@ -1,18 +1,21 @@ -import { parseQoderSessionFile } from './session-scanner-qoder-parser' -import { parseCodebuddySessionFile } from './session-scanner-codebuddy-parser' +import { parseQoderSessionFile } from './scanners/qoder/session-scanner-qoder-parser' +import { parseCodebuddySessionFile } from './scanners/codebuddy/session-scanner-codebuddy-parser' import type { AiVaultSession } from '../../shared/ai-vault-types' import { throwIfSignalAborted } from '../../shared/abort-signal-reason' -import { parseDevinSessionFile } from './session-scanner-devin-parser' -import { parseAntigravitySessionFile } from './session-scanner-antigravity-parser' -import { parseDroidSessionFile } from './session-scanner-droid-parser' -import { parseClineSessionFile } from './session-scanner-cline-parser' -import { parseGrokSessionFile } from './session-scanner-grok-parser' -import { parseMessageGraphSessionFile, parseRovoSessionFile } from './session-scanner-graph-parsers' -import { parseKimiSessionFile } from './session-scanner-kimi-parser' -import { parseMuseSessionFile } from './session-scanner-muse-parser' -import { splitOpenCodeSqliteCandidate } from './session-scanner-opencode-sqlite-paths' -import { parseJcodeSessionFile } from './session-scanner-jcode-parser' -import { parseKiroSessionFile } from './session-scanner-kiro-parser' +import { parseDevinSessionFile } from './scanners/devin/session-scanner-devin-parser' +import { parseAntigravitySessionFile } from './scanners/antigravity/session-scanner-antigravity-parser' +import { parseDroidSessionFile } from './scanners/droid/session-scanner-droid-parser' +import { parseClineSessionFile } from './scanners/cline/session-scanner-cline-parser' +import { parseGrokSessionFile } from './scanners/grok/session-scanner-grok-parser' +import { + parseMessageGraphSessionFile, + parseRovoSessionFile +} from './scanners/session-scanner-graph-parsers' +import { parseKimiSessionFile } from './scanners/kimi/session-scanner-kimi-parser' +import { parseMuseSessionFile } from './scanners/muse/session-scanner-muse-parser' +import { splitOpenCodeSqliteCandidate } from '../../shared/opencode-sqlite-session-path' +import { parseJcodeSessionFile } from './scanners/jcode/session-scanner-jcode-parser' +import { parseKiroSessionFile } from './scanners/kiro/session-scanner-kiro-parser' import { captureOpenCodeSqliteSessionViaWorker, captureOpenCode2SqliteSessionViaWorker, @@ -20,17 +23,17 @@ import { parseOpenCode2SqliteSessionViaWorker, parseOpenCodeSqliteSessionViaWorker, parseZcodeSqliteSessionViaWorker -} from './session-scanner-opencode-sqlite-worker-spawn' -import { parseClaudeSessionFile } from './session-scanner-primary-parsers' -import { parseGeminiSessionFile } from './session-scanner-gemini-parsers' -import { parseCodexSessionFile } from './session-scanner-codex-parser' -import { parseCopilotSessionFile } from './session-scanner-copilot-parser' -import { parseCursorSessionFile } from './session-scanner-cursor-parser' -import { parseHermesSessionFile } from './session-scanner-hermes-parser' -import { parseOpenCodeSessionFile } from './session-scanner-opencode-parser' +} from './scanners/opencode/reader-transport/session-scanner-opencode-sqlite-worker-spawn' +import { parseClaudeSessionFile } from './scanners/claude/session-scanner-primary-parsers' +import { parseGeminiSessionFile } from './scanners/gemini/session-scanner-gemini-parsers' +import { parseCodexSessionFile } from './scanners/codex/session-scanner-codex-parser' +import { parseCopilotSessionFile } from './scanners/copilot/session-scanner-copilot-parser' +import { parseCursorSessionFile } from './scanners/cursor/session-scanner-cursor-parser' +import { parseHermesSessionFile } from './scanners/hermes/session-scanner-hermes-parser' +import { parseOpenCodeSessionFile } from './scanners/opencode/session-scanner-opencode-parser' import type { SessionFileCandidate } from './session-scanner-types' -import type { TranscriptMessageSink } from './session-transcript-consumers' -import type { SkippedTranscriptRecord } from './session-transcript-record-budget' +import type { TranscriptMessageSink } from './transcripts/session-transcript-consumers' +import type { SkippedTranscriptRecord } from './transcripts/session-transcript-record-budget' /** Listing needs only a preview; active message sinks require the full transcript. */ async function readOpenCodeSqliteCandidate( diff --git a/src/main/ai-vault/session-scanner-agent-sources.ts b/src/main/ai-vault/session-scanner-agent-sources.ts index 5ef959af616..411a95761df 100644 --- a/src/main/ai-vault/session-scanner-agent-sources.ts +++ b/src/main/ai-vault/session-scanner-agent-sources.ts @@ -6,21 +6,20 @@ import type { AiVaultAgent } from '../../shared/ai-vault-types' import type { AiVaultDeletableAgent } from '../../shared/ai-vault-session-deletion' import { resolveGrokSessionsDir } from '../../shared/grok-session-paths' import { resolveKiroHomeDir } from '../../shared/kiro-home' -import { uniqueCodexSessionsDirs } from './session-scanner-codex-paths' +import { uniqueCodexSessionsDirs } from './scanners/codex/session-scanner-codex-paths' import { clineMessagesPathForMetadata, - isClineSessionMetadataPath -} from './session-scanner-cline-parser' -import { cursorChatMetaPath } from './session-scanner-cursor-chat-meta' -import { devinSessionsDbDependencyPath } from './session-scanner-devin-db' -import { resolveKimiSessionsDir } from './session-scanner-kimi-paths' -import { resolveMuseSessionsDir } from './session-scanner-muse-paths' -import { - isKiroSessionMetadataPath, kiroTranscriptPathForMetadata -} from './session-scanner-kiro-parser' -import { OPENCLAW_AGENT_SOURCE } from './openclaw-session-layout' -import { isOmpConversationDirectory } from './session-scanner-omp-subagent-transcripts' +} from '../../shared/ai-vault-session-log-resource' +import { isClineSessionMetadataPath } from './scanners/cline/session-scanner-cline-parser' +import { cursorChatMetaPath } from './scanners/cursor/session-scanner-cursor-chat-meta' +import { devinSessionsDbDependencyPath } from './scanners/devin/session-scanner-devin-db' +import { resolveKimiSessionsDir } from './scanners/kimi/session-scanner-kimi-paths' +import { resolveMuseSessionsDir } from '../../shared/muse-session-log' +import { isKiroSessionMetadataPath } from './scanners/kiro/session-scanner-kiro-parser' + +import { OPENCLAW_AGENT_SOURCE } from './scanners/openclaw/openclaw-session-layout' +import { isOmpConversationDirectory } from './scanners/omp/session-scanner-omp-subagent-transcripts' import { claudeProjectsRootDirs, codexHomeSessionsDir, @@ -29,7 +28,7 @@ import { wslHomeSessionDirs } from './session-scanner-roots' import { getHermesHome } from '../hermes/hermes-default-home' -import { SUBAGENT_DIR_NAME } from './session-scanner-subagent-transcripts' +import { SUBAGENT_DIR_NAME } from './scanners/claude/session-scanner-subagent-transcripts' import type { AiVaultScanOptions } from './session-scanner-types' import { normalizeAgentSessionsDir, primeAgentSessionsDirFromEnv } from './session-scanner-values' diff --git a/src/main/ai-vault/session-scanner-candidate-parse.ts b/src/main/ai-vault/session-scanner-candidate-parse.ts index ddd4f7f8668..263ebafdaaf 100644 --- a/src/main/ai-vault/session-scanner-candidate-parse.ts +++ b/src/main/ai-vault/session-scanner-candidate-parse.ts @@ -1,6 +1,6 @@ import { yieldToEventLoop } from '../../shared/event-loop-yield' import { isConversationNameRequestSession } from './conversation-name-request-sessions' -import { candidateFileTime } from './antigravity-transcript-candidates' +import { candidateFileTime } from './scanners/antigravity/antigravity-transcript-candidates' import { aiVaultAgentLabel, isAiVaultSessionResumableContent, @@ -11,18 +11,18 @@ import { import { aiVaultScanIssueText } from '../../shared/ai-vault-scan-issue-copy' import type { ExecutionHostId } from '../../shared/execution-host' import { ScannedSessionCollection } from './session-root-dedup' -import type { AntigravityWorkspaceResolver } from './session-scanner-antigravity-history' +import type { AntigravityWorkspaceResolver } from './scanners/antigravity/session-scanner-antigravity-history' import { parseAgentSessionFileCached, parseListedSessionFile, type SessionParseStats -} from './session-scanner-parse-cache' +} from './parse-cache/session-scanner-parse-cache' import { recordSessionScanIssue, scanIssueTextFromError } from './session-scan-issues' import { getSessionParseCacheEntry, noteSessionParseCacheListed, sessionParseCacheKey -} from './session-parse-cache-store' +} from './parse-cache/session-parse-cache-store' import { canStopParsingSessions } from './session-scan-cutoff' import type { SessionFileCandidate, SessionParseResult } from './session-scanner-types' import { throwIfAiVaultScanCancelled } from './ai-vault-scan-cancellation' diff --git a/src/main/ai-vault/session-scanner-candidates.ts b/src/main/ai-vault/session-scanner-candidates.ts index 1bd23526406..7bfe0a144d6 100644 --- a/src/main/ai-vault/session-scanner-candidates.ts +++ b/src/main/ai-vault/session-scanner-candidates.ts @@ -1,12 +1,12 @@ -import { prioritizeAntigravityTranscriptCandidates } from './antigravity-transcript-candidates' +import { prioritizeAntigravityTranscriptCandidates } from './scanners/antigravity/antigravity-transcript-candidates' import { readCodexRolloutSessionMetaId } from '../codex/codex-rollout-session-meta' import { codexRolloutHardlinkIdentity, dedupeCodexRolloutAliases, dedupeCodexRolloutFileAliases -} from './codex-session-root-dedup' -import { antigravityHistoryPathForBrainDir } from './session-scanner-antigravity-paths' -import { codexHomeForSessionsDir } from './session-scanner-codex-paths' +} from './scanners/codex/codex-session-root-dedup' +import { antigravityHistoryPathForBrainDir } from './scanners/antigravity/session-scanner-antigravity-paths' +import { codexHomeForSessionsDir } from './scanners/codex/session-scanner-codex-paths' import { DEFAULT_CODEX_HOME_DIR } from './session-scanner-source-discovery' import type { AiVaultScanOptions, diff --git a/src/main/ai-vault/session-scanner-core-parser-wsl-stall.test.ts b/src/main/ai-vault/session-scanner-core-parser-wsl-stall.test.ts index a20abf5004f..f20598d81eb 100644 --- a/src/main/ai-vault/session-scanner-core-parser-wsl-stall.test.ts +++ b/src/main/ai-vault/session-scanner-core-parser-wsl-stall.test.ts @@ -24,10 +24,8 @@ vi.mock('node:path', async (importOriginal) => { return { ...actual.win32, default: actual.win32 } }) -import { - parseAgentSessionFileCached, - resetSessionParseCacheForTests -} from './session-scanner-parse-cache' +import { parseAgentSessionFileCached } from './parse-cache/session-scanner-parse-cache' +import { resetSessionParseCacheForTests } from './parse-cache/session-parse-cache-store' import { resetWslTranscriptFsGateForTests, WSL_TRANSCRIPT_FS_ROUTE_QUARANTINE_BASE_MS, diff --git a/src/main/ai-vault/session-scanner-cutoff.test.ts b/src/main/ai-vault/session-scanner-cutoff.test.ts index e133fb8db60..48ea38cb669 100644 --- a/src/main/ai-vault/session-scanner-cutoff.test.ts +++ b/src/main/ai-vault/session-scanner-cutoff.test.ts @@ -5,11 +5,11 @@ import { afterEach, describe, expect, it, vi } from 'vitest' import { scanAiVaultSessions } from './session-scanner' import { isolatedScanRoots, jsonLines } from './session-scanner-test-fixtures' import { parseSessionCandidates } from './session-scanner-candidate-parse' -import { createSessionParseStats } from './session-scanner-parse-cache' +import { createSessionParseStats } from './parse-cache/session-scanner-parse-cache' import { resetSessionParseCacheForTests, storeSessionParseCacheEntry -} from './session-parse-cache-store' +} from './parse-cache/session-parse-cache-store' import { createAccumulator, finalizeSession, sessionSortTime } from './session-scanner-accumulator' import * as cutoff from './session-scan-cutoff' diff --git a/src/main/ai-vault/session-scanner-discovery.ts b/src/main/ai-vault/session-scanner-discovery.ts index d462e6ab52d..ecb97d10edb 100644 --- a/src/main/ai-vault/session-scanner-discovery.ts +++ b/src/main/ai-vault/session-scanner-discovery.ts @@ -4,7 +4,7 @@ import { mapWithConcurrency } from '../../shared/map-with-concurrency' import { PrioritySemaphore } from '../../shared/priority-semaphore' import { isWslUncPath } from '../../shared/wsl-paths' import { SessionNewestFiles } from './session-newest-files' -import type { SessionSidecarObservation } from './session-sidecar-stat' +import type { SessionSidecarObservation } from './parse-cache/session-sidecar-stat' import type { AiVaultAgent, AiVaultScanIssue } from '../../shared/ai-vault-types' import { wslGatedReaddir, wslGatedStat } from '../native-chat/wsl-transcript-fs-access' import { WslTranscriptFsError } from '../native-chat/wsl-transcript-fs-gate' diff --git a/src/main/ai-vault/session-scanner-every-agent-fixture.ts b/src/main/ai-vault/session-scanner-every-agent-fixture.ts index 4c3f68a4d6e..666b7291d39 100644 --- a/src/main/ai-vault/session-scanner-every-agent-fixture.ts +++ b/src/main/ai-vault/session-scanner-every-agent-fixture.ts @@ -4,10 +4,10 @@ import { writeMuseScannerFixture, writeOpenCode2SqliteFixture } from './session-scanner-test-fixtures' -import { writeKiroSessionFixture } from './session-scanner-kiro-fixtures' +import { writeKiroSessionFixture } from './scanners/kiro/session-scanner-kiro-fixtures' import { writeDocumentAgentFixtures } from './session-scanner-document-agent-fixtures' import { writeLogAgentFixtures } from './session-scanner-log-agent-fixtures' -import { writeOpenCodeSqliteDatabase } from './session-scanner-opencode-sqlite-fixture' +import { writeOpenCodeSqliteDatabase } from './scanners/opencode/sqlite/session-scanner-opencode-sqlite-fixture' export type EveryAgentVault = { roots: ReturnType diff --git a/src/main/ai-vault/session-scanner-first-user-prompt.ts b/src/main/ai-vault/session-scanner-first-user-prompt.ts index 752ce3c7c62..7d709bfd7df 100644 --- a/src/main/ai-vault/session-scanner-first-user-prompt.ts +++ b/src/main/ai-vault/session-scanner-first-user-prompt.ts @@ -1,6 +1,6 @@ import { isKnownHarnessInjectedUserTurnText } from '../../shared/harness-injected-user-turns' import { getFirstUserPromptCaptureMode } from './session-scanner-first-user-prompt-capture' -import { stripGrokUserQueryEnvelope } from './session-scanner-grok-user-text' +import { stripGrokUserQueryEnvelope } from './scanners/grok/session-scanner-grok-user-text' // Import directly to avoid a cycle through the session-scanner-values re-export. import { sliceAtCodeUnitLimit } from './session-scanner-text-normalization' diff --git a/src/main/ai-vault/session-scanner-incremental-fixtures.ts b/src/main/ai-vault/session-scanner-incremental-fixtures.ts index eeebcd2159d..c51ab18f909 100644 --- a/src/main/ai-vault/session-scanner-incremental-fixtures.ts +++ b/src/main/ai-vault/session-scanner-incremental-fixtures.ts @@ -1,7 +1,7 @@ import type { AiVaultAgent } from '../../shared/ai-vault-types' -import { antigravityFixture } from './session-scanner-antigravity-fixtures' -import { codexFixture } from './session-scanner-codex-fixtures' +import { antigravityFixture } from './scanners/antigravity/session-scanner-antigravity-fixtures' +import { codexFixture } from './scanners/codex/session-scanner-codex-fixtures' import { primeAgentFixture } from './session-scanner-prime-agent-fixtures' export type IncrementalAgentFixture = { diff --git a/src/main/ai-vault/session-scanner-index-cache-wsl-stall.test.ts b/src/main/ai-vault/session-scanner-index-cache-wsl-stall.test.ts index c5e4430947d..2194723b1be 100644 --- a/src/main/ai-vault/session-scanner-index-cache-wsl-stall.test.ts +++ b/src/main/ai-vault/session-scanner-index-cache-wsl-stall.test.ts @@ -19,12 +19,12 @@ import { readCodexSessionIndexTitle, resetCodexSessionIndexTitleCacheForTests, _hasCodexSessionIndexTitleCacheEntryForTest -} from './session-scanner-codex-title-index' +} from './scanners/codex/session-scanner-codex-title-index' import { clearKimiSessionIndexCache, hasKimiSessionIndexCacheEntryForTests, readKimiWorkDirBySessionId -} from './session-scanner-kimi-paths' +} from './scanners/kimi/session-scanner-kimi-paths' import { readJsonObjectIfExists } from './session-scanner-values' import { resetWslTranscriptFsGateForTests, diff --git a/src/main/ai-vault/session-scanner-json-document-memory.test.ts b/src/main/ai-vault/session-scanner-json-document-memory.test.ts index 18e9098f266..5b18d93aeb8 100644 --- a/src/main/ai-vault/session-scanner-json-document-memory.test.ts +++ b/src/main/ai-vault/session-scanner-json-document-memory.test.ts @@ -2,10 +2,10 @@ import { mkdtemp, open, rm, writeFile } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join } from 'node:path' import { expect, it } from 'vitest' -import { parseHermesSessionFile } from './session-scanner-hermes-parser' -import { parseDevinSessionFile } from './session-scanner-devin-parser' -import { parseGeminiSessionFile } from './session-scanner-gemini-parsers' -import { parseClineSessionFile } from './session-scanner-cline-parser' +import { parseHermesSessionFile } from './scanners/hermes/session-scanner-hermes-parser' +import { parseDevinSessionFile } from './scanners/devin/session-scanner-devin-parser' +import { parseGeminiSessionFile } from './scanners/gemini/session-scanner-gemini-parsers' +import { parseClineSessionFile } from './scanners/cline/session-scanner-cline-parser' const providers = [ { agent: 'hermes', parse: parseHermesSessionFile, array: 'messages' }, diff --git a/src/main/ai-vault/session-scanner-jsonl-reader.test.ts b/src/main/ai-vault/session-scanner-jsonl-reader.test.ts index 4c3d5b47a30..ebca4c8527c 100644 --- a/src/main/ai-vault/session-scanner-jsonl-reader.test.ts +++ b/src/main/ai-vault/session-scanner-jsonl-reader.test.ts @@ -1,7 +1,7 @@ import { afterEach, expect, it, vi } from 'vitest' import { isAiVaultScanCancelledError } from '../../shared/ai-vault-types' import { consumeCompleteJsonlLines } from './session-scanner-jsonl-reader' -import { MAX_SESSION_TRANSCRIPT_RECORD_BYTES } from './session-transcript-record-budget' +import { MAX_SESSION_TRANSCRIPT_RECORD_BYTES } from './transcripts/session-transcript-record-budget' type ChunkSource = { chunks: Buffer[] diff --git a/src/main/ai-vault/session-scanner-jsonl-reader.ts b/src/main/ai-vault/session-scanner-jsonl-reader.ts index 7331aacadfc..d11ecd89cd3 100644 --- a/src/main/ai-vault/session-scanner-jsonl-reader.ts +++ b/src/main/ai-vault/session-scanner-jsonl-reader.ts @@ -4,7 +4,7 @@ import { throwIfAiVaultScanCancelled } from './ai-vault-scan-cancellation' import { MAX_SESSION_TRANSCRIPT_RECORD_BYTES, type SkippedTranscriptRecord -} from './session-transcript-record-budget' +} from './transcripts/session-transcript-record-budget' const NEWLINE_BYTE = 0x0a const CARRIAGE_RETURN_BYTE = 0x0d diff --git a/src/main/ai-vault/session-scanner-messages.test.ts b/src/main/ai-vault/session-scanner-messages.test.ts index cb176c90079..49e256f0e89 100644 --- a/src/main/ai-vault/session-scanner-messages.test.ts +++ b/src/main/ai-vault/session-scanner-messages.test.ts @@ -1,13 +1,13 @@ import { expect, it, vi } from 'vitest' import { createAccumulator } from './session-scanner-accumulator' -import { decodeSessionMessage } from './session-decoded-message' +import { decodeSessionMessage } from './transcripts/session-decoded-message' import { withFullFirstUserPromptCapture } from './session-scanner-first-user-prompt-capture' import { addDecodedSessionMessage, addPreviewMessage, addSessionContent } from './session-scanner-messages' -import type { TranscriptMessage } from './session-transcript-consumers' +import type { TranscriptMessage } from './transcripts/session-transcript-consumers' const AT = '2026-05-01T00:00:00.000Z' diff --git a/src/main/ai-vault/session-scanner-messages.ts b/src/main/ai-vault/session-scanner-messages.ts index 019b9a1c4f7..e6a99313fe0 100644 --- a/src/main/ai-vault/session-scanner-messages.ts +++ b/src/main/ai-vault/session-scanner-messages.ts @@ -10,8 +10,11 @@ import { sliceAtCodeUnitLimit } from './session-scanner-text-normalization' import type { SessionAccumulator } from './session-scanner-types' -import { transcriptMessagesFromDecodedMessage } from './session-transcript-message-content' -import { decodeSessionMessage, type DecodedSessionMessage } from './session-decoded-message' +import { transcriptMessagesFromDecodedMessage } from './transcripts/session-transcript-message-content' +import { + decodeSessionMessage, + type DecodedSessionMessage +} from './transcripts/session-decoded-message' const SESSION_PREVIEW_MESSAGE_LIMIT = 5 diff --git a/src/main/ai-vault/session-scanner-opencode-sqlite-paths.ts b/src/main/ai-vault/session-scanner-opencode-sqlite-paths.ts deleted file mode 100644 index cc9d93781df..00000000000 --- a/src/main/ai-vault/session-scanner-opencode-sqlite-paths.ts +++ /dev/null @@ -1,5 +0,0 @@ -export { - buildOpenCodeSqliteCandidatePath, - splitOpenCodeSqliteCandidate, - looksLikeOpenCodeSqliteCandidate -} from '../../shared/opencode-sqlite-session-path' diff --git a/src/main/ai-vault/session-scanner-parse-wsl-stall.test.ts b/src/main/ai-vault/session-scanner-parse-wsl-stall.test.ts index 5d5b53117cc..599bb033e96 100644 --- a/src/main/ai-vault/session-scanner-parse-wsl-stall.test.ts +++ b/src/main/ai-vault/session-scanner-parse-wsl-stall.test.ts @@ -14,10 +14,8 @@ vi.mock('node:fs/promises', async (importOriginal) => ({ readdir: mocks.readdir })) -import { - parseAgentSessionFileCached, - resetSessionParseCacheForTests -} from './session-scanner-parse-cache' +import { parseAgentSessionFileCached } from './parse-cache/session-scanner-parse-cache' +import { resetSessionParseCacheForTests } from './parse-cache/session-parse-cache-store' import { resetWslTranscriptFsGateForTests, WSL_TRANSCRIPT_FS_ROUTE_QUARANTINE_BASE_MS, diff --git a/src/main/ai-vault/session-scanner-parser-stream-cleanup.test.ts b/src/main/ai-vault/session-scanner-parser-stream-cleanup.test.ts index 7571f4c6cc4..218c7d530d3 100644 --- a/src/main/ai-vault/session-scanner-parser-stream-cleanup.test.ts +++ b/src/main/ai-vault/session-scanner-parser-stream-cleanup.test.ts @@ -24,12 +24,12 @@ vi.mock('node:readline', async (importOriginal) => ({ createInterface: mocks.createInterface })) -import { parseAntigravitySessionFile } from './session-scanner-antigravity-parser' -import { parseDroidSessionFile } from './session-scanner-droid-parser' -import { parseMessageGraphSessionFile } from './session-scanner-graph-parsers' -import { parseGrokSessionFile } from './session-scanner-grok-parser' -import { parseKimiSessionFile } from './session-scanner-kimi-parser' -import { clearKimiSessionIndexCache } from './session-scanner-kimi-paths' +import { parseAntigravitySessionFile } from './scanners/antigravity/session-scanner-antigravity-parser' +import { parseDroidSessionFile } from './scanners/droid/session-scanner-droid-parser' +import { parseMessageGraphSessionFile } from './scanners/session-scanner-graph-parsers' +import { parseGrokSessionFile } from './scanners/grok/session-scanner-grok-parser' +import { parseKimiSessionFile } from './scanners/kimi/session-scanner-kimi-parser' +import { clearKimiSessionIndexCache } from './scanners/kimi/session-scanner-kimi-paths' const PARSE_FAILURE = 'parser failed mid-transcript' diff --git a/src/main/ai-vault/session-scanner-record-budget.test.ts b/src/main/ai-vault/session-scanner-record-budget.test.ts index 4ef452e2327..43e2036e015 100644 --- a/src/main/ai-vault/session-scanner-record-budget.test.ts +++ b/src/main/ai-vault/session-scanner-record-budget.test.ts @@ -4,21 +4,27 @@ import { join } from 'node:path' import { afterEach, expect, it } from 'vitest' import { createSessionParseStats, - parseAgentSessionFileCached, - resetSessionParseCacheForTests -} from './session-scanner-parse-cache' -import { getSessionParseCacheEntry } from './session-parse-cache-store' + parseAgentSessionFileCached +} from './parse-cache/session-scanner-parse-cache' +import { + resetSessionParseCacheForTests, + getSessionParseCacheEntry +} from './parse-cache/session-parse-cache-store' + import { aiVaultScanIssueText } from '../../shared/ai-vault-scan-issue-copy' -import { codexFixture, codexWorkerFixtureLines } from './session-scanner-codex-fixtures' +import { + codexFixture, + codexWorkerFixtureLines +} from './scanners/codex/session-scanner-codex-fixtures' import { scanAiVaultSessions } from './session-scanner' import { isolatedScanRoots, writeJsonlFile } from './session-scanner-test-fixtures' -import { MAX_SESSION_TRANSCRIPT_RECORD_BYTES } from './session-transcript-record-budget' +import { MAX_SESSION_TRANSCRIPT_RECORD_BYTES } from './transcripts/session-transcript-record-budget' import { flushSessionParseCachePersist, initSessionParseCachePersistence, resetSessionParseCachePersistenceForTests -} from './session-parse-cache-persistence' -import { kiroTranscriptPathForMetadata } from './session-scanner-kiro-parser' +} from './parse-cache/session-parse-cache-persistence' +import { kiroTranscriptPathForMetadata } from '../../shared/ai-vault-session-log-resource' import type { SessionFileCandidate } from './session-scanner-types' const SESSION_FILE = 'aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee.jsonl' diff --git a/src/main/ai-vault/session-scanner-recoverable-empty.test.ts b/src/main/ai-vault/session-scanner-recoverable-empty.test.ts index b0de0134f23..074e60fd52f 100644 --- a/src/main/ai-vault/session-scanner-recoverable-empty.test.ts +++ b/src/main/ai-vault/session-scanner-recoverable-empty.test.ts @@ -4,8 +4,8 @@ import { join } from 'node:path' import { afterEach, describe, expect, it } from 'vitest' import { isAiVaultSessionRecoverableEmpty } from '../../shared/ai-vault-types' import { scanAiVaultSessions } from './session-scanner' -import { parseClaudeSessionContent } from './session-scanner-primary-parsers' -import { countSubagentTranscripts } from './session-scanner-subagent-transcripts' +import { parseClaudeSessionContent } from './scanners/claude/session-scanner-primary-parsers' +import { countSubagentTranscripts } from './scanners/claude/session-scanner-subagent-transcripts' import { isolatedScanRoots, writeJsonlFile } from './session-scanner-test-fixtures' let tempRoots: string[] = [] diff --git a/src/main/ai-vault/session-scanner-roots.ts b/src/main/ai-vault/session-scanner-roots.ts index ba2414568b6..d69230d1609 100644 --- a/src/main/ai-vault/session-scanner-roots.ts +++ b/src/main/ai-vault/session-scanner-roots.ts @@ -3,7 +3,7 @@ import { homedir } from 'node:os' import { join } from 'node:path' import { resolveAbsoluteDirOverride } from '../../shared/absolute-dir-override' import { WSL_CODEX_RUNTIME_HOME_SEGMENTS } from '../pty/shell-startup/codex-home-wsl-env' -import { resolveOmpSessionsDir } from './omp-session-root' +import { resolveOmpSessionsDir } from './scanners/omp/omp-session-root' /** Where each transcript agent's session tree sits under a home dir (host or WSL guest). */ export const AGENT_SESSION_HOME_SEGMENTS = { diff --git a/src/main/ai-vault/session-scanner-scope-cwd-facts.test.ts b/src/main/ai-vault/session-scanner-scope-cwd-facts.test.ts index 8c16acc90d1..0558b6deabd 100644 --- a/src/main/ai-vault/session-scanner-scope-cwd-facts.test.ts +++ b/src/main/ai-vault/session-scanner-scope-cwd-facts.test.ts @@ -8,12 +8,12 @@ import { flushSessionParseCachePersist, initSessionParseCachePersistence, resetSessionParseCachePersistenceForTests -} from './session-parse-cache-persistence' -import { resetSessionParseCacheForTests } from './session-parse-cache-store' +} from './parse-cache/session-parse-cache-persistence' +import { resetSessionParseCacheForTests } from './parse-cache/session-parse-cache-store' import { scanAiVaultSessions } from './session-scanner' import SyncDatabase from '../sqlite/sync-database' -import { SessionParseCacheDatabase } from './session-parse-cache-database' -import { parseAgentSessionFileCached } from './session-scanner-parse-cache' +import { SessionParseCacheDatabase } from './parse-cache/session-parse-cache-database' +import { parseAgentSessionFileCached } from './parse-cache/session-scanner-parse-cache' import { isolatedScanRoots, jsonLines } from './session-scanner-test-fixtures' const reads = vi.hoisted((): string[] => []) diff --git a/src/main/ai-vault/session-scanner-scope-walk.test.ts b/src/main/ai-vault/session-scanner-scope-walk.test.ts index bb6d52aa071..3da98ca3b63 100644 --- a/src/main/ai-vault/session-scanner-scope-walk.test.ts +++ b/src/main/ai-vault/session-scanner-scope-walk.test.ts @@ -14,20 +14,23 @@ import { storeSessionParseCacheEntry, storeSessionScopeCwd, resetSessionParseCacheForTests -} from './session-parse-cache-store' -import { createSessionParseStats, parseAgentSessionFileCached } from './session-scanner-parse-cache' +} from './parse-cache/session-parse-cache-store' +import { + createSessionParseStats, + parseAgentSessionFileCached +} from './parse-cache/session-scanner-parse-cache' import { scanAiVaultSessions } from './session-scanner' -import { createAntigravityWorkspaceResolver } from './session-scanner-antigravity-history' +import { createAntigravityWorkspaceResolver } from './scanners/antigravity/session-scanner-antigravity-history' import { scanInScopeSessions } from './session-scanner-scope-walk' import * as eventLoop from '../../shared/event-loop-yield' import { AI_VAULT_SCOPE_CWD_SOURCES } from './session-scope-cwd' -import { SessionParseCacheDatabase } from './session-parse-cache-database' +import { SessionParseCacheDatabase } from './parse-cache/session-parse-cache-database' import SyncDatabase from '../sqlite/sync-database' import { initSessionParseCachePersistence, flushSessionParseCachePersist, resetSessionParseCachePersistenceForTests -} from './session-parse-cache-persistence' +} from './parse-cache/session-parse-cache-persistence' import { isolatedScanRoots, jsonLines, diff --git a/src/main/ai-vault/session-scanner-scope-walk.ts b/src/main/ai-vault/session-scanner-scope-walk.ts index 9ce9bb1c567..f62e1807c1d 100644 --- a/src/main/ai-vault/session-scanner-scope-walk.ts +++ b/src/main/ai-vault/session-scanner-scope-walk.ts @@ -11,12 +11,12 @@ import { resolveSessionScopeCwd, storeSessionScopeCwd, type SessionScopeCwdStamp -} from './session-parse-cache-store' -import type { AntigravityWorkspaceResolver } from './session-scanner-antigravity-history' +} from './parse-cache/session-parse-cache-store' +import type { AntigravityWorkspaceResolver } from './scanners/antigravity/session-scanner-antigravity-history' import { parseSessionCandidates } from './session-scanner-candidate-parse' import { sessionSortTime } from './session-scanner-accumulator' import { discoveryFileCandidates, dropCodexHardlinkAliases } from './session-scanner-candidates' -import type { SessionParseStats } from './session-scanner-parse-cache' +import type { SessionParseStats } from './parse-cache/session-scanner-parse-cache' import { inventoryCwdBucketFiles, selectCwdBucketFiles, @@ -31,8 +31,8 @@ import type { SessionFileDiscovery } from './session-scanner-types' import { AI_VAULT_SCOPE_CWD_SOURCES, scopeWalksAgentFiles } from './session-scope-cwd' -import { sidecarUnchanged } from './session-sidecar-stat' -import { prioritizeAntigravityTranscriptCandidates } from './antigravity-transcript-candidates' +import { sidecarUnchanged } from './parse-cache/session-sidecar-stat' +import { prioritizeAntigravityTranscriptCandidates } from './scanners/antigravity/antigravity-transcript-candidates' type ScopeScanArgs = { inventory: CwdBucketInventory[] diff --git a/src/main/ai-vault/session-scanner-source-discovery.ts b/src/main/ai-vault/session-scanner-source-discovery.ts index 0f2599f9910..b713f8c331b 100644 --- a/src/main/ai-vault/session-scanner-source-discovery.ts +++ b/src/main/ai-vault/session-scanner-source-discovery.ts @@ -1,12 +1,12 @@ import { delimiter } from 'node:path' import type { AiVaultAgent, AiVaultScanIssue } from '../../shared/ai-vault-types' import { discoverFiles } from './session-scanner-discovery' -import { opencodeDiscoveries } from './session-scanner-opencode-sources' -import { zcodeDiscoveries } from './session-scanner-zcode-sources' -import { antigravityDiscoveries } from './session-scanner-antigravity-sources' +import { opencodeDiscoveries } from './scanners/opencode/session-scanner-opencode-sources' +import { zcodeDiscoveries } from './scanners/zcode/session-scanner-zcode-sources' +import { antigravityDiscoveries } from './scanners/antigravity/session-scanner-antigravity-sources' import { AI_VAULT_AGENT_SOURCES, type AiVaultAgentSource } from './session-scanner-agent-sources' import { normalizedWslHomeDirs } from './session-scanner-roots' -import { configureOpenCodeWslReaders } from './session-scanner-opencode-wsl-client' +import { configureOpenCodeWslReaders } from './scanners/opencode/reader-transport/session-scanner-opencode-wsl-client' import { scopeWalksAgentFiles } from './session-scope-cwd' import type { AiVaultScanOptions, SessionFileDiscovery } from './session-scanner-types' diff --git a/src/main/ai-vault/session-scanner-types.ts b/src/main/ai-vault/session-scanner-types.ts index 7162037c42b..df28d4bf509 100644 --- a/src/main/ai-vault/session-scanner-types.ts +++ b/src/main/ai-vault/session-scanner-types.ts @@ -8,9 +8,9 @@ import type { ExecutionHostId } from '../../shared/execution-host' import type { TranscriptMessageSink, TranscriptSessionIdentity -} from './session-transcript-consumers' -import type { SessionSidecarObservation } from './session-sidecar-stat' -import type { OpenCodeWslRuntime } from './session-scanner-opencode-wsl-runtime' +} from './transcripts/session-transcript-consumers' +import type { SessionSidecarObservation } from './parse-cache/session-sidecar-stat' +import type { OpenCodeWslRuntime } from './scanners/opencode/reader-transport/session-scanner-opencode-wsl-runtime' export type AiVaultScanOptions = { claudeProjectsDir?: string diff --git a/src/main/ai-vault/session-scanner-unlimited-dedup.test.ts b/src/main/ai-vault/session-scanner-unlimited-dedup.test.ts index bf9a1d55746..5c0bf81f247 100644 --- a/src/main/ai-vault/session-scanner-unlimited-dedup.test.ts +++ b/src/main/ai-vault/session-scanner-unlimited-dedup.test.ts @@ -13,7 +13,7 @@ vi.mock('./session-scanner-source-discovery', () => ({ vi.mock('./session-scanner-candidates', () => ({ sessionCandidatesFromDiscoveries: async () => candidates() })) -vi.mock('./session-scanner-parse-cache', () => ({ +vi.mock('./parse-cache/session-scanner-parse-cache', () => ({ createSessionParseStats: () => ({ reused: 0, incremental: 0, diff --git a/src/main/ai-vault/session-scanner-wsl-stop-gaps.test.ts b/src/main/ai-vault/session-scanner-wsl-stop-gaps.test.ts index 63c70b598df..7ac5235a95b 100644 --- a/src/main/ai-vault/session-scanner-wsl-stop-gaps.test.ts +++ b/src/main/ai-vault/session-scanner-wsl-stop-gaps.test.ts @@ -1,6 +1,6 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import type { ProcessResult } from '@orca/process-host/process-spec' -import type { OpenCodeSqliteProcessOptions } from './session-scanner-opencode-sqlite-process-client' +import type { OpenCodeSqliteProcessOptions } from './scanners/opencode/reader-transport/session-scanner-opencode-sqlite-process-client' const mocks = vi.hoisted(() => ({ runProcess: vi.fn<(spec: { args?: string[] }) => Promise>(), @@ -10,13 +10,19 @@ const mocks = vi.hoisted(() => ({ })) vi.mock('@orca/process-host', () => ({ runProcess: mocks.runProcess })) -vi.mock('./session-scanner-opencode-sqlite-process-client', () => ({ - createOpenCodeSqliteProcessClient: mocks.create -})) -vi.mock('./session-scanner-opencode-sqlite-open', async (importOriginal) => ({ - ...(await importOriginal()), - readOpenCodeDatabase: mocks.readDb -})) +vi.mock( + './scanners/opencode/reader-transport/session-scanner-opencode-sqlite-process-client', + () => ({ + createOpenCodeSqliteProcessClient: mocks.create + }) +) +vi.mock( + './scanners/opencode/sqlite/session-scanner-opencode-sqlite-open', + async (importOriginal) => ({ + ...(await importOriginal()), + readOpenCodeDatabase: mocks.readDb + }) +) vi.mock('../wsl/execution/wsl-executable-path', () => ({ resolveWslExecutablePath: () => 'wsl.exe' })) @@ -30,11 +36,11 @@ import { WSL_TRANSCRIPT_RUNNING_LEASE_MS } from '../native-chat/wsl-transcript-r import { configureOpenCodeWslReaders, openCodeWslClient -} from './session-scanner-opencode-wsl-client' +} from './scanners/opencode/reader-transport/session-scanner-opencode-wsl-client' import { devinSessionsIndexForSidecar, resetDevinSessionsIndexCacheForTests -} from './session-scanner-devin-db' +} from './scanners/devin/session-scanner-devin-db' import { listRunningWslHomeDirsUnlessStopped } from '../wsl/discovery/wsl-home-unless-stopped' import { clearWslHomeCache, rememberWslHome } from '../wsl/discovery/wsl-home-cache' import { _resetRunningWslDistroCacheForTests } from '../wsl/discovery/wsl-running-distro-cache' diff --git a/src/main/ai-vault/session-scanner.test.ts b/src/main/ai-vault/session-scanner.test.ts index bc0f2aa0b7c..d54549b2a30 100644 --- a/src/main/ai-vault/session-scanner.test.ts +++ b/src/main/ai-vault/session-scanner.test.ts @@ -5,36 +5,39 @@ import { afterEach, describe, expect, it, vi } from 'vitest' import { AI_VAULT_AGENTS } from '../../shared/ai-vault-types' import { scanAiVaultSessions } from './session-scanner' import { isolatedScanRoots, jsonLines } from './session-scanner-test-fixtures' -import { KIRO_FIXTURE_SESSION_ID } from './session-scanner-kiro-fixtures' +import { KIRO_FIXTURE_SESSION_ID } from './scanners/kiro/session-scanner-kiro-fixtures' import { writeEveryAgentVault } from './session-scanner-every-agent-fixture' // Use synchronous SQLite implementations because worker bundles are absent in the test runtime. -vi.mock('./session-scanner-opencode-sqlite-worker-spawn', async () => { - const v1List = await import('./session-scanner-opencode-sqlite-list') - const v1Parse = await import('./session-scanner-opencode-sqlite') - const v2List = await import('./session-scanner-opencode2-sqlite-list') - const v2Parse = await import('./session-scanner-opencode2-sqlite') - return { - listOpenCodeSqliteSessionsViaWorker: ( - args: Parameters[0] - ) => v1List.listOpenCodeSqliteSessions(args), - listZcodeSqliteSessionsViaWorker: ( - args: Parameters[0] - ) => v1List.listOpenCodeSqliteSessions({ ...args, agent: 'zcode' }), - parseOpenCodeSqliteSessionViaWorker: ( - args: Parameters[0] - ) => v1Parse.parseOpenCodeSqliteSession(args), - parseZcodeSqliteSessionViaWorker: ( - args: Parameters[0] - ) => v1Parse.parseOpenCodeSqliteSession({ ...args, agent: 'zcode' }), - listOpenCode2SqliteSessionsViaWorker: ( - args: Parameters[0] - ) => v2List.listOpenCode2SqliteSessions(args), - parseOpenCode2SqliteSessionViaWorker: ( - args: Parameters[0] - ) => v2Parse.parseOpenCode2SqliteSession(args) +vi.mock( + './scanners/opencode/reader-transport/session-scanner-opencode-sqlite-worker-spawn', + async () => { + const v1List = await import('./scanners/opencode/sqlite/session-scanner-opencode-sqlite-list') + const v1Parse = await import('./scanners/opencode/sqlite/session-scanner-opencode-sqlite') + const v2List = await import('./scanners/opencode2/session-scanner-opencode2-sqlite-list') + const v2Parse = await import('./scanners/opencode2/session-scanner-opencode2-sqlite') + return { + listOpenCodeSqliteSessionsViaWorker: ( + args: Parameters[0] + ) => v1List.listOpenCodeSqliteSessions(args), + listZcodeSqliteSessionsViaWorker: ( + args: Parameters[0] + ) => v1List.listOpenCodeSqliteSessions({ ...args, agent: 'zcode' }), + parseOpenCodeSqliteSessionViaWorker: ( + args: Parameters[0] + ) => v1Parse.parseOpenCodeSqliteSession(args), + parseZcodeSqliteSessionViaWorker: ( + args: Parameters[0] + ) => v1Parse.parseOpenCodeSqliteSession({ ...args, agent: 'zcode' }), + listOpenCode2SqliteSessionsViaWorker: ( + args: Parameters[0] + ) => v2List.listOpenCode2SqliteSessions(args), + parseOpenCode2SqliteSessionViaWorker: ( + args: Parameters[0] + ) => v2Parse.parseOpenCode2SqliteSession(args) + } } -}) +) let tempRoots: string[] = [] diff --git a/src/main/ai-vault/session-scanner.ts b/src/main/ai-vault/session-scanner.ts index da443f86f0c..bd8c9f894d0 100644 --- a/src/main/ai-vault/session-scanner.ts +++ b/src/main/ai-vault/session-scanner.ts @@ -10,22 +10,25 @@ import { dedupeScannedSessions } from './session-root-dedup' import { createAntigravityWorkspaceResolver, readLocalAntigravityHistory -} from './session-scanner-antigravity-history' +} from './scanners/antigravity/session-scanner-antigravity-history' import { sessionCandidatesFromDiscoveries } from './session-scanner-candidates' import { parseSessionCandidates } from './session-scanner-candidate-parse' -import { createSessionParseStats } from './session-scanner-parse-cache' +import { createSessionParseStats } from './parse-cache/session-scanner-parse-cache' import { recordSessionScanIssue } from './session-scan-issues' import { aiVaultScanWorkload, noteAiVaultScanReading } from './ai-vault-scan-progress' import { yieldScanInventory } from './session-scanner-scope-inventory' import { prepareScopeScan, scanInScopeSessions } from './session-scanner-scope-walk' import { discoverAiVaultSessionSources } from './session-scanner-source-discovery' -import { cursorChatMetaRefusals, withCursorChatMetaScan } from './session-scanner-cursor-chat-meta' +import { + cursorChatMetaRefusals, + withCursorChatMetaScan +} from './scanners/cursor/session-scanner-cursor-chat-meta' import type { AiVaultScanOptions } from './session-scanner-types' import { clampPositiveInteger } from './session-scanner-values' import { throwIfAiVaultScanCancelled } from './ai-vault-scan-cancellation' import { DEFAULT_AI_VAULT_SCAN_LIMIT } from '../../shared/ai-vault-session-depth' -import { withDevinSessionsDbScan } from './session-scanner-devin-db' -import { withOpenCodeSqliteScanScope } from './session-scanner-opencode-sqlite-scan-scope' +import { withDevinSessionsDbScan } from './scanners/devin/session-scanner-devin-db' +import { withOpenCodeSqliteScanScope } from './scanners/opencode/sqlite/session-scanner-opencode-sqlite-scan-scope' const SESSION_PARSE_CANDIDATE_MULTIPLIER = 2 diff --git a/src/main/ai-vault/session-scope-cwd.ts b/src/main/ai-vault/session-scope-cwd.ts index 77c81aa3482..f8b917f7780 100644 --- a/src/main/ai-vault/session-scope-cwd.ts +++ b/src/main/ai-vault/session-scope-cwd.ts @@ -9,12 +9,15 @@ import { import type { FileWithMtime, SessionFileCandidate } from './session-scanner-types' import { asRecord } from './session-scanner-record-value' import { extractString, parseJsonObject } from './session-scanner-values' -import { clineManifestCwd } from './session-scanner-cline-parser' -import { cursorChatMetaUnavailable, readCursorChatMeta } from './session-scanner-cursor-chat-meta' -import { rovoSessionCwd } from './session-scanner-graph-parsers' -import { grokSessionCwd } from './session-scanner-grok-parser' -import { listedKiroMetadata } from './session-scanner-kiro-parser' -import { openCodeSessionCwd } from './session-scanner-opencode-parser' +import { clineManifestCwd } from './scanners/cline/session-scanner-cline-parser' +import { + cursorChatMetaUnavailable, + readCursorChatMeta +} from './scanners/cursor/session-scanner-cursor-chat-meta' +import { rovoSessionCwd } from './scanners/session-scanner-graph-parsers' +import { grokSessionCwd } from './scanners/grok/session-scanner-grok-parser' +import { listedKiroMetadata } from './scanners/kiro/session-scanner-kiro-parser' +import { openCodeSessionCwd } from './scanners/opencode/session-scanner-opencode-parser' type HeadRecord = Record diff --git a/src/main/ai-vault/session-subagent-reader.ts b/src/main/ai-vault/session-subagent-reader.ts index 5921419c54a..7316622b6e7 100644 --- a/src/main/ai-vault/session-subagent-reader.ts +++ b/src/main/ai-vault/session-subagent-reader.ts @@ -1,7 +1,7 @@ import type { AiVaultSubagentListResult } from '../../shared/ai-vault-types' -import { listClaudeSubagentSessions } from './session-scanner-claude-subagents' -import { listOmpSubagentSessions } from './session-scanner-omp-subagent-listing' -import type { AiVaultServiceSubagentRequest } from './session-scanner-service-protocol' +import { listClaudeSubagentSessions } from './scanners/claude/session-scanner-claude-subagents' +import { listOmpSubagentSessions } from './scanners/omp/session-scanner-omp-subagent-listing' +import type { AiVaultServiceSubagentRequest } from './scan-service/session-scanner-service-protocol' export function listLocalAiVaultSubagentSessions( request: AiVaultServiceSubagentRequest diff --git a/src/main/ai-vault/session-title-file-reader-wsl-stall.test.ts b/src/main/ai-vault/session-titles/session-title-file-reader-wsl-stall.test.ts similarity index 95% rename from src/main/ai-vault/session-title-file-reader-wsl-stall.test.ts rename to src/main/ai-vault/session-titles/session-title-file-reader-wsl-stall.test.ts index a613d96afae..fe8ffeffa3d 100644 --- a/src/main/ai-vault/session-title-file-reader-wsl-stall.test.ts +++ b/src/main/ai-vault/session-titles/session-title-file-reader-wsl-stall.test.ts @@ -22,11 +22,11 @@ import { mkdtemp, rm, writeFile } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join } from 'node:path' import { readAiVaultSessionTitlesFromFiles } from './session-title-file-reader' -import { resetSessionParseCacheForTests } from './session-scanner-parse-cache' +import { resetSessionParseCacheForTests } from '../parse-cache/session-parse-cache-store' import { resetWslTranscriptFsGateForTests, WSL_TRANSCRIPT_FS_SCAN_TIMEOUT_MS -} from '../native-chat/wsl-transcript-fs-gate' +} from '../../native-chat/wsl-transcript-fs-gate' let releaseStall: (() => void) | undefined let tempRoot: string | undefined diff --git a/src/main/ai-vault/session-title-file-reader.test.ts b/src/main/ai-vault/session-titles/session-title-file-reader.test.ts similarity index 97% rename from src/main/ai-vault/session-title-file-reader.test.ts rename to src/main/ai-vault/session-titles/session-title-file-reader.test.ts index 0ef123e839e..b6d0389f7bb 100644 --- a/src/main/ai-vault/session-title-file-reader.test.ts +++ b/src/main/ai-vault/session-titles/session-title-file-reader.test.ts @@ -5,7 +5,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' const parseAgentSessionFileCached = vi.hoisted(() => vi.fn()) -vi.mock('./session-scanner-parse-cache', () => ({ parseAgentSessionFileCached })) +vi.mock('../parse-cache/session-scanner-parse-cache', () => ({ parseAgentSessionFileCached })) const { readAiVaultSessionTitlesFromFiles } = await import('./session-title-file-reader') const { resolveHostReadableAiVaultTitleRequests } = await import('./session-title-request-paths') diff --git a/src/main/ai-vault/session-title-file-reader.ts b/src/main/ai-vault/session-titles/session-title-file-reader.ts similarity index 92% rename from src/main/ai-vault/session-title-file-reader.ts rename to src/main/ai-vault/session-titles/session-title-file-reader.ts index a5313bfc245..df22c3dfd57 100644 --- a/src/main/ai-vault/session-title-file-reader.ts +++ b/src/main/ai-vault/session-titles/session-title-file-reader.ts @@ -1,11 +1,11 @@ -import { wslGatedLstat } from '../native-chat/wsl-transcript-fs-access' +import { wslGatedLstat } from '../../native-chat/wsl-transcript-fs-access' import { AI_VAULT_SESSION_TITLE_REQUEST_MAX_COUNT, type AiVaultSessionTitle, type AiVaultSessionTitleRequest, type AiVaultSessionTitlesResult -} from '../../shared/ai-vault-session-title' -import { parseAgentSessionFileCached } from './session-scanner-parse-cache' +} from '../../../shared/ai-vault-session-title' +import { parseAgentSessionFileCached } from '../parse-cache/session-scanner-parse-cache' const TITLE_PARSE_CONCURRENCY = 4 diff --git a/src/main/ai-vault/session-title-request-paths.ts b/src/main/ai-vault/session-titles/session-title-request-paths.ts similarity index 76% rename from src/main/ai-vault/session-title-request-paths.ts rename to src/main/ai-vault/session-titles/session-title-request-paths.ts index 37c7aac7285..b4e7728920f 100644 --- a/src/main/ai-vault/session-title-request-paths.ts +++ b/src/main/ai-vault/session-titles/session-title-request-paths.ts @@ -1,6 +1,6 @@ -import type { AiVaultSessionTitleRequest } from '../../shared/ai-vault-session-title' -import { toHostReadableTranscriptPath } from '../native-chat/host-readable-transcript-path' -import { wslTranscriptFsRefusal } from '../native-chat/wsl-transcript-fs-gate' +import type { AiVaultSessionTitleRequest } from '../../../shared/ai-vault-session-title' +import { toHostReadableTranscriptPath } from '../../native-chat/host-readable-transcript-path' +import { wslTranscriptFsRefusal } from '../../native-chat/wsl-transcript-fs-error' export function resolveHostReadableAiVaultTitleRequests( requests: AiVaultSessionTitleRequest[], diff --git a/src/main/ai-vault/session-title-resolver.ts b/src/main/ai-vault/session-titles/session-title-resolver.ts similarity index 85% rename from src/main/ai-vault/session-title-resolver.ts rename to src/main/ai-vault/session-titles/session-title-resolver.ts index 661462b2706..9816d463ae7 100644 --- a/src/main/ai-vault/session-title-resolver.ts +++ b/src/main/ai-vault/session-titles/session-title-resolver.ts @@ -1,11 +1,11 @@ import { extname } from 'node:path' -import { hasUnsafeProviderSessionIdChars } from '../../shared/agent-session/lifecycle/agent-session-resume' +import { hasUnsafeProviderSessionIdChars } from '../../../shared/agent-session/lifecycle/agent-session-resume' import { AI_VAULT_SESSION_TITLE_REQUEST_MAX_COUNT, type AiVaultSessionTitleRequest, type AiVaultSessionTitlesResult -} from '../../shared/ai-vault-session-title' -import { resolveAiVaultSessionTitlesInBackground } from './session-scanner-background' +} from '../../../shared/ai-vault-session-title' +import { resolveAiVaultSessionTitlesInBackground } from '../scan-service/session-scanner-background' const TRANSCRIPT_PATH_MAX_LENGTH = 32_768 diff --git a/src/main/ai-vault/session-title-result-validation.ts b/src/main/ai-vault/session-titles/session-title-result-validation.ts similarity index 96% rename from src/main/ai-vault/session-title-result-validation.ts rename to src/main/ai-vault/session-titles/session-title-result-validation.ts index 79768b12b6d..44353b3e468 100644 --- a/src/main/ai-vault/session-title-result-validation.ts +++ b/src/main/ai-vault/session-titles/session-title-result-validation.ts @@ -2,7 +2,7 @@ import { AI_VAULT_SESSION_TITLE_REQUEST_MAX_COUNT, type AiVaultSessionTitle, type AiVaultSessionTitlesResult -} from '../../shared/ai-vault-session-title' +} from '../../../shared/ai-vault-session-title' export function parseAiVaultSessionTitlesResult(value: unknown): AiVaultSessionTitlesResult { if (!value || typeof value !== 'object') { diff --git a/src/main/ai-vault/local-log-tail-reader.test.ts b/src/main/ai-vault/transcripts/local-log-tail-reader.test.ts similarity index 96% rename from src/main/ai-vault/local-log-tail-reader.test.ts rename to src/main/ai-vault/transcripts/local-log-tail-reader.test.ts index cc0c1889e40..64d34c8edd1 100644 --- a/src/main/ai-vault/local-log-tail-reader.test.ts +++ b/src/main/ai-vault/transcripts/local-log-tail-reader.test.ts @@ -2,7 +2,7 @@ import { mkdtemp, rename, rm, truncate, writeFile } from 'node:fs/promises' import { join } from 'node:path' import { tmpdir } from 'node:os' import { afterEach, describe, expect, it } from 'vitest' -import { LOCAL_LOG_TAIL_CHUNK_BYTES } from '../../shared/local-log-tail-types' +import { LOCAL_LOG_TAIL_CHUNK_BYTES } from '../../../shared/local-log-tail-types' import { readLocalLogTailRange } from './local-log-tail-reader' const tempPaths: string[] = [] diff --git a/src/main/ai-vault/local-log-tail-reader.ts b/src/main/ai-vault/transcripts/local-log-tail-reader.ts similarity index 94% rename from src/main/ai-vault/local-log-tail-reader.ts rename to src/main/ai-vault/transcripts/local-log-tail-reader.ts index 87e4b2e065f..86b1eb2636b 100644 --- a/src/main/ai-vault/local-log-tail-reader.ts +++ b/src/main/ai-vault/transcripts/local-log-tail-reader.ts @@ -1,9 +1,9 @@ import { open } from 'node:fs/promises' -import { LOCAL_READ_OPEN_FLAGS } from '../ipc/filesystem/local-regular-file-read' +import { LOCAL_READ_OPEN_FLAGS } from '../../ipc/filesystem/local-regular-file-read' import { LOCAL_LOG_TAIL_CHUNK_BYTES, type LocalLogTailReadResult -} from '../../shared/local-log-tail-types' +} from '../../../shared/local-log-tail-types' export function localLogFileIdentity(stats: { dev: number diff --git a/src/main/ai-vault/remote-session-content-lines.test.ts b/src/main/ai-vault/transcripts/remote-session-content-lines.test.ts similarity index 100% rename from src/main/ai-vault/remote-session-content-lines.test.ts rename to src/main/ai-vault/transcripts/remote-session-content-lines.test.ts diff --git a/src/main/ai-vault/remote-session-content-lines.ts b/src/main/ai-vault/transcripts/remote-session-content-lines.ts similarity index 94% rename from src/main/ai-vault/remote-session-content-lines.ts rename to src/main/ai-vault/transcripts/remote-session-content-lines.ts index eb1c3764cac..cb48d9009ab 100644 --- a/src/main/ai-vault/remote-session-content-lines.ts +++ b/src/main/ai-vault/transcripts/remote-session-content-lines.ts @@ -1,6 +1,6 @@ -import { splitTranscriptStreamLines } from '../native-chat/transcript-stream-lines' +import { splitTranscriptStreamLines } from '../../native-chat/transcript-stream-lines' import { setImmediate as yieldToEventLoop } from 'node:timers/promises' -import { throwIfAiVaultScanCancelled } from './ai-vault-scan-cancellation' +import { throwIfAiVaultScanCancelled } from '../ai-vault-scan-cancellation' import { MAX_SESSION_TRANSCRIPT_RECORD_BYTES } from './session-transcript-record-budget' export type RemoteSessionContent = string | AsyncIterable diff --git a/src/main/ai-vault/remote-session-file-stat.ts b/src/main/ai-vault/transcripts/remote-session-file-stat.ts similarity index 88% rename from src/main/ai-vault/remote-session-file-stat.ts rename to src/main/ai-vault/transcripts/remote-session-file-stat.ts index 787d37b4a1f..2f8aeb7a2b6 100644 --- a/src/main/ai-vault/remote-session-file-stat.ts +++ b/src/main/ai-vault/transcripts/remote-session-file-stat.ts @@ -1,4 +1,4 @@ -import { errorMessage } from './session-scanner-values' +import { errorMessage } from '../session-scanner-values' export function isMissingRemoteSessionPathError(error: unknown): boolean { const code = diff --git a/src/main/ai-vault/session-decoded-message.ts b/src/main/ai-vault/transcripts/session-decoded-message.ts similarity index 95% rename from src/main/ai-vault/session-decoded-message.ts rename to src/main/ai-vault/transcripts/session-decoded-message.ts index 9f5343035a6..b15b6e37b27 100644 --- a/src/main/ai-vault/session-decoded-message.ts +++ b/src/main/ai-vault/transcripts/session-decoded-message.ts @@ -1,5 +1,5 @@ -import type { AiVaultSessionPreviewMessage } from '../../shared/ai-vault-types' -import { asRecord } from './session-scanner-record-value' +import type { AiVaultSessionPreviewMessage } from '../../../shared/ai-vault-types' +import { asRecord } from '../session-scanner-record-value' export type DecodedToolCall = { kind: 'tool_call' diff --git a/src/main/ai-vault/session-document-consumer-replacement.test.ts b/src/main/ai-vault/transcripts/session-document-consumer-replacement.test.ts similarity index 95% rename from src/main/ai-vault/session-document-consumer-replacement.test.ts rename to src/main/ai-vault/transcripts/session-document-consumer-replacement.test.ts index fe3d8837c69..6639e798191 100644 --- a/src/main/ai-vault/session-document-consumer-replacement.test.ts +++ b/src/main/ai-vault/transcripts/session-document-consumer-replacement.test.ts @@ -4,8 +4,8 @@ import { join } from 'node:path' import { expect, it } from 'vitest' import { readWholeTranscript } from './session-transcript-reader' import { registerTranscriptConsumer } from './session-transcript-consumers' -import { SessionSearchIndexWriter } from '../ai-vault-search/session-search-index-writer' -import { openSessionSearchIndexFile } from '../ai-vault-search/session-search-index-test-fixture' +import { SessionSearchIndexWriter } from '../../ai-vault-search/session-search-index-writer' +import { openSessionSearchIndexFile } from '../../ai-vault-search/session-search-index-test-fixture' it.each(['hermes', 'gemini', 'devin', 'cline'] as const)( 'indexes only the final %s message array, preserving JSON last-field semantics', diff --git a/src/main/ai-vault/session-document-discarded-scalar-memory.test.ts b/src/main/ai-vault/transcripts/session-document-discarded-scalar-memory.test.ts similarity index 100% rename from src/main/ai-vault/session-document-discarded-scalar-memory.test.ts rename to src/main/ai-vault/transcripts/session-document-discarded-scalar-memory.test.ts diff --git a/src/main/ai-vault/session-document-stream-boundaries.test.ts b/src/main/ai-vault/transcripts/session-document-stream-boundaries.test.ts similarity index 97% rename from src/main/ai-vault/session-document-stream-boundaries.test.ts rename to src/main/ai-vault/transcripts/session-document-stream-boundaries.test.ts index f6dfe349000..17798b16118 100644 --- a/src/main/ai-vault/session-document-stream-boundaries.test.ts +++ b/src/main/ai-vault/transcripts/session-document-stream-boundaries.test.ts @@ -2,11 +2,11 @@ import { describe, it, expect } from 'vitest' import { parseHermesSessionContent, parseHermesSessionDocument -} from './session-scanner-hermes-parser' +} from '../scanners/hermes/session-scanner-hermes-parser' import { parseClineSessionContent, parseClineSessionDocuments -} from './session-scanner-cline-parser' +} from '../scanners/cline/session-scanner-cline-parser' import { remoteSessionContentLines, streamedSessionContentLines diff --git a/src/main/ai-vault/session-document-stream-contract.test.ts b/src/main/ai-vault/transcripts/session-document-stream-contract.test.ts similarity index 100% rename from src/main/ai-vault/session-document-stream-contract.test.ts rename to src/main/ai-vault/transcripts/session-document-stream-contract.test.ts diff --git a/src/main/ai-vault/session-document-stream-parity.test.ts b/src/main/ai-vault/transcripts/session-document-stream-parity.test.ts similarity index 92% rename from src/main/ai-vault/session-document-stream-parity.test.ts rename to src/main/ai-vault/transcripts/session-document-stream-parity.test.ts index 441d25d2752..50dee9d63dd 100644 --- a/src/main/ai-vault/session-document-stream-parity.test.ts +++ b/src/main/ai-vault/transcripts/session-document-stream-parity.test.ts @@ -2,16 +2,19 @@ import { describe, it, expect } from 'vitest' import { parseHermesSessionContent, parseHermesSessionDocument -} from './session-scanner-hermes-parser' -import { parseDevinSessionContent, parseDevinSessionDocument } from './session-scanner-devin-parser' +} from '../scanners/hermes/session-scanner-hermes-parser' +import { + parseDevinSessionContent, + parseDevinSessionDocument +} from '../scanners/devin/session-scanner-devin-parser' import { parseGeminiSessionContent, parseGeminiSessionDocument -} from './session-scanner-gemini-parsers' +} from '../scanners/gemini/session-scanner-gemini-parsers' import { parseClineSessionContent, parseClineSessionDocuments -} from './session-scanner-cline-parser' +} from '../scanners/cline/session-scanner-cline-parser' const file = { path: '/sessions/identity/identity.json', diff --git a/src/main/ai-vault/session-document-stream-projection.test.ts b/src/main/ai-vault/transcripts/session-document-stream-projection.test.ts similarity index 93% rename from src/main/ai-vault/session-document-stream-projection.test.ts rename to src/main/ai-vault/transcripts/session-document-stream-projection.test.ts index 2234153da37..09dc335d090 100644 --- a/src/main/ai-vault/session-document-stream-projection.test.ts +++ b/src/main/ai-vault/transcripts/session-document-stream-projection.test.ts @@ -1,5 +1,8 @@ import { describe, it, expect } from 'vitest' -import { parseDevinSessionContent, parseDevinSessionDocument } from './session-scanner-devin-parser' +import { + parseDevinSessionContent, + parseDevinSessionDocument +} from '../scanners/devin/session-scanner-devin-parser' import { readStreamedSessionDocument } from './session-document-stream' const file = { path: '/devin/test.json', modifiedAt: new Date(0).toISOString(), mtimeMs: 0 } const options = { diff --git a/src/main/ai-vault/session-document-stream.ts b/src/main/ai-vault/transcripts/session-document-stream.ts similarity index 96% rename from src/main/ai-vault/session-document-stream.ts rename to src/main/ai-vault/transcripts/session-document-stream.ts index 6dea2041bf6..9d0bccc4cbd 100644 --- a/src/main/ai-vault/session-document-stream.ts +++ b/src/main/ai-vault/transcripts/session-document-stream.ts @@ -1,8 +1,8 @@ import { StringDecoder } from 'node:string_decoder' import { FlexAssembler, arrayRule, objectRule } from 'stream-json/core/utils/flex-assembler.js' import { setImmediate as yieldToEventLoop } from 'node:timers/promises' -import { createJsonTokenReader } from '../../shared/json-token-reader' -import { throwIfAiVaultScanCancelled } from './ai-vault-scan-cancellation' +import { createJsonTokenReader } from '../../../shared/json-token-reader' +import { throwIfAiVaultScanCancelled } from '../ai-vault-scan-cancellation' /** Fold one root array while retaining only the root fields the agent parser uses. */ export async function readStreamedSessionDocument(args: { diff --git a/src/main/ai-vault/session-transcript-channel.ts b/src/main/ai-vault/transcripts/session-transcript-channel.ts similarity index 100% rename from src/main/ai-vault/session-transcript-channel.ts rename to src/main/ai-vault/transcripts/session-transcript-channel.ts diff --git a/src/main/ai-vault/session-transcript-consumers.test.ts b/src/main/ai-vault/transcripts/session-transcript-consumers.test.ts similarity index 92% rename from src/main/ai-vault/session-transcript-consumers.test.ts rename to src/main/ai-vault/transcripts/session-transcript-consumers.test.ts index 11c90c4c9d0..bcba135a725 100644 --- a/src/main/ai-vault/session-transcript-consumers.test.ts +++ b/src/main/ai-vault/transcripts/session-transcript-consumers.test.ts @@ -2,14 +2,12 @@ import { appendFile, mkdir, mkdtemp, rm, stat, truncate, utimes, writeFile } fro import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, expect, it, vi } from 'vitest' -import { isAiVaultScanCancelledError } from '../../shared/ai-vault-types' -import { scanAiVaultSessions } from './session-scanner' -import { - parseAgentSessionFileCached, - resetSessionParseCacheForTests -} from './session-scanner-parse-cache' -import { isolatedScanRoots, jsonLines } from './session-scanner-test-fixtures' -import type { FileWithMtime, SessionFileCandidate } from './session-scanner-types' +import { isAiVaultScanCancelledError } from '../../../shared/ai-vault-types' +import { scanAiVaultSessions } from '../session-scanner' +import { parseAgentSessionFileCached } from '../parse-cache/session-scanner-parse-cache' +import { resetSessionParseCacheForTests } from '../parse-cache/session-parse-cache-store' +import { isolatedScanRoots, jsonLines } from '../session-scanner-test-fixtures' +import type { FileWithMtime, SessionFileCandidate } from '../session-scanner-types' import { readWholeTranscript } from './session-transcript-reader' const OPENCODE_SQLITE_SESSION = { @@ -23,13 +21,16 @@ const OPENCODE_SQLITE_MESSAGES = [ ] // Replace worker transport while retaining the transcript channel integration. -vi.mock('./session-scanner-opencode-sqlite-worker-spawn', async (importOriginal) => ({ - ...(await importOriginal()), - parseOpenCodeSqliteSessionViaWorker: () => Promise.resolve(OPENCODE_SQLITE_SESSION), - captureOpenCodeSqliteSessionViaWorker: () => - Promise.resolve({ session: OPENCODE_SQLITE_SESSION, messages: OPENCODE_SQLITE_MESSAGES }) -})) -import type * as OpenCodeSqliteWorkerSpawn from './session-scanner-opencode-sqlite-worker-spawn' +vi.mock( + '../scanners/opencode/reader-transport/session-scanner-opencode-sqlite-worker-spawn', + async (importOriginal) => ({ + ...(await importOriginal()), + parseOpenCodeSqliteSessionViaWorker: () => Promise.resolve(OPENCODE_SQLITE_SESSION), + captureOpenCodeSqliteSessionViaWorker: () => + Promise.resolve({ session: OPENCODE_SQLITE_SESSION, messages: OPENCODE_SQLITE_MESSAGES }) + }) +) +import type * as OpenCodeSqliteWorkerSpawn from '../scanners/opencode/reader-transport/session-scanner-opencode-sqlite-worker-spawn' import { registerTranscriptConsumer, resetTranscriptConsumersForTests, diff --git a/src/main/ai-vault/session-transcript-consumers.ts b/src/main/ai-vault/transcripts/session-transcript-consumers.ts similarity index 96% rename from src/main/ai-vault/session-transcript-consumers.ts rename to src/main/ai-vault/transcripts/session-transcript-consumers.ts index b8f4f70513c..9effd1af176 100644 --- a/src/main/ai-vault/session-transcript-consumers.ts +++ b/src/main/ai-vault/transcripts/session-transcript-consumers.ts @@ -1,5 +1,5 @@ -import type { AiVaultSession } from '../../shared/ai-vault-types' -import type { SessionFileCandidate } from './session-scanner-types' +import type { AiVaultSession } from '../../../shared/ai-vault-types' +import type { SessionFileCandidate } from '../session-scanner-types' // Publish reads so new consumers do not require reader or cache changes. diff --git a/src/main/ai-vault/session-transcript-every-agent-capture.test.ts b/src/main/ai-vault/transcripts/session-transcript-every-agent-capture.test.ts similarity index 55% rename from src/main/ai-vault/session-transcript-every-agent-capture.test.ts rename to src/main/ai-vault/transcripts/session-transcript-every-agent-capture.test.ts index f38396dd290..6730ac40e69 100644 --- a/src/main/ai-vault/session-transcript-every-agent-capture.test.ts +++ b/src/main/ai-vault/transcripts/session-transcript-every-agent-capture.test.ts @@ -4,50 +4,54 @@ import { join } from 'node:path' import { afterEach, expect, it, vi } from 'vitest' // Replace the worker transport with its real in-process readers. -vi.mock('./session-scanner-opencode-sqlite-worker-spawn', async () => { - const list = await import('./session-scanner-opencode-sqlite-list') - const list2 = await import('./session-scanner-opencode2-sqlite-list') - const parse = await import('./session-scanner-opencode-sqlite') - const parse2 = await import('./session-scanner-opencode2-sqlite') - const capture = await import('./session-scanner-opencode-sqlite-capture') - const capture2 = await import('./session-scanner-opencode2-sqlite') - return { - resolveOpenCodeSqliteWorkerEntryPath: () => null, - listOpenCodeSqliteSessionsViaWorker: ( - args: Parameters[0] - ) => list.listOpenCodeSqliteSessions(args), - listOpenCode2SqliteSessionsViaWorker: ( - args: Parameters[0] - ) => list2.listOpenCode2SqliteSessions(args), - listZcodeSqliteSessionsViaWorker: ( - args: Parameters[0] - ) => list.listOpenCodeSqliteSessions({ ...args, agent: 'zcode' }), - parseOpenCodeSqliteSessionViaWorker: ( - args: Parameters[0] - ) => parse.parseOpenCodeSqliteSession(args), - parseOpenCode2SqliteSessionViaWorker: ( - args: Parameters[0] - ) => parse2.parseOpenCode2SqliteSession(args), - parseZcodeSqliteSessionViaWorker: ( - args: Parameters[0] - ) => parse.parseOpenCodeSqliteSession({ ...args, agent: 'zcode' }), - captureOpenCodeSqliteSessionViaWorker: ( - args: Parameters[0] - ) => capture.captureOpenCodeSqliteSession(args), - captureOpenCode2SqliteSessionViaWorker: ( - args: Parameters[0] - ) => capture2.captureOpenCode2SqliteSession(args), - captureZcodeSqliteSessionViaWorker: ( - args: Parameters[0] - ) => capture.captureOpenCodeSqliteSession({ ...args, agent: 'zcode' }) +vi.mock( + '../scanners/opencode/reader-transport/session-scanner-opencode-sqlite-worker-spawn', + async () => { + const list = await import('../scanners/opencode/sqlite/session-scanner-opencode-sqlite-list') + const list2 = await import('../scanners/opencode2/session-scanner-opencode2-sqlite-list') + const parse = await import('../scanners/opencode/sqlite/session-scanner-opencode-sqlite') + const parse2 = await import('../scanners/opencode2/session-scanner-opencode2-sqlite') + const capture = + await import('../scanners/opencode/sqlite/session-scanner-opencode-sqlite-capture') + const capture2 = await import('../scanners/opencode2/session-scanner-opencode2-sqlite') + return { + resolveOpenCodeSqliteWorkerEntryPath: () => null, + listOpenCodeSqliteSessionsViaWorker: ( + args: Parameters[0] + ) => list.listOpenCodeSqliteSessions(args), + listOpenCode2SqliteSessionsViaWorker: ( + args: Parameters[0] + ) => list2.listOpenCode2SqliteSessions(args), + listZcodeSqliteSessionsViaWorker: ( + args: Parameters[0] + ) => list.listOpenCodeSqliteSessions({ ...args, agent: 'zcode' }), + parseOpenCodeSqliteSessionViaWorker: ( + args: Parameters[0] + ) => parse.parseOpenCodeSqliteSession(args), + parseOpenCode2SqliteSessionViaWorker: ( + args: Parameters[0] + ) => parse2.parseOpenCode2SqliteSession(args), + parseZcodeSqliteSessionViaWorker: ( + args: Parameters[0] + ) => parse.parseOpenCodeSqliteSession({ ...args, agent: 'zcode' }), + captureOpenCodeSqliteSessionViaWorker: ( + args: Parameters[0] + ) => capture.captureOpenCodeSqliteSession(args), + captureOpenCode2SqliteSessionViaWorker: ( + args: Parameters[0] + ) => capture2.captureOpenCode2SqliteSession(args), + captureZcodeSqliteSessionViaWorker: ( + args: Parameters[0] + ) => capture.captureOpenCodeSqliteSession({ ...args, agent: 'zcode' }) + } } -}) -import { AI_VAULT_AGENTS, type AiVaultAgent } from '../../shared/ai-vault-types' -import { scanAiVaultSessions } from './session-scanner' -import { writeEveryAgentVault } from './session-scanner-every-agent-fixture' -import { resetSessionParseCacheForTests } from './session-scanner-parse-cache' -import { writeOpenCodeSqliteDatabase } from './session-scanner-opencode-sqlite-fixture' -import { splitOpenCodeSqliteCandidate } from './session-scanner-opencode-sqlite-paths' +) +import { AI_VAULT_AGENTS, type AiVaultAgent } from '../../../shared/ai-vault-types' +import { scanAiVaultSessions } from '../session-scanner' +import { writeEveryAgentVault } from '../session-scanner-every-agent-fixture' +import { resetSessionParseCacheForTests } from '../parse-cache/session-parse-cache-store' +import { writeOpenCodeSqliteDatabase } from '../scanners/opencode/sqlite/session-scanner-opencode-sqlite-fixture' +import { splitOpenCodeSqliteCandidate } from '../../../shared/opencode-sqlite-session-path' import { registerTranscriptConsumer, resetTranscriptConsumersForTests, diff --git a/src/main/ai-vault/session-transcript-message-content.test.ts b/src/main/ai-vault/transcripts/session-transcript-message-content.test.ts similarity index 100% rename from src/main/ai-vault/session-transcript-message-content.test.ts rename to src/main/ai-vault/transcripts/session-transcript-message-content.test.ts diff --git a/src/main/ai-vault/session-transcript-message-content.ts b/src/main/ai-vault/transcripts/session-transcript-message-content.ts similarity index 96% rename from src/main/ai-vault/session-transcript-message-content.ts rename to src/main/ai-vault/transcripts/session-transcript-message-content.ts index 4e5c3c08e21..6a447f53302 100644 --- a/src/main/ai-vault/session-transcript-message-content.ts +++ b/src/main/ai-vault/transcripts/session-transcript-message-content.ts @@ -4,8 +4,8 @@ import { type DecodedSessionMessage, type DecodedToolCall } from './session-decoded-message' -import { sliceAtCodeUnitLimit } from './session-scanner-text-normalization' -import type { AiVaultSessionPreviewMessage } from '../../shared/ai-vault-types' +import { sliceAtCodeUnitLimit } from '../../../shared/surrogate-safe-text-slice' +import type { AiVaultSessionPreviewMessage } from '../../../shared/ai-vault-types' import type { TranscriptMessage, TranscriptMessageRole } from './session-transcript-consumers' // Bound pathological messages; consumers may impose tighter limits. diff --git a/src/main/ai-vault/session-transcript-reader.ts b/src/main/ai-vault/transcripts/session-transcript-reader.ts similarity index 94% rename from src/main/ai-vault/session-transcript-reader.ts rename to src/main/ai-vault/transcripts/session-transcript-reader.ts index fe3cfaeb893..42decf8bf09 100644 --- a/src/main/ai-vault/session-transcript-reader.ts +++ b/src/main/ai-vault/transcripts/session-transcript-reader.ts @@ -1,20 +1,20 @@ import { createHash } from 'node:crypto' -import { readTranscriptSlice } from '../native-chat/wsl-transcript-fs-access' -import type { AiVaultSession } from '../../shared/ai-vault-types' -import { parseAgentSessionFile } from './session-scanner-agent-parser' -import { consumeCompleteJsonlLines } from './session-scanner-jsonl-reader' -import type { ResumableSessionParseState, SessionFileCandidate } from './session-scanner-types' +import { readTranscriptSlice } from '../../native-chat/wsl-transcript-fs-access' +import type { AiVaultSession } from '../../../shared/ai-vault-types' +import { parseAgentSessionFile } from '../session-scanner-agent-parser' +import { consumeCompleteJsonlLines } from '../session-scanner-jsonl-reader' +import type { ResumableSessionParseState, SessionFileCandidate } from '../session-scanner-types' import { invalidateSessionParseCacheEntry, type SessionParseResumePoint -} from './session-parse-cache-store' +} from '../parse-cache/session-parse-cache-store' import { TranscriptMessageChannel } from './session-transcript-channel' import { hasTranscriptConsumers, transcriptResumableOffsets } from './session-transcript-consumers' import { mergeSkippedTranscriptRecords, type SkippedTranscriptRecord } from './session-transcript-record-budget' -import { throwIfAiVaultScanCancelled } from './ai-vault-scan-cancellation' +import { throwIfAiVaultScanCancelled } from '../ai-vault-scan-cancellation' type TranscriptSessionEnrichment = { /** Complete consumer metadata before committing; the returned fold stays unmodified. */ diff --git a/src/main/ai-vault/session-transcript-record-budget.test.ts b/src/main/ai-vault/transcripts/session-transcript-record-budget.test.ts similarity index 100% rename from src/main/ai-vault/session-transcript-record-budget.test.ts rename to src/main/ai-vault/transcripts/session-transcript-record-budget.test.ts diff --git a/src/main/ai-vault/session-transcript-record-budget.ts b/src/main/ai-vault/transcripts/session-transcript-record-budget.ts similarity index 100% rename from src/main/ai-vault/session-transcript-record-budget.ts rename to src/main/ai-vault/transcripts/session-transcript-record-budget.ts diff --git a/src/main/claude/claude-transcript-catch-up.ts b/src/main/claude/claude-transcript-catch-up.ts index 6d58c2362ad..7819bc6ec08 100644 --- a/src/main/claude/claude-transcript-catch-up.ts +++ b/src/main/claude/claude-transcript-catch-up.ts @@ -1,6 +1,6 @@ import { join } from 'node:path' import { isRootAgentJournalItem } from '../../shared/agent-session/journal/agent-session-journal-producer' -import { encodeClaudeProjectPaths } from '../ai-vault/claude-project-dir-encoding' +import { encodeClaudeProjectPaths } from '../ai-vault/scanners/claude/claude-project-dir-encoding' import { wslGatedStat } from '../native-chat/wsl-transcript-fs-access' import type { StructuredAgentSessionEventSink } from '../native-chat/agent-session-wire/structured-agent-session-event-sink' import { runHistoryCatchUp } from '../native-chat/agent-session-wire/structured-agent-session-history-catch-up' diff --git a/src/main/codex/codex-legacy-session-resume.test.ts b/src/main/codex/codex-legacy-session-resume.test.ts index 10d5e50d615..8e7780747cb 100644 --- a/src/main/codex/codex-legacy-session-resume.test.ts +++ b/src/main/codex/codex-legacy-session-resume.test.ts @@ -15,7 +15,7 @@ import type * as NodeFsPromises from 'node:fs/promises' import { codexRolloutHardlinkIdentity, dedupeCodexRolloutFileAliases -} from '../ai-vault/codex-session-root-dedup' +} from '../ai-vault/scanners/codex/codex-session-root-dedup' import { prepareLegacySharedCodexSessionResume } from './codex-legacy-session-resume' import { ManagedCodexHomeTemporarilyUnavailableError } from '../codex-accounts/host-codex-managed-home-ownership' diff --git a/src/main/foreign-sqlite-readers/foreign-sqlite-reader-entry.ts b/src/main/foreign-sqlite-readers/foreign-sqlite-reader-entry.ts index 00976398c60..3dc41805bf9 100644 --- a/src/main/foreign-sqlite-readers/foreign-sqlite-reader-entry.ts +++ b/src/main/foreign-sqlite-readers/foreign-sqlite-reader-entry.ts @@ -1,6 +1,6 @@ import { parentPort } from 'node:worker_threads' -import { handleOpenCodeSqliteRequest } from '../ai-vault/session-scanner-opencode-sqlite-dispatch' -import type { OpenCodeSqliteWorkerRequest } from '../ai-vault/session-scanner-opencode-sqlite-worker-protocol' +import { handleOpenCodeSqliteRequest } from '../ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-dispatch' +import type { OpenCodeSqliteWorkerRequest } from '../ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-worker-protocol' import { handleForeignSqliteReaderRequest } from './foreign-sqlite-reader-dispatch' import type { ForeignSqliteReaderRequest, diff --git a/src/main/foreign-sqlite-readers/readers/opencode-binder-sessions.ts b/src/main/foreign-sqlite-readers/readers/opencode-binder-sessions.ts index 28687f14593..c74ad8f2a49 100644 --- a/src/main/foreign-sqlite-readers/readers/opencode-binder-sessions.ts +++ b/src/main/foreign-sqlite-readers/readers/opencode-binder-sessions.ts @@ -1,5 +1,5 @@ import { statSync } from 'node:fs' -import { readOpenCodeDatabase } from '../../ai-vault/session-scanner-opencode-sqlite-open' +import { readOpenCodeDatabase } from '../../ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-open' import { columnExists, tableExists } from '../../opencode-usage/schema-helpers' import { isRecord } from '../../../shared/agent-status-child-work-value-guards' import type { BinderSessionRow, OpenCodeSessionCursor } from '../opencode-binder-sessions-result' diff --git a/src/main/foreign-sqlite-readers/readers/opencode-prompt-failure.ts b/src/main/foreign-sqlite-readers/readers/opencode-prompt-failure.ts index d83207aa966..e7228a47330 100644 --- a/src/main/foreign-sqlite-readers/readers/opencode-prompt-failure.ts +++ b/src/main/foreign-sqlite-readers/readers/opencode-prompt-failure.ts @@ -1,6 +1,6 @@ import { z } from 'zod' import { usageLimitResetsAt } from '../../../shared/agent-session/failures/agent-session-usage-limit' -import { readOpenCodeDatabase } from '../../ai-vault/session-scanner-opencode-sqlite-open' +import { readOpenCodeDatabase } from '../../ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-open' import { columnExists, tableExists } from '../../opencode-usage/schema-helpers' import { openCodePromptFailureSchema, diff --git a/src/main/ipc/ai-vault-scan-coalescing.test.ts b/src/main/ipc/ai-vault-scan-coalescing.test.ts index 354c53a5867..11ef0650cfe 100644 --- a/src/main/ipc/ai-vault-scan-coalescing.test.ts +++ b/src/main/ipc/ai-vault-scan-coalescing.test.ts @@ -15,7 +15,7 @@ vi.mock('electron', () => ({ ipcMain: { handle: mocks.ipcHandle, on: vi.fn() }, BrowserWindow: { getAllWindows: () => [] } })) -vi.mock('../ai-vault/session-scanner-service-spawn', async (importOriginal) => ({ +vi.mock('../ai-vault/scan-service/session-scanner-service-spawn', async (importOriginal) => ({ ...(await importOriginal()), scanAiVaultSessionsInService: mocks.scanAiVaultSessionsInService, resolveAiVaultSessionTitlesInService: mocks.resolveAiVaultSessionTitlesInService diff --git a/src/main/ipc/ai-vault-search-all-hosts-real-index.test.ts b/src/main/ipc/ai-vault-search-all-hosts-real-index.test.ts index 0484e633125..17d9a8e0d5a 100644 --- a/src/main/ipc/ai-vault-search-all-hosts-real-index.test.ts +++ b/src/main/ipc/ai-vault-search-all-hosts-real-index.test.ts @@ -1,8 +1,8 @@ import { mkdir, rm, writeFile } from 'node:fs/promises' import { join } from 'node:path' import { afterEach, beforeEach, expect, it } from 'vitest' -import { resetSessionParseCacheForTests } from '../ai-vault/session-scanner-parse-cache' -import { resetTranscriptConsumersForTests } from '../ai-vault/session-transcript-consumers' +import { resetSessionParseCacheForTests } from '../ai-vault/parse-cache/session-parse-cache-store' +import { resetTranscriptConsumersForTests } from '../ai-vault/transcripts/session-transcript-consumers' import { SessionSearchInstance } from '../ai-vault-search/session-search-instance' import { claudeLines, diff --git a/src/main/ipc/ai-vault-search.test.ts b/src/main/ipc/ai-vault-search.test.ts index 126daee4be0..816e6e36e97 100644 --- a/src/main/ipc/ai-vault-search.test.ts +++ b/src/main/ipc/ai-vault-search.test.ts @@ -8,7 +8,7 @@ const { clearSearch, handlers, sshSearch, sshHostInfos, runtimeSearch } = vi.hoi sshHostInfos: vi.fn<() => { targetId: string }[]>(() => []), runtimeSearch: vi.fn() })) -vi.mock('../ai-vault/session-scanner-service-spawn', () => ({ +vi.mock('../ai-vault/scan-service/session-scanner-service-spawn', () => ({ clearSessionSearchInService: clearSearch })) vi.mock('electron', () => ({ diff --git a/src/main/ipc/ai-vault-search.ts b/src/main/ipc/ai-vault-search.ts index 9f1a1a87873..13134af10e7 100644 --- a/src/main/ipc/ai-vault-search.ts +++ b/src/main/ipc/ai-vault-search.ts @@ -26,7 +26,7 @@ import { type ParsedExecutionHost } from '../../shared/execution-host' import { redactStatusForTransport } from '../../shared/ai-vault-search-transport' -import { clearSessionSearchInService } from '../ai-vault/session-scanner-service-spawn' +import { clearSessionSearchInService } from '../ai-vault/scan-service/session-scanner-service-spawn' import { searchAllExecutionHosts, type SessionSearchHostLeg } from './ai-vault-search-all-hosts' import { getActiveRuntimeAiVaultHostInfosResult } from './ai-vault' import { AI_VAULT_ALL_HOST_TIMEOUT_MS } from './ai-vault-all-host-timeouts' diff --git a/src/main/ipc/ai-vault-session-title-routing.ts b/src/main/ipc/ai-vault-session-title-routing.ts index 5a9d953e064..8159cea709f 100644 --- a/src/main/ipc/ai-vault-session-title-routing.ts +++ b/src/main/ipc/ai-vault-session-title-routing.ts @@ -7,7 +7,7 @@ import { parseRoutableExecutionHostId, requestedExecutionHostScope } from '../../shared/execution-host' -import { resolveLocalAiVaultSessionTitles } from '../ai-vault/session-title-resolver' +import { resolveLocalAiVaultSessionTitles } from '../ai-vault/session-titles/session-title-resolver' export type RuntimeAiVaultSessionTitleResolver = ( environmentId: string, diff --git a/src/main/ipc/ai-vault-subagent-list.ts b/src/main/ipc/ai-vault-subagent-list.ts index 6c985c8b97c..a5e8a483bb1 100644 --- a/src/main/ipc/ai-vault-subagent-list.ts +++ b/src/main/ipc/ai-vault-subagent-list.ts @@ -1,6 +1,6 @@ import { resolve } from 'node:path' import { getAiVaultWslHomeDirs } from '../ai-vault/cached-session-list' -import { listAiVaultSubagentSessionsInBackground } from '../ai-vault/session-scanner-background' +import { listAiVaultSubagentSessionsInBackground } from '../ai-vault/scan-service/session-scanner-background' import { claudeProjectsRootDirs } from '../ai-vault/session-scanner-roots' import { sessionRowRootDirs } from '../ai-vault/session-scanner-agent-sources' import { isPathInsideOrEqual } from '../../shared/cross-platform-path' diff --git a/src/main/ipc/ai-vault-unresolved-owner.test.ts b/src/main/ipc/ai-vault-unresolved-owner.test.ts index 36db14ab6ca..8149c596e70 100644 --- a/src/main/ipc/ai-vault-unresolved-owner.test.ts +++ b/src/main/ipc/ai-vault-unresolved-owner.test.ts @@ -9,7 +9,7 @@ const mocks = vi.hoisted(() => ({ vi.mock('electron', () => ({ app: { on: vi.fn() }, ipcMain: { handle: vi.fn() } })) -vi.mock('../ai-vault/session-scanner-service-spawn', async (importOriginal) => ({ +vi.mock('../ai-vault/scan-service/session-scanner-service-spawn', async (importOriginal) => ({ ...(await importOriginal()), scanAiVaultSessionsInService: mocks.scanLocalSessions })) diff --git a/src/main/ipc/ai-vault.test.ts b/src/main/ipc/ai-vault.test.ts index 69694be58d3..d6d3a7b2dd4 100644 --- a/src/main/ipc/ai-vault.test.ts +++ b/src/main/ipc/ai-vault.test.ts @@ -3,7 +3,7 @@ import { join, sep } from 'node:path' import { beforeEach, describe, expect, it, vi } from 'vitest' import type { AiVaultListResult, AiVaultSession } from '../../shared/ai-vault-types' import type * as CachedSessionListModule from '../ai-vault/cached-session-list' -import type * as SessionParseCacheModule from '../ai-vault/session-scanner-parse-cache' +import type * as SessionParseCacheModule from '../ai-vault/parse-cache/session-parse-cache-store' const mocks = vi.hoisted(() => ({ scanLocalSessions: vi.fn(), @@ -24,7 +24,7 @@ vi.mock('electron', () => ({ shell: { trashItem: mocks.trashItem } })) -vi.mock('../ai-vault/session-scanner-service-spawn', async (importOriginal) => ({ +vi.mock('../ai-vault/scan-service/session-scanner-service-spawn', async (importOriginal) => ({ ...(await importOriginal()), scanAiVaultSessionsInService: mocks.scanLocalSessions, resolveAiVaultSessionTitlesInService: mocks.resolveAiVaultSessionTitlesInService, @@ -44,7 +44,7 @@ vi.mock('../ai-vault/cached-session-list', async (importOriginal) => { } }) -vi.mock('../ai-vault/session-scanner-parse-cache', async (importOriginal) => { +vi.mock('../ai-vault/parse-cache/session-parse-cache-store', async (importOriginal) => { const actual = await importOriginal() return { ...actual, @@ -58,7 +58,7 @@ vi.mock('../wsl/discovery/distro-catalog', () => ({ hasCachedWslDistros: vi.fn(() => false) })) -const { resolveOmpSessionsDir } = await import('../ai-vault/omp-session-root') +const { resolveOmpSessionsDir } = await import('../ai-vault/scanners/omp/omp-session-root') const { _internals, registerAiVaultHandlers } = await import('./ai-vault') const { deleteAiVaultSession: deleteAiVaultSessionWithDeps } = await import('./ai-vault-delete') const { deleteAiVaultSessionForRemoteClient } = await import('../ai-vault/host-session-delete') diff --git a/src/main/ipc/filesystem/filesystem-file-content-inspection.ts b/src/main/ipc/filesystem/filesystem-file-content-inspection.ts index 2014a4ee99e..910adce424a 100644 --- a/src/main/ipc/filesystem/filesystem-file-content-inspection.ts +++ b/src/main/ipc/filesystem/filesystem-file-content-inspection.ts @@ -2,7 +2,7 @@ import { IMAGE_AND_PDF_PREVIEW_MIME_TYPES, filePreviewExtension } from '../../../shared/file-preview-kind' -import { localLogFileIdentity } from '../../ai-vault/local-log-tail-reader' +import { localLogFileIdentity } from '../../ai-vault/transcripts/local-log-tail-reader' import { BINARY_PROBE_BYTES, isBinaryBuffer } from '../../../shared/binary-buffer' import { fileTooLargeError, diff --git a/src/main/ipc/local-log-tail.test.ts b/src/main/ipc/local-log-tail.test.ts index 909da8a13b9..1430383af51 100644 --- a/src/main/ipc/local-log-tail.test.ts +++ b/src/main/ipc/local-log-tail.test.ts @@ -22,7 +22,7 @@ vi.mock('./local-file-access-resolution', () => ({ resolveUserNamedRegularFile: resolveAuthorizedPathMock })) -vi.mock('../ai-vault/local-log-tail-reader', () => ({ +vi.mock('../ai-vault/transcripts/local-log-tail-reader', () => ({ readLocalLogTailRange: readRangeMock })) diff --git a/src/main/ipc/local-log-tail.ts b/src/main/ipc/local-log-tail.ts index a53f79646ac..4daa2de52f4 100644 --- a/src/main/ipc/local-log-tail.ts +++ b/src/main/ipc/local-log-tail.ts @@ -6,7 +6,7 @@ import type { LocalLogTailReadResult, LocalLogTailWatchArgs } from '../../shared/local-log-tail-types' -import { readLocalLogTailRange } from '../ai-vault/local-log-tail-reader' +import { readLocalLogTailRange } from '../ai-vault/transcripts/local-log-tail-reader' import type { Store } from '../persistence/loading-store/store' import { resolveUserNamedRegularFile } from './local-file-access-resolution' import { abortWhenRendererGone } from './renderer-lifetime-abort' diff --git a/src/main/native-chat/agent-session-journal/adopted-directory-probe.ts b/src/main/native-chat/agent-session-journal/adopted-directory-probe.ts index a79763d3451..74d0d4513fc 100644 --- a/src/main/native-chat/agent-session-journal/adopted-directory-probe.ts +++ b/src/main/native-chat/agent-session-journal/adopted-directory-probe.ts @@ -1,6 +1,9 @@ import { dirname } from 'node:path' import { runProcess } from '@orca/process-host' -import { pickAllowedEnv, RUNTIME_ENV_ALLOWLIST } from '../../ai-vault/session-scanner-service-env' +import { + pickAllowedEnv, + RUNTIME_ENV_ALLOWLIST +} from '../../ai-vault/scan-service/session-scanner-service-env' export const ADOPTED_DIRECTORY_PROBE_TIMEOUT_MS = 5_000 export const ADOPTED_DIRECTORY_PROBE_MAX_OUTPUT_BYTES = 4_096 diff --git a/src/main/native-chat/agent-session-journal/adopted-transcript-source.ts b/src/main/native-chat/agent-session-journal/adopted-transcript-source.ts index 4a62879c651..e5b271faae5 100644 --- a/src/main/native-chat/agent-session-journal/adopted-transcript-source.ts +++ b/src/main/native-chat/agent-session-journal/adopted-transcript-source.ts @@ -4,7 +4,7 @@ import type { AgentType } from '../../../shared/agent-status-types' import { normalizeRuntimePathForComparison } from '../../../shared/cross-platform-path' import { readNodeFileWithinLimit } from '../../../shared/node-bounded-file-reader' import { asRecord, extractString, parseJsonObject } from '../../ai-vault/session-scanner-values' -import { readOpenCodeTranscriptSignalViaWorker } from '../../ai-vault/session-scanner-opencode-sqlite-worker-spawn' +import { readOpenCodeTranscriptSignalViaWorker } from '../../ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-worker-spawn' import { samePiDirectory } from '../../pi/rpc-launch-resolution' import { admitTranscriptPath } from '../transcript-path-admission' import { adoptedDirectoryProbes } from './adopted-directory-probe' diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-adopted-import.test.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-adopted-import.test.ts index 18d380bcbca..dfe92f51d3c 100644 --- a/src/main/native-chat/agent-session-wire/structured-agent-session-adopted-import.test.ts +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-adopted-import.test.ts @@ -28,19 +28,22 @@ import { structuredAgentsDeclaringNothing } from './structured-agent-session-adapter-router-test-support' import { structuredAgentRuntimeRegistration } from '../../runtime/structured-agent-runtime-registrations' -import { writeOpenCodeSqliteDatabase } from '../../ai-vault/session-scanner-opencode-sqlite-fixture' +import { writeOpenCodeSqliteDatabase } from '../../ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-fixture' -vi.mock('../../ai-vault/session-scanner-opencode-sqlite-worker-spawn', async (importOriginal) => { - const query = await import('../transcript-opencode-sqlite-query') - return { - ...(await importOriginal()), - readOpenCodeTranscriptPageViaWorker: async ( - args: Parameters[0] - ) => query.readOpenCodeTranscriptPage(args), - readOpenCodeTranscriptSignalViaWorker: async (args: { dbPath: string; sessionId: string }) => - query.readOpenCodeTranscriptSignal(args.dbPath, args.sessionId) +vi.mock( + '../../ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-worker-spawn', + async (importOriginal) => { + const query = await import('../transcript-opencode-sqlite-query') + return { + ...(await importOriginal()), + readOpenCodeTranscriptPageViaWorker: async ( + args: Parameters[0] + ) => query.readOpenCodeTranscriptPage(args), + readOpenCodeTranscriptSignalViaWorker: async (args: { dbPath: string; sessionId: string }) => + query.readOpenCodeTranscriptSignal(args.dbPath, args.sessionId) + } } -}) +) const NOW = 1_800_000_000_000 const SESSION = 'codex_adopting_session' diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-create-adoption-budget.test.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-create-adoption-budget.test.ts index 31b0aa2b231..9927ebf4470 100644 --- a/src/main/native-chat/agent-session-wire/structured-agent-session-create-adoption-budget.test.ts +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-create-adoption-budget.test.ts @@ -1,13 +1,16 @@ import { mkdir, realpath, writeFile, rm, symlink, readFile } from 'node:fs/promises' -vi.mock('../../ai-vault/session-scanner-opencode-sqlite-worker-spawn', async (original) => { - const query = await import('../transcript-opencode-sqlite-query') - return { - ...(await original()), - readOpenCodeTranscriptPageViaWorker: query.readOpenCodeTranscriptPage, - readOpenCodeTranscriptSignalViaWorker: async (args: { dbPath: string; sessionId: string }) => - query.readOpenCodeTranscriptSignal(args.dbPath, args.sessionId) +vi.mock( + '../../ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-worker-spawn', + async (original) => { + const query = await import('../transcript-opencode-sqlite-query') + return { + ...(await original()), + readOpenCodeTranscriptPageViaWorker: query.readOpenCodeTranscriptPage, + readOpenCodeTranscriptSignalViaWorker: async (args: { dbPath: string; sessionId: string }) => + query.readOpenCodeTranscriptSignal(args.dbPath, args.sessionId) + } } -}) +) import { join } from 'node:path' import { expect, it, vi } from 'vitest' import { createRestTestRig } from './structured-agent-session-rest-test-rig' @@ -21,7 +24,7 @@ import { } from './structured-agent-session-host-test-data' import { claudeProviderHandle } from '../../../shared/agent-session/lifecycle/agent-session-provider-handle-encoding' import { adoptedDirectoryProbes } from '../agent-session-journal/adopted-directory-probe' -import { writeOpenCodeSqliteDatabase } from '../../ai-vault/session-scanner-opencode-sqlite-fixture' +import { writeOpenCodeSqliteDatabase } from '../../ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-fixture' import { structuredAgentRuntimeRegistration } from '../../runtime/structured-agent-runtime-registrations' import { structuredAgentsDeclaringNothing } from './structured-agent-session-adapter-router-test-support' import { resolveAgentSessionLaunchDirectory } from '../../runtime/agent-session/agent-session-launch-directory' diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-create-adoption-contract-test-fixture.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-create-adoption-contract-test-fixture.ts index 2423a7ba381..caf98b85eda 100644 --- a/src/main/native-chat/agent-session-wire/structured-agent-session-create-adoption-contract-test-fixture.ts +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-create-adoption-contract-test-fixture.ts @@ -1,13 +1,16 @@ import { writeFile } from 'node:fs/promises' -vi.mock('../../ai-vault/session-scanner-opencode-sqlite-worker-spawn', async (original) => { - const query = await import('../transcript-opencode-sqlite-query') - return { - ...(await original()), - readOpenCodeTranscriptPageViaWorker: query.readOpenCodeTranscriptPage, - readOpenCodeTranscriptSignalViaWorker: async (args: { dbPath: string; sessionId: string }) => - query.readOpenCodeTranscriptSignal(args.dbPath, args.sessionId) +vi.mock( + '../../ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-worker-spawn', + async (original) => { + const query = await import('../transcript-opencode-sqlite-query') + return { + ...(await original()), + readOpenCodeTranscriptPageViaWorker: query.readOpenCodeTranscriptPage, + readOpenCodeTranscriptSignalViaWorker: async (args: { dbPath: string; sessionId: string }) => + query.readOpenCodeTranscriptSignal(args.dbPath, args.sessionId) + } } -}) +) import { join } from 'node:path' import { afterEach, beforeEach, vi } from 'vitest' import { createRestTestRig, type RestTestRig } from './structured-agent-session-rest-test-rig' diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-create-adoption-restart.test.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-create-adoption-restart.test.ts index d4c2a200bdd..c9b69ce3b30 100644 --- a/src/main/native-chat/agent-session-wire/structured-agent-session-create-adoption-restart.test.ts +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-create-adoption-restart.test.ts @@ -1,13 +1,16 @@ import { writeFile, rm } from 'node:fs/promises' -vi.mock('../../ai-vault/session-scanner-opencode-sqlite-worker-spawn', async (original) => { - const query = await import('../transcript-opencode-sqlite-query') - return { - ...(await original()), - readOpenCodeTranscriptPageViaWorker: query.readOpenCodeTranscriptPage, - readOpenCodeTranscriptSignalViaWorker: async (args: { dbPath: string; sessionId: string }) => - query.readOpenCodeTranscriptSignal(args.dbPath, args.sessionId) +vi.mock( + '../../ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-worker-spawn', + async (original) => { + const query = await import('../transcript-opencode-sqlite-query') + return { + ...(await original()), + readOpenCodeTranscriptPageViaWorker: query.readOpenCodeTranscriptPage, + readOpenCodeTranscriptSignalViaWorker: async (args: { dbPath: string; sessionId: string }) => + query.readOpenCodeTranscriptSignal(args.dbPath, args.sessionId) + } } -}) +) import { join } from 'node:path' import { expect, it, vi } from 'vitest' import { restTestSend } from './structured-agent-session-rest-test-rig' diff --git a/src/main/native-chat/agent-session-wire/structured-agent-session-create-adoption.test.ts b/src/main/native-chat/agent-session-wire/structured-agent-session-create-adoption.test.ts index 6b384228daa..3c9a3eee05a 100644 --- a/src/main/native-chat/agent-session-wire/structured-agent-session-create-adoption.test.ts +++ b/src/main/native-chat/agent-session-wire/structured-agent-session-create-adoption.test.ts @@ -1,13 +1,16 @@ import { mkdir, realpath, rename, writeFile } from 'node:fs/promises' -vi.mock('../../ai-vault/session-scanner-opencode-sqlite-worker-spawn', async (original) => { - const query = await import('../transcript-opencode-sqlite-query') - return { - ...(await original()), - readOpenCodeTranscriptPageViaWorker: query.readOpenCodeTranscriptPage, - readOpenCodeTranscriptSignalViaWorker: async (args: { dbPath: string; sessionId: string }) => - query.readOpenCodeTranscriptSignal(args.dbPath, args.sessionId) +vi.mock( + '../../ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-worker-spawn', + async (original) => { + const query = await import('../transcript-opencode-sqlite-query') + return { + ...(await original()), + readOpenCodeTranscriptPageViaWorker: query.readOpenCodeTranscriptPage, + readOpenCodeTranscriptSignalViaWorker: async (args: { dbPath: string; sessionId: string }) => + query.readOpenCodeTranscriptSignal(args.dbPath, args.sessionId) + } } -}) +) import { join } from 'node:path' import { expect, it, vi } from 'vitest' import { diff --git a/src/main/native-chat/session-file-id-layouts.ts b/src/main/native-chat/session-file-id-layouts.ts index eb8be04ea14..66ef2b8445a 100644 --- a/src/main/native-chat/session-file-id-layouts.ts +++ b/src/main/native-chat/session-file-id-layouts.ts @@ -1,6 +1,6 @@ import { win32 } from 'node:path' import { GROK_CHAT_HISTORY_FILE } from '../../shared/grok-session-paths' -import { isOmpConversationDirectory } from '../ai-vault/session-scanner-omp-subagent-transcripts' +import { isOmpConversationDirectory } from '../ai-vault/scanners/omp/session-scanner-omp-subagent-transcripts' export type SessionIdLookupAgent = 'claude' | 'codex' | 'grok' | 'omp' diff --git a/src/main/native-chat/session-file-resolver.ts b/src/main/native-chat/session-file-resolver.ts index e7bf106194c..4d69446eb82 100644 --- a/src/main/native-chat/session-file-resolver.ts +++ b/src/main/native-chat/session-file-resolver.ts @@ -8,7 +8,7 @@ import { } from '../../shared/native-chat/native-chat-agent-support' import { isWslUncPath } from '../../shared/wsl-paths' import { walkSessionFiles } from '../ai-vault/session-scanner-discovery' -import { resolveOmpSessionsDir } from '../ai-vault/omp-session-root' +import { resolveOmpSessionsDir } from '../ai-vault/scanners/omp/omp-session-root' import { claudeProjectsHostDirs, codexHomeSessionsDir, diff --git a/src/main/native-chat/structured-agent-cli-conversation-adoption.test.ts b/src/main/native-chat/structured-agent-cli-conversation-adoption.test.ts index cb12de5e0d2..dfeb90b92b5 100644 --- a/src/main/native-chat/structured-agent-cli-conversation-adoption.test.ts +++ b/src/main/native-chat/structured-agent-cli-conversation-adoption.test.ts @@ -20,23 +20,26 @@ import { import { resolveStructuredAgentSessionAdoptionForCreate } from '../runtime/agent-session/structured-agent-session-create-adoption' import { prepareLegacyTranscriptImport } from './agent-session-journal/journal-legacy-import' import type { AgentSessionAccountHome } from '../../shared/agent-session/lifecycle/agent-session-account-home' -import { writeOpenCodeSqliteDatabase } from '../ai-vault/session-scanner-opencode-sqlite-fixture' +import { writeOpenCodeSqliteDatabase } from '../ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-fixture' import { resolveAcpLaunchInvocation } from '../acp/acp-structured-launch-resolution' import { acpLaunchSpecFor } from '../acp/acp-launch-specs' import { resolveOpenCodeDatabasePath } from '../opencode/opencode-data-directory' import * as hostReadableTranscriptPath from './host-readable-transcript-path' -vi.mock('../ai-vault/session-scanner-opencode-sqlite-worker-spawn', async (importOriginal) => { - const query = await import('./transcript-opencode-sqlite-query') - return { - ...(await importOriginal()), - readOpenCodeTranscriptPageViaWorker: async ( - args: Parameters[0] - ) => query.readOpenCodeTranscriptPage(args), - readOpenCodeTranscriptSignalViaWorker: async (args: { dbPath: string; sessionId: string }) => - query.readOpenCodeTranscriptSignal(args.dbPath, args.sessionId) +vi.mock( + '../ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-worker-spawn', + async (importOriginal) => { + const query = await import('./transcript-opencode-sqlite-query') + return { + ...(await importOriginal()), + readOpenCodeTranscriptPageViaWorker: async ( + args: Parameters[0] + ) => query.readOpenCodeTranscriptPage(args), + readOpenCodeTranscriptSignalViaWorker: async (args: { dbPath: string; sessionId: string }) => + query.readOpenCodeTranscriptSignal(args.dbPath, args.sessionId) + } } -}) +) const SESSION_ID = '0198c2a4-7d1e-7c3a-9a4b-1f2e3d4c5b6a' let root: string | null = null diff --git a/src/main/native-chat/structured-chat-naming-publication.test.ts b/src/main/native-chat/structured-chat-naming-publication.test.ts index 20136fa845c..6c83c99796d 100644 --- a/src/main/native-chat/structured-chat-naming-publication.test.ts +++ b/src/main/native-chat/structured-chat-naming-publication.test.ts @@ -6,7 +6,7 @@ import { agentSessionConversationView } from '../../shared/agent-session/lifecyc import { agentSessionRecordFixture } from '../../shared/agent-session/lifecycle/agent-session-record.test-fixture' import { codexProviderHandle } from '../../shared/agent-session/lifecycle/agent-session-provider-handle-encoding' import { listResult } from '../ai-vault/structured-session-ownership.test-support' -import * as scanner from '../ai-vault/session-scanner-background' +import * as scanner from '../ai-vault/scan-service/session-scanner-background' import { resetAiVaultSessionListCacheForTests } from '../ai-vault/cached-session-list' import { OrcaRuntimeService } from '../runtime/orca-runtime' import { RpcDispatcher } from '../runtime/rpc/dispatcher' diff --git a/src/main/native-chat/transcript-opencode-database.test.ts b/src/main/native-chat/transcript-opencode-database.test.ts index 92fddb0d694..050eaeaf17c 100644 --- a/src/main/native-chat/transcript-opencode-database.test.ts +++ b/src/main/native-chat/transcript-opencode-database.test.ts @@ -31,17 +31,23 @@ vi.mock('../opencode-usage/opencode-database-discovery', () => ({ listOpenCodeDatabasesInDirectory: mocks.directory, compareOpenCodeClaimPriority: (a: string, b: string) => a.localeCompare(b) })) -vi.mock('../ai-vault/opencode-wsl-runtime-preparation', () => ({ +vi.mock('../ai-vault/scanners/opencode/reader-transport/opencode-wsl-runtime-preparation', () => ({ prepareOpenCodeWslReaders: mocks.prepare })) -vi.mock('../ai-vault/session-scanner-opencode-wsl-client', () => ({ - configureOpenCodeWslReaders: mocks.configure, - openCodeWslPath: mocks.wslPath -})) -vi.mock('../ai-vault/session-scanner-opencode-sqlite-worker-spawn', () => ({ - readOpenCodeTranscriptSignalViaWorker: mocks.readSignal, - readOpenCodeTranscriptPageViaWorker: vi.fn() -})) +vi.mock( + '../ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-wsl-client', + () => ({ + configureOpenCodeWslReaders: mocks.configure, + openCodeWslPath: mocks.wslPath + }) +) +vi.mock( + '../ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-worker-spawn', + () => ({ + readOpenCodeTranscriptSignalViaWorker: mocks.readSignal, + readOpenCodeTranscriptPageViaWorker: vi.fn() + }) +) import { resolveOpenCodeTranscriptDbPath, openCodeTranscriptDefaultDeps diff --git a/src/main/native-chat/transcript-opencode-database.ts b/src/main/native-chat/transcript-opencode-database.ts index c6e672c56f4..a896bc16db6 100644 --- a/src/main/native-chat/transcript-opencode-database.ts +++ b/src/main/native-chat/transcript-opencode-database.ts @@ -3,12 +3,12 @@ import { wslGatedAccess } from './wsl-transcript-fs-access' import { join } from 'node:path' import { waitForPromiseWithSignal } from '../../shared/abort-signal-reason' import { getAiVaultWslScanHomeDirs } from '../ai-vault/cached-session-list' -import { prepareOpenCodeWslReaders } from '../ai-vault/opencode-wsl-runtime-preparation' +import { prepareOpenCodeWslReaders } from '../ai-vault/scanners/opencode/reader-transport/opencode-wsl-runtime-preparation' import { configureOpenCodeWslReaders, openCodeWslPath -} from '../ai-vault/session-scanner-opencode-wsl-client' -import { readOpenCodeTranscriptSignalViaWorker } from '../ai-vault/session-scanner-opencode-sqlite-worker-spawn' +} from '../ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-wsl-client' +import { readOpenCodeTranscriptSignalViaWorker } from '../ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-worker-spawn' import { compareOpenCodeClaimPriority, listOpenCodeDatabases, diff --git a/src/main/native-chat/transcript-opencode-sqlite-query.ts b/src/main/native-chat/transcript-opencode-sqlite-query.ts index c2683b7553a..16aa5304b00 100644 --- a/src/main/native-chat/transcript-opencode-sqlite-query.ts +++ b/src/main/native-chat/transcript-opencode-sqlite-query.ts @@ -1,6 +1,6 @@ -import { openOpenCodeDatabaseReadonly } from '../ai-vault/session-scanner-opencode-sqlite-open' -import { zcodeVisibleMessageFilter } from '../ai-vault/session-scanner-zcode-visibility' -import { zcodeTranscriptOrder } from '../ai-vault/session-scanner-zcode-order' +import { openOpenCodeDatabaseReadonly } from '../ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-open' +import { zcodeVisibleMessageFilter } from '../ai-vault/scanners/zcode/session-scanner-zcode-visibility' +import { zcodeTranscriptOrder } from '../ai-vault/scanners/zcode/session-scanner-zcode-order' import { readOpenCode2TranscriptPage, readOpenCode2TranscriptSignal diff --git a/src/main/native-chat/transcript-opencode.ts b/src/main/native-chat/transcript-opencode.ts index 8238d84439a..65e2e6fe75d 100644 --- a/src/main/native-chat/transcript-opencode.ts +++ b/src/main/native-chat/transcript-opencode.ts @@ -1,14 +1,14 @@ import { OPENCODE_CAPTURE_RECORD_LIMIT, OPENCODE_CAPTURE_TEXT_LIMIT -} from '../ai-vault/opencode-transcript-capture-limits' +} from '../ai-vault/scanners/opencode/sqlite/opencode-transcript-capture-limits' import type { NativeChatMessage } from '../../shared/native-chat/native-chat-types' import { errorMessage } from '../ai-vault/session-scanner-values' import type { ReadTranscriptResult } from './transcript-reader' import { readOpenCodeTranscriptPageViaWorker, readOpenCodeTranscriptSignalViaWorker -} from '../ai-vault/session-scanner-opencode-sqlite-worker-spawn' +} from '../ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-worker-spawn' import { discoverOpenCodeTranscriptDatabase } from './transcript-opencode-database' import type { OpenCodeTranscriptPage, diff --git a/src/main/native-chat/transcript-zcode.test.ts b/src/main/native-chat/transcript-zcode.test.ts index 7eaeb99d876..9721bfee35c 100644 --- a/src/main/native-chat/transcript-zcode.test.ts +++ b/src/main/native-chat/transcript-zcode.test.ts @@ -13,7 +13,7 @@ import { readOpenCodeNativeChatTranscriptTail } from './transcript-opencode' import { subscribeOpenCodeNativeChatTranscript } from './transcript-opencode-subscribe' -import { handleOpenCodeSqliteRequest } from '../ai-vault/session-scanner-opencode-sqlite-dispatch' +import { handleOpenCodeSqliteRequest } from '../ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-dispatch' const cleanups: (() => void)[] = [] afterEach(() => { diff --git a/src/main/native-chat/wsl-transcript-fs-process-spawn.ts b/src/main/native-chat/wsl-transcript-fs-process-spawn.ts index 458e2670f32..ba604aa0287 100644 --- a/src/main/native-chat/wsl-transcript-fs-process-spawn.ts +++ b/src/main/native-chat/wsl-transcript-fs-process-spawn.ts @@ -1,7 +1,10 @@ import { fork, type ChildProcess } from 'node:child_process' import { existsSync } from 'node:fs' import { join } from 'node:path' -import { pickAllowedEnv, RUNTIME_ENV_ALLOWLIST } from '../ai-vault/session-scanner-service-env' +import { + pickAllowedEnv, + RUNTIME_ENV_ALLOWLIST +} from '../ai-vault/scan-service/session-scanner-service-env' const PROCESS_ENTRY_FILENAME = 'wsl-transcript-fs-process-entry.js' diff --git a/src/main/omp/omp-transcript-import.ts b/src/main/omp/omp-transcript-import.ts index 4e8dea868b2..e462093ca76 100644 --- a/src/main/omp/omp-transcript-import.ts +++ b/src/main/omp/omp-transcript-import.ts @@ -1,5 +1,5 @@ import { homedir } from 'node:os' -import { resolveOmpSessionsDir } from '../ai-vault/omp-session-root' +import { resolveOmpSessionsDir } from '../ai-vault/scanners/omp/omp-session-root' import { directoryTranscriptImport } from '../native-chat/structured-agent-cli-conversations' import { findOmpSessionByCwd } from './omp-session-cwd-lookup' diff --git a/src/main/opencode-usage/scanner-windows-data-directory.test.ts b/src/main/opencode-usage/scanner-windows-data-directory.test.ts index 59470f77ef3..3550591de88 100644 --- a/src/main/opencode-usage/scanner-windows-data-directory.test.ts +++ b/src/main/opencode-usage/scanner-windows-data-directory.test.ts @@ -2,20 +2,23 @@ import { mkdirSync, mkdtempSync, rmSync } from 'node:fs' import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' -import { opencodeDiscoveries } from '../ai-vault/session-scanner-opencode-sources' +import { opencodeDiscoveries } from '../ai-vault/scanners/opencode/session-scanner-opencode-sources' import Database from '../sqlite/sync-database' import { scanOpenCodeUsageDatabases } from './scanner' -vi.mock('../ai-vault/session-scanner-opencode-sqlite-worker-spawn', async () => { - const { listOpenCodeSqliteSessions } = - await import('../ai-vault/session-scanner-opencode-sqlite-list') - const { listOpenCode2SqliteSessions } = - await import('../ai-vault/session-scanner-opencode2-sqlite-list') - return { - listOpenCodeSqliteSessionsViaWorker: listOpenCodeSqliteSessions, - listOpenCode2SqliteSessionsViaWorker: listOpenCode2SqliteSessions +vi.mock( + '../ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-worker-spawn', + async () => { + const { listOpenCodeSqliteSessions } = + await import('../ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-list') + const { listOpenCode2SqliteSessions } = + await import('../ai-vault/scanners/opencode2/session-scanner-opencode2-sqlite-list') + return { + listOpenCodeSqliteSessionsViaWorker: listOpenCodeSqliteSessions, + listOpenCode2SqliteSessionsViaWorker: listOpenCode2SqliteSessions + } } -}) +) describe('OpenCode usage discovery on Windows', () => { const originalPlatform = Object.getOwnPropertyDescriptor(process, 'platform')! diff --git a/src/main/opencode/opencode-transcript-import.ts b/src/main/opencode/opencode-transcript-import.ts index 47867446b62..da3acd4be20 100644 --- a/src/main/opencode/opencode-transcript-import.ts +++ b/src/main/opencode/opencode-transcript-import.ts @@ -61,7 +61,7 @@ export const OPENCODE_TRANSCRIPT_IMPORT: StructuredAgentTranscriptImport = { throw error } const { readOpenCodeTranscriptSignalViaWorker } = - await import('../ai-vault/session-scanner-opencode-sqlite-worker-spawn') + await import('../ai-vault/scanners/opencode/reader-transport/session-scanner-opencode-sqlite-worker-spawn') const signal = await readOpenCodeTranscriptSignalViaWorker({ dbPath, sessionId: providerSessionId diff --git a/src/main/orcad/orcad-forked-child-paths.test.ts b/src/main/orcad/orcad-forked-child-paths.test.ts index cbc9bff0880..5cc1337ddb7 100644 --- a/src/main/orcad/orcad-forked-child-paths.test.ts +++ b/src/main/orcad/orcad-forked-child-paths.test.ts @@ -7,7 +7,7 @@ import { getWatcherProcessEntryPath } from '../ipc/filesystem/watcher-process/pa import { AI_VAULT_SERVICE_ENTRY_FILENAME, getAiVaultServiceEntryPath -} from '../ai-vault/session-scanner-service-entry-path' +} from '../ai-vault/scan-service/session-scanner-service-entry-path' import { FOREIGN_SQLITE_READER_ENTRY_FILENAME, resolveForeignSqliteReaderEntryPath diff --git a/src/main/orcad/orcad-session-scanner-idle.ts b/src/main/orcad/orcad-session-scanner-idle.ts index 75855b57d74..f7e83c9a354 100644 --- a/src/main/orcad/orcad-session-scanner-idle.ts +++ b/src/main/orcad/orcad-session-scanner-idle.ts @@ -14,7 +14,7 @@ export async function applyOrcadSessionScannerIdleTimeout(): Promise { const timeoutMs = orcadSessionScannerIdleTimeoutMs() if (timeoutMs !== null) { const { setAiVaultServiceIdleTimeoutMs } = - await import('../ai-vault/session-scanner-service-spawn') + await import('../ai-vault/scan-service/session-scanner-service-spawn') setAiVaultServiceIdleTimeoutMs(timeoutMs) } } diff --git a/src/main/qoder/real-cli.test.ts b/src/main/qoder/real-cli.test.ts index 97ebf7dd3b3..b6c07218ff0 100644 --- a/src/main/qoder/real-cli.test.ts +++ b/src/main/qoder/real-cli.test.ts @@ -16,7 +16,7 @@ import { join } from 'node:path' import { expect, it, vi } from 'vitest' import { runProcess } from '@orca/process-host' import { makePaneKey } from '../../shared/stable-pane-id' -import { parseQoderSessionFile } from '../ai-vault/session-scanner-qoder-parser' +import { parseQoderSessionFile } from '../ai-vault/scanners/qoder/session-scanner-qoder-parser' const sandbox = vi.hoisted(() => ({ home: '' })) vi.mock('node:os', async (importOriginal) => { diff --git a/src/main/runtime/agent-session/structured-agent-session-held-signal.test.ts b/src/main/runtime/agent-session/structured-agent-session-held-signal.test.ts index 450c26e2741..abdaf7fcca7 100644 --- a/src/main/runtime/agent-session/structured-agent-session-held-signal.test.ts +++ b/src/main/runtime/agent-session/structured-agent-session-held-signal.test.ts @@ -21,7 +21,7 @@ import { import { createStructuredAgentSessionLogger } from '../../native-chat/agent-session-wire/structured-agent-session-logger' import { openAgentSessionRecordStoreOnce } from './records/agent-session-record-store-slot' -vi.mock('../../ai-vault/session-scanner-service-spawn', async (importOriginal) => ({ +vi.mock('../../ai-vault/scan-service/session-scanner-service-spawn', async (importOriginal) => ({ ...(await importOriginal()), scanAiVaultSessionsInService: vi.fn(), resolveAiVaultSessionTitlesInService: vi.fn() diff --git a/src/main/runtime/rpc/methods/ai-vault.test.ts b/src/main/runtime/rpc/methods/ai-vault.test.ts index d704c56d598..56d9253ce33 100644 --- a/src/main/runtime/rpc/methods/ai-vault.test.ts +++ b/src/main/runtime/rpc/methods/ai-vault.test.ts @@ -5,7 +5,7 @@ import type { RpcRequest } from '../core' import { OrcaRuntimeService } from '../../orca-runtime' import { RuntimeAiVaultCommands } from '../../runtime-ai-vault-commands' import type { AiVaultListResult, AiVaultSession } from '../../../../shared/ai-vault-types' -import type { AiVaultServiceScanOptions } from '../../../ai-vault/session-scanner-service-protocol' +import type { AiVaultServiceScanOptions } from '../../../ai-vault/scan-service/session-scanner-service-protocol' import { AI_VAULT_SESSION_TITLES_RUNTIME_CAPABILITY, RUNTIME_CAPABILITIES @@ -19,7 +19,7 @@ const { scanAiVaultSessionsInService, resolveAiVaultSessionTitlesInService } = v resolveAiVaultSessionTitlesInService: vi.fn() })) -vi.mock('../../../ai-vault/session-scanner-service-spawn', async (importOriginal) => ({ +vi.mock('../../../ai-vault/scan-service/session-scanner-service-spawn', async (importOriginal) => ({ ...(await importOriginal()), scanAiVaultSessionsInService, resolveAiVaultSessionTitlesInService diff --git a/src/main/runtime/runtime-ai-vault-commands.ts b/src/main/runtime/runtime-ai-vault-commands.ts index c10bd636dd9..40fba4b9de5 100644 --- a/src/main/runtime/runtime-ai-vault-commands.ts +++ b/src/main/runtime/runtime-ai-vault-commands.ts @@ -13,7 +13,7 @@ import type { AiVaultDeleteSessionArgs, AiVaultDeleteSessionResult } from '../../shared/ai-vault-session-deletion' -import { resolveLocalAiVaultSessionTitles } from '../ai-vault/session-title-resolver' +import { resolveLocalAiVaultSessionTitles } from '../ai-vault/session-titles/session-title-resolver' export class RuntimeAiVaultCommands { constructor( diff --git a/src/main/startup/browser-process-user-agent-ordering.test.ts b/src/main/startup/browser-process-user-agent-ordering.test.ts index 6bb4707d2cb..03fc5ff1947 100644 --- a/src/main/startup/browser-process-user-agent-ordering.test.ts +++ b/src/main/startup/browser-process-user-agent-ordering.test.ts @@ -166,7 +166,7 @@ vi.mock('../persistence/profile-state/profile-state-access', () => ({ } })) vi.mock('../window/desktop-integration/macos-press-and-hold-default') -vi.mock('../ai-vault/session-parse-cache-persistence') +vi.mock('../ai-vault/parse-cache/session-parse-cache-persistence') vi.mock('../orca-profiles/profile-index-store', () => ({ initOrcaProfilePaths: vi.fn() })) vi.mock('../orca-profiles/profile-storage-paths', () => ({ getProfileUserDataPath: () => '/canonical-user-data' diff --git a/src/main/startup/main-process-preflight.ts b/src/main/startup/main-process-preflight.ts index 278addebb64..ff1c27a911b 100644 --- a/src/main/startup/main-process-preflight.ts +++ b/src/main/startup/main-process-preflight.ts @@ -74,7 +74,7 @@ import { desktopWorktreeWatcherRemoval } from '../ipc/filesystem/watchers/filesy import { setDefaultProxySessionResolver } from '../network/proxy-settings' import { initDataPath, getCanonicalUserDataPath } from '../persistence/loading-store/user-data-path' import { applyMacPressAndHoldDefaultAtStartup } from '../window/desktop-integration/macos-press-and-hold-default' -import { configureSessionParseCachePersistence } from '../ai-vault/session-parse-cache-persistence' +import { configureSessionParseCachePersistence } from '../ai-vault/parse-cache/session-parse-cache-persistence' import { initOrcaProfilePaths } from '../orca-profiles/profile-index-store' import { getProfileUserDataPath } from '../orca-profiles/profile-storage-paths' import { recoverPendingProfileProjectMoves } from '../orca-profiles/profile-project-move-intent' diff --git a/src/main/workspaces/removal/retirement/worktree-retirement-discovery.ts b/src/main/workspaces/removal/retirement/worktree-retirement-discovery.ts index a24b8b9d808..c51fe6e78ae 100644 --- a/src/main/workspaces/removal/retirement/worktree-retirement-discovery.ts +++ b/src/main/workspaces/removal/retirement/worktree-retirement-discovery.ts @@ -5,7 +5,7 @@ import { isWslUncPath, parseWslUncPath } from '../../../../shared/wsl-paths' import { encodeClaudeProjectPaths, isClaudeProjectDirInScope -} from '../../../ai-vault/claude-project-dir-encoding' +} from '../../../ai-vault/scanners/claude/claude-project-dir-encoding' import { wslGatedReaddir, wslGatedStat } from '../../../native-chat/wsl-transcript-fs-access' import type { RetirementScanResult } from './worktree-retirement-backfill-scan' import { normalizeRetirableGeneratedName } from './worktree-name-retirement' diff --git a/src/shared/wsl-move/wsl-move-storage-dispositions.ts b/src/shared/wsl-move/wsl-move-storage-dispositions.ts index 0c12464535b..30036d08efe 100644 --- a/src/shared/wsl-move/wsl-move-storage-dispositions.ts +++ b/src/shared/wsl-move/wsl-move-storage-dispositions.ts @@ -110,8 +110,8 @@ export const SQLITE_SCHEMA_FILE_DATABASES: Record = { 'src/main/ai-vault-search/session-search-query-schema.ts': 'ai-vault-search', 'src/main/ai-vault-search/session-search-schema.ts': 'ai-vault-search', 'src/main/ai-vault-search/session-search-write-buffer.ts': 'ai-vault-search-staging', - 'src/main/ai-vault/session-parse-cache-database.ts': 'ai-vault-parse-cache', - 'src/main/ai-vault/session-scope-cwds-table.ts': 'ai-vault-parse-cache', + 'src/main/ai-vault/parse-cache/session-parse-cache-database.ts': 'ai-vault-parse-cache', + 'src/main/ai-vault/parse-cache/session-scope-cwds-table.ts': 'ai-vault-parse-cache', 'src/main/browser/cookies/browser-cookie-staged-import.ts': 'browser-cookie-import', 'src/main/native-chat/agent-session-attachments/agent-session-attachment-claims.ts': 'agent-session-journal', @@ -133,7 +133,8 @@ export const SQLITE_SCHEMA_FILE_DATABASES: Record = { 'src/main/runtime/orchestration/db/reset/removed-orchestration-work-store.ts': 'orchestration', 'src/main/runtime/orchestration/mutation-receipt-capacity.ts': 'orchestration', // Test fixtures that mirror third-party agent and browser databases. - 'src/main/ai-vault/session-scanner-opencode-sqlite-fixture.ts': 'test-fixture', + 'src/main/ai-vault/scanners/opencode/sqlite/session-scanner-opencode-sqlite-fixture.ts': + 'test-fixture', 'src/main/ai-vault/session-scanner-test-fixtures.ts': 'test-fixture', 'src/main/browser/cookies/browser-cookie-import-test-database.ts': 'test-fixture', 'src/main/codex/codex-state-db-test-fixture.ts': 'test-fixture', diff --git a/tests/tools/omp-history-title-smoke.mjs b/tests/tools/omp-history-title-smoke.mjs index 7c5d84aaa2c..21c4a088347 100644 --- a/tests/tools/omp-history-title-smoke.mjs +++ b/tests/tools/omp-history-title-smoke.mjs @@ -32,10 +32,10 @@ const { SessionManager } = await import( source(process.argv[2], 'packages/coding-agent/src/session/session-manager.ts') ) const { parseMessageGraphSessionFile } = await import( - source(orcaRoot, 'src/main/ai-vault/session-scanner-graph-parsers.ts') + source(orcaRoot, 'src/main/ai-vault/scanners/session-scanner-graph-parsers.ts') ) const { createSessionParseStats, parseAgentSessionFileCached } = await import( - source(orcaRoot, 'src/main/ai-vault/session-scanner-parse-cache.ts') + source(orcaRoot, 'src/main/ai-vault/parse-cache/session-scanner-parse-cache.ts') ) const stats = createSessionParseStats() const manager = SessionManager.create(scratch, join(scratch, 'sessions')) diff --git a/tests/tools/omp-session-root-upstream-smoke.mjs b/tests/tools/omp-session-root-upstream-smoke.mjs index 3fa1079804c..d3d9f415903 100644 --- a/tests/tools/omp-session-root-upstream-smoke.mjs +++ b/tests/tools/omp-session-root-upstream-smoke.mjs @@ -4,7 +4,7 @@ import { mkdir, mkdtemp, rm } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join, resolve } from 'node:path' import { pathToFileURL } from 'node:url' -import { resolveOmpSessionsDir } from '../../src/main/ai-vault/omp-session-root.ts' +import { resolveOmpSessionsDir } from '../../src/main/ai-vault/scanners/omp/omp-session-root.ts' assert.ok(process.argv[2], 'Pass a read-only OMP checkout path') const root = await mkdtemp(join(tmpdir(), 'orca-omp-root-parity-'))