wiki-viewer 1.7.2 → 1.8.1

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 (424) hide show
  1. package/.next/standalone/.github/workflows/publish.yml +1 -1
  2. package/.next/standalone/.next/BUILD_ID +1 -1
  3. package/.next/standalone/.next/app-path-routes-manifest.json +6 -0
  4. package/.next/standalone/.next/build-manifest.json +3 -3
  5. package/.next/standalone/.next/prerender-manifest.json +3 -3
  6. package/.next/standalone/.next/routes-manifest.json +40 -0
  7. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  8. package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
  9. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  10. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  11. package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  12. package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  13. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  14. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  15. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  16. package/.next/standalone/.next/server/app/_not-found.rsc +2 -2
  17. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  18. package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  19. package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  20. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  21. package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  22. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  23. package/.next/standalone/.next/server/app/api/agent/activity/route.js +6 -6
  24. package/.next/standalone/.next/server/app/api/agent/activity/route.js.nft.json +1 -1
  25. package/.next/standalone/.next/server/app/api/agent/admin/agents/[agentId]/revoke/route.js +6 -6
  26. package/.next/standalone/.next/server/app/api/agent/admin/agents/[agentId]/revoke/route.js.nft.json +1 -1
  27. package/.next/standalone/.next/server/app/api/agent/admin/agents/route.js +6 -6
  28. package/.next/standalone/.next/server/app/api/agent/admin/agents/route.js.nft.json +1 -1
  29. package/.next/standalone/.next/server/app/api/agent/admin/registrations/[regId]/approve/route.js +7 -7
  30. package/.next/standalone/.next/server/app/api/agent/admin/registrations/[regId]/approve/route.js.nft.json +1 -1
  31. package/.next/standalone/.next/server/app/api/agent/admin/registrations/[regId]/deny/route.js +5 -5
  32. package/.next/standalone/.next/server/app/api/agent/admin/registrations/[regId]/deny/route.js.nft.json +1 -1
  33. package/.next/standalone/.next/server/app/api/agent/admin/registrations/route.js +5 -5
  34. package/.next/standalone/.next/server/app/api/agent/admin/registrations/route.js.nft.json +1 -1
  35. package/.next/standalone/.next/server/app/api/agent/events/[...path]/route.js +8 -7
  36. package/.next/standalone/.next/server/app/api/agent/events/[...path]/route.js.nft.json +1 -1
  37. package/.next/standalone/.next/server/app/api/agent/files/[...path]/route.js +9 -8
  38. package/.next/standalone/.next/server/app/api/agent/files/[...path]/route.js.nft.json +1 -1
  39. package/.next/standalone/.next/server/app/api/agent/fs/file/[...path]/route.js +8 -7
  40. package/.next/standalone/.next/server/app/api/agent/fs/file/[...path]/route.js.nft.json +1 -1
  41. package/.next/standalone/.next/server/app/api/agent/fs/ls/[[...path]]/route.js +7 -7
  42. package/.next/standalone/.next/server/app/api/agent/fs/ls/[[...path]]/route.js.nft.json +1 -1
  43. package/.next/standalone/.next/server/app/api/agent/fs/move/route.js +6 -5
  44. package/.next/standalone/.next/server/app/api/agent/fs/move/route.js.nft.json +1 -1
  45. package/.next/standalone/.next/server/app/api/agent/fs/search/route.js +7 -6
  46. package/.next/standalone/.next/server/app/api/agent/fs/search/route.js.nft.json +1 -1
  47. package/.next/standalone/.next/server/app/api/agent/internal/span/route.js +6 -5
  48. package/.next/standalone/.next/server/app/api/agent/internal/span/route.js.nft.json +1 -1
  49. package/.next/standalone/.next/server/app/api/agent/settings/route.js +7 -7
  50. package/.next/standalone/.next/server/app/api/agent/settings/route.js.nft.json +1 -1
  51. package/.next/standalone/.next/server/app/api/agent/sidecar/[...path]/route.js +8 -7
  52. package/.next/standalone/.next/server/app/api/agent/sidecar/[...path]/route.js.nft.json +1 -1
  53. package/.next/standalone/.next/server/app/api/app-proxy/[...path]/route.js +2 -2
  54. package/.next/standalone/.next/server/app/api/app-proxy/[...path]/route.js.nft.json +1 -1
  55. package/.next/standalone/.next/server/app/api/assets/[...path]/route.js +8 -2
  56. package/.next/standalone/.next/server/app/api/assets/[...path]/route.js.nft.json +1 -1
  57. package/.next/standalone/.next/server/app/api/auth/[...all]/route.js +5 -5
  58. package/.next/standalone/.next/server/app/api/auth/[...all]/route.js.nft.json +1 -1
  59. package/.next/standalone/.next/server/app/api/system/admins/route/app-paths-manifest.json +3 -0
  60. package/.next/standalone/.next/server/app/api/system/admins/route/build-manifest.json +9 -0
  61. package/.next/standalone/.next/server/app/api/system/admins/route/server-reference-manifest.json +4 -0
  62. package/.next/standalone/.next/server/app/api/system/admins/route.js +14 -0
  63. package/.next/standalone/.next/server/app/api/system/admins/route.js.map +5 -0
  64. package/.next/standalone/.next/server/app/api/system/admins/route.js.nft.json +1 -0
  65. package/.next/standalone/.next/server/app/api/system/admins/route_client-reference-manifest.js +3 -0
  66. package/.next/standalone/.next/server/app/api/system/auth-config/route.js +6 -6
  67. package/.next/standalone/.next/server/app/api/system/auth-config/route.js.nft.json +1 -1
  68. package/.next/standalone/.next/server/app/api/system/auth-settings/route.js +4 -4
  69. package/.next/standalone/.next/server/app/api/system/auth-settings/route.js.nft.json +1 -1
  70. package/.next/standalone/.next/server/app/api/system/browse/route.js +4 -4
  71. package/.next/standalone/.next/server/app/api/system/browse/route.js.nft.json +1 -1
  72. package/.next/standalone/.next/server/app/api/system/clear-root/route.js +5 -5
  73. package/.next/standalone/.next/server/app/api/system/clear-root/route.js.nft.json +1 -1
  74. package/.next/standalone/.next/server/app/api/system/config/route.js +6 -6
  75. package/.next/standalone/.next/server/app/api/system/config/route.js.nft.json +1 -1
  76. package/.next/standalone/.next/server/app/api/system/pins/route.js +4 -4
  77. package/.next/standalone/.next/server/app/api/system/pins/route.js.nft.json +1 -1
  78. package/.next/standalone/.next/server/app/api/system/reveal/route.js +6 -6
  79. package/.next/standalone/.next/server/app/api/system/reveal/route.js.nft.json +1 -1
  80. package/.next/standalone/.next/server/app/api/system/root-status/route.js +5 -5
  81. package/.next/standalone/.next/server/app/api/system/root-status/route.js.nft.json +1 -1
  82. package/.next/standalone/.next/server/app/api/system/set-root/route.js +6 -6
  83. package/.next/standalone/.next/server/app/api/system/set-root/route.js.nft.json +1 -1
  84. package/.next/standalone/.next/server/app/api/system/users/route/app-paths-manifest.json +3 -0
  85. package/.next/standalone/.next/server/app/api/system/users/route/build-manifest.json +9 -0
  86. package/.next/standalone/.next/server/app/api/system/users/route/server-reference-manifest.json +4 -0
  87. package/.next/standalone/.next/server/app/api/system/users/route.js +14 -0
  88. package/.next/standalone/.next/server/app/api/system/users/route.js.map +5 -0
  89. package/.next/standalone/.next/server/app/api/system/users/route.js.nft.json +1 -0
  90. package/.next/standalone/.next/server/app/api/system/users/route_client-reference-manifest.js +3 -0
  91. package/.next/standalone/.next/server/app/api/system/workspaces/[id]/open/route/app-paths-manifest.json +3 -0
  92. package/.next/standalone/.next/server/app/api/system/workspaces/[id]/open/route/build-manifest.json +9 -0
  93. package/.next/standalone/.next/server/app/api/system/workspaces/[id]/open/route/server-reference-manifest.json +4 -0
  94. package/.next/standalone/.next/server/app/api/system/workspaces/[id]/open/route.js +14 -0
  95. package/.next/standalone/.next/server/app/api/system/workspaces/[id]/open/route.js.map +5 -0
  96. package/.next/standalone/.next/server/app/api/system/workspaces/[id]/open/route.js.nft.json +1 -0
  97. package/.next/standalone/.next/server/app/api/system/workspaces/[id]/open/route_client-reference-manifest.js +3 -0
  98. package/.next/standalone/.next/server/app/api/system/workspaces/[id]/route/app-paths-manifest.json +3 -0
  99. package/.next/standalone/.next/server/app/api/system/workspaces/[id]/route/build-manifest.json +9 -0
  100. package/.next/standalone/.next/server/app/api/system/workspaces/[id]/route/server-reference-manifest.json +4 -0
  101. package/.next/standalone/.next/server/app/api/system/workspaces/[id]/route.js +14 -0
  102. package/.next/standalone/.next/server/app/api/system/workspaces/[id]/route.js.map +5 -0
  103. package/.next/standalone/.next/server/app/api/system/workspaces/[id]/route.js.nft.json +1 -0
  104. package/.next/standalone/.next/server/app/api/system/workspaces/[id]/route_client-reference-manifest.js +3 -0
  105. package/.next/standalone/.next/server/app/api/system/workspaces/route/app-paths-manifest.json +3 -0
  106. package/.next/standalone/.next/server/app/api/system/workspaces/route/build-manifest.json +9 -0
  107. package/.next/standalone/.next/server/app/api/system/workspaces/route/server-reference-manifest.json +4 -0
  108. package/.next/standalone/.next/server/app/api/system/workspaces/route.js +14 -0
  109. package/.next/standalone/.next/server/app/api/system/workspaces/route.js.map +5 -0
  110. package/.next/standalone/.next/server/app/api/system/workspaces/route.js.nft.json +1 -0
  111. package/.next/standalone/.next/server/app/api/system/workspaces/route_client-reference-manifest.js +3 -0
  112. package/.next/standalone/.next/server/app/api/upload/[...path]/route.js +8 -2
  113. package/.next/standalone/.next/server/app/api/upload/[...path]/route.js.nft.json +1 -1
  114. package/.next/standalone/.next/server/app/api/wiki/app/route.js +5 -5
  115. package/.next/standalone/.next/server/app/api/wiki/app/route.js.nft.json +1 -1
  116. package/.next/standalone/.next/server/app/api/wiki/content/route.js +6 -6
  117. package/.next/standalone/.next/server/app/api/wiki/content/route.js.nft.json +1 -1
  118. package/.next/standalone/.next/server/app/api/wiki/download/route.js +7 -7
  119. package/.next/standalone/.next/server/app/api/wiki/download/route.js.nft.json +1 -1
  120. package/.next/standalone/.next/server/app/api/wiki/file/route.js +8 -2
  121. package/.next/standalone/.next/server/app/api/wiki/file/route.js.nft.json +1 -1
  122. package/.next/standalone/.next/server/app/api/wiki/folder/route.js +6 -6
  123. package/.next/standalone/.next/server/app/api/wiki/folder/route.js.nft.json +1 -1
  124. package/.next/standalone/.next/server/app/api/wiki/move/route.js +6 -6
  125. package/.next/standalone/.next/server/app/api/wiki/move/route.js.nft.json +1 -1
  126. package/.next/standalone/.next/server/app/api/wiki/new-file/route.js +7 -7
  127. package/.next/standalone/.next/server/app/api/wiki/new-file/route.js.nft.json +1 -1
  128. package/.next/standalone/.next/server/app/api/wiki/page/route.js +7 -7
  129. package/.next/standalone/.next/server/app/api/wiki/page/route.js.nft.json +1 -1
  130. package/.next/standalone/.next/server/app/api/wiki/presence/route.js +7 -7
  131. package/.next/standalone/.next/server/app/api/wiki/presence/route.js.nft.json +1 -1
  132. package/.next/standalone/.next/server/app/api/wiki/route.js +6 -6
  133. package/.next/standalone/.next/server/app/api/wiki/route.js.nft.json +1 -1
  134. package/.next/standalone/.next/server/app/api/wiki/search/route/app-paths-manifest.json +3 -0
  135. package/.next/standalone/.next/server/app/api/wiki/search/route/build-manifest.json +9 -0
  136. package/.next/standalone/.next/server/app/api/wiki/search/route/server-reference-manifest.json +4 -0
  137. package/.next/standalone/.next/server/app/api/wiki/search/route.js +15 -0
  138. package/.next/standalone/.next/server/app/api/wiki/search/route.js.map +5 -0
  139. package/.next/standalone/.next/server/app/api/wiki/search/route.js.nft.json +1 -0
  140. package/.next/standalone/.next/server/app/api/wiki/search/route_client-reference-manifest.js +3 -0
  141. package/.next/standalone/.next/server/app/api/wiki/slugs/route.js +6 -6
  142. package/.next/standalone/.next/server/app/api/wiki/slugs/route.js.nft.json +1 -1
  143. package/.next/standalone/.next/server/app/api/wiki/upload/route.js +7 -7
  144. package/.next/standalone/.next/server/app/api/wiki/upload/route.js.nft.json +1 -1
  145. package/.next/standalone/.next/server/app/api/wiki/watch/route.js +7 -9
  146. package/.next/standalone/.next/server/app/api/wiki/watch/route.js.nft.json +1 -1
  147. package/.next/standalone/.next/server/app/index.html +1 -1
  148. package/.next/standalone/.next/server/app/index.rsc +3 -3
  149. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  150. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +3 -3
  151. package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  152. package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +2 -2
  153. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  154. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  155. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  156. package/.next/standalone/.next/server/app/signin/page.js +1 -1
  157. package/.next/standalone/.next/server/app/signin/page.js.nft.json +1 -1
  158. package/.next/standalone/.next/server/app/signin/page_client-reference-manifest.js +1 -1
  159. package/.next/standalone/.next/server/app-paths-manifest.json +6 -0
  160. package/.next/standalone/.next/server/chunks/0p91_next_dist_esm_build_templates_app-route_0d2jbo5.js +1 -1
  161. package/.next/standalone/.next/server/chunks/0p91_next_dist_esm_build_templates_app-route_0ytral2.js +1 -1
  162. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0-244bv._.js +16 -0
  163. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0xz-_0v._.js → [root-of-the-server]__0-inabx._.js} +2 -2
  164. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0-ao6a_._.js → [root-of-the-server]__0.-9jt0._.js} +1 -1
  165. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0~-r-8f._.js → [root-of-the-server]__00c1-dr._.js} +1 -1
  166. package/.next/standalone/.next/server/chunks/[root-of-the-server]__00lep-u._.js +3 -0
  167. package/.next/standalone/.next/server/chunks/[root-of-the-server]__00mtevo._.js +3 -0
  168. package/.next/standalone/.next/server/chunks/[root-of-the-server]__00qu86p._.js +3 -0
  169. package/.next/standalone/.next/server/chunks/[root-of-the-server]__012753j._.js +3 -0
  170. package/.next/standalone/.next/server/chunks/[root-of-the-server]__01hp8ax._.js +3 -0
  171. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0269d2e._.js +1 -1
  172. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0jhr.ex._.js → [root-of-the-server]__02n6z97._.js} +1 -1
  173. package/.next/standalone/.next/server/chunks/[root-of-the-server]__036mhjp._.js +5 -0
  174. package/.next/standalone/.next/server/chunks/[root-of-the-server]__03p0ob1._.js +16 -0
  175. package/.next/standalone/.next/server/chunks/[root-of-the-server]__05t~v6l._.js +3 -0
  176. package/.next/standalone/.next/server/chunks/[root-of-the-server]__068ni_k._.js +3 -0
  177. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__082nhm6._.js → [root-of-the-server]__07vphbd._.js} +1 -1
  178. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0pg6dn-._.js → [root-of-the-server]__08lkuwa._.js} +1 -1
  179. package/.next/standalone/.next/server/chunks/[root-of-the-server]__09cqzem._.js +3 -0
  180. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0p_ox-k._.js → [root-of-the-server]__09k4q9e._.js} +1 -1
  181. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0_0_601._.js +3 -0
  182. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ae3dk6._.js +3 -0
  183. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0s28.4-._.js → [root-of-the-server]__0af-x45._.js} +1 -1
  184. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0cqu-wm._.js +3 -0
  185. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0d75a5q._.js +1 -1
  186. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0d7x3e1._.js +3 -0
  187. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0d7zxm_._.js +3 -0
  188. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0e7vs98._.js +3 -0
  189. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0fxzg4v._.js +3 -0
  190. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0gda_iu._.js +3 -0
  191. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0hu~q20._.js +3 -0
  192. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0jk1uf4._.js +3 -0
  193. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0l-8clq._.js +3 -0
  194. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0lhka0x._.js +3 -0
  195. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0kdn1le._.js → [root-of-the-server]__0na11h0._.js} +2 -2
  196. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0nd.b_c._.js +3 -0
  197. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0otb8ra._.js +3 -0
  198. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0p0-p__._.js +3 -0
  199. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0piofm3._.js +3 -0
  200. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0rrf-jr._.js +3 -0
  201. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0s6_lzw._.js +3 -0
  202. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0sh13v5._.js +3 -0
  203. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ta~flu._.js +3 -0
  204. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0v4im4p._.js +3 -0
  205. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0qn8e~s._.js → [root-of-the-server]__0v_kyp-._.js} +1 -1
  206. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0vatqe-._.js +3 -0
  207. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0vdb2nr._.js +3 -0
  208. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0wdh63w._.js +3 -0
  209. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0z3wg9x._.js +12 -0
  210. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0mzo03s._.js → [root-of-the-server]__0~.-3yk._.js} +1 -1
  211. package/.next/standalone/.next/server/chunks/[root-of-the-server]__123._fe._.js +3 -0
  212. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__12800b1._.js → [root-of-the-server]__12ee_s6._.js} +1 -1
  213. package/.next/standalone/.next/server/chunks/[root-of-the-server]__12onytt._.js +3 -0
  214. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__04udrya._.js → [root-of-the-server]__12q8ch8._.js} +2 -2
  215. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1377.79._.js +3 -0
  216. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1378-ox._.js +3 -0
  217. package/.next/standalone/.next/server/chunks/[root-of-the-server]__13aid91._.js +3 -0
  218. package/.next/standalone/.next/server/chunks/[root-of-the-server]__13hp4tw._.js +12 -0
  219. package/.next/standalone/.next/server/chunks/_079xuln._.js +1 -1
  220. package/.next/standalone/.next/server/chunks/_0dr1r1g._.js +452 -0
  221. package/.next/standalone/.next/server/chunks/_101exke._.js +452 -0
  222. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_system_admins_route_actions_0dsm7cx.js +3 -0
  223. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_system_users_route_actions_0whj5cy.js +3 -0
  224. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_system_workspaces_[id]_open_route_actions_1087xu7.js +3 -0
  225. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_system_workspaces_[id]_route_actions_0~h7-8s.js +3 -0
  226. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_system_workspaces_route_actions_0mkalc3.js +3 -0
  227. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_wiki_search_route_actions_0inxu93.js +3 -0
  228. package/.next/standalone/.next/server/chunks/node_modules__pnpm_0aj5g-w._.js +1 -1
  229. package/.next/standalone/.next/server/chunks/src_lib_search_0d-_j3u._.js +46 -0
  230. package/.next/standalone/.next/server/chunks/src_lib_search_0ymmp0c._.js +46 -0
  231. package/.next/standalone/.next/server/chunks/ssr/{0~w0_katex_dist_katex_mjs_0b8ra51._.js → 0~w0_katex_dist_katex_mjs_04mhawr._.js} +1 -1
  232. package/.next/standalone/.next/server/chunks/ssr/12y~_mermaid_dist_chunks_mermaid_core_erDiagram-TEJ5UH35_mjs_0v6rnqy._.js +1 -1
  233. package/.next/standalone/.next/server/chunks/ssr/12y~_mermaid_dist_mermaid_core_mjs_0hj_n-~._.js +1 -1
  234. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0btcd4o._.js → [root-of-the-server]__02twzph._.js} +2 -2
  235. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0ytvlzs._.js → [root-of-the-server]__09~x2v~._.js} +2 -2
  236. package/.next/standalone/.next/server/chunks/ssr/_0pqaawz._.js +18 -18
  237. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0c71i8a._.js → node_modules__pnpm_0.96tmo._.js} +1 -1
  238. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0lm8e2c._.js → node_modules__pnpm_011vy_q._.js} +2 -2
  239. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0ezm2us._.js → node_modules__pnpm_01o_5qt._.js} +1 -1
  240. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0j3mvgg._.js → node_modules__pnpm_04n0h6.._.js} +1 -1
  241. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0~ln0by._.js → node_modules__pnpm_093dp2q._.js} +1 -1
  242. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_11e~j49._.js → node_modules__pnpm_09ej62_._.js} +1 -1
  243. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0de8xt-._.js → node_modules__pnpm_09ljbdz._.js} +2 -2
  244. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0-x6zex._.js → node_modules__pnpm_09~_ob2._.js} +1 -1
  245. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0yq5z.h._.js → node_modules__pnpm_0a01ng7._.js} +2 -2
  246. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0kwc-vs._.js → node_modules__pnpm_0b8qx0g._.js} +1 -1
  247. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0hrbz84._.js → node_modules__pnpm_0bbc---._.js} +1 -1
  248. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0hobcbs._.js → node_modules__pnpm_0c.309.._.js} +1 -1
  249. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0rw91-f._.js → node_modules__pnpm_0c8aunj._.js} +1 -1
  250. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0o.c1z8._.js → node_modules__pnpm_0hk6xys._.js} +2 -2
  251. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0dboa_e._.js → node_modules__pnpm_0hlzy8f._.js} +1 -1
  252. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0j53hti._.js → node_modules__pnpm_0nw5ou2._.js} +1 -1
  253. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0xrmzh1._.js → node_modules__pnpm_0o.dn8o._.js} +1 -1
  254. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0cxwhfd._.js → node_modules__pnpm_0s0ur~d._.js} +1 -1
  255. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_07rxv2x._.js → node_modules__pnpm_0shlang._.js} +1 -1
  256. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0i.pw_m._.js → node_modules__pnpm_0sq3c2r._.js} +1 -1
  257. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0ajzar9._.js → node_modules__pnpm_0t9jb7d._.js} +1 -1
  258. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_012nt.s._.js → node_modules__pnpm_0wmx9kq._.js} +2 -2
  259. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0z~h2ow._.js → node_modules__pnpm_0xfx0sf._.js} +1 -1
  260. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0cbsnwf._.js → node_modules__pnpm_0yiz.-t._.js} +1 -1
  261. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0bum3-3._.js → node_modules__pnpm_11sut1u._.js} +1 -1
  262. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0mdo4i3._.js → node_modules__pnpm_124u4o2._.js} +2 -2
  263. package/.next/standalone/.next/server/chunks/ssr/{node_modules__pnpm_0il8j.j._.js → node_modules__pnpm_13tajgx._.js} +2 -2
  264. package/.next/standalone/.next/server/chunks/ssr/src_app_signin_00yk0vm._.js +2 -2
  265. package/.next/standalone/.next/server/edge/chunks/{08yl_next_dist_esm_build_templates_edge-wrapper_0o9h3w_.js → 08yl_next_dist_esm_build_templates_edge-wrapper_0xbpts6.js} +2 -2
  266. package/.next/standalone/.next/server/edge/chunks/[root-of-the-server]__0.pmgt2._.js +3 -0
  267. package/.next/standalone/.next/server/functions-config-manifest.json +6 -0
  268. package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
  269. package/.next/standalone/.next/server/middleware-manifest.json +8 -8
  270. package/.next/standalone/.next/server/pages/404.html +1 -1
  271. package/.next/standalone/.next/server/pages/500.html +1 -1
  272. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  273. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  274. package/.next/standalone/.next/static/chunks/0c_~zevf2n0r4.css +2 -0
  275. package/.next/standalone/.next/static/chunks/0l4842ez-0_66.js +129 -0
  276. package/.next/standalone/README.md +46 -2
  277. package/.next/standalone/agents/bootstrap-prompt.md +3 -1
  278. package/.next/standalone/agents/wiki-viewer-skill/SKILL.md +38 -11
  279. package/.next/standalone/docs/workspacing-plan.md +364 -0
  280. package/.next/standalone/package.json +2 -2
  281. package/.next/standalone/packages/wiki-viewer-mcp/README.md +6 -5
  282. package/.next/standalone/packages/wiki-viewer-mcp/dist/http-client.js +4 -0
  283. package/.next/standalone/packages/wiki-viewer-mcp/dist/index.js +4 -0
  284. package/.next/standalone/packages/wiki-viewer-mcp/src/http-client.ts +6 -0
  285. package/.next/standalone/packages/wiki-viewer-mcp/src/index.ts +5 -0
  286. package/.next/standalone/src/app/api/agent/activity/route.ts +9 -8
  287. package/.next/standalone/src/app/api/agent/events/[...path]/route.ts +20 -8
  288. package/.next/standalone/src/app/api/agent/files/[...path]/route.ts +16 -9
  289. package/.next/standalone/src/app/api/agent/fs/file/[...path]/route.ts +28 -18
  290. package/.next/standalone/src/app/api/agent/fs/ls/[[...path]]/route.ts +12 -7
  291. package/.next/standalone/src/app/api/agent/fs/move/route.ts +16 -11
  292. package/.next/standalone/src/app/api/agent/fs/search/route.ts +49 -13
  293. package/.next/standalone/src/app/api/agent/internal/span/route.ts +9 -5
  294. package/.next/standalone/src/app/api/agent/register/route.ts +9 -1
  295. package/.next/standalone/src/app/api/agent/settings/route.ts +7 -3
  296. package/.next/standalone/src/app/api/agent/sidecar/[...path]/route.ts +8 -4
  297. package/.next/standalone/src/app/api/agents/install/route.ts +20 -2
  298. package/.next/standalone/src/app/api/assets/[...path]/route.ts +9 -4
  299. package/.next/standalone/src/app/api/system/admins/route.ts +103 -0
  300. package/.next/standalone/src/app/api/system/reveal/route.ts +7 -6
  301. package/.next/standalone/src/app/api/system/set-root/route.ts +24 -1
  302. package/.next/standalone/src/app/api/system/users/route.ts +120 -0
  303. package/.next/standalone/src/app/api/system/workspaces/[id]/open/route.ts +34 -0
  304. package/.next/standalone/src/app/api/system/workspaces/[id]/route.ts +74 -0
  305. package/.next/standalone/src/app/api/system/workspaces/route.ts +67 -0
  306. package/.next/standalone/src/app/api/upload/[...path]/route.ts +10 -5
  307. package/.next/standalone/src/app/api/wiki/app/route.ts +10 -9
  308. package/.next/standalone/src/app/api/wiki/content/route.ts +14 -14
  309. package/.next/standalone/src/app/api/wiki/download/route.ts +7 -6
  310. package/.next/standalone/src/app/api/wiki/file/route.ts +7 -2
  311. package/.next/standalone/src/app/api/wiki/folder/route.ts +6 -5
  312. package/.next/standalone/src/app/api/wiki/move/route.ts +7 -7
  313. package/.next/standalone/src/app/api/wiki/new-file/route.ts +7 -6
  314. package/.next/standalone/src/app/api/wiki/page/route.ts +6 -5
  315. package/.next/standalone/src/app/api/wiki/presence/route.ts +8 -7
  316. package/.next/standalone/src/app/api/wiki/route.ts +13 -11
  317. package/.next/standalone/src/app/api/wiki/search/route.ts +44 -0
  318. package/.next/standalone/src/app/api/wiki/slugs/route.ts +8 -8
  319. package/.next/standalone/src/app/api/wiki/upload/route.ts +6 -5
  320. package/.next/standalone/src/app/api/wiki/watch/route.ts +16 -40
  321. package/.next/standalone/src/app/globals.css +484 -484
  322. package/.next/standalone/src/app/page.tsx +163 -49
  323. package/.next/standalone/src/components/auth-settings-sheet.tsx +171 -2
  324. package/.next/standalone/src/components/dir-picker.tsx +8 -6
  325. package/.next/standalone/src/components/editor/comment-thread.tsx +2 -1
  326. package/.next/standalone/src/components/editor/csv-viewer.tsx +3 -2
  327. package/.next/standalone/src/components/editor/editor-toolbar.tsx +2 -2
  328. package/.next/standalone/src/components/editor/editor.tsx +6 -5
  329. package/.next/standalone/src/components/editor/file-fallback-viewer.tsx +3 -2
  330. package/.next/standalone/src/components/editor/folder-index.tsx +2 -1
  331. package/.next/standalone/src/components/editor/image-viewer.tsx +2 -1
  332. package/.next/standalone/src/components/editor/media-popover.tsx +2 -1
  333. package/.next/standalone/src/components/editor/media-viewer.tsx +2 -1
  334. package/.next/standalone/src/components/editor/mermaid-viewer.tsx +3 -2
  335. package/.next/standalone/src/components/editor/node-app-viewer.tsx +4 -3
  336. package/.next/standalone/src/components/editor/notebook-viewer.tsx +3 -2
  337. package/.next/standalone/src/components/editor/office/docx-viewer.tsx +2 -1
  338. package/.next/standalone/src/components/editor/office/office-chrome.tsx +3 -2
  339. package/.next/standalone/src/components/editor/office/pptx-viewer.tsx +2 -1
  340. package/.next/standalone/src/components/editor/office/xlsx-viewer.tsx +2 -1
  341. package/.next/standalone/src/components/editor/pdf-viewer.tsx +2 -1
  342. package/.next/standalone/src/components/editor/proof-span-popover.tsx +2 -1
  343. package/.next/standalone/src/components/editor/source-viewer.tsx +3 -2
  344. package/.next/standalone/src/components/editor/suggest-edit-popover.tsx +2 -1
  345. package/.next/standalone/src/components/editor/suggestion-card.tsx +2 -1
  346. package/.next/standalone/src/components/editor/website-viewer.tsx +2 -1
  347. package/.next/standalone/src/components/editor/wiki-link-create-dialog.tsx +2 -1
  348. package/.next/standalone/src/components/search/search-command-dialog.tsx +109 -0
  349. package/.next/standalone/src/components/search/sidebar-search-box.tsx +121 -0
  350. package/.next/standalone/src/components/search/snippet-text.tsx +48 -0
  351. package/.next/standalone/src/components/ui/command.tsx +3 -2
  352. package/.next/standalone/src/lib/auth/admin.ts +112 -0
  353. package/.next/standalone/src/lib/auth/server.ts +13 -2
  354. package/.next/standalone/src/lib/config.ts +56 -4
  355. package/.next/standalone/src/lib/proof/audit.ts +19 -10
  356. package/.next/standalone/src/lib/proof/auth.ts +11 -0
  357. package/.next/standalone/src/lib/proof/collab-state.ts +4 -2
  358. package/.next/standalone/src/lib/proof/file-lock.ts +5 -0
  359. package/.next/standalone/src/lib/proof/idempotency.ts +5 -0
  360. package/.next/standalone/src/lib/proof/lease.ts +40 -27
  361. package/.next/standalone/src/lib/proof/mutex.ts +4 -0
  362. package/.next/standalone/src/lib/proof/raw-fs.ts +2 -3
  363. package/.next/standalone/src/lib/proof/registry.ts +5 -0
  364. package/.next/standalone/src/lib/search/indexable-exts.ts +25 -0
  365. package/.next/standalone/src/lib/search/indexer.ts +567 -0
  366. package/.next/standalone/src/lib/search/sanitize.ts +35 -0
  367. package/.next/standalone/src/lib/search/search-db.ts +57 -0
  368. package/.next/standalone/src/lib/search/watcher-pool.ts +79 -0
  369. package/.next/standalone/src/lib/workspace-client.ts +82 -0
  370. package/.next/standalone/src/lib/workspace-context.ts +142 -0
  371. package/.next/standalone/src/lib/workspaces.ts +196 -0
  372. package/.next/standalone/src/stores/ai-panel-store.ts +3 -2
  373. package/.next/standalone/src/stores/editor-store.ts +4 -3
  374. package/.next/standalone/src/stores/proof-store.ts +4 -3
  375. package/.next/standalone/src/stores/search-store.ts +86 -0
  376. package/.next/standalone/src/stores/wiki-slugs-store.ts +2 -1
  377. package/.next/standalone/src/tests/proof/admin-create-user.test.ts +43 -0
  378. package/.next/standalone/src/tests/proof/agent-workspace-scope.test.ts +134 -0
  379. package/.next/standalone/src/tests/proof/collab-state.test.ts +43 -41
  380. package/.next/standalone/src/tests/proof/preload.ts +21 -0
  381. package/.next/standalone/src/tests/proof/search-index.test.ts +339 -0
  382. package/.next/standalone/src/tests/proof/workspace-isolation.test.ts +87 -0
  383. package/.next/standalone/src/tests/proof/workspaces-api.test.ts +227 -0
  384. package/.next/standalone/tsconfig.tsbuildinfo +1 -1
  385. package/README.md +46 -2
  386. package/package.json +2 -2
  387. package/.next/standalone/.next/server/chunks/0p91_next_dist_esm_build_templates_app-route_0o~h4zq.js +0 -5
  388. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0.hb9q2._.js +0 -3
  389. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0.uux34._.js +0 -3
  390. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0092hkp._.js +0 -3
  391. package/.next/standalone/.next/server/chunks/[root-of-the-server]__05f6x0i._.js +0 -3
  392. package/.next/standalone/.next/server/chunks/[root-of-the-server]__05idwm9._.js +0 -3
  393. package/.next/standalone/.next/server/chunks/[root-of-the-server]__06-dtd0._.js +0 -3
  394. package/.next/standalone/.next/server/chunks/[root-of-the-server]__06sek6_._.js +0 -3
  395. package/.next/standalone/.next/server/chunks/[root-of-the-server]__07fpqks._.js +0 -3
  396. package/.next/standalone/.next/server/chunks/[root-of-the-server]__094q5bj._.js +0 -3
  397. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0awzyon._.js +0 -3
  398. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0d_da6q._.js +0 -3
  399. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0hhhvm7._.js +0 -3
  400. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0kk26wc._.js +0 -3
  401. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0km8suj._.js +0 -3
  402. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0kur4ro._.js +0 -15
  403. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0mkwoul._.js +0 -12
  404. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0qc2~6l._.js +0 -15
  405. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0qyd-o8._.js +0 -3
  406. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0rkve~v._.js +0 -3
  407. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0rzo40z._.js +0 -3
  408. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0sjocwy._.js +0 -3
  409. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ssj9~d._.js +0 -3
  410. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0s~i040._.js +0 -3
  411. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0t220d-._.js +0 -3
  412. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0t5mg.n._.js +0 -3
  413. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0trsqf4._.js +0 -3
  414. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0xq124z._.js +0 -3
  415. package/.next/standalone/.next/server/chunks/[root-of-the-server]__106uw_c._.js +0 -3
  416. package/.next/standalone/.next/server/chunks/[root-of-the-server]__10w2q~o._.js +0 -3
  417. package/.next/standalone/.next/server/chunks/[root-of-the-server]__13w-0iy._.js +0 -3
  418. package/.next/standalone/.next/server/chunks/src_lib_auth_server_ts_00f4e0h._.js +0 -452
  419. package/.next/standalone/.next/server/edge/chunks/[root-of-the-server]__0ug2rvl._.js +0 -3
  420. package/.next/standalone/.next/static/chunks/0vwkqw_rofm-c.js +0 -129
  421. package/.next/standalone/.next/static/chunks/0zay6349~v_wc.css +0 -2
  422. /package/.next/standalone/.next/static/{0XvNCOSEq7cbARTLtAolL → 17VWCQ9_AhwJBT4yjkvWG}/_buildManifest.js +0 -0
  423. /package/.next/standalone/.next/static/{0XvNCOSEq7cbARTLtAolL → 17VWCQ9_AhwJBT4yjkvWG}/_clientMiddlewareManifest.js +0 -0
  424. /package/.next/standalone/.next/static/{0XvNCOSEq7cbARTLtAolL → 17VWCQ9_AhwJBT4yjkvWG}/_ssgManifest.js +0 -0
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Search database lifecycle.
3
+ *
4
+ * Separate from auth.db: FTS5 shadow tables would pollute the auth schema and
5
+ * better-auth's migrator could misidentify them. search.db is rebuildable from
6
+ * the filesystem at any time -- deleting it only triggers a rescan on next access.
7
+ *
8
+ * Mirrors src/lib/proof/audit.ts structure.
9
+ */
10
+ import Database from "better-sqlite3";
11
+ import path from "node:path";
12
+ import os from "node:os";
13
+ import { mkdirSync } from "node:fs";
14
+
15
+ function dataDir(): string {
16
+ return path.join(process.env.HOME ?? os.homedir(), ".wiki-viewer");
17
+ }
18
+
19
+ let _db: InstanceType<typeof Database> | null = null;
20
+
21
+ export function getSearchDb(): InstanceType<typeof Database> {
22
+ if (_db) return _db;
23
+ const dir = dataDir();
24
+ mkdirSync(dir, { recursive: true });
25
+ _db = new Database(path.join(dir, "search.db"));
26
+ _db.pragma("journal_mode = WAL");
27
+ _db.pragma("synchronous = NORMAL");
28
+ _db.pragma("temp_store = MEMORY");
29
+ _db.pragma("mmap_size = 134217728"); // 128 MiB
30
+ _db.exec(`
31
+ CREATE VIRTUAL TABLE IF NOT EXISTS docs USING fts5(
32
+ ws UNINDEXED,
33
+ path UNINDEXED,
34
+ name,
35
+ frontmatter,
36
+ body,
37
+ tokenize = 'porter unicode61 remove_diacritics 2'
38
+ );
39
+ CREATE TABLE IF NOT EXISTS docs_meta (
40
+ ws TEXT NOT NULL,
41
+ path TEXT NOT NULL,
42
+ size INTEGER NOT NULL,
43
+ mtime_ns INTEGER NOT NULL,
44
+ sha TEXT NOT NULL,
45
+ indexed_at TEXT NOT NULL,
46
+ PRIMARY KEY (ws, path)
47
+ ) WITHOUT ROWID;
48
+ CREATE INDEX IF NOT EXISTS docs_meta_ws_idx ON docs_meta(ws);
49
+ `);
50
+ return _db;
51
+ }
52
+
53
+ /** Reset cached DB handle. Used by tests to pick up a new HOME. */
54
+ export function _resetSearchDb(): void {
55
+ try { _db?.close(); } catch { /* ignore */ }
56
+ _db = null;
57
+ }
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Shared chokidar watcher pool.
3
+ *
4
+ * Ensures exactly ONE FSWatcher per workspace regardless of how many SSE
5
+ * connections or indexer subscriptions are active. When the last subscriber
6
+ * unsubscribes, the watcher is closed.
7
+ *
8
+ * The watch route and the indexer both subscribe through this pool.
9
+ */
10
+ import { watch, type FSWatcher } from "chokidar";
11
+ import path from "node:path";
12
+
13
+ export type WatchEvent = "add" | "unlink" | "addDir" | "unlinkDir" | "change";
14
+ export type WatchListener = (ev: WatchEvent, relPath: string) => void;
15
+
16
+ interface PoolEntry {
17
+ watcher: FSWatcher;
18
+ listeners: Set<WatchListener>;
19
+ rootDir: string;
20
+ }
21
+
22
+ const pool = new Map<string, PoolEntry>();
23
+
24
+ /**
25
+ * Subscribe to file-system events for a workspace.
26
+ * Returns an unsubscribe function. Call it when the subscriber is done.
27
+ * The pool creates a watcher on first subscribe and closes it on last unsubscribe.
28
+ */
29
+ export function subscribe(
30
+ wsId: string,
31
+ rootDir: string,
32
+ fn: WatchListener,
33
+ ): () => void {
34
+ let entry = pool.get(wsId);
35
+ if (!entry) {
36
+ const watcher = watch(rootDir, {
37
+ ignoreInitial: true,
38
+ ignored: /(node_modules|\.git|\.next|\.proof)/,
39
+ persistent: true,
40
+ awaitWriteFinish: { stabilityThreshold: 150, pollInterval: 50 },
41
+ });
42
+ entry = { watcher, listeners: new Set(), rootDir };
43
+ pool.set(wsId, entry);
44
+
45
+ const emit = (ev: WatchEvent, abs: string) => {
46
+ const e = pool.get(wsId);
47
+ if (!e) return;
48
+ const rel = path.relative(e.rootDir, abs);
49
+ e.listeners.forEach((l) => {
50
+ try { l(ev, rel); } catch { /* listener errors must not crash the pool */ }
51
+ });
52
+ };
53
+
54
+ watcher.on("add", (p: string) => emit("add", p));
55
+ watcher.on("unlink", (p: string) => emit("unlink", p));
56
+ watcher.on("change", (p: string) => emit("change", p));
57
+ watcher.on("addDir", (p: string) => { const rel = path.relative(rootDir, p); if (rel) emit("addDir", p); });
58
+ watcher.on("unlinkDir", (p: string) => { const rel = path.relative(rootDir, p); if (rel) emit("unlinkDir", p); });
59
+ }
60
+ entry.listeners.add(fn);
61
+
62
+ return () => {
63
+ const e = pool.get(wsId);
64
+ if (!e) return;
65
+ e.listeners.delete(fn);
66
+ if (e.listeners.size === 0) {
67
+ e.watcher.close().catch(() => { /* ignore */ });
68
+ pool.delete(wsId);
69
+ }
70
+ };
71
+ }
72
+
73
+ /** Reset entire pool. Used by tests. */
74
+ export function _resetWatcherPool(): void {
75
+ for (const e of pool.values()) {
76
+ e.watcher.close().catch(() => { /* ignore */ });
77
+ }
78
+ pool.clear();
79
+ }
@@ -0,0 +1,82 @@
1
+ /**
2
+ * workspace-client.ts — browser-safe ws injection helpers.
3
+ * No React, no server imports. Safe to use in any "use client" file.
4
+ */
5
+
6
+ /**
7
+ * URL prefixes that are workspace-scoped and need ?ws= injected.
8
+ * Rules:
9
+ * include: /api/wiki, /api/assets/, /api/agent/ (except sub-paths below),
10
+ * /api/upload/, /api/system/reveal
11
+ * exclude: /api/agent/admin, /api/agent/register, /api/agents
12
+ * (those are global registrations, not file-workspace calls)
13
+ */
14
+ const WS_SCOPED_PREFIXES = [
15
+ "/api/wiki",
16
+ "/api/assets/",
17
+ "/api/upload/",
18
+ "/api/system/reveal",
19
+ ];
20
+
21
+ const WS_AGENT_PREFIX = "/api/agent/";
22
+
23
+ const WS_AGENT_EXCLUDED_PREFIXES = [
24
+ "/api/agent/admin",
25
+ "/api/agent/register",
26
+ "/api/agents",
27
+ ];
28
+
29
+ export function getActiveWorkspaceId(): string | null {
30
+ if (typeof window === "undefined") return null;
31
+ return new URLSearchParams(window.location.search).get("ws");
32
+ }
33
+
34
+ /** Returns true if this URL is workspace-scoped and needs ?ws= appended. */
35
+ function needsWs(pathname: string): boolean {
36
+ // Excluded patterns first (match on prefix + segment boundary so
37
+ // "/api/agent/adminfoo" is NOT treated as "/api/agent/admin").
38
+ for (const ex of WS_AGENT_EXCLUDED_PREFIXES) {
39
+ if (pathname === ex || pathname.startsWith(ex + "/")) return false;
40
+ }
41
+ if (pathname.startsWith(WS_AGENT_PREFIX)) return true;
42
+ for (const prefix of WS_SCOPED_PREFIXES) {
43
+ if (pathname.startsWith(prefix)) return true;
44
+ }
45
+ return false;
46
+ }
47
+
48
+ /**
49
+ * Append ?ws=<activeId> to a workspace-scoped URL if:
50
+ * - the URL needs ws injection (needsWs)
51
+ * - an active workspace id exists in the current URL
52
+ * - the URL doesn't already carry a ws= param
53
+ *
54
+ * Handles both plain paths (/api/wiki) and paths with existing query strings
55
+ * (/api/wiki/content?path=foo → /api/wiki/content?path=foo&ws=<id>).
56
+ */
57
+ export function withWs(url: string): string {
58
+ const wsId = getActiveWorkspaceId();
59
+ if (!wsId) return url;
60
+
61
+ // Split on first '?' to isolate the pathname
62
+ const qIdx = url.indexOf("?");
63
+ const pathname = qIdx === -1 ? url : url.slice(0, qIdx);
64
+ const search = qIdx === -1 ? "" : url.slice(qIdx + 1);
65
+
66
+ if (!needsWs(pathname)) return url;
67
+
68
+ // Don't double-inject
69
+ const params = new URLSearchParams(search);
70
+ if (params.has("ws")) return url;
71
+
72
+ params.set("ws", wsId);
73
+ return `${pathname}?${params.toString()}`;
74
+ }
75
+
76
+ /**
77
+ * drop-in fetch replacement that injects ?ws=<activeId> on workspace-scoped
78
+ * URLs. Non-scoped URLs pass through unchanged.
79
+ */
80
+ export function wsFetch(input: string, init?: RequestInit): Promise<Response> {
81
+ return fetch(withWs(input), init);
82
+ }
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Request-scoped workspace resolution for browser/session routes.
3
+ *
4
+ * Determines which workspace a request targets and enforces access control.
5
+ * Phase B routes call this instead of getRootDir().
6
+ */
7
+
8
+ import path from "node:path";
9
+ import { requireUser } from "@/lib/auth/server";
10
+ import { isAdmin } from "@/lib/auth/admin";
11
+ import { getRootDir } from "@/lib/root-dir";
12
+ import {
13
+ getWorkspace,
14
+ listWorkspaces,
15
+ userCanAccess,
16
+ migrateConfigToWorkspaces,
17
+ type Workspace,
18
+ } from "@/lib/workspaces";
19
+
20
+ /**
21
+ * Synthetic fallback workspace built from the legacy process-global rootDir
22
+ * (root-dir.ts). Used only when the registry has no workspaces — keeps the
23
+ * ROOT_DIR / CLI / test paths working until Phase E removes the global.
24
+ * Returns null when no global root is set either.
25
+ */
26
+ function fallbackWorkspace(): Workspace | null {
27
+ const root = getRootDir();
28
+ if (!root) return null;
29
+ return {
30
+ id: "ws_default",
31
+ name: path.basename(root) || "workspace",
32
+ rootDir: root,
33
+ createdAt: new Date(0).toISOString(),
34
+ };
35
+ }
36
+
37
+ /**
38
+ * Resolve the target workspace from the request alone (no auth/access check).
39
+ * Selection: ?ws= query → x-workspace header → most-recent lastOpenedAt →
40
+ * synthetic fallback from the global rootDir. Returns null if nothing resolves.
41
+ */
42
+ async function pickWorkspace(req: Request): Promise<Workspace | null> {
43
+ await migrateConfigToWorkspaces();
44
+ const url = new URL(req.url);
45
+ const wsId = url.searchParams.get("ws") ?? req.headers.get("x-workspace") ?? null;
46
+ if (wsId) {
47
+ return (await getWorkspace(wsId)) ?? null;
48
+ }
49
+ const all = await listWorkspaces();
50
+ if (all.length === 0) return fallbackWorkspace();
51
+ return all
52
+ .slice()
53
+ .sort((a, b) => {
54
+ const ta = a.lastOpenedAt ? new Date(a.lastOpenedAt).getTime() : 0;
55
+ const tb = b.lastOpenedAt ? new Date(b.lastOpenedAt).getTime() : 0;
56
+ if (tb !== ta) return tb - ta;
57
+ return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
58
+ })[0];
59
+ }
60
+
61
+ export interface WorkspaceContext {
62
+ ok: true;
63
+ ws: Workspace;
64
+ rootDir: string;
65
+ userId: string;
66
+ isAdmin: boolean;
67
+ }
68
+
69
+ export interface WorkspaceError {
70
+ ok: false;
71
+ status: number;
72
+ code: string;
73
+ }
74
+
75
+ /**
76
+ * Resolves the workspace for a browser/session request.
77
+ *
78
+ * Selection order:
79
+ * 1. `?ws=<id>` query param (preferred).
80
+ * 2. `x-workspace` header.
81
+ * 3. Fall back to the workspace with the most recent lastOpenedAt.
82
+ * If exactly one workspace exists, use it.
83
+ * If zero workspaces → 400 WORKSPACE_REQUIRED.
84
+ */
85
+ export async function resolveWorkspaceForUser(
86
+ req: Request,
87
+ ): Promise<WorkspaceContext | WorkspaceError> {
88
+ // Authenticate
89
+ const auth = await requireUser(req);
90
+ if (!auth.ok) return { ok: false, status: 401, code: "UNAUTHORIZED" };
91
+
92
+ const admin = await isAdmin(auth.user.id, auth.user.email);
93
+ const url = new URL(req.url);
94
+ const explicitWsId =
95
+ url.searchParams.get("ws") ?? req.headers.get("x-workspace") ?? null;
96
+
97
+ const ws = await pickWorkspace(req);
98
+ if (!ws) {
99
+ // No workspace and no global root configured yet.
100
+ return {
101
+ ok: false,
102
+ status: explicitWsId ? 404 : 400,
103
+ code: explicitWsId ? "WORKSPACE_NOT_FOUND" : "WORKSPACE_REQUIRED",
104
+ };
105
+ }
106
+
107
+ if (!userCanAccess(ws, auth.user.id, admin)) {
108
+ return { ok: false, status: 403, code: "WORKSPACE_FORBIDDEN" };
109
+ }
110
+
111
+ return { ok: true, ws, rootDir: ws.rootDir, userId: auth.user.id, isAdmin: admin };
112
+ }
113
+
114
+ export interface AgentWorkspaceContext {
115
+ ok: true;
116
+ ws: Workspace;
117
+ rootDir: string;
118
+ }
119
+
120
+ /**
121
+ * Resolve the target workspace for an AUTHENTICATED agent request.
122
+ *
123
+ * Phase B: resolution only (no per-agent workspace grant check — that is added
124
+ * in Phase C, which will verify the agent's scope.workspaceId === ws.id).
125
+ * Selection mirrors the session resolver: ?ws / x-workspace / default / global.
126
+ */
127
+ export async function resolveWorkspaceForAgent(
128
+ req: Request,
129
+ ): Promise<AgentWorkspaceContext | WorkspaceError> {
130
+ const ws = await pickWorkspace(req);
131
+ if (!ws) {
132
+ const url = new URL(req.url);
133
+ const explicit =
134
+ url.searchParams.get("ws") ?? req.headers.get("x-workspace") ?? null;
135
+ return {
136
+ ok: false,
137
+ status: explicit ? 404 : 400,
138
+ code: explicit ? "WORKSPACE_NOT_FOUND" : "WORKSPACE_REQUIRED",
139
+ };
140
+ }
141
+ return { ok: true, ws, rootDir: ws.rootDir };
142
+ }
@@ -0,0 +1,196 @@
1
+ /**
2
+ * Workspace registry — persisted in ~/.wiki-viewer/config.json under `workspaces[]`.
3
+ *
4
+ * Design choice: rootDir is the natural namespace key for in-memory stores
5
+ * (lease, mutex, idempotency). Each workspace has a stable `id` for URLs and
6
+ * access control. All mutations read fresh config inside the function to
7
+ * avoid stale in-memory copies.
8
+ */
9
+
10
+ import path from "node:path";
11
+ import { randomBytes } from "node:crypto";
12
+ import { readConfig, updateConfig } from "./config";
13
+
14
+ export interface Workspace {
15
+ /** "ws_" + 6 random url-safe bytes. Stable, used in ?ws= query param. */
16
+ id: string;
17
+ /** Display label. Defaults to path.basename(rootDir). */
18
+ name: string;
19
+ /** Absolute, path.resolve'd rootDir. */
20
+ rootDir: string;
21
+ createdAt: string;
22
+ lastOpenedAt?: string;
23
+ /** Per-workspace pinned paths (moved from flat config.pinnedPaths). */
24
+ pinnedPaths?: string[];
25
+ /** User id of admin who created this workspace. */
26
+ createdBy?: string;
27
+ /**
28
+ * Explicit access list. Empty / undefined = any signed-in user may access.
29
+ * Admin users always have access regardless of this list.
30
+ */
31
+ allowedUserIds?: string[];
32
+ }
33
+
34
+ // ── Queries ────────────────────────────────────────────────────────────────────
35
+
36
+ export async function listWorkspaces(): Promise<Workspace[]> {
37
+ const cfg = await readConfig();
38
+ return (cfg.workspaces ?? []) as Workspace[];
39
+ }
40
+
41
+ export async function getWorkspace(id: string): Promise<Workspace | null> {
42
+ const list = await listWorkspaces();
43
+ return list.find((w) => w.id === id) ?? null;
44
+ }
45
+
46
+ export async function resolveWorkspaceRoot(id: string): Promise<string | null> {
47
+ const ws = await getWorkspace(id);
48
+ return ws?.rootDir ?? null;
49
+ }
50
+
51
+ // ── Mutations ──────────────────────────────────────────────────────────────────
52
+
53
+ export async function createWorkspace(input: {
54
+ rootDir: string;
55
+ name?: string;
56
+ createdBy?: string;
57
+ }): Promise<Workspace> {
58
+ const rootDir = path.resolve(input.rootDir);
59
+ const ws: Workspace = {
60
+ id: "ws_" + randomBytes(6).toString("base64url"),
61
+ name: input.name ?? path.basename(rootDir),
62
+ rootDir,
63
+ createdAt: new Date().toISOString(),
64
+ lastOpenedAt: new Date().toISOString(),
65
+ createdBy: input.createdBy,
66
+ };
67
+ await updateConfig((cfg) => ({
68
+ ...cfg,
69
+ workspaces: [...((cfg.workspaces ?? []) as Workspace[]), ws],
70
+ }));
71
+ return ws;
72
+ }
73
+
74
+ function mutateWorkspace(
75
+ id: string,
76
+ fn: (w: Workspace) => Workspace,
77
+ ): Promise<void> {
78
+ return updateConfig((cfg) => {
79
+ const workspaces = ((cfg.workspaces ?? []) as Workspace[]).map((w) =>
80
+ w.id === id ? fn(w) : w,
81
+ );
82
+ return { ...cfg, workspaces };
83
+ }).then(() => undefined);
84
+ }
85
+
86
+ export async function renameWorkspace(id: string, name: string): Promise<void> {
87
+ await mutateWorkspace(id, (w) => ({ ...w, name }));
88
+ }
89
+
90
+ export async function removeWorkspace(id: string): Promise<void> {
91
+ await updateConfig((cfg) => ({
92
+ ...cfg,
93
+ workspaces: ((cfg.workspaces ?? []) as Workspace[]).filter((w) => w.id !== id),
94
+ }));
95
+ // Purge search index for the removed workspace. Import dynamically to avoid
96
+ // circular dependency if search modules ever import from workspaces.
97
+ try {
98
+ const { purgeWorkspace } = await import("./search/indexer");
99
+ await purgeWorkspace(id);
100
+ } catch (e) {
101
+ console.error("[search] purge failed on workspace remove", e);
102
+ }
103
+ }
104
+
105
+ export async function setWorkspaceAccess(id: string, userIds: string[]): Promise<void> {
106
+ await mutateWorkspace(id, (w) => ({ ...w, allowedUserIds: userIds }));
107
+ }
108
+
109
+ export async function setWorkspacePins(id: string, pinnedPaths: string[]): Promise<void> {
110
+ await mutateWorkspace(id, (w) => ({ ...w, pinnedPaths }));
111
+ }
112
+
113
+ export async function touchWorkspace(id: string): Promise<void> {
114
+ await mutateWorkspace(id, (w) => ({ ...w, lastOpenedAt: new Date().toISOString() }));
115
+ }
116
+
117
+ // ── Access control ─────────────────────────────────────────────────────────────
118
+
119
+ /**
120
+ * True if userId may use this workspace.
121
+ * Admin always passes. If allowedUserIds is empty/undefined, any signed-in user passes.
122
+ */
123
+ export function userCanAccess(ws: Workspace, userId: string, isAdmin: boolean): boolean {
124
+ if (isAdmin) return true;
125
+ if (!ws.allowedUserIds || ws.allowedUserIds.length === 0) return true;
126
+ return ws.allowedUserIds.includes(userId);
127
+ }
128
+
129
+ // ── Path safety ────────────────────────────────────────────────────────────────
130
+
131
+ /**
132
+ * Returns the absolute path for `rel` within `rootDir`, or null on traversal.
133
+ * Replicates root-dir.ts safeRootPath exactly, but takes an explicit rootDir
134
+ * instead of reading the process-global. Phase B removes safeRootPath in
135
+ * favour of this function.
136
+ */
137
+ export function safeWorkspacePath(rootDir: string, rel: string): string | null {
138
+ if (!rootDir) return null;
139
+ if (!rel || rel === ".") return rootDir;
140
+ const resolved = path.resolve(rootDir, rel);
141
+ if (resolved !== rootDir && !resolved.startsWith(rootDir + path.sep)) return null;
142
+ return resolved;
143
+ }
144
+
145
+ // ── Migration ──────────────────────────────────────────────────────────────────
146
+
147
+ // Guard: true once migration has run in this process (cheap fast-path).
148
+ let _migrated = false;
149
+
150
+ /**
151
+ * Idempotent migration: if config.workspaces is absent/empty, synthesise one
152
+ * workspace from the old single-root sources, in priority order:
153
+ * 1. config.lastOpenedPath (existing single-user config)
154
+ * 2. process.env.ROOT_DIR (CLI / `wiki-viewer <dir>` / service boot)
155
+ * This makes a ROOT_DIR-launched server register a REAL workspace (visible in
156
+ * the switcher) instead of relying only on the synthetic fallback.
157
+ * Does NOT delete the old fields (rollback safety). Logs once.
158
+ */
159
+ export async function migrateConfigToWorkspaces(): Promise<void> {
160
+ if (_migrated) return;
161
+
162
+ const seedRoot = (cfg: { lastOpenedPath?: string }): string | null =>
163
+ cfg.lastOpenedPath ??
164
+ (process.env.ROOT_DIR ? path.resolve(process.env.ROOT_DIR) : null);
165
+
166
+ // Fast-path read to skip the serialized write when nothing to do.
167
+ const cfg = await readConfig();
168
+ if (((cfg.workspaces ?? []) as Workspace[]).length > 0 || !seedRoot(cfg)) {
169
+ _migrated = true;
170
+ return;
171
+ }
172
+
173
+ let created: Workspace | null = null;
174
+ // Atomic: re-check inside the lock so concurrent callers can't both create.
175
+ await updateConfig((fresh) => {
176
+ const existing = (fresh.workspaces ?? []) as Workspace[];
177
+ const seed = seedRoot(fresh);
178
+ if (existing.length > 0 || !seed) return fresh;
179
+ const rootDir = path.resolve(seed);
180
+ created = {
181
+ id: "ws_" + randomBytes(6).toString("base64url"),
182
+ name: path.basename(rootDir),
183
+ rootDir,
184
+ createdAt: new Date().toISOString(),
185
+ lastOpenedAt: new Date().toISOString(),
186
+ pinnedPaths: fresh.pinnedPaths,
187
+ };
188
+ return { ...fresh, workspaces: [created] };
189
+ });
190
+ if (created) {
191
+ console.log(
192
+ `[wiki-viewer] Migrated lastOpenedPath → workspace "${(created as Workspace).name}" (${(created as Workspace).id})`,
193
+ );
194
+ }
195
+ _migrated = true;
196
+ }
@@ -1,6 +1,7 @@
1
1
  "use client";
2
2
  import { create } from "zustand";
3
3
  import type { ActivityEvent } from "@/lib/proof/activity-shared";
4
+ import { wsFetch } from "@/lib/workspace-client";
4
5
  import { deriveConnections } from "@/lib/proof/activity-shared";
5
6
  import { authHeaders } from "@/lib/proof/client-auth";
6
7
 
@@ -49,7 +50,7 @@ export const useAIPanelStore = create<AIPanelState>((set) => ({
49
50
  const hasToken = !!(token && token.trim());
50
51
 
51
52
  try {
52
- const res = await fetch("/api/agent/activity?limit=50", {
53
+ const res = await wsFetch("/api/agent/activity?limit=50", {
53
54
  headers: authHeaders(),
54
55
  });
55
56
  if (!res.ok) {
@@ -63,7 +64,7 @@ export const useAIPanelStore = create<AIPanelState>((set) => ({
63
64
  // Also fetch rate-limit setting
64
65
  let rateLimit: number | null = null;
65
66
  try {
66
- const sr = await fetch("/api/agent/settings", { headers: authHeaders() });
67
+ const sr = await wsFetch("/api/agent/settings", { headers: authHeaders() });
67
68
  if (sr.ok) {
68
69
  const sd = (await sr.json()) as { rateLimit: number };
69
70
  rateLimit = sd.rateLimit ?? null;
@@ -1,5 +1,6 @@
1
1
  import { create } from "zustand";
2
2
  import type { FrontMatter, SaveStatus } from "@/types";
3
+ import { wsFetch } from "@/lib/workspace-client";
3
4
 
4
5
  // Adapter around ccmc's /api/wiki/content endpoints.
5
6
  // The API returns { content: string } and accepts { path, content }.
@@ -23,7 +24,7 @@ interface PageData {
23
24
  }
24
25
 
25
26
  async function fetchPageFromApi(path: string): Promise<PageData> {
26
- const res = await fetch(`/api/wiki/content?path=${encodeURIComponent(path)}`);
27
+ const res = await wsFetch(`/api/wiki/content?path=${encodeURIComponent(path)}`);
27
28
  if (!res.ok) {
28
29
  throw new FetchPageError(`Failed to fetch page: ${path}`, res.status);
29
30
  }
@@ -55,7 +56,7 @@ async function savePageToApi(
55
56
  ): Promise<SaveResult> {
56
57
  const body: Record<string, unknown> = { path, content };
57
58
  if (baseRevision !== null) body.baseRevision = baseRevision;
58
- const res = await fetch("/api/wiki/content", {
59
+ const res = await wsFetch("/api/wiki/content", {
59
60
  method: "PUT",
60
61
  headers: { "Content-Type": "application/json" },
61
62
  body: JSON.stringify(body),
@@ -63,7 +64,7 @@ async function savePageToApi(
63
64
  if (res.status === 409) {
64
65
  // Server has a newer revision. Fetch current content and surface the conflict.
65
66
  const conflictData = (await res.json()) as { currentRevision?: number };
66
- const freshRes = await fetch(`/api/wiki/content?path=${encodeURIComponent(path)}`);
67
+ const freshRes = await wsFetch(`/api/wiki/content?path=${encodeURIComponent(path)}`);
67
68
  const freshContent = freshRes.ok
68
69
  ? ((await freshRes.json()) as { content: string }).content
69
70
  : content;
@@ -1,5 +1,6 @@
1
1
  import { create } from "zustand";
2
2
  import { authHeaders } from "@/lib/proof/client-auth";
3
+ import { wsFetch } from "@/lib/workspace-client";
3
4
  import { useEditorStore } from "@/stores/editor-store";
4
5
  import type { Sidecar, ProofEvent, Block, Snapshot } from "@/lib/proof/types";
5
6
 
@@ -31,7 +32,7 @@ export const useProofStore = create<ProofState>((set, get) => ({
31
32
  loadSidecar: async (path: string) => {
32
33
  const encoded = encodeURIComponent(path).replace(/%2F/g, "/");
33
34
  try {
34
- const res = await fetch(`/api/agent/sidecar/${encoded}`, {
35
+ const res = await wsFetch(`/api/agent/sidecar/${encoded}`, {
35
36
  headers: authHeaders(),
36
37
  });
37
38
  if (!res.ok) return;
@@ -55,7 +56,7 @@ export const useProofStore = create<ProofState>((set, get) => ({
55
56
  loadSnapshot: async (path: string) => {
56
57
  const encoded = encodeURIComponent(path).replace(/%2F/g, "/");
57
58
  try {
58
- const res = await fetch(`/api/agent/files/${encoded}`, {
59
+ const res = await wsFetch(`/api/agent/files/${encoded}`, {
59
60
  headers: authHeaders(),
60
61
  });
61
62
  if (!res.ok) return;
@@ -84,7 +85,7 @@ export const useProofStore = create<ProofState>((set, get) => ({
84
85
  const entry = get().byPath[path] ?? defaultEntry();
85
86
  const encoded = encodeURIComponent(path).replace(/%2F/g, "/");
86
87
  try {
87
- const res = await fetch(
88
+ const res = await wsFetch(
88
89
  `/api/agent/events/${encoded}?after=${entry.lastEventId}`,
89
90
  { headers: authHeaders() },
90
91
  );