@a1hvdy/cc-openclaw 0.3.2

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 (491) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +207 -0
  3. package/configs/.gitkeep +0 -0
  4. package/configs/council-reviewer-prompt.md +82 -0
  5. package/configs/council-system-prompt.md +141 -0
  6. package/dist/scripts/bench/ab-harness.d.ts +58 -0
  7. package/dist/scripts/bench/ab-harness.d.ts.map +1 -0
  8. package/dist/scripts/bench/ab-harness.js +78 -0
  9. package/dist/scripts/bench/ab-harness.js.map +1 -0
  10. package/dist/src/channels/adapter.d.ts +103 -0
  11. package/dist/src/channels/adapter.d.ts.map +1 -0
  12. package/dist/src/channels/adapter.js +38 -0
  13. package/dist/src/channels/adapter.js.map +1 -0
  14. package/dist/src/channels/telegram/completion-summary.d.ts +22 -0
  15. package/dist/src/channels/telegram/completion-summary.d.ts.map +1 -0
  16. package/dist/src/channels/telegram/completion-summary.js +186 -0
  17. package/dist/src/channels/telegram/completion-summary.js.map +1 -0
  18. package/dist/src/channels/telegram/error-renderer.d.ts +30 -0
  19. package/dist/src/channels/telegram/error-renderer.d.ts.map +1 -0
  20. package/dist/src/channels/telegram/error-renderer.js +133 -0
  21. package/dist/src/channels/telegram/error-renderer.js.map +1 -0
  22. package/dist/src/channels/telegram/event-reducer.d.ts +34 -0
  23. package/dist/src/channels/telegram/event-reducer.d.ts.map +1 -0
  24. package/dist/src/channels/telegram/event-reducer.js +579 -0
  25. package/dist/src/channels/telegram/event-reducer.js.map +1 -0
  26. package/dist/src/channels/telegram/index.d.ts +14 -0
  27. package/dist/src/channels/telegram/index.d.ts.map +1 -0
  28. package/dist/src/channels/telegram/index.js +14 -0
  29. package/dist/src/channels/telegram/index.js.map +1 -0
  30. package/dist/src/channels/telegram/injector.d.ts +54 -0
  31. package/dist/src/channels/telegram/injector.d.ts.map +1 -0
  32. package/dist/src/channels/telegram/injector.js +200 -0
  33. package/dist/src/channels/telegram/injector.js.map +1 -0
  34. package/dist/src/channels/telegram/live-card.d.ts +230 -0
  35. package/dist/src/channels/telegram/live-card.d.ts.map +1 -0
  36. package/dist/src/channels/telegram/live-card.js +916 -0
  37. package/dist/src/channels/telegram/live-card.js.map +1 -0
  38. package/dist/src/channels/telegram/state-machine.d.ts +23 -0
  39. package/dist/src/channels/telegram/state-machine.d.ts.map +1 -0
  40. package/dist/src/channels/telegram/state-machine.js +72 -0
  41. package/dist/src/channels/telegram/state-machine.js.map +1 -0
  42. package/dist/src/channels/telegram/tool-tracker.d.ts +147 -0
  43. package/dist/src/channels/telegram/tool-tracker.d.ts.map +1 -0
  44. package/dist/src/channels/telegram/tool-tracker.js +520 -0
  45. package/dist/src/channels/telegram/tool-tracker.js.map +1 -0
  46. package/dist/src/circuit-breaker.d.ts +22 -0
  47. package/dist/src/circuit-breaker.d.ts.map +1 -0
  48. package/dist/src/circuit-breaker.js +47 -0
  49. package/dist/src/circuit-breaker.js.map +1 -0
  50. package/dist/src/command-router/cc-handler.d.ts +67 -0
  51. package/dist/src/command-router/cc-handler.d.ts.map +1 -0
  52. package/dist/src/command-router/cc-handler.js +980 -0
  53. package/dist/src/command-router/cc-handler.js.map +1 -0
  54. package/dist/src/command-router/index.d.ts +3 -0
  55. package/dist/src/command-router/index.d.ts.map +1 -0
  56. package/dist/src/command-router/index.js +2 -0
  57. package/dist/src/command-router/index.js.map +1 -0
  58. package/dist/src/constants.d.ts +132 -0
  59. package/dist/src/constants.d.ts.map +1 -0
  60. package/dist/src/constants.js +140 -0
  61. package/dist/src/constants.js.map +1 -0
  62. package/dist/src/council/consensus.d.ts +21 -0
  63. package/dist/src/council/consensus.d.ts.map +1 -0
  64. package/dist/src/council/consensus.js +52 -0
  65. package/dist/src/council/consensus.js.map +1 -0
  66. package/dist/src/council/council.d.ts +68 -0
  67. package/dist/src/council/council.d.ts.map +1 -0
  68. package/dist/src/council/council.js +914 -0
  69. package/dist/src/council/council.js.map +1 -0
  70. package/dist/src/council/index.d.ts +3 -0
  71. package/dist/src/council/index.d.ts.map +1 -0
  72. package/dist/src/council/index.js +3 -0
  73. package/dist/src/council/index.js.map +1 -0
  74. package/dist/src/engines/base-oneshot-session.d.ts +88 -0
  75. package/dist/src/engines/base-oneshot-session.d.ts.map +1 -0
  76. package/dist/src/engines/base-oneshot-session.js +228 -0
  77. package/dist/src/engines/base-oneshot-session.js.map +1 -0
  78. package/dist/src/engines/index.d.ts +7 -0
  79. package/dist/src/engines/index.d.ts.map +1 -0
  80. package/dist/src/engines/index.js +7 -0
  81. package/dist/src/engines/index.js.map +1 -0
  82. package/dist/src/engines/persistent-codex-session.d.ts +17 -0
  83. package/dist/src/engines/persistent-codex-session.d.ts.map +1 -0
  84. package/dist/src/engines/persistent-codex-session.js +106 -0
  85. package/dist/src/engines/persistent-codex-session.js.map +1 -0
  86. package/dist/src/engines/persistent-cursor-session.d.ts +22 -0
  87. package/dist/src/engines/persistent-cursor-session.d.ts.map +1 -0
  88. package/dist/src/engines/persistent-cursor-session.js +242 -0
  89. package/dist/src/engines/persistent-cursor-session.js.map +1 -0
  90. package/dist/src/engines/persistent-custom-session.d.ts +79 -0
  91. package/dist/src/engines/persistent-custom-session.d.ts.map +1 -0
  92. package/dist/src/engines/persistent-custom-session.js +939 -0
  93. package/dist/src/engines/persistent-custom-session.js.map +1 -0
  94. package/dist/src/engines/persistent-gemini-session.d.ts +22 -0
  95. package/dist/src/engines/persistent-gemini-session.d.ts.map +1 -0
  96. package/dist/src/engines/persistent-gemini-session.js +217 -0
  97. package/dist/src/engines/persistent-gemini-session.js.map +1 -0
  98. package/dist/src/engines/persistent-session.d.ts +77 -0
  99. package/dist/src/engines/persistent-session.d.ts.map +1 -0
  100. package/dist/src/engines/persistent-session.js +730 -0
  101. package/dist/src/engines/persistent-session.js.map +1 -0
  102. package/dist/src/health/handler.d.ts +40 -0
  103. package/dist/src/health/handler.d.ts.map +1 -0
  104. package/dist/src/health/handler.js +70 -0
  105. package/dist/src/health/handler.js.map +1 -0
  106. package/dist/src/health/index.d.ts +2 -0
  107. package/dist/src/health/index.d.ts.map +1 -0
  108. package/dist/src/health/index.js +2 -0
  109. package/dist/src/health/index.js.map +1 -0
  110. package/dist/src/index.d.ts +49 -0
  111. package/dist/src/index.d.ts.map +1 -0
  112. package/dist/src/index.js +84 -0
  113. package/dist/src/index.js.map +1 -0
  114. package/dist/src/lib/auto-recovery.d.ts +45 -0
  115. package/dist/src/lib/auto-recovery.d.ts.map +1 -0
  116. package/dist/src/lib/auto-recovery.js +217 -0
  117. package/dist/src/lib/auto-recovery.js.map +1 -0
  118. package/dist/src/lib/cache-parity.d.ts +39 -0
  119. package/dist/src/lib/cache-parity.d.ts.map +1 -0
  120. package/dist/src/lib/cache-parity.js +92 -0
  121. package/dist/src/lib/cache-parity.js.map +1 -0
  122. package/dist/src/lib/circuit-breaker.d.ts +22 -0
  123. package/dist/src/lib/circuit-breaker.d.ts.map +1 -0
  124. package/dist/src/lib/circuit-breaker.js +47 -0
  125. package/dist/src/lib/circuit-breaker.js.map +1 -0
  126. package/dist/src/lib/config.d.ts +74 -0
  127. package/dist/src/lib/config.d.ts.map +1 -0
  128. package/dist/src/lib/config.js +244 -0
  129. package/dist/src/lib/config.js.map +1 -0
  130. package/dist/src/lib/drift-detector.d.ts +47 -0
  131. package/dist/src/lib/drift-detector.d.ts.map +1 -0
  132. package/dist/src/lib/drift-detector.js +192 -0
  133. package/dist/src/lib/drift-detector.js.map +1 -0
  134. package/dist/src/lib/error-formatter.d.ts +78 -0
  135. package/dist/src/lib/error-formatter.d.ts.map +1 -0
  136. package/dist/src/lib/error-formatter.js +149 -0
  137. package/dist/src/lib/error-formatter.js.map +1 -0
  138. package/dist/src/lib/heartbeat-workaround.d.ts +45 -0
  139. package/dist/src/lib/heartbeat-workaround.d.ts.map +1 -0
  140. package/dist/src/lib/heartbeat-workaround.js +61 -0
  141. package/dist/src/lib/heartbeat-workaround.js.map +1 -0
  142. package/dist/src/lib/index.d.ts +8 -0
  143. package/dist/src/lib/index.d.ts.map +1 -0
  144. package/dist/src/lib/index.js +8 -0
  145. package/dist/src/lib/index.js.map +1 -0
  146. package/dist/src/lib/register-guard.d.ts +49 -0
  147. package/dist/src/lib/register-guard.d.ts.map +1 -0
  148. package/dist/src/lib/register-guard.js +73 -0
  149. package/dist/src/lib/register-guard.js.map +1 -0
  150. package/dist/src/lib/route-flag.d.ts +50 -0
  151. package/dist/src/lib/route-flag.d.ts.map +1 -0
  152. package/dist/src/lib/route-flag.js +52 -0
  153. package/dist/src/lib/route-flag.js.map +1 -0
  154. package/dist/src/lib/sysprompt-strip.d.ts +54 -0
  155. package/dist/src/lib/sysprompt-strip.d.ts.map +1 -0
  156. package/dist/src/lib/sysprompt-strip.js +75 -0
  157. package/dist/src/lib/sysprompt-strip.js.map +1 -0
  158. package/dist/src/lib/telemetry.d.ts +39 -0
  159. package/dist/src/lib/telemetry.d.ts.map +1 -0
  160. package/dist/src/lib/telemetry.js +73 -0
  161. package/dist/src/lib/telemetry.js.map +1 -0
  162. package/dist/src/lib/test-mode.d.ts +27 -0
  163. package/dist/src/lib/test-mode.d.ts.map +1 -0
  164. package/dist/src/lib/test-mode.js +38 -0
  165. package/dist/src/lib/test-mode.js.map +1 -0
  166. package/dist/src/lib/vendor-paths.d.ts +15 -0
  167. package/dist/src/lib/vendor-paths.d.ts.map +1 -0
  168. package/dist/src/lib/vendor-paths.js +32 -0
  169. package/dist/src/lib/vendor-paths.js.map +1 -0
  170. package/dist/src/logger.d.ts +17 -0
  171. package/dist/src/logger.d.ts.map +1 -0
  172. package/dist/src/logger.js +46 -0
  173. package/dist/src/logger.js.map +1 -0
  174. package/dist/src/mcp/bridge.d.ts +22 -0
  175. package/dist/src/mcp/bridge.d.ts.map +1 -0
  176. package/dist/src/mcp/bridge.js +78 -0
  177. package/dist/src/mcp/bridge.js.map +1 -0
  178. package/dist/src/mcp/index.d.ts +3 -0
  179. package/dist/src/mcp/index.d.ts.map +1 -0
  180. package/dist/src/mcp/index.js +2 -0
  181. package/dist/src/mcp/index.js.map +1 -0
  182. package/dist/src/models.d.ts +70 -0
  183. package/dist/src/models.d.ts.map +1 -0
  184. package/dist/src/models.js +289 -0
  185. package/dist/src/models.js.map +1 -0
  186. package/dist/src/openai-compat/cli-stream-parser.d.ts +135 -0
  187. package/dist/src/openai-compat/cli-stream-parser.d.ts.map +1 -0
  188. package/dist/src/openai-compat/cli-stream-parser.js +195 -0
  189. package/dist/src/openai-compat/cli-stream-parser.js.map +1 -0
  190. package/dist/src/openai-compat/index.d.ts +2 -0
  191. package/dist/src/openai-compat/index.d.ts.map +1 -0
  192. package/dist/src/openai-compat/index.js +2 -0
  193. package/dist/src/openai-compat/index.js.map +1 -0
  194. package/dist/src/openai-compat/openai-compat.d.ts +281 -0
  195. package/dist/src/openai-compat/openai-compat.d.ts.map +1 -0
  196. package/dist/src/openai-compat/openai-compat.js +939 -0
  197. package/dist/src/openai-compat/openai-compat.js.map +1 -0
  198. package/dist/src/openai-compat/skill-resolver.d.ts +36 -0
  199. package/dist/src/openai-compat/skill-resolver.d.ts.map +1 -0
  200. package/dist/src/openai-compat/skill-resolver.js +134 -0
  201. package/dist/src/openai-compat/skill-resolver.js.map +1 -0
  202. package/dist/src/openai-compat/sse-translator.d.ts +32 -0
  203. package/dist/src/openai-compat/sse-translator.d.ts.map +1 -0
  204. package/dist/src/openai-compat/sse-translator.js +155 -0
  205. package/dist/src/openai-compat/sse-translator.js.map +1 -0
  206. package/dist/src/proxy/anthropic-adapter.d.ts +137 -0
  207. package/dist/src/proxy/anthropic-adapter.d.ts.map +1 -0
  208. package/dist/src/proxy/anthropic-adapter.js +392 -0
  209. package/dist/src/proxy/anthropic-adapter.js.map +1 -0
  210. package/dist/src/proxy/handler.d.ts +40 -0
  211. package/dist/src/proxy/handler.d.ts.map +1 -0
  212. package/dist/src/proxy/handler.js +378 -0
  213. package/dist/src/proxy/handler.js.map +1 -0
  214. package/dist/src/proxy/index.d.ts +5 -0
  215. package/dist/src/proxy/index.d.ts.map +1 -0
  216. package/dist/src/proxy/index.js +5 -0
  217. package/dist/src/proxy/index.js.map +1 -0
  218. package/dist/src/proxy/schema-cleaner.d.ts +12 -0
  219. package/dist/src/proxy/schema-cleaner.d.ts.map +1 -0
  220. package/dist/src/proxy/schema-cleaner.js +34 -0
  221. package/dist/src/proxy/schema-cleaner.js.map +1 -0
  222. package/dist/src/proxy/thought-cache.d.ts +20 -0
  223. package/dist/src/proxy/thought-cache.d.ts.map +1 -0
  224. package/dist/src/proxy/thought-cache.js +53 -0
  225. package/dist/src/proxy/thought-cache.js.map +1 -0
  226. package/dist/src/session/embedded-server.d.ts +26 -0
  227. package/dist/src/session/embedded-server.d.ts.map +1 -0
  228. package/dist/src/session/embedded-server.js +367 -0
  229. package/dist/src/session/embedded-server.js.map +1 -0
  230. package/dist/src/session/inbox-manager.d.ts +39 -0
  231. package/dist/src/session/inbox-manager.d.ts.map +1 -0
  232. package/dist/src/session/inbox-manager.js +111 -0
  233. package/dist/src/session/inbox-manager.js.map +1 -0
  234. package/dist/src/session/index.d.ts +4 -0
  235. package/dist/src/session/index.d.ts.map +1 -0
  236. package/dist/src/session/index.js +4 -0
  237. package/dist/src/session/index.js.map +1 -0
  238. package/dist/src/session/session-manager.d.ts +212 -0
  239. package/dist/src/session/session-manager.d.ts.map +1 -0
  240. package/dist/src/session/session-manager.js +1351 -0
  241. package/dist/src/session/session-manager.js.map +1 -0
  242. package/dist/src/session-bootstrap/cwd-patch.d.ts +51 -0
  243. package/dist/src/session-bootstrap/cwd-patch.d.ts.map +1 -0
  244. package/dist/src/session-bootstrap/cwd-patch.js +955 -0
  245. package/dist/src/session-bootstrap/cwd-patch.js.map +1 -0
  246. package/dist/src/session-bootstrap/index.d.ts +4 -0
  247. package/dist/src/session-bootstrap/index.d.ts.map +1 -0
  248. package/dist/src/session-bootstrap/index.js +4 -0
  249. package/dist/src/session-bootstrap/index.js.map +1 -0
  250. package/dist/src/session-bootstrap/sysprompt-strip.d.ts +26 -0
  251. package/dist/src/session-bootstrap/sysprompt-strip.d.ts.map +1 -0
  252. package/dist/src/session-bootstrap/sysprompt-strip.js +57 -0
  253. package/dist/src/session-bootstrap/sysprompt-strip.js.map +1 -0
  254. package/dist/src/session-bootstrap/think-conflict-resolver.d.ts +33 -0
  255. package/dist/src/session-bootstrap/think-conflict-resolver.d.ts.map +1 -0
  256. package/dist/src/session-bootstrap/think-conflict-resolver.js +234 -0
  257. package/dist/src/session-bootstrap/think-conflict-resolver.js.map +1 -0
  258. package/dist/src/types.d.ts +489 -0
  259. package/dist/src/types.d.ts.map +1 -0
  260. package/dist/src/types.js +8 -0
  261. package/dist/src/types.js.map +1 -0
  262. package/dist/src/validation.d.ts +32 -0
  263. package/dist/src/validation.d.ts.map +1 -0
  264. package/dist/src/validation.js +104 -0
  265. package/dist/src/validation.js.map +1 -0
  266. package/dist/tests/_helpers/subprocess-mock.d.ts +35 -0
  267. package/dist/tests/_helpers/subprocess-mock.d.ts.map +1 -0
  268. package/dist/tests/_helpers/subprocess-mock.js +136 -0
  269. package/dist/tests/_helpers/subprocess-mock.js.map +1 -0
  270. package/dist/tests/auto-recovery.test.d.ts +2 -0
  271. package/dist/tests/auto-recovery.test.d.ts.map +1 -0
  272. package/dist/tests/auto-recovery.test.js +189 -0
  273. package/dist/tests/auto-recovery.test.js.map +1 -0
  274. package/dist/tests/bench-harness.test.d.ts +2 -0
  275. package/dist/tests/bench-harness.test.d.ts.map +1 -0
  276. package/dist/tests/bench-harness.test.js +21 -0
  277. package/dist/tests/bench-harness.test.js.map +1 -0
  278. package/dist/tests/cache-parity.test.d.ts +2 -0
  279. package/dist/tests/cache-parity.test.d.ts.map +1 -0
  280. package/dist/tests/cache-parity.test.js +401 -0
  281. package/dist/tests/cache-parity.test.js.map +1 -0
  282. package/dist/tests/command-router.test.d.ts +2 -0
  283. package/dist/tests/command-router.test.d.ts.map +1 -0
  284. package/dist/tests/command-router.test.js +60 -0
  285. package/dist/tests/command-router.test.js.map +1 -0
  286. package/dist/tests/council.test.d.ts +2 -0
  287. package/dist/tests/council.test.d.ts.map +1 -0
  288. package/dist/tests/council.test.js +20 -0
  289. package/dist/tests/council.test.js.map +1 -0
  290. package/dist/tests/drift-detector.test.d.ts +2 -0
  291. package/dist/tests/drift-detector.test.d.ts.map +1 -0
  292. package/dist/tests/drift-detector.test.js +268 -0
  293. package/dist/tests/drift-detector.test.js.map +1 -0
  294. package/dist/tests/eager-bootstrap-gating.test.d.ts +9 -0
  295. package/dist/tests/eager-bootstrap-gating.test.d.ts.map +1 -0
  296. package/dist/tests/eager-bootstrap-gating.test.js +97 -0
  297. package/dist/tests/eager-bootstrap-gating.test.js.map +1 -0
  298. package/dist/tests/engines.test.d.ts +2 -0
  299. package/dist/tests/engines.test.d.ts.map +1 -0
  300. package/dist/tests/engines.test.js +8 -0
  301. package/dist/tests/engines.test.js.map +1 -0
  302. package/dist/tests/error-formatter.test.d.ts +2 -0
  303. package/dist/tests/error-formatter.test.d.ts.map +1 -0
  304. package/dist/tests/error-formatter.test.js +220 -0
  305. package/dist/tests/error-formatter.test.js.map +1 -0
  306. package/dist/tests/health.test.d.ts +2 -0
  307. package/dist/tests/health.test.d.ts.map +1 -0
  308. package/dist/tests/health.test.js +110 -0
  309. package/dist/tests/health.test.js.map +1 -0
  310. package/dist/tests/heartbeat-workaround.test.d.ts +2 -0
  311. package/dist/tests/heartbeat-workaround.test.d.ts.map +1 -0
  312. package/dist/tests/heartbeat-workaround.test.js +90 -0
  313. package/dist/tests/heartbeat-workaround.test.js.map +1 -0
  314. package/dist/tests/index.test.d.ts +2 -0
  315. package/dist/tests/index.test.d.ts.map +1 -0
  316. package/dist/tests/index.test.js +7 -0
  317. package/dist/tests/index.test.js.map +1 -0
  318. package/dist/tests/lib-sysprompt-strip.test.d.ts +2 -0
  319. package/dist/tests/lib-sysprompt-strip.test.d.ts.map +1 -0
  320. package/dist/tests/lib-sysprompt-strip.test.js +145 -0
  321. package/dist/tests/lib-sysprompt-strip.test.js.map +1 -0
  322. package/dist/tests/listener-activation.test.d.ts +2 -0
  323. package/dist/tests/listener-activation.test.d.ts.map +1 -0
  324. package/dist/tests/listener-activation.test.js +87 -0
  325. package/dist/tests/listener-activation.test.js.map +1 -0
  326. package/dist/tests/mcp-bridge.test.d.ts +2 -0
  327. package/dist/tests/mcp-bridge.test.d.ts.map +1 -0
  328. package/dist/tests/mcp-bridge.test.js +137 -0
  329. package/dist/tests/mcp-bridge.test.js.map +1 -0
  330. package/dist/tests/openai-compat.test.d.ts +2 -0
  331. package/dist/tests/openai-compat.test.d.ts.map +1 -0
  332. package/dist/tests/openai-compat.test.js +8 -0
  333. package/dist/tests/openai-compat.test.js.map +1 -0
  334. package/dist/tests/proxy-heartbeat-integration.test.d.ts +15 -0
  335. package/dist/tests/proxy-heartbeat-integration.test.d.ts.map +1 -0
  336. package/dist/tests/proxy-heartbeat-integration.test.js +122 -0
  337. package/dist/tests/proxy-heartbeat-integration.test.js.map +1 -0
  338. package/dist/tests/proxy.test.d.ts +2 -0
  339. package/dist/tests/proxy.test.d.ts.map +1 -0
  340. package/dist/tests/proxy.test.js +8 -0
  341. package/dist/tests/proxy.test.js.map +1 -0
  342. package/dist/tests/register-guard-stacking.test.d.ts +2 -0
  343. package/dist/tests/register-guard-stacking.test.d.ts.map +1 -0
  344. package/dist/tests/register-guard-stacking.test.js +61 -0
  345. package/dist/tests/register-guard-stacking.test.js.map +1 -0
  346. package/dist/tests/register-guard.test.d.ts +2 -0
  347. package/dist/tests/register-guard.test.d.ts.map +1 -0
  348. package/dist/tests/register-guard.test.js +129 -0
  349. package/dist/tests/register-guard.test.js.map +1 -0
  350. package/dist/tests/route-flag-rollback.test.d.ts +2 -0
  351. package/dist/tests/route-flag-rollback.test.d.ts.map +1 -0
  352. package/dist/tests/route-flag-rollback.test.js +70 -0
  353. package/dist/tests/route-flag-rollback.test.js.map +1 -0
  354. package/dist/tests/route-flag.test.d.ts +2 -0
  355. package/dist/tests/route-flag.test.d.ts.map +1 -0
  356. package/dist/tests/route-flag.test.js +101 -0
  357. package/dist/tests/route-flag.test.js.map +1 -0
  358. package/dist/tests/session-bootstrap.test.d.ts +2 -0
  359. package/dist/tests/session-bootstrap.test.d.ts.map +1 -0
  360. package/dist/tests/session-bootstrap.test.js +183 -0
  361. package/dist/tests/session-bootstrap.test.js.map +1 -0
  362. package/dist/tests/session.test.d.ts +2 -0
  363. package/dist/tests/session.test.d.ts.map +1 -0
  364. package/dist/tests/session.test.js +17 -0
  365. package/dist/tests/session.test.js.map +1 -0
  366. package/dist/tests/state-machine.test.d.ts +2 -0
  367. package/dist/tests/state-machine.test.d.ts.map +1 -0
  368. package/dist/tests/state-machine.test.js +133 -0
  369. package/dist/tests/state-machine.test.js.map +1 -0
  370. package/dist/tests/streaming/cli-stream-parser.test.d.ts +2 -0
  371. package/dist/tests/streaming/cli-stream-parser.test.d.ts.map +1 -0
  372. package/dist/tests/streaming/cli-stream-parser.test.js +233 -0
  373. package/dist/tests/streaming/cli-stream-parser.test.js.map +1 -0
  374. package/dist/tests/streaming/feature-flag.test.d.ts +14 -0
  375. package/dist/tests/streaming/feature-flag.test.d.ts.map +1 -0
  376. package/dist/tests/streaming/feature-flag.test.js +163 -0
  377. package/dist/tests/streaming/feature-flag.test.js.map +1 -0
  378. package/dist/tests/streaming/no-tools-prompt.test.d.ts +17 -0
  379. package/dist/tests/streaming/no-tools-prompt.test.d.ts.map +1 -0
  380. package/dist/tests/streaming/no-tools-prompt.test.js +229 -0
  381. package/dist/tests/streaming/no-tools-prompt.test.js.map +1 -0
  382. package/dist/tests/streaming/skill-plus-tools.test.d.ts +14 -0
  383. package/dist/tests/streaming/skill-plus-tools.test.d.ts.map +1 -0
  384. package/dist/tests/streaming/skill-plus-tools.test.js +234 -0
  385. package/dist/tests/streaming/skill-plus-tools.test.js.map +1 -0
  386. package/dist/tests/streaming/sse-translator.test.d.ts +2 -0
  387. package/dist/tests/streaming/sse-translator.test.d.ts.map +1 -0
  388. package/dist/tests/streaming/sse-translator.test.js +227 -0
  389. package/dist/tests/streaming/sse-translator.test.js.map +1 -0
  390. package/dist/tests/streaming/tool-result-roundtrip.test.d.ts +11 -0
  391. package/dist/tests/streaming/tool-result-roundtrip.test.d.ts.map +1 -0
  392. package/dist/tests/streaming/tool-result-roundtrip.test.js +215 -0
  393. package/dist/tests/streaming/tool-result-roundtrip.test.js.map +1 -0
  394. package/dist/tests/streaming/tool-use-translation.test.d.ts +10 -0
  395. package/dist/tests/streaming/tool-use-translation.test.d.ts.map +1 -0
  396. package/dist/tests/streaming/tool-use-translation.test.js +251 -0
  397. package/dist/tests/streaming/tool-use-translation.test.js.map +1 -0
  398. package/dist/tests/telegram-bridge.test.d.ts +2 -0
  399. package/dist/tests/telegram-bridge.test.d.ts.map +1 -0
  400. package/dist/tests/telegram-bridge.test.js +17 -0
  401. package/dist/tests/telegram-bridge.test.js.map +1 -0
  402. package/dist/tests/telegram-injector.test.d.ts +2 -0
  403. package/dist/tests/telegram-injector.test.d.ts.map +1 -0
  404. package/dist/tests/telegram-injector.test.js +74 -0
  405. package/dist/tests/telegram-injector.test.js.map +1 -0
  406. package/dist/tests/telemetry.test.d.ts +2 -0
  407. package/dist/tests/telemetry.test.d.ts.map +1 -0
  408. package/dist/tests/telemetry.test.js +405 -0
  409. package/dist/tests/telemetry.test.js.map +1 -0
  410. package/dist/tests/test-mode.test.d.ts +2 -0
  411. package/dist/tests/test-mode.test.d.ts.map +1 -0
  412. package/dist/tests/test-mode.test.js +39 -0
  413. package/dist/tests/test-mode.test.js.map +1 -0
  414. package/mcp-config.template.json +13 -0
  415. package/mcp-tools.json +1 -0
  416. package/openclaw-mcp-bridge.cjs +152 -0
  417. package/openclaw.plugin.json +30 -0
  418. package/package.json +45 -0
  419. package/skills/.gitkeep +0 -0
  420. package/stubs/commands-status-deps.runtime.js +10 -0
  421. package/stubs/status.runtime.js +149 -0
  422. package/vendor/base-oneshot-session.d.ts +87 -0
  423. package/vendor/base-oneshot-session.js +227 -0
  424. package/vendor/base-oneshot-session.js.map +1 -0
  425. package/vendor/circuit-breaker.d.ts +21 -0
  426. package/vendor/circuit-breaker.js +47 -0
  427. package/vendor/circuit-breaker.js.map +1 -0
  428. package/vendor/consensus.d.ts +20 -0
  429. package/vendor/consensus.js +52 -0
  430. package/vendor/consensus.js.map +1 -0
  431. package/vendor/constants.d.ts +130 -0
  432. package/vendor/constants.js +139 -0
  433. package/vendor/constants.js.map +1 -0
  434. package/vendor/council.d.ts +67 -0
  435. package/vendor/council.js +913 -0
  436. package/vendor/council.js.map +1 -0
  437. package/vendor/embedded-server.d.ts +25 -0
  438. package/vendor/embedded-server.js +360 -0
  439. package/vendor/embedded-server.js.map +1 -0
  440. package/vendor/inbox-manager.d.ts +38 -0
  441. package/vendor/inbox-manager.js +111 -0
  442. package/vendor/inbox-manager.js.map +1 -0
  443. package/vendor/index.d.ts +63 -0
  444. package/vendor/index.js +705 -0
  445. package/vendor/index.js.map +1 -0
  446. package/vendor/logger.d.ts +16 -0
  447. package/vendor/logger.js +44 -0
  448. package/vendor/logger.js.map +1 -0
  449. package/vendor/models.d.ts +69 -0
  450. package/vendor/models.js +289 -0
  451. package/vendor/models.js.map +1 -0
  452. package/vendor/openai-compat.d.ts +197 -0
  453. package/vendor/openai-compat.js +721 -0
  454. package/vendor/openai-compat.js.map +1 -0
  455. package/vendor/persistent-codex-session.d.ts +16 -0
  456. package/vendor/persistent-codex-session.js +105 -0
  457. package/vendor/persistent-codex-session.js.map +1 -0
  458. package/vendor/persistent-cursor-session.d.ts +21 -0
  459. package/vendor/persistent-cursor-session.js +241 -0
  460. package/vendor/persistent-cursor-session.js.map +1 -0
  461. package/vendor/persistent-custom-session.d.ts +78 -0
  462. package/vendor/persistent-custom-session.js +937 -0
  463. package/vendor/persistent-custom-session.js.map +1 -0
  464. package/vendor/persistent-gemini-session.d.ts +21 -0
  465. package/vendor/persistent-gemini-session.js +216 -0
  466. package/vendor/persistent-gemini-session.js.map +1 -0
  467. package/vendor/persistent-session.d.ts +74 -0
  468. package/vendor/persistent-session.js +684 -0
  469. package/vendor/persistent-session.js.map +1 -0
  470. package/vendor/proxy/anthropic-adapter.d.ts +136 -0
  471. package/vendor/proxy/anthropic-adapter.js +392 -0
  472. package/vendor/proxy/anthropic-adapter.js.map +1 -0
  473. package/vendor/proxy/handler.d.ts +39 -0
  474. package/vendor/proxy/handler.js +323 -0
  475. package/vendor/proxy/handler.js.map +1 -0
  476. package/vendor/proxy/schema-cleaner.d.ts +11 -0
  477. package/vendor/proxy/schema-cleaner.js +34 -0
  478. package/vendor/proxy/schema-cleaner.js.map +1 -0
  479. package/vendor/proxy/thought-cache.d.ts +19 -0
  480. package/vendor/proxy/thought-cache.js +53 -0
  481. package/vendor/proxy/thought-cache.js.map +1 -0
  482. package/vendor/session-manager.d.ts +211 -0
  483. package/vendor/session-manager.js +1345 -0
  484. package/vendor/session-manager.js.map +1 -0
  485. package/vendor/skill-resolver.js +107 -0
  486. package/vendor/types.d.ts +466 -0
  487. package/vendor/types.js +8 -0
  488. package/vendor/types.js.map +1 -0
  489. package/vendor/validation.d.ts +31 -0
  490. package/vendor/validation.js +104 -0
  491. package/vendor/validation.js.map +1 -0
@@ -0,0 +1,937 @@
1
+ /**
2
+ * Persistent Custom Session — generic wrapper for any coding agent CLI
3
+ *
4
+ * Supports two operating modes based on CustomEngineConfig.persistent:
5
+ *
6
+ * persistent=true — long-running subprocess with stream-json I/O over
7
+ * stdin/stdout (like Claude Code). Started once, messages
8
+ * sent as JSON lines on stdin.
9
+ *
10
+ * persistent=false — one-shot per send (like Gemini/Codex). Each send()
11
+ * spawns a new process with the message as a CLI argument.
12
+ *
13
+ * The config maps OpenClaw session concepts (permission modes, models, etc.)
14
+ * to the target CLI's flags, so any coding agent with a CLI can be integrated
15
+ * without writing engine-specific code.
16
+ */
17
+ import { spawn } from 'node:child_process';
18
+ import { EventEmitter } from 'node:events';
19
+ import * as readline from 'node:readline';
20
+ import * as fs from 'node:fs';
21
+ import * as path from 'node:path';
22
+ import { getModelPricing as _getModelPricingBase, } from './types.js';
23
+ import { resolveAlias, estimateTokens } from './models.js';
24
+ import { CONTEXT_HIGH_THRESHOLD, MAX_HISTORY_ITEMS, DEFAULT_HISTORY_LIMIT, SESSION_READY_TIMEOUT_MS, SESSION_READY_FALLBACK_MS, TURN_TIMEOUT_MS, COMPACT_TIMEOUT_MS, STOP_SIGKILL_DELAY_MS, SESSION_EVENT, } from './constants.js';
25
+ // ─── Helpers ────────────────────────────────────────────────────────────────
26
+ function getModelPricing(model, engineConfig) {
27
+ // Try the model registry first; fall back to engine-level pricing
28
+ const base = _getModelPricingBase(model, 'claude-sonnet-4-6');
29
+ if (base.input === 0 && base.output === 0 && engineConfig.pricing) {
30
+ return engineConfig.pricing;
31
+ }
32
+ return base;
33
+ }
34
+ function resolveBin(engineConfig) {
35
+ if (engineConfig.binEnv) {
36
+ const envVal = process.env[engineConfig.binEnv];
37
+ if (envVal)
38
+ return envVal;
39
+ }
40
+ return engineConfig.bin;
41
+ }
42
+ /** Build sanitizer function from config patterns + common defaults */
43
+ function buildSanitizer(engineConfig) {
44
+ const patterns = [
45
+ // Always sanitize Bearer tokens and common API key patterns
46
+ { re: /Bearer [a-zA-Z0-9_-]+/g, replacement: 'Bearer ***' },
47
+ { re: /sk-[a-zA-Z0-9_-]{10,}/g, replacement: 'sk-***' },
48
+ ];
49
+ if (engineConfig.sanitizePatterns) {
50
+ for (const p of engineConfig.sanitizePatterns) {
51
+ try {
52
+ patterns.push({ re: new RegExp(p, 'g'), replacement: '***' });
53
+ }
54
+ catch {
55
+ // Invalid regex — skip silently
56
+ }
57
+ }
58
+ }
59
+ return (text) => {
60
+ let result = text;
61
+ for (const { re, replacement } of patterns) {
62
+ re.lastIndex = 0;
63
+ result = result.replace(re, replacement);
64
+ }
65
+ return result;
66
+ };
67
+ }
68
+ // ─── PersistentCustomSession ───────────────────────────────────────────────
69
+ export class PersistentCustomSession extends EventEmitter {
70
+ options;
71
+ engineConfig;
72
+ engineBin;
73
+ sanitize;
74
+ // Persistent mode state
75
+ proc = null;
76
+ _rl = null;
77
+ _streamCallbacks = null;
78
+ _contextHighFired = false;
79
+ // One-shot mode state
80
+ currentProc = null;
81
+ _currentRl = null;
82
+ // Shared state
83
+ _isReady = false;
84
+ _isPaused = false;
85
+ _isBusy = false;
86
+ currentRequestId = 0;
87
+ _startTime = null;
88
+ _history = [];
89
+ sessionId;
90
+ _stats = {
91
+ turns: 0,
92
+ toolCalls: 0,
93
+ toolErrors: 0,
94
+ tokensIn: 0,
95
+ tokensOut: 0,
96
+ cachedTokens: 0,
97
+ costUsd: 0,
98
+ lastActivity: null,
99
+ };
100
+ constructor(config) {
101
+ super();
102
+ if (!config.customEngine) {
103
+ throw new Error('CustomEngineConfig is required for custom engine sessions');
104
+ }
105
+ this.engineConfig = config.customEngine;
106
+ this.engineBin = resolveBin(this.engineConfig);
107
+ this.sanitize = buildSanitizer(this.engineConfig);
108
+ this.options = {
109
+ ...config,
110
+ permissionMode: config.permissionMode || 'acceptEdits',
111
+ };
112
+ }
113
+ get pid() {
114
+ return this.proc?.pid ?? this.currentProc?.pid ?? undefined;
115
+ }
116
+ get isReady() {
117
+ return this._isReady;
118
+ }
119
+ get isPaused() {
120
+ return this._isPaused;
121
+ }
122
+ get isBusy() {
123
+ return this._isBusy;
124
+ }
125
+ // ─── Start ───────────────────────────────────────────────────────────────
126
+ async start() {
127
+ // Normalize CWD
128
+ if (this.options.cwd) {
129
+ this.options.cwd = path.resolve(this.options.cwd);
130
+ if (!fs.existsSync(this.options.cwd)) {
131
+ fs.mkdirSync(this.options.cwd, { recursive: true });
132
+ }
133
+ }
134
+ if (this.engineConfig.persistent) {
135
+ return this._startPersistent();
136
+ }
137
+ else {
138
+ return this._startOneShot();
139
+ }
140
+ }
141
+ // ── Persistent mode start ───────────────────────────────────────────────
142
+ async _startPersistent() {
143
+ const a = this.engineConfig.args;
144
+ const args = [];
145
+ // Print mode
146
+ if (a.print)
147
+ args.push(a.print);
148
+ // I/O format
149
+ if (a.inputFormat && a.inputFormatValue)
150
+ args.push(a.inputFormat, a.inputFormatValue);
151
+ if (a.outputFormat && a.outputFormatValue)
152
+ args.push(a.outputFormat, a.outputFormatValue);
153
+ // Streaming flags
154
+ if (a.replayUserMessages)
155
+ args.push(a.replayUserMessages);
156
+ if (a.verbose)
157
+ args.push(a.verbose);
158
+ if (a.includePartialMessages)
159
+ args.push(a.includePartialMessages);
160
+ // Permission mode
161
+ this._appendPermissionArgs(args);
162
+ // Model
163
+ if (this.options.model && a.model) {
164
+ args.push(a.model, this.options.model);
165
+ }
166
+ // Resume
167
+ if (this.options.resumeSessionId && a.resume) {
168
+ args.push(a.resume, this.options.resumeSessionId);
169
+ }
170
+ // System prompts
171
+ if (this.options.systemPrompt && a.systemPrompt) {
172
+ args.push(a.systemPrompt, this.options.systemPrompt);
173
+ }
174
+ if (this.options.appendSystemPrompt && a.appendSystemPrompt) {
175
+ args.push(a.appendSystemPrompt, this.options.appendSystemPrompt);
176
+ }
177
+ // Limits
178
+ if (this.options.maxTurns && a.maxTurns) {
179
+ args.push(a.maxTurns, String(this.options.maxTurns));
180
+ }
181
+ // Skip permissions
182
+ if (this.options.dangerouslySkipPermissions && a.skipPermissions) {
183
+ args.push(a.skipPermissions);
184
+ }
185
+ // Effort
186
+ if (this.options.effort && this.options.effort !== 'auto' && a.effort) {
187
+ args.push(a.effort, this.options.effort);
188
+ }
189
+ // Extra static args
190
+ if (a.extra?.length)
191
+ args.push(...a.extra);
192
+ // Spawn environment
193
+ const spawnEnv = {
194
+ ...process.env,
195
+ PATH: process.env.PATH || '/usr/local/bin:/usr/bin:/bin',
196
+ ...this.engineConfig.env,
197
+ };
198
+ this.proc = spawn(this.engineBin, args, {
199
+ cwd: this.options.cwd,
200
+ env: spawnEnv,
201
+ stdio: ['pipe', 'pipe', 'pipe'],
202
+ detached: true,
203
+ });
204
+ this.proc.unref();
205
+ // Parse stdout line-by-line
206
+ this._rl = readline.createInterface({ input: this.proc.stdout, crlfDelay: Infinity });
207
+ this._rl.on('line', (line) => {
208
+ if (!line.trim())
209
+ return;
210
+ try {
211
+ const event = JSON.parse(line);
212
+ this._handlePersistentEvent(event);
213
+ }
214
+ catch {
215
+ this.emit(SESSION_EVENT.LOG, `[${this.engineConfig.name}-stdout] ${line}`);
216
+ }
217
+ });
218
+ this.proc.stderr?.on('data', (data) => {
219
+ this.emit(SESSION_EVENT.LOG, `[${this.engineConfig.name}-stderr] ${this.sanitize(data.toString())}`);
220
+ });
221
+ this.proc.on('close', (code) => {
222
+ this._isReady = false;
223
+ this.emit(SESSION_EVENT.CLOSE, code);
224
+ });
225
+ this.proc.on('error', (err) => {
226
+ this.emit(SESSION_EVENT.ERROR, err);
227
+ });
228
+ // Wait for ready
229
+ return new Promise((resolve, reject) => {
230
+ const timeout = setTimeout(() => reject(new Error(`Timeout waiting for ${this.engineConfig.name} session ready`)), SESSION_READY_TIMEOUT_MS);
231
+ this.once(SESSION_EVENT.READY, () => {
232
+ clearTimeout(timeout);
233
+ resolve(this);
234
+ });
235
+ this.once(SESSION_EVENT.ERROR, (err) => {
236
+ clearTimeout(timeout);
237
+ reject(err);
238
+ });
239
+ const onCloseBeforeReady = (code) => {
240
+ if (!this._isReady) {
241
+ clearTimeout(timeout);
242
+ reject(new Error(`${this.engineConfig.name} process exited prematurely with code ${code}. Session failed to start.`));
243
+ }
244
+ };
245
+ this.once(SESSION_EVENT.CLOSE, onCloseBeforeReady);
246
+ const onInit = () => {
247
+ if (!this._isReady) {
248
+ this._isReady = true;
249
+ this.removeListener(SESSION_EVENT.CLOSE, onCloseBeforeReady);
250
+ this.emit(SESSION_EVENT.READY);
251
+ }
252
+ };
253
+ this.once(SESSION_EVENT.INIT, onInit);
254
+ // Fallback: mark ready after 2s if no init event
255
+ setTimeout(() => {
256
+ this.removeListener(SESSION_EVENT.INIT, onInit);
257
+ if (this.proc?.killed || this.proc?.exitCode !== null) {
258
+ clearTimeout(timeout);
259
+ this.removeListener(SESSION_EVENT.CLOSE, onCloseBeforeReady);
260
+ reject(new Error(`${this.engineConfig.name} CLI crashed on startup. Fallback timer aborted.`));
261
+ return;
262
+ }
263
+ if (!this._isReady) {
264
+ this._isReady = true;
265
+ this.removeListener(SESSION_EVENT.CLOSE, onCloseBeforeReady);
266
+ this.emit(SESSION_EVENT.READY);
267
+ }
268
+ }, SESSION_READY_FALLBACK_MS);
269
+ });
270
+ }
271
+ // ── One-shot mode start ─────────────────────────────────────────────────
272
+ async _startOneShot() {
273
+ const eName = this.engineConfig.name;
274
+ this.sessionId = `${eName}-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;
275
+ this._startTime = new Date().toISOString();
276
+ this._isReady = true;
277
+ this.emit(SESSION_EVENT.READY);
278
+ this.emit(SESSION_EVENT.INIT, { type: 'system', subtype: 'init', session_id: this.sessionId });
279
+ return this;
280
+ }
281
+ // ─── Send ────────────────────────────────────────────────────────────────
282
+ async send(message, options = {}) {
283
+ if (!this._isReady)
284
+ throw new Error('Session not ready. Call start() first.');
285
+ if (this.engineConfig.persistent) {
286
+ return this._sendPersistent(message, options);
287
+ }
288
+ else {
289
+ return this._sendOneShot(message, options);
290
+ }
291
+ }
292
+ // ── Persistent mode send ────────────────────────────────────────────────
293
+ async _sendPersistent(message, options) {
294
+ if (!this.proc)
295
+ throw new Error('Session not ready. Call start() first.');
296
+ const requestId = ++this.currentRequestId;
297
+ let finalMessage = typeof message === 'string' ? message : message;
298
+ if (typeof finalMessage === 'string') {
299
+ if (options.effort === 'high' || options.effort === 'max') {
300
+ finalMessage = `ultrathink\n\n${finalMessage}`;
301
+ }
302
+ if (options.plan) {
303
+ finalMessage = `/plan ${finalMessage}`;
304
+ }
305
+ }
306
+ const payload = {
307
+ type: 'user',
308
+ message: {
309
+ role: 'user',
310
+ content: typeof finalMessage === 'string' ? [{ type: 'text', text: finalMessage }] : finalMessage,
311
+ },
312
+ };
313
+ this.proc.stdin.write(JSON.stringify(payload) + '\n');
314
+ if (options.callbacks)
315
+ this._streamCallbacks = options.callbacks;
316
+ if (options.waitForComplete) {
317
+ this._isBusy = true;
318
+ try {
319
+ return await this._waitForTurnComplete(options.timeout || TURN_TIMEOUT_MS);
320
+ }
321
+ finally {
322
+ this._isBusy = false;
323
+ if (options.callbacks)
324
+ this._streamCallbacks = null;
325
+ }
326
+ }
327
+ return { requestId, sent: true };
328
+ }
329
+ // ── One-shot mode send ──────────────────────────────────────────────────
330
+ async _sendOneShot(message, options) {
331
+ const requestId = ++this.currentRequestId;
332
+ const textMessage = typeof message === 'string' ? message : JSON.stringify(message);
333
+ if (!options.waitForComplete) {
334
+ this._runOneShot(textMessage, options).catch((err) => this.emit(SESSION_EVENT.ERROR, err));
335
+ return { requestId, sent: true };
336
+ }
337
+ this._isBusy = true;
338
+ try {
339
+ return await this._runOneShot(textMessage, options);
340
+ }
341
+ finally {
342
+ this._isBusy = false;
343
+ }
344
+ }
345
+ async _runOneShot(message, options) {
346
+ const a = this.engineConfig.args;
347
+ const args = [];
348
+ // Print mode + message
349
+ if (a.print)
350
+ args.push(a.print);
351
+ args.push(message);
352
+ // Output format
353
+ if (a.outputFormat && a.outputFormatValue)
354
+ args.push(a.outputFormat, a.outputFormatValue);
355
+ // Permission mode
356
+ this._appendPermissionArgs(args);
357
+ // Skip permissions
358
+ if (this.options.dangerouslySkipPermissions && a.skipPermissions) {
359
+ args.push(a.skipPermissions);
360
+ }
361
+ // Model
362
+ if (this.options.model && a.model)
363
+ args.push(a.model, this.options.model);
364
+ // System prompts
365
+ if (this.options.systemPrompt && a.systemPrompt) {
366
+ args.push(a.systemPrompt, this.options.systemPrompt);
367
+ }
368
+ // Max turns
369
+ if (this.options.maxTurns && a.maxTurns) {
370
+ args.push(a.maxTurns, String(this.options.maxTurns));
371
+ }
372
+ // Effort
373
+ if (this.options.effort && this.options.effort !== 'auto' && a.effort) {
374
+ args.push(a.effort, this.options.effort);
375
+ }
376
+ // Workspace
377
+ if (this.options.cwd && a.workspace) {
378
+ args.push(a.workspace, this.options.cwd);
379
+ }
380
+ // Extra static args
381
+ if (a.extra?.length)
382
+ args.push(...a.extra);
383
+ const timeout = options.timeout || 300_000;
384
+ const spawnEnv = {
385
+ ...process.env,
386
+ ...this.engineConfig.env,
387
+ };
388
+ return new Promise((resolve, reject) => {
389
+ const resultText = { value: '' };
390
+ let stderr = '';
391
+ let settled = false;
392
+ let gotUsageFromEvents = false;
393
+ const proc = spawn(this.engineBin, args, {
394
+ cwd: this.options.cwd,
395
+ env: spawnEnv,
396
+ stdio: ['pipe', 'pipe', 'pipe'],
397
+ });
398
+ this.currentProc = proc;
399
+ const timer = setTimeout(() => {
400
+ if (!settled) {
401
+ settled = true;
402
+ proc.kill('SIGTERM');
403
+ reject(new Error(`Timeout waiting for ${this.engineConfig.name} response`));
404
+ }
405
+ }, timeout);
406
+ const rl = readline.createInterface({ input: proc.stdout, crlfDelay: Infinity });
407
+ this._currentRl = rl;
408
+ rl.on('line', (line) => {
409
+ if (!line.trim())
410
+ return;
411
+ try {
412
+ const event = JSON.parse(line);
413
+ this._handleOneShotEvent(event, options, resultText, () => {
414
+ gotUsageFromEvents = true;
415
+ });
416
+ }
417
+ catch {
418
+ // Non-JSON line — treat as plain text
419
+ resultText.value += line + '\n';
420
+ try {
421
+ options.callbacks?.onText?.(line + '\n');
422
+ }
423
+ catch {
424
+ /* ignore callback errors */
425
+ }
426
+ this.emit(SESSION_EVENT.TEXT, line + '\n');
427
+ }
428
+ });
429
+ proc.stderr?.on('data', (data) => {
430
+ const sanitized = this.sanitize(data.toString());
431
+ stderr += sanitized;
432
+ this.emit(SESSION_EVENT.LOG, `[${this.engineConfig.name}-stderr] ${sanitized}`);
433
+ });
434
+ proc.on('close', (code) => {
435
+ clearTimeout(timer);
436
+ this.currentProc = null;
437
+ if (this._currentRl) {
438
+ this._currentRl.close();
439
+ this._currentRl = null;
440
+ }
441
+ if (settled)
442
+ return;
443
+ settled = true;
444
+ const now = new Date().toISOString();
445
+ this._stats.turns++;
446
+ this._stats.lastActivity = now;
447
+ if (!gotUsageFromEvents && resultText.value.length > 0) {
448
+ this._stats.tokensIn += estimateTokens(message);
449
+ this._stats.tokensOut += estimateTokens(resultText.value);
450
+ this._updateCost();
451
+ }
452
+ this._history.push({ time: now, type: 'result', event: { text: resultText.value, code } });
453
+ if (this._history.length > MAX_HISTORY_ITEMS)
454
+ this._history.shift();
455
+ const event = {
456
+ type: 'result',
457
+ result: resultText.value,
458
+ stop_reason: code === 0 ? 'end_turn' : 'error',
459
+ };
460
+ this.emit(SESSION_EVENT.RESULT, event);
461
+ this.emit(SESSION_EVENT.TURN_COMPLETE, event);
462
+ if (code !== 0 && !resultText.value) {
463
+ reject(new Error(stderr || `${this.engineConfig.name} exited with code ${code}`));
464
+ }
465
+ else if (code !== 0) {
466
+ reject(new Error(stderr || `${this.engineConfig.name} exited with code ${code}`));
467
+ }
468
+ else {
469
+ resolve({ text: resultText.value, event });
470
+ }
471
+ });
472
+ proc.on('error', (err) => {
473
+ clearTimeout(timer);
474
+ if (!settled) {
475
+ settled = true;
476
+ reject(err);
477
+ }
478
+ });
479
+ });
480
+ }
481
+ // ─── Event Handling (Persistent mode) ───────────────────────────────────
482
+ _handlePersistentEvent(event) {
483
+ const type = event.type;
484
+ this._stats.lastActivity = new Date().toISOString();
485
+ this._history.push({ time: this._stats.lastActivity, type, event });
486
+ if (this._history.length > MAX_HISTORY_ITEMS)
487
+ this._history.shift();
488
+ switch (type) {
489
+ case 'system':
490
+ if (event.subtype === 'init') {
491
+ this.sessionId = event.session_id;
492
+ this._startTime = new Date().toISOString();
493
+ this.emit(SESSION_EVENT.INIT, event);
494
+ }
495
+ this.emit(SESSION_EVENT.SYSTEM, event);
496
+ break;
497
+ case 'stream_event': {
498
+ const inner = event.event;
499
+ if (!inner)
500
+ break;
501
+ const innerType = inner.type;
502
+ if (innerType === 'content_block_start') {
503
+ const block = inner.content_block;
504
+ if (block?.type === 'tool_use') {
505
+ this._stats.toolCalls++;
506
+ const toolEvent = { tool: { name: block.name, input: {} } };
507
+ try {
508
+ this._streamCallbacks?.onToolUse?.(toolEvent);
509
+ }
510
+ catch {
511
+ /* ignore */
512
+ }
513
+ this.emit(SESSION_EVENT.TOOL_USE, toolEvent);
514
+ }
515
+ }
516
+ else if (innerType === 'content_block_delta') {
517
+ const delta = inner.delta;
518
+ if (delta?.type === 'text_delta' && delta.text) {
519
+ try {
520
+ this._streamCallbacks?.onText?.(delta.text);
521
+ }
522
+ catch {
523
+ /* ignore */
524
+ }
525
+ this.emit(SESSION_EVENT.TEXT, delta.text);
526
+ }
527
+ }
528
+ else if (innerType === 'message_delta') {
529
+ const usage = inner.usage;
530
+ if (usage) {
531
+ this._stats.tokensIn += usage.input_tokens || 0;
532
+ this._stats.tokensOut += usage.output_tokens || 0;
533
+ this._stats.cachedTokens += usage.cache_read_input_tokens || 0;
534
+ this._updateCost();
535
+ }
536
+ }
537
+ this.emit(SESSION_EVENT.STREAM_EVENT, event);
538
+ break;
539
+ }
540
+ case 'user':
541
+ this._stats.turns++;
542
+ this.emit(SESSION_EVENT.USER_ECHO, event);
543
+ break;
544
+ case 'assistant':
545
+ this.emit(SESSION_EVENT.ASSISTANT, event);
546
+ if (event.message?.content && Array.isArray(event.message.content)) {
547
+ for (const block of event.message.content) {
548
+ if (block.type === 'tool_use') {
549
+ this._stats.toolCalls++;
550
+ const toolEvent = {
551
+ tool: {
552
+ name: block.name,
553
+ input: block.input || {},
554
+ },
555
+ };
556
+ try {
557
+ this._streamCallbacks?.onToolUse?.(toolEvent);
558
+ }
559
+ catch {
560
+ /* ignore */
561
+ }
562
+ this.emit(SESSION_EVENT.TOOL_USE, toolEvent);
563
+ }
564
+ }
565
+ }
566
+ break;
567
+ case 'tool_use':
568
+ this._stats.toolCalls++;
569
+ try {
570
+ this._streamCallbacks?.onToolUse?.(event);
571
+ }
572
+ catch {
573
+ /* ignore */
574
+ }
575
+ this.emit(SESSION_EVENT.TOOL_USE, event);
576
+ break;
577
+ case 'tool_result':
578
+ try {
579
+ this._streamCallbacks?.onToolResult?.(event);
580
+ }
581
+ catch {
582
+ /* ignore */
583
+ }
584
+ if (event.is_error || event.error) {
585
+ this._stats.toolErrors++;
586
+ }
587
+ this.emit(SESSION_EVENT.TOOL_RESULT, event);
588
+ break;
589
+ case 'error':
590
+ this.emit(SESSION_EVENT.ERROR, new Error(String(event.error) || JSON.stringify(event)));
591
+ break;
592
+ case 'result': {
593
+ const usage = event.usage;
594
+ if (usage) {
595
+ this._stats.tokensIn += usage.input_tokens || 0;
596
+ this._stats.tokensOut += usage.output_tokens || 0;
597
+ this._stats.cachedTokens += usage.cache_read_input_tokens || 0;
598
+ this._updateCost();
599
+ }
600
+ this.emit(SESSION_EVENT.RESULT, event);
601
+ this.emit(SESSION_EVENT.TURN_COMPLETE, event);
602
+ const totalTokens = this._stats.tokensIn + this._stats.tokensOut;
603
+ if (totalTokens > CONTEXT_HIGH_THRESHOLD && !this._contextHighFired) {
604
+ this._contextHighFired = true;
605
+ }
606
+ break;
607
+ }
608
+ default:
609
+ this.emit(SESSION_EVENT.EVENT, event);
610
+ }
611
+ }
612
+ // ─── Event Handling (One-shot mode) ─────────────────────────────────────
613
+ _handleOneShotEvent(event, options, resultText, markUsageReceived) {
614
+ const type = event.type;
615
+ switch (type) {
616
+ case 'system':
617
+ if (event.session_id)
618
+ this.sessionId = String(event.session_id);
619
+ break;
620
+ case 'user':
621
+ // Echo of user prompt — skip
622
+ break;
623
+ case 'assistant': {
624
+ const msg = event.message;
625
+ if (!msg)
626
+ break;
627
+ const contentArr = msg.content;
628
+ if (contentArr) {
629
+ for (const block of contentArr) {
630
+ if (block.type === 'text' && block.text) {
631
+ resultText.value += block.text;
632
+ try {
633
+ options.callbacks?.onText?.(block.text);
634
+ }
635
+ catch {
636
+ /* ignore */
637
+ }
638
+ this.emit(SESSION_EVENT.TEXT, block.text);
639
+ }
640
+ }
641
+ }
642
+ break;
643
+ }
644
+ case 'message': {
645
+ if (event.role === 'user')
646
+ break;
647
+ const text = event.content || '';
648
+ if (text) {
649
+ resultText.value += text;
650
+ try {
651
+ options.callbacks?.onText?.(text);
652
+ }
653
+ catch {
654
+ /* ignore */
655
+ }
656
+ this.emit(SESSION_EVENT.TEXT, text);
657
+ }
658
+ break;
659
+ }
660
+ case 'tool_use':
661
+ this._stats.toolCalls++;
662
+ try {
663
+ options.callbacks?.onToolUse?.(event);
664
+ }
665
+ catch {
666
+ /* ignore */
667
+ }
668
+ this.emit(SESSION_EVENT.TOOL_USE, event);
669
+ break;
670
+ case 'tool_result':
671
+ try {
672
+ options.callbacks?.onToolResult?.(event);
673
+ }
674
+ catch {
675
+ /* ignore */
676
+ }
677
+ if (event.is_error)
678
+ this._stats.toolErrors++;
679
+ this.emit(SESSION_EVENT.TOOL_RESULT, event);
680
+ break;
681
+ case 'result': {
682
+ const usage = event.usage;
683
+ if (usage) {
684
+ this._stats.tokensIn += usage.input_tokens || usage.inputTokens || usage.prompt_tokens || 0;
685
+ this._stats.tokensOut += usage.output_tokens || usage.outputTokens || usage.completion_tokens || 0;
686
+ const cached = usage.cache_read_input_tokens || usage.cached_tokens || 0;
687
+ if (cached)
688
+ this._stats.cachedTokens += cached;
689
+ this._updateCost();
690
+ markUsageReceived();
691
+ }
692
+ const resultStr = event.result;
693
+ if (resultStr && !resultText.value)
694
+ resultText.value = resultStr;
695
+ break;
696
+ }
697
+ case 'error':
698
+ this.emit(SESSION_EVENT.LOG, `[${this.engineConfig.name}-error] ${event.error || JSON.stringify(event)}`);
699
+ break;
700
+ default:
701
+ break;
702
+ }
703
+ }
704
+ // ─── Wait for Turn Complete (Persistent mode) ───────────────────────────
705
+ _waitForTurnComplete(timeout) {
706
+ return new Promise((resolve, reject) => {
707
+ let settled = false;
708
+ let streamedText = '';
709
+ let allAssistantText = '';
710
+ const toolNames = [];
711
+ const onText = (chunk) => {
712
+ streamedText += chunk;
713
+ };
714
+ this.on(SESSION_EVENT.TEXT, onText);
715
+ const onAssistant = (event) => {
716
+ if (event.message?.content && Array.isArray(event.message.content)) {
717
+ for (const block of event.message.content) {
718
+ if (block.type === 'text' && block.text)
719
+ allAssistantText += block.text + '\n';
720
+ }
721
+ }
722
+ };
723
+ this.on(SESSION_EVENT.ASSISTANT, onAssistant);
724
+ const onToolUse = (event) => {
725
+ const tool = event.tool;
726
+ toolNames.push(tool?.name || event.name || 'unknown');
727
+ };
728
+ this.on(SESSION_EVENT.TOOL_USE, onToolUse);
729
+ const cleanup = () => {
730
+ clearTimeout(timer);
731
+ this.removeListener(SESSION_EVENT.TEXT, onText);
732
+ this.removeListener(SESSION_EVENT.ASSISTANT, onAssistant);
733
+ this.removeListener(SESSION_EVENT.TOOL_USE, onToolUse);
734
+ this.removeListener(SESSION_EVENT.TURN_COMPLETE, onTurnComplete);
735
+ this.removeListener(SESSION_EVENT.ERROR, onError);
736
+ this.removeListener(SESSION_EVENT.CLOSE, onClose);
737
+ };
738
+ const timer = setTimeout(() => {
739
+ if (settled)
740
+ return;
741
+ settled = true;
742
+ cleanup();
743
+ reject(new Error('Timeout waiting for response'));
744
+ }, timeout);
745
+ const onTurnComplete = (event) => {
746
+ if (settled)
747
+ return;
748
+ settled = true;
749
+ cleanup();
750
+ let text = event.result || streamedText || allAssistantText.trim() || '';
751
+ if (!text && toolNames.length > 0) {
752
+ const unique = [...new Set(toolNames)];
753
+ text = `[Agent completed ${toolNames.length} tool calls: ${unique.join(', ')}]`;
754
+ }
755
+ resolve({ text, event });
756
+ };
757
+ const onError = (err) => {
758
+ if (settled)
759
+ return;
760
+ settled = true;
761
+ cleanup();
762
+ reject(err);
763
+ };
764
+ const onClose = (code) => {
765
+ if (settled)
766
+ return;
767
+ settled = true;
768
+ cleanup();
769
+ const text = streamedText || allAssistantText.trim() || '';
770
+ resolve({
771
+ text,
772
+ event: {
773
+ type: 'result',
774
+ result: text,
775
+ stop_reason: 'process_exit',
776
+ exit_code: code,
777
+ },
778
+ });
779
+ };
780
+ this.once(SESSION_EVENT.TURN_COMPLETE, onTurnComplete);
781
+ this.once(SESSION_EVENT.ERROR, onError);
782
+ this.once(SESSION_EVENT.CLOSE, onClose);
783
+ });
784
+ }
785
+ // ─── Utilities ───────────────────────────────────────────────────────────
786
+ getStats() {
787
+ const ctxWindow = this.engineConfig.contextWindow ?? 200_000;
788
+ return {
789
+ turns: this._stats.turns,
790
+ toolCalls: this._stats.toolCalls,
791
+ toolErrors: this._stats.toolErrors,
792
+ tokensIn: this._stats.tokensIn,
793
+ tokensOut: this._stats.tokensOut,
794
+ cachedTokens: this._stats.cachedTokens,
795
+ costUsd: Math.round(this._stats.costUsd * 10000) / 10000,
796
+ isReady: this._isReady,
797
+ startTime: this._startTime,
798
+ lastActivity: this._stats.lastActivity,
799
+ contextPercent: this.engineConfig.persistent
800
+ ? Math.min(100, Math.round(((this._stats.tokensIn + this._stats.tokensOut) / ctxWindow) * 100))
801
+ : 0,
802
+ sessionId: this.sessionId,
803
+ uptime: this._startTime ? Math.round((Date.now() - new Date(this._startTime).getTime()) / 1000) : 0,
804
+ };
805
+ }
806
+ getHistory(limit = DEFAULT_HISTORY_LIMIT) {
807
+ return this._history.slice(-limit);
808
+ }
809
+ async compact(summary) {
810
+ if (!this.engineConfig.persistent) {
811
+ const event = {
812
+ type: 'result',
813
+ result: `${this.engineConfig.name} engine does not support compaction (one-shot mode)`,
814
+ };
815
+ return { text: event.result, event };
816
+ }
817
+ const msg = summary ? `/compact ${summary}` : '/compact';
818
+ return this.send(msg, { waitForComplete: true, timeout: COMPACT_TIMEOUT_MS });
819
+ }
820
+ getEffort() {
821
+ return this.options.effort || 'auto';
822
+ }
823
+ setEffort(level) {
824
+ this.options.effort = level;
825
+ }
826
+ getCost() {
827
+ const pricing = getModelPricing(this.options.model, this.engineConfig);
828
+ const cachedPrice = pricing.cached ?? 0;
829
+ const nonCachedIn = Math.max(0, this._stats.tokensIn - this._stats.cachedTokens);
830
+ return {
831
+ model: this.options.model || this.engineConfig.name,
832
+ tokensIn: this._stats.tokensIn,
833
+ tokensOut: this._stats.tokensOut,
834
+ cachedTokens: this._stats.cachedTokens,
835
+ pricing: { inputPer1M: pricing.input, outputPer1M: pricing.output, cachedPer1M: cachedPrice || undefined },
836
+ breakdown: {
837
+ inputCost: (nonCachedIn / 1_000_000) * pricing.input,
838
+ cachedCost: (this._stats.cachedTokens / 1_000_000) * cachedPrice,
839
+ outputCost: (this._stats.tokensOut / 1_000_000) * pricing.output,
840
+ },
841
+ totalUsd: this._stats.costUsd,
842
+ };
843
+ }
844
+ resolveModel(alias) {
845
+ return resolveAlias(alias);
846
+ }
847
+ pause() {
848
+ this._isPaused = true;
849
+ this.emit(SESSION_EVENT.PAUSED, { sessionId: this.sessionId });
850
+ }
851
+ resume() {
852
+ this._isPaused = false;
853
+ this.emit(SESSION_EVENT.RESUMED, { sessionId: this.sessionId });
854
+ }
855
+ stop() {
856
+ // Persistent mode cleanup
857
+ if (this._rl) {
858
+ this._rl.close();
859
+ this._rl = null;
860
+ }
861
+ if (this.proc) {
862
+ const pid = this.proc.pid;
863
+ this.proc.stdin?.end();
864
+ this.proc.stdout?.destroy();
865
+ this.proc.stderr?.destroy();
866
+ try {
867
+ process.kill(-pid, 'SIGTERM');
868
+ }
869
+ catch (err) {
870
+ if (err.code !== 'ESRCH') {
871
+ try {
872
+ this.proc.kill('SIGTERM');
873
+ }
874
+ catch {
875
+ /* ESRCH expected */
876
+ }
877
+ }
878
+ }
879
+ const p = this.proc;
880
+ setTimeout(() => {
881
+ try {
882
+ process.kill(-pid, 'SIGKILL');
883
+ }
884
+ catch {
885
+ /* ESRCH expected */
886
+ }
887
+ try {
888
+ p.kill('SIGKILL');
889
+ }
890
+ catch {
891
+ /* ESRCH expected */
892
+ }
893
+ }, STOP_SIGKILL_DELAY_MS);
894
+ this.proc = null;
895
+ }
896
+ // One-shot mode cleanup
897
+ if (this._currentRl) {
898
+ this._currentRl.close();
899
+ this._currentRl = null;
900
+ }
901
+ if (this.currentProc) {
902
+ this.currentProc.stdin?.end();
903
+ this.currentProc.stdout?.destroy();
904
+ this.currentProc.stderr?.destroy();
905
+ try {
906
+ this.currentProc.kill('SIGTERM');
907
+ }
908
+ catch {
909
+ /* ignore */
910
+ }
911
+ this.currentProc = null;
912
+ }
913
+ this._isReady = false;
914
+ this._isPaused = false;
915
+ this.emit(SESSION_EVENT.CLOSE, 143);
916
+ }
917
+ // ─── Private ─────────────────────────────────────────────────────────────
918
+ _appendPermissionArgs(args) {
919
+ const a = this.engineConfig.args;
920
+ const mode = this.options.permissionMode;
921
+ if (!mode || !a.permissionMode)
922
+ return;
923
+ // Map mode name if the engine uses different names
924
+ const mapped = this.engineConfig.permissionModes?.[mode] ?? mode;
925
+ args.push(a.permissionMode, mapped);
926
+ }
927
+ _updateCost() {
928
+ const pricing = getModelPricing(this.options.model, this.engineConfig);
929
+ const cachedPrice = pricing.cached ?? 0;
930
+ const nonCachedIn = Math.max(0, this._stats.tokensIn - this._stats.cachedTokens);
931
+ this._stats.costUsd =
932
+ (nonCachedIn / 1_000_000) * pricing.input +
933
+ (this._stats.cachedTokens / 1_000_000) * cachedPrice +
934
+ (this._stats.tokensOut / 1_000_000) * pricing.output;
935
+ }
936
+ }
937
+ //# sourceMappingURL=persistent-custom-session.js.map