@kortix/sdk 0.9.98

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 (618) hide show
  1. package/README.md +313 -0
  2. package/dist/files/client.d.ts +96 -0
  3. package/dist/files/client.d.ts.map +1 -0
  4. package/dist/files/client.js +346 -0
  5. package/dist/files/client.js.map +1 -0
  6. package/dist/files/types.d.ts +82 -0
  7. package/dist/files/types.d.ts.map +1 -0
  8. package/dist/files/types.js +6 -0
  9. package/dist/files/types.js.map +1 -0
  10. package/dist/index.d.ts +119 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +93 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/kortix.d.ts +897 -0
  15. package/dist/kortix.d.ts.map +1 -0
  16. package/dist/kortix.js +772 -0
  17. package/dist/kortix.js.map +1 -0
  18. package/dist/opencode/client.d.ts +89 -0
  19. package/dist/opencode/client.d.ts.map +1 -0
  20. package/dist/opencode/client.js +191 -0
  21. package/dist/opencode/client.js.map +1 -0
  22. package/dist/opencode/env.d.ts +13 -0
  23. package/dist/opencode/env.d.ts.map +1 -0
  24. package/dist/opencode/env.js +63 -0
  25. package/dist/opencode/env.js.map +1 -0
  26. package/dist/opencode/kortix-master.d.ts +487 -0
  27. package/dist/opencode/kortix-master.d.ts.map +1 -0
  28. package/dist/opencode/kortix-master.js +313 -0
  29. package/dist/opencode/kortix-master.js.map +1 -0
  30. package/dist/opencode/triggers.d.ts +6 -0
  31. package/dist/opencode/triggers.d.ts.map +1 -0
  32. package/dist/opencode/triggers.js +34 -0
  33. package/dist/opencode/triggers.js.map +1 -0
  34. package/dist/platform/api/errors.d.ts +106 -0
  35. package/dist/platform/api/errors.d.ts.map +1 -0
  36. package/dist/platform/api/errors.js +137 -0
  37. package/dist/platform/api/errors.js.map +1 -0
  38. package/dist/platform/api-client.d.ts +35 -0
  39. package/dist/platform/api-client.d.ts.map +1 -0
  40. package/dist/platform/api-client.js +279 -0
  41. package/dist/platform/api-client.js.map +1 -0
  42. package/dist/platform/auth-core.d.ts +60 -0
  43. package/dist/platform/auth-core.d.ts.map +1 -0
  44. package/dist/platform/auth-core.js +104 -0
  45. package/dist/platform/auth-core.js.map +1 -0
  46. package/dist/platform/auth.d.ts +88 -0
  47. package/dist/platform/auth.d.ts.map +1 -0
  48. package/dist/platform/auth.js +161 -0
  49. package/dist/platform/auth.js.map +1 -0
  50. package/dist/platform/config-node.d.ts +33 -0
  51. package/dist/platform/config-node.d.ts.map +1 -0
  52. package/dist/platform/config-node.js +63 -0
  53. package/dist/platform/config-node.js.map +1 -0
  54. package/dist/platform/config.d.ts +77 -0
  55. package/dist/platform/config.d.ts.map +1 -0
  56. package/dist/platform/config.js +62 -0
  57. package/dist/platform/config.js.map +1 -0
  58. package/dist/platform/feature-flags.d.ts +25 -0
  59. package/dist/platform/feature-flags.d.ts.map +1 -0
  60. package/dist/platform/feature-flags.js +114 -0
  61. package/dist/platform/feature-flags.js.map +1 -0
  62. package/dist/platform/fresh-sessions.d.ts +4 -0
  63. package/dist/platform/fresh-sessions.d.ts.map +1 -0
  64. package/dist/platform/fresh-sessions.js +22 -0
  65. package/dist/platform/fresh-sessions.js.map +1 -0
  66. package/dist/platform/instance-routes.d.ts +17 -0
  67. package/dist/platform/instance-routes.d.ts.map +1 -0
  68. package/dist/platform/instance-routes.js +105 -0
  69. package/dist/platform/instance-routes.js.map +1 -0
  70. package/dist/platform/logger.d.ts +20 -0
  71. package/dist/platform/logger.d.ts.map +1 -0
  72. package/dist/platform/logger.js +44 -0
  73. package/dist/platform/logger.js.map +1 -0
  74. package/dist/platform/opencode-errors.d.ts +20 -0
  75. package/dist/platform/opencode-errors.d.ts.map +1 -0
  76. package/dist/platform/opencode-errors.js +71 -0
  77. package/dist/platform/opencode-errors.js.map +1 -0
  78. package/dist/platform/platform-client/backups.d.ts +22 -0
  79. package/dist/platform/platform-client/backups.d.ts.map +1 -0
  80. package/dist/platform/platform-client/backups.js +16 -0
  81. package/dist/platform/platform-client/backups.js.map +1 -0
  82. package/dist/platform/platform-client/index.d.ts +21 -0
  83. package/dist/platform/platform-client/index.d.ts.map +1 -0
  84. package/dist/platform/platform-client/index.js +21 -0
  85. package/dist/platform/platform-client/index.js.map +1 -0
  86. package/dist/platform/platform-client/instance-admin.d.ts +67 -0
  87. package/dist/platform/platform-client/instance-admin.d.ts.map +1 -0
  88. package/dist/platform/platform-client/instance-admin.js +59 -0
  89. package/dist/platform/platform-client/instance-admin.js.map +1 -0
  90. package/dist/platform/platform-client/invites.d.ts +35 -0
  91. package/dist/platform/platform-client/invites.d.ts.map +1 -0
  92. package/dist/platform/platform-client/invites.js +25 -0
  93. package/dist/platform/platform-client/invites.js.map +1 -0
  94. package/dist/platform/platform-client/lifecycle.d.ts +78 -0
  95. package/dist/platform/platform-client/lifecycle.d.ts.map +1 -0
  96. package/dist/platform/platform-client/lifecycle.js +151 -0
  97. package/dist/platform/platform-client/lifecycle.js.map +1 -0
  98. package/dist/platform/platform-client/members.d.ts +81 -0
  99. package/dist/platform/platform-client/members.d.ts.map +1 -0
  100. package/dist/platform/platform-client/members.js +59 -0
  101. package/dist/platform/platform-client/members.js.map +1 -0
  102. package/dist/platform/platform-client/shared.d.ts +44 -0
  103. package/dist/platform/platform-client/shared.d.ts.map +1 -0
  104. package/dist/platform/platform-client/shared.js +177 -0
  105. package/dist/platform/platform-client/shared.js.map +1 -0
  106. package/dist/platform/platform-client/ssh.d.ts +29 -0
  107. package/dist/platform/platform-client/ssh.d.ts.map +1 -0
  108. package/dist/platform/platform-client/ssh.js +14 -0
  109. package/dist/platform/platform-client/ssh.js.map +1 -0
  110. package/dist/platform/platform-client/types.d.ts +56 -0
  111. package/dist/platform/platform-client/types.d.ts.map +1 -0
  112. package/dist/platform/platform-client/types.js +19 -0
  113. package/dist/platform/platform-client/types.js.map +1 -0
  114. package/dist/platform/platform-client/updates.d.ts +117 -0
  115. package/dist/platform/platform-client/updates.d.ts.map +1 -0
  116. package/dist/platform/platform-client/updates.js +97 -0
  117. package/dist/platform/platform-client/updates.js.map +1 -0
  118. package/dist/platform/platform-client/urls.d.ts +18 -0
  119. package/dist/platform/platform-client/urls.d.ts.map +1 -0
  120. package/dist/platform/platform-client/urls.js +31 -0
  121. package/dist/platform/platform-client/urls.js.map +1 -0
  122. package/dist/platform/projects-client/access.d.ts +273 -0
  123. package/dist/platform/projects-client/access.d.ts.map +1 -0
  124. package/dist/platform/projects-client/access.js +89 -0
  125. package/dist/platform/projects-client/access.js.map +1 -0
  126. package/dist/platform/projects-client/accounts.d.ts +184 -0
  127. package/dist/platform/projects-client/accounts.d.ts.map +1 -0
  128. package/dist/platform/projects-client/accounts.js +78 -0
  129. package/dist/platform/projects-client/accounts.js.map +1 -0
  130. package/dist/platform/projects-client/agent-config.d.ts +58 -0
  131. package/dist/platform/projects-client/agent-config.d.ts.map +1 -0
  132. package/dist/platform/projects-client/agent-config.js +9 -0
  133. package/dist/platform/projects-client/agent-config.js.map +1 -0
  134. package/dist/platform/projects-client/agent-scope.d.ts +12 -0
  135. package/dist/platform/projects-client/agent-scope.d.ts.map +1 -0
  136. package/dist/platform/projects-client/agent-scope.js +6 -0
  137. package/dist/platform/projects-client/agent-scope.js.map +1 -0
  138. package/dist/platform/projects-client/apps.d.ts +98 -0
  139. package/dist/platform/projects-client/apps.d.ts.map +1 -0
  140. package/dist/platform/projects-client/apps.js +29 -0
  141. package/dist/platform/projects-client/apps.js.map +1 -0
  142. package/dist/platform/projects-client/audit.d.ts +85 -0
  143. package/dist/platform/projects-client/audit.d.ts.map +1 -0
  144. package/dist/platform/projects-client/audit.js +51 -0
  145. package/dist/platform/projects-client/audit.js.map +1 -0
  146. package/dist/platform/projects-client/billing.d.ts +336 -0
  147. package/dist/platform/projects-client/billing.d.ts.map +1 -0
  148. package/dist/platform/projects-client/billing.js +260 -0
  149. package/dist/platform/projects-client/billing.js.map +1 -0
  150. package/dist/platform/projects-client/change-requests.d.ts +119 -0
  151. package/dist/platform/projects-client/change-requests.d.ts.map +1 -0
  152. package/dist/platform/projects-client/change-requests.js +56 -0
  153. package/dist/platform/projects-client/change-requests.js.map +1 -0
  154. package/dist/platform/projects-client/channels.d.ts +135 -0
  155. package/dist/platform/projects-client/channels.d.ts.map +1 -0
  156. package/dist/platform/projects-client/channels.js +103 -0
  157. package/dist/platform/projects-client/channels.js.map +1 -0
  158. package/dist/platform/projects-client/connectors.d.ts +148 -0
  159. package/dist/platform/projects-client/connectors.d.ts.map +1 -0
  160. package/dist/platform/projects-client/connectors.js +66 -0
  161. package/dist/platform/projects-client/connectors.js.map +1 -0
  162. package/dist/platform/projects-client/files.d.ts +37 -0
  163. package/dist/platform/projects-client/files.d.ts.map +1 -0
  164. package/dist/platform/projects-client/files.js +58 -0
  165. package/dist/platform/projects-client/files.js.map +1 -0
  166. package/dist/platform/projects-client/gateway.d.ts +177 -0
  167. package/dist/platform/projects-client/gateway.d.ts.map +1 -0
  168. package/dist/platform/projects-client/gateway.js +59 -0
  169. package/dist/platform/projects-client/gateway.js.map +1 -0
  170. package/dist/platform/projects-client/git-history.d.ts +74 -0
  171. package/dist/platform/projects-client/git-history.d.ts.map +1 -0
  172. package/dist/platform/projects-client/git-history.js +40 -0
  173. package/dist/platform/projects-client/git-history.js.map +1 -0
  174. package/dist/platform/projects-client/github.d.ts +62 -0
  175. package/dist/platform/projects-client/github.d.ts.map +1 -0
  176. package/dist/platform/projects-client/github.js +30 -0
  177. package/dist/platform/projects-client/github.js.map +1 -0
  178. package/dist/platform/projects-client/index.d.ts +32 -0
  179. package/dist/platform/projects-client/index.d.ts.map +1 -0
  180. package/dist/platform/projects-client/index.js +34 -0
  181. package/dist/platform/projects-client/index.js.map +1 -0
  182. package/dist/platform/projects-client/marketplace-catalog.d.ts +76 -0
  183. package/dist/platform/projects-client/marketplace-catalog.d.ts.map +1 -0
  184. package/dist/platform/projects-client/marketplace-catalog.js +48 -0
  185. package/dist/platform/projects-client/marketplace-catalog.js.map +1 -0
  186. package/dist/platform/projects-client/marketplace.d.ts +80 -0
  187. package/dist/platform/projects-client/marketplace.d.ts.map +1 -0
  188. package/dist/platform/projects-client/marketplace.js +52 -0
  189. package/dist/platform/projects-client/marketplace.js.map +1 -0
  190. package/dist/platform/projects-client/model-defaults.d.ts +36 -0
  191. package/dist/platform/projects-client/model-defaults.d.ts.map +1 -0
  192. package/dist/platform/projects-client/model-defaults.js +16 -0
  193. package/dist/platform/projects-client/model-defaults.js.map +1 -0
  194. package/dist/platform/projects-client/policies.d.ts +21 -0
  195. package/dist/platform/projects-client/policies.d.ts.map +1 -0
  196. package/dist/platform/projects-client/policies.js +10 -0
  197. package/dist/platform/projects-client/policies.js.map +1 -0
  198. package/dist/platform/projects-client/projects.d.ts +235 -0
  199. package/dist/platform/projects-client/projects.d.ts.map +1 -0
  200. package/dist/platform/projects-client/projects.js +161 -0
  201. package/dist/platform/projects-client/projects.js.map +1 -0
  202. package/dist/platform/projects-client/public-session-shares.d.ts +52 -0
  203. package/dist/platform/projects-client/public-session-shares.d.ts.map +1 -0
  204. package/dist/platform/projects-client/public-session-shares.js +54 -0
  205. package/dist/platform/projects-client/public-session-shares.js.map +1 -0
  206. package/dist/platform/projects-client/review.d.ts +57 -0
  207. package/dist/platform/projects-client/review.d.ts.map +1 -0
  208. package/dist/platform/projects-client/review.js +28 -0
  209. package/dist/platform/projects-client/review.js.map +1 -0
  210. package/dist/platform/projects-client/sandbox-shares.d.ts +25 -0
  211. package/dist/platform/projects-client/sandbox-shares.d.ts.map +1 -0
  212. package/dist/platform/projects-client/sandbox-shares.js +29 -0
  213. package/dist/platform/projects-client/sandbox-shares.js.map +1 -0
  214. package/dist/platform/projects-client/sandbox.d.ts +123 -0
  215. package/dist/platform/projects-client/sandbox.d.ts.map +1 -0
  216. package/dist/platform/projects-client/sandbox.js +45 -0
  217. package/dist/platform/projects-client/sandbox.js.map +1 -0
  218. package/dist/platform/projects-client/secrets.d.ts +122 -0
  219. package/dist/platform/projects-client/secrets.d.ts.map +1 -0
  220. package/dist/platform/projects-client/secrets.js +34 -0
  221. package/dist/platform/projects-client/secrets.js.map +1 -0
  222. package/dist/platform/projects-client/session-sandbox.d.ts +61 -0
  223. package/dist/platform/projects-client/session-sandbox.d.ts.map +1 -0
  224. package/dist/platform/projects-client/session-sandbox.js +82 -0
  225. package/dist/platform/projects-client/session-sandbox.js.map +1 -0
  226. package/dist/platform/projects-client/sessions.d.ts +216 -0
  227. package/dist/platform/projects-client/sessions.d.ts.map +1 -0
  228. package/dist/platform/projects-client/sessions.js +74 -0
  229. package/dist/platform/projects-client/sessions.js.map +1 -0
  230. package/dist/platform/projects-client/setup-links.d.ts +35 -0
  231. package/dist/platform/projects-client/setup-links.d.ts.map +1 -0
  232. package/dist/platform/projects-client/setup-links.js +24 -0
  233. package/dist/platform/projects-client/setup-links.js.map +1 -0
  234. package/dist/platform/projects-client/shared.d.ts +66 -0
  235. package/dist/platform/projects-client/shared.d.ts.map +1 -0
  236. package/dist/platform/projects-client/shared.js +44 -0
  237. package/dist/platform/projects-client/shared.js.map +1 -0
  238. package/dist/platform/projects-client/tokens.d.ts +77 -0
  239. package/dist/platform/projects-client/tokens.d.ts.map +1 -0
  240. package/dist/platform/projects-client/tokens.js +43 -0
  241. package/dist/platform/projects-client/tokens.js.map +1 -0
  242. package/dist/platform/projects-client/transcription.d.ts +5 -0
  243. package/dist/platform/projects-client/transcription.d.ts.map +1 -0
  244. package/dist/platform/projects-client/transcription.js +14 -0
  245. package/dist/platform/projects-client/transcription.js.map +1 -0
  246. package/dist/platform/projects-client/triggers.d.ts +102 -0
  247. package/dist/platform/projects-client/triggers.d.ts.map +1 -0
  248. package/dist/platform/projects-client/triggers.js +27 -0
  249. package/dist/platform/projects-client/triggers.js.map +1 -0
  250. package/dist/platform/session-id.d.ts +9 -0
  251. package/dist/platform/session-id.d.ts.map +1 -0
  252. package/dist/platform/session-id.js +23 -0
  253. package/dist/platform/session-id.js.map +1 -0
  254. package/dist/platform/storage/managed-storage.d.ts +97 -0
  255. package/dist/platform/storage/managed-storage.d.ts.map +1 -0
  256. package/dist/platform/storage/managed-storage.js +271 -0
  257. package/dist/platform/storage/managed-storage.js.map +1 -0
  258. package/dist/platform/strings.d.ts +12 -0
  259. package/dist/platform/strings.d.ts.map +1 -0
  260. package/dist/platform/strings.js +17 -0
  261. package/dist/platform/strings.js.map +1 -0
  262. package/dist/platform/ui.d.ts +11 -0
  263. package/dist/platform/ui.d.ts.map +1 -0
  264. package/dist/platform/ui.js +22 -0
  265. package/dist/platform/ui.js.map +1 -0
  266. package/dist/react/chat/index.d.ts +3 -0
  267. package/dist/react/chat/index.d.ts.map +1 -0
  268. package/dist/react/chat/index.js +7 -0
  269. package/dist/react/chat/index.js.map +1 -0
  270. package/dist/react/chat/render-parts.d.ts +39 -0
  271. package/dist/react/chat/render-parts.d.ts.map +1 -0
  272. package/dist/react/chat/render-parts.js +34 -0
  273. package/dist/react/chat/render-parts.js.map +1 -0
  274. package/dist/react/chat/use-chat-turns.d.ts +19 -0
  275. package/dist/react/chat/use-chat-turns.d.ts.map +1 -0
  276. package/dist/react/chat/use-chat-turns.js +27 -0
  277. package/dist/react/chat/use-chat-turns.js.map +1 -0
  278. package/dist/react/file-keys.d.ts +18 -0
  279. package/dist/react/file-keys.d.ts.map +1 -0
  280. package/dist/react/file-keys.js +18 -0
  281. package/dist/react/file-keys.js.map +1 -0
  282. package/dist/react/index.d.ts +12 -0
  283. package/dist/react/index.d.ts.map +1 -0
  284. package/dist/react/index.js +49 -0
  285. package/dist/react/index.js.map +1 -0
  286. package/dist/react/model-flatten.d.ts +33 -0
  287. package/dist/react/model-flatten.d.ts.map +1 -0
  288. package/dist/react/model-flatten.js +59 -0
  289. package/dist/react/model-flatten.js.map +1 -0
  290. package/dist/react/opencode.d.ts +43 -0
  291. package/dist/react/opencode.d.ts.map +1 -0
  292. package/dist/react/opencode.js +100 -0
  293. package/dist/react/opencode.js.map +1 -0
  294. package/dist/react/prefetch-session-start.d.ts +10 -0
  295. package/dist/react/prefetch-session-start.d.ts.map +1 -0
  296. package/dist/react/prefetch-session-start.js +17 -0
  297. package/dist/react/prefetch-session-start.js.map +1 -0
  298. package/dist/react/provider-refresh.d.ts +7 -0
  299. package/dist/react/provider-refresh.d.ts.map +1 -0
  300. package/dist/react/provider-refresh.js +28 -0
  301. package/dist/react/provider-refresh.js.map +1 -0
  302. package/dist/react/provider-selection.d.ts +31 -0
  303. package/dist/react/provider-selection.d.ts.map +1 -0
  304. package/dist/react/provider-selection.js +135 -0
  305. package/dist/react/provider-selection.js.map +1 -0
  306. package/dist/react/route-project.d.ts +7 -0
  307. package/dist/react/route-project.d.ts.map +1 -0
  308. package/dist/react/route-project.js +19 -0
  309. package/dist/react/route-project.js.map +1 -0
  310. package/dist/react/session-start-stash.d.ts +56 -0
  311. package/dist/react/session-start-stash.d.ts.map +1 -0
  312. package/dist/react/session-start-stash.js +202 -0
  313. package/dist/react/session-start-stash.js.map +1 -0
  314. package/dist/react/use-canonical-opencode-session.d.ts +35 -0
  315. package/dist/react/use-canonical-opencode-session.d.ts.map +1 -0
  316. package/dist/react/use-canonical-opencode-session.js +52 -0
  317. package/dist/react/use-canonical-opencode-session.js.map +1 -0
  318. package/dist/react/use-change-requests.d.ts +321 -0
  319. package/dist/react/use-change-requests.d.ts.map +1 -0
  320. package/dist/react/use-change-requests.js +43 -0
  321. package/dist/react/use-change-requests.js.map +1 -0
  322. package/dist/react/use-current-runtime.d.ts +8 -0
  323. package/dist/react/use-current-runtime.d.ts.map +1 -0
  324. package/dist/react/use-current-runtime.js +12 -0
  325. package/dist/react/use-current-runtime.js.map +1 -0
  326. package/dist/react/use-gateway-catalog-sync.d.ts +2 -0
  327. package/dist/react/use-gateway-catalog-sync.d.ts.map +1 -0
  328. package/dist/react/use-gateway-catalog-sync.js +39 -0
  329. package/dist/react/use-gateway-catalog-sync.js.map +1 -0
  330. package/dist/react/use-kortix-master.d.ts +384 -0
  331. package/dist/react/use-kortix-master.d.ts.map +1 -0
  332. package/dist/react/use-kortix-master.js +958 -0
  333. package/dist/react/use-kortix-master.js.map +1 -0
  334. package/dist/react/use-model-store.d.ts +71 -0
  335. package/dist/react/use-model-store.d.ts.map +1 -0
  336. package/dist/react/use-model-store.js +411 -0
  337. package/dist/react/use-model-store.js.map +1 -0
  338. package/dist/react/use-opencode-config.d.ts +15 -0
  339. package/dist/react/use-opencode-config.d.ts.map +1 -0
  340. package/dist/react/use-opencode-config.js +79 -0
  341. package/dist/react/use-opencode-config.js.map +1 -0
  342. package/dist/react/use-opencode-events/diagnostics.d.ts +11 -0
  343. package/dist/react/use-opencode-events/diagnostics.d.ts.map +1 -0
  344. package/dist/react/use-opencode-events/diagnostics.js +58 -0
  345. package/dist/react/use-opencode-events/diagnostics.js.map +1 -0
  346. package/dist/react/use-opencode-events/handle-event.d.ts +20 -0
  347. package/dist/react/use-opencode-events/handle-event.d.ts.map +1 -0
  348. package/dist/react/use-opencode-events/handle-event.js +450 -0
  349. package/dist/react/use-opencode-events/handle-event.js.map +1 -0
  350. package/dist/react/use-opencode-events/helpers.d.ts +30 -0
  351. package/dist/react/use-opencode-events/helpers.d.ts.map +1 -0
  352. package/dist/react/use-opencode-events/helpers.js +93 -0
  353. package/dist/react/use-opencode-events/helpers.js.map +1 -0
  354. package/dist/react/use-opencode-events/index.d.ts +25 -0
  355. package/dist/react/use-opencode-events/index.d.ts.map +1 -0
  356. package/dist/react/use-opencode-events/index.js +242 -0
  357. package/dist/react/use-opencode-events/index.js.map +1 -0
  358. package/dist/react/use-opencode-events/types.d.ts +10 -0
  359. package/dist/react/use-opencode-events/types.d.ts.map +1 -0
  360. package/dist/react/use-opencode-events/types.js +2 -0
  361. package/dist/react/use-opencode-events/types.js.map +1 -0
  362. package/dist/react/use-opencode-events/use-event-stream-refs.d.ts +22 -0
  363. package/dist/react/use-opencode-events/use-event-stream-refs.d.ts.map +1 -0
  364. package/dist/react/use-opencode-events/use-event-stream-refs.js +158 -0
  365. package/dist/react/use-opencode-events/use-event-stream-refs.js.map +1 -0
  366. package/dist/react/use-opencode-local.d.ts +139 -0
  367. package/dist/react/use-opencode-local.d.ts.map +1 -0
  368. package/dist/react/use-opencode-local.js +484 -0
  369. package/dist/react/use-opencode-local.js.map +1 -0
  370. package/dist/react/use-opencode-mcp.d.ts +34 -0
  371. package/dist/react/use-opencode-mcp.d.ts.map +1 -0
  372. package/dist/react/use-opencode-mcp.js +190 -0
  373. package/dist/react/use-opencode-mcp.js.map +1 -0
  374. package/dist/react/use-opencode-pty.d.ts +30 -0
  375. package/dist/react/use-opencode-pty.d.ts.map +1 -0
  376. package/dist/react/use-opencode-pty.js +126 -0
  377. package/dist/react/use-opencode-pty.js.map +1 -0
  378. package/dist/react/use-opencode-sessions/agents.d.ts +14 -0
  379. package/dist/react/use-opencode-sessions/agents.d.ts.map +1 -0
  380. package/dist/react/use-opencode-sessions/agents.js +82 -0
  381. package/dist/react/use-opencode-sessions/agents.js.map +1 -0
  382. package/dist/react/use-opencode-sessions/commands.d.ts +8 -0
  383. package/dist/react/use-opencode-sessions/commands.d.ts.map +1 -0
  384. package/dist/react/use-opencode-sessions/commands.js +46 -0
  385. package/dist/react/use-opencode-sessions/commands.js.map +1 -0
  386. package/dist/react/use-opencode-sessions/files.d.ts +2 -0
  387. package/dist/react/use-opencode-sessions/files.d.ts.map +1 -0
  388. package/dist/react/use-opencode-sessions/files.js +181 -0
  389. package/dist/react/use-opencode-sessions/files.js.map +1 -0
  390. package/dist/react/use-opencode-sessions/index.d.ts +15 -0
  391. package/dist/react/use-opencode-sessions/index.d.ts.map +1 -0
  392. package/dist/react/use-opencode-sessions/index.js +21 -0
  393. package/dist/react/use-opencode-sessions/index.js.map +1 -0
  394. package/dist/react/use-opencode-sessions/keys.d.ts +94 -0
  395. package/dist/react/use-opencode-sessions/keys.d.ts.map +1 -0
  396. package/dist/react/use-opencode-sessions/keys.js +39 -0
  397. package/dist/react/use-opencode-sessions/keys.js.map +1 -0
  398. package/dist/react/use-opencode-sessions/mcp.d.ts +3 -0
  399. package/dist/react/use-opencode-sessions/mcp.d.ts.map +1 -0
  400. package/dist/react/use-opencode-sessions/mcp.js +23 -0
  401. package/dist/react/use-opencode-sessions/mcp.js.map +1 -0
  402. package/dist/react/use-opencode-sessions/messages.d.ts +75 -0
  403. package/dist/react/use-opencode-sessions/messages.d.ts.map +1 -0
  404. package/dist/react/use-opencode-sessions/messages.js +319 -0
  405. package/dist/react/use-opencode-sessions/messages.js.map +1 -0
  406. package/dist/react/use-opencode-sessions/parts.d.ts +23 -0
  407. package/dist/react/use-opencode-sessions/parts.d.ts.map +1 -0
  408. package/dist/react/use-opencode-sessions/parts.js +49 -0
  409. package/dist/react/use-opencode-sessions/parts.js.map +1 -0
  410. package/dist/react/use-opencode-sessions/permissions.d.ts +17 -0
  411. package/dist/react/use-opencode-sessions/permissions.d.ts.map +1 -0
  412. package/dist/react/use-opencode-sessions/permissions.js +66 -0
  413. package/dist/react/use-opencode-sessions/permissions.js.map +1 -0
  414. package/dist/react/use-opencode-sessions/projects.d.ts +5 -0
  415. package/dist/react/use-opencode-sessions/projects.d.ts.map +1 -0
  416. package/dist/react/use-opencode-sessions/projects.js +54 -0
  417. package/dist/react/use-opencode-sessions/projects.js.map +1 -0
  418. package/dist/react/use-opencode-sessions/providers.d.ts +10 -0
  419. package/dist/react/use-opencode-sessions/providers.d.ts.map +1 -0
  420. package/dist/react/use-opencode-sessions/providers.js +98 -0
  421. package/dist/react/use-opencode-sessions/providers.js.map +1 -0
  422. package/dist/react/use-opencode-sessions/sessions.d.ts +35 -0
  423. package/dist/react/use-opencode-sessions/sessions.d.ts.map +1 -0
  424. package/dist/react/use-opencode-sessions/sessions.js +380 -0
  425. package/dist/react/use-opencode-sessions/sessions.js.map +1 -0
  426. package/dist/react/use-opencode-sessions/shared.d.ts +43 -0
  427. package/dist/react/use-opencode-sessions/shared.d.ts.map +1 -0
  428. package/dist/react/use-opencode-sessions/shared.js +109 -0
  429. package/dist/react/use-opencode-sessions/shared.js.map +1 -0
  430. package/dist/react/use-opencode-sessions/sharing.d.ts +4 -0
  431. package/dist/react/use-opencode-sessions/sharing.d.ts.map +1 -0
  432. package/dist/react/use-opencode-sessions/sharing.js +57 -0
  433. package/dist/react/use-opencode-sessions/sharing.js.map +1 -0
  434. package/dist/react/use-opencode-sessions/tools.d.ts +5 -0
  435. package/dist/react/use-opencode-sessions/tools.d.ts.map +1 -0
  436. package/dist/react/use-opencode-sessions/tools.js +54 -0
  437. package/dist/react/use-opencode-sessions/tools.js.map +1 -0
  438. package/dist/react/use-permission-self-heal.d.ts +45 -0
  439. package/dist/react/use-permission-self-heal.d.ts.map +1 -0
  440. package/dist/react/use-permission-self-heal.js +144 -0
  441. package/dist/react/use-permission-self-heal.js.map +1 -0
  442. package/dist/react/use-project-config.d.ts +11 -0
  443. package/dist/react/use-project-config.d.ts.map +1 -0
  444. package/dist/react/use-project-config.js +22 -0
  445. package/dist/react/use-project-config.js.map +1 -0
  446. package/dist/react/use-project-models.d.ts +11 -0
  447. package/dist/react/use-project-models.d.ts.map +1 -0
  448. package/dist/react/use-project-models.js +25 -0
  449. package/dist/react/use-project-models.js.map +1 -0
  450. package/dist/react/use-project-secrets.d.ts +265 -0
  451. package/dist/react/use-project-secrets.d.ts.map +1 -0
  452. package/dist/react/use-project-secrets.js +41 -0
  453. package/dist/react/use-project-secrets.js.map +1 -0
  454. package/dist/react/use-project-triggers.d.ts +228 -0
  455. package/dist/react/use-project-triggers.d.ts.map +1 -0
  456. package/dist/react/use-project-triggers.js +42 -0
  457. package/dist/react/use-project-triggers.js.map +1 -0
  458. package/dist/react/use-question-self-heal.d.ts +36 -0
  459. package/dist/react/use-question-self-heal.d.ts.map +1 -0
  460. package/dist/react/use-question-self-heal.js +95 -0
  461. package/dist/react/use-question-self-heal.js.map +1 -0
  462. package/dist/react/use-runtime-phase.d.ts +9 -0
  463. package/dist/react/use-runtime-phase.d.ts.map +1 -0
  464. package/dist/react/use-runtime-phase.js +20 -0
  465. package/dist/react/use-runtime-phase.js.map +1 -0
  466. package/dist/react/use-runtime-reconnect.d.ts +90 -0
  467. package/dist/react/use-runtime-reconnect.d.ts.map +1 -0
  468. package/dist/react/use-runtime-reconnect.js +234 -0
  469. package/dist/react/use-runtime-reconnect.js.map +1 -0
  470. package/dist/react/use-session-picks.d.ts +17 -0
  471. package/dist/react/use-session-picks.d.ts.map +1 -0
  472. package/dist/react/use-session-picks.js +36 -0
  473. package/dist/react/use-session-picks.js.map +1 -0
  474. package/dist/react/use-session-prefetch.d.ts +18 -0
  475. package/dist/react/use-session-prefetch.d.ts.map +1 -0
  476. package/dist/react/use-session-prefetch.js +84 -0
  477. package/dist/react/use-session-prefetch.js.map +1 -0
  478. package/dist/react/use-session-send.d.ts +183 -0
  479. package/dist/react/use-session-send.d.ts.map +1 -0
  480. package/dist/react/use-session-send.js +287 -0
  481. package/dist/react/use-session-send.js.map +1 -0
  482. package/dist/react/use-session-sync.d.ts +24 -0
  483. package/dist/react/use-session-sync.d.ts.map +1 -0
  484. package/dist/react/use-session-sync.js +375 -0
  485. package/dist/react/use-session-sync.js.map +1 -0
  486. package/dist/react/use-session.d.ts +171 -0
  487. package/dist/react/use-session.d.ts.map +1 -0
  488. package/dist/react/use-session.js +396 -0
  489. package/dist/react/use-session.js.map +1 -0
  490. package/dist/react/use-visible-agents.d.ts +22 -0
  491. package/dist/react/use-visible-agents.d.ts.map +1 -0
  492. package/dist/react/use-visible-agents.js +45 -0
  493. package/dist/react/use-visible-agents.js.map +1 -0
  494. package/dist/server.d.ts +55 -0
  495. package/dist/server.d.ts.map +1 -0
  496. package/dist/server.js +122 -0
  497. package/dist/server.js.map +1 -0
  498. package/dist/session/health.d.ts +49 -0
  499. package/dist/session/health.d.ts.map +1 -0
  500. package/dist/session/health.js +57 -0
  501. package/dist/session/health.js.map +1 -0
  502. package/dist/session/index.d.ts +19 -0
  503. package/dist/session/index.d.ts.map +1 -0
  504. package/dist/session/index.js +19 -0
  505. package/dist/session/index.js.map +1 -0
  506. package/dist/session/preview.d.ts +24 -0
  507. package/dist/session/preview.d.ts.map +1 -0
  508. package/dist/session/preview.js +85 -0
  509. package/dist/session/preview.js.map +1 -0
  510. package/dist/session/url.d.ts +160 -0
  511. package/dist/session/url.d.ts.map +1 -0
  512. package/dist/session/url.js +522 -0
  513. package/dist/session/url.js.map +1 -0
  514. package/dist/state/chat-events.d.ts +141 -0
  515. package/dist/state/chat-events.d.ts.map +1 -0
  516. package/dist/state/chat-events.js +135 -0
  517. package/dist/state/chat-events.js.map +1 -0
  518. package/dist/state/current-runtime.d.ts +44 -0
  519. package/dist/state/current-runtime.d.ts.map +1 -0
  520. package/dist/state/current-runtime.js +44 -0
  521. package/dist/state/current-runtime.js.map +1 -0
  522. package/dist/state/diagnostics-store.d.ts +114 -0
  523. package/dist/state/diagnostics-store.d.ts.map +1 -0
  524. package/dist/state/diagnostics-store.js +319 -0
  525. package/dist/state/diagnostics-store.js.map +1 -0
  526. package/dist/state/event-stream.d.ts +134 -0
  527. package/dist/state/event-stream.d.ts.map +1 -0
  528. package/dist/state/event-stream.js +424 -0
  529. package/dist/state/event-stream.js.map +1 -0
  530. package/dist/state/idb-sync-cache.d.ts +18 -0
  531. package/dist/state/idb-sync-cache.d.ts.map +1 -0
  532. package/dist/state/idb-sync-cache.js +209 -0
  533. package/dist/state/idb-sync-cache.js.map +1 -0
  534. package/dist/state/opencode-compaction-store.d.ts +10 -0
  535. package/dist/state/opencode-compaction-store.d.ts.map +1 -0
  536. package/dist/state/opencode-compaction-store.js +32 -0
  537. package/dist/state/opencode-compaction-store.js.map +1 -0
  538. package/dist/state/opencode-pending-store.d.ts +19 -0
  539. package/dist/state/opencode-pending-store.d.ts.map +1 -0
  540. package/dist/state/opencode-pending-store.js +76 -0
  541. package/dist/state/opencode-pending-store.js.map +1 -0
  542. package/dist/state/sandbox-connection-store.d.ts +62 -0
  543. package/dist/state/sandbox-connection-store.d.ts.map +1 -0
  544. package/dist/state/sandbox-connection-store.js +290 -0
  545. package/dist/state/sandbox-connection-store.js.map +1 -0
  546. package/dist/state/server-store/active.d.ts +49 -0
  547. package/dist/state/server-store/active.d.ts.map +1 -0
  548. package/dist/state/server-store/active.js +76 -0
  549. package/dist/state/server-store/active.js.map +1 -0
  550. package/dist/state/server-store/types.d.ts +12 -0
  551. package/dist/state/server-store/types.d.ts.map +1 -0
  552. package/dist/state/server-store/types.js +2 -0
  553. package/dist/state/server-store/types.js.map +1 -0
  554. package/dist/state/server-store/url-helpers.d.ts +33 -0
  555. package/dist/state/server-store/url-helpers.d.ts.map +1 -0
  556. package/dist/state/server-store/url-helpers.js +55 -0
  557. package/dist/state/server-store/url-helpers.js.map +1 -0
  558. package/dist/state/server-store.d.ts +18 -0
  559. package/dist/state/server-store.d.ts.map +1 -0
  560. package/dist/state/server-store.js +23 -0
  561. package/dist/state/server-store.js.map +1 -0
  562. package/dist/state/session-runtime-registry.d.ts +49 -0
  563. package/dist/state/session-runtime-registry.d.ts.map +1 -0
  564. package/dist/state/session-runtime-registry.js +85 -0
  565. package/dist/state/session-runtime-registry.js.map +1 -0
  566. package/dist/state/sync-store/ascending-id.d.ts +2 -0
  567. package/dist/state/sync-store/ascending-id.d.ts.map +1 -0
  568. package/dist/state/sync-store/ascending-id.js +21 -0
  569. package/dist/state/sync-store/ascending-id.js.map +1 -0
  570. package/dist/state/sync-store/binary.d.ts +7 -0
  571. package/dist/state/sync-store/binary.d.ts.map +1 -0
  572. package/dist/state/sync-store/binary.js +21 -0
  573. package/dist/state/sync-store/binary.js.map +1 -0
  574. package/dist/state/sync-store/stream-cache.d.ts +2 -0
  575. package/dist/state/sync-store/stream-cache.d.ts.map +1 -0
  576. package/dist/state/sync-store/stream-cache.js +29 -0
  577. package/dist/state/sync-store/stream-cache.js.map +1 -0
  578. package/dist/state/sync-store/types.d.ts +29 -0
  579. package/dist/state/sync-store/types.d.ts.map +1 -0
  580. package/dist/state/sync-store/types.js +2 -0
  581. package/dist/state/sync-store/types.js.map +1 -0
  582. package/dist/state/sync-store.d.ts +39 -0
  583. package/dist/state/sync-store.d.ts.map +1 -0
  584. package/dist/state/sync-store.js +692 -0
  585. package/dist/state/sync-store.js.map +1 -0
  586. package/dist/state/tab-store.d.ts +91 -0
  587. package/dist/state/tab-store.d.ts.map +1 -0
  588. package/dist/state/tab-store.js +369 -0
  589. package/dist/state/tab-store.js.map +1 -0
  590. package/dist/transcript.d.ts +40 -0
  591. package/dist/transcript.d.ts.map +1 -0
  592. package/dist/transcript.js +126 -0
  593. package/dist/transcript.js.map +1 -0
  594. package/dist/turns/classify.d.ts +166 -0
  595. package/dist/turns/classify.d.ts.map +1 -0
  596. package/dist/turns/classify.js +259 -0
  597. package/dist/turns/classify.js.map +1 -0
  598. package/dist/turns/errors.d.ts +11 -0
  599. package/dist/turns/errors.d.ts.map +1 -0
  600. package/dist/turns/errors.js +85 -0
  601. package/dist/turns/errors.js.map +1 -0
  602. package/dist/turns/index.d.ts +264 -0
  603. package/dist/turns/index.d.ts.map +1 -0
  604. package/dist/turns/index.js +1243 -0
  605. package/dist/turns/index.js.map +1 -0
  606. package/dist/turns/tool-registry.d.ts +33 -0
  607. package/dist/turns/tool-registry.d.ts.map +1 -0
  608. package/dist/turns/tool-registry.js +108 -0
  609. package/dist/turns/tool-registry.js.map +1 -0
  610. package/dist/turns/types.d.ts +125 -0
  611. package/dist/turns/types.d.ts.map +1 -0
  612. package/dist/turns/types.js +12 -0
  613. package/dist/turns/types.js.map +1 -0
  614. package/dist/turns/view-model.d.ts +127 -0
  615. package/dist/turns/view-model.d.ts.map +1 -0
  616. package/dist/turns/view-model.js +401 -0
  617. package/dist/turns/view-model.js.map +1 -0
  618. package/package.json +155 -0
@@ -0,0 +1,1243 @@
1
+ /**
2
+ * Turn grouping & part helpers — framework-agnostic.
3
+ *
4
+ * Pure functions that transform SDK message data into view-model shapes.
5
+ * Single implementation shared by the web and mobile UIs.
6
+ *
7
+ * IMPORTANT: No React / DOM / framework imports allowed in this module.
8
+ * Matches the SolidJS reference in opencode/packages/ui/src/components/session-turn.tsx
9
+ */
10
+ export { unwrapError } from './errors.js';
11
+ export * from './tool-registry.js';
12
+ export * from './classify.js';
13
+ export * from './view-model.js';
14
+ import { unwrapError } from './errors.js';
15
+ // ============================================================================
16
+ // Type guards
17
+ // ============================================================================
18
+ export function isTextPart(part) {
19
+ return part.type === 'text';
20
+ }
21
+ export function isReasoningPart(part) {
22
+ return part.type === 'reasoning';
23
+ }
24
+ export function isToolPart(part) {
25
+ return part.type === 'tool';
26
+ }
27
+ export function isFilePart(part) {
28
+ return part.type === 'file';
29
+ }
30
+ export function isAgentPart(part) {
31
+ return part.type === 'agent';
32
+ }
33
+ export function isCompactionPart(part) {
34
+ return part.type === 'compaction';
35
+ }
36
+ export function isSnapshotPart(part) {
37
+ return part.type === 'snapshot';
38
+ }
39
+ export function isPatchPart(part) {
40
+ return part.type === 'patch';
41
+ }
42
+ /** Get the text content from any part that has a `text` field. */
43
+ export function getPartText(part) {
44
+ if (isTextPart(part))
45
+ return part.text;
46
+ if (isReasoningPart(part))
47
+ return part.text;
48
+ return undefined;
49
+ }
50
+ // ============================================================================
51
+ // Attachment helpers (images, PDFs)
52
+ // ============================================================================
53
+ /**
54
+ * Check if a file part is an image or PDF attachment.
55
+ * Matches SolidJS `isAttachment()` — session-turn.tsx:128
56
+ */
57
+ export function isAttachment(part) {
58
+ if (!isFilePart(part))
59
+ return false;
60
+ const mime = part.mime;
61
+ return mime.startsWith('image/') || mime === 'application/pdf';
62
+ }
63
+ /** Split user message parts into attachment parts and sticky (non-attachment) parts. */
64
+ export function splitUserParts(parts) {
65
+ const attachments = [];
66
+ const stickyParts = [];
67
+ for (const p of parts) {
68
+ if (isAttachment(p)) {
69
+ attachments.push(p);
70
+ }
71
+ else {
72
+ stickyParts.push(p);
73
+ }
74
+ }
75
+ return { attachments, stickyParts };
76
+ }
77
+ // ============================================================================
78
+ // Turn grouping
79
+ // ============================================================================
80
+ /**
81
+ * Group messages into turns: each turn starts with a user message followed
82
+ * by 0+ assistant messages.
83
+ *
84
+ * Uses parentID-based linking (matching SolidJS session-turn.tsx:272-292):
85
+ * assistant messages are associated with their parent user message via
86
+ * `parentID`. Falls back to sequential ordering when parentID is absent.
87
+ */
88
+ export function groupMessagesIntoTurns(messages) {
89
+ const turns = [];
90
+ const turnsByUserMsgId = new Map();
91
+ // First pass: create turns from user messages.
92
+ // Dedupe by id — a user message can transiently appear twice (e.g. an
93
+ // optimistic copy + the real one before reconcile finishes, or a hydrate
94
+ // that races a part.updated event). Two turns with the same userMessage.id
95
+ // would crash list renderers keyed by it (e.g. FlatList's keyExtractor).
96
+ for (const msg of messages) {
97
+ if (msg.info.role === 'user') {
98
+ if (turnsByUserMsgId.has(msg.info.id))
99
+ continue;
100
+ const turn = { userMessage: msg, assistantMessages: [] };
101
+ turns.push(turn);
102
+ turnsByUserMsgId.set(msg.info.id, turn);
103
+ }
104
+ }
105
+ // Second pass: link assistant messages via parentID or sequential
106
+ let lastTurn = null;
107
+ for (const msg of messages) {
108
+ if (msg.info.role === 'user') {
109
+ lastTurn = turnsByUserMsgId.get(msg.info.id) ?? null;
110
+ continue;
111
+ }
112
+ if (msg.info.role !== 'assistant')
113
+ continue;
114
+ const assistantMsg = msg.info;
115
+ // Try parentID-based linking first (matches SolidJS)
116
+ if (assistantMsg.parentID) {
117
+ const parentTurn = turnsByUserMsgId.get(assistantMsg.parentID);
118
+ if (parentTurn) {
119
+ parentTurn.assistantMessages.push(msg);
120
+ continue;
121
+ }
122
+ }
123
+ // Fall back to sequential ordering — attach to the most recently seen
124
+ // user turn in iteration order. This keeps streaming parts that arrive
125
+ // before their parent metadata in the right turn.
126
+ if (lastTurn) {
127
+ lastTurn.assistantMessages.push(msg);
128
+ continue;
129
+ }
130
+ // Orphan assistant message that precedes every user message in the
131
+ // session (e.g. a session-init failure with no parentID). Attaching to
132
+ // the LAST turn would surface its error under an unrelated, much later
133
+ // user prompt. Attach to the FIRST turn instead so it renders at its
134
+ // real chronological position — or create a synthetic turn if no user
135
+ // messages exist at all.
136
+ if (turns.length > 0) {
137
+ turns[0].assistantMessages.unshift(msg);
138
+ continue;
139
+ }
140
+ const syntheticTurn = { userMessage: msg, assistantMessages: [] };
141
+ turns.push(syntheticTurn);
142
+ }
143
+ return turns;
144
+ }
145
+ // ============================================================================
146
+ // Part collection helpers
147
+ // ============================================================================
148
+ /** Collect all parts from a turn's assistant messages. */
149
+ export function collectTurnParts(turn) {
150
+ const result = [];
151
+ for (const msg of turn.assistantMessages) {
152
+ for (const part of msg.parts) {
153
+ result.push({ part, message: msg });
154
+ }
155
+ }
156
+ return result;
157
+ }
158
+ /** Find the last non-empty text part in a turn (the "response"). */
159
+ export function findLastTextPart(parts) {
160
+ for (let i = parts.length - 1; i >= 0; i--) {
161
+ const p = parts[i].part;
162
+ if (isTextPart(p) && p.text?.trim()) {
163
+ return p;
164
+ }
165
+ }
166
+ return undefined;
167
+ }
168
+ /** Check if a turn has tool steps. */
169
+ export function turnHasSteps(parts) {
170
+ return parts.some(({ part }) => part.type === 'tool' ||
171
+ part.type === 'compaction' ||
172
+ part.type === 'snapshot' ||
173
+ part.type === 'patch');
174
+ }
175
+ // ============================================================================
176
+ // Shell mode detection
177
+ // ============================================================================
178
+ /**
179
+ * Detect "shell mode": user message is entirely synthetic text parts AND
180
+ * there's exactly one assistant message with exactly one part which is a bash tool.
181
+ *
182
+ * Stricter than our previous implementation — matches SolidJS session-turn.tsx:364-379
183
+ * which checks `msgParts.length !== 1` (exactly one assistant part total).
184
+ */
185
+ export function isShellMode(turn) {
186
+ const userParts = turn.userMessage.parts;
187
+ if (userParts.length === 0)
188
+ return false;
189
+ const allSynthetic = userParts.every((p) => isTextPart(p) && p.synthetic);
190
+ if (!allSynthetic)
191
+ return false;
192
+ if (turn.assistantMessages.length !== 1)
193
+ return false;
194
+ const assistantParts = turn.assistantMessages[0].parts;
195
+ // Strict: exactly 1 part total (not just 1 tool part)
196
+ if (assistantParts.length !== 1)
197
+ return false;
198
+ const part = assistantParts[0];
199
+ return isToolPart(part) && part.tool === 'bash';
200
+ }
201
+ /** Get the bash tool part when in shell mode. */
202
+ export function getShellModePart(turn) {
203
+ if (!isShellMode(turn))
204
+ return undefined;
205
+ return turn.assistantMessages[0].parts[0];
206
+ }
207
+ // ============================================================================
208
+ // Working state
209
+ // ============================================================================
210
+ /** Check if this is the last user message in the session. */
211
+ export function isLastUserMessage(messageId, allMessages) {
212
+ for (let i = allMessages.length - 1; i >= 0; i--) {
213
+ if (allMessages[i].info.role === 'user') {
214
+ return allMessages[i].info.id === messageId;
215
+ }
216
+ }
217
+ return false;
218
+ }
219
+ /** Derive the "working" state for a turn. Only the last turn shows as working. */
220
+ export function getWorkingState(sessionStatus, isLast) {
221
+ if (!isLast)
222
+ return false;
223
+ if (!sessionStatus)
224
+ return false;
225
+ return sessionStatus.type !== 'idle';
226
+ }
227
+ // ============================================================================
228
+ // Response part separation
229
+ // ============================================================================
230
+ /**
231
+ * Whether the last text part (the "response") should be extracted from the
232
+ * steps list and shown separately in the Response section.
233
+ *
234
+ * Matches SolidJS session-turn.tsx:440-443
235
+ */
236
+ export function shouldHideResponsePart(working, responsePartId) {
237
+ return !working && !!responsePartId;
238
+ }
239
+ /**
240
+ * Get the list of tool parts to hide from the step list.
241
+ * Matches SolidJS session-turn.tsx:332-339
242
+ */
243
+ export function getHiddenToolParts(permission, question) {
244
+ const out = [];
245
+ if (permission?.tool)
246
+ out.push(permission.tool);
247
+ if (question?.tool)
248
+ out.push(question.tool);
249
+ return out;
250
+ }
251
+ /** Check if a specific tool part should be hidden due to active permission/question. */
252
+ export function isToolPartHidden(part, messageId, hidden) {
253
+ return hidden.some((h) => h.messageID === messageId && h.callID === part.callID);
254
+ }
255
+ // ============================================================================
256
+ // Answered question parts (shown when collapsed)
257
+ // ============================================================================
258
+ /**
259
+ * Collect answered question parts that should be shown outside of the
260
+ * steps list. Questions are always rendered standalone (never inside steps),
261
+ * so answered questions are shown regardless of stepsExpanded state.
262
+ */
263
+ export function getAnsweredQuestionParts(turn, _stepsExpanded, hasActiveQuestion) {
264
+ // Active question takes precedence — don't also show old answered ones
265
+ if (hasActiveQuestion)
266
+ return [];
267
+ const result = [];
268
+ for (const msg of turn.assistantMessages) {
269
+ for (const part of msg.parts) {
270
+ if (!isToolPart(part))
271
+ continue;
272
+ const tp = part;
273
+ const answers = tp.state?.metadata?.answers;
274
+ if (tp.tool === 'question' && (answers?.length ?? 0) > 0) {
275
+ result.push({ part, message: msg });
276
+ }
277
+ }
278
+ }
279
+ return result;
280
+ }
281
+ // ============================================================================
282
+ // Error extraction — with deep JSON unwrapping
283
+ // ============================================================================
284
+ /** Extract error message from assistant messages in a turn. */
285
+ export function getTurnError(turn) {
286
+ for (const msg of turn.assistantMessages) {
287
+ const info = msg.info;
288
+ if (info.error) {
289
+ return unwrapError(info.error);
290
+ }
291
+ }
292
+ return undefined;
293
+ }
294
+ // ============================================================================
295
+ // Status text computation
296
+ // ============================================================================
297
+ /**
298
+ * Derive human-readable status from a part.
299
+ * Matches SolidJS computeStatusFromPart — session-turn.tsx:83-119
300
+ */
301
+ export function computeStatusFromPart(part) {
302
+ if (!part)
303
+ return undefined;
304
+ if (isToolPart(part)) {
305
+ switch (part.tool) {
306
+ case 'task':
307
+ case 'session_spawn':
308
+ case 'session_start_background':
309
+ case 'session-spawn':
310
+ case 'session-start-background':
311
+ return 'Delegating to agent...';
312
+ case 'agent_spawn':
313
+ case 'agent-spawn':
314
+ case 'agent_task':
315
+ case 'agent-task':
316
+ return 'Delegating to agent...';
317
+ case 'agent_task_update':
318
+ case 'agent-task-update':
319
+ case 'task_update':
320
+ case 'task-update':
321
+ return 'Updating task...';
322
+ case 'agent_message':
323
+ case 'agent-message':
324
+ case 'agent_task_message':
325
+ case 'agent-task-message':
326
+ case 'task_message':
327
+ case 'task-message':
328
+ return 'Messaging agent...';
329
+ case 'task_create':
330
+ case 'task-create':
331
+ case 'task_start':
332
+ case 'task-start':
333
+ return 'Creating task...';
334
+ case 'task_list':
335
+ case 'task-list':
336
+ return 'Listing tasks...';
337
+ case 'task_done':
338
+ case 'task-done':
339
+ return 'Updating task...';
340
+ case 'todowrite':
341
+ case 'todoread':
342
+ return 'Planning...';
343
+ case 'read':
344
+ return 'Gathering context...';
345
+ case 'list':
346
+ case 'grep':
347
+ case 'glob':
348
+ return 'Searching codebase...';
349
+ case 'webfetch':
350
+ case 'scrape-webpage':
351
+ return 'Fetching web page...';
352
+ case 'websearch':
353
+ case 'web-search':
354
+ case 'web_search':
355
+ return 'Searching web...';
356
+ case 'image-search':
357
+ return 'Searching images...';
358
+ case 'image-gen':
359
+ return 'Generating image...';
360
+ case 'video-gen':
361
+ return 'Generating video...';
362
+ case 'presentation-gen':
363
+ return 'Creating presentation...';
364
+ case 'show':
365
+ case 'show-user':
366
+ return 'Showing output...';
367
+ case 'edit':
368
+ case 'write':
369
+ case 'morph_edit':
370
+ return 'Making edits...';
371
+ case 'bash':
372
+ return 'Running commands...';
373
+ case 'apply_patch':
374
+ return 'Applying patches...';
375
+ case 'prune':
376
+ return 'Pruning context...';
377
+ case 'distill':
378
+ return 'Distilling context...';
379
+ case 'compress':
380
+ return 'Compressing context...';
381
+ case 'context_info':
382
+ return 'Updating context info...';
383
+ default:
384
+ return `Running ${part.tool}...`;
385
+ }
386
+ }
387
+ if (isReasoningPart(part)) {
388
+ const text = part.text?.trimStart();
389
+ if (text) {
390
+ const match = text.match(/^\*\*(.+?)\*\*/);
391
+ if (match)
392
+ return `Thinking about ${match[1].trim()}...`;
393
+ }
394
+ return 'Thinking...';
395
+ }
396
+ if (isTextPart(part))
397
+ return 'Gathering thoughts...';
398
+ return undefined;
399
+ }
400
+ /**
401
+ * Get status text for a turn, with child session delegation.
402
+ *
403
+ * Matches SolidJS rawStatus — session-turn.tsx:381-428
404
+ * When the last part is a running `task` tool, drills into the child session
405
+ * to derive the real status.
406
+ */
407
+ export function getTurnStatus(parts, childMessages) {
408
+ // Scan parts in reverse for the last meaningful status
409
+ for (let i = parts.length - 1; i >= 0; i--) {
410
+ const p = parts[i].part;
411
+ // If it's a running task orchestration tool, try to get status from child session
412
+ const tp = isToolPart(p) ? p : undefined;
413
+ if (tp &&
414
+ (tp.tool === 'task' ||
415
+ tp.tool === 'agent_task' ||
416
+ tp.tool === 'agent-task' ||
417
+ tp.tool === 'task_create' ||
418
+ tp.tool === 'task-create' ||
419
+ tp.tool === 'task_start' ||
420
+ tp.tool === 'task-start') &&
421
+ tp.state.status === 'running' &&
422
+ childMessages &&
423
+ childMessages.length > 0) {
424
+ // Walk child session messages in reverse to find status
425
+ for (let mi = childMessages.length - 1; mi >= 0; mi--) {
426
+ const childMsg = childMessages[mi];
427
+ if (childMsg.info.role !== 'assistant')
428
+ continue;
429
+ for (let pi = childMsg.parts.length - 1; pi >= 0; pi--) {
430
+ const childStatus = computeStatusFromPart(childMsg.parts[pi]);
431
+ if (childStatus)
432
+ return childStatus;
433
+ }
434
+ }
435
+ // Fall through to parent status
436
+ return 'Delegating to agent...';
437
+ }
438
+ const s = computeStatusFromPart(p);
439
+ if (s)
440
+ return s;
441
+ }
442
+ return 'Considering next steps...';
443
+ }
444
+ // ============================================================================
445
+ // Duration formatting
446
+ // ============================================================================
447
+ export function formatDuration(ms) {
448
+ // Sub-second durations are noise — skip the badge entirely. Callers
449
+ // should conditionally render based on whether the returned string is
450
+ // non-empty, so nothing visible changes when a tool returns in 200ms.
451
+ if (!Number.isFinite(ms) || ms < 1000)
452
+ return '';
453
+ const seconds = Math.floor(ms / 1000);
454
+ if (seconds < 60)
455
+ return `${seconds}s`;
456
+ const minutes = Math.floor(seconds / 60);
457
+ const secs = seconds % 60;
458
+ return secs > 0 ? `${minutes}m ${secs}s` : `${minutes}m`;
459
+ }
460
+ // ============================================================================
461
+ // Child session helpers
462
+ // ============================================================================
463
+ /**
464
+ * Extract child session ID from a task tool part's metadata.
465
+ */
466
+ export function getChildSessionId(part) {
467
+ // Native task tool, agent_spawn, or agent_task
468
+ const t = part.tool || '';
469
+ if (t === 'task' ||
470
+ t === 'agent_spawn' ||
471
+ t === 'agent-spawn' ||
472
+ t === 'agent_message' ||
473
+ t === 'agent-message' ||
474
+ t === 'agent_task' ||
475
+ t === 'agent-task' ||
476
+ t === 'agent_task_update' ||
477
+ t === 'agent-task-update' ||
478
+ t === 'agent_task_message' ||
479
+ t === 'agent-task-message' ||
480
+ t === 'agent_task_start' ||
481
+ t === 'agent-task-start' ||
482
+ t === 'task_create' ||
483
+ t === 'task-create' ||
484
+ t === 'task_start' ||
485
+ t === 'task-start' ||
486
+ t === 'task_update' ||
487
+ t === 'task-update' ||
488
+ t === 'task_message' ||
489
+ t === 'task-message') {
490
+ // 1. Try metadata (ctx.metadata — available immediately for built-in tools)
491
+ const metaSessionId = part.state?.metadata?.sessionId;
492
+ if (typeof metaSessionId === 'string' && metaSessionId)
493
+ return metaSessionId;
494
+ // 2. Try title (plugin tools embed session ID in title via ctx.metadata)
495
+ const title = part.state?.title;
496
+ if (title) {
497
+ const tm = title.match(/\bses_[a-zA-Z0-9]+/);
498
+ if (tm)
499
+ return tm[0];
500
+ }
501
+ // 3. Try output text (available after tool completes)
502
+ const output = part.state?.output;
503
+ if (output) {
504
+ const m = output.match(/\bses_[a-zA-Z0-9]+/);
505
+ if (m)
506
+ return m[0];
507
+ }
508
+ return undefined;
509
+ }
510
+ // session_spawn / session_start_background: extract session ID from output text
511
+ // Output format: "- **Session:** ses_xxx" or "Session: ses_xxx"
512
+ const toolName = part.tool?.replace(/-/g, '_') || '';
513
+ if (toolName === 'session_spawn' || toolName === 'session_start_background') {
514
+ const output = part.state?.output;
515
+ if (output) {
516
+ const match = output.match(/\*?\*?Session:?\*?\*?\s*(ses_[a-zA-Z0-9]+)/);
517
+ if (match)
518
+ return match[1];
519
+ }
520
+ return undefined;
521
+ }
522
+ return undefined;
523
+ }
524
+ /**
525
+ * Extract the error message from a child (sub-agent) session's raw messages.
526
+ *
527
+ * Mirrors `getTurnError` but operates over the flat `MessageWithParts` list
528
+ * returned by `useOpenCodeMessages`, so a parent thread can surface a sub-agent
529
+ * failure (e.g. "Free usage exceeded, subscribe to Go") that otherwise only
530
+ * lives on the child session and never reaches the parent's turn renderer.
531
+ * Scans newest-first so the most recent failure wins.
532
+ */
533
+ export function getChildSessionError(childMessages) {
534
+ if (!childMessages)
535
+ return undefined;
536
+ for (let i = childMessages.length - 1; i >= 0; i--) {
537
+ const info = childMessages[i]?.info;
538
+ if (info?.role === 'assistant' && info.error) {
539
+ return unwrapError(info.error);
540
+ }
541
+ }
542
+ return undefined;
543
+ }
544
+ /**
545
+ * Collect all tool parts from a child session's assistant messages.
546
+ * Matches SolidJS getSessionToolParts — message-part.tsx:160-174
547
+ */
548
+ export function getChildSessionToolParts(childMessages) {
549
+ const result = [];
550
+ for (const msg of childMessages) {
551
+ if (msg.info.role !== 'assistant')
552
+ continue;
553
+ for (const part of msg.parts) {
554
+ if (isToolPart(part) && shouldShowToolPart(part)) {
555
+ result.push(part);
556
+ }
557
+ }
558
+ }
559
+ return result;
560
+ }
561
+ // ============================================================================
562
+ // Tool part filtering
563
+ // ============================================================================
564
+ const HIDDEN_TOOLS = new Set(['todoread', 'context_info']);
565
+ export function shouldShowToolPart(part) {
566
+ return !HIDDEN_TOOLS.has(part.tool);
567
+ }
568
+ // ============================================================================
569
+ // Tool info (icon + title + subtitle)
570
+ // ============================================================================
571
+ /**
572
+ * Get icon, title, subtitle for a tool part.
573
+ * Matches SolidJS getToolInfo — message-part.tsx:184-270
574
+ *
575
+ * Icon names are Lucide icon names used by the React frontend.
576
+ */
577
+ export function getToolInfo(tool,
578
+ // biome-ignore lint/suspicious/noExplicitAny: tool inputs are free-form wire data with heterogeneous shapes
579
+ input = {}) {
580
+ switch (tool) {
581
+ case 'read':
582
+ return { icon: 'glasses', title: 'Read', subtitle: getFilename(input.filePath) };
583
+ case 'list':
584
+ return { icon: 'list', title: 'List', subtitle: getDirectory(input.path) };
585
+ case 'glob':
586
+ return { icon: 'search', title: 'Glob', subtitle: input.pattern };
587
+ case 'grep':
588
+ return { icon: 'search', title: 'Grep', subtitle: input.pattern };
589
+ case 'webfetch':
590
+ return { icon: 'globe', title: 'Web Fetch', subtitle: input.url };
591
+ case 'websearch':
592
+ case 'web-search':
593
+ case 'web_search':
594
+ return { icon: 'search', title: 'Web Search', subtitle: input.query };
595
+ case 'scrape-webpage':
596
+ return { icon: 'globe', title: 'Scrape', subtitle: input.urls?.split?.(',')[0] };
597
+ case 'image-search':
598
+ return { icon: 'image', title: 'Image Search', subtitle: input.query };
599
+ case 'image-gen':
600
+ return { icon: 'image', title: 'Image Gen', subtitle: input.prompt?.slice?.(0, 40) };
601
+ case 'video-gen':
602
+ return { icon: 'cpu', title: 'Video Gen', subtitle: input.prompt?.slice?.(0, 40) };
603
+ case 'presentation-gen': {
604
+ const action = input.action || '';
605
+ const labels = {
606
+ create_slide: 'Create Slide',
607
+ list_slides: 'List Slides',
608
+ preview: 'Preview',
609
+ export_pdf: 'Export PDF',
610
+ export_pptx: 'Export PPTX',
611
+ };
612
+ return {
613
+ icon: 'presentation',
614
+ title: labels[action] || 'Presentation',
615
+ subtitle: input.slide_title || input.presentation_name,
616
+ };
617
+ }
618
+ case 'show':
619
+ case 'show-user':
620
+ return { icon: 'globe', title: 'Output', subtitle: input.title || input.description };
621
+ case 'task':
622
+ return {
623
+ icon: 'square-kanban',
624
+ title: `Agent (${input.subagent_type || 'task'})`,
625
+ subtitle: getAgentCardLabel(input),
626
+ };
627
+ case 'session_spawn':
628
+ case 'session_start_background':
629
+ case 'session-spawn':
630
+ case 'session-start-background':
631
+ case 'oc-session_spawn':
632
+ case 'oc-session-spawn':
633
+ case 'oc-session_start_background':
634
+ case 'oc-session-start-background':
635
+ return {
636
+ icon: 'square-kanban',
637
+ title: `Worker (${input.agent || 'KortixWorker'})`,
638
+ subtitle: input.description || input.prompt?.slice(0, 60),
639
+ };
640
+ case 'bash':
641
+ return { icon: 'terminal', title: 'Shell', subtitle: input.description };
642
+ case 'edit':
643
+ case 'morph_edit':
644
+ return { icon: 'file-pen', title: 'Edit', subtitle: getFileWithDir(input.filePath) };
645
+ case 'write':
646
+ return { icon: 'file-pen', title: 'Write', subtitle: getFileWithDir(input.filePath) };
647
+ case 'apply_patch':
648
+ return {
649
+ icon: 'file-pen',
650
+ title: 'Patch',
651
+ subtitle: input.files?.length
652
+ ? `${input.files.length} file${input.files.length > 1 ? 's' : ''}`
653
+ : undefined,
654
+ };
655
+ case 'todowrite':
656
+ return { icon: 'check-square', title: 'Todos' };
657
+ case 'todoread':
658
+ return { icon: 'check-square', title: 'Todos (read)' };
659
+ case 'question':
660
+ return { icon: 'message-circle', title: 'Questions' };
661
+ case 'prune':
662
+ return { icon: 'scissors', title: 'DCP Prune', subtitle: input.reason };
663
+ case 'distill':
664
+ return { icon: 'scissors', title: 'DCP Distill' };
665
+ case 'compress':
666
+ return { icon: 'scissors', title: 'DCP Compress', subtitle: input.topic };
667
+ case 'context_info':
668
+ return { icon: 'scissors', title: 'Context Info' };
669
+ case 'session_read':
670
+ case 'session-read':
671
+ case 'oc-session_read':
672
+ case 'oc-session-read':
673
+ return {
674
+ icon: 'glasses',
675
+ title: `Session Read (${input.mode || 'summary'})`,
676
+ subtitle: input.session_id?.slice(-12),
677
+ };
678
+ case 'session_search':
679
+ case 'session-search':
680
+ case 'oc-session_search':
681
+ case 'oc-session-search':
682
+ return { icon: 'search', title: 'Session Search', subtitle: input.query };
683
+ case 'session_message':
684
+ case 'session-message':
685
+ case 'oc-session_message':
686
+ case 'oc-session-message':
687
+ return {
688
+ icon: 'message-circle',
689
+ title: 'Message → Session',
690
+ subtitle: input.session_id?.slice(-12),
691
+ };
692
+ case 'session_lineage':
693
+ case 'session-lineage':
694
+ case 'oc-session_lineage':
695
+ case 'oc-session-lineage':
696
+ return {
697
+ icon: 'list-tree',
698
+ title: 'Session Lineage',
699
+ subtitle: input.session_id?.slice(-12),
700
+ };
701
+ case 'session_list_background':
702
+ case 'session-list-background':
703
+ case 'session_list_spawned':
704
+ case 'session-list-spawned':
705
+ case 'oc-session_list_background':
706
+ case 'oc-session-list-background':
707
+ case 'oc-session_list_spawned':
708
+ case 'oc-session-list-spawned':
709
+ return { icon: 'layers', title: 'Background Sessions', subtitle: input.project || 'all' };
710
+ case 'session_stats':
711
+ case 'session-stats':
712
+ case 'oc-session_stats':
713
+ case 'oc-session-stats':
714
+ return {
715
+ icon: 'layers',
716
+ title: 'Session Stats',
717
+ subtitle: input.session_id?.slice(-12) || 'current',
718
+ };
719
+ case 'session_list':
720
+ case 'session-list':
721
+ case 'oc-session_list':
722
+ case 'oc-session-list':
723
+ return { icon: 'list', title: 'Session List', subtitle: input.search };
724
+ case 'session_get':
725
+ case 'session-get':
726
+ case 'oc-session_get':
727
+ case 'oc-session-get':
728
+ return { icon: 'book-open', title: 'Session Get', subtitle: input.session_id?.slice(-12) };
729
+ case 'session_context':
730
+ case 'session-context':
731
+ case 'oc-session_context':
732
+ case 'oc-session-context':
733
+ return {
734
+ icon: 'book-open',
735
+ title: 'Session Context',
736
+ subtitle: input.session_id?.slice(-12),
737
+ };
738
+ case 'project_delete':
739
+ case 'project-delete':
740
+ case 'oc-project_delete':
741
+ case 'oc-project-delete':
742
+ return { icon: 'trash-2', title: 'Workspace Delete Disabled', subtitle: input.project };
743
+ case 'project_list':
744
+ case 'project-list':
745
+ case 'oc-project_list':
746
+ case 'oc-project-list':
747
+ return { icon: 'folder', title: 'Projects' };
748
+ case 'project_get':
749
+ case 'project-get':
750
+ case 'oc-project_get':
751
+ case 'oc-project-get':
752
+ case 'project_update':
753
+ case 'project-update':
754
+ case 'oc-project_update':
755
+ case 'oc-project-update':
756
+ return { icon: 'folder', title: 'Project', subtitle: input.name || input.project };
757
+ case 'project_select':
758
+ case 'project-select':
759
+ case 'oc-project_select':
760
+ case 'oc-project-select':
761
+ return { icon: 'folder', title: 'Project Select', subtitle: input.project };
762
+ case 'project_create':
763
+ case 'project-create':
764
+ case 'oc-project_create':
765
+ case 'oc-project-create':
766
+ return { icon: 'folder-plus', title: 'Project Create', subtitle: input.name };
767
+ case 'triggers':
768
+ case 'trigger_create':
769
+ case 'trigger-create':
770
+ case 'oc-trigger_create':
771
+ case 'oc-trigger-create':
772
+ return { icon: 'clock', title: 'Create Trigger', subtitle: input.name };
773
+ case 'trigger_list':
774
+ case 'trigger-list':
775
+ case 'oc-trigger_list':
776
+ case 'oc-trigger-list':
777
+ return { icon: 'clock', title: 'List Triggers' };
778
+ case 'trigger_get':
779
+ case 'trigger-get':
780
+ case 'oc-trigger_get':
781
+ case 'oc-trigger-get':
782
+ return { icon: 'clock', title: 'Trigger Details', subtitle: input.name || input.id };
783
+ case 'trigger_delete':
784
+ case 'trigger-delete':
785
+ case 'oc-trigger_delete':
786
+ case 'oc-trigger-delete':
787
+ return { icon: 'clock', title: 'Delete Trigger', subtitle: input.name || input.id };
788
+ case 'trigger_update':
789
+ case 'trigger-update':
790
+ case 'oc-trigger_update':
791
+ case 'oc-trigger-update':
792
+ return { icon: 'clock', title: 'Update Trigger', subtitle: input.name || input.id };
793
+ case 'trigger_test':
794
+ case 'trigger-test':
795
+ case 'oc-trigger_test':
796
+ case 'oc-trigger-test':
797
+ return { icon: 'clock', title: 'Test Trigger', subtitle: input.name || input.id };
798
+ case 'trigger_pause':
799
+ case 'trigger-pause':
800
+ case 'oc-trigger_pause':
801
+ case 'oc-trigger-pause':
802
+ return { icon: 'clock', title: 'Pause Trigger', subtitle: input.name || input.id };
803
+ case 'trigger_resume':
804
+ case 'trigger-resume':
805
+ case 'oc-trigger_resume':
806
+ case 'oc-trigger-resume':
807
+ return { icon: 'clock', title: 'Resume Trigger', subtitle: input.name || input.id };
808
+ case 'agent_spawn':
809
+ case 'agent-spawn':
810
+ return {
811
+ icon: 'cpu',
812
+ title: `Agent (${input.agent_type || 'worker'})`,
813
+ subtitle: input.description,
814
+ };
815
+ case 'agent_message':
816
+ case 'agent-message':
817
+ return { icon: 'message-circle', title: 'Agent Message', subtitle: input.agent_id };
818
+ case 'agent_stop':
819
+ case 'agent-stop':
820
+ return { icon: 'ban', title: 'Agent Stop', subtitle: input.agent_id };
821
+ case 'agent_status':
822
+ case 'agent-status':
823
+ return { icon: 'layers', title: 'Agent Status' };
824
+ case 'agent_task':
825
+ case 'agent-task':
826
+ case 'oc-agent_task':
827
+ case 'oc-agent-task':
828
+ return { icon: 'check-square', title: 'Create Task', subtitle: input.title };
829
+ case 'agent_task_update':
830
+ case 'agent-task-update':
831
+ case 'oc-agent_task_update':
832
+ case 'oc-agent-task-update':
833
+ return { icon: 'check-square', title: 'Update Task', subtitle: input.task_id };
834
+ case 'agent_task_list':
835
+ case 'agent-task-list':
836
+ case 'oc-agent_task_list':
837
+ case 'oc-agent-task-list':
838
+ return { icon: 'check-square', title: 'List Tasks' };
839
+ case 'agent_task_get':
840
+ case 'agent-task-get':
841
+ case 'oc-agent_task_get':
842
+ case 'oc-agent-task-get':
843
+ return { icon: 'check-square', title: 'Task Details', subtitle: input.task_id };
844
+ case 'task_create':
845
+ case 'task-create':
846
+ return { icon: 'plus', title: 'Create Task', subtitle: input.title };
847
+ case 'task_list':
848
+ case 'task-list':
849
+ return { icon: 'list', title: 'Tasks', subtitle: input.status || 'all' };
850
+ case 'task_update':
851
+ case 'task-update':
852
+ return { icon: 'refresh-cw', title: 'Update Task', subtitle: input.id };
853
+ case 'task_done':
854
+ case 'task-done':
855
+ return { icon: 'check-circle', title: 'Task Done', subtitle: input.id };
856
+ case 'task_delete':
857
+ case 'task-delete':
858
+ return { icon: 'trash-2', title: 'Delete Task', subtitle: input.id };
859
+ case 'pty_spawn':
860
+ return { icon: 'terminal', title: 'Spawn', subtitle: input.title || input.command };
861
+ case 'pty_read':
862
+ return { icon: 'terminal', title: 'Terminal Output', subtitle: input.id };
863
+ case 'pty_write':
864
+ case 'pty_input':
865
+ return { icon: 'terminal', title: 'Terminal Input', subtitle: input.id };
866
+ case 'pty_kill':
867
+ return { icon: 'terminal', title: 'Kill Process', subtitle: input.id };
868
+ default:
869
+ return { icon: 'cpu', title: tool };
870
+ }
871
+ }
872
+ // ============================================================================
873
+ // Path helpers
874
+ // ============================================================================
875
+ /** Extract filename from a path. */
876
+ export function getFilename(path) {
877
+ if (!path)
878
+ return undefined;
879
+ const parts = path.split('/');
880
+ return parts[parts.length - 1] || path;
881
+ }
882
+ /** Extract filename + parent directory, e.g. "main.go /workspace" */
883
+ export function getFileWithDir(path) {
884
+ if (!path)
885
+ return undefined;
886
+ const parts = path.split('/');
887
+ const filename = parts[parts.length - 1] || path;
888
+ if (parts.length <= 1)
889
+ return filename;
890
+ // Get parent directory name (last directory segment)
891
+ const dir = parts[parts.length - 2];
892
+ return dir ? `${filename} /${dir}` : filename;
893
+ }
894
+ /** Extract directory from a path and strip trailing slash. */
895
+ export function getDirectory(path) {
896
+ if (!path)
897
+ return undefined;
898
+ const idx = path.lastIndexOf('/');
899
+ if (idx < 0)
900
+ return undefined;
901
+ return path.slice(0, idx) || '/';
902
+ }
903
+ /** Strip the project root directory from paths for display. */
904
+ export function relativizePath(path, projectDir) {
905
+ if (!projectDir)
906
+ return path;
907
+ if (path.startsWith(projectDir)) {
908
+ const rel = path.slice(projectDir.length);
909
+ return rel.startsWith('/') ? rel.slice(1) : rel;
910
+ }
911
+ return path;
912
+ }
913
+ // ============================================================================
914
+ // Agent card labels
915
+ // ============================================================================
916
+ function firstMeaningfulLine(value, maxLength = 120) {
917
+ if (typeof value !== 'string')
918
+ return '';
919
+ const line = value
920
+ .split('\n')
921
+ .map((segment) => segment.trim())
922
+ .find(Boolean);
923
+ if (!line)
924
+ return '';
925
+ return line.length > maxLength ? `${line.slice(0, maxLength).trim()}…` : line;
926
+ }
927
+ /**
928
+ * One-line label for an agent/task card, with graceful fallbacks when the
929
+ * tool input has no description.
930
+ */
931
+ export function getAgentCardLabel(input) {
932
+ const description = firstMeaningfulLine(input.description);
933
+ if (description)
934
+ return description;
935
+ const title = firstMeaningfulLine(input.title, 80);
936
+ if (title)
937
+ return title;
938
+ const message = firstMeaningfulLine(input.message);
939
+ if (message)
940
+ return message;
941
+ const promptPreview = firstMeaningfulLine(input.prompt);
942
+ if (promptPreview)
943
+ return promptPreview;
944
+ const agentId = firstMeaningfulLine(input.agent_id, 40);
945
+ if (agentId)
946
+ return `Agent ${agentId}`;
947
+ return 'Worker task';
948
+ }
949
+ // ============================================================================
950
+ // Diagnostics
951
+ // ============================================================================
952
+ /**
953
+ * Filter diagnostics for a file path, keeping only errors (severity=1), max 3.
954
+ * Matches SolidJS getDiagnostics — message-part.tsx:53-90
955
+ */
956
+ export function getDiagnostics(diagnosticsByFile, filePath) {
957
+ if (!diagnosticsByFile || !filePath)
958
+ return [];
959
+ const diags = diagnosticsByFile[filePath] ?? [];
960
+ return diags.filter((d) => d.severity === 1).slice(0, 3);
961
+ }
962
+ // ============================================================================
963
+ // Permission / Question matching
964
+ // ============================================================================
965
+ /** Get the permission request matching a specific tool part. */
966
+ export function getPermissionForTool(permissions, callID) {
967
+ return permissions.find((p) => p.tool?.callID === callID);
968
+ }
969
+ /** Get the question request matching a specific tool part. */
970
+ export function getQuestionForTool(questions, callID) {
971
+ return questions.find((q) => q.tool?.callID === callID);
972
+ }
973
+ // ============================================================================
974
+ // Cost & Token helpers
975
+ // ============================================================================
976
+ /**
977
+ * Platform markup applied to raw provider costs.
978
+ *
979
+ * The step-finish parts report raw provider cost (what the LLM vendor charges).
980
+ * The billing system deducts cost × COST_MARKUP from the user's credits.
981
+ * We apply the same multiplier here so the UI matches what's actually billed.
982
+ *
983
+ * Must stay in sync with KORTIX_MARKUP in apps/api/src/config.ts.
984
+ */
985
+ export const COST_MARKUP = 1.2;
986
+ function estimateTokenCost(tokens, rates) {
987
+ if (!tokens)
988
+ return 0;
989
+ const input = tokens.input ?? 0;
990
+ const output = (tokens.output ?? 0) + (tokens.reasoning ?? 0);
991
+ const cacheRead = tokens.cache?.read ?? 0;
992
+ const cacheWrite = tokens.cache?.write ?? 0;
993
+ const regularInput = Math.max(0, input - cacheRead - cacheWrite);
994
+ let cost = (regularInput / 1_000_000) * rates.inputPer1M;
995
+ cost += (output / 1_000_000) * rates.outputPer1M;
996
+ if (cacheRead > 0) {
997
+ cost += (cacheRead / 1_000_000) * (rates.cacheReadPer1M ?? rates.inputPer1M);
998
+ }
999
+ if (cacheWrite > 0) {
1000
+ cost += (cacheWrite / 1_000_000) * rates.inputPer1M;
1001
+ }
1002
+ return cost;
1003
+ }
1004
+ function stepFinishRawCost(sfp, providerID, modelID, lookup) {
1005
+ const reported = sfp.cost || 0;
1006
+ if (reported > 0)
1007
+ return reported;
1008
+ if (!lookup || !providerID || !modelID)
1009
+ return 0;
1010
+ const rates = lookup(providerID, modelID);
1011
+ if (!rates)
1012
+ return 0;
1013
+ return estimateTokenCost(sfp.tokens, rates);
1014
+ }
1015
+ function assistantMessageIds(message) {
1016
+ if (message.role !== 'assistant')
1017
+ return {};
1018
+ const assistant = message;
1019
+ return { providerID: assistant.providerID, modelID: assistant.modelID };
1020
+ }
1021
+ /**
1022
+ * Aggregate cost/token info from step-finish parts in a turn.
1023
+ * Returns undefined if no step-finish parts found.
1024
+ *
1025
+ * The cost is multiplied by COST_MARKUP so the displayed value matches
1026
+ * the actual credits deducted (raw provider cost × 1.2).
1027
+ */
1028
+ export function getTurnCost(parts, lookup) {
1029
+ let totalCost = 0;
1030
+ let input = 0;
1031
+ let output = 0;
1032
+ let reasoning = 0;
1033
+ let cacheRead = 0;
1034
+ let cacheWrite = 0;
1035
+ let found = false;
1036
+ for (const { part, message } of parts) {
1037
+ if (part.type === 'step-finish') {
1038
+ found = true;
1039
+ const sfp = part;
1040
+ const { providerID, modelID } = assistantMessageIds(message.info);
1041
+ totalCost += stepFinishRawCost(sfp, providerID, modelID, lookup);
1042
+ input += sfp.tokens?.input || 0;
1043
+ output += sfp.tokens?.output || 0;
1044
+ reasoning += sfp.tokens?.reasoning || 0;
1045
+ cacheRead += sfp.tokens?.cache?.read || 0;
1046
+ cacheWrite += sfp.tokens?.cache?.write || 0;
1047
+ }
1048
+ }
1049
+ if (!found) {
1050
+ for (const { message } of parts) {
1051
+ if (message.info.role !== 'assistant')
1052
+ continue;
1053
+ const assistant = message.info;
1054
+ const stepCost = assistantTokensCost(assistant, lookup);
1055
+ if (stepCost <= 0)
1056
+ continue;
1057
+ found = true;
1058
+ totalCost += stepCost;
1059
+ const t = assistant.tokens;
1060
+ if (t) {
1061
+ input += t.input ?? 0;
1062
+ output += t.output ?? 0;
1063
+ reasoning += t.reasoning ?? 0;
1064
+ cacheRead += t.cache?.read ?? 0;
1065
+ cacheWrite += t.cache?.write ?? 0;
1066
+ }
1067
+ }
1068
+ }
1069
+ if (!found)
1070
+ return undefined;
1071
+ return {
1072
+ cost: totalCost * COST_MARKUP,
1073
+ tokens: { input, output, reasoning, cacheRead, cacheWrite },
1074
+ };
1075
+ }
1076
+ function assistantTokensCost(assistant, lookup) {
1077
+ if (!lookup || !assistant.providerID || !assistant.modelID || !assistant.tokens)
1078
+ return 0;
1079
+ const rates = lookup(assistant.providerID, assistant.modelID);
1080
+ if (!rates)
1081
+ return 0;
1082
+ return estimateTokenCost({
1083
+ input: assistant.tokens.input,
1084
+ output: assistant.tokens.output,
1085
+ reasoning: assistant.tokens.reasoning,
1086
+ cache: assistant.tokens.cache,
1087
+ }, rates);
1088
+ }
1089
+ /**
1090
+ * Aggregate billed cost for an entire session from step-finish parts.
1091
+ * Matches per-turn `getTurnCost` and mobile session stats aggregation.
1092
+ */
1093
+ export function getSessionCost(messages, lookup) {
1094
+ let totalCost = 0;
1095
+ for (const msg of messages) {
1096
+ if (msg.info?.role !== 'assistant')
1097
+ continue;
1098
+ const assistant = msg.info;
1099
+ const { providerID, modelID } = assistantMessageIds(assistant);
1100
+ let msgCost = 0;
1101
+ let sawStepFinish = false;
1102
+ for (const part of msg.parts) {
1103
+ if (part.type !== 'step-finish')
1104
+ continue;
1105
+ sawStepFinish = true;
1106
+ msgCost += stepFinishRawCost(part, providerID, modelID, lookup);
1107
+ }
1108
+ if (!sawStepFinish) {
1109
+ msgCost += assistantTokensCost(assistant, lookup);
1110
+ }
1111
+ totalCost += msgCost;
1112
+ }
1113
+ return totalCost * COST_MARKUP;
1114
+ }
1115
+ /** Format cost in USD (e.g. "$0.0032") */
1116
+ export function formatCost(cost) {
1117
+ if (cost === 0)
1118
+ return '$0.00';
1119
+ if (cost < 0.001)
1120
+ return `$${cost.toFixed(4)}`;
1121
+ if (cost < 0.01)
1122
+ return `$${cost.toFixed(3)}`;
1123
+ return `$${cost.toFixed(2)}`;
1124
+ }
1125
+ /** Format token count (e.g. "12.3k") */
1126
+ export function formatTokens(tokens) {
1127
+ if (tokens < 1000)
1128
+ return String(tokens);
1129
+ if (tokens < 10000)
1130
+ return `${(tokens / 1000).toFixed(1)}k`;
1131
+ return `${Math.round(tokens / 1000)}k`;
1132
+ }
1133
+ // ============================================================================
1134
+ // Retry helpers
1135
+ // ============================================================================
1136
+ /**
1137
+ * Extract retry info from session status.
1138
+ * Truncates message to 60 chars matching SolidJS session-turn.tsx:695
1139
+ */
1140
+ export function getRetryInfo(status) {
1141
+ if (!status || status.type !== 'retry')
1142
+ return undefined;
1143
+ const retry = status;
1144
+ return {
1145
+ attempt: retry.attempt,
1146
+ message: retry.message.length > 60 ? `${retry.message.slice(0, 60)}...` : retry.message,
1147
+ next: retry.next,
1148
+ };
1149
+ }
1150
+ /**
1151
+ * Extract the full retry error message from session status (not truncated).
1152
+ */
1153
+ export function getRetryMessage(status) {
1154
+ if (!status || status.type !== 'retry')
1155
+ return undefined;
1156
+ return unwrapError(status.message);
1157
+ }
1158
+ // ============================================================================
1159
+ // hasDiffs check
1160
+ // ============================================================================
1161
+ /** Check if a user message has associated file diffs. */
1162
+ export function hasDiffs(userMessage) {
1163
+ const summary = userMessage.info.summary;
1164
+ return (summary?.diffs?.length ?? 0) > 0;
1165
+ }
1166
+ // ============================================================================
1167
+ // ANSI strip (used by bash tool renderer)
1168
+ // ============================================================================
1169
+ // OSC payloads (window titles, OSC-8 hyperlink URLs) are never more than a
1170
+ // couple hundred bytes in real terminal output; capping the run length keeps
1171
+ // stripAnsi linear-time even when `str.replace` retries the scan from every
1172
+ // unterminated OSC start in an adversarial input (see turns.test.ts).
1173
+ const ANSI_RE =
1174
+ // biome-ignore lint/suspicious/noControlCharactersInRegex: matching terminal escape sequences requires literal ESC/BEL control characters
1175
+ /\x1B\[[\d;]*[A-Za-z]|\x1B\][^\x07]{0,512}\x07|\x1B[()#][A-Z0-9]|\x1B\[?[\d;]*[hl]|\x1B[>=<]|\x1B\[[?]?\d*[A-Z]|\x1B\[\d*[JKHG]|\x1B\[\d*;\d*[Hf]|\x1b\[[0-9;]*m/g;
1176
+ /** Strip ANSI escape codes from terminal output. */
1177
+ export function stripAnsi(str) {
1178
+ if (!str)
1179
+ return '';
1180
+ return str.replace(ANSI_RE, '');
1181
+ }
1182
+ // ============================================================================
1183
+ // Session list helpers (sidebar / tabs)
1184
+ // ============================================================================
1185
+ /**
1186
+ * Build a map from parent session ID → array of child session IDs.
1187
+ * Used to aggregate child session status (permissions, busy) in the sidebar.
1188
+ * Matches SolidJS reference `childMapByParent()` in helpers.ts.
1189
+ */
1190
+ export function childMapByParent(sessions) {
1191
+ const map = new Map();
1192
+ for (const session of sessions) {
1193
+ if (!session.parentID)
1194
+ continue;
1195
+ const existing = map.get(session.parentID);
1196
+ if (existing) {
1197
+ existing.push(session.id);
1198
+ }
1199
+ else {
1200
+ map.set(session.parentID, [session.id]);
1201
+ }
1202
+ }
1203
+ return map;
1204
+ }
1205
+ /**
1206
+ * Sort comparator for sessions.
1207
+ * Two tiers:
1208
+ * 1. Sessions updated within `now - 60s` are pinned to top, sorted by ID (stable).
1209
+ * 2. Older sessions sorted by `updated` time descending.
1210
+ * Matches SolidJS reference `sortSessions()` in helpers.ts.
1211
+ */
1212
+ export function sortSessions(now) {
1213
+ const oneMinuteAgo = now - 60 * 1000;
1214
+ return (a, b) => {
1215
+ const aUpdated = a.time.updated ?? a.time.created;
1216
+ const bUpdated = b.time.updated ?? b.time.created;
1217
+ const aRecent = aUpdated > oneMinuteAgo;
1218
+ const bRecent = bUpdated > oneMinuteAgo;
1219
+ if (aRecent && bRecent)
1220
+ return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
1221
+ if (aRecent && !bRecent)
1222
+ return -1;
1223
+ if (!aRecent && bRecent)
1224
+ return 1;
1225
+ return bUpdated - aUpdated;
1226
+ };
1227
+ }
1228
+ /**
1229
+ * Recursively collect ALL descendant session IDs for a given parent.
1230
+ * Walks the full tree so deeply nested sub-agents are included.
1231
+ */
1232
+ export function allDescendantIds(childMap, sessionId) {
1233
+ const directChildren = childMap.get(sessionId);
1234
+ if (!directChildren || directChildren.length === 0)
1235
+ return [];
1236
+ const result = [];
1237
+ for (const childId of directChildren) {
1238
+ result.push(childId);
1239
+ result.push(...allDescendantIds(childMap, childId));
1240
+ }
1241
+ return result;
1242
+ }
1243
+ //# sourceMappingURL=index.js.map