@qwen-code/qwen-code 0.19.5 → 0.19.6-nightly.20260705.015ee4248
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/bundled/dataviz/SKILL.md +50 -0
- package/bundled/dataviz/references/anti-patterns.md +12 -0
- package/bundled/dataviz/references/choosing-a-form.md +16 -0
- package/bundled/dataviz/references/palette.md +57 -0
- package/bundled/dataviz/scripts/validate_palette.js +328 -0
- package/bundled/loop/SKILL.md +1 -1
- package/bundled/qc-helper/docs/configuration/settings.md +14 -8
- package/bundled/qc-helper/docs/features/headless.md +2 -2
- package/bundled/qc-helper/docs/features/scheduled-tasks.md +4 -2
- package/bundled/qc-helper/docs/reference/keyboard-shortcuts.md +1 -1
- package/bundled/review/DESIGN.md +23 -0
- package/bundled/review/SKILL.md +65 -8
- package/chunks/{MaxSizedBox-5JV77KRA.js → MaxSizedBox-PRXTXIGC.js} +31 -30
- package/chunks/{StandaloneSessionPicker-MGUGB6PH.js → StandaloneSessionPicker-PV7BSC5D.js} +42 -41
- package/chunks/{acpAgent-4F36XM3X.js → acpAgent-F34HNAM3.js} +939 -424
- package/chunks/{agent-IWBUZI6A.js → agent-XSQDKLST.js} +26 -25
- package/chunks/{agent-headless-JUTICAYO.js → agent-headless-B63XCKWX.js} +26 -25
- package/chunks/{anthropicContentGenerator-WL3LJOUB.js → anthropicContentGenerator-INXXI4PW.js} +7 -7
- package/chunks/{artifact-tool-W76WC2JX.js → artifact-tool-H2TNPNP5.js} +16 -3
- package/chunks/{askUserQuestion-J3P6TH3V.js → askUserQuestion-MKL5ZTMC.js} +2 -2
- package/chunks/{bridge-DHZHQ4UV.js → bridge-NCZDJBRF.js} +34 -32
- package/chunks/{channel-worker-supervisor-EVPAYNZ5.js → channel-worker-supervisor-JUYQ5Z4R.js} +5 -5
- package/chunks/{chunk-AVQDCKNF.js → chunk-22MNNNXE.js} +4 -0
- package/chunks/chunk-3RW4AZJV.js +5063 -0
- package/chunks/chunk-3VJ7MT3N.js +111 -0
- package/chunks/{chunk-JKGCBO3O.js → chunk-3VRMGS3A.js} +4 -4
- package/chunks/{chunk-TN6RT6EJ.js → chunk-3WOJO5EJ.js} +16 -4
- package/chunks/{chunk-G7OQ3RFJ.js → chunk-42XGFRJS.js} +3 -3
- package/chunks/{chunk-MOUXUCXQ.js → chunk-4KJ2BPIT.js} +1 -1
- package/chunks/{chunk-PPFWEV7G.js → chunk-4RQIB5UZ.js} +62 -62
- package/chunks/{chunk-JJ6B3ZD3.js → chunk-544UZQBD.js} +3 -3
- package/chunks/{chunk-B236XPGF.js → chunk-5UDYETKK.js} +1 -1
- package/chunks/{chunk-7DMQRPC7.js → chunk-6BEOH4KK.js} +1 -1
- package/chunks/{chunk-CXBG27SF.js → chunk-6IAWPIQ6.js} +3 -2
- package/chunks/{chunk-MDBNFHIO.js → chunk-6MDY7FX3.js} +5 -5
- package/chunks/{chunk-RM3PGSGL.js → chunk-6SHO7WFF.js} +15 -2
- package/chunks/{chunk-YCU7QV7Q.js → chunk-73WGF3NW.js} +34 -1
- package/chunks/{chunk-T42ACHFI.js → chunk-7LTB54MK.js} +1 -1
- package/chunks/{chunk-SJVPSHXU.js → chunk-7U6J224Z.js} +132 -25
- package/chunks/{chunk-CSPSJU5R.js → chunk-7WLJPMWU.js} +17 -17
- package/chunks/{chunk-R6RI2HIC.js → chunk-ACD5DFUY.js} +41 -14
- package/chunks/{chunk-EWALXUAD.js → chunk-AGHU5VRK.js} +8 -0
- package/chunks/{chunk-GLPV75ES.js → chunk-AHNJGLFV.js} +2 -2
- package/chunks/{chunk-DRS2HTNT.js → chunk-AOAFX4PL.js} +5 -5
- package/chunks/{chunk-QHYITL6P.js → chunk-CK7IUFOB.js} +63 -22
- package/chunks/{chunk-RSBQS6M4.js → chunk-CODWJXQA.js} +1 -1
- package/chunks/{chunk-LWGLBVWA.js → chunk-CSOTA7KX.js} +1 -1
- package/chunks/{chunk-UJT42DB6.js → chunk-DFH4T5IQ.js} +6 -6
- package/chunks/{chunk-DX3TKXNT.js → chunk-DJACOX4C.js} +2 -2
- package/chunks/{chunk-KKQWC6WS.js → chunk-DNV4FSN5.js} +1 -1
- package/chunks/{chunk-YPCPZSZB.js → chunk-DT3B47QP.js} +1 -1
- package/chunks/{chunk-NIOPRZNN.js → chunk-E7KNELIZ.js} +1 -1
- package/chunks/{chunk-DG573EOO.js → chunk-FEJ2FZ3U.js} +1 -1
- package/chunks/{chunk-M5ITDKSM.js → chunk-FHGQFG2K.js} +1 -1
- package/chunks/{chunk-HISPEX42.js → chunk-FSXFNDTI.js} +7 -7
- package/chunks/{chunk-LHMZCIKL.js → chunk-FUW7YGJU.js} +3 -1
- package/chunks/{chunk-Y4UQT3PM.js → chunk-FV5SBNNC.js} +1 -1
- package/chunks/{chunk-YTFBURQD.js → chunk-GB6HDZIK.js} +10 -2
- package/chunks/{chunk-D5KISTLW.js → chunk-H6EMK6QK.js} +1 -1
- package/chunks/{chunk-2Z43HUXT.js → chunk-HLKG6CZN.js} +3 -2
- package/chunks/{chunk-VXGPYF7U.js → chunk-IFEWJXFS.js} +1 -1
- package/chunks/{chunk-TENOUWY2.js → chunk-IJRL2S3D.js} +3 -3
- package/chunks/{chunk-OQHLUA2Y.js → chunk-IL6ZEDZ2.js} +4 -4
- package/chunks/{chunk-2CAII5HD.js → chunk-J7XUJALJ.js} +1 -1
- package/chunks/chunk-JFFOH2XO.js +2472 -0
- package/chunks/{chunk-NNEJEBCF.js → chunk-K3FZXSTO.js} +95 -107
- package/chunks/{chunk-NDY7OENU.js → chunk-KB4ICCA5.js} +3 -3
- package/chunks/{chunk-MNOXKSM2.js → chunk-LFFF2SPV.js} +3 -3
- package/chunks/{chunk-J3ERRYYI.js → chunk-LTMDKOZC.js} +2 -2
- package/chunks/{chunk-R3UWLLRQ.js → chunk-M7AGQP5D.js} +1 -1
- package/chunks/{chunk-CBJE2PLG.js → chunk-MLB5AB2I.js} +4 -4
- package/chunks/{chunk-YHTNWGRR.js → chunk-MZ7BABX3.js} +1 -1
- package/chunks/{chunk-SJBIFVD2.js → chunk-NFE3DQ4R.js} +7 -3
- package/chunks/{chunk-BC4R5C5R.js → chunk-NLD2WKE3.js} +55 -12
- package/chunks/{chunk-ALX6BUYW.js → chunk-NUGPZXAZ.js} +35 -1
- package/chunks/{chunk-NSSVORTQ.js → chunk-NYKWPUAE.js} +17 -13
- package/chunks/{chunk-K4I4STSL.js → chunk-OGEJMKN5.js} +2 -2
- package/chunks/{chunk-HTWHAN44.js → chunk-PC4ZXHU2.js} +1 -1
- package/chunks/{chunk-2YH27UNF.js → chunk-QLBBV7C6.js} +1 -1
- package/chunks/chunk-QT7XKZT7.js +293 -0
- package/chunks/{chunk-NPQWQYU6.js → chunk-QYNNN7BK.js} +1 -1
- package/chunks/chunk-R4N3OALZ.js +5631 -0
- package/chunks/{chunk-G4M7FPNY.js → chunk-RB5GAQR6.js} +2 -2
- package/chunks/{chunk-SBMHB6N5.js → chunk-RPHMD5UC.js} +15 -15
- package/chunks/{chunk-CHY5C5T4.js → chunk-SJ2CTIYH.js} +185 -88
- package/chunks/chunk-SLQXGMYY.js +949 -0
- package/chunks/{chunk-BZHLWC6T.js → chunk-SUAKHHK7.js} +2 -2
- package/chunks/{chunk-IMAMNLY6.js → chunk-SWV4CVYG.js} +158 -3
- package/chunks/{chunk-XKSCTXPK.js → chunk-TDGF35EN.js} +4 -3
- package/chunks/{chunk-TOAUDIS7.js → chunk-TLWA7TPR.js} +6 -2
- package/chunks/{chunk-WALEWZ44.js → chunk-UVHL5TCO.js} +1 -1
- package/chunks/{chunk-ZISMVA6U.js → chunk-VDMM5LVR.js} +1566 -37
- package/chunks/{chunk-BPFJQGY7.js → chunk-VEB3NYSO.js} +164 -5
- package/chunks/{chunk-L7OJ3ZO3.js → chunk-VZ7HY3YU.js} +1 -1
- package/chunks/{chunk-6KPZJJ6U.js → chunk-W4I6PLEG.js} +131 -38
- package/chunks/{chunk-QOMAHFYI.js → chunk-W7EEOR7D.js} +3 -3
- package/chunks/{chunk-6QVQZAW6.js → chunk-WKP5QZOP.js} +1 -1
- package/chunks/{chunk-YXK4GPYO.js → chunk-WMPVYQ4P.js} +30 -1
- package/chunks/{chunk-DM4E337C.js → chunk-WNTS5A2R.js} +5 -5
- package/chunks/{chunk-6QTCOQX7.js → chunk-WOG7QWIT.js} +3086 -2635
- package/chunks/{chunk-UY2TCIZS.js → chunk-X265R5C6.js} +3 -3
- package/chunks/{chunk-LKWAVAB5.js → chunk-X2XNQQJI.js} +2 -2
- package/chunks/{chunk-MTNTVOJR.js → chunk-X3YGAX7V.js} +6 -3
- package/chunks/{chunk-EROWZQN7.js → chunk-XD3OLPII.js} +6 -6
- package/chunks/{chunk-RNGAT2Y2.js → chunk-YYL6HROQ.js} +1 -1
- package/chunks/{chunk-XKZXGIRM.js → chunk-YZ2LNTHO.js} +2 -2
- package/chunks/{chunk-Z7XNVNPM.js → chunk-YZ5ANQMR.js} +3 -3
- package/chunks/{chunk-4MCC4XHH.js → chunk-Z7EYROOJ.js} +3568 -5508
- package/chunks/{chunk-5B2WNM6V.js → chunk-ZI4MGBB5.js} +1 -1
- package/chunks/{chunk-WZ724G6K.js → chunk-ZPGE42V7.js} +6 -6
- package/chunks/{computer-use-ON3JQUHW.js → computer-use-5I2UHVNY.js} +26 -25
- package/chunks/{contextCommand-OGCG7W6N.js → contextCommand-3NWY7AJG.js} +28 -27
- package/chunks/{cron-create-6YTCOX6P.js → cron-create-O6ZHD3JN.js} +22 -7
- package/chunks/{cron-delete-E3NIFSUK.js → cron-delete-BFD5B2XX.js} +4 -4
- package/chunks/{cron-list-Q64MNQNE.js → cron-list-KI6FV4KN.js} +4 -4
- package/chunks/{daemon-EEB2RYOL.js → daemon-DRUMLVFP.js} +140 -0
- package/chunks/daemon-status-provider-A2DK3ZTO.js +74 -0
- package/chunks/{dist-AP5V4WYU.js → dist-AAO65DPC.js} +2 -2
- package/chunks/{dist-X4ZDE726.js → dist-ABQ7VWRR.js} +3 -3
- package/chunks/{dist-SNXOUPYS.js → dist-AW5ZYMUI.js} +2 -2
- package/chunks/{dist-Z57Q4YF5.js → dist-DN6M6TJ5.js} +525 -95
- package/chunks/{dist-IZP2VV4C.js → dist-JPSVN367.js} +2 -2
- package/chunks/{earlyInputCapture-DAFHSGVW.js → earlyInputCapture-5TMSSPQ5.js} +27 -26
- package/chunks/{edit-3QFNCSZH.js → edit-V4ITLSUD.js} +27 -26
- package/chunks/{en-M4EBUBNU.js → en-AXARKOWO.js} +2 -0
- package/chunks/{enter-worktree-62EQQMLD.js → enter-worktree-7ULPRMTJ.js} +26 -25
- package/chunks/{enterPlanMode-VUQSE4EG.js → enterPlanMode-YSHMLHJZ.js} +26 -25
- package/chunks/{errors-PW75PZXE.js → errors-TCUTD7NF.js} +28 -27
- package/chunks/{exit-worktree-VVNH7OVY.js → exit-worktree-JZDCKR6A.js} +26 -25
- package/chunks/{exitPlanMode-RUYRCYZW.js → exitPlanMode-GOQBN6SG.js} +26 -25
- package/chunks/{fast-path-TFRJRTTR.js → fast-path-F2HGAKO2.js} +3 -3
- package/chunks/{fast-path-settings-UQLRFDQP.js → fast-path-settings-RCRXH2JG.js} +2 -2
- package/chunks/{gemini-XW7ZDUVR.js → gemini-3M7ECKNW.js} +86 -80
- package/chunks/{geminiContentGenerator-MZDVHVZH.js → geminiContentGenerator-5EG3QEJM.js} +4 -4
- package/chunks/{glob-WAY2PUWA.js → glob-2DBDTLR4.js} +54 -29
- package/chunks/{grep-W6CBKSYC.js → grep-R27DLGWT.js} +26 -25
- package/chunks/{initializer-HK2XE6P2.js → initializer-OXB6BJZU.js} +32 -31
- package/chunks/{keychain-token-storage-GPAKRDKQ.js → keychain-token-storage-UJV5XP4Z.js} +2 -2
- package/chunks/{list-RVLIIKKL.js → list-HLCOEOSF.js} +33 -32
- package/chunks/{loadedSettingsAdapter-C63OUYZC.js → loadedSettingsAdapter-JHTVH3YO.js} +31 -30
- package/chunks/{loop-wakeup-G2EHBRGR.js → loop-wakeup-CUVIY2JY.js} +5 -5
- package/chunks/{ls-IDHUVSAG.js → ls-L654WOAT.js} +4 -4
- package/chunks/{lsp-FSRYXGFT.js → lsp-M35KE54Y.js} +2 -2
- package/chunks/mcp-2JWEFAIN.js +67 -0
- package/chunks/{monitor-FOG36ABM.js → monitor-5QKFZFDX.js} +26 -25
- package/chunks/nonInteractiveCli-W5W5PIHI.js +112 -0
- package/chunks/{notebook-edit-GC6NXRCX.js → notebook-edit-XAFBWORI.js} +27 -26
- package/chunks/{openaiContentGenerator-EXR3ZL3Z.js → openaiContentGenerator-NULJROYV.js} +13 -12
- package/chunks/{pidfile-FNZM2DDH.js → pidfile-3LT7PZSW.js} +27 -26
- package/chunks/{qwenContentGenerator-A7B6J4U7.js → qwenContentGenerator-KLSURVNH.js} +28 -27
- package/chunks/{qwenOAuth2-LWLA6MQG.js → qwenOAuth2-ZV7YLMND.js} +5 -5
- package/chunks/{read-file-6JL4ULMY.js → read-file-HDAM3RHJ.js} +8 -8
- package/chunks/{read-mcp-resource-PIJF24RO.js → read-mcp-resource-CNQHBSJM.js} +2 -2
- package/chunks/record-artifact-PP3LKHTS.js +343 -0
- package/chunks/{ripGrep-DIUGLJE5.js → ripGrep-W36NLR7M.js} +26 -25
- package/chunks/{run-qwen-serve-CME3AKM4.js → run-qwen-serve-IMI2CQB5.js} +72 -28
- package/chunks/{scheduler-L7F6GDDT.js → scheduler-I5NKE5UJ.js} +26 -25
- package/chunks/{send-message-33PYFMCT.js → send-message-OA6MV4EU.js} +3 -3
- package/chunks/{serve-SRCBOJGP.js → serve-JMHMOYBO.js} +33 -32
- package/chunks/{server-QSQ45QFR.js → server-QIYIN34N.js} +1358 -492
- package/chunks/{session-5DG6NXHZ.js → session-BLL6HB35.js} +68 -65
- package/chunks/{settings-3EEQI4MN.js → settings-ABECXCTY.js} +30 -29
- package/chunks/{shell-B7FNYF5S.js → shell-A2TQI3U4.js} +26 -25
- package/chunks/{skill-AAOGHD5O.js → skill-4GTWZZWR.js} +10 -10
- package/chunks/{spawnChannel-3CBN3ZLK.js → spawnChannel-DFUVGP53.js} +30 -29
- package/chunks/{src-T5A7P7FS.js → src-ZORBMUM7.js} +77 -43
- package/chunks/{startInteractiveUI-2FGEQ6AS.js → startInteractiveUI-FH5MVXUE.js} +449 -175
- package/chunks/{syntheticOutput-YOSWIHDJ.js → syntheticOutput-F7LSDCAR.js} +3 -3
- package/chunks/{task-create-NHS2NGB3.js → task-create-RPFZNB4B.js} +7 -7
- package/chunks/{task-list-5UIB564R.js → task-list-TGGJX7EA.js} +5 -5
- package/chunks/{task-stop-HGXZ2VZ3.js → task-stop-W7NGTMYQ.js} +2 -2
- package/chunks/{task-update-IYYWUILG.js → task-update-5WUG5MVQ.js} +7 -7
- package/chunks/{team-create-KDF6W6PV.js → team-create-F76QOR6H.js} +26 -25
- package/chunks/{team-delete-FEKJCU4P.js → team-delete-UHQQ2QQX.js} +5 -5
- package/chunks/{team-plan-approval-PSFKQX7M.js → team-plan-approval-OKM7YZC2.js} +26 -25
- package/chunks/{theme-manager-5XOA2AO7.js → theme-manager-6R7EVWHW.js} +27 -26
- package/chunks/{todoWrite-TKMVZ2HT.js → todoWrite-C4ZAMSR3.js} +4 -4
- package/chunks/{tool-search-LFRILZXC.js → tool-search-UWXDKI7D.js} +9 -9
- package/chunks/{trustedFolders-7HQY6T6X.js → trustedFolders-DHASVVUP.js} +27 -26
- package/chunks/{validateNonInterActiveAuth-UC27B7BA.js → validateNonInterActiveAuth-56J7MOOP.js} +62 -59
- package/chunks/version-NE2I4PBN.js +10 -0
- package/chunks/{web-fetch-J4PIW36Q.js → web-fetch-UYGMOHW4.js} +5 -5
- package/chunks/{workflow-KUTESS6L.js → workflow-HGF3URV3.js} +35 -27
- package/chunks/{workspace-providers-status-LJT5AQDS.js → workspace-providers-status-KXB2OZFQ.js} +33 -32
- package/chunks/{workspace-service-YOBYVDXH.js → workspace-service-NSTI55BC.js} +39 -38
- package/chunks/workspace-skills-status-X5S6JGQZ.js +69 -0
- package/chunks/{write-file-FJYBZUHP.js → write-file-HVKT5VTX.js} +27 -26
- package/chunks/yargs-B64EYTCF.js +10 -0
- package/chunks/{zh-SLZNSSZB.js → zh-RS3HZHFH.js} +2 -0
- package/chunks/{zh-TW-P53C2SL5.js → zh-TW-L5GRQ4S4.js} +2 -0
- package/cli-entry.js +81 -8
- package/cli.js +348 -55
- package/locales/en.js +2 -0
- package/locales/zh-TW.js +2 -0
- package/locales/zh.js +2 -0
- package/node_modules/@qwen-code/audio-capture/package.json +1 -1
- package/node_modules/@qwen-code/audio-capture/prebuilds/darwin-arm64/@qwen-code+audio-capture.node +0 -0
- package/node_modules/@qwen-code/audio-capture/prebuilds/darwin-x64/@qwen-code+audio-capture.node +0 -0
- package/node_modules/@qwen-code/audio-capture/prebuilds/win32-x64/@qwen-code+audio-capture.node +0 -0
- package/package.json +3 -3
- package/web-shell/assets/{arc-D_rAuMDd.js → arc-Csx4m4N0.js} +1 -1
- package/web-shell/assets/{architectureDiagram-3BPJPVTR-DUCzbHVo.js → architectureDiagram-3BPJPVTR-BEa0vCM7.js} +1 -1
- package/web-shell/assets/{blockDiagram-GPEHLZMM-BEEBt1LL.js → blockDiagram-GPEHLZMM-BPzbKnn3.js} +1 -1
- package/web-shell/assets/{c4Diagram-AAUBKEIU-5ZJ_DeFL.js → c4Diagram-AAUBKEIU-B8YO71yP.js} +1 -1
- package/web-shell/assets/channel-QU1XUuVe.js +1 -0
- package/web-shell/assets/{chunk-2J33WTMH-Cfw7EiLn.js → chunk-2J33WTMH-32XhwSHt.js} +1 -1
- package/web-shell/assets/{chunk-4BX2VUAB-FGuZNCZY.js → chunk-4BX2VUAB-Bmoyo6PS.js} +1 -1
- package/web-shell/assets/{chunk-55IACEB6-CaBwYPBF.js → chunk-55IACEB6-TwH6PFhs.js} +1 -1
- package/web-shell/assets/{chunk-727SXJPM-BlR04OFz.js → chunk-727SXJPM-RI_IVUtZ.js} +1 -1
- package/web-shell/assets/{chunk-AQP2D5EJ-D3_mYJH5.js → chunk-AQP2D5EJ-DH6GIAZD.js} +1 -1
- package/web-shell/assets/{chunk-FMBD7UC4-7D4q4SbB.js → chunk-FMBD7UC4-DeD3k3D5.js} +1 -1
- package/web-shell/assets/{chunk-ND2GUHAM-BjX_Iwmr.js → chunk-ND2GUHAM-BLPb8nv3.js} +1 -1
- package/web-shell/assets/{chunk-QZHKN3VN-C3Hz_ZQh.js → chunk-QZHKN3VN-PZpyglW1.js} +1 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-fv1EWO-L.js +1 -0
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-fv1EWO-L.js +1 -0
- package/web-shell/assets/{cose-bilkent-S5V4N54A-Ax4UycaT.js → cose-bilkent-S5V4N54A-Jsd0yKfz.js} +1 -1
- package/web-shell/assets/{dagre-BM42HDAG-C6hmPtGt.js → dagre-BM42HDAG-B-zADciZ.js} +1 -1
- package/web-shell/assets/{diagram-2AECGRRQ-tXZnxjmw.js → diagram-2AECGRRQ-Cn6GDxoo.js} +1 -1
- package/web-shell/assets/{diagram-5GNKFQAL-99dwIzQG.js → diagram-5GNKFQAL-udLgyJxO.js} +1 -1
- package/web-shell/assets/{diagram-KO2AKTUF-Bqhn0-2s.js → diagram-KO2AKTUF-EcLpfzy3.js} +1 -1
- package/web-shell/assets/{diagram-LMA3HP47-DzThVSvo.js → diagram-LMA3HP47-D-YFbYsJ.js} +1 -1
- package/web-shell/assets/{diagram-OG6HWLK6-DPE8vjln.js → diagram-OG6HWLK6-C8oRUATa.js} +1 -1
- package/web-shell/assets/{erDiagram-TEJ5UH35-KzUKgQCV.js → erDiagram-TEJ5UH35-DPH5nStc.js} +1 -1
- package/web-shell/assets/{flowDiagram-I6XJVG4X-DBN-DXw5.js → flowDiagram-I6XJVG4X-CSOTwkAt.js} +1 -1
- package/web-shell/assets/{ganttDiagram-6RSMTGT7-DuBsP9u8.js → ganttDiagram-6RSMTGT7-D0L988t0.js} +1 -1
- package/web-shell/assets/{gitGraphDiagram-PVQCEYII-BjWHMyKR.js → gitGraphDiagram-PVQCEYII-B9Oo7gxS.js} +1 -1
- package/web-shell/assets/index-BYZZL5N7.css +5 -0
- package/web-shell/assets/index-C_oTyz0s.js +753 -0
- package/web-shell/assets/{infoDiagram-5YYISTIA-BVux0vP6.js → infoDiagram-5YYISTIA-Ddj4YN2P.js} +1 -1
- package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-2qzw7f--.js → ishikawaDiagram-YF4QCWOH-CBjafcl7.js} +1 -1
- package/web-shell/assets/{journeyDiagram-JHISSGLW-Dnl65sxL.js → journeyDiagram-JHISSGLW-Bn3XD99u.js} +1 -1
- package/web-shell/assets/{kanban-definition-UN3LZRKU-BElSQYtY.js → kanban-definition-UN3LZRKU-D7PBPJmE.js} +1 -1
- package/web-shell/assets/{linear-BjoycSSY.js → linear-Bmfo22rZ.js} +1 -1
- package/web-shell/assets/{mermaid.core-xe6bvMRz.js → mermaid.core-xRkAI-EI.js} +5 -5
- package/web-shell/assets/{mindmap-definition-RKZ34NQL-D8DQgI4U.js → mindmap-definition-RKZ34NQL-B30zRinm.js} +1 -1
- package/web-shell/assets/{pieDiagram-4H26LBE5-Dwh7Gp7c.js → pieDiagram-4H26LBE5-DblnKR9Z.js} +1 -1
- package/web-shell/assets/{quadrantDiagram-W4KKPZXB-BXKNBln2.js → quadrantDiagram-W4KKPZXB-COkHFKjF.js} +1 -1
- package/web-shell/assets/{requirementDiagram-4Y6WPE33-BzaC3cIA.js → requirementDiagram-4Y6WPE33-DDU3MMyn.js} +1 -1
- package/web-shell/assets/{sankeyDiagram-5OEKKPKP-DP2t7eZk.js → sankeyDiagram-5OEKKPKP-Dt4lqEYv.js} +1 -1
- package/web-shell/assets/{sequenceDiagram-3UESZ5HK-XlFiWEYv.js → sequenceDiagram-3UESZ5HK-BRzby5gN.js} +1 -1
- package/web-shell/assets/{stateDiagram-AJRCARHV-CupgUMJO.js → stateDiagram-AJRCARHV-CylzByc3.js} +1 -1
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-BKWZIKkM.js +1 -0
- package/web-shell/assets/{timeline-definition-PNZ67QCA-DstuGywa.js → timeline-definition-PNZ67QCA-BSzaNx6w.js} +1 -1
- package/web-shell/assets/{vennDiagram-CIIHVFJN-CnbNp6zu.js → vennDiagram-CIIHVFJN-BbzeKzCo.js} +1 -1
- package/web-shell/assets/{wardley-L42UT6IY-DnvoHq6R.js → wardley-L42UT6IY-BRJwCgE_.js} +1 -1
- package/web-shell/assets/{wardleyDiagram-YWT4CUSO-Cz0xHEWB.js → wardleyDiagram-YWT4CUSO-BmAs0mJ-.js} +1 -1
- package/web-shell/assets/{xychartDiagram-2RQKCTM6-p36gfo88.js → xychartDiagram-2RQKCTM6-DqywSqVW.js} +1 -1
- package/web-shell/index.html +2 -2
- package/bundled/loop/SKILL.test.ts +0 -119
- package/bundled/loop/autonomous-loop.test.ts +0 -59
- package/bundled/loop/loop-task-file.test.ts +0 -1064
- package/bundled/loop/loop-tick-resolver.test.ts +0 -906
- package/chunks/chunk-EJ7BN3EN.js +0 -11396
- package/chunks/chunk-L7QPM2YD.js +0 -481
- package/chunks/daemon-status-provider-P72STMLB.js +0 -72
- package/chunks/nonInteractiveCli-6BYQSJTB.js +0 -109
- package/chunks/workspace-skills-status-ONEPXJV6.js +0 -62
- package/web-shell/assets/channel-B5ynH0q8.js +0 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-CK3ibywp.js +0 -1
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-CK3ibywp.js +0 -1
- package/web-shell/assets/index-9qfvU0_r.css +0 -5
- package/web-shell/assets/index-CWzDaQT5.js +0 -717
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-By3E4QwN.js +0 -1
- package/chunks/{chunk-UFC57OYT.js → chunk-VRDMOSQS.js} +54 -54
|
@@ -0,0 +1,2472 @@
|
|
|
1
|
+
// Force strict mode and setup for ESM
|
|
2
|
+
"use strict";
|
|
3
|
+
import {
|
|
4
|
+
require_undici
|
|
5
|
+
} from "./chunk-54YZOP7P.js";
|
|
6
|
+
import {
|
|
7
|
+
writeStderrLine
|
|
8
|
+
} from "./chunk-Y6Z2O3WR.js";
|
|
9
|
+
import {
|
|
10
|
+
getActiveGoal
|
|
11
|
+
} from "./chunk-WOG7QWIT.js";
|
|
12
|
+
import {
|
|
13
|
+
ToolNames
|
|
14
|
+
} from "./chunk-X3YGAX7V.js";
|
|
15
|
+
import {
|
|
16
|
+
createDebugLogger
|
|
17
|
+
} from "./chunk-22MNNNXE.js";
|
|
18
|
+
import {
|
|
19
|
+
init_esbuild_shims
|
|
20
|
+
} from "./chunk-A4BMJM77.js";
|
|
21
|
+
import {
|
|
22
|
+
__name,
|
|
23
|
+
__toESM
|
|
24
|
+
} from "./chunk-J2S4EL5Y.js";
|
|
25
|
+
|
|
26
|
+
// packages/cli/src/acp-integration/session/HistoryReplayer.ts
|
|
27
|
+
init_esbuild_shims();
|
|
28
|
+
|
|
29
|
+
// packages/cli/src/acp-integration/session/emitters/MessageEmitter.ts
|
|
30
|
+
init_esbuild_shims();
|
|
31
|
+
|
|
32
|
+
// packages/cli/src/acp-integration/session/emitters/BaseEmitter.ts
|
|
33
|
+
init_esbuild_shims();
|
|
34
|
+
var BaseEmitter = class {
|
|
35
|
+
constructor(ctx) {
|
|
36
|
+
this.ctx = ctx;
|
|
37
|
+
}
|
|
38
|
+
static {
|
|
39
|
+
__name(this, "BaseEmitter");
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Converts an ISO timestamp string or epoch ms to epoch ms number.
|
|
43
|
+
* Returns undefined if the input is not a valid timestamp.
|
|
44
|
+
*/
|
|
45
|
+
static toEpochMs(ts) {
|
|
46
|
+
if (typeof ts === "number") {
|
|
47
|
+
return Number.isFinite(ts) ? ts : void 0;
|
|
48
|
+
}
|
|
49
|
+
if (typeof ts === "string") {
|
|
50
|
+
const ms = new Date(ts).getTime();
|
|
51
|
+
return Number.isFinite(ms) ? ms : void 0;
|
|
52
|
+
}
|
|
53
|
+
return void 0;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Sends a session update to the ACP client.
|
|
57
|
+
* If a message rewriter is configured, updates pass through it first
|
|
58
|
+
* (original messages are sent as-is, rewritten versions are appended).
|
|
59
|
+
*/
|
|
60
|
+
async sendUpdate(update) {
|
|
61
|
+
if (this.ctx.messageRewriter) {
|
|
62
|
+
return this.ctx.messageRewriter.interceptUpdate(update);
|
|
63
|
+
}
|
|
64
|
+
return this.ctx.sendUpdate(update);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Gets the session configuration.
|
|
68
|
+
*/
|
|
69
|
+
get config() {
|
|
70
|
+
return this.ctx.config;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Gets the session ID.
|
|
74
|
+
*/
|
|
75
|
+
get sessionId() {
|
|
76
|
+
return this.ctx.sessionId;
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
// packages/cli/src/acp-integration/session/emitters/MessageEmitter.ts
|
|
81
|
+
var MessageEmitter = class extends BaseEmitter {
|
|
82
|
+
static {
|
|
83
|
+
__name(this, "MessageEmitter");
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Emits a StopHookLoop event when Stop hooks create a loop.
|
|
87
|
+
* This informs the client that Stop hooks have been executed multiple times.
|
|
88
|
+
*
|
|
89
|
+
* @param iterationCount - The current iteration count
|
|
90
|
+
* @param reasons - Array of reasons from each Stop hook execution
|
|
91
|
+
* @param stopHookCount - Number of Stop hooks that were executed
|
|
92
|
+
*/
|
|
93
|
+
async emitStopHookLoop(iterationCount, reasons, stopHookCount) {
|
|
94
|
+
const activeGoal = getActiveGoal(this.sessionId);
|
|
95
|
+
await this.sendUpdate({
|
|
96
|
+
sessionUpdate: "agent_message_chunk",
|
|
97
|
+
content: { type: "text", text: "" },
|
|
98
|
+
_meta: {
|
|
99
|
+
stopHookLoop: {
|
|
100
|
+
iterationCount,
|
|
101
|
+
reasons,
|
|
102
|
+
stopHookCount,
|
|
103
|
+
...activeGoal ? {
|
|
104
|
+
goal: {
|
|
105
|
+
condition: activeGoal.condition,
|
|
106
|
+
iterations: activeGoal.iterations,
|
|
107
|
+
setAt: activeGoal.setAt,
|
|
108
|
+
lastReason: activeGoal.lastReason
|
|
109
|
+
}
|
|
110
|
+
} : {}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
async emitGoalTerminal(event) {
|
|
116
|
+
await this.sendUpdate({
|
|
117
|
+
sessionUpdate: "agent_message_chunk",
|
|
118
|
+
content: { type: "text", text: "" },
|
|
119
|
+
_meta: {
|
|
120
|
+
goalTerminal: event
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
async emitGoalStatus(status) {
|
|
125
|
+
await this.sendUpdate({
|
|
126
|
+
sessionUpdate: "agent_message_chunk",
|
|
127
|
+
content: { type: "text", text: "" },
|
|
128
|
+
_meta: {
|
|
129
|
+
goalStatus: status
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Emits a user message chunk.
|
|
135
|
+
*
|
|
136
|
+
* @param text - The user message text content
|
|
137
|
+
* @param timestamp - Optional server-side timestamp (ISO string or ms) for message ordering
|
|
138
|
+
*/
|
|
139
|
+
async emitUserMessage(text, timestamp) {
|
|
140
|
+
const epochMs = BaseEmitter.toEpochMs(timestamp);
|
|
141
|
+
await this.sendUpdate({
|
|
142
|
+
sessionUpdate: "user_message_chunk",
|
|
143
|
+
content: { type: "text", text },
|
|
144
|
+
...epochMs != null && { _meta: { timestamp: epochMs } }
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Emits an agent thought chunk.
|
|
149
|
+
*
|
|
150
|
+
* @param text - The thought text content
|
|
151
|
+
* @param timestamp - Optional server-side timestamp (ISO string or ms) for message ordering
|
|
152
|
+
*/
|
|
153
|
+
async emitAgentThought(text, timestamp, subagentMeta) {
|
|
154
|
+
const _meta = this.buildChunkMeta(
|
|
155
|
+
BaseEmitter.toEpochMs(timestamp),
|
|
156
|
+
subagentMeta
|
|
157
|
+
);
|
|
158
|
+
await this.sendUpdate({
|
|
159
|
+
sessionUpdate: "agent_thought_chunk",
|
|
160
|
+
content: { type: "text", text },
|
|
161
|
+
..._meta ? { _meta } : {}
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Emits an agent message chunk.
|
|
166
|
+
*
|
|
167
|
+
* @param text - The agent message text content
|
|
168
|
+
* @param timestamp - Optional server-side timestamp (ISO string or ms) for message ordering
|
|
169
|
+
*/
|
|
170
|
+
async emitAgentMessage(text, timestamp, subagentMeta) {
|
|
171
|
+
const _meta = this.buildChunkMeta(
|
|
172
|
+
BaseEmitter.toEpochMs(timestamp),
|
|
173
|
+
subagentMeta
|
|
174
|
+
);
|
|
175
|
+
await this.sendUpdate({
|
|
176
|
+
sessionUpdate: "agent_message_chunk",
|
|
177
|
+
content: { type: "text", text },
|
|
178
|
+
..._meta ? { _meta } : {}
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Emits usage metadata.
|
|
183
|
+
*/
|
|
184
|
+
async emitUsageMetadata(usageMetadata, text = "", durationMs, subagentMeta) {
|
|
185
|
+
const usage = {
|
|
186
|
+
inputTokens: usageMetadata.promptTokenCount ?? 0,
|
|
187
|
+
outputTokens: usageMetadata.candidatesTokenCount ?? 0,
|
|
188
|
+
totalTokens: usageMetadata.totalTokenCount ?? 0,
|
|
189
|
+
thoughtTokens: usageMetadata.thoughtsTokenCount,
|
|
190
|
+
cachedReadTokens: usageMetadata.cachedContentTokenCount
|
|
191
|
+
};
|
|
192
|
+
const cumulative = this.ctx.cumulativeUsage;
|
|
193
|
+
if (cumulative) {
|
|
194
|
+
const addFinite = /* @__PURE__ */ __name((total, value) => typeof value === "number" && Number.isFinite(value) ? total + value : total, "addFinite");
|
|
195
|
+
cumulative.promptTokens = addFinite(
|
|
196
|
+
cumulative.promptTokens,
|
|
197
|
+
usage.inputTokens
|
|
198
|
+
);
|
|
199
|
+
cumulative.candidateTokens = addFinite(
|
|
200
|
+
cumulative.candidateTokens,
|
|
201
|
+
usage.outputTokens
|
|
202
|
+
);
|
|
203
|
+
cumulative.cachedTokens = addFinite(
|
|
204
|
+
cumulative.cachedTokens,
|
|
205
|
+
usage.cachedReadTokens
|
|
206
|
+
);
|
|
207
|
+
cumulative.apiTimeMs = addFinite(cumulative.apiTimeMs, durationMs);
|
|
208
|
+
}
|
|
209
|
+
const meta = typeof durationMs === "number" ? { usage, durationMs, ...subagentMeta } : { usage, ...subagentMeta };
|
|
210
|
+
await this.sendUpdate({
|
|
211
|
+
sessionUpdate: "agent_message_chunk",
|
|
212
|
+
content: { type: "text", text },
|
|
213
|
+
_meta: meta
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Emits a message chunk based on role and thought flag.
|
|
218
|
+
* This is the unified method that handles all message types.
|
|
219
|
+
*
|
|
220
|
+
* @param text - The message text content
|
|
221
|
+
* @param role - Whether this is a user or assistant message
|
|
222
|
+
* @param isThought - Whether this is an assistant thought (only applies to assistant role)
|
|
223
|
+
* @param timestamp - Optional server-side timestamp (ISO string or ms) for message ordering
|
|
224
|
+
*/
|
|
225
|
+
async emitMessage(text, role, isThought = false, timestamp, subagentMeta) {
|
|
226
|
+
if (role === "user") {
|
|
227
|
+
return this.emitUserMessage(text, timestamp);
|
|
228
|
+
}
|
|
229
|
+
return isThought ? this.emitAgentThought(text, timestamp, subagentMeta) : this.emitAgentMessage(text, timestamp, subagentMeta);
|
|
230
|
+
}
|
|
231
|
+
buildChunkMeta(epochMs, subagentMeta) {
|
|
232
|
+
const meta = {
|
|
233
|
+
...subagentMeta?.parentToolCallId ? { parentToolCallId: subagentMeta.parentToolCallId } : {},
|
|
234
|
+
...subagentMeta?.subagentType ? { subagentType: subagentMeta.subagentType } : {},
|
|
235
|
+
...epochMs != null ? { timestamp: epochMs } : {}
|
|
236
|
+
};
|
|
237
|
+
return Object.keys(meta).length > 0 ? meta : void 0;
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
// packages/cli/src/acp-integration/session/emitters/ToolCallEmitter.ts
|
|
242
|
+
init_esbuild_shims();
|
|
243
|
+
|
|
244
|
+
// packages/cli/src/acp-integration/session/emitters/PlanEmitter.ts
|
|
245
|
+
init_esbuild_shims();
|
|
246
|
+
var PlanEmitter = class extends BaseEmitter {
|
|
247
|
+
static {
|
|
248
|
+
__name(this, "PlanEmitter");
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Emits a plan update with the given todo items.
|
|
252
|
+
*
|
|
253
|
+
* @param todos - Array of todo items to send as plan entries
|
|
254
|
+
*/
|
|
255
|
+
async emitPlan(todos) {
|
|
256
|
+
const entries = todos.map((todo) => ({
|
|
257
|
+
content: todo.content,
|
|
258
|
+
priority: "medium",
|
|
259
|
+
// Default priority since todos don't have priority
|
|
260
|
+
status: todo.status
|
|
261
|
+
}));
|
|
262
|
+
const cumulative = this.ctx.cumulativeUsage;
|
|
263
|
+
await this.sendUpdate({
|
|
264
|
+
sessionUpdate: "plan",
|
|
265
|
+
entries,
|
|
266
|
+
...cumulative ? { _meta: { stats: { ...cumulative } } } : {}
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Extracts todos from tool result display or args.
|
|
271
|
+
* Tries multiple sources in priority order:
|
|
272
|
+
* 1. Result display object with type 'todo_list'
|
|
273
|
+
* 2. Result display as JSON string
|
|
274
|
+
* 3. Args with 'todos' array
|
|
275
|
+
*
|
|
276
|
+
* @param resultDisplay - The tool result display (object, string, or undefined)
|
|
277
|
+
* @param args - The tool call arguments (fallback source)
|
|
278
|
+
* @returns Array of todos if found, null otherwise
|
|
279
|
+
*/
|
|
280
|
+
extractTodos(resultDisplay, args) {
|
|
281
|
+
const fromDisplay = this.extractFromResultDisplay(resultDisplay);
|
|
282
|
+
if (fromDisplay) return fromDisplay;
|
|
283
|
+
if (args && Array.isArray(args["todos"])) {
|
|
284
|
+
return args["todos"];
|
|
285
|
+
}
|
|
286
|
+
return null;
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Extracts todos from a result display value.
|
|
290
|
+
* Handles both object and JSON string formats.
|
|
291
|
+
*/
|
|
292
|
+
extractFromResultDisplay(resultDisplay) {
|
|
293
|
+
if (!resultDisplay) return null;
|
|
294
|
+
if (typeof resultDisplay === "object") {
|
|
295
|
+
const obj = resultDisplay;
|
|
296
|
+
if (obj["type"] === "todo_list" && Array.isArray(obj["todos"])) {
|
|
297
|
+
return obj["todos"];
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
if (typeof resultDisplay === "string") {
|
|
301
|
+
try {
|
|
302
|
+
const parsed = JSON.parse(resultDisplay);
|
|
303
|
+
if (parsed?.["type"] === "todo_list" && Array.isArray(parsed["todos"])) {
|
|
304
|
+
return parsed["todos"];
|
|
305
|
+
}
|
|
306
|
+
} catch {
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
return null;
|
|
310
|
+
}
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
// packages/cli/src/utils/truncatedDiffPreview.ts
|
|
314
|
+
init_esbuild_shims();
|
|
315
|
+
function buildTruncatedDiffPreviewText(display) {
|
|
316
|
+
const fileName = typeof display["fileName"] === "string" ? display["fileName"] : "the edited file";
|
|
317
|
+
const fileDiffLength = typeof display["fileDiffLength"] === "number" ? ` Original fileDiff length: ${display["fileDiffLength"]} chars.` : "";
|
|
318
|
+
if (display["fileDiffTruncated"] === true) {
|
|
319
|
+
return `Full diff omitted from saved session history for ${fileName}.${fileDiffLength}`;
|
|
320
|
+
}
|
|
321
|
+
return `Saved session preview only for ${fileName}; full original and new file contents are unavailable.`;
|
|
322
|
+
}
|
|
323
|
+
__name(buildTruncatedDiffPreviewText, "buildTruncatedDiffPreviewText");
|
|
324
|
+
|
|
325
|
+
// packages/cli/src/acp-integration/session/emitters/ToolCallEmitter.ts
|
|
326
|
+
var KIND_MAP = {
|
|
327
|
+
["read" /* Read */]: "read",
|
|
328
|
+
["edit" /* Edit */]: "edit",
|
|
329
|
+
["delete" /* Delete */]: "delete",
|
|
330
|
+
["move" /* Move */]: "move",
|
|
331
|
+
["search" /* Search */]: "search",
|
|
332
|
+
["execute" /* Execute */]: "execute",
|
|
333
|
+
["think" /* Think */]: "think",
|
|
334
|
+
["fetch" /* Fetch */]: "fetch",
|
|
335
|
+
// ACP defines no 'agent' ToolKind (verified through @agentclientprotocol/sdk
|
|
336
|
+
// 0.25.1). The daemon's ClientSideConnection Zod-validates every session/update
|
|
337
|
+
// and session/request_permission from the `qwen --acp` child before fanning out
|
|
338
|
+
// to SSE clients, so emitting 'agent' is rejected at that hop and the frame is
|
|
339
|
+
// dropped. Map the internal Kind.Agent to 'other' on the wire to stay
|
|
340
|
+
// protocol-valid; dedicated agent UI is delivered out-of-band (via _meta.toolName)
|
|
341
|
+
// in a follow-up rather than via a kind the protocol can't carry.
|
|
342
|
+
["agent" /* Agent */]: "other",
|
|
343
|
+
["other" /* Other */]: "other"
|
|
344
|
+
};
|
|
345
|
+
var ToolCallEmitter = class _ToolCallEmitter extends BaseEmitter {
|
|
346
|
+
static {
|
|
347
|
+
__name(this, "ToolCallEmitter");
|
|
348
|
+
}
|
|
349
|
+
planEmitter;
|
|
350
|
+
constructor(ctx) {
|
|
351
|
+
super(ctx);
|
|
352
|
+
this.planEmitter = new PlanEmitter(ctx);
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Emits a tool call start event.
|
|
356
|
+
*
|
|
357
|
+
* @param params - Tool call start parameters
|
|
358
|
+
* @returns true if event was emitted, false if skipped (e.g., TodoWriteTool)
|
|
359
|
+
*/
|
|
360
|
+
async emitStart(params) {
|
|
361
|
+
if (this.isTodoWriteTool(params.toolName)) {
|
|
362
|
+
return false;
|
|
363
|
+
}
|
|
364
|
+
const { title, locations, kind } = this.resolveToolMetadata(
|
|
365
|
+
params.toolName,
|
|
366
|
+
params.args
|
|
367
|
+
);
|
|
368
|
+
const provenance = _ToolCallEmitter.resolveToolProvenance(
|
|
369
|
+
params.toolName,
|
|
370
|
+
params.subagentMeta
|
|
371
|
+
);
|
|
372
|
+
await this.sendUpdate({
|
|
373
|
+
sessionUpdate: "tool_call",
|
|
374
|
+
toolCallId: params.callId,
|
|
375
|
+
status: params.status || "pending",
|
|
376
|
+
title,
|
|
377
|
+
content: [],
|
|
378
|
+
locations,
|
|
379
|
+
kind,
|
|
380
|
+
rawInput: params.args ?? {},
|
|
381
|
+
_meta: {
|
|
382
|
+
toolName: params.toolName,
|
|
383
|
+
...params.subagentMeta,
|
|
384
|
+
provenance: provenance.provenance,
|
|
385
|
+
...provenance.serverId ? { serverId: provenance.serverId } : {},
|
|
386
|
+
...BaseEmitter.toEpochMs(params.timestamp) != null && {
|
|
387
|
+
timestamp: BaseEmitter.toEpochMs(params.timestamp)
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
});
|
|
391
|
+
return true;
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* Emits a tool call result event.
|
|
395
|
+
* Handles TodoWriteTool specially by routing to plan updates.
|
|
396
|
+
*
|
|
397
|
+
* @param params - Tool call result parameters
|
|
398
|
+
*/
|
|
399
|
+
async emitResult(params) {
|
|
400
|
+
if (this.isTodoWriteTool(params.toolName)) {
|
|
401
|
+
const todos = this.planEmitter.extractTodos(
|
|
402
|
+
params.resultDisplay,
|
|
403
|
+
params.args
|
|
404
|
+
);
|
|
405
|
+
if (todos && todos.length > 0) {
|
|
406
|
+
await this.planEmitter.emitPlan(todos);
|
|
407
|
+
} else if (params.args && Array.isArray(params.args["todos"])) {
|
|
408
|
+
await this.planEmitter.emitPlan([]);
|
|
409
|
+
}
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
let contentArray = [];
|
|
413
|
+
const diffContent = this.extractDiffContent(params.resultDisplay);
|
|
414
|
+
if (diffContent) {
|
|
415
|
+
contentArray = [diffContent];
|
|
416
|
+
} else if (params.error) {
|
|
417
|
+
contentArray = [
|
|
418
|
+
{
|
|
419
|
+
type: "content",
|
|
420
|
+
content: { type: "text", text: params.error.message }
|
|
421
|
+
}
|
|
422
|
+
];
|
|
423
|
+
} else {
|
|
424
|
+
contentArray = this.transformPartsToToolCallContent(params.message);
|
|
425
|
+
}
|
|
426
|
+
const provenance = _ToolCallEmitter.resolveToolProvenance(
|
|
427
|
+
params.toolName,
|
|
428
|
+
params.subagentMeta
|
|
429
|
+
);
|
|
430
|
+
const update = {
|
|
431
|
+
sessionUpdate: "tool_call_update",
|
|
432
|
+
toolCallId: params.callId,
|
|
433
|
+
status: params.success ? "completed" : "failed",
|
|
434
|
+
content: contentArray,
|
|
435
|
+
_meta: {
|
|
436
|
+
toolName: params.toolName,
|
|
437
|
+
...params.subagentMeta,
|
|
438
|
+
provenance: provenance.provenance,
|
|
439
|
+
...provenance.serverId ? { serverId: provenance.serverId } : {},
|
|
440
|
+
...BaseEmitter.toEpochMs(params.timestamp) != null && {
|
|
441
|
+
timestamp: BaseEmitter.toEpochMs(params.timestamp)
|
|
442
|
+
},
|
|
443
|
+
...params.artifacts && params.artifacts.length > 0 ? { artifacts: params.artifacts } : {}
|
|
444
|
+
}
|
|
445
|
+
};
|
|
446
|
+
if (params.resultDisplay !== void 0 && !this.isTruncatedSessionDiffDisplay(params.resultDisplay)) {
|
|
447
|
+
update["rawOutput"] = params.resultDisplay;
|
|
448
|
+
}
|
|
449
|
+
await this.sendUpdate(update);
|
|
450
|
+
}
|
|
451
|
+
/**
|
|
452
|
+
* Emits a tool call error event.
|
|
453
|
+
* Use this for explicit error handling when not using emitResult.
|
|
454
|
+
*
|
|
455
|
+
* @param callId - The tool call ID
|
|
456
|
+
* @param toolName - The tool name
|
|
457
|
+
* @param error - The error that occurred
|
|
458
|
+
* @param subagentMeta - Optional subagent metadata
|
|
459
|
+
*/
|
|
460
|
+
async emitError(callId, toolName, error, subagentMeta) {
|
|
461
|
+
const provenance = _ToolCallEmitter.resolveToolProvenance(
|
|
462
|
+
toolName,
|
|
463
|
+
subagentMeta
|
|
464
|
+
);
|
|
465
|
+
await this.sendUpdate({
|
|
466
|
+
sessionUpdate: "tool_call_update",
|
|
467
|
+
toolCallId: callId,
|
|
468
|
+
status: "failed",
|
|
469
|
+
content: [
|
|
470
|
+
{ type: "content", content: { type: "text", text: error.message } }
|
|
471
|
+
],
|
|
472
|
+
_meta: {
|
|
473
|
+
toolName,
|
|
474
|
+
...subagentMeta,
|
|
475
|
+
provenance: provenance.provenance,
|
|
476
|
+
...provenance.serverId ? { serverId: provenance.serverId } : {}
|
|
477
|
+
}
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
481
|
+
* Resolve a tool's provenance for UI dispatch on tool_call events.
|
|
482
|
+
* The SDK reads `_meta.
|
|
483
|
+
* provenance` + `_meta.serverId` to render builtin / MCP-server-badge /
|
|
484
|
+
* subagent-block differently. Without this stamping, the SDK falls
|
|
485
|
+
* back to string-matching the toolName which can't reliably
|
|
486
|
+
* distinguish builtin from subagent.
|
|
487
|
+
*
|
|
488
|
+
* Resolution rules:
|
|
489
|
+
* - `subagentMeta` present → `'subagent'` (a Task tool / Codex
|
|
490
|
+
* subagent / etc. wrapping its own tool calls)
|
|
491
|
+
* - toolName matches `mcp__<server>__<tool>` → `'mcp'` with
|
|
492
|
+
* `serverId: <server>`. Naming convention from
|
|
493
|
+
* `packages/core/src/tools/mcp-tool.ts` in the
|
|
494
|
+
* `@qwen-code/qwen-code-core` package — mirrors the SDK's same
|
|
495
|
+
* heuristic fallback so SDK consumers stay consistent with
|
|
496
|
+
* daemon classification.
|
|
497
|
+
* - everything else → `'builtin'`
|
|
498
|
+
*
|
|
499
|
+
* Static + pure so it can be unit-tested without an emitter
|
|
500
|
+
* instance. Exported via `ToolCallEmitter.resolveToolProvenance`.
|
|
501
|
+
*/
|
|
502
|
+
static resolveToolProvenance(toolName, subagentMeta) {
|
|
503
|
+
if (subagentMeta !== void 0) {
|
|
504
|
+
return { provenance: "subagent" };
|
|
505
|
+
}
|
|
506
|
+
if (toolName.startsWith("mcp__")) {
|
|
507
|
+
const parts = toolName.split("__");
|
|
508
|
+
if (parts.length >= 3 && parts[1] && parts[1].length > 0) {
|
|
509
|
+
return { provenance: "mcp", serverId: parts[1] };
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
return { provenance: "builtin" };
|
|
513
|
+
}
|
|
514
|
+
// ==================== Public Utilities ====================
|
|
515
|
+
/**
|
|
516
|
+
* Checks if a tool name is the TodoWriteTool.
|
|
517
|
+
* Exposed for external use in components that need to check this.
|
|
518
|
+
*/
|
|
519
|
+
isTodoWriteTool(toolName) {
|
|
520
|
+
return toolName === ToolNames.TODO_WRITE;
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* Checks if a tool name is the ExitPlanModeTool.
|
|
524
|
+
*/
|
|
525
|
+
isExitPlanModeTool(toolName) {
|
|
526
|
+
return toolName === ToolNames.EXIT_PLAN_MODE;
|
|
527
|
+
}
|
|
528
|
+
/**
|
|
529
|
+
* Checks if a tool name is the EnterPlanModeTool.
|
|
530
|
+
*/
|
|
531
|
+
isEnterPlanModeTool(toolName) {
|
|
532
|
+
return toolName === ToolNames.ENTER_PLAN_MODE;
|
|
533
|
+
}
|
|
534
|
+
/**
|
|
535
|
+
* Resolves tool metadata from the registry.
|
|
536
|
+
* Falls back to defaults if tool not found or build fails.
|
|
537
|
+
*
|
|
538
|
+
* @param toolName - Name of the tool
|
|
539
|
+
* @param args - Tool call arguments (used to build invocation)
|
|
540
|
+
*/
|
|
541
|
+
resolveToolMetadata(toolName, args) {
|
|
542
|
+
const toolRegistry = this.config.getToolRegistry();
|
|
543
|
+
const tool = toolRegistry.getTool(toolName);
|
|
544
|
+
let title = tool?.displayName ?? toolName;
|
|
545
|
+
let locations = [];
|
|
546
|
+
let kind = "other";
|
|
547
|
+
if (tool && args) {
|
|
548
|
+
try {
|
|
549
|
+
const invocation = tool.build(args);
|
|
550
|
+
title = `${title}: ${invocation.getDescription()}`;
|
|
551
|
+
locations = invocation.toolLocations().map((loc) => ({
|
|
552
|
+
path: loc.path,
|
|
553
|
+
line: loc.line ?? null
|
|
554
|
+
}));
|
|
555
|
+
kind = this.mapToolKind(tool.kind, toolName);
|
|
556
|
+
} catch {
|
|
557
|
+
if (typeof args["description"] === "string") {
|
|
558
|
+
title = `${title}: ${args["description"]}`;
|
|
559
|
+
}
|
|
560
|
+
if (tool.kind) {
|
|
561
|
+
kind = this.mapToolKind(tool.kind, toolName);
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
return { title, locations, kind };
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* Maps core Tool Kind enum to ACP ToolKind string literals.
|
|
569
|
+
*
|
|
570
|
+
* @param kind - The core Kind enum value
|
|
571
|
+
* @param toolName - Optional tool name to handle special cases like exit_plan_mode
|
|
572
|
+
*/
|
|
573
|
+
mapToolKind(kind, toolName) {
|
|
574
|
+
if (toolName && (this.isExitPlanModeTool(toolName) || this.isEnterPlanModeTool(toolName))) {
|
|
575
|
+
return "switch_mode";
|
|
576
|
+
}
|
|
577
|
+
return KIND_MAP[kind] ?? "other";
|
|
578
|
+
}
|
|
579
|
+
// ==================== Private Helpers ====================
|
|
580
|
+
/**
|
|
581
|
+
* Extracts diff content from resultDisplay if it's a diff type (edit tool result).
|
|
582
|
+
* Returns null if not a diff.
|
|
583
|
+
*/
|
|
584
|
+
extractDiffContent(resultDisplay) {
|
|
585
|
+
if (!resultDisplay || typeof resultDisplay !== "object") return null;
|
|
586
|
+
const obj = resultDisplay;
|
|
587
|
+
if ("fileName" in obj && "newContent" in obj) {
|
|
588
|
+
if (this.isTruncatedSessionDiffDisplay(resultDisplay)) {
|
|
589
|
+
return {
|
|
590
|
+
type: "content",
|
|
591
|
+
content: {
|
|
592
|
+
type: "text",
|
|
593
|
+
text: buildTruncatedDiffPreviewText(obj)
|
|
594
|
+
}
|
|
595
|
+
};
|
|
596
|
+
}
|
|
597
|
+
return {
|
|
598
|
+
type: "diff",
|
|
599
|
+
path: obj["fileName"],
|
|
600
|
+
oldText: obj["originalContent"] ?? "",
|
|
601
|
+
newText: obj["newContent"]
|
|
602
|
+
};
|
|
603
|
+
}
|
|
604
|
+
return null;
|
|
605
|
+
}
|
|
606
|
+
isTruncatedSessionDiffDisplay(resultDisplay) {
|
|
607
|
+
if (!resultDisplay || typeof resultDisplay !== "object") return false;
|
|
608
|
+
const obj = resultDisplay;
|
|
609
|
+
return obj["truncatedForSession"] === true && "fileName" in obj && "newContent" in obj;
|
|
610
|
+
}
|
|
611
|
+
/**
|
|
612
|
+
* Transforms Part[] to ToolCallContent[].
|
|
613
|
+
* Extracts text from functionResponse parts and text parts.
|
|
614
|
+
*/
|
|
615
|
+
transformPartsToToolCallContent(parts) {
|
|
616
|
+
const result = [];
|
|
617
|
+
for (const part of parts) {
|
|
618
|
+
if ("text" in part && part.text) {
|
|
619
|
+
result.push({
|
|
620
|
+
type: "content",
|
|
621
|
+
content: { type: "text", text: part.text }
|
|
622
|
+
});
|
|
623
|
+
}
|
|
624
|
+
if ("functionResponse" in part && part.functionResponse) {
|
|
625
|
+
try {
|
|
626
|
+
const resp = part.functionResponse.response;
|
|
627
|
+
const outputField = resp["output"];
|
|
628
|
+
const errorField = resp["error"];
|
|
629
|
+
const responseText = typeof outputField === "string" ? outputField : typeof errorField === "string" ? errorField : JSON.stringify(resp);
|
|
630
|
+
result.push({
|
|
631
|
+
type: "content",
|
|
632
|
+
content: { type: "text", text: responseText }
|
|
633
|
+
});
|
|
634
|
+
} catch {
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
return result;
|
|
639
|
+
}
|
|
640
|
+
};
|
|
641
|
+
|
|
642
|
+
// packages/cli/src/utils/chat-record-tool-call-id.ts
|
|
643
|
+
init_esbuild_shims();
|
|
644
|
+
function getToolResultCallId(record) {
|
|
645
|
+
return getExplicitToolResultCallId(record) ?? record.uuid;
|
|
646
|
+
}
|
|
647
|
+
__name(getToolResultCallId, "getToolResultCallId");
|
|
648
|
+
function getExplicitToolResultCallId(record) {
|
|
649
|
+
const resultCallId = record.toolCallResult?.callId;
|
|
650
|
+
if (typeof resultCallId === "string" && resultCallId.length > 0) {
|
|
651
|
+
return resultCallId;
|
|
652
|
+
}
|
|
653
|
+
return extractFunctionResponseId(record);
|
|
654
|
+
}
|
|
655
|
+
__name(getExplicitToolResultCallId, "getExplicitToolResultCallId");
|
|
656
|
+
function extractFunctionResponseId(record) {
|
|
657
|
+
if (!record.message?.parts) {
|
|
658
|
+
return void 0;
|
|
659
|
+
}
|
|
660
|
+
for (const part of record.message.parts) {
|
|
661
|
+
const id = "functionResponse" in part ? part.functionResponse?.id : void 0;
|
|
662
|
+
if (typeof id === "string" && id.length > 0) {
|
|
663
|
+
return id;
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
return void 0;
|
|
667
|
+
}
|
|
668
|
+
__name(extractFunctionResponseId, "extractFunctionResponseId");
|
|
669
|
+
|
|
670
|
+
// packages/cli/src/acp-integration/session/HistoryReplayer.ts
|
|
671
|
+
var MISSING_TOOL_RESULT_MESSAGE = "Tool result missing from saved history; the previous run likely ended before this tool completed.";
|
|
672
|
+
var HistoryReplayer = class {
|
|
673
|
+
static {
|
|
674
|
+
__name(this, "HistoryReplayer");
|
|
675
|
+
}
|
|
676
|
+
ctx;
|
|
677
|
+
messageEmitter;
|
|
678
|
+
toolCallEmitter;
|
|
679
|
+
pendingReplayToolCalls = /* @__PURE__ */ new Map();
|
|
680
|
+
constructor(ctx) {
|
|
681
|
+
this.ctx = ctx;
|
|
682
|
+
this.messageEmitter = new MessageEmitter(ctx);
|
|
683
|
+
this.toolCallEmitter = new ToolCallEmitter(ctx);
|
|
684
|
+
}
|
|
685
|
+
/**
|
|
686
|
+
* Replays all chat records from a loaded session.
|
|
687
|
+
*
|
|
688
|
+
* @param records - Array of chat records to replay
|
|
689
|
+
*/
|
|
690
|
+
async replay(records) {
|
|
691
|
+
this.pendingReplayToolCalls.clear();
|
|
692
|
+
try {
|
|
693
|
+
let replayError;
|
|
694
|
+
try {
|
|
695
|
+
for (const record of records) {
|
|
696
|
+
await this.replayRecord(record);
|
|
697
|
+
}
|
|
698
|
+
} catch (error) {
|
|
699
|
+
replayError = error;
|
|
700
|
+
}
|
|
701
|
+
let danglingError;
|
|
702
|
+
try {
|
|
703
|
+
await this.failDanglingToolCalls();
|
|
704
|
+
} catch (error) {
|
|
705
|
+
danglingError = error;
|
|
706
|
+
}
|
|
707
|
+
if (replayError && danglingError) {
|
|
708
|
+
throw new AggregateError(
|
|
709
|
+
[replayError, danglingError],
|
|
710
|
+
"Replay and dangling-cleanup both failed"
|
|
711
|
+
);
|
|
712
|
+
}
|
|
713
|
+
if (replayError) {
|
|
714
|
+
throw replayError;
|
|
715
|
+
}
|
|
716
|
+
if (danglingError) {
|
|
717
|
+
throw danglingError;
|
|
718
|
+
}
|
|
719
|
+
} finally {
|
|
720
|
+
this.pendingReplayToolCalls.clear();
|
|
721
|
+
this.setActiveRecordId(null);
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
/**
|
|
725
|
+
* Replays a single chat record.
|
|
726
|
+
*/
|
|
727
|
+
async replayRecord(record) {
|
|
728
|
+
this.setActiveRecordId(record.uuid, record.timestamp);
|
|
729
|
+
try {
|
|
730
|
+
switch (record.type) {
|
|
731
|
+
case "user":
|
|
732
|
+
if (record.subtype === "notification" || record.subtype === "cron") {
|
|
733
|
+
const displayText = record.systemPayload?.displayText;
|
|
734
|
+
if (displayText) {
|
|
735
|
+
await this.messageEmitter.emitUserMessage(
|
|
736
|
+
displayText,
|
|
737
|
+
record.timestamp
|
|
738
|
+
);
|
|
739
|
+
}
|
|
740
|
+
break;
|
|
741
|
+
}
|
|
742
|
+
if (record.subtype === "mid_turn_user_message") {
|
|
743
|
+
const displayText = record.systemPayload?.displayText;
|
|
744
|
+
if (displayText) {
|
|
745
|
+
await this.messageEmitter.emitUserMessage(
|
|
746
|
+
displayText,
|
|
747
|
+
record.timestamp
|
|
748
|
+
);
|
|
749
|
+
} else if (record.message) {
|
|
750
|
+
await this.replayContent(
|
|
751
|
+
record.message,
|
|
752
|
+
"user",
|
|
753
|
+
record.timestamp,
|
|
754
|
+
record.uuid
|
|
755
|
+
);
|
|
756
|
+
}
|
|
757
|
+
break;
|
|
758
|
+
}
|
|
759
|
+
if (record.message) {
|
|
760
|
+
await this.replayContent(
|
|
761
|
+
record.message,
|
|
762
|
+
"user",
|
|
763
|
+
record.timestamp,
|
|
764
|
+
record.uuid
|
|
765
|
+
);
|
|
766
|
+
}
|
|
767
|
+
break;
|
|
768
|
+
case "assistant":
|
|
769
|
+
if (record.message) {
|
|
770
|
+
await this.replayContent(
|
|
771
|
+
record.message,
|
|
772
|
+
"assistant",
|
|
773
|
+
record.timestamp,
|
|
774
|
+
record.uuid
|
|
775
|
+
);
|
|
776
|
+
}
|
|
777
|
+
if (record.usageMetadata) {
|
|
778
|
+
await this.replayUsageMetadata(record.usageMetadata);
|
|
779
|
+
}
|
|
780
|
+
break;
|
|
781
|
+
case "tool_result":
|
|
782
|
+
await this.replayToolResult(record);
|
|
783
|
+
break;
|
|
784
|
+
case "system":
|
|
785
|
+
if (record.subtype === "slash_command") {
|
|
786
|
+
await this.replaySlashCommandResult(record);
|
|
787
|
+
}
|
|
788
|
+
break;
|
|
789
|
+
default:
|
|
790
|
+
break;
|
|
791
|
+
}
|
|
792
|
+
} finally {
|
|
793
|
+
this.setActiveRecordId(null);
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
/**
|
|
797
|
+
* Replays content from a message (user or assistant).
|
|
798
|
+
* Handles text parts, thought parts, and function calls.
|
|
799
|
+
*
|
|
800
|
+
* @param content - The content to replay
|
|
801
|
+
* @param role - The role (user or assistant)
|
|
802
|
+
* @param timestamp - Optional server-side timestamp from the JSONL record
|
|
803
|
+
*/
|
|
804
|
+
async replayContent(content, role, timestamp, recordId) {
|
|
805
|
+
for (const part of content.parts ?? []) {
|
|
806
|
+
if ("text" in part && part.text) {
|
|
807
|
+
const isThought = part.thought ?? false;
|
|
808
|
+
await this.messageEmitter.emitMessage(
|
|
809
|
+
part.text,
|
|
810
|
+
role,
|
|
811
|
+
isThought,
|
|
812
|
+
timestamp
|
|
813
|
+
);
|
|
814
|
+
}
|
|
815
|
+
if ("functionCall" in part && part.functionCall) {
|
|
816
|
+
const functionName = part.functionCall.name ?? "";
|
|
817
|
+
const sourceCallId = part.functionCall.id;
|
|
818
|
+
const callId = sourceCallId ?? `${functionName}-${Date.now()}`;
|
|
819
|
+
const emitted = await this.toolCallEmitter.emitStart({
|
|
820
|
+
toolName: functionName,
|
|
821
|
+
callId,
|
|
822
|
+
args: part.functionCall.args,
|
|
823
|
+
status: "in_progress",
|
|
824
|
+
timestamp
|
|
825
|
+
});
|
|
826
|
+
if (emitted && role === "assistant" && recordId && sourceCallId) {
|
|
827
|
+
this.pendingReplayToolCalls.set(callId, {
|
|
828
|
+
callId,
|
|
829
|
+
toolName: functionName,
|
|
830
|
+
timestamp,
|
|
831
|
+
recordId
|
|
832
|
+
});
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
/**
|
|
838
|
+
* Replays usage metadata.
|
|
839
|
+
* @param usageMetadata - The usage metadata to replay
|
|
840
|
+
*/
|
|
841
|
+
async replayUsageMetadata(usageMetadata) {
|
|
842
|
+
await this.messageEmitter.emitUsageMetadata(usageMetadata);
|
|
843
|
+
}
|
|
844
|
+
/**
|
|
845
|
+
* Replays a tool result record.
|
|
846
|
+
*/
|
|
847
|
+
async replayToolResult(record) {
|
|
848
|
+
if (!record.message?.parts) {
|
|
849
|
+
return;
|
|
850
|
+
}
|
|
851
|
+
const result = record.toolCallResult;
|
|
852
|
+
const callId = getToolResultCallId(record);
|
|
853
|
+
this.pendingReplayToolCalls.delete(callId);
|
|
854
|
+
const toolName = this.extractToolNameFromRecord(record);
|
|
855
|
+
await this.toolCallEmitter.emitResult({
|
|
856
|
+
toolName,
|
|
857
|
+
callId,
|
|
858
|
+
success: !result?.error,
|
|
859
|
+
message: record.message.parts,
|
|
860
|
+
resultDisplay: result?.resultDisplay,
|
|
861
|
+
// For TodoWriteTool fallback, try to extract args from the record
|
|
862
|
+
// Note: args aren't stored in tool_result records by default
|
|
863
|
+
args: void 0,
|
|
864
|
+
timestamp: record.timestamp
|
|
865
|
+
});
|
|
866
|
+
const { resultDisplay } = result ?? {};
|
|
867
|
+
if (!!resultDisplay && typeof resultDisplay === "object" && "type" in resultDisplay && resultDisplay.type === "task_execution") {
|
|
868
|
+
await this.emitTaskUsageFromResultDisplay(
|
|
869
|
+
resultDisplay
|
|
870
|
+
);
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
async failDanglingToolCalls() {
|
|
874
|
+
let firstError;
|
|
875
|
+
for (const pending of this.pendingReplayToolCalls.values()) {
|
|
876
|
+
this.setActiveRecordId(pending.recordId, pending.timestamp);
|
|
877
|
+
try {
|
|
878
|
+
await this.toolCallEmitter.emitResult({
|
|
879
|
+
toolName: pending.toolName,
|
|
880
|
+
callId: pending.callId,
|
|
881
|
+
success: false,
|
|
882
|
+
message: [],
|
|
883
|
+
error: new Error(MISSING_TOOL_RESULT_MESSAGE),
|
|
884
|
+
timestamp: pending.timestamp
|
|
885
|
+
});
|
|
886
|
+
} catch (error) {
|
|
887
|
+
firstError ??= error;
|
|
888
|
+
} finally {
|
|
889
|
+
this.setActiveRecordId(null);
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
if (firstError) {
|
|
893
|
+
throw firstError;
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
/**
|
|
897
|
+
* Emits token usage from a AgentResultDisplay execution summary, if present.
|
|
898
|
+
*/
|
|
899
|
+
async emitTaskUsageFromResultDisplay(resultDisplay) {
|
|
900
|
+
const summary = resultDisplay.executionSummary;
|
|
901
|
+
if (!summary) {
|
|
902
|
+
return;
|
|
903
|
+
}
|
|
904
|
+
const usageMetadata = {};
|
|
905
|
+
if (Number.isFinite(summary.inputTokens)) {
|
|
906
|
+
usageMetadata.promptTokenCount = summary.inputTokens;
|
|
907
|
+
}
|
|
908
|
+
if (Number.isFinite(summary.outputTokens)) {
|
|
909
|
+
usageMetadata.candidatesTokenCount = summary.outputTokens;
|
|
910
|
+
}
|
|
911
|
+
if (Number.isFinite(summary.thoughtTokens)) {
|
|
912
|
+
usageMetadata.thoughtsTokenCount = summary.thoughtTokens;
|
|
913
|
+
}
|
|
914
|
+
if (Number.isFinite(summary.cachedTokens)) {
|
|
915
|
+
usageMetadata.cachedContentTokenCount = summary.cachedTokens;
|
|
916
|
+
}
|
|
917
|
+
if (Number.isFinite(summary.totalTokens)) {
|
|
918
|
+
usageMetadata.totalTokenCount = summary.totalTokens;
|
|
919
|
+
}
|
|
920
|
+
if (Object.keys(usageMetadata).length > 0) {
|
|
921
|
+
await this.messageEmitter.emitUsageMetadata(usageMetadata);
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
/**
|
|
925
|
+
* Replays a slash_command system record by re-emitting its output as an
|
|
926
|
+
* agent message chunk. This allows Zed to reconstruct the correct turn
|
|
927
|
+
* structure (user → agent) on session resume without polluting model context.
|
|
928
|
+
*/
|
|
929
|
+
async replaySlashCommandResult(record) {
|
|
930
|
+
const payload = record.systemPayload;
|
|
931
|
+
if (payload?.phase !== "result" || !payload.outputHistoryItems?.length) {
|
|
932
|
+
return;
|
|
933
|
+
}
|
|
934
|
+
for (const item of payload.outputHistoryItems) {
|
|
935
|
+
const text = typeof item["text"] === "string" ? item["text"] : "";
|
|
936
|
+
if (text) {
|
|
937
|
+
await this.messageEmitter.emitAgentMessage(
|
|
938
|
+
text.replace(/\n/g, " \n"),
|
|
939
|
+
record.timestamp
|
|
940
|
+
);
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
/**
|
|
945
|
+
* Extracts tool name from a chat record's function response.
|
|
946
|
+
*/
|
|
947
|
+
extractToolNameFromRecord(record) {
|
|
948
|
+
if (record.message?.parts) {
|
|
949
|
+
for (const part of record.message.parts) {
|
|
950
|
+
if ("functionResponse" in part && part.functionResponse?.name) {
|
|
951
|
+
return part.functionResponse.name;
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
return "";
|
|
956
|
+
}
|
|
957
|
+
setActiveRecordId(recordId, timestamp) {
|
|
958
|
+
const context = this.ctx;
|
|
959
|
+
if (typeof context.setActiveRecordId === "function") {
|
|
960
|
+
context.setActiveRecordId(recordId, timestamp);
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
};
|
|
964
|
+
|
|
965
|
+
// packages/cli/src/services/setup-github.ts
|
|
966
|
+
init_esbuild_shims();
|
|
967
|
+
var import_undici2 = __toESM(require_undici(), 1);
|
|
968
|
+
import { promises as fsp } from "node:fs";
|
|
969
|
+
import * as path from "node:path";
|
|
970
|
+
|
|
971
|
+
// packages/cli/src/utils/gitUtils.ts
|
|
972
|
+
init_esbuild_shims();
|
|
973
|
+
var import_undici = __toESM(require_undici(), 1);
|
|
974
|
+
import * as childProcess from "node:child_process";
|
|
975
|
+
var debugLogger = createDebugLogger("GIT");
|
|
976
|
+
async function runGit(args, opts = {}) {
|
|
977
|
+
return await new Promise((resolve2, reject) => {
|
|
978
|
+
childProcess.execFile(
|
|
979
|
+
"git",
|
|
980
|
+
args,
|
|
981
|
+
{
|
|
982
|
+
encoding: "utf-8",
|
|
983
|
+
...opts.cwd ? { cwd: opts.cwd } : {}
|
|
984
|
+
},
|
|
985
|
+
(err, stdout) => {
|
|
986
|
+
if (err) {
|
|
987
|
+
reject(err);
|
|
988
|
+
return;
|
|
989
|
+
}
|
|
990
|
+
resolve2(String(stdout ?? "").trim());
|
|
991
|
+
}
|
|
992
|
+
);
|
|
993
|
+
});
|
|
994
|
+
}
|
|
995
|
+
__name(runGit, "runGit");
|
|
996
|
+
var isGitHubRepositoryAsync = /* @__PURE__ */ __name(async (opts = {}) => {
|
|
997
|
+
try {
|
|
998
|
+
const remotes = await runGit(["remote", "-v"], opts);
|
|
999
|
+
return remotes.split("\n").some((line) => {
|
|
1000
|
+
const remoteUrl = line.trim().split(/\s+/)[1];
|
|
1001
|
+
return remoteUrl ? isGitHubRemoteUrl(remoteUrl) : false;
|
|
1002
|
+
});
|
|
1003
|
+
} catch (_error) {
|
|
1004
|
+
debugLogger.debug(`Failed to get git remote:`, _error);
|
|
1005
|
+
return false;
|
|
1006
|
+
}
|
|
1007
|
+
}, "isGitHubRepositoryAsync");
|
|
1008
|
+
function isGitHubRemoteUrl(remoteUrl) {
|
|
1009
|
+
if (remoteUrl.startsWith("git@github.com:")) {
|
|
1010
|
+
return true;
|
|
1011
|
+
}
|
|
1012
|
+
if (remoteUrl.startsWith("git@")) {
|
|
1013
|
+
return false;
|
|
1014
|
+
}
|
|
1015
|
+
try {
|
|
1016
|
+
return new URL(remoteUrl).hostname === "github.com";
|
|
1017
|
+
} catch {
|
|
1018
|
+
return false;
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
__name(isGitHubRemoteUrl, "isGitHubRemoteUrl");
|
|
1022
|
+
var getGitRepoRootAsync = /* @__PURE__ */ __name(async (opts = {}) => {
|
|
1023
|
+
const gitRepoRoot = await runGit(["rev-parse", "--show-toplevel"], opts);
|
|
1024
|
+
if (!gitRepoRoot) {
|
|
1025
|
+
throw new Error(`Git repo returned empty value`);
|
|
1026
|
+
}
|
|
1027
|
+
return gitRepoRoot;
|
|
1028
|
+
}, "getGitRepoRootAsync");
|
|
1029
|
+
var getLatestGitHubRelease = /* @__PURE__ */ __name(async (proxy) => {
|
|
1030
|
+
try {
|
|
1031
|
+
const controller = new AbortController();
|
|
1032
|
+
const endpoint = `https://api.github.com/repos/QwenLM/qwen-code-action/releases/latest`;
|
|
1033
|
+
const response = await fetch(endpoint, {
|
|
1034
|
+
method: "GET",
|
|
1035
|
+
headers: {
|
|
1036
|
+
Accept: "application/vnd.github+json",
|
|
1037
|
+
"Content-Type": "application/json",
|
|
1038
|
+
"X-GitHub-Api-Version": "2022-11-28"
|
|
1039
|
+
},
|
|
1040
|
+
dispatcher: proxy ? new import_undici.ProxyAgent(proxy) : void 0,
|
|
1041
|
+
signal: AbortSignal.any([AbortSignal.timeout(3e4), controller.signal])
|
|
1042
|
+
});
|
|
1043
|
+
if (!response.ok) {
|
|
1044
|
+
throw new Error(
|
|
1045
|
+
`Invalid response code: ${response.status} - ${response.statusText}`
|
|
1046
|
+
);
|
|
1047
|
+
}
|
|
1048
|
+
const releaseTag = (await response.json()).tag_name;
|
|
1049
|
+
if (!releaseTag) {
|
|
1050
|
+
throw new Error(`Response did not include tag_name field`);
|
|
1051
|
+
}
|
|
1052
|
+
return releaseTag;
|
|
1053
|
+
} catch (_error) {
|
|
1054
|
+
debugLogger.debug(
|
|
1055
|
+
`Failed to determine latest qwen-code-action release:`,
|
|
1056
|
+
_error
|
|
1057
|
+
);
|
|
1058
|
+
throw new Error(
|
|
1059
|
+
`Unable to determine the latest qwen-code-action release on GitHub.`
|
|
1060
|
+
);
|
|
1061
|
+
}
|
|
1062
|
+
}, "getLatestGitHubRelease");
|
|
1063
|
+
async function getGitHubRepoInfoAsync(opts = {}) {
|
|
1064
|
+
return parseGitHubRepoInfo(
|
|
1065
|
+
await runGit(["remote", "get-url", "origin"], opts)
|
|
1066
|
+
);
|
|
1067
|
+
}
|
|
1068
|
+
__name(getGitHubRepoInfoAsync, "getGitHubRepoInfoAsync");
|
|
1069
|
+
function parseGitHubRepoInfo(remoteUrl) {
|
|
1070
|
+
let urlToParse = remoteUrl;
|
|
1071
|
+
if (remoteUrl.startsWith("git@github.com:")) {
|
|
1072
|
+
urlToParse = remoteUrl.replace("git@github.com:", "");
|
|
1073
|
+
} else if (remoteUrl.startsWith("git@")) {
|
|
1074
|
+
throw new Error(
|
|
1075
|
+
`Owner & repo could not be extracted from remote URL: ${remoteUrl}`
|
|
1076
|
+
);
|
|
1077
|
+
}
|
|
1078
|
+
let parsedUrl;
|
|
1079
|
+
try {
|
|
1080
|
+
parsedUrl = new URL(urlToParse, "https://github.com");
|
|
1081
|
+
} catch {
|
|
1082
|
+
throw new Error(
|
|
1083
|
+
`Owner & repo could not be extracted from remote URL: ${remoteUrl}`
|
|
1084
|
+
);
|
|
1085
|
+
}
|
|
1086
|
+
if (parsedUrl.hostname !== "github.com") {
|
|
1087
|
+
throw new Error(
|
|
1088
|
+
`Owner & repo could not be extracted from remote URL: ${remoteUrl}`
|
|
1089
|
+
);
|
|
1090
|
+
}
|
|
1091
|
+
const parts = parsedUrl.pathname.split("/").filter((part) => part !== "");
|
|
1092
|
+
if (parts.length !== 2 || !parts[0] || !parts[1]) {
|
|
1093
|
+
throw new Error(
|
|
1094
|
+
`Owner & repo could not be extracted from remote URL: ${remoteUrl}`
|
|
1095
|
+
);
|
|
1096
|
+
}
|
|
1097
|
+
return { owner: parts[0], repo: parts[1].replace(/\.git$/, "") };
|
|
1098
|
+
}
|
|
1099
|
+
__name(parseGitHubRepoInfo, "parseGitHubRepoInfo");
|
|
1100
|
+
|
|
1101
|
+
// packages/cli/src/services/setup-github.ts
|
|
1102
|
+
var debugLogger2 = createDebugLogger("SETUP_GITHUB");
|
|
1103
|
+
var GITHUB_WORKFLOW_PATHS = [
|
|
1104
|
+
"qwen-dispatch/qwen-dispatch.yml",
|
|
1105
|
+
"qwen-assistant/qwen-invoke.yml",
|
|
1106
|
+
"issue-triage/qwen-triage.yml",
|
|
1107
|
+
"issue-triage/qwen-scheduled-triage.yml",
|
|
1108
|
+
"pr-review/qwen-review.yml"
|
|
1109
|
+
];
|
|
1110
|
+
var GITIGNORE_ENTRIES = [".qwen/", "gha-creds-*.json"];
|
|
1111
|
+
var MAX_WORKFLOW_DOWNLOAD_BYTES = 5 * 1024 * 1024;
|
|
1112
|
+
var SetupGithubError = class extends Error {
|
|
1113
|
+
static {
|
|
1114
|
+
__name(this, "SetupGithubError");
|
|
1115
|
+
}
|
|
1116
|
+
code;
|
|
1117
|
+
status;
|
|
1118
|
+
partial;
|
|
1119
|
+
partialResult;
|
|
1120
|
+
constructor(code, message, status, partialResult) {
|
|
1121
|
+
super(message);
|
|
1122
|
+
this.name = "SetupGithubError";
|
|
1123
|
+
this.code = code;
|
|
1124
|
+
this.status = status;
|
|
1125
|
+
this.partial = partialResult !== void 0;
|
|
1126
|
+
this.partialResult = partialResult;
|
|
1127
|
+
}
|
|
1128
|
+
};
|
|
1129
|
+
var nodeFileOps = {
|
|
1130
|
+
assertCanWrite() {
|
|
1131
|
+
},
|
|
1132
|
+
async ensureWorkflowDirectory(gitRepoRoot) {
|
|
1133
|
+
await fsp.mkdir(path.join(gitRepoRoot, ".github", "workflows"), {
|
|
1134
|
+
recursive: true
|
|
1135
|
+
});
|
|
1136
|
+
},
|
|
1137
|
+
async writeTextFile(gitRepoRoot, relativePath, content) {
|
|
1138
|
+
const target = path.join(gitRepoRoot, relativePath);
|
|
1139
|
+
await fsp.writeFile(target, content, { mode: 420 });
|
|
1140
|
+
return { sizeBytes: Buffer.byteLength(content, "utf8") };
|
|
1141
|
+
},
|
|
1142
|
+
async readTextFile(gitRepoRoot, relativePath) {
|
|
1143
|
+
try {
|
|
1144
|
+
return await fsp.readFile(path.join(gitRepoRoot, relativePath), "utf8");
|
|
1145
|
+
} catch (error) {
|
|
1146
|
+
if (error.code === "ENOENT") {
|
|
1147
|
+
return void 0;
|
|
1148
|
+
}
|
|
1149
|
+
throw error;
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
};
|
|
1153
|
+
async function setupGithub(options = {}) {
|
|
1154
|
+
const cwd = options.cwd ?? process.cwd();
|
|
1155
|
+
const fileOps = options.fileOps ?? nodeFileOps;
|
|
1156
|
+
if (!await isGitHubRepositoryAsync({ cwd })) {
|
|
1157
|
+
throw new SetupGithubError(
|
|
1158
|
+
"github_repository_not_found",
|
|
1159
|
+
"Unable to determine the GitHub repository. /setup-github must be run from a git repository.",
|
|
1160
|
+
400
|
|
1161
|
+
);
|
|
1162
|
+
}
|
|
1163
|
+
let gitRepoRoot;
|
|
1164
|
+
try {
|
|
1165
|
+
gitRepoRoot = await getGitRepoRootAsync({ cwd });
|
|
1166
|
+
} catch (error) {
|
|
1167
|
+
debugLogger2.debug("Failed to get git repo root:", error);
|
|
1168
|
+
throw new SetupGithubError(
|
|
1169
|
+
"github_repository_not_found",
|
|
1170
|
+
"Unable to determine the GitHub repository. /setup-github must be run from a git repository.",
|
|
1171
|
+
400
|
|
1172
|
+
);
|
|
1173
|
+
}
|
|
1174
|
+
if (options.workspaceRoot) {
|
|
1175
|
+
const [gitRootReal, workspaceReal] = await Promise.all([
|
|
1176
|
+
realpathOrResolve(gitRepoRoot),
|
|
1177
|
+
realpathOrResolve(options.workspaceRoot)
|
|
1178
|
+
]);
|
|
1179
|
+
if (gitRootReal !== workspaceReal) {
|
|
1180
|
+
throw new SetupGithubError(
|
|
1181
|
+
"github_git_root_mismatch",
|
|
1182
|
+
"The Git repository root must match the daemon workspace root.",
|
|
1183
|
+
400
|
|
1184
|
+
);
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
fileOps.assertCanWrite?.();
|
|
1188
|
+
let releaseTag;
|
|
1189
|
+
try {
|
|
1190
|
+
releaseTag = await getLatestGitHubRelease(options.proxy);
|
|
1191
|
+
} catch (error) {
|
|
1192
|
+
writeStderrLine(
|
|
1193
|
+
`qwen setup-github: failed to determine latest qwen-code-action release: ${error instanceof Error ? error.message : String(error)}`
|
|
1194
|
+
);
|
|
1195
|
+
debugLogger2.debug(
|
|
1196
|
+
"Failed to determine latest qwen-code-action release:",
|
|
1197
|
+
error
|
|
1198
|
+
);
|
|
1199
|
+
throw new SetupGithubError(
|
|
1200
|
+
"github_release_lookup_failed",
|
|
1201
|
+
"Unable to determine the latest qwen-code-action release on GitHub.",
|
|
1202
|
+
502
|
|
1203
|
+
);
|
|
1204
|
+
}
|
|
1205
|
+
const readmeUrl = `https://github.com/QwenLM/qwen-code-action/blob/${releaseTag}/README.md#quick-start`;
|
|
1206
|
+
const secretsUrl = await resolveSecretsUrl(cwd);
|
|
1207
|
+
const downloads = await downloadWorkflows({
|
|
1208
|
+
releaseTag,
|
|
1209
|
+
proxy: options.proxy,
|
|
1210
|
+
abortSignal: options.abortSignal,
|
|
1211
|
+
fetchImpl: options.fetchImpl ?? fetch
|
|
1212
|
+
});
|
|
1213
|
+
const result = {
|
|
1214
|
+
kind: "github_setup",
|
|
1215
|
+
workspaceCwd: options.workspaceRoot ?? gitRepoRoot,
|
|
1216
|
+
gitRepoRoot,
|
|
1217
|
+
releaseTag,
|
|
1218
|
+
readmeUrl,
|
|
1219
|
+
...secretsUrl ? { secretsUrl } : {},
|
|
1220
|
+
workflows: [],
|
|
1221
|
+
gitignore: { path: ".gitignore", status: "skipped" },
|
|
1222
|
+
warnings: []
|
|
1223
|
+
};
|
|
1224
|
+
result.gitignore = await updateGitignore(gitRepoRoot, fileOps);
|
|
1225
|
+
if (result.gitignore.status === "failed") {
|
|
1226
|
+
result.warnings.push("Failed to update .gitignore.");
|
|
1227
|
+
}
|
|
1228
|
+
try {
|
|
1229
|
+
await fileOps.ensureWorkflowDirectory(gitRepoRoot);
|
|
1230
|
+
for (const workflow of downloads) {
|
|
1231
|
+
const relativePath = path.posix.join(
|
|
1232
|
+
".github",
|
|
1233
|
+
"workflows",
|
|
1234
|
+
path.posix.basename(workflow.sourcePath)
|
|
1235
|
+
);
|
|
1236
|
+
try {
|
|
1237
|
+
const write = await fileOps.writeTextFile(
|
|
1238
|
+
gitRepoRoot,
|
|
1239
|
+
relativePath,
|
|
1240
|
+
workflow.content
|
|
1241
|
+
);
|
|
1242
|
+
result.workflows.push({
|
|
1243
|
+
sourcePath: workflow.sourcePath,
|
|
1244
|
+
path: relativePath,
|
|
1245
|
+
status: "written",
|
|
1246
|
+
sizeBytes: write.sizeBytes
|
|
1247
|
+
});
|
|
1248
|
+
} catch (error) {
|
|
1249
|
+
result.partial = true;
|
|
1250
|
+
result.workflows.push({
|
|
1251
|
+
sourcePath: workflow.sourcePath,
|
|
1252
|
+
path: relativePath,
|
|
1253
|
+
status: "failed",
|
|
1254
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1255
|
+
});
|
|
1256
|
+
throw new SetupGithubError(
|
|
1257
|
+
"github_workflow_write_failed",
|
|
1258
|
+
`Unable to write ${relativePath}.`,
|
|
1259
|
+
500,
|
|
1260
|
+
result
|
|
1261
|
+
);
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1264
|
+
} catch (error) {
|
|
1265
|
+
if (error instanceof SetupGithubError) throw error;
|
|
1266
|
+
throw new SetupGithubError(
|
|
1267
|
+
"github_workflow_write_failed",
|
|
1268
|
+
"Unable to create .github/workflows.",
|
|
1269
|
+
500,
|
|
1270
|
+
result
|
|
1271
|
+
);
|
|
1272
|
+
}
|
|
1273
|
+
return result;
|
|
1274
|
+
}
|
|
1275
|
+
__name(setupGithub, "setupGithub");
|
|
1276
|
+
async function updateGitignore(gitRepoRoot, fileOps = nodeFileOps) {
|
|
1277
|
+
try {
|
|
1278
|
+
const existingContent = await fileOps.readTextFile(
|
|
1279
|
+
gitRepoRoot,
|
|
1280
|
+
".gitignore"
|
|
1281
|
+
);
|
|
1282
|
+
if (existingContent === void 0) {
|
|
1283
|
+
const content = GITIGNORE_ENTRIES.join("\n") + "\n";
|
|
1284
|
+
await fileOps.writeTextFile(gitRepoRoot, ".gitignore", content);
|
|
1285
|
+
return {
|
|
1286
|
+
path: ".gitignore",
|
|
1287
|
+
status: "created",
|
|
1288
|
+
added: [...GITIGNORE_ENTRIES]
|
|
1289
|
+
};
|
|
1290
|
+
}
|
|
1291
|
+
const missingEntries = GITIGNORE_ENTRIES.filter(
|
|
1292
|
+
(entry) => !existingContent.split(/\r?\n/).some((line) => line.split("#")[0].trim() === entry)
|
|
1293
|
+
);
|
|
1294
|
+
if (missingEntries.length === 0) {
|
|
1295
|
+
return { path: ".gitignore", status: "unchanged" };
|
|
1296
|
+
}
|
|
1297
|
+
const nextContent = existingContent + "\n" + missingEntries.join("\n") + "\n";
|
|
1298
|
+
await fileOps.writeTextFile(gitRepoRoot, ".gitignore", nextContent);
|
|
1299
|
+
return {
|
|
1300
|
+
path: ".gitignore",
|
|
1301
|
+
status: "updated",
|
|
1302
|
+
added: missingEntries
|
|
1303
|
+
};
|
|
1304
|
+
} catch (error) {
|
|
1305
|
+
debugLogger2.debug("Failed to update .gitignore:", error);
|
|
1306
|
+
return {
|
|
1307
|
+
path: ".gitignore",
|
|
1308
|
+
status: "failed",
|
|
1309
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1310
|
+
};
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1313
|
+
__name(updateGitignore, "updateGitignore");
|
|
1314
|
+
async function downloadWorkflows(options) {
|
|
1315
|
+
const internalAbort = new AbortController();
|
|
1316
|
+
try {
|
|
1317
|
+
const dispatcher = options.proxy ? new import_undici2.ProxyAgent(options.proxy) : void 0;
|
|
1318
|
+
return await Promise.all(
|
|
1319
|
+
GITHUB_WORKFLOW_PATHS.map(async (workflow) => {
|
|
1320
|
+
const endpoint = `https://raw.githubusercontent.com/QwenLM/qwen-code-action/refs/tags/${options.releaseTag}/examples/workflows/${workflow}`;
|
|
1321
|
+
const response = await options.fetchImpl(endpoint, {
|
|
1322
|
+
method: "GET",
|
|
1323
|
+
dispatcher,
|
|
1324
|
+
signal: AbortSignal.any([
|
|
1325
|
+
AbortSignal.timeout(3e4),
|
|
1326
|
+
internalAbort.signal,
|
|
1327
|
+
...options.abortSignal ? [options.abortSignal] : []
|
|
1328
|
+
])
|
|
1329
|
+
});
|
|
1330
|
+
if (!response.ok) {
|
|
1331
|
+
throw new Error(
|
|
1332
|
+
`Invalid response code downloading ${endpoint}: ${response.status} - ${response.statusText}`
|
|
1333
|
+
);
|
|
1334
|
+
}
|
|
1335
|
+
return {
|
|
1336
|
+
sourcePath: workflow,
|
|
1337
|
+
content: await readResponseTextWithLimit(response, workflow)
|
|
1338
|
+
};
|
|
1339
|
+
})
|
|
1340
|
+
);
|
|
1341
|
+
} catch (error) {
|
|
1342
|
+
internalAbort.abort();
|
|
1343
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1344
|
+
debugLogger2.debug("Failed to download qwen-code-action workflows:", error);
|
|
1345
|
+
throw new SetupGithubError(
|
|
1346
|
+
"github_workflow_download_failed",
|
|
1347
|
+
`Unable to download qwen-code-action workflows from GitHub. ${message}`,
|
|
1348
|
+
502
|
|
1349
|
+
);
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1352
|
+
__name(downloadWorkflows, "downloadWorkflows");
|
|
1353
|
+
async function readResponseTextWithLimit(response, sourcePath) {
|
|
1354
|
+
const contentLength = response.headers.get("content-length");
|
|
1355
|
+
if (contentLength !== null) {
|
|
1356
|
+
const parsedLength = Number(contentLength);
|
|
1357
|
+
if (Number.isFinite(parsedLength) && parsedLength > MAX_WORKFLOW_DOWNLOAD_BYTES) {
|
|
1358
|
+
throw new Error(
|
|
1359
|
+
`${sourcePath} exceeds download limit of ${MAX_WORKFLOW_DOWNLOAD_BYTES} bytes`
|
|
1360
|
+
);
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
if (!response.body) return "";
|
|
1364
|
+
const reader = response.body.getReader();
|
|
1365
|
+
const chunks = [];
|
|
1366
|
+
let totalBytes = 0;
|
|
1367
|
+
try {
|
|
1368
|
+
while (true) {
|
|
1369
|
+
const { done, value } = await reader.read();
|
|
1370
|
+
if (done) break;
|
|
1371
|
+
if (!value) continue;
|
|
1372
|
+
totalBytes += value.byteLength;
|
|
1373
|
+
if (totalBytes > MAX_WORKFLOW_DOWNLOAD_BYTES) {
|
|
1374
|
+
await reader.cancel().catch(() => {
|
|
1375
|
+
});
|
|
1376
|
+
throw new Error(
|
|
1377
|
+
`${sourcePath} exceeds download limit of ${MAX_WORKFLOW_DOWNLOAD_BYTES} bytes`
|
|
1378
|
+
);
|
|
1379
|
+
}
|
|
1380
|
+
chunks.push(value);
|
|
1381
|
+
}
|
|
1382
|
+
} finally {
|
|
1383
|
+
reader.releaseLock();
|
|
1384
|
+
}
|
|
1385
|
+
const body = new Uint8Array(totalBytes);
|
|
1386
|
+
let offset = 0;
|
|
1387
|
+
for (const chunk of chunks) {
|
|
1388
|
+
body.set(chunk, offset);
|
|
1389
|
+
offset += chunk.byteLength;
|
|
1390
|
+
}
|
|
1391
|
+
return new TextDecoder().decode(body);
|
|
1392
|
+
}
|
|
1393
|
+
__name(readResponseTextWithLimit, "readResponseTextWithLimit");
|
|
1394
|
+
async function resolveSecretsUrl(cwd) {
|
|
1395
|
+
try {
|
|
1396
|
+
const repoInfo = await getGitHubRepoInfoAsync({ cwd });
|
|
1397
|
+
return `https://github.com/${repoInfo.owner}/${repoInfo.repo}/settings/secrets/actions`;
|
|
1398
|
+
} catch {
|
|
1399
|
+
return void 0;
|
|
1400
|
+
}
|
|
1401
|
+
}
|
|
1402
|
+
__name(resolveSecretsUrl, "resolveSecretsUrl");
|
|
1403
|
+
async function realpathOrResolve(input) {
|
|
1404
|
+
try {
|
|
1405
|
+
return await fsp.realpath(input);
|
|
1406
|
+
} catch {
|
|
1407
|
+
return path.resolve(input);
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
__name(realpathOrResolve, "realpathOrResolve");
|
|
1411
|
+
|
|
1412
|
+
// packages/cli/src/ui/utils/export/collect.ts
|
|
1413
|
+
init_esbuild_shims();
|
|
1414
|
+
import { randomUUID } from "node:crypto";
|
|
1415
|
+
function extractToolNameFromRecord(record) {
|
|
1416
|
+
if (!record.message?.parts) {
|
|
1417
|
+
return void 0;
|
|
1418
|
+
}
|
|
1419
|
+
for (const part of record.message.parts) {
|
|
1420
|
+
if ("functionResponse" in part && part.functionResponse?.name) {
|
|
1421
|
+
return part.functionResponse.name;
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1424
|
+
return void 0;
|
|
1425
|
+
}
|
|
1426
|
+
__name(extractToolNameFromRecord, "extractToolNameFromRecord");
|
|
1427
|
+
function normalizeFunctionCallArgs(args) {
|
|
1428
|
+
if (args && typeof args === "object") {
|
|
1429
|
+
return args;
|
|
1430
|
+
}
|
|
1431
|
+
if (typeof args === "string") {
|
|
1432
|
+
try {
|
|
1433
|
+
const parsed = JSON.parse(args);
|
|
1434
|
+
if (parsed && typeof parsed === "object") {
|
|
1435
|
+
return parsed;
|
|
1436
|
+
}
|
|
1437
|
+
} catch {
|
|
1438
|
+
}
|
|
1439
|
+
}
|
|
1440
|
+
return void 0;
|
|
1441
|
+
}
|
|
1442
|
+
__name(normalizeFunctionCallArgs, "normalizeFunctionCallArgs");
|
|
1443
|
+
function buildToolCallArgsIndex(records) {
|
|
1444
|
+
const byId = /* @__PURE__ */ new Map();
|
|
1445
|
+
const byName = /* @__PURE__ */ new Map();
|
|
1446
|
+
for (const record of records) {
|
|
1447
|
+
if (record.type !== "assistant" || !record.message?.parts) continue;
|
|
1448
|
+
for (const part of record.message.parts) {
|
|
1449
|
+
if (!("functionCall" in part) || !part.functionCall?.name) continue;
|
|
1450
|
+
const normalizedArgs = normalizeFunctionCallArgs(part.functionCall.args);
|
|
1451
|
+
if (!normalizedArgs) continue;
|
|
1452
|
+
const toolName = part.functionCall.name;
|
|
1453
|
+
const callId = typeof part.functionCall.id === "string" ? part.functionCall.id : null;
|
|
1454
|
+
if (callId) {
|
|
1455
|
+
byId.set(callId, normalizedArgs);
|
|
1456
|
+
}
|
|
1457
|
+
const queue = byName.get(toolName) ?? [];
|
|
1458
|
+
queue.push(normalizedArgs);
|
|
1459
|
+
byName.set(toolName, queue);
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
return { byId, byName };
|
|
1463
|
+
}
|
|
1464
|
+
__name(buildToolCallArgsIndex, "buildToolCallArgsIndex");
|
|
1465
|
+
function calculateFileStats(records) {
|
|
1466
|
+
const argsIndex = buildToolCallArgsIndex(records);
|
|
1467
|
+
const byNameCursor = /* @__PURE__ */ new Map();
|
|
1468
|
+
const stats = {
|
|
1469
|
+
filesWritten: 0,
|
|
1470
|
+
linesAdded: 0,
|
|
1471
|
+
linesRemoved: 0,
|
|
1472
|
+
writtenFilePaths: /* @__PURE__ */ new Set()
|
|
1473
|
+
};
|
|
1474
|
+
for (const record of records) {
|
|
1475
|
+
if (record.type !== "tool_result" || !record.toolCallResult) continue;
|
|
1476
|
+
const toolName = extractToolNameFromRecord(record);
|
|
1477
|
+
const callId = getExplicitToolResultCallId(record);
|
|
1478
|
+
const argsFromId = callId && argsIndex.byId.has(callId) ? argsIndex.byId.get(callId) : void 0;
|
|
1479
|
+
let args = argsFromId;
|
|
1480
|
+
if (!args && toolName) {
|
|
1481
|
+
const queue = argsIndex.byName.get(toolName);
|
|
1482
|
+
if (queue && queue.length > 0) {
|
|
1483
|
+
const cursor = byNameCursor.get(toolName) ?? 0;
|
|
1484
|
+
args = queue[cursor];
|
|
1485
|
+
byNameCursor.set(toolName, cursor + 1);
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1488
|
+
const { resultDisplay } = record.toolCallResult;
|
|
1489
|
+
if (resultDisplay && typeof resultDisplay === "object" && "fileName" in resultDisplay) {
|
|
1490
|
+
const display = resultDisplay;
|
|
1491
|
+
const hasOriginalContent = "originalContent" in display;
|
|
1492
|
+
const hasNewContent = "newContent" in display;
|
|
1493
|
+
let filePath;
|
|
1494
|
+
if (typeof display.fileName === "string") {
|
|
1495
|
+
filePath = args?.["file_path"] || display.fileName;
|
|
1496
|
+
} else {
|
|
1497
|
+
filePath = "unknown";
|
|
1498
|
+
}
|
|
1499
|
+
if (hasOriginalContent || hasNewContent) {
|
|
1500
|
+
stats.filesWritten++;
|
|
1501
|
+
stats.writtenFilePaths.add(filePath);
|
|
1502
|
+
if (display.diffStat) {
|
|
1503
|
+
stats.linesAdded += display.diffStat.model_added_lines ?? 0;
|
|
1504
|
+
stats.linesRemoved += display.diffStat.model_removed_lines ?? 0;
|
|
1505
|
+
} else if (!display.truncatedForSession) {
|
|
1506
|
+
const oldText = String(display.originalContent ?? "");
|
|
1507
|
+
const newText = String(display.newContent ?? "");
|
|
1508
|
+
const oldLines = oldText.split("\n").filter((line) => line.length > 0).length;
|
|
1509
|
+
const newLines = newText.split("\n").filter((line) => line.length > 0).length;
|
|
1510
|
+
stats.linesAdded += newLines;
|
|
1511
|
+
stats.linesRemoved += oldLines;
|
|
1512
|
+
}
|
|
1513
|
+
}
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1516
|
+
return stats;
|
|
1517
|
+
}
|
|
1518
|
+
__name(calculateFileStats, "calculateFileStats");
|
|
1519
|
+
function extractTaskToolTokens(record) {
|
|
1520
|
+
if (record.type !== "tool_result" || !record.toolCallResult?.resultDisplay) {
|
|
1521
|
+
return 0;
|
|
1522
|
+
}
|
|
1523
|
+
const { resultDisplay } = record.toolCallResult;
|
|
1524
|
+
if (typeof resultDisplay === "object" && "type" in resultDisplay && resultDisplay.type === "task_execution" && "executionSummary" in resultDisplay) {
|
|
1525
|
+
const summary = resultDisplay.executionSummary;
|
|
1526
|
+
if (typeof summary.totalTokens === "number") {
|
|
1527
|
+
return summary.totalTokens;
|
|
1528
|
+
}
|
|
1529
|
+
return (summary.inputTokens ?? 0) + (summary.outputTokens ?? 0) + (summary.thoughtTokens ?? 0) + (summary.cachedTokens ?? 0);
|
|
1530
|
+
}
|
|
1531
|
+
return 0;
|
|
1532
|
+
}
|
|
1533
|
+
__name(extractTaskToolTokens, "extractTaskToolTokens");
|
|
1534
|
+
function calculateTokenStats(records) {
|
|
1535
|
+
let totalTokens = 0;
|
|
1536
|
+
let lastValidRecord = null;
|
|
1537
|
+
for (const record of records) {
|
|
1538
|
+
if (record.type === "assistant") {
|
|
1539
|
+
if (record.usageMetadata) {
|
|
1540
|
+
totalTokens += record.usageMetadata.totalTokenCount ?? 0;
|
|
1541
|
+
}
|
|
1542
|
+
if (record.usageMetadata?.totalTokenCount !== void 0 && record.contextWindowSize !== void 0) {
|
|
1543
|
+
lastValidRecord = {
|
|
1544
|
+
totalTokenCount: record.usageMetadata.totalTokenCount,
|
|
1545
|
+
contextWindowSize: record.contextWindowSize
|
|
1546
|
+
};
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1549
|
+
const taskTokens = extractTaskToolTokens(record);
|
|
1550
|
+
if (taskTokens > 0) {
|
|
1551
|
+
totalTokens += taskTokens;
|
|
1552
|
+
}
|
|
1553
|
+
}
|
|
1554
|
+
if (lastValidRecord) {
|
|
1555
|
+
const percent = lastValidRecord.totalTokenCount / lastValidRecord.contextWindowSize * 100;
|
|
1556
|
+
return {
|
|
1557
|
+
totalTokens,
|
|
1558
|
+
contextUsagePercent: Math.round(percent * 10) / 10,
|
|
1559
|
+
contextWindowSize: lastValidRecord.contextWindowSize
|
|
1560
|
+
};
|
|
1561
|
+
}
|
|
1562
|
+
const lastAssistantRecord = [...records].reverse().find((r) => r.type === "assistant" && r.contextWindowSize !== void 0);
|
|
1563
|
+
return {
|
|
1564
|
+
totalTokens,
|
|
1565
|
+
contextWindowSize: lastAssistantRecord?.contextWindowSize
|
|
1566
|
+
};
|
|
1567
|
+
}
|
|
1568
|
+
__name(calculateTokenStats, "calculateTokenStats");
|
|
1569
|
+
function createExportSessionConfig(config) {
|
|
1570
|
+
const supportedConfig = {
|
|
1571
|
+
...config,
|
|
1572
|
+
getToolRegistry: /* @__PURE__ */ __name(() => {
|
|
1573
|
+
const registry = config.getToolRegistry?.();
|
|
1574
|
+
return {
|
|
1575
|
+
getTool: /* @__PURE__ */ __name((toolName) => registry?.getTool?.(toolName) ?? null, "getTool")
|
|
1576
|
+
};
|
|
1577
|
+
}, "getToolRegistry")
|
|
1578
|
+
};
|
|
1579
|
+
return new Proxy(supportedConfig, {
|
|
1580
|
+
get(target, prop, receiver) {
|
|
1581
|
+
if (prop in target) {
|
|
1582
|
+
return Reflect.get(target, prop, receiver);
|
|
1583
|
+
}
|
|
1584
|
+
if (typeof prop === "symbol") {
|
|
1585
|
+
return void 0;
|
|
1586
|
+
}
|
|
1587
|
+
throw new Error(
|
|
1588
|
+
`Export session replay config does not implement ${prop}`
|
|
1589
|
+
);
|
|
1590
|
+
}
|
|
1591
|
+
});
|
|
1592
|
+
}
|
|
1593
|
+
__name(createExportSessionConfig, "createExportSessionConfig");
|
|
1594
|
+
async function extractMetadata(conversation, config) {
|
|
1595
|
+
const { sessionId, startTime, messages } = conversation;
|
|
1596
|
+
const firstRecord = messages[0];
|
|
1597
|
+
const cwd = firstRecord?.cwd ?? "";
|
|
1598
|
+
const gitBranch = firstRecord?.gitBranch;
|
|
1599
|
+
let gitRepo;
|
|
1600
|
+
if (cwd) {
|
|
1601
|
+
const { getGitRepoName } = await import("./src-ZORBMUM7.js");
|
|
1602
|
+
gitRepo = getGitRepoName(cwd);
|
|
1603
|
+
}
|
|
1604
|
+
let model;
|
|
1605
|
+
for (const record of messages) {
|
|
1606
|
+
if (record.type === "assistant" && record.model) {
|
|
1607
|
+
model = record.model;
|
|
1608
|
+
break;
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1611
|
+
const channel = config.getChannel?.();
|
|
1612
|
+
const promptCount = messages.filter((m) => m.type === "user").length;
|
|
1613
|
+
const fileStats = calculateFileStats(messages);
|
|
1614
|
+
const tokenStats = calculateTokenStats(messages);
|
|
1615
|
+
return {
|
|
1616
|
+
sessionId,
|
|
1617
|
+
startTime,
|
|
1618
|
+
exportTime: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1619
|
+
cwd,
|
|
1620
|
+
gitRepo,
|
|
1621
|
+
gitBranch,
|
|
1622
|
+
model,
|
|
1623
|
+
channel,
|
|
1624
|
+
promptCount,
|
|
1625
|
+
contextUsagePercent: tokenStats.contextUsagePercent,
|
|
1626
|
+
contextWindowSize: tokenStats.contextWindowSize,
|
|
1627
|
+
totalTokens: tokenStats.totalTokens,
|
|
1628
|
+
filesWritten: fileStats.writtenFilePaths.size,
|
|
1629
|
+
linesAdded: fileStats.linesAdded,
|
|
1630
|
+
linesRemoved: fileStats.linesRemoved,
|
|
1631
|
+
uniqueFiles: Array.from(fileStats.writtenFilePaths)
|
|
1632
|
+
};
|
|
1633
|
+
}
|
|
1634
|
+
__name(extractMetadata, "extractMetadata");
|
|
1635
|
+
var ExportSessionContext = class {
|
|
1636
|
+
static {
|
|
1637
|
+
__name(this, "ExportSessionContext");
|
|
1638
|
+
}
|
|
1639
|
+
sessionId;
|
|
1640
|
+
config;
|
|
1641
|
+
messages = [];
|
|
1642
|
+
currentMessage = null;
|
|
1643
|
+
activeRecordId = null;
|
|
1644
|
+
activeRecordTimestamp = null;
|
|
1645
|
+
toolCallMap = /* @__PURE__ */ new Map();
|
|
1646
|
+
constructor(sessionId, config) {
|
|
1647
|
+
this.sessionId = sessionId;
|
|
1648
|
+
this.config = createExportSessionConfig(config);
|
|
1649
|
+
}
|
|
1650
|
+
async sendUpdate(update) {
|
|
1651
|
+
switch (update.sessionUpdate) {
|
|
1652
|
+
case "user_message_chunk":
|
|
1653
|
+
this.handleMessageChunk("user", update.content);
|
|
1654
|
+
break;
|
|
1655
|
+
case "agent_message_chunk": {
|
|
1656
|
+
const usageMeta = update._meta;
|
|
1657
|
+
const usageMetadata = usageMeta?.usage ? {
|
|
1658
|
+
promptTokenCount: usageMeta.usage.inputTokens,
|
|
1659
|
+
candidatesTokenCount: usageMeta.usage.outputTokens,
|
|
1660
|
+
totalTokenCount: usageMeta.usage.totalTokens,
|
|
1661
|
+
thoughtsTokenCount: usageMeta.usage.thoughtTokens,
|
|
1662
|
+
cachedContentTokenCount: usageMeta.usage.cachedReadTokens
|
|
1663
|
+
} : void 0;
|
|
1664
|
+
this.handleMessageChunk(
|
|
1665
|
+
"assistant",
|
|
1666
|
+
update.content,
|
|
1667
|
+
"assistant",
|
|
1668
|
+
usageMetadata
|
|
1669
|
+
);
|
|
1670
|
+
break;
|
|
1671
|
+
}
|
|
1672
|
+
case "agent_thought_chunk":
|
|
1673
|
+
this.handleMessageChunk("assistant", update.content, "thinking");
|
|
1674
|
+
break;
|
|
1675
|
+
case "tool_call":
|
|
1676
|
+
this.flushCurrentMessage();
|
|
1677
|
+
this.handleToolCallStart(update);
|
|
1678
|
+
break;
|
|
1679
|
+
case "tool_call_update":
|
|
1680
|
+
this.handleToolCallUpdate(update);
|
|
1681
|
+
break;
|
|
1682
|
+
case "plan":
|
|
1683
|
+
this.flushCurrentMessage();
|
|
1684
|
+
this.handlePlanUpdate(update);
|
|
1685
|
+
break;
|
|
1686
|
+
default:
|
|
1687
|
+
break;
|
|
1688
|
+
}
|
|
1689
|
+
}
|
|
1690
|
+
setActiveRecordId(recordId, timestamp) {
|
|
1691
|
+
this.activeRecordId = recordId;
|
|
1692
|
+
this.activeRecordTimestamp = timestamp ?? null;
|
|
1693
|
+
}
|
|
1694
|
+
getMessageTimestamp() {
|
|
1695
|
+
return this.activeRecordTimestamp ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
1696
|
+
}
|
|
1697
|
+
getMessageUuid() {
|
|
1698
|
+
return this.activeRecordId ?? randomUUID();
|
|
1699
|
+
}
|
|
1700
|
+
handleMessageChunk(role, content, messageRole = role, usageMetadata) {
|
|
1701
|
+
if (content.type !== "text" || !content.text) return;
|
|
1702
|
+
if (this.currentMessage && (this.currentMessage.type !== role || this.currentMessage.role !== messageRole)) {
|
|
1703
|
+
this.flushCurrentMessage();
|
|
1704
|
+
}
|
|
1705
|
+
if (this.currentMessage && this.currentMessage.type === role && this.currentMessage.role === messageRole) {
|
|
1706
|
+
this.currentMessage.parts.push({ text: content.text });
|
|
1707
|
+
if (usageMetadata && role === "assistant") {
|
|
1708
|
+
this.currentMessage.usageMetadata = usageMetadata;
|
|
1709
|
+
}
|
|
1710
|
+
} else {
|
|
1711
|
+
this.currentMessage = {
|
|
1712
|
+
type: role,
|
|
1713
|
+
role: messageRole,
|
|
1714
|
+
parts: [{ text: content.text }],
|
|
1715
|
+
timestamp: Date.now(),
|
|
1716
|
+
...usageMetadata && role === "assistant" ? { usageMetadata } : {}
|
|
1717
|
+
};
|
|
1718
|
+
}
|
|
1719
|
+
}
|
|
1720
|
+
handleToolCallStart(update) {
|
|
1721
|
+
const toolCall = {
|
|
1722
|
+
toolCallId: update.toolCallId,
|
|
1723
|
+
kind: update.kind || "other",
|
|
1724
|
+
title: typeof update.title === "string" ? update.title : update.title || "",
|
|
1725
|
+
status: update.status || "pending",
|
|
1726
|
+
rawInput: update.rawInput,
|
|
1727
|
+
locations: update.locations,
|
|
1728
|
+
timestamp: Date.now()
|
|
1729
|
+
};
|
|
1730
|
+
this.toolCallMap.set(update.toolCallId, toolCall);
|
|
1731
|
+
const uuid = this.getMessageUuid();
|
|
1732
|
+
this.messages.push({
|
|
1733
|
+
uuid,
|
|
1734
|
+
sessionId: this.sessionId,
|
|
1735
|
+
timestamp: this.getMessageTimestamp(),
|
|
1736
|
+
type: "tool_call",
|
|
1737
|
+
toolCall
|
|
1738
|
+
});
|
|
1739
|
+
}
|
|
1740
|
+
handleToolCallUpdate(update) {
|
|
1741
|
+
const toolCall = this.toolCallMap.get(update.toolCallId);
|
|
1742
|
+
if (toolCall) {
|
|
1743
|
+
if (update.status) toolCall.status = update.status;
|
|
1744
|
+
if (update.content) toolCall.content = update.content;
|
|
1745
|
+
if (update.title)
|
|
1746
|
+
toolCall.title = typeof update.title === "string" ? update.title : "";
|
|
1747
|
+
}
|
|
1748
|
+
}
|
|
1749
|
+
handlePlanUpdate(update) {
|
|
1750
|
+
const uuid = this.getMessageUuid();
|
|
1751
|
+
const timestamp = this.getMessageTimestamp();
|
|
1752
|
+
const todoText = update.entries.map((entry) => {
|
|
1753
|
+
const checkbox = entry.status === "completed" ? "[x]" : entry.status === "in_progress" ? "[-]" : "[ ]";
|
|
1754
|
+
return `- ${checkbox} ${entry.content}`;
|
|
1755
|
+
}).join("\n");
|
|
1756
|
+
const todoContent = [
|
|
1757
|
+
{
|
|
1758
|
+
type: "content",
|
|
1759
|
+
content: {
|
|
1760
|
+
type: "text",
|
|
1761
|
+
text: todoText
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1764
|
+
];
|
|
1765
|
+
this.messages.push({
|
|
1766
|
+
uuid,
|
|
1767
|
+
sessionId: this.sessionId,
|
|
1768
|
+
timestamp,
|
|
1769
|
+
type: "tool_call",
|
|
1770
|
+
toolCall: {
|
|
1771
|
+
toolCallId: uuid,
|
|
1772
|
+
// Use the same uuid as toolCallId for plan updates
|
|
1773
|
+
kind: "todowrite",
|
|
1774
|
+
title: "TodoList",
|
|
1775
|
+
status: "completed",
|
|
1776
|
+
content: todoContent,
|
|
1777
|
+
timestamp: Date.parse(timestamp)
|
|
1778
|
+
}
|
|
1779
|
+
});
|
|
1780
|
+
}
|
|
1781
|
+
flushCurrentMessage() {
|
|
1782
|
+
if (!this.currentMessage) return;
|
|
1783
|
+
const uuid = this.getMessageUuid();
|
|
1784
|
+
const exportMessage = {
|
|
1785
|
+
uuid,
|
|
1786
|
+
sessionId: this.sessionId,
|
|
1787
|
+
timestamp: this.getMessageTimestamp(),
|
|
1788
|
+
type: this.currentMessage.type,
|
|
1789
|
+
message: {
|
|
1790
|
+
role: this.currentMessage.role,
|
|
1791
|
+
parts: this.currentMessage.parts
|
|
1792
|
+
}
|
|
1793
|
+
};
|
|
1794
|
+
if (this.currentMessage.type === "assistant" && this.currentMessage.usageMetadata) {
|
|
1795
|
+
exportMessage.usageMetadata = this.currentMessage.usageMetadata;
|
|
1796
|
+
}
|
|
1797
|
+
this.messages.push(exportMessage);
|
|
1798
|
+
this.currentMessage = null;
|
|
1799
|
+
}
|
|
1800
|
+
flushMessages() {
|
|
1801
|
+
this.flushCurrentMessage();
|
|
1802
|
+
}
|
|
1803
|
+
getMessages() {
|
|
1804
|
+
return this.messages;
|
|
1805
|
+
}
|
|
1806
|
+
};
|
|
1807
|
+
async function collectSessionData(conversation, config) {
|
|
1808
|
+
const exportContext = new ExportSessionContext(
|
|
1809
|
+
conversation.sessionId,
|
|
1810
|
+
config
|
|
1811
|
+
);
|
|
1812
|
+
const replayer = new HistoryReplayer(exportContext);
|
|
1813
|
+
await replayer.replay(conversation.messages);
|
|
1814
|
+
exportContext.flushMessages();
|
|
1815
|
+
const messages = exportContext.getMessages();
|
|
1816
|
+
const metadata = await extractMetadata(conversation, config);
|
|
1817
|
+
return {
|
|
1818
|
+
sessionId: conversation.sessionId,
|
|
1819
|
+
startTime: conversation.startTime,
|
|
1820
|
+
messages,
|
|
1821
|
+
metadata
|
|
1822
|
+
};
|
|
1823
|
+
}
|
|
1824
|
+
__name(collectSessionData, "collectSessionData");
|
|
1825
|
+
|
|
1826
|
+
// packages/cli/src/ui/utils/export/normalize.ts
|
|
1827
|
+
init_esbuild_shims();
|
|
1828
|
+
function normalizeSessionData(sessionData, originalRecords, config) {
|
|
1829
|
+
const normalized = [...sessionData.messages];
|
|
1830
|
+
const toolCallIndexById = /* @__PURE__ */ new Map();
|
|
1831
|
+
normalized.forEach((message, index) => {
|
|
1832
|
+
if (message.type === "tool_call" && message.toolCall?.toolCallId) {
|
|
1833
|
+
toolCallIndexById.set(message.toolCall.toolCallId, index);
|
|
1834
|
+
}
|
|
1835
|
+
});
|
|
1836
|
+
const assistantMessageIndexByUuid = /* @__PURE__ */ new Map();
|
|
1837
|
+
normalized.forEach((message, index) => {
|
|
1838
|
+
if (message.type === "assistant") {
|
|
1839
|
+
assistantMessageIndexByUuid.set(message.uuid, index);
|
|
1840
|
+
}
|
|
1841
|
+
});
|
|
1842
|
+
for (const record of originalRecords) {
|
|
1843
|
+
if (record.type !== "tool_result") continue;
|
|
1844
|
+
const toolCallMessage = buildToolCallMessageFromResult(record, config);
|
|
1845
|
+
if (!toolCallMessage?.toolCall) continue;
|
|
1846
|
+
const existingIndex = toolCallIndexById.get(
|
|
1847
|
+
toolCallMessage.toolCall.toolCallId
|
|
1848
|
+
);
|
|
1849
|
+
if (existingIndex === void 0) {
|
|
1850
|
+
toolCallIndexById.set(
|
|
1851
|
+
toolCallMessage.toolCall.toolCallId,
|
|
1852
|
+
normalized.length
|
|
1853
|
+
);
|
|
1854
|
+
normalized.push(toolCallMessage);
|
|
1855
|
+
continue;
|
|
1856
|
+
}
|
|
1857
|
+
const existingMessage = normalized[existingIndex];
|
|
1858
|
+
if (existingMessage.type !== "tool_call" || !existingMessage.toolCall) {
|
|
1859
|
+
continue;
|
|
1860
|
+
}
|
|
1861
|
+
mergeToolCallData(existingMessage.toolCall, toolCallMessage.toolCall);
|
|
1862
|
+
}
|
|
1863
|
+
for (const record of originalRecords) {
|
|
1864
|
+
if (record.type !== "assistant") continue;
|
|
1865
|
+
if (!record.usageMetadata) continue;
|
|
1866
|
+
const existingIndex = assistantMessageIndexByUuid.get(record.uuid);
|
|
1867
|
+
if (existingIndex !== void 0) {
|
|
1868
|
+
if (!normalized[existingIndex].usageMetadata) {
|
|
1869
|
+
normalized[existingIndex].usageMetadata = record.usageMetadata;
|
|
1870
|
+
}
|
|
1871
|
+
}
|
|
1872
|
+
}
|
|
1873
|
+
return {
|
|
1874
|
+
...sessionData,
|
|
1875
|
+
messages: normalized
|
|
1876
|
+
};
|
|
1877
|
+
}
|
|
1878
|
+
__name(normalizeSessionData, "normalizeSessionData");
|
|
1879
|
+
function mergeToolCallData(existing, incoming) {
|
|
1880
|
+
if (!existing.content || existing.content.length === 0) {
|
|
1881
|
+
existing.content = incoming.content;
|
|
1882
|
+
}
|
|
1883
|
+
if (existing.status === "pending" || existing.status === "in_progress") {
|
|
1884
|
+
existing.status = incoming.status;
|
|
1885
|
+
}
|
|
1886
|
+
if (!existing.rawInput && incoming.rawInput) {
|
|
1887
|
+
existing.rawInput = incoming.rawInput;
|
|
1888
|
+
}
|
|
1889
|
+
if (!existing.kind || existing.kind === "other") {
|
|
1890
|
+
existing.kind = incoming.kind;
|
|
1891
|
+
}
|
|
1892
|
+
if ((!existing.title || existing.title === "") && incoming.title) {
|
|
1893
|
+
existing.title = incoming.title;
|
|
1894
|
+
}
|
|
1895
|
+
if ((!existing.locations || existing.locations.length === 0) && incoming.locations && incoming.locations.length > 0) {
|
|
1896
|
+
existing.locations = incoming.locations;
|
|
1897
|
+
}
|
|
1898
|
+
}
|
|
1899
|
+
__name(mergeToolCallData, "mergeToolCallData");
|
|
1900
|
+
function buildToolCallMessageFromResult(record, config) {
|
|
1901
|
+
const toolCallResult = record.toolCallResult;
|
|
1902
|
+
const toolName = extractToolNameFromRecord2(record);
|
|
1903
|
+
if (toolName === ToolNames.TODO_WRITE) {
|
|
1904
|
+
return null;
|
|
1905
|
+
}
|
|
1906
|
+
const toolCallId = getToolResultCallId(record);
|
|
1907
|
+
const functionCallArgs = extractFunctionCallArgs(record);
|
|
1908
|
+
const { kind, title, locations } = resolveToolMetadata(
|
|
1909
|
+
config,
|
|
1910
|
+
toolName,
|
|
1911
|
+
functionCallArgs ?? toolCallResult?.args
|
|
1912
|
+
);
|
|
1913
|
+
const rawInput = normalizeRawInput(
|
|
1914
|
+
functionCallArgs ?? toolCallResult?.args
|
|
1915
|
+
);
|
|
1916
|
+
const content = extractDiffContent(toolCallResult?.resultDisplay) ?? transformPartsToToolCallContent(record.message?.parts ?? []);
|
|
1917
|
+
return {
|
|
1918
|
+
uuid: record.uuid,
|
|
1919
|
+
parentUuid: record.parentUuid,
|
|
1920
|
+
sessionId: record.sessionId,
|
|
1921
|
+
timestamp: record.timestamp,
|
|
1922
|
+
type: "tool_call",
|
|
1923
|
+
toolCall: {
|
|
1924
|
+
toolCallId,
|
|
1925
|
+
kind,
|
|
1926
|
+
title,
|
|
1927
|
+
status: toolCallResult?.error ? "failed" : "completed",
|
|
1928
|
+
rawInput,
|
|
1929
|
+
content,
|
|
1930
|
+
locations,
|
|
1931
|
+
timestamp: Date.parse(record.timestamp)
|
|
1932
|
+
}
|
|
1933
|
+
};
|
|
1934
|
+
}
|
|
1935
|
+
__name(buildToolCallMessageFromResult, "buildToolCallMessageFromResult");
|
|
1936
|
+
function extractToolNameFromRecord2(record) {
|
|
1937
|
+
if (!record.message?.parts) {
|
|
1938
|
+
return "";
|
|
1939
|
+
}
|
|
1940
|
+
for (const part of record.message.parts) {
|
|
1941
|
+
if ("functionResponse" in part && part.functionResponse?.name) {
|
|
1942
|
+
return part.functionResponse.name;
|
|
1943
|
+
}
|
|
1944
|
+
}
|
|
1945
|
+
return "";
|
|
1946
|
+
}
|
|
1947
|
+
__name(extractToolNameFromRecord2, "extractToolNameFromRecord");
|
|
1948
|
+
function extractFunctionCallArgs(record) {
|
|
1949
|
+
if (!record.message?.parts) {
|
|
1950
|
+
return void 0;
|
|
1951
|
+
}
|
|
1952
|
+
for (const part of record.message.parts) {
|
|
1953
|
+
if ("functionCall" in part && part.functionCall?.args) {
|
|
1954
|
+
return part.functionCall.args;
|
|
1955
|
+
}
|
|
1956
|
+
}
|
|
1957
|
+
return void 0;
|
|
1958
|
+
}
|
|
1959
|
+
__name(extractFunctionCallArgs, "extractFunctionCallArgs");
|
|
1960
|
+
function resolveToolMetadata(config, toolName, args) {
|
|
1961
|
+
const toolRegistry = config.getToolRegistry?.();
|
|
1962
|
+
const tool = toolName ? toolRegistry?.getTool?.(toolName) : void 0;
|
|
1963
|
+
let title = tool?.displayName ?? toolName ?? "tool_call";
|
|
1964
|
+
let locations;
|
|
1965
|
+
const kind = mapToolKind(tool?.kind, toolName);
|
|
1966
|
+
if (tool?.build && args) {
|
|
1967
|
+
try {
|
|
1968
|
+
const invocation = tool.build(args);
|
|
1969
|
+
title = `${title}: ${invocation.getDescription()}`;
|
|
1970
|
+
locations = invocation.toolLocations().map((loc) => ({
|
|
1971
|
+
path: loc.path,
|
|
1972
|
+
line: loc.line ?? null
|
|
1973
|
+
}));
|
|
1974
|
+
} catch {
|
|
1975
|
+
}
|
|
1976
|
+
}
|
|
1977
|
+
return { kind, title, locations };
|
|
1978
|
+
}
|
|
1979
|
+
__name(resolveToolMetadata, "resolveToolMetadata");
|
|
1980
|
+
function mapToolKind(kind, toolName) {
|
|
1981
|
+
if (toolName && (toolName === ToolNames.EXIT_PLAN_MODE || toolName === ToolNames.ENTER_PLAN_MODE)) {
|
|
1982
|
+
return "switch_mode";
|
|
1983
|
+
}
|
|
1984
|
+
if (toolName && toolName === ToolNames.TODO_WRITE) {
|
|
1985
|
+
return "todowrite";
|
|
1986
|
+
}
|
|
1987
|
+
const allowedKinds = /* @__PURE__ */ new Set([
|
|
1988
|
+
"read",
|
|
1989
|
+
"edit",
|
|
1990
|
+
"delete",
|
|
1991
|
+
"move",
|
|
1992
|
+
"search",
|
|
1993
|
+
"execute",
|
|
1994
|
+
"think",
|
|
1995
|
+
"fetch",
|
|
1996
|
+
"other"
|
|
1997
|
+
]);
|
|
1998
|
+
if (kind && allowedKinds.has(kind)) {
|
|
1999
|
+
return kind;
|
|
2000
|
+
}
|
|
2001
|
+
return "other";
|
|
2002
|
+
}
|
|
2003
|
+
__name(mapToolKind, "mapToolKind");
|
|
2004
|
+
function extractDiffContent(resultDisplay) {
|
|
2005
|
+
if (!resultDisplay || typeof resultDisplay !== "object") {
|
|
2006
|
+
return null;
|
|
2007
|
+
}
|
|
2008
|
+
const display = resultDisplay;
|
|
2009
|
+
if ("fileName" in display && "newContent" in display) {
|
|
2010
|
+
if (display["truncatedForSession"] === true) {
|
|
2011
|
+
return [
|
|
2012
|
+
{
|
|
2013
|
+
type: "content",
|
|
2014
|
+
content: {
|
|
2015
|
+
type: "text",
|
|
2016
|
+
text: buildTruncatedDiffPreviewText(display)
|
|
2017
|
+
}
|
|
2018
|
+
}
|
|
2019
|
+
];
|
|
2020
|
+
}
|
|
2021
|
+
return [
|
|
2022
|
+
{
|
|
2023
|
+
type: "diff",
|
|
2024
|
+
path: display["fileName"],
|
|
2025
|
+
oldText: display["originalContent"] ?? "",
|
|
2026
|
+
newText: display["newContent"]
|
|
2027
|
+
}
|
|
2028
|
+
];
|
|
2029
|
+
}
|
|
2030
|
+
return null;
|
|
2031
|
+
}
|
|
2032
|
+
__name(extractDiffContent, "extractDiffContent");
|
|
2033
|
+
function normalizeRawInput(value) {
|
|
2034
|
+
if (typeof value === "string") return value;
|
|
2035
|
+
if (typeof value === "object" && value !== null) return value;
|
|
2036
|
+
return void 0;
|
|
2037
|
+
}
|
|
2038
|
+
__name(normalizeRawInput, "normalizeRawInput");
|
|
2039
|
+
function transformPartsToToolCallContent(parts) {
|
|
2040
|
+
const content = [];
|
|
2041
|
+
for (const part of parts) {
|
|
2042
|
+
if ("text" in part && part.text) {
|
|
2043
|
+
content.push({
|
|
2044
|
+
type: "content",
|
|
2045
|
+
content: { type: "text", text: part.text }
|
|
2046
|
+
});
|
|
2047
|
+
continue;
|
|
2048
|
+
}
|
|
2049
|
+
if ("functionResponse" in part && part.functionResponse) {
|
|
2050
|
+
const response = part.functionResponse.response;
|
|
2051
|
+
const outputField = response?.["output"];
|
|
2052
|
+
const errorField = response?.["error"];
|
|
2053
|
+
const responseText = typeof outputField === "string" ? outputField : typeof errorField === "string" ? errorField : JSON.stringify(response);
|
|
2054
|
+
content.push({
|
|
2055
|
+
type: "content",
|
|
2056
|
+
content: { type: "text", text: responseText }
|
|
2057
|
+
});
|
|
2058
|
+
}
|
|
2059
|
+
}
|
|
2060
|
+
return content;
|
|
2061
|
+
}
|
|
2062
|
+
__name(transformPartsToToolCallContent, "transformPartsToToolCallContent");
|
|
2063
|
+
|
|
2064
|
+
// packages/cli/src/ui/utils/export/formatters/markdown.ts
|
|
2065
|
+
init_esbuild_shims();
|
|
2066
|
+
function toMarkdown(sessionData) {
|
|
2067
|
+
const lines = [];
|
|
2068
|
+
const metadata = sessionData.metadata;
|
|
2069
|
+
lines.push("# Chat Session Export\n");
|
|
2070
|
+
lines.push(`- **Session ID**: \`${sanitizeText(sessionData.sessionId)}\``);
|
|
2071
|
+
lines.push(`- **Start Time**: ${sanitizeText(sessionData.startTime)}`);
|
|
2072
|
+
lines.push(
|
|
2073
|
+
`- **Exported**: ${sanitizeText(metadata?.exportTime ?? (/* @__PURE__ */ new Date()).toISOString())}`
|
|
2074
|
+
);
|
|
2075
|
+
lines.push("");
|
|
2076
|
+
if (metadata?.cwd) {
|
|
2077
|
+
lines.push(`- **Working Directory**: \`${sanitizeText(metadata.cwd)}\``);
|
|
2078
|
+
}
|
|
2079
|
+
if (metadata?.gitRepo) {
|
|
2080
|
+
lines.push(`- **Git Repository**: ${sanitizeText(metadata.gitRepo)}`);
|
|
2081
|
+
}
|
|
2082
|
+
if (metadata?.gitBranch) {
|
|
2083
|
+
lines.push(`- **Git Branch**: \`${sanitizeText(metadata.gitBranch)}\``);
|
|
2084
|
+
}
|
|
2085
|
+
lines.push("");
|
|
2086
|
+
if (metadata?.model) {
|
|
2087
|
+
lines.push(`- **Model**: ${sanitizeText(metadata.model)}`);
|
|
2088
|
+
}
|
|
2089
|
+
if (metadata?.channel) {
|
|
2090
|
+
lines.push(`- **Channel**: ${sanitizeText(metadata.channel)}`);
|
|
2091
|
+
}
|
|
2092
|
+
if (metadata?.promptCount !== void 0) {
|
|
2093
|
+
lines.push(`- **Prompt Count**: ${metadata.promptCount}`);
|
|
2094
|
+
}
|
|
2095
|
+
lines.push("");
|
|
2096
|
+
if (metadata?.totalTokens !== void 0) {
|
|
2097
|
+
lines.push(`- **Total Tokens**: ${metadata.totalTokens}`);
|
|
2098
|
+
}
|
|
2099
|
+
if (metadata?.contextWindowSize !== void 0) {
|
|
2100
|
+
lines.push(`- **Context Window Size**: ${metadata.contextWindowSize}`);
|
|
2101
|
+
}
|
|
2102
|
+
if (metadata?.contextUsagePercent !== void 0) {
|
|
2103
|
+
lines.push(`- **Context Usage**: ${metadata.contextUsagePercent}%`);
|
|
2104
|
+
}
|
|
2105
|
+
lines.push("");
|
|
2106
|
+
if (metadata?.filesWritten !== void 0) {
|
|
2107
|
+
lines.push(`- **Files Written**: ${metadata.filesWritten}`);
|
|
2108
|
+
}
|
|
2109
|
+
if (metadata?.linesAdded !== void 0) {
|
|
2110
|
+
lines.push(`- **Lines Added**: ${metadata.linesAdded}`);
|
|
2111
|
+
}
|
|
2112
|
+
if (metadata?.linesRemoved !== void 0) {
|
|
2113
|
+
lines.push(`- **Lines Removed**: ${metadata.linesRemoved}`);
|
|
2114
|
+
}
|
|
2115
|
+
if (metadata?.uniqueFiles && metadata.uniqueFiles.length > 0) {
|
|
2116
|
+
lines.push("");
|
|
2117
|
+
lines.push("<details>");
|
|
2118
|
+
lines.push(
|
|
2119
|
+
`<summary><strong>Unique Files Referenced (${metadata.uniqueFiles.length})</strong></summary>`
|
|
2120
|
+
);
|
|
2121
|
+
lines.push("");
|
|
2122
|
+
for (const file of metadata.uniqueFiles) {
|
|
2123
|
+
lines.push(`- \`${sanitizeText(file)}\``);
|
|
2124
|
+
}
|
|
2125
|
+
lines.push("</details>");
|
|
2126
|
+
}
|
|
2127
|
+
lines.push("\n---\n");
|
|
2128
|
+
for (const message of sessionData.messages) {
|
|
2129
|
+
if (message.type === "user") {
|
|
2130
|
+
lines.push("## User\n");
|
|
2131
|
+
lines.push(formatMessageContent(message));
|
|
2132
|
+
} else if (message.type === "assistant") {
|
|
2133
|
+
lines.push("## Assistant\n");
|
|
2134
|
+
lines.push(formatMessageContent(message));
|
|
2135
|
+
} else if (message.type === "tool_call") {
|
|
2136
|
+
lines.push(formatToolCall(message));
|
|
2137
|
+
} else if (message.type === "system") {
|
|
2138
|
+
lines.push("### System\n");
|
|
2139
|
+
const text = formatMessageContent(message);
|
|
2140
|
+
lines.push(`> ${text.replace(/\n/g, "\n> ")}`);
|
|
2141
|
+
}
|
|
2142
|
+
lines.push("\n");
|
|
2143
|
+
}
|
|
2144
|
+
return lines.join("\n");
|
|
2145
|
+
}
|
|
2146
|
+
__name(toMarkdown, "toMarkdown");
|
|
2147
|
+
function formatMessageContent(message) {
|
|
2148
|
+
const text = extractTextFromMessage(message);
|
|
2149
|
+
const processedText = text.replace(
|
|
2150
|
+
/--- Content from referenced files ---\n([\s\S]*?)\n--- End of content ---/g,
|
|
2151
|
+
(match, content) => `
|
|
2152
|
+
> **Referenced Files:**
|
|
2153
|
+
|
|
2154
|
+
${createCodeBlock(content)}
|
|
2155
|
+
`
|
|
2156
|
+
);
|
|
2157
|
+
return processedText;
|
|
2158
|
+
}
|
|
2159
|
+
__name(formatMessageContent, "formatMessageContent");
|
|
2160
|
+
function formatToolCall(message) {
|
|
2161
|
+
if (!message.toolCall) return "";
|
|
2162
|
+
const lines = [];
|
|
2163
|
+
const { title, status, rawInput, content, locations } = message.toolCall;
|
|
2164
|
+
const titleStr = typeof title === "string" ? title : JSON.stringify(title);
|
|
2165
|
+
lines.push(`### Tool: ${sanitizeText(titleStr)}`);
|
|
2166
|
+
lines.push(`**Status**: ${sanitizeText(status)}
|
|
2167
|
+
`);
|
|
2168
|
+
if (rawInput) {
|
|
2169
|
+
lines.push("**Input:**");
|
|
2170
|
+
const inputStr = typeof rawInput === "string" ? rawInput : JSON.stringify(rawInput, null, 2);
|
|
2171
|
+
lines.push(createCodeBlock(inputStr, "json"));
|
|
2172
|
+
lines.push("");
|
|
2173
|
+
}
|
|
2174
|
+
if (locations && locations.length > 0) {
|
|
2175
|
+
lines.push("**Affected Files:**");
|
|
2176
|
+
for (const loc of locations) {
|
|
2177
|
+
const lineSuffix = loc.line ? `:${loc.line}` : "";
|
|
2178
|
+
lines.push(`- \`${sanitizeText(loc.path)}${lineSuffix}\``);
|
|
2179
|
+
}
|
|
2180
|
+
lines.push("");
|
|
2181
|
+
}
|
|
2182
|
+
if (content && content.length > 0) {
|
|
2183
|
+
lines.push("**Output:**");
|
|
2184
|
+
for (const item of content) {
|
|
2185
|
+
if (item.type === "content" && item["content"]) {
|
|
2186
|
+
const contentData = item["content"];
|
|
2187
|
+
if (contentData.type === "text" && contentData.text) {
|
|
2188
|
+
let language = "";
|
|
2189
|
+
if (locations && locations.length === 1 && locations[0].path) {
|
|
2190
|
+
language = getLanguageFromPath(locations[0].path);
|
|
2191
|
+
}
|
|
2192
|
+
lines.push(createCodeBlock(contentData.text, language));
|
|
2193
|
+
}
|
|
2194
|
+
} else if (item.type === "diff") {
|
|
2195
|
+
const path2 = item["path"];
|
|
2196
|
+
const diffText = item["newText"];
|
|
2197
|
+
lines.push(`
|
|
2198
|
+
*Diff for \`${sanitizeText(path2)}\`:*`);
|
|
2199
|
+
lines.push(createCodeBlock(diffText, "diff"));
|
|
2200
|
+
}
|
|
2201
|
+
}
|
|
2202
|
+
}
|
|
2203
|
+
return lines.join("\n");
|
|
2204
|
+
}
|
|
2205
|
+
__name(formatToolCall, "formatToolCall");
|
|
2206
|
+
function extractTextFromMessage(message) {
|
|
2207
|
+
if (!message.message?.parts) return "";
|
|
2208
|
+
const textParts = [];
|
|
2209
|
+
for (const part of message.message.parts) {
|
|
2210
|
+
if ("text" in part) {
|
|
2211
|
+
textParts.push(part.text);
|
|
2212
|
+
}
|
|
2213
|
+
}
|
|
2214
|
+
return textParts.join("\n");
|
|
2215
|
+
}
|
|
2216
|
+
__name(extractTextFromMessage, "extractTextFromMessage");
|
|
2217
|
+
function createCodeBlock(content, language = "") {
|
|
2218
|
+
const fence = buildFence(content);
|
|
2219
|
+
return `${fence}${language}
|
|
2220
|
+
${content}
|
|
2221
|
+
${fence}`;
|
|
2222
|
+
}
|
|
2223
|
+
__name(createCodeBlock, "createCodeBlock");
|
|
2224
|
+
function sanitizeText(value) {
|
|
2225
|
+
return (value ?? "").replace(/&/g, "&").replace(/</g, "<");
|
|
2226
|
+
}
|
|
2227
|
+
__name(sanitizeText, "sanitizeText");
|
|
2228
|
+
function buildFence(value) {
|
|
2229
|
+
const matches = (value ?? "").match(/`+/g);
|
|
2230
|
+
const maxRun = matches ? Math.max(...matches.map((match) => match.length)) : 0;
|
|
2231
|
+
const fenceLength = Math.max(3, maxRun + 1);
|
|
2232
|
+
return "`".repeat(fenceLength);
|
|
2233
|
+
}
|
|
2234
|
+
__name(buildFence, "buildFence");
|
|
2235
|
+
function getLanguageFromPath(path2) {
|
|
2236
|
+
const ext = path2.split(".").pop()?.toLowerCase();
|
|
2237
|
+
switch (ext) {
|
|
2238
|
+
case "ts":
|
|
2239
|
+
case "tsx":
|
|
2240
|
+
return "typescript";
|
|
2241
|
+
case "js":
|
|
2242
|
+
case "jsx":
|
|
2243
|
+
case "mjs":
|
|
2244
|
+
case "cjs":
|
|
2245
|
+
return "javascript";
|
|
2246
|
+
case "py":
|
|
2247
|
+
return "python";
|
|
2248
|
+
case "rb":
|
|
2249
|
+
return "ruby";
|
|
2250
|
+
case "go":
|
|
2251
|
+
return "go";
|
|
2252
|
+
case "rs":
|
|
2253
|
+
return "rust";
|
|
2254
|
+
case "java":
|
|
2255
|
+
return "java";
|
|
2256
|
+
case "c":
|
|
2257
|
+
case "cpp":
|
|
2258
|
+
case "h":
|
|
2259
|
+
case "hpp":
|
|
2260
|
+
return "cpp";
|
|
2261
|
+
case "cs":
|
|
2262
|
+
return "csharp";
|
|
2263
|
+
case "html":
|
|
2264
|
+
return "html";
|
|
2265
|
+
case "css":
|
|
2266
|
+
return "css";
|
|
2267
|
+
case "json":
|
|
2268
|
+
return "json";
|
|
2269
|
+
case "md":
|
|
2270
|
+
return "markdown";
|
|
2271
|
+
case "sh":
|
|
2272
|
+
case "bash":
|
|
2273
|
+
case "zsh":
|
|
2274
|
+
return "bash";
|
|
2275
|
+
case "yaml":
|
|
2276
|
+
case "yml":
|
|
2277
|
+
return "yaml";
|
|
2278
|
+
case "xml":
|
|
2279
|
+
return "xml";
|
|
2280
|
+
case "sql":
|
|
2281
|
+
return "sql";
|
|
2282
|
+
default:
|
|
2283
|
+
return "";
|
|
2284
|
+
}
|
|
2285
|
+
}
|
|
2286
|
+
__name(getLanguageFromPath, "getLanguageFromPath");
|
|
2287
|
+
|
|
2288
|
+
// packages/cli/src/ui/utils/export/formatters/html.ts
|
|
2289
|
+
init_esbuild_shims();
|
|
2290
|
+
|
|
2291
|
+
// packages/web-templates/src/index.ts
|
|
2292
|
+
init_esbuild_shims();
|
|
2293
|
+
|
|
2294
|
+
// packages/web-templates/src/generated/insightTemplate.ts
|
|
2295
|
+
init_esbuild_shims();
|
|
2296
|
+
var INSIGHT_JS = '(function(e,B){"use strict";function U({data:t}){const{totalMessages:n=0,totalLinesAdded:l=0,totalLinesRemoved:s=0,totalFiles:r=0}=t,a=Object.keys(t.heatmap||{});let o=0;if(a.length>0){const c=a.map(x=>new Date(x)).map(x=>x.getTime()),d=new Date(Math.min(...c)),g=new Date(Math.max(...c)),E=Math.abs(g.getTime()-d.getTime());o=Math.ceil(E/(1e3*60*60*24))+1}const i=o>0?Math.round(n/o):0;return e.createElement("div",{className:"stats-row"},e.createElement("div",{className:"stat"},e.createElement("div",{className:"stat-value"},n),e.createElement("div",{className:"stat-label"},"Messages")),e.createElement("div",{className:"stat"},e.createElement("div",{className:"stat-value"},"+",l,"/-",s),e.createElement("div",{className:"stat-label"},"Lines")),e.createElement("div",{className:"stat"},e.createElement("div",{className:"stat-value"},r),e.createElement("div",{className:"stat-label"},"Files")),e.createElement("div",{className:"stat"},e.createElement("div",{className:"stat-value"},o),e.createElement("div",{className:"stat-label"},"Days")),e.createElement("div",{className:"stat"},e.createElement("div",{className:"stat-value"},i),e.createElement("div",{className:"stat-label"},"Msgs/Day")))}function K({insights:t}){return e.createElement("div",{className:"grid gap-4 md:grid-cols-2 md:gap-6"},e.createElement(J,{activeHours:t.activeHours,cardClass:"glass-card p-6",sectionTitleClass:"text-lg font-semibold tracking-tight text-slate-900"}))}function J({activeHours:t,cardClass:n,sectionTitleClass:l}){const r=[{label:"Morning",time:"06:00 - 12:00",hours:[6,7,8,9,10,11],color:"#fbbf24"},{label:"Afternoon",time:"12:00 - 18:00",hours:[12,13,14,15,16,17],color:"#0ea5e9"},{label:"Evening",time:"18:00 - 22:00",hours:[18,19,20,21],color:"#6366f1"},{label:"Night",time:"22:00 - 06:00",hours:[22,23,0,1,2,3,4,5],color:"#475569"}].map(o=>{const i=o.hours.reduce((m,c)=>m+(t[c]||0),0);return{...o,total:i}}),a=Math.max(...r.map(o=>o.total));return e.createElement("div",{className:`${n} h-full flex flex-col min-h-[320px]`},e.createElement("div",{className:"flex items-center justify-between mb-4"},e.createElement("h3",{className:l},"Active Hours")),e.createElement("div",{className:"flex-1 flex flex-col justify-center gap-4"},r.map(o=>e.createElement("div",{key:o.label,className:"space-y-2"},e.createElement("div",{className:"flex justify-between items-center text-sm"},e.createElement("div",{className:"flex items-center gap-2"},e.createElement("span",{className:"rounded-full",style:{width:"12px",height:"12px",backgroundColor:o.color}}),e.createElement("span",{className:"font-medium text-slate-700"},o.label),e.createElement("span",{className:"text-xs text-slate-400 hidden xl:inline"},o.time)),e.createElement("span",{className:"font-semibold text-slate-900"},o.total)),e.createElement("div",{className:"w-full rounded-full overflow-hidden",style:{height:"12px",backgroundColor:"#e2e8f0"}},e.createElement("div",{className:"h-full rounded-full",style:{width:`${a>0?o.total/a*100:0}%`,backgroundColor:o.color}}))))))}function V({heatmap:t}){return e.createElement("div",{className:"glass-card p-6 mt-4 md:mt-6"},e.createElement("div",{className:"mb-3"},e.createElement("h3",{className:"text-lg font-semibold tracking-tight text-slate-900"},"Activity Heatmap"),e.createElement("p",{className:"text-xs text-slate-500"},"Showing past year of activity")),e.createElement("div",{className:"heatmap-container"},e.createElement("div",{className:"min-w-[720px] rounded-xl bg-white/70"},e.createElement(X,{heatmapData:t}))),e.createElement(Z,null))}function X({heatmapData:t}){const a=new Date,o=new Date(a);o.setFullYear(a.getFullYear()-1);const i=[],m=new Date(o);for(;m<=a;)i.push(new Date(m)),m.setDate(m.getDate()+1);const c=[0,2,4,10,20],d=["#ebedf0","#9be9a8","#40c463","#30a14e","#216e39"];function g(u){if(u===0)return d[0];for(let f=c.length-1;f>=1;f--)if(u>=c[f])return d[f];return d[1]}const E=50,x=20,A=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],w=o.getDay(),W=[];let h=-1,T=-100;return i.forEach((u,f)=>{const C=f+w,_=Math.floor(C/7),v=E+_*16,N=u.getMonth();N!==h&&(v-T>30&&(W.push({x:v,text:A[N]}),T=v),h=N)}),e.createElement("svg",{className:"heatmap-svg",width:1e3,height:130,viewBox:"0 0 1000 130"},i.map((u,f)=>{const C=f+w,_=Math.floor(C/7),v=u.getDay(),N=E+_*16,j=x+v*16,k=u.toISOString().split("T")[0],S=t[k]||0,L=g(S);return e.createElement("rect",{key:k,className:"heatmap-day",x:N,y:j,width:14,height:14,rx:"2",fill:L,"data-date":k,"data-count":S},e.createElement("title",null,k,": ",S," activities"))}),W.map((u,f)=>e.createElement("text",{key:f,x:u.x,y:"15",fontSize:"12",fill:"#64748b"},u.text)))}function Z(){const t=["#ebedf0","#9be9a8","#40c463","#30a14e","#216e39"];return e.createElement("div",{className:"flex items-center gap-2 mt-4"},e.createElement("span",{className:"text-xs text-slate-500"},"Less"),t.map((n,l)=>e.createElement("span",{key:l,className:"inline-block rounded",style:{width:"10px",height:"10px",backgroundColor:n}})),e.createElement("span",{className:"text-xs text-slate-500"},"More"))}function p({children:t}){if(!t||typeof t!="string")return t;const n=t.split(/(\\*\\*.*?\\*\\*)/g);return e.createElement(e.Fragment,null,n.map((l,s)=>l.startsWith("**")&&l.endsWith("**")&&l.length>=4?e.createElement("strong",{key:s},l.slice(2,-2)):l))}function F({text:t,label:n="Copy"}){const[l,s]=e.useState(!1),r=()=>{navigator.clipboard.writeText(t).then(()=>{s(!0),setTimeout(()=>s(!1),2e3)})};return e.createElement("button",{className:"copy-btn",onClick:r},l?"Copied!":n)}function R(t){return typeof t=="string"&&t.trim().length>0}function ee({qualitative:t,targetSections:n}){const{atAGlance:l}=t;if(!l)return null;const s=[{key:"wins",label:"What\'s working:",body:l.whats_working,href:"#section-wins",link:"Impressive Things You Did \u2192",showLink:n.wins},{key:"friction",label:"What\'s hindering you:",body:l.whats_hindering,href:"#section-friction",link:"Where Things Go Wrong \u2192",showLink:n.friction},{key:"features",label:"Quick wins to try:",body:l.quick_wins,href:"#section-features",link:"Features to Try \u2192",showLink:n.features},{key:"horizon",label:"Ambitious workflows:",body:l.ambitious_workflows,href:"#section-horizon",link:"On the Horizon \u2192",showLink:n.horizon}].filter(r=>R(r.body));return s.length===0?null:e.createElement("div",{className:"at-a-glance"},e.createElement("div",{className:"glance-title"},"At a Glance"),e.createElement("div",{className:"glance-sections"},s.map(r=>e.createElement("div",{key:r.key,className:"glance-section"},e.createElement("strong",null,r.label)," ",e.createElement(p,null,r.body),r.showLink&&e.createElement("a",{href:r.href,className:"see-more"},r.link)))))}function te({sections:t}){return t.length===0?null:e.createElement("nav",{className:"nav-toc"},t.map(n=>e.createElement("a",{key:n.href,href:n.href},n.label)))}function ne({qualitative:t,topGoals:n,topTools:l}){const{projectAreas:s}=t,r=Array.isArray(l)?Object.fromEntries(l):l;return e.createElement(e.Fragment,null,e.createElement("h2",{id:"section-work",className:"text-xl font-semibold text-slate-900 mt-8 mb-4"},"What You Work On"),Array.isArray(s==null?void 0:s.areas)&&s.areas.length>0&&e.createElement("div",{className:"project-areas mb-6"},s.areas.map((a,o)=>e.createElement("div",{key:o,className:"project-area"},e.createElement("div",{className:"area-header"},e.createElement("span",{className:"area-name"},a.name),e.createElement("span",{className:"area-count"},"~",a.session_count," sessions")),e.createElement("div",{className:"area-desc"},e.createElement(p,null,a.description))))),e.createElement("div",{style:{display:"grid",gridTemplateColumns:"repeat(2, 1fr)",gap:"24px",marginBottom:"24px"}},n&&Object.keys(n).length>0&&e.createElement(D,{data:n,title:"What You Wanted",color:"#0ea5e9"}),r&&Object.keys(r).length>0&&e.createElement(D,{data:r,title:"Top Tools Used",color:"#6366f1"})))}function le({qualitative:t,insights:n}){const{interactionStyle:l}=t;return l?e.createElement(e.Fragment,null,e.createElement("h2",{id:"section-usage",className:"text-xl font-semibold text-slate-900 mt-8 mb-4"},"How You Use Qwen Code"),e.createElement("div",{className:"narrative"},e.createElement("p",null,e.createElement(p,null,l.narrative)),l.key_pattern&&e.createElement("div",{className:"key-insight"},e.createElement("strong",null,"Key pattern:")," ",e.createElement(p,null,l.key_pattern))),e.createElement(K,{insights:n}),e.createElement(V,{heatmap:n.heatmap})):null}function re({qualitative:t,primarySuccess:n,outcomes:l}){const s=t==null?void 0:t.impressiveWorkflows;return e.createElement(e.Fragment,null,e.createElement("h2",{id:"section-wins",className:"text-xl font-semibold text-slate-900 mt-8 mb-4"},"Impressive Things You Did"),(s==null?void 0:s.intro)&&e.createElement("p",{className:"section-intro"},e.createElement(p,null,s.intro)),s&&e.createElement("div",{className:"big-wins"},Array.isArray(s.impressive_workflows)&&s.impressive_workflows.map((r,a)=>e.createElement("div",{key:a,className:"big-win"},e.createElement("div",{className:"big-win-title"},r.title),e.createElement("div",{className:"big-win-desc"},e.createElement(p,null,r.description))))),e.createElement("div",{style:{display:"grid",gridTemplateColumns:"repeat(2, 1fr)",gap:"24px",marginTop:"24px",marginBottom:"24px"}},n&&Object.keys(n).length>0&&e.createElement(D,{data:n,title:"What Helped Most (Qwen\'s Capabilities)",color:"#3b82f6",allowedKeys:["fast_accurate_search","correct_code_edits","good_explanations","proactive_help","multi_file_changes","good_debugging"]}),l&&Object.keys(l).length>0&&e.createElement(D,{data:l,title:"Outcomes",color:"#8b5cf6",allowedKeys:["fully_achieved","mostly_achieved","partially_achieved","not_achieved","unclear_from_transcript"]})))}function se(t){return t==="unclear_from_transcript"?"Unclear":t.split("_").map(n=>n.charAt(0).toUpperCase()+n.slice(1)).join(" ")}function D({data:t,title:n,color:l="#3b82f6",allowedKeys:s=null}){if(!t||Object.keys(t).length===0)return null;let r=Object.entries(t).filter(([,o])=>Number.isFinite(o)&&o!==0);if(s&&(r=r.filter(([o])=>s.includes(o))),r.sort((o,i)=>i[1]-o[1]),r=r.slice(0,10),r.length===0)return null;const a=Math.max(...r.map(([,o])=>o));return e.createElement("div",{className:"bar-chart-card",style:{flex:1,minWidth:0,backgroundColor:"#ffffff",borderRadius:"12px",padding:"20px",boxShadow:"0 1px 3px rgba(0, 0, 0, 0.08)",border:"1px solid #e2e8f0"}},e.createElement("h3",{style:{fontSize:"13px",fontWeight:700,color:"#64748b",marginTop:0,marginBottom:"16px",textTransform:"uppercase",letterSpacing:"0.5px"}},n),e.createElement("div",{className:"bar-chart",style:{display:"flex",flexDirection:"column",gap:"10px"}},r.map(([o,i])=>{const m=a>0?i/a*100:0;return e.createElement("div",{key:o,className:"bar-row",style:{display:"flex",alignItems:"center",gap:"12px"}},e.createElement("div",{className:"bar-label",style:{width:"130px",fontSize:"13px",color:"#475569",textAlign:"left",flexShrink:0,whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis"}},se(o)),e.createElement("div",{className:"bar-wrapper",style:{flex:1,display:"flex",alignItems:"center",gap:"10px",minWidth:0}},e.createElement("div",{className:"bar-bg",style:{flex:1,height:"8px",backgroundColor:"#f1f5f9",borderRadius:"4px",overflow:"hidden"}},e.createElement("div",{className:"bar-fill",style:{width:`${m}%`,height:"100%",backgroundColor:l,borderRadius:"4px",transition:"width 0.3s ease"}})),e.createElement("span",{className:"bar-value",style:{fontSize:"13px",fontWeight:600,color:"#475569",minWidth:"24px",textAlign:"right"}},i)))})))}function ae({qualitative:t,satisfaction:n,friction:l}){const s=t==null?void 0:t.frictionPoints;return e.createElement(e.Fragment,null,e.createElement("h2",{id:"section-friction",className:"text-xl font-semibold text-slate-900 mt-8 mb-4"},"Where Things Go Wrong"),(s==null?void 0:s.intro)&&e.createElement("p",{className:"section-intro"},e.createElement(p,null,s.intro)),s&&e.createElement("div",{className:"friction-categories"},Array.isArray(s.categories)&&s.categories.map((r,a)=>e.createElement("div",{key:a,className:"friction-category"},e.createElement("div",{className:"friction-title"},r.category),e.createElement("div",{className:"friction-desc"},e.createElement(p,null,r.description)),Array.isArray(r.examples)&&r.examples.length>0&&e.createElement("ul",{className:"friction-examples"},r.examples.map((o,i)=>e.createElement("li",{key:i},e.createElement(p,null,o))))))),e.createElement("div",{style:{display:"grid",gridTemplateColumns:"repeat(2, 1fr)",gap:"24px",marginTop:"24px",marginBottom:"24px"}},l&&Object.keys(l).length>0&&e.createElement(D,{data:l,title:"Primary Friction Types",color:"#ef4444",allowedKeys:["misunderstood_request","wrong_approach","buggy_code","user_rejected_action","excessive_changes"]}),n&&Object.keys(n).length>0&&e.createElement(D,{data:n,title:"Inferred Satisfaction (model-estimated)",color:"#10b981",allowedKeys:["happy","satisfied","likely_satisfied","dissatisfied","frustrated"]})))}function oe({additions:t}){const[n,l]=e.useState(new Array(t.length).fill(!0)),[s,r]=e.useState(!1),a=m=>{const c=n.map((d,g)=>g===m?!d:d);l(c)},o=()=>{const m=t.filter((c,d)=>n[d]).map(c=>c.addition).join(`\n\n`);m&&navigator.clipboard.writeText(m).then(()=>{r(!0),setTimeout(()=>r(!1),2e3)})},i=n.filter(Boolean).length;return e.createElement("div",{className:"qwen-md-section"},e.createElement("h3",null,"Suggested QWEN.md Additions"),e.createElement("p",{className:"text-xs text-slate-500 mb-3"},"Just copy this into Qwen Code to add it to your QWEN.md."),e.createElement("div",{className:"qwen-md-actions",style:{marginBottom:"12px"}},e.createElement("button",{className:`copy-all-btn ${s?"copied":""}`,onClick:o,disabled:i===0},s?"Copied All!":`Copy All Checked (${i})`)),t.map((m,c)=>e.createElement("div",{key:c,className:"qwen-md-item"},e.createElement("input",{type:"checkbox",checked:n[c],onChange:()=>a(c),className:"cmd-checkbox"}),e.createElement("div",{style:{flex:1}},e.createElement("code",{className:"cmd-code"},m.addition),e.createElement("div",{className:"cmd-why"},e.createElement(p,null,m.why))),e.createElement(F,{text:m.addition}))))}function ie({qualitative:t}){const{improvements:n}=t;if(!n)return null;const l=Array.isArray(n.Qwen_md_additions)&&n.Qwen_md_additions.length>0||Array.isArray(n.features_to_try)&&n.features_to_try.length>0,s=Array.isArray(n.usage_patterns)&&n.usage_patterns.length>0;return!l&&!s?null:e.createElement(e.Fragment,null,l&&e.createElement(e.Fragment,null,e.createElement("h2",{id:"section-features",className:"text-xl font-semibold text-slate-900 mt-8 mb-4"},"Existing Qwen Code Features to Try"),Array.isArray(n.Qwen_md_additions)&&n.Qwen_md_additions.length>0&&e.createElement(oe,{additions:n.Qwen_md_additions}),e.createElement("p",{className:"text-xs text-slate-500 mb-3"},"Just copy this into Qwen Code and it\'ll set it up for you."),e.createElement("div",{className:"features-section"},Array.isArray(n.features_to_try)&&n.features_to_try.map((r,a)=>e.createElement("div",{key:a,className:"feature-card"},e.createElement("div",{className:"feature-title"},r.feature),e.createElement("div",{className:"feature-oneliner"},e.createElement(p,null,r.one_liner)),e.createElement("div",{className:"feature-why"},e.createElement("strong",null,"Why for you:")," ",e.createElement(p,null,r.why_for_you)),e.createElement("div",{className:"feature-examples"},e.createElement("div",{className:"feature-example"},e.createElement("div",{className:"example-code-row"},e.createElement("code",{className:"example-code"},r.example_code),e.createElement(F,{text:r.example_code})))))))),s&&e.createElement(e.Fragment,null,e.createElement("h2",{id:"section-patterns",className:"text-xl font-semibold text-slate-900 mt-8 mb-4"},"New Ways to Use Qwen Code"),e.createElement("p",{className:"text-xs text-slate-500 mb-3"},"Just copy this into Qwen Code and it\'ll walk you through it."),e.createElement("div",{className:"patterns-section"},Array.isArray(n.usage_patterns)&&n.usage_patterns.map((r,a)=>e.createElement("div",{key:a,className:"pattern-card"},e.createElement("div",{className:"pattern-title"},r.title),e.createElement("div",{className:"pattern-summary"},e.createElement(p,null,r.suggestion)),e.createElement("div",{className:"pattern-detail"},e.createElement(p,null,r.detail)),e.createElement("div",{className:"copyable-prompt-section"},e.createElement("div",{className:"prompt-label"},"Paste into Qwen Code:"),e.createElement("div",{className:"copyable-prompt-row"},e.createElement("code",{className:"copyable-prompt"},r.copyable_prompt),e.createElement(F,{text:r.copyable_prompt}))))))))}function me({qualitative:t}){const{futureOpportunities:n}=t;return n?e.createElement(e.Fragment,null,e.createElement("h2",{id:"section-horizon",className:"text-xl font-semibold text-slate-900 mt-8 mb-4"},"On the Horizon"),n.intro&&e.createElement("p",{className:"section-intro"},e.createElement(p,null,n.intro)),e.createElement("div",{className:"horizon-section"},Array.isArray(n.opportunities)&&n.opportunities.map((l,s)=>e.createElement("div",{key:s,className:"horizon-card"},e.createElement("div",{className:"horizon-title"},l.title),e.createElement("div",{className:"horizon-possible"},e.createElement(p,null,l.whats_possible)),e.createElement("div",{className:"horizon-tip"},e.createElement("strong",null,"Getting started:")," ",e.createElement(p,null,l.how_to_try)),e.createElement("div",{className:"pattern-prompt"},e.createElement("div",{className:"prompt-label"},"Paste into Qwen Code:"),e.createElement("div",{style:{display:"flex",alignItems:"flex-start",gap:"8px"}},e.createElement("code",{style:{flex:1}},l.copyable_prompt),e.createElement(F,{text:l.copyable_prompt}))))))):null}function ce({qualitative:t}){const{memorableMoment:n}=t;return n?e.createElement("div",{className:"fun-ending"},e.createElement("div",{className:"fun-headline"},\'"\',n.headline,\'"\'),e.createElement("div",{className:"fun-detail"},e.createElement(p,null,n.detail))):null}const de={light:{background:"linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%)",textPrimary:"#0f172a",textSecondary:"#475569",textMuted:"#64748b",cardBackground:"rgba(255,255,255,0.7)",cardBackgroundSecondary:"rgba(255,255,255,0.5)",borderColor:"#e2e8f0",heatmapColors:["#9be9a8","#40c463","#30a14e","#216e39"],heatmapEmpty:"#ebedf0"},dark:{background:"linear-gradient(135deg, #0f172a 0%, #1e293b 100%)",textPrimary:"#f8fafc",textSecondary:"#e2e8f0",textMuted:"#94a3b8",cardBackground:"rgba(255,255,255,0.05)",cardBackgroundSecondary:"rgba(255,255,255,0.04)",borderColor:"rgba(255,255,255,0.08)",heatmapColors:["#0e4429","#006d32","#26a641","#39d353"],heatmapEmpty:"#2d333b"}};function pe({data:t,theme:n="light"}){var h,T,u,f,C,_;const l=de[n],{totalMessages:s=0,totalSessions:r=0,totalLinesAdded:a=0,totalLinesRemoved:o=0,totalFiles:i=0,currentStreak:m=0,longestStreak:c=0,activeHours:d={}}=t,g=Object.keys(t.heatmap||{});let E=0,x="";if(g.length>0){E=g.length;const v=g.map(S=>new Date(S).getTime()),N=new Date(Math.min(...v)),j=new Date(Math.max(...v)),k=S=>S.toISOString().split("T")[0];x=`${k(N)} \u2014 ${k(j)}`}const A=(u=(T=(h=t.qualitative)==null?void 0:h.interactionStyle)==null?void 0:T.key_pattern)!=null?u:null,w=(_=(C=(f=t.qualitative)==null?void 0:f.memorableMoment)==null?void 0:C.headline)!=null?_:null,W=fe(t.heatmap||{},l);return e.createElement("div",{id:"share-card",style:{width:"1200px",background:l.background,color:l.textPrimary,fontFamily:\'ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"\',display:"flex",flexDirection:"column",padding:"48px 56px",position:"absolute",left:"-9999px",top:"-9999px",overflow:"hidden",boxSizing:"border-box"}},e.createElement("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:"32px"}},e.createElement("div",null,e.createElement("div",{style:{fontSize:"32px",fontWeight:700,letterSpacing:"-0.02em",lineHeight:1.2}},"Qwen Code Insights"),e.createElement("div",{style:{fontSize:"14px",color:l.textMuted,marginTop:"6px"}},x)),e.createElement("div",{style:{fontSize:"11px",color:l.textMuted,textTransform:"uppercase",letterSpacing:"0.15em",paddingTop:"8px"}},"qwen.ai")),e.createElement("div",{style:{display:"grid",gridTemplateColumns:"repeat(6, 1fr)",gap:"16px",marginBottom:"32px"}},e.createElement(M,{value:String(s),label:"Messages",theme:l}),e.createElement(M,{value:String(r),label:"Sessions",theme:l}),e.createElement(M,{value:`+${a}/-${o}`,label:"Lines Changed",small:!0,theme:l}),e.createElement(M,{value:String(i),label:"Files",theme:l}),e.createElement(M,{value:`${m}d`,label:"Streak",theme:l}),e.createElement(M,{value:`${c}d`,label:"Best Streak",theme:l})),e.createElement("div",{style:{display:"grid",gridTemplateColumns:"1fr 1fr",gap:"24px",marginBottom:"16px"}},e.createElement("div",{style:{background:l.cardBackground,borderRadius:"12px",padding:"20px",display:"flex",flexDirection:"column"}},e.createElement("div",{style:{fontSize:"12px",fontWeight:600,color:l.textMuted,textTransform:"uppercase",letterSpacing:"0.08em",marginBottom:"12px"}},"Activity \xB7 ",E," active days"),e.createElement("div",{style:{flex:1,display:"flex",alignItems:"center",justifyContent:"center"}},e.createElement(ge,{cells:W})),e.createElement(ye,{theme:l})),e.createElement("div",{style:{display:"flex",flexDirection:"column",gap:"16px"}},e.createElement("div",{style:{background:l.cardBackground,borderRadius:"12px",padding:"20px",display:"flex",flexDirection:"column"}},e.createElement("div",{style:{fontSize:"12px",fontWeight:600,color:l.textMuted,textTransform:"uppercase",letterSpacing:"0.08em",marginBottom:"12px"}},"Active Hours"),e.createElement("div",{style:{flex:1,display:"flex",flexDirection:"column",justifyContent:"center",gap:"10px"}},e.createElement(ue,{activeHours:d,theme:l}))),e.createElement("div",{style:{background:l.cardBackgroundSecondary,borderRadius:"12px",padding:"16px 16px",position:"relative"}},e.createElement("div",{style:{position:"absolute",left:"12px",fontSize:"64px",fontWeight:700,color:n==="light"?"rgba(99,102,241,0.15)":"rgba(99,102,241,0.2)",lineHeight:1,fontFamily:\'Georgia, "Times New Roman", serif\',userSelect:"none",pointerEvents:"none"}},"\u201C"),e.createElement("div",{style:{paddingLeft:"40px",position:"relative"}},A&&e.createElement("div",{style:{fontSize:"13px",color:l.textSecondary,lineHeight:1.6,marginBottom:w?"8px":0}},A),w&&e.createElement("div",{style:{fontSize:"12px",color:l.textMuted,lineHeight:1.5,fontStyle:"italic"}},w))))),e.createElement("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",marginTop:"auto",paddingTop:"24px",borderTop:`1px solid ${l.borderColor}`,flexShrink:0}},e.createElement("div",{style:{fontSize:"12px",color:l.textMuted}},"Generated by Qwen Code \xB7 ",new Date().toISOString().split("T")[0]),e.createElement("div",{style:{fontSize:"12px",color:l.textMuted}},"github.com/QwenLM/qwen-code")))}function M({value:t,label:n,small:l,theme:s}){return e.createElement("div",{style:{textAlign:"center"}},e.createElement("div",{style:{fontSize:l?"18px":"28px",fontWeight:700,color:s.textPrimary,lineHeight:1.2}},t),e.createElement("div",{style:{fontSize:"11px",color:s.textMuted,textTransform:"uppercase",letterSpacing:"0.05em",marginTop:"4px"}},n))}function ue({activeHours:t,theme:n}){const s=[{label:"Morning",time:"06\u201312",hours:[6,7,8,9,10,11],color:"#fbbf24"},{label:"Afternoon",time:"12\u201318",hours:[12,13,14,15,16,17],color:"#0ea5e9"},{label:"Evening",time:"18\u201322",hours:[18,19,20,21],color:"#6366f1"},{label:"Night",time:"22\u201306",hours:[22,23,0,1,2,3,4,5],color:"#475569"}].map(a=>({...a,total:a.hours.reduce((o,i)=>o+(t[i]||0),0)})),r=Math.max(...s.map(a=>a.total),1);return e.createElement(e.Fragment,null,s.map(a=>{const o=r>0?a.total/r*100:0;return e.createElement("div",{key:a.label},e.createElement("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",fontSize:"12px",marginBottom:"4px"}},e.createElement("div",{style:{display:"flex",alignItems:"center",gap:"6px"}},e.createElement("span",{style:{width:"8px",height:"8px",borderRadius:"50%",backgroundColor:a.color,display:"inline-block",flexShrink:0}}),e.createElement("span",{style:{color:n.textSecondary,fontWeight:500}},a.label),e.createElement("span",{style:{color:n.textMuted,fontSize:"11px"}},a.time)),e.createElement("span",{style:{color:n.textMuted,fontWeight:600}},a.total)),e.createElement("div",{style:{height:"6px",background:n.borderColor,borderRadius:"3px",overflow:"hidden"}},e.createElement("div",{style:{width:`${o}%`,height:"100%",backgroundColor:a.color,borderRadius:"3px"}})))}))}function fe(t,n){const l=new Date,r=26*7,a=new Date(l);a.setDate(a.getDate()-r+1),a.setDate(a.getDate()-a.getDay());const o=[],i=new Date(l);i.setDate(i.getDate()+(6-i.getDay()));const m=new Date(a);for(;m<=i;){const c=m.toISOString().split("T")[0],d=t[c]||0;o.push({color:he(d,n)}),m.setDate(m.getDate()+1)}return o}function he(t,n){return t===0?n.heatmapEmpty:t<2?n.heatmapColors[0]:t<4?n.heatmapColors[1]:t<10?n.heatmapColors[2]:n.heatmapColors[3]}function ge({cells:t}){const l=Math.ceil(t.length/7),s=14,r=3,a=l*(s+r),o=7*(s+r);return e.createElement("svg",{width:a,height:o,viewBox:`0 0 ${a} ${o}`},t.map((i,m)=>{const c=Math.floor(m/7),d=m%7;return e.createElement("rect",{key:m,x:c*(s+r),y:d*(s+r),width:s,height:s,rx:2,fill:i.color})}))}function ye({theme:t}){return e.createElement("div",{style:{display:"flex",alignItems:"center",gap:"8px",marginTop:"12px"}},e.createElement("span",{style:{fontSize:"11px",color:t.textMuted}},"Less"),[t.heatmapEmpty,t.heatmapColors[0],t.heatmapColors[1],t.heatmapColors[2],t.heatmapColors[3]].map((n,l)=>e.createElement("span",{key:l,style:{width:"10px",height:"10px",borderRadius:"2px",backgroundColor:n,display:"inline-block"}})),e.createElement("span",{style:{fontSize:"11px",color:t.textMuted}},"More"))}function b(t){return typeof t=="string"?t.trim().length>0:typeof t=="number"?Number.isFinite(t)&&t!==0:typeof t=="boolean"?t:Array.isArray(t)?t.some(n=>b(n)):t&&typeof t=="object"?Object.values(t).some(n=>b(n)):!1}function z(t){return Array.isArray(t)?t.some(([,n])=>Number.isFinite(n)&&n!==0):!!t&&Object.values(t).some(n=>Number.isFinite(n)&&n!==0)}function H(t){return Array.isArray(t)&&t.some(n=>b(n))}function xe({data:t}){var u,f,C,_,v,N,j,k,S,L,G,Y;const[n,l]=e.useState("dark"),s=e.useRef(!1),r=async()=>{const q=document.getElementById("share-card");if(!q||!window.html2canvas){alert("Export functionality is not available.");return}try{const y=q.cloneNode(!0);y.style.position="fixed",y.style.left="-9999px",y.style.top="0",y.style.pointerEvents="none",document.body.appendChild(y);const Q=await window.html2canvas(y,{scale:2,useCORS:!0,logging:!1,width:1200,height:y.scrollHeight});document.body.removeChild(y);const P=Q.toDataURL("image/png"),I=document.createElement("a");I.href=P,I.download=`qwen-insights-card-${new Date().toISOString().slice(0,10)}.png`,I.click()}catch(y){console.error("Export card error:",y),alert("Failed to export card. Please try again.")}};e.useEffect(()=>{s.current&&(s.current=!1,r())},[n]);const a=q=>{q===n?r():(s.current=!0,l(q))};if(!t)return e.createElement("div",{className:"text-center text-slate-600"},"No insight data available");const o=Object.keys(t.heatmap||{});let i="";if(o.length>0){const y=o.map(O=>new Date(O)).map(O=>O.getTime()),Q=new Date(Math.min(...y)),P=new Date(Math.max(...y)),I=O=>O.toISOString().split("T")[0];i=`${I(Q)} to ${I(P)}`}const m=b((u=t.qualitative)==null?void 0:u.atAGlance),c=!!t.qualitative&&(b(t.qualitative.projectAreas)||z(t.topGoals)||z(t.topTools)),d=b((f=t.qualitative)==null?void 0:f.interactionStyle),g=!!t.qualitative&&(b(t.qualitative.impressiveWorkflows)||z(t.primarySuccess)||z(t.outcomes)),E=!!t.qualitative&&(b(t.qualitative.frictionPoints)||z(t.satisfaction)||z(t.friction)),x=!!t.qualitative&&(H((C=t.qualitative.improvements)==null?void 0:C.Qwen_md_additions)||H((_=t.qualitative.improvements)==null?void 0:_.features_to_try)),A=!!t.qualitative&&H((v=t.qualitative.improvements)==null?void 0:v.usage_patterns),w=b((N=t.qualitative)==null?void 0:N.futureOpportunities),W=b((j=t.qualitative)==null?void 0:j.memorableMoment),h=[];c&&h.push({href:"#section-work",label:"What You Work On"}),d&&h.push({href:"#section-usage",label:"How You Use Qwen Code"}),g&&h.push({href:"#section-wins",label:"Impressive Things"}),E&&h.push({href:"#section-friction",label:"Where Things Go Wrong"}),x&&h.push({href:"#section-features",label:"Features to Try"}),A&&h.push({href:"#section-patterns",label:"New Usage Patterns"}),w&&h.push({href:"#section-horizon",label:"On the Horizon"});const T={wins:g,friction:E,features:x,horizon:w};return e.createElement("div",null,e.createElement("header",{className:"insights-header"},e.createElement("div",{className:"header-content"},e.createElement("div",{className:"header-title-section"},e.createElement("h1",{className:"header-title"},"Qwen Code Insights"),e.createElement("p",{className:"header-subtitle"},t.totalMessages?`${t.totalMessages.toLocaleString()} messages across ${(k=t.totalSessions)==null?void 0:k.toLocaleString()} sessions`:"Your personalized coding journey and patterns",i&&` \xB7 ${i}`)),e.createElement(Ee,{onExport:a}))),m&&t.qualitative&&e.createElement(ee,{qualitative:t.qualitative,targetSections:T}),h.length>0&&e.createElement(te,{sections:h}),e.createElement(U,{data:t}),c&&t.qualitative&&e.createElement(ne,{qualitative:t.qualitative,topGoals:t.topGoals,topTools:t.topTools}),d&&t.qualitative&&e.createElement(le,{qualitative:t.qualitative,insights:t}),g&&e.createElement(re,{qualitative:t.qualitative,primarySuccess:(S=t.primarySuccess)!=null?S:{},outcomes:(L=t.outcomes)!=null?L:{}}),E&&e.createElement(ae,{qualitative:t.qualitative,satisfaction:(G=t.satisfaction)!=null?G:{},friction:(Y=t.friction)!=null?Y:{}}),(x||A)&&t.qualitative&&e.createElement(ie,{qualitative:t.qualitative}),w&&t.qualitative&&e.createElement(me,{qualitative:t.qualitative}),W&&t.qualitative&&e.createElement(ce,{qualitative:t.qualitative}),e.createElement(pe,{data:t,theme:n}))}function Ee({onExport:t}){const[n,l]=e.useState(!1),s=e.useRef(null);e.useEffect(()=>{if(!n)return;const a=o=>{s.current&&!s.current.contains(o.target)&&l(!1)};return document.addEventListener("mousedown",a),()=>document.removeEventListener("mousedown",a)},[n]);const r=a=>{l(!1),t(a)};return e.createElement("div",{className:"export-dropdown-wrapper",ref:s},e.createElement("button",{className:"export-card-btn",onClick:()=>l(!n)},e.createElement("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"},e.createElement("path",{d:"M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8"}),e.createElement("polyline",{points:"16 6 12 2 8 6"}),e.createElement("line",{x1:"12",y1:"2",x2:"12",y2:"15"})),e.createElement("span",null,"Export Card"),e.createElement("svg",{width:"12",height:"12",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:`export-chevron ${n?"open":""}`},e.createElement("polyline",{points:"6 9 12 15 18 9"}))),n&&e.createElement("div",{className:"export-dropdown"},e.createElement("button",{className:"export-dropdown-item",onClick:()=>r("light")},e.createElement("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"},e.createElement("circle",{cx:"12",cy:"12",r:"5"}),e.createElement("line",{x1:"12",y1:"1",x2:"12",y2:"3"}),e.createElement("line",{x1:"12",y1:"21",x2:"12",y2:"23"}),e.createElement("line",{x1:"4.22",y1:"4.22",x2:"5.64",y2:"5.64"}),e.createElement("line",{x1:"18.36",y1:"18.36",x2:"19.78",y2:"19.78"}),e.createElement("line",{x1:"1",y1:"12",x2:"3",y2:"12"}),e.createElement("line",{x1:"21",y1:"12",x2:"23",y2:"12"}),e.createElement("line",{x1:"4.22",y1:"19.78",x2:"5.64",y2:"18.36"}),e.createElement("line",{x1:"18.36",y1:"5.64",x2:"19.78",y2:"4.22"})),e.createElement("span",null,"Light Theme")),e.createElement("button",{className:"export-dropdown-item",onClick:()=>r("dark")},e.createElement("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"},e.createElement("path",{d:"M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"})),e.createElement("span",null,"Dark Theme"))))}const $=document.getElementById("react-root");$&&window.INSIGHT_DATA&&B?B.createRoot($).render(e.createElement(xe,{data:window.INSIGHT_DATA})):console.error("Failed to mount React app:",{container:!!$,data:!!window.INSIGHT_DATA,ReactDOM:!!B})})(React,ReactDOM);';
|
|
2297
|
+
var INSIGHT_CSS = '*,:before,:after,::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: #3b82f680;--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border:0 solid #e5e7eb}:before,:after{--tw-content: ""}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";line-height:1.5}body{line-height:inherit;margin:0;background-image:linear-gradient(to bottom right,var(--tw-gradient-stops));--tw-gradient-from: #f8fafc var(--tw-gradient-from-position);--tw-gradient-to: #f1f5f9 var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), #fff var(--tw-gradient-via-position), var(--tw-gradient-to);--tw-text-opacity: 1;min-height:100vh;color:rgb(15 23 42 / var(--tw-text-opacity, 1));-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glass-card{--tw-border-opacity: 1;border-width:1px;border-color:rgb(226 232 240 / var(--tw-border-opacity, 1));--tw-shadow: 0 10px 40px #0f172a14;--tw-shadow-colored: 0 10px 40px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow);--tw-backdrop-blur: blur(8px);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);background-color:#fff9;border-radius:1rem}.col-span-2{grid-column:span 2 / span 2}.mx-auto{margin-left:auto;margin-right:auto}.mb-8{margin-bottom:2rem}.ml-2{margin-left:.5rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-4{margin-top:1rem}.mt-6{margin-top:1.5rem}.block{display:block}.flex{display:flex}.inline-flex{display:inline-flex}.grid{display:grid}.h-56{height:14rem}.h-full{height:100%}.min-h-screen{min-height:100vh}.w-full{width:100%}.min-w-\\[720px\\]{min-width:720px}.max-w-6xl{max-width:72rem}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.flex-col{flex-direction:column}.items-start{align-items:flex-start}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse))}.divide-slate-200>:not([hidden])~:not([hidden]){--tw-divide-opacity: 1;border-color:rgb(226 232 240 / var(--tw-divide-opacity, 1))}.overflow-x-auto{overflow-x:auto}.rounded-full{border-radius:9999px}.rounded-xl{border-radius:1.25rem}.border{border-width:1px}.border-slate-100{--tw-border-opacity: 1;border-color:rgb(241 245 249 / var(--tw-border-opacity, 1))}.bg-emerald-50{--tw-bg-opacity: 1;background-color:rgb(236 253 245 / var(--tw-bg-opacity, 1))}.bg-slate-100{--tw-bg-opacity: 1;background-color:rgb(241 245 249 / var(--tw-bg-opacity, 1))}.bg-slate-50{--tw-bg-opacity: 1;background-color:rgb(248 250 252 / var(--tw-bg-opacity, 1))}.bg-slate-900{--tw-bg-opacity: 1;background-color:rgb(15 23 42 / var(--tw-bg-opacity, 1))}.bg-white\\/70{background-color:#ffffff73}.bg-gradient-to-br{background-image:linear-gradient(to bottom right,var(--tw-gradient-stops))}.from-slate-50{--tw-gradient-from: #f8fafc var(--tw-gradient-from-position);--tw-gradient-to: #f8fafc00 var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.via-white{--tw-gradient-to: #ffffff00 var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), #ffffff var(--tw-gradient-via-position), var(--tw-gradient-to)}.to-slate-100{--tw-gradient-to: #f1f5f9 var(--tw-gradient-to-position)}.p-4{padding:1rem}.p-6{padding:1.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.px-8{padding-left:2rem;padding-right:2rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-10{padding-top:2.5rem;padding-bottom:2.5rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.text-left{text-align:left}.text-center{text-align:center}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.tracking-\\[0\\.2em\\]{letter-spacing:.2em}.tracking-tight{letter-spacing:-.025em}.tracking-wide{letter-spacing:.025em}.text-emerald-700{--tw-text-opacity: 1;color:rgb(4 120 87 / var(--tw-text-opacity, 1))}.text-rose-700{--tw-text-opacity: 1;color:rgb(190 18 60 / var(--tw-text-opacity, 1))}.text-slate-200{--tw-text-opacity: 1;color:rgb(226 232 240 / var(--tw-text-opacity, 1))}.text-slate-400{--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity, 1))}.text-slate-500{--tw-text-opacity: 1;color:rgb(100 116 139 / var(--tw-text-opacity, 1))}.text-slate-600{--tw-text-opacity: 1;color:rgb(71 85 105 / var(--tw-text-opacity, 1))}.text-slate-700{--tw-text-opacity: 1;color:rgb(51 65 85 / var(--tw-text-opacity, 1))}.text-slate-900{--tw-text-opacity: 1;color:rgb(15 23 42 / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.shadow-inner{--tw-shadow: inset 0 2px 4px 0 #0000000d;--tw-shadow-colored: inset 0 2px 4px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-soft{--tw-shadow: 0 10px 40px #0f172a14;--tw-shadow-colored: 0 10px 40px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-slate-100{--tw-shadow-color: #f1f5f9;--tw-shadow: var(--tw-shadow-colored)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.hover\\:-translate-y-\\[1px\\]:hover{--tw-translate-y: -1px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\\:shadow-lg:hover{--tw-shadow: 0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a;--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.focus-visible\\:outline:focus-visible{outline-style:solid}.focus-visible\\:outline-2:focus-visible{outline-width:2px}.focus-visible\\:outline-offset-2:focus-visible{outline-offset:2px}.focus-visible\\:outline-slate-400:focus-visible{outline-color:#94a3b8}.active\\:translate-y-\\[1px\\]:active{--tw-translate-y: 1px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.group:hover .group-hover\\:translate-x-0\\.5{--tw-translate-x: .125rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@media (min-width: 768px){.md\\:mt-6{margin-top:1.5rem}.md\\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\\:gap-6{gap:1.5rem}.md\\:py-12{padding-top:3rem;padding-bottom:3rem}.md\\:text-4xl{font-size:2.25rem;line-height:2.5rem}}.heatmap-container{width:100%;overflow-x:auto}.heatmap-svg{min-width:720px}.heatmap-day{cursor:pointer}.heatmap-day:hover{stroke:#00000024;stroke-width:1px}.heatmap-legend{display:flex;align-items:center;gap:4px;font-size:12px;color:#64748b;margin-top:8px}.heatmap-legend-item{width:10px;height:10px;border-radius:2px}.nav-toc{display:flex;flex-wrap:wrap;gap:8px;margin:24px 0 32px;padding:16px;background:#fff;border-radius:8px;border:1px solid #e2e8f0}.nav-toc a{font-size:12px;color:#64748b;text-decoration:none;padding:6px 12px;border-radius:6px;background:#f1f5f9;transition:all .15s}.nav-toc a:hover{background:#e2e8f0;color:#334155}.at-a-glance{background:linear-gradient(135deg,#fef3c7,#fde68a);border:1px solid #f59e0b;border-radius:12px;padding:20px 24px;margin-bottom:32px}.glance-title{font-size:16px;font-weight:700;color:#92400e;margin-bottom:16px}.glance-sections{display:flex;flex-direction:column;gap:12px}.glance-section{font-size:14px;color:#78350f;line-height:1.6}.glance-section strong{color:#92400e;font-weight:700}.see-more{color:#b45309;text-decoration:none;font-size:13px;white-space:nowrap;margin-left:4px}.see-more:hover{text-decoration:underline}.project-areas{display:flex;flex-direction:column;gap:12px;margin-bottom:32px}.project-area{background:#fff;border:1px solid #e2e8f0;border-radius:8px;padding:16px}.area-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:8px}.area-name{font-weight:600;font-size:15px;color:#0f172a}.area-count{font-size:12px;color:#64748b;background:#f1f5f9;padding:2px 8px;border-radius:4px}.area-desc{font-size:14px;color:#475569;line-height:1.5}.narrative{background:#fff;border:1px solid #e2e8f0;border-radius:8px;padding:20px;margin-bottom:24px}.narrative p{margin-top:0;margin-bottom:12px;font-size:14px;color:#475569;line-height:1.7}.key-insight{background:#f0fdf4;border:1px solid #bbf7d0;border-radius:8px;padding:12px 16px;margin-top:12px;font-size:14px;color:#166534}.section-intro{font-size:14px;color:#64748b;margin-bottom:16px}.big-wins{display:flex;flex-direction:column;gap:12px;margin-bottom:24px}.big-win{background:#f0fdf4;border:1px solid #bbf7d0;border-radius:8px;padding:16px}.big-win-title{font-weight:600;font-size:15px;color:#166534;margin-bottom:8px}.big-win-desc{font-size:14px;color:#15803d;line-height:1.5}.friction-categories{display:flex;flex-direction:column;gap:16px;margin-bottom:24px}.friction-category{background:#fef2f2;border:1px solid #fca5a5;border-radius:8px;padding:16px}.friction-title{font-weight:600;font-size:15px;color:#991b1b;margin-bottom:6px}.friction-desc{font-size:13px;color:#7f1d1d;margin-bottom:10px}.friction-examples{margin:0 0 0 10px;padding:0;font-size:13px;color:#334155;list-style-type:disc}.friction-examples li{margin-bottom:4px}.qwen-md-section{background:#eff6ff;border:1px solid #bfdbfe;border-radius:8px;padding:12px;margin-bottom:20px}.qwen-md-section h3{font-size:13px;font-weight:600;color:#1e40af;margin:0 0 8px}.qwen-md-actions{margin-bottom:8px;padding-bottom:8px;border-bottom:1px solid #dbeafe}.copy-all-btn{background:#2563eb;color:#fff;border:none;border-radius:4px;padding:4px 10px;font-size:11px;cursor:pointer;font-weight:500;transition:all .2s}.copy-all-btn:hover{background:#1d4ed8}.copy-all-btn.copied{background:#16a34a}.qwen-md-item{display:flex;flex-wrap:wrap;align-items:flex-start;gap:8px;padding:8px 0;border-bottom:1px solid #dbeafe}.qwen-md-item:last-child{border-bottom:none}.cmd-checkbox{margin-top:2px}.cmd-code{background:#fff;padding:6px 10px;border-radius:4px;font-size:11px;color:#1e40af;border:1px solid #bfdbfe;font-family:monospace;display:block;white-space:pre-wrap;word-break:break-word;flex:1}.cmd-why{font-size:11px;color:#64748b;width:100%;padding-left:20px;margin-top:4px}.features-section,.patterns-section{display:flex;flex-direction:column;gap:12px;margin:16px 0}.feature-card{background:#f0fdf4;border:1px solid #86efac;border-radius:8px;padding:16px}.pattern-card{background:#f0f9ff;border:1px solid #7dd3fc;border-radius:8px;padding:16px}.feature-title,.pattern-title{font-weight:600;font-size:15px;color:#0f172a;margin-bottom:6px}.feature-oneliner,.pattern-summary{font-size:14px;color:#475569;margin-bottom:8px}.feature-why,.pattern-detail{font-size:13px;color:#334155;line-height:1.5}.feature-examples{margin-top:12px}.feature-example{padding:8px 0;border-top:1px solid #d1fae5}.feature-example:first-child{border-top:none}.example-code-row,.copyable-prompt-row{display:flex;align-items:flex-start;gap:8px}.example-code{flex:1;background:#f1f5f9;padding:8px 12px;border-radius:4px;font-family:monospace;font-size:12px;color:#334155;overflow-x:auto;white-space:pre-wrap}.copyable-prompt-section{margin-top:12px;padding-top:12px;border-top:1px solid #e2e8f0}.copyable-prompt{flex:1;background:#f8fafc;padding:10px 12px;border-radius:4px;font-family:monospace;font-size:12px;color:#334155;border:1px solid #e2e8f0;white-space:pre-wrap;line-height:1.5}.prompt-label{font-size:11px;font-weight:600;text-transform:uppercase;color:#64748b;margin-bottom:6px}.copy-btn{background:#e2e8f0;border:none;border-radius:4px;padding:4px 8px;font-size:11px;cursor:pointer;color:#475569;flex-shrink:0;transition:all .2s}.copy-btn:hover{background:#cbd5e1}.horizon-section{display:flex;flex-direction:column;gap:16px}.horizon-card{background:linear-gradient(135deg,#faf5ff,#f5f3ff);border:1px solid #c4b5fd;border-radius:8px;padding:16px}.horizon-title{font-weight:600;font-size:15px;color:#5b21b6;margin-bottom:8px}.horizon-possible{font-size:14px;color:#334155;margin-bottom:10px;line-height:1.5}.horizon-tip{font-size:13px;color:#6b21a8;background:#fff9;padding:8px 12px;border-radius:4px}.pattern-prompt{background:#f8fafc;padding:12px;border-radius:6px;margin-top:12px;border:1px solid #e2e8f0;display:flex;flex-direction:column;gap:8px}.pattern-prompt code{font-family:monospace;font-size:12px;color:#334155;display:block;white-space:pre-wrap}.fun-ending{background:linear-gradient(135deg,#fef3c7,#fde68a);border:1px solid #fbbf24;border-radius:12px;padding:24px;margin-top:40px;text-align:center}.fun-headline{font-size:18px;font-weight:600;color:#78350f;margin-bottom:8px}.fun-detail{font-size:14px;color:#92400e}.stats-row{display:flex;gap:24px;margin-bottom:40px;padding:20px 0;border-top:1px solid #e2e8f0;border-bottom:1px solid #e2e8f0;flex-wrap:wrap}.stat{text-align:center}.stat-value{font-size:24px;font-weight:700;color:#0f172a}.stat-label{font-size:11px;color:#64748b;text-transform:uppercase}@media (max-width: 640px){.stats-row{justify-content:center}}.header-with-action{position:relative}.insights-header{margin-bottom:2rem;padding:1.5rem 0;border-bottom:1px solid #e2e8f0}.header-content{display:flex;justify-content:space-between;align-items:center;gap:1.5rem;flex-wrap:wrap}.header-title-section{flex:1;min-width:0}.header-title{font-size:1.75rem;font-weight:700;color:#0f172a;letter-spacing:-.02em;margin:0 0 .375rem;line-height:1.2}.header-subtitle{font-size:.875rem;color:#64748b;margin:0;font-weight:400}.export-dropdown-wrapper{position:relative}.export-card-btn{display:inline-flex;align-items:center;gap:.5rem;height:36px;padding:0 .875rem;border:1px solid #e2e8f0;border-radius:8px;background:#fff;color:#334155;font-size:.8125rem;font-weight:500;cursor:pointer;transition:all .15s ease}.export-card-btn:hover{background:#f8fafc;border-color:#cbd5e1}.export-card-btn:active{background:#f1f5f9}.export-chevron{transition:transform .15s ease;opacity:.5}.export-chevron.open{transform:rotate(180deg)}.export-dropdown{position:absolute;top:calc(100% + 4px);right:0;min-width:160px;background:#fff;border:1px solid #e2e8f0;border-radius:8px;box-shadow:0 4px 16px #00000014;padding:4px;z-index:50}.export-dropdown-item{display:flex;align-items:center;gap:.5rem;width:100%;padding:.5rem .75rem;border:none;border-radius:6px;background:none;color:#334155;font-size:.8125rem;font-weight:400;cursor:pointer;transition:background .1s ease}.export-dropdown-item:hover{background:#f1f5f9}.export-dropdown-item:active{background:#e2e8f0}@media (max-width: 640px){.header-content{flex-direction:column;align-items:flex-start;gap:1rem}.header-title{font-size:1.5rem}}';
|
|
2298
|
+
|
|
2299
|
+
// packages/web-templates/src/generated/exportHtmlTemplate.ts
|
|
2300
|
+
init_esbuild_shims();
|
|
2301
|
+
var HTML_TEMPLATE = '<!doctype html>\n<html lang="en" class="dark">\n <head>\n <meta charset="UTF-8" />\n <meta name="viewport" content="width=device-width, initial-scale=1.0" />\n <link\n rel="icon"\n type="image/svg+xml"\n href="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20141.38%20140%22%3E%0A%20%20%3Cpath%0A%20%20%20%20fill%3D%22%23000000%22%0A%20%20%20%20d%3D%22m140.93%2085-16.35-28.33-1.93-3.34%208.66-15a3.323%203.323%200%200%200%200-3.34l-9.62-16.67c-.3-.51-.72-.93-1.22-1.22s-1.07-.45-1.67-.45H82.23l-8.66-15a3.33%203.33%200%200%200-2.89-1.67H51.43c-.59%200-1.17.16-1.66.45-.5.29-.92.71-1.22%201.22L32.19%2029.98l-1.92%203.33H12.96c-.59%200-1.17.16-1.66.45-.5.29-.93.71-1.22%201.22L.45%2051.66a3.323%203.323%200%200%200%200%203.34l18.28%2031.67-8.66%2015a3.32%203.32%200%200%200%200%203.34l9.62%2016.67c.3.51.72.93%201.22%201.22s1.07.45%201.67.45h36.56l8.66%2015a3.35%203.35%200%200%200%202.89%201.67h19.25a3.34%203.34%200%200%200%202.89-1.67l18.28-31.67h17.32c.6%200%201.17-.16%201.67-.45s.92-.71%201.22-1.22l9.62-16.67a3.323%203.323%200%200%200%200-3.34ZM51.44%203.33%2061.07%2020l-9.63%2016.66h76.98l-9.62%2016.66H45.67l-11.54-20zM57.21%20120H22.58l9.63-16.67h19.25l-38.5-66.67h19.25l9.62%2016.67L68.78%20100l-11.55%2020Zm61.59-33.34-9.62-16.67-38.49%2066.67-9.63-16.67%209.63-16.66%2026.94-46.67h23.1l17.32%2030z%22%0A%20%20%2F%3E%0A%3C%2Fsvg%3E"\n />\n <script\n crossorigin\n src="https://unpkg.com/react@18.2.0/umd/react.production.min.js"\n ></script>\n <script\n crossorigin\n src="https://unpkg.com/react-dom@18.2.0/umd/react-dom.production.min.js"\n ></script>\n <script>\n const withKey = (props, key) =>\n key == null ? props : Object.assign({}, props, { key });\n const jsx = (type, props, key) =>\n React.createElement(type, withKey(props, key));\n const jsxRuntime = {\n Fragment: React.Fragment,\n jsx,\n jsxs: jsx,\n jsxDEV: jsx,\n };\n window.ReactJSXRuntime = jsxRuntime;\n window[\'react/jsx-runtime\'] = jsxRuntime;\n window[\'react/jsx-dev-runtime\'] = jsxRuntime;\n </script>\n <script src="https://unpkg.com/@qwen-code/webui@latest/dist/index.umd.js"></script>\n <link\n rel="stylesheet"\n href="https://unpkg.com/@qwen-code/webui@latest/dist/styles.css"\n />\n <title>Qwen Code Chat Export</title>\n <script>\n // Pre-hydrate FOUC guard: must run before <style> below applies layout.\n // The storage key \'qwen-export-theme\' is duplicated here verbatim and\n // MUST stay in sync with EXPORT_THEME_STORAGE_KEY in\n // src/components/useExportTheme.ts.\n (function () {\n try {\n var stored = window.localStorage.getItem(\'qwen-export-theme\');\n var theme = stored === \'light\' || stored === \'dark\' ? stored : \'dark\';\n var root = document.documentElement;\n // Toggle-style writes mirror the React hook\'s effect, so the two\n // code paths converge on identical class state.\n root.classList.toggle(\'light\', theme === \'light\');\n root.classList.toggle(\'dark\', theme === \'dark\');\n } catch (e) {\n // localStorage may be unavailable (private mode, file:// sandbox);\n // the static class="dark" attribute on <html> remains the default.\n }\n })();\n </script>\n <style>\n @font-face {\n font-family: "Press Start 2P";\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url("data:font/woff2;base64,d09GMgABAAAAAALQAAwAAAAABfwAAAKBAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHCgGYABUEQgKgkSCDAsOAAE2AiQDDgQgBYRKByAb4QTIBB76Oev9JKW02x5ClpELSxHm1M0JQ+OBJAtDpAAVUQ7i///V+A/YgLVswlGo/7a+lmW3sfnUvoBFcUKzUFEnKo08S0F2T8TiAAJQieDvSGUVdW3smBv2LuCGjSpG3jQTD/m9OI5lTDomdQG1hkoMkCJu1ZYsmL42dEu7W8q5gUan/J6yyO+FX5NO5qQPxaqGnEINZ2q7kDf0+i4UigAXdiQUNMppoJnOzcxnDMwX5lXzinnJPDtkzhQFwjTx0DGrx1zkoNhIYr5LTKHjclcs+z3Frrh2ue3Kvk6bxzoRJLsIQpWcQhW27bgJwoUHYXNi2WWnVRUWaVNS0XMJ1eIUHlSX0l3l7BZOOos1ySk7NUWl6+eobG3Nfpj96g8EvukB3Qjouo4+O6svG9/0b8ZyKmfoZj9gzBqq8I2MS7Pf2JquL9vZwHJ51djyD01vbVHRDxSslvFBZwMHjQvexMxIvz3oyftul2+k9yBS+xGM+l+d+Pvo/zH5fVXMRvsHhG4u9/dRsgQyF67l9+jYgZuy+Ath2O6EUzU7E6BxF41nQk2cgkN8IIlOPKecMgWccSrE4XdaOECf00oUaeTm34EpvHhZIodEEllllBWmWcJLyQmsPjNHAousMEkijVRQR5OgNc4qq7TiZZg89pJCE/G0MM4kPuYqqIOKrQw3WmQBjVQSSLLm1H1NiGmCN21uwK/JpZRuWignd/klmbWXFEtZZIn1o8cmkaDqX5JIJgWNNqYYR9s0GsRFZhhntKJSjI+KTaFDZ+MoRllkjHWK2ADCxilLQGTkJZo4NAJMDwhAiK0CJD+jjKFRwWBapYFh5rdzfogQC/m1XLplXiEFEwAA") format("woff2");\n }\n :root{--bg-primary: #18181b;--bg-secondary: #27272a;--text-primary: #f4f4f5;--text-secondary: #a1a1aa;--border-color: #3f3f46;--accent-color: #3b82f6;--header-bg: rgba(24, 24, 27, .95);--scrollbar-thumb-hover: #52525b}:root.light{--bg-primary: #ffffff;--bg-secondary: #f3f4f6;--text-primary: #1f2937;--text-secondary: #6b7280;--border-color: #e5e7eb;--accent-color: #2563eb;--header-bg: rgba(249, 250, 251, .95);--scrollbar-thumb-hover: #d1d5db;--app-primary-foreground: #1f2937;--app-secondary-foreground: #6b7280;--app-background: #ffffff;--app-primary-background: #ffffff;--app-background-secondary: #f3f4f6;--app-background-tertiary: #e5e7eb;--app-foreground: #1f2937;--app-foreground-secondary: #6b7280;--app-foreground-muted: #9ca3af;--app-border: #e5e7eb;--app-primary-border-color: #e5e7eb;--app-input-background: #ffffff;--app-input-border: #d1d5db;--app-input-placeholder-foreground: #9ca3af;--app-ghost-button-hover-background: rgba(0, 0, 0, .05);--app-header-background: #f9fafb;--app-list-hover-background: rgba(0, 0, 0, .05);--app-list-active-background: #3b82f6;--app-menu-background: #ffffff;--app-menu-border: #e5e7eb;--app-menu-foreground: #1f2937;--app-tool-background: #ffffff;--app-code-background: #f3f4f6;--app-secondary-background: #f3f4f6;--app-input-secondary-background: #f3f4f6;--app-input-foreground: #1f2937;--app-button-background: #e5e7eb;--app-button-secondary-background: #f3f4f6;--app-button-foreground: #1f2937;--app-transparent-inner-border: rgba(0, 0, 0, .1);--app-warning-foreground: #b45309}body{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;margin:0;padding:0;background-color:var(--bg-primary);color:var(--text-primary);line-height:1.6;-webkit-font-smoothing:antialiased}.page-wrapper{min-height:100vh;display:flex;flex-direction:column;align-items:center}.header{width:100%;padding:16px 24px;border-bottom:1px solid var(--border-color);background-color:var(--header-bg);backdrop-filter:blur(8px);position:sticky;top:0;z-index:100;display:flex;justify-content:space-between;align-items:center;box-sizing:border-box}.header-left{display:flex;align-items:center;gap:12px}.header-right{display:flex;align-items:center;gap:8px}.theme-toggle{display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;padding:0;background:transparent;border:1px solid var(--border-color);border-radius:999px;color:var(--text-secondary);cursor:pointer;transition:background-color .15s ease,color .15s ease,border-color .15s ease}.theme-toggle:hover{background-color:var(--bg-secondary);color:var(--text-primary)}.theme-toggle:focus-visible{outline:2px solid var(--accent-color);outline-offset:2px}.theme-toggle:active{transform:scale(.95)}.logo-icon{width:24px;height:24px;flex-shrink:0;display:flex;align-items:center;justify-content:center}.logo-icon svg{width:100%;height:100%}.logo{display:flex;flex-direction:column;line-height:1}.logo-text{font-family:"Press Start 2P",cursive;font-weight:400;font-size:24px;letter-spacing:-.05em;position:relative;color:#fff}.logo-text-inner{background:linear-gradient(to right,#60a5fa,#a855f7);-webkit-background-clip:text;-webkit-text-fill-color:transparent;position:relative;z-index:2}.logo-text:before,.logo-text:after{content:attr(data-text);position:absolute;top:0;left:0;width:100%;height:100%;z-index:1;background:none;-webkit-text-fill-color:transparent;-webkit-text-stroke:1px rgba(96,165,250,.3)}.logo-text:before{transform:translate(2px,2px);-webkit-text-stroke:1px rgba(168,85,247,.3)}.logo-text:after{transform:translate(4px,4px);opacity:.4}.logo-sub{font-size:11px;font-weight:600;color:var(--text-secondary);letter-spacing:.05em;text-transform:uppercase;margin-top:4px}.badge{font-size:11px;padding:2px 8px;border-radius:999px;background-color:var(--bg-secondary);color:var(--text-secondary);border:1px solid var(--border-color);font-weight:500}.meta{display:flex;gap:24px;font-size:13px;color:var(--text-secondary)}.meta-item{display:flex;align-items:center;gap:8px}.meta-label{color:var(--text-secondary)}::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar-track{background:var(--bg-primary)}::-webkit-scrollbar-thumb{background:var(--bg-secondary);border-radius:5px;border:2px solid var(--bg-primary)}::-webkit-scrollbar-thumb:hover{background:var(--scrollbar-thumb-hover)}@media (max-width: 768px){.chat-container{max-width:100%;padding:20px 16px}.header{padding:12px 16px}.meta{width:100%;flex-direction:column;gap:6px}}@media (max-width: 480px){.chat-container{padding:16px 12px}}.content-wrapper{display:flex;width:100%;max-width:1600px;height:calc(100vh - 73px)}.chat-container{flex:1;min-width:0;overflow-y:auto;padding:24px;box-sizing:border-box}.metadata-sidebar{width:320px;min-width:320px;padding:12px;border-right:1px solid var(--border-color);background-color:var(--bg-secondary);display:flex;flex-direction:column;gap:12px;overflow-y:auto;height:100%;box-sizing:border-box}.metadata-section{display:flex;flex-direction:column;gap:8px}.metadata-section-title{font-size:10px;font-weight:600;color:var(--text-secondary);text-transform:uppercase;letter-spacing:.05em;margin:0;padding-bottom:4px;border-bottom:1px solid var(--border-color)}.metadata-section-small{margin-top:auto;padding-top:12px;border-top:1px solid var(--border-color)}.metadata-item{display:flex;flex-direction:column;gap:2px}.metadata-item-empty{font-size:12px;color:var(--text-secondary);margin:0;padding:4px 0}.metadata-content{display:flex;flex-direction:column;gap:2px;min-width:0}.metadata-content .metadata-label{font-size:10px;color:var(--text-secondary)}.metadata-content .metadata-value{font-size:12px;color:var(--text-primary);word-break:break-all;line-height:1.3;cursor:pointer}.metadata-content .metadata-value.multiline{white-space:pre-wrap}.metadata-content .metadata-value.text-green{color:#22c55e}.metadata-content .metadata-value.text-red{color:#ef4444}.metadata-value-with-copy{display:flex;align-items:center;gap:8px}.metadata-value-with-copy .metadata-value{flex:1;min-width:0}.copy-button{display:inline-flex;align-items:center;justify-content:center;padding:4px;background:transparent;border:1px solid var(--border-color, #3f3f46);border-radius:4px;color:var(--text-secondary, #a1a1aa);cursor:pointer;transition:all .15s ease;flex-shrink:0}.copy-button:hover{background:var(--bg-hover, #27272a);color:var(--text-primary, #f4f4f5);border-color:var(--border-hover, #52525b)}.copy-button:active{transform:scale(.95)}@media (max-width: 1024px){.metadata-sidebar{width:320px;min-width:320px;padding:10px}}@media (max-width: 768px){.content-wrapper{flex-direction:column;height:auto}.chat-container{height:auto;min-height:50vh}.metadata-sidebar{width:100%;min-width:100%;height:auto;max-height:none;border-right:none;border-top:1px solid var(--border-color);padding:12px;gap:12px}.metadata-section{flex-direction:row;flex-wrap:wrap;gap:12px}.metadata-section-title{width:100%;border-bottom:none;padding-bottom:0}.metadata-item{flex:1;min-width:140px}.metadata-section-small{margin-top:0;padding-top:0;border-top:none}}.modal-overlay{position:fixed;inset:0;z-index:1000;background-color:#0009;display:flex;align-items:center;justify-content:center;padding:24px}.modal-container{background-color:var(--bg-secondary);border:1px solid var(--border-color);border-radius:12px;width:100%;max-width:800px;max-height:80vh;display:flex;flex-direction:column;box-shadow:0 25px 50px -12px #00000080}.modal-header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid var(--border-color);flex-shrink:0}.modal-title{font-size:13px;color:var(--text-secondary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.modal-close{background:none;border:none;color:var(--text-secondary);cursor:pointer;font-size:16px;padding:4px 8px;border-radius:6px;line-height:1;transition:background-color .15s,color .15s}.modal-close:hover{background-color:var(--border-color);color:var(--text-primary)}.modal-content{margin:0;padding:16px;overflow:auto;font-size:13px;line-height:1.6;color:var(--text-primary);white-space:pre-wrap;word-break:break-word}\n </style>\n </head>\n <body>\n <div id="app"></div>\n\n <script id="chat-data" type="application/json"></script>\n <script>\n (()=>{var f=`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 141.38 140">\n <path\n fill="#000000"\n d="m140.93 85-16.35-28.33-1.93-3.34 8.66-15a3.323 3.323 0 0 0 0-3.34l-9.62-16.67c-.3-.51-.72-.93-1.22-1.22s-1.07-.45-1.67-.45H82.23l-8.66-15a3.33 3.33 0 0 0-2.89-1.67H51.43c-.59 0-1.17.16-1.66.45-.5.29-.92.71-1.22 1.22L32.19 29.98l-1.92 3.33H12.96c-.59 0-1.17.16-1.66.45-.5.29-.93.71-1.22 1.22L.45 51.66a3.323 3.323 0 0 0 0 3.34l18.28 31.67-8.66 15a3.32 3.32 0 0 0 0 3.34l9.62 16.67c.3.51.72.93 1.22 1.22s1.07.45 1.67.45h36.56l8.66 15a3.35 3.35 0 0 0 2.89 1.67h19.25a3.34 3.34 0 0 0 2.89-1.67l18.28-31.67h17.32c.6 0 1.17-.16 1.67-.45s.92-.71 1.22-1.22l9.62-16.67a3.323 3.323 0 0 0 0-3.34ZM51.44 3.33 61.07 20l-9.63 16.66h76.98l-9.62 16.66H45.67l-11.54-20zM57.21 120H22.58l9.63-16.67h19.25l-38.5-66.67h19.25l9.62 16.67L68.78 100l-11.55 20Zm61.59-33.34-9.62-16.67-38.49 66.67-9.63-16.67 9.63-16.66 26.94-46.67h23.1l17.32 30z"\n />\n</svg>\n`;var l=window.React,h=({state:e,onClose:t})=>(l.useEffect(()=>{if(e.visible){let o=document.body.style.overflow;return document.body.style.overflow="hidden",()=>{document.body.style.overflow=o}}},[e.visible]),e.visible?l.createElement("div",{className:"modal-overlay",onClick:t},l.createElement("div",{className:"modal-container",onClick:o=>o.stopPropagation()},l.createElement("div",{className:"modal-header"},l.createElement("span",{className:"modal-title font-mono"},e.fileName),l.createElement("button",{className:"modal-close",onClick:t,"aria-label":"Close"},"\\u2715")),l.createElement("pre",{className:"modal-content"},e.content))):null),x=()=>{let[e,t]=l.useState({visible:!1,content:"",fileName:""}),o=l.useCallback((n,p="temp")=>{t({visible:!0,content:n,fileName:p})},[]),i=l.useCallback(()=>{t(n=>({...n,visible:!1}))},[]);return{modalState:e,openModal:o,closeModal:i}};var z=window.React,b=()=>{let{modalState:e,openModal:t,closeModal:o}=x();return{platformContext:z.useMemo(()=>({platform:"web",postMessage:n=>{console.log("Posted message:",n)},onMessage:n=>(window.addEventListener("message",n),()=>window.removeEventListener("message",n)),openFile:n=>{console.log("Opening file:",n)},openTempFile:t,getResourceUrl:()=>{},features:{canOpenFile:!1,canOpenTempFile:!0,canCopy:!0}}),[t]),modalState:e,closeModal:o}};var a=({label:e,value:t,valueClass:o})=>t==null||t===""?null:React.createElement("div",{className:"metadata-item"},React.createElement("div",{className:"metadata-content"},React.createElement("span",{className:"metadata-label"},e),React.createElement("span",{className:`metadata-value ${o||""}`,title:typeof t=="string"?t:void 0},t)));var v=e=>!!e&&typeof e=="object",w=()=>{let e=document.getElementById("chat-data");if(!(e!=null&&e.textContent))return{};try{let t=JSON.parse(e.textContent);return t&&typeof t=="object"?t:{}}catch(t){return console.error("Failed to parse chat data.",t),{}}};var y=e=>{if(!e)return"-";try{return new Date(e).toLocaleString("en-US",{year:"numeric",month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}catch(t){return e}},k=e=>{if(!e)return"-";try{let o=new Date(e).getTime();if(Number.isNaN(o))return"-";let n=Math.max(0,new Date().getTime()-o),p=Math.floor(n/1e3),c=Math.floor(p/60),d=Math.floor(c/60),s=Math.floor(d/24),m=Math.floor(s/7),g=Math.floor(s/30),u=Math.floor(s/365);return p<60?"just now":c<60?`${c} minute${c===1?"":"s"} ago`:d<24?`${d} hour${d===1?"":"s"} ago`:s<7?`${s} day${s===1?"":"s"} ago`:m<4?`${m} week${m===1?"":"s"} ago`:g<12?`${g} month${g===1?"":"s"} ago`:`${u} year${u===1?"":"s"} ago`}catch(t){return"-"}};var M=e=>{if(e!=null)return e>=1e6?`${(e/1e6).toFixed(e%1e6===0?0:1)}m`:e>=1e3?`${(e/1e3).toFixed(e%1e3===0?0:1)}k`:e.toString()};var T=({metadata:e})=>React.createElement("aside",{className:"metadata-sidebar"},React.createElement("div",{className:"metadata-section"},React.createElement("h3",{className:"metadata-section-title"},"Session Info"),React.createElement(a,{label:"Session created",value:k(e.startTime)}),React.createElement(a,{label:"Project",value:e.cwd,valueClass:"multiline"}),e.gitRepo&&React.createElement(a,{label:"Repository",value:e.gitRepo}),e.gitBranch&&React.createElement(a,{label:"Branch",value:e.gitBranch}),e.model&&React.createElement(a,{label:"Model",value:e.model}),e.channel&&React.createElement(a,{label:"Channel",value:e.channel})),React.createElement("div",{className:"metadata-section"},React.createElement("h3",{className:"metadata-section-title"},"Statistics"),React.createElement(a,{label:"Prompts",value:e.promptCount}),e.contextUsagePercent!==void 0&&e.contextWindowSize!==void 0&&React.createElement(a,{label:"Context",value:`${e.contextUsagePercent>100?">100":e.contextUsagePercent}% of ${M(e.contextWindowSize)}`,valueClass:e.contextUsagePercent>100?"text-red":void 0}),e.totalTokens!==void 0&&React.createElement(a,{label:"Tokens",value:e.totalTokens.toLocaleString()})),React.createElement("div",{className:"metadata-section"},React.createElement("h3",{className:"metadata-section-title"},"File Operations"),e.filesWritten!==void 0&&e.filesWritten>0&&React.createElement(a,{label:"Files modified",value:e.filesWritten}),e.linesAdded!==void 0&&e.linesAdded>0&&React.createElement(a,{label:"Added",value:`+${e.linesAdded}`,valueClass:"text-green"}),e.linesRemoved!==void 0&&e.linesRemoved>0&&React.createElement(a,{label:"Removed",value:`-${e.linesRemoved}`,valueClass:"text-red"}),(e.filesWritten===void 0||e.filesWritten===0)&&(e.linesAdded===void 0||e.linesAdded===0)&&(e.linesRemoved===void 0||e.linesRemoved===0)&&React.createElement("p",{className:"metadata-item metadata-item-empty"},"No file changes")),React.createElement("div",{className:"metadata-section metadata-section-small"},React.createElement(a,{label:"Session ID",value:e.sessionId,valueClass:"font-mono"}),React.createElement(a,{label:"Export Time",value:y(e.exportTime)})));var $=()=>React.createElement("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true"},React.createElement("circle",{cx:"12",cy:"12",r:"4"}),React.createElement("path",{d:"M12 2v2"}),React.createElement("path",{d:"M12 20v2"}),React.createElement("path",{d:"m4.93 4.93 1.41 1.41"}),React.createElement("path",{d:"m17.66 17.66 1.41 1.41"}),React.createElement("path",{d:"M2 12h2"}),React.createElement("path",{d:"M20 12h2"}),React.createElement("path",{d:"m6.34 17.66-1.41 1.41"}),React.createElement("path",{d:"m19.07 4.93-1.41 1.41"})),D=()=>React.createElement("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true"},React.createElement("path",{d:"M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"})),C=({theme:e,onToggle:t})=>{let o=e==="light",i=o?"Switch to dark theme":"Switch to light theme";return React.createElement("button",{type:"button",className:"theme-toggle","aria-label":i,"aria-pressed":o,title:i,onClick:t},React.createElement(o?D:$,null))};var L=window.React,{useCallback:j,useEffect:I,useState:W}=L,N="qwen-export-theme",R=e=>e==="light"||e==="dark",F=()=>{try{let e=window.localStorage.getItem(N);if(R(e))return e}catch(e){}return"dark"},O=e=>{let t=document.documentElement;t.classList.toggle("light",e==="light"),t.classList.toggle("dark",e==="dark")},S=()=>{let[e,t]=W(F);I(()=>{O(e);try{window.localStorage.setItem(N,e)}catch(i){}},[e]);let o=j(()=>{t(i=>i==="light"?"dark":"light")},[]);return{theme:e,toggleTheme:o}};var A=window.ReactDOM,r=window.React,{ChatViewer:U,PlatformProvider:V}=QwenCodeWebUI,B=f?f.replace(/<svg([^>]*)>/,\'<svg$1><defs><linearGradient id="qwen-logo-gradient" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="0%" stop-color="#60a5fa" /><stop offset="100%" stop-color="#a855f7" /></linearGradient></defs>\').replace(/fill="[^"]*"/,\'fill="url(#qwen-logo-gradient)"\'):f,H=()=>{let e=w(),o=(Array.isArray(e.messages)?e.messages:[]).filter(v).filter(m=>m.type!=="system"),i=e.metadata,{platformContext:n,modalState:p,closeModal:c}=b(),{theme:d,toggleTheme:s}=S();return r.createElement("div",{className:"page-wrapper"},r.createElement("header",{className:"header"},r.createElement("div",{className:"header-left"},r.createElement("div",{className:"logo-icon","aria-hidden":"true",dangerouslySetInnerHTML:{__html:B}}),r.createElement("div",{className:"logo"},r.createElement("div",{className:"logo-text","data-text":"QWEN"},r.createElement("span",{className:"logo-text-inner"},"QWEN")))),r.createElement("div",{className:"header-right"},r.createElement(C,{theme:d,onToggle:s}))),r.createElement("div",{className:"content-wrapper"},r.createElement("div",{className:"chat-container"},r.createElement(V,{value:n},r.createElement(U,{messages:o,autoScroll:!1,theme:d}))),i&&r.createElement(T,{metadata:i})),r.createElement(h,{state:p,onClose:c}))},E=document.getElementById("app");E?A.createRoot(E).render(r.createElement(H,null)):console.error("App container not found.");})();;\n </script>\n </body>\n</html>\n';
|
|
2302
|
+
|
|
2303
|
+
// packages/cli/src/ui/utils/export/formatters/html.ts
|
|
2304
|
+
function escapeJsonForHtml(json) {
|
|
2305
|
+
return json.replace(/<\/script/gi, "<\\/script").replace(/&/g, "\\u0026").replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
2306
|
+
}
|
|
2307
|
+
__name(escapeJsonForHtml, "escapeJsonForHtml");
|
|
2308
|
+
function loadHtmlTemplate() {
|
|
2309
|
+
return HTML_TEMPLATE;
|
|
2310
|
+
}
|
|
2311
|
+
__name(loadHtmlTemplate, "loadHtmlTemplate");
|
|
2312
|
+
function injectDataIntoHtmlTemplate(template, data) {
|
|
2313
|
+
const jsonData = JSON.stringify(data, null, 2);
|
|
2314
|
+
const escapedJsonData = escapeJsonForHtml(jsonData);
|
|
2315
|
+
const idAttribute = 'id="chat-data"';
|
|
2316
|
+
const idIndex = template.indexOf(idAttribute);
|
|
2317
|
+
if (idIndex === -1) {
|
|
2318
|
+
return template;
|
|
2319
|
+
}
|
|
2320
|
+
const openTagStart = template.lastIndexOf("<script", idIndex);
|
|
2321
|
+
if (openTagStart === -1) {
|
|
2322
|
+
return template;
|
|
2323
|
+
}
|
|
2324
|
+
const openTagEnd = template.indexOf(">", idIndex);
|
|
2325
|
+
if (openTagEnd === -1) {
|
|
2326
|
+
return template;
|
|
2327
|
+
}
|
|
2328
|
+
const closeTagStart = template.indexOf("</script>", openTagEnd);
|
|
2329
|
+
if (closeTagStart === -1) {
|
|
2330
|
+
return template;
|
|
2331
|
+
}
|
|
2332
|
+
const lineStart = template.lastIndexOf("\n", openTagStart);
|
|
2333
|
+
const lineIndent = lineStart === -1 ? "" : template.slice(lineStart + 1, openTagStart);
|
|
2334
|
+
const indentedJson = escapedJsonData.split("\n").map((line) => `${lineIndent}${line}`).join("\n");
|
|
2335
|
+
const before = template.slice(0, openTagEnd + 1);
|
|
2336
|
+
const after = template.slice(closeTagStart);
|
|
2337
|
+
return `${before}
|
|
2338
|
+
${indentedJson}
|
|
2339
|
+
${after}`;
|
|
2340
|
+
}
|
|
2341
|
+
__name(injectDataIntoHtmlTemplate, "injectDataIntoHtmlTemplate");
|
|
2342
|
+
function toHtml(sessionData) {
|
|
2343
|
+
const template = loadHtmlTemplate();
|
|
2344
|
+
return injectDataIntoHtmlTemplate(template, sessionData);
|
|
2345
|
+
}
|
|
2346
|
+
__name(toHtml, "toHtml");
|
|
2347
|
+
|
|
2348
|
+
// packages/cli/src/ui/utils/export/formatters/json.ts
|
|
2349
|
+
init_esbuild_shims();
|
|
2350
|
+
function toJson(sessionData) {
|
|
2351
|
+
return JSON.stringify(sessionData, null, 2);
|
|
2352
|
+
}
|
|
2353
|
+
__name(toJson, "toJson");
|
|
2354
|
+
|
|
2355
|
+
// packages/cli/src/ui/utils/export/formatters/jsonl.ts
|
|
2356
|
+
init_esbuild_shims();
|
|
2357
|
+
function toJsonl(sessionData) {
|
|
2358
|
+
const lines = [];
|
|
2359
|
+
const sourceMetadata = sessionData.metadata;
|
|
2360
|
+
const metadata = {
|
|
2361
|
+
type: "session_metadata",
|
|
2362
|
+
sessionId: sessionData.sessionId,
|
|
2363
|
+
startTime: sessionData.startTime
|
|
2364
|
+
};
|
|
2365
|
+
if (sourceMetadata?.exportTime) {
|
|
2366
|
+
metadata["exportTime"] = sourceMetadata.exportTime;
|
|
2367
|
+
}
|
|
2368
|
+
if (sourceMetadata?.cwd) {
|
|
2369
|
+
metadata["cwd"] = sourceMetadata.cwd;
|
|
2370
|
+
}
|
|
2371
|
+
if (sourceMetadata?.gitRepo) {
|
|
2372
|
+
metadata["gitRepo"] = sourceMetadata.gitRepo;
|
|
2373
|
+
}
|
|
2374
|
+
if (sourceMetadata?.gitBranch) {
|
|
2375
|
+
metadata["gitBranch"] = sourceMetadata.gitBranch;
|
|
2376
|
+
}
|
|
2377
|
+
if (sourceMetadata?.model) {
|
|
2378
|
+
metadata["model"] = sourceMetadata.model;
|
|
2379
|
+
}
|
|
2380
|
+
if (sourceMetadata?.channel) {
|
|
2381
|
+
metadata["channel"] = sourceMetadata.channel;
|
|
2382
|
+
}
|
|
2383
|
+
if (sourceMetadata?.promptCount !== void 0) {
|
|
2384
|
+
metadata["promptCount"] = sourceMetadata.promptCount;
|
|
2385
|
+
}
|
|
2386
|
+
if (sourceMetadata?.contextUsagePercent !== void 0) {
|
|
2387
|
+
metadata["contextUsagePercent"] = sourceMetadata.contextUsagePercent;
|
|
2388
|
+
}
|
|
2389
|
+
if (sourceMetadata?.contextWindowSize !== void 0) {
|
|
2390
|
+
metadata["contextWindowSize"] = sourceMetadata.contextWindowSize;
|
|
2391
|
+
}
|
|
2392
|
+
if (sourceMetadata?.totalTokens !== void 0) {
|
|
2393
|
+
metadata["totalTokens"] = sourceMetadata.totalTokens;
|
|
2394
|
+
}
|
|
2395
|
+
if (sourceMetadata?.filesWritten !== void 0) {
|
|
2396
|
+
metadata["filesWritten"] = sourceMetadata.filesWritten;
|
|
2397
|
+
}
|
|
2398
|
+
if (sourceMetadata?.linesAdded !== void 0) {
|
|
2399
|
+
metadata["linesAdded"] = sourceMetadata.linesAdded;
|
|
2400
|
+
}
|
|
2401
|
+
if (sourceMetadata?.linesRemoved !== void 0) {
|
|
2402
|
+
metadata["linesRemoved"] = sourceMetadata.linesRemoved;
|
|
2403
|
+
}
|
|
2404
|
+
if (sourceMetadata?.uniqueFiles && sourceMetadata.uniqueFiles.length > 0) {
|
|
2405
|
+
metadata["uniqueFiles"] = sourceMetadata.uniqueFiles;
|
|
2406
|
+
}
|
|
2407
|
+
lines.push(JSON.stringify(metadata));
|
|
2408
|
+
for (const message of sessionData.messages) {
|
|
2409
|
+
lines.push(JSON.stringify(message));
|
|
2410
|
+
}
|
|
2411
|
+
return lines.join("\n");
|
|
2412
|
+
}
|
|
2413
|
+
__name(toJsonl, "toJsonl");
|
|
2414
|
+
|
|
2415
|
+
// packages/cli/src/ui/utils/export/utils.ts
|
|
2416
|
+
init_esbuild_shims();
|
|
2417
|
+
function generateExportFilename(extension) {
|
|
2418
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
2419
|
+
return `qwen-code-export-${timestamp}.${extension}`;
|
|
2420
|
+
}
|
|
2421
|
+
__name(generateExportFilename, "generateExportFilename");
|
|
2422
|
+
|
|
2423
|
+
// packages/cli/src/ui/utils/export/index.ts
|
|
2424
|
+
init_esbuild_shims();
|
|
2425
|
+
|
|
2426
|
+
export {
|
|
2427
|
+
GITHUB_WORKFLOW_PATHS,
|
|
2428
|
+
SetupGithubError,
|
|
2429
|
+
setupGithub,
|
|
2430
|
+
MessageEmitter,
|
|
2431
|
+
PlanEmitter,
|
|
2432
|
+
ToolCallEmitter,
|
|
2433
|
+
HistoryReplayer,
|
|
2434
|
+
collectSessionData,
|
|
2435
|
+
normalizeSessionData,
|
|
2436
|
+
toMarkdown,
|
|
2437
|
+
INSIGHT_JS,
|
|
2438
|
+
INSIGHT_CSS,
|
|
2439
|
+
toHtml,
|
|
2440
|
+
toJson,
|
|
2441
|
+
toJsonl,
|
|
2442
|
+
generateExportFilename
|
|
2443
|
+
};
|
|
2444
|
+
/**
|
|
2445
|
+
* @license
|
|
2446
|
+
* Copyright 2025 Qwen
|
|
2447
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
2448
|
+
*/
|
|
2449
|
+
/**
|
|
2450
|
+
* @license
|
|
2451
|
+
* Copyright 2025 Qwen Team
|
|
2452
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
2453
|
+
*/
|
|
2454
|
+
/**
|
|
2455
|
+
* @license
|
|
2456
|
+
* Copyright 2025 Google LLC
|
|
2457
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
2458
|
+
*/
|
|
2459
|
+
/**
|
|
2460
|
+
* @license
|
|
2461
|
+
* Copyright 2025 Qwen Team
|
|
2462
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
2463
|
+
*
|
|
2464
|
+
* This file is code-generated; do not edit manually.
|
|
2465
|
+
*/
|
|
2466
|
+
/**
|
|
2467
|
+
* @license
|
|
2468
|
+
* Copyright 2025 Qwen Team
|
|
2469
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
2470
|
+
*
|
|
2471
|
+
* This HTML template is code-generated; do not edit manually.
|
|
2472
|
+
*/
|