@herbertgao/pi-extensions 2026.9.6 → 2026.9.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -8
- package/THIRD_PARTY_NOTICES.md +0 -4
- package/node_modules/@narumitw/pi-btw/README.md +2 -0
- package/node_modules/@narumitw/pi-btw/dist/index.ts +284 -365
- package/node_modules/@narumitw/pi-btw/dist/index.ts.map +3 -3
- package/node_modules/@narumitw/pi-btw/package.json +52 -53
- package/node_modules/@narumitw/pi-btw/src/bring-to-main.ts +494 -547
- package/node_modules/@narumitw/pi-btw/src/btw.ts +814 -856
- package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +673 -674
- package/node_modules/@narumitw/pi-btw/src/keybindings.ts +228 -270
- package/node_modules/@narumitw/pi-btw/src/main-tree-picker.ts +309 -318
- package/node_modules/@narumitw/pi-btw/src/menu.ts +416 -454
- package/node_modules/@narumitw/pi-btw/src/settings.ts +203 -219
- package/node_modules/@narumitw/pi-btw/src/side-thread.ts +173 -201
- package/node_modules/@narumitw/pi-btw/src/text.ts +21 -23
- package/node_modules/@narumitw/pi-btw/src/transcript-markdown.ts +65 -0
- package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +611 -662
- package/node_modules/grok-mermaid/CHANGELOG.md +46 -0
- package/node_modules/grok-mermaid/LICENSE +205 -0
- package/node_modules/grok-mermaid/README.md +191 -0
- package/node_modules/grok-mermaid/dist/ansi.d.ts +16 -0
- package/node_modules/grok-mermaid/dist/ansi.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/ansi.js +23 -0
- package/node_modules/grok-mermaid/dist/ansi.js.map +1 -0
- package/node_modules/grok-mermaid/dist/canvas.d.ts +87 -0
- package/node_modules/grok-mermaid/dist/canvas.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/canvas.js +366 -0
- package/node_modules/grok-mermaid/dist/canvas.js.map +1 -0
- package/node_modules/grok-mermaid/dist/graph.d.ts +74 -0
- package/node_modules/grok-mermaid/dist/graph.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/graph.js +91 -0
- package/node_modules/grok-mermaid/dist/graph.js.map +1 -0
- package/node_modules/grok-mermaid/dist/index.d.ts +32 -0
- package/node_modules/grok-mermaid/dist/index.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/index.js +100 -0
- package/node_modules/grok-mermaid/dist/index.js.map +1 -0
- package/node_modules/grok-mermaid/dist/labels.d.ts +62 -0
- package/node_modules/grok-mermaid/dist/labels.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/labels.js +324 -0
- package/node_modules/grok-mermaid/dist/labels.js.map +1 -0
- package/node_modules/grok-mermaid/dist/layout-seq.d.ts +12 -0
- package/node_modules/grok-mermaid/dist/layout-seq.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/layout-seq.js +194 -0
- package/node_modules/grok-mermaid/dist/layout-seq.js.map +1 -0
- package/node_modules/grok-mermaid/dist/layout.d.ts +87 -0
- package/node_modules/grok-mermaid/dist/layout.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/layout.js +881 -0
- package/node_modules/grok-mermaid/dist/layout.js.map +1 -0
- package/node_modules/grok-mermaid/dist/parse.d.ts +83 -0
- package/node_modules/grok-mermaid/dist/parse.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/parse.js +1151 -0
- package/node_modules/grok-mermaid/dist/parse.js.map +1 -0
- package/node_modules/grok-mermaid/dist/source-box.d.ts +18 -0
- package/node_modules/grok-mermaid/dist/source-box.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/source-box.js +78 -0
- package/node_modules/grok-mermaid/dist/source-box.js.map +1 -0
- package/node_modules/grok-mermaid/dist/types.d.ts +42 -0
- package/node_modules/grok-mermaid/dist/types.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/types.js +1 -0
- package/node_modules/grok-mermaid/dist/types.js.map +1 -0
- package/node_modules/grok-mermaid/dist/width-data.d.ts +2 -0
- package/node_modules/grok-mermaid/dist/width-data.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/width-data.js +994 -0
- package/node_modules/grok-mermaid/dist/width-data.js.map +1 -0
- package/node_modules/grok-mermaid/dist/width.d.ts +18 -0
- package/node_modules/grok-mermaid/dist/width.d.ts.map +1 -0
- package/node_modules/grok-mermaid/dist/width.js +76 -0
- package/node_modules/grok-mermaid/dist/width.js.map +1 -0
- package/node_modules/grok-mermaid/package.json +49 -0
- package/node_modules/grok-mermaid/src/ansi.ts +34 -0
- package/node_modules/grok-mermaid/src/canvas.ts +373 -0
- package/node_modules/grok-mermaid/src/graph.ts +142 -0
- package/node_modules/grok-mermaid/src/index.ts +104 -0
- package/node_modules/grok-mermaid/src/labels.ts +326 -0
- package/node_modules/grok-mermaid/src/layout-seq.ts +203 -0
- package/node_modules/grok-mermaid/src/layout.ts +1015 -0
- package/node_modules/grok-mermaid/src/parse.ts +1189 -0
- package/node_modules/grok-mermaid/src/source-box.ts +89 -0
- package/node_modules/grok-mermaid/src/types.ts +43 -0
- package/node_modules/grok-mermaid/src/width-data.ts +993 -0
- package/node_modules/grok-mermaid/src/width.ts +74 -0
- package/node_modules/pi-lens/CHANGELOG.md +239 -0
- package/node_modules/pi-lens/config/dependency-cruiser-eager-allowlist.json +3 -0
- package/node_modules/pi-lens/dist/clients/actionable-warnings.js +30 -4
- package/node_modules/pi-lens/dist/clients/agent-behavior-client.js +2 -0
- package/node_modules/pi-lens/dist/clients/bash-file-access.js +26 -0
- package/node_modules/pi-lens/dist/clients/biome-client.js +1 -1
- package/node_modules/pi-lens/dist/clients/blocker-freshness.js +403 -35
- package/node_modules/pi-lens/dist/clients/bootstrap.js +6 -1
- package/node_modules/pi-lens/dist/clients/cascade-format.js +200 -4
- package/node_modules/pi-lens/dist/clients/code-quality-warnings.js +10 -2
- package/node_modules/pi-lens/dist/clients/degradation-ledger.js +16 -1
- package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +12 -1
- package/node_modules/pi-lens/dist/clients/dispatch/ast-grep-catalog.js +65 -0
- package/node_modules/pi-lens/dist/clients/dispatch/auxiliary-lsp.js +28 -0
- package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +9 -2
- package/node_modules/pi-lens/dist/clients/dispatch/finding-policy.js +222 -0
- package/node_modules/pi-lens/dist/clients/dispatch/indent-detect.js +389 -13
- package/node_modules/pi-lens/dist/clients/dispatch/integration.js +175 -25
- package/node_modules/pi-lens/dist/clients/dispatch/rule-ignores.js +62 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +21 -41
- package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +6 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +7 -7
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shfmt.js +2 -12
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tree-sitter.js +2 -21
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/types.js +4 -1
- package/node_modules/pi-lens/dist/clients/disposition-publish.js +1 -0
- package/node_modules/pi-lens/dist/clients/effective-config.js +1 -1
- package/node_modules/pi-lens/dist/clients/file-kinds.js +26 -1
- package/node_modules/pi-lens/dist/clients/file-role.js +21 -21
- package/node_modules/pi-lens/dist/clients/file-utils.js +156 -10
- package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +56 -9
- package/node_modules/pi-lens/dist/clients/format-service.js +39 -21
- package/node_modules/pi-lens/dist/clients/formatters.js +60 -13
- package/node_modules/pi-lens/dist/clients/generation-guard.js +2 -2
- package/node_modules/pi-lens/dist/clients/git-guard.js +11 -3
- package/node_modules/pi-lens/dist/clients/indent-retarget.js +78 -8
- package/node_modules/pi-lens/dist/clients/installer/index.js +333 -114
- package/node_modules/pi-lens/dist/clients/instance-reaper-state.js +7 -0
- package/node_modules/pi-lens/dist/clients/instance-reaper.js +20 -10
- package/node_modules/pi-lens/dist/clients/language-profile.js +23 -1
- package/node_modules/pi-lens/dist/clients/language-registry.js +5 -1
- package/node_modules/pi-lens/dist/clients/latency-logger.js +4 -1
- package/node_modules/pi-lens/dist/clients/lens-engine.js +12 -3
- package/node_modules/pi-lens/dist/clients/lens-events.js +2 -1
- package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +79 -0
- package/node_modules/pi-lens/dist/clients/live-bus-emitter.js +2 -1
- package/node_modules/pi-lens/dist/clients/lsp/client.js +25 -21
- package/node_modules/pi-lens/dist/clients/lsp/config.js +2 -2
- package/node_modules/pi-lens/dist/clients/lsp/index.js +7 -0
- package/node_modules/pi-lens/dist/clients/lsp/launch.js +16 -4
- package/node_modules/pi-lens/dist/clients/lsp/server.js +19 -2
- package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +2 -1
- package/node_modules/pi-lens/dist/clients/lsp-mutation.js +5 -3
- package/node_modules/pi-lens/dist/clients/map-with-concurrency.js +12 -8
- package/node_modules/pi-lens/dist/clients/mcp/session.js +36 -4
- package/node_modules/pi-lens/dist/clients/ndjson-logger.js +24 -7
- package/node_modules/pi-lens/dist/clients/observed-mutation.js +40 -2
- package/node_modules/pi-lens/dist/clients/opaque-mutation-scan.js +23 -3
- package/node_modules/pi-lens/dist/clients/opengrep-client.js +110 -15
- package/node_modules/pi-lens/dist/clients/path-utils.js +123 -3
- package/node_modules/pi-lens/dist/clients/performance-report.js +5 -1
- package/node_modules/pi-lens/dist/clients/php-cs-fixer-config.js +1 -1
- package/node_modules/pi-lens/dist/clients/pipeline.js +74 -5
- package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +37 -5
- package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +145 -18
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/dead-code.js +4 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +59 -3
- package/node_modules/pi-lens/dist/clients/project-lens-config.js +45 -2
- package/node_modules/pi-lens/dist/clients/read-guard.js +70 -11
- package/node_modules/pi-lens/dist/clients/resource-sampler.js +147 -9
- package/node_modules/pi-lens/dist/clients/ruff-client.js +1 -1
- package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +33 -5
- package/node_modules/pi-lens/dist/clients/runtime-context.js +6 -2
- package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +77 -7
- package/node_modules/pi-lens/dist/clients/runtime-session.js +21 -2
- package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +43 -12
- package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +330 -85
- package/node_modules/pi-lens/dist/clients/runtime-turn.js +147 -17
- package/node_modules/pi-lens/dist/clients/safe-spawn.js +258 -5
- package/node_modules/pi-lens/dist/clients/scratch-tree-policy.js +6 -0
- package/node_modules/pi-lens/dist/clients/session-event-guard.js +50 -5
- package/node_modules/pi-lens/dist/clients/sg-runner.js +23 -11
- package/node_modules/pi-lens/dist/clients/sgconfig.js +79 -2
- package/node_modules/pi-lens/dist/clients/test-runner-client.js +6 -41
- package/node_modules/pi-lens/dist/clients/test-runner-delivery.js +43 -0
- package/node_modules/pi-lens/dist/clients/tool-agreement.js +423 -0
- package/node_modules/pi-lens/dist/clients/tool-config.js +50 -0
- package/node_modules/pi-lens/dist/clients/tool-cwd.js +47 -76
- package/node_modules/pi-lens/dist/clients/tool-policy.js +163 -7
- package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +120 -0
- package/node_modules/pi-lens/dist/clients/tree-sitter-query-loader.js +127 -189
- package/node_modules/pi-lens/dist/clients/widget-state.js +98 -0
- package/node_modules/pi-lens/dist/clients/word-index.js +5 -2
- package/node_modules/pi-lens/dist/clients/write-ordering-guard.js +7 -0
- package/node_modules/pi-lens/dist/index.js +27416 -24153
- package/node_modules/pi-lens/dist/mcp/server.js +5 -2
- package/node_modules/pi-lens/dist/tools/lens-diagnostic-mark.js +7 -1
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +168 -53
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +244 -72
- package/node_modules/pi-lens/docs/audit1.md +5 -5
- package/node_modules/pi-lens/docs/dependencies.md +11 -0
- package/node_modules/pi-lens/docs/dispositions.md +52 -0
- package/node_modules/pi-lens/docs/environment-variables.md +2 -2
- package/node_modules/pi-lens/docs/features.md +4 -4
- package/node_modules/pi-lens/docs/globalconfig.md +3 -1
- package/node_modules/pi-lens/docs/language-coverage.md +1 -0
- package/node_modules/pi-lens/docs/pi-lens-fixer.md +53 -94
- package/node_modules/pi-lens/docs/pi-lens-investigator.md +43 -38
- package/node_modules/pi-lens/docs/pi-lens-retro.md +97 -0
- package/node_modules/pi-lens/docs/pi-lens-reviewer.md +53 -66
- package/node_modules/pi-lens/docs/release-qa-baseline.md +22 -0
- package/node_modules/pi-lens/docs/settings.md +7 -4
- package/node_modules/pi-lens/docs/tree-sitter_rules_catalog.md +1 -1
- package/node_modules/pi-lens/docs/usage.md +2 -0
- package/node_modules/pi-lens/package.json +1 -1
- package/node_modules/pi-lens/rules/tree-sitter-queries/typescript/sql-injection.yml +24 -12
- package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +40 -0
- package/node_modules/pi-lens/skills/pi-lens-ast-grep/SKILL.md +15 -0
- package/node_modules/pi-lens/skills/pi-lens-lsp-navigation/SKILL.md +7 -0
- package/package.json +6 -11
- package/node_modules/@luxusai/pi-hindsight/CHANGELOG.md +0 -376
- package/node_modules/@luxusai/pi-hindsight/README.md +0 -92
- package/node_modules/@luxusai/pi-hindsight/docs/adr/001-memory-lifecycle-and-scope.md +0 -56
- package/node_modules/@luxusai/pi-hindsight/docs/adr/002-explicit-routing-strategy-seam.md +0 -169
- package/node_modules/@luxusai/pi-hindsight/docs/adr/003-tui-memory-mode-vocabulary.md +0 -107
- package/node_modules/@luxusai/pi-hindsight/docs/adr/004-lifeos-dual-bank-design.md +0 -89
- package/node_modules/@luxusai/pi-hindsight/docs/adr/005-domain-banks-and-agent-first-surface.md +0 -189
- package/node_modules/@luxusai/pi-hindsight/docs/assets/logos/pi-hindsight-logo-dark.webp +0 -0
- package/node_modules/@luxusai/pi-hindsight/docs/assets/logos/pi-hindsight-logo-dark@2x.webp +0 -0
- package/node_modules/@luxusai/pi-hindsight/docs/coding-memory-evaluation.md +0 -54
- package/node_modules/@luxusai/pi-hindsight/docs/compatibility.md +0 -75
- package/node_modules/@luxusai/pi-hindsight/docs/hindsight-core-functions.md +0 -300
- package/node_modules/@luxusai/pi-hindsight/docs/mission-and-mental-model-quality.md +0 -158
- package/node_modules/@luxusai/pi-hindsight/docs/next-opt-out-design.md +0 -164
- package/node_modules/@luxusai/pi-hindsight/docs/risky-memory-modes.md +0 -139
- package/node_modules/@luxusai/pi-hindsight/docs/starter-mental-model-suggestions.md +0 -74
- package/node_modules/@luxusai/pi-hindsight/docs/surface-reference.md +0 -261
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-operations.ts +0 -151
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-selection.ts +0 -18
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-settings-presenter.ts +0 -46
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-templates.ts +0 -383
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/banking.ts +0 -240
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/knowledge-page-seed.ts +0 -176
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/retain-strategies.ts +0 -178
- package/node_modules/@luxusai/pi-hindsight/extensions/client/client-retry.ts +0 -41
- package/node_modules/@luxusai/pi-hindsight/extensions/client/client.ts +0 -386
- package/node_modules/@luxusai/pi-hindsight/extensions/client/fetch-compat.ts +0 -39
- package/node_modules/@luxusai/pi-hindsight/extensions/client/timeout.ts +0 -34
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config-defaults.ts +0 -140
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config-editing-model.ts +0 -61
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config-editing-registry.ts +0 -925
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config-field-paths.ts +0 -247
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config-normalize.ts +0 -547
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config-writer.ts +0 -480
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config.ts +0 -182
- package/node_modules/@luxusai/pi-hindsight/extensions/config/setup-gate.ts +0 -86
- package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-execute.ts +0 -1010
- package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-parse.ts +0 -175
- package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-plan.ts +0 -425
- package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-presentation.ts +0 -210
- package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-sessions.ts +0 -817
- package/node_modules/@luxusai/pi-hindsight/extensions/index.ts +0 -25
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/git-seed.ts +0 -319
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle-recall.ts +0 -196
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle-retain.ts +0 -189
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle-runtime.ts +0 -65
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle.ts +0 -260
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/mental-models.ts +0 -244
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/observation-scopes.ts +0 -59
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/recall-cleanup.ts +0 -82
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/recall-visibility.ts +0 -45
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/recall.ts +0 -331
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain-cursor.ts +0 -354
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain-job-builder.ts +0 -66
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain-receipts.ts +0 -132
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain.ts +0 -228
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-bank-template-operations.ts +0 -74
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-config-operations.ts +0 -16
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-control-operations.ts +0 -648
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-diagnostics-operations.ts +0 -105
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-identity.ts +0 -68
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-operation-service.ts +0 -71
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-operation-types.ts +0 -13
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-recall-operations.ts +0 -162
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-retain-operations.ts +0 -131
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-scope.ts +0 -104
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-session-operations.ts +0 -37
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/operation-catalog.ts +0 -893
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/reflect-presenter.ts +0 -35
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/scope-migrate.ts +0 -177
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/tools.ts +0 -7
- package/node_modules/@luxusai/pi-hindsight/extensions/queue/flush-presenter.ts +0 -21
- package/node_modules/@luxusai/pi-hindsight/extensions/queue/jsonl-queue-store.ts +0 -112
- package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue-delivery.ts +0 -111
- package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue-lock.ts +0 -214
- package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue-operations.ts +0 -70
- package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue.ts +0 -392
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/bank-template-presentation.ts +0 -45
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/commands.ts +0 -9
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/guided-setup.ts +0 -860
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/prefill-input.ts +0 -105
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-flow.ts +0 -189
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-server-probe.ts +0 -299
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-actions.ts +0 -201
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-facts.ts +0 -47
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-render.ts +0 -239
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-types.ts +0 -50
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui.ts +0 -259
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/tool-presenters.ts +0 -77
- package/node_modules/@luxusai/pi-hindsight/extensions/types.ts +0 -534
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/diagnostics.ts +0 -319
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/messages.ts +0 -325
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/sanitize.ts +0 -42
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/session-memory-meta.ts +0 -244
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/session-operations.ts +0 -56
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/session.ts +0 -50
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/status-fields.ts +0 -167
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/status-health.ts +0 -207
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/status.ts +0 -120
- package/node_modules/@luxusai/pi-hindsight/extensions/version.ts +0 -8
- package/node_modules/@luxusai/pi-hindsight/package.json +0 -118
- package/node_modules/@luxusai/pi-hindsight/skills/hindsight-memory-doctor/SKILL.md +0 -75
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
import type { ResolvedConfig } from "../types.js";
|
|
2
|
-
|
|
3
|
-
interface JsonlEntry {
|
|
4
|
-
type?: string;
|
|
5
|
-
id?: string;
|
|
6
|
-
parentId?: string | null;
|
|
7
|
-
timestamp?: string;
|
|
8
|
-
cwd?: string;
|
|
9
|
-
parentSession?: unknown;
|
|
10
|
-
message?: unknown;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export interface ParsedMessage {
|
|
14
|
-
id?: string;
|
|
15
|
-
parentId: string | null;
|
|
16
|
-
timestamp?: string;
|
|
17
|
-
data: Record<string, unknown>;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export interface ParsedSession {
|
|
21
|
-
cwd?: string;
|
|
22
|
-
sessionId?: string;
|
|
23
|
-
parentSessionId?: string;
|
|
24
|
-
parentSessionFile?: string;
|
|
25
|
-
sessionTimestamp?: string;
|
|
26
|
-
malformedLineCount: number;
|
|
27
|
-
messages: ParsedMessage[];
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
31
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function stringField(record: Record<string, unknown>, keys: string[]): string | undefined {
|
|
35
|
-
for (const key of keys) {
|
|
36
|
-
const value = record[key];
|
|
37
|
-
if (typeof value === "string" && value.trim()) return value;
|
|
38
|
-
}
|
|
39
|
-
return undefined;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function parentSessionInfo(value: unknown): { id?: string; file?: string } {
|
|
43
|
-
if (typeof value === "string" && value.trim()) return { file: value };
|
|
44
|
-
if (!isRecord(value)) return {};
|
|
45
|
-
const id = stringField(value, ["id", "sessionId"]);
|
|
46
|
-
const file = stringField(value, ["file", "path", "sessionFile"]);
|
|
47
|
-
return { ...(id ? { id } : {}), ...(file ? { file } : {}) };
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export function parseImportSessionJsonl(text: string): ParsedSession {
|
|
51
|
-
const messages: ParsedMessage[] = [];
|
|
52
|
-
let cwd: string | undefined;
|
|
53
|
-
let sessionId: string | undefined;
|
|
54
|
-
let parentSessionId: string | undefined;
|
|
55
|
-
let parentSessionFile: string | undefined;
|
|
56
|
-
let sessionTimestamp: string | undefined;
|
|
57
|
-
let malformedLineCount = 0;
|
|
58
|
-
for (const line of text.split("\n")) {
|
|
59
|
-
if (!line.trim()) continue;
|
|
60
|
-
let entry: JsonlEntry;
|
|
61
|
-
try {
|
|
62
|
-
const parsed = JSON.parse(line) as unknown;
|
|
63
|
-
if (!isRecord(parsed)) {
|
|
64
|
-
malformedLineCount += 1;
|
|
65
|
-
continue;
|
|
66
|
-
}
|
|
67
|
-
entry = parsed as JsonlEntry;
|
|
68
|
-
} catch {
|
|
69
|
-
malformedLineCount += 1;
|
|
70
|
-
continue;
|
|
71
|
-
}
|
|
72
|
-
if (entry.type === "session") {
|
|
73
|
-
if (typeof entry.cwd === "string") cwd = entry.cwd;
|
|
74
|
-
if (typeof entry.id === "string") sessionId = entry.id;
|
|
75
|
-
const parent = parentSessionInfo(entry.parentSession);
|
|
76
|
-
if (parent.id) parentSessionId = parent.id;
|
|
77
|
-
if (parent.file) parentSessionFile = parent.file;
|
|
78
|
-
if (typeof entry.timestamp === "string") sessionTimestamp = entry.timestamp;
|
|
79
|
-
}
|
|
80
|
-
if (entry.type !== "message" || !isRecord(entry.message)) continue;
|
|
81
|
-
messages.push({
|
|
82
|
-
...(typeof entry.id === "string" ? { id: entry.id } : {}),
|
|
83
|
-
parentId: entry.parentId ?? null,
|
|
84
|
-
...(typeof entry.timestamp === "string" ? { timestamp: entry.timestamp } : {}),
|
|
85
|
-
data: {
|
|
86
|
-
...entry.message,
|
|
87
|
-
...(typeof entry.id === "string" ? { id: entry.id } : {}),
|
|
88
|
-
parentId: entry.parentId ?? null,
|
|
89
|
-
...(typeof entry.timestamp === "string" ? { timestamp: entry.timestamp } : {}),
|
|
90
|
-
},
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
return {
|
|
94
|
-
...(cwd ? { cwd } : {}),
|
|
95
|
-
...(sessionId ? { sessionId } : {}),
|
|
96
|
-
...(parentSessionId ? { parentSessionId } : {}),
|
|
97
|
-
...(parentSessionFile ? { parentSessionFile } : {}),
|
|
98
|
-
...(sessionTimestamp ? { sessionTimestamp } : {}),
|
|
99
|
-
malformedLineCount,
|
|
100
|
-
messages,
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
export function parsePiSessionJsonl(text: string): {
|
|
105
|
-
cwd?: string;
|
|
106
|
-
malformedLineCount: number;
|
|
107
|
-
messages: Record<string, unknown>[];
|
|
108
|
-
} {
|
|
109
|
-
const parsed = parseImportSessionJsonl(text);
|
|
110
|
-
return {
|
|
111
|
-
...(parsed.cwd ? { cwd: parsed.cwd } : {}),
|
|
112
|
-
malformedLineCount: parsed.malformedLineCount,
|
|
113
|
-
messages: parsed.messages.map((message) => message.data),
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
export interface ImportBranch {
|
|
118
|
-
leafId: string;
|
|
119
|
-
messages: ParsedMessage[];
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
function fallbackLeafId(messages: ParsedMessage[]): string {
|
|
123
|
-
const last = messages.at(-1);
|
|
124
|
-
if (last?.id) return last.id;
|
|
125
|
-
return "root";
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
export function leafIds(messages: ParsedMessage[]): string[] {
|
|
129
|
-
const ids = new Set(
|
|
130
|
-
messages.map((message) => message.id).filter((id): id is string => typeof id === "string"),
|
|
131
|
-
);
|
|
132
|
-
const parents = new Set(
|
|
133
|
-
messages
|
|
134
|
-
.map((message) => message.parentId)
|
|
135
|
-
.filter((id): id is string => typeof id === "string"),
|
|
136
|
-
);
|
|
137
|
-
const leaves = [...ids].filter((id) => !parents.has(id));
|
|
138
|
-
return leaves.length ? leaves : [fallbackLeafId(messages)];
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
function messagesForLeaf(messages: ParsedMessage[], leafId: string): ParsedMessage[] {
|
|
142
|
-
const byId = new Map(
|
|
143
|
-
messages
|
|
144
|
-
.map((message) => [message.id, message])
|
|
145
|
-
.filter((entry): entry is [string, ParsedMessage] => typeof entry[0] === "string"),
|
|
146
|
-
);
|
|
147
|
-
const path: ParsedMessage[] = [];
|
|
148
|
-
const seen = new Set<string>();
|
|
149
|
-
let current: string | null | undefined = leafId;
|
|
150
|
-
|
|
151
|
-
while (current) {
|
|
152
|
-
if (seen.has(current)) break;
|
|
153
|
-
seen.add(current);
|
|
154
|
-
const message = byId.get(current);
|
|
155
|
-
if (!message) break;
|
|
156
|
-
path.push(message);
|
|
157
|
-
current = message.parentId;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
if (!path.length && messages.length === 1) return messages;
|
|
161
|
-
return path.reverse();
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
export function selectImportBranches(
|
|
165
|
-
parsed: ParsedSession,
|
|
166
|
-
includeBranches: ResolvedConfig["import"]["includeBranches"],
|
|
167
|
-
): ImportBranch[] {
|
|
168
|
-
const leaves = leafIds(parsed.messages);
|
|
169
|
-
const selectedLeaves =
|
|
170
|
-
includeBranches === "all-leaves" ? leaves : [fallbackLeafId(parsed.messages)];
|
|
171
|
-
return selectedLeaves.map((leafId) => ({
|
|
172
|
-
leafId,
|
|
173
|
-
messages: messagesForLeaf(parsed.messages, leafId),
|
|
174
|
-
}));
|
|
175
|
-
}
|
|
@@ -1,425 +0,0 @@
|
|
|
1
|
-
import type { ImportMode, ImportQualityProfile, ResolvedConfig, UpdateMode } from "../types.js";
|
|
2
|
-
import { createHash } from "node:crypto";
|
|
3
|
-
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
4
|
-
import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
|
|
5
|
-
import { stableSessionId } from "../utils/session.js";
|
|
6
|
-
import {
|
|
7
|
-
type ImportBranch,
|
|
8
|
-
leafIds,
|
|
9
|
-
type ParsedSession,
|
|
10
|
-
selectImportBranches,
|
|
11
|
-
} from "./import-parse.js";
|
|
12
|
-
|
|
13
|
-
type ImportToolResults = ResolvedConfig["import"]["toolResults"];
|
|
14
|
-
|
|
15
|
-
export type ImportDocumentStatus = "pending" | "queued" | "completed" | "failed" | "skipped";
|
|
16
|
-
|
|
17
|
-
export interface ImportCheckpointDocument {
|
|
18
|
-
documentId: string;
|
|
19
|
-
leafId: string;
|
|
20
|
-
contentHash: string;
|
|
21
|
-
messageCount: number;
|
|
22
|
-
importMode?: ImportMode;
|
|
23
|
-
toolResults?: ImportToolResults;
|
|
24
|
-
importQualityProfile?: ImportQualityProfile;
|
|
25
|
-
projectionVersion?: string;
|
|
26
|
-
importProfile?: string;
|
|
27
|
-
chunkIndex?: number;
|
|
28
|
-
messageRange?: { start: number; end: number };
|
|
29
|
-
status: ImportDocumentStatus;
|
|
30
|
-
skipReason?: "already-imported" | "empty-curated-projection";
|
|
31
|
-
updatedAt: string;
|
|
32
|
-
error?: string;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export interface ImportCheckpoint {
|
|
36
|
-
version: 1;
|
|
37
|
-
runId: string;
|
|
38
|
-
sourceFile: string;
|
|
39
|
-
bankId: string;
|
|
40
|
-
sessionId: string;
|
|
41
|
-
cwd: string;
|
|
42
|
-
includeBranches: "current-only" | "all-leaves";
|
|
43
|
-
importMode?: ImportMode;
|
|
44
|
-
toolResults?: ImportToolResults;
|
|
45
|
-
importQualityProfile?: ImportQualityProfile;
|
|
46
|
-
importProfile?: string;
|
|
47
|
-
updateMode: UpdateMode;
|
|
48
|
-
startedAt: string;
|
|
49
|
-
updatedAt: string;
|
|
50
|
-
documents: Record<string, ImportCheckpointDocument>;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export interface ImportCheckpointReadResult {
|
|
54
|
-
checkpoint?: ImportCheckpoint;
|
|
55
|
-
error: string | null;
|
|
56
|
-
action: string | null;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export function resolveImportCheckpointPath(cwd: string, checkpointPath: string): string {
|
|
60
|
-
return isAbsolute(checkpointPath) ? checkpointPath : join(cwd, checkpointPath);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export function importRunId(args: {
|
|
64
|
-
sourceFile: string;
|
|
65
|
-
bankId: string;
|
|
66
|
-
sessionId: string;
|
|
67
|
-
includeBranches: "current-only" | "all-leaves";
|
|
68
|
-
importMode?: ImportMode;
|
|
69
|
-
updateMode: UpdateMode;
|
|
70
|
-
}): string {
|
|
71
|
-
return [
|
|
72
|
-
"pi-import",
|
|
73
|
-
args.bankId,
|
|
74
|
-
args.sessionId,
|
|
75
|
-
args.includeBranches,
|
|
76
|
-
args.importMode ?? "legacy",
|
|
77
|
-
args.updateMode,
|
|
78
|
-
args.sourceFile,
|
|
79
|
-
]
|
|
80
|
-
.join(":")
|
|
81
|
-
.replace(/\s+/g, "_");
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
function isPlainRecord(value: unknown): value is Record<string, unknown> {
|
|
85
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
function isImportMode(value: unknown): value is ImportMode {
|
|
89
|
-
return value === "curated" || value === "raw" || value === "forensic";
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
function isImportToolResults(value: unknown): value is ImportToolResults {
|
|
93
|
-
return value === "errors-only" || value === "summary" || value === "content";
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
function isImportQualityProfile(value: unknown): value is ImportQualityProfile {
|
|
97
|
-
return value === "compatible" || value === "strict";
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
function isUpdateMode(value: unknown): value is UpdateMode {
|
|
101
|
-
return value === "append" || value === "replace";
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
function isSkipReason(value: unknown): value is ImportCheckpointDocument["skipReason"] {
|
|
105
|
-
return value === "already-imported" || value === "empty-curated-projection";
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
function isMessageRange(value: unknown): value is { start: number; end: number } {
|
|
109
|
-
return isPlainRecord(value) && typeof value.start === "number" && typeof value.end === "number";
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
function hasValidCheckpointRunFields(value: Record<string, unknown>): boolean {
|
|
113
|
-
return (
|
|
114
|
-
(value.includeBranches === undefined ||
|
|
115
|
-
value.includeBranches === "current-only" ||
|
|
116
|
-
value.includeBranches === "all-leaves") &&
|
|
117
|
-
(value.importMode === undefined || isImportMode(value.importMode)) &&
|
|
118
|
-
(value.toolResults === undefined || isImportToolResults(value.toolResults)) &&
|
|
119
|
-
(value.importQualityProfile === undefined ||
|
|
120
|
-
isImportQualityProfile(value.importQualityProfile)) &&
|
|
121
|
-
(value.updateMode === undefined || isUpdateMode(value.updateMode))
|
|
122
|
-
);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
function isImportCheckpointDocument(value: unknown): value is ImportCheckpointDocument {
|
|
126
|
-
if (!isPlainRecord(value)) return false;
|
|
127
|
-
return (
|
|
128
|
-
typeof value.documentId === "string" &&
|
|
129
|
-
typeof value.leafId === "string" &&
|
|
130
|
-
typeof value.contentHash === "string" &&
|
|
131
|
-
typeof value.messageCount === "number" &&
|
|
132
|
-
(value.importMode === undefined || isImportMode(value.importMode)) &&
|
|
133
|
-
(value.toolResults === undefined || isImportToolResults(value.toolResults)) &&
|
|
134
|
-
(value.importQualityProfile === undefined ||
|
|
135
|
-
isImportQualityProfile(value.importQualityProfile)) &&
|
|
136
|
-
(value.projectionVersion === undefined || typeof value.projectionVersion === "string") &&
|
|
137
|
-
(value.importProfile === undefined || typeof value.importProfile === "string") &&
|
|
138
|
-
(value.chunkIndex === undefined || typeof value.chunkIndex === "number") &&
|
|
139
|
-
(value.messageRange === undefined || isMessageRange(value.messageRange)) &&
|
|
140
|
-
(value.status === "pending" ||
|
|
141
|
-
value.status === "queued" ||
|
|
142
|
-
value.status === "completed" ||
|
|
143
|
-
value.status === "failed" ||
|
|
144
|
-
value.status === "skipped") &&
|
|
145
|
-
(value.skipReason === undefined || isSkipReason(value.skipReason)) &&
|
|
146
|
-
typeof value.updatedAt === "string" &&
|
|
147
|
-
(value.error === undefined || typeof value.error === "string")
|
|
148
|
-
);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
export async function readImportCheckpoint(path: string): Promise<ImportCheckpoint | undefined> {
|
|
152
|
-
try {
|
|
153
|
-
const parsed = JSON.parse(await readFile(path, "utf8")) as unknown;
|
|
154
|
-
if (!isPlainRecord(parsed)) throw new Error("import checkpoint must be a JSON object");
|
|
155
|
-
if (!hasValidCheckpointRunFields(parsed)) {
|
|
156
|
-
throw new Error("import checkpoint run fields are invalid");
|
|
157
|
-
}
|
|
158
|
-
const record = parsed as unknown as ImportCheckpoint;
|
|
159
|
-
if (record.documents !== undefined && !isPlainRecord(record.documents)) {
|
|
160
|
-
throw new Error("import checkpoint documents must be a JSON object");
|
|
161
|
-
}
|
|
162
|
-
const documents = record.documents ?? {};
|
|
163
|
-
for (const [documentId, document] of Object.entries(documents)) {
|
|
164
|
-
if (!isImportCheckpointDocument(document) || document.documentId !== documentId) {
|
|
165
|
-
throw new Error(`import checkpoint document ${documentId} is invalid`);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
return { ...record, version: 1, documents };
|
|
169
|
-
} catch (error) {
|
|
170
|
-
if ((error as NodeJS.ErrnoException).code === "ENOENT") return undefined;
|
|
171
|
-
throw error;
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
export async function readImportCheckpointSafe(path: string): Promise<ImportCheckpointReadResult> {
|
|
176
|
-
try {
|
|
177
|
-
const checkpoint = await readImportCheckpoint(path);
|
|
178
|
-
return { ...(checkpoint ? { checkpoint } : {}), error: null, action: null };
|
|
179
|
-
} catch (error) {
|
|
180
|
-
return {
|
|
181
|
-
error: error instanceof Error ? error.message : String(error),
|
|
182
|
-
action: `Move or repair ${path}, then open /hindsight and press i to re-run import. The next successful import can recreate the checkpoint.`,
|
|
183
|
-
};
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
export async function writeImportCheckpoint(
|
|
188
|
-
path: string,
|
|
189
|
-
checkpoint: ImportCheckpoint,
|
|
190
|
-
): Promise<void> {
|
|
191
|
-
await mkdir(dirname(path), { recursive: true });
|
|
192
|
-
const tmp = `${path}.tmp`;
|
|
193
|
-
await writeFile(tmp, `${JSON.stringify(checkpoint, null, 2)}\n`, "utf8");
|
|
194
|
-
await rename(tmp, path);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
export function createImportCheckpoint(args: {
|
|
198
|
-
runId: string;
|
|
199
|
-
sourceFile: string;
|
|
200
|
-
bankId: string;
|
|
201
|
-
sessionId: string;
|
|
202
|
-
cwd: string;
|
|
203
|
-
includeBranches: "current-only" | "all-leaves";
|
|
204
|
-
importMode?: ImportMode;
|
|
205
|
-
toolResults?: ImportToolResults;
|
|
206
|
-
importQualityProfile?: ImportQualityProfile;
|
|
207
|
-
updateMode: UpdateMode;
|
|
208
|
-
now: string;
|
|
209
|
-
}): ImportCheckpoint {
|
|
210
|
-
return {
|
|
211
|
-
version: 1,
|
|
212
|
-
runId: args.runId,
|
|
213
|
-
sourceFile: args.sourceFile,
|
|
214
|
-
bankId: args.bankId,
|
|
215
|
-
sessionId: args.sessionId,
|
|
216
|
-
cwd: args.cwd,
|
|
217
|
-
includeBranches: args.includeBranches,
|
|
218
|
-
...(args.importMode ? { importMode: args.importMode } : {}),
|
|
219
|
-
...(args.toolResults ? { toolResults: args.toolResults } : {}),
|
|
220
|
-
...(args.importQualityProfile ? { importQualityProfile: args.importQualityProfile } : {}),
|
|
221
|
-
updateMode: args.updateMode,
|
|
222
|
-
startedAt: args.now,
|
|
223
|
-
updatedAt: args.now,
|
|
224
|
-
documents: {},
|
|
225
|
-
};
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
export interface ImportManifestEntry {
|
|
229
|
-
documentId: string;
|
|
230
|
-
bankId: string;
|
|
231
|
-
sourceFile: string;
|
|
232
|
-
importedAt: string;
|
|
233
|
-
contentHash: string;
|
|
234
|
-
messageCount: number;
|
|
235
|
-
leafId: string;
|
|
236
|
-
sessionId: string;
|
|
237
|
-
cwd: string;
|
|
238
|
-
includeBranches: "current-only" | "all-leaves";
|
|
239
|
-
importMode?: ImportMode;
|
|
240
|
-
toolResults?: "errors-only" | "summary" | "content";
|
|
241
|
-
importQualityProfile?: ImportQualityProfile;
|
|
242
|
-
projectionVersion?: string;
|
|
243
|
-
importProfile?: string;
|
|
244
|
-
chunkIndex?: number;
|
|
245
|
-
messageRange?: { start: number; end: number };
|
|
246
|
-
updateMode: UpdateMode;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
export interface ImportManifest {
|
|
250
|
-
version: 1;
|
|
251
|
-
imports: Record<string, ImportManifestEntry>;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
export interface ImportManifestReadResult {
|
|
255
|
-
manifest: ImportManifest;
|
|
256
|
-
error: string | null;
|
|
257
|
-
action: string | null;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
export function resolveImportManifestPath(cwd: string, manifestPath: string): string {
|
|
261
|
-
return isAbsolute(manifestPath) ? manifestPath : join(cwd, manifestPath);
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
export function hashImportContent(content: string): string {
|
|
265
|
-
return createHash("sha256").update(content).digest("hex");
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
function isImportManifestEntry(value: unknown): value is ImportManifestEntry {
|
|
269
|
-
if (!isPlainRecord(value)) return false;
|
|
270
|
-
return (
|
|
271
|
-
typeof value.documentId === "string" &&
|
|
272
|
-
typeof value.bankId === "string" &&
|
|
273
|
-
typeof value.sourceFile === "string" &&
|
|
274
|
-
typeof value.importedAt === "string" &&
|
|
275
|
-
typeof value.contentHash === "string" &&
|
|
276
|
-
typeof value.messageCount === "number" &&
|
|
277
|
-
typeof value.leafId === "string" &&
|
|
278
|
-
typeof value.sessionId === "string" &&
|
|
279
|
-
typeof value.cwd === "string" &&
|
|
280
|
-
(value.includeBranches === "current-only" || value.includeBranches === "all-leaves") &&
|
|
281
|
-
(value.importMode === undefined ||
|
|
282
|
-
value.importMode === "curated" ||
|
|
283
|
-
value.importMode === "raw" ||
|
|
284
|
-
value.importMode === "forensic") &&
|
|
285
|
-
(value.toolResults === undefined ||
|
|
286
|
-
value.toolResults === "errors-only" ||
|
|
287
|
-
value.toolResults === "summary" ||
|
|
288
|
-
value.toolResults === "content") &&
|
|
289
|
-
(value.importQualityProfile === undefined ||
|
|
290
|
-
value.importQualityProfile === "compatible" ||
|
|
291
|
-
value.importQualityProfile === "strict") &&
|
|
292
|
-
(value.updateMode === "append" || value.updateMode === "replace")
|
|
293
|
-
);
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
export async function readImportManifest(path: string): Promise<ImportManifest> {
|
|
297
|
-
try {
|
|
298
|
-
const parsed = JSON.parse(await readFile(path, "utf8")) as unknown;
|
|
299
|
-
if (!isPlainRecord(parsed)) throw new Error("manifest must be a JSON object");
|
|
300
|
-
const record = parsed as Partial<ImportManifest>;
|
|
301
|
-
if (record.imports !== undefined && !isPlainRecord(record.imports)) {
|
|
302
|
-
throw new Error("manifest imports must be a JSON object");
|
|
303
|
-
}
|
|
304
|
-
const imports = record.imports ?? {};
|
|
305
|
-
for (const [documentId, entry] of Object.entries(imports)) {
|
|
306
|
-
if (!isImportManifestEntry(entry) || entry.documentId !== documentId) {
|
|
307
|
-
throw new Error(`manifest import entry ${documentId} is invalid`);
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
return { version: 1, imports };
|
|
311
|
-
} catch (error) {
|
|
312
|
-
if ((error as NodeJS.ErrnoException).code === "ENOENT") return { version: 1, imports: {} };
|
|
313
|
-
throw error;
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
export async function readImportManifestSafe(path: string): Promise<ImportManifestReadResult> {
|
|
318
|
-
try {
|
|
319
|
-
return { manifest: await readImportManifest(path), error: null, action: null };
|
|
320
|
-
} catch (error) {
|
|
321
|
-
return {
|
|
322
|
-
manifest: { version: 1, imports: {} },
|
|
323
|
-
error: error instanceof Error ? error.message : String(error),
|
|
324
|
-
action: `Move or repair ${path}, then open /hindsight and press i to re-run import. New successful imports will recreate the manifest.`,
|
|
325
|
-
};
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
export async function writeImportManifest(path: string, manifest: ImportManifest): Promise<void> {
|
|
330
|
-
await mkdir(dirname(path), { recursive: true });
|
|
331
|
-
const tmp = `${path}.tmp`;
|
|
332
|
-
await writeFile(tmp, `${JSON.stringify(manifest, null, 2)}\n`, "utf8");
|
|
333
|
-
await rename(tmp, path);
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
export async function upsertImportManifestEntries(
|
|
337
|
-
path: string,
|
|
338
|
-
entries: ImportManifestEntry[],
|
|
339
|
-
): Promise<ImportManifest> {
|
|
340
|
-
const manifest = (await readImportManifestSafe(path)).manifest;
|
|
341
|
-
for (const entry of entries) manifest.imports[entry.documentId] = entry;
|
|
342
|
-
await writeImportManifest(path, manifest);
|
|
343
|
-
return manifest;
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
export function importManifestSummary(manifest: ImportManifest): {
|
|
347
|
-
count: number;
|
|
348
|
-
latest?: ImportManifestEntry;
|
|
349
|
-
} {
|
|
350
|
-
const entries = Object.values(manifest.imports).sort((a, b) =>
|
|
351
|
-
b.importedAt.localeCompare(a.importedAt),
|
|
352
|
-
);
|
|
353
|
-
return { count: entries.length, ...(entries[0] ? { latest: entries[0] } : {}) };
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
export interface ImportPlan {
|
|
357
|
-
sessionFile: string;
|
|
358
|
-
bankId: string;
|
|
359
|
-
cwd: string;
|
|
360
|
-
sessionId: string;
|
|
361
|
-
leaves: string[];
|
|
362
|
-
includeBranches: ResolvedConfig["import"]["includeBranches"];
|
|
363
|
-
branches: ImportBranch[];
|
|
364
|
-
manifestPath: string;
|
|
365
|
-
checkpointPath: string;
|
|
366
|
-
updateMode: "append" | "replace";
|
|
367
|
-
runId: string;
|
|
368
|
-
importConfig: ResolvedConfig;
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
function sameCwd(left: string | undefined, right: string | undefined): boolean {
|
|
372
|
-
if (!left || !right) return false;
|
|
373
|
-
return resolve(left) === resolve(right);
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
export function buildImportPlan(args: {
|
|
377
|
-
sessionFile: string;
|
|
378
|
-
parsed: ParsedSession;
|
|
379
|
-
bankId: string;
|
|
380
|
-
config: ResolvedConfig;
|
|
381
|
-
cwd?: string;
|
|
382
|
-
requireMatchingCwd?: boolean;
|
|
383
|
-
includeBranches?: ResolvedConfig["import"]["includeBranches"];
|
|
384
|
-
}): ImportPlan {
|
|
385
|
-
if (args.cwd && args.requireMatchingCwd && !args.parsed.cwd) {
|
|
386
|
-
throw new Error(
|
|
387
|
-
`Refusing to import session without cwd; current cwd is ${args.cwd}. Use explicit file import for unscoped sessions.`,
|
|
388
|
-
);
|
|
389
|
-
}
|
|
390
|
-
if (args.cwd && args.parsed.cwd && !sameCwd(args.parsed.cwd, args.cwd)) {
|
|
391
|
-
throw new Error(
|
|
392
|
-
`Refusing to import session from cwd ${args.parsed.cwd}; current cwd is ${args.cwd}. Use project-scoped import from the matching repo.`,
|
|
393
|
-
);
|
|
394
|
-
}
|
|
395
|
-
const cwd = resolve(args.cwd ?? args.parsed.cwd ?? dirname(args.sessionFile));
|
|
396
|
-
const sessionId = args.parsed.sessionId ?? stableSessionId(args.sessionFile, cwd);
|
|
397
|
-
const leaves = leafIds(args.parsed.messages);
|
|
398
|
-
const includeBranches = args.includeBranches ?? args.config.import.includeBranches;
|
|
399
|
-
const branches = selectImportBranches(args.parsed, includeBranches);
|
|
400
|
-
const manifestPath = resolveImportManifestPath(cwd, args.config.import.manifestPath);
|
|
401
|
-
const checkpointPath = resolveImportCheckpointPath(cwd, args.config.import.checkpointPath);
|
|
402
|
-
const updateMode = args.config.import.replaceExistingImportedDocs ? "replace" : "append";
|
|
403
|
-
const runId = importRunId({
|
|
404
|
-
sourceFile: args.sessionFile,
|
|
405
|
-
bankId: args.bankId,
|
|
406
|
-
sessionId,
|
|
407
|
-
includeBranches,
|
|
408
|
-
importMode: args.config.import.mode,
|
|
409
|
-
updateMode,
|
|
410
|
-
});
|
|
411
|
-
return {
|
|
412
|
-
sessionFile: args.sessionFile,
|
|
413
|
-
bankId: args.bankId,
|
|
414
|
-
cwd,
|
|
415
|
-
sessionId,
|
|
416
|
-
leaves,
|
|
417
|
-
includeBranches,
|
|
418
|
-
branches,
|
|
419
|
-
manifestPath,
|
|
420
|
-
checkpointPath,
|
|
421
|
-
updateMode,
|
|
422
|
-
runId,
|
|
423
|
-
importConfig: { ...args.config, import: { ...args.config.import, includeBranches } },
|
|
424
|
-
};
|
|
425
|
-
}
|