zidane 9.1.1 → 9.1.3
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.
- package/dist/{acp-Di9WvMDF.js → acp-CeCavNlg.js} +7 -7
- package/dist/{acp-Di9WvMDF.js.map → acp-CeCavNlg.js.map} +1 -1
- package/dist/acp-cli.js +5 -5
- package/dist/acp.d.ts +2 -2
- package/dist/acp.js +1 -1
- package/dist/{agent-DJhpTS-B.js → agent-Dh_XZ7fj.js} +74 -19
- package/dist/agent-Dh_XZ7fj.js.map +1 -0
- package/dist/agent.d.ts +1 -1
- package/dist/agent.js +1 -1
- package/dist/{auth-store-port-DFgf22oo.js → auth-store-port-BKpjlJ8a.js} +2 -2
- package/dist/{auth-store-port-DFgf22oo.js.map → auth-store-port-BKpjlJ8a.js.map} +1 -1
- package/dist/{auto-update-restart-BFB7Ek87.js → auto-update-restart-CQJtndMG.js} +277 -41
- package/dist/auto-update-restart-CQJtndMG.js.map +1 -0
- package/dist/{browser-BcoCCB_n.js → browser-BkdeKnxO.js} +56 -2
- package/dist/browser-BkdeKnxO.js.map +1 -0
- package/dist/{browser-entry-ypi8CyE-.d.ts → browser-entry-BCwruqNa.d.ts} +10 -10
- package/dist/{browser-entry-ypi8CyE-.d.ts.map → browser-entry-BCwruqNa.d.ts.map} +1 -1
- package/dist/channels.d.ts +5 -5
- package/dist/chat/browser.d.ts +4 -4
- package/dist/chat/browser.js +6 -6
- package/dist/chat/pure.d.ts +5 -5
- package/dist/chat/pure.js +8 -8
- package/dist/chat.d.ts +5 -5
- package/dist/chat.js +55 -55
- package/dist/chat.js.map +1 -1
- package/dist/{cli-shared-CabruH8Z.js → cli-shared-DeRHgYvl.js} +4 -4
- package/dist/{cli-shared-CabruH8Z.js.map → cli-shared-DeRHgYvl.js.map} +1 -1
- package/dist/cli-style-DBEm6CyT.js +105 -0
- package/dist/cli-style-DBEm6CyT.js.map +1 -0
- package/dist/{client-core-CIixwznM.d.ts → client-core-C_4m_oL6.d.ts} +4 -4
- package/dist/{client-core-CIixwznM.d.ts.map → client-core-C_4m_oL6.d.ts.map} +1 -1
- package/dist/{client-CCaIXWue.d.ts → client-ygTASGis.d.ts} +2 -2
- package/dist/{client-CCaIXWue.d.ts.map → client-ygTASGis.d.ts.map} +1 -1
- package/dist/codemode-worker.js +8 -5
- package/dist/codemode-worker.js.map +1 -1
- package/dist/codemode.d.ts +16 -0
- package/dist/codemode.d.ts.map +1 -1
- package/dist/codemode.js +2 -2
- package/dist/{connection-loop-QmWL-fJf.d.ts → connection-loop-D_pRONCr.d.ts} +4 -4
- package/dist/{connection-loop-QmWL-fJf.d.ts.map → connection-loop-D_pRONCr.d.ts.map} +1 -1
- package/dist/contexts/daytona.d.ts +3 -3
- package/dist/contexts/docker.d.ts +1 -1
- package/dist/contexts/e2b.d.ts +2 -2
- package/dist/contexts/sandbox.d.ts +1 -1
- package/dist/{contexts-C72b0mMa.js → contexts-DLZTSRHU.js} +17 -106
- package/dist/contexts-DLZTSRHU.js.map +1 -0
- package/dist/contexts.d.ts +4 -4
- package/dist/contexts.js +2 -2
- package/dist/{credentials-wwETW8rI.js → credentials-Bqg-qNBM.js} +2 -2
- package/dist/{credentials-wwETW8rI.js.map → credentials-Bqg-qNBM.js.map} +1 -1
- package/dist/{cwd-picker-CcekODCt.js → cwd-picker-BsHA6HKv.js} +4 -4
- package/dist/{cwd-picker-CcekODCt.js.map → cwd-picker-BsHA6HKv.js.map} +1 -1
- package/dist/daemon-cli.js +4 -3
- package/dist/daemon-cli.js.map +1 -1
- package/dist/{decisions-CXmK0nz9.js → decisions-hsw5XS2g.js} +3 -1
- package/dist/decisions-hsw5XS2g.js.map +1 -0
- package/dist/{discovery-DycXFxdA.js → discovery-CX7nbMCn.js} +4 -4
- package/dist/{discovery-DycXFxdA.js.map → discovery-CX7nbMCn.js.map} +1 -1
- package/dist/durable/sqlite.d.ts +2 -2
- package/dist/durable.d.ts +1 -1
- package/dist/{engine-VQ86XGdG.js → engine-CxBGgU94.js} +6 -6
- package/dist/{engine-VQ86XGdG.js.map → engine-CxBGgU94.js.map} +1 -1
- package/dist/{eval-Bod0I1W_.js → eval-CfGUDAkN.js} +3 -3
- package/dist/{eval-Bod0I1W_.js.map → eval-CfGUDAkN.js.map} +1 -1
- package/dist/eval.d.ts +1 -1
- package/dist/eval.js +1 -1
- package/dist/{executor-C7RQrkEq.js → executor-j_LFRBwS.js} +4 -4
- package/dist/{executor-C7RQrkEq.js.map → executor-j_LFRBwS.js.map} +1 -1
- package/dist/{extension-mark-BqKdEZwF.js → extension-mark-_rhkDWL5.js} +9 -6
- package/dist/extension-mark-_rhkDWL5.js.map +1 -0
- package/dist/extensions/testing.d.ts +1 -1
- package/dist/extensions/testing.js +2 -2
- package/dist/{extensions-BCx4QuGB.js → extensions-ADlhBQ_1.js} +8 -8
- package/dist/{extensions-BCx4QuGB.js.map → extensions-ADlhBQ_1.js.map} +1 -1
- package/dist/{extensions-client-D8tEAcMw.d.ts → extensions-client-D4Q2XRKV.d.ts} +31 -5
- package/dist/extensions-client-D4Q2XRKV.d.ts.map +1 -0
- package/dist/extensions.d.ts +1 -1
- package/dist/extensions.js +6 -6
- package/dist/{fold-rules-DvLK8pbf.d.ts → fold-rules-1DpDwG9h.d.ts} +2 -2
- package/dist/{fold-rules-DvLK8pbf.d.ts.map → fold-rules-1DpDwG9h.d.ts.map} +1 -1
- package/dist/{google-Crva32sk.js → google-B-Dhmzzf.js} +2 -2
- package/dist/{google-Crva32sk.js.map → google-B-Dhmzzf.js.map} +1 -1
- package/dist/{headless-CCm-jLLT.js → headless-CQm19BL0.js} +4 -4
- package/dist/{headless-CCm-jLLT.js.map → headless-CQm19BL0.js.map} +1 -1
- package/dist/headless.d.ts +1 -1
- package/dist/headless.js +1 -1
- package/dist/history-worker.js +1 -1
- package/dist/{host-wO_6GW0y.js → host-C61ntFBC.js} +276 -103
- package/dist/host-C61ntFBC.js.map +1 -0
- package/dist/{host-BHMs9jsN.js → host-DEoEzQal.js} +13 -4
- package/dist/host-DEoEzQal.js.map +1 -0
- package/dist/{host-scoped-settings-CrbcqOkP.js → host-scoped-settings-WBYaCork.js} +2 -2
- package/dist/{host-scoped-settings-CrbcqOkP.js.map → host-scoped-settings-WBYaCork.js.map} +1 -1
- package/dist/{host-signals-Jsjd_-4g.js → host-signals-Cb2TlGtN.js} +5 -5
- package/dist/{host-signals-Jsjd_-4g.js.map → host-signals-Cb2TlGtN.js.map} +1 -1
- package/dist/{host-version-CNAr9pov.js → host-version-BIx4CuBM.js} +2 -2
- package/dist/{host-version-CNAr9pov.js.map → host-version-BIx4CuBM.js.map} +1 -1
- package/dist/{index-C6nnKu32.d.ts → index-B0PLo9jn.d.ts} +4 -4
- package/dist/{index-C6nnKu32.d.ts.map → index-B0PLo9jn.d.ts.map} +1 -1
- package/dist/{index-Djnc8Peh.d.ts → index-De4x-s76.d.ts} +14 -14
- package/dist/{index-Djnc8Peh.d.ts.map → index-De4x-s76.d.ts.map} +1 -1
- package/dist/{index-CGbOWa7y.d.ts → index-WlE93Q6d.d.ts} +411 -3
- package/dist/index-WlE93Q6d.d.ts.map +1 -0
- package/dist/{index-CCf_WeTQ.d.ts → index-f-XWIoYo.d.ts} +2 -2
- package/dist/{index-CCf_WeTQ.d.ts.map → index-f-XWIoYo.d.ts.map} +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.js +17 -17
- package/dist/ipc/browser-types.d.ts +304 -7
- package/dist/ipc/browser-types.d.ts.map +1 -1
- package/dist/ipc/browser.d.ts +4 -4
- package/dist/ipc/browser.js +2 -2
- package/dist/ipc/remote.d.ts +6 -6
- package/dist/ipc/remote.js +3 -3
- package/dist/{ipc-BzWhIybr.js → ipc-DiH_P-wr.js} +4 -4
- package/dist/{ipc-BzWhIybr.js.map → ipc-DiH_P-wr.js.map} +1 -1
- package/dist/ipc.d.ts +10 -10
- package/dist/ipc.js +8 -8
- package/dist/{json-Dj-YATkZ.js → json-BjClr43H.js} +2 -20
- package/dist/json-BjClr43H.js.map +1 -0
- package/dist/{links-CJG_rFvf.js → links-BbC_lOnn.js} +9 -9
- package/dist/{links-CJG_rFvf.js.map → links-BbC_lOnn.js.map} +1 -1
- package/dist/{loaded-entry-DTURJo_R.js → loaded-entry-C0vkCVNQ.js} +2 -2
- package/dist/{loaded-entry-DTURJo_R.js.map → loaded-entry-C0vkCVNQ.js.map} +1 -1
- package/dist/mcp.d.ts +1 -1
- package/dist/{media-type-BtA0cbfI.d.ts → media-type-ZSmAGHvg.d.ts} +188 -7
- package/dist/media-type-ZSmAGHvg.d.ts.map +1 -0
- package/dist/{memory-DuVGrzbl.js → memory-C3w8nO8f.js} +132 -31
- package/dist/memory-C3w8nO8f.js.map +1 -0
- package/dist/model-test-CAtJ76kM.js.map +1 -1
- package/dist/{move-session-kylExJ5H.js → move-session-D7ILECs-.js} +4 -4
- package/dist/{move-session-kylExJ5H.js.map → move-session-D7ILECs-.js.map} +1 -1
- package/dist/{nested-call-record-DlzPeTB7.js → nested-call-record-OayszZBQ.js} +4 -3
- package/dist/nested-call-record-OayszZBQ.js.map +1 -0
- package/dist/output/stream-json.d.ts +1 -1
- package/dist/output/terminal.d.ts +1 -1
- package/dist/{path-display-COVV71Yu.js → path-display-DRAEpKOU.js} +3 -3
- package/dist/{path-display-COVV71Yu.js.map → path-display-DRAEpKOU.js.map} +1 -1
- package/dist/plugins.d.ts +1 -1
- package/dist/{prelude-CVKoUzV8.js → prelude-BwiSR1uA.js} +16 -5
- package/dist/prelude-BwiSR1uA.js.map +1 -0
- package/dist/{presets-CBt6rFfS.js → presets-CMY43nUP.js} +3 -3
- package/dist/{presets-CBt6rFfS.js.map → presets-CMY43nUP.js.map} +1 -1
- package/dist/presets.d.ts +1 -1
- package/dist/presets.js +1 -1
- package/dist/{protocol-CEVqBO-q.d.ts → protocol-C2lqKuMd.d.ts} +50 -7
- package/dist/protocol-C2lqKuMd.d.ts.map +1 -0
- package/dist/protocol-DOGyHgLQ.js.map +1 -1
- package/dist/protocol-NSllElLw.js.map +1 -1
- package/dist/providers/anthropic.d.ts +1 -1
- package/dist/providers/arcee.d.ts +1 -1
- package/dist/providers/baseten.d.ts +1 -1
- package/dist/providers/cerebras.d.ts +1 -1
- package/dist/providers/google.d.ts +1 -1
- package/dist/providers/google.js +1 -1
- package/dist/providers/local.d.ts +1 -1
- package/dist/providers/neuralwatt.d.ts +1 -1
- package/dist/providers/openai-compat.d.ts +1 -1
- package/dist/providers/openai.d.ts +1 -1
- package/dist/providers/openrouter.d.ts +1 -1
- package/dist/providers/xai.d.ts +1 -1
- package/dist/{providers-Z0TaBp1O.js → providers-CpXV_uLE.js} +5 -5
- package/dist/providers-CpXV_uLE.js.map +1 -0
- package/dist/providers.d.ts +1 -1
- package/dist/providers.js +1 -1
- package/dist/{readonly-db-D7Z-k0pQ.js → readonly-db-DrbT8tX6.js} +2 -2
- package/dist/{readonly-db-D7Z-k0pQ.js.map → readonly-db-DrbT8tX6.js.map} +1 -1
- package/dist/{registry-BKjeBnoy.js → registry-CJHvmvaP.js} +2 -2
- package/dist/{registry-BKjeBnoy.js.map → registry-CJHvmvaP.js.map} +1 -1
- package/dist/{registry-B6Ww76iW.js → registry-CN6JlZKj.js} +2 -2
- package/dist/{registry-B6Ww76iW.js.map → registry-CN6JlZKj.js.map} +1 -1
- package/dist/{registry-B9INJwJR.js → registry-CnnKaY9s.js} +324 -39
- package/dist/registry-CnnKaY9s.js.map +1 -0
- package/dist/{remote-hosts-BMWoHCWO.js → remote-hosts-DoO9CJUQ.js} +4 -4
- package/dist/{remote-hosts-BMWoHCWO.js.map → remote-hosts-DoO9CJUQ.js.map} +1 -1
- package/dist/{repo-url-D4Dr8NfZ.js → repo-url-DLjjuVk_.js} +169 -2
- package/dist/repo-url-DLjjuVk_.js.map +1 -0
- package/dist/restate.d.ts +2 -2
- package/dist/{sandbox-BwiPGKF7.d.ts → sandbox-B4OW6oNx.d.ts} +2 -2
- package/dist/{sandbox-BwiPGKF7.d.ts.map → sandbox-B4OW6oNx.d.ts.map} +1 -1
- package/dist/script-progress-CrZ507Qq.js +900 -0
- package/dist/script-progress-CrZ507Qq.js.map +1 -0
- package/dist/session/sqlite.d.ts +1 -1
- package/dist/session.d.ts +1 -1
- package/dist/{setting-BQBSyUq0.js → setting-D_FpKFMw.js} +6 -6
- package/dist/{setting-BQBSyUq0.js.map → setting-D_FpKFMw.js.map} +1 -1
- package/dist/{settings-catalog-4IU2i_jG.js → settings-catalog-DEZlXP51.js} +14 -2
- package/dist/settings-catalog-DEZlXP51.js.map +1 -0
- package/dist/{settings-keys-iI_Y-7MC.js → settings-keys-CW2UgHgb.js} +3 -3
- package/dist/{settings-keys-iI_Y-7MC.js.map → settings-keys-CW2UgHgb.js.map} +1 -1
- package/dist/{skills-CFXRItJ6.js → skills-CEbosUlM.js} +2 -2
- package/dist/{skills-CFXRItJ6.js.map → skills-CEbosUlM.js.map} +1 -1
- package/dist/skills.d.ts +1 -1
- package/dist/skills.js +1 -1
- package/dist/{source-Bl1Z501r.js → source-3ZnEPOSa.js} +3 -2
- package/dist/source-3ZnEPOSa.js.map +1 -0
- package/dist/{sqlite-runtime-BZ2L4RaG.d.ts → sqlite-runtime-CS_LBaAN.d.ts} +2 -2
- package/dist/sqlite-runtime-CS_LBaAN.d.ts.map +1 -0
- package/dist/{src-BY_ND2xn.js → src-BmTXDta8.js} +2 -2
- package/dist/{src-BY_ND2xn.js.map → src-BmTXDta8.js.map} +1 -1
- package/dist/{store-C6gI7FfZ.js → store-ByCDaKgJ.js} +14 -3
- package/dist/store-ByCDaKgJ.js.map +1 -0
- package/dist/{system-freeze-m5o1sGIM.js → system-freeze-XgDPIwQS.js} +3 -3
- package/dist/{system-freeze-m5o1sGIM.js.map → system-freeze-XgDPIwQS.js.map} +1 -1
- package/dist/{todo-edits-CbukbjyV.js → todo-edits-Dyj32ds6.js} +4 -3
- package/dist/todo-edits-Dyj32ds6.js.map +1 -0
- package/dist/tools/fetch-url.d.ts +1 -1
- package/dist/tools/web-search.d.ts +1 -1
- package/dist/{tools-CVTGhggj.js → tools-BsrGQ8K4.js} +2 -2
- package/dist/{tools-CVTGhggj.js.map → tools-BsrGQ8K4.js.map} +1 -1
- package/dist/tools.d.ts +1 -1
- package/dist/tools.js +3 -3
- package/dist/{transcript-anchors-CiSi_UBn.js → transcript-anchors-DMjvyUjk.js} +3 -3
- package/dist/{transcript-anchors-CiSi_UBn.js.map → transcript-anchors-DMjvyUjk.js.map} +1 -1
- package/dist/{transcript-reconcile-jbSBjLq2.js → transcript-reconcile-DpQO85wl.js} +3 -3
- package/dist/{transcript-reconcile-jbSBjLq2.js.map → transcript-reconcile-DpQO85wl.js.map} +1 -1
- package/dist/tui.d.ts +9 -9
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +289 -38
- package/dist/tui.js.map +1 -1
- package/dist/{types-bDQagoiL.d.ts → types-2HrgolQz.d.ts} +20 -8
- package/dist/types-2HrgolQz.d.ts.map +1 -0
- package/dist/types-4q1bFG53.js +122 -0
- package/dist/types-4q1bFG53.js.map +1 -0
- package/dist/{types-DnRd9_cA.d.ts → types-SXqk6hLD.d.ts} +3 -3
- package/dist/{types-DnRd9_cA.d.ts.map → types-SXqk6hLD.d.ts.map} +1 -1
- package/dist/types-myxheQkw.js.map +1 -1
- package/dist/types.d.ts +3 -3
- package/dist/{usage-summary-BfcXjiSM.js → usage-summary-BM7B3JdI.js} +2 -2
- package/dist/{usage-summary-BfcXjiSM.js.map → usage-summary-BM7B3JdI.js.map} +1 -1
- package/dist/{version-DqqqvHDP.js → version-szdW1Od9.js} +2 -2
- package/dist/{version-DqqqvHDP.js.map → version-szdW1Od9.js.map} +1 -1
- package/dist/{wait-task-BX4NcOOm.js → wait-task-BiI5UaZQ.js} +13 -3
- package/dist/wait-task-BiI5UaZQ.js.map +1 -0
- package/dist/{wire-CLm2rMK0.js → wire-C3l9jl9x.js} +2 -2
- package/dist/{wire-CLm2rMK0.js.map → wire-C3l9jl9x.js.map} +1 -1
- package/dist/{write-file-0E6TUJ9A.js → write-file-Dquu7MzB.js} +5 -3
- package/dist/write-file-Dquu7MzB.js.map +1 -0
- package/dist/{ws-DfGGYQ4W.js → ws-CEHi0CiB.js} +4 -4
- package/dist/{ws-DfGGYQ4W.js.map → ws-CEHi0CiB.js.map} +1 -1
- package/dist/{ws-client-CFMbhsNq.js → ws-client-t8XNWxcq.js} +2 -2
- package/dist/{ws-client-CFMbhsNq.js.map → ws-client-t8XNWxcq.js.map} +1 -1
- package/docs/CHAT.md +55 -0
- package/docs/CODEMODE.md +37 -0
- package/docs/EXTENSIONS.md +8 -6
- package/docs/RELEASE-NOTES-NEXT.md +48 -1
- package/docs/RELEASE.md +9 -1
- package/package.json +2 -3
- package/dist/agent-DJhpTS-B.js.map +0 -1
- package/dist/auto-update-restart-BFB7Ek87.js.map +0 -1
- package/dist/browser-BcoCCB_n.js.map +0 -1
- package/dist/contexts-C72b0mMa.js.map +0 -1
- package/dist/decisions-CXmK0nz9.js.map +0 -1
- package/dist/extension-mark-BqKdEZwF.js.map +0 -1
- package/dist/extensions-client-D8tEAcMw.d.ts.map +0 -1
- package/dist/host-BHMs9jsN.js.map +0 -1
- package/dist/host-wO_6GW0y.js.map +0 -1
- package/dist/index-CGbOWa7y.d.ts.map +0 -1
- package/dist/json-Dj-YATkZ.js.map +0 -1
- package/dist/media-type-BtA0cbfI.d.ts.map +0 -1
- package/dist/memory-DuVGrzbl.js.map +0 -1
- package/dist/nested-call-events-BYk8XvGX.js +0 -182
- package/dist/nested-call-events-BYk8XvGX.js.map +0 -1
- package/dist/nested-call-record-DlzPeTB7.js.map +0 -1
- package/dist/prelude-CVKoUzV8.js.map +0 -1
- package/dist/protocol-CEVqBO-q.d.ts.map +0 -1
- package/dist/providers-Z0TaBp1O.js.map +0 -1
- package/dist/registry-B9INJwJR.js.map +0 -1
- package/dist/repo-url-D4Dr8NfZ.js.map +0 -1
- package/dist/settings-catalog-4IU2i_jG.js.map +0 -1
- package/dist/source-Bl1Z501r.js.map +0 -1
- package/dist/sqlite-runtime-BZ2L4RaG.d.ts.map +0 -1
- package/dist/store-C6gI7FfZ.js.map +0 -1
- package/dist/todo-edits-CbukbjyV.js.map +0 -1
- package/dist/types-DTMEhKJO.js +0 -14
- package/dist/types-DTMEhKJO.js.map +0 -1
- package/dist/types-bDQagoiL.d.ts.map +0 -1
- package/dist/wait-task-BX4NcOOm.js.map +0 -1
- package/dist/write-file-0E6TUJ9A.js.map +0 -1
- package/scripts/eval.ts +0 -179
|
@@ -0,0 +1,900 @@
|
|
|
1
|
+
import { n as previewNestedOutput } from "./nested-call-record-OayszZBQ.js";
|
|
2
|
+
//#region src/chat/command-notes.ts
|
|
3
|
+
/** The persisted invocation header block: `` `❯ /commit args` ``. */
|
|
4
|
+
function commandHeaderBlock(invocation) {
|
|
5
|
+
return `\`❯ ${invocation}\``;
|
|
6
|
+
}
|
|
7
|
+
/** `/name args` from a persisted header block, or null when the text is not one. */
|
|
8
|
+
function parseCommandHeader(text) {
|
|
9
|
+
const match = /^`❯ (\/[\s\S]+)`$/.exec(text.trim());
|
|
10
|
+
return match ? match[1] : null;
|
|
11
|
+
}
|
|
12
|
+
const PREFIX_SEPARATOR = /^\s*(?:[:·—-]\s*)?/;
|
|
13
|
+
/**
|
|
14
|
+
* The receipt text for one note. Older displays repeat the command
|
|
15
|
+
* (`/commit: 83dfea7`, `/review — 3 reviewers, fixes applied`); the prompt
|
|
16
|
+
* bubble above already names it, so the prefix goes, and a leftover ` — `
|
|
17
|
+
* becomes a comma. A note without a display shows its first line.
|
|
18
|
+
*/
|
|
19
|
+
function commandNoteText(display, text, invocation) {
|
|
20
|
+
let line = (display ?? text.split("\n").find((l) => l.trim()) ?? "").trim();
|
|
21
|
+
const prefix = [invocation, invocation?.split(/\s/, 1)[0]].filter((p) => Boolean(p)).find((p) => line.startsWith(p)) ?? /^\/[\w.:-]+/.exec(line)?.[0];
|
|
22
|
+
if (prefix) {
|
|
23
|
+
const rest = line.slice(prefix.length).replace(PREFIX_SEPARATOR, "");
|
|
24
|
+
if (rest) line = /^[0-9a-f]{7,40}$/.test(rest) ? `committed ${rest}` : rest;
|
|
25
|
+
}
|
|
26
|
+
line = line.replace(/\s+—\s+/g, ", ");
|
|
27
|
+
return line.length > 160 ? `${line.slice(0, 159)}…` : line;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The `display` a context note persists with: the command's marker, its
|
|
31
|
+
* first line when it gave none, or `''` for a model-only note
|
|
32
|
+
* (`display: false`), which shows nothing.
|
|
33
|
+
*/
|
|
34
|
+
function noteDisplay(display, text) {
|
|
35
|
+
return display === false ? "" : display ?? commandNoteText(void 0, text);
|
|
36
|
+
}
|
|
37
|
+
/** A command step label: the display as given, a leftover ` — ` turned into a comma. */
|
|
38
|
+
function commandStepLabel(display) {
|
|
39
|
+
return display.replace(/\s+—\s+/g, ", ");
|
|
40
|
+
}
|
|
41
|
+
const merged = /* @__PURE__ */ new WeakMap();
|
|
42
|
+
function isTopPrompt(event) {
|
|
43
|
+
return event.kind === "user-prompt" && !event.childId && (event.depth ?? 0) === 0;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* One receipt line per exchange: every `command-note` in an exchange moves
|
|
47
|
+
* to its end and joins into a single event (`committed 83dfea7, pushed to
|
|
48
|
+
* origin/main`). Returns `events` itself when there is nothing to merge;
|
|
49
|
+
* the merged event keeps its identity while its notes do not change, so
|
|
50
|
+
* memoised rows stay put.
|
|
51
|
+
*
|
|
52
|
+
* @param events - Transcript events in display order.
|
|
53
|
+
*/
|
|
54
|
+
function gatherCommandNotes(events) {
|
|
55
|
+
if (!events.some((e) => e.kind === "command-note")) return events;
|
|
56
|
+
const out = [];
|
|
57
|
+
let notes = [];
|
|
58
|
+
const flush = () => {
|
|
59
|
+
if (notes.length === 0) return;
|
|
60
|
+
const first = notes[0];
|
|
61
|
+
const key = notes.map((n) => n.text).join("\0");
|
|
62
|
+
let event = first;
|
|
63
|
+
if (notes.length > 1) {
|
|
64
|
+
const cached = merged.get(first);
|
|
65
|
+
event = cached?.key === key ? cached.event : {
|
|
66
|
+
...first,
|
|
67
|
+
text: notes.map((n) => n.text).join(", ")
|
|
68
|
+
};
|
|
69
|
+
merged.set(first, {
|
|
70
|
+
key,
|
|
71
|
+
event
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
let at = out.length;
|
|
75
|
+
while (at > 0 && out[at - 1].kind === "separator") at--;
|
|
76
|
+
out.splice(at, 0, event);
|
|
77
|
+
notes = [];
|
|
78
|
+
};
|
|
79
|
+
for (const event of events) {
|
|
80
|
+
if (isTopPrompt(event)) flush();
|
|
81
|
+
if (event.kind === "command-note" && !event.childId) {
|
|
82
|
+
notes.push(event);
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
out.push(event);
|
|
86
|
+
}
|
|
87
|
+
flush();
|
|
88
|
+
return out.length === events.length && out.every((e, i) => e === events[i]) ? events : out;
|
|
89
|
+
}
|
|
90
|
+
//#endregion
|
|
91
|
+
//#region src/chat/nested-call-events.ts
|
|
92
|
+
/** `name(json args)`, as `store.ts`' `toolCallPreview` writes it (not imported: `store.ts` imports this module). */
|
|
93
|
+
function callPreview(name, input) {
|
|
94
|
+
const args = JSON.stringify(input);
|
|
95
|
+
return args && args !== "{}" ? `${name}(${args})` : name;
|
|
96
|
+
}
|
|
97
|
+
function tagFields(tag) {
|
|
98
|
+
return {
|
|
99
|
+
...tag?.turnId ? { turnId: tag.turnId } : {},
|
|
100
|
+
...tag?.childId !== void 0 ? { childId: tag.childId } : {},
|
|
101
|
+
...tag?.depth !== void 0 ? { depth: tag.depth } : {}
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* The `tool` row for a nested call as it starts.
|
|
106
|
+
*
|
|
107
|
+
* @param call - The nested call.
|
|
108
|
+
* @param call.callId - Its call id.
|
|
109
|
+
* @param call.name - Tool it called.
|
|
110
|
+
* @param call.input - Arguments it passed.
|
|
111
|
+
* @param call.parentToolCallId - Id of the calling tool, which the row groups under.
|
|
112
|
+
* @param call.runsNestedAgent - The called tool runs a subagent.
|
|
113
|
+
* @param call.startedAt - When the call started (epoch ms, the host's clock), live only.
|
|
114
|
+
* @param tag - Turn, subagent and depth to stamp on the event.
|
|
115
|
+
*/
|
|
116
|
+
function nestedToolEvent(call, tag) {
|
|
117
|
+
return {
|
|
118
|
+
kind: "tool",
|
|
119
|
+
text: callPreview(call.name, call.input),
|
|
120
|
+
tool: call.name,
|
|
121
|
+
callId: call.callId,
|
|
122
|
+
input: call.input,
|
|
123
|
+
parentToolCallId: call.parentToolCallId,
|
|
124
|
+
...call.runsNestedAgent ? { runsNestedAgent: true } : {},
|
|
125
|
+
...call.startedAt !== void 0 ? { startedAt: call.startedAt } : {},
|
|
126
|
+
...tagFields(tag)
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* The `tool-result` row for a nested call as it ends; the output is cut to a preview.
|
|
131
|
+
*
|
|
132
|
+
* @param result - The nested call's result.
|
|
133
|
+
* @param result.callId - Its call id.
|
|
134
|
+
* @param result.name - Tool it called.
|
|
135
|
+
* @param result.output - Full output; the row keeps a preview.
|
|
136
|
+
* @param result.isError - The call failed.
|
|
137
|
+
* @param result.parentToolCallId - Id of the calling tool, which the row groups under.
|
|
138
|
+
* @param result.runsNestedAgent - The called tool runs a subagent.
|
|
139
|
+
* @param result.durationMs - How long the call ran. `0` reads as unknown: a durable run's records carry no wall time.
|
|
140
|
+
* @param tag - Turn, subagent and depth to stamp on the event.
|
|
141
|
+
*/
|
|
142
|
+
function nestedResultEvent(result, tag) {
|
|
143
|
+
return {
|
|
144
|
+
kind: "tool-result",
|
|
145
|
+
text: previewNestedOutput(result.output).output,
|
|
146
|
+
tool: result.name,
|
|
147
|
+
callId: result.callId,
|
|
148
|
+
parentToolCallId: result.parentToolCallId,
|
|
149
|
+
...result.runsNestedAgent ? { runsNestedAgent: true } : {},
|
|
150
|
+
...result.isError ? { isError: true } : {},
|
|
151
|
+
...result.durationMs ? { durationMs: result.durationMs } : {},
|
|
152
|
+
...tagFields(tag)
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* A persisted record as the events the live run emitted for it.
|
|
157
|
+
*
|
|
158
|
+
* @param records - Nested calls stored on the calling tool's result.
|
|
159
|
+
* @param parentToolCallId - Id of the calling tool.
|
|
160
|
+
* @param tag - Turn, subagent and depth to stamp on the events.
|
|
161
|
+
*/
|
|
162
|
+
function nestedRecordEvents(records, parentToolCallId, tag) {
|
|
163
|
+
return records.flatMap((record) => [nestedToolEvent({
|
|
164
|
+
callId: record.id,
|
|
165
|
+
name: record.name,
|
|
166
|
+
input: record.input ?? {},
|
|
167
|
+
parentToolCallId,
|
|
168
|
+
runsNestedAgent: record.runsNestedAgent
|
|
169
|
+
}, tag), nestedResultEvent({
|
|
170
|
+
callId: record.id,
|
|
171
|
+
name: record.name,
|
|
172
|
+
output: record.output ?? "",
|
|
173
|
+
isError: record.status !== "ok",
|
|
174
|
+
parentToolCallId,
|
|
175
|
+
runsNestedAgent: record.runsNestedAgent,
|
|
176
|
+
durationMs: record.durationMs
|
|
177
|
+
}, tag)]);
|
|
178
|
+
}
|
|
179
|
+
//#endregion
|
|
180
|
+
//#region src/chat/ansi.ts
|
|
181
|
+
const ESC = 27;
|
|
182
|
+
/** Parser states: plain text, after ESC, in a CSI, in an OSC / DCS string, after ESC inside one. */
|
|
183
|
+
const TEXT = 0;
|
|
184
|
+
const AFTER_ESC = 1;
|
|
185
|
+
const CSI = 2;
|
|
186
|
+
const STRING = 3;
|
|
187
|
+
const STRING_ESC = 4;
|
|
188
|
+
/**
|
|
189
|
+
* Whether `text` holds anything {@link parseAnsi} changes: an escape, a carriage return, a backspace.
|
|
190
|
+
*
|
|
191
|
+
* @param text - Terminal output.
|
|
192
|
+
*/
|
|
193
|
+
function hasAnsi(text) {
|
|
194
|
+
for (let i = 0; i < text.length; i++) {
|
|
195
|
+
const code = text.charCodeAt(i);
|
|
196
|
+
if (code === ESC || code === 155 || code === 157 || code === 13 || code === 8) return true;
|
|
197
|
+
}
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
200
|
+
function sameStyle(a, b) {
|
|
201
|
+
if (a === b) return true;
|
|
202
|
+
if (!a || !b) return false;
|
|
203
|
+
return a.fg === b.fg && a.bg === b.bg && a.bold === b.bold && a.dim === b.dim && a.italic === b.italic && a.underline === b.underline && a.inverse === b.inverse;
|
|
204
|
+
}
|
|
205
|
+
function hex(n) {
|
|
206
|
+
return Math.max(0, Math.min(255, n)).toString(16).padStart(2, "0");
|
|
207
|
+
}
|
|
208
|
+
/** An extended color (`38;5;n`, `38;2;r;g;b`) read from `params` at `i` (the `5` or `2`); returns it and the index after it. */
|
|
209
|
+
function extendedColor(params, i) {
|
|
210
|
+
if (params[i] === 5) return [params[i + 1] !== void 0 ? Math.max(0, Math.min(255, params[i + 1])) : void 0, i + 2];
|
|
211
|
+
if (params[i] === 2) return [`#${hex(params[i + 1] ?? 0)}${hex(params[i + 2] ?? 0)}${hex(params[i + 3] ?? 0)}`, i + 4];
|
|
212
|
+
return [void 0, i + 1];
|
|
213
|
+
}
|
|
214
|
+
/** `style` after an SGR sequence. A style object is never changed, so spans can compare by reference. */
|
|
215
|
+
function applySgr(style, raw) {
|
|
216
|
+
const params = raw === "" ? [0] : raw.split(/[;:]/).map((p) => p === "" ? 0 : Number(p));
|
|
217
|
+
let next = { ...style };
|
|
218
|
+
for (let i = 0; i < params.length; i++) {
|
|
219
|
+
const p = params[i];
|
|
220
|
+
if (p === 0) next = {};
|
|
221
|
+
else if (p === 1) next.bold = true;
|
|
222
|
+
else if (p === 2) next.dim = true;
|
|
223
|
+
else if (p === 3) next.italic = true;
|
|
224
|
+
else if (p === 4) next.underline = true;
|
|
225
|
+
else if (p === 7) next.inverse = true;
|
|
226
|
+
else if (p === 22) {
|
|
227
|
+
delete next.bold;
|
|
228
|
+
delete next.dim;
|
|
229
|
+
} else if (p === 23) delete next.italic;
|
|
230
|
+
else if (p === 24) delete next.underline;
|
|
231
|
+
else if (p === 27) delete next.inverse;
|
|
232
|
+
else if (p >= 30 && p <= 37) next.fg = p - 30;
|
|
233
|
+
else if (p >= 90 && p <= 97) next.fg = p - 90 + 8;
|
|
234
|
+
else if (p === 39) delete next.fg;
|
|
235
|
+
else if (p >= 40 && p <= 47) next.bg = p - 40;
|
|
236
|
+
else if (p >= 100 && p <= 107) next.bg = p - 100 + 8;
|
|
237
|
+
else if (p === 49) delete next.bg;
|
|
238
|
+
else if (p === 38 || p === 48) {
|
|
239
|
+
const [color, after] = extendedColor(params, i + 1);
|
|
240
|
+
if (color !== void 0) {
|
|
241
|
+
if (p === 38) next.fg = color;
|
|
242
|
+
else next.bg = color;
|
|
243
|
+
}
|
|
244
|
+
i = after - 1;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
if (Object.keys(next).length === 0) return void 0;
|
|
248
|
+
return sameStyle(style, next) ? style : next;
|
|
249
|
+
}
|
|
250
|
+
/** Creates an incremental {@link AnsiLines} reader. The style carries across chunks and lines, as in a terminal. */
|
|
251
|
+
function createAnsiLines() {
|
|
252
|
+
let state = TEXT;
|
|
253
|
+
let params = "";
|
|
254
|
+
let style;
|
|
255
|
+
let line = [];
|
|
256
|
+
/** A `\r` arrived: the next printable starts the line over, unless `\n` follows. */
|
|
257
|
+
let pendingCr = false;
|
|
258
|
+
const append = (text) => {
|
|
259
|
+
if (pendingCr) {
|
|
260
|
+
line = [];
|
|
261
|
+
pendingCr = false;
|
|
262
|
+
}
|
|
263
|
+
const last = line[line.length - 1];
|
|
264
|
+
if (last && sameStyle(last.style, style)) {
|
|
265
|
+
last.text += text;
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
line.push(style ? {
|
|
269
|
+
text,
|
|
270
|
+
style
|
|
271
|
+
} : { text });
|
|
272
|
+
};
|
|
273
|
+
const backspace = () => {
|
|
274
|
+
const last = line[line.length - 1];
|
|
275
|
+
if (!last) return;
|
|
276
|
+
last.text = last.text.slice(0, -1);
|
|
277
|
+
if (last.text === "") line.pop();
|
|
278
|
+
};
|
|
279
|
+
return {
|
|
280
|
+
push(chunk) {
|
|
281
|
+
const done = [];
|
|
282
|
+
let i = 0;
|
|
283
|
+
while (i < chunk.length) {
|
|
284
|
+
const code = chunk.charCodeAt(i);
|
|
285
|
+
if (state === TEXT) {
|
|
286
|
+
if (code === ESC) state = AFTER_ESC;
|
|
287
|
+
else if (code === 10) {
|
|
288
|
+
done.push(line);
|
|
289
|
+
line = [];
|
|
290
|
+
pendingCr = false;
|
|
291
|
+
} else if (code === 13) pendingCr = true;
|
|
292
|
+
else if (code === 8) backspace();
|
|
293
|
+
else if (code === 155) {
|
|
294
|
+
state = CSI;
|
|
295
|
+
params = "";
|
|
296
|
+
} else if (code === 157) state = STRING;
|
|
297
|
+
else if (code === 9 || code >= 32 && !(code >= 127 && code < 160)) {
|
|
298
|
+
let end = i + 1;
|
|
299
|
+
while (end < chunk.length) {
|
|
300
|
+
const c = chunk.charCodeAt(end);
|
|
301
|
+
if (c === ESC || c === 10 || c === 13 || c === 8 || c < 32 && c !== 9 || c >= 127 && c < 160) break;
|
|
302
|
+
end++;
|
|
303
|
+
}
|
|
304
|
+
append(chunk.slice(i, end));
|
|
305
|
+
i = end;
|
|
306
|
+
continue;
|
|
307
|
+
}
|
|
308
|
+
} else if (state === AFTER_ESC) {
|
|
309
|
+
if (code === 91) {
|
|
310
|
+
state = CSI;
|
|
311
|
+
params = "";
|
|
312
|
+
} else if (code === 93 || code === 80 || code === 88 || code === 94 || code === 95) state = STRING;
|
|
313
|
+
else if (code < 32 || code > 47) state = TEXT;
|
|
314
|
+
} else if (state === CSI) {
|
|
315
|
+
if (code >= 64 && code <= 126) {
|
|
316
|
+
if (code === 109) style = applySgr(style, params);
|
|
317
|
+
state = TEXT;
|
|
318
|
+
} else if (params.length < 64) params += chunk[i];
|
|
319
|
+
} else if (state === STRING) {
|
|
320
|
+
if (code === 7 || code === 156) state = TEXT;
|
|
321
|
+
else if (code === ESC) state = STRING_ESC;
|
|
322
|
+
} else state = code === 92 ? TEXT : STRING;
|
|
323
|
+
i++;
|
|
324
|
+
}
|
|
325
|
+
return done;
|
|
326
|
+
},
|
|
327
|
+
partial: () => pendingCr ? [] : line
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* `text` as lines of styled spans. A text without a closing newline still
|
|
332
|
+
* yields its last line; an empty text yields one empty line.
|
|
333
|
+
*
|
|
334
|
+
* @param text - Terminal output.
|
|
335
|
+
*/
|
|
336
|
+
function parseAnsi(text) {
|
|
337
|
+
const reader = createAnsiLines();
|
|
338
|
+
const lines = reader.push(text);
|
|
339
|
+
lines.push(reader.partial());
|
|
340
|
+
return lines;
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* The visible text of a line.
|
|
344
|
+
*
|
|
345
|
+
* @param spans - The line's spans.
|
|
346
|
+
*/
|
|
347
|
+
function ansiLineText(spans) {
|
|
348
|
+
return spans.map((span) => span.text).join("");
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* `text` without its escapes, as a terminal would show it.
|
|
352
|
+
*
|
|
353
|
+
* @param text - Terminal output.
|
|
354
|
+
*/
|
|
355
|
+
function stripAnsi(text) {
|
|
356
|
+
if (!hasAnsi(text)) return text;
|
|
357
|
+
return parseAnsi(text).map(ansiLineText).join("\n");
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* A line cut to `max` visible characters, the last one an ellipsis when it is cut.
|
|
361
|
+
*
|
|
362
|
+
* @param spans - The line's spans.
|
|
363
|
+
* @param max - Visible characters kept.
|
|
364
|
+
*/
|
|
365
|
+
function clipAnsiLine(spans, max) {
|
|
366
|
+
if (ansiLineText(spans).length <= max) return [...spans];
|
|
367
|
+
const out = [];
|
|
368
|
+
let room = max - 1;
|
|
369
|
+
for (const span of spans) {
|
|
370
|
+
if (room <= 0) break;
|
|
371
|
+
const text = span.text.slice(0, room);
|
|
372
|
+
out.push(span.style ? {
|
|
373
|
+
text,
|
|
374
|
+
style: span.style
|
|
375
|
+
} : { text });
|
|
376
|
+
room -= text.length;
|
|
377
|
+
}
|
|
378
|
+
out.push({ text: "…" });
|
|
379
|
+
return out;
|
|
380
|
+
}
|
|
381
|
+
//#endregion
|
|
382
|
+
//#region src/chat/output-tail.ts
|
|
383
|
+
/**
|
|
384
|
+
* Creates an empty {@link OutputTail}.
|
|
385
|
+
*
|
|
386
|
+
* @param maxLines - Lines kept.
|
|
387
|
+
* @param lineChars - Characters kept per line.
|
|
388
|
+
*/
|
|
389
|
+
function createOutputTail(maxLines, lineChars) {
|
|
390
|
+
const tail = [];
|
|
391
|
+
const commands = /* @__PURE__ */ new Map();
|
|
392
|
+
let nextId = 0;
|
|
393
|
+
const shape = (spans) => {
|
|
394
|
+
const clipped = clipAnsiLine(spans, lineChars);
|
|
395
|
+
const text = ansiLineText(clipped);
|
|
396
|
+
return clipped.some((span) => span.style) ? {
|
|
397
|
+
text,
|
|
398
|
+
spans: clipped
|
|
399
|
+
} : { text };
|
|
400
|
+
};
|
|
401
|
+
const push = (entry) => {
|
|
402
|
+
tail.push(entry);
|
|
403
|
+
if (tail.length > maxLines) tail.splice(0, tail.length - maxLines);
|
|
404
|
+
};
|
|
405
|
+
return {
|
|
406
|
+
item(stream, text, line) {
|
|
407
|
+
const at = line !== void 0 ? { line } : {};
|
|
408
|
+
for (const spans of createAnsiLines().push(`${text}\n`)) push({
|
|
409
|
+
id: nextId++,
|
|
410
|
+
stream,
|
|
411
|
+
...shape(spans),
|
|
412
|
+
...at
|
|
413
|
+
});
|
|
414
|
+
},
|
|
415
|
+
chunk(stream, text, line) {
|
|
416
|
+
const key = `${stream}\u0000${line ?? ""}`;
|
|
417
|
+
let command = commands.get(key);
|
|
418
|
+
if (!command) {
|
|
419
|
+
command = {
|
|
420
|
+
reader: createAnsiLines(),
|
|
421
|
+
stream,
|
|
422
|
+
...line !== void 0 ? { line } : {}
|
|
423
|
+
};
|
|
424
|
+
commands.set(key, command);
|
|
425
|
+
}
|
|
426
|
+
const at = line !== void 0 ? { line } : {};
|
|
427
|
+
for (const spans of command.reader.push(text)) {
|
|
428
|
+
push({
|
|
429
|
+
id: command.openId ?? nextId++,
|
|
430
|
+
stream,
|
|
431
|
+
...shape(spans),
|
|
432
|
+
...at
|
|
433
|
+
});
|
|
434
|
+
command.openId = void 0;
|
|
435
|
+
}
|
|
436
|
+
if (command.reader.partial().length > 0 && command.openId === void 0) command.openId = nextId++;
|
|
437
|
+
},
|
|
438
|
+
lines() {
|
|
439
|
+
const open = [...commands.values()].flatMap(({ reader, stream, line, openId }) => {
|
|
440
|
+
const spans = reader.partial();
|
|
441
|
+
return spans.length === 0 || openId === void 0 ? [] : [{
|
|
442
|
+
id: openId,
|
|
443
|
+
stream,
|
|
444
|
+
...shape(spans),
|
|
445
|
+
...line !== void 0 ? { line } : {}
|
|
446
|
+
}];
|
|
447
|
+
});
|
|
448
|
+
return [...tail, ...open].slice(-maxLines);
|
|
449
|
+
}
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
//#endregion
|
|
453
|
+
//#region src/chat/script-progress.ts
|
|
454
|
+
/** Output lines a progress state keeps. */
|
|
455
|
+
const SCRIPT_OUTPUT_TAIL_LINES = 8;
|
|
456
|
+
/** Characters kept per output line. */
|
|
457
|
+
const SCRIPT_OUTPUT_LINE_CHARS = 240;
|
|
458
|
+
/** Creates an empty {@link ScriptProgressTracker}. */
|
|
459
|
+
function createScriptProgressTracker() {
|
|
460
|
+
const lines = /* @__PURE__ */ new Map();
|
|
461
|
+
const lineOf = /* @__PURE__ */ new Map();
|
|
462
|
+
const running = /* @__PURE__ */ new Set();
|
|
463
|
+
let done = 0;
|
|
464
|
+
let failed = 0;
|
|
465
|
+
let ended;
|
|
466
|
+
const output = createOutputTail(8, 240);
|
|
467
|
+
return {
|
|
468
|
+
start(callId, line) {
|
|
469
|
+
if (line === void 0 || lineOf.has(callId)) return;
|
|
470
|
+
lineOf.set(callId, line);
|
|
471
|
+
running.add(callId);
|
|
472
|
+
const entry = lines.get(line);
|
|
473
|
+
if (entry) {
|
|
474
|
+
entry.calls++;
|
|
475
|
+
entry.status = "running";
|
|
476
|
+
entry.latest = callId;
|
|
477
|
+
} else lines.set(line, {
|
|
478
|
+
line,
|
|
479
|
+
status: "running",
|
|
480
|
+
calls: 1,
|
|
481
|
+
latest: callId
|
|
482
|
+
});
|
|
483
|
+
},
|
|
484
|
+
finish(callId, ok) {
|
|
485
|
+
if (!running.delete(callId)) return;
|
|
486
|
+
done++;
|
|
487
|
+
if (!ok) failed++;
|
|
488
|
+
const entry = lines.get(lineOf.get(callId));
|
|
489
|
+
if (entry && entry.latest === callId) entry.status = ok ? "ok" : "error";
|
|
490
|
+
},
|
|
491
|
+
output(stream, text, line) {
|
|
492
|
+
if (stream === "output" || stream === "console") output.item(stream, text, line);
|
|
493
|
+
else output.chunk(stream, text, line);
|
|
494
|
+
},
|
|
495
|
+
end(ok) {
|
|
496
|
+
ended = ok ? "ok" : "error";
|
|
497
|
+
},
|
|
498
|
+
snapshot() {
|
|
499
|
+
return {
|
|
500
|
+
lines: [...lines.values()].sort((a, b) => a.line - b.line).map(({ line, status, calls }) => ({
|
|
501
|
+
line,
|
|
502
|
+
status,
|
|
503
|
+
calls
|
|
504
|
+
})),
|
|
505
|
+
done,
|
|
506
|
+
running: running.size,
|
|
507
|
+
failed,
|
|
508
|
+
output: output.lines(),
|
|
509
|
+
...ended ? { ended } : {}
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
};
|
|
513
|
+
}
|
|
514
|
+
/**
|
|
515
|
+
* The final progress of a script from its saved call records, or `undefined`
|
|
516
|
+
* when none carries a line (the script ran without live progress).
|
|
517
|
+
*
|
|
518
|
+
* @param records - The calls saved on the script's result.
|
|
519
|
+
* @param ok - The script's own result was no error.
|
|
520
|
+
*/
|
|
521
|
+
function scriptProgressFromRecords(records, ok) {
|
|
522
|
+
if (!records.some((record) => record.line !== void 0)) return void 0;
|
|
523
|
+
const tracker = createScriptProgressTracker();
|
|
524
|
+
for (const record of records) {
|
|
525
|
+
tracker.start(record.id, record.line);
|
|
526
|
+
tracker.finish(record.id, record.status === "ok");
|
|
527
|
+
}
|
|
528
|
+
if (ok !== void 0) tracker.end(ok);
|
|
529
|
+
return tracker.snapshot();
|
|
530
|
+
}
|
|
531
|
+
/**
|
|
532
|
+
* `events` with `event`, a `tool-progress` state, in place of the one it
|
|
533
|
+
* replaces (same call, same subagent), or appended. Other events are appended.
|
|
534
|
+
* A script keeps one progress event, however long it runs.
|
|
535
|
+
*
|
|
536
|
+
* @param events - The transcript so far.
|
|
537
|
+
* @param event - The live event.
|
|
538
|
+
*/
|
|
539
|
+
function upsertToolProgress(events, event) {
|
|
540
|
+
if (event.kind === "tool-progress") {
|
|
541
|
+
const at = events.findLastIndex((e) => e.kind === "tool-progress" && e.callId === event.callId && e.childId === event.childId);
|
|
542
|
+
if (at !== -1) {
|
|
543
|
+
const next = events.slice();
|
|
544
|
+
next[at] = event;
|
|
545
|
+
return next;
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
return [...events, event];
|
|
549
|
+
}
|
|
550
|
+
/**
|
|
551
|
+
* The latest `tool-progress` state of each script, by call id (`childId` + NUL + `callId`).
|
|
552
|
+
*
|
|
553
|
+
* @param events - The transcript's events.
|
|
554
|
+
*/
|
|
555
|
+
function scriptProgressByCall(events) {
|
|
556
|
+
const found = /* @__PURE__ */ new Map();
|
|
557
|
+
for (const event of events) if (event.kind === "tool-progress" && event.callId && event.scriptProgress) found.set(scriptProgressKey(event.callId, event.childId), event.scriptProgress);
|
|
558
|
+
return found;
|
|
559
|
+
}
|
|
560
|
+
/**
|
|
561
|
+
* Key of a script in {@link scriptProgressByCall}.
|
|
562
|
+
*
|
|
563
|
+
* @param callId - The script's call id.
|
|
564
|
+
* @param childId - The subagent that ran it, if any.
|
|
565
|
+
*/
|
|
566
|
+
function scriptProgressKey(callId, childId) {
|
|
567
|
+
return `${childId ?? ""}\u0000${callId}`;
|
|
568
|
+
}
|
|
569
|
+
const OPTIONS_LINE = /^\s*\/\/ @options:(.*)$/;
|
|
570
|
+
function readOptions(json) {
|
|
571
|
+
let value;
|
|
572
|
+
try {
|
|
573
|
+
value = JSON.parse(json);
|
|
574
|
+
} catch {
|
|
575
|
+
return {
|
|
576
|
+
other: [],
|
|
577
|
+
raw: json
|
|
578
|
+
};
|
|
579
|
+
}
|
|
580
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return {
|
|
581
|
+
other: [],
|
|
582
|
+
raw: json
|
|
583
|
+
};
|
|
584
|
+
const options = { other: [] };
|
|
585
|
+
for (const [key, field] of Object.entries(value)) if (key === "timeout_ms" && typeof field === "number") options.timeoutMs = field;
|
|
586
|
+
else if (key === "max_output_tokens" && typeof field === "number") options.maxOutputTokens = field;
|
|
587
|
+
else options.other.push({
|
|
588
|
+
key,
|
|
589
|
+
value: JSON.stringify(field)
|
|
590
|
+
});
|
|
591
|
+
return options;
|
|
592
|
+
}
|
|
593
|
+
/**
|
|
594
|
+
* The view of a script: its lines with their states, the counts, and the
|
|
595
|
+
* percent when it is exact (see {@link countOnceCallSites}).
|
|
596
|
+
*
|
|
597
|
+
* @param code - The script, as the model wrote it.
|
|
598
|
+
* @param progress - Its progress, when it streamed any.
|
|
599
|
+
* @param finished - The script ended (`ok` tells how).
|
|
600
|
+
* @param ok - It ended without error.
|
|
601
|
+
* @param result - Its result text: a failed script's names the line it threw at.
|
|
602
|
+
*/
|
|
603
|
+
function scriptProgressView(code, progress, finished, ok = true, result) {
|
|
604
|
+
const ended = finished || progress?.ended !== void 0;
|
|
605
|
+
const endedOk = progress?.ended !== void 0 ? progress.ended === "ok" : ok;
|
|
606
|
+
const error = ended && !endedOk && result ? scriptErrorOf(result) : void 0;
|
|
607
|
+
const source = code.split("\n").map((line) => line.replace(/\r$/, ""));
|
|
608
|
+
const optionsMatch = source[0] !== void 0 ? OPTIONS_LINE.exec(source[0]) : null;
|
|
609
|
+
const options = optionsMatch ? readOptions(optionsMatch[1].trim()) : void 0;
|
|
610
|
+
let first = optionsMatch ? 1 : 0;
|
|
611
|
+
while (first < source.length && source[first].trim() === "") first++;
|
|
612
|
+
let last = source.length - 1;
|
|
613
|
+
while (last >= first && source[last].trim() === "") last--;
|
|
614
|
+
const byLine = new Map(progress?.lines.map((entry) => [entry.line, entry]));
|
|
615
|
+
const furthest = progress?.lines.length ? progress.lines[progress.lines.length - 1].line : 0;
|
|
616
|
+
const reached = ended && endedOk ? Number.POSITIVE_INFINITY : furthest;
|
|
617
|
+
const lines = [];
|
|
618
|
+
for (let i = first; i <= last; i++) {
|
|
619
|
+
const number = i + 1;
|
|
620
|
+
const entry = byLine.get(number);
|
|
621
|
+
const state = error?.line === number ? "failed" : !progress ? "passed" : entry ? entry.status === "running" ? "running" : entry.status === "ok" ? "done" : "failed" : number <= reached ? "passed" : "idle";
|
|
622
|
+
lines.push({
|
|
623
|
+
number,
|
|
624
|
+
label: number - first,
|
|
625
|
+
text: source[i],
|
|
626
|
+
state,
|
|
627
|
+
calls: entry?.calls ?? 0
|
|
628
|
+
});
|
|
629
|
+
}
|
|
630
|
+
const lastLine = lines.at(-1);
|
|
631
|
+
if (progress && ended && endedOk && lastLine?.state === "passed") lastLine.state = "done";
|
|
632
|
+
const done = progress?.done ?? 0;
|
|
633
|
+
const total = progress ? countOnceCallSites(code) : void 0;
|
|
634
|
+
const exact = total !== void 0 && done + (progress?.running ?? 0) <= total;
|
|
635
|
+
const running = progress?.lines.find((entry) => entry.status === "running")?.line;
|
|
636
|
+
return {
|
|
637
|
+
lines,
|
|
638
|
+
...options !== void 0 ? { options } : {},
|
|
639
|
+
tracked: progress !== void 0,
|
|
640
|
+
done,
|
|
641
|
+
running: progress?.running ?? 0,
|
|
642
|
+
failed: progress?.failed ?? 0,
|
|
643
|
+
...exact ? {
|
|
644
|
+
total,
|
|
645
|
+
percent: ended && endedOk ? 100 : Math.min(100, Math.round(done / total * 100))
|
|
646
|
+
} : {},
|
|
647
|
+
...!ended && progress ? { active: running ?? (furthest || void 0) } : {},
|
|
648
|
+
output: progress?.output ?? [],
|
|
649
|
+
...error && lines.some((line) => line.number === error.line) ? { error } : {}
|
|
650
|
+
};
|
|
651
|
+
}
|
|
652
|
+
const SCRIPT_ERROR = /^Script error: (.+)$/m;
|
|
653
|
+
const EXCERPT_LINE = /^(\d+) \| /m;
|
|
654
|
+
/**
|
|
655
|
+
* The error a failed script threw and the line it names, out of its result
|
|
656
|
+
* (`Script error: …` then the `12 | source` excerpt the sandbox writes).
|
|
657
|
+
*
|
|
658
|
+
* @param result - The script's result text.
|
|
659
|
+
*/
|
|
660
|
+
function scriptErrorOf(result) {
|
|
661
|
+
const message = SCRIPT_ERROR.exec(result)?.[1]?.trim();
|
|
662
|
+
const line = EXCERPT_LINE.exec(result)?.[1];
|
|
663
|
+
return message && line ? {
|
|
664
|
+
line: Number(line),
|
|
665
|
+
message
|
|
666
|
+
} : void 0;
|
|
667
|
+
}
|
|
668
|
+
/**
|
|
669
|
+
* `code` with the text of strings, comments and regular expressions replaced
|
|
670
|
+
* by spaces (newlines kept), so a scan sees only code. Template literals keep
|
|
671
|
+
* their `${…}` expressions.
|
|
672
|
+
*
|
|
673
|
+
* @param code - The script, as the model wrote it.
|
|
674
|
+
*/
|
|
675
|
+
function maskScriptSource(code) {
|
|
676
|
+
const out = code.split("");
|
|
677
|
+
const blank = (from, to) => {
|
|
678
|
+
for (let k = from; k < to; k++) if (out[k] !== "\n") out[k] = " ";
|
|
679
|
+
};
|
|
680
|
+
/** Brace depth of each open `${`, innermost last. */
|
|
681
|
+
const templates = [];
|
|
682
|
+
let braces = 0;
|
|
683
|
+
let prev = "";
|
|
684
|
+
let i = 0;
|
|
685
|
+
const n = code.length;
|
|
686
|
+
/** Skip a template's text from `i` (after the backtick or the `}` of an expression). */
|
|
687
|
+
const templateText = () => {
|
|
688
|
+
const start = i;
|
|
689
|
+
while (i < n) {
|
|
690
|
+
const c = code[i];
|
|
691
|
+
if (c === "\\") {
|
|
692
|
+
i += 2;
|
|
693
|
+
continue;
|
|
694
|
+
}
|
|
695
|
+
if (c === "`") {
|
|
696
|
+
blank(start, i);
|
|
697
|
+
i++;
|
|
698
|
+
prev = "`";
|
|
699
|
+
return;
|
|
700
|
+
}
|
|
701
|
+
if (c === "$" && code[i + 1] === "{") {
|
|
702
|
+
blank(start, i);
|
|
703
|
+
templates.push(braces);
|
|
704
|
+
i += 2;
|
|
705
|
+
prev = "{";
|
|
706
|
+
return;
|
|
707
|
+
}
|
|
708
|
+
i++;
|
|
709
|
+
}
|
|
710
|
+
blank(start, n);
|
|
711
|
+
};
|
|
712
|
+
while (i < n) {
|
|
713
|
+
const c = code[i];
|
|
714
|
+
if (c === "/" && code[i + 1] === "/") {
|
|
715
|
+
const end = code.indexOf("\n", i);
|
|
716
|
+
blank(i, end === -1 ? n : end);
|
|
717
|
+
i = end === -1 ? n : end;
|
|
718
|
+
continue;
|
|
719
|
+
}
|
|
720
|
+
if (c === "/" && code[i + 1] === "*") {
|
|
721
|
+
const end = code.indexOf("*/", i + 2);
|
|
722
|
+
blank(i, end === -1 ? n : end + 2);
|
|
723
|
+
i = end === -1 ? n : end + 2;
|
|
724
|
+
continue;
|
|
725
|
+
}
|
|
726
|
+
if (c === "\"" || c === "'") {
|
|
727
|
+
let j = i + 1;
|
|
728
|
+
while (j < n && code[j] !== c && code[j] !== "\n") j += code[j] === "\\" ? 2 : 1;
|
|
729
|
+
blank(i + 1, Math.min(j, n));
|
|
730
|
+
i = j + 1;
|
|
731
|
+
prev = c;
|
|
732
|
+
continue;
|
|
733
|
+
}
|
|
734
|
+
if (c === "`") {
|
|
735
|
+
i++;
|
|
736
|
+
templateText();
|
|
737
|
+
continue;
|
|
738
|
+
}
|
|
739
|
+
if (c === "/" && (prev === "" || "(,=:[!&|?{};+-*%<>~^".includes(prev))) {
|
|
740
|
+
let j = i + 1;
|
|
741
|
+
let inClass = false;
|
|
742
|
+
while (j < n && code[j] !== "\n") {
|
|
743
|
+
const d = code[j];
|
|
744
|
+
if (d === "\\") {
|
|
745
|
+
j += 2;
|
|
746
|
+
continue;
|
|
747
|
+
}
|
|
748
|
+
if (d === "[") inClass = true;
|
|
749
|
+
else if (d === "]") inClass = false;
|
|
750
|
+
else if (d === "/" && !inClass) break;
|
|
751
|
+
j++;
|
|
752
|
+
}
|
|
753
|
+
blank(i + 1, Math.min(j, n));
|
|
754
|
+
i = j + 1;
|
|
755
|
+
prev = ")";
|
|
756
|
+
continue;
|
|
757
|
+
}
|
|
758
|
+
if (c === "{") braces++;
|
|
759
|
+
else if (c === "}") {
|
|
760
|
+
if (templates.length > 0 && templates[templates.length - 1] === braces) {
|
|
761
|
+
templates.pop();
|
|
762
|
+
i++;
|
|
763
|
+
templateText();
|
|
764
|
+
continue;
|
|
765
|
+
}
|
|
766
|
+
braces--;
|
|
767
|
+
}
|
|
768
|
+
if (!/\s/.test(c)) prev = /[\w$]/.test(c) ? "w" : c;
|
|
769
|
+
i++;
|
|
770
|
+
}
|
|
771
|
+
return out.join("");
|
|
772
|
+
}
|
|
773
|
+
const TOOL_CALL = /\btools\s*(?:\.\s*[A-Z_$][\w$]*|\[\s*(["'`])\s*\1\s*\])\s*\(/gi;
|
|
774
|
+
const TOOL_REF = /\btools\b/g;
|
|
775
|
+
const SH_CALL = /(?<![\w$.])sh\s*\(/g;
|
|
776
|
+
const SH_REF = /(?<![\w$.])sh\b/g;
|
|
777
|
+
const WORD = /[\w$]/;
|
|
778
|
+
/**
|
|
779
|
+
* How many calls a script makes, when every call can run once at most: each
|
|
780
|
+
* `tools.<name>(…)` or `sh(…)` sits outside loops and functions (callbacks,
|
|
781
|
+
* helpers, methods). `undefined` when one may run more than once, when the
|
|
782
|
+
* script reaches `tools` or `sh` another way (a reference, a computed name),
|
|
783
|
+
* or when it makes no call. A call in a branch that does not run makes the
|
|
784
|
+
* count high, never low, so a percent from it never runs ahead.
|
|
785
|
+
*
|
|
786
|
+
* @param code - The script, as the model wrote it.
|
|
787
|
+
*/
|
|
788
|
+
function countOnceCallSites(code) {
|
|
789
|
+
const masked = maskScriptSource(code);
|
|
790
|
+
const sites = /* @__PURE__ */ new Set();
|
|
791
|
+
for (const match of masked.matchAll(TOOL_CALL)) sites.add(match.index);
|
|
792
|
+
if ((masked.match(TOOL_REF)?.length ?? 0) !== sites.size) return void 0;
|
|
793
|
+
const shCalls = [...masked.matchAll(SH_CALL)];
|
|
794
|
+
if ((masked.match(SH_REF)?.length ?? 0) !== shCalls.length) return void 0;
|
|
795
|
+
for (const match of shCalls) sites.add(match.index);
|
|
796
|
+
if (sites.size === 0) return void 0;
|
|
797
|
+
const stack = [];
|
|
798
|
+
let pending = null;
|
|
799
|
+
let nextParen = null;
|
|
800
|
+
const repeating = () => stack.some((scope) => scope.repeats);
|
|
801
|
+
/** A body without braces opens where its first token starts. */
|
|
802
|
+
const openBody = () => {
|
|
803
|
+
if (pending === "loopBody") stack.push({
|
|
804
|
+
close: "stmt",
|
|
805
|
+
repeats: true
|
|
806
|
+
});
|
|
807
|
+
else if (pending === "arrowBody") stack.push({
|
|
808
|
+
close: "expr",
|
|
809
|
+
repeats: true
|
|
810
|
+
});
|
|
811
|
+
pending = null;
|
|
812
|
+
};
|
|
813
|
+
const closeTo = (close) => {
|
|
814
|
+
while (stack.length > 0) {
|
|
815
|
+
const scope = stack.pop();
|
|
816
|
+
if (scope.close === close) return scope;
|
|
817
|
+
}
|
|
818
|
+
};
|
|
819
|
+
const popWhile = (closes) => {
|
|
820
|
+
while (stack.length > 0 && closes.includes(stack[stack.length - 1].close)) stack.pop();
|
|
821
|
+
};
|
|
822
|
+
let i = 0;
|
|
823
|
+
const n = masked.length;
|
|
824
|
+
while (i < n) {
|
|
825
|
+
const c = masked[i];
|
|
826
|
+
if (/\s/.test(c)) {
|
|
827
|
+
i++;
|
|
828
|
+
continue;
|
|
829
|
+
}
|
|
830
|
+
if (WORD.test(c)) {
|
|
831
|
+
let j = i;
|
|
832
|
+
while (j < n && WORD.test(masked[j])) j++;
|
|
833
|
+
const word = masked.slice(i, j);
|
|
834
|
+
openBody();
|
|
835
|
+
if (sites.has(i) && repeating()) return void 0;
|
|
836
|
+
if (word === "for" || word === "while") nextParen = "loop";
|
|
837
|
+
else if (word === "if" || word === "switch" || word === "catch" || word === "with") nextParen = "cond";
|
|
838
|
+
else if (word === "function") nextParen = "fn";
|
|
839
|
+
else if (word === "do") pending = "loopBody";
|
|
840
|
+
i = j;
|
|
841
|
+
continue;
|
|
842
|
+
}
|
|
843
|
+
if (c === "=" && masked[i + 1] === ">") {
|
|
844
|
+
pending = "arrowBody";
|
|
845
|
+
i += 2;
|
|
846
|
+
continue;
|
|
847
|
+
}
|
|
848
|
+
if (c === "{") {
|
|
849
|
+
const repeats = pending === "loopBody" || pending === "fnBody" || pending === "braceIsFn" || pending === "arrowBody";
|
|
850
|
+
stack.push({
|
|
851
|
+
close: "}",
|
|
852
|
+
repeats
|
|
853
|
+
});
|
|
854
|
+
pending = null;
|
|
855
|
+
i++;
|
|
856
|
+
continue;
|
|
857
|
+
}
|
|
858
|
+
if (c === ";") {
|
|
859
|
+
popWhile(["stmt", "expr"]);
|
|
860
|
+
pending = null;
|
|
861
|
+
i++;
|
|
862
|
+
continue;
|
|
863
|
+
}
|
|
864
|
+
if (c === ",") {
|
|
865
|
+
popWhile(["expr"]);
|
|
866
|
+
pending = null;
|
|
867
|
+
i++;
|
|
868
|
+
continue;
|
|
869
|
+
}
|
|
870
|
+
if (c === ")" || c === "]" || c === "}") {
|
|
871
|
+
const scope = closeTo(c);
|
|
872
|
+
pending = null;
|
|
873
|
+
if (c === ")" && scope) {
|
|
874
|
+
if (scope.kind === "loop") pending = "loopBody";
|
|
875
|
+
else if (scope.kind === "fn") pending = "fnBody";
|
|
876
|
+
else if (scope.kind === "other") pending = "braceIsFn";
|
|
877
|
+
}
|
|
878
|
+
i++;
|
|
879
|
+
continue;
|
|
880
|
+
}
|
|
881
|
+
openBody();
|
|
882
|
+
if (c === "(") {
|
|
883
|
+
stack.push({
|
|
884
|
+
close: ")",
|
|
885
|
+
repeats: false,
|
|
886
|
+
kind: nextParen ?? "other"
|
|
887
|
+
});
|
|
888
|
+
nextParen = null;
|
|
889
|
+
} else if (c === "[") stack.push({
|
|
890
|
+
close: "]",
|
|
891
|
+
repeats: false
|
|
892
|
+
});
|
|
893
|
+
i++;
|
|
894
|
+
}
|
|
895
|
+
return sites.size;
|
|
896
|
+
}
|
|
897
|
+
//#endregion
|
|
898
|
+
export { commandNoteText as C, parseCommandHeader as D, noteDisplay as E, commandHeaderBlock as S, gatherCommandNotes as T, parseAnsi as _, maskScriptSource as a, nestedResultEvent as b, scriptProgressFromRecords as c, upsertToolProgress as d, createOutputTail as f, hasAnsi as g, createAnsiLines as h, createScriptProgressTracker as i, scriptProgressKey as l, clipAnsiLine as m, SCRIPT_OUTPUT_TAIL_LINES as n, scriptErrorOf as o, ansiLineText as p, countOnceCallSites as r, scriptProgressByCall as s, SCRIPT_OUTPUT_LINE_CHARS as t, scriptProgressView as u, stripAnsi as v, commandStepLabel as w, nestedToolEvent as x, nestedRecordEvents as y };
|
|
899
|
+
|
|
900
|
+
//# sourceMappingURL=script-progress-CrZ507Qq.js.map
|