@xyagent/cli 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (385) hide show
  1. package/README.md +860 -0
  2. package/bin/agentlink +8585 -0
  3. package/bin/agentlink-agent +7 -0
  4. package/bin/agentlink-mcp-stdio +173 -0
  5. package/docs/LOGGING.md +159 -0
  6. package/package.json +38 -0
  7. package/src/core.mjs +320 -0
  8. package/src/tunnel.mjs +291 -0
  9. package/src/tunnel_proxy.mjs +913 -0
  10. package/src/tunnel_service.mjs +699 -0
  11. package/src/tunnel_state.mjs +301 -0
  12. package/src/unified_producer.mjs +259 -0
  13. package/src-ext/README.md +75 -0
  14. package/src-ext/bin.mjs +128 -0
  15. package/src-ext/commands/agent.mjs +66 -0
  16. package/src-ext/commands/help.mjs +31 -0
  17. package/src-ext/commands/pair.mjs +455 -0
  18. package/src-ext/commands/reload.mjs +78 -0
  19. package/src-ext/commands/service.mjs +64 -0
  20. package/src-ext/core/accountResolver.mjs +137 -0
  21. package/src-ext/core/activeRuns.mjs +76 -0
  22. package/src-ext/core/agentlinkToolsBootstrap.mjs +75 -0
  23. package/src-ext/core/agentlinkToolsRegistry.mjs +323 -0
  24. package/src-ext/core/agentlinkToolsServer.mjs +109 -0
  25. package/src-ext/core/approvalGateway.mjs +132 -0
  26. package/src-ext/core/attachAuditLog.mjs +79 -0
  27. package/src-ext/core/attachDenylist.mjs +128 -0
  28. package/src-ext/core/autoTunnelDetector.mjs +98 -0
  29. package/src-ext/core/autoTunnelGateway.mjs +393 -0
  30. package/src-ext/core/autoTunnelWiring.mjs +184 -0
  31. package/src-ext/core/boundedMap.mjs +98 -0
  32. package/src-ext/core/bridgeAttachAutoScanner.mjs +237 -0
  33. package/src-ext/core/bridgeHooks.mjs +168 -0
  34. package/src-ext/core/bridgeSelfUninstall.mjs +133 -0
  35. package/src-ext/core/claudeTrust.mjs +74 -0
  36. package/src-ext/core/codexTrust.mjs +77 -0
  37. package/src-ext/core/cosUploadClient.mjs +326 -0
  38. package/src-ext/core/createWorkspace.mjs +170 -0
  39. package/src-ext/core/daemonRestart.mjs +49 -0
  40. package/src-ext/core/defaultWorkspace.mjs +65 -0
  41. package/src-ext/core/ensureGitRepo.mjs +57 -0
  42. package/src-ext/core/hermesProfile.mjs +75 -0
  43. package/src-ext/core/interruptGateway.mjs +119 -0
  44. package/src-ext/core/interruptRunListener.mjs +106 -0
  45. package/src-ext/core/mcpRuntimeFanout.mjs +236 -0
  46. package/src-ext/core/mcpStdioClient.mjs +316 -0
  47. package/src-ext/core/openclawGatewayClient.mjs +230 -0
  48. package/src-ext/core/pairCodeClient.mjs +331 -0
  49. package/src-ext/core/pairInventory.mjs +59 -0
  50. package/src-ext/core/pathExpand.mjs +34 -0
  51. package/src-ext/core/preprocessAttachments.mjs +113 -0
  52. package/src-ext/core/relayWorker.mjs +284 -0
  53. package/src-ext/core/relayWorkerHttp.mjs +58 -0
  54. package/src-ext/core/scanWorkspaces.mjs +842 -0
  55. package/src-ext/core/sessionSlot.mjs +70 -0
  56. package/src-ext/core/stateMachine.mjs +85 -0
  57. package/src-ext/core/toolsServerLifecycle.mjs +169 -0
  58. package/src-ext/core/unifiedDispatchHandler.mjs +439 -0
  59. package/src-ext/core/usageReporter.mjs +207 -0
  60. package/src-ext/openclaw-plugin/envelope-builder.cjs +619 -0
  61. package/src-ext/openclaw-plugin/index.cjs +1919 -0
  62. package/src-ext/openclaw-plugin/openclaw.plugin.json +20 -0
  63. package/src-ext/openclaw-plugin/package.json +12 -0
  64. package/src-ext/openclaw-plugin/relay-defaults.json +3 -0
  65. package/src-ext/openclaw-plugin/todoTranslatorUtils.cjs +101 -0
  66. package/src-ext/runtime/_shared/cliExec.mjs +138 -0
  67. package/src-ext/runtime/_shared/cosTextRefs.mjs +120 -0
  68. package/src-ext/runtime/_shared/fetchAndBase64Encode.mjs +52 -0
  69. package/src-ext/runtime/_shared/relayObjectToBlock.mjs +307 -0
  70. package/src-ext/runtime/_shared/sessionPicker.mjs +418 -0
  71. package/src-ext/runtime/_shared/slashCommandRouter.mjs +1346 -0
  72. package/src-ext/runtime/_shared/todoTranslatorUtils.mjs +94 -0
  73. package/src-ext/runtime/claude/askUserQuestionTranslator.mjs +241 -0
  74. package/src-ext/runtime/claude/customCommandsCollector.mjs +132 -0
  75. package/src-ext/runtime/claude/handleRequest.mjs +1418 -0
  76. package/src-ext/runtime/claude/index.mjs +160 -0
  77. package/src-ext/runtime/claude/internalCommandNames.mjs +58 -0
  78. package/src-ext/runtime/claude/launcher.mjs +313 -0
  79. package/src-ext/runtime/claude/mcpConfigAdapter.mjs +174 -0
  80. package/src-ext/runtime/claude/mcpConfigWriter.mjs +57 -0
  81. package/src-ext/runtime/claude/modelContextWindow.mjs +30 -0
  82. package/src-ext/runtime/claude/modelScanner.mjs +257 -0
  83. package/src-ext/runtime/claude/permissionInterruptBlock.mjs +86 -0
  84. package/src-ext/runtime/claude/permissionPromptServer.mjs +170 -0
  85. package/src-ext/runtime/claude/permissionPromptServerWorker.mjs +214 -0
  86. package/src-ext/runtime/claude/preflight.mjs +62 -0
  87. package/src-ext/runtime/claude/stdoutParser.mjs +365 -0
  88. package/src-ext/runtime/claude/todoTranslator.mjs +66 -0
  89. package/src-ext/runtime/claude/usageProbe.mjs +576 -0
  90. package/src-ext/runtime/claude/usageProbeStrip.mjs +14 -0
  91. package/src-ext/runtime/codex/codexCustomCommandsCollector.mjs +87 -0
  92. package/src-ext/runtime/codex/elicitationHandler.mjs +91 -0
  93. package/src-ext/runtime/codex/eventMapper.mjs +154 -0
  94. package/src-ext/runtime/codex/handleRequest.mjs +1152 -0
  95. package/src-ext/runtime/codex/index.mjs +142 -0
  96. package/src-ext/runtime/codex/mcpConfigAdapter.mjs +155 -0
  97. package/src-ext/runtime/codex/modelScanner.mjs +305 -0
  98. package/src-ext/runtime/codex/planNotificationHandler.mjs +61 -0
  99. package/src-ext/runtime/codex/preflight.mjs +67 -0
  100. package/src-ext/runtime/hermes/commandBackend.mjs +117 -0
  101. package/src-ext/runtime/hermes/envSetup.mjs +229 -0
  102. package/src-ext/runtime/hermes/gatewayManager.mjs +625 -0
  103. package/src-ext/runtime/hermes/handleRequest.mjs +1257 -0
  104. package/src-ext/runtime/hermes/httpBackend.mjs +219 -0
  105. package/src-ext/runtime/hermes/index.mjs +196 -0
  106. package/src-ext/runtime/hermes/mcpConfigAdapter.mjs +189 -0
  107. package/src-ext/runtime/hermes/preflight.mjs +359 -0
  108. package/src-ext/runtime/hermes/responsesBackend.mjs +276 -0
  109. package/src-ext/runtime/hermes/sessionStore.mjs +78 -0
  110. package/src-ext/runtime/hermes/todoTranslator.mjs +90 -0
  111. package/src-ext/runtime/hermes/workspaceRpc.mjs +124 -0
  112. package/src-ext/runtime/openclaw/buildOpenclawDaemonInput.mjs +143 -0
  113. package/src-ext/runtime/openclaw/mcpConfigAdapter.mjs +91 -0
  114. package/src-ext/runtime/openclaw/openclawConfig.mjs +145 -0
  115. package/src-ext/runtime/picoclaw/constants.mjs +39 -0
  116. package/src-ext/runtime/picoclaw/handleRequest.mjs +289 -0
  117. package/src-ext/runtime/picoclaw/index.mjs +314 -0
  118. package/src-ext/runtime/picoclaw/pairFlow.mjs +224 -0
  119. package/src-ext/runtime/picoclaw/state.mjs +78 -0
  120. package/src-ext/runtime/picoclaw/todoTranslator.mjs +67 -0
  121. package/src-ext/runtime/picoclaw/translator.mjs +272 -0
  122. package/src-ext/runtime/picoclaw/wsClient.mjs +129 -0
  123. package/src-ext/service/serviceManager.mjs +521 -0
  124. package/src-shared/README.md +44 -0
  125. package/src-shared/chat_push_normalizer.mjs +113 -0
  126. package/src-shared/correlation.mjs +25 -0
  127. package/src-shared/envelope_builder.mjs +612 -0
  128. package/src-shared/logger.mjs +167 -0
  129. package/src-shared/relay-defaults.json +3 -0
  130. package/src-shared/relay_revoke.mjs +46 -0
  131. package/src-shared/vendor/README.md +60 -0
  132. package/src-shared/vendor/smol-toml/LICENSE +24 -0
  133. package/src-shared/vendor/smol-toml/README.md +236 -0
  134. package/src-shared/vendor/smol-toml/VENDORED.md +37 -0
  135. package/src-shared/vendor/smol-toml/dist/date.d.ts +41 -0
  136. package/src-shared/vendor/smol-toml/dist/date.js +127 -0
  137. package/src-shared/vendor/smol-toml/dist/error.d.ts +38 -0
  138. package/src-shared/vendor/smol-toml/dist/error.js +63 -0
  139. package/src-shared/vendor/smol-toml/dist/extract.d.ts +30 -0
  140. package/src-shared/vendor/smol-toml/dist/extract.js +109 -0
  141. package/src-shared/vendor/smol-toml/dist/index.cjs +900 -0
  142. package/src-shared/vendor/smol-toml/dist/index.d.ts +43 -0
  143. package/src-shared/vendor/smol-toml/dist/index.js +33 -0
  144. package/src-shared/vendor/smol-toml/dist/parse.d.ts +37 -0
  145. package/src-shared/vendor/smol-toml/dist/parse.js +148 -0
  146. package/src-shared/vendor/smol-toml/dist/primitive.d.ts +31 -0
  147. package/src-shared/vendor/smol-toml/dist/primitive.js +178 -0
  148. package/src-shared/vendor/smol-toml/dist/stringify.d.ts +31 -0
  149. package/src-shared/vendor/smol-toml/dist/stringify.js +163 -0
  150. package/src-shared/vendor/smol-toml/dist/struct.d.ts +32 -0
  151. package/src-shared/vendor/smol-toml/dist/struct.js +194 -0
  152. package/src-shared/vendor/smol-toml/dist/util.d.ts +42 -0
  153. package/src-shared/vendor/smol-toml/dist/util.js +100 -0
  154. package/src-shared/vendor/smol-toml/package.json +54 -0
  155. package/src-shared/vendor/yaml/LICENSE +13 -0
  156. package/src-shared/vendor/yaml/README.md +155 -0
  157. package/src-shared/vendor/yaml/VENDORED.md +29 -0
  158. package/src-shared/vendor/yaml/bin.mjs +11 -0
  159. package/src-shared/vendor/yaml/browser/dist/compose/compose-collection.js +88 -0
  160. package/src-shared/vendor/yaml/browser/dist/compose/compose-doc.js +42 -0
  161. package/src-shared/vendor/yaml/browser/dist/compose/compose-node.js +92 -0
  162. package/src-shared/vendor/yaml/browser/dist/compose/compose-scalar.js +80 -0
  163. package/src-shared/vendor/yaml/browser/dist/compose/composer.js +217 -0
  164. package/src-shared/vendor/yaml/browser/dist/compose/resolve-block-map.js +113 -0
  165. package/src-shared/vendor/yaml/browser/dist/compose/resolve-block-scalar.js +198 -0
  166. package/src-shared/vendor/yaml/browser/dist/compose/resolve-block-seq.js +47 -0
  167. package/src-shared/vendor/yaml/browser/dist/compose/resolve-end.js +37 -0
  168. package/src-shared/vendor/yaml/browser/dist/compose/resolve-flow-collection.js +203 -0
  169. package/src-shared/vendor/yaml/browser/dist/compose/resolve-flow-scalar.js +223 -0
  170. package/src-shared/vendor/yaml/browser/dist/compose/resolve-props.js +148 -0
  171. package/src-shared/vendor/yaml/browser/dist/compose/util-contains-newline.js +34 -0
  172. package/src-shared/vendor/yaml/browser/dist/compose/util-empty-scalar-position.js +27 -0
  173. package/src-shared/vendor/yaml/browser/dist/compose/util-flow-indent-check.js +15 -0
  174. package/src-shared/vendor/yaml/browser/dist/compose/util-map-includes.js +17 -0
  175. package/src-shared/vendor/yaml/browser/dist/doc/Document.js +334 -0
  176. package/src-shared/vendor/yaml/browser/dist/doc/anchors.js +72 -0
  177. package/src-shared/vendor/yaml/browser/dist/doc/applyReviver.js +55 -0
  178. package/src-shared/vendor/yaml/browser/dist/doc/createNode.js +89 -0
  179. package/src-shared/vendor/yaml/browser/dist/doc/directives.js +176 -0
  180. package/src-shared/vendor/yaml/browser/dist/errors.js +57 -0
  181. package/src-shared/vendor/yaml/browser/dist/index.js +17 -0
  182. package/src-shared/vendor/yaml/browser/dist/log.js +14 -0
  183. package/src-shared/vendor/yaml/browser/dist/nodes/Alias.js +101 -0
  184. package/src-shared/vendor/yaml/browser/dist/nodes/Collection.js +147 -0
  185. package/src-shared/vendor/yaml/browser/dist/nodes/Node.js +38 -0
  186. package/src-shared/vendor/yaml/browser/dist/nodes/Pair.js +36 -0
  187. package/src-shared/vendor/yaml/browser/dist/nodes/Scalar.js +24 -0
  188. package/src-shared/vendor/yaml/browser/dist/nodes/YAMLMap.js +144 -0
  189. package/src-shared/vendor/yaml/browser/dist/nodes/YAMLSeq.js +113 -0
  190. package/src-shared/vendor/yaml/browser/dist/nodes/addPairToJSMap.js +104 -0
  191. package/src-shared/vendor/yaml/browser/dist/nodes/identity.js +36 -0
  192. package/src-shared/vendor/yaml/browser/dist/nodes/toJS.js +37 -0
  193. package/src-shared/vendor/yaml/browser/dist/parse/cst-scalar.js +214 -0
  194. package/src-shared/vendor/yaml/browser/dist/parse/cst-stringify.js +61 -0
  195. package/src-shared/vendor/yaml/browser/dist/parse/cst-visit.js +97 -0
  196. package/src-shared/vendor/yaml/browser/dist/parse/cst.js +98 -0
  197. package/src-shared/vendor/yaml/browser/dist/parse/lexer.js +717 -0
  198. package/src-shared/vendor/yaml/browser/dist/parse/line-counter.js +39 -0
  199. package/src-shared/vendor/yaml/browser/dist/parse/parser.js +954 -0
  200. package/src-shared/vendor/yaml/browser/dist/public-api.js +99 -0
  201. package/src-shared/vendor/yaml/browser/dist/schema/Schema.js +38 -0
  202. package/src-shared/vendor/yaml/browser/dist/schema/common/map.js +17 -0
  203. package/src-shared/vendor/yaml/browser/dist/schema/common/null.js +15 -0
  204. package/src-shared/vendor/yaml/browser/dist/schema/common/seq.js +17 -0
  205. package/src-shared/vendor/yaml/browser/dist/schema/common/string.js +14 -0
  206. package/src-shared/vendor/yaml/browser/dist/schema/core/bool.js +19 -0
  207. package/src-shared/vendor/yaml/browser/dist/schema/core/float.js +43 -0
  208. package/src-shared/vendor/yaml/browser/dist/schema/core/int.js +38 -0
  209. package/src-shared/vendor/yaml/browser/dist/schema/core/schema.js +23 -0
  210. package/src-shared/vendor/yaml/browser/dist/schema/json/schema.js +62 -0
  211. package/src-shared/vendor/yaml/browser/dist/schema/tags.js +83 -0
  212. package/src-shared/vendor/yaml/browser/dist/schema/yaml-1.1/binary.js +66 -0
  213. package/src-shared/vendor/yaml/browser/dist/schema/yaml-1.1/bool.js +26 -0
  214. package/src-shared/vendor/yaml/browser/dist/schema/yaml-1.1/float.js +46 -0
  215. package/src-shared/vendor/yaml/browser/dist/schema/yaml-1.1/int.js +71 -0
  216. package/src-shared/vendor/yaml/browser/dist/schema/yaml-1.1/omap.js +74 -0
  217. package/src-shared/vendor/yaml/browser/dist/schema/yaml-1.1/pairs.js +78 -0
  218. package/src-shared/vendor/yaml/browser/dist/schema/yaml-1.1/schema.js +37 -0
  219. package/src-shared/vendor/yaml/browser/dist/schema/yaml-1.1/set.js +93 -0
  220. package/src-shared/vendor/yaml/browser/dist/schema/yaml-1.1/timestamp.js +101 -0
  221. package/src-shared/vendor/yaml/browser/dist/stringify/foldFlowLines.js +146 -0
  222. package/src-shared/vendor/yaml/browser/dist/stringify/stringify.js +124 -0
  223. package/src-shared/vendor/yaml/browser/dist/stringify/stringifyCollection.js +143 -0
  224. package/src-shared/vendor/yaml/browser/dist/stringify/stringifyComment.js +20 -0
  225. package/src-shared/vendor/yaml/browser/dist/stringify/stringifyDocument.js +85 -0
  226. package/src-shared/vendor/yaml/browser/dist/stringify/stringifyNumber.js +24 -0
  227. package/src-shared/vendor/yaml/browser/dist/stringify/stringifyPair.js +150 -0
  228. package/src-shared/vendor/yaml/browser/dist/stringify/stringifyString.js +328 -0
  229. package/src-shared/vendor/yaml/browser/dist/util.js +11 -0
  230. package/src-shared/vendor/yaml/browser/dist/visit.js +233 -0
  231. package/src-shared/vendor/yaml/browser/index.js +5 -0
  232. package/src-shared/vendor/yaml/browser/package.json +3 -0
  233. package/src-shared/vendor/yaml/dist/cli.d.ts +8 -0
  234. package/src-shared/vendor/yaml/dist/cli.mjs +199 -0
  235. package/src-shared/vendor/yaml/dist/compose/compose-collection.d.ts +11 -0
  236. package/src-shared/vendor/yaml/dist/compose/compose-collection.js +90 -0
  237. package/src-shared/vendor/yaml/dist/compose/compose-doc.d.ts +7 -0
  238. package/src-shared/vendor/yaml/dist/compose/compose-doc.js +44 -0
  239. package/src-shared/vendor/yaml/dist/compose/compose-node.d.ts +28 -0
  240. package/src-shared/vendor/yaml/dist/compose/compose-node.js +95 -0
  241. package/src-shared/vendor/yaml/dist/compose/compose-scalar.d.ts +5 -0
  242. package/src-shared/vendor/yaml/dist/compose/compose-scalar.js +82 -0
  243. package/src-shared/vendor/yaml/dist/compose/composer.d.ts +62 -0
  244. package/src-shared/vendor/yaml/dist/compose/composer.js +221 -0
  245. package/src-shared/vendor/yaml/dist/compose/resolve-block-map.d.ts +6 -0
  246. package/src-shared/vendor/yaml/dist/compose/resolve-block-map.js +115 -0
  247. package/src-shared/vendor/yaml/dist/compose/resolve-block-scalar.d.ts +11 -0
  248. package/src-shared/vendor/yaml/dist/compose/resolve-block-scalar.js +200 -0
  249. package/src-shared/vendor/yaml/dist/compose/resolve-block-seq.d.ts +6 -0
  250. package/src-shared/vendor/yaml/dist/compose/resolve-block-seq.js +49 -0
  251. package/src-shared/vendor/yaml/dist/compose/resolve-end.d.ts +6 -0
  252. package/src-shared/vendor/yaml/dist/compose/resolve-end.js +39 -0
  253. package/src-shared/vendor/yaml/dist/compose/resolve-flow-collection.d.ts +7 -0
  254. package/src-shared/vendor/yaml/dist/compose/resolve-flow-collection.js +205 -0
  255. package/src-shared/vendor/yaml/dist/compose/resolve-flow-scalar.d.ts +10 -0
  256. package/src-shared/vendor/yaml/dist/compose/resolve-flow-scalar.js +225 -0
  257. package/src-shared/vendor/yaml/dist/compose/resolve-props.d.ts +23 -0
  258. package/src-shared/vendor/yaml/dist/compose/resolve-props.js +150 -0
  259. package/src-shared/vendor/yaml/dist/compose/util-contains-newline.d.ts +2 -0
  260. package/src-shared/vendor/yaml/dist/compose/util-contains-newline.js +36 -0
  261. package/src-shared/vendor/yaml/dist/compose/util-empty-scalar-position.d.ts +2 -0
  262. package/src-shared/vendor/yaml/dist/compose/util-empty-scalar-position.js +29 -0
  263. package/src-shared/vendor/yaml/dist/compose/util-flow-indent-check.d.ts +3 -0
  264. package/src-shared/vendor/yaml/dist/compose/util-flow-indent-check.js +17 -0
  265. package/src-shared/vendor/yaml/dist/compose/util-map-includes.d.ts +4 -0
  266. package/src-shared/vendor/yaml/dist/compose/util-map-includes.js +19 -0
  267. package/src-shared/vendor/yaml/dist/doc/Document.d.ts +141 -0
  268. package/src-shared/vendor/yaml/dist/doc/Document.js +336 -0
  269. package/src-shared/vendor/yaml/dist/doc/anchors.d.ts +24 -0
  270. package/src-shared/vendor/yaml/dist/doc/anchors.js +77 -0
  271. package/src-shared/vendor/yaml/dist/doc/applyReviver.d.ts +9 -0
  272. package/src-shared/vendor/yaml/dist/doc/applyReviver.js +57 -0
  273. package/src-shared/vendor/yaml/dist/doc/createNode.d.ts +17 -0
  274. package/src-shared/vendor/yaml/dist/doc/createNode.js +91 -0
  275. package/src-shared/vendor/yaml/dist/doc/directives.d.ts +49 -0
  276. package/src-shared/vendor/yaml/dist/doc/directives.js +178 -0
  277. package/src-shared/vendor/yaml/dist/errors.d.ts +21 -0
  278. package/src-shared/vendor/yaml/dist/errors.js +62 -0
  279. package/src-shared/vendor/yaml/dist/index.d.ts +22 -0
  280. package/src-shared/vendor/yaml/dist/index.js +50 -0
  281. package/src-shared/vendor/yaml/dist/log.d.ts +3 -0
  282. package/src-shared/vendor/yaml/dist/log.js +17 -0
  283. package/src-shared/vendor/yaml/dist/nodes/Alias.d.ts +28 -0
  284. package/src-shared/vendor/yaml/dist/nodes/Alias.js +103 -0
  285. package/src-shared/vendor/yaml/dist/nodes/Collection.d.ts +73 -0
  286. package/src-shared/vendor/yaml/dist/nodes/Collection.js +151 -0
  287. package/src-shared/vendor/yaml/dist/nodes/Node.d.ts +47 -0
  288. package/src-shared/vendor/yaml/dist/nodes/Node.js +40 -0
  289. package/src-shared/vendor/yaml/dist/nodes/Pair.d.ts +21 -0
  290. package/src-shared/vendor/yaml/dist/nodes/Pair.js +39 -0
  291. package/src-shared/vendor/yaml/dist/nodes/Scalar.d.ts +42 -0
  292. package/src-shared/vendor/yaml/dist/nodes/Scalar.js +27 -0
  293. package/src-shared/vendor/yaml/dist/nodes/YAMLMap.d.ts +53 -0
  294. package/src-shared/vendor/yaml/dist/nodes/YAMLMap.js +147 -0
  295. package/src-shared/vendor/yaml/dist/nodes/YAMLSeq.d.ts +60 -0
  296. package/src-shared/vendor/yaml/dist/nodes/YAMLSeq.js +115 -0
  297. package/src-shared/vendor/yaml/dist/nodes/addPairToJSMap.d.ts +4 -0
  298. package/src-shared/vendor/yaml/dist/nodes/addPairToJSMap.js +106 -0
  299. package/src-shared/vendor/yaml/dist/nodes/identity.d.ts +23 -0
  300. package/src-shared/vendor/yaml/dist/nodes/identity.js +53 -0
  301. package/src-shared/vendor/yaml/dist/nodes/toJS.d.ts +27 -0
  302. package/src-shared/vendor/yaml/dist/nodes/toJS.js +39 -0
  303. package/src-shared/vendor/yaml/dist/options.d.ts +338 -0
  304. package/src-shared/vendor/yaml/dist/parse/cst-scalar.d.ts +64 -0
  305. package/src-shared/vendor/yaml/dist/parse/cst-scalar.js +218 -0
  306. package/src-shared/vendor/yaml/dist/parse/cst-stringify.d.ts +8 -0
  307. package/src-shared/vendor/yaml/dist/parse/cst-stringify.js +63 -0
  308. package/src-shared/vendor/yaml/dist/parse/cst-visit.d.ts +39 -0
  309. package/src-shared/vendor/yaml/dist/parse/cst-visit.js +99 -0
  310. package/src-shared/vendor/yaml/dist/parse/cst.d.ts +108 -0
  311. package/src-shared/vendor/yaml/dist/parse/cst.js +112 -0
  312. package/src-shared/vendor/yaml/dist/parse/lexer.d.ts +87 -0
  313. package/src-shared/vendor/yaml/dist/parse/lexer.js +719 -0
  314. package/src-shared/vendor/yaml/dist/parse/line-counter.d.ts +22 -0
  315. package/src-shared/vendor/yaml/dist/parse/line-counter.js +41 -0
  316. package/src-shared/vendor/yaml/dist/parse/parser.d.ts +84 -0
  317. package/src-shared/vendor/yaml/dist/parse/parser.js +958 -0
  318. package/src-shared/vendor/yaml/dist/public-api.d.ts +43 -0
  319. package/src-shared/vendor/yaml/dist/public-api.js +104 -0
  320. package/src-shared/vendor/yaml/dist/schema/Schema.d.ts +18 -0
  321. package/src-shared/vendor/yaml/dist/schema/Schema.js +40 -0
  322. package/src-shared/vendor/yaml/dist/schema/common/map.d.ts +2 -0
  323. package/src-shared/vendor/yaml/dist/schema/common/map.js +19 -0
  324. package/src-shared/vendor/yaml/dist/schema/common/null.d.ts +4 -0
  325. package/src-shared/vendor/yaml/dist/schema/common/null.js +17 -0
  326. package/src-shared/vendor/yaml/dist/schema/common/seq.d.ts +2 -0
  327. package/src-shared/vendor/yaml/dist/schema/common/seq.js +19 -0
  328. package/src-shared/vendor/yaml/dist/schema/common/string.d.ts +2 -0
  329. package/src-shared/vendor/yaml/dist/schema/common/string.js +16 -0
  330. package/src-shared/vendor/yaml/dist/schema/core/bool.d.ts +4 -0
  331. package/src-shared/vendor/yaml/dist/schema/core/bool.js +21 -0
  332. package/src-shared/vendor/yaml/dist/schema/core/float.d.ts +4 -0
  333. package/src-shared/vendor/yaml/dist/schema/core/float.js +47 -0
  334. package/src-shared/vendor/yaml/dist/schema/core/int.d.ts +4 -0
  335. package/src-shared/vendor/yaml/dist/schema/core/int.js +42 -0
  336. package/src-shared/vendor/yaml/dist/schema/core/schema.d.ts +1 -0
  337. package/src-shared/vendor/yaml/dist/schema/core/schema.js +25 -0
  338. package/src-shared/vendor/yaml/dist/schema/json/schema.d.ts +2 -0
  339. package/src-shared/vendor/yaml/dist/schema/json/schema.js +64 -0
  340. package/src-shared/vendor/yaml/dist/schema/json-schema.d.ts +69 -0
  341. package/src-shared/vendor/yaml/dist/schema/tags.d.ts +40 -0
  342. package/src-shared/vendor/yaml/dist/schema/tags.js +86 -0
  343. package/src-shared/vendor/yaml/dist/schema/types.d.ts +90 -0
  344. package/src-shared/vendor/yaml/dist/schema/yaml-1.1/binary.d.ts +2 -0
  345. package/src-shared/vendor/yaml/dist/schema/yaml-1.1/binary.js +68 -0
  346. package/src-shared/vendor/yaml/dist/schema/yaml-1.1/bool.d.ts +7 -0
  347. package/src-shared/vendor/yaml/dist/schema/yaml-1.1/bool.js +29 -0
  348. package/src-shared/vendor/yaml/dist/schema/yaml-1.1/float.d.ts +4 -0
  349. package/src-shared/vendor/yaml/dist/schema/yaml-1.1/float.js +50 -0
  350. package/src-shared/vendor/yaml/dist/schema/yaml-1.1/int.d.ts +5 -0
  351. package/src-shared/vendor/yaml/dist/schema/yaml-1.1/int.js +76 -0
  352. package/src-shared/vendor/yaml/dist/schema/yaml-1.1/omap.d.ts +28 -0
  353. package/src-shared/vendor/yaml/dist/schema/yaml-1.1/omap.js +77 -0
  354. package/src-shared/vendor/yaml/dist/schema/yaml-1.1/pairs.d.ts +10 -0
  355. package/src-shared/vendor/yaml/dist/schema/yaml-1.1/pairs.js +82 -0
  356. package/src-shared/vendor/yaml/dist/schema/yaml-1.1/schema.d.ts +1 -0
  357. package/src-shared/vendor/yaml/dist/schema/yaml-1.1/schema.js +39 -0
  358. package/src-shared/vendor/yaml/dist/schema/yaml-1.1/set.d.ts +28 -0
  359. package/src-shared/vendor/yaml/dist/schema/yaml-1.1/set.js +96 -0
  360. package/src-shared/vendor/yaml/dist/schema/yaml-1.1/timestamp.d.ts +6 -0
  361. package/src-shared/vendor/yaml/dist/schema/yaml-1.1/timestamp.js +105 -0
  362. package/src-shared/vendor/yaml/dist/stringify/foldFlowLines.d.ts +34 -0
  363. package/src-shared/vendor/yaml/dist/stringify/foldFlowLines.js +151 -0
  364. package/src-shared/vendor/yaml/dist/stringify/stringify.d.ts +21 -0
  365. package/src-shared/vendor/yaml/dist/stringify/stringify.js +127 -0
  366. package/src-shared/vendor/yaml/dist/stringify/stringifyCollection.d.ts +17 -0
  367. package/src-shared/vendor/yaml/dist/stringify/stringifyCollection.js +145 -0
  368. package/src-shared/vendor/yaml/dist/stringify/stringifyComment.d.ts +10 -0
  369. package/src-shared/vendor/yaml/dist/stringify/stringifyComment.js +24 -0
  370. package/src-shared/vendor/yaml/dist/stringify/stringifyDocument.d.ts +4 -0
  371. package/src-shared/vendor/yaml/dist/stringify/stringifyDocument.js +87 -0
  372. package/src-shared/vendor/yaml/dist/stringify/stringifyNumber.d.ts +2 -0
  373. package/src-shared/vendor/yaml/dist/stringify/stringifyNumber.js +26 -0
  374. package/src-shared/vendor/yaml/dist/stringify/stringifyPair.d.ts +3 -0
  375. package/src-shared/vendor/yaml/dist/stringify/stringifyPair.js +152 -0
  376. package/src-shared/vendor/yaml/dist/stringify/stringifyString.d.ts +9 -0
  377. package/src-shared/vendor/yaml/dist/stringify/stringifyString.js +330 -0
  378. package/src-shared/vendor/yaml/dist/test-events.d.ts +4 -0
  379. package/src-shared/vendor/yaml/dist/test-events.js +134 -0
  380. package/src-shared/vendor/yaml/dist/util.d.ts +12 -0
  381. package/src-shared/vendor/yaml/dist/util.js +28 -0
  382. package/src-shared/vendor/yaml/dist/visit.d.ts +102 -0
  383. package/src-shared/vendor/yaml/dist/visit.js +236 -0
  384. package/src-shared/vendor/yaml/package.json +96 -0
  385. package/src-shared/vendor/yaml/util.js +2 -0
@@ -0,0 +1,219 @@
1
+ // Hermes HTTP backend.
2
+ //
3
+ // OpenAI-compatible streaming SSE 协议。任何兼容 /v1/chat/completions(含
4
+ // `stream: true`)的服务都能跑:OpenAI、Azure OpenAI、DeepSeek、自建 vLLM、
5
+ // LiteLLM、Cloudflare Workers AI 兼容层、本地 ollama 兼容层。
6
+ //
7
+ // 只用 stdlib(global fetch + ReadableStream)。Node 18+ 自带。
8
+
9
+ /**
10
+ * @typedef {Object} ChatMessage
11
+ * @property {"system"|"user"|"assistant"|"tool"} role
12
+ * @property {string} content
13
+ */
14
+
15
+ /**
16
+ * @typedef {Object} BackendOptions
17
+ * @property {string} apiBaseUrl base URL ending without /chat/completions
18
+ * @property {string} [apiKey] Bearer token; some servers don't need one
19
+ * @property {string} model model name passed verbatim
20
+ * @property {AbortSignal} [signal]
21
+ */
22
+
23
+ /**
24
+ * @typedef {Object} StreamChunk
25
+ * @property {"delta"|"done"|"usage"|"error"} kind
26
+ * @property {string} [text] delta only
27
+ * @property {string} [fullText] done only — accumulated final text
28
+ * @property {Object} [usage] usage only — {prompt_tokens, completion_tokens, total_tokens}
29
+ * @property {string} [error] error only — message
30
+ */
31
+
32
+ /**
33
+ * Stream a chat completion. Yields {kind, ...} chunks as the response arrives.
34
+ *
35
+ * @param {ChatMessage[]} messages
36
+ * @param {BackendOptions} opts
37
+ * @returns {AsyncGenerator<StreamChunk, void, void>}
38
+ */
39
+ export async function* streamChat(messages, opts) {
40
+ const url = `${opts.apiBaseUrl.replace(/\/+$/, "")}/chat/completions`;
41
+ const headers = {
42
+ "Content-Type": "application/json",
43
+ "Accept": "text/event-stream",
44
+ };
45
+ if (opts.apiKey) headers["Authorization"] = `Bearer ${opts.apiKey}`;
46
+
47
+ let res;
48
+ try {
49
+ res = await fetch(url, {
50
+ method: "POST",
51
+ headers,
52
+ body: JSON.stringify({
53
+ model: opts.model,
54
+ messages,
55
+ stream: true,
56
+ }),
57
+ signal: opts.signal,
58
+ });
59
+ } catch (err) {
60
+ yield { kind: "error", error: `fetch failed: ${err?.message || String(err)}` };
61
+ return;
62
+ }
63
+ if (!res.ok) {
64
+ const body = await safeReadText(res);
65
+ yield {
66
+ kind: "error",
67
+ error: `http ${res.status}: ${body.slice(0, 400)}`,
68
+ };
69
+ return;
70
+ }
71
+ if (!res.body) {
72
+ yield { kind: "error", error: "empty response body" };
73
+ return;
74
+ }
75
+
76
+ const reader = res.body.getReader();
77
+ const decoder = new TextDecoder("utf-8");
78
+ let pending = "";
79
+ let accum = "";
80
+ let usage = null;
81
+
82
+ try {
83
+ while (true) {
84
+ const { value, done } = await reader.read();
85
+ if (done) break;
86
+ pending += decoder.decode(value, { stream: true });
87
+
88
+ // Process complete events delimited by blank line ("\n\n").
89
+ let dblIdx;
90
+ while ((dblIdx = pending.indexOf("\n\n")) !== -1) {
91
+ const frame = pending.slice(0, dblIdx);
92
+ pending = pending.slice(dblIdx + 2);
93
+
94
+ // SSE per-frame state:
95
+ // - frameEvent : value of "event:" header (defaults to "message")
96
+ // - frameData : concatenation of all "data:" lines in the frame
97
+ // hermes-agent api_server 在子 agent / 工具触发时会单独发一帧
98
+ // event: hermes.tool.progress
99
+ // data: {"tool":"<name>","emoji":"...","label":"..."}
100
+ // 这帧不带 OpenAI chat.completion.chunk 结构,必须按 frameEvent 分流。
101
+ let frameEvent = "";
102
+ const frameDataLines = [];
103
+ for (const rawLine of frame.split("\n")) {
104
+ const line = rawLine.replace(/\r$/, "");
105
+ if (line.startsWith(":")) continue; // comment / heartbeat
106
+ if (line.startsWith("event:")) {
107
+ frameEvent = line.slice(6).trim();
108
+ continue;
109
+ }
110
+ if (line.startsWith("data:")) {
111
+ frameDataLines.push(line.slice(5).trim());
112
+ }
113
+ }
114
+ const payload = frameDataLines.join("\n");
115
+ if (!payload) continue;
116
+
117
+ // Hermes 自定义事件:tool / subagent 进度通知。整帧 yield 一条
118
+ // hermes_tool_progress chunk,handleRequest 负责映射到 unified protocol。
119
+ if (frameEvent === "hermes.tool.progress") {
120
+ try {
121
+ const parsed = JSON.parse(payload);
122
+ yield {
123
+ kind: "hermes_tool_progress",
124
+ tool: String(parsed?.tool || ""),
125
+ label: String(parsed?.label || ""),
126
+ emoji: String(parsed?.emoji || ""),
127
+ };
128
+ } catch {
129
+ // 解析失败静默忽略 — 不阻塞正文流
130
+ }
131
+ continue;
132
+ }
133
+
134
+ // OpenAI chat.completion.chunk 路径:兼容多 data 行合并 (SSE spec) +
135
+ // [DONE] sentinel。
136
+ if (payload === "[DONE]") {
137
+ // Server signals end — flush + return.
138
+ yield { kind: "done", fullText: accum };
139
+ if (usage) yield { kind: "usage", usage };
140
+ return;
141
+ }
142
+ // 简化:旧实现把每行 data: 单独尝试 parse;新实现先合并整帧再 parse。
143
+ // OpenAI 流通常每帧只有一条 data 行,行为等价;多行合并是 SSE spec 兼容。
144
+ const parsed = (() => {
145
+ try { return JSON.parse(payload); } catch { return null; }
146
+ })();
147
+ if (parsed) {
148
+ // OpenAI streaming shape: choices[].delta.content + optional usage on
149
+ // last chunk (with stream_options.include_usage=true).
150
+ //
151
+ // Reasoning models (deepseek-r1, qwen-qwq, some OpenAI-compatible
152
+ // proxies) additionally emit `delta.reasoning_content` (string) when
153
+ // the model is in chain-of-thought mode. We yield those as a separate
154
+ // `kind: "thinking"` chunk so the unified envelope chain can route
155
+ // them to content_block{type:"thinking"}. Most providers that inline
156
+ // thinking inside delta.content (e.g. Gemini via OpenAI-compat
157
+ // gateway) won't trigger this branch — that's expected, since the
158
+ // upstream has not split reasoning out.
159
+ const choice = parsed?.choices?.[0];
160
+ const reasoningDelta = choice?.delta?.reasoning_content;
161
+ if (typeof reasoningDelta === "string" && reasoningDelta.length > 0) {
162
+ yield { kind: "thinking", text: reasoningDelta };
163
+ }
164
+ // OpenAI tool-calling streaming shape:
165
+ // delta.tool_calls = [{ index, id?, function: { name?, arguments? } }]
166
+ // arguments arrives incrementally as a JSON string; id/name typically
167
+ // only on the first chunk for each call.
168
+ const toolCalls = choice?.delta?.tool_calls;
169
+ if (Array.isArray(toolCalls)) {
170
+ for (const tc of toolCalls) {
171
+ if (!tc || typeof tc !== "object") continue;
172
+ const callId = String(tc.id || "");
173
+ const name = String(tc.function?.name || "");
174
+ const args = String(tc.function?.arguments || "");
175
+ if (callId && name) {
176
+ yield { kind: "tool_use_start", call_id: callId, name };
177
+ }
178
+ if (args.length > 0 && callId) {
179
+ yield { kind: "tool_use_args_delta", call_id: callId, arguments: args };
180
+ }
181
+ }
182
+ }
183
+ const delta = choice?.delta?.content;
184
+ if (typeof delta === "string" && delta.length > 0) {
185
+ accum += delta;
186
+ yield { kind: "delta", text: delta };
187
+ }
188
+ if (parsed?.usage) {
189
+ usage = parsed.usage;
190
+ }
191
+ // Stop when finish_reason is present.
192
+ if (choice?.finish_reason) {
193
+ // OpenAI signals tool-call turn end via finish_reason === "tool_calls".
194
+ // We don't synthesize tool_use.completed here — the dispatch handler
195
+ // does that based on argument accumulation. Just signal done.
196
+ yield { kind: "done", fullText: accum };
197
+ if (usage) yield { kind: "usage", usage };
198
+ return;
199
+ }
200
+ }
201
+ }
202
+ }
203
+ // Stream closed without [DONE] — best-effort flush.
204
+ if (accum) yield { kind: "done", fullText: accum };
205
+ if (usage) yield { kind: "usage", usage };
206
+ } catch (err) {
207
+ yield { kind: "error", error: `stream read failed: ${err?.message || String(err)}` };
208
+ } finally {
209
+ try { reader.releaseLock(); } catch {}
210
+ }
211
+ }
212
+
213
+ async function safeReadText(res) {
214
+ try {
215
+ return await res.text();
216
+ } catch {
217
+ return "";
218
+ }
219
+ }
@@ -0,0 +1,196 @@
1
+ // Hermes 桥接入口 — long-poll worker 模式。
2
+ //
3
+ // 与旧 SSE 订阅模式的本质差异:
4
+ // - 不再 subscribe relay 流;改用 GET /v1/gateways/<gw>/requests/next 长轮询拉用户消息
5
+ // - 拉到 request 后串行调本地 LLM(http 或 command 后端)
6
+ // - 流式 native event 通过 POST /v1/gateways/<gw>/requests/<rid>/events 推回
7
+ // - 心跳走 POST /v1/gateways/<gw>/meta(无 bridge.status envelope)
8
+ //
9
+ // 服务端 hermes/openclaw adapter 期望 OpenAI Responses API 形态的 native event:
10
+ // { event: "start" } ← turn 开始
11
+ // { event: "chunk", data: "<openai-style json line>" }← 流式 delta
12
+ // { event: "end" } ← turn 完成
13
+ // { event: "error", error: "msg" } ← 失败
14
+ //
15
+ // 我们这里把 hermes backend 的 {kind:"delta",text:"..."} 转成 OpenAI Responses API
16
+ // 风格的 chunk:
17
+ // {"type":"response.output_text.delta","delta":"..."}
18
+ // 然后用 {event:"chunk", data:JSON.stringify(...)} 包一层送上去。
19
+ // 最终 finalize 用 {event:"end"} 发,服务端翻译为 unified run.completed。
20
+
21
+ import process from "node:process";
22
+
23
+ import { createSessionSlot, SESSION_STATES } from "../../core/sessionSlot.mjs";
24
+ import { createRelayWorker } from "../../core/relayWorker.mjs";
25
+ import { bootstrapAgentlinkTools } from "../../core/agentlinkToolsBootstrap.mjs";
26
+ import { installAutoTunnel } from "../../core/autoTunnelWiring.mjs";
27
+ import { resolveSession } from "../../core/pairCodeClient.mjs";
28
+ import { createUsageReporter } from "../../core/usageReporter.mjs";
29
+ import { runWorkerWithRevokeHandling } from "../../core/bridgeSelfUninstall.mjs";
30
+
31
+ import { hermesPreflightWithHeal, resolveProfileHome } from "./preflight.mjs";
32
+ import { manageProfileGateway } from "./gatewayManager.mjs";
33
+ import { createHermesHandleRequest } from "./handleRequest.mjs";
34
+
35
+
36
+ export async function runHermesBridge({ options, positional, log }) {
37
+ // 1. preflight
38
+ const pre = await hermesPreflightWithHeal({ options, log });
39
+ if (!pre.ok) {
40
+ process.stderr.write(`hermes preflight failed: ${pre.error}\n`);
41
+ if (pre.hint) process.stderr.write(`${pre.hint}\n`);
42
+ process.exit(65);
43
+ }
44
+ log.info("bridge.preflight.pass", "hermes preflight ok", {
45
+ backend: pre.backend, model: pre.model,
46
+ });
47
+
48
+ // 2. resolve session(consume pair code 或读本地状态)
49
+ let gwId, relayBase, bridgeToken, profileName;
50
+ try {
51
+ const r = await resolveSession({ runtime: "hermes", options, log });
52
+ gwId = r.gwId;
53
+ relayBase = r.relayUrl;
54
+ bridgeToken = r.bridgeToken;
55
+ // T2.1: 从 pair state 读取 profileName(N2.3 写入的字段);旧 pair state 无此字段时为空字符串
56
+ profileName = r.profileName ?? "";
57
+ log.info("bridge.preflight.pass", "hermes runtime entry reached", {
58
+ relay: relayBase, gw_id: gwId, source: r.source, has_bridge_token: !!bridgeToken,
59
+ profile_name: profileName || "(none)",
60
+ });
61
+ } catch (err) {
62
+ process.stderr.write(`${err?.message || err}\n`);
63
+ process.exit(65);
64
+ }
65
+ if (!bridgeToken) {
66
+ process.stderr.write("缺少 bridge_token,请重新运行 agentlink pair <code> -r hermes\n");
67
+ process.exit(65);
68
+ }
69
+
70
+ const sessLog = log.child({ gw: gwId });
71
+
72
+ // 3.1: 计算默认 profileHome(模型 b:此值作为无 workspace_path 时的 fallback)
73
+ // T2.1: 用 profileName(来自 pair state)而非 gwId 派生 profileHome;旧 pair state 无此字段则 fallback ~/.hermes
74
+ const profileHome = resolveProfileHome(profileName);
75
+ // T2.2: slug 用于 manageProfileGateway key,优先用 profileName;旧 pair state 无 profileName 则 fallback gwId 截断
76
+ const slug = profileName || String(gwId).toLowerCase().slice(0, 32);
77
+
78
+ // 模型 b: 默认 profile gateway 在 bridge 启动时 ensure 一次(保持向后兼容)。
79
+ // per-conversation 路由(带 workspace_path 的 dispatch)会在 defaultOpenclawInvoke
80
+ // 里 per-request 调 manageProfileGateway,不依赖此处的 gatewayBaseUrl。
81
+ let gatewayBaseUrl = null;
82
+ try {
83
+ const gwResult = await manageProfileGateway(slug, profileHome, {
84
+ mode: "ensure", log: sessLog,
85
+ });
86
+ if (gwResult.ok) {
87
+ gatewayBaseUrl = gwResult.baseUrl + "/v1";
88
+ } else {
89
+ sessLog.warn("bridge.profile.gateway.ensure.failed",
90
+ "default profile gateway ensure failed, falling back to preflight apiBaseUrl", {
91
+ error: gwResult.error, slug, profileHome,
92
+ });
93
+ }
94
+ } catch (err) {
95
+ sessLog.warn("bridge.profile.gateway.ensure.error",
96
+ "default profile gateway ensure threw, falling back to preflight apiBaseUrl", {
97
+ error: err?.message, slug, profileHome,
98
+ });
99
+ }
100
+
101
+ // 默认 pre:bridge 启动时绑定到默认 profile(无 workspace_path 时使用)
102
+ const effectivePre = gatewayBaseUrl
103
+ ? { ...pre, apiBaseUrl: gatewayBaseUrl }
104
+ : pre;
105
+
106
+ sessLog.info("bridge.preflight.pass", "hermes profile resolved", {
107
+ profileHome, slug, gatewayBaseUrl, effective_api_base: effectivePre.apiBaseUrl,
108
+ model_b_routing: "per-conversation dispatch will route by workspace_path",
109
+ });
110
+
111
+ const worker = createRelayWorker({
112
+ relayUrl: relayBase, gwId, bridgeToken, runtime: "hermes", log: sessLog,
113
+ });
114
+ installAutoTunnel({ relayUrl: relayBase, log: sessLog });
115
+
116
+ // usage reporter — flush 时把 native event 推到"最近一个" in-flight request。
117
+ // hermes 是单 in-flight 模型(turn 串行),所以维护 lastRequestId 就够了。
118
+ let lastRequestId = null;
119
+ const usage = createUsageReporter({
120
+ runtime: "hermes",
121
+ log: sessLog,
122
+ publishEvent: (event) => {
123
+ if (!lastRequestId) return Promise.resolve(false);
124
+ return worker.publishEvent(lastRequestId, event);
125
+ },
126
+ });
127
+ usage.setContextWindow(Number(options.contextWindow) || 32_000);
128
+
129
+ const slot = createSessionSlot({ log: sessLog, name: "hermes" });
130
+ slot.transition(SESSION_STATES.READY, "hermes-no-spawn");
131
+
132
+ // agentlinkToolsServer + discovery 文件(见 claude/index.mjs 同段注释)
133
+ let toolsLifecycle = null;
134
+ try {
135
+ toolsLifecycle = await bootstrapAgentlinkTools({
136
+ runtime: "hermes", gwId, relayUrl: relayBase, bridgeToken,
137
+ worker, log: sessLog, version: pre?.version || "",
138
+ getLastRequestId: () => lastRequestId,
139
+ });
140
+ } catch (err) {
141
+ sessLog.warn("agentlink_tools.bootstrap.failed",
142
+ "agentlink tools server failed to start; continuing without tools", { err: err?.message });
143
+ }
144
+
145
+ let shuttingDown = false;
146
+ async function shutdown(reason) {
147
+ if (shuttingDown) return;
148
+ shuttingDown = true;
149
+ sessLog.info("bridge.shutdown", "shutting down", { reason });
150
+ worker.stop(reason);
151
+ try { usage.dispose(); } catch {}
152
+ if (toolsLifecycle?.stop) {
153
+ try { await toolsLifecycle.stop(); } catch {}
154
+ }
155
+ }
156
+ process.once("SIGINT", () => { void shutdown("SIGINT").then(() => process.exit(0)); });
157
+ process.once("SIGTERM", () => { void shutdown("SIGTERM").then(() => process.exit(0)); });
158
+
159
+ // ---- handler:每条 in-flight 请求一次完整 turn ----
160
+ // D-C2.1.3: 替换内联 handleRequest,改为 createHermesHandleRequest 工厂函数
161
+ // 模型 b: 传入 manageProfileGateway 供 per-conversation dispatch 路由(workspace_path → profile gateway)
162
+ // profileHome 作为无 workspace_path 时的 fallback 默认值
163
+ const _handleRequestImpl = createHermesHandleRequest({
164
+ pre: effectivePre, // 默认 profile 的 pre(无 workspace_path 时 fallback)
165
+ log: sessLog,
166
+ gwId,
167
+ usage,
168
+ profileHome, // 默认 profileHome(fallback,来自 resolveProfileHome(profileName))
169
+ dispatchHandlerOptions: {
170
+ relayUrl: relayBase,
171
+ bridgeToken,
172
+ },
173
+ // workspaceRpc 由 handleRequest 内部用 profileHome 实例化(不再显式传入)
174
+ scanner: toolsLifecycle?.scanner ?? null,
175
+ // 模型 b: 注入真实 manageProfileGateway,供 per-conv 路由使用
176
+ _manageProfileGateway: manageProfileGateway,
177
+ });
178
+
179
+ async function handleRequest(request, ctx) {
180
+ lastRequestId = ctx.requestId;
181
+ return _handleRequestImpl(request, ctx);
182
+ }
183
+
184
+ // ---- 启动 worker 主循环 ----
185
+ // 用 runWorkerWithRevokeHandling 而不是裸 worker.run() —— 让 bridge 在收到
186
+ // App 端解绑信号(HTTP 404 on /requests/next)时自动 spawn `agentlink
187
+ // uninstall` 卸 launchd plist + 清本地 pair state,配对双向闭环。
188
+ sessLog.info("bridge.loop.entered", "hermes worker entering long-poll loop", {
189
+ gw_id: gwId, backend: pre.backend, model: pre.model,
190
+ });
191
+ await runWorkerWithRevokeHandling({
192
+ worker, handler: handleRequest, runtime: "hermes", log: sessLog,
193
+ });
194
+ }
195
+
196
+ // helpers 已移入 handleRequest.mjs
@@ -0,0 +1,189 @@
1
+ // mcpConfigAdapter.mjs — Hermes 的 MCP server 配置注入器。
2
+ //
3
+ // hermes-agent 读 ~/.hermes/config.yaml 的 `mcp_servers:` top-level key:
4
+ //
5
+ // mcp_servers:
6
+ // agentlink:
7
+ // command: node
8
+ // args: [...]
9
+ //
10
+ // 见 ~/.hermes/hermes-agent/tools/mcp_tool.py 第 2121 行: config.get("mcp_servers")
11
+ //
12
+ // 跟 Codex 不同:Hermes YAML 用 vendored `yaml` 包的 `parseDocument`,可以保留
13
+ // 用户的注释与 key 顺序(yaml 2.x 文档级 API)。
14
+ //
15
+ // 操作要求(spec.md Hermes MCP server registration):
16
+ // - vendored yaml 2.x parseDocument API
17
+ // - 用户其它 keys / 注释 保留
18
+ // - 若 ~/.hermes/ 不存在 → hermes 未装 → 返回 { ok: false, reason: "hermes_not_installed" }
19
+ // 而非创建空目录(避免把 ~/.hermes/ 误当成 hermes 装好了)
20
+
21
+ import path from "node:path";
22
+ import os from "node:os";
23
+ import fs from "node:fs/promises";
24
+
25
+ import { fileURLToPath } from "node:url";
26
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
27
+ const YAML = await import(
28
+ path.join(__dirname, "../../../src-shared/vendor/yaml/dist/index.js")
29
+ );
30
+
31
+ export const fileExtension = "yaml";
32
+
33
+ const SERVER_NAME = "agentlink";
34
+
35
+ function hermesHome() {
36
+ return path.join(os.homedir(), ".hermes");
37
+ }
38
+
39
+ function configPath() {
40
+ return path.join(hermesHome(), "config.yaml");
41
+ }
42
+
43
+ /**
44
+ * 检查 Hermes 是否安装。判定:`~/.hermes/` 目录存在(hermes-agent 启动会自创)。
45
+ */
46
+ async function isHermesInstalled() {
47
+ try {
48
+ const st = await fs.stat(hermesHome());
49
+ return st.isDirectory();
50
+ } catch {
51
+ return false;
52
+ }
53
+ }
54
+
55
+ export async function read() {
56
+ if (!(await isHermesInstalled())) {
57
+ const e = new Error("hermes not installed (~/.hermes/ missing)");
58
+ e.kind = "not_installed";
59
+ e.reason = "hermes_not_installed";
60
+ throw e;
61
+ }
62
+ return await fs.readFile(configPath(), "utf8");
63
+ }
64
+
65
+ export async function register({ args, log } = {}) {
66
+ if (!(await isHermesInstalled())) {
67
+ return { ok: false, reason: "hermes_not_installed", mode: "noop_hermes_missing" };
68
+ }
69
+ const cfgPath = configPath();
70
+ const desired = {
71
+ command: "node",
72
+ args: args.slice(),
73
+ };
74
+
75
+ let raw = "";
76
+ try {
77
+ raw = await fs.readFile(cfgPath, "utf8");
78
+ } catch (err) {
79
+ if (err.code !== "ENOENT") throw err;
80
+ }
81
+
82
+ let doc;
83
+ if (raw.trim().length > 0) {
84
+ try {
85
+ doc = YAML.parseDocument(raw);
86
+ } catch (err) {
87
+ const e = new Error(`hermes config.yaml parse failed: ${err.message}`);
88
+ e.kind = "parse_failed";
89
+ throw e;
90
+ }
91
+ } else {
92
+ doc = YAML.parseDocument("mcp_servers:\n");
93
+ }
94
+
95
+ // idempotent check: 取出 current,跟 desired 比对
96
+ const currentNode = doc.getIn(["mcp_servers", SERVER_NAME], true);
97
+ const current = currentNode ? currentNode.toJSON() : null;
98
+ if (yamlEqual(current, desired)) {
99
+ return { changed: false, configPath: cfgPath, mode: "noop_idempotent" };
100
+ }
101
+
102
+ // 确保 mcp_servers 是个 Map(parseDocument 对 null/missing 都给一个空块)
103
+ if (!doc.has("mcp_servers") || doc.get("mcp_servers") === null) {
104
+ doc.set("mcp_servers", { [SERVER_NAME]: desired });
105
+ } else {
106
+ doc.setIn(["mcp_servers", SERVER_NAME], desired);
107
+ }
108
+
109
+ await fs.writeFile(cfgPath, doc.toString(), { mode: 0o600 });
110
+ log?.info?.("mcp.fanout.hermes.write", "wrote agentlink mcp entry", {
111
+ configPath: cfgPath,
112
+ });
113
+ return { changed: true, configPath: cfgPath };
114
+ }
115
+
116
+ export async function deregister({ log } = {}) {
117
+ const cfgPath = configPath();
118
+ let raw;
119
+ try {
120
+ raw = await fs.readFile(cfgPath, "utf8");
121
+ } catch (err) {
122
+ if (err.code === "ENOENT") {
123
+ return { changed: false, configPath: cfgPath, mode: "noop_no_config" };
124
+ }
125
+ throw err;
126
+ }
127
+ let doc;
128
+ try { doc = YAML.parseDocument(raw); }
129
+ catch { return { changed: false, configPath: cfgPath, mode: "noop_parse_failed" }; }
130
+
131
+ if (!doc.hasIn(["mcp_servers", SERVER_NAME])) {
132
+ return { changed: false, configPath: cfgPath, mode: "noop_not_registered" };
133
+ }
134
+ doc.deleteIn(["mcp_servers", SERVER_NAME]);
135
+ await fs.writeFile(cfgPath, doc.toString(), { mode: 0o600 });
136
+ log?.info?.("mcp.fanout.hermes.delete", "removed agentlink mcp entry", {
137
+ configPath: cfgPath,
138
+ });
139
+ return { changed: true, configPath: cfgPath };
140
+ }
141
+
142
+ export async function status() {
143
+ if (!(await isHermesInstalled())) {
144
+ return { installed: false, registered: false, reason: "hermes_not_installed" };
145
+ }
146
+ const cfgPath = configPath();
147
+ let raw;
148
+ try {
149
+ raw = await fs.readFile(cfgPath, "utf8");
150
+ } catch (err) {
151
+ if (err.code === "ENOENT") {
152
+ return { installed: true, registered: false, configPath: cfgPath, reason: "no_config_file" };
153
+ }
154
+ return { installed: true, registered: false, error: err.message };
155
+ }
156
+ let doc;
157
+ try { doc = YAML.parseDocument(raw); }
158
+ catch { return { installed: true, registered: false, configPath: cfgPath, reason: "parse_failed" }; }
159
+ const entryNode = doc.getIn(["mcp_servers", SERVER_NAME], true);
160
+ if (!entryNode) {
161
+ return { installed: true, registered: false, configPath: cfgPath };
162
+ }
163
+ const entry = entryNode.toJSON();
164
+ return {
165
+ installed: true,
166
+ registered: true,
167
+ configPath: cfgPath,
168
+ version: extractAgentlinkVersion(entry.args),
169
+ };
170
+ }
171
+
172
+ function yamlEqual(a, b) {
173
+ if (a === b) return true;
174
+ if (!a || !b) return false;
175
+ if (a.command !== b.command) return false;
176
+ if (!Array.isArray(a.args) || !Array.isArray(b.args)) return false;
177
+ if (a.args.length !== b.args.length) return false;
178
+ for (let i = 0; i < a.args.length; i++) {
179
+ if (a.args[i] !== b.args[i]) return false;
180
+ }
181
+ return true;
182
+ }
183
+
184
+ function extractAgentlinkVersion(args) {
185
+ if (!Array.isArray(args)) return null;
186
+ const idx = args.indexOf("--agentlink-version");
187
+ if (idx >= 0 && idx + 1 < args.length) return args[idx + 1];
188
+ return null;
189
+ }