@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,283 @@
1
+ import { existsSync, readdirSync, readFileSync, statSync, } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { basename, dirname, extname, join, resolve, sep } from "node:path";
4
+ import { parse as parseYaml } from "yaml";
5
+ import { markAdvertisedFileSourceActivated, resolveAdvertisedFileReadPath, } from "../../mcp/filesystem/advertised-files.js";
6
+ import { expandHomePath, isPathInsideRoot } from "../../mcp/filesystem/roots.js";
7
+ const FRONTMATTER_DELIMITER = "---";
8
+ export function effectiveSkillPaths(config, cwd) {
9
+ const defaultPathCandidates = [
10
+ join(homedir(), ".agents", "skills"),
11
+ resolve(cwd, ".agents", "skills"),
12
+ config.configSkillsDir,
13
+ join(config.agentDir, "skills"),
14
+ ];
15
+ const defaultPaths = defaultPathCandidates.filter((path) => path !== undefined && existsSync(path));
16
+ const seen = new Set();
17
+ return [...defaultPaths, ...config.skillPaths]
18
+ .map((path) => resolveSkillPath(path, cwd))
19
+ .filter((path) => {
20
+ if (seen.has(path))
21
+ return false;
22
+ seen.add(path);
23
+ return true;
24
+ });
25
+ }
26
+ function resolveSkillPath(path, cwd) {
27
+ return resolve(cwd, expandHomePath(path));
28
+ }
29
+ export function loadWorkspaceSkills(config, cwd) {
30
+ if (!config.skillsEnabled)
31
+ return { skills: [], diagnostics: [] };
32
+ const skills = [];
33
+ const diagnostics = [];
34
+ const winners = new Map();
35
+ for (const sourcePath of effectiveSkillPaths(config, cwd)) {
36
+ const candidates = discoverSkills(sourcePath, diagnostics);
37
+ for (const skill of candidates) {
38
+ const existing = winners.get(skill.name);
39
+ if (existing) {
40
+ diagnostics.push({
41
+ type: "collision",
42
+ message: `Skill '${skill.name}' from ${skill.filePath} was ignored because ${existing.skill.filePath} was loaded first.`,
43
+ collision: {
44
+ resourceType: "skill",
45
+ name: skill.name,
46
+ winnerPath: existing.skill.filePath,
47
+ loserPath: skill.filePath,
48
+ winnerSource: existing.source,
49
+ loserSource: sourcePath,
50
+ },
51
+ });
52
+ continue;
53
+ }
54
+ winners.set(skill.name, { skill, source: sourcePath });
55
+ skills.push(skill);
56
+ }
57
+ }
58
+ if (config.subagents)
59
+ return { skills, diagnostics };
60
+ return { skills, diagnostics };
61
+ }
62
+ function discoverSkills(sourcePath, diagnostics) {
63
+ if (!existsSync(sourcePath))
64
+ return [];
65
+ let stats;
66
+ try {
67
+ stats = statSync(sourcePath);
68
+ }
69
+ catch (error) {
70
+ diagnostics.push({
71
+ type: "warning",
72
+ message: `Unable to inspect skill path ${sourcePath}: ${errorMessage(error)}`,
73
+ path: sourcePath,
74
+ });
75
+ return [];
76
+ }
77
+ if (stats.isFile()) {
78
+ const skill = loadSkillFile(sourcePath, diagnostics);
79
+ return skill ? [skill] : [];
80
+ }
81
+ if (!stats.isDirectory())
82
+ return [];
83
+ const entry = join(sourcePath, "SKILL.md");
84
+ if (existsSync(entry)) {
85
+ const skill = loadSkillFile(entry, diagnostics);
86
+ return skill ? [skill] : [];
87
+ }
88
+ const skills = [];
89
+ for (const entryName of sortedDirectoryEntries(sourcePath, diagnostics)) {
90
+ const child = join(sourcePath, entryName);
91
+ let childStats;
92
+ try {
93
+ childStats = statSync(child);
94
+ }
95
+ catch (error) {
96
+ diagnostics.push({
97
+ type: "warning",
98
+ message: `Unable to inspect skill candidate ${child}: ${errorMessage(error)}`,
99
+ path: child,
100
+ });
101
+ continue;
102
+ }
103
+ if (childStats.isDirectory()) {
104
+ skills.push(...discoverSkills(child, diagnostics));
105
+ continue;
106
+ }
107
+ if (childStats.isFile() && extname(entryName).toLowerCase() === ".md") {
108
+ const skill = loadSkillFile(child, diagnostics);
109
+ if (skill)
110
+ skills.push(skill);
111
+ }
112
+ }
113
+ return skills;
114
+ }
115
+ function sortedDirectoryEntries(path, diagnostics) {
116
+ try {
117
+ return readdirSync(path).sort((left, right) => left.localeCompare(right));
118
+ }
119
+ catch (error) {
120
+ diagnostics.push({
121
+ type: "warning",
122
+ message: `Unable to read skill directory ${path}: ${errorMessage(error)}`,
123
+ path,
124
+ });
125
+ return [];
126
+ }
127
+ }
128
+ function loadSkillFile(filePath, diagnostics) {
129
+ let content;
130
+ try {
131
+ content = readFileSync(filePath, "utf8");
132
+ }
133
+ catch (error) {
134
+ diagnostics.push({
135
+ type: "warning",
136
+ message: `Unable to read skill file ${filePath}: ${errorMessage(error)}`,
137
+ path: filePath,
138
+ });
139
+ return undefined;
140
+ }
141
+ let frontmatter = {};
142
+ try {
143
+ frontmatter = parseSkillFrontmatter(content);
144
+ }
145
+ catch (error) {
146
+ diagnostics.push({
147
+ type: "error",
148
+ message: `Invalid skill frontmatter in ${filePath}: ${errorMessage(error)}`,
149
+ path: filePath,
150
+ });
151
+ return undefined;
152
+ }
153
+ const baseDir = dirname(filePath);
154
+ const summary = skillSummaryFromFrontmatter(frontmatter, filePath);
155
+ if (!summary.name) {
156
+ diagnostics.push({
157
+ type: "error",
158
+ message: `Skill ${filePath} has an invalid or empty name.`,
159
+ path: filePath,
160
+ });
161
+ return undefined;
162
+ }
163
+ return {
164
+ ...summary,
165
+ filePath: resolve(filePath),
166
+ baseDir: resolve(baseDir),
167
+ };
168
+ }
169
+ export function skillSummaryFromContent(content, filePath) {
170
+ return skillSummaryFromFrontmatter(parseSkillFrontmatter(content), filePath);
171
+ }
172
+ function skillSummaryFromFrontmatter(frontmatter, filePath) {
173
+ return {
174
+ name: normalizedSkillName(frontmatter.name, filePath),
175
+ description: typeof frontmatter.description === "string" ? frontmatter.description.trim() : "",
176
+ disableModelInvocation: frontmatter["disable-model-invocation"] === true,
177
+ };
178
+ }
179
+ function parseSkillFrontmatter(content) {
180
+ const lines = content.replace(/^\uFEFF/, "").split(/\r?\n/);
181
+ if (lines[0]?.trim() !== FRONTMATTER_DELIMITER)
182
+ return {};
183
+ const end = lines.findIndex((line, index) => index > 0 && line.trim() === FRONTMATTER_DELIMITER);
184
+ if (end < 0)
185
+ throw new Error("opening '---' is missing a closing delimiter");
186
+ const parsed = parseYaml(lines.slice(1, end).join("\n"));
187
+ if (parsed === null || parsed === undefined)
188
+ return {};
189
+ if (typeof parsed !== "object" || Array.isArray(parsed)) {
190
+ throw new Error("frontmatter must be a YAML mapping");
191
+ }
192
+ return parsed;
193
+ }
194
+ function normalizedSkillName(value, filePath) {
195
+ const explicit = typeof value === "string" ? value.trim() : "";
196
+ if (explicit)
197
+ return explicit;
198
+ if (basename(filePath).toLowerCase() === "skill.md")
199
+ return basename(dirname(filePath)).trim();
200
+ return basename(filePath, extname(filePath)).trim();
201
+ }
202
+ function errorMessage(error) {
203
+ return error instanceof Error ? error.message : String(error);
204
+ }
205
+ export function resolveSkillReadPath(skills, activatedSkillDirs, inputPath) {
206
+ const virtualRead = resolveVirtualSkillReadPath(skills, activatedSkillDirs, inputPath);
207
+ if (virtualRead)
208
+ return virtualRead;
209
+ const resolution = resolveAdvertisedFileReadPath(skills, activatedSkillDirs, inputPath);
210
+ if (!resolution)
211
+ return undefined;
212
+ return {
213
+ absolutePath: resolution.absolutePath,
214
+ skill: resolution.source,
215
+ isSkillFile: resolution.isEntryFile,
216
+ };
217
+ }
218
+ function resolveVirtualSkillReadPath(skills, activatedSkillDirs, inputPath) {
219
+ const prefix = "skills://";
220
+ if (!inputPath.startsWith(prefix))
221
+ return undefined;
222
+ const requested = inputPath.slice(prefix.length);
223
+ const slashIndex = requested.indexOf("/");
224
+ const encodedName = slashIndex === -1 ? requested : requested.slice(0, slashIndex);
225
+ if (!encodedName)
226
+ throw new Error(`Invalid skill URI: ${inputPath}`);
227
+ let name;
228
+ try {
229
+ name = decodeURIComponent(encodedName);
230
+ }
231
+ catch {
232
+ throw new Error(`Invalid skill URI: ${inputPath}`);
233
+ }
234
+ const skill = skills.find((candidate) => candidate.name === name);
235
+ if (!skill)
236
+ throw new Error(`Unknown advertised skill: ${name}`);
237
+ if (slashIndex === -1 || slashIndex === requested.length - 1) {
238
+ return {
239
+ absolutePath: resolve(skill.filePath),
240
+ skill,
241
+ isSkillFile: true,
242
+ };
243
+ }
244
+ const relativePart = requested.slice(slashIndex + 1);
245
+ const segments = relativePart.split("/").map((segment) => {
246
+ let decoded;
247
+ try {
248
+ decoded = decodeURIComponent(segment);
249
+ }
250
+ catch {
251
+ throw new Error(`Invalid skill URI: ${inputPath}`);
252
+ }
253
+ if (!decoded || decoded === "." || decoded === ".." || decoded.includes("/") || decoded.includes("\\")) {
254
+ throw new Error(`Invalid skill URI: ${inputPath}`);
255
+ }
256
+ return decoded;
257
+ });
258
+ const baseDir = resolve(skill.baseDir);
259
+ if (!activatedSkillDirs.has(baseDir))
260
+ return undefined;
261
+ const absolutePath = resolve(baseDir, ...segments);
262
+ if (!isPathInsideRoot(absolutePath, baseDir)) {
263
+ throw new Error(`Skill resource is outside its skill directory: ${inputPath}`);
264
+ }
265
+ return {
266
+ absolutePath,
267
+ skill,
268
+ isSkillFile: false,
269
+ };
270
+ }
271
+ export function markSkillActivated(activatedSkillDirs, skill) {
272
+ markAdvertisedFileSourceActivated(activatedSkillDirs, skill);
273
+ }
274
+ export function formatPathForPrompt(path) {
275
+ const home = resolve(homedir());
276
+ const resolvedPath = resolve(path);
277
+ if (resolvedPath === home)
278
+ return "~";
279
+ if (resolvedPath.startsWith(`${home}${sep}`)) {
280
+ return `~/${resolvedPath.slice(home.length + 1).split(sep).join("/")}`;
281
+ }
282
+ return resolvedPath.split(sep).join("/");
283
+ }
@@ -1,8 +1,8 @@
1
1
  import { mkdtemp, rm } from "node:fs/promises";
2
2
  import { tmpdir } from "node:os";
3
3
  import { join } from "node:path";
4
- import { git, getGitEligibility, safeWorkspaceRefSegment } from "./git.js";
5
- const REVIEW_REF_PREFIX = "refs/devspace/review";
4
+ import { git, getGitEligibility, safeWorkspaceRefSegment } from "../git/git.js";
5
+ const REVIEW_REF_PREFIX = "refs/forgerelay/review";
6
6
  const DEFAULT_MAX_REVIEW_WORKSPACE_STATES = 128;
7
7
  export function createReviewCheckpointManager(options = {}) {
8
8
  const maxWorkspaceStates = options.maxWorkspaceStates ?? DEFAULT_MAX_REVIEW_WORKSPACE_STATES;