@jingyi0605/codingns 0.8.5 → 0.9.5

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 (515) hide show
  1. package/bin/codingns.mjs +7 -156
  2. package/dist/public/assets/AdaptiveButlerPage-kkJDsnCO.js +2 -0
  3. package/dist/public/assets/{App-BOHBGFOd.js → App-DrNI9lWA.js} +6 -6
  4. package/dist/public/assets/{BootstrapPage-BxHQT4nA.js → BootstrapPage-QgVH5Mps.js} +1 -1
  5. package/dist/public/assets/{ConversationPage-DWFsF6BB.js → ConversationPage-DVk8VfIj.js} +6 -6
  6. package/dist/public/assets/{DesktopDetachPreviewPage-DOgEjYEf.js → DesktopDetachPreviewPage-BhfP0TpH.js} +1 -1
  7. package/dist/public/assets/DesktopModal-DRmDrv0S.js +1 -0
  8. package/dist/public/assets/DesktopWindowPage-DNbJXnSs.js +2 -0
  9. package/dist/public/assets/FileContextPanel---fLO4ve.js +1 -0
  10. package/dist/public/assets/GitSidebar-sXUE0TqT.js +6 -0
  11. package/dist/public/assets/MobileCreateSessionSheet-BftZ5pvb.js +1 -0
  12. package/dist/public/assets/MobileSheet-nw5SCa3N.js +1 -0
  13. package/dist/public/assets/{MobileTopHeaderFrame-lcp2GscV.js → MobileTopHeaderFrame-DH_D02Wy.js} +1 -1
  14. package/dist/public/assets/MobileWorkspaceSwitcherHeader-2K406G5p.js +1 -0
  15. package/dist/public/assets/{PluginAccessOverview-DGcKAMQl.js → PluginAccessOverview-BVJihw3D.js} +1 -1
  16. package/dist/public/assets/PluginContainerPage-CR4vStvr.js +1 -0
  17. package/dist/public/assets/{PluginDetailPage-CAJ7LFpD.js → PluginDetailPage-CrMX0Mnm.js} +1 -1
  18. package/dist/public/assets/{PluginsListPage-BxZG1NyT.js → PluginsListPage-FtIL71Yg.js} +1 -1
  19. package/dist/public/assets/{RelayConnectEntryPage-CfNO_TIl.js → RelayConnectEntryPage-Bt1apX53.js} +1 -1
  20. package/dist/public/assets/{ServerSettingsModal-by36Z_5k.js → ServerSettingsModal-D-guzPrI.js} +1 -1
  21. package/dist/public/assets/SessionIndexPage-CX2FppcJ.js +1 -0
  22. package/dist/public/assets/SettingsPage-BI2Olcvr.js +2 -0
  23. package/dist/public/assets/TerminalManagerPanel-B5MKGPy-.js +1 -0
  24. package/dist/public/assets/{TerminalPage-C4LNoPBp.js → TerminalPage-C2dTNGHK.js} +2 -2
  25. package/dist/public/assets/TerminalRuntimeFallbackModal-DAqOxFD8.js +1 -0
  26. package/dist/public/assets/{ToolFilesPage-47zbdgTW.js → ToolFilesPage-IsNwyE6T.js} +1 -1
  27. package/dist/public/assets/{ToolGitPage-Fuk_b_jg.js → ToolGitPage-BK1JBERN.js} +1 -1
  28. package/dist/public/assets/{ToolProcessesPage-sWSMWD-9.js → ToolProcessesPage-DwTYUQCK.js} +1 -1
  29. package/dist/public/assets/{ToolsHomePage-R1mZlbZi.js → ToolsHomePage-BLOy7lPg.js} +1 -1
  30. package/dist/public/assets/{WorkbenchLandingPage-CqmiFH2u.js → WorkbenchLandingPage-CqZKR6EA.js} +1 -1
  31. package/dist/public/assets/WorkbenchLayout-BksVkkFF.css +1 -0
  32. package/dist/public/assets/WorkbenchLayout-CJHQtwuL.js +1022 -0
  33. package/dist/public/assets/{WorkbenchModal-C7qoQElW.js → WorkbenchModal-BM-OeW-b.js} +1 -1
  34. package/dist/public/assets/WorkbenchShellRoute-2bKI6Q9k.js +1 -0
  35. package/dist/public/assets/WorkbenchShellRoute-BjuZD101.css +1 -0
  36. package/dist/public/assets/WorkspaceDebugDetailPage-BMsEN5iG.js +1 -0
  37. package/dist/public/assets/WorkspaceDetailPage-5H9Gosx2.js +1 -0
  38. package/dist/public/assets/WorkspaceHomePage-DQiXKgiP.js +1 -0
  39. package/dist/public/assets/{client-runtime-manager-wmCJZKYd.js → client-runtime-manager-CgPJq21V.js} +1 -1
  40. package/dist/public/assets/index-BARqMVSw.css +1 -0
  41. package/dist/public/assets/index-BUoNjVrY.js +50 -0
  42. package/dist/public/assets/{login-direct-candidate-resolver-BOAgTuUf.js → login-direct-candidate-resolver-CGaxAXV8.js} +1 -1
  43. package/dist/public/assets/{plugin-permission-copy-Cq99cnzV.js → plugin-permission-copy-BR9gWy8b.js} +1 -1
  44. package/dist/public/assets/{plugins-api-BQTV5DOp.js → plugins-api-CdCsrG2e.js} +1 -1
  45. package/dist/public/assets/{preferences-service-DJxbEEeg.js → preferences-service-lOhnlxzP.js} +1 -1
  46. package/dist/public/assets/{relay-entry-D-LfvdiX.js → relay-entry-CQpxTS8y.js} +1 -1
  47. package/dist/public/assets/{terminal-runtime-meta-BJmy8dyK.js → terminal-runtime-meta-oteTx66X.js} +1 -1
  48. package/dist/public/assets/useRegisteredDebugTemplates-Bu2ykZ6s.js +1 -0
  49. package/dist/public/assets/workbench-navigation-DlgXuFW2.js +1 -0
  50. package/dist/public/index.html +2 -2
  51. package/dist/server/config/env.d.ts +1 -0
  52. package/dist/server/config/env.js +3 -0
  53. package/dist/server/config/env.js.map +1 -1
  54. package/dist/server/middlewares/auth-guard.js +10 -5
  55. package/dist/server/middlewares/auth-guard.js.map +1 -1
  56. package/dist/server/modules/affairs-indexer/contracts/src/errors/app-error.d.ts +11 -0
  57. package/dist/server/modules/affairs-indexer/contracts/src/errors/app-error.js +22 -0
  58. package/dist/server/modules/affairs-indexer/contracts/src/errors/app-error.js.map +1 -0
  59. package/dist/server/modules/affairs-indexer/contracts/src/errors/error-codes.d.ts +23 -0
  60. package/dist/server/modules/affairs-indexer/contracts/src/errors/error-codes.js +23 -0
  61. package/dist/server/modules/affairs-indexer/contracts/src/errors/error-codes.js.map +1 -0
  62. package/dist/server/modules/affairs-indexer/contracts/src/index.d.ts +4 -0
  63. package/dist/server/modules/affairs-indexer/contracts/src/index.js +5 -0
  64. package/dist/server/modules/affairs-indexer/contracts/src/index.js.map +1 -0
  65. package/dist/server/modules/affairs-indexer/contracts/src/types/cli-command-context.d.ts +7 -0
  66. package/dist/server/modules/affairs-indexer/contracts/src/types/cli-command-context.js +2 -0
  67. package/dist/server/modules/affairs-indexer/contracts/src/types/cli-command-context.js.map +1 -0
  68. package/dist/server/modules/affairs-indexer/contracts/src/types/runtime-config.d.ts +16 -0
  69. package/dist/server/modules/affairs-indexer/contracts/src/types/runtime-config.js +2 -0
  70. package/dist/server/modules/affairs-indexer/contracts/src/types/runtime-config.js.map +1 -0
  71. package/dist/server/modules/affairs-indexer/core/src/config/load-runtime-config.d.ts +10 -0
  72. package/dist/server/modules/affairs-indexer/core/src/config/load-runtime-config.js +215 -0
  73. package/dist/server/modules/affairs-indexer/core/src/config/load-runtime-config.js.map +1 -0
  74. package/dist/server/modules/affairs-indexer/core/src/index.d.ts +31 -0
  75. package/dist/server/modules/affairs-indexer/core/src/index.js +32 -0
  76. package/dist/server/modules/affairs-indexer/core/src/index.js.map +1 -0
  77. package/dist/server/modules/affairs-indexer/core/src/logging/structured-logger.d.ts +20 -0
  78. package/dist/server/modules/affairs-indexer/core/src/logging/structured-logger.js +47 -0
  79. package/dist/server/modules/affairs-indexer/core/src/logging/structured-logger.js.map +1 -0
  80. package/dist/server/modules/affairs-indexer/core/src/parser/base-complex-parser-adapter.d.ts +17 -0
  81. package/dist/server/modules/affairs-indexer/core/src/parser/base-complex-parser-adapter.js +63 -0
  82. package/dist/server/modules/affairs-indexer/core/src/parser/base-complex-parser-adapter.js.map +1 -0
  83. package/dist/server/modules/affairs-indexer/core/src/parser/complex-document-skip-adapter.d.ts +12 -0
  84. package/dist/server/modules/affairs-indexer/core/src/parser/complex-document-skip-adapter.js +42 -0
  85. package/dist/server/modules/affairs-indexer/core/src/parser/complex-document-skip-adapter.js.map +1 -0
  86. package/dist/server/modules/affairs-indexer/core/src/parser/csv-parser-adapter.d.ts +7 -0
  87. package/dist/server/modules/affairs-indexer/core/src/parser/csv-parser-adapter.js +107 -0
  88. package/dist/server/modules/affairs-indexer/core/src/parser/csv-parser-adapter.js.map +1 -0
  89. package/dist/server/modules/affairs-indexer/core/src/parser/document-parser.d.ts +19 -0
  90. package/dist/server/modules/affairs-indexer/core/src/parser/document-parser.js +37 -0
  91. package/dist/server/modules/affairs-indexer/core/src/parser/document-parser.js.map +1 -0
  92. package/dist/server/modules/affairs-indexer/core/src/parser/docx-parser-adapter.d.ts +7 -0
  93. package/dist/server/modules/affairs-indexer/core/src/parser/docx-parser-adapter.js +123 -0
  94. package/dist/server/modules/affairs-indexer/core/src/parser/docx-parser-adapter.js.map +1 -0
  95. package/dist/server/modules/affairs-indexer/core/src/parser/openxml-utils.d.ts +8 -0
  96. package/dist/server/modules/affairs-indexer/core/src/parser/openxml-utils.js +111 -0
  97. package/dist/server/modules/affairs-indexer/core/src/parser/openxml-utils.js.map +1 -0
  98. package/dist/server/modules/affairs-indexer/core/src/parser/parser-adapter.d.ts +42 -0
  99. package/dist/server/modules/affairs-indexer/core/src/parser/parser-adapter.js +2 -0
  100. package/dist/server/modules/affairs-indexer/core/src/parser/parser-adapter.js.map +1 -0
  101. package/dist/server/modules/affairs-indexer/core/src/parser/parser-capability-registry.d.ts +18 -0
  102. package/dist/server/modules/affairs-indexer/core/src/parser/parser-capability-registry.js +91 -0
  103. package/dist/server/modules/affairs-indexer/core/src/parser/parser-capability-registry.js.map +1 -0
  104. package/dist/server/modules/affairs-indexer/core/src/parser/parser-router.d.ts +18 -0
  105. package/dist/server/modules/affairs-indexer/core/src/parser/parser-router.js +59 -0
  106. package/dist/server/modules/affairs-indexer/core/src/parser/parser-router.js.map +1 -0
  107. package/dist/server/modules/affairs-indexer/core/src/parser/parser-skip-repository.d.ts +48 -0
  108. package/dist/server/modules/affairs-indexer/core/src/parser/parser-skip-repository.js +193 -0
  109. package/dist/server/modules/affairs-indexer/core/src/parser/parser-skip-repository.js.map +1 -0
  110. package/dist/server/modules/affairs-indexer/core/src/parser/pdf-parser-adapter.d.ts +7 -0
  111. package/dist/server/modules/affairs-indexer/core/src/parser/pdf-parser-adapter.js +371 -0
  112. package/dist/server/modules/affairs-indexer/core/src/parser/pdf-parser-adapter.js.map +1 -0
  113. package/dist/server/modules/affairs-indexer/core/src/parser/plain-text-parser-adapter.d.ts +10 -0
  114. package/dist/server/modules/affairs-indexer/core/src/parser/plain-text-parser-adapter.js +55 -0
  115. package/dist/server/modules/affairs-indexer/core/src/parser/plain-text-parser-adapter.js.map +1 -0
  116. package/dist/server/modules/affairs-indexer/core/src/parser/plain-text-parser.d.ts +9 -0
  117. package/dist/server/modules/affairs-indexer/core/src/parser/plain-text-parser.js +2 -0
  118. package/dist/server/modules/affairs-indexer/core/src/parser/plain-text-parser.js.map +1 -0
  119. package/dist/server/modules/affairs-indexer/core/src/parser/pptx-parser-adapter.d.ts +7 -0
  120. package/dist/server/modules/affairs-indexer/core/src/parser/pptx-parser-adapter.js +130 -0
  121. package/dist/server/modules/affairs-indexer/core/src/parser/pptx-parser-adapter.js.map +1 -0
  122. package/dist/server/modules/affairs-indexer/core/src/parser/xlsx-parser-adapter.d.ts +7 -0
  123. package/dist/server/modules/affairs-indexer/core/src/parser/xlsx-parser-adapter.js +228 -0
  124. package/dist/server/modules/affairs-indexer/core/src/parser/xlsx-parser-adapter.js.map +1 -0
  125. package/dist/server/modules/affairs-indexer/core/src/repositories/catalog-repository.d.ts +205 -0
  126. package/dist/server/modules/affairs-indexer/core/src/repositories/catalog-repository.js +1471 -0
  127. package/dist/server/modules/affairs-indexer/core/src/repositories/catalog-repository.js.map +1 -0
  128. package/dist/server/modules/affairs-indexer/core/src/repositories/catalog-write-repository.d.ts +161 -0
  129. package/dist/server/modules/affairs-indexer/core/src/repositories/catalog-write-repository.js +1350 -0
  130. package/dist/server/modules/affairs-indexer/core/src/repositories/catalog-write-repository.js.map +1 -0
  131. package/dist/server/modules/affairs-indexer/core/src/scanner/file-scanner.d.ts +32 -0
  132. package/dist/server/modules/affairs-indexer/core/src/scanner/file-scanner.js +208 -0
  133. package/dist/server/modules/affairs-indexer/core/src/scanner/file-scanner.js.map +1 -0
  134. package/dist/server/modules/affairs-indexer/core/src/services/dirty/dirty-scope-resolver.d.ts +30 -0
  135. package/dist/server/modules/affairs-indexer/core/src/services/dirty/dirty-scope-resolver.js +66 -0
  136. package/dist/server/modules/affairs-indexer/core/src/services/dirty/dirty-scope-resolver.js.map +1 -0
  137. package/dist/server/modules/affairs-indexer/core/src/services/export/export-builder.d.ts +33 -0
  138. package/dist/server/modules/affairs-indexer/core/src/services/export/export-builder.js +705 -0
  139. package/dist/server/modules/affairs-indexer/core/src/services/export/export-builder.js.map +1 -0
  140. package/dist/server/modules/affairs-indexer/core/src/services/indexer/allowed-extensions-diff-service.d.ts +80 -0
  141. package/dist/server/modules/affairs-indexer/core/src/services/indexer/allowed-extensions-diff-service.js +193 -0
  142. package/dist/server/modules/affairs-indexer/core/src/services/indexer/allowed-extensions-diff-service.js.map +1 -0
  143. package/dist/server/modules/affairs-indexer/core/src/services/indexer/text-indexer.d.ts +77 -0
  144. package/dist/server/modules/affairs-indexer/core/src/services/indexer/text-indexer.js +467 -0
  145. package/dist/server/modules/affairs-indexer/core/src/services/indexer/text-indexer.js.map +1 -0
  146. package/dist/server/modules/affairs-indexer/core/src/services/mcp/mcp-stdio-server.d.ts +17 -0
  147. package/dist/server/modules/affairs-indexer/core/src/services/mcp/mcp-stdio-server.js +264 -0
  148. package/dist/server/modules/affairs-indexer/core/src/services/mcp/mcp-stdio-server.js.map +1 -0
  149. package/dist/server/modules/affairs-indexer/core/src/services/search/offline-search-service.d.ts +11 -0
  150. package/dist/server/modules/affairs-indexer/core/src/services/search/offline-search-service.js +76 -0
  151. package/dist/server/modules/affairs-indexer/core/src/services/search/offline-search-service.js.map +1 -0
  152. package/dist/server/modules/affairs-indexer/core/src/services/search/search-index-builder.d.ts +26 -0
  153. package/dist/server/modules/affairs-indexer/core/src/services/search/search-index-builder.js +305 -0
  154. package/dist/server/modules/affairs-indexer/core/src/services/search/search-index-builder.js.map +1 -0
  155. package/dist/server/modules/affairs-indexer/core/src/services/tagging/tag-recompute-service.d.ts +53 -0
  156. package/dist/server/modules/affairs-indexer/core/src/services/tagging/tag-recompute-service.js +566 -0
  157. package/dist/server/modules/affairs-indexer/core/src/services/tagging/tag-recompute-service.js.map +1 -0
  158. package/dist/server/modules/affairs-indexer/core/src/services/watch/watch-service.d.ts +47 -0
  159. package/dist/server/modules/affairs-indexer/core/src/services/watch/watch-service.js +227 -0
  160. package/dist/server/modules/affairs-indexer/core/src/services/watch/watch-service.js.map +1 -0
  161. package/dist/server/modules/affairs-indexer/core/src/sqlite/catalog-schema.d.ts +5 -0
  162. package/dist/server/modules/affairs-indexer/core/src/sqlite/catalog-schema.js +245 -0
  163. package/dist/server/modules/affairs-indexer/core/src/sqlite/catalog-schema.js.map +1 -0
  164. package/dist/server/modules/affairs-indexer/core/src/sqlite/detect-catalog-schema.d.ts +14 -0
  165. package/dist/server/modules/affairs-indexer/core/src/sqlite/detect-catalog-schema.js +87 -0
  166. package/dist/server/modules/affairs-indexer/core/src/sqlite/detect-catalog-schema.js.map +1 -0
  167. package/dist/server/modules/affairs-indexer/core/src/sqlite/init-catalog.d.ts +13 -0
  168. package/dist/server/modules/affairs-indexer/core/src/sqlite/init-catalog.js +16 -0
  169. package/dist/server/modules/affairs-indexer/core/src/sqlite/init-catalog.js.map +1 -0
  170. package/dist/server/modules/affairs-indexer/core/src/sqlite/migration-runner.d.ts +22 -0
  171. package/dist/server/modules/affairs-indexer/core/src/sqlite/migration-runner.js +430 -0
  172. package/dist/server/modules/affairs-indexer/core/src/sqlite/migration-runner.js.map +1 -0
  173. package/dist/server/modules/affairs-indexer/core/src/sqlite/open-database.d.ts +26 -0
  174. package/dist/server/modules/affairs-indexer/core/src/sqlite/open-database.js +19 -0
  175. package/dist/server/modules/affairs-indexer/core/src/sqlite/open-database.js.map +1 -0
  176. package/dist/server/modules/affairs-indexer/core/src/tagging/simple-tag-inference.d.ts +21 -0
  177. package/dist/server/modules/affairs-indexer/core/src/tagging/simple-tag-inference.js +94 -0
  178. package/dist/server/modules/affairs-indexer/core/src/tagging/simple-tag-inference.js.map +1 -0
  179. package/dist/server/modules/affairs-indexer/core/src/utils/abort.d.ts +2 -0
  180. package/dist/server/modules/affairs-indexer/core/src/utils/abort.js +13 -0
  181. package/dist/server/modules/affairs-indexer/core/src/utils/abort.js.map +1 -0
  182. package/dist/server/modules/affairs-indexer/core/src/utils/file-streaming.d.ts +9 -0
  183. package/dist/server/modules/affairs-indexer/core/src/utils/file-streaming.js +64 -0
  184. package/dist/server/modules/affairs-indexer/core/src/utils/file-streaming.js.map +1 -0
  185. package/dist/server/modules/affairs-indexer/core/src/utils/root-command-lock.d.ts +10 -0
  186. package/dist/server/modules/affairs-indexer/core/src/utils/root-command-lock.js +230 -0
  187. package/dist/server/modules/affairs-indexer/core/src/utils/root-command-lock.js.map +1 -0
  188. package/dist/server/modules/affairs-indexer/core/src/utils/rss-log.d.ts +2 -0
  189. package/dist/server/modules/affairs-indexer/core/src/utils/rss-log.js +19 -0
  190. package/dist/server/modules/affairs-indexer/core/src/utils/rss-log.js.map +1 -0
  191. package/dist/server/modules/affairs-indexer/internal-command-runner.d.ts +31 -0
  192. package/dist/server/modules/affairs-indexer/internal-command-runner.js +643 -0
  193. package/dist/server/modules/affairs-indexer/internal-command-runner.js.map +1 -0
  194. package/dist/server/modules/assistant-capability/assistant-capability-controller.d.ts +0 -49
  195. package/dist/server/modules/assistant-capability/assistant-capability-controller.js +10 -56
  196. package/dist/server/modules/assistant-capability/assistant-capability-controller.js.map +1 -1
  197. package/dist/server/modules/assistant-capability/assistant-capability-service.d.ts +2 -46
  198. package/dist/server/modules/assistant-capability/assistant-capability-service.js +15 -158
  199. package/dist/server/modules/assistant-capability/assistant-capability-service.js.map +1 -1
  200. package/dist/server/modules/browser-runtime/opencli-bridge-browser-executor.d.ts +4 -2
  201. package/dist/server/modules/browser-runtime/opencli-bridge-browser-executor.js +62 -21
  202. package/dist/server/modules/browser-runtime/opencli-bridge-browser-executor.js.map +1 -1
  203. package/dist/server/modules/butler/butler-control-session-service.d.ts +3 -4
  204. package/dist/server/modules/butler/butler-control-session-service.js +39 -62
  205. package/dist/server/modules/butler/butler-control-session-service.js.map +1 -1
  206. package/dist/server/modules/butler/butler-controller.d.ts +11 -3
  207. package/dist/server/modules/butler/butler-controller.js +19 -4
  208. package/dist/server/modules/butler/butler-controller.js.map +1 -1
  209. package/dist/server/modules/butler/butler-follow-up-service.d.ts +3 -0
  210. package/dist/server/modules/butler/butler-follow-up-service.js +11 -1
  211. package/dist/server/modules/butler/butler-follow-up-service.js.map +1 -1
  212. package/dist/server/modules/butler/butler-inbox-service.d.ts +3 -0
  213. package/dist/server/modules/butler/butler-inbox-service.js +14 -2
  214. package/dist/server/modules/butler/butler-inbox-service.js.map +1 -1
  215. package/dist/server/modules/butler/butler-profile-service.d.ts +1 -1
  216. package/dist/server/modules/butler/butler-profile-service.js +34 -63
  217. package/dist/server/modules/butler/butler-profile-service.js.map +1 -1
  218. package/dist/server/modules/butler/butler-project-service.d.ts +1 -3
  219. package/dist/server/modules/butler/butler-project-service.js +1 -7
  220. package/dist/server/modules/butler/butler-project-service.js.map +1 -1
  221. package/dist/server/modules/butler/butler-session-service.d.ts +4 -0
  222. package/dist/server/modules/butler/butler-session-service.js +127 -0
  223. package/dist/server/modules/butler/butler-session-service.js.map +1 -1
  224. package/dist/server/modules/butler/butler-session-summary-service.js +0 -2
  225. package/dist/server/modules/butler/butler-session-summary-service.js.map +1 -1
  226. package/dist/server/modules/butler/butler-workspace-context.d.ts +5 -1
  227. package/dist/server/modules/butler/butler-workspace-context.js +21 -12
  228. package/dist/server/modules/butler/butler-workspace-context.js.map +1 -1
  229. package/dist/server/modules/file/file-content-service.d.ts +11 -0
  230. package/dist/server/modules/file/file-content-service.js +55 -0
  231. package/dist/server/modules/file/file-content-service.js.map +1 -1
  232. package/dist/server/modules/file/file-controller.d.ts +36 -2
  233. package/dist/server/modules/file/file-controller.js +461 -19
  234. package/dist/server/modules/file/file-controller.js.map +1 -1
  235. package/dist/server/modules/file/file-preview-link-service.d.ts +1 -0
  236. package/dist/server/modules/file/file-preview-link-service.js +25 -0
  237. package/dist/server/modules/file/file-preview-link-service.js.map +1 -1
  238. package/dist/server/modules/file/file-preview-service.js +15 -4
  239. package/dist/server/modules/file/file-preview-service.js.map +1 -1
  240. package/dist/server/modules/file/file-preview-types.d.ts +9 -1
  241. package/dist/server/modules/file/file-preview-types.js +8 -1
  242. package/dist/server/modules/file/file-preview-types.js.map +1 -1
  243. package/dist/server/modules/file/file-search-service.js +200 -12
  244. package/dist/server/modules/file/file-search-service.js.map +1 -1
  245. package/dist/server/modules/file/recent-modified-file-service.d.ts +15 -0
  246. package/dist/server/modules/file/recent-modified-file-service.js +102 -0
  247. package/dist/server/modules/file/recent-modified-file-service.js.map +1 -0
  248. package/dist/server/modules/file/runtime/codingns-workspace-bridge.js +24 -5
  249. package/dist/server/modules/file/workspace-file-bridge-service.d.ts +20 -0
  250. package/dist/server/modules/file/workspace-file-bridge-service.js +22 -0
  251. package/dist/server/modules/file/workspace-file-bridge-service.js.map +1 -1
  252. package/dist/server/modules/file/workspace-file-bridge-watch-service.d.ts +9 -0
  253. package/dist/server/modules/file/workspace-file-bridge-watch-service.js +28 -0
  254. package/dist/server/modules/file/workspace-file-bridge-watch-service.js.map +1 -1
  255. package/dist/server/modules/file/workspace-index-apply-service.d.ts +25 -0
  256. package/dist/server/modules/file/workspace-index-apply-service.js +42 -0
  257. package/dist/server/modules/file/workspace-index-apply-service.js.map +1 -0
  258. package/dist/server/modules/office/office-controller.d.ts +15 -1
  259. package/dist/server/modules/office/office-controller.js +26 -1
  260. package/dist/server/modules/office/office-controller.js.map +1 -1
  261. package/dist/server/modules/office/onlyoffice-integration-service.d.ts +78 -0
  262. package/dist/server/modules/office/onlyoffice-integration-service.js +610 -0
  263. package/dist/server/modules/office/onlyoffice-integration-service.js.map +1 -0
  264. package/dist/server/modules/plugins/plugin-file-gateway-service.d.ts +12 -0
  265. package/dist/server/modules/plugins/plugin-file-gateway-service.js +13 -0
  266. package/dist/server/modules/plugins/plugin-file-gateway-service.js.map +1 -1
  267. package/dist/server/modules/preferences/profile-service.d.ts +1 -0
  268. package/dist/server/modules/preferences/profile-service.js +27 -3
  269. package/dist/server/modules/preferences/profile-service.js.map +1 -1
  270. package/dist/server/modules/sessions/codex-app-server-helper-process.js +0 -8
  271. package/dist/server/modules/sessions/codex-app-server-helper-process.js.map +1 -1
  272. package/dist/server/modules/sessions/session-controller.d.ts +1 -0
  273. package/dist/server/modules/sessions/session-controller.js +3 -0
  274. package/dist/server/modules/sessions/session-controller.js.map +1 -1
  275. package/dist/server/modules/sessions/session-history-service.d.ts +2 -0
  276. package/dist/server/modules/sessions/session-history-service.js +78 -3
  277. package/dist/server/modules/sessions/session-history-service.js.map +1 -1
  278. package/dist/server/modules/sessions/session-live-runtime-service.d.ts +1 -0
  279. package/dist/server/modules/sessions/session-live-runtime-service.js +4 -0
  280. package/dist/server/modules/sessions/session-live-runtime-service.js.map +1 -1
  281. package/dist/server/modules/sessions/session-permission-request-service.js +0 -4
  282. package/dist/server/modules/sessions/session-permission-request-service.js.map +1 -1
  283. package/dist/server/modules/sessions/workspace-session-instruction-watch-service.d.ts +23 -0
  284. package/dist/server/modules/sessions/workspace-session-instruction-watch-service.js +122 -0
  285. package/dist/server/modules/sessions/workspace-session-instruction-watch-service.js.map +1 -0
  286. package/dist/server/modules/sessions/workspace-session-runtime-context-service.d.ts +15 -0
  287. package/dist/server/modules/sessions/workspace-session-runtime-context-service.js +93 -10
  288. package/dist/server/modules/sessions/workspace-session-runtime-context-service.js.map +1 -1
  289. package/dist/server/modules/skills/builtin-skills/codingns-assistant/SKILL.md +6 -7
  290. package/dist/server/modules/skills/builtin-skills/codingns-assistant/references/cli-workflow.md +2 -3
  291. package/dist/server/modules/system/host-resource-controller.d.ts +7 -0
  292. package/dist/server/modules/system/host-resource-controller.js +12 -0
  293. package/dist/server/modules/system/host-resource-controller.js.map +1 -0
  294. package/dist/server/modules/system/host-resource-service.d.ts +54 -0
  295. package/dist/server/modules/system/host-resource-service.js +162 -0
  296. package/dist/server/modules/system/host-resource-service.js.map +1 -0
  297. package/dist/server/modules/tasks/observability-service.d.ts +12 -2
  298. package/dist/server/modules/tasks/observability-service.js +13 -1
  299. package/dist/server/modules/tasks/observability-service.js.map +1 -1
  300. package/dist/server/modules/tasks/task-helper-client.d.ts +36 -2
  301. package/dist/server/modules/tasks/task-helper-client.js +201 -19
  302. package/dist/server/modules/tasks/task-helper-client.js.map +1 -1
  303. package/dist/server/modules/tasks/task-helper-pool.d.ts +37 -0
  304. package/dist/server/modules/tasks/task-helper-pool.js +173 -0
  305. package/dist/server/modules/tasks/task-helper-pool.js.map +1 -0
  306. package/dist/server/modules/tasks/task-helper-process-handlers.d.ts +27 -0
  307. package/dist/server/modules/tasks/task-helper-process-handlers.js +25 -1
  308. package/dist/server/modules/tasks/task-helper-process-handlers.js.map +1 -1
  309. package/dist/server/modules/tasks/task-helper-process.js +75 -26
  310. package/dist/server/modules/tasks/task-helper-process.js.map +1 -1
  311. package/dist/server/modules/tasks/task-helper-scheduling.d.ts +11 -0
  312. package/dist/server/modules/tasks/task-helper-scheduling.js +43 -0
  313. package/dist/server/modules/tasks/task-helper-scheduling.js.map +1 -0
  314. package/dist/server/modules/tasks/task-lane-executors.js +19 -3
  315. package/dist/server/modules/tasks/task-lane-executors.js.map +1 -1
  316. package/dist/server/modules/tasks/task-manager.d.ts +1 -0
  317. package/dist/server/modules/tasks/task-manager.js +3 -0
  318. package/dist/server/modules/tasks/task-manager.js.map +1 -1
  319. package/dist/server/modules/tasks/task-registry.d.ts +1 -0
  320. package/dist/server/modules/tasks/task-registry.js +3 -0
  321. package/dist/server/modules/tasks/task-registry.js.map +1 -1
  322. package/dist/server/modules/tasks/task-scheduler.d.ts +6 -0
  323. package/dist/server/modules/tasks/task-scheduler.js +162 -7
  324. package/dist/server/modules/tasks/task-scheduler.js.map +1 -1
  325. package/dist/server/modules/tasks/task-types.d.ts +29 -3
  326. package/dist/server/modules/tasks/task-types.js +15 -2
  327. package/dist/server/modules/tasks/task-types.js.map +1 -1
  328. package/dist/server/modules/workbench/affairs-assistant-session-snapshot-service.d.ts +68 -0
  329. package/dist/server/modules/workbench/affairs-assistant-session-snapshot-service.js +303 -0
  330. package/dist/server/modules/workbench/affairs-assistant-session-snapshot-service.js.map +1 -0
  331. package/dist/server/modules/workbench/workbench-controller.d.ts +5 -0
  332. package/dist/server/modules/workbench/workbench-controller.js +31 -1
  333. package/dist/server/modules/workbench/workbench-controller.js.map +1 -1
  334. package/dist/server/modules/workbench/workbench-service.d.ts +9 -2
  335. package/dist/server/modules/workbench/workbench-service.js +55 -18
  336. package/dist/server/modules/workbench/workbench-service.js.map +1 -1
  337. package/dist/server/modules/workspace/affairs-library-controller.d.ts +125 -0
  338. package/dist/server/modules/workspace/affairs-library-controller.js +175 -0
  339. package/dist/server/modules/workspace/affairs-library-controller.js.map +1 -0
  340. package/dist/server/modules/workspace/affairs-library-debug-log.d.ts +23 -0
  341. package/dist/server/modules/workspace/affairs-library-debug-log.js +107 -0
  342. package/dist/server/modules/workspace/affairs-library-debug-log.js.map +1 -0
  343. package/dist/server/modules/workspace/affairs-library-dirty-watch-service.d.ts +52 -0
  344. package/dist/server/modules/workspace/affairs-library-dirty-watch-service.js +555 -0
  345. package/dist/server/modules/workspace/affairs-library-dirty-watch-service.js.map +1 -0
  346. package/dist/server/modules/workspace/affairs-library-preview-link-service.d.ts +30 -0
  347. package/dist/server/modules/workspace/affairs-library-preview-link-service.js +167 -0
  348. package/dist/server/modules/workspace/affairs-library-preview-link-service.js.map +1 -0
  349. package/dist/server/modules/workspace/affairs-library-refresh-contract.d.ts +56 -0
  350. package/dist/server/modules/workspace/affairs-library-refresh-contract.js +48 -0
  351. package/dist/server/modules/workspace/affairs-library-refresh-contract.js.map +1 -0
  352. package/dist/server/modules/workspace/affairs-library-service.d.ts +353 -0
  353. package/dist/server/modules/workspace/affairs-library-service.js +3895 -0
  354. package/dist/server/modules/workspace/affairs-library-service.js.map +1 -0
  355. package/dist/server/modules/workspace/affairs-lightweight-session-controller.d.ts +86 -0
  356. package/dist/server/modules/workspace/affairs-lightweight-session-controller.js +193 -0
  357. package/dist/server/modules/workspace/affairs-lightweight-session-controller.js.map +1 -0
  358. package/dist/server/modules/workspace/affairs-lightweight-session-service.d.ts +146 -0
  359. package/dist/server/modules/workspace/affairs-lightweight-session-service.js +1593 -0
  360. package/dist/server/modules/workspace/affairs-lightweight-session-service.js.map +1 -0
  361. package/dist/server/modules/workspace/affairs-tag-controller.d.ts +110 -0
  362. package/dist/server/modules/workspace/affairs-tag-controller.js +102 -0
  363. package/dist/server/modules/workspace/affairs-tag-controller.js.map +1 -0
  364. package/dist/server/modules/workspace/affairs-tag-service.d.ts +174 -0
  365. package/dist/server/modules/workspace/affairs-tag-service.js +719 -0
  366. package/dist/server/modules/workspace/affairs-tag-service.js.map +1 -0
  367. package/dist/server/modules/workspace/teable-api-client.d.ts +118 -0
  368. package/dist/server/modules/workspace/teable-api-client.js +142 -0
  369. package/dist/server/modules/workspace/teable-api-client.js.map +1 -0
  370. package/dist/server/modules/workspace/teable-catalog-controller.d.ts +18 -0
  371. package/dist/server/modules/workspace/teable-catalog-controller.js +17 -0
  372. package/dist/server/modules/workspace/teable-catalog-controller.js.map +1 -0
  373. package/dist/server/modules/workspace/teable-catalog-service.d.ts +36 -0
  374. package/dist/server/modules/workspace/teable-catalog-service.js +124 -0
  375. package/dist/server/modules/workspace/teable-catalog-service.js.map +1 -0
  376. package/dist/server/modules/workspace/teable-credential-service.d.ts +8 -0
  377. package/dist/server/modules/workspace/teable-credential-service.js +37 -0
  378. package/dist/server/modules/workspace/teable-credential-service.js.map +1 -0
  379. package/dist/server/modules/workspace/teable-field-mapping-controller.d.ts +25 -0
  380. package/dist/server/modules/workspace/teable-field-mapping-controller.js +31 -0
  381. package/dist/server/modules/workspace/teable-field-mapping-controller.js.map +1 -0
  382. package/dist/server/modules/workspace/teable-field-mapping-service.d.ts +38 -0
  383. package/dist/server/modules/workspace/teable-field-mapping-service.js +215 -0
  384. package/dist/server/modules/workspace/teable-field-mapping-service.js.map +1 -0
  385. package/dist/server/modules/workspace/teable-global-binding-controller.d.ts +22 -0
  386. package/dist/server/modules/workspace/teable-global-binding-controller.js +25 -0
  387. package/dist/server/modules/workspace/teable-global-binding-controller.js.map +1 -0
  388. package/dist/server/modules/workspace/teable-global-binding-service.d.ts +35 -0
  389. package/dist/server/modules/workspace/teable-global-binding-service.js +151 -0
  390. package/dist/server/modules/workspace/teable-global-binding-service.js.map +1 -0
  391. package/dist/server/modules/workspace/teable-mirror-sync-controller.d.ts +29 -0
  392. package/dist/server/modules/workspace/teable-mirror-sync-controller.js +50 -0
  393. package/dist/server/modules/workspace/teable-mirror-sync-controller.js.map +1 -0
  394. package/dist/server/modules/workspace/teable-mirror-sync-service.d.ts +157 -0
  395. package/dist/server/modules/workspace/teable-mirror-sync-service.js +917 -0
  396. package/dist/server/modules/workspace/teable-mirror-sync-service.js.map +1 -0
  397. package/dist/server/modules/workspace/teable-runtime-controller.d.ts +58 -0
  398. package/dist/server/modules/workspace/teable-runtime-controller.js +60 -0
  399. package/dist/server/modules/workspace/teable-runtime-controller.js.map +1 -0
  400. package/dist/server/modules/workspace/teable-runtime-service.d.ts +96 -0
  401. package/dist/server/modules/workspace/teable-runtime-service.js +362 -0
  402. package/dist/server/modules/workspace/teable-runtime-service.js.map +1 -0
  403. package/dist/server/modules/workspace/teable-workbench-sync-config-controller.d.ts +22 -0
  404. package/dist/server/modules/workspace/teable-workbench-sync-config-controller.js +20 -0
  405. package/dist/server/modules/workspace/teable-workbench-sync-config-controller.js.map +1 -0
  406. package/dist/server/modules/workspace/teable-workbench-sync-config-service.d.ts +22 -0
  407. package/dist/server/modules/workspace/teable-workbench-sync-config-service.js +159 -0
  408. package/dist/server/modules/workspace/teable-workbench-sync-config-service.js.map +1 -0
  409. package/dist/server/modules/workspace/workspace-controller.d.ts +2 -1
  410. package/dist/server/modules/workspace/workspace-controller.js +8 -2
  411. package/dist/server/modules/workspace/workspace-controller.js.map +1 -1
  412. package/dist/server/modules/workspace/workspace-service.js +60 -9
  413. package/dist/server/modules/workspace/workspace-service.js.map +1 -1
  414. package/dist/server/routes/affairs.d.ts +11 -0
  415. package/dist/server/routes/affairs.js +126 -0
  416. package/dist/server/routes/affairs.js.map +1 -0
  417. package/dist/server/routes/assistant.js +0 -5
  418. package/dist/server/routes/assistant.js.map +1 -1
  419. package/dist/server/routes/files.js +5 -0
  420. package/dist/server/routes/files.js.map +1 -1
  421. package/dist/server/routes/office.js +4 -0
  422. package/dist/server/routes/office.js.map +1 -1
  423. package/dist/server/routes/system.d.ts +2 -1
  424. package/dist/server/routes/system.js +2 -1
  425. package/dist/server/routes/system.js.map +1 -1
  426. package/dist/server/routes/workbench.js +15 -0
  427. package/dist/server/routes/workbench.js.map +1 -1
  428. package/dist/server/routes/workspaces.d.ts +4 -1
  429. package/dist/server/routes/workspaces.js +56 -1
  430. package/dist/server/routes/workspaces.js.map +1 -1
  431. package/dist/server/server/create-server.d.ts +20 -2
  432. package/dist/server/server/create-server.js +180 -33
  433. package/dist/server/server/create-server.js.map +1 -1
  434. package/dist/server/shared/http/error-handler.js +10 -0
  435. package/dist/server/shared/http/error-handler.js.map +1 -1
  436. package/dist/server/storage/repositories/affairs-assistant-session-snapshot-repository.d.ts +10 -0
  437. package/dist/server/storage/repositories/affairs-assistant-session-snapshot-repository.js +47 -0
  438. package/dist/server/storage/repositories/affairs-assistant-session-snapshot-repository.js.map +1 -0
  439. package/dist/server/storage/repositories/butler-profile-repository.js +7 -3
  440. package/dist/server/storage/repositories/butler-profile-repository.js.map +1 -1
  441. package/dist/server/storage/repositories/office-onlyoffice-setting-repository.d.ts +19 -0
  442. package/dist/server/storage/repositories/office-onlyoffice-setting-repository.js +55 -0
  443. package/dist/server/storage/repositories/office-onlyoffice-setting-repository.js.map +1 -0
  444. package/dist/server/storage/repositories/session-index-repository.js +9 -2
  445. package/dist/server/storage/repositories/session-index-repository.js.map +1 -1
  446. package/dist/server/storage/repositories/user-affairs-library-setting-repository.d.ts +10 -0
  447. package/dist/server/storage/repositories/user-affairs-library-setting-repository.js +72 -0
  448. package/dist/server/storage/repositories/user-affairs-library-setting-repository.js.map +1 -0
  449. package/dist/server/storage/repositories/user-preference-profile-repository.js +6 -3
  450. package/dist/server/storage/repositories/user-preference-profile-repository.js.map +1 -1
  451. package/dist/server/storage/repositories/user-teable-credential-repository.d.ts +9 -0
  452. package/dist/server/storage/repositories/user-teable-credential-repository.js +45 -0
  453. package/dist/server/storage/repositories/user-teable-credential-repository.js.map +1 -0
  454. package/dist/server/storage/repositories/user-teable-field-mapping-repository.d.ts +10 -0
  455. package/dist/server/storage/repositories/user-teable-field-mapping-repository.js +69 -0
  456. package/dist/server/storage/repositories/user-teable-field-mapping-repository.js.map +1 -0
  457. package/dist/server/storage/repositories/user-teable-global-setting-repository.d.ts +8 -0
  458. package/dist/server/storage/repositories/user-teable-global-setting-repository.js +52 -0
  459. package/dist/server/storage/repositories/user-teable-global-setting-repository.js.map +1 -0
  460. package/dist/server/storage/repositories/user-teable-mirror-record-mapping-repository.d.ts +9 -0
  461. package/dist/server/storage/repositories/user-teable-mirror-record-mapping-repository.js +66 -0
  462. package/dist/server/storage/repositories/user-teable-mirror-record-mapping-repository.js.map +1 -0
  463. package/dist/server/storage/repositories/user-teable-mirror-table-binding-repository.d.ts +9 -0
  464. package/dist/server/storage/repositories/user-teable-mirror-table-binding-repository.js +67 -0
  465. package/dist/server/storage/repositories/user-teable-mirror-table-binding-repository.js.map +1 -0
  466. package/dist/server/storage/repositories/user-teable-sync-log-repository.d.ts +14 -0
  467. package/dist/server/storage/repositories/user-teable-sync-log-repository.js +97 -0
  468. package/dist/server/storage/repositories/user-teable-sync-log-repository.js.map +1 -0
  469. package/dist/server/storage/repositories/user-teable-workbench-sync-config-repository.d.ts +8 -0
  470. package/dist/server/storage/repositories/user-teable-workbench-sync-config-repository.js +55 -0
  471. package/dist/server/storage/repositories/user-teable-workbench-sync-config-repository.js.map +1 -0
  472. package/dist/server/storage/repositories/workspace-navigation-state-repository.d.ts +3 -0
  473. package/dist/server/storage/repositories/workspace-navigation-state-repository.js +47 -4
  474. package/dist/server/storage/repositories/workspace-navigation-state-repository.js.map +1 -1
  475. package/dist/server/storage/sqlite/client.js +633 -123
  476. package/dist/server/storage/sqlite/client.js.map +1 -1
  477. package/dist/server/storage/sqlite/schema.sql +214 -25
  478. package/dist/server/types/domain.d.ts +133 -20
  479. package/dist/server/ws/workbench-ws-hub.js +2 -2
  480. package/dist/server/ws/workbench-ws-hub.js.map +1 -1
  481. package/node_modules/@codingns/session-sync-core/dist/runtime/codex-permissions.js +0 -2
  482. package/node_modules/@codingns/session-sync-core/dist/runtime/codex-permissions.js.map +1 -1
  483. package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.js +0 -6
  484. package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.js.map +1 -1
  485. package/node_modules/@codingns/session-sync-core/dist/sqlite/node-sqlite.d.ts +22 -3
  486. package/node_modules/@codingns/session-sync-core/dist/sqlite/node-sqlite.js +29 -2
  487. package/node_modules/@codingns/session-sync-core/dist/sqlite/node-sqlite.js.map +1 -1
  488. package/node_modules/@codingns/session-sync-core/package.json +3 -1
  489. package/package.json +1 -1
  490. package/dist/public/assets/AdaptiveButlerPage-B153lk5H.css +0 -1
  491. package/dist/public/assets/AdaptiveButlerPage-CJw8Ae62.js +0 -3
  492. package/dist/public/assets/DesktopModal-D_A8sgQU.js +0 -1
  493. package/dist/public/assets/DesktopWindowPage-DK7L7osV.js +0 -2
  494. package/dist/public/assets/FileContextPanel-BdCoubcJ.js +0 -1
  495. package/dist/public/assets/GitSidebar-BeZ0hj7A.js +0 -6
  496. package/dist/public/assets/MobileCreateSessionSheet-DfLMVu8q.js +0 -1
  497. package/dist/public/assets/MobileSheet-5kZ-w-gU.js +0 -1
  498. package/dist/public/assets/MobileWorkspaceSwitcherHeader-C6JMiOq_.js +0 -1
  499. package/dist/public/assets/PluginContainerPage-BlY-xJDh.js +0 -1
  500. package/dist/public/assets/SessionIndexPage-DkBp9Mqz.js +0 -1
  501. package/dist/public/assets/SettingsPage-C-ASmJAG.js +0 -2
  502. package/dist/public/assets/TerminalManagerPanel-NVZRxxmH.js +0 -1
  503. package/dist/public/assets/TerminalRuntimeFallbackModal-Bzum5nZ0.js +0 -1
  504. package/dist/public/assets/WorkbenchLayout-OFi6CWgH.js +0 -244
  505. package/dist/public/assets/WorkbenchShellRoute-B4XB8SwG.css +0 -1
  506. package/dist/public/assets/WorkbenchShellRoute-BAQe_E0O.js +0 -1
  507. package/dist/public/assets/WorkspaceDebugDetailPage-DhKa6e9y.js +0 -1
  508. package/dist/public/assets/WorkspaceDetailPage-BPsrFffw.js +0 -1
  509. package/dist/public/assets/WorkspaceHomePage-KAtqZOAb.js +0 -1
  510. package/dist/public/assets/file-tree-icon-Mg1DiBRX.js +0 -590
  511. package/dist/public/assets/index-C4t-vvqk.css +0 -1
  512. package/dist/public/assets/index-CL97fwWB.js +0 -42
  513. package/dist/public/assets/realtime-client-CLafKzzJ.js +0 -1
  514. package/dist/public/assets/useRegisteredDebugTemplates-DQAWVdCo.js +0 -1
  515. package/dist/public/assets/workbench-navigation-MEzCSmsK.js +0 -1
@@ -0,0 +1,1471 @@
1
+ import { openDatabase, } from "../sqlite/open-database.js";
2
+ function compareTagPostingRows(left, right) {
3
+ return left.rootType.localeCompare(right.rootType, "zh-Hans-CN")
4
+ || left.tagPath.localeCompare(right.tagPath, "zh-Hans-CN")
5
+ || left.path.localeCompare(right.path, "zh-Hans-CN")
6
+ || left.documentId.localeCompare(right.documentId, "zh-Hans-CN")
7
+ || Number(left.derived) - Number(right.derived);
8
+ }
9
+ function attachTags(documentRows, directTagRows, derivedTagRows) {
10
+ const directTagsByDocument = new Map();
11
+ for (const row of directTagRows) {
12
+ const current = directTagsByDocument.get(row.document_id) ?? [];
13
+ current.push(row.tag_path);
14
+ directTagsByDocument.set(row.document_id, current);
15
+ }
16
+ const derivedTagsByDocument = new Map();
17
+ for (const row of derivedTagRows) {
18
+ const current = derivedTagsByDocument.get(row.document_id) ?? [];
19
+ current.push(row.tag_path);
20
+ derivedTagsByDocument.set(row.document_id, current);
21
+ }
22
+ return documentRows.map(row => {
23
+ const documentId = String(row.document_id);
24
+ return {
25
+ documentId,
26
+ path: String(row.path),
27
+ title: String(row.title),
28
+ summary: String(row.summary ?? ""),
29
+ tags: directTagsByDocument.get(documentId) ?? [],
30
+ derivedTags: derivedTagsByDocument.get(documentId) ?? [],
31
+ mtime: String(row.mtime),
32
+ };
33
+ });
34
+ }
35
+ function mapDocumentRows(rows) {
36
+ return rows.map(row => ({
37
+ documentId: String(row.document_id),
38
+ path: String(row.path),
39
+ title: String(row.title),
40
+ summary: String(row.summary ?? ""),
41
+ mtime: String(row.mtime),
42
+ }));
43
+ }
44
+ function fetchDocumentTagsForIds(db, documentIds) {
45
+ if (documentIds.length === 0) {
46
+ return {
47
+ directTagRows: [],
48
+ derivedTagRows: [],
49
+ };
50
+ }
51
+ const placeholders = documentIds.map(() => "?").join(", ");
52
+ const directTagRows = db.prepare(`
53
+ SELECT dt.document_id, t.path AS tag_path
54
+ FROM document_tags dt
55
+ JOIN tags t ON t.id = dt.tag_id
56
+ WHERE dt.document_id IN (${placeholders})
57
+ ORDER BY dt.document_id, t.path
58
+ `).all(...documentIds);
59
+ const derivedTagRows = db.prepare(`
60
+ SELECT ddt.document_id, t.path AS tag_path
61
+ FROM derived_document_tags ddt
62
+ JOIN tags t ON t.id = ddt.tag_id
63
+ WHERE ddt.document_id IN (${placeholders})
64
+ ORDER BY ddt.document_id, t.path
65
+ `).all(...documentIds);
66
+ return {
67
+ directTagRows,
68
+ derivedTagRows,
69
+ };
70
+ }
71
+ /**
72
+ * 最小 SQLite 查询仓库。
73
+ * 第二阶段继续承接只读查询,并补最小增量导出所需查询。
74
+ */
75
+ export class CatalogRepository {
76
+ dbPath;
77
+ dbOptions;
78
+ constructor(dbPath, dbOptions = {}) {
79
+ this.dbPath = dbPath;
80
+ this.dbOptions = dbOptions;
81
+ }
82
+ listTagDefinitions(includeDisabled = false) {
83
+ const db = openDatabase(this.dbPath, this.dbOptions);
84
+ try {
85
+ const rows = db.prepare(`
86
+ SELECT
87
+ id,
88
+ root_type,
89
+ path,
90
+ name,
91
+ parent_id,
92
+ canonical_name,
93
+ description,
94
+ status,
95
+ created_by,
96
+ created_at,
97
+ updated_at,
98
+ disabled_at
99
+ FROM tags
100
+ ${includeDisabled ? "" : "WHERE status <> 'disabled'"}
101
+ ORDER BY path
102
+ `).all();
103
+ return rows.map(row => ({
104
+ id: String(row.id),
105
+ rootType: String(row.root_type),
106
+ path: String(row.path),
107
+ name: String(row.name),
108
+ parentId: row.parent_id ? String(row.parent_id) : null,
109
+ canonicalName: String(row.canonical_name),
110
+ description: typeof row.description === "string" ? row.description : null,
111
+ status: String(row.status),
112
+ createdBy: String(row.created_by),
113
+ createdAt: String(row.created_at),
114
+ updatedAt: String(row.updated_at ?? row.created_at),
115
+ disabledAt: typeof row.disabled_at === "string" ? row.disabled_at : null,
116
+ }));
117
+ }
118
+ finally {
119
+ db.close();
120
+ }
121
+ }
122
+ getTagDefinitionById(tagId) {
123
+ const db = openDatabase(this.dbPath, this.dbOptions);
124
+ try {
125
+ const row = db.prepare(`
126
+ SELECT
127
+ id,
128
+ root_type,
129
+ path,
130
+ name,
131
+ parent_id,
132
+ canonical_name,
133
+ description,
134
+ status,
135
+ created_by,
136
+ created_at,
137
+ updated_at,
138
+ disabled_at
139
+ FROM tags
140
+ WHERE id = ?
141
+ `).get(tagId);
142
+ if (!row) {
143
+ return null;
144
+ }
145
+ return {
146
+ id: String(row.id),
147
+ rootType: String(row.root_type),
148
+ path: String(row.path),
149
+ name: String(row.name),
150
+ parentId: row.parent_id ? String(row.parent_id) : null,
151
+ canonicalName: String(row.canonical_name),
152
+ description: typeof row.description === "string" ? row.description : null,
153
+ status: String(row.status),
154
+ createdBy: String(row.created_by),
155
+ createdAt: String(row.created_at),
156
+ updatedAt: String(row.updated_at ?? row.created_at),
157
+ disabledAt: typeof row.disabled_at === "string" ? row.disabled_at : null,
158
+ };
159
+ }
160
+ finally {
161
+ db.close();
162
+ }
163
+ }
164
+ listTagRulesByTagIds(tagIds) {
165
+ const normalizedIds = [...new Set(tagIds.map(item => item.trim()).filter(Boolean))];
166
+ if (normalizedIds.length === 0) {
167
+ return [];
168
+ }
169
+ const db = openDatabase(this.dbPath, this.dbOptions);
170
+ try {
171
+ const placeholders = normalizedIds.map(() => "?").join(", ");
172
+ const rows = db.prepare(`
173
+ SELECT
174
+ r.id,
175
+ r.tag_id,
176
+ t.path AS tag_path,
177
+ r.enabled,
178
+ r.rule_type,
179
+ r.scope_json,
180
+ r.matcher_json,
181
+ r.min_score,
182
+ r.priority,
183
+ r.source,
184
+ r.created_at,
185
+ r.updated_at
186
+ FROM tag_rules r
187
+ JOIN tags t ON t.id = r.tag_id
188
+ WHERE r.tag_id IN (${placeholders})
189
+ ORDER BY t.path, r.priority, r.created_at
190
+ `).all(...normalizedIds);
191
+ return rows.map(mapTagRuleRow);
192
+ }
193
+ finally {
194
+ db.close();
195
+ }
196
+ }
197
+ listAllEnabledTagRules() {
198
+ const db = openDatabase(this.dbPath, this.dbOptions);
199
+ try {
200
+ const rows = db.prepare(`
201
+ SELECT
202
+ r.id,
203
+ r.tag_id,
204
+ t.path AS tag_path,
205
+ r.enabled,
206
+ r.rule_type,
207
+ r.scope_json,
208
+ r.matcher_json,
209
+ r.min_score,
210
+ r.priority,
211
+ r.source,
212
+ r.created_at,
213
+ r.updated_at
214
+ FROM tag_rules r
215
+ JOIN tags t ON t.id = r.tag_id
216
+ WHERE r.enabled = 1
217
+ AND t.status = 'active'
218
+ ORDER BY t.path, r.priority, r.created_at
219
+ `).all();
220
+ return rows.map(mapTagRuleRow);
221
+ }
222
+ finally {
223
+ db.close();
224
+ }
225
+ }
226
+ listManualDocumentTagBindingsByDocumentIds(documentIds) {
227
+ const normalizedIds = [...new Set(documentIds.map(item => item.trim()).filter(Boolean))];
228
+ if (normalizedIds.length === 0) {
229
+ return [];
230
+ }
231
+ const db = openDatabase(this.dbPath, this.dbOptions);
232
+ try {
233
+ const placeholders = normalizedIds.map(() => "?").join(", ");
234
+ const documentRows = db.prepare(`
235
+ SELECT
236
+ d.id AS document_id,
237
+ f.path,
238
+ f.inode_key,
239
+ f.content_hash,
240
+ f.size,
241
+ f.extension
242
+ FROM documents d
243
+ JOIN files f ON f.id = d.file_id
244
+ WHERE d.id IN (${placeholders})
245
+ AND f.status = 'active'
246
+ AND d.index_status = 'indexed'
247
+ `).all(...normalizedIds);
248
+ const currentDocuments = documentRows.map((row) => ({
249
+ documentId: String(row.document_id),
250
+ path: String(row.path),
251
+ inodeKey: typeof row.inode_key === "string" && row.inode_key.trim() ? String(row.inode_key) : null,
252
+ contentHash: typeof row.content_hash === "string" && row.content_hash.trim() ? String(row.content_hash) : null,
253
+ size: Number(row.size ?? 0),
254
+ extension: String(row.extension ?? ""),
255
+ }));
256
+ const resolvedRows = this.resolveManualFileTagBindingsForDocuments(db, currentDocuments);
257
+ const legacyRows = db.prepare(`
258
+ SELECT
259
+ b.id,
260
+ b.document_id,
261
+ b.tag_id,
262
+ t.path AS tag_path,
263
+ b.source,
264
+ b.created_at,
265
+ b.updated_at
266
+ FROM manual_document_tag_bindings b
267
+ JOIN tags t ON t.id = b.tag_id
268
+ WHERE b.document_id IN (${placeholders})
269
+ AND t.status = 'active'
270
+ ORDER BY b.document_id, t.path
271
+ `).all(...normalizedIds);
272
+ const identityRowsByDocument = new Map();
273
+ resolvedRows.forEach((row) => {
274
+ const current = identityRowsByDocument.get(row.documentId) ?? [];
275
+ current.push(row);
276
+ identityRowsByDocument.set(row.documentId, current);
277
+ });
278
+ const legacyRowsByDocument = new Map();
279
+ legacyRows.forEach((row) => {
280
+ const mapped = {
281
+ id: String(row.id),
282
+ documentId: String(row.document_id),
283
+ tagId: String(row.tag_id),
284
+ tagPath: String(row.tag_path),
285
+ source: String(row.source),
286
+ createdAt: String(row.created_at),
287
+ updatedAt: String(row.updated_at),
288
+ };
289
+ const current = legacyRowsByDocument.get(mapped.documentId) ?? [];
290
+ current.push(mapped);
291
+ legacyRowsByDocument.set(mapped.documentId, current);
292
+ });
293
+ return normalizedIds
294
+ .flatMap((documentId) => {
295
+ const identityRows = identityRowsByDocument.get(documentId);
296
+ if (identityRows && identityRows.length > 0) {
297
+ return identityRows;
298
+ }
299
+ return legacyRowsByDocument.get(documentId) ?? [];
300
+ })
301
+ .sort((left, right) => left.documentId.localeCompare(right.documentId, "zh-Hans-CN")
302
+ || left.tagPath.localeCompare(right.tagPath, "zh-Hans-CN"));
303
+ }
304
+ finally {
305
+ db.close();
306
+ }
307
+ }
308
+ getManualTagBindingStats() {
309
+ const db = openDatabase(this.dbPath, this.dbOptions);
310
+ try {
311
+ const row = db.prepare(`
312
+ WITH legacy_active AS (
313
+ SELECT
314
+ mdtb.document_id,
315
+ mdtb.tag_id,
316
+ f.inode_key,
317
+ f.content_hash,
318
+ f.size,
319
+ f.extension
320
+ FROM manual_document_tag_bindings mdtb
321
+ JOIN documents d ON d.id = mdtb.document_id
322
+ JOIN files f ON f.id = d.file_id
323
+ WHERE f.status = 'active'
324
+ AND d.index_status IN ('indexed', 'failed', 'skipped')
325
+ ),
326
+ legacy_only AS (
327
+ SELECT la.document_id, la.tag_id
328
+ FROM legacy_active la
329
+ WHERE NOT EXISTS (
330
+ SELECT 1
331
+ FROM manual_file_tag_bindings mftb
332
+ WHERE mftb.tag_id = la.tag_id
333
+ AND (
334
+ (la.inode_key IS NOT NULL AND mftb.inode_key = la.inode_key)
335
+ OR (
336
+ la.content_hash IS NOT NULL
337
+ AND mftb.content_hash = la.content_hash
338
+ AND mftb.file_size = la.size
339
+ AND mftb.extension = la.extension
340
+ )
341
+ )
342
+ )
343
+ )
344
+ SELECT
345
+ (SELECT COUNT(*) FROM manual_file_tag_bindings) AS identity_binding_count,
346
+ (SELECT COUNT(*) FROM manual_document_tag_bindings) AS legacy_binding_count,
347
+ (SELECT COUNT(*) FROM legacy_only) AS legacy_fallback_binding_count,
348
+ (SELECT COUNT(DISTINCT document_id) FROM legacy_only) AS legacy_fallback_document_count
349
+ `).get();
350
+ return {
351
+ identityBindingCount: Number(row?.identity_binding_count ?? 0),
352
+ legacyBindingCount: Number(row?.legacy_binding_count ?? 0),
353
+ legacyFallbackBindingCount: Number(row?.legacy_fallback_binding_count ?? 0),
354
+ legacyFallbackDocumentCount: Number(row?.legacy_fallback_document_count ?? 0),
355
+ };
356
+ }
357
+ finally {
358
+ db.close();
359
+ }
360
+ }
361
+ resolveManualFileTagBindingsForDocuments(db, documents) {
362
+ if (documents.length === 0) {
363
+ return [];
364
+ }
365
+ const inodeKeys = [...new Set(documents.map((item) => item.inodeKey).filter((item) => Boolean(item)))];
366
+ const contentHashes = [...new Set(documents.map((item) => item.contentHash).filter((item) => Boolean(item)))];
367
+ if (inodeKeys.length === 0 && contentHashes.length === 0) {
368
+ return [];
369
+ }
370
+ const predicateParts = [];
371
+ const predicateParams = [];
372
+ if (inodeKeys.length > 0) {
373
+ predicateParts.push(`b.inode_key IN (${inodeKeys.map(() => "?").join(", ")})`);
374
+ predicateParams.push(...inodeKeys);
375
+ }
376
+ if (contentHashes.length > 0) {
377
+ predicateParts.push(`b.content_hash IN (${contentHashes.map(() => "?").join(", ")})`);
378
+ predicateParams.push(...contentHashes);
379
+ }
380
+ const candidateRows = db.prepare(`
381
+ SELECT
382
+ b.id,
383
+ b.inode_key,
384
+ b.content_hash,
385
+ b.file_size,
386
+ b.extension,
387
+ b.tag_id,
388
+ t.path AS tag_path,
389
+ b.source,
390
+ b.created_at,
391
+ b.updated_at
392
+ FROM manual_file_tag_bindings b
393
+ JOIN tags t ON t.id = b.tag_id
394
+ WHERE t.status = 'active'
395
+ AND (${predicateParts.join(" OR ")})
396
+ ORDER BY t.path, b.updated_at DESC, b.id
397
+ `).all(...predicateParams);
398
+ if (candidateRows.length === 0) {
399
+ return [];
400
+ }
401
+ const candidates = candidateRows.map((row) => ({
402
+ id: String(row.id),
403
+ inodeKey: typeof row.inode_key === "string" && row.inode_key.trim() ? String(row.inode_key) : null,
404
+ contentHash: typeof row.content_hash === "string" && row.content_hash.trim() ? String(row.content_hash) : null,
405
+ fileSize: Number(row.file_size ?? 0),
406
+ extension: String(row.extension ?? ""),
407
+ tagId: String(row.tag_id),
408
+ tagPath: String(row.tag_path),
409
+ source: String(row.source),
410
+ createdAt: String(row.created_at),
411
+ updatedAt: String(row.updated_at),
412
+ }));
413
+ const candidateInodeKeys = [...new Set(candidates.map((item) => item.inodeKey).filter((item) => Boolean(item)))];
414
+ const candidateContentHashes = [...new Set(candidates.map((item) => item.contentHash).filter((item) => Boolean(item)))];
415
+ const activeIdentityRows = this.listActiveDocumentIdentitiesByKeys(db, candidateInodeKeys, candidateContentHashes);
416
+ const activeDocIdsByInode = buildDocumentIdsByInode(activeIdentityRows);
417
+ const activeDocIdsByContent = buildDocumentIdsByContent(activeIdentityRows);
418
+ const resolved = new Map();
419
+ for (const document of documents) {
420
+ const documentContentKey = buildContentIdentityKey(document.contentHash, document.size, document.extension);
421
+ for (const candidate of candidates) {
422
+ const matchedByInode = Boolean(candidate.inodeKey && document.inodeKey && candidate.inodeKey === document.inodeKey);
423
+ const matchedByContent = !matchedByInode && matchesContentFallback(document, candidate, activeDocIdsByInode, activeDocIdsByContent, documentContentKey);
424
+ if (!matchedByInode && !matchedByContent) {
425
+ continue;
426
+ }
427
+ resolved.set(`${document.documentId}:${candidate.tagId}`, {
428
+ id: candidate.id,
429
+ documentId: document.documentId,
430
+ tagId: candidate.tagId,
431
+ tagPath: candidate.tagPath,
432
+ source: candidate.source,
433
+ createdAt: candidate.createdAt,
434
+ updatedAt: candidate.updatedAt,
435
+ });
436
+ }
437
+ }
438
+ return [...resolved.values()];
439
+ }
440
+ listActiveDocumentIdentitiesByKeys(db, inodeKeys, contentHashes) {
441
+ if (inodeKeys.length === 0 && contentHashes.length === 0) {
442
+ return [];
443
+ }
444
+ const predicateParts = [];
445
+ const params = [];
446
+ if (inodeKeys.length > 0) {
447
+ predicateParts.push(`f.inode_key IN (${inodeKeys.map(() => "?").join(", ")})`);
448
+ params.push(...inodeKeys);
449
+ }
450
+ if (contentHashes.length > 0) {
451
+ predicateParts.push(`f.content_hash IN (${contentHashes.map(() => "?").join(", ")})`);
452
+ params.push(...contentHashes);
453
+ }
454
+ const rows = db.prepare(`
455
+ SELECT
456
+ d.id AS document_id,
457
+ f.path,
458
+ f.inode_key,
459
+ f.content_hash,
460
+ f.size,
461
+ f.extension
462
+ FROM documents d
463
+ JOIN files f ON f.id = d.file_id
464
+ WHERE f.status = 'active'
465
+ AND d.index_status = 'indexed'
466
+ AND (${predicateParts.join(" OR ")})
467
+ `).all(...params);
468
+ return rows.map((row) => ({
469
+ documentId: String(row.document_id),
470
+ path: String(row.path),
471
+ inodeKey: typeof row.inode_key === "string" && row.inode_key.trim() ? String(row.inode_key) : null,
472
+ contentHash: typeof row.content_hash === "string" && row.content_hash.trim() ? String(row.content_hash) : null,
473
+ size: Number(row.size ?? 0),
474
+ extension: String(row.extension ?? ""),
475
+ }));
476
+ }
477
+ listFolderTagBindingsByPaths(paths) {
478
+ const normalizedPaths = [...new Set(paths.map(normalizeFolderBindingPath))];
479
+ if (normalizedPaths.length === 0) {
480
+ return [];
481
+ }
482
+ const db = openDatabase(this.dbPath, this.dbOptions);
483
+ try {
484
+ const placeholders = normalizedPaths.map(() => "?").join(", ");
485
+ const rows = db.prepare(`
486
+ SELECT
487
+ b.id,
488
+ b.folder_path,
489
+ b.tag_id,
490
+ t.path AS tag_path,
491
+ b.apply_mode,
492
+ b.created_at,
493
+ b.updated_at
494
+ FROM folder_tag_bindings b
495
+ JOIN tags t ON t.id = b.tag_id
496
+ WHERE b.folder_path IN (${placeholders})
497
+ ORDER BY b.folder_path, t.path
498
+ `).all(...normalizedPaths);
499
+ return rows.map(row => ({
500
+ id: String(row.id),
501
+ folderPath: String(row.folder_path),
502
+ tagId: String(row.tag_id),
503
+ tagPath: String(row.tag_path),
504
+ applyMode: String(row.apply_mode),
505
+ createdAt: String(row.created_at),
506
+ updatedAt: String(row.updated_at),
507
+ }));
508
+ }
509
+ finally {
510
+ db.close();
511
+ }
512
+ }
513
+ listEffectiveFolderTagBindingsForDocumentPaths(paths) {
514
+ const normalizedPaths = [...new Set(paths.map(item => item.trim().replace(/^\.\/+/, "")).filter(Boolean))];
515
+ if (normalizedPaths.length === 0) {
516
+ return [];
517
+ }
518
+ const db = openDatabase(this.dbPath, this.dbOptions);
519
+ try {
520
+ const valuePlaceholders = normalizedPaths.map(() => "(?)").join(", ");
521
+ const rows = db.prepare(`
522
+ WITH target_paths(path) AS (
523
+ VALUES ${valuePlaceholders}
524
+ )
525
+ SELECT
526
+ b.id,
527
+ b.folder_path,
528
+ b.tag_id,
529
+ t.path AS tag_path,
530
+ b.apply_mode,
531
+ b.created_at,
532
+ b.updated_at,
533
+ f.path AS document_path,
534
+ d.id AS document_id
535
+ FROM target_paths p
536
+ JOIN files f ON f.path = p.path
537
+ JOIN documents d ON d.file_id = f.id
538
+ JOIN folder_tag_bindings b ON (
539
+ b.folder_path = '.'
540
+ OR f.path = b.folder_path
541
+ OR f.path LIKE b.folder_path || '/%'
542
+ )
543
+ JOIN tags t ON t.id = b.tag_id
544
+ WHERE f.status = 'active'
545
+ AND d.index_status = 'indexed'
546
+ ORDER BY f.path, b.folder_path, t.path
547
+ `).all(...normalizedPaths);
548
+ return rows.map(row => ({
549
+ id: String(row.id),
550
+ folderPath: String(row.folder_path),
551
+ tagId: String(row.tag_id),
552
+ tagPath: String(row.tag_path),
553
+ applyMode: String(row.apply_mode),
554
+ createdAt: String(row.created_at),
555
+ updatedAt: String(row.updated_at),
556
+ documentPath: String(row.document_path),
557
+ documentId: String(row.document_id),
558
+ }));
559
+ }
560
+ finally {
561
+ db.close();
562
+ }
563
+ }
564
+ listEffectiveFolderTagBindingsForFolderScope(folderPath) {
565
+ const normalizedFolderPath = normalizeScopedFolderPath(folderPath);
566
+ const db = openDatabase(this.dbPath, this.dbOptions);
567
+ try {
568
+ const whereClause = normalizedFolderPath === "."
569
+ ? ""
570
+ : "AND (f.path = ? OR f.path LIKE ?)";
571
+ const params = normalizedFolderPath === "."
572
+ ? []
573
+ : [normalizedFolderPath, `${normalizedFolderPath}/%`];
574
+ const rows = db.prepare(`
575
+ SELECT
576
+ b.id,
577
+ b.folder_path,
578
+ b.tag_id,
579
+ t.path AS tag_path,
580
+ b.apply_mode,
581
+ b.created_at,
582
+ b.updated_at,
583
+ f.path AS document_path,
584
+ d.id AS document_id
585
+ FROM files f
586
+ JOIN documents d ON d.file_id = f.id
587
+ JOIN folder_tag_bindings b ON (
588
+ b.folder_path = '.'
589
+ OR f.path = b.folder_path
590
+ OR f.path LIKE b.folder_path || '/%'
591
+ )
592
+ JOIN tags t ON t.id = b.tag_id
593
+ WHERE f.status = 'active'
594
+ AND d.index_status = 'indexed'
595
+ ${whereClause}
596
+ ORDER BY f.path, b.folder_path, t.path
597
+ `).all(...params);
598
+ return rows.map(row => ({
599
+ id: String(row.id),
600
+ folderPath: String(row.folder_path),
601
+ tagId: String(row.tag_id),
602
+ tagPath: String(row.tag_path),
603
+ applyMode: String(row.apply_mode),
604
+ createdAt: String(row.created_at),
605
+ updatedAt: String(row.updated_at),
606
+ documentPath: String(row.document_path),
607
+ documentId: String(row.document_id),
608
+ }));
609
+ }
610
+ finally {
611
+ db.close();
612
+ }
613
+ }
614
+ listResolvedDocumentTagsByDocumentIds(documentIds) {
615
+ const normalizedIds = [...new Set(documentIds.map(item => item.trim()).filter(Boolean))];
616
+ if (normalizedIds.length === 0) {
617
+ return [];
618
+ }
619
+ const db = openDatabase(this.dbPath, this.dbOptions);
620
+ try {
621
+ const placeholders = normalizedIds.map(() => "?").join(", ");
622
+ const directRows = db.prepare(`
623
+ SELECT
624
+ dt.document_id,
625
+ t.path,
626
+ dt.tag_id,
627
+ dt.source AS source_type,
628
+ dt.source_ref,
629
+ dt.evidence,
630
+ dt.confidence,
631
+ dt.updated_at
632
+ FROM document_tags dt
633
+ JOIN tags t ON t.id = dt.tag_id
634
+ WHERE dt.document_id IN (${placeholders})
635
+ `).all(...normalizedIds);
636
+ const derivedRows = db.prepare(`
637
+ SELECT
638
+ ddt.document_id,
639
+ t.path,
640
+ ddt.tag_id,
641
+ ddt.source AS source_type,
642
+ ddt.source_ref,
643
+ ddt.evidence,
644
+ 1 AS confidence,
645
+ ddt.updated_at
646
+ FROM derived_document_tags ddt
647
+ JOIN tags t ON t.id = ddt.tag_id
648
+ WHERE ddt.document_id IN (${placeholders})
649
+ `).all(...normalizedIds);
650
+ return [...directRows, ...derivedRows]
651
+ .map(row => ({
652
+ documentId: String(row.document_id),
653
+ path: String(row.path),
654
+ tagId: String(row.tag_id),
655
+ sourceType: String(row.source_type),
656
+ sourceRef: typeof row.source_ref === "string" ? row.source_ref : null,
657
+ evidence: typeof row.evidence === "string" ? row.evidence : null,
658
+ confidence: Number(row.confidence ?? 0),
659
+ updatedAt: String(row.updated_at),
660
+ }))
661
+ .sort((left, right) => left.path.localeCompare(right.path, "zh-Hans-CN"));
662
+ }
663
+ finally {
664
+ db.close();
665
+ }
666
+ }
667
+ listRecomputeCandidateDocuments(scope) {
668
+ const db = openDatabase(this.dbPath, this.dbOptions);
669
+ try {
670
+ if (scope.kind === "document" && scope.documentId) {
671
+ const rows = db.prepare(`
672
+ SELECT d.id AS document_id, f.path, COALESCE(d.title, f.name) AS title,
673
+ COALESCE(d.summary, '') AS summary,
674
+ COALESCE(group_concat(c.content, char(10)), '') AS content_text,
675
+ f.mtime, f.ctime, f.extension
676
+ FROM documents d
677
+ JOIN files f ON f.id = d.file_id
678
+ LEFT JOIN chunks c ON c.document_id = d.id
679
+ WHERE d.id = ?
680
+ AND f.status = 'active'
681
+ AND d.index_status = 'indexed'
682
+ GROUP BY d.id, f.path, d.title, f.name, d.summary, f.mtime, f.ctime, f.extension
683
+ `).all(scope.documentId);
684
+ return rows.map(mapTagRecomputeRow);
685
+ }
686
+ if (scope.kind === "folder" && scope.folderPath) {
687
+ const normalizedPath = normalizeScopedFolderPath(scope.folderPath);
688
+ const includeContentText = scope.mode !== "folder_bindings_only";
689
+ const contentJoinClause = includeContentText
690
+ ? "LEFT JOIN chunks c ON c.document_id = d.id"
691
+ : "";
692
+ const contentSelectClause = includeContentText
693
+ ? "COALESCE(group_concat(c.content, char(10)), '') AS content_text,"
694
+ : "'' AS content_text,";
695
+ const whereClause = normalizedPath === "."
696
+ ? ""
697
+ : "AND (f.path = ? OR f.path LIKE ?)";
698
+ const groupByClause = includeContentText
699
+ ? "GROUP BY d.id, f.path, d.title, f.name, d.summary, f.mtime, f.ctime, f.extension"
700
+ : "";
701
+ const params = normalizedPath === "."
702
+ ? []
703
+ : [normalizedPath, `${normalizedPath}/%`];
704
+ const rows = db.prepare(`
705
+ SELECT d.id AS document_id, f.path, COALESCE(d.title, f.name) AS title,
706
+ COALESCE(d.summary, '') AS summary,
707
+ ${contentSelectClause}
708
+ f.mtime, f.ctime, f.extension
709
+ FROM documents d
710
+ JOIN files f ON f.id = d.file_id
711
+ ${contentJoinClause}
712
+ WHERE f.status = 'active'
713
+ AND d.index_status = 'indexed'
714
+ ${whereClause}
715
+ ${groupByClause}
716
+ ORDER BY f.path
717
+ `).all(...params);
718
+ return rows.map(mapTagRecomputeRow);
719
+ }
720
+ if (scope.kind === "tag" && scope.tagId) {
721
+ const rows = db.prepare(`
722
+ SELECT DISTINCT d.id AS document_id, f.path, COALESCE(d.title, f.name) AS title,
723
+ COALESCE(d.summary, '') AS summary,
724
+ COALESCE(group_concat(c.content, char(10)), '') AS content_text,
725
+ f.mtime, f.ctime, f.extension
726
+ FROM tag_rules r
727
+ JOIN tags t ON t.id = r.tag_id
728
+ JOIN documents d
729
+ LEFT JOIN chunks c ON c.document_id = d.id
730
+ JOIN files f ON f.id = d.file_id
731
+ WHERE r.tag_id = ?
732
+ AND f.status = 'active'
733
+ AND d.index_status = 'indexed'
734
+ GROUP BY d.id, f.path, d.title, f.name, d.summary, f.mtime, f.ctime, f.extension
735
+ ORDER BY f.path
736
+ `).all(scope.tagId);
737
+ return rows.map(mapTagRecomputeRow);
738
+ }
739
+ return this.listAllRecomputeCandidateDocuments(db);
740
+ }
741
+ finally {
742
+ db.close();
743
+ }
744
+ }
745
+ getDocumentContext(documentId, filePath) {
746
+ if (!documentId && !filePath) {
747
+ throw new Error("documentId 或 filePath 至少提供一个");
748
+ }
749
+ const db = openDatabase(this.dbPath, this.dbOptions);
750
+ try {
751
+ let row;
752
+ if (documentId) {
753
+ row = db.prepare(`
754
+ SELECT d.id AS document_id, f.path, COALESCE(d.title, f.name) AS title,
755
+ COALESCE(d.summary, '') AS summary, f.mtime, f.inode_key, f.content_hash, f.size, f.extension
756
+ FROM documents d
757
+ JOIN files f ON f.id = d.file_id
758
+ WHERE d.id = ?
759
+ AND f.status = 'active'
760
+ AND d.index_status = 'indexed'
761
+ `).get(documentId);
762
+ }
763
+ else if (filePath) {
764
+ row = db.prepare(`
765
+ SELECT d.id AS document_id, f.path, COALESCE(d.title, f.name) AS title,
766
+ COALESCE(d.summary, '') AS summary, f.mtime, f.inode_key, f.content_hash, f.size, f.extension
767
+ FROM documents d
768
+ JOIN files f ON f.id = d.file_id
769
+ WHERE f.path = ?
770
+ AND f.status = 'active'
771
+ AND d.index_status = 'indexed'
772
+ `).get(filePath);
773
+ }
774
+ if (!row) {
775
+ return null;
776
+ }
777
+ const resolvedDocumentId = String(row.document_id);
778
+ const tags = db.prepare(`
779
+ SELECT t.path AS tag_path
780
+ FROM tags t
781
+ JOIN document_tags dt ON dt.tag_id = t.id
782
+ WHERE dt.document_id = ?
783
+ UNION ALL
784
+ SELECT t.path AS tag_path
785
+ FROM tags t
786
+ JOIN derived_document_tags ddt ON ddt.tag_id = t.id
787
+ WHERE ddt.document_id = ?
788
+ ORDER BY tag_path
789
+ `).all(resolvedDocumentId, resolvedDocumentId);
790
+ return {
791
+ documentId: resolvedDocumentId,
792
+ path: String(row.path),
793
+ title: String(row.title),
794
+ summary: String(row.summary ?? ""),
795
+ modifiedAt: String(row.mtime),
796
+ inodeKey: typeof row.inode_key === "string" && row.inode_key.trim() ? String(row.inode_key) : null,
797
+ contentHash: typeof row.content_hash === "string" && row.content_hash.trim() ? String(row.content_hash) : null,
798
+ size: Number(row.size ?? 0),
799
+ extension: String(row.extension ?? ""),
800
+ tags: tags.map(item => item.tag_path),
801
+ };
802
+ }
803
+ finally {
804
+ db.close();
805
+ }
806
+ }
807
+ browseTags(rootType, parentPath) {
808
+ const db = openDatabase(this.dbPath, this.dbOptions);
809
+ try {
810
+ let sql = `
811
+ SELECT id, path, name, root_type, parent_id
812
+ FROM tags
813
+ WHERE status = 'active'
814
+ AND (
815
+ EXISTS (SELECT 1 FROM document_tags dt WHERE dt.tag_id = tags.id)
816
+ OR EXISTS (SELECT 1 FROM derived_document_tags ddt WHERE ddt.tag_id = tags.id)
817
+ OR EXISTS (SELECT 1 FROM tags child WHERE child.parent_id = tags.id AND child.status = 'active')
818
+ )
819
+ `;
820
+ const params = [];
821
+ if (rootType) {
822
+ sql += ` AND root_type = ?`;
823
+ params.push(rootType);
824
+ }
825
+ if (parentPath) {
826
+ const parentRow = db.prepare(`SELECT id FROM tags WHERE path = ?`).get(parentPath);
827
+ if (!parentRow?.id) {
828
+ return [];
829
+ }
830
+ sql += ` AND parent_id = ?`;
831
+ params.push(String(parentRow.id));
832
+ }
833
+ sql += ` ORDER BY path`;
834
+ const rows = db.prepare(sql).all(...params);
835
+ return rows.map(row => {
836
+ let parentPathValue = null;
837
+ if (row.parent_id) {
838
+ const parent = db.prepare(`SELECT path FROM tags WHERE id = ?`).get(row.parent_id);
839
+ parentPathValue = parent?.path ?? null;
840
+ }
841
+ return {
842
+ path: row.path,
843
+ name: row.name,
844
+ rootType: row.root_type,
845
+ parentPath: parentPathValue,
846
+ depth: row.path.split("/").length - 1,
847
+ };
848
+ });
849
+ }
850
+ finally {
851
+ db.close();
852
+ }
853
+ }
854
+ searchDocuments(query, limit = 20) {
855
+ const normalizedQuery = query.trim();
856
+ if (!normalizedQuery) {
857
+ return [];
858
+ }
859
+ const db = openDatabase(this.dbPath, this.dbOptions);
860
+ try {
861
+ const keyword = `%${normalizedQuery}%`;
862
+ const rows = db.prepare(`
863
+ SELECT d.id AS document_id, f.path, COALESCE(d.title, f.name) AS title,
864
+ COALESCE(d.summary, '') AS summary, f.mtime
865
+ FROM documents d
866
+ JOIN files f ON f.id = d.file_id
867
+ WHERE f.status = 'active'
868
+ AND d.index_status = 'indexed'
869
+ AND (
870
+ f.path LIKE ?
871
+ OR COALESCE(d.title, '') LIKE ?
872
+ OR COALESCE(d.summary, '') LIKE ?
873
+ )
874
+ ORDER BY f.mtime DESC, f.path ASC
875
+ LIMIT ?
876
+ `).all(keyword, keyword, keyword, limit);
877
+ return rows.map(row => ({
878
+ documentId: String(row.document_id),
879
+ path: String(row.path),
880
+ title: String(row.title),
881
+ summary: String(row.summary ?? ""),
882
+ modifiedAt: String(row.mtime),
883
+ }));
884
+ }
885
+ finally {
886
+ db.close();
887
+ }
888
+ }
889
+ listExportDocumentsByDocumentIds(documentIds) {
890
+ const normalizedIds = [...new Set(documentIds.map(item => item.trim()).filter(Boolean))];
891
+ if (normalizedIds.length === 0) {
892
+ return [];
893
+ }
894
+ const db = openDatabase(this.dbPath, this.dbOptions);
895
+ try {
896
+ const placeholders = normalizedIds.map(() => "?").join(", ");
897
+ const documentRows = db.prepare(`
898
+ SELECT d.id AS document_id, f.path, COALESCE(d.title, f.name) AS title,
899
+ COALESCE(d.summary, '') AS summary, f.mtime
900
+ FROM documents d
901
+ JOIN files f ON f.id = d.file_id
902
+ WHERE f.status = 'active'
903
+ AND d.index_status = 'indexed'
904
+ AND d.id IN (${placeholders})
905
+ ORDER BY f.path
906
+ `).all(...normalizedIds);
907
+ if (documentRows.length === 0) {
908
+ return [];
909
+ }
910
+ const ids = documentRows.map(row => String(row.document_id));
911
+ const { directTagRows, derivedTagRows, } = fetchDocumentTagsForIds(db, ids);
912
+ return attachTags(documentRows, directTagRows, derivedTagRows);
913
+ }
914
+ finally {
915
+ db.close();
916
+ }
917
+ }
918
+ listExportDocuments() {
919
+ const db = openDatabase(this.dbPath, this.dbOptions);
920
+ try {
921
+ const documentRows = db.prepare(`
922
+ SELECT d.id AS document_id, f.path, COALESCE(d.title, f.name) AS title,
923
+ COALESCE(d.summary, '') AS summary, f.mtime
924
+ FROM documents d
925
+ JOIN files f ON f.id = d.file_id
926
+ WHERE f.status = 'active'
927
+ AND d.index_status = 'indexed'
928
+ ORDER BY f.path
929
+ `).all();
930
+ const directTagRows = db.prepare(`
931
+ SELECT dt.document_id, t.path AS tag_path
932
+ FROM document_tags dt
933
+ JOIN tags t ON t.id = dt.tag_id
934
+ ORDER BY dt.document_id, t.path
935
+ `).all();
936
+ const derivedTagRows = db.prepare(`
937
+ SELECT ddt.document_id, t.path AS tag_path
938
+ FROM derived_document_tags ddt
939
+ JOIN tags t ON t.id = ddt.tag_id
940
+ ORDER BY ddt.document_id, t.path
941
+ `).all();
942
+ return attachTags(documentRows, directTagRows, derivedTagRows);
943
+ }
944
+ finally {
945
+ db.close();
946
+ }
947
+ }
948
+ listActiveFileExtensions() {
949
+ const db = openDatabase(this.dbPath, this.dbOptions);
950
+ try {
951
+ const rows = db.prepare(`
952
+ SELECT DISTINCT extension
953
+ FROM files
954
+ WHERE status = 'active'
955
+ AND extension IS NOT NULL
956
+ AND extension <> ''
957
+ ORDER BY extension
958
+ `).all();
959
+ return rows.map(row => String(row.extension));
960
+ }
961
+ finally {
962
+ db.close();
963
+ }
964
+ }
965
+ listExportDocumentsByPaths(paths) {
966
+ const normalizedPaths = [...new Set(paths.map(item => item.trim()).filter(Boolean))];
967
+ if (normalizedPaths.length === 0) {
968
+ return [];
969
+ }
970
+ const db = openDatabase(this.dbPath, this.dbOptions);
971
+ try {
972
+ const placeholders = normalizedPaths.map(() => "?").join(", ");
973
+ const documentRows = db.prepare(`
974
+ SELECT d.id AS document_id, f.path, COALESCE(d.title, f.name) AS title,
975
+ COALESCE(d.summary, '') AS summary, f.mtime
976
+ FROM documents d
977
+ JOIN files f ON f.id = d.file_id
978
+ WHERE f.status = 'active'
979
+ AND d.index_status = 'indexed'
980
+ AND f.path IN (${placeholders})
981
+ ORDER BY f.path
982
+ `).all(...normalizedPaths);
983
+ if (documentRows.length === 0) {
984
+ return [];
985
+ }
986
+ const documentIds = documentRows.map(row => String(row.document_id));
987
+ const tagPlaceholders = documentIds.map(() => "?").join(", ");
988
+ const directTagRows = db.prepare(`
989
+ SELECT dt.document_id, t.path AS tag_path
990
+ FROM document_tags dt
991
+ JOIN tags t ON t.id = dt.tag_id
992
+ WHERE dt.document_id IN (${tagPlaceholders})
993
+ ORDER BY dt.document_id, t.path
994
+ `).all(...documentIds);
995
+ const derivedTagRows = db.prepare(`
996
+ SELECT ddt.document_id, t.path AS tag_path
997
+ FROM derived_document_tags ddt
998
+ JOIN tags t ON t.id = ddt.tag_id
999
+ WHERE ddt.document_id IN (${tagPlaceholders})
1000
+ ORDER BY ddt.document_id, t.path
1001
+ `).all(...documentIds);
1002
+ return attachTags(documentRows, directTagRows, derivedTagRows);
1003
+ }
1004
+ finally {
1005
+ db.close();
1006
+ }
1007
+ }
1008
+ listExportDocumentsByExtensions(extensions) {
1009
+ const normalizedExtensions = [...new Set(extensions
1010
+ .map(item => item.trim().toLowerCase())
1011
+ .filter(Boolean)
1012
+ .map(item => item.startsWith(".") ? item : `.${item}`))];
1013
+ if (normalizedExtensions.length === 0) {
1014
+ return [];
1015
+ }
1016
+ const db = openDatabase(this.dbPath, this.dbOptions);
1017
+ try {
1018
+ const placeholders = normalizedExtensions.map(() => "?").join(", ");
1019
+ const documentRows = db.prepare(`
1020
+ SELECT d.id AS document_id, f.path, COALESCE(d.title, f.name) AS title,
1021
+ COALESCE(d.summary, '') AS summary, f.mtime
1022
+ FROM documents d
1023
+ JOIN files f ON f.id = d.file_id
1024
+ WHERE f.status = 'active'
1025
+ AND d.index_status = 'indexed'
1026
+ AND f.extension IN (${placeholders})
1027
+ ORDER BY f.path
1028
+ `).all(...normalizedExtensions);
1029
+ if (documentRows.length === 0) {
1030
+ return [];
1031
+ }
1032
+ const documentIds = documentRows.map(row => String(row.document_id));
1033
+ const { directTagRows, derivedTagRows, } = fetchDocumentTagsForIds(db, documentIds);
1034
+ return attachTags(documentRows, directTagRows, derivedTagRows);
1035
+ }
1036
+ finally {
1037
+ db.close();
1038
+ }
1039
+ }
1040
+ listExportTags() {
1041
+ const db = openDatabase(this.dbPath, this.dbOptions);
1042
+ try {
1043
+ const rows = db.prepare(`
1044
+ SELECT t.path, t.name, t.root_type, parent.path AS parent_path
1045
+ FROM tags t
1046
+ LEFT JOIN tags parent ON parent.id = t.parent_id
1047
+ WHERE t.status = 'active'
1048
+ AND (
1049
+ EXISTS (SELECT 1 FROM document_tags dt WHERE dt.tag_id = t.id)
1050
+ OR EXISTS (SELECT 1 FROM derived_document_tags ddt WHERE ddt.tag_id = t.id)
1051
+ OR EXISTS (SELECT 1 FROM tags child WHERE child.parent_id = t.id AND child.status = 'active')
1052
+ )
1053
+ ORDER BY t.path
1054
+ `).all();
1055
+ return rows.map(row => ({
1056
+ path: String(row.path),
1057
+ name: String(row.name),
1058
+ rootType: String(row.root_type),
1059
+ parentPath: row.parent_path ? String(row.parent_path) : null,
1060
+ depth: String(row.path).split("/").length - 1,
1061
+ }));
1062
+ }
1063
+ finally {
1064
+ db.close();
1065
+ }
1066
+ }
1067
+ *iterateExportDocuments(batchSize = 1000) {
1068
+ const db = openDatabase(this.dbPath, this.dbOptions);
1069
+ try {
1070
+ let lastPath = "";
1071
+ while (true) {
1072
+ const rows = db.prepare(`
1073
+ SELECT d.id AS document_id, f.path, COALESCE(d.title, f.name) AS title,
1074
+ COALESCE(d.summary, '') AS summary, f.mtime
1075
+ FROM documents d
1076
+ JOIN files f ON f.id = d.file_id
1077
+ WHERE f.status = 'active'
1078
+ AND d.index_status = 'indexed'
1079
+ AND f.path > ?
1080
+ ORDER BY f.path
1081
+ LIMIT ?
1082
+ `).all(lastPath, batchSize);
1083
+ if (rows.length === 0) {
1084
+ return;
1085
+ }
1086
+ yield mapDocumentRows(rows);
1087
+ lastPath = String(rows[rows.length - 1]?.path ?? lastPath);
1088
+ }
1089
+ }
1090
+ finally {
1091
+ db.close();
1092
+ }
1093
+ }
1094
+ *iterateExportDocumentRecords(batchSize = 1000) {
1095
+ const db = openDatabase(this.dbPath, this.dbOptions);
1096
+ try {
1097
+ let lastPath = "";
1098
+ while (true) {
1099
+ const documentRows = db.prepare(`
1100
+ SELECT d.id AS document_id, f.path, COALESCE(d.title, f.name) AS title,
1101
+ COALESCE(d.summary, '') AS summary, f.mtime
1102
+ FROM documents d
1103
+ JOIN files f ON f.id = d.file_id
1104
+ WHERE f.status = 'active'
1105
+ AND d.index_status = 'indexed'
1106
+ AND f.path > ?
1107
+ ORDER BY f.path
1108
+ LIMIT ?
1109
+ `).all(lastPath, batchSize);
1110
+ if (documentRows.length === 0) {
1111
+ return;
1112
+ }
1113
+ const documentIds = documentRows.map(row => String(row.document_id));
1114
+ const { directTagRows, derivedTagRows, } = fetchDocumentTagsForIds(db, documentIds);
1115
+ yield attachTags(documentRows, directTagRows, derivedTagRows);
1116
+ lastPath = String(documentRows[documentRows.length - 1]?.path ?? lastPath);
1117
+ }
1118
+ }
1119
+ finally {
1120
+ db.close();
1121
+ }
1122
+ }
1123
+ *iterateDocumentTagRows(batchSize = 5000) {
1124
+ const db = openDatabase(this.dbPath, this.dbOptions);
1125
+ try {
1126
+ let offset = 0;
1127
+ while (true) {
1128
+ const rows = db.prepare(`
1129
+ SELECT dt.document_id, t.path AS tag_path, 0 AS derived
1130
+ FROM document_tags dt
1131
+ JOIN tags t ON t.id = dt.tag_id
1132
+ ORDER BY dt.document_id, t.path
1133
+ LIMIT ? OFFSET ?
1134
+ `).all(batchSize, offset);
1135
+ if (rows.length === 0) {
1136
+ break;
1137
+ }
1138
+ yield rows.map(row => ({
1139
+ documentId: String(row.document_id),
1140
+ tagPath: String(row.tag_path),
1141
+ derived: Number(row.derived) === 1,
1142
+ }));
1143
+ offset += rows.length;
1144
+ }
1145
+ offset = 0;
1146
+ while (true) {
1147
+ const rows = db.prepare(`
1148
+ SELECT ddt.document_id, t.path AS tag_path, 1 AS derived
1149
+ FROM derived_document_tags ddt
1150
+ JOIN tags t ON t.id = ddt.tag_id
1151
+ ORDER BY ddt.document_id, t.path
1152
+ LIMIT ? OFFSET ?
1153
+ `).all(batchSize, offset);
1154
+ if (rows.length === 0) {
1155
+ return;
1156
+ }
1157
+ yield rows.map(row => ({
1158
+ documentId: String(row.document_id),
1159
+ tagPath: String(row.tag_path),
1160
+ derived: Number(row.derived) === 1,
1161
+ }));
1162
+ offset += rows.length;
1163
+ }
1164
+ }
1165
+ finally {
1166
+ db.close();
1167
+ }
1168
+ }
1169
+ *iterateTagPostingRows(batchSize = 5000) {
1170
+ const directIterator = this.iterateDirectTagPostingRows(batchSize);
1171
+ const derivedIterator = this.iterateDerivedTagPostingRows(batchSize);
1172
+ let directState = directIterator.next();
1173
+ let derivedState = derivedIterator.next();
1174
+ let directIndex = 0;
1175
+ let derivedIndex = 0;
1176
+ while (!directState.done || !derivedState.done) {
1177
+ const mergedBatch = [];
1178
+ while (mergedBatch.length < batchSize && (!directState.done || !derivedState.done)) {
1179
+ if (directState.done) {
1180
+ mergedBatch.push(derivedState.value[derivedIndex]);
1181
+ derivedIndex += 1;
1182
+ }
1183
+ else if (derivedState.done) {
1184
+ mergedBatch.push(directState.value[directIndex]);
1185
+ directIndex += 1;
1186
+ }
1187
+ else {
1188
+ const directRow = directState.value[directIndex];
1189
+ const derivedRow = derivedState.value[derivedIndex];
1190
+ if (compareTagPostingRows(directRow, derivedRow) <= 0) {
1191
+ mergedBatch.push(directRow);
1192
+ directIndex += 1;
1193
+ }
1194
+ else {
1195
+ mergedBatch.push(derivedRow);
1196
+ derivedIndex += 1;
1197
+ }
1198
+ }
1199
+ if (!directState.done && directIndex >= directState.value.length) {
1200
+ directState = directIterator.next();
1201
+ directIndex = 0;
1202
+ }
1203
+ if (!derivedState.done && derivedIndex >= derivedState.value.length) {
1204
+ derivedState = derivedIterator.next();
1205
+ derivedIndex = 0;
1206
+ }
1207
+ }
1208
+ if (mergedBatch.length === 0) {
1209
+ return;
1210
+ }
1211
+ yield mergedBatch;
1212
+ }
1213
+ }
1214
+ *iterateDirectTagPostingRows(batchSize = 5000) {
1215
+ const db = openDatabase(this.dbPath);
1216
+ try {
1217
+ let lastRootType = "";
1218
+ let lastTagPath = "";
1219
+ let lastPath = "";
1220
+ let lastDocumentId = "";
1221
+ while (true) {
1222
+ const rows = db.prepare(`
1223
+ SELECT t.root_type, t.path AS tag_path, dt.document_id, f.path, COALESCE(d.title, f.name) AS title, 0 AS derived
1224
+ FROM document_tags dt
1225
+ JOIN tags t ON t.id = dt.tag_id
1226
+ JOIN documents d ON d.id = dt.document_id
1227
+ JOIN files f ON f.id = d.file_id
1228
+ WHERE f.status = 'active'
1229
+ AND d.index_status = 'indexed'
1230
+ AND (
1231
+ t.root_type > ?
1232
+ OR (t.root_type = ? AND t.path > ?)
1233
+ OR (t.root_type = ? AND t.path = ? AND f.path > ?)
1234
+ OR (t.root_type = ? AND t.path = ? AND f.path = ? AND dt.document_id > ?)
1235
+ )
1236
+ ORDER BY t.root_type, t.path, f.path, dt.document_id
1237
+ LIMIT ?
1238
+ `).all(lastRootType, lastRootType, lastTagPath, lastRootType, lastTagPath, lastPath, lastRootType, lastTagPath, lastPath, lastDocumentId, batchSize);
1239
+ if (rows.length === 0) {
1240
+ return;
1241
+ }
1242
+ const mapped = rows.map(row => ({
1243
+ rootType: String(row.root_type),
1244
+ tagPath: String(row.tag_path),
1245
+ documentId: String(row.document_id),
1246
+ path: String(row.path),
1247
+ title: String(row.title),
1248
+ derived: false,
1249
+ }));
1250
+ yield mapped;
1251
+ const lastRow = mapped[mapped.length - 1];
1252
+ lastRootType = lastRow?.rootType ?? lastRootType;
1253
+ lastTagPath = lastRow?.tagPath ?? lastTagPath;
1254
+ lastPath = lastRow?.path ?? lastPath;
1255
+ lastDocumentId = lastRow?.documentId ?? lastDocumentId;
1256
+ }
1257
+ }
1258
+ finally {
1259
+ db.close();
1260
+ }
1261
+ }
1262
+ *iterateDerivedTagPostingRows(batchSize = 5000) {
1263
+ const db = openDatabase(this.dbPath);
1264
+ try {
1265
+ let lastRootType = "";
1266
+ let lastTagPath = "";
1267
+ let lastPath = "";
1268
+ let lastDocumentId = "";
1269
+ while (true) {
1270
+ const rows = db.prepare(`
1271
+ SELECT t.root_type, t.path AS tag_path, ddt.document_id, f.path, COALESCE(d.title, f.name) AS title, 1 AS derived
1272
+ FROM derived_document_tags ddt
1273
+ JOIN tags t ON t.id = ddt.tag_id
1274
+ JOIN documents d ON d.id = ddt.document_id
1275
+ JOIN files f ON f.id = d.file_id
1276
+ WHERE f.status = 'active'
1277
+ AND d.index_status = 'indexed'
1278
+ AND (
1279
+ t.root_type > ?
1280
+ OR (t.root_type = ? AND t.path > ?)
1281
+ OR (t.root_type = ? AND t.path = ? AND f.path > ?)
1282
+ OR (t.root_type = ? AND t.path = ? AND f.path = ? AND ddt.document_id > ?)
1283
+ )
1284
+ ORDER BY t.root_type, t.path, f.path, ddt.document_id
1285
+ LIMIT ?
1286
+ `).all(lastRootType, lastRootType, lastTagPath, lastRootType, lastTagPath, lastPath, lastRootType, lastTagPath, lastPath, lastDocumentId, batchSize);
1287
+ if (rows.length === 0) {
1288
+ return;
1289
+ }
1290
+ const mapped = rows.map(row => ({
1291
+ rootType: String(row.root_type),
1292
+ tagPath: String(row.tag_path),
1293
+ documentId: String(row.document_id),
1294
+ path: String(row.path),
1295
+ title: String(row.title),
1296
+ derived: true,
1297
+ }));
1298
+ yield mapped;
1299
+ const lastRow = mapped[mapped.length - 1];
1300
+ lastRootType = lastRow?.rootType ?? lastRootType;
1301
+ lastTagPath = lastRow?.tagPath ?? lastTagPath;
1302
+ lastPath = lastRow?.path ?? lastPath;
1303
+ lastDocumentId = lastRow?.documentId ?? lastDocumentId;
1304
+ }
1305
+ }
1306
+ finally {
1307
+ db.close();
1308
+ }
1309
+ }
1310
+ *iterateTagRecomputeDocuments(batchSize = 1000) {
1311
+ const db = openDatabase(this.dbPath);
1312
+ try {
1313
+ let lastPath = "";
1314
+ while (true) {
1315
+ const rows = db.prepare(`
1316
+ SELECT d.id AS document_id, f.path, COALESCE(d.title, f.name) AS title,
1317
+ COALESCE(d.summary, '') AS summary,
1318
+ COALESCE(group_concat(c.content, char(10)), '') AS content_text,
1319
+ f.mtime, f.ctime, f.extension
1320
+ FROM documents d
1321
+ JOIN files f ON f.id = d.file_id
1322
+ LEFT JOIN chunks c ON c.document_id = d.id
1323
+ WHERE f.status = 'active'
1324
+ AND d.index_status = 'indexed'
1325
+ AND f.path > ?
1326
+ GROUP BY d.id, f.path, d.title, f.name, d.summary, f.mtime, f.ctime, f.extension
1327
+ ORDER BY f.path
1328
+ LIMIT ?
1329
+ `).all(lastPath, batchSize);
1330
+ if (rows.length === 0) {
1331
+ return;
1332
+ }
1333
+ yield rows.map(row => ({
1334
+ documentId: String(row.document_id),
1335
+ path: String(row.path),
1336
+ title: String(row.title),
1337
+ summary: String(row.summary ?? ""),
1338
+ contentText: String(row.content_text ?? ""),
1339
+ mtime: String(row.mtime),
1340
+ ctime: String(row.ctime),
1341
+ extension: String(row.extension),
1342
+ }));
1343
+ lastPath = String(rows[rows.length - 1]?.path ?? lastPath);
1344
+ }
1345
+ }
1346
+ finally {
1347
+ db.close();
1348
+ }
1349
+ }
1350
+ listAllRecomputeCandidateDocuments(db) {
1351
+ const rows = db.prepare(`
1352
+ SELECT d.id AS document_id, f.path, COALESCE(d.title, f.name) AS title,
1353
+ COALESCE(d.summary, '') AS summary,
1354
+ COALESCE(group_concat(c.content, char(10)), '') AS content_text,
1355
+ f.mtime, f.ctime, f.extension
1356
+ FROM documents d
1357
+ JOIN files f ON f.id = d.file_id
1358
+ LEFT JOIN chunks c ON c.document_id = d.id
1359
+ WHERE f.status = 'active'
1360
+ AND d.index_status = 'indexed'
1361
+ GROUP BY d.id, f.path, d.title, f.name, d.summary, f.mtime, f.ctime, f.extension
1362
+ ORDER BY f.path
1363
+ `).all();
1364
+ return rows.map(mapTagRecomputeRow);
1365
+ }
1366
+ }
1367
+ function buildDocumentIdsByInode(rows) {
1368
+ const byInode = new Map();
1369
+ rows.forEach((row) => {
1370
+ if (!row.inodeKey) {
1371
+ return;
1372
+ }
1373
+ const current = byInode.get(row.inodeKey) ?? new Set();
1374
+ current.add(row.documentId);
1375
+ byInode.set(row.inodeKey, current);
1376
+ });
1377
+ return byInode;
1378
+ }
1379
+ function buildDocumentIdsByContent(rows) {
1380
+ const byContent = new Map();
1381
+ rows.forEach((row) => {
1382
+ const key = buildContentIdentityKey(row.contentHash, row.size, row.extension);
1383
+ if (!key) {
1384
+ return;
1385
+ }
1386
+ const current = byContent.get(key) ?? new Set();
1387
+ current.add(row.documentId);
1388
+ byContent.set(key, current);
1389
+ });
1390
+ return byContent;
1391
+ }
1392
+ function buildContentIdentityKey(contentHash, size, extension) {
1393
+ if (!contentHash) {
1394
+ return null;
1395
+ }
1396
+ return `${contentHash}::${size}::${extension}`;
1397
+ }
1398
+ function matchesContentFallback(document, candidate, activeDocIdsByInode, activeDocIdsByContent, documentContentKey) {
1399
+ const candidateContentKey = buildContentIdentityKey(candidate.contentHash, candidate.fileSize, candidate.extension);
1400
+ if (!documentContentKey || !candidateContentKey || documentContentKey !== candidateContentKey) {
1401
+ return false;
1402
+ }
1403
+ const contentMatches = activeDocIdsByContent.get(candidateContentKey);
1404
+ if (!contentMatches || contentMatches.size !== 1 || !contentMatches.has(document.documentId)) {
1405
+ return false;
1406
+ }
1407
+ if (!candidate.inodeKey) {
1408
+ return true;
1409
+ }
1410
+ const inodeMatches = activeDocIdsByInode.get(candidate.inodeKey);
1411
+ return !inodeMatches || (inodeMatches.size === 1 && inodeMatches.has(document.documentId));
1412
+ }
1413
+ function mapTagRecomputeRow(row) {
1414
+ return {
1415
+ documentId: String(row.document_id),
1416
+ path: String(row.path),
1417
+ title: String(row.title),
1418
+ summary: String(row.summary ?? ""),
1419
+ contentText: String(row.content_text ?? ""),
1420
+ mtime: String(row.mtime),
1421
+ ctime: String(row.ctime),
1422
+ extension: String(row.extension),
1423
+ };
1424
+ }
1425
+ function normalizeScopedFolderPath(value) {
1426
+ const normalized = value.trim().replace(/^\.\/+/, "").replace(/\/+$/g, "");
1427
+ if (!normalized || normalized === ".") {
1428
+ return ".";
1429
+ }
1430
+ return normalized;
1431
+ }
1432
+ function parseJsonRecord(value) {
1433
+ if (typeof value !== "string" || !value.trim()) {
1434
+ return {};
1435
+ }
1436
+ try {
1437
+ const parsed = JSON.parse(value);
1438
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
1439
+ return parsed;
1440
+ }
1441
+ }
1442
+ catch {
1443
+ return {};
1444
+ }
1445
+ return {};
1446
+ }
1447
+ function mapTagRuleRow(row) {
1448
+ const scope = parseJsonRecord(row.scope_json);
1449
+ const matcher = parseJsonRecord(row.matcher_json);
1450
+ const relationValue = typeof scope.relation === "string" ? scope.relation.toLowerCase() : "and";
1451
+ const relation = relationValue === "or" || relationValue === "not" ? relationValue : "and";
1452
+ return {
1453
+ id: String(row.id),
1454
+ tagId: String(row.tag_id),
1455
+ tagPath: String(row.tag_path),
1456
+ enabled: Number(row.enabled ?? 0) === 1,
1457
+ relation,
1458
+ ruleType: String(row.rule_type),
1459
+ matcher,
1460
+ minScore: row.min_score === null || row.min_score === undefined ? null : Number(row.min_score),
1461
+ priority: Number(row.priority ?? 0),
1462
+ source: String(row.source ?? "smart_rule"),
1463
+ createdAt: String(row.created_at),
1464
+ updatedAt: String(row.updated_at),
1465
+ };
1466
+ }
1467
+ function normalizeFolderBindingPath(value) {
1468
+ const normalized = value.trim().replace(/^\.\/+/, "").replace(/\/+$/g, "");
1469
+ return normalized || ".";
1470
+ }
1471
+ //# sourceMappingURL=catalog-repository.js.map