@hienlh/ppm 0.19.0 → 0.19.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (508) hide show
  1. package/CHANGELOG.md +13 -1
  2. package/assets/skills/ppm/SKILL.md +1 -1
  3. package/assets/skills/ppm/references/cli-reference.md +4 -4
  4. package/assets/skills/ppm/references/http-api.md +1 -1
  5. package/dist/web/assets/{adaptive-context-menu-JfuUSqbe.js → adaptive-context-menu-BbuRVTLn.js} +1 -1
  6. package/dist/web/assets/{ai-resource-editor-MfdJKVM5.js → ai-resource-editor-BCCOUzox.js} +1 -1
  7. package/dist/web/assets/{ai-settings-section-CJE7jFsj.js → ai-settings-section-BEM1z7kp.js} +1 -1
  8. package/dist/web/assets/{angular-html-VzxSzTCy.js → angular-html-BlcrLjUx.js} +1 -1
  9. package/dist/web/assets/{angular-ts-CmJ4bmzM.js → angular-ts-BUjtceAJ.js} +1 -1
  10. package/dist/web/assets/{api-client-qRWu6_s5.js → api-client-BzWM7XPR.js} +1 -1
  11. package/dist/web/assets/api-client-D1CePgQ4.js +1 -0
  12. package/dist/web/assets/api-settings-CNtKkHqW.js +1 -0
  13. package/dist/web/assets/{api-settings-CPg4yGvS.js → api-settings-Cubuqjsu.js} +1 -1
  14. package/dist/web/assets/{api-themes-DsAp8m7m.js → api-themes-YsZgf6Xj.js} +1 -1
  15. package/dist/web/assets/{apl-do17bnVx.js → apl-B3g0v1pk.js} +1 -1
  16. package/dist/web/assets/{astro-ClY0e0OA.js → astro-FRnyn7cH.js} +1 -1
  17. package/dist/web/assets/{audio-preview-Fw935Mok.js → audio-preview-DWTRm4HC.js} +1 -1
  18. package/dist/web/assets/{blade-BXSdXDGq.js → blade-NLdOqUKw.js} +1 -1
  19. package/dist/web/assets/{bot-CWZAuloY.js → bot-D6sx11y0.js} +1 -1
  20. package/dist/web/assets/{bsl-MxsMKDUZ.js → bsl-CenHZfaU.js} +1 -1
  21. package/dist/web/assets/{button-CrwgGd1y.js → button-Cq8yixjf.js} +1 -1
  22. package/dist/web/assets/{cairo-4CIrzX_p.js → cairo-B_WR0aiQ.js} +1 -1
  23. package/dist/web/assets/chat-tab-CmXGsJGc.js +15 -0
  24. package/dist/web/assets/{chevron-down-D7CbB5f6.js → chevron-down-Dp0rpHb8.js} +1 -1
  25. package/dist/web/assets/chevron-right-De-Wz5Lz.js +1 -0
  26. package/dist/web/assets/circle-BCy0AUCo.js +1 -0
  27. package/dist/web/assets/{circle-question-mark-BBzFZrNh.js → circle-question-mark-CzR7YRc-.js} +1 -1
  28. package/dist/web/assets/clock-C1CQUQPZ.js +1 -0
  29. package/dist/web/assets/{cobol-phPOE89d.js → cobol-DOynhWYj.js} +1 -1
  30. package/dist/web/assets/code-DJgYrFzm.js +1 -0
  31. package/dist/web/assets/code-editor-DtHXzNZ1.js +7 -0
  32. package/dist/web/assets/{coffee-Cjuukfz3.js → coffee-Bn6dbw4P.js} +1 -1
  33. package/dist/web/assets/{conflict-editor-Ni0PPsKu.js → conflict-editor-Cgb-z12D.js} +1 -1
  34. package/dist/web/assets/{context-menu-BEAa1qhd.js → context-menu-DfWZAxQy.js} +1 -1
  35. package/dist/web/assets/{copy-CbPdNp7E.js → copy-BewHj66E.js} +1 -1
  36. package/dist/web/assets/{cpp-CT7tGBC3.js → cpp-CoZR9t8r.js} +1 -1
  37. package/dist/web/assets/{createLucideIcon-ConhwJnb.js → createLucideIcon-D8pyde1A.js} +1 -1
  38. package/dist/web/assets/{crystal-D8U1Qnqh.js → crystal-BSheONSg.js} +1 -1
  39. package/dist/web/assets/{csv-preview-Coc2oed1.js → csv-preview-BZMHfFH3.js} +1 -1
  40. package/dist/web/assets/{data-grid-overlay-editor-B8WQkZDB.js → data-grid-overlay-editor-gwPoVSCU.js} +1 -1
  41. package/dist/web/assets/{data-grid-types-KpjaKAci.js → data-grid-types-Dq_H1IPa.js} +1 -1
  42. package/dist/web/assets/{database-BqyeGogo.js → database-Y3ESDK4-.js} +1 -1
  43. package/dist/web/assets/database-viewer-GVaQVMdb.js +1 -0
  44. package/dist/web/assets/{dialog-DrL3WEXd.js → dialog-BSfuiTkJ.js} +1 -1
  45. package/dist/web/assets/{diff-viewer-CT0lmDc9.js → diff-viewer-BG5_fH1E.js} +1 -1
  46. package/dist/web/assets/{dist-C2_dKAa_.js → dist-aDSxTR_v.js} +1 -1
  47. package/dist/web/assets/{docx-preview-76KDw1eE.js → docx-preview-DqVDOMmv.js} +1 -1
  48. package/dist/web/assets/{download-DAF7SXcf.js → download-DG3_9xXy.js} +1 -1
  49. package/dist/web/assets/{edge-Db4ze6bw.js → edge-DTtoslQu.js} +1 -1
  50. package/dist/web/assets/{edit-diff-preview-DyC_-4My.js → edit-diff-preview-CXSbSUBX.js} +1 -1
  51. package/dist/web/assets/{elixir-RZPZ0472.js → elixir-CIBCZ3Zi.js} +1 -1
  52. package/dist/web/assets/{elm-DNZcQt_7.js → elm-BLmb7K1H.js} +1 -1
  53. package/dist/web/assets/{erb-DRONsZXs.js → erb-BBY8ApRd.js} +1 -1
  54. package/dist/web/assets/{erlang-DeG0-QwJ.js → erlang-D5Zb5_P0.js} +1 -1
  55. package/dist/web/assets/{esm-CZy-sSoK.js → esm-6F8v1jLL.js} +1 -1
  56. package/dist/web/assets/explorer-body-BPFnjxYj.js +2 -0
  57. package/dist/web/assets/explorer-window-content-Da1T9uM4.js +1 -0
  58. package/dist/web/assets/{extension-store-ClQpnxQr.js → extension-store-Bhu--fPX.js} +1 -1
  59. package/dist/web/assets/{extension-webview-BW5GuBnH.js → extension-webview-BSh6KGd7.js} +1 -1
  60. package/dist/web/assets/{external-link-ojDHcQxQ.js → external-link-B6Hl0U4X.js} +1 -1
  61. package/dist/web/assets/{eye-off-Rq1n2-oe.js → eye-off-CUdzgmX8.js} +1 -1
  62. package/dist/web/assets/{file-exclamation-point-Bpg-zDPP.js → file-exclamation-point-JzhTU2TX.js} +1 -1
  63. package/dist/web/assets/{file-store-28e44KP3.js → file-store-6HW2Lfl4.js} +1 -1
  64. package/dist/web/assets/{folder-symlink-LD-mr54V.js → folder-symlink-Dx1hOk8X.js} +1 -1
  65. package/dist/web/assets/{fortran-fixed-form-CK5VRJNd.js → fortran-fixed-form-CBdwkEUJ.js} +1 -1
  66. package/dist/web/assets/{fsharp-TVVgzHWp.js → fsharp-AT4XdVYH.js} +1 -1
  67. package/dist/web/assets/{gdresource-DiUcyewI.js → gdresource-D852fWBR.js} +1 -1
  68. package/dist/web/assets/{git-commit-CfOruFrg.js → git-commit-DWfWAyxy.js} +1 -1
  69. package/dist/web/assets/{git-log-panel-D1-YXZ0O.js → git-log-panel-DNC9fV0M.js} +1 -1
  70. package/dist/web/assets/{git-rebase-Bxyr24oc.js → git-rebase-C6opk8gr.js} +1 -1
  71. package/dist/web/assets/glide-data-grid-CICFjJon.js +141 -0
  72. package/dist/web/assets/{glimmer-js-CT5aJxz_.js → glimmer-js-DLi5mWYO.js} +1 -1
  73. package/dist/web/assets/{glimmer-ts-CRjP9Yey.js → glimmer-ts-D-scFX30.js} +1 -1
  74. package/dist/web/assets/{glsl-BX2--oI_.js → glsl-dbQzF4iA.js} +1 -1
  75. package/dist/web/assets/{graphql-BIQsvBxQ.js → graphql-D1m5Wen2.js} +1 -1
  76. package/dist/web/assets/group-chat-tab-DbUkcOaJ.js +1 -0
  77. package/dist/web/assets/{hack-CTWk0k1m.js → hack-CqYmpO7u.js} +1 -1
  78. package/dist/web/assets/{haml-DGh27hXc.js → haml-BXzKWEag.js} +1 -1
  79. package/dist/web/assets/{hand-DKSxDa5c.js → hand-x0ejq3fS.js} +1 -1
  80. package/dist/web/assets/{handlebars-BJL1jNrG.js → handlebars-DXnrtHtq.js} +1 -1
  81. package/dist/web/assets/{html-DALyDNqU.js → html-DhgQJ-xL.js} +1 -1
  82. package/dist/web/assets/{html-derivative-B4XcU57e.js → html-derivative-xZRft-YE.js} +1 -1
  83. package/dist/web/assets/{http-DfMo7nNu.js → http-B53mSj14.js} +1 -1
  84. package/dist/web/assets/{hurl-CGc_n2Qf.js → hurl-CsomVy04.js} +1 -1
  85. package/dist/web/assets/{hxml-40zZ1t4x.js → hxml-LffjWwKA.js} +1 -1
  86. package/dist/web/assets/{image-preview-Cp3XB8UO.js → image-preview-CNA6XMNS.js} +1 -1
  87. package/dist/web/assets/index-DTqbMiVc.js +52 -0
  88. package/dist/web/assets/{input-DTmI80l2.js → input-D0ol5jW0.js} +1 -1
  89. package/dist/web/assets/{jinja-D5zuIn9u.js → jinja-CCHURl7V.js} +1 -1
  90. package/dist/web/assets/{jison-Dxut9QwA.js → jison-7qBd8dnR.js} +1 -1
  91. package/dist/web/assets/{julia-Cu85tTPo.js → julia-BY9pnTcy.js} +1 -1
  92. package/dist/web/assets/{just-CctM4uLa.js → just-D7wRSNRr.js} +1 -1
  93. package/dist/web/assets/{keybindings-store-Bi0q9x4Q.js → keybindings-store-BGkB72gM.js} +1 -1
  94. package/dist/web/assets/keybindings-store-Bq6VWl5X.js +1 -0
  95. package/dist/web/assets/{keyboard-AdwmYDSu.js → keyboard-DBBaoQSu.js} +1 -1
  96. package/dist/web/assets/{latex-kpwS_CC7.js → latex-RgsCae55.js} +1 -1
  97. package/dist/web/assets/{lib-Ca7ai8xa.js → lib-v9x_qXgI.js} +1 -1
  98. package/dist/web/assets/{liquid-B8Rr0xue.js → liquid-CnDFzvOZ.js} +1 -1
  99. package/dist/web/assets/loader-circle-DouKgIXy.js +1 -0
  100. package/dist/web/assets/{lock-BEtt_eTO.js → lock-CNxUGpTk.js} +1 -1
  101. package/dist/web/assets/{lua-C_3gixwM.js → lua-0lj5W8sm.js} +1 -1
  102. package/dist/web/assets/markdown-renderer-DEAVpo0C.js +1 -0
  103. package/dist/web/assets/markdown-renderer-dbLIvU2M.js +3 -0
  104. package/dist/web/assets/{marko-B28rvNL-.js → marko-CQgqAhbV.js} +1 -1
  105. package/dist/web/assets/{mdc-DQ6-STFO.js → mdc-BkIcTiIy.js} +1 -1
  106. package/dist/web/assets/{media-url-BjvbfTTl.js → media-url-DDciwvLU.js} +1 -1
  107. package/dist/web/assets/{mobile-bottom-sheet-DXn5g2LB.js → mobile-bottom-sheet-pjcHKorA.js} +1 -1
  108. package/dist/web/assets/mobile-explorer-sheet-CD_kl-jA.js +1 -0
  109. package/dist/web/assets/{monitor-CXI_XpWJ.js → monitor-CxPV_fQI.js} +1 -1
  110. package/dist/web/assets/{monitor-smartphone-C1wUPOSg.js → monitor-smartphone-DLZ6Q05s.js} +1 -1
  111. package/dist/web/assets/{nextflow-B1xq2O8L.js → nextflow-DvIW68DS.js} +1 -1
  112. package/dist/web/assets/{nginx-xsLxRGxO.js → nginx-O-hft0gG.js} +1 -1
  113. package/dist/web/assets/{nim-wqcek3WO.js → nim-BxrR4HwQ.js} +1 -1
  114. package/dist/web/assets/notification-store-Dgbsw9p9.js +1 -0
  115. package/dist/web/assets/{number-overlay-editor-1c4sgZJt.js → number-overlay-editor-BoLRYuZT.js} +1 -1
  116. package/dist/web/assets/{overview-panel-Cr2xsHc6.js → overview-panel-l3g1gT5e.js} +1 -1
  117. package/dist/web/assets/{panel-store-Dv28vz3L.js → panel-store-UOV8wrfR.js} +1 -1
  118. package/dist/web/assets/{pdf-preview-DKeIIJTv.js → pdf-preview-B2CJ_EKv.js} +1 -1
  119. package/dist/web/assets/{pencil-CHKLOgLs.js → pencil-BlIIg6RH.js} +1 -1
  120. package/dist/web/assets/{perl-BH54gN9q.js → perl-Da-uNqmL.js} +1 -1
  121. package/dist/web/assets/{php-Br5ZrEZm.js → php-JMu45mEx.js} +1 -1
  122. package/dist/web/assets/play-DpEEBJTT.js +1 -0
  123. package/dist/web/assets/{plus-BxqD2FIZ.js → plus-BR0qewJI.js} +1 -1
  124. package/dist/web/assets/portal-container-context-D-495m5C.js +1 -0
  125. package/dist/web/assets/{postgres-viewer-BJPr_FYL.js → postgres-viewer-DstZwUai.js} +3 -3
  126. package/dist/web/assets/{process-table-BqTcAJ-h.js → process-table-kmQ2-8qJ.js} +1 -1
  127. package/dist/web/assets/{project-store-KHjFTCxf.js → project-store-DTUCS65m.js} +1 -1
  128. package/dist/web/assets/{pug-8VCubZ3H.js → pug-CLzyQhia.js} +1 -1
  129. package/dist/web/assets/{qml-D8AF1RZ6.js → qml-BHXfGB1l.js} +1 -1
  130. package/dist/web/assets/{razor-6v042IJW.js → razor-BqetJLN3.js} +1 -1
  131. package/dist/web/assets/{react-DHs6efqI.js → react-B549sK_T.js} +1 -1
  132. package/dist/web/assets/{refresh-cw-BALzw7L3.js → refresh-cw-BQU5g2CY.js} +1 -1
  133. package/dist/web/assets/remote-desktop-mobile-sheet-KKTRNjOL.js +2 -0
  134. package/dist/web/assets/{remote-desktop-mobile-view-DaoB49k4.js → remote-desktop-mobile-view-C1ST4-Fm.js} +1 -1
  135. package/dist/web/assets/{remote-desktop-readiness-gate--LJgsuoj.js → remote-desktop-readiness-gate-BH3BE5wA.js} +1 -1
  136. package/dist/web/assets/{remote-desktop-window-content-Cihx4PNZ.js → remote-desktop-window-content-BaZJQt_N.js} +1 -1
  137. package/dist/web/assets/{rotate-ccw-CuvNBM80.js → rotate-ccw-CpjRo90J.js} +1 -1
  138. package/dist/web/assets/{rst-mTGFo4AQ.js → rst-iQdJZ0BP.js} +1 -1
  139. package/dist/web/assets/{ruby-BBaOP636.js → ruby-CNwzZGdH.js} +1 -1
  140. package/dist/web/assets/{run-in-terminal-Zl5iIx-B.js → run-in-terminal-CBXmVGWa.js} +1 -1
  141. package/dist/web/assets/{sas-D5QEkIH2.js → sas-BpBIT2eR.js} +1 -1
  142. package/dist/web/assets/{save-Dxq-Zepc.js → save-DYLiVzU8.js} +1 -1
  143. package/dist/web/assets/{scroll-area-B5yhPpZo.js → scroll-area-lc0ZHORr.js} +1 -1
  144. package/dist/web/assets/{scss-C5Mu6y2u.js → scss-D1MotuEp.js} +1 -1
  145. package/dist/web/assets/{send-Cits8q0l.js → send-C_sLFt56.js} +1 -1
  146. package/dist/web/assets/{send-to-chat-Cv7ikFUC.js → send-to-chat-DJAdlvJ8.js} +1 -1
  147. package/dist/web/assets/{settings-store-Dp4i8zeA.js → settings-store-zbPkG7o-.js} +2 -2
  148. package/dist/web/assets/settings-tab-Cn-AqUP_.js +1 -0
  149. package/dist/web/assets/{settings-tab-BtMvvKAF.js → settings-tab-xyRpt2gq.js} +1 -1
  150. package/dist/web/assets/{shaderlab-mLnpMpN3.js → shaderlab-BNqmcPQi.js} +1 -1
  151. package/dist/web/assets/{shallow-BBJ_qoEF.js → shallow-CmPMAPte.js} +1 -1
  152. package/dist/web/assets/{shellsession-qdcDfUuk.js → shellsession-BBLOVOO-.js} +1 -1
  153. package/dist/web/assets/{shield-check-CH7F1P7m.js → shield-check-CUI36aSc.js} +1 -1
  154. package/dist/web/assets/{shield-off-C9HiF0-6.js → shield-off-GdkkVhb3.js} +1 -1
  155. package/dist/web/assets/{soy-CGGf1G43.js → soy-BpTGo9uy.js} +1 -1
  156. package/dist/web/assets/{sparkles-BnuLH6Ck.js → sparkles-Dh-_J2Rd.js} +1 -1
  157. package/dist/web/assets/{sparql-tQHB50VD.js → sparql-D7A3yKob.js} +1 -1
  158. package/dist/web/assets/{sql-query-editor-DZqnYIB7.js → sql-query-editor-B86NiZHI.js} +1 -1
  159. package/dist/web/assets/{sqlite-viewer-DXutos0e.js → sqlite-viewer-DB775F6C.js} +1 -1
  160. package/dist/web/assets/{stata-DVQNLMcR.js → stata-B7N56ptS.js} +1 -1
  161. package/dist/web/assets/{surrealql-lu576tBi.js → surrealql-CTmnD-lv.js} +1 -1
  162. package/dist/web/assets/{svelte-CSCrOBjT.js → svelte-BppwY9TR.js} +1 -1
  163. package/dist/web/assets/{switch-BPol3BFC.js → switch-BmjKoIpR.js} +1 -1
  164. package/dist/web/assets/{system-monitor-body-Ct8_GX_f.js → system-monitor-body-BDxHQvy9.js} +2 -2
  165. package/dist/web/assets/system-monitor-tab-BoTHLx6B.js +1 -0
  166. package/dist/web/assets/system-monitor-window-content-B9Y98UW6.js +1 -0
  167. package/dist/web/assets/{tab-host-window-content-C5kYP0-z.js → tab-host-window-content-C1j8zr68.js} +1 -1
  168. package/dist/web/assets/{tab-store-DS3YlUwR.js → tab-store-DzYSsw5a.js} +1 -1
  169. package/dist/web/assets/{table-BXDyImqk.js → table-D5Q4ap4W.js} +1 -1
  170. package/dist/web/assets/team-member-sheet-Cxz6h5Ne.js +2 -0
  171. package/dist/web/assets/{team-member-window-content-BJ_XFw8-.js → team-member-window-content-CUSuRHCB.js} +1 -1
  172. package/dist/web/assets/{templ-CPt8AS4Q.js → templ-CvTMKKra.js} +1 -1
  173. package/dist/web/assets/{terminal-tab-8bKQ3CWR.js → terminal-tab-B9I_HlES.js} +3 -3
  174. package/dist/web/assets/{tex-BrTByT7i.js → tex--c4POEUE.js} +1 -1
  175. package/dist/web/assets/{text-wrap-CzMjB6GD.js → text-wrap-DBvQD3kc.js} +1 -1
  176. package/dist/web/assets/{tool-cards-pIu_cmEL.js → tool-cards-D3KSzd2K.js} +4 -4
  177. package/dist/web/assets/{trash-2-BjShZ7if.js → trash-2-By4VMbC4.js} +1 -1
  178. package/dist/web/assets/{triangle-alert-qQ6Plydp.js → triangle-alert-CUTURFbG.js} +1 -1
  179. package/dist/web/assets/{ts-tags-DSqEZ7A8.js → ts-tags--kx7D-Hw.js} +1 -1
  180. package/dist/web/assets/{twig-DW9qc1bf.js → twig-UG9uMHGd.js} +1 -1
  181. package/dist/web/assets/{upload-7Zs6oaK5.js → upload-BNlX8D07.js} +1 -1
  182. package/dist/web/assets/{use-blob-url-DKbV7PM_.js → use-blob-url-Bdxopwwc.js} +1 -1
  183. package/dist/web/assets/{use-coarse-long-press-DGyC48NF.js → use-coarse-long-press-BmI_GVW5.js} +1 -1
  184. package/dist/web/assets/{use-is-mobile-ClE-UcPF.js → use-is-mobile-B9UZNwSm.js} +1 -1
  185. package/dist/web/assets/{use-monaco-theme-DaxAk3gB.js → use-monaco-theme-CVCye2kq.js} +1 -1
  186. package/dist/web/assets/use-open-team-member-D9EOB8-i.js +1 -0
  187. package/dist/web/assets/{use-remote-desktop-display-choice-BUA_1eaH.js → use-remote-desktop-display-choice-neUqyE3p.js} +1 -1
  188. package/dist/web/assets/{use-visual-viewport-CCX21c9w.js → use-visual-viewport-Sfb6CZ80.js} +1 -1
  189. package/dist/web/assets/{use-websocket-CWpG7PWN.js → use-websocket-xOOwBdwP.js} +1 -1
  190. package/dist/web/assets/vendor-markdown-Ls5AcU91.js +291 -0
  191. package/dist/web/assets/{vendor-ui-CXJtBULr.js → vendor-ui-CaeeFO0B.js} +1 -1
  192. package/dist/web/assets/video-preview-DvpgBDhM.js +1 -0
  193. package/dist/web/assets/{vue-html-CG5BKtq1.js → vue-html-8KEW6-I9.js} +1 -1
  194. package/dist/web/assets/{vue-CJNDL1g-.js → vue-jjTomlbt.js} +1 -1
  195. package/dist/web/assets/{vue-vine-Dd5HZ7T5.js → vue-vine-C5tohCkU.js} +1 -1
  196. package/dist/web/assets/{window-pip-registry-9H6Y-HqR.js → window-pip-registry-FdZdGF7h.js} +1 -1
  197. package/dist/web/assets/{window-store-CNzkeUyO.js → window-store-D0x_fxr0.js} +1 -1
  198. package/dist/web/assets/x-DiOUR_mp.js +1 -0
  199. package/dist/web/assets/{xml-DTOm5niz.js → xml-ByFFosqL.js} +1 -1
  200. package/dist/web/assets/{xsl-BD_kBC04.js → xsl-CZUwiLkj.js} +1 -1
  201. package/dist/web/index.html +59 -59
  202. package/dist/web/monacoeditorwork/css.worker.bundle.js +122 -122
  203. package/dist/web/monacoeditorwork/editor.worker.bundle.js +78 -78
  204. package/dist/web/monacoeditorwork/html.worker.bundle.js +110 -110
  205. package/dist/web/monacoeditorwork/json.worker.bundle.js +108 -108
  206. package/dist/web/monacoeditorwork/ts.worker.bundle.js +81 -81
  207. package/dist/web/sw.js +1 -1
  208. package/package.json +1 -1
  209. package/scripts/check-ppm-dir-usage.sh +0 -0
  210. package/scripts/install.sh +0 -0
  211. package/scripts/release.sh +0 -0
  212. package/src/providers/claude-agent-sdk.ts +51 -43
  213. package/src/providers/codex-app-server/codex-provider.ts +7 -1
  214. package/src/server/routes/chat.ts +28 -3
  215. package/src/server/ws/chat.ts +9 -4
  216. package/src/server/ws/terminal.ts +9 -3
  217. package/src/services/media-transcode/ffmpeg-capabilities.ts +48 -7
  218. package/src/services/named-tunnel/named-tunnel-retry.ts +26 -0
  219. package/src/services/named-tunnel/network-ready.ts +63 -0
  220. package/src/services/supervisor.ts +98 -0
  221. package/src/services/transcript-images.ts +14 -7
  222. package/src/services/upgrade.service.ts +7 -2
  223. package/src/shared/image-limits.ts +37 -0
  224. package/src/types/api.ts +3 -1
  225. package/src/types/chat.ts +6 -0
  226. package/src/types/extension-messages.ts +2 -0
  227. package/src/web/components/chat/attachment-chips.tsx +10 -0
  228. package/src/web/components/chat/chat-tab.tsx +37 -13
  229. package/src/web/components/chat/message-input.tsx +102 -11
  230. package/src/web/components/chat/session-debug-dialog.tsx +2 -1
  231. package/src/web/components/chat/user-message-parse.ts +33 -11
  232. package/src/web/components/database/database-viewer.tsx +34 -11
  233. package/src/web/components/database/extract-query-table.ts +24 -0
  234. package/src/web/components/database/glide-data-grid.tsx +11 -4
  235. package/src/web/components/database/glide-grid-types.ts +4 -0
  236. package/src/web/components/database/split-sql-statements.ts +116 -0
  237. package/src/web/components/database/sql-completion-provider.ts +1 -26
  238. package/src/web/components/database/sql-query-editor.tsx +2 -1
  239. package/src/web/components/database/use-database.ts +16 -1
  240. package/src/web/components/database/use-glide-cell-content.ts +11 -6
  241. package/src/web/components/editor/code-editor.tsx +30 -56
  242. package/src/web/hooks/use-chat.ts +6 -3
  243. package/src/web/lib/attachment-marker-split.ts +44 -0
  244. package/src/web/lib/image-animation.ts +51 -0
  245. package/src/web/lib/image-resize-limits.ts +47 -0
  246. package/src/web/lib/image-resize.ts +133 -0
  247. package/dist/web/assets/api-client-DLWwuUkJ.js +0 -1
  248. package/dist/web/assets/api-settings-BFuaZrNC.js +0 -1
  249. package/dist/web/assets/chat-tab-bSOVoC5N.js +0 -15
  250. package/dist/web/assets/chevron-right-D7Pn5agw.js +0 -1
  251. package/dist/web/assets/circle-4g2coECH.js +0 -1
  252. package/dist/web/assets/clock-DbiNiwCG.js +0 -1
  253. package/dist/web/assets/code-DdKXqtf_.js +0 -1
  254. package/dist/web/assets/code-editor-COTa37oe.js +0 -10
  255. package/dist/web/assets/database-viewer-Dta7lSSk.js +0 -1
  256. package/dist/web/assets/explorer-body-BGjR2Gbt.js +0 -2
  257. package/dist/web/assets/explorer-window-content-DAhHh5EQ.js +0 -1
  258. package/dist/web/assets/glide-data-grid-BSsqxe2v.js +0 -138
  259. package/dist/web/assets/group-chat-tab-CMtzoaFc.js +0 -1
  260. package/dist/web/assets/index-BkHlMfPD.js +0 -52
  261. package/dist/web/assets/keybindings-store-_KfovSz7.js +0 -1
  262. package/dist/web/assets/loader-circle-DD65e9-7.js +0 -1
  263. package/dist/web/assets/markdown-renderer-DroTmKbJ.js +0 -1
  264. package/dist/web/assets/markdown-renderer-ntDi3Tx-.js +0 -3
  265. package/dist/web/assets/mobile-explorer-sheet-BP6iU4ma.js +0 -1
  266. package/dist/web/assets/notification-store-II5Kw9rD.js +0 -1
  267. package/dist/web/assets/play-CPbVzGgq.js +0 -1
  268. package/dist/web/assets/portal-container-context-BmG4--I-.js +0 -1
  269. package/dist/web/assets/remote-desktop-mobile-sheet-CYZUjYTO.js +0 -2
  270. package/dist/web/assets/settings-tab-UPPycGRF.js +0 -1
  271. package/dist/web/assets/system-monitor-tab-DC_EerdI.js +0 -1
  272. package/dist/web/assets/system-monitor-window-content-D25DMNpw.js +0 -1
  273. package/dist/web/assets/team-member-sheet-DvmioeQL.js +0 -2
  274. package/dist/web/assets/use-open-team-member-CopUuDHG.js +0 -1
  275. package/dist/web/assets/vendor-markdown-CKTlmXbz.js +0 -291
  276. package/dist/web/assets/video-preview-C2_fdunE.js +0 -1
  277. package/dist/web/assets/x-Dzu9ecti.js +0 -1
  278. /package/dist/web/assets/{abap-Cjj2olMr.js → abap-C5DFF0s3.js} +0 -0
  279. /package/dist/web/assets/{actionscript-3-DCkW7kWC.js → actionscript-3-B0qyRNbc.js} +0 -0
  280. /package/dist/web/assets/{ada-AEWvZXuX.js → ada-bAJzplug.js} +0 -0
  281. /package/dist/web/assets/{andromeeda-D7cSpME6.js → andromeeda-DUCpISy6.js} +0 -0
  282. /package/dist/web/assets/{apache-DjvX0RSe.js → apache-BhAr84Z_.js} +0 -0
  283. /package/dist/web/assets/{apex-70xIZ0pH.js → apex-CRv8YnNq.js} +0 -0
  284. /package/dist/web/assets/{applescript-C3qKqxmA.js → applescript-CD-Cw8bt.js} +0 -0
  285. /package/dist/web/assets/{ara-iGt2zixk.js → ara-BUzeQYoG.js} +0 -0
  286. /package/dist/web/assets/{asciidoc-Bs2t-06W.js → asciidoc-CT2hTg-v.js} +0 -0
  287. /package/dist/web/assets/{asm-B-T0eqhE.js → asm-CAu35JeY.js} +0 -0
  288. /package/dist/web/assets/{aurora-x-D3h_9M3E.js → aurora-x-BeFJoIA1.js} +0 -0
  289. /package/dist/web/assets/{awk-CZwfwpPi.js → awk-Vau-DrGN.js} +0 -0
  290. /package/dist/web/assets/{ayu-dark-DulkglEA.js → ayu-dark-CLe-OTsQ.js} +0 -0
  291. /package/dist/web/assets/{ayu-light-DyNQiRpn.js → ayu-light-CJbQfu4M.js} +0 -0
  292. /package/dist/web/assets/{ayu-mirage-CcEt4xkI.js → ayu-mirage-GWaKwdrx.js} +0 -0
  293. /package/dist/web/assets/{ballerina-OhQPjyHS.js → ballerina-DWu0USI5.js} +0 -0
  294. /package/dist/web/assets/{bat-DqKcJTUn.js → bat-_07Huw7E.js} +0 -0
  295. /package/dist/web/assets/{beancount-BdXlMi8T.js → beancount-EcvogrcF.js} +0 -0
  296. /package/dist/web/assets/{berry-DvgY6BkY.js → berry-BBB87SY7.js} +0 -0
  297. /package/dist/web/assets/{bibtex-BSRJq0yM.js → bibtex-DbueS87A.js} +0 -0
  298. /package/dist/web/assets/{bicep-DpAdumKt.js → bicep-tcmXnUo4.js} +0 -0
  299. /package/dist/web/assets/{bird2-rlbtp8di.js → bird2-B2qwilIR.js} +0 -0
  300. /package/dist/web/assets/{c-AjOLBXIs.js → c-Z58oivSt.js} +0 -0
  301. /package/dist/web/assets/{c3-DqIXz4Ia.js → c3-U40cGT9p.js} +0 -0
  302. /package/dist/web/assets/{cadence-DAJtUpOE.js → cadence-BFcD-LyM.js} +0 -0
  303. /package/dist/web/assets/{catppuccin-frappe-DUPoeZfb.js → catppuccin-frappe-RkC9AX6J.js} +0 -0
  304. /package/dist/web/assets/{catppuccin-latte-CK3U68Ql.js → catppuccin-latte-Bsi4l-nO.js} +0 -0
  305. /package/dist/web/assets/{catppuccin-macchiato-BzteLnIX.js → catppuccin-macchiato-B8JIdTW-.js} +0 -0
  306. /package/dist/web/assets/{catppuccin-mocha-ozLd0aBR.js → catppuccin-mocha-oH8wwrDj.js} +0 -0
  307. /package/dist/web/assets/{clarity-6KqEoBfz.js → clarity-C3WNeRCR.js} +0 -0
  308. /package/dist/web/assets/{clojure-B_uBL5C7.js → clojure-CFoAz7u9.js} +0 -0
  309. /package/dist/web/assets/{cmake-B3nxBNmj.js → cmake-Bcsqp9yR.js} +0 -0
  310. /package/dist/web/assets/{codeowners-DkS-51at.js → codeowners-DC2Z7heP.js} +0 -0
  311. /package/dist/web/assets/{codeql-rpr1z_mR.js → codeql-BfG68Al5.js} +0 -0
  312. /package/dist/web/assets/{common-lisp-BfNbv_W6.js → common-lisp-Z5P-lKQe.js} +0 -0
  313. /package/dist/web/assets/{coq-EAW-1nw0.js → coq-BJslqrnv.js} +0 -0
  314. /package/dist/web/assets/{csharp-BE3Gn5bq.js → csharp-DhhZTOTs.js} +0 -0
  315. /package/dist/web/assets/{css-Cr27CfPY.js → css-DiFIpMfE.js} +0 -0
  316. /package/dist/web/assets/{csv-B5VtaPtH.js → csv-DViLbHxI.js} +0 -0
  317. /package/dist/web/assets/{cue-jm6lYNrx.js → cue-CoG3mg2I.js} +0 -0
  318. /package/dist/web/assets/{cypher-DXkvK-pn.js → cypher-jTxC8NAB.js} +0 -0
  319. /package/dist/web/assets/{d-CgG1_yzd.js → d-6hKIUAbU.js} +0 -0
  320. /package/dist/web/assets/{dark-plus-CALzcIVB.js → dark-plus-D_-np2Sr.js} +0 -0
  321. /package/dist/web/assets/{dart-BEVoLlWg.js → dart-CVpxLpVn.js} +0 -0
  322. /package/dist/web/assets/{dax-H0BW3Q_P.js → dax-BPqJ8qIY.js} +0 -0
  323. /package/dist/web/assets/{desktop-BtYq1l_0.js → desktop-u_y5_Hr5.js} +0 -0
  324. /package/dist/web/assets/{diff-CnBYdfTg.js → diff-Duj1XMrd.js} +0 -0
  325. /package/dist/web/assets/{dist-CJJKpgR7.js → dist-CEZ4plgH.js} +0 -0
  326. /package/dist/web/assets/{docker-COBitpld.js → docker-8UGSCc7N.js} +0 -0
  327. /package/dist/web/assets/{dotenv-CG0x1m7c.js → dotenv-DVnj8kyR.js} +0 -0
  328. /package/dist/web/assets/{dracula-CLCi47X-.js → dracula-D0cEmSg7.js} +0 -0
  329. /package/dist/web/assets/{dracula-soft-BMv5cCAV.js → dracula-soft-DfGS5Yfr.js} +0 -0
  330. /package/dist/web/assets/{dream-maker-1Bd4OSww.js → dream-maker-qG8kMGTF.js} +0 -0
  331. /package/dist/web/assets/{emacs-lisp-B-2zKLn-.js → emacs-lisp-iVqyMLyT.js} +0 -0
  332. /package/dist/web/assets/{everforest-dark-BGVynCbV.js → everforest-dark-Cruygd5U.js} +0 -0
  333. /package/dist/web/assets/{everforest-light--rn3R7Cm.js → everforest-light-BiJa8RHL.js} +0 -0
  334. /package/dist/web/assets/{fennel-SWg9Us_u.js → fennel-H6XSEIoz.js} +0 -0
  335. /package/dist/web/assets/{fish-B04oqgKk.js → fish-ho_7CxX6.js} +0 -0
  336. /package/dist/web/assets/{fluent-BefzAGMN.js → fluent-1l5ssJTF.js} +0 -0
  337. /package/dist/web/assets/{fortran-free-form-alw7jMxb.js → fortran-free-form-Bo1x233A.js} +0 -0
  338. /package/dist/web/assets/{gdscript-BAyhvjCx.js → gdscript-DffFMp_k.js} +0 -0
  339. /package/dist/web/assets/{gdshader-Crl09X-B.js → gdshader-CvnpAiAF.js} +0 -0
  340. /package/dist/web/assets/{genie-BSIGRHu7.js → genie-2eOvAEzW.js} +0 -0
  341. /package/dist/web/assets/{gherkin-DJhSnSWH.js → gherkin-DL-5OUlV.js} +0 -0
  342. /package/dist/web/assets/{github-dark-r8C6qwug.js → github-dark-DrTZprgG.js} +0 -0
  343. /package/dist/web/assets/{github-dark-default-FVtXjcm8.js → github-dark-default-_mDH8IMP.js} +0 -0
  344. /package/dist/web/assets/{github-dark-dimmed-CzrUPgSb.js → github-dark-dimmed-C48hJuLn.js} +0 -0
  345. /package/dist/web/assets/{github-dark-high-contrast-1s9rF5EB.js → github-dark-high-contrast-BQ-zGGNe.js} +0 -0
  346. /package/dist/web/assets/{github-light-BvIWCkl7.js → github-light-BYc90Yx8.js} +0 -0
  347. /package/dist/web/assets/{github-light-default-CVdhzrxV.js → github-light-default-Daecj4J5.js} +0 -0
  348. /package/dist/web/assets/{github-light-high-contrast-CBAf6hjF.js → github-light-high-contrast-DoafCbsU.js} +0 -0
  349. /package/dist/web/assets/{gleam-DvL1q7aa.js → gleam-hUWWjmnp.js} +0 -0
  350. /package/dist/web/assets/{gn-BG5NvwAf.js → gn-7PJ3R70o.js} +0 -0
  351. /package/dist/web/assets/{gnuplot-BARnM-zG.js → gnuplot-V-Pxck7b.js} +0 -0
  352. /package/dist/web/assets/{go-DXvjjq4q.js → go-ARF6DprD.js} +0 -0
  353. /package/dist/web/assets/{groovy-CRylSKhr.js → groovy-CKGBIPOz.js} +0 -0
  354. /package/dist/web/assets/{gruvbox-dark-hard-BVPjnqm7.js → gruvbox-dark-hard-Cm9wqdI3.js} +0 -0
  355. /package/dist/web/assets/{gruvbox-dark-medium-U_PDgq0a.js → gruvbox-dark-medium-Cmsd6dG8.js} +0 -0
  356. /package/dist/web/assets/{gruvbox-dark-soft-CkzNtpbr.js → gruvbox-dark-soft-BBGlGGCz.js} +0 -0
  357. /package/dist/web/assets/{gruvbox-light-hard-DfMmR2G8.js → gruvbox-light-hard-BCR7KmqG.js} +0 -0
  358. /package/dist/web/assets/{gruvbox-light-medium-BGCak-dd.js → gruvbox-light-medium-CP32bga8.js} +0 -0
  359. /package/dist/web/assets/{gruvbox-light-soft-DnpM3fkN.js → gruvbox-light-soft-qjxk8ps6.js} +0 -0
  360. /package/dist/web/assets/{haskell-DXgGIDD_.js → haskell-C5DzwGRa.js} +0 -0
  361. /package/dist/web/assets/{haxe-B7qlTpRz.js → haxe-C8f_jCVv.js} +0 -0
  362. /package/dist/web/assets/{hcl-ADWfVe_Q.js → hcl-DetJkf6E.js} +0 -0
  363. /package/dist/web/assets/{hjson-BaM9gLbq.js → hjson-DeZhwIdo.js} +0 -0
  364. /package/dist/web/assets/{hlsl-iqaRA4MG.js → hlsl-SMIDLRyX.js} +0 -0
  365. /package/dist/web/assets/{horizon-BPpTnhB9.js → horizon-BMAVDxMx.js} +0 -0
  366. /package/dist/web/assets/{horizon-bright-yBLg3QbE.js → horizon-bright-3BaV_VGD.js} +0 -0
  367. /package/dist/web/assets/{houston-eFOp0ySL.js → houston-BWBbEPvb.js} +0 -0
  368. /package/dist/web/assets/{hy-BALeMn3i.js → hy-DcsmE-Nm.js} +0 -0
  369. /package/dist/web/assets/{imba-CdGUm_GD.js → imba-CnkgnYMf.js} +0 -0
  370. /package/dist/web/assets/{ini-DG7imsqe.js → ini-BnvTdau7.js} +0 -0
  371. /package/dist/web/assets/{java-D5GTT474.js → java-BLFACXat.js} +0 -0
  372. /package/dist/web/assets/{javascript-V7WwJvRm.js → javascript-BKcFWENk.js} +0 -0
  373. /package/dist/web/assets/{json-B9FhwAgR.js → json-3AJtJADf.js} +0 -0
  374. /package/dist/web/assets/{json5--Abk7MUy.js → json5-DLyDVlwe.js} +0 -0
  375. /package/dist/web/assets/{jsonc-C8jb-Z6x.js → jsonc-B5DgF1jW.js} +0 -0
  376. /package/dist/web/assets/{jsonl-CaJNxfkm.js → jsonl-CV_O71a2.js} +0 -0
  377. /package/dist/web/assets/{jsonnet-CPrKMSCU.js → jsonnet-DZfPLgYz.js} +0 -0
  378. /package/dist/web/assets/{jssm-DEu-9_uo.js → jssm-Cr1zYOsY.js} +0 -0
  379. /package/dist/web/assets/{jsx-MfAsCWDW.js → jsx-VN-JS2_q.js} +0 -0
  380. /package/dist/web/assets/{kanagawa-dragon-DnbcAduF.js → kanagawa-dragon-D9CcT3xg.js} +0 -0
  381. /package/dist/web/assets/{kanagawa-lotus-yxsY3ew8.js → kanagawa-lotus-DLXsB8fr.js} +0 -0
  382. /package/dist/web/assets/{kanagawa-wave-C2RyvZaM.js → kanagawa-wave-weDs3Wjz.js} +0 -0
  383. /package/dist/web/assets/{kdl-CvssmvcU.js → kdl-0XF56jnT.js} +0 -0
  384. /package/dist/web/assets/{kotlin-jufO49mU.js → kotlin-BPkH9vzk.js} +0 -0
  385. /package/dist/web/assets/{kusto-BAFnylR7.js → kusto-DMVpADb9.js} +0 -0
  386. /package/dist/web/assets/{laserwave-BgxFC4Ge.js → laserwave-Cl6T2cGP.js} +0 -0
  387. /package/dist/web/assets/{lean-Bgt24V1D.js → lean-BvwzQGl1.js} +0 -0
  388. /package/dist/web/assets/{less-Bk_UaqsM.js → less-DI_03xkC.js} +0 -0
  389. /package/dist/web/assets/{light-plus-nMxFfInN.js → light-plus-hIiIsQN_.js} +0 -0
  390. /package/dist/web/assets/{llvm-3_PASDOO.js → llvm-B5hjjSWc.js} +0 -0
  391. /package/dist/web/assets/{log-CKm0CxB1.js → log-D28raQiE.js} +0 -0
  392. /package/dist/web/assets/{logo-DFP1_5U6.js → logo-6Cdd4ASb.js} +0 -0
  393. /package/dist/web/assets/{luau-BcZnoyh3.js → luau-CK9nKpOX.js} +0 -0
  394. /package/dist/web/assets/{make-CpNSwgwT.js → make-CVnxKCB6.js} +0 -0
  395. /package/dist/web/assets/{markdown-DhU3Djpv.js → markdown-B9mMQzD5.js} +0 -0
  396. /package/dist/web/assets/{material-theme-DD5L3OqF.js → material-theme-BZSs2o0j.js} +0 -0
  397. /package/dist/web/assets/{material-theme-darker-CG2_tD3R.js → material-theme-darker-BeAQBzQ_.js} +0 -0
  398. /package/dist/web/assets/{material-theme-lighter-CzNkUc9Y.js → material-theme-lighter-BAe0IXcs.js} +0 -0
  399. /package/dist/web/assets/{material-theme-ocean-BtLiAaF_.js → material-theme-ocean-CiPIf0Np.js} +0 -0
  400. /package/dist/web/assets/{material-theme-palenight-Brvjz035.js → material-theme-palenight-DJBb4_XN.js} +0 -0
  401. /package/dist/web/assets/{matlab-CCY0KtMD.js → matlab-CY0dbp_s.js} +0 -0
  402. /package/dist/web/assets/{mdx-CH6YY0aS.js → mdx-DU9zbF7h.js} +0 -0
  403. /package/dist/web/assets/{mermaid-Bqh3gFI0.js → mermaid-UmmjGwdh.js} +0 -0
  404. /package/dist/web/assets/{min-dark-BUwfTzI6.js → min-dark-C59GkzOm.js} +0 -0
  405. /package/dist/web/assets/{min-light-oLanXCOk.js → min-light-B9QglrdQ.js} +0 -0
  406. /package/dist/web/assets/{mipsasm-CTh3hPWK.js → mipsasm-Dc6Jsr_D.js} +0 -0
  407. /package/dist/web/assets/{mojo-DXdszZKa.js → mojo-D5ij-nGW.js} +0 -0
  408. /package/dist/web/assets/{monokai-TNE_tRxc.js → monokai-QAtE_yCP.js} +0 -0
  409. /package/dist/web/assets/{moonbit-jrk-Gx1X.js → moonbit-BMtIdiTL.js} +0 -0
  410. /package/dist/web/assets/{move-DItn61bH.js → move-BB_jMHYZ.js} +0 -0
  411. /package/dist/web/assets/{narrat-3kB4dkh0.js → narrat-BvvoKGVn.js} +0 -0
  412. /package/dist/web/assets/{nextflow-groovy-CSKtwETr.js → nextflow-groovy-CqxtAsnF.js} +0 -0
  413. /package/dist/web/assets/{night-owl-Dm91nSIq.js → night-owl-CLoE9kjt.js} +0 -0
  414. /package/dist/web/assets/{night-owl-light-riwrcPRg.js → night-owl-light-BwIFT5Xd.js} +0 -0
  415. /package/dist/web/assets/{nix-sLgl9zGF.js → nix-BKlnVT9r.js} +0 -0
  416. /package/dist/web/assets/{nord-TWkJPI6M.js → nord-B7R1KRAK.js} +0 -0
  417. /package/dist/web/assets/{nushell-CDZi4-Gf.js → nushell-CzUme-NJ.js} +0 -0
  418. /package/dist/web/assets/{objective-c-DW9PboNp.js → objective-c-D-UKKiOc.js} +0 -0
  419. /package/dist/web/assets/{objective-cpp-2XCCX6q1.js → objective-cpp-BucWn4Fx.js} +0 -0
  420. /package/dist/web/assets/{ocaml-CxPdnjrh.js → ocaml-EJCNXMGo.js} +0 -0
  421. /package/dist/web/assets/{odin-BJjlKpkM.js → odin-CEjnRU_3.js} +0 -0
  422. /package/dist/web/assets/{one-dark-pro-K1KOmBZ7.js → one-dark-pro-Bv469NX5.js} +0 -0
  423. /package/dist/web/assets/{one-light-DQB-vUyZ.js → one-light-BlzO5RWI.js} +0 -0
  424. /package/dist/web/assets/{openscad-DCoLwn4j.js → openscad-Czl6alLw.js} +0 -0
  425. /package/dist/web/assets/{pascal-z2ktbbWp.js → pascal-BI9fLvG4.js} +0 -0
  426. /package/dist/web/assets/{pkl-Dyq4-v6z.js → pkl-ChQLsyjU.js} +0 -0
  427. /package/dist/web/assets/{plastic-C4Rq5PnD.js → plastic-DGL3mtdL.js} +0 -0
  428. /package/dist/web/assets/{plsql-BCIjO63y.js → plsql-BJDjqcWp.js} +0 -0
  429. /package/dist/web/assets/{po-_kXpd_0n.js → po-DK5O3OpF.js} +0 -0
  430. /package/dist/web/assets/{poimandres-C9XggjB3.js → poimandres-CnuqZT4T.js} +0 -0
  431. /package/dist/web/assets/{polar-DV_1L04z.js → polar-DCsUxSsQ.js} +0 -0
  432. /package/dist/web/assets/{postcss-BuqS91mQ.js → postcss-8UjdFmis.js} +0 -0
  433. /package/dist/web/assets/{powerquery-DK13B2Dc.js → powerquery-CAp0CGQj.js} +0 -0
  434. /package/dist/web/assets/{powershell-tkuhhtuP.js → powershell-CbBsKZJP.js} +0 -0
  435. /package/dist/web/assets/{prisma-WNXfBtpr.js → prisma-BnNpXCJN.js} +0 -0
  436. /package/dist/web/assets/{prolog-BzEdNKfO.js → prolog-CC-l9E8Y.js} +0 -0
  437. /package/dist/web/assets/{proto-B5meVsrA.js → proto-CV_1k2rL.js} +0 -0
  438. /package/dist/web/assets/{puppet-C7h_p4r2.js → puppet-2D8HU2bv.js} +0 -0
  439. /package/dist/web/assets/{purescript-qH1KxAs6.js → purescript-BEJAORgU.js} +0 -0
  440. /package/dist/web/assets/{python-DeTIYd5V.js → python-BBdbb7nn.js} +0 -0
  441. /package/dist/web/assets/{qmldir-4Rm5AvD3.js → qmldir-D5ZYI4Ie.js} +0 -0
  442. /package/dist/web/assets/{qss-YRbeNtr0.js → qss-BOJVGyXE.js} +0 -0
  443. /package/dist/web/assets/{r-DHwHK0Jh.js → r-B5dlEtkj.js} +0 -0
  444. /package/dist/web/assets/{racket-gKn4SFLQ.js → racket-BUAEygJ6.js} +0 -0
  445. /package/dist/web/assets/{raku-DWTmAj3A.js → raku-BG0Ss0ID.js} +0 -0
  446. /package/dist/web/assets/{red-BFuHRZFS.js → red-C5yyQbtG.js} +0 -0
  447. /package/dist/web/assets/{reg-DYoOF5tH.js → reg-DHoBWtLf.js} +0 -0
  448. /package/dist/web/assets/{regexp-6rXQHD2-.js → regexp-DDtJrlKv.js} +0 -0
  449. /package/dist/web/assets/{rel-Z_tTruCU.js → rel-CR6WJDRD.js} +0 -0
  450. /package/dist/web/assets/{riscv-DfTfKuvU.js → riscv-2V9tC-nx.js} +0 -0
  451. /package/dist/web/assets/{ron-CsUtW8gQ.js → ron-QLTmqGUw.js} +0 -0
  452. /package/dist/web/assets/{rose-pine-Dng_vCo6.js → rose-pine-be0__X3A.js} +0 -0
  453. /package/dist/web/assets/{rose-pine-dawn-Ds88Nezf.js → rose-pine-dawn-n_WQJwsW.js} +0 -0
  454. /package/dist/web/assets/{rose-pine-moon-DWpzrqNz.js → rose-pine-moon-t2aLtzgB.js} +0 -0
  455. /package/dist/web/assets/{rosmsg-h2sO84oD.js → rosmsg-Ce1JD8vt.js} +0 -0
  456. /package/dist/web/assets/{rust-Dx86yfCi.js → rust-5fHH-ZoW.js} +0 -0
  457. /package/dist/web/assets/{sass-BwwVhdT9.js → sass-DPmGFiOJ.js} +0 -0
  458. /package/dist/web/assets/{scala-WJqNEN-w.js → scala-BRMVFbZF.js} +0 -0
  459. /package/dist/web/assets/{scheme-uwj-t1Rp.js → scheme-BMSJWevF.js} +0 -0
  460. /package/dist/web/assets/{sdbl-BYy5hgEz.js → sdbl-DTZ-pEHI.js} +0 -0
  461. /package/dist/web/assets/{shellscript-DWTW_w2K.js → shellscript-6-9yg5Cz.js} +0 -0
  462. /package/dist/web/assets/{slack-dark-BvhGq5vQ.js → slack-dark-DKJgiR7e.js} +0 -0
  463. /package/dist/web/assets/{slack-ochin-C9g0ZRFr.js → slack-ochin-WjehVgyK.js} +0 -0
  464. /package/dist/web/assets/{smalltalk-ZEiZ6i7U.js → smalltalk-BChf4SN1.js} +0 -0
  465. /package/dist/web/assets/{snazzy-light-29OA24q5.js → snazzy-light-C1WAwOx6.js} +0 -0
  466. /package/dist/web/assets/{solarized-dark-Bnq9IOn_.js → solarized-dark-BxREZrGx.js} +0 -0
  467. /package/dist/web/assets/{solarized-light-CYdI7T5g.js → solarized-light-DG29B1pR.js} +0 -0
  468. /package/dist/web/assets/{solidity-DcuIDB-_.js → solidity-bDbtGwdR.js} +0 -0
  469. /package/dist/web/assets/{splunk-D5ONE91g.js → splunk-Ceqx5njI.js} +0 -0
  470. /package/dist/web/assets/{sql-DIwJJDU-.js → sql-OwMEKbz8.js} +0 -0
  471. /package/dist/web/assets/{ssh-config-D8717tLI.js → ssh-config-WAR3lu2k.js} +0 -0
  472. /package/dist/web/assets/{stylus-Cm1lO4Y6.js → stylus-Cjmoz3d8.js} +0 -0
  473. /package/dist/web/assets/{swift-X8oWpSeU.js → swift-S_ZSBG1q.js} +0 -0
  474. /package/dist/web/assets/{synthwave-84-DF-t1UKY.js → synthwave-84-DiUeWMSh.js} +0 -0
  475. /package/dist/web/assets/{system-verilog-JYyHFpPf.js → system-verilog-RRjqPjUV.js} +0 -0
  476. /package/dist/web/assets/{systemd-Da-5Ma_c.js → systemd-BD3SkXoU.js} +0 -0
  477. /package/dist/web/assets/{talonscript-CXraVPho.js → talonscript-DWefISOm.js} +0 -0
  478. /package/dist/web/assets/{tasl-BCmWezH9.js → tasl-DCjSS-09.js} +0 -0
  479. /package/dist/web/assets/{tcl-BTufzfbf.js → tcl-DTYqT_66.js} +0 -0
  480. /package/dist/web/assets/{terraform-CtUA9c8W.js → terraform-CkbP5QnR.js} +0 -0
  481. /package/dist/web/assets/{tokyo-night-BCThYXmz.js → tokyo-night-qVSqO9xy.js} +0 -0
  482. /package/dist/web/assets/{toml-D5YlDr6Y.js → toml-D9F5Osqs.js} +0 -0
  483. /package/dist/web/assets/{tsv-CBB-P_Sl.js → tsv-C5tpHoxm.js} +0 -0
  484. /package/dist/web/assets/{tsx-D5B4juDp.js → tsx-CMWkGtGm.js} +0 -0
  485. /package/dist/web/assets/{turtle-D8PCeJ-v.js → turtle-Cn4z3xOi.js} +0 -0
  486. /package/dist/web/assets/{typescript-CMPnTawp.js → typescript-DSyAEWsn.js} +0 -0
  487. /package/dist/web/assets/{typespec-CHxldxIW.js → typespec-B93Qap7y.js} +0 -0
  488. /package/dist/web/assets/{typst-Q8CqX5OR.js → typst-DtlOmFlX.js} +0 -0
  489. /package/dist/web/assets/{v-Bf2hKAMu.js → v-Dfzf-szS.js} +0 -0
  490. /package/dist/web/assets/{vala-Cbete-UE.js → vala-CyiQZQ9f.js} +0 -0
  491. /package/dist/web/assets/{vb-CA-xWAcX.js → vb-C7DGSldd.js} +0 -0
  492. /package/dist/web/assets/{verilog-B3wb8CfT.js → verilog-kF-hClY2.js} +0 -0
  493. /package/dist/web/assets/{vesper-D6r3VJq_.js → vesper-BmKcADuz.js} +0 -0
  494. /package/dist/web/assets/{vhdl-C42S_797.js → vhdl-CDnb16KJ.js} +0 -0
  495. /package/dist/web/assets/{viml-BePrIAs8.js → viml-B8cs6Ady.js} +0 -0
  496. /package/dist/web/assets/{vitesse-black-DRqn61Ck.js → vitesse-black-BR6o9Gto.js} +0 -0
  497. /package/dist/web/assets/{vitesse-dark-39_8UE-w.js → vitesse-dark-Dye14-KB.js} +0 -0
  498. /package/dist/web/assets/{vitesse-light-B1jwrxDm.js → vitesse-light-BLpswIxf.js} +0 -0
  499. /package/dist/web/assets/{vyper-tDJv3imF.js → vyper-DU51Z97W.js} +0 -0
  500. /package/dist/web/assets/{wasm-DR7eskZH.js → wasm-CVqlJAR2.js} +0 -0
  501. /package/dist/web/assets/{wenyan-CezVfqN3.js → wenyan-DhCa3hCn.js} +0 -0
  502. /package/dist/web/assets/{wgsl-CwOcIiIG.js → wgsl-Bj1Ec4vv.js} +0 -0
  503. /package/dist/web/assets/{wikitext-C5coomYc.js → wikitext-C90DHNa0.js} +0 -0
  504. /package/dist/web/assets/{wit-C9yyX6-U.js → wit-DUgbOD7Z.js} +0 -0
  505. /package/dist/web/assets/{wolfram-BWi0rMAa.js → wolfram-BgwUqD1I.js} +0 -0
  506. /package/dist/web/assets/{yaml-CGXhKUtT.js → yaml-DEQulj-8.js} +0 -0
  507. /package/dist/web/assets/{zenscript-Do7WLoJh.js → zenscript-C7Jp7TgT.js} +0 -0
  508. /package/dist/web/assets/{zig-Cr80Qrru.js → zig-9x4qXYLg.js} +0 -0
@@ -49,7 +49,12 @@ export function useGlideCellContent(
49
49
  pkCol: string | null,
50
50
  addPendingEdit: (pkVal: unknown, col: string, newVal: unknown) => void,
51
51
  pendingRef: React.RefObject<Map<string, PendingEdit>>,
52
+ readOnly = false,
52
53
  ): UseGlideCellContentResult {
54
+ // Read through a ref: getCellContent is stable (canvas render loop) and must
55
+ // still see the current mode without being re-created.
56
+ const readOnlyRef = useRef(readOnly);
57
+ readOnlyRef.current = readOnly;
53
58
  const rowsRef = useRef(rows);
54
59
  rowsRef.current = rows;
55
60
  const colOrderRef = useRef(columnOrder);
@@ -106,7 +111,7 @@ export function useGlideCellContent(
106
111
  }
107
112
  return {
108
113
  kind: GridCellKind.Text, data: "", displayData: placeholder,
109
- allowOverlay: !isPk, readonly: isPk,
114
+ allowOverlay: !isPk, readonly: isPk || readOnlyRef.current,
110
115
  themeOverride: hasPending ? PENDING_THEME : (isNewRow || placeholder !== "NULL" ? { textDark: "#9ca3af" } : { textDark: "#6b7280" }),
111
116
  };
112
117
  }
@@ -115,27 +120,27 @@ export function useGlideCellContent(
115
120
  if (kind === GridCellKind.Number && typeof val === "number") {
116
121
  return {
117
122
  kind: GridCellKind.Number, data: val, displayData: String(val),
118
- allowOverlay: !isPk, readonly: isPk,
123
+ allowOverlay: !isPk, readonly: isPk || readOnlyRef.current,
119
124
  themeOverride: hasPending ? PENDING_THEME : undefined,
120
125
  };
121
126
  }
122
127
 
123
128
  // Boolean cells
124
129
  if (kind === GridCellKind.Boolean && typeof val === "boolean") {
125
- return { kind: GridCellKind.Boolean, data: val, readonly: isPk, allowOverlay: false };
130
+ return { kind: GridCellKind.Boolean, data: val, readonly: isPk || readOnlyRef.current, allowOverlay: false };
126
131
  }
127
132
 
128
133
  // Text cell
129
134
  const strVal = formatCellValue(val);
130
135
  return {
131
136
  kind: GridCellKind.Text, data: strVal, displayData: truncateDisplay(strVal),
132
- allowOverlay: !isPk, readonly: isPk,
137
+ allowOverlay: !isPk, readonly: isPk || readOnlyRef.current,
133
138
  themeOverride: hasPending ? PENDING_THEME : undefined,
134
139
  };
135
140
  }, []); // stable — reads from refs
136
141
 
137
142
  const onCellEdited = useCallback(([colIdx, rowIdx]: Item, newValue: EditableGridCell) => {
138
- if (!pkCol) return;
143
+ if (!pkCol || readOnly) return;
139
144
  const colName = colOrderRef.current[colIdx];
140
145
  const row = rowsRef.current[rowIdx];
141
146
  if (!colName || !row) return;
@@ -153,7 +158,7 @@ export function useGlideCellContent(
153
158
  }
154
159
 
155
160
  addPendingEdit(pkVal, colName, parsed);
156
- }, [pkCol, addPendingEdit]);
161
+ }, [pkCol, readOnly, addPendingEdit]);
157
162
 
158
163
  return { getCellContent, onCellEdited };
159
164
  }
@@ -14,7 +14,8 @@ import { EditorToolbar } from "./editor-toolbar";
14
14
  import { EditorLanguagePicker } from "./editor-language-picker";
15
15
  import { SaveAsDialog } from "./save-as-dialog";
16
16
  import { EditorMobileToolbar } from "./editor-mobile-toolbar";
17
- import { createSqlCompletionProvider, clearCompletionCache, getStatementAtCursor, type SchemaInfo } from "../database/sql-completion-provider";
17
+ import { createSqlCompletionProvider, clearCompletionCache, type SchemaInfo } from "../database/sql-completion-provider";
18
+ import { getStatementAtCursor, splitSqlStatements } from "../database/split-sql-statements";
18
19
  import { useConnections, type Connection } from "../database/use-connections";
19
20
  import { GlideDataGrid } from "../database/glide-data-grid";
20
21
  import type { GridColumnSchema } from "../database/glide-grid-types";
@@ -509,76 +510,49 @@ export const CodeEditor = memo(function CodeEditor({ metadata, tabId }: CodeEdit
509
510
  if (model !== thisModel) return { lenses: [], dispose: () => {} };
510
511
 
511
512
  const lenses: MonacoType.languages.CodeLens[] = [];
512
- const text = model.getValue();
513
- const lines = text.split("\n");
514
- let stmtStartLine = -1;
515
- let stmtLines: string[] = [];
516
- let dollarBlock = false; // Track DO $$ ... $$ blocks
517
-
518
- // Transaction block tracking: group BEGIN...COMMIT into single Run Transaction
519
- const txPattern = /^(BEGIN|COMMIT|ROLLBACK|END)(;|\s|$)/i;
520
- let txBlockStartLine = -1;
521
- let txBlockStmts: string[] = [];
522
513
 
523
514
  const addLens = (line: number, stmt: string, title = "\u25B7 Run") => {
524
515
  const trimmed = stmt.trim();
525
- if (!trimmed || trimmed.startsWith("--")) return;
516
+ if (!trimmed) return;
526
517
  lenses.push({
527
518
  range: { startLineNumber: line, startColumn: 1, endLineNumber: line, endColumn: 1 },
528
519
  command: { id: cmdId, title, arguments: [trimmed] },
529
520
  });
530
521
  };
531
522
 
532
- for (let i = 0; i < lines.length; i++) {
533
- const trimmed = lines[i]!.trim();
534
- if (stmtStartLine === -1) {
535
- if (!trimmed || trimmed.startsWith("--")) continue;
536
- stmtStartLine = i + 1;
537
- stmtLines = [];
538
- }
539
- stmtLines.push(lines[i]!);
540
-
541
- // Detect $$ dollar-quoted block start/end
542
- const dollarMatches = (trimmed.match(/\$\$/g) || []).length;
543
- if (dollarMatches % 2 === 1) dollarBlock = !dollarBlock;
544
-
545
- // Only split on ; when NOT inside a $$ block
546
- if (!dollarBlock && trimmed.endsWith(";")) {
547
- const stmt = stmtLines.join("\n").trim();
548
- const isTxStart = /^BEGIN(;|\s|$)/i.test(stmt);
549
- const isTxEnd = /^(COMMIT|ROLLBACK|END)(;|\s|$)/i.test(stmt);
550
-
551
- if (txBlockStartLine === -1 && isTxStart) {
552
- // Start collecting transaction block
553
- txBlockStartLine = stmtStartLine;
554
- txBlockStmts = [stmt];
555
- } else if (txBlockStartLine > -1) {
556
- txBlockStmts.push(stmt);
557
- // Individual Run for non-tx-control statements inside block
558
- if (!isTxEnd && !txPattern.test(stmt)) {
559
- addLens(stmtStartLine, stmt);
560
- }
561
- if (isTxEnd) {
562
- // Complete block — add Run Transaction at BEGIN line
563
- addLens(txBlockStartLine, txBlockStmts.join("\n"), "\u25B7 Run Transaction");
564
- txBlockStartLine = -1;
565
- txBlockStmts = [];
566
- }
567
- } else {
568
- addLens(stmtStartLine, stmt);
569
- }
523
+ // Transaction block tracking: group BEGIN...COMMIT into single Run Transaction
524
+ const txPattern = /^(BEGIN|COMMIT|ROLLBACK|END)(;|\s|$)/i;
525
+ let txBlockStartLine = -1;
526
+ let txBlockStmts: string[] = [];
570
527
 
571
- stmtStartLine = -1;
572
- stmtLines = [];
528
+ for (const { sql, startLine } of splitSqlStatements(model.getValue())) {
529
+ const isTxStart = /^BEGIN(;|\s|$)/i.test(sql);
530
+ const isTxEnd = /^(COMMIT|ROLLBACK|END)(;|\s|$)/i.test(sql);
531
+
532
+ if (txBlockStartLine === -1 && isTxStart) {
533
+ // Start collecting transaction block
534
+ txBlockStartLine = startLine;
535
+ txBlockStmts = [sql];
536
+ } else if (txBlockStartLine > -1) {
537
+ txBlockStmts.push(sql);
538
+ // Individual Run for non-tx-control statements inside block
539
+ if (!isTxEnd && !txPattern.test(sql)) {
540
+ addLens(startLine, sql);
541
+ }
542
+ if (isTxEnd) {
543
+ // Complete block — add Run Transaction at BEGIN line
544
+ addLens(txBlockStartLine, txBlockStmts.join("\n"), "\u25B7 Run Transaction");
545
+ txBlockStartLine = -1;
546
+ txBlockStmts = [];
547
+ }
548
+ } else {
549
+ addLens(startLine, sql);
573
550
  }
574
551
  }
575
552
  // Unclosed transaction block — still offer Run Transaction
576
553
  if (txBlockStartLine > -1 && txBlockStmts.length > 1) {
577
554
  addLens(txBlockStartLine, txBlockStmts.join("\n"), "\u25B7 Run Transaction");
578
555
  }
579
- if (stmtStartLine > 0 && stmtLines.join("").trim()) {
580
- addLens(stmtStartLine, stmtLines.join("\n"));
581
- }
582
556
  return { lenses, dispose: () => {} };
583
557
  },
584
558
  });
@@ -878,7 +852,7 @@ function SqlResultPanel({ result, error, loading, connName, onClose, onOpenInTab
878
852
  <GlideDataGrid
879
853
  columns={tableData.columns} rows={tableData.rows} total={tableData.total} limit={tableData.limit}
880
854
  schema={querySchema} loading={false}
881
- page={1} onPageChange={NOOP} onCellUpdate={NOOP}
855
+ page={1} onPageChange={NOOP} onCellUpdate={NOOP} readOnly
882
856
  orderBy={null} orderDir="ASC" onToggleSort={NOOP}
883
857
  connectionName={connName}
884
858
  />
@@ -90,7 +90,7 @@ interface UseChatReturn {
90
90
  backgroundShells: BackgroundShell[];
91
91
  killBackgroundShell: (shellId: string) => void;
92
92
  findBackgroundShellByOutput: (name: string) => BackgroundShell | undefined;
93
- sendMessage: (content: string, opts?: { permissionMode?: string; priority?: 'now' | 'next' | 'later'; images?: Array<{ data: string; mediaType: string }> }) => void;
93
+ sendMessage: (content: string, opts?: { permissionMode?: string; priority?: 'now' | 'next' | 'later'; images?: Array<{ data: string; mediaType: string }>; imagePaths?: string[] }) => void;
94
94
  respondToApproval: (requestId: string, approved: boolean, data?: unknown) => void;
95
95
  cancelStreaming: () => void;
96
96
  reconnect: () => void;
@@ -1035,8 +1035,10 @@ export function useChat(sessionId: string | null, providerId = "claude", project
1035
1035
  }, [sessionId, providerId, projectName, updateTeamActivity, loadTeamDetail]);
1036
1036
 
1037
1037
  const sendMessage = useCallback(
1038
- (content: string, opts?: { permissionMode?: string; priority?: 'now' | 'next' | 'later'; images?: Array<{ data: string; mediaType: string }> }) => {
1039
- if (!content.trim()) return;
1038
+ (content: string, opts?: { permissionMode?: string; priority?: 'now' | 'next' | 'later'; images?: Array<{ data: string; mediaType: string }>; imagePaths?: string[] }) => {
1039
+ // An attachment-only message is legitimate now that images travel with it: the
1040
+ // caller may have nothing to say beyond the picture.
1041
+ if (!content.trim() && !opts?.images?.length) return;
1040
1042
 
1041
1043
  const isFollowUp = phaseRef.current !== "idle";
1042
1044
 
@@ -1089,6 +1091,7 @@ export function useChat(sessionId: string | null, providerId = "claude", project
1089
1091
  permissionMode: opts?.permissionMode,
1090
1092
  priority: opts?.priority,
1091
1093
  images: opts?.images,
1094
+ imagePaths: opts?.imagePaths,
1092
1095
  ...(modelRef.current && { model: modelRef.current }),
1093
1096
  ...(effortRef.current && { effort: effortRef.current }),
1094
1097
  ...(thinkingRef.current !== null && { thinking: thinkingRef.current }),
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Which attachments are announced as already-included, and which as files to open.
3
+ *
4
+ * Split out from the composer so it can be asserted on. The decision looks obvious and is
5
+ * not: it has to follow the payloads that actually go out, not merely which attachments have
6
+ * one. The per-message caps can leave an image behind, and announcing that its contents are
7
+ * included would hand the model neither the picture nor a reason to open the file.
8
+ */
9
+
10
+ /** The parts of an attachment this split needs. */
11
+ export interface MarkerCandidate {
12
+ serverPath?: string;
13
+ imageData?: { data: string; mediaType: string };
14
+ }
15
+
16
+ export interface MarkerSplit {
17
+ /** Uploaded paths whose payloads are travelling in this message. */
18
+ inlineImagePaths: string[];
19
+ /** Uploaded paths the model has to open for itself. */
20
+ pathOnlyPaths: string[];
21
+ }
22
+
23
+ /**
24
+ * Sort `attachments` by whether their payload is in `inlineImages`.
25
+ *
26
+ * An attachment with no uploaded path is in neither list: there is nothing to name. Identity
27
+ * is what pairs a payload to its attachment — `inlineImages` holds the very objects the
28
+ * attachments carry, so a second image with byte-identical data is not mistaken for the one
29
+ * that was picked.
30
+ */
31
+ export function splitAttachmentMarkers(
32
+ attachments: MarkerCandidate[],
33
+ inlineImages: Array<{ data: string; mediaType: string }>,
34
+ ): MarkerSplit {
35
+ const sent = new Set(inlineImages);
36
+ const inlineImagePaths: string[] = [];
37
+ const pathOnlyPaths: string[] = [];
38
+ for (const a of attachments) {
39
+ if (!a.serverPath) continue;
40
+ if (a.imageData && sent.has(a.imageData)) inlineImagePaths.push(a.serverPath);
41
+ else pathOnlyPaths.push(a.serverPath);
42
+ }
43
+ return { inlineImagePaths, pathOnlyPaths };
44
+ }
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Whether an image file carries more than one frame.
3
+ *
4
+ * Re-encoding through a canvas keeps a single frame, so an animated image that goes through
5
+ * the downscaler comes out silently flattened — and for the animations people paste into a
6
+ * chat, a screen recording of a bug or a flow, the motion *is* the content. Better to leave
7
+ * such a file at its original size than to shrink away the thing being shown.
8
+ *
9
+ * Detection reads container markers rather than decoding: an animated WebP declares an `ANIM`
10
+ * chunk and an animated PNG an `acTL` chunk, both within the first few hundred bytes. GIF is
11
+ * treated as animated without inspection — the marker for a still GIF is the *absence* of
12
+ * extra frame separators, which cannot be established from a prefix, and a still GIF is rare
13
+ * enough that assuming motion costs almost nothing.
14
+ */
15
+
16
+ /** Bytes read from the front of a file to look for animation markers. */
17
+ const HEADER_BYTES = 4096;
18
+
19
+ function findAscii(bytes: Uint8Array, needle: string): boolean {
20
+ const target = new TextEncoder().encode(needle);
21
+ outer: for (let i = 0; i + target.length <= bytes.length; i++) {
22
+ for (let j = 0; j < target.length; j++) {
23
+ if (bytes[i + j] !== target[j]) continue outer;
24
+ }
25
+ return true;
26
+ }
27
+ return false;
28
+ }
29
+
30
+ export function hasAnimationMarker(type: string, header: Uint8Array): boolean {
31
+ if (type === "image/gif") return true;
32
+ if (type === "image/webp") return findAscii(header, "ANIM");
33
+ if (type === "image/png" || type === "image/apng") return findAscii(header, "acTL");
34
+ // AVIF sequences and anything unrecognised: not decodable here anyway, so the caller
35
+ // falls back to sending the file by path.
36
+ return false;
37
+ }
38
+
39
+ /** Read enough of `file` to answer, treating an unreadable file as animated (do not touch it). */
40
+ export async function isAnimatedImage(file: File): Promise<boolean> {
41
+ if (file.type === "image/gif") return true;
42
+ if (file.type !== "image/webp" && file.type !== "image/png" && file.type !== "image/apng") {
43
+ return false;
44
+ }
45
+ try {
46
+ const head = new Uint8Array(await file.slice(0, HEADER_BYTES).arrayBuffer());
47
+ return hasAnimationMarker(file.type, head);
48
+ } catch {
49
+ return true;
50
+ }
51
+ }
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Ceilings on what may be sent as inline image payloads in one message.
3
+ *
4
+ * The chat socket refuses a message outright when it carries more than five images or one
5
+ * above seven million base64 characters, and the WebSocket frame itself has a size past which
6
+ * Bun closes the connection — which loses the message with nothing shown to the user. Both are
7
+ * worth staying under by a margin rather than discovering at the boundary.
8
+ *
9
+ * Exceeding these is not an error: the attachment travels by path instead, which is how every
10
+ * attachment worked before inlining existed.
11
+ */
12
+ export const INLINE_IMAGE_LIMITS = {
13
+ /** Server refuses a message carrying more than five. */
14
+ maxImages: 4,
15
+ /** Server refuses a single payload above 7,000,000 base64 characters. */
16
+ maxBase64PerImage: 5_000_000,
17
+ /** Frame budget across all payloads in one message, well under the 16 MiB default. */
18
+ maxBase64Total: 10_000_000,
19
+ } as const;
20
+
21
+ /** The subset of an attachment this module needs to decide whether it can ride inline. */
22
+ export interface InlineCandidate {
23
+ imageData?: { data: string; mediaType: string };
24
+ }
25
+
26
+ /**
27
+ * The image payloads that may ride on one message, in order, up to those ceilings.
28
+ *
29
+ * An attachment past a ceiling is left out rather than refused: its path is still in the
30
+ * message, so the model can open it the old way. A candidate that does not fit is skipped
31
+ * instead of ending the scan, so one large image does not exclude the small ones after it.
32
+ */
33
+ export function selectInlineImages(
34
+ attachments: InlineCandidate[],
35
+ ): Array<{ data: string; mediaType: string }> {
36
+ const picked: Array<{ data: string; mediaType: string }> = [];
37
+ let total = 0;
38
+ for (const a of attachments) {
39
+ if (!a.imageData) continue;
40
+ if (picked.length >= INLINE_IMAGE_LIMITS.maxImages) break;
41
+ if (a.imageData.data.length > INLINE_IMAGE_LIMITS.maxBase64PerImage) continue;
42
+ if (total + a.imageData.data.length > INLINE_IMAGE_LIMITS.maxBase64Total) continue;
43
+ total += a.imageData.data.length;
44
+ picked.push(a.imageData);
45
+ }
46
+ return picked;
47
+ }
@@ -0,0 +1,133 @@
1
+ import { MAX_IMAGE_DIMENSION, fitWithin } from "../../shared/image-limits";
2
+ import { isAnimatedImage } from "./image-animation";
3
+
4
+ /**
5
+ * Downscaling of attachments before they are sent.
6
+ *
7
+ * An image is billed by area, so a screenshot straight off a high-resolution display costs
8
+ * several thousand tokens on every turn for the rest of the session's life — and past the
9
+ * API's ceiling it is refused outright, which fails not just that turn but every later one,
10
+ * since the transcript is replayed in full each time.
11
+ *
12
+ * Done in the browser because that is where the image already exists as pixels: the decoder
13
+ * scales it on the way in, and the smaller file is what gets uploaded, previewed, embedded and
14
+ * stored, so nothing downstream ever sees the oversized original.
15
+ */
16
+
17
+ /** Longest side an attachment is reduced to. Below the API ceiling, still legible for text. */
18
+ export const ATTACHMENT_MAX_DIMENSION = 1600;
19
+
20
+ /** Media types the chat socket accepts as an inline payload. */
21
+ const INLINE_MEDIA_TYPES = new Set(["image/png", "image/jpeg", "image/gif", "image/webp"]);
22
+
23
+ export type ResizeKind =
24
+ /** Re-encoded smaller. Safe to send inline: dimensions and type are both known good. */
25
+ | "scaled"
26
+ /** Already small enough and of a type the socket takes. Safe to send inline unchanged. */
27
+ | "inlineable"
28
+ /** Could not be measured or re-encoded. Must go by path — see the note on `downscaleImage`. */
29
+ | "asis";
30
+
31
+ export interface ResizeOutcome {
32
+ kind: ResizeKind;
33
+ file: File;
34
+ /** Original dimensions, when they could be read. */
35
+ from?: { width: number; height: number };
36
+ /** Dimensions after scaling, when a scale happened. */
37
+ to?: { width: number; height: number };
38
+ }
39
+
40
+ /** Canvas encodes to a handful of types; anything else round-trips as PNG. */
41
+ export function encodeType(type: string): string {
42
+ return type === "image/jpeg" || type === "image/webp" ? type : "image/png";
43
+ }
44
+
45
+ /**
46
+ * Return a copy of `file` scaled to fit `max`, and say whether the result may be sent inline.
47
+ *
48
+ * Never throws: a browser without `createImageBitmap`, an image it cannot decode (HEIC on
49
+ * Android, AVIF, a corrupt EXIF header), or a canvas that will not encode all resolve to
50
+ * `kind: "asis"` with the original file.
51
+ *
52
+ * That distinction is the point. Sending an unmeasured original inline is worse than not
53
+ * inlining at all: an oversized payload is refused by the API, and the refusal is not confined
54
+ * to the turn — the transcript replays it, so every later turn fails too, and the retry path
55
+ * pushes the same bytes again. A caller that cannot scale an image must fall back to passing
56
+ * its path, which is what the product did before inlining existed and still works.
57
+ */
58
+ export async function downscaleImage(
59
+ file: File,
60
+ max: number = ATTACHMENT_MAX_DIMENSION,
61
+ ): Promise<ResizeOutcome> {
62
+ const asis: ResizeOutcome = { kind: "asis", file };
63
+ if (!file.type.startsWith("image/") || file.type === "image/svg+xml") return asis;
64
+ if (typeof createImageBitmap !== "function" || typeof document === "undefined") return asis;
65
+
66
+ let probe: ImageBitmap;
67
+ try {
68
+ probe = await createImageBitmap(file);
69
+ } catch {
70
+ return asis;
71
+ }
72
+
73
+ const from = { width: probe.width, height: probe.height };
74
+ // `fitWithin` treats its bound as an exclusive ceiling, which is right for the API's limit
75
+ // but would re-encode an image measuring exactly the attachment target for one pixel.
76
+ const to = fitWithin(from.width, from.height, max + 1);
77
+
78
+ // A canvas keeps one frame, so scaling an animation throws the animation away. Send it at
79
+ // its own size when the API will still take it, and by path when it will not — losing the
80
+ // motion is not a trade worth making silently for a picture someone chose to send moving.
81
+ if (to && (await isAnimatedImage(file))) {
82
+ probe.close?.();
83
+ return Math.max(from.width, from.height) < MAX_IMAGE_DIMENSION && INLINE_MEDIA_TYPES.has(file.type)
84
+ ? { kind: "inlineable", file, from }
85
+ : { kind: "asis", file, from };
86
+ }
87
+
88
+ if (!to) {
89
+ probe.close?.();
90
+ // Already small enough — inline it only if the socket takes this type as-is.
91
+ return INLINE_MEDIA_TYPES.has(file.type)
92
+ ? { kind: "inlineable", file, from }
93
+ : { kind: "asis", file, from };
94
+ }
95
+
96
+ let bitmap = probe;
97
+ try {
98
+ // Let the decoder do the scaling where it can: a full-size bitmap of a phone photo is
99
+ // tens of megabytes of RGBA held on the main thread purely to be thrown away.
100
+ try {
101
+ bitmap = await createImageBitmap(file, {
102
+ resizeWidth: to.width,
103
+ resizeHeight: to.height,
104
+ resizeQuality: "high",
105
+ });
106
+ probe.close?.();
107
+ } catch {
108
+ bitmap = probe;
109
+ }
110
+
111
+ const canvas = document.createElement("canvas");
112
+ canvas.width = to.width;
113
+ canvas.height = to.height;
114
+ const ctx = canvas.getContext("2d");
115
+ if (!ctx) return { kind: "asis", file, from };
116
+ ctx.imageSmoothingEnabled = true;
117
+ ctx.imageSmoothingQuality = "high";
118
+ ctx.drawImage(bitmap, 0, 0, to.width, to.height);
119
+
120
+ const type = encodeType(file.type);
121
+ const blob = await new Promise<Blob | null>((res) => canvas.toBlob(res, type, 0.92));
122
+ // Some encoders answer with an empty blob rather than null on failure.
123
+ if (!blob || blob.size === 0) return { kind: "asis", file, from };
124
+
125
+ const name = type === file.type ? file.name : file.name.replace(/\.[^.]+$/, "") + ".png";
126
+ return { kind: "scaled", file: new File([blob], name, { type }), from, to };
127
+ } catch {
128
+ return { kind: "asis", file, from };
129
+ } finally {
130
+ bitmap.close?.();
131
+ }
132
+ }
133
+
@@ -1 +0,0 @@
1
- import"./vendor-markdown-CKTlmXbz.js";import"./vendor-ui-CXJtBULr.js";import{i as e,n as t}from"./api-client-qRWu6_s5.js";export{t as api,e as projectUrl};
@@ -1 +0,0 @@
1
- import"./vendor-markdown-CKTlmXbz.js";import"./vendor-ui-CXJtBULr.js";import"./api-client-qRWu6_s5.js";import{v as e}from"./api-settings-CPg4yGvS.js";export{e as updateDeviceName};