@akira-tl/forgerelay 0.8.8 → 0.8.9

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 (246) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +10 -18
  3. package/capabilities/host-integration/GUIDE.md +2 -2
  4. package/dist/activity/{audit-store.js → history/audit-store.js} +129 -21
  5. package/dist/activity/history/bash-output-store.js +250 -0
  6. package/dist/activity/{host-turn-store.js → history/host-turn-store.js} +4 -1
  7. package/dist/activity/{query-service.js → history/query-service.js} +13 -7
  8. package/dist/activity/{lifecycle.js → runtime/lifecycle.js} +1 -1
  9. package/dist/activity/{mcp-query-tools.js → runtime/mcp-query-tools.js} +3 -3
  10. package/dist/activity/storage/history.js +12 -0
  11. package/dist/activity/storage/paths.js +56 -0
  12. package/dist/activity/storage/segmented-log.js +149 -0
  13. package/dist/cli/setup-support.js +116 -0
  14. package/dist/cli.js +18 -126
  15. package/dist/lsp/code-intelligence.js +1 -1
  16. package/dist/lsp/test-support/server-fixture.js +9 -9
  17. package/dist/mcp/filesystem/filesystem-tools.js +245 -0
  18. package/dist/mcp/hooks/command-runner.js +79 -0
  19. package/dist/{hook-cli.js → mcp/hooks/hook-cli.js} +1 -1
  20. package/dist/{hooks.js → mcp/hooks/hooks.js} +3 -80
  21. package/dist/{oauth-provider.js → mcp/oauth/oauth-provider.js} +1 -1
  22. package/dist/{oauth-store.js → mcp/oauth/oauth-store.js} +5 -4
  23. package/dist/{operations → mcp/operations}/native-bulk-mutations.js +2 -2
  24. package/dist/mcp/panel/app.js +143 -0
  25. package/dist/{mcp-app-template.js → mcp/panel/mcp-app-template.js} +2 -38
  26. package/dist/mcp/process/runtime.js +257 -0
  27. package/dist/mcp/process/tools.js +346 -0
  28. package/dist/mcp/server/core/activity-support.js +70 -0
  29. package/dist/{capabilities.js → mcp/server/core/capabilities.js} +5 -3
  30. package/dist/{capability-registry.js → mcp/server/core/capability-registry.js} +2 -2
  31. package/dist/mcp/server/core/capability-support.js +90 -0
  32. package/dist/mcp/server/core/schemas.js +216 -0
  33. package/dist/mcp/server/core/tool-support.js +207 -0
  34. package/dist/mcp/server/core/version.js +9 -0
  35. package/dist/mcp/server/operations/runtime/filesystem-tools.js +400 -0
  36. package/dist/mcp/server/operations/runtime/operation-runtime.js +523 -0
  37. package/dist/mcp/server/transport/http-server.js +301 -0
  38. package/dist/mcp/server/transport/http-support.js +43 -0
  39. package/dist/mcp/server/workspace/runtime/workspace-open-presentation.js +222 -0
  40. package/dist/mcp/server/workspace/runtime/workspace-open-schema.js +187 -0
  41. package/dist/mcp/server/workspace/runtime/workspace-open.js +552 -0
  42. package/dist/mcp/server/workspace/runtime/workspace-tools.js +601 -0
  43. package/dist/{config.js → runtime/config/config.js} +3 -3
  44. package/dist/{user-config.js → runtime/config/user-config.js} +14 -54
  45. package/dist/{db → runtime/state/db}/client.js +1 -1
  46. package/dist/{db → runtime/state/db}/migrations.js +34 -3
  47. package/dist/runtime/state/lock/file-lock.js +130 -0
  48. package/dist/runtime/testing/server-fixture.js +190 -0
  49. package/dist/server.js +116 -4202
  50. package/dist/subagents/providers/adapters/claude.js +86 -52
  51. package/dist/subagents/providers/adapters/codex.js +103 -39
  52. package/dist/subagents/providers/adapters/opencode.js +114 -84
  53. package/dist/subagents/providers/adapters/pi.js +59 -8
  54. package/dist/subagents/providers/availability.js +15 -30
  55. package/dist/subagents/providers/runtime/external-command.js +56 -0
  56. package/dist/subagents/sessions/capability.js +1 -1
  57. package/dist/subagents/sessions/execution.js +1 -1
  58. package/dist/subagents/sessions/mcp/activity-audit-test-support.js +30 -0
  59. package/dist/subagents/sessions/store.js +1 -1
  60. package/dist/ui/.vite/manifest.json +342 -410
  61. package/dist/ui/activity-panel-app.html +2 -4
  62. package/dist/ui/assets/activity-panel-app-7Xe0alhm.css +1 -0
  63. package/dist/ui/assets/activity-panel-app-Sl1Jro8v.js +115 -0
  64. package/dist/ui/assets/angular-html-B_yn91wW.js +1 -0
  65. package/dist/ui/assets/{angular-ts-Bxh4-O1-.js → angular-ts-DSgtloKz.js} +1 -1
  66. package/dist/ui/assets/{apl-BmYHKQ6m.js → apl-NatWtF8X.js} +1 -1
  67. package/dist/ui/assets/{astro-C51vqDKq.js → astro-BYFEVBuN.js} +1 -1
  68. package/dist/ui/assets/{blade-CdhVsmwq.js → blade-DoO7yvMR.js} +1 -1
  69. package/dist/ui/assets/c-Rl2hMCcg.js +1 -0
  70. package/dist/ui/assets/{cobol-Cf6azoN_.js → cobol-ByC5mWiB.js} +1 -1
  71. package/dist/ui/assets/{coffee-vVdGzlmt.js → coffee-Dez77Qov.js} +1 -1
  72. package/dist/ui/assets/cpp-DtaAQT9h.js +1 -0
  73. package/dist/ui/assets/{crystal-5UZy6KIX.js → crystal-Bgmbf8ec.js} +1 -1
  74. package/dist/ui/assets/css-C1tjBtVN.js +1 -0
  75. package/dist/ui/assets/{edge-CESgo4ia.js → edge-DeH6u8Wg.js} +1 -1
  76. package/dist/ui/assets/{elixir-9FKfw4cJ.js → elixir-_H3KnmWT.js} +1 -1
  77. package/dist/ui/assets/{elm-Dv7A0aLa.js → elm-CsCe3U28.js} +1 -1
  78. package/dist/ui/assets/{erb-DHFmDvM0.js → erb-CbM-L2g8.js} +1 -1
  79. package/dist/ui/assets/{git-rebase-utbU6CzV.js → git-rebase-D0s5pDh9.js} +1 -1
  80. package/dist/ui/assets/{glimmer-js-t2kiCkyB.js → glimmer-js-BfOToq_A.js} +1 -1
  81. package/dist/ui/assets/{glimmer-ts-F0Jv5okV.js → glimmer-ts-CCUOkL2K.js} +1 -1
  82. package/dist/ui/assets/glsl-DH4ec9dE.js +1 -0
  83. package/dist/ui/assets/graphql-DilAMBoI.js +1 -0
  84. package/dist/ui/assets/{hack-8yjdbaSA.js → hack-BDkNDZlF.js} +1 -1
  85. package/dist/ui/assets/haml-D_QBp6K7.js +1 -0
  86. package/dist/ui/assets/{handlebars-BBFEg4Lo.js → handlebars-DePUrTpC.js} +1 -1
  87. package/dist/ui/assets/heavy-payload-DOwZpO6n.js +290 -0
  88. package/dist/ui/assets/html-By4dNnM4.js +1 -0
  89. package/dist/ui/assets/{html-derivative-DJAQcZyc.js → html-derivative-DDw9Ef4Q.js} +1 -1
  90. package/dist/ui/assets/{http-Dg5LSYRK.js → http-B0QxWc9M.js} +1 -1
  91. package/dist/ui/assets/{hurl-Y5uYzMZR.js → hurl-vMQ4lda1.js} +1 -1
  92. package/dist/ui/assets/java-DYRe2lWG.js +1 -0
  93. package/dist/ui/assets/javascript-CxyGqwcL.js +1 -0
  94. package/dist/ui/assets/{jinja-Bt30h8Ik.js → jinja-JUwV-fZt.js} +1 -1
  95. package/dist/ui/assets/{jison-D5uZ1Nyo.js → jison-7ZqCEvS8.js} +1 -1
  96. package/dist/ui/assets/json-dbltgiiA.js +1 -0
  97. package/dist/ui/assets/jsx-oDopT7YQ.js +1 -0
  98. package/dist/ui/assets/{julia-76hRaaGz.js → julia-CkKiNSav.js} +1 -1
  99. package/dist/ui/assets/{just-CDE7W0vW.js → just-DuqCAKJ3.js} +1 -1
  100. package/dist/ui/assets/{latex-CVO2Byab.js → latex-sudcRDSn.js} +1 -1
  101. package/dist/ui/assets/{liquid-CA-AS3EX.js → liquid-Di-08Js7.js} +1 -1
  102. package/dist/ui/assets/lua-YlqdMoV0.js +1 -0
  103. package/dist/ui/assets/{marko-_BWrPfny.js → marko-CJRNyJDb.js} +1 -1
  104. package/dist/ui/assets/{mdc-PyJv85eS.js → mdc-t12CzZHs.js} +1 -1
  105. package/dist/ui/assets/{nginx-DAWVw8yu.js → nginx-57-b4XwT.js} +1 -1
  106. package/dist/ui/assets/{nim-CKE1dzpU.js → nim-BzrswYQa.js} +1 -1
  107. package/dist/ui/assets/{perl-BBhWva19.js → perl-D9JR_iIh.js} +1 -1
  108. package/dist/ui/assets/{php-ChIeaAoF.js → php-Py2gFHil.js} +1 -1
  109. package/dist/ui/assets/{pug-CMgI5afi.js → pug-PzLLy0h1.js} +1 -1
  110. package/dist/ui/assets/{qml-CjxTkcFH.js → qml-By8fwgV4.js} +1 -1
  111. package/dist/ui/assets/r-CcezTbLq.js +1 -0
  112. package/dist/ui/assets/{razor-i4DbHr8p.js → razor-dG-vdhL_.js} +1 -1
  113. package/dist/ui/assets/regexp-BlsQ-N_8.js +1 -0
  114. package/dist/ui/assets/{rst-oy_97Kl4.js → rst-C2awDCat.js} +1 -1
  115. package/dist/ui/assets/{ruby-C5zYZIyl.js → ruby-zA2W_49d.js} +1 -1
  116. package/dist/ui/assets/{sas-BnMEh2S3.js → sas-D49bhyaN.js} +1 -1
  117. package/dist/ui/assets/scss-BQb-cp01.js +1 -0
  118. package/dist/ui/assets/shellscript-Dga4H_Ni.js +1 -0
  119. package/dist/ui/assets/{shellsession-BpE5o7_3.js → shellsession-n3-5CqcF.js} +1 -1
  120. package/dist/ui/assets/{soy-COesmhTY.js → soy-XYBOf_BA.js} +1 -1
  121. package/dist/ui/assets/sql-ET4u5Cpl.js +1 -0
  122. package/dist/ui/assets/{stata-CGQEuSZq.js → stata-CLHcJHO_.js} +1 -1
  123. package/dist/ui/assets/{surrealql-Bz4JbU-9.js → surrealql-BdjQ60T4.js} +1 -1
  124. package/dist/ui/assets/{svelte-1jM2ejXj.js → svelte-B2RPtKJe.js} +1 -1
  125. package/dist/ui/assets/{templ-C-VwELcp.js → templ-CrByPW_W.js} +1 -1
  126. package/dist/ui/assets/{tex-t1rUiQCm.js → tex-DZBkg363.js} +1 -1
  127. package/dist/ui/assets/{ts-tags-Bewoa6pS.js → ts-tags-DJR3Gphb.js} +1 -1
  128. package/dist/ui/assets/tsx-CajzROyy.js +1 -0
  129. package/dist/ui/assets/{twig-DVg-vELl.js → twig-BZjk5Zda.js} +1 -1
  130. package/dist/ui/assets/typescript-B-EWToLj.js +1 -0
  131. package/dist/ui/assets/{vue-wPQ7UlMy.js → vue-D_rHCCr8.js} +1 -1
  132. package/dist/ui/assets/{vue-html-BHtJ8geX.js → vue-html-CC4WlvVt.js} +1 -1
  133. package/dist/ui/assets/{vue-vine-CNSGAWwc.js → vue-vine-BgNMVgpk.js} +1 -1
  134. package/dist/ui/assets/xml-BI86-WbH.js +1 -0
  135. package/dist/ui/assets/{xsl-3_vJ27aE.js → xsl-DXeLZV4J.js} +1 -1
  136. package/dist/ui/assets/yaml-60_PFlWa.js +1 -0
  137. package/dist/workspaces/bootstrap.js +72 -0
  138. package/dist/workspaces/context.js +302 -0
  139. package/dist/workspaces/conversation-test-support.js +86 -0
  140. package/dist/{git-worktrees.js → workspaces/git/git-worktrees.js} +1 -1
  141. package/dist/workspaces/inventory.js +131 -0
  142. package/dist/workspaces/paths.js +55 -0
  143. package/dist/{remote-auth.js → workspaces/relay/auth/remote-auth.js} +2 -2
  144. package/dist/workspaces/relay/result-support.js +111 -0
  145. package/dist/workspaces/relay/tests/test-support.js +203 -0
  146. package/dist/{remote-mcp-connection-pool.js → workspaces/relay/transport/remote-mcp-connection-pool.js} +1 -1
  147. package/dist/workspaces/relay/types.js +1 -0
  148. package/dist/{remote-workspace-relay.js → workspaces/relay/workspace-relay.js} +23 -172
  149. package/dist/workspaces/resources/skills.js +285 -0
  150. package/dist/{review-checkpoints.js → workspaces/review/review-checkpoints.js} +2 -2
  151. package/dist/workspaces/sessions.js +457 -0
  152. package/dist/{workspace-store.js → workspaces/state/workspace-store.js} +2 -2
  153. package/dist/workspaces.js +68 -995
  154. package/docs/chatgpt-coding-workflow.md +3 -11
  155. package/docs/configuration.md +12 -25
  156. package/docs/gotchas.md +0 -30
  157. package/docs/roadmap.md +6 -10
  158. package/docs/security.md +1 -5
  159. package/docs/setup.md +0 -11
  160. package/package.json +6 -8
  161. package/scripts/ci/architecture.mjs +109 -0
  162. package/scripts/ci/verify.mjs +5 -0
  163. package/scripts/debug/accept/bootstrap.mjs +326 -0
  164. package/scripts/debug/accept/harness.mjs +76 -0
  165. package/scripts/debug/accept/support.mjs +432 -0
  166. package/scripts/debug/accept.mjs +43 -806
  167. package/scripts/debug/relay-accept/support.mjs +135 -0
  168. package/scripts/debug/relay-accept.mjs +26 -115
  169. package/scripts/debug/traffic/support.mjs +167 -0
  170. package/scripts/debug/traffic/traffic-audit.mjs +4 -161
  171. package/scripts/{lsp-interop-support.test.mjs → lsp/interop-support.test.mjs} +1 -1
  172. package/scripts/{lsp-interop.mjs → lsp/interop.mjs} +3 -3
  173. package/scripts/wiki/sync.mjs +21 -10
  174. package/dist/activity/bash-output-store.js +0 -127
  175. package/dist/pi-tools.js +0 -110
  176. package/dist/skills.js +0 -127
  177. package/dist/ui/assets/activity-panel-app-7AckaxIR.js +0 -2
  178. package/dist/ui/assets/angular-html-BkgDQl-G.js +0 -1
  179. package/dist/ui/assets/c-IBzBpxAO.js +0 -1
  180. package/dist/ui/assets/chunk-EyZ2wyi3.js +0 -1
  181. package/dist/ui/assets/cpp-CVHeO-Jk.js +0 -1
  182. package/dist/ui/assets/css-DEfus9J5.js +0 -1
  183. package/dist/ui/assets/glsl-_ooCjaeB.js +0 -1
  184. package/dist/ui/assets/graphql-B9LqP-cY.js +0 -1
  185. package/dist/ui/assets/haml-BU5EoZBn.js +0 -1
  186. package/dist/ui/assets/heavy-payload-Bol1_mcs.js +0 -4
  187. package/dist/ui/assets/html-D-C6YZk4.js +0 -1
  188. package/dist/ui/assets/java-ppHvycj5.js +0 -1
  189. package/dist/ui/assets/javascript-DDTjKLlQ.js +0 -1
  190. package/dist/ui/assets/json-Cw91r8h1.js +0 -1
  191. package/dist/ui/assets/jsx-04X2FT_1.js +0 -1
  192. package/dist/ui/assets/lua-CiyBp52Y.js +0 -1
  193. package/dist/ui/assets/r-DfFga4si.js +0 -1
  194. package/dist/ui/assets/regexp-iC9_nbSI.js +0 -1
  195. package/dist/ui/assets/review-payload-BqJp0c5e.js +0 -1
  196. package/dist/ui/assets/scrollbar-CvE-I-jG.js +0 -287
  197. package/dist/ui/assets/scss-BfZXsAWQ.js +0 -1
  198. package/dist/ui/assets/shellscript-BC2srNaB.js +0 -1
  199. package/dist/ui/assets/sql-Ccv_yeUm.js +0 -1
  200. package/dist/ui/assets/tsx-CTXzrBkN.js +0 -1
  201. package/dist/ui/assets/typescript--ElHoFkw.js +0 -1
  202. package/dist/ui/assets/workspace-app-BLW7p6IZ.js +0 -114
  203. package/dist/ui/assets/workspace-app-BjNqR0en.js +0 -1
  204. package/dist/ui/assets/workspace-app-CmaYU4DW.js +0 -3
  205. package/dist/ui/assets/workspace-app-D2bJ5fjt.css +0 -1
  206. package/dist/ui/assets/workspace-lifecycle-app-BVbI2Ilf.js +0 -1
  207. package/dist/ui/assets/xml-JnmX6vyS.js +0 -1
  208. package/dist/ui/assets/yaml-OAcZkP-w.js +0 -1
  209. package/dist/ui/workspace-app.html +0 -18
  210. package/dist/ui/workspace-lifecycle-app.html +0 -18
  211. package/docs/agent-profile-schema.md +0 -114
  212. package/docs/artifact-exchange.md +0 -65
  213. package/docs/versioning.md +0 -205
  214. /package/capabilities/{managed-worktrees → workspace/managed-worktrees}/GUIDE.md +0 -0
  215. /package/capabilities/{workspace-tasks → workspace/workspace-tasks}/GUIDE.md +0 -0
  216. /package/dist/activity/{process-output-audit.js → runtime/process-output-audit.js} +0 -0
  217. /package/dist/{artifact-error.js → mcp/artifacts/artifact-error.js} +0 -0
  218. /package/dist/{artifact-tools.js → mcp/artifacts/artifact-tools.js} +0 -0
  219. /package/dist/{incoming-artifacts.js → mcp/artifacts/incoming-artifacts.js} +0 -0
  220. /package/dist/{advertised-files.js → mcp/filesystem/advertised-files.js} +0 -0
  221. /package/dist/{apply-patch.js → mcp/filesystem/apply-patch.js} +0 -0
  222. /package/dist/{file-mutations.js → mcp/filesystem/file-mutations.js} +0 -0
  223. /package/dist/{roots.js → mcp/filesystem/roots.js} +0 -0
  224. /package/dist/{oauth → mcp/oauth}/public-url.js +0 -0
  225. /package/dist/{oauth → mcp/oauth}/router.js +0 -0
  226. /package/dist/{operations → mcp/operations}/batch/executor.js +0 -0
  227. /package/dist/{operations → mcp/operations}/batch/scheduler.js +0 -0
  228. /package/dist/{operations → mcp/operations}/batch/types.js +0 -0
  229. /package/dist/{operations → mcp/operations}/bulk-mutation.js +0 -0
  230. /package/dist/{operations → mcp/operations}/bulk-read.js +0 -0
  231. /package/dist/{operations → mcp/operations}/core-operation-executor.js +0 -0
  232. /package/dist/{process-platform.js → mcp/process/process-platform.js} +0 -0
  233. /package/dist/{process-sessions.js → mcp/process/process-sessions.js} +0 -0
  234. /package/dist/{request-meta.js → mcp/request-meta.js} +0 -0
  235. /package/dist/{mcp-sessions.js → mcp/server/transport/mcp-sessions.js} +0 -0
  236. /package/dist/{server-shutdown.js → mcp/server/transport/server-shutdown.js} +0 -0
  237. /package/dist/{logger.js → runtime/logging/logger.js} +0 -0
  238. /package/dist/{db → runtime/state/db}/schema.js +0 -0
  239. /package/dist/{composite-activity.js → workspaces/composite/composite-activity.js} +0 -0
  240. /package/dist/{composite-workspaces.js → workspaces/composite/composite-workspaces.js} +0 -0
  241. /package/dist/{git.js → workspaces/git/git.js} +0 -0
  242. /package/dist/{workspace-presentation.js → workspaces/presentation/workspace-presentation.js} +0 -0
  243. /package/dist/{remote-transport.js → workspaces/relay/transport/remote-transport.js} +0 -0
  244. /package/dist/{workspace-task-reminders.js → workspaces/tasks/workspace-task-reminders.js} +0 -0
  245. /package/dist/{workspace-tasks.js → workspaces/tasks/workspace-tasks.js} +0 -0
  246. /package/scripts/{lsp-interop-support.mjs → lsp/interop-support.mjs} +0 -0
@@ -1,5 +1,5 @@
1
1
  import { randomUUID } from "node:crypto";
2
- import { HookExecutionError } from "../hooks.js";
2
+ import { HookExecutionError } from "../../mcp/hooks/hooks.js";
3
3
  export class ActivityLifecycle {
4
4
  auditStore;
5
5
  activityId;
@@ -1,8 +1,8 @@
1
1
  import { registerAppTool } from "@modelcontextprotocol/ext-apps/server";
2
2
  import * as z from "zod/v4";
3
- import { logEvent, transportSessionIdPrefix } from "../logger.js";
4
- import { hostConversationScopeId } from "../request-meta.js";
5
- import { ACTIVITY_PANEL_DEFAULT_EXPANDED_META_KEY, ACTIVITY_PANEL_WORKSPACE_META_KEY, } from "./ui/contract.js";
3
+ import { logEvent, transportSessionIdPrefix } from "../../runtime/logging/logger.js";
4
+ import { hostConversationScopeId } from "../../mcp/request-meta.js";
5
+ import { ACTIVITY_PANEL_DEFAULT_EXPANDED_META_KEY, ACTIVITY_PANEL_WORKSPACE_META_KEY, } from "../ui/contract.js";
6
6
  const READ_ONLY_ANNOTATIONS = {
7
7
  readOnlyHint: true,
8
8
  destructiveHint: false,
@@ -0,0 +1,12 @@
1
+ import { removeWorkspaceActivityStorage } from "./paths.js";
2
+ /**
3
+ * User-requested Workspace deletion is the retention boundary for durable
4
+ * Activity history by default. Index rows are removed before the backing files
5
+ * so a crash cannot leave SQLite pointing at already-deleted payload shards.
6
+ */
7
+ export function deleteWorkspaceActivityHistory(input) {
8
+ input.outputs.deleteWorkspace(input.workspaceId);
9
+ input.audit.deleteWorkspace(input.workspaceId);
10
+ input.turns.deleteWorkspace(input.workspaceId);
11
+ removeWorkspaceActivityStorage(input.stateDir, input.workspaceId);
12
+ }
@@ -0,0 +1,56 @@
1
+ import { createHash } from "node:crypto";
2
+ import { mkdirSync, rmSync } from "node:fs";
3
+ import { dirname, join, relative, resolve, sep } from "node:path";
4
+ const SAFE_WORKSPACE_ID = /^(?:ws|rws|cws)_[a-z0-9]+$/i;
5
+ export function activityWorkspaceStorageKey(workspace) {
6
+ if (workspace.id && SAFE_WORKSPACE_ID.test(workspace.id))
7
+ return workspace.id;
8
+ return `root_${createHash("sha256").update(`${workspace.mode}\0${resolve(workspace.root)}`).digest("hex").slice(0, 20)}`;
9
+ }
10
+ export function activityWorkspaceDirectory(stateDir, workspace) {
11
+ return join(stateDir, "workspaces", activityWorkspaceStorageKey(workspace), "activity");
12
+ }
13
+ export function activityEventLogPrefix(stateDir, workspace) {
14
+ return join(activityWorkspaceDirectory(stateDir, workspace), "events");
15
+ }
16
+ export function bashOutputDirectory(stateDir, workspace) {
17
+ return join(activityWorkspaceDirectory(stateDir, workspace), "bash");
18
+ }
19
+ export function bashOutputLogPrefix(stateDir, workspace, outputId) {
20
+ return join(bashOutputDirectory(stateDir, workspace), outputId);
21
+ }
22
+ export function bashOutputMetadataPrefix(stateDir, workspace, outputId, field) {
23
+ return join(bashOutputDirectory(stateDir, workspace), `${outputId}-${field}`);
24
+ }
25
+ export function removeWorkspaceActivityStorage(stateDir, workspaceId) {
26
+ if (!SAFE_WORKSPACE_ID.test(workspaceId)) {
27
+ throw new Error(`Invalid Workspace id for Activity storage cleanup: ${workspaceId}`);
28
+ }
29
+ rmSync(join(stateDir, "workspaces", workspaceId, "activity"), {
30
+ recursive: true,
31
+ force: true,
32
+ });
33
+ }
34
+ export function ensurePrivateDirectory(path) {
35
+ mkdirSync(path, { recursive: true, mode: 0o700 });
36
+ }
37
+ export function stateRelativePath(stateDir, path) {
38
+ const relationship = relative(resolve(stateDir), resolve(path));
39
+ if (relationship === "" ||
40
+ relationship === ".." ||
41
+ relationship.startsWith(`..${sep}`)) {
42
+ throw new Error(`Activity log path is outside ForgeRelay state directory: ${path}`);
43
+ }
44
+ return relationship.split(sep).join("/");
45
+ }
46
+ export function resolveStateRelativePath(stateDir, path) {
47
+ const absolute = resolve(stateDir, path);
48
+ const relationship = relative(resolve(stateDir), absolute);
49
+ if (relationship === ".." || relationship.startsWith(`..${sep}`)) {
50
+ throw new Error(`Activity log reference escapes ForgeRelay state directory: ${path}`);
51
+ }
52
+ return absolute;
53
+ }
54
+ export function ensureParentPrivate(path) {
55
+ ensurePrivateDirectory(dirname(path));
56
+ }
@@ -0,0 +1,149 @@
1
+ import { closeSync, constants as fsConstants, fstatSync, openSync, readSync, readdirSync, statSync, writeSync, } from "node:fs";
2
+ import { basename, dirname, join } from "node:path";
3
+ import { ensureParentPrivate, resolveStateRelativePath, stateRelativePath } from "./paths.js";
4
+ /**
5
+ * Segment files are deliberately small enough to inspect, copy, prune, and
6
+ * recover independently. The logical stream may be arbitrarily large; no
7
+ * individual on-disk activity/output file should grow without bound.
8
+ */
9
+ export const ACTIVITY_LOG_SEGMENT_BYTES = 8 * 1024 * 1024;
10
+ export class SegmentedLogStore {
11
+ stateDir;
12
+ segmentBytes;
13
+ appendOffsets = new Map();
14
+ constructor(stateDir, segmentBytes = ACTIVITY_LOG_SEGMENT_BYTES) {
15
+ this.stateDir = stateDir;
16
+ this.segmentBytes = segmentBytes;
17
+ }
18
+ append(prefixPath, data) {
19
+ const prefix = stateRelativePath(this.stateDir, prefixPath);
20
+ const currentOffset = this.appendOffsets.get(prefix) ?? this.discoverLength(prefixPath);
21
+ this.writeAt(prefixPath, currentOffset, data);
22
+ this.appendOffsets.set(prefix, currentOffset + data.byteLength);
23
+ return { prefix, offset: currentOffset, length: data.byteLength };
24
+ }
25
+ appendAt(prefix, logicalOffset, data) {
26
+ const prefixPath = resolveStateRelativePath(this.stateDir, prefix);
27
+ this.writeAt(prefixPath, logicalOffset, data);
28
+ const next = logicalOffset + data.byteLength;
29
+ const known = this.appendOffsets.get(prefix);
30
+ if (known === undefined || next > known)
31
+ this.appendOffsets.set(prefix, next);
32
+ }
33
+ read(reference) {
34
+ return this.readRange(reference.prefix, reference.offset, reference.offset + reference.length);
35
+ }
36
+ readRange(prefix, start, end) {
37
+ if (!Number.isSafeInteger(start) || start < 0 || !Number.isSafeInteger(end) || end < start) {
38
+ throw new Error(`Invalid segmented log range: ${start}..${end}.`);
39
+ }
40
+ if (start === end)
41
+ return Buffer.alloc(0);
42
+ const prefixPath = resolveStateRelativePath(this.stateDir, prefix);
43
+ const result = Buffer.allocUnsafe(end - start);
44
+ let logicalOffset = start;
45
+ let resultOffset = 0;
46
+ while (logicalOffset < end) {
47
+ const segmentIndex = Math.floor(logicalOffset / this.segmentBytes);
48
+ const segmentOffset = logicalOffset % this.segmentBytes;
49
+ const available = Math.min(end - logicalOffset, this.segmentBytes - segmentOffset);
50
+ const path = segmentPath(prefixPath, segmentIndex);
51
+ const fd = openSync(path, fsConstants.O_RDONLY);
52
+ try {
53
+ const bytesRead = readSync(fd, result, resultOffset, available, segmentOffset);
54
+ if (bytesRead !== available) {
55
+ throw new Error(`Segmented log ${path} ended before logical offset ${logicalOffset + available}.`);
56
+ }
57
+ }
58
+ finally {
59
+ closeSync(fd);
60
+ }
61
+ logicalOffset += available;
62
+ resultOffset += available;
63
+ }
64
+ return result;
65
+ }
66
+ logicalLength(prefix) {
67
+ const known = this.appendOffsets.get(prefix);
68
+ if (known !== undefined)
69
+ return known;
70
+ const prefixPath = resolveStateRelativePath(this.stateDir, prefix);
71
+ const length = this.discoverLength(prefixPath);
72
+ this.appendOffsets.set(prefix, length);
73
+ return length;
74
+ }
75
+ writeAt(prefixPath, logicalOffset, data) {
76
+ if (!Number.isSafeInteger(logicalOffset) || logicalOffset < 0) {
77
+ throw new Error(`Invalid segmented log offset: ${logicalOffset}.`);
78
+ }
79
+ if (data.byteLength === 0)
80
+ return;
81
+ ensureParentPrivate(prefixPath);
82
+ const bytes = Buffer.from(data.buffer, data.byteOffset, data.byteLength);
83
+ let sourceOffset = 0;
84
+ let current = logicalOffset;
85
+ while (sourceOffset < bytes.length) {
86
+ const segmentIndex = Math.floor(current / this.segmentBytes);
87
+ const segmentOffset = current % this.segmentBytes;
88
+ const writable = Math.min(bytes.length - sourceOffset, this.segmentBytes - segmentOffset);
89
+ const path = segmentPath(prefixPath, segmentIndex);
90
+ const fd = openSync(path, fsConstants.O_CREAT | fsConstants.O_WRONLY, 0o600);
91
+ try {
92
+ const stats = fstatSync(fd);
93
+ if (stats.size !== segmentOffset) {
94
+ throw new Error(`Segmented log append position mismatch for ${path}: expected ${segmentOffset}, found ${stats.size}.`);
95
+ }
96
+ const written = writeSync(fd, bytes, sourceOffset, writable, segmentOffset);
97
+ if (written !== writable) {
98
+ throw new Error(`Short write while appending segmented log ${path}.`);
99
+ }
100
+ }
101
+ finally {
102
+ closeSync(fd);
103
+ }
104
+ sourceOffset += writable;
105
+ current += writable;
106
+ }
107
+ }
108
+ discoverLength(prefixPath) {
109
+ const directory = dirname(prefixPath);
110
+ const stem = basename(prefixPath);
111
+ let files;
112
+ try {
113
+ files = readdirSync(directory);
114
+ }
115
+ catch (error) {
116
+ if (error.code === "ENOENT")
117
+ return 0;
118
+ throw error;
119
+ }
120
+ const pattern = new RegExp(`^${escapeRegExp(stem)}\\.(\\d{6})\\.log$`);
121
+ let maxIndex = -1;
122
+ let maxSize = 0;
123
+ for (const file of files) {
124
+ const match = pattern.exec(file);
125
+ if (!match)
126
+ continue;
127
+ const index = Number(match[1]);
128
+ const size = statSync(join(directory, file)).size;
129
+ if (size > this.segmentBytes) {
130
+ throw new Error(`Segmented log shard exceeds ${this.segmentBytes} bytes: ${join(directory, file)}.`);
131
+ }
132
+ if (index > maxIndex) {
133
+ maxIndex = index;
134
+ maxSize = size;
135
+ }
136
+ }
137
+ if (maxIndex < 0)
138
+ return 0;
139
+ if (maxSize < this.segmentBytes)
140
+ return maxIndex * this.segmentBytes + maxSize;
141
+ return (maxIndex + 1) * this.segmentBytes;
142
+ }
143
+ }
144
+ export function segmentPath(prefixPath, index) {
145
+ return `${prefixPath}.${String(index).padStart(6, "0")}.log`;
146
+ }
147
+ function escapeRegExp(value) {
148
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
149
+ }
@@ -0,0 +1,116 @@
1
+ import { createRequire } from "node:module";
2
+ import * as prompts from "@clack/prompts";
3
+ import { satisfies } from "semver";
4
+ const SUPPORTED_NODE_RANGE = ">=20.12 <27";
5
+ const require = createRequire(import.meta.url);
6
+ export function isNullConfigValue(value) {
7
+ const normalized = value.trim().toLowerCase();
8
+ return !normalized || normalized === "null" || normalized === "none";
9
+ }
10
+ export function normalizeOptionalPublicBaseUrl(value) {
11
+ const trimmed = value.trim();
12
+ if (isNullConfigValue(trimmed))
13
+ return null;
14
+ return compactPublicBaseUrlConfig(normalizePublicBaseUrlsInput(trimmed));
15
+ }
16
+ export function normalizePublicBaseUrlsInput(value) {
17
+ const entries = value
18
+ .split(",")
19
+ .map((entry) => entry.trim())
20
+ .filter(Boolean);
21
+ if (entries.length === 0)
22
+ throw new Error("Enter at least one public base URL.");
23
+ return Array.from(new Set(entries.map((entry) => normalizePublicBaseUrl(entry))));
24
+ }
25
+ export function compactPublicBaseUrlConfig(baseUrls) {
26
+ return baseUrls.length === 1 ? baseUrls[0] : baseUrls;
27
+ }
28
+ export function normalizePublicBaseUrl(value) {
29
+ const trimmed = value.trim();
30
+ const parsed = new URL(trimmed);
31
+ parsed.hash = "";
32
+ parsed.search = "";
33
+ parsed.pathname = parsed.pathname.replace(/\/+$/, "");
34
+ return parsed.toString().replace(/\/$/, "");
35
+ }
36
+ export async function textPrompt(options) {
37
+ const result = await prompts.text({
38
+ ...options,
39
+ validate: (value) => options.validate?.(value?.trim() ? value : options.defaultValue),
40
+ });
41
+ if (prompts.isCancel(result))
42
+ throw new SetupCancelledError();
43
+ const value = String(result).trim();
44
+ return value || options.defaultValue;
45
+ }
46
+ export function validatePort(value) {
47
+ const port = Number(value);
48
+ return Number.isInteger(port) && port >= 1 && port <= 65535
49
+ ? undefined
50
+ : "Enter a port between 1 and 65535.";
51
+ }
52
+ export function validateRequiredPublicBaseUrls(value) {
53
+ const trimmed = value?.trim() ?? "";
54
+ if (!trimmed)
55
+ return "Enter at least one public base URL from your tunnel or reverse proxy.";
56
+ try {
57
+ normalizePublicBaseUrlsInput(trimmed);
58
+ return undefined;
59
+ }
60
+ catch (error) {
61
+ return error instanceof Error ? error.message : String(error);
62
+ }
63
+ }
64
+ export function assertSupportedNode() {
65
+ if (satisfies(process.versions.node, SUPPORTED_NODE_RANGE))
66
+ return;
67
+ throw new Error([
68
+ `ForgeRelay requires Node ${SUPPORTED_NODE_RANGE}.`,
69
+ `Current Node: ${process.version}`,
70
+ "",
71
+ "Install Node 22 LTS or use a version manager such as nvm, fnm, or mise.",
72
+ ].join("\n"));
73
+ }
74
+ export function nodeVersionStatus() {
75
+ return satisfies(process.versions.node, SUPPORTED_NODE_RANGE)
76
+ ? `supported ${SUPPORTED_NODE_RANGE}`
77
+ : `unsupported, requires ${SUPPORTED_NODE_RANGE}`;
78
+ }
79
+ export class SetupCancelledError extends Error {
80
+ }
81
+ export function checkSqliteNative() {
82
+ try {
83
+ const Database = require("better-sqlite3");
84
+ const db = new Database(":memory:");
85
+ db.close();
86
+ return "ok";
87
+ }
88
+ catch (error) {
89
+ return error instanceof Error ? error.message : String(error);
90
+ }
91
+ }
92
+ export function checkGitAvailable() {
93
+ try {
94
+ const { execFileSync } = require("node:child_process");
95
+ return execFileSync("git", ["--version"], { encoding: "utf8" }).trim();
96
+ }
97
+ catch (error) {
98
+ const message = error instanceof Error ? error.message : String(error);
99
+ return `unavailable (${message})`;
100
+ }
101
+ }
102
+ export function checkBashShell() {
103
+ try {
104
+ const { execFileSync } = require("node:child_process");
105
+ const command = process.env.BASH?.trim() || "bash";
106
+ const version = execFileSync(command, ["--version"], {
107
+ encoding: "utf8",
108
+ windowsHide: true,
109
+ }).split(/\r?\n/, 1)[0]?.trim();
110
+ return version ? `${command} (${version})` : command;
111
+ }
112
+ catch (error) {
113
+ const message = error instanceof Error ? error.message : String(error);
114
+ return `unavailable (${message})`;
115
+ }
116
+ }
package/dist/cli.js CHANGED
@@ -8,23 +8,21 @@ import { tmpdir } from "node:os";
8
8
  import { join, resolve } from "node:path";
9
9
  import { fileURLToPath } from "node:url";
10
10
  import * as prompts from "@clack/prompts";
11
- import { getShellConfig } from "@earendil-works/pi-coding-agent";
12
- import { satisfies } from "semver";
13
- import { loadConfig } from "./config.js";
14
- import { runHooksCommand } from "./hook-cli.js";
11
+ import { loadConfig } from "./runtime/config/config.js";
12
+ import { runHooksCommand } from "./mcp/hooks/hook-cli.js";
15
13
  import { executeSubagentSession } from "./subagents/sessions/execution.js";
16
14
  import { SubagentDeliveryMailbox } from "./subagents/sessions/delivery-mailbox.js";
17
15
  import { SubagentSessionManager } from "./subagents/sessions/manager.js";
18
16
  import { formatSubagentProviderAvailabilitySummary } from "./subagents/providers/availability.js";
19
17
  import { parseSubagentRunArgs } from "./subagents/cli-target.js";
20
- import { ensureForgeRelayInstanceId, generateInstanceId, generateOwnerToken, loadForgeRelayFiles, removeForgeRelayRemote, renameForgeRelayRemote, resolveSubagentsFlag, writeForgeRelayAuth, writeForgeRelayConfig, writeForgeRelayRemote, } from "./user-config.js";
21
- import { expandHomePath } from "./roots.js";
22
- import { shutdownHttpServer } from "./server-shutdown.js";
23
- import { publicEndpointUrl } from "./oauth/public-url.js";
24
- import { authenticateRemote, defaultRemoteAlias, isRemoteMcpUnauthorized, normalizeRemoteServiceTarget, refreshRemoteAuthentication, verifyRemoteMcp, } from "./remote-auth.js";
25
- import { defaultSshRouteAlias, parseSshRoute, readRemoteOwnerToken, withRemoteServiceEndpoint, } from "./remote-transport.js";
18
+ import { ensureForgeRelayInstanceId, generateInstanceId, generateOwnerToken, loadForgeRelayFiles, removeForgeRelayRemote, renameForgeRelayRemote, resolveSubagentsFlag, writeForgeRelayAuth, writeForgeRelayConfig, writeForgeRelayRemote, } from "./runtime/config/user-config.js";
19
+ import { expandHomePath } from "./mcp/filesystem/roots.js";
20
+ import { shutdownHttpServer } from "./mcp/server/transport/server-shutdown.js";
21
+ import { publicEndpointUrl } from "./mcp/oauth/public-url.js";
22
+ import { authenticateRemote, defaultRemoteAlias, isRemoteMcpUnauthorized, normalizeRemoteServiceTarget, refreshRemoteAuthentication, verifyRemoteMcp, } from "./workspaces/relay/auth/remote-auth.js";
23
+ import { defaultSshRouteAlias, parseSshRoute, readRemoteOwnerToken, withRemoteServiceEndpoint, } from "./workspaces/relay/transport/remote-transport.js";
24
+ import { normalizeOptionalPublicBaseUrl, normalizePublicBaseUrlsInput, compactPublicBaseUrlConfig, textPrompt, validatePort, validateRequiredPublicBaseUrls, assertSupportedNode, nodeVersionStatus, SetupCancelledError, checkSqliteNative, checkGitAvailable, checkBashShell } from "./cli/setup-support.js";
26
25
  const require = createRequire(import.meta.url);
27
- const SUPPORTED_NODE_RANGE = ">=20.12 <27";
28
26
  async function main(argv) {
29
27
  assertSupportedNode();
30
28
  const [rawCommand, ...args] = argv;
@@ -74,11 +72,11 @@ function normalizeCommand(command) {
74
72
  async function ensureConfigured() {
75
73
  const files = loadForgeRelayFiles();
76
74
  if (files.configExists && files.authExists) {
77
- ensureForgeRelayInstanceId();
75
+ await ensureForgeRelayInstanceId();
78
76
  return;
79
77
  }
80
78
  if (process.env.FORGERELAY_OAUTH_OWNER_TOKEN) {
81
- ensureForgeRelayInstanceId();
79
+ await ensureForgeRelayInstanceId();
82
80
  return;
83
81
  }
84
82
  if (!input.isTTY || !output.isTTY) {
@@ -156,7 +154,7 @@ async function runInit({ force }) {
156
154
  instanceId: files.auth.instanceId ?? generateInstanceId(),
157
155
  };
158
156
  const configPath = writeForgeRelayConfig(config);
159
- const authPath = writeForgeRelayAuth(auth);
157
+ const authPath = await writeForgeRelayAuth(auth);
160
158
  const lines = [
161
159
  `Config: ${configPath}`,
162
160
  `Auth: ${authPath}`,
@@ -316,7 +314,7 @@ async function runAuthCommand(args) {
316
314
  if (!fromAlias || !toAlias || extra.length > 0) {
317
315
  throw new Error("Usage: forgerelay auth rename <old-alias> <new-alias>");
318
316
  }
319
- renameForgeRelayRemote(fromAlias, toAlias);
317
+ await renameForgeRelayRemote(fromAlias, toAlias);
320
318
  console.log(`Renamed remote ${fromAlias} to ${toAlias}.`);
321
319
  return;
322
320
  }
@@ -324,7 +322,7 @@ async function runAuthCommand(args) {
324
322
  const [alias, ...extra] = rest;
325
323
  if (!alias || extra.length > 0)
326
324
  throw new Error("Usage: forgerelay auth remove <alias>");
327
- removeForgeRelayRemote(alias);
325
+ await removeForgeRelayRemote(alias);
328
326
  console.log(`Removed remote ${alias}.`);
329
327
  return;
330
328
  }
@@ -341,7 +339,7 @@ async function runAuthCommand(args) {
341
339
  let refreshed = false;
342
340
  if (remote.accessTokenExpiresAt <= Math.floor(Date.now() / 1000)) {
343
341
  remote = await refreshRemoteAuthentication(remote, endpoint);
344
- writeForgeRelayRemote(alias, remote);
342
+ await writeForgeRelayRemote(alias, remote);
345
343
  refreshed = true;
346
344
  }
347
345
  try {
@@ -351,7 +349,7 @@ async function runAuthCommand(args) {
351
349
  if (refreshed || !isRemoteMcpUnauthorized(error))
352
350
  throw error;
353
351
  remote = await refreshRemoteAuthentication(remote, endpoint);
354
- writeForgeRelayRemote(alias, remote);
352
+ await writeForgeRelayRemote(alias, remote);
355
353
  await verifyRemoteMcp(remote, endpoint);
356
354
  }
357
355
  });
@@ -378,9 +376,9 @@ async function runAuthCommand(args) {
378
376
  : defaultRemoteAlias(remote.target);
379
377
  const alias = parsed.alias?.trim() || existingAlias || defaultAlias;
380
378
  if (!files.auth.instanceId) {
381
- ensureForgeRelayInstanceId();
379
+ await ensureForgeRelayInstanceId();
382
380
  }
383
- writeForgeRelayRemote(alias, remote);
381
+ await writeForgeRelayRemote(alias, remote);
384
382
  console.log(`Authenticated remote ${alias} (${remote.instanceId}).`);
385
383
  }
386
384
  async function runDoctor() {
@@ -641,112 +639,6 @@ function printVersion() {
641
639
  }
642
640
  console.log(packageJson.version);
643
641
  }
644
- function isNullConfigValue(value) {
645
- const normalized = value.trim().toLowerCase();
646
- return !normalized || normalized === "null" || normalized === "none";
647
- }
648
- function normalizeOptionalPublicBaseUrl(value) {
649
- const trimmed = value.trim();
650
- if (isNullConfigValue(trimmed))
651
- return null;
652
- return compactPublicBaseUrlConfig(normalizePublicBaseUrlsInput(trimmed));
653
- }
654
- function normalizePublicBaseUrlsInput(value) {
655
- const entries = value
656
- .split(",")
657
- .map((entry) => entry.trim())
658
- .filter(Boolean);
659
- if (entries.length === 0)
660
- throw new Error("Enter at least one public base URL.");
661
- return Array.from(new Set(entries.map((entry) => normalizePublicBaseUrl(entry))));
662
- }
663
- function compactPublicBaseUrlConfig(baseUrls) {
664
- return baseUrls.length === 1 ? baseUrls[0] : baseUrls;
665
- }
666
- function normalizePublicBaseUrl(value) {
667
- const trimmed = value.trim();
668
- const parsed = new URL(trimmed);
669
- parsed.hash = "";
670
- parsed.search = "";
671
- parsed.pathname = parsed.pathname.replace(/\/+$/, "");
672
- return parsed.toString().replace(/\/$/, "");
673
- }
674
- async function textPrompt(options) {
675
- const result = await prompts.text({
676
- ...options,
677
- validate: (value) => options.validate?.(value?.trim() ? value : options.defaultValue),
678
- });
679
- if (prompts.isCancel(result))
680
- throw new SetupCancelledError();
681
- const value = String(result).trim();
682
- return value || options.defaultValue;
683
- }
684
- function validatePort(value) {
685
- const port = Number(value);
686
- return Number.isInteger(port) && port >= 1 && port <= 65535
687
- ? undefined
688
- : "Enter a port between 1 and 65535.";
689
- }
690
- function validateRequiredPublicBaseUrls(value) {
691
- const trimmed = value?.trim() ?? "";
692
- if (!trimmed)
693
- return "Enter at least one public base URL from your tunnel or reverse proxy.";
694
- try {
695
- normalizePublicBaseUrlsInput(trimmed);
696
- return undefined;
697
- }
698
- catch (error) {
699
- return error instanceof Error ? error.message : String(error);
700
- }
701
- }
702
- function assertSupportedNode() {
703
- if (satisfies(process.versions.node, SUPPORTED_NODE_RANGE))
704
- return;
705
- throw new Error([
706
- `ForgeRelay requires Node ${SUPPORTED_NODE_RANGE}.`,
707
- `Current Node: ${process.version}`,
708
- "",
709
- "Install Node 22 LTS or use a version manager such as nvm, fnm, or mise.",
710
- ].join("\n"));
711
- }
712
- function nodeVersionStatus() {
713
- return satisfies(process.versions.node, SUPPORTED_NODE_RANGE)
714
- ? `supported ${SUPPORTED_NODE_RANGE}`
715
- : `unsupported, requires ${SUPPORTED_NODE_RANGE}`;
716
- }
717
- class SetupCancelledError extends Error {
718
- }
719
- function checkSqliteNative() {
720
- try {
721
- const Database = require("better-sqlite3");
722
- const db = new Database(":memory:");
723
- db.close();
724
- return "ok";
725
- }
726
- catch (error) {
727
- return error instanceof Error ? error.message : String(error);
728
- }
729
- }
730
- function checkGitAvailable() {
731
- try {
732
- const { execFileSync } = require("node:child_process");
733
- return execFileSync("git", ["--version"], { encoding: "utf8" }).trim();
734
- }
735
- catch (error) {
736
- const message = error instanceof Error ? error.message : String(error);
737
- return `unavailable (${message})`;
738
- }
739
- }
740
- function checkBashShell() {
741
- try {
742
- const { shell, args } = getShellConfig();
743
- return `${shell} ${args.join(" ")}`;
744
- }
745
- catch (error) {
746
- const message = error instanceof Error ? error.message : String(error);
747
- return `unavailable (${message})`;
748
- }
749
- }
750
642
  main(process.argv.slice(2)).catch((error) => {
751
643
  console.error(error instanceof Error ? error.message : String(error));
752
644
  process.exitCode = 1;
@@ -5,7 +5,7 @@ import { pathToFileURL } from "node:url";
5
5
  import { createMessageConnection } from "vscode-jsonrpc/node";
6
6
  import { DefinitionRequest, DocumentDiagnosticReportKind, DocumentDiagnosticRequest, DocumentSymbolRequest, ExitNotification, HoverRequest, InitializeRequest, ReferencesRequest, InitializedNotification, MarkupKind, PositionEncodingKind, PublishDiagnosticsNotification, ShutdownRequest, WorkspaceSymbolRequest, } from "vscode-languageserver-protocol";
7
7
  import { LanguageServerConfigurationError, } from "./language-server-config.js";
8
- import { terminateProcessTree } from "../process-platform.js";
8
+ import { terminateProcessTree } from "../mcp/process/process-platform.js";
9
9
  import { CodeIntelligenceError } from "./code-intelligence-error.js";
10
10
  import { DEFAULT_CODE_INTELLIGENCE_RESULT_LIMIT } from "./code-intelligence-types.js";
11
11
  import { normalizeHoverContents } from "./normalization/hover.js";
@@ -4,16 +4,16 @@ import { tmpdir } from "node:os";
4
4
  import { join } from "node:path";
5
5
  import { Client } from "@modelcontextprotocol/sdk/client/index.js";
6
6
  import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
7
- import { ActivityAuditStore } from "../../activity/audit-store.js";
8
- import { BashOutputStore } from "../../activity/bash-output-store.js";
9
- import { HostTurnStore } from "../../activity/host-turn-store.js";
10
- import { ActivityLifecycle } from "../../activity/lifecycle.js";
11
- import { ActivityQueryService } from "../../activity/query-service.js";
12
- import { loadConfig } from "../../config.js";
13
- import { createReviewCheckpointManager } from "../../review-checkpoints.js";
14
- import { ProcessManager } from "../../process-sessions.js";
7
+ import { ActivityAuditStore } from "../../activity/history/audit-store.js";
8
+ import { BashOutputStore } from "../../activity/history/bash-output-store.js";
9
+ import { HostTurnStore } from "../../activity/history/host-turn-store.js";
10
+ import { ActivityLifecycle } from "../../activity/runtime/lifecycle.js";
11
+ import { ActivityQueryService } from "../../activity/history/query-service.js";
12
+ import { loadConfig } from "../../runtime/config/config.js";
13
+ import { createReviewCheckpointManager } from "../../workspaces/review/review-checkpoints.js";
14
+ import { ProcessManager } from "../../mcp/process/process-sessions.js";
15
15
  import { createMcpServer } from "../../server.js";
16
- import { SqliteWorkspaceStore } from "../../workspace-store.js";
16
+ import { SqliteWorkspaceStore } from "../../workspaces/state/workspace-store.js";
17
17
  import { WorkspaceRegistry } from "../../workspaces.js";
18
18
  import { CodeIntelligenceManager } from "../runtime/manager.js";
19
19
  export async function createCodeIntelligenceServerFixture(t, options = {}) {