@jini-ai/agent-runtime 0.1.0

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 (399) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +43 -0
  3. package/dist/acp-model-probe.d.ts +48 -0
  4. package/dist/acp-model-probe.d.ts.map +1 -0
  5. package/dist/acp-model-probe.js +15 -0
  6. package/dist/acp-model-probe.js.map +1 -0
  7. package/dist/agent-protocol/acp/account-failure.d.ts +54 -0
  8. package/dist/agent-protocol/acp/account-failure.d.ts.map +1 -0
  9. package/dist/agent-protocol/acp/account-failure.js +37 -0
  10. package/dist/agent-protocol/acp/account-failure.js.map +1 -0
  11. package/dist/agent-protocol/acp/constants.d.ts +26 -0
  12. package/dist/agent-protocol/acp/constants.d.ts.map +1 -0
  13. package/dist/agent-protocol/acp/constants.js +39 -0
  14. package/dist/agent-protocol/acp/constants.js.map +1 -0
  15. package/dist/agent-protocol/acp/index.d.ts +14 -0
  16. package/dist/agent-protocol/acp/index.d.ts.map +1 -0
  17. package/dist/agent-protocol/acp/index.js +14 -0
  18. package/dist/agent-protocol/acp/index.js.map +1 -0
  19. package/dist/agent-protocol/acp/json.d.ts +82 -0
  20. package/dist/agent-protocol/acp/json.d.ts.map +1 -0
  21. package/dist/agent-protocol/acp/json.js +144 -0
  22. package/dist/agent-protocol/acp/json.js.map +1 -0
  23. package/dist/agent-protocol/acp/models.d.ts +112 -0
  24. package/dist/agent-protocol/acp/models.d.ts.map +1 -0
  25. package/dist/agent-protocol/acp/models.js +293 -0
  26. package/dist/agent-protocol/acp/models.js.map +1 -0
  27. package/dist/agent-protocol/acp/rpc.d.ts +107 -0
  28. package/dist/agent-protocol/acp/rpc.d.ts.map +1 -0
  29. package/dist/agent-protocol/acp/rpc.js +162 -0
  30. package/dist/agent-protocol/acp/rpc.js.map +1 -0
  31. package/dist/agent-protocol/acp/session-params.d.ts +55 -0
  32. package/dist/agent-protocol/acp/session-params.d.ts.map +1 -0
  33. package/dist/agent-protocol/acp/session-params.js +81 -0
  34. package/dist/agent-protocol/acp/session-params.js.map +1 -0
  35. package/dist/agent-protocol/acp/session.d.ts +101 -0
  36. package/dist/agent-protocol/acp/session.d.ts.map +1 -0
  37. package/dist/agent-protocol/acp/session.js +832 -0
  38. package/dist/agent-protocol/acp/session.js.map +1 -0
  39. package/dist/agent-protocol/acp/text-suppression.d.ts +73 -0
  40. package/dist/agent-protocol/acp/text-suppression.d.ts.map +1 -0
  41. package/dist/agent-protocol/acp/text-suppression.js +229 -0
  42. package/dist/agent-protocol/acp/text-suppression.js.map +1 -0
  43. package/dist/agent-protocol/acp/types.d.ts +27 -0
  44. package/dist/agent-protocol/acp/types.d.ts.map +1 -0
  45. package/dist/agent-protocol/acp/types.js +2 -0
  46. package/dist/agent-protocol/acp/types.js.map +1 -0
  47. package/dist/agent-protocol/acp/updates.d.ts +166 -0
  48. package/dist/agent-protocol/acp/updates.d.ts.map +1 -0
  49. package/dist/agent-protocol/acp/updates.js +268 -0
  50. package/dist/agent-protocol/acp/updates.js.map +1 -0
  51. package/dist/agent-protocol/core/index.d.ts +6 -0
  52. package/dist/agent-protocol/core/index.d.ts.map +1 -0
  53. package/dist/agent-protocol/core/index.js +6 -0
  54. package/dist/agent-protocol/core/index.js.map +1 -0
  55. package/dist/agent-protocol/core/json-line-stream.d.ts +42 -0
  56. package/dist/agent-protocol/core/json-line-stream.d.ts.map +1 -0
  57. package/dist/agent-protocol/core/json-line-stream.js +333 -0
  58. package/dist/agent-protocol/core/json-line-stream.js.map +1 -0
  59. package/dist/agent-protocol/index.d.ts +8 -0
  60. package/dist/agent-protocol/index.d.ts.map +1 -0
  61. package/dist/agent-protocol/index.js +8 -0
  62. package/dist/agent-protocol/index.js.map +1 -0
  63. package/dist/agent-protocol/pi-rpc/events.d.ts +26 -0
  64. package/dist/agent-protocol/pi-rpc/events.d.ts.map +1 -0
  65. package/dist/agent-protocol/pi-rpc/events.js +167 -0
  66. package/dist/agent-protocol/pi-rpc/events.js.map +1 -0
  67. package/dist/agent-protocol/pi-rpc/index.d.ts +11 -0
  68. package/dist/agent-protocol/pi-rpc/index.d.ts.map +1 -0
  69. package/dist/agent-protocol/pi-rpc/index.js +11 -0
  70. package/dist/agent-protocol/pi-rpc/index.js.map +1 -0
  71. package/dist/agent-protocol/pi-rpc/internal.d.ts +45 -0
  72. package/dist/agent-protocol/pi-rpc/internal.d.ts.map +1 -0
  73. package/dist/agent-protocol/pi-rpc/internal.js +41 -0
  74. package/dist/agent-protocol/pi-rpc/internal.js.map +1 -0
  75. package/dist/agent-protocol/pi-rpc/models.d.ts +21 -0
  76. package/dist/agent-protocol/pi-rpc/models.d.ts.map +1 -0
  77. package/dist/agent-protocol/pi-rpc/models.js +48 -0
  78. package/dist/agent-protocol/pi-rpc/models.js.map +1 -0
  79. package/dist/agent-protocol/pi-rpc/session.d.ts +106 -0
  80. package/dist/agent-protocol/pi-rpc/session.d.ts.map +1 -0
  81. package/dist/agent-protocol/pi-rpc/session.js +371 -0
  82. package/dist/agent-protocol/pi-rpc/session.js.map +1 -0
  83. package/dist/amr-model-cache.d.ts +40 -0
  84. package/dist/amr-model-cache.d.ts.map +1 -0
  85. package/dist/amr-model-cache.js +79 -0
  86. package/dist/amr-model-cache.js.map +1 -0
  87. package/dist/amr-profile-resolver.d.ts +21 -0
  88. package/dist/amr-profile-resolver.d.ts.map +1 -0
  89. package/dist/amr-profile-resolver.js +4 -0
  90. package/dist/amr-profile-resolver.js.map +1 -0
  91. package/dist/artifact-taxonomy.d.ts +27 -0
  92. package/dist/artifact-taxonomy.d.ts.map +1 -0
  93. package/dist/artifact-taxonomy.js +5 -0
  94. package/dist/artifact-taxonomy.js.map +1 -0
  95. package/dist/auth.d.ts +25 -0
  96. package/dist/auth.d.ts.map +1 -0
  97. package/dist/auth.js +332 -0
  98. package/dist/auth.js.map +1 -0
  99. package/dist/capabilities.d.ts +9 -0
  100. package/dist/capabilities.d.ts.map +1 -0
  101. package/dist/capabilities.js +2 -0
  102. package/dist/capabilities.js.map +1 -0
  103. package/dist/claude-stream.d.ts +37 -0
  104. package/dist/claude-stream.d.ts.map +1 -0
  105. package/dist/claude-stream.js +660 -0
  106. package/dist/claude-stream.js.map +1 -0
  107. package/dist/copilot-stream.d.ts +37 -0
  108. package/dist/copilot-stream.d.ts.map +1 -0
  109. package/dist/copilot-stream.js +136 -0
  110. package/dist/copilot-stream.js.map +1 -0
  111. package/dist/defs/aider.d.ts +13 -0
  112. package/dist/defs/aider.d.ts.map +1 -0
  113. package/dist/defs/aider.js +63 -0
  114. package/dist/defs/aider.js.map +1 -0
  115. package/dist/defs/amp.d.ts +12 -0
  116. package/dist/defs/amp.d.ts.map +1 -0
  117. package/dist/defs/amp.js +56 -0
  118. package/dist/defs/amp.js.map +1 -0
  119. package/dist/defs/amr.d.ts +37 -0
  120. package/dist/defs/amr.d.ts.map +1 -0
  121. package/dist/defs/amr.js +303 -0
  122. package/dist/defs/amr.js.map +1 -0
  123. package/dist/defs/antigravity.d.ts +25 -0
  124. package/dist/defs/antigravity.d.ts.map +1 -0
  125. package/dist/defs/antigravity.js +213 -0
  126. package/dist/defs/antigravity.js.map +1 -0
  127. package/dist/defs/claude.d.ts +30 -0
  128. package/dist/defs/claude.d.ts.map +1 -0
  129. package/dist/defs/claude.js +130 -0
  130. package/dist/defs/claude.js.map +1 -0
  131. package/dist/defs/codebuddy.d.ts +26 -0
  132. package/dist/defs/codebuddy.d.ts.map +1 -0
  133. package/dist/defs/codebuddy.js +124 -0
  134. package/dist/defs/codebuddy.js.map +1 -0
  135. package/dist/defs/codex.d.ts +30 -0
  136. package/dist/defs/codex.d.ts.map +1 -0
  137. package/dist/defs/codex.js +196 -0
  138. package/dist/defs/codex.js.map +1 -0
  139. package/dist/defs/copilot.d.ts +12 -0
  140. package/dist/defs/copilot.d.ts.map +1 -0
  141. package/dist/defs/copilot.js +88 -0
  142. package/dist/defs/copilot.js.map +1 -0
  143. package/dist/defs/cursor-agent.d.ts +27 -0
  144. package/dist/defs/cursor-agent.d.ts.map +1 -0
  145. package/dist/defs/cursor-agent.js +93 -0
  146. package/dist/defs/cursor-agent.js.map +1 -0
  147. package/dist/defs/deepseek.d.ts +12 -0
  148. package/dist/defs/deepseek.d.ts.map +1 -0
  149. package/dist/defs/deepseek.js +53 -0
  150. package/dist/defs/deepseek.js.map +1 -0
  151. package/dist/defs/devin.d.ts +12 -0
  152. package/dist/defs/devin.d.ts.map +1 -0
  153. package/dist/defs/devin.js +45 -0
  154. package/dist/defs/devin.js.map +1 -0
  155. package/dist/defs/grok-build.d.ts +26 -0
  156. package/dist/defs/grok-build.d.ts.map +1 -0
  157. package/dist/defs/grok-build.js +105 -0
  158. package/dist/defs/grok-build.js.map +1 -0
  159. package/dist/defs/hermes.d.ts +13 -0
  160. package/dist/defs/hermes.d.ts.map +1 -0
  161. package/dist/defs/hermes.js +51 -0
  162. package/dist/defs/hermes.js.map +1 -0
  163. package/dist/defs/index.d.ts +33 -0
  164. package/dist/defs/index.d.ts.map +1 -0
  165. package/dist/defs/index.js +33 -0
  166. package/dist/defs/index.js.map +1 -0
  167. package/dist/defs/kilo.d.ts +12 -0
  168. package/dist/defs/kilo.d.ts.map +1 -0
  169. package/dist/defs/kilo.js +20 -0
  170. package/dist/defs/kilo.js.map +1 -0
  171. package/dist/defs/kimi.d.ts +13 -0
  172. package/dist/defs/kimi.d.ts.map +1 -0
  173. package/dist/defs/kimi.js +26 -0
  174. package/dist/defs/kimi.js.map +1 -0
  175. package/dist/defs/kiro.d.ts +12 -0
  176. package/dist/defs/kiro.d.ts.map +1 -0
  177. package/dist/defs/kiro.js +20 -0
  178. package/dist/defs/kiro.js.map +1 -0
  179. package/dist/defs/mimo.d.ts +13 -0
  180. package/dist/defs/mimo.d.ts.map +1 -0
  181. package/dist/defs/mimo.js +26 -0
  182. package/dist/defs/mimo.js.map +1 -0
  183. package/dist/defs/opencode.d.ts +27 -0
  184. package/dist/defs/opencode.d.ts.map +1 -0
  185. package/dist/defs/opencode.js +89 -0
  186. package/dist/defs/opencode.js.map +1 -0
  187. package/dist/defs/pi.d.ts +18 -0
  188. package/dist/defs/pi.d.ts.map +1 -0
  189. package/dist/defs/pi.js +94 -0
  190. package/dist/defs/pi.js.map +1 -0
  191. package/dist/defs/qoder.d.ts +11 -0
  192. package/dist/defs/qoder.d.ts.map +1 -0
  193. package/dist/defs/qoder.js +50 -0
  194. package/dist/defs/qoder.js.map +1 -0
  195. package/dist/defs/qwen.d.ts +11 -0
  196. package/dist/defs/qwen.d.ts.map +1 -0
  197. package/dist/defs/qwen.js +28 -0
  198. package/dist/defs/qwen.js.map +1 -0
  199. package/dist/defs/reasonix.d.ts +20 -0
  200. package/dist/defs/reasonix.d.ts.map +1 -0
  201. package/dist/defs/reasonix.js +60 -0
  202. package/dist/defs/reasonix.js.map +1 -0
  203. package/dist/defs/shared.d.ts +23 -0
  204. package/dist/defs/shared.d.ts.map +1 -0
  205. package/dist/defs/shared.js +58 -0
  206. package/dist/defs/shared.js.map +1 -0
  207. package/dist/defs/trae-cli.d.ts +14 -0
  208. package/dist/defs/trae-cli.d.ts.map +1 -0
  209. package/dist/defs/trae-cli.js +22 -0
  210. package/dist/defs/trae-cli.js.map +1 -0
  211. package/dist/defs/vibe.d.ts +12 -0
  212. package/dist/defs/vibe.d.ts.map +1 -0
  213. package/dist/defs/vibe.js +20 -0
  214. package/dist/defs/vibe.js.map +1 -0
  215. package/dist/detection.d.ts +14 -0
  216. package/dist/detection.d.ts.map +1 -0
  217. package/dist/detection.js +266 -0
  218. package/dist/detection.js.map +1 -0
  219. package/dist/diagnostics.d.ts +8 -0
  220. package/dist/diagnostics.d.ts.map +1 -0
  221. package/dist/diagnostics.js +95 -0
  222. package/dist/diagnostics.js.map +1 -0
  223. package/dist/env.d.ts +19 -0
  224. package/dist/env.d.ts.map +1 -0
  225. package/dist/env.js +95 -0
  226. package/dist/env.js.map +1 -0
  227. package/dist/executables.d.ts +24 -0
  228. package/dist/executables.d.ts.map +1 -0
  229. package/dist/executables.js +349 -0
  230. package/dist/executables.js.map +1 -0
  231. package/dist/index.d.ts +74 -0
  232. package/dist/index.d.ts.map +1 -0
  233. package/dist/index.js +102 -0
  234. package/dist/index.js.map +1 -0
  235. package/dist/invocation.d.ts +6 -0
  236. package/dist/invocation.d.ts.map +1 -0
  237. package/dist/invocation.js +47 -0
  238. package/dist/invocation.js.map +1 -0
  239. package/dist/json-event-stream.d.ts +9 -0
  240. package/dist/json-event-stream.d.ts.map +1 -0
  241. package/dist/json-event-stream.js +856 -0
  242. package/dist/json-event-stream.js.map +1 -0
  243. package/dist/launch.d.ts +12 -0
  244. package/dist/launch.d.ts.map +1 -0
  245. package/dist/launch.js +221 -0
  246. package/dist/launch.js.map +1 -0
  247. package/dist/mcp.d.ts +44 -0
  248. package/dist/mcp.d.ts.map +1 -0
  249. package/dist/mcp.js +12 -0
  250. package/dist/mcp.js.map +1 -0
  251. package/dist/metadata.d.ts +24 -0
  252. package/dist/metadata.d.ts.map +1 -0
  253. package/dist/metadata.js +100 -0
  254. package/dist/metadata.js.map +1 -0
  255. package/dist/mmd-routes.d.ts +12 -0
  256. package/dist/mmd-routes.d.ts.map +1 -0
  257. package/dist/mmd-routes.js +146 -0
  258. package/dist/mmd-routes.js.map +1 -0
  259. package/dist/model-registry.d.ts +120 -0
  260. package/dist/model-registry.d.ts.map +1 -0
  261. package/dist/model-registry.js +77 -0
  262. package/dist/model-registry.js.map +1 -0
  263. package/dist/models.d.ts +16 -0
  264. package/dist/models.d.ts.map +1 -0
  265. package/dist/models.js +93 -0
  266. package/dist/models.js.map +1 -0
  267. package/dist/opencode-log.d.ts +16 -0
  268. package/dist/opencode-log.d.ts.map +1 -0
  269. package/dist/opencode-log.js +163 -0
  270. package/dist/opencode-log.js.map +1 -0
  271. package/dist/paths.d.ts +3 -0
  272. package/dist/paths.d.ts.map +1 -0
  273. package/dist/paths.js +29 -0
  274. package/dist/paths.js.map +1 -0
  275. package/dist/pi-models.d.ts +13 -0
  276. package/dist/pi-models.d.ts.map +1 -0
  277. package/dist/pi-models.js +36 -0
  278. package/dist/pi-models.js.map +1 -0
  279. package/dist/prompt-augmenter.d.ts +60 -0
  280. package/dist/prompt-augmenter.d.ts.map +1 -0
  281. package/dist/prompt-augmenter.js +26 -0
  282. package/dist/prompt-augmenter.js.map +1 -0
  283. package/dist/prompt-budget.d.ts +20 -0
  284. package/dist/prompt-budget.d.ts.map +1 -0
  285. package/dist/prompt-budget.js +226 -0
  286. package/dist/prompt-budget.js.map +1 -0
  287. package/dist/prompt-file.d.ts +7 -0
  288. package/dist/prompt-file.d.ts.map +1 -0
  289. package/dist/prompt-file.js +27 -0
  290. package/dist/prompt-file.js.map +1 -0
  291. package/dist/providers/aihubmix.d.ts +99 -0
  292. package/dist/providers/aihubmix.d.ts.map +1 -0
  293. package/dist/providers/aihubmix.js +239 -0
  294. package/dist/providers/aihubmix.js.map +1 -0
  295. package/dist/providers/anthropic-messages.d.ts +116 -0
  296. package/dist/providers/anthropic-messages.d.ts.map +1 -0
  297. package/dist/providers/anthropic-messages.js +313 -0
  298. package/dist/providers/anthropic-messages.js.map +1 -0
  299. package/dist/providers/azure-chat.d.ts +99 -0
  300. package/dist/providers/azure-chat.d.ts.map +1 -0
  301. package/dist/providers/azure-chat.js +164 -0
  302. package/dist/providers/azure-chat.js.map +1 -0
  303. package/dist/providers/connection-guard.d.ts +67 -0
  304. package/dist/providers/connection-guard.d.ts.map +1 -0
  305. package/dist/providers/connection-guard.js +211 -0
  306. package/dist/providers/connection-guard.js.map +1 -0
  307. package/dist/providers/elevenlabs.d.ts +28 -0
  308. package/dist/providers/elevenlabs.d.ts.map +1 -0
  309. package/dist/providers/elevenlabs.js +138 -0
  310. package/dist/providers/elevenlabs.js.map +1 -0
  311. package/dist/providers/google-messages.d.ts +108 -0
  312. package/dist/providers/google-messages.d.ts.map +1 -0
  313. package/dist/providers/google-messages.js +284 -0
  314. package/dist/providers/google-messages.js.map +1 -0
  315. package/dist/providers/google.d.ts +20 -0
  316. package/dist/providers/google.d.ts.map +1 -0
  317. package/dist/providers/google.js +42 -0
  318. package/dist/providers/google.js.map +1 -0
  319. package/dist/providers/index.d.ts +39 -0
  320. package/dist/providers/index.d.ts.map +1 -0
  321. package/dist/providers/index.js +39 -0
  322. package/dist/providers/index.js.map +1 -0
  323. package/dist/providers/model-catalog.d.ts +32 -0
  324. package/dist/providers/model-catalog.d.ts.map +1 -0
  325. package/dist/providers/model-catalog.js +394 -0
  326. package/dist/providers/model-catalog.js.map +1 -0
  327. package/dist/providers/oauth-callback-server.d.ts +35 -0
  328. package/dist/providers/oauth-callback-server.d.ts.map +1 -0
  329. package/dist/providers/oauth-callback-server.js +217 -0
  330. package/dist/providers/oauth-callback-server.js.map +1 -0
  331. package/dist/providers/oauth-credentials.d.ts +29 -0
  332. package/dist/providers/oauth-credentials.d.ts.map +1 -0
  333. package/dist/providers/oauth-credentials.js +70 -0
  334. package/dist/providers/oauth-credentials.js.map +1 -0
  335. package/dist/providers/oauth-provider.d.ts +95 -0
  336. package/dist/providers/oauth-provider.d.ts.map +1 -0
  337. package/dist/providers/oauth-provider.js +130 -0
  338. package/dist/providers/oauth-provider.js.map +1 -0
  339. package/dist/providers/oauth-tokens.d.ts +35 -0
  340. package/dist/providers/oauth-tokens.d.ts.map +1 -0
  341. package/dist/providers/oauth-tokens.js +136 -0
  342. package/dist/providers/oauth-tokens.js.map +1 -0
  343. package/dist/providers/ollama-chat.d.ts +106 -0
  344. package/dist/providers/ollama-chat.d.ts.map +1 -0
  345. package/dist/providers/ollama-chat.js +292 -0
  346. package/dist/providers/ollama-chat.js.map +1 -0
  347. package/dist/providers/openai-chat.d.ts +147 -0
  348. package/dist/providers/openai-chat.d.ts.map +1 -0
  349. package/dist/providers/openai-chat.js +302 -0
  350. package/dist/providers/openai-chat.js.map +1 -0
  351. package/dist/providers/pkce.d.ts +81 -0
  352. package/dist/providers/pkce.d.ts.map +1 -0
  353. package/dist/providers/pkce.js +176 -0
  354. package/dist/providers/pkce.js.map +1 -0
  355. package/dist/providers/sse-decode.d.ts +47 -0
  356. package/dist/providers/sse-decode.d.ts.map +1 -0
  357. package/dist/providers/sse-decode.js +109 -0
  358. package/dist/providers/sse-decode.js.map +1 -0
  359. package/dist/providers/token-params.d.ts +29 -0
  360. package/dist/providers/token-params.d.ts.map +1 -0
  361. package/dist/providers/token-params.js +41 -0
  362. package/dist/providers/token-params.js.map +1 -0
  363. package/dist/providers/turn-end-guard.d.ts +37 -0
  364. package/dist/providers/turn-end-guard.d.ts.map +1 -0
  365. package/dist/providers/turn-end-guard.js +42 -0
  366. package/dist/providers/turn-end-guard.js.map +1 -0
  367. package/dist/providers/types.d.ts +36 -0
  368. package/dist/providers/types.d.ts.map +1 -0
  369. package/dist/providers/types.js +13 -0
  370. package/dist/providers/types.js.map +1 -0
  371. package/dist/qoder-stream.d.ts +19 -0
  372. package/dist/qoder-stream.d.ts.map +1 -0
  373. package/dist/qoder-stream.js +167 -0
  374. package/dist/qoder-stream.js.map +1 -0
  375. package/dist/registry.d.ts +5 -0
  376. package/dist/registry.d.ts.map +1 -0
  377. package/dist/registry.js +58 -0
  378. package/dist/registry.js.map +1 -0
  379. package/dist/resolution.d.ts +2 -0
  380. package/dist/resolution.d.ts.map +1 -0
  381. package/dist/resolution.js +19 -0
  382. package/dist/resolution.js.map +1 -0
  383. package/dist/role-marker-guard.d.ts +53 -0
  384. package/dist/role-marker-guard.d.ts.map +1 -0
  385. package/dist/role-marker-guard.js +280 -0
  386. package/dist/role-marker-guard.js.map +1 -0
  387. package/dist/telemetry-sink.d.ts +35 -0
  388. package/dist/telemetry-sink.d.ts.map +1 -0
  389. package/dist/telemetry-sink.js +5 -0
  390. package/dist/telemetry-sink.js.map +1 -0
  391. package/dist/terminal-launch.d.ts +11 -0
  392. package/dist/terminal-launch.d.ts.map +1 -0
  393. package/dist/terminal-launch.js +123 -0
  394. package/dist/terminal-launch.js.map +1 -0
  395. package/dist/types.d.ts +185 -0
  396. package/dist/types.d.ts.map +1 -0
  397. package/dist/types.js +2 -0
  398. package/dist/types.js.map +1 -0
  399. package/package.json +47 -0
@@ -0,0 +1,856 @@
1
+ function isRecord(value) {
2
+ return value != null && typeof value === 'object' && !Array.isArray(value);
3
+ }
4
+ function safeParseJson(value) {
5
+ if (value == null)
6
+ return null;
7
+ if (typeof value === 'object')
8
+ return value;
9
+ if (typeof value !== 'string')
10
+ return null;
11
+ try {
12
+ return JSON.parse(value);
13
+ }
14
+ catch {
15
+ return null;
16
+ }
17
+ }
18
+ function stringifyContent(value) {
19
+ if (typeof value === 'string')
20
+ return value;
21
+ if (value == null)
22
+ return '';
23
+ try {
24
+ return JSON.stringify(value);
25
+ }
26
+ catch {
27
+ // Genuinely unreachable through this module's real call graph, not just
28
+ // unobserved: every one of this function's 8 call sites passes either
29
+ // `obj` itself or a field/subfield of `obj` (e.g. `statePart.output`,
30
+ // `obj.content`, `item.aggregated_output`), and `obj` is only ever
31
+ // produced one way in this file — `handleLine`'s `obj = JSON.parse(line)`
32
+ // (this module's sole exported entry point, `createJsonEventStreamHandler`,
33
+ // routes every event through it). A value that came out of `JSON.parse`
34
+ // can only be `null`/a string/a plain finite number/a boolean/an array/a
35
+ // plain object — the JSON grammar has no circular-reference or BigInt
36
+ // production — so `JSON.stringify` can never throw on it or on any of
37
+ // its nested fields. Kept (not deleted) as protection against a future
38
+ // caller that feeds this module data from somewhere other than
39
+ // `JSON.parse`, the same "keep the defensive branch, document it, don't
40
+ // force a test around impossible data" call `@jini-ai/cli`'s
41
+ // `defaultReadFile`'s `finish()` guard made on 2026-07-22 — see
42
+ // `source-map.md`'s 2026-07-22 entry for the full re-derivation.
43
+ return String(value);
44
+ }
45
+ }
46
+ function parseJsonObjectsFromContent(value) {
47
+ // No `!trimmed` early-return: this function's only real call site
48
+ // (`connectorToolSelectionErrorMessage`, below) has already checked
49
+ // `content.includes('CONNECTOR_TOOL_NOT_FOUND')` before calling in, so
50
+ // `value` can never trim down to empty here. The guard was dead code for
51
+ // every real caller; removed rather than padded with a test, since the
52
+ // fallback path below already produces the same `[]` result for an empty
53
+ // string on its own (safeParseJson('') throws -> null -> not a record;
54
+ // ''.split(/\r?\n/u) yields [''] -> same outcome), so nothing changes
55
+ // for a hypothetical future caller either.
56
+ const trimmed = value.trim();
57
+ const direct = safeParseJson(trimmed);
58
+ if (isRecord(direct))
59
+ return [direct];
60
+ const objects = [];
61
+ for (const line of trimmed.split(/\r?\n/u)) {
62
+ const parsedLine = safeParseJson(line.trim());
63
+ if (isRecord(parsedLine))
64
+ objects.push(parsedLine);
65
+ }
66
+ return objects;
67
+ }
68
+ function extractConnectorApiError(value) {
69
+ if (isRecord(value.error)) {
70
+ if (typeof value.error.code === 'string')
71
+ return value.error;
72
+ if (isRecord(value.error.data) && isRecord(value.error.data.error)) {
73
+ const wrappedError = value.error.data.error;
74
+ if (typeof wrappedError.code === 'string')
75
+ return wrappedError;
76
+ }
77
+ }
78
+ return null;
79
+ }
80
+ function connectorToolSelectionErrorMessage(content) {
81
+ if (!content.includes('CONNECTOR_TOOL_NOT_FOUND'))
82
+ return null;
83
+ let error = null;
84
+ for (const parsed of parseJsonObjectsFromContent(content)) {
85
+ const parsedError = extractConnectorApiError(parsed);
86
+ if (parsedError?.code === 'CONNECTOR_TOOL_NOT_FOUND') {
87
+ error = parsedError;
88
+ break;
89
+ }
90
+ }
91
+ if (!error)
92
+ return null;
93
+ const details = isRecord(error.details) ? error.details : {};
94
+ const connectorId = typeof details.connectorId === 'string' && details.connectorId
95
+ ? details.connectorId
96
+ : undefined;
97
+ const toolName = typeof details.toolName === 'string' && details.toolName
98
+ ? details.toolName
99
+ : 'the requested connector tool';
100
+ const target = connectorId
101
+ ? `Connector tool ${toolName} is not allowed for connector ${connectorId}.`
102
+ : `Connector tool ${toolName} is not allowed.`;
103
+ return `${target} Re-list the connector catalog and choose one of the currently allowed read-only tools.`;
104
+ }
105
+ function extractErrorMessage(value, fallback) {
106
+ if (typeof value === 'string') {
107
+ const parsed = safeParseJson(value);
108
+ if (parsed && typeof parsed === 'object') {
109
+ return extractErrorMessage(parsed, value);
110
+ }
111
+ return value;
112
+ }
113
+ if (isRecord(value)) {
114
+ if (typeof value.detail === 'string' && value.detail)
115
+ return value.detail;
116
+ if (typeof value.message === 'string' && value.message) {
117
+ return extractErrorMessage(value.message, value.message);
118
+ }
119
+ if (typeof value.error === 'string' && value.error)
120
+ return value.error;
121
+ if (value.error && typeof value.error === 'object') {
122
+ return extractErrorMessage(value.error, fallback);
123
+ }
124
+ if (value.data && typeof value.data === 'object') {
125
+ const dataMessage = extractErrorMessage(value.data, '');
126
+ if (dataMessage)
127
+ return dataMessage;
128
+ }
129
+ if (typeof value.name === 'string' && value.name)
130
+ return value.name;
131
+ }
132
+ return fallback;
133
+ }
134
+ function isRecoverableCodexReconnect(message) {
135
+ return (message.startsWith('Reconnecting...') &&
136
+ (message.includes('timeout waiting for child process to exit') ||
137
+ message.includes('stream disconnected before completion')));
138
+ }
139
+ function formatOpenCodeUsage(tokens) {
140
+ if (!isRecord(tokens))
141
+ return null;
142
+ const usage = {};
143
+ if (typeof tokens.input === 'number')
144
+ usage.input_tokens = tokens.input;
145
+ if (typeof tokens.output === 'number')
146
+ usage.output_tokens = tokens.output;
147
+ if (typeof tokens.reasoning === 'number')
148
+ usage.thought_tokens = tokens.reasoning;
149
+ if (isRecord(tokens.cache)) {
150
+ if (typeof tokens.cache.read === 'number')
151
+ usage.cached_read_tokens = tokens.cache.read;
152
+ if (typeof tokens.cache.write === 'number')
153
+ usage.cached_write_tokens = tokens.cache.write;
154
+ }
155
+ return Object.keys(usage).length > 0 ? usage : null;
156
+ }
157
+ function handleOpenCodeEvent(obj, onEvent, state) {
158
+ if (!isRecord(obj))
159
+ return false;
160
+ const part = isRecord(obj.part) ? obj.part : {};
161
+ if (obj.type === 'step_start') {
162
+ // `sessionID` is OpenCode's own session handle (capture-style resume).
163
+ // Surface it on the step-start status so the daemon can persist it to
164
+ // `agent_sessions` and replay it as `run -s <id>` next turn. OpenCode
165
+ // stamps it on every stream event; step_start is the turn opener, so a
166
+ // create turn always exposes it here.
167
+ const sessionId = typeof obj.sessionID === 'string' && obj.sessionID.length > 0
168
+ ? obj.sessionID
169
+ : null;
170
+ onEvent({ type: 'status', label: 'running', sessionId });
171
+ return true;
172
+ }
173
+ if (obj.type === 'text' && typeof part.text === 'string' && part.text.length > 0) {
174
+ onEvent({ type: 'text_delta', delta: part.text });
175
+ return true;
176
+ }
177
+ if (obj.type === 'tool_use' && typeof part.tool === 'string' && typeof part.callID === 'string') {
178
+ const statePart = isRecord(part.state) ? part.state : null;
179
+ const key = `${obj.sessionID || 'session'}:${part.callID}`;
180
+ if (!state.openCodeToolUses.has(key)) {
181
+ state.openCodeToolUses.add(key);
182
+ onEvent({
183
+ type: 'tool_use',
184
+ id: part.callID,
185
+ name: part.tool,
186
+ input: safeParseJson(statePart?.input) ?? statePart?.input ?? null,
187
+ });
188
+ }
189
+ if (statePart?.status === 'completed') {
190
+ onEvent({
191
+ type: 'tool_result',
192
+ toolUseId: part.callID,
193
+ content: stringifyContent(statePart.output),
194
+ isError: false,
195
+ });
196
+ }
197
+ return true;
198
+ }
199
+ if (obj.type === 'step_finish') {
200
+ const usage = formatOpenCodeUsage(part.tokens);
201
+ if (usage) {
202
+ onEvent({
203
+ type: 'usage',
204
+ usage,
205
+ costUsd: typeof part.cost === 'number' ? part.cost : undefined,
206
+ });
207
+ }
208
+ return true;
209
+ }
210
+ if (obj.type === 'error') {
211
+ // OpenCode emits structured error frames on stdout (e.g. provider auth
212
+ // failures, network errors, schema mismatches) and still exits 0. Surface
213
+ // them as proper `error` events so server.ts's `sendAgentEvent` wrapper
214
+ // can flip the run to `failed` and forward a visible SSE error to the
215
+ // chat UI. Previously we downgraded these to `type:'raw'`, which is not
216
+ // rendered as an assistant message — the run looked like a fast clean
217
+ // success while the user actually got nothing back. See issue #691.
218
+ //
219
+ // Shape mirrors the qoder-stream contract (`{type, message, raw}`) so
220
+ // the daemon's existing error-handling path recognises it without
221
+ // further wiring.
222
+ const message = extractErrorMessage(obj.error ?? obj.message, 'OpenCode error');
223
+ onEvent({ type: 'error', message, raw: stringifyContent(obj) });
224
+ return true;
225
+ }
226
+ return false;
227
+ }
228
+ function handleGeminiEvent(obj, onEvent, state) {
229
+ if (!isRecord(obj))
230
+ return false;
231
+ const isAssistantTextMessage = obj.type === 'message' &&
232
+ obj.role === 'assistant' &&
233
+ typeof obj.content === 'string' &&
234
+ obj.content.length > 0;
235
+ if (!isAssistantTextMessage) {
236
+ flushPendingArtifactText(state, onEvent);
237
+ }
238
+ if (obj.type === 'init') {
239
+ onEvent({
240
+ type: 'status',
241
+ label: 'initializing',
242
+ model: typeof obj.model === 'string' ? obj.model : undefined,
243
+ });
244
+ return true;
245
+ }
246
+ if (obj.type === 'message' && obj.role === 'user') {
247
+ return true;
248
+ }
249
+ if (obj.type === 'message' &&
250
+ obj.role === 'assistant' &&
251
+ typeof obj.content === 'string' &&
252
+ obj.content.length > 0) {
253
+ const delta = stripDuplicateArtifactText(obj.content, state);
254
+ if (delta)
255
+ onEvent({ type: 'text_delta', delta });
256
+ return true;
257
+ }
258
+ if (obj.type === 'tool_use' &&
259
+ typeof obj.tool_id === 'string' &&
260
+ typeof obj.tool_name === 'string') {
261
+ const input = safeParseJson(obj.parameters) ?? obj.parameters ?? null;
262
+ if (obj.tool_name === 'write_todos') {
263
+ const todoInput = todoWriteInputFromParsedValue(input);
264
+ if (todoInput) {
265
+ onEvent({
266
+ type: 'tool_use',
267
+ id: `${obj.tool_id}:todo-native`,
268
+ name: 'TodoWrite',
269
+ input: todoInput,
270
+ });
271
+ return true;
272
+ }
273
+ }
274
+ if (isFileWriteToolUse(obj.tool_name, input)) {
275
+ state.suppressNextArtifactText = true;
276
+ }
277
+ onEvent({
278
+ type: 'tool_use',
279
+ id: obj.tool_id,
280
+ name: obj.tool_name,
281
+ input,
282
+ });
283
+ return true;
284
+ }
285
+ if (obj.type === 'tool_result' && typeof obj.tool_id === 'string') {
286
+ const error = isRecord(obj.error) ? obj.error : null;
287
+ const errorMessage = error ? extractErrorMessage(error, '') : '';
288
+ const output = typeof obj.output === 'string'
289
+ ? obj.output
290
+ : errorMessage || stringifyContent(obj.output);
291
+ onEvent({
292
+ type: 'tool_result',
293
+ toolUseId: obj.tool_id,
294
+ content: output,
295
+ isError: obj.status === 'error' || Boolean(error),
296
+ });
297
+ return true;
298
+ }
299
+ if (obj.type === 'error') {
300
+ const severity = typeof obj.severity === 'string' ? obj.severity.toLowerCase() : '';
301
+ const message = extractErrorMessage(obj.message ?? obj.error, severity === 'warning' ? 'Gemini CLI warning' : 'Gemini CLI error');
302
+ if (severity === 'warning') {
303
+ onEvent({ type: 'status', label: 'warning', detail: message });
304
+ }
305
+ else {
306
+ onEvent({ type: 'error', message, raw: stringifyContent(obj) });
307
+ }
308
+ return true;
309
+ }
310
+ if (obj.type === 'result') {
311
+ if (obj.status === 'error' || isRecord(obj.error)) {
312
+ onEvent({
313
+ type: 'error',
314
+ message: extractErrorMessage(obj.error, 'Gemini CLI error'),
315
+ raw: stringifyContent(obj),
316
+ });
317
+ return true;
318
+ }
319
+ if (!isRecord(obj.stats))
320
+ return true;
321
+ const usage = {};
322
+ if (typeof obj.stats.input_tokens === 'number')
323
+ usage.input_tokens = obj.stats.input_tokens;
324
+ if (typeof obj.stats.output_tokens === 'number')
325
+ usage.output_tokens = obj.stats.output_tokens;
326
+ if (typeof obj.stats.cached === 'number')
327
+ usage.cached_read_tokens = obj.stats.cached;
328
+ onEvent({
329
+ type: 'usage',
330
+ usage,
331
+ durationMs: typeof obj.stats.duration_ms === 'number' ? obj.stats.duration_ms : undefined,
332
+ });
333
+ return true;
334
+ }
335
+ return false;
336
+ }
337
+ function handleKimiEvent(obj, onEvent) {
338
+ if (!isRecord(obj))
339
+ return false;
340
+ if (obj.role === 'assistant' && Array.isArray(obj.tool_calls)) {
341
+ for (const rawCall of obj.tool_calls) {
342
+ const call = isRecord(rawCall) ? rawCall : null;
343
+ const fn = isRecord(call?.function) ? call.function : null;
344
+ const id = typeof call?.id === 'string' && call.id.trim()
345
+ ? call.id.trim()
346
+ : null;
347
+ const name = typeof fn?.name === 'string' && fn.name.trim()
348
+ ? fn.name.trim()
349
+ : null;
350
+ if (!id || !name)
351
+ continue;
352
+ const input = safeParseJson(fn?.arguments) ?? fn?.arguments ?? null;
353
+ onEvent({ type: 'tool_use', id, name, input });
354
+ }
355
+ return true;
356
+ }
357
+ if (obj.role === 'tool' &&
358
+ typeof obj.tool_call_id === 'string' &&
359
+ obj.tool_call_id.trim()) {
360
+ onEvent({
361
+ type: 'tool_result',
362
+ toolUseId: obj.tool_call_id.trim(),
363
+ content: stringifyContent(obj.content),
364
+ isError: false,
365
+ });
366
+ return true;
367
+ }
368
+ if (obj.role === 'assistant' &&
369
+ typeof obj.content === 'string' &&
370
+ obj.content.length > 0) {
371
+ onEvent({ type: 'text_delta', delta: obj.content });
372
+ return true;
373
+ }
374
+ if (obj.role === 'meta' && obj.type === 'session.resume_hint') {
375
+ return true;
376
+ }
377
+ return false;
378
+ }
379
+ function extractCursorText(message) {
380
+ const content = isRecord(message) ? message.content : undefined;
381
+ const blocks = Array.isArray(content) ? content : [];
382
+ return blocks
383
+ .filter((block) => isRecord(block) && block.type === 'text' && typeof block.text === 'string')
384
+ .map((block) => block.text)
385
+ .join('');
386
+ }
387
+ function normalizeTodoStatus(value) {
388
+ const status = typeof value === 'string'
389
+ ? value.trim().toLowerCase().replace(/[-\s]+/g, '_')
390
+ : '';
391
+ if (status === 'completed' || status === 'complete' || status === 'done' || status.startsWith('completed')) {
392
+ return 'completed';
393
+ }
394
+ if (status === 'in_progress' || status === 'doing' || status === 'active' || status.startsWith('in_progress')) {
395
+ return 'in_progress';
396
+ }
397
+ if (status === 'stopped' ||
398
+ status === 'failed' ||
399
+ status === 'blocked' ||
400
+ status === 'canceled' ||
401
+ status === 'cancelled' ||
402
+ status.startsWith('stopped') ||
403
+ status.startsWith('failed') ||
404
+ status.startsWith('blocked') ||
405
+ status.startsWith('canceled') ||
406
+ status.startsWith('cancelled')) {
407
+ return 'stopped';
408
+ }
409
+ return 'pending';
410
+ }
411
+ // Takes `unknown[]`, not `unknown`: every real call site
412
+ // (`todoWriteInputFromParsedValue`'s three call sites and
413
+ // `codexTodoListInput`) already runs `Array.isArray(...)` before calling in,
414
+ // so a runtime `!Array.isArray` guard here was dead code for every real
415
+ // caller. Narrowed the parameter type to remove the branch instead of
416
+ // padding a test around unreachable data.
417
+ function todoWriteInputFromItems(items) {
418
+ const todos = items
419
+ .map((raw) => {
420
+ if (!isRecord(raw))
421
+ return null;
422
+ const content = typeof raw.content === 'string'
423
+ ? raw.content
424
+ : typeof raw.label === 'string'
425
+ ? raw.label
426
+ : typeof raw.description === 'string'
427
+ ? raw.description
428
+ : typeof raw.text === 'string'
429
+ ? raw.text
430
+ : '';
431
+ if (!content)
432
+ return null;
433
+ return {
434
+ content,
435
+ status: raw.completed === true
436
+ ? 'completed'
437
+ : normalizeTodoStatus(raw.status),
438
+ };
439
+ })
440
+ .filter((todo) => todo !== null);
441
+ return todos.length > 0 ? { todos } : null;
442
+ }
443
+ function todoWriteInputFromParsedValue(value) {
444
+ if (Array.isArray(value))
445
+ return todoWriteInputFromItems(value);
446
+ if (!isRecord(value))
447
+ return null;
448
+ if (Array.isArray(value.todos))
449
+ return todoWriteInputFromItems(value.todos);
450
+ if (Array.isArray(value.todo))
451
+ return todoWriteInputFromItems(value.todo);
452
+ return null;
453
+ }
454
+ function stripDuplicateArtifactText(text, state) {
455
+ if (!state.suppressNextArtifactText &&
456
+ !state.suppressDuplicateArtifactText &&
457
+ state.artifactOpenCandidate.length === 0) {
458
+ return text;
459
+ }
460
+ const openTag = '<artifact';
461
+ const current = `${state.artifactOpenCandidate}${text}`;
462
+ state.artifactOpenCandidate = '';
463
+ if (state.suppressDuplicateArtifactText) {
464
+ const closeIndex = current.indexOf('</artifact>');
465
+ if (closeIndex === -1)
466
+ return '';
467
+ state.suppressDuplicateArtifactText = false;
468
+ state.suppressNextArtifactText = false;
469
+ return stripDuplicateArtifactText(current.slice(closeIndex + '</artifact>'.length), state);
470
+ }
471
+ const openIndex = current.indexOf(openTag);
472
+ if (openIndex === -1) {
473
+ const candidateLength = artifactOpenCandidateLength(current, openTag);
474
+ if (state.suppressNextArtifactText && candidateLength > 0) {
475
+ state.artifactOpenCandidate = current.slice(-candidateLength);
476
+ return current.slice(0, -candidateLength);
477
+ }
478
+ // Reaching here with `suppressNextArtifactText` false is structurally
479
+ // unreachable. To get past the top guard without it, `artifactOpenCandidate`
480
+ // must have been non-empty at entry — but the only place that sets a
481
+ // non-empty candidate is the branch right above (which requires this same
482
+ // flag to be true when it does), and the only place that clears the
483
+ // candidate other than the unconditional reset at the top of this function
484
+ // (`flushPendingArtifactText`) clears the flag in the same breath. So a
485
+ // leftover non-empty candidate always implies the flag is still true too.
486
+ // No `if` needed — it's always true by the time we get here.
487
+ state.suppressNextArtifactText = false;
488
+ return current;
489
+ }
490
+ state.suppressDuplicateArtifactText = true;
491
+ state.suppressNextArtifactText = false;
492
+ const prefix = `${state.pendingArtifactText}${current.slice(0, openIndex)}`;
493
+ state.pendingArtifactText = '';
494
+ return `${prefix}${stripDuplicateArtifactText(current.slice(openIndex), state)}`;
495
+ }
496
+ function artifactOpenCandidateLength(text, openTag) {
497
+ const max = Math.min(openTag.length - 1, text.length);
498
+ for (let len = max; len > 0; len -= 1) {
499
+ if (openTag.startsWith(text.slice(-len)))
500
+ return len;
501
+ }
502
+ return 0;
503
+ }
504
+ function flushPendingArtifactText(state, onEvent) {
505
+ const delta = `${state.pendingArtifactText}${state.artifactOpenCandidate}`;
506
+ if (!delta)
507
+ return;
508
+ state.pendingArtifactText = '';
509
+ state.artifactOpenCandidate = '';
510
+ state.suppressNextArtifactText = false;
511
+ onEvent({ type: 'text_delta', delta });
512
+ }
513
+ function isFileWriteToolUse(toolName, input) {
514
+ if (!isRecord(input))
515
+ return false;
516
+ const path = typeof input.file_path === 'string'
517
+ ? input.file_path
518
+ : typeof input.path === 'string'
519
+ ? input.path
520
+ : '';
521
+ const writesFile = toolName === 'write_file' ||
522
+ toolName === 'write' ||
523
+ toolName === 'replace' ||
524
+ toolName === 'edit';
525
+ if (!writesFile)
526
+ return false;
527
+ if (/\.(html|htm|css|js|jsx|ts|tsx|md)$/iu.test(path))
528
+ return true;
529
+ return typeof input.content === 'string' || typeof input.new_string === 'string';
530
+ }
531
+ function codexTodoListInput(item) {
532
+ if (item.type !== 'todo_list' || !Array.isArray(item.items))
533
+ return null;
534
+ return todoWriteInputFromItems(item.items);
535
+ }
536
+ function emitCodexTodoList(item, onEvent) {
537
+ if (typeof item.id !== 'string')
538
+ return false;
539
+ const input = codexTodoListInput(item);
540
+ if (!input)
541
+ return false;
542
+ onEvent({
543
+ type: 'tool_use',
544
+ id: item.id,
545
+ name: 'TodoWrite',
546
+ input,
547
+ });
548
+ return true;
549
+ }
550
+ function emitCursorTextDelta(text, onEvent, state) {
551
+ // Timestamped assistant events WITHOUT `model_call_id` are cursor-agent's
552
+ // real-time incremental deltas (`--stream-partial-output`): the final turn
553
+ // text is the in-order concatenation of every such delta. Emit each one
554
+ // verbatim — do NOT dedupe by content. Legitimately repeated deltas
555
+ // (`"ha"`, `"ha"` -> `"haha"`) or a delta that happens to be a prefix of
556
+ // earlier text are real content, not duplicates; content-based prefix or
557
+ // equality checks would silently drop them. Duplicate suppression and
558
+ // dropped-chunk recovery belong to the buffered terminal replay paths
559
+ // (`model_call_id` and no-timestamp events) via reconcileCursorTurnReplay.
560
+ //
561
+ // No `!text` guard: this function's only real call site
562
+ // (`handleCursorEvent`, below) already returns early on `if (!text) return
563
+ // false;` before ever calling in, so `text` is always non-empty here. The
564
+ // guard was dead code for the one real caller; removed rather than padded
565
+ // with a test.
566
+ state.cursorTextSoFar += text;
567
+ onEvent({ type: 'text_delta', delta: text });
568
+ }
569
+ /**
570
+ * Reconcile a Cursor terminal replay against the text already emitted for the
571
+ * CURRENT turn. A terminal replay (either a `model_call_id` message or a
572
+ * non-timestamped final assistant message) carries the full text for the
573
+ * current turn only, so it must be compared against
574
+ * `cursorTextSoFar.slice(cursorTurnStart)` — NOT the whole cross-turn buffer,
575
+ * which would miss the current-turn prefix on later turns and re-append the
576
+ * whole replay (duplicate output like "secondsecond turn").
577
+ *
578
+ * Only a verified prefix permits suffix recovery: if the emitted turn text is
579
+ * a prefix of the replay (including the empty case where no chunk arrived),
580
+ * emit the missing suffix. On divergence (a non-final chunk was dropped, so
581
+ * the emitted text is not a prefix) leave the append-only stream untouched
582
+ * rather than duplicate already-shown text. Always advances the turn boundary.
583
+ */
584
+ function reconcileCursorTurnReplay(text, onEvent, state) {
585
+ const emittedTurn = state.cursorTextSoFar.slice(state.cursorTurnStart);
586
+ if (text && text !== emittedTurn && text.startsWith(emittedTurn)) {
587
+ const suffix = text.slice(emittedTurn.length);
588
+ if (suffix)
589
+ onEvent({ type: 'text_delta', delta: suffix });
590
+ state.cursorTextSoFar += suffix;
591
+ }
592
+ state.cursorTurnStart = state.cursorTextSoFar.length;
593
+ }
594
+ function handleCursorEvent(obj, onEvent, state) {
595
+ if (!isRecord(obj))
596
+ return false;
597
+ if (obj.type === 'system' && obj.subtype === 'init') {
598
+ onEvent({
599
+ type: 'status',
600
+ label: 'initializing',
601
+ model: typeof obj.model === 'string' ? obj.model : undefined,
602
+ });
603
+ return true;
604
+ }
605
+ if (obj.type === 'assistant' && obj.message) {
606
+ // Cursor sends a final assistant message that replays the full text for
607
+ // the current turn — either tagged with `model_call_id`, or (fallback)
608
+ // as a non-timestamped terminal assistant message. Both are reconciled
609
+ // against the current turn's emitted text via reconcileCursorTurnReplay.
610
+ if (typeof obj.model_call_id === 'string') {
611
+ const text = extractCursorText(obj.message);
612
+ reconcileCursorTurnReplay(text, onEvent, state);
613
+ return true;
614
+ }
615
+ const text = extractCursorText(obj.message);
616
+ if (!text)
617
+ return false;
618
+ if (typeof obj.timestamp_ms === 'number') {
619
+ // Incremental streaming chunk within a turn — accumulate as usual.
620
+ emitCursorTextDelta(text, onEvent, state);
621
+ return true;
622
+ }
623
+ // Non-timestamped final assistant message: a terminal replay that marks a
624
+ // turn boundary. Reconcile against the current turn (not the whole
625
+ // cross-turn buffer) so later fallback-terminated turns do not duplicate
626
+ // output, then advance the turn boundary.
627
+ reconcileCursorTurnReplay(text, onEvent, state);
628
+ return true;
629
+ }
630
+ if (obj.type === 'result' && isRecord(obj.usage)) {
631
+ const usage = {};
632
+ if (typeof obj.usage.inputTokens === 'number')
633
+ usage.input_tokens = obj.usage.inputTokens;
634
+ if (typeof obj.usage.outputTokens === 'number')
635
+ usage.output_tokens = obj.usage.outputTokens;
636
+ if (typeof obj.usage.cacheReadTokens === 'number') {
637
+ usage.cached_read_tokens = obj.usage.cacheReadTokens;
638
+ }
639
+ if (typeof obj.usage.cacheWriteTokens === 'number') {
640
+ usage.cached_write_tokens = obj.usage.cacheWriteTokens;
641
+ }
642
+ onEvent({
643
+ type: 'usage',
644
+ usage,
645
+ durationMs: typeof obj.duration_ms === 'number' ? obj.duration_ms : undefined,
646
+ });
647
+ return true;
648
+ }
649
+ return false;
650
+ }
651
+ function handleCodexEvent(obj, onEvent, state) {
652
+ if (!isRecord(obj))
653
+ return false;
654
+ if (obj.type === 'error') {
655
+ const message = extractErrorMessage(obj.message ?? obj.error, 'Codex error');
656
+ // Reconnecting events are recoverable — treat as status warning, not fatal
657
+ if (isRecoverableCodexReconnect(message)) {
658
+ onEvent({ type: 'status', label: message });
659
+ return true;
660
+ }
661
+ if (!state.codexErrorEmitted) {
662
+ state.codexErrorEmitted = true;
663
+ onEvent({ type: 'error', message });
664
+ }
665
+ return true;
666
+ }
667
+ if (obj.type === 'turn.failed') {
668
+ if (!state.codexErrorEmitted) {
669
+ state.codexErrorEmitted = true;
670
+ onEvent({
671
+ type: 'error',
672
+ message: extractErrorMessage(obj.error ?? obj.message, 'Codex turn failed'),
673
+ });
674
+ }
675
+ return true;
676
+ }
677
+ if (obj.type === 'thread.started') {
678
+ // `thread_id` is Codex's own session handle, surfaced on the same
679
+ // `sessionId` status channel claude uses (claude-stream.ts). It serves two
680
+ // consumers: (1) the daemon persists it to `agent_sessions` and replays it
681
+ // as `exec resume <thread_id>` on the next turn (capture-style resume), and
682
+ // (2) it identifies this run's rollout file
683
+ // (`$CODEX_HOME/sessions/**/rollout-*-<thread_id>.jsonl`), the only place
684
+ // codex records per-call usage, which run_finished reads to recover the
685
+ // turn's first-call cache hit (codex's stream usage is cumulative only).
686
+ // Codex emits this both for a fresh `exec` and for `exec resume` (echoing
687
+ // the resumed id), so it is a stable capture point either way.
688
+ const threadId = typeof obj.thread_id === 'string' && obj.thread_id.length > 0
689
+ ? obj.thread_id
690
+ : null;
691
+ onEvent({ type: 'status', label: 'initializing', sessionId: threadId });
692
+ return true;
693
+ }
694
+ if (obj.type === 'turn.started') {
695
+ state.codexPreviousEventWasAgentMessage = false;
696
+ state.codexLastAgentMessageEndedWithNewline = false;
697
+ onEvent({ type: 'status', label: 'thinking' });
698
+ return true;
699
+ }
700
+ if (obj.type === 'item.started' && isRecord(obj.item)) {
701
+ const item = obj.item;
702
+ if (emitCodexTodoList(item, onEvent)) {
703
+ state.codexPreviousEventWasAgentMessage = false;
704
+ state.codexLastAgentMessageEndedWithNewline = false;
705
+ return true;
706
+ }
707
+ if (item.type === 'command_execution' && typeof item.id === 'string') {
708
+ state.codexPreviousEventWasAgentMessage = false;
709
+ state.codexLastAgentMessageEndedWithNewline = false;
710
+ if (!state.codexToolUses.has(item.id)) {
711
+ state.codexToolUses.add(item.id);
712
+ onEvent({
713
+ type: 'tool_use',
714
+ id: item.id,
715
+ name: 'Bash',
716
+ input: {
717
+ command: typeof item.command === 'string' ? item.command : '',
718
+ },
719
+ });
720
+ }
721
+ return true;
722
+ }
723
+ }
724
+ if (obj.type === 'item.updated' && isRecord(obj.item)) {
725
+ const item = obj.item;
726
+ if (emitCodexTodoList(item, onEvent)) {
727
+ state.codexPreviousEventWasAgentMessage = false;
728
+ state.codexLastAgentMessageEndedWithNewline = false;
729
+ return true;
730
+ }
731
+ }
732
+ if (obj.type === 'item.completed' && isRecord(obj.item)) {
733
+ const item = obj.item;
734
+ if (emitCodexTodoList(item, onEvent)) {
735
+ state.codexPreviousEventWasAgentMessage = false;
736
+ state.codexLastAgentMessageEndedWithNewline = false;
737
+ return true;
738
+ }
739
+ if (item.type === 'command_execution' && typeof item.id === 'string') {
740
+ state.codexPreviousEventWasAgentMessage = false;
741
+ state.codexLastAgentMessageEndedWithNewline = false;
742
+ if (!state.codexToolUses.has(item.id)) {
743
+ state.codexToolUses.add(item.id);
744
+ onEvent({
745
+ type: 'tool_use',
746
+ id: item.id,
747
+ name: 'Bash',
748
+ input: {
749
+ command: typeof item.command === 'string' ? item.command : '',
750
+ },
751
+ });
752
+ }
753
+ const content = stringifyContent(item.aggregated_output ?? '');
754
+ onEvent({
755
+ type: 'tool_result',
756
+ toolUseId: item.id,
757
+ content,
758
+ isError: typeof item.exit_code === 'number' ? item.exit_code !== 0 : item.status === 'failed',
759
+ });
760
+ const connectorToolError = connectorToolSelectionErrorMessage(content);
761
+ if (connectorToolError && !state.codexErrorEmitted) {
762
+ state.codexErrorEmitted = true;
763
+ onEvent({ type: 'error', message: connectorToolError });
764
+ }
765
+ return true;
766
+ }
767
+ }
768
+ if (obj.type === 'item.completed' &&
769
+ isRecord(obj.item) &&
770
+ obj.item.type === 'agent_message' &&
771
+ typeof obj.item.text === 'string' &&
772
+ obj.item.text.length > 0) {
773
+ const text = obj.item.text;
774
+ const needsBoundary = state.codexPreviousEventWasAgentMessage &&
775
+ !state.codexLastAgentMessageEndedWithNewline &&
776
+ !text.startsWith('\n');
777
+ const delta = needsBoundary ? `\n${text}` : text;
778
+ onEvent({ type: 'text_delta', delta });
779
+ state.codexPreviousEventWasAgentMessage = true;
780
+ state.codexLastAgentMessageEndedWithNewline = text.endsWith('\n');
781
+ return true;
782
+ }
783
+ if (obj.type === 'turn.completed' && isRecord(obj.usage)) {
784
+ const usage = {};
785
+ if (typeof obj.usage.input_tokens === 'number')
786
+ usage.input_tokens = obj.usage.input_tokens;
787
+ if (typeof obj.usage.output_tokens === 'number')
788
+ usage.output_tokens = obj.usage.output_tokens;
789
+ if (typeof obj.usage.reasoning_output_tokens === 'number') {
790
+ usage.thought_tokens = obj.usage.reasoning_output_tokens;
791
+ }
792
+ if (typeof obj.usage.cached_input_tokens === 'number') {
793
+ usage.cached_read_tokens = obj.usage.cached_input_tokens;
794
+ }
795
+ onEvent({ type: 'usage', usage });
796
+ return true;
797
+ }
798
+ return false;
799
+ }
800
+ export function createJsonEventStreamHandler(kind, onEvent) {
801
+ let buffer = '';
802
+ const state = {
803
+ cursorTextSoFar: '',
804
+ cursorTurnStart: 0,
805
+ openCodeToolUses: new Set(),
806
+ codexToolUses: new Set(),
807
+ codexErrorEmitted: false,
808
+ codexPreviousEventWasAgentMessage: false,
809
+ codexLastAgentMessageEndedWithNewline: false,
810
+ suppressNextArtifactText: false,
811
+ suppressDuplicateArtifactText: false,
812
+ artifactOpenCandidate: '',
813
+ pendingArtifactText: '',
814
+ };
815
+ function handleLine(line) {
816
+ let obj;
817
+ try {
818
+ obj = JSON.parse(line);
819
+ }
820
+ catch {
821
+ onEvent({ type: 'raw', line });
822
+ return;
823
+ }
824
+ if (kind === 'opencode' && handleOpenCodeEvent(obj, onEvent, state))
825
+ return;
826
+ if (kind === 'gemini' && handleGeminiEvent(obj, onEvent, state))
827
+ return;
828
+ if (kind === 'kimi' && handleKimiEvent(obj, onEvent))
829
+ return;
830
+ if (kind === 'cursor-agent' && handleCursorEvent(obj, onEvent, state))
831
+ return;
832
+ if (kind === 'codex' && handleCodexEvent(obj, onEvent, state))
833
+ return;
834
+ onEvent({ type: 'raw', line });
835
+ }
836
+ function feed(chunk) {
837
+ buffer += chunk;
838
+ let nl;
839
+ while ((nl = buffer.indexOf('\n')) !== -1) {
840
+ const line = buffer.slice(0, nl).trim();
841
+ buffer = buffer.slice(nl + 1);
842
+ if (!line)
843
+ continue;
844
+ handleLine(line);
845
+ }
846
+ }
847
+ function flush() {
848
+ const rem = buffer.trim();
849
+ buffer = '';
850
+ if (rem)
851
+ handleLine(rem);
852
+ flushPendingArtifactText(state, onEvent);
853
+ }
854
+ return { feed, flush };
855
+ }
856
+ //# sourceMappingURL=json-event-stream.js.map