@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.
Files changed (304) hide show
  1. package/README.md +3 -8
  2. package/THIRD_PARTY_NOTICES.md +0 -4
  3. package/node_modules/@narumitw/pi-btw/README.md +2 -0
  4. package/node_modules/@narumitw/pi-btw/dist/index.ts +284 -365
  5. package/node_modules/@narumitw/pi-btw/dist/index.ts.map +3 -3
  6. package/node_modules/@narumitw/pi-btw/package.json +52 -53
  7. package/node_modules/@narumitw/pi-btw/src/bring-to-main.ts +494 -547
  8. package/node_modules/@narumitw/pi-btw/src/btw.ts +814 -856
  9. package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +673 -674
  10. package/node_modules/@narumitw/pi-btw/src/keybindings.ts +228 -270
  11. package/node_modules/@narumitw/pi-btw/src/main-tree-picker.ts +309 -318
  12. package/node_modules/@narumitw/pi-btw/src/menu.ts +416 -454
  13. package/node_modules/@narumitw/pi-btw/src/settings.ts +203 -219
  14. package/node_modules/@narumitw/pi-btw/src/side-thread.ts +173 -201
  15. package/node_modules/@narumitw/pi-btw/src/text.ts +21 -23
  16. package/node_modules/@narumitw/pi-btw/src/transcript-markdown.ts +65 -0
  17. package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +611 -662
  18. package/node_modules/grok-mermaid/CHANGELOG.md +46 -0
  19. package/node_modules/grok-mermaid/LICENSE +205 -0
  20. package/node_modules/grok-mermaid/README.md +191 -0
  21. package/node_modules/grok-mermaid/dist/ansi.d.ts +16 -0
  22. package/node_modules/grok-mermaid/dist/ansi.d.ts.map +1 -0
  23. package/node_modules/grok-mermaid/dist/ansi.js +23 -0
  24. package/node_modules/grok-mermaid/dist/ansi.js.map +1 -0
  25. package/node_modules/grok-mermaid/dist/canvas.d.ts +87 -0
  26. package/node_modules/grok-mermaid/dist/canvas.d.ts.map +1 -0
  27. package/node_modules/grok-mermaid/dist/canvas.js +366 -0
  28. package/node_modules/grok-mermaid/dist/canvas.js.map +1 -0
  29. package/node_modules/grok-mermaid/dist/graph.d.ts +74 -0
  30. package/node_modules/grok-mermaid/dist/graph.d.ts.map +1 -0
  31. package/node_modules/grok-mermaid/dist/graph.js +91 -0
  32. package/node_modules/grok-mermaid/dist/graph.js.map +1 -0
  33. package/node_modules/grok-mermaid/dist/index.d.ts +32 -0
  34. package/node_modules/grok-mermaid/dist/index.d.ts.map +1 -0
  35. package/node_modules/grok-mermaid/dist/index.js +100 -0
  36. package/node_modules/grok-mermaid/dist/index.js.map +1 -0
  37. package/node_modules/grok-mermaid/dist/labels.d.ts +62 -0
  38. package/node_modules/grok-mermaid/dist/labels.d.ts.map +1 -0
  39. package/node_modules/grok-mermaid/dist/labels.js +324 -0
  40. package/node_modules/grok-mermaid/dist/labels.js.map +1 -0
  41. package/node_modules/grok-mermaid/dist/layout-seq.d.ts +12 -0
  42. package/node_modules/grok-mermaid/dist/layout-seq.d.ts.map +1 -0
  43. package/node_modules/grok-mermaid/dist/layout-seq.js +194 -0
  44. package/node_modules/grok-mermaid/dist/layout-seq.js.map +1 -0
  45. package/node_modules/grok-mermaid/dist/layout.d.ts +87 -0
  46. package/node_modules/grok-mermaid/dist/layout.d.ts.map +1 -0
  47. package/node_modules/grok-mermaid/dist/layout.js +881 -0
  48. package/node_modules/grok-mermaid/dist/layout.js.map +1 -0
  49. package/node_modules/grok-mermaid/dist/parse.d.ts +83 -0
  50. package/node_modules/grok-mermaid/dist/parse.d.ts.map +1 -0
  51. package/node_modules/grok-mermaid/dist/parse.js +1151 -0
  52. package/node_modules/grok-mermaid/dist/parse.js.map +1 -0
  53. package/node_modules/grok-mermaid/dist/source-box.d.ts +18 -0
  54. package/node_modules/grok-mermaid/dist/source-box.d.ts.map +1 -0
  55. package/node_modules/grok-mermaid/dist/source-box.js +78 -0
  56. package/node_modules/grok-mermaid/dist/source-box.js.map +1 -0
  57. package/node_modules/grok-mermaid/dist/types.d.ts +42 -0
  58. package/node_modules/grok-mermaid/dist/types.d.ts.map +1 -0
  59. package/node_modules/grok-mermaid/dist/types.js +1 -0
  60. package/node_modules/grok-mermaid/dist/types.js.map +1 -0
  61. package/node_modules/grok-mermaid/dist/width-data.d.ts +2 -0
  62. package/node_modules/grok-mermaid/dist/width-data.d.ts.map +1 -0
  63. package/node_modules/grok-mermaid/dist/width-data.js +994 -0
  64. package/node_modules/grok-mermaid/dist/width-data.js.map +1 -0
  65. package/node_modules/grok-mermaid/dist/width.d.ts +18 -0
  66. package/node_modules/grok-mermaid/dist/width.d.ts.map +1 -0
  67. package/node_modules/grok-mermaid/dist/width.js +76 -0
  68. package/node_modules/grok-mermaid/dist/width.js.map +1 -0
  69. package/node_modules/grok-mermaid/package.json +49 -0
  70. package/node_modules/grok-mermaid/src/ansi.ts +34 -0
  71. package/node_modules/grok-mermaid/src/canvas.ts +373 -0
  72. package/node_modules/grok-mermaid/src/graph.ts +142 -0
  73. package/node_modules/grok-mermaid/src/index.ts +104 -0
  74. package/node_modules/grok-mermaid/src/labels.ts +326 -0
  75. package/node_modules/grok-mermaid/src/layout-seq.ts +203 -0
  76. package/node_modules/grok-mermaid/src/layout.ts +1015 -0
  77. package/node_modules/grok-mermaid/src/parse.ts +1189 -0
  78. package/node_modules/grok-mermaid/src/source-box.ts +89 -0
  79. package/node_modules/grok-mermaid/src/types.ts +43 -0
  80. package/node_modules/grok-mermaid/src/width-data.ts +993 -0
  81. package/node_modules/grok-mermaid/src/width.ts +74 -0
  82. package/node_modules/pi-lens/CHANGELOG.md +239 -0
  83. package/node_modules/pi-lens/config/dependency-cruiser-eager-allowlist.json +3 -0
  84. package/node_modules/pi-lens/dist/clients/actionable-warnings.js +30 -4
  85. package/node_modules/pi-lens/dist/clients/agent-behavior-client.js +2 -0
  86. package/node_modules/pi-lens/dist/clients/bash-file-access.js +26 -0
  87. package/node_modules/pi-lens/dist/clients/biome-client.js +1 -1
  88. package/node_modules/pi-lens/dist/clients/blocker-freshness.js +403 -35
  89. package/node_modules/pi-lens/dist/clients/bootstrap.js +6 -1
  90. package/node_modules/pi-lens/dist/clients/cascade-format.js +200 -4
  91. package/node_modules/pi-lens/dist/clients/code-quality-warnings.js +10 -2
  92. package/node_modules/pi-lens/dist/clients/degradation-ledger.js +16 -1
  93. package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +12 -1
  94. package/node_modules/pi-lens/dist/clients/dispatch/ast-grep-catalog.js +65 -0
  95. package/node_modules/pi-lens/dist/clients/dispatch/auxiliary-lsp.js +28 -0
  96. package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +9 -2
  97. package/node_modules/pi-lens/dist/clients/dispatch/finding-policy.js +222 -0
  98. package/node_modules/pi-lens/dist/clients/dispatch/indent-detect.js +389 -13
  99. package/node_modules/pi-lens/dist/clients/dispatch/integration.js +175 -25
  100. package/node_modules/pi-lens/dist/clients/dispatch/rule-ignores.js +62 -0
  101. package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +21 -41
  102. package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +6 -1
  103. package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +7 -7
  104. package/node_modules/pi-lens/dist/clients/dispatch/runners/shfmt.js +2 -12
  105. package/node_modules/pi-lens/dist/clients/dispatch/runners/tree-sitter.js +2 -21
  106. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +1 -1
  107. package/node_modules/pi-lens/dist/clients/dispatch/types.js +4 -1
  108. package/node_modules/pi-lens/dist/clients/disposition-publish.js +1 -0
  109. package/node_modules/pi-lens/dist/clients/effective-config.js +1 -1
  110. package/node_modules/pi-lens/dist/clients/file-kinds.js +26 -1
  111. package/node_modules/pi-lens/dist/clients/file-role.js +21 -21
  112. package/node_modules/pi-lens/dist/clients/file-utils.js +156 -10
  113. package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +56 -9
  114. package/node_modules/pi-lens/dist/clients/format-service.js +39 -21
  115. package/node_modules/pi-lens/dist/clients/formatters.js +60 -13
  116. package/node_modules/pi-lens/dist/clients/generation-guard.js +2 -2
  117. package/node_modules/pi-lens/dist/clients/git-guard.js +11 -3
  118. package/node_modules/pi-lens/dist/clients/indent-retarget.js +78 -8
  119. package/node_modules/pi-lens/dist/clients/installer/index.js +333 -114
  120. package/node_modules/pi-lens/dist/clients/instance-reaper-state.js +7 -0
  121. package/node_modules/pi-lens/dist/clients/instance-reaper.js +20 -10
  122. package/node_modules/pi-lens/dist/clients/language-profile.js +23 -1
  123. package/node_modules/pi-lens/dist/clients/language-registry.js +5 -1
  124. package/node_modules/pi-lens/dist/clients/latency-logger.js +4 -1
  125. package/node_modules/pi-lens/dist/clients/lens-engine.js +12 -3
  126. package/node_modules/pi-lens/dist/clients/lens-events.js +2 -1
  127. package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +79 -0
  128. package/node_modules/pi-lens/dist/clients/live-bus-emitter.js +2 -1
  129. package/node_modules/pi-lens/dist/clients/lsp/client.js +25 -21
  130. package/node_modules/pi-lens/dist/clients/lsp/config.js +2 -2
  131. package/node_modules/pi-lens/dist/clients/lsp/index.js +7 -0
  132. package/node_modules/pi-lens/dist/clients/lsp/launch.js +16 -4
  133. package/node_modules/pi-lens/dist/clients/lsp/server.js +19 -2
  134. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +2 -1
  135. package/node_modules/pi-lens/dist/clients/lsp-mutation.js +5 -3
  136. package/node_modules/pi-lens/dist/clients/map-with-concurrency.js +12 -8
  137. package/node_modules/pi-lens/dist/clients/mcp/session.js +36 -4
  138. package/node_modules/pi-lens/dist/clients/ndjson-logger.js +24 -7
  139. package/node_modules/pi-lens/dist/clients/observed-mutation.js +40 -2
  140. package/node_modules/pi-lens/dist/clients/opaque-mutation-scan.js +23 -3
  141. package/node_modules/pi-lens/dist/clients/opengrep-client.js +110 -15
  142. package/node_modules/pi-lens/dist/clients/path-utils.js +123 -3
  143. package/node_modules/pi-lens/dist/clients/performance-report.js +5 -1
  144. package/node_modules/pi-lens/dist/clients/php-cs-fixer-config.js +1 -1
  145. package/node_modules/pi-lens/dist/clients/pipeline.js +74 -5
  146. package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +37 -5
  147. package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +145 -18
  148. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/dead-code.js +4 -1
  149. package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +59 -3
  150. package/node_modules/pi-lens/dist/clients/project-lens-config.js +45 -2
  151. package/node_modules/pi-lens/dist/clients/read-guard.js +70 -11
  152. package/node_modules/pi-lens/dist/clients/resource-sampler.js +147 -9
  153. package/node_modules/pi-lens/dist/clients/ruff-client.js +1 -1
  154. package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +33 -5
  155. package/node_modules/pi-lens/dist/clients/runtime-context.js +6 -2
  156. package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +77 -7
  157. package/node_modules/pi-lens/dist/clients/runtime-session.js +21 -2
  158. package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +43 -12
  159. package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +330 -85
  160. package/node_modules/pi-lens/dist/clients/runtime-turn.js +147 -17
  161. package/node_modules/pi-lens/dist/clients/safe-spawn.js +258 -5
  162. package/node_modules/pi-lens/dist/clients/scratch-tree-policy.js +6 -0
  163. package/node_modules/pi-lens/dist/clients/session-event-guard.js +50 -5
  164. package/node_modules/pi-lens/dist/clients/sg-runner.js +23 -11
  165. package/node_modules/pi-lens/dist/clients/sgconfig.js +79 -2
  166. package/node_modules/pi-lens/dist/clients/test-runner-client.js +6 -41
  167. package/node_modules/pi-lens/dist/clients/test-runner-delivery.js +43 -0
  168. package/node_modules/pi-lens/dist/clients/tool-agreement.js +423 -0
  169. package/node_modules/pi-lens/dist/clients/tool-config.js +50 -0
  170. package/node_modules/pi-lens/dist/clients/tool-cwd.js +47 -76
  171. package/node_modules/pi-lens/dist/clients/tool-policy.js +163 -7
  172. package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +120 -0
  173. package/node_modules/pi-lens/dist/clients/tree-sitter-query-loader.js +127 -189
  174. package/node_modules/pi-lens/dist/clients/widget-state.js +98 -0
  175. package/node_modules/pi-lens/dist/clients/word-index.js +5 -2
  176. package/node_modules/pi-lens/dist/clients/write-ordering-guard.js +7 -0
  177. package/node_modules/pi-lens/dist/index.js +27416 -24153
  178. package/node_modules/pi-lens/dist/mcp/server.js +5 -2
  179. package/node_modules/pi-lens/dist/tools/lens-diagnostic-mark.js +7 -1
  180. package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +168 -53
  181. package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +244 -72
  182. package/node_modules/pi-lens/docs/audit1.md +5 -5
  183. package/node_modules/pi-lens/docs/dependencies.md +11 -0
  184. package/node_modules/pi-lens/docs/dispositions.md +52 -0
  185. package/node_modules/pi-lens/docs/environment-variables.md +2 -2
  186. package/node_modules/pi-lens/docs/features.md +4 -4
  187. package/node_modules/pi-lens/docs/globalconfig.md +3 -1
  188. package/node_modules/pi-lens/docs/language-coverage.md +1 -0
  189. package/node_modules/pi-lens/docs/pi-lens-fixer.md +53 -94
  190. package/node_modules/pi-lens/docs/pi-lens-investigator.md +43 -38
  191. package/node_modules/pi-lens/docs/pi-lens-retro.md +97 -0
  192. package/node_modules/pi-lens/docs/pi-lens-reviewer.md +53 -66
  193. package/node_modules/pi-lens/docs/release-qa-baseline.md +22 -0
  194. package/node_modules/pi-lens/docs/settings.md +7 -4
  195. package/node_modules/pi-lens/docs/tree-sitter_rules_catalog.md +1 -1
  196. package/node_modules/pi-lens/docs/usage.md +2 -0
  197. package/node_modules/pi-lens/package.json +1 -1
  198. package/node_modules/pi-lens/rules/tree-sitter-queries/typescript/sql-injection.yml +24 -12
  199. package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +40 -0
  200. package/node_modules/pi-lens/skills/pi-lens-ast-grep/SKILL.md +15 -0
  201. package/node_modules/pi-lens/skills/pi-lens-lsp-navigation/SKILL.md +7 -0
  202. package/package.json +6 -11
  203. package/node_modules/@luxusai/pi-hindsight/CHANGELOG.md +0 -376
  204. package/node_modules/@luxusai/pi-hindsight/README.md +0 -92
  205. package/node_modules/@luxusai/pi-hindsight/docs/adr/001-memory-lifecycle-and-scope.md +0 -56
  206. package/node_modules/@luxusai/pi-hindsight/docs/adr/002-explicit-routing-strategy-seam.md +0 -169
  207. package/node_modules/@luxusai/pi-hindsight/docs/adr/003-tui-memory-mode-vocabulary.md +0 -107
  208. package/node_modules/@luxusai/pi-hindsight/docs/adr/004-lifeos-dual-bank-design.md +0 -89
  209. package/node_modules/@luxusai/pi-hindsight/docs/adr/005-domain-banks-and-agent-first-surface.md +0 -189
  210. package/node_modules/@luxusai/pi-hindsight/docs/assets/logos/pi-hindsight-logo-dark.webp +0 -0
  211. package/node_modules/@luxusai/pi-hindsight/docs/assets/logos/pi-hindsight-logo-dark@2x.webp +0 -0
  212. package/node_modules/@luxusai/pi-hindsight/docs/coding-memory-evaluation.md +0 -54
  213. package/node_modules/@luxusai/pi-hindsight/docs/compatibility.md +0 -75
  214. package/node_modules/@luxusai/pi-hindsight/docs/hindsight-core-functions.md +0 -300
  215. package/node_modules/@luxusai/pi-hindsight/docs/mission-and-mental-model-quality.md +0 -158
  216. package/node_modules/@luxusai/pi-hindsight/docs/next-opt-out-design.md +0 -164
  217. package/node_modules/@luxusai/pi-hindsight/docs/risky-memory-modes.md +0 -139
  218. package/node_modules/@luxusai/pi-hindsight/docs/starter-mental-model-suggestions.md +0 -74
  219. package/node_modules/@luxusai/pi-hindsight/docs/surface-reference.md +0 -261
  220. package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-operations.ts +0 -151
  221. package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-selection.ts +0 -18
  222. package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-settings-presenter.ts +0 -46
  223. package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-templates.ts +0 -383
  224. package/node_modules/@luxusai/pi-hindsight/extensions/banks/banking.ts +0 -240
  225. package/node_modules/@luxusai/pi-hindsight/extensions/banks/knowledge-page-seed.ts +0 -176
  226. package/node_modules/@luxusai/pi-hindsight/extensions/banks/retain-strategies.ts +0 -178
  227. package/node_modules/@luxusai/pi-hindsight/extensions/client/client-retry.ts +0 -41
  228. package/node_modules/@luxusai/pi-hindsight/extensions/client/client.ts +0 -386
  229. package/node_modules/@luxusai/pi-hindsight/extensions/client/fetch-compat.ts +0 -39
  230. package/node_modules/@luxusai/pi-hindsight/extensions/client/timeout.ts +0 -34
  231. package/node_modules/@luxusai/pi-hindsight/extensions/config/config-defaults.ts +0 -140
  232. package/node_modules/@luxusai/pi-hindsight/extensions/config/config-editing-model.ts +0 -61
  233. package/node_modules/@luxusai/pi-hindsight/extensions/config/config-editing-registry.ts +0 -925
  234. package/node_modules/@luxusai/pi-hindsight/extensions/config/config-field-paths.ts +0 -247
  235. package/node_modules/@luxusai/pi-hindsight/extensions/config/config-normalize.ts +0 -547
  236. package/node_modules/@luxusai/pi-hindsight/extensions/config/config-writer.ts +0 -480
  237. package/node_modules/@luxusai/pi-hindsight/extensions/config/config.ts +0 -182
  238. package/node_modules/@luxusai/pi-hindsight/extensions/config/setup-gate.ts +0 -86
  239. package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-execute.ts +0 -1010
  240. package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-parse.ts +0 -175
  241. package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-plan.ts +0 -425
  242. package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-presentation.ts +0 -210
  243. package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-sessions.ts +0 -817
  244. package/node_modules/@luxusai/pi-hindsight/extensions/index.ts +0 -25
  245. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/git-seed.ts +0 -319
  246. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle-recall.ts +0 -196
  247. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle-retain.ts +0 -189
  248. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle-runtime.ts +0 -65
  249. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle.ts +0 -260
  250. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/mental-models.ts +0 -244
  251. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/observation-scopes.ts +0 -59
  252. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/recall-cleanup.ts +0 -82
  253. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/recall-visibility.ts +0 -45
  254. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/recall.ts +0 -331
  255. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain-cursor.ts +0 -354
  256. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain-job-builder.ts +0 -66
  257. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain-receipts.ts +0 -132
  258. package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain.ts +0 -228
  259. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-bank-template-operations.ts +0 -74
  260. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-config-operations.ts +0 -16
  261. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-control-operations.ts +0 -648
  262. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-diagnostics-operations.ts +0 -105
  263. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-identity.ts +0 -68
  264. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-operation-service.ts +0 -71
  265. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-operation-types.ts +0 -13
  266. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-recall-operations.ts +0 -162
  267. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-retain-operations.ts +0 -131
  268. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-scope.ts +0 -104
  269. package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-session-operations.ts +0 -37
  270. package/node_modules/@luxusai/pi-hindsight/extensions/operations/operation-catalog.ts +0 -893
  271. package/node_modules/@luxusai/pi-hindsight/extensions/operations/reflect-presenter.ts +0 -35
  272. package/node_modules/@luxusai/pi-hindsight/extensions/operations/scope-migrate.ts +0 -177
  273. package/node_modules/@luxusai/pi-hindsight/extensions/operations/tools.ts +0 -7
  274. package/node_modules/@luxusai/pi-hindsight/extensions/queue/flush-presenter.ts +0 -21
  275. package/node_modules/@luxusai/pi-hindsight/extensions/queue/jsonl-queue-store.ts +0 -112
  276. package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue-delivery.ts +0 -111
  277. package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue-lock.ts +0 -214
  278. package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue-operations.ts +0 -70
  279. package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue.ts +0 -392
  280. package/node_modules/@luxusai/pi-hindsight/extensions/tui/bank-template-presentation.ts +0 -45
  281. package/node_modules/@luxusai/pi-hindsight/extensions/tui/commands.ts +0 -9
  282. package/node_modules/@luxusai/pi-hindsight/extensions/tui/guided-setup.ts +0 -860
  283. package/node_modules/@luxusai/pi-hindsight/extensions/tui/prefill-input.ts +0 -105
  284. package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-flow.ts +0 -189
  285. package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-server-probe.ts +0 -299
  286. package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-actions.ts +0 -201
  287. package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-facts.ts +0 -47
  288. package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-render.ts +0 -239
  289. package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-types.ts +0 -50
  290. package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui.ts +0 -259
  291. package/node_modules/@luxusai/pi-hindsight/extensions/tui/tool-presenters.ts +0 -77
  292. package/node_modules/@luxusai/pi-hindsight/extensions/types.ts +0 -534
  293. package/node_modules/@luxusai/pi-hindsight/extensions/utils/diagnostics.ts +0 -319
  294. package/node_modules/@luxusai/pi-hindsight/extensions/utils/messages.ts +0 -325
  295. package/node_modules/@luxusai/pi-hindsight/extensions/utils/sanitize.ts +0 -42
  296. package/node_modules/@luxusai/pi-hindsight/extensions/utils/session-memory-meta.ts +0 -244
  297. package/node_modules/@luxusai/pi-hindsight/extensions/utils/session-operations.ts +0 -56
  298. package/node_modules/@luxusai/pi-hindsight/extensions/utils/session.ts +0 -50
  299. package/node_modules/@luxusai/pi-hindsight/extensions/utils/status-fields.ts +0 -167
  300. package/node_modules/@luxusai/pi-hindsight/extensions/utils/status-health.ts +0 -207
  301. package/node_modules/@luxusai/pi-hindsight/extensions/utils/status.ts +0 -120
  302. package/node_modules/@luxusai/pi-hindsight/extensions/version.ts +0 -8
  303. package/node_modules/@luxusai/pi-hindsight/package.json +0 -118
  304. package/node_modules/@luxusai/pi-hindsight/skills/hindsight-memory-doctor/SKILL.md +0 -75
@@ -1,817 +0,0 @@
1
- import type { HindsightLikeClient, ResolvedConfig } from "../types.js";
2
- import { basename, dirname, extname, join, resolve } from "node:path";
3
- import {
4
- buildImportPlan,
5
- createImportCheckpoint,
6
- hashImportContent,
7
- type ImportCheckpoint,
8
- type ImportCheckpointDocument,
9
- type ImportDocumentStatus,
10
- type ImportPlan,
11
- readImportCheckpointSafe,
12
- readImportManifestSafe,
13
- upsertImportManifestEntries,
14
- writeImportCheckpoint,
15
- } from "./import-plan.js";
16
- import { createHash } from "node:crypto";
17
- import {
18
- deliverImportRetain,
19
- type ImportDocumentPreview,
20
- importRetainJobMatchesIdentity,
21
- ImportRetainQueuedError,
22
- type ImportRetainResult,
23
- isImportRetainQueuedError,
24
- previewImportBranch,
25
- retainImportBranch,
26
- } from "./import-execute.js";
27
- import { importDocumentId } from "../utils/session.js";
28
- import { readdir, readFile, stat } from "node:fs/promises";
29
- import { redactError, redactSecrets } from "../utils/sanitize.js";
30
- import { removeQueuedRetains } from "../queue/queue.js";
31
- import { resolveOperationBank } from "../banks/bank-selection.js";
32
- import { type ParsedSession, parseImportSessionJsonl } from "./import-parse.js";
33
- export { parseImportSessionJsonl, parsePiSessionJsonl } from "./import-parse.js";
34
- export { selectImportBranches } from "./import-parse.js";
35
- export type { ImportBranch } from "./import-parse.js";
36
- export type { ParsedMessage, ParsedSession } from "./import-parse.js";
37
-
38
- export interface ImportSessionDocumentResult extends ImportDocumentPreview {}
39
-
40
- export interface ImportExecutionResult {
41
- documents: ImportSessionDocumentResult[];
42
- messageCount: number;
43
- retained: boolean;
44
- }
45
-
46
- function checkpointDocument(args: {
47
- document: ImportDocumentPreview;
48
- status: ImportDocumentStatus;
49
- toolResults: ImportPlan["importConfig"]["import"]["toolResults"];
50
- updatedAt: string;
51
- error?: string;
52
- }): ImportCheckpointDocument {
53
- return {
54
- documentId: args.document.documentId,
55
- leafId: args.document.leafId,
56
- contentHash: args.document.contentHash,
57
- messageCount: args.document.messageCount,
58
- ...(args.document.importMode ? { importMode: args.document.importMode } : {}),
59
- toolResults: args.toolResults,
60
- ...(args.document.importQualityProfile
61
- ? { importQualityProfile: args.document.importQualityProfile }
62
- : {}),
63
- ...(args.document.projectionVersion
64
- ? { projectionVersion: args.document.projectionVersion }
65
- : {}),
66
- ...(args.document.importProfile ? { importProfile: args.document.importProfile } : {}),
67
- ...(args.document.chunkIndex !== undefined ? { chunkIndex: args.document.chunkIndex } : {}),
68
- ...(args.document.messageRange ? { messageRange: args.document.messageRange } : {}),
69
- status: args.status,
70
- ...(args.document.skipReason ? { skipReason: args.document.skipReason } : {}),
71
- updatedAt: args.updatedAt,
72
- ...(args.error ? { error: args.error } : {}),
73
- };
74
- }
75
-
76
- export async function executeImportPlan(args: {
77
- client: HindsightLikeClient;
78
- parsed: ParsedSession;
79
- plan: ImportPlan;
80
- dryRun?: boolean;
81
- onProgress?: ImportProgressReporter;
82
- }): Promise<ImportExecutionResult> {
83
- const {
84
- sessionFile,
85
- bankId,
86
- cwd,
87
- sessionId,
88
- leaves,
89
- includeBranches,
90
- branches,
91
- manifestPath,
92
- checkpointPath,
93
- updateMode,
94
- runId,
95
- importConfig,
96
- } = args.plan;
97
- const now = new Date().toISOString();
98
- const existingCheckpoint = importConfig.import.resume
99
- ? (await readImportCheckpointSafe(checkpointPath)).checkpoint
100
- : undefined;
101
- let checkpoint: ImportCheckpoint =
102
- existingCheckpoint?.runId === runId
103
- ? existingCheckpoint
104
- : createImportCheckpoint({
105
- runId,
106
- sourceFile: sessionFile,
107
- bankId,
108
- sessionId,
109
- cwd,
110
- includeBranches,
111
- importMode: importConfig.import.mode,
112
- toolResults: importConfig.import.toolResults,
113
- importQualityProfile: importConfig.import.qualityProfile,
114
- updateMode,
115
- now,
116
- });
117
- checkpoint = {
118
- ...checkpoint,
119
- updatedAt: now,
120
- toolResults: importConfig.import.toolResults,
121
- importQualityProfile: importConfig.import.qualityProfile,
122
- };
123
-
124
- const results = [];
125
- for (const branch of branches) {
126
- const common = {
127
- sessionFile,
128
- bankId,
129
- config: importConfig,
130
- parsed: args.parsed,
131
- cwd,
132
- sessionId,
133
- leaves,
134
- branch,
135
- };
136
- args.onProgress?.({
137
- phase: "previewing",
138
- message: `Projecting branch ${branch.leafId}`,
139
- sessionFile,
140
- });
141
- const previews = previewImportBranch(common);
142
- for (const [index, preview] of previews.entries()) {
143
- args.onProgress?.({
144
- phase: args.dryRun ? "previewing" : "retaining",
145
- message: `${args.dryRun ? "Previewing" : "Importing"} document ${index + 1}/${previews.length} for branch ${branch.leafId}`,
146
- sessionFile,
147
- current: index + 1,
148
- total: previews.length,
149
- });
150
- const previous = checkpoint.documents[preview.document.documentId];
151
- const canSkip =
152
- !args.dryRun &&
153
- importConfig.import.resume &&
154
- previous?.status === "completed" &&
155
- previous.contentHash === preview.document.contentHash;
156
- if (args.dryRun || canSkip) {
157
- if (canSkip && previous)
158
- await removeQueuedRetains(cwd, importConfig, (job) =>
159
- importRetainJobMatchesIdentity(job, {
160
- bankId,
161
- documentId: preview.document.documentId,
162
- updateMode,
163
- sourceFile: sessionFile,
164
- cwd,
165
- sessionId,
166
- leafId: previous.leafId,
167
- includeBranches,
168
- ...(previous.importMode ? { importMode: previous.importMode } : {}),
169
- ...(previous.toolResults ? { toolResults: previous.toolResults } : {}),
170
- ...(previous.importQualityProfile
171
- ? { importQualityProfile: previous.importQualityProfile }
172
- : {}),
173
- ...(previous.projectionVersion
174
- ? { projectionVersion: previous.projectionVersion }
175
- : {}),
176
- ...(previous.importProfile ? { importProfile: previous.importProfile } : {}),
177
- ...(previous.chunkIndex !== undefined ? { chunkIndex: previous.chunkIndex } : {}),
178
- ...(previous.messageRange ? { messageRange: previous.messageRange } : {}),
179
- contentHash: previous.contentHash,
180
- }),
181
- );
182
- results.push({
183
- ...preview,
184
- document: {
185
- ...preview.document,
186
- wouldWrite: false,
187
- status: canSkip ? ("skipped" as const) : preview.document.status,
188
- ...(canSkip ? { skipReason: "already-imported" as const } : {}),
189
- },
190
- });
191
- continue;
192
- }
193
-
194
- if (preview.document.status === "skipped") {
195
- const skippedAt = new Date().toISOString();
196
- checkpoint.documents[preview.document.documentId] = checkpointDocument({
197
- document: preview.document,
198
- status: "skipped",
199
- toolResults: importConfig.import.toolResults,
200
- updatedAt: skippedAt,
201
- });
202
- checkpoint.updatedAt = skippedAt;
203
- await writeImportCheckpoint(checkpointPath, checkpoint);
204
- results.push({
205
- ...preview,
206
- document: { ...preview.document, wouldWrite: false, status: "skipped" as const },
207
- });
208
- continue;
209
- }
210
-
211
- checkpoint.documents[preview.document.documentId] = checkpointDocument({
212
- document: preview.document,
213
- status: "pending",
214
- toolResults: importConfig.import.toolResults,
215
- updatedAt: new Date().toISOString(),
216
- });
217
- await writeImportCheckpoint(checkpointPath, checkpoint);
218
-
219
- let completed: ImportRetainResult | undefined;
220
- try {
221
- const retained = await retainImportBranch({
222
- ...common,
223
- client: args.client,
224
- documentId: preview.document.documentId,
225
- });
226
- const completedAt = new Date().toISOString();
227
- checkpoint.documents[retained.document.documentId] = checkpointDocument({
228
- document: retained.document,
229
- status: "completed",
230
- toolResults: importConfig.import.toolResults,
231
- updatedAt: completedAt,
232
- });
233
- checkpoint.updatedAt = completedAt;
234
- await writeImportCheckpoint(checkpointPath, checkpoint);
235
- completed = retained;
236
- } catch (error) {
237
- const failedAt = new Date().toISOString();
238
- const message = redactError(error);
239
- const status = isImportRetainQueuedError(error) ? "queued" : "failed";
240
- checkpoint.documents[preview.document.documentId] = checkpointDocument({
241
- document: preview.document,
242
- status,
243
- toolResults: importConfig.import.toolResults,
244
- updatedAt: failedAt,
245
- error: message,
246
- });
247
- checkpoint.updatedAt = failedAt;
248
- await writeImportCheckpoint(checkpointPath, checkpoint);
249
- results.push({
250
- ...preview,
251
- document: { ...preview.document, status, error: message },
252
- });
253
- throw error;
254
- }
255
- if (!completed) throw new Error("Import retain completed without result.");
256
- await upsertImportManifestEntries(manifestPath, [completed.manifestEntry]);
257
- results.push({
258
- ...completed,
259
- document: { ...completed.document, status: "completed" as const },
260
- });
261
- }
262
- }
263
-
264
- const skippedResults = results.filter((result) => result.document.status === "skipped");
265
- if (!args.dryRun && skippedResults.length > 0) {
266
- const manifest = (await readImportManifestSafe(manifestPath)).manifest;
267
- const missingSkippedEntries = skippedResults
268
- .filter((result) => result.document.skipReason !== "empty-curated-projection")
269
- .filter((result) => !manifest.imports[result.document.documentId])
270
- .map((result) => result.manifestEntry);
271
- if (missingSkippedEntries.length > 0)
272
- await upsertImportManifestEntries(manifestPath, missingSkippedEntries);
273
- }
274
-
275
- const documents = results.map((result) => result.document);
276
- return {
277
- documents,
278
- messageCount: documents.reduce((count, document) => count + document.messageCount, 0),
279
- retained: !args.dryRun,
280
- };
281
- }
282
-
283
- const KEPT_CHAT_TRANSCRIPT_EVENTS = new Set(["user_message", "assistant_reply", "process_end"]);
284
-
285
- export interface ChatTranscriptEvent {
286
- type: string;
287
- timestamp?: string;
288
- content?: unknown;
289
- channel?: string;
290
- sessionId?: string;
291
- conversationId?: string;
292
- data: Record<string, unknown>;
293
- }
294
-
295
- export interface ChatTranscriptImportResult {
296
- sourceFile: string;
297
- documentId: string;
298
- retained: boolean;
299
- skipped: boolean;
300
- skipReason?: string;
301
- dryRun: boolean;
302
- bankId: string;
303
- keptEventCount: number;
304
- droppedEventCount: number;
305
- malformedLineCount: number;
306
- retainedTurnCount: number;
307
- droppedEventTypes: Array<{ type: string; count: number }>;
308
- contentHash: string;
309
- contentBytes: number;
310
- }
311
-
312
- function isRecord(value: unknown): value is Record<string, unknown> {
313
- return typeof value === "object" && value !== null && !Array.isArray(value);
314
- }
315
-
316
- function stringField(record: Record<string, unknown>, keys: string[]): string | undefined {
317
- for (const key of keys) {
318
- const value = record[key];
319
- if (typeof value === "string" && value.trim()) return value;
320
- }
321
- return undefined;
322
- }
323
-
324
- function eventType(record: Record<string, unknown>): string | undefined {
325
- return stringField(record, ["type", "event", "event_type", "kind"]);
326
- }
327
-
328
- function normalizeChatTranscriptEvent(
329
- record: Record<string, unknown>,
330
- ): ChatTranscriptEvent | undefined {
331
- const type = eventType(record);
332
- if (!type) return undefined;
333
- const content = record.content ?? record.text ?? record.message ?? record.output;
334
- const timestamp = stringField(record, ["timestamp", "created_at", "time"]);
335
- const channel = stringField(record, ["channel", "channel_id"]);
336
- const sessionId = stringField(record, ["session_id", "sessionId"]);
337
- const conversationId = stringField(record, ["conversation_id", "conversationId", "thread_id"]);
338
- return {
339
- type,
340
- ...(timestamp ? { timestamp } : {}),
341
- ...(content !== undefined ? { content } : {}),
342
- ...(channel ? { channel } : {}),
343
- ...(sessionId ? { sessionId } : {}),
344
- ...(conversationId ? { conversationId } : {}),
345
- data: record,
346
- };
347
- }
348
-
349
- export function parseChatTranscriptJsonl(text: string): {
350
- kept: ChatTranscriptEvent[];
351
- droppedEventTypes: Array<{ type: string; count: number }>;
352
- droppedEventCount: number;
353
- malformedLineCount: number;
354
- } {
355
- const kept: ChatTranscriptEvent[] = [];
356
- const dropped = new Map<string, number>();
357
- let malformedLineCount = 0;
358
- for (const line of text.split("\n")) {
359
- if (!line.trim()) continue;
360
- let parsed: unknown;
361
- try {
362
- parsed = JSON.parse(line);
363
- } catch {
364
- malformedLineCount += 1;
365
- continue;
366
- }
367
- if (!isRecord(parsed)) {
368
- malformedLineCount += 1;
369
- continue;
370
- }
371
- const event = normalizeChatTranscriptEvent(parsed);
372
- if (!event) {
373
- malformedLineCount += 1;
374
- continue;
375
- }
376
- if (KEPT_CHAT_TRANSCRIPT_EVENTS.has(event.type)) kept.push(event);
377
- else dropped.set(event.type, (dropped.get(event.type) ?? 0) + 1);
378
- }
379
- return {
380
- kept,
381
- droppedEventTypes: [...dropped]
382
- .map(([type, count]) => ({ type, count }))
383
- .sort((left, right) => right.count - left.count || left.type.localeCompare(right.type)),
384
- droppedEventCount: [...dropped.values()].reduce((total, count) => total + count, 0),
385
- malformedLineCount,
386
- };
387
- }
388
-
389
- function firstDefined(
390
- events: ChatTranscriptEvent[],
391
- key: "channel" | "sessionId" | "conversationId",
392
- ): string | undefined {
393
- return events.find((event) => event[key])?.[key];
394
- }
395
-
396
- function tagValue(value: string): string {
397
- return (
398
- value
399
- .trim()
400
- .toLowerCase()
401
- .replace(/[^a-z0-9._-]+/g, "-")
402
- .slice(0, 80) || "unknown"
403
- );
404
- }
405
-
406
- function documentId(sourceFile: string, kept: ChatTranscriptEvent[]): string {
407
- const basis = JSON.stringify({ sourceFile, first: kept[0]?.data, last: kept.at(-1)?.data });
408
- return `pi-gateway-import:${createHash("sha256").update(basis).digest("hex").slice(0, 16)}`;
409
- }
410
-
411
- export async function importChatTranscript(args: {
412
- sourceFile: string;
413
- cwd: string;
414
- bankId: string;
415
- client: HindsightLikeClient;
416
- config: ResolvedConfig;
417
- dryRun?: boolean;
418
- onProgress?: ImportProgressReporter;
419
- }): Promise<ChatTranscriptImportResult> {
420
- args.onProgress?.({
421
- phase: "reading",
422
- message: `Reading chat transcript ${args.sourceFile}`,
423
- sessionFile: args.sourceFile,
424
- });
425
- const parsed = parseChatTranscriptJsonl(await readFile(args.sourceFile, "utf8"));
426
- args.onProgress?.({
427
- phase: "planning",
428
- message: `Planning chat transcript import for ${parsed.kept.length} kept event${parsed.kept.length === 1 ? "" : "s"}`,
429
- sessionFile: args.sourceFile,
430
- });
431
- const docId = documentId(args.sourceFile, parsed.kept);
432
- const channel = firstDefined(parsed.kept, "channel");
433
- const sessionId = firstDefined(parsed.kept, "sessionId");
434
- const conversationId = firstDefined(parsed.kept, "conversationId");
435
- const contentRaw = JSON.stringify(
436
- {
437
- source: "chat-transcript-import",
438
- sourceFile: args.sourceFile,
439
- channel,
440
- sessionId,
441
- conversationId,
442
- events: parsed.kept.map((event) => event.data),
443
- droppedEventCount: parsed.droppedEventCount,
444
- droppedEventTypes: parsed.droppedEventTypes,
445
- },
446
- null,
447
- 2,
448
- );
449
- const content = args.config.retain.redactSecrets ? redactSecrets(contentRaw) : contentRaw;
450
- const contentHash = createHash("sha256").update(content).digest("hex");
451
- const result: ChatTranscriptImportResult = {
452
- sourceFile: args.sourceFile,
453
- documentId: docId,
454
- retained: false,
455
- skipped: parsed.kept.length === 0,
456
- ...(parsed.kept.length === 0
457
- ? { skipReason: "No high-signal chat transcript events found." }
458
- : {}),
459
- dryRun: Boolean(args.dryRun),
460
- bankId: args.bankId,
461
- keptEventCount: parsed.kept.length,
462
- droppedEventCount: parsed.droppedEventCount,
463
- malformedLineCount: parsed.malformedLineCount,
464
- retainedTurnCount: parsed.kept.filter((event) => event.type === "user_message").length,
465
- droppedEventTypes: parsed.droppedEventTypes,
466
- contentHash,
467
- contentBytes: Buffer.byteLength(content, "utf8"),
468
- };
469
- if (args.dryRun || parsed.kept.length === 0) return result;
470
- args.onProgress?.({
471
- phase: "retaining",
472
- message: `Importing chat transcript document ${docId}`,
473
- sessionFile: args.sourceFile,
474
- current: 1,
475
- total: 1,
476
- });
477
- const delivery = await deliverImportRetain({
478
- cwd: args.cwd,
479
- config: args.config,
480
- client: args.client,
481
- bankId: args.bankId,
482
- content,
483
- context: `Chat transcript import from ${basename(args.sourceFile)}`,
484
- documentId: docId,
485
- updateMode: "replace",
486
- tags: [
487
- "source:chat",
488
- "import:chat",
489
- "imported:true",
490
- ...(channel ? [`channel:${tagValue(channel)}`] : []),
491
- ...(sessionId ? [`session:${tagValue(sessionId)}`] : []),
492
- ...(conversationId ? [`conversation:${tagValue(conversationId)}`] : []),
493
- `document:${docId}`,
494
- ],
495
- metadata: {
496
- source_file: args.sourceFile,
497
- imported: "true",
498
- source: "chat-transcript",
499
- ...(channel ? { channel } : {}),
500
- ...(sessionId ? { session_id: sessionId } : {}),
501
- ...(conversationId ? { conversation_id: conversationId } : {}),
502
- content_hash: contentHash,
503
- },
504
- });
505
- if (!delivery.delivered) {
506
- throw new ImportRetainQueuedError(
507
- `Chat transcript import queued as ${delivery.queueJobId}; ${delivery.remaining} retain job${delivery.remaining === 1 ? "" : "s"} pending`,
508
- );
509
- }
510
- return { ...result, retained: true };
511
- }
512
-
513
- export type ImportOperationDeps = {
514
- getClient(): HindsightLikeClient;
515
- getConfig(): ResolvedConfig;
516
- getProjectBankId(): string;
517
- };
518
-
519
- export async function importMemorySession(
520
- args: {
521
- sessionFile: string;
522
- cwd?: string;
523
- bank?: string;
524
- dryRun?: boolean;
525
- includeBranches?: ResolvedConfig["import"]["includeBranches"];
526
- onProgress?: ImportProgressReporter;
527
- },
528
- deps: ImportOperationDeps,
529
- ) {
530
- const bankId = resolveOperationBank({
531
- requestedBank: args.bank,
532
- config: deps.getConfig(),
533
- projectBankId: deps.getProjectBankId(),
534
- });
535
- const result = await importPiSession({
536
- sessionFile: args.sessionFile,
537
- ...(args.cwd ? { cwd: args.cwd } : {}),
538
- bankId,
539
- client: deps.getClient(),
540
- config: deps.getConfig(),
541
- ...(args.dryRun !== undefined ? { dryRun: args.dryRun } : {}),
542
- ...(args.includeBranches ? { includeBranches: args.includeBranches } : {}),
543
- ...(args.onProgress ? { onProgress: args.onProgress } : {}),
544
- });
545
- return { bankId, ...result };
546
- }
547
-
548
- export async function importMemoryChatTranscript(
549
- args: {
550
- sourceFile: string;
551
- cwd: string;
552
- bank?: string;
553
- dryRun?: boolean;
554
- onProgress?: ImportProgressReporter;
555
- },
556
- deps: ImportOperationDeps,
557
- ) {
558
- const bankId = resolveOperationBank({
559
- requestedBank: args.bank ?? "global",
560
- config: deps.getConfig(),
561
- projectBankId: deps.getProjectBankId(),
562
- });
563
- return importChatTranscript({
564
- sourceFile: args.sourceFile,
565
- cwd: args.cwd,
566
- bankId,
567
- client: deps.getClient(),
568
- config: deps.getConfig(),
569
- ...(args.dryRun !== undefined ? { dryRun: args.dryRun } : {}),
570
- ...(args.onProgress ? { onProgress: args.onProgress } : {}),
571
- });
572
- }
573
-
574
- export async function importMemoryProjectSessions(
575
- args: {
576
- cwd: string;
577
- currentSessionFile?: string;
578
- searchDir?: string;
579
- bank?: string;
580
- dryRun?: boolean;
581
- includeBranches?: ResolvedConfig["import"]["includeBranches"];
582
- onProgress?: ImportProgressReporter;
583
- },
584
- deps: ImportOperationDeps,
585
- ) {
586
- const bankId = resolveOperationBank({
587
- requestedBank: args.bank,
588
- config: deps.getConfig(),
589
- projectBankId: deps.getProjectBankId(),
590
- });
591
- const result = await importProjectSessions({
592
- cwd: args.cwd,
593
- ...(args.currentSessionFile ? { currentSessionFile: args.currentSessionFile } : {}),
594
- ...(args.searchDir ? { searchDir: args.searchDir } : {}),
595
- bankId,
596
- client: deps.getClient(),
597
- config: deps.getConfig(),
598
- ...(args.dryRun !== undefined ? { dryRun: args.dryRun } : {}),
599
- ...(args.includeBranches ? { includeBranches: args.includeBranches } : {}),
600
- ...(args.onProgress ? { onProgress: args.onProgress } : {}),
601
- });
602
- return { bankId, ...result };
603
- }
604
-
605
- export type ImportProgressEvent = {
606
- phase:
607
- | "reading"
608
- | "planning"
609
- | "previewing"
610
- | "retaining"
611
- | "discovering"
612
- | "discovered"
613
- | "session";
614
- message: string;
615
- sessionFile?: string;
616
- current?: number;
617
- total?: number;
618
- };
619
-
620
- export type ImportProgressReporter = (event: ImportProgressEvent) => void;
621
-
622
- function sameProjectCwd(sessionCwd: string | undefined, cwd: string): boolean {
623
- if (!sessionCwd) return false;
624
- return resolve(sessionCwd) === resolve(cwd);
625
- }
626
-
627
- async function isFile(path: string): Promise<boolean> {
628
- try {
629
- return (await stat(path)).isFile();
630
- } catch {
631
- return false;
632
- }
633
- }
634
-
635
- function projectSessionCheckpointPath(basePath: string, sessionFile: string): string {
636
- return `${basePath}.${hashImportContent(sessionFile).slice(0, 12)}.json`;
637
- }
638
-
639
- export async function discoverProjectSessionFiles(args: {
640
- cwd: string;
641
- currentSessionFile?: string;
642
- searchDir?: string;
643
- }): Promise<ProjectSessionDiscoveryResult> {
644
- const searchDir =
645
- args.searchDir ?? (args.currentSessionFile ? dirname(args.currentSessionFile) : undefined);
646
- if (!searchDir) return { sessionFiles: [], scanned: 0 };
647
- const entries = await readdir(searchDir);
648
- const candidates = entries
649
- .filter((entry) => extname(entry) === ".jsonl")
650
- .map((entry) => join(searchDir, entry));
651
- const sessionFiles: string[] = [];
652
- let scanned = 0;
653
- for (const candidate of candidates) {
654
- if (!(await isFile(candidate))) continue;
655
- scanned += 1;
656
- try {
657
- const parsed = parseImportSessionJsonl(await readFile(candidate, "utf8"));
658
- if (sameProjectCwd(parsed.cwd, args.cwd)) sessionFiles.push(candidate);
659
- } catch {
660
- // Ignore unrelated or malformed JSONL files during project-scoped discovery.
661
- }
662
- }
663
- return { sessionFiles: sessionFiles.sort(), scanned };
664
- }
665
-
666
- export interface ProjectSessionDiscoveryResult {
667
- sessionFiles: string[];
668
- scanned: number;
669
- }
670
-
671
- export interface ImportProjectSessionsResult {
672
- sessionFiles: string[];
673
- scanned: number;
674
- imported: ImportSessionResult[];
675
- messageCount: number;
676
- documentCount: number;
677
- dryRun: boolean;
678
- malformedLineCount: number;
679
- }
680
-
681
- export interface ImportSessionResult {
682
- sessionFile: string;
683
- documentId: string;
684
- messageCount: number;
685
- retained: boolean;
686
- dryRun: boolean;
687
- manifestPath: string;
688
- checkpointPath: string;
689
- runId: string;
690
- malformedLineCount: number;
691
- documents: ImportSessionDocumentResult[];
692
- }
693
-
694
- export async function importPiSession(args: {
695
- sessionFile: string;
696
- cwd?: string;
697
- bankId: string;
698
- client: HindsightLikeClient;
699
- config: ResolvedConfig;
700
- dryRun?: boolean;
701
- requireMatchingCwd?: boolean;
702
- includeBranches?: ResolvedConfig["import"]["includeBranches"];
703
- onProgress?: ImportProgressReporter;
704
- }): Promise<ImportSessionResult> {
705
- args.onProgress?.({
706
- phase: "reading",
707
- message: `Reading session file ${args.sessionFile}`,
708
- sessionFile: args.sessionFile,
709
- });
710
- const text = await readFile(args.sessionFile, "utf8");
711
- const parsed = parseImportSessionJsonl(text);
712
- args.onProgress?.({
713
- phase: "planning",
714
- message: `Planning import for ${parsed.messages.length} message${parsed.messages.length === 1 ? "" : "s"}`,
715
- sessionFile: args.sessionFile,
716
- });
717
- const plan = buildImportPlan({
718
- sessionFile: args.sessionFile,
719
- parsed,
720
- bankId: args.bankId,
721
- config: args.config,
722
- ...(args.cwd ? { cwd: args.cwd } : {}),
723
- ...(args.requireMatchingCwd !== undefined
724
- ? { requireMatchingCwd: args.requireMatchingCwd }
725
- : {}),
726
- ...(args.includeBranches ? { includeBranches: args.includeBranches } : {}),
727
- });
728
- const execution = await executeImportPlan({
729
- client: args.client,
730
- parsed,
731
- plan,
732
- ...(args.dryRun !== undefined ? { dryRun: args.dryRun } : {}),
733
- ...(args.onProgress ? { onProgress: args.onProgress } : {}),
734
- });
735
-
736
- const first = execution.documents[0] ?? {
737
- documentId: importDocumentId(plan.sessionId, "root"),
738
- };
739
- return {
740
- sessionFile: args.sessionFile,
741
- documentId: first.documentId,
742
- messageCount: execution.messageCount,
743
- retained: execution.retained,
744
- dryRun: Boolean(args.dryRun),
745
- manifestPath: plan.manifestPath,
746
- checkpointPath: plan.checkpointPath,
747
- runId: plan.runId,
748
- malformedLineCount: parsed.malformedLineCount,
749
- documents: execution.documents,
750
- };
751
- }
752
-
753
- export async function importProjectSessions(args: {
754
- cwd: string;
755
- currentSessionFile?: string;
756
- searchDir?: string;
757
- bankId: string;
758
- client: HindsightLikeClient;
759
- config: ResolvedConfig;
760
- dryRun?: boolean;
761
- includeBranches?: ResolvedConfig["import"]["includeBranches"];
762
- onProgress?: ImportProgressReporter;
763
- }): Promise<ImportProjectSessionsResult> {
764
- args.onProgress?.({ phase: "discovering", message: "Scanning project session files" });
765
- const discovery = await discoverProjectSessionFiles({
766
- cwd: args.cwd,
767
- ...(args.currentSessionFile ? { currentSessionFile: args.currentSessionFile } : {}),
768
- ...(args.searchDir ? { searchDir: args.searchDir } : {}),
769
- });
770
- args.onProgress?.({
771
- phase: "discovered",
772
- message: `Found ${discovery.sessionFiles.length} project session${discovery.sessionFiles.length === 1 ? "" : "s"} after scanning ${discovery.scanned} file${discovery.scanned === 1 ? "" : "s"}`,
773
- current: discovery.sessionFiles.length,
774
- total: discovery.scanned,
775
- });
776
- const imported: ImportSessionResult[] = [];
777
- for (const [index, sessionFile] of discovery.sessionFiles.entries()) {
778
- args.onProgress?.({
779
- phase: "session",
780
- message: `Importing project session ${index + 1}/${discovery.sessionFiles.length}: ${sessionFile}`,
781
- sessionFile,
782
- current: index + 1,
783
- total: discovery.sessionFiles.length,
784
- });
785
- imported.push(
786
- await importPiSession({
787
- sessionFile,
788
- cwd: args.cwd,
789
- requireMatchingCwd: true,
790
- bankId: args.bankId,
791
- client: args.client,
792
- config: {
793
- ...args.config,
794
- import: {
795
- ...args.config.import,
796
- checkpointPath: projectSessionCheckpointPath(
797
- args.config.import.checkpointPath,
798
- sessionFile,
799
- ),
800
- },
801
- },
802
- ...(args.dryRun !== undefined ? { dryRun: args.dryRun } : {}),
803
- ...(args.includeBranches ? { includeBranches: args.includeBranches } : {}),
804
- ...(args.onProgress ? { onProgress: args.onProgress } : {}),
805
- }),
806
- );
807
- }
808
- return {
809
- sessionFiles: discovery.sessionFiles,
810
- scanned: discovery.scanned,
811
- imported,
812
- messageCount: imported.reduce((count, result) => count + result.messageCount, 0),
813
- documentCount: imported.reduce((count, result) => count + result.documents.length, 0),
814
- dryRun: Boolean(args.dryRun),
815
- malformedLineCount: imported.reduce((count, result) => count + result.malformedLineCount, 0),
816
- };
817
- }