@akira-tl/forgerelay 0.8.8 → 0.8.10

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 (264) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +10 -18
  3. package/capabilities/code-intelligence/GUIDE.md +7 -3
  4. package/capabilities/host-integration/GUIDE.md +2 -2
  5. package/capabilities/subagents/GUIDE.md +9 -0
  6. package/capabilities/{workspace-tasks → workspace/workspace-tasks}/GUIDE.md +6 -0
  7. package/dist/activity/{audit-store.js → history/audit-store.js} +129 -21
  8. package/dist/activity/history/bash-output-store.js +250 -0
  9. package/dist/activity/{host-turn-store.js → history/host-turn-store.js} +4 -1
  10. package/dist/activity/{query-service.js → history/query-service.js} +13 -7
  11. package/dist/activity/{lifecycle.js → runtime/lifecycle.js} +1 -1
  12. package/dist/activity/{mcp-query-tools.js → runtime/mcp-query-tools.js} +3 -3
  13. package/dist/activity/storage/history.js +12 -0
  14. package/dist/activity/storage/paths.js +56 -0
  15. package/dist/activity/storage/segmented-log.js +149 -0
  16. package/dist/cli/init.js +180 -0
  17. package/dist/cli/setup-support.js +181 -0
  18. package/dist/cli.js +23 -216
  19. package/dist/lsp/code-intelligence.js +18 -4
  20. package/dist/lsp/runtime/diagnostic-snapshots.js +52 -1
  21. package/dist/lsp/runtime/managed-language-servers.js +172 -0
  22. package/dist/lsp/runtime/manager.js +37 -2
  23. package/dist/lsp/runtime/process-launch.js +3 -0
  24. package/dist/lsp/test-support/server-fixture.js +14 -11
  25. package/dist/mcp/filesystem/filesystem-tools.js +245 -0
  26. package/dist/mcp/hooks/command-runner.js +79 -0
  27. package/dist/{hook-cli.js → mcp/hooks/hook-cli.js} +1 -1
  28. package/dist/{hooks.js → mcp/hooks/hooks.js} +3 -80
  29. package/dist/{oauth-provider.js → mcp/oauth/oauth-provider.js} +1 -1
  30. package/dist/{oauth-store.js → mcp/oauth/oauth-store.js} +5 -4
  31. package/dist/{operations → mcp/operations}/native-bulk-mutations.js +2 -2
  32. package/dist/mcp/panel/app.js +143 -0
  33. package/dist/{mcp-app-template.js → mcp/panel/mcp-app-template.js} +2 -38
  34. package/dist/{process-platform.js → mcp/process/process-platform.js} +21 -9
  35. package/dist/{process-sessions.js → mcp/process/process-sessions.js} +3 -3
  36. package/dist/mcp/process/runtime.js +257 -0
  37. package/dist/mcp/process/tools.js +346 -0
  38. package/dist/mcp/server/core/activity-support.js +70 -0
  39. package/dist/{capabilities.js → mcp/server/core/capabilities.js} +5 -3
  40. package/dist/{capability-registry.js → mcp/server/core/capability-registry.js} +9 -4
  41. package/dist/mcp/server/core/capability-support.js +90 -0
  42. package/dist/mcp/server/core/schemas.js +216 -0
  43. package/dist/mcp/server/core/tool-support.js +210 -0
  44. package/dist/mcp/server/core/version.js +9 -0
  45. package/dist/mcp/server/operations/runtime/filesystem-tools.js +455 -0
  46. package/dist/mcp/server/operations/runtime/mutation-diagnostics.js +54 -0
  47. package/dist/mcp/server/operations/runtime/operation-runtime.js +524 -0
  48. package/dist/mcp/server/transport/http-server.js +301 -0
  49. package/dist/mcp/server/transport/http-support.js +43 -0
  50. package/dist/mcp/server/workspace/runtime/workspace-open-presentation.js +242 -0
  51. package/dist/mcp/server/workspace/runtime/workspace-open-schema.js +187 -0
  52. package/dist/mcp/server/workspace/runtime/workspace-open.js +555 -0
  53. package/dist/mcp/server/workspace/runtime/workspace-tools.js +601 -0
  54. package/dist/mcp/server-instructions.js +1 -1
  55. package/dist/{config.js → runtime/config/config.js} +4 -3
  56. package/dist/{user-config.js → runtime/config/user-config.js} +14 -63
  57. package/dist/{db → runtime/state/db}/client.js +1 -1
  58. package/dist/{db → runtime/state/db}/migrations.js +34 -3
  59. package/dist/runtime/state/lock/file-lock.js +130 -0
  60. package/dist/runtime/testing/server-fixture.js +190 -0
  61. package/dist/server.js +133 -4189
  62. package/dist/subagents/providers/adapters/claude.js +86 -52
  63. package/dist/subagents/providers/adapters/codex.js +103 -39
  64. package/dist/subagents/providers/adapters/opencode.js +114 -84
  65. package/dist/subagents/providers/adapters/pi.js +59 -8
  66. package/dist/subagents/providers/availability.js +15 -30
  67. package/dist/subagents/providers/runtime/external-command.js +56 -0
  68. package/dist/subagents/sessions/capability.js +1 -1
  69. package/dist/subagents/sessions/execution.js +1 -1
  70. package/dist/subagents/sessions/mcp/activity-audit-test-support.js +30 -0
  71. package/dist/subagents/sessions/store.js +1 -1
  72. package/dist/ui/.vite/manifest.json +342 -410
  73. package/dist/ui/activity-panel-app.html +2 -4
  74. package/dist/ui/assets/activity-panel-app-7Xe0alhm.css +1 -0
  75. package/dist/ui/assets/activity-panel-app-Sl1Jro8v.js +115 -0
  76. package/dist/ui/assets/angular-html-B_yn91wW.js +1 -0
  77. package/dist/ui/assets/{angular-ts-Bxh4-O1-.js → angular-ts-DSgtloKz.js} +1 -1
  78. package/dist/ui/assets/{apl-BmYHKQ6m.js → apl-NatWtF8X.js} +1 -1
  79. package/dist/ui/assets/{astro-C51vqDKq.js → astro-BYFEVBuN.js} +1 -1
  80. package/dist/ui/assets/{blade-CdhVsmwq.js → blade-DoO7yvMR.js} +1 -1
  81. package/dist/ui/assets/c-Rl2hMCcg.js +1 -0
  82. package/dist/ui/assets/{cobol-Cf6azoN_.js → cobol-ByC5mWiB.js} +1 -1
  83. package/dist/ui/assets/{coffee-vVdGzlmt.js → coffee-Dez77Qov.js} +1 -1
  84. package/dist/ui/assets/cpp-DtaAQT9h.js +1 -0
  85. package/dist/ui/assets/{crystal-5UZy6KIX.js → crystal-Bgmbf8ec.js} +1 -1
  86. package/dist/ui/assets/css-C1tjBtVN.js +1 -0
  87. package/dist/ui/assets/{edge-CESgo4ia.js → edge-DeH6u8Wg.js} +1 -1
  88. package/dist/ui/assets/{elixir-9FKfw4cJ.js → elixir-_H3KnmWT.js} +1 -1
  89. package/dist/ui/assets/{elm-Dv7A0aLa.js → elm-CsCe3U28.js} +1 -1
  90. package/dist/ui/assets/{erb-DHFmDvM0.js → erb-CbM-L2g8.js} +1 -1
  91. package/dist/ui/assets/{git-rebase-utbU6CzV.js → git-rebase-D0s5pDh9.js} +1 -1
  92. package/dist/ui/assets/{glimmer-js-t2kiCkyB.js → glimmer-js-BfOToq_A.js} +1 -1
  93. package/dist/ui/assets/{glimmer-ts-F0Jv5okV.js → glimmer-ts-CCUOkL2K.js} +1 -1
  94. package/dist/ui/assets/glsl-DH4ec9dE.js +1 -0
  95. package/dist/ui/assets/graphql-DilAMBoI.js +1 -0
  96. package/dist/ui/assets/{hack-8yjdbaSA.js → hack-BDkNDZlF.js} +1 -1
  97. package/dist/ui/assets/haml-D_QBp6K7.js +1 -0
  98. package/dist/ui/assets/{handlebars-BBFEg4Lo.js → handlebars-DePUrTpC.js} +1 -1
  99. package/dist/ui/assets/heavy-payload-DOwZpO6n.js +290 -0
  100. package/dist/ui/assets/html-By4dNnM4.js +1 -0
  101. package/dist/ui/assets/{html-derivative-DJAQcZyc.js → html-derivative-DDw9Ef4Q.js} +1 -1
  102. package/dist/ui/assets/{http-Dg5LSYRK.js → http-B0QxWc9M.js} +1 -1
  103. package/dist/ui/assets/{hurl-Y5uYzMZR.js → hurl-vMQ4lda1.js} +1 -1
  104. package/dist/ui/assets/java-DYRe2lWG.js +1 -0
  105. package/dist/ui/assets/javascript-CxyGqwcL.js +1 -0
  106. package/dist/ui/assets/{jinja-Bt30h8Ik.js → jinja-JUwV-fZt.js} +1 -1
  107. package/dist/ui/assets/{jison-D5uZ1Nyo.js → jison-7ZqCEvS8.js} +1 -1
  108. package/dist/ui/assets/json-dbltgiiA.js +1 -0
  109. package/dist/ui/assets/jsx-oDopT7YQ.js +1 -0
  110. package/dist/ui/assets/{julia-76hRaaGz.js → julia-CkKiNSav.js} +1 -1
  111. package/dist/ui/assets/{just-CDE7W0vW.js → just-DuqCAKJ3.js} +1 -1
  112. package/dist/ui/assets/{latex-CVO2Byab.js → latex-sudcRDSn.js} +1 -1
  113. package/dist/ui/assets/{liquid-CA-AS3EX.js → liquid-Di-08Js7.js} +1 -1
  114. package/dist/ui/assets/lua-YlqdMoV0.js +1 -0
  115. package/dist/ui/assets/{marko-_BWrPfny.js → marko-CJRNyJDb.js} +1 -1
  116. package/dist/ui/assets/{mdc-PyJv85eS.js → mdc-t12CzZHs.js} +1 -1
  117. package/dist/ui/assets/{nginx-DAWVw8yu.js → nginx-57-b4XwT.js} +1 -1
  118. package/dist/ui/assets/{nim-CKE1dzpU.js → nim-BzrswYQa.js} +1 -1
  119. package/dist/ui/assets/{perl-BBhWva19.js → perl-D9JR_iIh.js} +1 -1
  120. package/dist/ui/assets/{php-ChIeaAoF.js → php-Py2gFHil.js} +1 -1
  121. package/dist/ui/assets/{pug-CMgI5afi.js → pug-PzLLy0h1.js} +1 -1
  122. package/dist/ui/assets/{qml-CjxTkcFH.js → qml-By8fwgV4.js} +1 -1
  123. package/dist/ui/assets/r-CcezTbLq.js +1 -0
  124. package/dist/ui/assets/{razor-i4DbHr8p.js → razor-dG-vdhL_.js} +1 -1
  125. package/dist/ui/assets/regexp-BlsQ-N_8.js +1 -0
  126. package/dist/ui/assets/{rst-oy_97Kl4.js → rst-C2awDCat.js} +1 -1
  127. package/dist/ui/assets/{ruby-C5zYZIyl.js → ruby-zA2W_49d.js} +1 -1
  128. package/dist/ui/assets/{sas-BnMEh2S3.js → sas-D49bhyaN.js} +1 -1
  129. package/dist/ui/assets/scss-BQb-cp01.js +1 -0
  130. package/dist/ui/assets/shellscript-Dga4H_Ni.js +1 -0
  131. package/dist/ui/assets/{shellsession-BpE5o7_3.js → shellsession-n3-5CqcF.js} +1 -1
  132. package/dist/ui/assets/{soy-COesmhTY.js → soy-XYBOf_BA.js} +1 -1
  133. package/dist/ui/assets/sql-ET4u5Cpl.js +1 -0
  134. package/dist/ui/assets/{stata-CGQEuSZq.js → stata-CLHcJHO_.js} +1 -1
  135. package/dist/ui/assets/{surrealql-Bz4JbU-9.js → surrealql-BdjQ60T4.js} +1 -1
  136. package/dist/ui/assets/{svelte-1jM2ejXj.js → svelte-B2RPtKJe.js} +1 -1
  137. package/dist/ui/assets/{templ-C-VwELcp.js → templ-CrByPW_W.js} +1 -1
  138. package/dist/ui/assets/{tex-t1rUiQCm.js → tex-DZBkg363.js} +1 -1
  139. package/dist/ui/assets/{ts-tags-Bewoa6pS.js → ts-tags-DJR3Gphb.js} +1 -1
  140. package/dist/ui/assets/tsx-CajzROyy.js +1 -0
  141. package/dist/ui/assets/{twig-DVg-vELl.js → twig-BZjk5Zda.js} +1 -1
  142. package/dist/ui/assets/typescript-B-EWToLj.js +1 -0
  143. package/dist/ui/assets/{vue-wPQ7UlMy.js → vue-D_rHCCr8.js} +1 -1
  144. package/dist/ui/assets/{vue-html-BHtJ8geX.js → vue-html-CC4WlvVt.js} +1 -1
  145. package/dist/ui/assets/{vue-vine-CNSGAWwc.js → vue-vine-BgNMVgpk.js} +1 -1
  146. package/dist/ui/assets/xml-BI86-WbH.js +1 -0
  147. package/dist/ui/assets/{xsl-3_vJ27aE.js → xsl-DXeLZV4J.js} +1 -1
  148. package/dist/ui/assets/yaml-60_PFlWa.js +1 -0
  149. package/dist/workspaces/bootstrap.js +72 -0
  150. package/dist/workspaces/context.js +337 -0
  151. package/dist/workspaces/conversation-test-support.js +86 -0
  152. package/dist/{git-worktrees.js → workspaces/git/git-worktrees.js} +1 -1
  153. package/dist/workspaces/inventory.js +131 -0
  154. package/dist/workspaces/paths.js +55 -0
  155. package/dist/{remote-auth.js → workspaces/relay/auth/remote-auth.js} +2 -2
  156. package/dist/workspaces/relay/result-support.js +111 -0
  157. package/dist/workspaces/relay/tests/test-support.js +203 -0
  158. package/dist/{remote-mcp-connection-pool.js → workspaces/relay/transport/remote-mcp-connection-pool.js} +1 -1
  159. package/dist/{remote-transport.js → workspaces/relay/transport/remote-transport.js} +30 -3
  160. package/dist/workspaces/relay/types.js +1 -0
  161. package/dist/{remote-workspace-relay.js → workspaces/relay/workspace-relay.js} +23 -172
  162. package/dist/workspaces/resources/resource-monitor.js +377 -0
  163. package/dist/workspaces/resources/skills.js +283 -0
  164. package/dist/{review-checkpoints.js → workspaces/review/review-checkpoints.js} +2 -2
  165. package/dist/workspaces/sessions.js +460 -0
  166. package/dist/{workspace-store.js → workspaces/state/workspace-store.js} +2 -2
  167. package/dist/workspaces.js +77 -993
  168. package/docs/chatgpt-coding-workflow.md +7 -14
  169. package/docs/configuration.md +26 -34
  170. package/docs/gotchas.md +0 -30
  171. package/docs/roadmap.md +6 -10
  172. package/docs/security.md +1 -5
  173. package/docs/setup.md +0 -11
  174. package/package.json +6 -9
  175. package/scripts/ci/architecture.mjs +109 -0
  176. package/scripts/ci/verify.mjs +5 -0
  177. package/scripts/debug/accept/bootstrap.mjs +326 -0
  178. package/scripts/debug/accept/harness.mjs +76 -0
  179. package/scripts/debug/accept/support.mjs +432 -0
  180. package/scripts/debug/accept.mjs +43 -806
  181. package/scripts/debug/relay-accept/support.mjs +135 -0
  182. package/scripts/debug/relay-accept.mjs +26 -115
  183. package/scripts/debug/traffic/support.mjs +167 -0
  184. package/scripts/debug/traffic/traffic-audit.mjs +4 -161
  185. package/scripts/{lsp-interop-support.test.mjs → lsp/interop-support.test.mjs} +1 -1
  186. package/scripts/{lsp-interop.mjs → lsp/interop.mjs} +3 -3
  187. package/scripts/release/publish.mjs +12 -9
  188. package/scripts/release/release-gate.test.mjs +3 -1
  189. package/scripts/release/release-version.test.mjs +13 -1
  190. package/scripts/release-parity.mjs +1 -1
  191. package/scripts/release-proof.mjs +15 -0
  192. package/scripts/release-proof.test.mjs +27 -1
  193. package/scripts/release-version.mjs +16 -1
  194. package/scripts/wiki/sync.mjs +21 -10
  195. package/dist/activity/bash-output-store.js +0 -127
  196. package/dist/pi-tools.js +0 -110
  197. package/dist/skills.js +0 -127
  198. package/dist/ui/assets/activity-panel-app-7AckaxIR.js +0 -2
  199. package/dist/ui/assets/angular-html-BkgDQl-G.js +0 -1
  200. package/dist/ui/assets/c-IBzBpxAO.js +0 -1
  201. package/dist/ui/assets/chunk-EyZ2wyi3.js +0 -1
  202. package/dist/ui/assets/cpp-CVHeO-Jk.js +0 -1
  203. package/dist/ui/assets/css-DEfus9J5.js +0 -1
  204. package/dist/ui/assets/glsl-_ooCjaeB.js +0 -1
  205. package/dist/ui/assets/graphql-B9LqP-cY.js +0 -1
  206. package/dist/ui/assets/haml-BU5EoZBn.js +0 -1
  207. package/dist/ui/assets/heavy-payload-Bol1_mcs.js +0 -4
  208. package/dist/ui/assets/html-D-C6YZk4.js +0 -1
  209. package/dist/ui/assets/java-ppHvycj5.js +0 -1
  210. package/dist/ui/assets/javascript-DDTjKLlQ.js +0 -1
  211. package/dist/ui/assets/json-Cw91r8h1.js +0 -1
  212. package/dist/ui/assets/jsx-04X2FT_1.js +0 -1
  213. package/dist/ui/assets/lua-CiyBp52Y.js +0 -1
  214. package/dist/ui/assets/r-DfFga4si.js +0 -1
  215. package/dist/ui/assets/regexp-iC9_nbSI.js +0 -1
  216. package/dist/ui/assets/review-payload-BqJp0c5e.js +0 -1
  217. package/dist/ui/assets/scrollbar-CvE-I-jG.js +0 -287
  218. package/dist/ui/assets/scss-BfZXsAWQ.js +0 -1
  219. package/dist/ui/assets/shellscript-BC2srNaB.js +0 -1
  220. package/dist/ui/assets/sql-Ccv_yeUm.js +0 -1
  221. package/dist/ui/assets/tsx-CTXzrBkN.js +0 -1
  222. package/dist/ui/assets/typescript--ElHoFkw.js +0 -1
  223. package/dist/ui/assets/workspace-app-BLW7p6IZ.js +0 -114
  224. package/dist/ui/assets/workspace-app-BjNqR0en.js +0 -1
  225. package/dist/ui/assets/workspace-app-CmaYU4DW.js +0 -3
  226. package/dist/ui/assets/workspace-app-D2bJ5fjt.css +0 -1
  227. package/dist/ui/assets/workspace-lifecycle-app-BVbI2Ilf.js +0 -1
  228. package/dist/ui/assets/xml-JnmX6vyS.js +0 -1
  229. package/dist/ui/assets/yaml-OAcZkP-w.js +0 -1
  230. package/dist/ui/workspace-app.html +0 -18
  231. package/dist/ui/workspace-lifecycle-app.html +0 -18
  232. package/docs/agent-profile-schema.md +0 -114
  233. package/docs/artifact-exchange.md +0 -65
  234. package/docs/versioning.md +0 -205
  235. package/skills/subagent-delegation/SKILL.md +0 -132
  236. /package/capabilities/{managed-worktrees → workspace/managed-worktrees}/GUIDE.md +0 -0
  237. /package/dist/activity/{process-output-audit.js → runtime/process-output-audit.js} +0 -0
  238. /package/dist/{artifact-error.js → mcp/artifacts/artifact-error.js} +0 -0
  239. /package/dist/{artifact-tools.js → mcp/artifacts/artifact-tools.js} +0 -0
  240. /package/dist/{incoming-artifacts.js → mcp/artifacts/incoming-artifacts.js} +0 -0
  241. /package/dist/{advertised-files.js → mcp/filesystem/advertised-files.js} +0 -0
  242. /package/dist/{apply-patch.js → mcp/filesystem/apply-patch.js} +0 -0
  243. /package/dist/{file-mutations.js → mcp/filesystem/file-mutations.js} +0 -0
  244. /package/dist/{roots.js → mcp/filesystem/roots.js} +0 -0
  245. /package/dist/{oauth → mcp/oauth}/public-url.js +0 -0
  246. /package/dist/{oauth → mcp/oauth}/router.js +0 -0
  247. /package/dist/{operations → mcp/operations}/batch/executor.js +0 -0
  248. /package/dist/{operations → mcp/operations}/batch/scheduler.js +0 -0
  249. /package/dist/{operations → mcp/operations}/batch/types.js +0 -0
  250. /package/dist/{operations → mcp/operations}/bulk-mutation.js +0 -0
  251. /package/dist/{operations → mcp/operations}/bulk-read.js +0 -0
  252. /package/dist/{operations → mcp/operations}/core-operation-executor.js +0 -0
  253. /package/dist/{request-meta.js → mcp/request-meta.js} +0 -0
  254. /package/dist/{mcp-sessions.js → mcp/server/transport/mcp-sessions.js} +0 -0
  255. /package/dist/{server-shutdown.js → mcp/server/transport/server-shutdown.js} +0 -0
  256. /package/dist/{logger.js → runtime/logging/logger.js} +0 -0
  257. /package/dist/{db → runtime/state/db}/schema.js +0 -0
  258. /package/dist/{composite-activity.js → workspaces/composite/composite-activity.js} +0 -0
  259. /package/dist/{composite-workspaces.js → workspaces/composite/composite-workspaces.js} +0 -0
  260. /package/dist/{git.js → workspaces/git/git.js} +0 -0
  261. /package/dist/{workspace-presentation.js → workspaces/presentation/workspace-presentation.js} +0 -0
  262. /package/dist/{workspace-task-reminders.js → workspaces/tasks/workspace-task-reminders.js} +0 -0
  263. /package/dist/{workspace-tasks.js → workspaces/tasks/workspace-tasks.js} +0 -0
  264. /package/scripts/{lsp-interop-support.mjs → lsp/interop-support.mjs} +0 -0
@@ -0,0 +1,216 @@
1
+ import * as z from "zod/v4";
2
+ export function resultOutputSchema(extra = {}) {
3
+ return {
4
+ result: z
5
+ .string()
6
+ .describe("Model-readable result text for follow-up reasoning and plain MCP hosts."),
7
+ ...extra,
8
+ };
9
+ }
10
+ export const workspaceSkillOutputSchema = z.object({
11
+ name: z.string(),
12
+ description: z.string(),
13
+ });
14
+ export const workspaceSkillDiagnosticOutputSchema = z.object({
15
+ type: z.enum(["warning", "error", "collision"]),
16
+ message: z.string(),
17
+ collision: z.object({
18
+ resourceType: z.enum(["extension", "skill", "prompt", "theme"]),
19
+ name: z.string(),
20
+ }).optional(),
21
+ });
22
+ export function redactSkillDiagnosticPaths(diagnostics) {
23
+ return diagnostics.map((diagnostic) => {
24
+ let message = diagnostic.message;
25
+ const hiddenPaths = [
26
+ diagnostic.path,
27
+ diagnostic.collision?.winnerPath,
28
+ diagnostic.collision?.loserPath,
29
+ ].filter((path) => Boolean(path));
30
+ for (const path of hiddenPaths) {
31
+ message = message.split(path).join("<skill-path>");
32
+ }
33
+ return {
34
+ type: diagnostic.type,
35
+ message,
36
+ ...(diagnostic.collision
37
+ ? {
38
+ collision: {
39
+ resourceType: diagnostic.collision.resourceType,
40
+ name: diagnostic.collision.name,
41
+ },
42
+ }
43
+ : {}),
44
+ };
45
+ });
46
+ }
47
+ export const capabilityFingerprintOutputSchema = z.object({
48
+ version: z.string(),
49
+ toolMode: z.enum(["minimal", "full", "codex"]),
50
+ capabilities: z.array(z.string()),
51
+ });
52
+ export const capabilityGuideOutputSchema = z.object({
53
+ name: z.string(),
54
+ description: z.string(),
55
+ whenToRead: z.string(),
56
+ path: z.string(),
57
+ });
58
+ export const capabilityCatalogGuideOutputSchema = z.object({
59
+ name: z.string(),
60
+ path: z.string(),
61
+ readBeforeFirstUse: z.boolean(),
62
+ });
63
+ export const capabilityCatalogOutputSchema = z.object({
64
+ name: z.string(),
65
+ description: z.string(),
66
+ available: z.boolean(),
67
+ unavailableReason: z.string().optional(),
68
+ batchPolicy: z.enum(["parallel", "serial", "unsupported"]),
69
+ guide: capabilityCatalogGuideOutputSchema,
70
+ });
71
+ export const capabilityErrorOutputSchema = z.object({
72
+ code: z.string(),
73
+ message: z.string(),
74
+ });
75
+ export const workspaceAgentsFileOutputSchema = z.object({
76
+ path: z.string(),
77
+ content: z.string(),
78
+ });
79
+ export const workspaceLocalAgentOutputSchema = z.object({
80
+ name: z.string(),
81
+ description: z.string(),
82
+ provider: z.string(),
83
+ model: z.string().optional(),
84
+ thinking: z.string().optional(),
85
+ providerAvailable: z.boolean().optional(),
86
+ providerUnavailableReason: z.string().optional(),
87
+ });
88
+ export const workspaceSubagentProviderOutputSchema = z.object({
89
+ name: z.string(),
90
+ available: z.boolean(),
91
+ continuationSupported: z.boolean(),
92
+ reason: z.string().optional(),
93
+ });
94
+ export const workspaceAvailableAgentsFileOutputSchema = z.object({
95
+ path: z.string(),
96
+ });
97
+ export const workspaceInventoryEntryOutputSchema = z.object({
98
+ label: z.string(),
99
+ workspaceId: z.string(),
100
+ root: z.string(),
101
+ status: z.string(),
102
+ state: z.enum(["active", "stale", "invalid", "closed"]),
103
+ mode: z.enum(["checkout", "worktree"]),
104
+ sourceRoot: z.string().optional(),
105
+ branch: z.string().optional(),
106
+ targetBranch: z.string().optional(),
107
+ managed: z.boolean(),
108
+ createdAt: z.string(),
109
+ lastUsedAt: z.string(),
110
+ idleMs: z.number().nonnegative(),
111
+ rootValid: z.boolean(),
112
+ current: z.boolean(),
113
+ });
114
+ export const workspaceInventorySummaryOutputSchema = z.object({
115
+ total: z.number().int().nonnegative(),
116
+ matching: z.number().int().nonnegative(),
117
+ active: z.number().int().nonnegative(),
118
+ stale: z.number().int().nonnegative(),
119
+ invalid: z.number().int().nonnegative(),
120
+ closed: z.number().int().nonnegative(),
121
+ });
122
+ export const workspaceInventoryPageOutputSchema = z.object({
123
+ offset: z.number().int().nonnegative(),
124
+ limit: z.number().int().positive(),
125
+ hasMore: z.boolean(),
126
+ });
127
+ export const workspaceTaskInspectionSummaryOutputSchema = z.object({
128
+ level: z.literal("summary"),
129
+ version: z.literal(1),
130
+ revision: z.number().int().nonnegative(),
131
+ lists: z.array(z.object({
132
+ id: z.string(),
133
+ name: z.string(),
134
+ state: z.enum(["active", "archived"]),
135
+ revision: z.number().int().positive(),
136
+ taskCount: z.number().int().nonnegative(),
137
+ unfinishedTaskCount: z.number().int().nonnegative(),
138
+ })),
139
+ });
140
+ export const workspaceInspectionMemberOutputSchema = z.object({
141
+ name: z.string(),
142
+ purpose: z.string(),
143
+ workspaceId: z.string(),
144
+ known: z.boolean(),
145
+ location: z.enum(["local", "relay"]).optional(),
146
+ state: z.enum(["active", "stale", "invalid", "closed"]).optional(),
147
+ status: z.string().optional(),
148
+ routeState: z.literal("known").optional(),
149
+ mode: z.enum(["checkout", "worktree"]).optional(),
150
+ rootValid: z.boolean().optional(),
151
+ });
152
+ export const workspaceInspectionOutputSchema = z.union([
153
+ z.object({
154
+ workspaceId: z.string(),
155
+ kind: z.literal("workspace"),
156
+ location: z.literal("local"),
157
+ label: z.string(),
158
+ root: z.string(),
159
+ status: z.string(),
160
+ state: z.enum(["active", "stale", "invalid", "closed"]),
161
+ mode: z.enum(["checkout", "worktree"]),
162
+ sourceRoot: z.string().optional(),
163
+ branch: z.string().optional(),
164
+ targetBranch: z.string().optional(),
165
+ managed: z.boolean(),
166
+ createdAt: z.string(),
167
+ lastUsedAt: z.string(),
168
+ idleMs: z.number().nonnegative(),
169
+ rootValid: z.boolean(),
170
+ taskSummary: workspaceTaskInspectionSummaryOutputSchema.optional(),
171
+ }),
172
+ z.object({
173
+ workspaceId: z.string(),
174
+ kind: z.literal("workspace"),
175
+ location: z.literal("relay"),
176
+ root: z.string(),
177
+ routeState: z.literal("known"),
178
+ status: z.string().optional(),
179
+ state: z.enum(["active", "stale", "invalid", "closed"]).optional(),
180
+ mode: z.enum(["checkout", "worktree"]),
181
+ sourceRoot: z.string().optional(),
182
+ branch: z.string().optional(),
183
+ targetBranch: z.string().optional(),
184
+ managed: z.boolean().optional(),
185
+ createdAt: z.string().optional(),
186
+ lastUsedAt: z.string().optional(),
187
+ idleMs: z.number().nonnegative().optional(),
188
+ rootValid: z.boolean().optional(),
189
+ taskSummary: workspaceTaskInspectionSummaryOutputSchema.optional(),
190
+ relay: z.string(),
191
+ executionLocation: z.string(),
192
+ }),
193
+ z.object({
194
+ workspaceId: z.string(),
195
+ kind: z.literal("composite"),
196
+ name: z.string(),
197
+ status: z.enum(["active", "closed"]),
198
+ state: z.enum(["active", "closed"]),
199
+ createdAt: z.string(),
200
+ lastUsedAt: z.string(),
201
+ members: z.array(workspaceInspectionMemberOutputSchema),
202
+ taskSummary: workspaceTaskInspectionSummaryOutputSchema.optional(),
203
+ }),
204
+ ]);
205
+ export const reviewFileOutputSchema = z.object({
206
+ path: z.string(),
207
+ previousPath: z.string().optional(),
208
+ type: z.enum(["change", "rename-pure", "rename-changed", "new", "deleted"]),
209
+ additions: z.number(),
210
+ removals: z.number(),
211
+ });
212
+ export const reviewSummaryOutputSchema = z.object({
213
+ files: z.number(),
214
+ additions: z.number(),
215
+ removals: z.number(),
216
+ });
@@ -0,0 +1,210 @@
1
+ import { resolve } from "node:path";
2
+ import { commandPreview, logEvent, workspaceLogLabel } from "../../../runtime/logging/logger.js";
3
+ import { formatAgentsPath } from "../../../workspaces.js";
4
+ export function workspaceLogContext(workspace, _transportSessionId) {
5
+ return {
6
+ workspaceId: workspace.id,
7
+ workspace: workspaceLogLabel(workspace.root, workspace.id),
8
+ };
9
+ }
10
+ export function formatDiscoveredWorkspaceInstructions(files, workspaceRoot) {
11
+ return [
12
+ "Workspace instructions discovered for this path. Apply them to follow-up work under their directories:",
13
+ ...files.flatMap((file) => [
14
+ `--- ${formatAgentsPath(file.path, workspaceRoot)} ---`,
15
+ file.content.trimEnd(),
16
+ ]),
17
+ ].join("\n");
18
+ }
19
+ export async function assertWorkspaceInstructionsLoadedBeforeSideEffect(workspaces, workspace, paths) {
20
+ const discovered = new Map();
21
+ for (const path of paths) {
22
+ const absolutePath = resolve(workspace.root, path);
23
+ for (const file of await workspaces.discoverPathInstructions(workspace, absolutePath)) {
24
+ discovered.set(file.path, file);
25
+ }
26
+ }
27
+ if (discovered.size === 0)
28
+ return;
29
+ throw new Error([
30
+ formatDiscoveredWorkspaceInstructions([...discovered.values()], workspace.root),
31
+ "Apply these instructions, then retry this tool call. No mutation or command was executed.",
32
+ ].join("\n"));
33
+ }
34
+ export function logToolCall(config, fields) {
35
+ if (!config.logging.toolCalls)
36
+ return;
37
+ const { command, ...safeFields } = fields;
38
+ logEvent(config.logging, fields.success ? "info" : "warn", "tool_call", {
39
+ ...safeFields,
40
+ commandPreview: config.logging.shellCommands && command ? commandPreview(command) : undefined,
41
+ });
42
+ }
43
+ export function contentText(content) {
44
+ return content
45
+ .filter((item) => item.type === "text")
46
+ .map((item) => item.text)
47
+ .join("\n");
48
+ }
49
+ export function toolErrorPreview(content) {
50
+ const text = contentText(content).replace(/\s+/g, " ").trim();
51
+ if (!text)
52
+ return undefined;
53
+ return text.length > 240 ? `${text.slice(0, 237)}...` : text;
54
+ }
55
+ export function logFailedToolResponse(config, fields, content, startedAt) {
56
+ logToolCall(config, {
57
+ ...fields,
58
+ success: false,
59
+ durationMs: Math.round(performance.now() - startedAt),
60
+ error: toolErrorPreview(content),
61
+ });
62
+ }
63
+ export function textBlock(text) {
64
+ return { type: "text", text };
65
+ }
66
+ export function attachWorkspaceTaskReminder(result, reminder) {
67
+ return attachWorkspaceNotice(result, reminder);
68
+ }
69
+ export function attachWorkspaceContextUpdate(result, update) {
70
+ return attachWorkspaceNotice(result, update);
71
+ }
72
+ function attachWorkspaceNotice(result, notice) {
73
+ if (!notice || toolResultIsError(result) || typeof result !== "object" || result === null)
74
+ return result;
75
+ const content = result.content;
76
+ if (!Array.isArray(content))
77
+ return result;
78
+ return { ...result, content: [...content, textBlock(notice)] };
79
+ }
80
+ export function textSummary(content) {
81
+ const text = contentText(content);
82
+ return {
83
+ lines: text.length === 0 ? 0 : text.split("\n").length,
84
+ characters: text.length,
85
+ };
86
+ }
87
+ export function contentLineCount(content) {
88
+ if (content.length === 0)
89
+ return 0;
90
+ return content.endsWith("\n")
91
+ ? content.slice(0, -1).split("\n").length
92
+ : content.split("\n").length;
93
+ }
94
+ export function countDiffStats(diff) {
95
+ if (!diff)
96
+ return { additions: 0, removals: 0 };
97
+ let additions = 0;
98
+ let removals = 0;
99
+ for (const line of diff.split("\n")) {
100
+ if (line.startsWith("+") && !line.startsWith("+++"))
101
+ additions++;
102
+ if (line.startsWith("-") && !line.startsWith("---"))
103
+ removals++;
104
+ }
105
+ return { additions, removals };
106
+ }
107
+ export function newFilePatch(path, content) {
108
+ const lines = content.length === 0
109
+ ? []
110
+ : content.endsWith("\n")
111
+ ? content.slice(0, -1).split("\n")
112
+ : content.split("\n");
113
+ const hunkLength = lines.length;
114
+ const hunkRange = hunkLength === 0 ? "+0,0" : `+1,${hunkLength}`;
115
+ const body = lines.map((line) => `+${line}`).join("\n");
116
+ return [
117
+ `diff --git a/${path} b/${path}`,
118
+ "new file mode 100644",
119
+ "index 0000000..0000000",
120
+ "--- /dev/null",
121
+ `+++ b/${path}`,
122
+ `@@ -0,0 ${hunkRange} @@`,
123
+ body,
124
+ ]
125
+ .filter((line) => line.length > 0)
126
+ .join("\n");
127
+ }
128
+ export function toolResultIsError(result) {
129
+ return typeof result === "object" && result !== null && result.isError === true;
130
+ }
131
+ export function toolResultText(result) {
132
+ if (typeof result !== "object" || result === null)
133
+ return String(result ?? "");
134
+ const record = result;
135
+ if (Array.isArray(record.content)) {
136
+ const text = record.content
137
+ .map((entry) => {
138
+ if (typeof entry !== "object" || entry === null)
139
+ return "";
140
+ const value = entry.text;
141
+ return typeof value === "string" ? value : "";
142
+ })
143
+ .filter(Boolean)
144
+ .join("\n");
145
+ if (text)
146
+ return text;
147
+ }
148
+ if (typeof record.structuredContent === "object" && record.structuredContent !== null) {
149
+ const value = record.structuredContent.result;
150
+ if (typeof value === "string")
151
+ return value;
152
+ }
153
+ return "";
154
+ }
155
+ export function toolResultContent(result) {
156
+ if (typeof result !== "object" || result === null)
157
+ return [];
158
+ const content = result.content;
159
+ return Array.isArray(content) ? content : [];
160
+ }
161
+ export function remapCompositeToolResult(result, executionWorkspaceId, compositeWorkspaceId, member) {
162
+ if (typeof result !== "object" || result === null)
163
+ return result;
164
+ const record = result;
165
+ const remapped = replaceWorkspaceIdentity(record, executionWorkspaceId, compositeWorkspaceId);
166
+ const meta = typeof remapped._meta === "object" && remapped._meta !== null
167
+ ? { ...remapped._meta }
168
+ : undefined;
169
+ if (meta) {
170
+ const card = typeof meta.card === "object" && meta.card !== null
171
+ ? { ...meta.card, workspaceId: compositeWorkspaceId, member }
172
+ : undefined;
173
+ if (card)
174
+ meta.card = card;
175
+ remapped._meta = meta;
176
+ }
177
+ const structured = typeof remapped.structuredContent === "object" && remapped.structuredContent !== null
178
+ ? { ...remapped.structuredContent, member }
179
+ : undefined;
180
+ if (structured)
181
+ remapped.structuredContent = structured;
182
+ return remapped;
183
+ }
184
+ export function replaceWorkspaceIdentity(value, from, to) {
185
+ if (typeof value === "string")
186
+ return value.split(from).join(to);
187
+ if (Array.isArray(value))
188
+ return value.map((entry) => replaceWorkspaceIdentity(entry, from, to));
189
+ if (!value || typeof value !== "object")
190
+ return value;
191
+ return Object.fromEntries(Object.entries(value)
192
+ .map(([key, entry]) => [key, replaceWorkspaceIdentity(entry, from, to)]));
193
+ }
194
+ export function toolResultAgentsFiles(result) {
195
+ if (typeof result !== "object" || result === null)
196
+ return [];
197
+ const structured = result.structuredContent;
198
+ if (typeof structured !== "object" || structured === null)
199
+ return [];
200
+ const agentsFiles = structured.agentsFiles;
201
+ if (!Array.isArray(agentsFiles))
202
+ return [];
203
+ return agentsFiles.flatMap((entry) => {
204
+ if (typeof entry !== "object" || entry === null)
205
+ return [];
206
+ const path = entry.path;
207
+ const content = entry.content;
208
+ return typeof path === "string" && typeof content === "string" ? [{ path, content }] : [];
209
+ });
210
+ }
@@ -0,0 +1,9 @@
1
+ import { readFileSync } from "node:fs";
2
+ export const FORGERELAY_VERSION = readForgeRelayVersion();
3
+ function readForgeRelayVersion() {
4
+ const packageJson = JSON.parse(readFileSync(new URL("../../../../package.json", import.meta.url), "utf8"));
5
+ if (typeof packageJson.version !== "string" || packageJson.version.length === 0) {
6
+ throw new Error("Unable to read ForgeRelay package version.");
7
+ }
8
+ return packageJson.version;
9
+ }