@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,359 @@
1
+ // Hermes 预检。
2
+ //
3
+ // Hermes runtime 走 Nous Research `hermes-agent` 项目(v0.9+)的本地
4
+ // OpenAI-compatible HTTP server(`hermes gateway` 启动后默认监听 8642 端口,
5
+ // 路由有 /v1/chat/completions、/v1/models、/health 等)。localhost 绑定本身
6
+ // 即鉴权,**不需要 API key**。设计目标:**依赖最少**,env / option 都不必配。
7
+ //
8
+ // 决策顺序(首个命中即用):
9
+ // 1. options.backend === "command" → command backend(显式 opt-in)
10
+ // 2. options.backend === "http" OR `HERMES_BRIDGE_API_BASE_URL` 已设 → http
11
+ // 3. `HERMES_BRIDGE_COMMAND` 已设(且 apiBaseUrl 未显式设)→ command(兼容)
12
+ // 4. 兜底 → http with `http://<API_SERVER_HOST>:<API_SERVER_PORT>/v1`
13
+ // (从 `~/.hermes/.env` 自动 load 这两个 env;用户没改就 `127.0.0.1:8642`)
14
+
15
+ import { spawnSync } from "node:child_process";
16
+ import fs from "node:fs";
17
+ import os from "node:os";
18
+ import path from "node:path";
19
+ import process from "node:process";
20
+
21
+ import { ensureHermesApiServer } from "./envSetup.mjs";
22
+ import { manageHermesGateway, manageProfileGateway, resolveProfilePort, probeHealth } from "./gatewayManager.mjs";
23
+
24
+ const PREFLIGHT_TIMEOUT_MS = 5000;
25
+
26
+ // Nous Research `hermes-agent` 的 home dir 与 gateway api-server 默认。
27
+ // 见 ~/.hermes/hermes-agent/gateway/platforms/api_server.py:
28
+ // DEFAULT_HOST = "127.0.0.1"; DEFAULT_PORT = 8642
29
+ const DEFAULT_API_SERVER_HOST = "127.0.0.1";
30
+ const DEFAULT_API_SERVER_PORT = "8642";
31
+
32
+ function resolveHermesHome() {
33
+ const fromEnv = String(process.env.HERMES_HOME || "").trim();
34
+ if (fromEnv) {
35
+ return fromEnv.startsWith("~")
36
+ ? path.join(os.homedir(), fromEnv.slice(1))
37
+ : fromEnv;
38
+ }
39
+ return path.join(os.homedir(), ".hermes");
40
+ }
41
+
42
+ /**
43
+ * 按 profileName 解析 per-agent hermes home 目录(profile 隔离入口)。
44
+ *
45
+ * 优先级:
46
+ * 1. HERMES_HOME env 已设(非空)→ 直接返回展开路径(向后兼容)
47
+ * 2. profileName 非空 → ~/.hermes/profiles/<profileName>(直接用,不截断不转换)
48
+ * 3. profileName 为空 → 兜底 ~/.hermes
49
+ *
50
+ * @param {string} profileName 用户选定的真实 hermes profile 名(profile 目录名)
51
+ * @returns {string} 绝对路径(不以 / 结尾)
52
+ */
53
+ export function resolveProfileHome(profileName) {
54
+ const fromEnv = String(process.env.HERMES_HOME || "").trim();
55
+ if (fromEnv) {
56
+ // 展开 ~ 前缀
57
+ const expanded = fromEnv.startsWith("~")
58
+ ? path.join(os.homedir(), fromEnv.slice(1))
59
+ : fromEnv;
60
+ // path.resolve 去掉尾斜杠,确保返回规范绝对路径
61
+ return path.resolve(expanded);
62
+ }
63
+ if (!profileName) {
64
+ return path.join(os.homedir(), ".hermes");
65
+ }
66
+ return path.join(os.homedir(), ".hermes", "profiles", profileName);
67
+ }
68
+
69
+ /**
70
+ * 从 ~/.hermes/.env 把 env 加载到 process.env,不覆盖已有值(process env > .env)。
71
+ */
72
+ function loadHermesEnvFile() {
73
+ const envPath = path.join(resolveHermesHome(), ".env");
74
+ let content;
75
+ try {
76
+ content = fs.readFileSync(envPath, "utf8");
77
+ } catch {
78
+ return false;
79
+ }
80
+ let loaded = 0;
81
+ for (const rawLine of content.split(/\r?\n/)) {
82
+ let line = rawLine.trim();
83
+ if (!line || line.startsWith("#")) continue;
84
+ if (line.startsWith("export ")) line = line.slice(7).trim();
85
+ const eq = line.indexOf("=");
86
+ if (eq < 0) continue;
87
+ const key = line.slice(0, eq).trim();
88
+ if (!key || key in process.env) continue;
89
+ let value = line.slice(eq + 1).trim();
90
+ if (
91
+ value.length >= 2 &&
92
+ value[0] === value[value.length - 1] &&
93
+ (value[0] === '"' || value[0] === "'")
94
+ ) {
95
+ value = value.slice(1, -1);
96
+ }
97
+ process.env[key] = value;
98
+ loaded += 1;
99
+ }
100
+ return loaded > 0;
101
+ }
102
+
103
+ /**
104
+ * 组装本地 hermes gateway 的 base URL:
105
+ * 1. HERMES_BRIDGE_API_BASE_URL(agentlink 最高优先级)
106
+ * 2. API_SERVER_HOST + API_SERVER_PORT(hermes 自家 env,从 ~/.hermes/.env load)
107
+ * 3. 兜底 127.0.0.1:8642
108
+ */
109
+ function resolveLocalApiBaseUrl() {
110
+ const explicit = String(process.env.HERMES_BRIDGE_API_BASE_URL || "").trim();
111
+ if (explicit) return explicit;
112
+ const host = (
113
+ String(process.env.API_SERVER_HOST || "").trim() ||
114
+ DEFAULT_API_SERVER_HOST
115
+ );
116
+ const port = (
117
+ String(process.env.API_SERVER_PORT || "").trim() ||
118
+ DEFAULT_API_SERVER_PORT
119
+ );
120
+ return `http://${host}:${port}/v1`;
121
+ }
122
+
123
+ /**
124
+ * @param {{ options?: any, log?: any }} args
125
+ * @returns {{ ok: boolean, error?: string, hint?: string,
126
+ * backend?: 'http'|'command',
127
+ * apiBaseUrl?: string, apiKey?: string, model?: string,
128
+ * command?: string[] }}
129
+ */
130
+ export function hermesPreflight({ options = {}, log } = {}) {
131
+ const pfLog = log ? log.child({ comp: "child", stage: "preflight" }) : null;
132
+ // 优先 load ~/.hermes/.env,让 API_SERVER_HOST/PORT 等 hermes 自家 env 进入
133
+ // process.env(不覆盖已有值)。必须在后续读取之前加载。
134
+ const envFileLoaded = loadHermesEnvFile();
135
+ const explicit = String(options.backend || "").toLowerCase();
136
+ const apiBaseUrl = String(
137
+ options.apiBaseUrl ||
138
+ options["api-base-url"] ||
139
+ "",
140
+ ).trim();
141
+ const apiKey = String(
142
+ options.apiKey ||
143
+ options["api-key"] ||
144
+ process.env.HERMES_BRIDGE_API_KEY ||
145
+ process.env.API_SERVER_KEY ||
146
+ "",
147
+ ).trim();
148
+ const model = String(
149
+ options.model || process.env.HERMES_BRIDGE_MODEL || "hermes-default",
150
+ ).trim();
151
+ const commandRaw = String(
152
+ options.command ||
153
+ options["bridge-command"] ||
154
+ process.env.HERMES_BRIDGE_COMMAND ||
155
+ "",
156
+ ).trim();
157
+
158
+ // command backend 仅在显式 opt-in(options.backend="command" 或仅设了
159
+ // HERMES_BRIDGE_COMMAND 而未设 apiBaseUrl)时走。除此之外一律 http,缺省
160
+ // 兜底本地 hermes gateway。
161
+ if (
162
+ explicit === "command" ||
163
+ (!explicit && commandRaw && !apiBaseUrl)
164
+ ) {
165
+ if (!commandRaw) {
166
+ return {
167
+ ok: false,
168
+ error: "command backend requested but no command set",
169
+ hint: "set --command or HERMES_BRIDGE_COMMAND",
170
+ };
171
+ }
172
+ const argv = parseCommand(commandRaw);
173
+ if (argv.length === 0) {
174
+ return { ok: false, error: "empty command", hint: "command parse failed" };
175
+ }
176
+ let res;
177
+ try {
178
+ res = spawnSync(argv[0], ["--version"], {
179
+ encoding: "utf8",
180
+ timeout: PREFLIGHT_TIMEOUT_MS,
181
+ shell: process.platform === "win32",
182
+ });
183
+ } catch {
184
+ // fall through
185
+ }
186
+ if (res?.error?.code === "ENOENT") {
187
+ return {
188
+ ok: false,
189
+ error: `command not found: ${argv[0]}`,
190
+ hint: "check $PATH or set absolute path in HERMES_BRIDGE_COMMAND",
191
+ };
192
+ }
193
+ pfLog?.info("bridge.preflight.pass", "hermes command backend selected", {
194
+ command: argv[0],
195
+ argc: argv.length,
196
+ });
197
+ return { ok: true, backend: "command", command: argv, model };
198
+ }
199
+
200
+ // http backend —— option 指定的 apiBaseUrl 优先;否则用 resolveLocalApiBaseUrl()
201
+ // 走 HERMES_BRIDGE_API_BASE_URL / API_SERVER_HOST+PORT / 默认本地兜底。apiKey
202
+ // 永远可选;用户改 API_SERVER_PORT 在 ~/.hermes/.env 即可,agentlink 自动跟随。
203
+ const effectiveBase = apiBaseUrl || resolveLocalApiBaseUrl();
204
+ pfLog?.info("bridge.preflight.pass", "hermes http backend selected", {
205
+ api_base_url: effectiveBase,
206
+ using_resolved_local: !apiBaseUrl,
207
+ hermes_env_loaded: envFileLoaded,
208
+ has_api_key: apiKey.length > 0,
209
+ model,
210
+ });
211
+ return { ok: true, backend: "http", apiBaseUrl: effectiveBase, apiKey, model };
212
+ }
213
+
214
+ // Tokenize a shell-ish command string. Supports double-quoted args. Not a
215
+ // full POSIX shell parser — keeps things predictable and dependency-free.
216
+ function parseCommand(raw) {
217
+ const out = [];
218
+ let buf = "";
219
+ let inQuote = false;
220
+ for (let i = 0; i < raw.length; i++) {
221
+ const c = raw[i];
222
+ if (c === '"') {
223
+ inQuote = !inQuote;
224
+ continue;
225
+ }
226
+ if (!inQuote && /\s/.test(c)) {
227
+ if (buf) {
228
+ out.push(buf);
229
+ buf = "";
230
+ }
231
+ continue;
232
+ }
233
+ buf += c;
234
+ }
235
+ if (buf) out.push(buf);
236
+ return out;
237
+ }
238
+
239
+ /**
240
+ * 判断 base URL 是否指向本机 —— 只有本机才能自愈,远程 hermes 我们不动用户配置。
241
+ */
242
+ function isLocalApiBase(baseUrl) {
243
+ try {
244
+ const host = new URL(baseUrl).hostname;
245
+ return host === "127.0.0.1" || host === "localhost" || host === "::1" || host === "0.0.0.0";
246
+ } catch {
247
+ return false;
248
+ }
249
+ }
250
+
251
+ /**
252
+ * 带自愈的 hermesPreflight:在 sync preflight 之后探活 `:8642/health`,挂了就主动
253
+ *
254
+ * 1. `ensureHermesApiServer({ log })` 补齐 / 强制 `~/.hermes/.env` 里
255
+ * `API_SERVER_ENABLED=true` + HOST/PORT,然后
256
+ * 2. `manageHermesGateway({ mode: "restart" })` 重启 gateway 让新 env 生效
257
+ *
258
+ * 设计动机:pair 流程虽然也会写 env,但用户路径太多(pair/pair-all/agent pair/
259
+ * 手动 nohup 起 bridge),靠 pair 兜底永远有遗漏;而且 hermes 版本升级会重写
260
+ * `.env` 模板(见 `~/.hermes/.env.bak-before-*`)抹掉我们的补丁。把自愈下沉到
261
+ * bridge 启动那一刻,任何路径起的 bridge 都能修。
262
+ *
263
+ * 远程 hermes(apiBaseUrl 指向非本机)跳过自愈 —— 用户既然指了远程,他自己负责
264
+ * 那边的服务状态,我们不去 SSH。
265
+ *
266
+ * 测试不变:tests 仍用 sync `hermesPreflight({})`,这里是给 bridge runtime 用的
267
+ * 额外 wrapper,互不耦合。
268
+ */
269
+ export async function hermesPreflightWithHeal({ options = {}, log, hermesHome } = {}) {
270
+ const pre = hermesPreflight({ options, log });
271
+ if (!pre.ok || pre.backend !== "http") return pre;
272
+ if (!isLocalApiBase(pre.apiBaseUrl)) return pre;
273
+
274
+ const pfLog = log ? log.child({ comp: "child", stage: "preflight-heal" }) : null;
275
+
276
+ // per-profile apiBaseUrl:若 hermesHome 传入,用 per-profile 端口(已在 index.mjs 通过
277
+ // manageProfileGateway 得到);否则沿用 pre.apiBaseUrl(向后兼容)。
278
+ const effectiveApiBaseUrl = pre.apiBaseUrl;
279
+ // apiBaseUrl 形如 "http://127.0.0.1:8642/v1";probeHealth 自己拼 /health
280
+ const probeBase = effectiveApiBaseUrl.replace(/\/v1\/?$/, "");
281
+ const first = await probeHealth(probeBase, { timeoutMs: 2000 });
282
+ if (first.ok) {
283
+ pfLog?.info?.("bridge.preflight.health_ok", "hermes gateway alive", { base: probeBase });
284
+ return pre;
285
+ }
286
+
287
+ pfLog?.warn?.("bridge.preflight.health_miss", "hermes gateway unreachable, self-healing", {
288
+ base: probeBase,
289
+ probe_error: first.error || `http_${first.status}`,
290
+ hermesHome: hermesHome || "(default)",
291
+ });
292
+
293
+ // 自愈:写 per-profile .env(若 hermesHome 传入则写到该目录,否则写全局 ~/.hermes/.env)
294
+ let envResult;
295
+ try {
296
+ envResult = ensureHermesApiServer({ log: pfLog, home: hermesHome || undefined });
297
+ } catch (err) {
298
+ return {
299
+ ok: false,
300
+ error: `hermes self-heal: env patch threw: ${err?.message || err}`,
301
+ hint: `check write perm on ${hermesHome ? hermesHome + "/.env" : "~/.hermes/.env"}`,
302
+ };
303
+ }
304
+ if (envResult.status === "no_home") {
305
+ return {
306
+ ok: false,
307
+ error: `${hermesHome || "~/.hermes"} 不存在 —— 先装 nous-research/hermes-agent 并跑一次 \`hermes gateway run\``,
308
+ hint: "https://github.com/NousResearch/hermes-agent",
309
+ };
310
+ }
311
+ if (envResult.status === "io_error") {
312
+ return {
313
+ ok: false,
314
+ error: `hermes self-heal: ${hermesHome ? hermesHome + "/.env" : "~/.hermes/.env"} 读写失败: ${envResult.error}`,
315
+ hint: `检查 ${hermesHome ? hermesHome + "/.env" : "~/.hermes/.env"} 文件权限`,
316
+ };
317
+ }
318
+
319
+ // 决定 manageHermesGateway 的 mode:env 真改了 → restart 强制让 stale 内存换掉
320
+ const envChanged =
321
+ envResult.status === "patched" &&
322
+ (envResult.overridden?.length > 0 ||
323
+ (envResult.appended || []).includes("API_SERVER_ENABLED"));
324
+ const mode = envChanged ? "restart" : "ensure";
325
+ const effectiveHome = hermesHome || resolveHermesHome();
326
+ const logPath = path.join(effectiveHome, "gateway.log");
327
+ let mgr;
328
+ try {
329
+ mgr = await manageHermesGateway({ baseUrl: probeBase, mode, logPath, log: pfLog });
330
+ } catch (err) {
331
+ return {
332
+ ok: false,
333
+ error: `hermes self-heal: gateway 启动失败: ${err?.message || err}`,
334
+ hint: `看日志:tail -50 ${logPath}`,
335
+ };
336
+ }
337
+ if (!mgr.ok) {
338
+ return {
339
+ ok: false,
340
+ error: `hermes self-heal: gateway 不健康 (${mgr.error || "unknown"})`,
341
+ hint: `看日志:tail -50 ${mgr.logPath || logPath}`,
342
+ };
343
+ }
344
+
345
+ // 再探一次确认通了;同时重跑 sync preflight 让新 env 进 process.env
346
+ const after = await probeHealth(probeBase, { timeoutMs: 2000 });
347
+ if (!after.ok) {
348
+ return {
349
+ ok: false,
350
+ error: `hermes self-heal: gateway 启动了但 /health 仍不通 (${after.error || `http_${after.status}`})`,
351
+ hint: `看日志:tail -50 ${mgr.logPath || logPath}`,
352
+ };
353
+ }
354
+ pfLog?.info?.("bridge.preflight.heal_ok", "hermes gateway self-healed", {
355
+ base: probeBase, env_changed: envChanged, mode, hermesHome: effectiveHome,
356
+ });
357
+ // 重跑一遍 sync preflight:env 已写入 process.env,pre.apiKey 可能从空变成 API_SERVER_KEY
358
+ return hermesPreflight({ options, log });
359
+ }
@@ -0,0 +1,276 @@
1
+ // Hermes runtime — Responses API (POST /v1/responses) streaming backend.
2
+ //
3
+ // 跟 httpBackend.mjs 并列:那条走 OpenAI 通用的 /v1/chat/completions(兼容
4
+ // LM Studio / Ollama / vLLM 等任意 OpenAI-compatible 后端),本文件走
5
+ // hermes-agent **自家**实现的 /v1/responses(OpenAI Responses API 风格)。
6
+ //
7
+ // 切到 /v1/responses 的唯一动机是:chat/completions 端点上 hermes-agent 不
8
+ // 把 delegate_task 的真实返回值(subagent 实际答案的 JSON)放进 SSE 流;
9
+ // `_handle_chat_completions` 的 `_on_tool_progress` 只过 `tool.started`,
10
+ // `tool.completed`(带 result)整个被丢(api_server.py:751)。Responses API
11
+ // 走 `tool_complete_callback` 把 result 直接 emit 成 `function_call_output`
12
+ // item,bridge 可以拿到子 agent 输出。
13
+ //
14
+ // 协议参考:~/.hermes/hermes-agent/gateway/platforms/api_server.py
15
+ // _write_sse_responses (line ~994)
16
+ //
17
+ // 关心的 SSE 事件:
18
+ // response.created — 初始 envelope(ignore)
19
+ // response.output_item.added — 新输出项加入
20
+ // item.type=message → 文本块容器开启(ignore,靠 delta 累积)
21
+ // item.type=function_call → tool 调用开始(status=in_progress)
22
+ // item.type=function_call_output → tool 调用结果(status=completed/failed)
23
+ // response.output_item.done with type=function_call
24
+ // → tool arguments 终态
25
+ // response.output_text.delta — 文本 delta
26
+ // response.completed — 终止
27
+ // response.failed — 终止 + 错误
28
+ //
29
+ // 输出 chunk(兼容 handleRequest defaultOpenclawInvoke 主循环):
30
+ // { kind: "delta", text } — 文本 delta(同 httpBackend)
31
+ // { kind: "thinking", text } — reasoning delta(同 httpBackend)
32
+ // { kind: "tool_call_started", call_id, name, arguments }
33
+ // — function_call item 抵达
34
+ // { kind: "tool_call_completed", call_id, name, result, is_error }
35
+ // — function_call_output item 抵达,
36
+ // result 是字符串(tool 返回值 JSON
37
+ // /纯文本,由调用方解析)
38
+ // { kind: "done", fullText, usage } — 终止
39
+ // { kind: "error", error } — 错误
40
+
41
+ /**
42
+ * @typedef {Object} ResponsesStreamOpts
43
+ * @property {string} apiBaseUrl base URL ending without /responses
44
+ * @property {string} [apiKey] optional bearer
45
+ * @property {string} model model id
46
+ */
47
+
48
+ const TOOL_NAME_FOR_OUTPUT_ITEM_PENDING = "__pending__";
49
+
50
+ /**
51
+ * 拉一次 hermes-agent /v1/responses 流,逐 chunk yield。
52
+ *
53
+ * @param {Array<{role: string, content: any}>} messages
54
+ * @param {ResponsesStreamOpts} opts
55
+ */
56
+ export async function* streamChat(messages, opts) {
57
+ const url = `${opts.apiBaseUrl.replace(/\/+$/, "")}/responses`;
58
+ const headers = {
59
+ "Content-Type": "application/json",
60
+ Accept: "text/event-stream",
61
+ };
62
+ if (opts.apiKey) headers.Authorization = `Bearer ${opts.apiKey}`;
63
+
64
+ // Responses API 请求体 —— hermes-agent 接受 OpenAI Responses 格式:
65
+ // { model, input: messages, stream: true }
66
+ // 多模态 content array(image_url / file 等)原样透传 —— hermes-agent
67
+ // 内部走相同的 message normalization 逻辑。
68
+ const body = {
69
+ model: opts.model,
70
+ input: messages,
71
+ stream: true,
72
+ };
73
+
74
+ let res;
75
+ try {
76
+ res = await fetch(url, {
77
+ method: "POST",
78
+ headers,
79
+ body: JSON.stringify(body),
80
+ signal: opts.signal,
81
+ });
82
+ } catch (err) {
83
+ yield { kind: "error", error: `fetch failed: ${err?.message || String(err)}` };
84
+ return;
85
+ }
86
+ if (!res.ok || !res.body) {
87
+ const text = await safeReadText(res);
88
+ yield {
89
+ kind: "error",
90
+ error: `responses backend HTTP ${res.status}: ${text.slice(0, 200)}`,
91
+ };
92
+ return;
93
+ }
94
+
95
+ const reader = res.body.getReader();
96
+ const decoder = new TextDecoder("utf-8");
97
+ let pending = "";
98
+ let accum = "";
99
+ let usage = null;
100
+ // 缓存 function_call item id → call_id / name,用于把 done 时的 arguments
101
+ // 跟之前 added 时的 call_id 配对。
102
+ const pendingFunctionCalls = new Map(); // item_id → { call_id, name, arguments }
103
+
104
+ try {
105
+ while (true) {
106
+ const { value, done } = await reader.read();
107
+ if (done) break;
108
+ pending += decoder.decode(value, { stream: true });
109
+
110
+ // SSE 帧分隔符是空行(\n\n)。
111
+ let frameEnd;
112
+ while ((frameEnd = pending.indexOf("\n\n")) !== -1) {
113
+ const frame = pending.slice(0, frameEnd);
114
+ pending = pending.slice(frameEnd + 2);
115
+
116
+ let frameEvent = "";
117
+ const dataLines = [];
118
+ for (const rawLine of frame.split("\n")) {
119
+ const line = rawLine.replace(/\r$/, "");
120
+ if (line.startsWith(":")) continue;
121
+ if (line.startsWith("event:")) {
122
+ frameEvent = line.slice(6).trim();
123
+ continue;
124
+ }
125
+ if (line.startsWith("data:")) {
126
+ dataLines.push(line.slice(5).trim());
127
+ }
128
+ }
129
+ const payload = dataLines.join("\n");
130
+ if (!payload) continue;
131
+
132
+ // Responses API 不发 [DONE] sentinel — 用 response.completed/failed
133
+ // 作为终止信号。但兜底处理一下(部分代理可能加)。
134
+ if (payload === "[DONE]") {
135
+ yield { kind: "done", fullText: accum };
136
+ if (usage) yield { kind: "usage", usage };
137
+ return;
138
+ }
139
+
140
+ let parsed;
141
+ try {
142
+ parsed = JSON.parse(payload);
143
+ } catch {
144
+ continue; // 不可解析帧静默丢
145
+ }
146
+
147
+ const eventType = frameEvent || parsed?.type || "";
148
+
149
+ if (eventType === "response.output_text.delta") {
150
+ const delta = String(parsed.delta || "");
151
+ if (delta) {
152
+ accum += delta;
153
+ yield { kind: "delta", text: delta };
154
+ }
155
+ } else if (eventType === "response.reasoning_summary_text.delta") {
156
+ const delta = String(parsed.delta || "");
157
+ if (delta) yield { kind: "thinking", text: delta };
158
+ } else if (eventType === "response.output_item.added") {
159
+ const item = parsed.item || {};
160
+ const itemType = item.type;
161
+ if (itemType === "function_call") {
162
+ // tool 开始;arguments 在 added 时通常已经完整(hermes-agent 这边
163
+ // tool args 是同步 dispatch,不分片)—— 但稳妥起见也接受空 args,
164
+ // 然后等 output_item.done 给出最终 arguments 再 yield 真正的
165
+ // tool_call_started。这里只记录,不 yield。
166
+ const callId = String(item.call_id || "");
167
+ const name = String(item.name || "");
168
+ const args = String(item.arguments || "");
169
+ if (callId && name) {
170
+ pendingFunctionCalls.set(item.id || callId, {
171
+ call_id: callId,
172
+ name,
173
+ arguments: args,
174
+ yieldedStart: false,
175
+ });
176
+ // 如果 arguments 已经完整(非空),立即 yield —— App 可以更早看到
177
+ // tool 调用。这是 hermes-agent 当前的实际行为(dispatch 时一次
178
+ // 性写入),保险地处理 added 也带完整 args 的情形。
179
+ if (args) {
180
+ yield {
181
+ kind: "tool_call_started",
182
+ call_id: callId,
183
+ name,
184
+ arguments: args,
185
+ };
186
+ const entry = pendingFunctionCalls.get(item.id || callId);
187
+ if (entry) entry.yieldedStart = true;
188
+ }
189
+ }
190
+ } else if (itemType === "function_call_output") {
191
+ const callId = String(item.call_id || "");
192
+ // result 在 item.output[].text 里 —— api_server.py:1199 总是用
193
+ // {type: "input_text", text: <result_str>}。容错读 .output 数组。
194
+ let resultText = "";
195
+ const out = Array.isArray(item.output) ? item.output : [];
196
+ if (out.length > 0 && typeof out[0] === "object") {
197
+ resultText = String(out[0]?.text ?? "");
198
+ }
199
+ const isError = item.status === "failed";
200
+ // 从 pendingFunctionCalls 找对应 name(call_id 匹配,不一定按 item.id)
201
+ let name = TOOL_NAME_FOR_OUTPUT_ITEM_PENDING;
202
+ for (const v of pendingFunctionCalls.values()) {
203
+ if (v.call_id === callId) {
204
+ name = v.name;
205
+ break;
206
+ }
207
+ }
208
+ if (callId) {
209
+ yield {
210
+ kind: "tool_call_completed",
211
+ call_id: callId,
212
+ name,
213
+ result: resultText,
214
+ is_error: isError,
215
+ };
216
+ }
217
+ }
218
+ // 其它 item.type(message / reasoning)不发 chunk —— text 通过 delta 累积。
219
+ } else if (eventType === "response.output_item.done") {
220
+ const item = parsed.item || {};
221
+ if (item.type === "function_call") {
222
+ const callId = String(item.call_id || "");
223
+ const name = String(item.name || "");
224
+ const args = String(item.arguments || "");
225
+ const entry = pendingFunctionCalls.get(item.id || callId);
226
+ // 如果 added 时没 yield(没 args),现在补 yield tool_call_started
227
+ if (entry && !entry.yieldedStart) {
228
+ entry.yieldedStart = true;
229
+ entry.arguments = args;
230
+ yield {
231
+ kind: "tool_call_started",
232
+ call_id: callId,
233
+ name,
234
+ arguments: args,
235
+ };
236
+ }
237
+ }
238
+ // function_call_output.done 不需要额外动作 —— added 时已经发了
239
+ // tool_call_completed chunk。
240
+ } else if (eventType === "response.completed") {
241
+ // 终态 envelope 里带 usage 信息。
242
+ const u = parsed.response?.usage;
243
+ if (u && typeof u === "object") {
244
+ usage = u;
245
+ }
246
+ yield { kind: "done", fullText: accum };
247
+ if (usage) yield { kind: "usage", usage };
248
+ return;
249
+ } else if (eventType === "response.failed") {
250
+ const err =
251
+ parsed.response?.error?.message ||
252
+ parsed.message ||
253
+ "hermes-agent responses error";
254
+ yield { kind: "error", error: String(err) };
255
+ return;
256
+ }
257
+ // 其它事件类型(response.created / response.in_progress 等)静默忽略。
258
+ }
259
+ }
260
+ // Stream 结束但没看到 response.completed —— best-effort flush
261
+ if (accum) yield { kind: "done", fullText: accum };
262
+ if (usage) yield { kind: "usage", usage };
263
+ } catch (err) {
264
+ yield { kind: "error", error: `stream read failed: ${err?.message || String(err)}` };
265
+ } finally {
266
+ try { reader.releaseLock(); } catch {}
267
+ }
268
+ }
269
+
270
+ async function safeReadText(res) {
271
+ try {
272
+ return await res.text();
273
+ } catch {
274
+ return "";
275
+ }
276
+ }