devchain-cli 0.23.2 → 0.23.3

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 (257) hide show
  1. package/dist/drizzle/0083_retire_documents.sql +2 -0
  2. package/dist/drizzle/0084_retire_codebase_overview.sql +1 -0
  3. package/dist/drizzle/0085_clumsy_zodiak.sql +166 -0
  4. package/dist/drizzle/meta/0083_snapshot.json +7422 -0
  5. package/dist/drizzle/meta/0084_snapshot.json +7422 -0
  6. package/dist/drizzle/meta/0085_snapshot.json +7446 -0
  7. package/dist/drizzle/meta/_journal.json +21 -0
  8. package/dist/server/app.main.module.js +0 -4
  9. package/dist/server/app.main.module.js.map +1 -1
  10. package/dist/server/app.normal.module.js +0 -4
  11. package/dist/server/app.normal.module.js.map +1 -1
  12. package/dist/server/modules/epic-time/controllers/external-estimate-log.controller.d.ts +1 -0
  13. package/dist/server/modules/epic-time/controllers/external-estimate-log.controller.js +48 -0
  14. package/dist/server/modules/epic-time/controllers/external-estimate-log.controller.js.map +1 -1
  15. package/dist/server/modules/epic-time/models/epic-time.models.d.ts +10 -0
  16. package/dist/server/modules/epic-time/services/epic-estimate-logging.service.d.ts +4 -1
  17. package/dist/server/modules/epic-time/services/epic-estimate-logging.service.js +43 -1
  18. package/dist/server/modules/epic-time/services/epic-estimate-logging.service.js.map +1 -1
  19. package/dist/server/modules/epics/subscribers/epic-assignment-notifier.subscriber.d.ts +1 -0
  20. package/dist/server/modules/epics/subscribers/epic-assignment-notifier.subscriber.js +31 -1
  21. package/dist/server/modules/epics/subscribers/epic-assignment-notifier.subscriber.js.map +1 -1
  22. package/dist/server/modules/external-integrations/connections/stable-integration-connection.d.ts +14 -0
  23. package/dist/server/modules/external-integrations/connections/stable-integration-connection.js +56 -0
  24. package/dist/server/modules/external-integrations/connections/stable-integration-connection.js.map +1 -0
  25. package/dist/server/modules/external-integrations/my-work/external-edit-session.service.d.ts +2 -1
  26. package/dist/server/modules/external-integrations/my-work/external-edit-session.service.js +51 -33
  27. package/dist/server/modules/external-integrations/my-work/external-edit-session.service.js.map +1 -1
  28. package/dist/server/modules/external-integrations/my-work/external-my-work.controller.js +2 -2
  29. package/dist/server/modules/external-integrations/my-work/external-my-work.controller.js.map +1 -1
  30. package/dist/server/modules/external-integrations/my-work/external-my-work.openapi.d.ts +1 -0
  31. package/dist/server/modules/external-integrations/my-work/external-my-work.openapi.js +33 -1
  32. package/dist/server/modules/external-integrations/my-work/external-my-work.openapi.js.map +1 -1
  33. package/dist/server/modules/external-integrations/my-work/external-my-work.service.d.ts +1 -1
  34. package/dist/server/modules/external-integrations/my-work/external-my-work.service.js +41 -48
  35. package/dist/server/modules/external-integrations/my-work/external-my-work.service.js.map +1 -1
  36. package/dist/server/modules/external-integrations/my-work/external-time-mutation.service.js +24 -11
  37. package/dist/server/modules/external-integrations/my-work/external-time-mutation.service.js.map +1 -1
  38. package/dist/server/modules/external-integrations/sessions/external-edit-session.store.js +3 -1
  39. package/dist/server/modules/external-integrations/sessions/external-edit-session.store.js.map +1 -1
  40. package/dist/server/modules/mcp/constants.d.ts +0 -2
  41. package/dist/server/modules/mcp/constants.js +1 -11
  42. package/dist/server/modules/mcp/constants.js.map +1 -1
  43. package/dist/server/modules/mcp/dtos/mcp.dto.d.ts +0 -165
  44. package/dist/server/modules/mcp/dtos/mcp.dto.js +1 -47
  45. package/dist/server/modules/mcp/dtos/mcp.dto.js.map +1 -1
  46. package/dist/server/modules/mcp/services/instructions-resolver.d.ts +4 -13
  47. package/dist/server/modules/mcp/services/instructions-resolver.js +26 -166
  48. package/dist/server/modules/mcp/services/instructions-resolver.js.map +1 -1
  49. package/dist/server/modules/mcp/services/mappers/dto-mappers.d.ts +2 -4
  50. package/dist/server/modules/mcp/services/mappers/dto-mappers.js +0 -22
  51. package/dist/server/modules/mcp/services/mappers/dto-mappers.js.map +1 -1
  52. package/dist/server/modules/mcp/services/mcp-tool-binding.registry.js +1 -2
  53. package/dist/server/modules/mcp/services/mcp-tool-binding.registry.js.map +1 -1
  54. package/dist/server/modules/mcp/services/utils/resource-resolver.d.ts +2 -4
  55. package/dist/server/modules/mcp/services/utils/resource-resolver.js +0 -59
  56. package/dist/server/modules/mcp/services/utils/resource-resolver.js.map +1 -1
  57. package/dist/server/modules/mcp/tool-descriptors/index.js +0 -2
  58. package/dist/server/modules/mcp/tool-descriptors/index.js.map +1 -1
  59. package/dist/server/modules/mcp/tool-descriptors/runtime-bindings.js +0 -2
  60. package/dist/server/modules/mcp/tool-descriptors/runtime-bindings.js.map +1 -1
  61. package/dist/server/modules/projects/helpers/project-import.d.ts +0 -33
  62. package/dist/server/modules/projects/helpers/project-import.js +0 -224
  63. package/dist/server/modules/projects/helpers/project-import.js.map +1 -1
  64. package/dist/server/modules/projects/services/project-registry-import.service.d.ts +3 -6
  65. package/dist/server/modules/projects/services/project-registry-import.service.js +7 -28
  66. package/dist/server/modules/projects/services/project-registry-import.service.js.map +1 -1
  67. package/dist/server/modules/projects/template-codec/codecs/teams.codec.js.map +1 -1
  68. package/dist/server/modules/registry/controllers/registry.controller.js +3 -10
  69. package/dist/server/modules/registry/controllers/registry.controller.js.map +1 -1
  70. package/dist/server/modules/registry/services/registry-orchestration.service.d.ts +11 -3
  71. package/dist/server/modules/registry/services/registry-orchestration.service.js +6 -1
  72. package/dist/server/modules/registry/services/registry-orchestration.service.js.map +1 -1
  73. package/dist/server/modules/session-reader/adapters/claude-session-reader.adapter.d.ts +8 -0
  74. package/dist/server/modules/session-reader/adapters/claude-session-reader.adapter.js +9 -0
  75. package/dist/server/modules/session-reader/adapters/claude-session-reader.adapter.js.map +1 -1
  76. package/dist/server/modules/session-reader/adapters/codex-session-reader.adapter.d.ts +10 -0
  77. package/dist/server/modules/session-reader/adapters/codex-session-reader.adapter.js +13 -0
  78. package/dist/server/modules/session-reader/adapters/codex-session-reader.adapter.js.map +1 -1
  79. package/dist/server/modules/session-reader/adapters/session-reader-adapter.interface.d.ts +20 -1
  80. package/dist/server/modules/session-reader/adapters/session-reader-adapter.interface.js.map +1 -1
  81. package/dist/server/modules/session-reader/data/pricing.json +12 -11
  82. package/dist/server/modules/session-reader/parsers/bounded-line-read.d.ts +2 -0
  83. package/dist/server/modules/session-reader/parsers/bounded-line-read.js +66 -0
  84. package/dist/server/modules/session-reader/parsers/bounded-line-read.js.map +1 -0
  85. package/dist/server/modules/session-reader/parsers/claude-jsonl.parser.d.ts +6 -0
  86. package/dist/server/modules/session-reader/parsers/claude-jsonl.parser.js +44 -13
  87. package/dist/server/modules/session-reader/parsers/claude-jsonl.parser.js.map +1 -1
  88. package/dist/server/modules/session-reader/parsers/codex-jsonl.parser.d.ts +22 -0
  89. package/dist/server/modules/session-reader/parsers/codex-jsonl.parser.js +61 -16
  90. package/dist/server/modules/session-reader/parsers/codex-jsonl.parser.js.map +1 -1
  91. package/dist/server/modules/session-reader/services/bounded-anchor-proof.d.ts +12 -0
  92. package/dist/server/modules/session-reader/services/bounded-anchor-proof.js +103 -0
  93. package/dist/server/modules/session-reader/services/bounded-anchor-proof.js.map +1 -0
  94. package/dist/server/modules/session-reader/services/metrics-merge.d.ts +17 -0
  95. package/dist/server/modules/session-reader/services/metrics-merge.js +114 -0
  96. package/dist/server/modules/session-reader/services/metrics-merge.js.map +1 -0
  97. package/dist/server/modules/session-reader/services/session-cache.service.d.ts +33 -4
  98. package/dist/server/modules/session-reader/services/session-cache.service.js +157 -144
  99. package/dist/server/modules/session-reader/services/session-cache.service.js.map +1 -1
  100. package/dist/server/modules/session-reader/services/session-reader.service.js +0 -1
  101. package/dist/server/modules/session-reader/services/session-reader.service.js.map +1 -1
  102. package/dist/server/modules/session-reader/services/transcript-watcher.service.d.ts +16 -0
  103. package/dist/server/modules/session-reader/services/transcript-watcher.service.js +370 -69
  104. package/dist/server/modules/session-reader/services/transcript-watcher.service.js.map +1 -1
  105. package/dist/server/modules/sessions/controllers/sessions.controller.d.ts +4 -1
  106. package/dist/server/modules/sessions/controllers/sessions.controller.js +32 -0
  107. package/dist/server/modules/sessions/controllers/sessions.controller.js.map +1 -1
  108. package/dist/server/modules/sessions/services/message-pool.types.d.ts +23 -0
  109. package/dist/server/modules/sessions/services/sessions-message-pool.service.d.ts +5 -2
  110. package/dist/server/modules/sessions/services/sessions-message-pool.service.js +82 -4
  111. package/dist/server/modules/sessions/services/sessions-message-pool.service.js.map +1 -1
  112. package/dist/server/modules/storage/db/schema.d.ts +57 -219
  113. package/dist/server/modules/storage/db/schema.js +15 -27
  114. package/dist/server/modules/storage/db/schema.js.map +1 -1
  115. package/dist/server/modules/storage/interfaces/storage.interface.d.ts +6 -23
  116. package/dist/server/modules/storage/interfaces/storage.interface.js.map +1 -1
  117. package/dist/server/modules/storage/local/delegates/external-estimate-log.delegate.d.ts +6 -1
  118. package/dist/server/modules/storage/local/delegates/external-estimate-log.delegate.js +163 -32
  119. package/dist/server/modules/storage/local/delegates/external-estimate-log.delegate.js.map +1 -1
  120. package/dist/server/modules/storage/local/delegates/external-managed-subtask.delegate.js +11 -1
  121. package/dist/server/modules/storage/local/delegates/external-managed-subtask.delegate.js.map +1 -1
  122. package/dist/server/modules/storage/local/delegates/integration.delegate.d.ts +1 -1
  123. package/dist/server/modules/storage/local/delegates/integration.delegate.js +17 -13
  124. package/dist/server/modules/storage/local/delegates/integration.delegate.js.map +1 -1
  125. package/dist/server/modules/storage/local/delegates/project.delegate.js +1 -10
  126. package/dist/server/modules/storage/local/delegates/project.delegate.js.map +1 -1
  127. package/dist/server/modules/storage/local/local-storage.service.d.ts +6 -9
  128. package/dist/server/modules/storage/local/local-storage.service.js +8 -22
  129. package/dist/server/modules/storage/local/local-storage.service.js.map +1 -1
  130. package/dist/server/modules/storage/models/domain.models.d.ts +14 -20
  131. package/dist/server/modules/storage/models/domain.models.js +2 -1
  132. package/dist/server/modules/storage/models/domain.models.js.map +1 -1
  133. package/dist/server/modules/terminal/services/human-prompt-state.service.d.ts +7 -0
  134. package/dist/server/modules/terminal/services/human-prompt-state.service.js +26 -0
  135. package/dist/server/modules/terminal/services/human-prompt-state.service.js.map +1 -1
  136. package/dist/server/modules/terminal/services/terminal-session/terminal-session.js +3 -2
  137. package/dist/server/modules/terminal/services/terminal-session/terminal-session.js.map +1 -1
  138. package/dist/server/modules/terminal/utils/terminal-activity.js +8 -1
  139. package/dist/server/modules/terminal/utils/terminal-activity.js.map +1 -1
  140. package/dist/server/templates/teams-dev.json +2 -2
  141. package/dist/server/tsconfig.tsbuildinfo +1 -1
  142. package/dist/server/ui/assets/{ExternalRichEditor-BnzvJiFh.js → ExternalRichEditor-akgwTdms.js} +24 -24
  143. package/dist/server/ui/assets/ReviewDetailPage-10JU-Gdr.js +1 -0
  144. package/dist/server/ui/assets/ReviewsPage-BIVn-pS5.js +6 -0
  145. package/dist/server/ui/assets/index-Bg8fZbSZ.css +32 -0
  146. package/dist/server/ui/assets/index-DHmiffN1.js +1000 -0
  147. package/dist/server/ui/assets/useReviewSubscription-Xua63feT.js +69 -0
  148. package/dist/server/ui/index.html +2 -2
  149. package/dist/templates/teams-dev.json +2 -2
  150. package/package.json +10 -1
  151. package/dist/server/modules/codebase-overview-analyzer/codebase-overview-analyzer.module.d.ts +0 -2
  152. package/dist/server/modules/codebase-overview-analyzer/codebase-overview-analyzer.module.js +0 -52
  153. package/dist/server/modules/codebase-overview-analyzer/codebase-overview-analyzer.module.js.map +0 -1
  154. package/dist/server/modules/codebase-overview-analyzer/controllers/codebase-overview.controller.d.ts +0 -30
  155. package/dist/server/modules/codebase-overview-analyzer/controllers/codebase-overview.controller.js +0 -230
  156. package/dist/server/modules/codebase-overview-analyzer/controllers/codebase-overview.controller.js.map +0 -1
  157. package/dist/server/modules/codebase-overview-analyzer/repositories/overview-scope.repository.d.ts +0 -24
  158. package/dist/server/modules/codebase-overview-analyzer/repositories/overview-scope.repository.js +0 -191
  159. package/dist/server/modules/codebase-overview-analyzer/repositories/overview-scope.repository.js.map +0 -1
  160. package/dist/server/modules/codebase-overview-analyzer/services/codebase-overview-analyzer.service.d.ts +0 -73
  161. package/dist/server/modules/codebase-overview-analyzer/services/codebase-overview-analyzer.service.js +0 -1133
  162. package/dist/server/modules/codebase-overview-analyzer/services/codebase-overview-analyzer.service.js.map +0 -1
  163. package/dist/server/modules/codebase-overview-analyzer/services/dependency-aggregation.service.d.ts +0 -14
  164. package/dist/server/modules/codebase-overview-analyzer/services/dependency-aggregation.service.js +0 -114
  165. package/dist/server/modules/codebase-overview-analyzer/services/dependency-aggregation.service.js.map +0 -1
  166. package/dist/server/modules/codebase-overview-analyzer/services/district-splitting.service.d.ts +0 -8
  167. package/dist/server/modules/codebase-overview-analyzer/services/district-splitting.service.js +0 -200
  168. package/dist/server/modules/codebase-overview-analyzer/services/district-splitting.service.js.map +0 -1
  169. package/dist/server/modules/codebase-overview-analyzer/services/evidence-query.service.d.ts +0 -11
  170. package/dist/server/modules/codebase-overview-analyzer/services/evidence-query.service.js +0 -164
  171. package/dist/server/modules/codebase-overview-analyzer/services/evidence-query.service.js.map +0 -1
  172. package/dist/server/modules/codebase-overview-analyzer/services/go-adapter.d.ts +0 -2
  173. package/dist/server/modules/codebase-overview-analyzer/services/go-adapter.js +0 -166
  174. package/dist/server/modules/codebase-overview-analyzer/services/go-adapter.js.map +0 -1
  175. package/dist/server/modules/codebase-overview-analyzer/services/hotspot-scoring.service.d.ts +0 -21
  176. package/dist/server/modules/codebase-overview-analyzer/services/hotspot-scoring.service.js +0 -253
  177. package/dist/server/modules/codebase-overview-analyzer/services/hotspot-scoring.service.js.map +0 -1
  178. package/dist/server/modules/codebase-overview-analyzer/services/identity-resolver.service.d.ts +0 -24
  179. package/dist/server/modules/codebase-overview-analyzer/services/identity-resolver.service.js +0 -98
  180. package/dist/server/modules/codebase-overview-analyzer/services/identity-resolver.service.js.map +0 -1
  181. package/dist/server/modules/codebase-overview-analyzer/services/java-adapter.d.ts +0 -2
  182. package/dist/server/modules/codebase-overview-analyzer/services/java-adapter.js +0 -155
  183. package/dist/server/modules/codebase-overview-analyzer/services/java-adapter.js.map +0 -1
  184. package/dist/server/modules/codebase-overview-analyzer/services/language-adapter-registry.service.d.ts +0 -19
  185. package/dist/server/modules/codebase-overview-analyzer/services/language-adapter-registry.service.js +0 -88
  186. package/dist/server/modules/codebase-overview-analyzer/services/language-adapter-registry.service.js.map +0 -1
  187. package/dist/server/modules/codebase-overview-analyzer/services/php-adapter.d.ts +0 -2
  188. package/dist/server/modules/codebase-overview-analyzer/services/php-adapter.js +0 -173
  189. package/dist/server/modules/codebase-overview-analyzer/services/php-adapter.js.map +0 -1
  190. package/dist/server/modules/codebase-overview-analyzer/services/python-adapter.d.ts +0 -2
  191. package/dist/server/modules/codebase-overview-analyzer/services/python-adapter.js +0 -171
  192. package/dist/server/modules/codebase-overview-analyzer/services/python-adapter.js.map +0 -1
  193. package/dist/server/modules/codebase-overview-analyzer/services/ruby-adapter.d.ts +0 -2
  194. package/dist/server/modules/codebase-overview-analyzer/services/ruby-adapter.js +0 -158
  195. package/dist/server/modules/codebase-overview-analyzer/services/ruby-adapter.js.map +0 -1
  196. package/dist/server/modules/codebase-overview-analyzer/services/rust-adapter.d.ts +0 -2
  197. package/dist/server/modules/codebase-overview-analyzer/services/rust-adapter.js +0 -222
  198. package/dist/server/modules/codebase-overview-analyzer/services/rust-adapter.js.map +0 -1
  199. package/dist/server/modules/codebase-overview-analyzer/services/scope-auto-detector.service.d.ts +0 -4
  200. package/dist/server/modules/codebase-overview-analyzer/services/scope-auto-detector.service.js +0 -72
  201. package/dist/server/modules/codebase-overview-analyzer/services/scope-auto-detector.service.js.map +0 -1
  202. package/dist/server/modules/codebase-overview-analyzer/services/scope-resolver.service.d.ts +0 -6
  203. package/dist/server/modules/codebase-overview-analyzer/services/scope-resolver.service.js +0 -37
  204. package/dist/server/modules/codebase-overview-analyzer/services/scope-resolver.service.js.map +0 -1
  205. package/dist/server/modules/codebase-overview-analyzer/services/typescript-adapter.d.ts +0 -2
  206. package/dist/server/modules/codebase-overview-analyzer/services/typescript-adapter.js +0 -108
  207. package/dist/server/modules/codebase-overview-analyzer/services/typescript-adapter.js.map +0 -1
  208. package/dist/server/modules/codebase-overview-analyzer/types/index.d.ts +0 -2
  209. package/dist/server/modules/codebase-overview-analyzer/types/index.js +0 -6
  210. package/dist/server/modules/codebase-overview-analyzer/types/index.js.map +0 -1
  211. package/dist/server/modules/codebase-overview-analyzer/types/overview.types.d.ts +0 -231
  212. package/dist/server/modules/codebase-overview-analyzer/types/overview.types.js +0 -3
  213. package/dist/server/modules/codebase-overview-analyzer/types/overview.types.js.map +0 -1
  214. package/dist/server/modules/codebase-overview-analyzer/types/scope-defaults.d.ts +0 -2
  215. package/dist/server/modules/codebase-overview-analyzer/types/scope-defaults.js +0 -13
  216. package/dist/server/modules/codebase-overview-analyzer/types/scope-defaults.js.map +0 -1
  217. package/dist/server/modules/codebase-overview-analyzer/types/scope.schema.d.ts +0 -54
  218. package/dist/server/modules/codebase-overview-analyzer/types/scope.schema.js +0 -27
  219. package/dist/server/modules/codebase-overview-analyzer/types/scope.schema.js.map +0 -1
  220. package/dist/server/modules/codebase-overview-analyzer/types/scope.types.d.ts +0 -12
  221. package/dist/server/modules/codebase-overview-analyzer/types/scope.types.js +0 -3
  222. package/dist/server/modules/codebase-overview-analyzer/types/scope.types.js.map +0 -1
  223. package/dist/server/modules/codebase-overview-analyzer/utils/constants.d.ts +0 -1
  224. package/dist/server/modules/codebase-overview-analyzer/utils/constants.js +0 -5
  225. package/dist/server/modules/codebase-overview-analyzer/utils/constants.js.map +0 -1
  226. package/dist/server/modules/codebase-overview-analyzer/utils/path-matcher.d.ts +0 -2
  227. package/dist/server/modules/codebase-overview-analyzer/utils/path-matcher.js +0 -17
  228. package/dist/server/modules/codebase-overview-analyzer/utils/path-matcher.js.map +0 -1
  229. package/dist/server/modules/documents/controllers/documents.controller.d.ts +0 -12
  230. package/dist/server/modules/documents/controllers/documents.controller.js +0 -174
  231. package/dist/server/modules/documents/controllers/documents.controller.js.map +0 -1
  232. package/dist/server/modules/documents/documents.module.d.ts +0 -2
  233. package/dist/server/modules/documents/documents.module.js +0 -22
  234. package/dist/server/modules/documents/documents.module.js.map +0 -1
  235. package/dist/server/modules/mcp/services/handlers/document-context.d.ts +0 -8
  236. package/dist/server/modules/mcp/services/handlers/document-context.js +0 -3
  237. package/dist/server/modules/mcp/services/handlers/document-context.js.map +0 -1
  238. package/dist/server/modules/mcp/services/handlers/document-tools.d.ts +0 -6
  239. package/dist/server/modules/mcp/services/handlers/document-tools.js +0 -109
  240. package/dist/server/modules/mcp/services/handlers/document-tools.js.map +0 -1
  241. package/dist/server/modules/mcp/services/utils/document-link-resolver.d.ts +0 -10
  242. package/dist/server/modules/mcp/services/utils/document-link-resolver.js +0 -124
  243. package/dist/server/modules/mcp/services/utils/document-link-resolver.js.map +0 -1
  244. package/dist/server/modules/mcp/tool-descriptors/document.bindings.d.ts +0 -1
  245. package/dist/server/modules/mcp/tool-descriptors/document.bindings.js +0 -19
  246. package/dist/server/modules/mcp/tool-descriptors/document.bindings.js.map +0 -1
  247. package/dist/server/modules/mcp/tool-descriptors/document.metadata.d.ts +0 -2
  248. package/dist/server/modules/mcp/tool-descriptors/document.metadata.js +0 -96
  249. package/dist/server/modules/mcp/tool-descriptors/document.metadata.js.map +0 -1
  250. package/dist/server/modules/storage/local/delegates/document.delegate.d.ts +0 -18
  251. package/dist/server/modules/storage/local/delegates/document.delegate.js +0 -275
  252. package/dist/server/modules/storage/local/delegates/document.delegate.js.map +0 -1
  253. package/dist/server/ui/assets/ReviewDetailPage-B6RB_uEX.js +0 -1
  254. package/dist/server/ui/assets/ReviewsPage-6iPnGQ1T.js +0 -6
  255. package/dist/server/ui/assets/index-CV8ydm7w.css +0 -32
  256. package/dist/server/ui/assets/index-DgajOeEy.js +0 -1197
  257. package/dist/server/ui/assets/useReviewSubscription-BfcypysB.js +0 -69
@@ -1,6 +1,7 @@
1
1
  import { OnModuleDestroy, OnModuleInit } from '@nestjs/common';
2
2
  import type { SessionReaderAdapter, SessionSourceRef } from '../adapters/session-reader-adapter.interface';
3
3
  import type { UnifiedSession } from '../dtos/unified-session.types';
4
+ import { type FileContentAnchors } from './bounded-anchor-proof';
4
5
  import { MetricsService } from '../../metrics/services/metrics.service';
5
6
  import type { CacheStats } from '../../metrics/types/metrics.types';
6
7
  import type { UnifiedChunk } from '../dtos/unified-chunk.types';
@@ -33,7 +34,7 @@ export interface SessionCacheEntry {
33
34
  lastSize: number;
34
35
  lastMtime: number;
35
36
  fileIdentity?: string;
36
- fileContentDigest?: string;
37
+ fileContentAnchors?: FileContentAnchors;
37
38
  sourceVersion: number;
38
39
  freshnessToken: unknown;
39
40
  lastAccessedAt: number;
@@ -42,6 +43,7 @@ export interface SessionCacheEntry {
42
43
  chunks?: CachedChunks;
43
44
  dto?: CachedTranscriptDto;
44
45
  boundaryFold: boolean;
46
+ continuationState?: unknown;
45
47
  }
46
48
  export type SourceChangeKind = 'cache-hit' | 'same-file-append' | 'file-replacement' | 'file-truncation' | 'same-file-rewrite' | 'db-update' | 'unknown-full-parse';
47
49
  export interface GetOrParseResult {
@@ -53,7 +55,25 @@ export interface GetOrParseResult {
53
55
  lastMtime: number;
54
56
  sourceVersion: number;
55
57
  boundaryFold: boolean;
58
+ fileContentAnchors?: FileContentAnchors;
59
+ continuationState?: unknown;
56
60
  }
61
+ export interface PreParseGeneration {
62
+ sourceVersion: number;
63
+ messageCount: number;
64
+ chunkCount: number;
65
+ }
66
+ export type RefreshIfPresentResult = {
67
+ present: false;
68
+ lastFullParse?: {
69
+ seq: number;
70
+ durationMs: number;
71
+ };
72
+ } | {
73
+ present: true;
74
+ preParse: PreParseGeneration;
75
+ result: GetOrParseResult;
76
+ };
57
77
  export declare class SessionCacheService implements OnModuleDestroy, OnModuleInit {
58
78
  private readonly metricsService;
59
79
  private readonly logger;
@@ -68,6 +88,8 @@ export declare class SessionCacheService implements OnModuleDestroy, OnModuleIni
68
88
  private dtoMisses;
69
89
  private budgetUsedBytes;
70
90
  private evictions;
91
+ private fullParseSeq;
92
+ private readonly fullParseCosts;
71
93
  private idleSweepTimer?;
72
94
  private readonly config;
73
95
  constructor(metricsService: MetricsService, config?: TranscriptCacheConfig);
@@ -80,10 +102,17 @@ export declare class SessionCacheService implements OnModuleDestroy, OnModuleIni
80
102
  getOrParse(sessionId: string, source: string | SessionSourceRef, adapter: SessionReaderAdapter): Promise<UnifiedSession>;
81
103
  getOrParseWithMeta(sessionId: string, source: string | SessionSourceRef, adapter: SessionReaderAdapter): Promise<GetOrParseResult>;
82
104
  private getOrParseResult;
105
+ refreshIfPresent(sessionId: string, source: string | SessionSourceRef, adapter: SessionReaderAdapter): Promise<RefreshIfPresentResult>;
106
+ private resolveIfPresentFlight;
107
+ private toRefreshResult;
83
108
  private startParseFlight;
84
109
  private sharedResult;
110
+ private timedFullParse;
111
+ private recordFullParse;
85
112
  private parseSession;
86
113
  getEntry(sessionId: string): SessionCacheEntry | undefined;
114
+ private preParseGeneration;
115
+ private preParseFromResult;
87
116
  getChunks(sessionId: string, sourceVersion: number): UnifiedChunk[] | undefined;
88
117
  setChunks(sessionId: string, sourceVersion: number, chunks: UnifiedChunk[]): void;
89
118
  getDto(sessionId: string, maxToolResultLength: number, enrichmentFingerprint: string): CachedTranscriptDto | undefined;
@@ -104,12 +133,12 @@ export declare class SessionCacheService implements OnModuleDestroy, OnModuleIni
104
133
  private estimateSourceWeight;
105
134
  private withoutDerivedChunks;
106
135
  private foldLeadingContinuationIntoCachedTail;
107
- private mergeMetrics;
108
136
  private mergeWarnings;
109
137
  private statFile;
110
138
  private classifyUnsafeFileChange;
111
- private tryHashFileContent;
112
- private hashFileContent;
139
+ private tryHashFileAnchors;
140
+ private resolveStoredAnchors;
141
+ private snapshotEndsOnLineBoundary;
113
142
  private toSourceRef;
114
143
  private sourceIdentity;
115
144
  private computeFreshness;
@@ -51,15 +51,17 @@ exports.getTranscriptCacheConfig = getTranscriptCacheConfig;
51
51
  const common_1 = require("@nestjs/common");
52
52
  const node_crypto_1 = require("node:crypto");
53
53
  const fs = __importStar(require("node:fs/promises"));
54
- const estimate_content_tokens_1 = require("../adapters/utils/estimate-content-tokens");
55
- const tool_result_fold_1 = require("../adapters/utils/tool-result-fold");
56
54
  const coalesce_turns_1 = require("../adapters/utils/coalesce-turns");
55
+ const metrics_merge_1 = require("./metrics-merge");
56
+ const bounded_anchor_proof_1 = require("./bounded-anchor-proof");
57
+ const bounded_line_read_1 = require("../parsers/bounded-line-read");
57
58
  const metrics_service_1 = require("../../metrics/services/metrics.service");
59
+ const chunk_builder_1 = require("../builders/chunk-builder");
58
60
  const DEFAULT_CACHE_IDLE_TTL_MS = 10 * 60 * 1_000;
59
61
  const DEFAULT_CACHE_SWEEP_INTERVAL_MS = 60_000;
60
62
  const DEFAULT_CACHE_BUDGET_BYTES = 64 * 1024 * 1024;
61
63
  const SAFE_INTEGER_LOW_BITS = 0x20_0000;
62
- const FILE_HASH_CHUNK_BYTES = 64 * 1024;
64
+ const FULL_PARSE_COST_CAP = 256;
63
65
  function fileSourceVersion(stat) {
64
66
  const digest = (0, node_crypto_1.createHash)('sha256')
65
67
  .update(`${stat.dev}:${stat.ino}:${stat.size}:${stat.mtimeMs}`)
@@ -88,6 +90,8 @@ let SessionCacheService = SessionCacheService_1 = class SessionCacheService {
88
90
  dtoMisses = 0;
89
91
  budgetUsedBytes = 0;
90
92
  evictions = 0;
93
+ fullParseSeq = 0;
94
+ fullParseCosts = new Map();
91
95
  idleSweepTimer;
92
96
  config;
93
97
  constructor(metricsService, config) {
@@ -106,6 +110,7 @@ let SessionCacheService = SessionCacheService_1 = class SessionCacheService {
106
110
  this.idleSweepTimer = undefined;
107
111
  }
108
112
  this.clear();
113
+ this.fullParseCosts.clear();
109
114
  }
110
115
  getCacheStats() {
111
116
  const total = this.hits + this.misses;
@@ -190,26 +195,77 @@ let SessionCacheService = SessionCacheService_1 = class SessionCacheService {
190
195
  if (sameSource)
191
196
  throw error;
192
197
  }
193
- if (sameSource && snapshot && flight.generation > arrivalGeneration) {
194
- return this.sharedResult(snapshot.result);
198
+ const shareable = snapshot && !snapshot.absent ? snapshot : undefined;
199
+ if (sameSource && shareable && flight.generation > arrivalGeneration) {
200
+ return this.sharedResult(shareable.result);
195
201
  }
196
202
  const next = flight.next ?? this.parseFlights.get(sessionId);
197
203
  if (next) {
198
204
  flight = next;
199
205
  continue;
200
206
  }
201
- const refresh = this.startParseFlight(sessionId, source, adapter, sameSource ? snapshot : undefined);
207
+ const refresh = this.startParseFlight(sessionId, source, adapter, sameSource ? shareable : undefined);
202
208
  flight.next = refresh;
203
209
  return (await refresh.promise).result;
204
210
  }
205
211
  }
206
- startParseFlight(sessionId, source, adapter, previous) {
212
+ async refreshIfPresent(sessionId, source, adapter) {
213
+ const snapshot = await this.resolveIfPresentFlight(sessionId, source, adapter);
214
+ return this.toRefreshResult(sessionId, snapshot);
215
+ }
216
+ async resolveIfPresentFlight(sessionId, source, adapter) {
217
+ const sourceIdentity = this.sourceIdentity(this.toSourceRef(source, adapter));
218
+ const arrivalGeneration = this.flightGeneration;
219
+ const existing = this.parseFlights.get(sessionId);
220
+ if (!existing) {
221
+ return this.startParseFlight(sessionId, source, adapter, undefined, 'ifPresent').promise;
222
+ }
223
+ let flight = existing;
224
+ for (;;) {
225
+ const sameSource = flight.sourceIdentity === sourceIdentity;
226
+ let snapshot;
227
+ try {
228
+ snapshot = await flight.promise;
229
+ }
230
+ catch {
231
+ }
232
+ const shareable = snapshot && !snapshot.absent ? snapshot : undefined;
233
+ if (sameSource && shareable && flight.generation > arrivalGeneration) {
234
+ return shareable;
235
+ }
236
+ const next = flight.next ?? this.parseFlights.get(sessionId);
237
+ if (next) {
238
+ flight = next;
239
+ continue;
240
+ }
241
+ const refresh = this.startParseFlight(sessionId, source, adapter, sameSource ? shareable : undefined, 'ifPresent');
242
+ flight.next = refresh;
243
+ return refresh.promise;
244
+ }
245
+ }
246
+ toRefreshResult(sessionId, snapshot) {
247
+ if (snapshot.absent || !snapshot.result) {
248
+ const record = this.fullParseCosts.get(sessionId);
249
+ return record
250
+ ? { present: false, lastFullParse: { seq: record.seq, durationMs: record.durationMs } }
251
+ : { present: false };
252
+ }
253
+ if (snapshot.preParse) {
254
+ return { present: true, preParse: snapshot.preParse, result: snapshot.result };
255
+ }
256
+ return {
257
+ present: true,
258
+ preParse: this.preParseFromResult(snapshot.result),
259
+ result: this.sharedResult(snapshot.result),
260
+ };
261
+ }
262
+ startParseFlight(sessionId, source, adapter, previous, mode = 'always') {
207
263
  const sourceIdentity = this.sourceIdentity(this.toSourceRef(source, adapter));
208
264
  const flight = {
209
265
  sourceIdentity,
210
266
  generation: ++this.flightGeneration,
211
267
  promise: Promise.resolve()
212
- .then(() => this.parseSession(sessionId, source, adapter, sourceIdentity, previous))
268
+ .then(() => this.parseSession(sessionId, source, adapter, sourceIdentity, previous, mode))
213
269
  .finally(() => {
214
270
  if (this.parseFlights.get(sessionId) === flight) {
215
271
  this.parseFlights.delete(sessionId);
@@ -223,30 +279,57 @@ let SessionCacheService = SessionCacheService_1 = class SessionCacheService {
223
279
  this.hits += 1;
224
280
  return { ...result, cacheHit: true, sourceChangeKind: 'cache-hit', boundaryFold: false };
225
281
  }
226
- async parseSession(sessionId, source, adapter, sourceIdentity, previous) {
282
+ async timedFullParse(sessionId, adapter, filePath, threadRef) {
283
+ const startedAt = performance.now();
284
+ const session = threadRef
285
+ ? await adapter.parseFullSession(filePath, threadRef)
286
+ : await adapter.parseFullSession(filePath);
287
+ this.recordFullParse(sessionId, performance.now() - startedAt);
288
+ return session;
289
+ }
290
+ recordFullParse(sessionId, durationMs) {
291
+ this.fullParseSeq += 1;
292
+ if (!this.fullParseCosts.has(sessionId) && this.fullParseCosts.size >= FULL_PARSE_COST_CAP) {
293
+ const oldest = this.fullParseCosts.keys().next().value;
294
+ if (oldest !== undefined)
295
+ this.fullParseCosts.delete(oldest);
296
+ }
297
+ this.fullParseCosts.set(sessionId, { seq: this.fullParseSeq, durationMs });
298
+ }
299
+ async parseSession(sessionId, source, adapter, sourceIdentity, previous, mode = 'always') {
227
300
  const now = Date.now();
228
301
  const ref = this.toSourceRef(source, adapter);
229
302
  const threadRef = typeof source !== 'string' ? ref : undefined;
230
303
  let freshness = await this.computeFreshness(ref, adapter);
231
304
  const retained = this.cache.get(sessionId);
232
305
  const cached = retained?.sourceIdentity === sourceIdentity ? retained : undefined;
306
+ if (mode === 'ifPresent' && !cached) {
307
+ return { absent: true, freshnessToken: freshness.token };
308
+ }
309
+ const preParse = mode === 'ifPresent' && cached ? this.preParseGeneration(cached) : undefined;
233
310
  if (previous && JSON.stringify(previous.freshnessToken) === JSON.stringify(freshness.token)) {
234
- if (cached?.session === previous.result.session)
311
+ if (cached && cached.session === previous.result?.session)
235
312
  this.touchLru(sessionId, cached, now);
236
- return { result: this.sharedResult(previous.result), freshnessToken: freshness.token };
313
+ return {
314
+ result: this.sharedResult(previous.result),
315
+ freshnessToken: freshness.token,
316
+ preParse,
317
+ };
237
318
  }
238
319
  const freshSession = this.takeFreshCachedSession(sessionId, cached, freshness.token, now);
239
320
  if (freshSession && cached) {
240
321
  return {
241
322
  result: this.toGetOrParseResult(freshSession, cached, true, 'cache-hit'),
242
323
  freshnessToken: freshness.token,
324
+ preParse,
243
325
  };
244
326
  }
245
327
  this.misses += 1;
246
328
  let session;
247
329
  let lastOffset;
248
330
  let boundaryFold = false;
249
- let acceptedFileDigests;
331
+ let acceptedFileAnchors;
332
+ let continuationState;
250
333
  const sameFileIdentity = ref.kind !== 'file' ||
251
334
  (cached?.fileIdentity !== undefined && cached.fileIdentity === freshness.fileIdentity);
252
335
  const fileReplaced = cached !== undefined && ref.kind === 'file' && !sameFileIdentity;
@@ -254,12 +337,12 @@ let SessionCacheService = SessionCacheService_1 = class SessionCacheService {
254
337
  ref.kind === 'file' &&
255
338
  sameFileIdentity &&
256
339
  freshness.size > cached.lastSize;
257
- const growthDigests = sameIdentityGrowth && cached.fileContentDigest !== undefined
258
- ? await this.tryHashFileContent(ref.filePath, freshness, cached.lastOffset)
340
+ const growthAnchors = sameIdentityGrowth && cached.fileContentAnchors !== undefined
341
+ ? await this.tryHashFileAnchors(ref.filePath, freshness, cached.lastOffset)
259
342
  : undefined;
260
343
  const provenSameFileAppend = sameIdentityGrowth &&
261
- cached.fileContentDigest !== undefined &&
262
- growthDigests?.prefixDigest === cached.fileContentDigest;
344
+ cached.fileContentAnchors !== undefined &&
345
+ (0, bounded_anchor_proof_1.anchorsEqual)(growthAnchors, cached.fileContentAnchors);
263
346
  let sourceChangeKind = !cached
264
347
  ? 'unknown-full-parse'
265
348
  : ref.kind === 'db'
@@ -273,26 +356,36 @@ let SessionCacheService = SessionCacheService_1 = class SessionCacheService {
273
356
  : freshness.size < cached.lastSize
274
357
  ? 'file-truncation'
275
358
  : 'same-file-rewrite';
276
- if (cached && provenSameFileAppend && growthDigests) {
359
+ if (cached && provenSameFileAppend && cached.fileContentAnchors) {
277
360
  this.logger.debug({ sessionId, lastOffset: cached.lastOffset, currentSize: freshness.size }, 'Incremental parse (source grew)');
278
361
  const incOptions = { byteOffset: cached.lastOffset, includeToolCalls: true };
362
+ if (adapter.incrementalMode === 'delta') {
363
+ incOptions.endByteOffset = freshness.size;
364
+ }
365
+ if (cached.continuationState !== undefined) {
366
+ incOptions.continuationState = cached.continuationState;
367
+ }
279
368
  let tentativeResult = threadRef
280
369
  ? await adapter.parseIncremental(ref.filePath, incOptions, threadRef)
281
370
  : await adapter.parseIncremental(ref.filePath, incOptions);
282
- const postParseDigests = await this.tryHashFileContent(ref.filePath, freshness, freshness.size);
283
- if (postParseDigests?.fullDigest !== growthDigests.fullDigest) {
371
+ const newOffset = tentativeResult.nextByteOffset;
372
+ const prefixHeld = newOffset >= cached.lastOffset &&
373
+ (0, bounded_anchor_proof_1.anchorsEqual)(await this.tryHashFileAnchors(ref.filePath, freshness, cached.lastOffset, true), cached.fileContentAnchors);
374
+ const proofAnchors = prefixHeld
375
+ ? await this.tryHashFileAnchors(ref.filePath, freshness, newOffset, true)
376
+ : undefined;
377
+ if (proofAnchors === undefined) {
284
378
  this.logger.debug({ sessionId }, 'Discarding incremental parse because its proven file revision drifted');
285
379
  tentativeResult = undefined;
286
380
  freshness = await this.computeFreshness(ref, adapter);
287
381
  sourceChangeKind = this.classifyUnsafeFileChange(cached, freshness);
288
- session = threadRef
289
- ? await adapter.parseFullSession(ref.filePath, threadRef)
290
- : await adapter.parseFullSession(ref.filePath);
382
+ session = await this.timedFullParse(sessionId, adapter, ref.filePath, threadRef);
291
383
  lastOffset = freshness.size;
292
384
  }
293
385
  else {
294
386
  const acceptedResult = tentativeResult;
295
- acceptedFileDigests = postParseDigests;
387
+ acceptedFileAnchors = proofAnchors;
388
+ continuationState = acceptedResult.continuationState;
296
389
  const newMessages = acceptedResult.entries;
297
390
  if (adapter.incrementalMode === 'snapshot') {
298
391
  const snapshotMetrics = acceptedResult.metrics ?? cached.session.metrics;
@@ -309,7 +402,7 @@ let SessionCacheService = SessionCacheService_1 = class SessionCacheService {
309
402
  boundaryFold = folded.tailMutatedWithoutNewMessage;
310
403
  const mergedMessages = folded.merged;
311
404
  const mergedMetrics = acceptedResult.metrics
312
- ? this.mergeMetrics(cached.session.metrics, acceptedResult.metrics, mergedMessages)
405
+ ? (0, metrics_merge_1.mergeMetrics)(cached.session.metrics, acceptedResult.metrics, (0, metrics_merge_1.deriveMergeInputsFromMessages)(cached.session.metrics, mergedMessages))
313
406
  : cached.session.metrics;
314
407
  session = {
315
408
  ...cached.session,
@@ -329,9 +422,7 @@ let SessionCacheService = SessionCacheService_1 = class SessionCacheService {
329
422
  else if (cached && freshness.size < cached.lastSize) {
330
423
  this.logger.debug({ sessionId }, 'Full reparse (source truncated)');
331
424
  }
332
- session = threadRef
333
- ? await adapter.parseFullSession(ref.filePath, threadRef)
334
- : await adapter.parseFullSession(ref.filePath);
425
+ session = await this.timedFullParse(sessionId, adapter, ref.filePath, threadRef);
335
426
  lastOffset = freshness.size;
336
427
  }
337
428
  const coalesced = (0, coalesce_turns_1.coalesceAssistantTurns)(session);
@@ -339,11 +430,7 @@ let SessionCacheService = SessionCacheService_1 = class SessionCacheService {
339
430
  session = { ...session, messages: coalesced.messages, metrics: coalesced.metrics };
340
431
  }
341
432
  session = this.withoutDerivedChunks(session);
342
- const fileContentDigest = ref.kind === 'file'
343
- ? lastOffset === freshness.size && acceptedFileDigests !== undefined
344
- ? acceptedFileDigests.fullDigest
345
- : (await this.tryHashFileContent(ref.filePath, freshness, lastOffset))?.prefixDigest
346
- : undefined;
433
+ const fileContentAnchors = await this.resolveStoredAnchors(ref, freshness, lastOffset, acceptedFileAnchors);
347
434
  this.deleteEntry(sessionId);
348
435
  const sourceWeightBytes = this.estimateSourceWeight(ref, session, freshness.size);
349
436
  const entry = {
@@ -353,13 +440,14 @@ let SessionCacheService = SessionCacheService_1 = class SessionCacheService {
353
440
  lastSize: freshness.size,
354
441
  lastMtime: freshness.mtimeMs,
355
442
  fileIdentity: freshness.fileIdentity,
356
- fileContentDigest,
443
+ fileContentAnchors,
357
444
  sourceVersion: freshness.sourceVersion,
358
445
  freshnessToken: freshness.token,
359
446
  lastAccessedAt: now,
360
447
  sourceWeightBytes,
361
448
  weights: { parsed: sourceWeightBytes * 2, chunks: 0, dto: 0 },
362
449
  boundaryFold,
450
+ continuationState,
363
451
  };
364
452
  this.cache.set(sessionId, entry);
365
453
  this.budgetUsedBytes += entry.weights.parsed;
@@ -367,11 +455,26 @@ let SessionCacheService = SessionCacheService_1 = class SessionCacheService {
367
455
  return {
368
456
  result: this.toGetOrParseResult(session, entry, false, sourceChangeKind),
369
457
  freshnessToken: freshness.token,
458
+ preParse,
370
459
  };
371
460
  }
372
461
  getEntry(sessionId) {
373
462
  return this.cache.get(sessionId);
374
463
  }
464
+ preParseGeneration(entry) {
465
+ return {
466
+ sourceVersion: entry.sourceVersion,
467
+ messageCount: entry.session.messages.length,
468
+ chunkCount: entry.chunks?.chunks.length ?? (0, chunk_builder_1.buildChunks)(entry.session.messages).length,
469
+ };
470
+ }
471
+ preParseFromResult(result) {
472
+ return {
473
+ sourceVersion: result.sourceVersion,
474
+ messageCount: result.session.messages.length,
475
+ chunkCount: result.session.chunks?.length ?? (0, chunk_builder_1.buildChunks)(result.session.messages).length,
476
+ };
477
+ }
375
478
  getChunks(sessionId, sourceVersion) {
376
479
  const entry = this.cache.get(sessionId);
377
480
  if (!entry?.chunks || entry.chunks.sourceVersion !== sourceVersion) {
@@ -473,6 +576,8 @@ let SessionCacheService = SessionCacheService_1 = class SessionCacheService {
473
576
  lastMtime: entry.lastMtime,
474
577
  sourceVersion: entry.sourceVersion,
475
578
  boundaryFold: cacheHit ? false : entry.boundaryFold,
579
+ fileContentAnchors: entry.fileContentAnchors,
580
+ continuationState: entry.continuationState,
476
581
  };
477
582
  }
478
583
  touchLru(sessionId, entry, now) {
@@ -516,27 +621,7 @@ let SessionCacheService = SessionCacheService_1 = class SessionCacheService {
516
621
  }
517
622
  foldLeadingContinuationIntoCachedTail(cachedMessages, newMessages) {
518
623
  const tail = cachedMessages[cachedMessages.length - 1];
519
- if (!tail || tail.role !== 'assistant' || newMessages.length === 0) {
520
- return { merged: [...cachedMessages, ...newMessages], tailMutatedWithoutNewMessage: false };
521
- }
522
- let foldCount = 0;
523
- let tailStopReason = tail.stopReason ?? null;
524
- while (foldCount < newMessages.length) {
525
- const m = newMessages[foldCount];
526
- if (m.isSidechain !== tail.isSidechain)
527
- break;
528
- if (m.isCompactSummary)
529
- break;
530
- const isToolResult = (0, tool_result_fold_1.isToolResultOnlyMessage)(m);
531
- const isContinuationAssistant = m.role === 'assistant';
532
- if (!isToolResult && !isContinuationAssistant)
533
- break;
534
- if (isContinuationAssistant && tailStopReason === 'end_turn')
535
- break;
536
- if (isContinuationAssistant)
537
- tailStopReason = m.stopReason ?? null;
538
- foldCount += 1;
539
- }
624
+ const { foldCount, tailMutatedWithoutNewMessage } = (0, metrics_merge_1.computeLeadingContinuationFold)((0, metrics_merge_1.describeTail)(tail), newMessages);
540
625
  if (foldCount === 0) {
541
626
  return { merged: [...cachedMessages, ...newMessages], tailMutatedWithoutNewMessage: false };
542
627
  }
@@ -552,51 +637,7 @@ let SessionCacheService = SessionCacheService_1 = class SessionCacheService {
552
637
  const remaining = newMessages.slice(foldCount);
553
638
  return {
554
639
  merged: [...cachedMessages.slice(0, -1), foldedTail, ...remaining],
555
- tailMutatedWithoutNewMessage: remaining.length === 0,
556
- };
557
- }
558
- mergeMetrics(existing, incremental, allMessages) {
559
- const inputTokens = existing.inputTokens + incremental.inputTokens;
560
- const outputTokens = existing.outputTokens + incremental.outputTokens;
561
- const cacheReadTokens = existing.cacheReadTokens + incremental.cacheReadTokens;
562
- const cacheCreationTokens = existing.cacheCreationTokens + incremental.cacheCreationTokens;
563
- const totalTokens = inputTokens + outputTokens + cacheReadTokens + cacheCreationTokens;
564
- let durationMs = existing.durationMs;
565
- if (allMessages.length >= 2) {
566
- durationMs =
567
- allMessages[allMessages.length - 1].timestamp.getTime() -
568
- allMessages[0].timestamp.getTime();
569
- }
570
- const modelsSet = new Set();
571
- if (existing.primaryModel)
572
- modelsSet.add(existing.primaryModel);
573
- if (incremental.primaryModel)
574
- modelsSet.add(incremental.primaryModel);
575
- if (existing.modelsUsed)
576
- existing.modelsUsed.forEach((m) => modelsSet.add(m));
577
- if (incremental.modelsUsed)
578
- incremental.modelsUsed.forEach((m) => modelsSet.add(m));
579
- const modelsUsed = modelsSet.size > 1 ? Array.from(modelsSet) : undefined;
580
- return {
581
- inputTokens,
582
- outputTokens,
583
- cacheReadTokens,
584
- cacheCreationTokens,
585
- totalTokens,
586
- costUsd: existing.costUsd + incremental.costUsd,
587
- primaryModel: incremental.primaryModel ?? existing.primaryModel,
588
- modelsUsed,
589
- isOngoing: incremental.isOngoing,
590
- visibleContextTokens: (0, estimate_content_tokens_1.estimateVisibleFromMessages)(allMessages),
591
- totalContextTokens: incremental.totalContextTokens > 0
592
- ? incremental.totalContextTokens
593
- : existing.totalContextTokens,
594
- contextWindowTokens: incremental.contextWindowTokens ?? existing.contextWindowTokens,
595
- messageCount: allMessages.length,
596
- durationMs,
597
- totalContextConsumption: existing.totalContextConsumption,
598
- compactionCount: existing.compactionCount,
599
- phaseBreakdowns: existing.phaseBreakdowns,
640
+ tailMutatedWithoutNewMessage,
600
641
  };
601
642
  }
602
643
  mergeWarnings(existing, incremental) {
@@ -628,59 +669,31 @@ let SessionCacheService = SessionCacheService_1 = class SessionCacheService {
628
669
  }
629
670
  return 'same-file-rewrite';
630
671
  }
631
- async tryHashFileContent(filePath, expected, prefixLength) {
672
+ async tryHashFileAnchors(filePath, expected, offset, allowGrowth = false) {
632
673
  try {
633
- return await this.hashFileContent(filePath, expected, prefixLength);
674
+ return await (0, bounded_anchor_proof_1.hashFileAnchors)(filePath, expected, offset, allowGrowth);
634
675
  }
635
676
  catch (error) {
636
- this.logger.debug({ error, filePath }, 'File prefix proof unavailable — append is unsafe');
677
+ this.logger.debug({ error, filePath }, 'File anchor proof unavailable — append is unsafe');
637
678
  return undefined;
638
679
  }
639
680
  }
640
- async hashFileContent(filePath, expected, prefixLength) {
641
- if (!Number.isSafeInteger(prefixLength) ||
642
- prefixLength < 0 ||
643
- prefixLength > expected.size ||
644
- expected.fileIdentity === undefined) {
645
- throw new Error('Invalid file prefix proof bounds');
646
- }
647
- const handle = await fs.open(filePath, 'r');
648
- const assertStableSnapshot = async () => {
649
- const current = await handle.stat();
650
- if (current.size !== expected.size ||
651
- current.mtime.getTime() !== expected.mtimeMs ||
652
- `${current.dev}:${current.ino}` !== expected.fileIdentity) {
653
- throw new Error('File changed while computing append proof');
654
- }
655
- };
681
+ async resolveStoredAnchors(ref, freshness, lastOffset, acceptedFileAnchors) {
682
+ if (ref.kind !== 'file')
683
+ return undefined;
684
+ if (acceptedFileAnchors)
685
+ return acceptedFileAnchors;
686
+ if (!(await this.snapshotEndsOnLineBoundary(ref.filePath, lastOffset)))
687
+ return undefined;
688
+ return this.tryHashFileAnchors(ref.filePath, freshness, lastOffset);
689
+ }
690
+ async snapshotEndsOnLineBoundary(filePath, offset) {
656
691
  try {
657
- await assertStableSnapshot();
658
- const prefixHash = (0, node_crypto_1.createHash)('sha256');
659
- const fullHash = (0, node_crypto_1.createHash)('sha256');
660
- const buffer = Buffer.allocUnsafe(Math.min(FILE_HASH_CHUNK_BYTES, Math.max(1, expected.size)));
661
- let position = 0;
662
- while (position < expected.size) {
663
- const requested = Math.min(buffer.byteLength, expected.size - position);
664
- const { bytesRead } = await handle.read(buffer, 0, requested, position);
665
- if (bytesRead === 0) {
666
- throw new Error('File ended while computing append proof');
667
- }
668
- const chunk = buffer.subarray(0, bytesRead);
669
- fullHash.update(chunk);
670
- const prefixBytes = Math.min(bytesRead, Math.max(0, prefixLength - position));
671
- if (prefixBytes > 0) {
672
- prefixHash.update(chunk.subarray(0, prefixBytes));
673
- }
674
- position += bytesRead;
675
- }
676
- await assertStableSnapshot();
677
- return {
678
- prefixDigest: prefixHash.digest('hex'),
679
- fullDigest: fullHash.digest('hex'),
680
- };
692
+ return (await (0, bounded_line_read_1.lastCompleteLineEnd)(filePath, 0, offset)) === offset;
681
693
  }
682
- finally {
683
- await handle.close();
694
+ catch (error) {
695
+ this.logger.debug({ error, filePath }, 'Line-boundary probe failed — withholding append proof');
696
+ return false;
684
697
  }
685
698
  }
686
699
  toSourceRef(source, adapter) {