@tomsun28/pizza 0.0.9 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (382) hide show
  1. package/README.md +20 -143
  2. package/README.zh-CN.md +36 -0
  3. package/dist/bun/cli.d.ts +2 -0
  4. package/dist/bun/cli.js +6 -0
  5. package/dist/bun/register-bedrock.d.ts +1 -0
  6. package/dist/bun/register-bedrock.js +3 -0
  7. package/dist/cli/args.d.ts +48 -0
  8. package/dist/cli/args.js +330 -0
  9. package/dist/cli/config-selector.d.ts +13 -0
  10. package/dist/cli/config-selector.js +30 -0
  11. package/dist/cli/file-processor.d.ts +14 -0
  12. package/dist/cli/file-processor.js +82 -0
  13. package/dist/cli/initial-message.d.ts +17 -0
  14. package/dist/cli/initial-message.js +21 -0
  15. package/dist/cli/list-models.d.ts +8 -0
  16. package/dist/cli/list-models.js +96 -0
  17. package/dist/cli.d.ts +2 -0
  18. package/dist/cli.js +68 -0
  19. package/dist/config.d.ts +79 -0
  20. package/dist/config.js +223 -0
  21. package/dist/core/agent/index.d.ts +6 -0
  22. package/dist/core/agent/index.js +6 -0
  23. package/dist/core/agent/types.d.ts +202 -0
  24. package/dist/core/agent/types.js +51 -0
  25. package/dist/core/auth-storage.d.ts +135 -0
  26. package/dist/core/auth-storage.js +417 -0
  27. package/dist/core/bash-executor.d.ts +31 -0
  28. package/dist/core/bash-executor.js +107 -0
  29. package/dist/core/compaction/branch-summarization.d.ts +87 -0
  30. package/dist/core/compaction/branch-summarization.js +242 -0
  31. package/dist/core/compaction/compaction-engine.d.ts +40 -0
  32. package/dist/core/compaction/compaction-engine.js +292 -0
  33. package/dist/core/compaction/compaction.d.ts +106 -0
  34. package/dist/core/compaction/compaction.js +295 -0
  35. package/dist/core/compaction/index.d.ts +7 -0
  36. package/dist/core/compaction/index.js +7 -0
  37. package/dist/core/compaction/utils.d.ts +37 -0
  38. package/dist/core/compaction/utils.js +152 -0
  39. package/dist/core/defaults.d.ts +2 -0
  40. package/dist/core/defaults.js +1 -0
  41. package/dist/core/diagnostics.d.ts +14 -0
  42. package/dist/core/diagnostics.js +1 -0
  43. package/dist/core/event-bus.d.ts +8 -0
  44. package/dist/core/event-bus.js +24 -0
  45. package/dist/core/event-store/events.d.ts +465 -0
  46. package/dist/core/event-store/events.js +6 -0
  47. package/dist/core/event-store/index.d.ts +10 -0
  48. package/dist/core/event-store/index.js +10 -0
  49. package/dist/core/event-store/sqlite-store.d.ts +27 -0
  50. package/dist/core/event-store/sqlite-store.js +275 -0
  51. package/dist/core/event-store/store.d.ts +91 -0
  52. package/dist/core/event-store/store.js +7 -0
  53. package/dist/core/event-store/thread-scoped-store.d.ts +29 -0
  54. package/dist/core/event-store/thread-scoped-store.js +50 -0
  55. package/dist/core/event-store/types.d.ts +70 -0
  56. package/dist/core/event-store/types.js +7 -0
  57. package/dist/core/event-store/workspace.d.ts +37 -0
  58. package/dist/core/event-store/workspace.js +71 -0
  59. package/dist/core/exec.d.ts +28 -0
  60. package/dist/core/exec.js +74 -0
  61. package/dist/core/export-html/ansi-to-html.d.ts +21 -0
  62. package/dist/core/export-html/ansi-to-html.js +248 -0
  63. package/dist/core/export-html/index.d.ts +29 -0
  64. package/dist/core/export-html/index.js +186 -0
  65. package/dist/core/export-html/template.css +1017 -0
  66. package/dist/core/export-html/template.html +55 -0
  67. package/dist/core/export-html/template.js +1742 -0
  68. package/dist/core/export-html/tool-renderer.d.ts +39 -0
  69. package/dist/core/export-html/tool-renderer.js +94 -0
  70. package/dist/core/export-html/vendor/highlight.min.js +1213 -0
  71. package/dist/core/export-html/vendor/marked.min.js +6 -0
  72. package/dist/core/extensions/index.d.ts +12 -0
  73. package/dist/core/extensions/index.js +9 -0
  74. package/dist/core/extensions/loader.d.ts +24 -0
  75. package/dist/core/extensions/loader.js +492 -0
  76. package/dist/core/extensions/runner.d.ts +167 -0
  77. package/dist/core/extensions/runner.js +898 -0
  78. package/dist/core/extensions/session-context.d.ts +67 -0
  79. package/dist/core/extensions/session-context.js +272 -0
  80. package/dist/core/extensions/types.d.ts +1147 -0
  81. package/dist/core/extensions/types.js +44 -0
  82. package/dist/core/extensions/wrapper.d.ts +19 -0
  83. package/dist/core/extensions/wrapper.js +21 -0
  84. package/dist/core/footer-data-provider.d.ts +47 -0
  85. package/dist/core/footer-data-provider.js +321 -0
  86. package/dist/core/goal/index.d.ts +3 -0
  87. package/dist/core/goal/index.js +1 -0
  88. package/dist/core/goal/scheduler.d.ts +83 -0
  89. package/dist/core/goal/scheduler.js +154 -0
  90. package/dist/core/goal/types.d.ts +182 -0
  91. package/dist/core/goal/types.js +11 -0
  92. package/dist/core/index.d.ts +8 -0
  93. package/dist/core/index.js +8 -0
  94. package/dist/core/intent/classifier.d.ts +53 -0
  95. package/dist/core/intent/classifier.js +353 -0
  96. package/dist/core/intent/index.d.ts +8 -0
  97. package/dist/core/intent/index.js +8 -0
  98. package/dist/core/intent/tool-adapter.d.ts +31 -0
  99. package/dist/core/intent/tool-adapter.js +168 -0
  100. package/dist/core/intent/types.d.ts +71 -0
  101. package/dist/core/intent/types.js +6 -0
  102. package/dist/core/keybindings.d.ts +297 -0
  103. package/dist/core/keybindings.js +250 -0
  104. package/dist/core/messages.d.ts +30 -0
  105. package/dist/core/messages.js +134 -0
  106. package/dist/core/model-registry.d.ts +131 -0
  107. package/dist/core/model-registry.js +634 -0
  108. package/dist/core/model-resolver.d.ts +109 -0
  109. package/dist/core/model-resolver.js +486 -0
  110. package/dist/core/output-guard.d.ts +5 -0
  111. package/dist/core/output-guard.js +58 -0
  112. package/dist/core/package-manager.d.ts +196 -0
  113. package/dist/core/package-manager.js +1873 -0
  114. package/dist/core/projection/boundary-inferrer.d.ts +58 -0
  115. package/dist/core/projection/boundary-inferrer.js +122 -0
  116. package/dist/core/projection/event-to-message.d.ts +35 -0
  117. package/dist/core/projection/event-to-message.js +253 -0
  118. package/dist/core/projection/goal-projection.d.ts +67 -0
  119. package/dist/core/projection/goal-projection.js +339 -0
  120. package/dist/core/projection/index.d.ts +13 -0
  121. package/dist/core/projection/index.js +13 -0
  122. package/dist/core/projection/session-manager.d.ts +100 -0
  123. package/dist/core/projection/session-manager.js +331 -0
  124. package/dist/core/projection/session-projection.d.ts +58 -0
  125. package/dist/core/projection/session-projection.js +257 -0
  126. package/dist/core/projection/task-history.d.ts +13 -0
  127. package/dist/core/projection/task-history.js +61 -0
  128. package/dist/core/projection/timeline-projection.d.ts +82 -0
  129. package/dist/core/projection/timeline-projection.js +276 -0
  130. package/dist/core/projection/types.d.ts +69 -0
  131. package/dist/core/projection/types.js +6 -0
  132. package/dist/core/prompt-templates.d.ts +51 -0
  133. package/dist/core/prompt-templates.js +249 -0
  134. package/dist/core/resolve-config-value.d.ts +22 -0
  135. package/dist/core/resolve-config-value.js +125 -0
  136. package/dist/core/resource-loader.d.ts +193 -0
  137. package/dist/core/resource-loader.js +685 -0
  138. package/dist/core/runtime/ai-client.d.ts +12 -0
  139. package/dist/core/runtime/ai-client.js +153 -0
  140. package/dist/core/runtime/checkpoint.d.ts +12 -0
  141. package/dist/core/runtime/checkpoint.js +78 -0
  142. package/dist/core/runtime/index.d.ts +12 -0
  143. package/dist/core/runtime/index.js +12 -0
  144. package/dist/core/runtime/llm-types.d.ts +99 -0
  145. package/dist/core/runtime/llm-types.js +6 -0
  146. package/dist/core/runtime/local-runtime.d.ts +23 -0
  147. package/dist/core/runtime/local-runtime.js +59 -0
  148. package/dist/core/runtime/policies.d.ts +72 -0
  149. package/dist/core/runtime/policies.js +37 -0
  150. package/dist/core/runtime/reactor.d.ts +213 -0
  151. package/dist/core/runtime/reactor.js +992 -0
  152. package/dist/core/runtime/runtime.d.ts +191 -0
  153. package/dist/core/runtime/runtime.js +449 -0
  154. package/dist/core/runtime/types.d.ts +42 -0
  155. package/dist/core/runtime/types.js +1 -0
  156. package/dist/core/sdk.d.ts +12 -0
  157. package/dist/core/sdk.js +10 -0
  158. package/dist/core/session-context-builder.d.ts +9 -0
  159. package/dist/core/session-context-builder.js +87 -0
  160. package/dist/core/session-cwd.d.ts +18 -0
  161. package/dist/core/session-cwd.js +36 -0
  162. package/dist/core/session-facade-factory.d.ts +79 -0
  163. package/dist/core/session-facade-factory.js +460 -0
  164. package/dist/core/session-facade.d.ts +57 -0
  165. package/dist/core/session-facade.js +91 -0
  166. package/dist/core/session-listing.d.ts +30 -0
  167. package/dist/core/session-listing.js +168 -0
  168. package/dist/core/session-reader.d.ts +19 -0
  169. package/dist/core/session-reader.js +101 -0
  170. package/dist/core/session-ref.d.ts +7 -0
  171. package/dist/core/session-ref.js +25 -0
  172. package/dist/core/session-services.d.ts +51 -0
  173. package/dist/core/session-services.js +90 -0
  174. package/dist/core/session-stats.d.ts +43 -0
  175. package/dist/core/session-stats.js +41 -0
  176. package/dist/core/settings-manager.d.ts +236 -0
  177. package/dist/core/settings-manager.js +706 -0
  178. package/dist/core/skill-block-parser.d.ts +12 -0
  179. package/dist/core/skill-block-parser.js +15 -0
  180. package/dist/core/skills.d.ts +59 -0
  181. package/dist/core/skills.js +408 -0
  182. package/dist/core/slash-commands.d.ts +13 -0
  183. package/dist/core/slash-commands.js +17 -0
  184. package/dist/core/source-info.d.ts +17 -0
  185. package/dist/core/source-info.js +18 -0
  186. package/dist/core/system-prompt.d.ts +27 -0
  187. package/dist/core/system-prompt.js +179 -0
  188. package/dist/core/timings.d.ts +7 -0
  189. package/dist/core/timings.js +30 -0
  190. package/dist/core/tools/bash.d.ts +95 -0
  191. package/dist/core/tools/bash.js +513 -0
  192. package/dist/core/tools/builtin-commands.d.ts +75 -0
  193. package/dist/core/tools/builtin-commands.js +503 -0
  194. package/dist/core/tools/compat-commands.d.ts +12 -0
  195. package/dist/core/tools/compat-commands.js +1280 -0
  196. package/dist/core/tools/edit-diff.d.ts +59 -0
  197. package/dist/core/tools/edit-diff.js +263 -0
  198. package/dist/core/tools/edit.d.ts +49 -0
  199. package/dist/core/tools/edit.js +340 -0
  200. package/dist/core/tools/file-mutation-queue.d.ts +5 -0
  201. package/dist/core/tools/file-mutation-queue.js +36 -0
  202. package/dist/core/tools/find.d.ts +34 -0
  203. package/dist/core/tools/find.js +459 -0
  204. package/dist/core/tools/grep.d.ts +36 -0
  205. package/dist/core/tools/grep.js +422 -0
  206. package/dist/core/tools/index.d.ts +70 -0
  207. package/dist/core/tools/index.js +129 -0
  208. package/dist/core/tools/line-anchors.d.ts +33 -0
  209. package/dist/core/tools/line-anchors.js +151 -0
  210. package/dist/core/tools/ls.d.ts +36 -0
  211. package/dist/core/tools/ls.js +268 -0
  212. package/dist/core/tools/path-utils.d.ts +7 -0
  213. package/dist/core/tools/path-utils.js +80 -0
  214. package/dist/core/tools/read.d.ts +35 -0
  215. package/dist/core/tools/read.js +244 -0
  216. package/dist/core/tools/render-utils.d.ts +20 -0
  217. package/dist/core/tools/render-utils.js +48 -0
  218. package/dist/core/tools/session-split.d.ts +9 -0
  219. package/dist/core/tools/session-split.js +77 -0
  220. package/dist/core/tools/tool-definition-wrapper.d.ts +13 -0
  221. package/dist/core/tools/tool-definition-wrapper.js +32 -0
  222. package/dist/core/tools/truncate.d.ts +69 -0
  223. package/dist/core/tools/truncate.js +204 -0
  224. package/dist/core/tools/write.d.ts +25 -0
  225. package/dist/core/tools/write.js +211 -0
  226. package/dist/core/types/session-types.d.ts +123 -0
  227. package/dist/core/types/session-types.js +8 -0
  228. package/dist/index.d.ts +27 -0
  229. package/dist/index.js +38 -0
  230. package/dist/main.d.ts +11 -2
  231. package/dist/main.js +577 -149
  232. package/dist/modes/event-mapper.d.ts +115 -0
  233. package/dist/modes/event-mapper.js +200 -0
  234. package/dist/modes/gui/server.d.ts +14 -0
  235. package/dist/modes/gui/server.js +1032 -0
  236. package/dist/modes/index.d.ts +10 -0
  237. package/dist/modes/index.js +9 -0
  238. package/dist/modes/interactive/assets/clankolas.png +0 -0
  239. package/dist/modes/interactive/components/armin.d.ts +33 -0
  240. package/dist/modes/interactive/components/armin.js +328 -0
  241. package/dist/modes/interactive/components/assistant-message.d.ts +19 -0
  242. package/dist/modes/interactive/components/assistant-message.js +115 -0
  243. package/dist/modes/interactive/components/bash-execution.d.ts +33 -0
  244. package/dist/modes/interactive/components/bash-execution.js +169 -0
  245. package/dist/modes/interactive/components/bordered-loader.d.ts +15 -0
  246. package/dist/modes/interactive/components/bordered-loader.js +50 -0
  247. package/dist/modes/interactive/components/branch-summary-message.d.ts +15 -0
  248. package/dist/modes/interactive/components/branch-summary-message.js +41 -0
  249. package/dist/modes/interactive/components/brand-header.d.ts +33 -0
  250. package/dist/modes/interactive/components/brand-header.js +235 -0
  251. package/dist/modes/interactive/components/compaction-summary-message.d.ts +15 -0
  252. package/dist/modes/interactive/components/compaction-summary-message.js +42 -0
  253. package/dist/modes/interactive/components/config-selector.d.ts +70 -0
  254. package/dist/modes/interactive/components/config-selector.js +469 -0
  255. package/dist/modes/interactive/components/countdown-timer.d.ts +13 -0
  256. package/dist/modes/interactive/components/countdown-timer.js +27 -0
  257. package/dist/modes/interactive/components/custom-editor.d.ts +27 -0
  258. package/dist/modes/interactive/components/custom-editor.js +94 -0
  259. package/dist/modes/interactive/components/custom-message.d.ts +19 -0
  260. package/dist/modes/interactive/components/custom-message.js +73 -0
  261. package/dist/modes/interactive/components/daxnuts.d.ts +22 -0
  262. package/dist/modes/interactive/components/daxnuts.js +137 -0
  263. package/dist/modes/interactive/components/diff.d.ts +11 -0
  264. package/dist/modes/interactive/components/diff.js +132 -0
  265. package/dist/modes/interactive/components/dynamic-border.d.ts +14 -0
  266. package/dist/modes/interactive/components/dynamic-border.js +19 -0
  267. package/dist/modes/interactive/components/earendil-announcement.d.ts +4 -0
  268. package/dist/modes/interactive/components/earendil-announcement.js +39 -0
  269. package/dist/modes/interactive/components/extension-editor.d.ts +19 -0
  270. package/dist/modes/interactive/components/extension-editor.js +105 -0
  271. package/dist/modes/interactive/components/extension-input.d.ts +22 -0
  272. package/dist/modes/interactive/components/extension-input.js +54 -0
  273. package/dist/modes/interactive/components/extension-selector.d.ts +23 -0
  274. package/dist/modes/interactive/components/extension-selector.js +70 -0
  275. package/dist/modes/interactive/components/footer.d.ts +55 -0
  276. package/dist/modes/interactive/components/footer.js +207 -0
  277. package/dist/modes/interactive/components/index.d.ts +31 -0
  278. package/dist/modes/interactive/components/index.js +32 -0
  279. package/dist/modes/interactive/components/keybinding-hints.d.ts +7 -0
  280. package/dist/modes/interactive/components/keybinding-hints.js +21 -0
  281. package/dist/modes/interactive/components/login-dialog.d.ts +41 -0
  282. package/dist/modes/interactive/components/login-dialog.js +138 -0
  283. package/dist/modes/interactive/components/model-selector.d.ts +32 -0
  284. package/dist/modes/interactive/components/model-selector.js +209 -0
  285. package/dist/modes/interactive/components/oauth-selector.d.ts +18 -0
  286. package/dist/modes/interactive/components/oauth-selector.js +91 -0
  287. package/dist/modes/interactive/components/settings-selector.d.ts +57 -0
  288. package/dist/modes/interactive/components/settings-selector.js +299 -0
  289. package/dist/modes/interactive/components/show-images-selector.d.ts +9 -0
  290. package/dist/modes/interactive/components/show-images-selector.js +37 -0
  291. package/dist/modes/interactive/components/skill-invocation-message.d.ts +16 -0
  292. package/dist/modes/interactive/components/skill-invocation-message.js +44 -0
  293. package/dist/modes/interactive/components/theme-selector.d.ts +10 -0
  294. package/dist/modes/interactive/components/theme-selector.js +47 -0
  295. package/dist/modes/interactive/components/thinking-selector.d.ts +10 -0
  296. package/dist/modes/interactive/components/thinking-selector.js +50 -0
  297. package/dist/modes/interactive/components/timeline-view.d.ts +31 -0
  298. package/dist/modes/interactive/components/timeline-view.js +81 -0
  299. package/dist/modes/interactive/components/tool-execution.d.ts +64 -0
  300. package/dist/modes/interactive/components/tool-execution.js +305 -0
  301. package/dist/modes/interactive/components/tree-selector.d.ts +88 -0
  302. package/dist/modes/interactive/components/tree-selector.js +1072 -0
  303. package/dist/modes/interactive/components/user-message-selector.d.ts +29 -0
  304. package/dist/modes/interactive/components/user-message-selector.js +110 -0
  305. package/dist/modes/interactive/components/user-message.d.ts +9 -0
  306. package/dist/modes/interactive/components/user-message.js +27 -0
  307. package/dist/modes/interactive/components/visual-truncate.d.ts +23 -0
  308. package/dist/modes/interactive/components/visual-truncate.js +32 -0
  309. package/dist/modes/interactive/interactive-mode.d.ts +394 -0
  310. package/dist/modes/interactive/interactive-mode.js +4116 -0
  311. package/dist/modes/interactive/theme/dark.json +85 -0
  312. package/dist/modes/interactive/theme/light.json +84 -0
  313. package/dist/modes/interactive/theme/theme-schema.json +335 -0
  314. package/dist/modes/interactive/theme/theme.d.ts +80 -0
  315. package/dist/modes/interactive/theme/theme.js +973 -0
  316. package/dist/modes/print-mode.d.ts +27 -0
  317. package/dist/modes/print-mode.js +102 -0
  318. package/dist/modes/rpc/jsonl.d.ts +16 -0
  319. package/dist/modes/rpc/jsonl.js +48 -0
  320. package/dist/modes/rpc/rpc-client.d.ts +219 -0
  321. package/dist/modes/rpc/rpc-client.js +405 -0
  322. package/dist/modes/rpc/rpc-mode.d.ts +19 -0
  323. package/dist/modes/rpc/rpc-mode.js +381 -0
  324. package/dist/modes/rpc/rpc-types.d.ts +406 -0
  325. package/dist/modes/rpc/rpc-types.js +7 -0
  326. package/dist/package-manager-cli.d.ts +3 -0
  327. package/dist/package-manager-cli.js +233 -0
  328. package/dist/utils/changelog.d.ts +20 -0
  329. package/dist/utils/changelog.js +86 -0
  330. package/dist/utils/child-process.d.ts +10 -0
  331. package/dist/utils/child-process.js +77 -0
  332. package/dist/utils/clipboard-image.d.ts +10 -0
  333. package/dist/utils/clipboard-image.js +244 -0
  334. package/dist/utils/clipboard-native.d.ts +7 -0
  335. package/dist/utils/clipboard-native.js +13 -0
  336. package/dist/utils/clipboard.d.ts +1 -0
  337. package/dist/utils/clipboard.js +77 -0
  338. package/dist/utils/exif-orientation.d.ts +4 -0
  339. package/dist/utils/exif-orientation.js +157 -0
  340. package/dist/utils/frontmatter.d.ts +7 -0
  341. package/dist/utils/frontmatter.js +25 -0
  342. package/dist/utils/git.d.ts +25 -0
  343. package/dist/utils/git.js +162 -0
  344. package/dist/utils/image-convert.d.ts +8 -0
  345. package/dist/utils/image-convert.js +38 -0
  346. package/dist/utils/image-resize.d.ts +35 -0
  347. package/dist/utils/image-resize.js +136 -0
  348. package/dist/utils/mime.d.ts +1 -0
  349. package/dist/utils/mime.js +25 -0
  350. package/dist/utils/path-shims.d.ts +1 -0
  351. package/dist/utils/path-shims.js +90 -0
  352. package/dist/utils/paths.d.ts +6 -0
  353. package/dist/utils/paths.js +18 -0
  354. package/dist/utils/photon.d.ts +20 -0
  355. package/dist/utils/photon.js +120 -0
  356. package/dist/utils/shell.d.ts +29 -0
  357. package/dist/utils/shell.js +189 -0
  358. package/dist/utils/sleep.d.ts +4 -0
  359. package/dist/utils/sleep.js +16 -0
  360. package/dist/utils/tools-manager.d.ts +3 -0
  361. package/dist/utils/tools-manager.js +101 -0
  362. package/dist/vendor/bin/darwin-arm64/fd +0 -0
  363. package/dist/vendor/bin/darwin-arm64/rg +0 -0
  364. package/dist/vendor/bin/darwin-x64/fd +0 -0
  365. package/dist/vendor/bin/darwin-x64/rg +0 -0
  366. package/dist/vendor/bin/linux-arm64/fd +0 -0
  367. package/dist/vendor/bin/linux-arm64/rg +0 -0
  368. package/dist/vendor/bin/linux-x64/fd +0 -0
  369. package/dist/vendor/bin/linux-x64/rg +0 -0
  370. package/dist/vendor/bin/win32-arm64/fd.exe +0 -0
  371. package/dist/vendor/bin/win32-arm64/rg.exe +0 -0
  372. package/dist/vendor/bin/win32-x64/fd.exe +0 -0
  373. package/dist/vendor/bin/win32-x64/rg.exe +0 -0
  374. package/package.json +90 -26
  375. package/dist/extension/core.d.ts +0 -69
  376. package/dist/extension/core.js +0 -270
  377. package/dist/extension/core.js.map +0 -1
  378. package/dist/extension/index.d.ts +0 -25
  379. package/dist/extension/index.js +0 -303
  380. package/dist/extension/index.js.map +0 -1
  381. package/dist/main.js.map +0 -1
  382. package/themes/pizza.json +0 -87
@@ -0,0 +1,1032 @@
1
+ import { createServer } from "node:http";
2
+ import { URL } from "node:url";
3
+ import { mapTypedEventToModeEvents } from "../event-mapper.js";
4
+ export async function runGuiModeWithFacade(facade, options) {
5
+ const host = options.host ?? "127.0.0.1";
6
+ const port = options.port ?? 0;
7
+ const clients = new Map();
8
+ let nextClientId = 1;
9
+ let shuttingDown = false;
10
+ const broadcast = (event, data) => {
11
+ for (const client of clients.values()) {
12
+ writeSse(client.res, event, data);
13
+ }
14
+ };
15
+ const unsubscribe = facade.subscribe((event) => {
16
+ for (const modeEvent of mapTypedEventToModeEvents(event)) {
17
+ broadcast("mode_event", modeEvent);
18
+ }
19
+ if (shouldBroadcastState(event.type)) {
20
+ broadcast("state", getGuiState(facade, options.cwd));
21
+ }
22
+ });
23
+ const server = createServer((req, res) => {
24
+ void handleRequest(req, res, {
25
+ facade,
26
+ cwd: options.cwd,
27
+ clients,
28
+ nextClientId: () => nextClientId++,
29
+ });
30
+ });
31
+ await listen(server, port, host);
32
+ const address = server.address();
33
+ const url = `http://${host}:${address.port}`;
34
+ console.log(`Pizza GUI listening on ${url}`);
35
+ if (options.initialMessage && options.initialMessage.trim().length > 0) {
36
+ void facade.prompt(options.initialMessage, normalizeInitialImages(options.initialImages)).catch((error) => {
37
+ broadcast("server_error", formatError(error));
38
+ });
39
+ }
40
+ const shutdown = async (exitCode = 0) => {
41
+ if (shuttingDown) {
42
+ process.exit(exitCode);
43
+ }
44
+ shuttingDown = true;
45
+ unsubscribe();
46
+ for (const client of clients.values()) {
47
+ client.res.end();
48
+ }
49
+ clients.clear();
50
+ await closeServer(server);
51
+ facade.dispose();
52
+ process.exit(exitCode);
53
+ };
54
+ const onSigint = () => {
55
+ void shutdown(0);
56
+ };
57
+ const onSigterm = () => {
58
+ void shutdown(143);
59
+ };
60
+ process.on("SIGINT", onSigint);
61
+ process.on("SIGTERM", onSigterm);
62
+ return new Promise(() => { });
63
+ }
64
+ async function handleRequest(req, res, context) {
65
+ const method = req.method ?? "GET";
66
+ const url = new URL(req.url ?? "/", "http://localhost");
67
+ try {
68
+ if (method === "GET" && url.pathname === "/") {
69
+ sendHtml(res, INDEX_HTML);
70
+ return;
71
+ }
72
+ if (method === "GET" && url.pathname === "/events") {
73
+ const id = context.nextClientId();
74
+ res.writeHead(200, {
75
+ "Content-Type": "text/event-stream; charset=utf-8",
76
+ "Cache-Control": "no-cache, no-transform",
77
+ Connection: "keep-alive",
78
+ "X-Accel-Buffering": "no",
79
+ });
80
+ res.write(": connected\n\n");
81
+ context.clients.set(id, { id, res });
82
+ writeSse(res, "state", getGuiState(context.facade, context.cwd));
83
+ req.on("close", () => {
84
+ context.clients.delete(id);
85
+ });
86
+ return;
87
+ }
88
+ if (method === "GET" && url.pathname === "/api/bootstrap") {
89
+ sendJson(res, {
90
+ state: getGuiState(context.facade, context.cwd),
91
+ messages: getGuiMessages(context.facade),
92
+ });
93
+ return;
94
+ }
95
+ if (method === "POST" && url.pathname === "/api/prompt") {
96
+ const body = await readJsonBody(req);
97
+ const message = typeof body.message === "string" ? body.message.trim() : "";
98
+ const behavior = body.behavior;
99
+ if (message.length === 0) {
100
+ sendJson(res, { success: false, error: "Message is required" }, 400);
101
+ return;
102
+ }
103
+ if (behavior === "steer") {
104
+ context.facade.steer(message);
105
+ }
106
+ else if (behavior === "follow_up" || context.facade.isRunning) {
107
+ context.facade.followUp(message);
108
+ }
109
+ else {
110
+ void context.facade.prompt(message).catch((error) => {
111
+ for (const client of context.clients.values()) {
112
+ writeSse(client.res, "server_error", formatError(error));
113
+ }
114
+ });
115
+ }
116
+ sendJson(res, { success: true });
117
+ return;
118
+ }
119
+ if (method === "POST" && url.pathname === "/api/abort") {
120
+ context.facade.abort();
121
+ sendJson(res, { success: true });
122
+ return;
123
+ }
124
+ sendJson(res, { success: false, error: "Not found" }, 404);
125
+ }
126
+ catch (error) {
127
+ sendJson(res, { success: false, error: formatError(error) }, 500);
128
+ }
129
+ }
130
+ function getGuiState(facade, cwd) {
131
+ const descriptor = facade.getProjection().getDescriptor();
132
+ const modelConfig = facade.model;
133
+ const model = facade.modelRegistry?.find(modelConfig.provider, modelConfig.model_id);
134
+ const messageCount = facade.getProjection().buildContext().messages.length;
135
+ return {
136
+ cwd,
137
+ sessionId: descriptor.session_id,
138
+ model: {
139
+ provider: modelConfig.provider,
140
+ modelId: modelConfig.model_id,
141
+ displayName: model?.name,
142
+ },
143
+ thinkingLevel: facade.thinkingLevel ?? "off",
144
+ isRunning: facade.isRunning,
145
+ messageCount,
146
+ toolCount: facade.tools.length,
147
+ };
148
+ }
149
+ function getGuiMessages(facade) {
150
+ return facade.getProjection().buildContext().messages;
151
+ }
152
+ function shouldBroadcastState(eventType) {
153
+ return (eventType === "USER_MESSAGE" ||
154
+ eventType === "AGENT_TURN_START" ||
155
+ eventType === "AGENT_TURN_COMPLETED" ||
156
+ eventType === "MODEL_CHANGED" ||
157
+ eventType === "THINKING_LEVEL_CHANGED" ||
158
+ eventType === "SESSION_CREATED");
159
+ }
160
+ function normalizeInitialImages(images) {
161
+ if (!images)
162
+ return undefined;
163
+ return images.map((image) => ({
164
+ type: "image",
165
+ data: image.data,
166
+ mime_type: image.mime_type ?? image.mimeType ?? "application/octet-stream",
167
+ }));
168
+ }
169
+ function readJsonBody(req) {
170
+ return new Promise((resolve, reject) => {
171
+ let body = "";
172
+ req.setEncoding("utf8");
173
+ req.on("data", (chunk) => {
174
+ body += chunk;
175
+ if (body.length > 1024 * 1024) {
176
+ req.destroy(new Error("Request body too large"));
177
+ }
178
+ });
179
+ req.on("end", () => {
180
+ if (!body.trim()) {
181
+ resolve({});
182
+ return;
183
+ }
184
+ try {
185
+ const parsed = JSON.parse(body);
186
+ resolve(isRecord(parsed) ? parsed : {});
187
+ }
188
+ catch (error) {
189
+ reject(error);
190
+ }
191
+ });
192
+ req.on("error", reject);
193
+ });
194
+ }
195
+ function isRecord(value) {
196
+ return typeof value === "object" && value !== null && !Array.isArray(value);
197
+ }
198
+ function sendHtml(res, html) {
199
+ res.writeHead(200, {
200
+ "Content-Type": "text/html; charset=utf-8",
201
+ "Cache-Control": "no-store",
202
+ });
203
+ res.end(html);
204
+ }
205
+ function sendJson(res, payload, status = 200) {
206
+ res.writeHead(status, {
207
+ "Content-Type": "application/json; charset=utf-8",
208
+ "Cache-Control": "no-store",
209
+ });
210
+ res.end(JSON.stringify(payload));
211
+ }
212
+ function writeSse(res, event, data) {
213
+ res.write(`event: ${event}\n`);
214
+ const json = JSON.stringify(data);
215
+ for (const line of json.split("\n")) {
216
+ res.write(`data: ${line}\n`);
217
+ }
218
+ res.write("\n");
219
+ }
220
+ function listen(server, port, host) {
221
+ return new Promise((resolve, reject) => {
222
+ const onError = (error) => {
223
+ server.off("listening", onListening);
224
+ reject(error);
225
+ };
226
+ const onListening = () => {
227
+ server.off("error", onError);
228
+ resolve();
229
+ };
230
+ server.once("error", onError);
231
+ server.once("listening", onListening);
232
+ server.listen(port, host);
233
+ });
234
+ }
235
+ function closeServer(server) {
236
+ return new Promise((resolve) => {
237
+ server.close(() => resolve());
238
+ });
239
+ }
240
+ function formatError(error) {
241
+ return error instanceof Error ? error.message : String(error);
242
+ }
243
+ const INDEX_HTML = String.raw `<!doctype html>
244
+ <html lang="en">
245
+ <head>
246
+ <meta charset="utf-8" />
247
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
248
+ <title>Pizza GUI</title>
249
+ <style>
250
+ :root {
251
+ color-scheme: light;
252
+ --bg: #f4f6fa;
253
+ --panel: #ffffff;
254
+ --panel-alt: #eef2f7;
255
+ --line: #d8dee8;
256
+ --line-strong: #bac5d3;
257
+ --text: #101820;
258
+ --muted: #657386;
259
+ --soft: #7a8798;
260
+ --accent: #0f766e;
261
+ --accent-strong: #0b5f59;
262
+ --warn: #b7791f;
263
+ --danger: #b42318;
264
+ --shadow: 0 20px 60px rgba(15, 23, 42, 0.08);
265
+ font-family:
266
+ Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
267
+ }
268
+
269
+ * {
270
+ box-sizing: border-box;
271
+ }
272
+
273
+ html,
274
+ body {
275
+ width: 100%;
276
+ height: 100%;
277
+ margin: 0;
278
+ background: var(--bg);
279
+ color: var(--text);
280
+ }
281
+
282
+ body {
283
+ overflow: hidden;
284
+ }
285
+
286
+ button,
287
+ textarea {
288
+ font: inherit;
289
+ }
290
+
291
+ button {
292
+ border: 1px solid var(--line);
293
+ background: var(--panel);
294
+ color: var(--text);
295
+ min-height: 36px;
296
+ padding: 0 12px;
297
+ border-radius: 6px;
298
+ cursor: pointer;
299
+ }
300
+
301
+ button:hover {
302
+ border-color: var(--line-strong);
303
+ }
304
+
305
+ button:disabled {
306
+ color: var(--soft);
307
+ cursor: not-allowed;
308
+ background: #f7f8fa;
309
+ }
310
+
311
+ .primary {
312
+ background: var(--accent);
313
+ border-color: var(--accent);
314
+ color: white;
315
+ }
316
+
317
+ .primary:hover {
318
+ background: var(--accent-strong);
319
+ border-color: var(--accent-strong);
320
+ }
321
+
322
+ .danger {
323
+ color: var(--danger);
324
+ }
325
+
326
+ .app {
327
+ display: grid;
328
+ grid-template-rows: 56px 1fr auto;
329
+ height: 100vh;
330
+ }
331
+
332
+ .topbar {
333
+ display: grid;
334
+ grid-template-columns: minmax(220px, 1fr) auto;
335
+ align-items: center;
336
+ gap: 16px;
337
+ padding: 0 20px;
338
+ border-bottom: 1px solid var(--line);
339
+ background: rgba(255, 255, 255, 0.88);
340
+ backdrop-filter: blur(14px);
341
+ }
342
+
343
+ .brand {
344
+ display: flex;
345
+ align-items: center;
346
+ gap: 12px;
347
+ min-width: 0;
348
+ }
349
+
350
+ .logo {
351
+ width: 28px;
352
+ height: 28px;
353
+ border-radius: 7px;
354
+ background:
355
+ linear-gradient(135deg, #0f766e 0%, #0f766e 50%, transparent 50%),
356
+ linear-gradient(315deg, #b7791f 0%, #b7791f 50%, #101820 50%);
357
+ box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.42);
358
+ flex: 0 0 auto;
359
+ }
360
+
361
+ .title {
362
+ font-weight: 700;
363
+ line-height: 1;
364
+ }
365
+
366
+ .path {
367
+ color: var(--muted);
368
+ font-size: 12px;
369
+ overflow: hidden;
370
+ text-overflow: ellipsis;
371
+ white-space: nowrap;
372
+ max-width: 66vw;
373
+ margin-top: 3px;
374
+ }
375
+
376
+ .meta {
377
+ display: flex;
378
+ align-items: center;
379
+ gap: 8px;
380
+ justify-content: flex-end;
381
+ min-width: 0;
382
+ }
383
+
384
+ .pill {
385
+ display: inline-flex;
386
+ align-items: center;
387
+ height: 28px;
388
+ padding: 0 9px;
389
+ border: 1px solid var(--line);
390
+ border-radius: 999px;
391
+ background: var(--panel);
392
+ color: var(--muted);
393
+ font-size: 12px;
394
+ max-width: 220px;
395
+ white-space: nowrap;
396
+ overflow: hidden;
397
+ text-overflow: ellipsis;
398
+ }
399
+
400
+ .pill.running {
401
+ color: var(--accent);
402
+ border-color: rgba(15, 118, 110, 0.35);
403
+ background: rgba(15, 118, 110, 0.08);
404
+ }
405
+
406
+ .timeline-wrap {
407
+ overflow: hidden;
408
+ display: grid;
409
+ grid-template-columns: minmax(0, 920px);
410
+ justify-content: center;
411
+ padding: 22px 18px;
412
+ }
413
+
414
+ .timeline {
415
+ overflow: auto;
416
+ padding: 0 2px 120px;
417
+ scroll-behavior: smooth;
418
+ }
419
+
420
+ .empty {
421
+ min-height: calc(100vh - 220px);
422
+ display: grid;
423
+ align-content: center;
424
+ justify-items: center;
425
+ gap: 10px;
426
+ color: var(--muted);
427
+ text-align: center;
428
+ }
429
+
430
+ .empty-title {
431
+ color: var(--text);
432
+ font-size: 24px;
433
+ font-weight: 720;
434
+ letter-spacing: 0;
435
+ }
436
+
437
+ .item {
438
+ margin: 0 0 12px;
439
+ border: 1px solid var(--line);
440
+ border-radius: 8px;
441
+ background: var(--panel);
442
+ box-shadow: var(--shadow);
443
+ overflow: hidden;
444
+ }
445
+
446
+ .item.user {
447
+ background: #101820;
448
+ color: white;
449
+ border-color: #101820;
450
+ }
451
+
452
+ .item.assistant {
453
+ background: var(--panel);
454
+ }
455
+
456
+ .item.tool,
457
+ .item.system {
458
+ box-shadow: none;
459
+ background: rgba(255, 255, 255, 0.72);
460
+ }
461
+
462
+ .item-head {
463
+ display: flex;
464
+ align-items: center;
465
+ justify-content: space-between;
466
+ gap: 12px;
467
+ min-height: 38px;
468
+ padding: 9px 12px;
469
+ border-bottom: 1px solid var(--line);
470
+ color: var(--muted);
471
+ font-size: 12px;
472
+ }
473
+
474
+ .user .item-head {
475
+ border-bottom-color: rgba(255, 255, 255, 0.14);
476
+ color: rgba(255, 255, 255, 0.72);
477
+ }
478
+
479
+ .item-title {
480
+ font-weight: 700;
481
+ color: inherit;
482
+ }
483
+
484
+ .item-status {
485
+ color: var(--soft);
486
+ white-space: nowrap;
487
+ }
488
+
489
+ .item-body {
490
+ padding: 13px 14px 15px;
491
+ white-space: pre-wrap;
492
+ overflow-wrap: anywhere;
493
+ line-height: 1.5;
494
+ font-size: 14px;
495
+ }
496
+
497
+ .item-body:empty::after {
498
+ content: " ";
499
+ }
500
+
501
+ .tool .item-body {
502
+ display: grid;
503
+ grid-template-columns: minmax(96px, auto) 1fr;
504
+ gap: 8px 12px;
505
+ align-items: start;
506
+ white-space: normal;
507
+ }
508
+
509
+ .tool-name {
510
+ color: var(--muted);
511
+ font-size: 12px;
512
+ font-weight: 700;
513
+ text-transform: uppercase;
514
+ }
515
+
516
+ .tool-label {
517
+ min-width: 0;
518
+ overflow-wrap: anywhere;
519
+ }
520
+
521
+ details {
522
+ grid-column: 1 / -1;
523
+ color: var(--muted);
524
+ font-size: 12px;
525
+ }
526
+
527
+ summary {
528
+ cursor: pointer;
529
+ }
530
+
531
+ pre {
532
+ margin: 8px 0 0;
533
+ padding: 10px;
534
+ max-height: 260px;
535
+ overflow: auto;
536
+ border-radius: 6px;
537
+ background: #111827;
538
+ color: #e5e7eb;
539
+ font-size: 12px;
540
+ line-height: 1.45;
541
+ }
542
+
543
+ .composer {
544
+ border-top: 1px solid var(--line);
545
+ background: rgba(255, 255, 255, 0.92);
546
+ backdrop-filter: blur(14px);
547
+ padding: 14px 18px 18px;
548
+ display: grid;
549
+ grid-template-columns: minmax(0, 920px);
550
+ justify-content: center;
551
+ }
552
+
553
+ .composer-inner {
554
+ display: grid;
555
+ grid-template-columns: 1fr auto auto;
556
+ gap: 10px;
557
+ align-items: end;
558
+ }
559
+
560
+ textarea {
561
+ width: 100%;
562
+ min-height: 48px;
563
+ max-height: 180px;
564
+ resize: vertical;
565
+ padding: 12px;
566
+ border: 1px solid var(--line);
567
+ border-radius: 8px;
568
+ background: var(--panel);
569
+ color: var(--text);
570
+ line-height: 1.45;
571
+ outline: none;
572
+ }
573
+
574
+ textarea:focus {
575
+ border-color: rgba(15, 118, 110, 0.52);
576
+ box-shadow: 0 0 0 3px rgba(15, 118, 110, 0.12);
577
+ }
578
+
579
+ .error-line {
580
+ margin-top: 8px;
581
+ color: var(--danger);
582
+ font-size: 12px;
583
+ min-height: 16px;
584
+ }
585
+
586
+ @media (max-width: 720px) {
587
+ .app {
588
+ grid-template-rows: auto 1fr auto;
589
+ }
590
+
591
+ .topbar {
592
+ grid-template-columns: 1fr;
593
+ align-items: start;
594
+ padding: 12px 14px;
595
+ }
596
+
597
+ .meta {
598
+ justify-content: flex-start;
599
+ flex-wrap: wrap;
600
+ }
601
+
602
+ .path {
603
+ max-width: calc(100vw - 86px);
604
+ }
605
+
606
+ .timeline-wrap {
607
+ padding: 14px 10px;
608
+ }
609
+
610
+ .composer {
611
+ padding: 10px;
612
+ }
613
+
614
+ .composer-inner {
615
+ grid-template-columns: 1fr;
616
+ }
617
+
618
+ button {
619
+ width: 100%;
620
+ }
621
+
622
+ .tool .item-body {
623
+ grid-template-columns: 1fr;
624
+ }
625
+ }
626
+ </style>
627
+ </head>
628
+ <body>
629
+ <div id="app" class="app">
630
+ <header class="topbar">
631
+ <div class="brand">
632
+ <div class="logo" aria-hidden="true"></div>
633
+ <div>
634
+ <div class="title">Pizza</div>
635
+ <div id="projectPath" class="path"></div>
636
+ </div>
637
+ </div>
638
+ <div class="meta">
639
+ <span id="modelPill" class="pill"></span>
640
+ <span id="statusPill" class="pill"></span>
641
+ <button id="stopButton" class="danger" type="button" disabled>Stop</button>
642
+ </div>
643
+ </header>
644
+ <main class="timeline-wrap">
645
+ <div id="timeline" class="timeline"></div>
646
+ </main>
647
+ <footer class="composer">
648
+ <form id="composerForm" class="composer-inner">
649
+ <textarea id="promptInput" placeholder="Ask Pizza to work on this project"></textarea>
650
+ <button id="followButton" type="button">Follow up</button>
651
+ <button id="sendButton" class="primary" type="submit">Send</button>
652
+ </form>
653
+ <div id="errorLine" class="error-line"></div>
654
+ </footer>
655
+ </div>
656
+ <script>
657
+ const timeline = document.getElementById("timeline");
658
+ const projectPath = document.getElementById("projectPath");
659
+ const modelPill = document.getElementById("modelPill");
660
+ const statusPill = document.getElementById("statusPill");
661
+ const stopButton = document.getElementById("stopButton");
662
+ const sendButton = document.getElementById("sendButton");
663
+ const followButton = document.getElementById("followButton");
664
+ const promptInput = document.getElementById("promptInput");
665
+ const composerForm = document.getElementById("composerForm");
666
+ const errorLine = document.getElementById("errorLine");
667
+
668
+ const state = {
669
+ items: [],
670
+ isRunning: false,
671
+ activeAssistantId: null,
672
+ tools: new Map(),
673
+ };
674
+
675
+ function setError(message) {
676
+ errorLine.textContent = message || "";
677
+ }
678
+
679
+ function scrollToBottom() {
680
+ timeline.scrollTop = timeline.scrollHeight;
681
+ }
682
+
683
+ function messageText(message) {
684
+ if (!message) return "";
685
+ if (typeof message.content === "string") return message.content;
686
+ if (Array.isArray(message.content)) {
687
+ return message.content
688
+ .map((block) => {
689
+ if (!block || typeof block !== "object") return "";
690
+ if (block.type === "text") return block.text || "";
691
+ if (block.type === "thinking") return "";
692
+ if (block.type === "toolCall") return "Tool call: " + (block.name || "tool");
693
+ if (block.type === "image") return "[image]";
694
+ return "";
695
+ })
696
+ .filter(Boolean)
697
+ .join("\n");
698
+ }
699
+ if (message.role === "bashExecution") {
700
+ return "$ " + message.command + "\n" + (message.output || "");
701
+ }
702
+ if (message.role === "compactionSummary") return message.summary || "";
703
+ if (message.role === "branchSummary") return message.summary || "";
704
+ if (message.role === "custom") return typeof message.display === "string" ? message.display : String(message.content || "");
705
+ return "";
706
+ }
707
+
708
+ function pushMessage(message) {
709
+ if (message.role === "toolResult") return;
710
+ if (message.role === "assistant" && state.activeAssistantId) {
711
+ const item = state.items.find((candidate) => candidate.id === state.activeAssistantId);
712
+ if (item) {
713
+ item.text = messageText(message);
714
+ item.status = "Done";
715
+ item.streaming = false;
716
+ state.activeAssistantId = null;
717
+ render();
718
+ return;
719
+ }
720
+ }
721
+
722
+ const role = message.role === "user" || message.role === "assistant" ? message.role : "system";
723
+ state.items.push({
724
+ id: "msg-" + Date.now() + "-" + Math.random().toString(16).slice(2),
725
+ type: role,
726
+ title: titleForMessage(message),
727
+ status: formatTime(message.timestamp),
728
+ text: messageText(message),
729
+ });
730
+ render();
731
+ }
732
+
733
+ function titleForMessage(message) {
734
+ if (message.role === "user") return "You";
735
+ if (message.role === "assistant") return "Pizza";
736
+ if (message.role === "bashExecution") return "Command";
737
+ if (message.role === "compactionSummary") return "Compaction";
738
+ if (message.role === "branchSummary") return "Branch";
739
+ return "System";
740
+ }
741
+
742
+ function formatTime(timestamp) {
743
+ if (!timestamp) return "";
744
+ return new Date(timestamp).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
745
+ }
746
+
747
+ function handleModeEvent(event) {
748
+ switch (event.type) {
749
+ case "message_committed":
750
+ pushMessage(event.message);
751
+ break;
752
+ case "streaming_message_started":
753
+ state.activeAssistantId = event.eventId;
754
+ state.items.push({
755
+ id: event.eventId,
756
+ type: "assistant",
757
+ title: "Pizza",
758
+ status: "Streaming",
759
+ text: "",
760
+ streaming: true,
761
+ });
762
+ render();
763
+ break;
764
+ case "streaming_message_updated": {
765
+ if (!state.activeAssistantId) return;
766
+ const item = state.items.find((candidate) => candidate.id === state.activeAssistantId);
767
+ if (item && event.delta) {
768
+ item.text += event.delta;
769
+ render();
770
+ }
771
+ break;
772
+ }
773
+ case "tool_started":
774
+ upsertTool(event.toolCallId, {
775
+ id: event.toolCallId,
776
+ type: "tool",
777
+ title: "Tool",
778
+ status: "Running",
779
+ name: event.toolName,
780
+ label: toolLabel(event.toolName, event.args),
781
+ details: event.args,
782
+ });
783
+ break;
784
+ case "tool_updated":
785
+ updateTool(event.toolCallId, { status: "Running", update: event.update });
786
+ break;
787
+ case "tool_finished":
788
+ updateTool(event.toolCallId, {
789
+ status: event.isError ? "Error" : "Done",
790
+ result: event.result,
791
+ isError: event.isError,
792
+ });
793
+ break;
794
+ case "turn_started":
795
+ state.isRunning = true;
796
+ renderMeta();
797
+ break;
798
+ case "turn_completed":
799
+ state.isRunning = false;
800
+ renderMeta();
801
+ break;
802
+ case "runtime_error":
803
+ case "agent_error":
804
+ setError(event.error);
805
+ state.items.push({
806
+ id: event.eventId,
807
+ type: "system",
808
+ title: "Error",
809
+ status: "",
810
+ text: event.error,
811
+ });
812
+ render();
813
+ break;
814
+ }
815
+ }
816
+
817
+ function upsertTool(id, data) {
818
+ const existing = state.items.find((item) => item.id === id);
819
+ if (existing) {
820
+ Object.assign(existing, data);
821
+ } else {
822
+ state.items.push(data);
823
+ }
824
+ state.tools.set(id, data);
825
+ render();
826
+ }
827
+
828
+ function updateTool(id, patch) {
829
+ const item = state.items.find((candidate) => candidate.id === id);
830
+ if (!item) return;
831
+ Object.assign(item, patch);
832
+ render();
833
+ }
834
+
835
+ function toolLabel(name, args) {
836
+ const value = (...keys) => {
837
+ for (const key of keys) {
838
+ if (args && args[key] !== undefined && args[key] !== null && String(args[key]).length > 0) {
839
+ return String(args[key]);
840
+ }
841
+ }
842
+ return "";
843
+ };
844
+ switch (name) {
845
+ case "read":
846
+ return value("path", "file_path", "file") || "Read file";
847
+ case "write":
848
+ return value("path", "file_path", "file") || "Write file";
849
+ case "edit":
850
+ return value("path", "file_path", "file") || "Edit file";
851
+ case "bash":
852
+ return value("command", "cmd") || "Run command";
853
+ case "grep":
854
+ return value("pattern", "query") || "Search code";
855
+ case "find":
856
+ return value("pattern", "path") || "Find files";
857
+ case "ls":
858
+ return value("path", "dir") || "List files";
859
+ default:
860
+ return value("path", "command", "query", "pattern") || name;
861
+ }
862
+ }
863
+
864
+ function renderMeta(meta) {
865
+ if (meta) {
866
+ state.meta = meta;
867
+ state.isRunning = meta.isRunning;
868
+ }
869
+ const current = state.meta || {};
870
+ projectPath.textContent = current.cwd || "";
871
+ const model = current.model;
872
+ modelPill.textContent = model ? model.provider + "/" + model.modelId : "No model";
873
+ statusPill.textContent = state.isRunning ? "Running" : "Idle";
874
+ statusPill.classList.toggle("running", state.isRunning);
875
+ stopButton.disabled = !state.isRunning;
876
+ sendButton.textContent = state.isRunning ? "Queue" : "Send";
877
+ }
878
+
879
+ function render() {
880
+ if (state.items.length === 0) {
881
+ timeline.innerHTML =
882
+ '<div class="empty"><div class="empty-title">Pizza GUI</div><div>Current project is ready.</div></div>';
883
+ renderMeta();
884
+ return;
885
+ }
886
+ timeline.innerHTML = state.items.map(renderItem).join("");
887
+ renderMeta();
888
+ scrollToBottom();
889
+ }
890
+
891
+ function renderItem(item) {
892
+ if (item.type === "tool") {
893
+ const status = escapeHtml(item.status || "");
894
+ const details = item.details ? renderDetails("Arguments", item.details) : "";
895
+ const result = item.result !== undefined ? renderDetails(item.isError ? "Error output" : "Result", item.result) : "";
896
+ const update = item.update ? '<details><summary>Update</summary><pre>' + escapeHtml(item.update) + "</pre></details>" : "";
897
+ return (
898
+ '<section class="item tool">' +
899
+ '<div class="item-head"><span class="item-title">' +
900
+ escapeHtml(item.name || "tool") +
901
+ '</span><span class="item-status">' +
902
+ status +
903
+ "</span></div>" +
904
+ '<div class="item-body"><div class="tool-name">Target</div><div class="tool-label">' +
905
+ escapeHtml(item.label || "") +
906
+ "</div>" +
907
+ update +
908
+ details +
909
+ result +
910
+ "</div></section>"
911
+ );
912
+ }
913
+
914
+ return (
915
+ '<section class="item ' +
916
+ escapeHtml(item.type) +
917
+ '"><div class="item-head"><span class="item-title">' +
918
+ escapeHtml(item.title || "") +
919
+ '</span><span class="item-status">' +
920
+ escapeHtml(item.status || "") +
921
+ '</span></div><div class="item-body">' +
922
+ escapeHtml(item.text || "") +
923
+ "</div></section>"
924
+ );
925
+ }
926
+
927
+ function renderDetails(label, data) {
928
+ return (
929
+ "<details><summary>" +
930
+ escapeHtml(label) +
931
+ "</summary><pre>" +
932
+ escapeHtml(JSON.stringify(data, null, 2)) +
933
+ "</pre></details>"
934
+ );
935
+ }
936
+
937
+ function escapeHtml(value) {
938
+ return String(value)
939
+ .replaceAll("&", "&amp;")
940
+ .replaceAll("<", "&lt;")
941
+ .replaceAll(">", "&gt;")
942
+ .replaceAll('"', "&quot;")
943
+ .replaceAll("'", "&#039;");
944
+ }
945
+
946
+ async function postJson(url, body) {
947
+ const response = await fetch(url, {
948
+ method: "POST",
949
+ headers: { "Content-Type": "application/json" },
950
+ body: JSON.stringify(body || {}),
951
+ });
952
+ const payload = await response.json();
953
+ if (!response.ok || payload.success === false) {
954
+ throw new Error(payload.error || "Request failed");
955
+ }
956
+ return payload;
957
+ }
958
+
959
+ composerForm.addEventListener("submit", async (event) => {
960
+ event.preventDefault();
961
+ const message = promptInput.value.trim();
962
+ if (!message) return;
963
+ setError("");
964
+ promptInput.value = "";
965
+ try {
966
+ await postJson("/api/prompt", { message });
967
+ } catch (error) {
968
+ setError(error.message);
969
+ promptInput.value = message;
970
+ }
971
+ });
972
+
973
+ followButton.addEventListener("click", async () => {
974
+ const message = promptInput.value.trim();
975
+ if (!message) return;
976
+ setError("");
977
+ promptInput.value = "";
978
+ try {
979
+ await postJson("/api/prompt", { message, behavior: "follow_up" });
980
+ } catch (error) {
981
+ setError(error.message);
982
+ promptInput.value = message;
983
+ }
984
+ });
985
+
986
+ stopButton.addEventListener("click", async () => {
987
+ setError("");
988
+ try {
989
+ await postJson("/api/abort", {});
990
+ } catch (error) {
991
+ setError(error.message);
992
+ }
993
+ });
994
+
995
+ promptInput.addEventListener("keydown", (event) => {
996
+ if (event.key === "Enter" && (event.metaKey || event.ctrlKey)) {
997
+ composerForm.requestSubmit();
998
+ }
999
+ });
1000
+
1001
+ async function start() {
1002
+ const response = await fetch("/api/bootstrap");
1003
+ const payload = await response.json();
1004
+ renderMeta(payload.state);
1005
+ state.items = [];
1006
+ for (const message of payload.messages || []) {
1007
+ pushMessage(message);
1008
+ }
1009
+ render();
1010
+
1011
+ const events = new EventSource("/events");
1012
+ events.addEventListener("state", (event) => renderMeta(JSON.parse(event.data)));
1013
+ events.addEventListener("mode_event", (event) => handleModeEvent(JSON.parse(event.data)));
1014
+ events.addEventListener("server_error", (event) => {
1015
+ try {
1016
+ setError(JSON.parse(event.data));
1017
+ } catch {
1018
+ setError(event.data);
1019
+ }
1020
+ });
1021
+ events.onerror = () => {
1022
+ setError("Connection lost. Refresh when the server is back.");
1023
+ };
1024
+ }
1025
+
1026
+ start().catch((error) => {
1027
+ setError(error.message);
1028
+ render();
1029
+ });
1030
+ </script>
1031
+ </body>
1032
+ </html>`;