@qwen-code/qwen-code 0.21.2 → 0.21.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundled/qc-helper/docs/configuration/settings.md +41 -38
- package/bundled/qc-helper/docs/features/channels/github.md +7 -0
- package/bundled/qc-helper/docs/features/channels/gitlab.md +6 -0
- package/bundled/qc-helper/docs/features/code-review.md +78 -23
- package/bundled/qc-helper/docs/features/commands.md +2 -0
- package/bundled/qc-helper/docs/features/hooks.md +115 -18
- package/bundled/qc-helper/docs/features/memory.md +27 -0
- package/bundled/qc-helper/docs/features/skills.md +46 -1
- package/bundled/qc-helper/docs/features/sub-agents.md +42 -9
- package/bundled/qc-helper/docs/features/tool-use-summaries.md +7 -7
- package/bundled/qc-helper/docs/qwen-serve.md +21 -1
- package/bundled/qc-helper/docs/reference/keyboard-shortcuts.md +13 -13
- package/bundled/qc-helper/docs/support/troubleshooting.md +6 -1
- package/bundled/review/DESIGN.md +167 -32
- package/bundled/review/SKILL.md +156 -32
- package/chunks/{MaxSizedBox-TQBQ247P.js → MaxSizedBox-OJR636GP.js} +40 -38
- package/chunks/{StandaloneSessionPicker-2HPTKCLX.js → StandaloneSessionPicker-AMMBF5UY.js} +62 -59
- package/chunks/{acp-startup-profiler-2C4A5ZTJ.js → acp-startup-profiler-3RICG2YW.js} +2 -2
- package/chunks/{acpAgent-PS6EDGH3.js → acpAgent-M57LVIQA.js} +662 -560
- package/chunks/{agent-VDOUB35F.js → agent-PE37ARLM.js} +36 -34
- package/chunks/{agent-headless-EO53EFS2.js → agent-headless-45ASME4R.js} +36 -34
- package/chunks/{anthropicContentGenerator-OFHSZJBF.js → anthropicContentGenerator-WCBYB6JG.js} +337 -27
- package/chunks/{artifact-tool-RDN2W7ND.js → artifact-tool-TBOYEKTY.js} +2 -2
- package/chunks/{askUserQuestion-OZERWH5R.js → askUserQuestion-23Y5WZFJ.js} +2 -2
- package/chunks/{bridge-W7AZSRZQ.js → bridge-K3ZRPO4D.js} +42 -40
- package/chunks/{ca-6W3SK7OQ.js → ca-4OJN75WT.js} +46 -5
- package/chunks/{channel-management-service-5S7YCWX5.js → channel-management-service-IXJ2MZTS.js} +7 -7
- package/chunks/{channel-settings-store-JFVRSNER.js → channel-settings-store-PEAR3IME.js} +43 -41
- package/chunks/{channel-worker-group-OVWGYMZS.js → channel-worker-group-NDG4WOOZ.js} +8 -8
- package/chunks/{channel-worker-manager-H55GKOQA.js → channel-worker-manager-ZCW6UW34.js} +8 -8
- package/chunks/{channel-worker-supervisor-CABBXYHK.js → channel-worker-supervisor-ATGFTZRN.js} +4 -4
- package/chunks/{chunk-W3UKBMSI.js → chunk-22YFMJBW.js} +84 -8
- package/chunks/{chunk-6MPDY6ZG.js → chunk-24ER7UV4.js} +1 -1
- package/chunks/{chunk-QDK4F2N5.js → chunk-2DNKEBXY.js} +1 -1
- package/chunks/{chunk-D6MDRSZ6.js → chunk-2LZCLQIS.js} +22 -11
- package/chunks/{chunk-JYBU6YUE.js → chunk-2M5N3DHY.js} +1 -1
- package/chunks/{chunk-KR32NIAN.js → chunk-2MI7ZTRT.js} +10 -10
- package/chunks/{chunk-LHKCY7DY.js → chunk-2UISUFHQ.js} +3 -3
- package/chunks/{chunk-JXVC2PL3.js → chunk-33FNCQSY.js} +2 -2
- package/chunks/{chunk-NBD76HUW.js → chunk-3LGZEYOF.js} +2 -2
- package/chunks/{chunk-CO2U743O.js → chunk-3MWNROHB.js} +4 -4
- package/chunks/{chunk-E2BHWIDT.js → chunk-3RXUYQJI.js} +6 -2
- package/chunks/{chunk-E5Z2AVNV.js → chunk-3SH53ANB.js} +0 -11
- package/chunks/{chunk-LYI2PZDK.js → chunk-3XF4WT3B.js} +2 -2
- package/chunks/{chunk-N4ACHWNH.js → chunk-432XCUHF.js} +1 -1
- package/chunks/{chunk-FNDXMN7I.js → chunk-4AGGSHCH.js} +774 -205
- package/chunks/{chunk-DUNI4EBW.js → chunk-4K3RV3OA.js} +80 -50
- package/chunks/{chunk-L2E5GFAG.js → chunk-4LKVQFHM.js} +2 -2
- package/chunks/{chunk-YDLJGZHL.js → chunk-4NFY2S7N.js} +0 -33
- package/chunks/{chunk-JLZ3RBQG.js → chunk-5JPVOYWA.js} +144 -11
- package/chunks/{chunk-6TAASXWL.js → chunk-5VYFXHY2.js} +3 -3
- package/chunks/{chunk-EU5TBFJI.js → chunk-6NE5NTHJ.js} +2 -2
- package/chunks/{chunk-XQK4XXTN.js → chunk-6O5DVH27.js} +1 -1
- package/chunks/{chunk-2RFKHEXL.js → chunk-6PLDPT2C.js} +1 -1
- package/chunks/{chunk-3APUUXRF.js → chunk-A5YZ3FA2.js} +2 -1
- package/chunks/{chunk-SHN4KHDK.js → chunk-A6SX5TAH.js} +3 -3
- package/chunks/{chunk-SZ3KHTDR.js → chunk-AKA24BGO.js} +1 -1
- package/chunks/{chunk-Q3T5KA2V.js → chunk-BFHXDAR7.js} +1 -1
- package/chunks/{chunk-L55JWS76.js → chunk-BGXZBI5B.js} +1 -1
- package/chunks/{chunk-P5VC5USY.js → chunk-BKGA75MU.js} +1 -1
- package/chunks/{chunk-2KKCCLPT.js → chunk-BKXTHMOZ.js} +1 -1
- package/chunks/{chunk-V4XNUDPE.js → chunk-BSKUTHLO.js} +15 -7
- package/chunks/{chunk-MM7TH7ZM.js → chunk-CFDR3GNL.js} +18 -3
- package/chunks/{chunk-E2FN6SM7.js → chunk-CIUUYB23.js} +5 -5
- package/chunks/{chunk-A7Y5H4TX.js → chunk-D2GPKXCQ.js} +7 -7
- package/chunks/{chunk-JCJ7LKNA.js → chunk-DIEFUBV6.js} +1644 -1570
- package/chunks/{chunk-GL4JOZXU.js → chunk-DSGJLHM3.js} +4 -4
- package/chunks/{chunk-675H6PLP.js → chunk-DYA25Y7U.js} +1 -1
- package/chunks/{chunk-3I6DUGQD.js → chunk-E4WHKETF.js} +32 -4
- package/chunks/{chunk-CU47KXB5.js → chunk-EGYJRIDF.js} +6 -6
- package/chunks/{chunk-6CQWRWUC.js → chunk-EIMKVOSF.js} +3 -3
- package/chunks/{chunk-QTERJVPZ.js → chunk-EKTCKZV5.js} +1 -0
- package/chunks/{chunk-NHFEMWAZ.js → chunk-FF75UUB2.js} +1 -1
- package/chunks/{chunk-L32VV3ZJ.js → chunk-FG63DZQA.js} +12 -12
- package/chunks/{chunk-FCYYAB4S.js → chunk-FHPKHXHT.js} +3 -3
- package/chunks/{chunk-GJ2GBPBD.js → chunk-FXVHVCNA.js} +5 -5
- package/chunks/{chunk-56Z7QEAQ.js → chunk-GMSBXEH4.js} +16 -16
- package/chunks/chunk-GOFAQQZA.js +132 -0
- package/chunks/{chunk-YUFIEIWC.js → chunk-GTM6IHBB.js} +2 -2
- package/chunks/{chunk-HIVKI6O6.js → chunk-H35Q5CEG.js} +9 -7
- package/chunks/{chunk-FJ5WUMUQ.js → chunk-H36SETQS.js} +1 -1
- package/chunks/{chunk-AUOULH6Q.js → chunk-H6FIBBXK.js} +1610 -2196
- package/chunks/{chunk-VEMNQMHA.js → chunk-H6ZYP74A.js} +5 -13
- package/chunks/{chunk-TTJZAIFP.js → chunk-HEBW74ZW.js} +3 -3
- package/chunks/{chunk-6FMJLI5M.js → chunk-HFVW54NL.js} +41 -6
- package/chunks/{chunk-44F4LBWZ.js → chunk-HIXVWF7I.js} +56 -18
- package/chunks/{chunk-EQNUDTL6.js → chunk-HUIQ4FYC.js} +2 -2
- package/chunks/{chunk-5NNHICSA.js → chunk-I7JDGNG6.js} +3 -3
- package/chunks/{chunk-PVNQRENX.js → chunk-IF6K42YJ.js} +1 -1
- package/chunks/{chunk-PJOHNFIY.js → chunk-IWGTGH4G.js} +5 -5
- package/chunks/{chunk-B4AJNNOL.js → chunk-J26HHFI5.js} +1 -1
- package/chunks/{chunk-CNTR4GR6.js → chunk-JELIWHXD.js} +1 -1
- package/chunks/{chunk-V25K5ID7.js → chunk-K2J5JZ6B.js} +1 -1
- package/chunks/{chunk-IGTHU3T4.js → chunk-KKN2IE7Q.js} +1 -1
- package/chunks/{chunk-TZTAV5RH.js → chunk-KVUBYJDM.js} +2 -2
- package/chunks/{chunk-3F2WDAV6.js → chunk-KXWERR6P.js} +14 -14
- package/chunks/{chunk-JJPKFJBT.js → chunk-L7FTDKCD.js} +3 -3
- package/chunks/chunk-LBOVL47Y.js +29 -0
- package/chunks/{chunk-FS674JW4.js → chunk-LBWNSLJK.js} +3 -3
- package/chunks/{chunk-I5BT7ADR.js → chunk-LGT3YMLN.js} +4 -4
- package/chunks/{chunk-UV6KF7T3.js → chunk-LZV2BZPL.js} +3 -3
- package/chunks/{chunk-P755N4CS.js → chunk-M5LIY7Y6.js} +6 -6
- package/chunks/{chunk-YGE3IXJP.js → chunk-M744OFVE.js} +1 -1
- package/chunks/{chunk-NTDH4IML.js → chunk-MCXMWLFT.js} +7 -7
- package/chunks/chunk-MISUEWB4.js +8749 -0
- package/chunks/{chunk-TEGJSJDF.js → chunk-MOHAWIAW.js} +2 -2
- package/chunks/{chunk-KXDONCPU.js → chunk-MTR4JWQJ.js} +4 -4
- package/chunks/{chunk-RSVPYAGK.js → chunk-MUEJ4R3E.js} +5 -5
- package/chunks/{chunk-PCK4B6LR.js → chunk-N42C2FU3.js} +1 -1
- package/chunks/{chunk-WWCMSZII.js → chunk-NW57GHNL.js} +71 -7
- package/chunks/{chunk-PQNHRFJC.js → chunk-NYX53SV4.js} +0 -2
- package/chunks/{chunk-QARJNL2V.js → chunk-O2ZYHG33.js} +5 -4
- package/chunks/{chunk-V7RNNPGC.js → chunk-P5Y23G2L.js} +18 -1
- package/chunks/{chunk-GURGAJTX.js → chunk-PDDYAXL2.js} +4 -1
- package/chunks/chunk-PWCQRLM5.js +1170 -0
- package/chunks/{chunk-VMX5RZQH.js → chunk-Q3G5L5KF.js} +18 -9
- package/chunks/{chunk-DQ2O5QOJ.js → chunk-QDWLUXKP.js} +1 -1
- package/chunks/chunk-QL4TN4HS.js +59 -0
- package/chunks/{chunk-E6CJ2SMM.js → chunk-QMBEW7EW.js} +2 -2
- package/chunks/{chunk-U4VTUMMK.js → chunk-QONSRAEV.js} +1 -1
- package/chunks/{chunk-DEEABGH2.js → chunk-QPSYIV2O.js} +3320 -536
- package/chunks/{chunk-Q5WZTTWE.js → chunk-QWDVZH24.js} +6 -8
- package/chunks/{chunk-2LEOZTBT.js → chunk-QWW6I2UO.js} +111 -26
- package/chunks/{chunk-LOY7RWQG.js → chunk-QYPT3QUD.js} +3 -3
- package/chunks/{chunk-6PQPKTXP.js → chunk-R7XNRHYD.js} +1 -1
- package/chunks/{chunk-7SJN2IWT.js → chunk-RCXCGZG6.js} +5 -5
- package/chunks/{chunk-HX6RLYUO.js → chunk-RL6J3BPE.js} +4 -4
- package/chunks/{chunk-Z3S5EMOW.js → chunk-RPYYTL7E.js} +60 -12
- package/chunks/{chunk-MB32MS4U.js → chunk-RR224BUP.js} +215 -174
- package/chunks/{chunk-H6I4PGRV.js → chunk-SKSF3LGQ.js} +4 -4
- package/chunks/{chunk-77V3VIKL.js → chunk-SQ3YD5MI.js} +9 -9
- package/chunks/{chunk-CBBP4BMC.js → chunk-SRY26X4H.js} +72 -206
- package/chunks/{chunk-RDJOB6S3.js → chunk-TXABHVZD.js} +1 -1
- package/chunks/{chunk-R2XWGR75.js → chunk-TYERNYH4.js} +2 -2
- package/chunks/chunk-TZTBZ25J.js +222 -0
- package/chunks/{chunk-45IOTAUS.js → chunk-U25CMJYY.js} +1 -1
- package/chunks/{chunk-7ULQIS27.js → chunk-UEJESCS7.js} +1 -1
- package/chunks/{chunk-HC45LTEN.js → chunk-UH7Z7Y45.js} +1 -1
- package/chunks/{chunk-CPZAH673.js → chunk-UKZEXS6K.js} +2 -0
- package/chunks/{chunk-54YCNSK5.js → chunk-UQDFEU47.js} +4113 -10152
- package/chunks/{chunk-XP4L6KS3.js → chunk-URN76TKR.js} +2 -2
- package/chunks/{chunk-XUGZYLDH.js → chunk-UWSXFI6E.js} +1 -1
- package/chunks/{chunk-AOHY3QJ3.js → chunk-VA5NLVPT.js} +3 -3
- package/chunks/{chunk-PZEXDV3H.js → chunk-VUNRNRN6.js} +71 -43
- package/chunks/{chunk-FANRZEAJ.js → chunk-VWOVHOTT.js} +1 -1
- package/chunks/{chunk-QTHQ6Z5X.js → chunk-WK4TJUEA.js} +1 -1
- package/chunks/{chunk-ZPZ7ZJEE.js → chunk-WUC6ZFXO.js} +1 -1
- package/chunks/{chunk-7KAXXBER.js → chunk-WY2ENRDN.js} +3 -3
- package/chunks/{chunk-TIRRPCFS.js → chunk-X6QNZOTC.js} +1 -1
- package/chunks/{chunk-KWHKHSIS.js → chunk-X6WUYMOV.js} +8 -8
- package/chunks/{chunk-IIUGIWWY.js → chunk-XC2VAFVZ.js} +1 -1
- package/chunks/{chunk-D4HTUMGX.js → chunk-XC656O42.js} +3 -3
- package/chunks/{chunk-RG64CDT2.js → chunk-XMJO6C44.js} +131 -48
- package/chunks/{chunk-ZMOJ7ISP.js → chunk-XUMAD5IT.js} +1 -1
- package/chunks/{chunk-THVU3RNH.js → chunk-YAVY33G4.js} +1 -1
- package/chunks/{chunk-YANIWTRZ.js → chunk-YPUHMQXV.js} +1 -1
- package/chunks/{chunk-QCXGC7QB.js → chunk-YU6TBRTA.js} +3 -3
- package/chunks/{chunk-OFZKFPYG.js → chunk-YWMDTMAU.js} +3 -3
- package/chunks/{chunk-DSFHVTWD.js → chunk-YXEVDA66.js} +2 -2
- package/chunks/{chunk-JE2CEOBO.js → chunk-ZGSUFIL5.js} +4 -4
- package/chunks/{chunk-BBIQAX4V.js → chunk-ZJES4C3I.js} +30 -18
- package/chunks/{computer-use-5QWCFNKD.js → computer-use-UJMK6JQU.js} +36 -34
- package/chunks/{config-utils-WADIDWGG.js → config-utils-7COTJMWK.js} +4 -4
- package/chunks/{contextCommand-4Z7T7TUM.js → contextCommand-4YABGF4S.js} +40 -38
- package/chunks/{core-runtime-6N4EFC2Q.js → core-runtime-7M4VM3DA.js} +36 -34
- package/chunks/{create-sub-session-AEREHZBQ.js → create-sub-session-HOFDW4N7.js} +39 -37
- package/chunks/{create-sub-session-62YZWVAY.js → create-sub-session-J32WC64U.js} +2 -2
- package/chunks/{cron-create-6E7GIQTG.js → cron-create-HMFSHIAR.js} +4 -4
- package/chunks/{cron-delete-JD26XY3W.js → cron-delete-ZJFHOX57.js} +4 -4
- package/chunks/{cron-list-CUWFB44G.js → cron-list-ZEX2NBMN.js} +4 -4
- package/chunks/{daemon-PCNCI5YU.js → daemon-CCIX4BMG.js} +47 -6
- package/chunks/{daemon-status-provider-DDF7C5M7.js → daemon-status-provider-W2U5Q3J5.js} +47 -45
- package/chunks/{daemon-trust-policy-Q4KSOJTR.js → daemon-trust-policy-IFICWPXP.js} +42 -40
- package/chunks/{daemon-trust-policy-monitor-V6FTE3IY.js → daemon-trust-policy-monitor-GX7EO6FW.js} +42 -40
- package/chunks/{de-SY6O76BF.js → de-A6TI4LBB.js} +46 -5
- package/chunks/{deferred-core-runtime-GHJ5GQHK.js → deferred-core-runtime-U36OOOKE.js} +36 -34
- package/chunks/display-image-VS3TXYQH.js +184 -0
- package/chunks/{dist-ZHXOBXDN.js → dist-3BMEUGTG.js} +1 -1
- package/chunks/{dist-26BIMQT6.js → dist-4KAX7CCL.js} +289 -27
- package/chunks/{dist-OAOC5OV4.js → dist-7JGAAQSC.js} +2 -2
- package/chunks/{dist-SL2LUMML.js → dist-A7H2KKUC.js} +1 -1
- package/chunks/{dist-2PERFI23.js → dist-DPPHJAVL.js} +3 -3
- package/chunks/{dist-PVEAFLHY.js → dist-HVBMEYWK.js} +1 -1
- package/chunks/{dist-ULIG4M5H.js → dist-NEBRI7WO.js} +67 -15
- package/chunks/{dist-WGMNT3JQ.js → dist-SFQ34F4M.js} +24 -6
- package/chunks/{earlyInputCapture-TQXLLISD.js → earlyInputCapture-5ZWDH3SB.js} +37 -35
- package/chunks/{edit-FJEUV6KZ.js → edit-J7SW6UP6.js} +36 -34
- package/chunks/{en-NBK3JKCE.js → en-L4UQDLWW.js} +57 -6
- package/chunks/{enter-worktree-7GE3TZ4P.js → enter-worktree-NRLOHRB6.js} +36 -34
- package/chunks/{enterPlanMode-KR5TMPCJ.js → enterPlanMode-GDSTEFSM.js} +36 -34
- package/chunks/{environment-SWL3CMB3.js → environment-KHYEKG5W.js} +39 -37
- package/chunks/{errors-XQE7BGZV.js → errors-VNLAJV3O.js} +39 -37
- package/chunks/{exit-worktree-CHKTYNCV.js → exit-worktree-ARVID7DF.js} +36 -34
- package/chunks/{exitPlanMode-QYAG6LWX.js → exitPlanMode-4ZFY7KUH.js} +36 -34
- package/chunks/{fast-path-Z2K7W6DC.js → fast-path-KA65VREJ.js} +9 -5
- package/chunks/{fr-4KG5V7UT.js → fr-QF7RI5ZE.js} +46 -5
- package/chunks/{gemini-YU4XKEDG.js → gemini-5PMCNPF7.js} +149 -90
- package/chunks/{geminiContentGenerator-ZZX6NBO4.js → geminiContentGenerator-NFSYJ4HA.js} +6 -6
- package/chunks/{glob-VYF5CXSX.js → glob-F3EAUDAX.js} +36 -34
- package/chunks/{goal-tools-HGO6VXPB.js → goal-tools-SPQ5M6D3.js} +3 -3
- package/chunks/{grep-5DP5ZUTW.js → grep-UJMPVZER.js} +36 -34
- package/chunks/{handleAutoUpdate-UVBJ56DL.js → handleAutoUpdate-MG4FRZPN.js} +42 -40
- package/chunks/{i18n-UQNYHEUD.js → i18n-EVHV4ZF3.js} +38 -36
- package/chunks/{image-gen-WHPIZNWF.js → image-gen-UC7XVHI7.js} +9 -9
- package/chunks/{initializer-GMIICF4W.js → initializer-O5B6HUBI.js} +43 -41
- package/chunks/{installationInfo-4MGG4WVI.js → installationInfo-2LIKCNVX.js} +37 -35
- package/chunks/{ja-F3GSQXMF.js → ja-URQESVGW.js} +46 -5
- package/chunks/{keychain-token-storage-IKO4G53C.js → keychain-token-storage-7BT4TQ2A.js} +2 -2
- package/chunks/{kittyProtocolDetector-MBRTDRBK.js → kittyProtocolDetector-BFLAKYXH.js} +1 -1
- package/chunks/{list-CPN2W334.js → list-BPKIE3Z4.js} +45 -43
- package/chunks/{list-agents-PXJ7ZUFB.js → list-agents-TWEGRJWO.js} +2 -2
- package/chunks/{loadedSettingsAdapter-ZQAV5NDO.js → loadedSettingsAdapter-NGLFF4V4.js} +42 -40
- package/chunks/{loggingContentGenerator-5E7W4IEP.js → loggingContentGenerator-7TFESRG5.js} +52 -37
- package/chunks/{loop-wakeup-Y26NQZ5I.js → loop-wakeup-6LLEOQYV.js} +5 -5
- package/chunks/{ls-ONQTTMQR.js → ls-H5WX22VK.js} +4 -4
- package/chunks/{lsp-YGHHRGMD.js → lsp-G6FXYEIS.js} +2 -2
- package/chunks/{managed-npm-update-MKKAXYXA.js → managed-npm-update-CLZGGV7F.js} +39 -37
- package/chunks/{mcp-V5NTJF6X.js → mcp-X5OZOOXX.js} +42 -40
- package/chunks/{monitor-CO3ASY6E.js → monitor-TGSVSAZZ.js} +36 -34
- package/chunks/nonInteractiveCli-GUMJ5JLG.js +150 -0
- package/chunks/{notebook-edit-Z7AEE6FM.js → notebook-edit-EZISE7IC.js} +36 -34
- package/chunks/{openaiContentGenerator-CA3MQOP3.js → openaiContentGenerator-ZAKS5A6P.js} +18 -18
- package/chunks/{pidfile-NL7MKDRU.js → pidfile-PCMBX4LR.js} +37 -35
- package/chunks/{processUtils-PB5K2DYH.js → processUtils-2CSVE5BW.js} +2 -2
- package/chunks/{pt-EQ33KWEN.js → pt-EEEQXRUI.js} +46 -5
- package/chunks/{qwenContentGenerator-JYFNDCOS.js → qwenContentGenerator-S3H6PIC4.js} +42 -40
- package/chunks/{qwenOAuth2-W2ALKQDD.js → qwenOAuth2-MNU425VE.js} +8 -8
- package/chunks/{read-file-IEOR5H5W.js → read-file-HXJXHBI6.js} +10 -10
- package/chunks/{read-mcp-resource-U2IJN5HM.js → read-mcp-resource-DRZSI3HE.js} +2 -2
- package/chunks/{record-artifact-MGPJ7EG4.js → record-artifact-IPIRWMFY.js} +3 -3
- package/chunks/{resumeHistoryUtils-BNBTP5AS.js → resumeHistoryUtils-4QAMC2S6.js} +44 -42
- package/chunks/{ripGrep-UMQODKEB.js → ripGrep-MCETPF2E.js} +36 -34
- package/chunks/{ru-7OZAUKGG.js → ru-WGZDYQAB.js} +46 -5
- package/chunks/{run-qwen-serve-RN2R6QQW.js → run-qwen-serve-3NMODTXV.js} +219 -55
- package/chunks/{runtime-QFJ2MJF5.js → runtime-AQOV7DVP.js} +49 -45
- package/chunks/{scheduler-AMYUFOZI.js → scheduler-DN7SZ6ZE.js} +36 -34
- package/chunks/{sdk-exporters-http-4BQANSJ6.js → sdk-exporters-http-IKNWQJNV.js} +2 -2
- package/chunks/{sdk-impl-Z4VXWVFX.js → sdk-impl-7CUUMQDB.js} +2 -2
- package/chunks/{send-message-PMP4ATVM.js → send-message-HGCVVDTZ.js} +5 -4
- package/chunks/{serve-EIIYJVX3.js → serve-WZB45HVT.js} +42 -40
- package/chunks/{server-EP2LLAPD.js → server-GOTZFEEZ.js} +616 -387
- package/chunks/{session-GMPZBLOW.js → session-23LOFLWN.js} +149 -87
- package/chunks/{settings-LN7RNKBS.js → settings-LI2ORVXC.js} +41 -39
- package/chunks/{shell-EM2OWU5X.js → shell-GLC6OP3C.js} +36 -34
- package/chunks/{skill-T5VPSK73.js → skill-C7W6M4GO.js} +27 -14
- package/chunks/{skill-settings-GMR3GMNY.js → skill-settings-W25NCK5I.js} +41 -39
- package/chunks/{spawnChannel-YPCU62DI.js → spawnChannel-OHJLEBLD.js} +38 -36
- package/chunks/{standalone-update-JAKIM2NF.js → standalone-update-E4V5V7WT.js} +39 -37
- package/chunks/{startInteractiveUI-YETQWGYF.js → startInteractiveUI-FKILLW7Q.js} +1815 -1034
- package/chunks/{syntheticOutput-D7E6ZFKR.js → syntheticOutput-EYL7DWO7.js} +3 -3
- package/chunks/{task-create-NFCYD43L.js → task-create-CSCEG4SM.js} +10 -9
- package/chunks/{task-list-TAVMGEVD.js → task-list-6CVQPORX.js} +6 -6
- package/chunks/{task-stop-ZDF2UJRM.js → task-stop-Y5ZTFVRX.js} +2 -2
- package/chunks/{task-update-6L7LHGEX.js → task-update-C52LNFU5.js} +10 -9
- package/chunks/{team-create-LFJ6HGNY.js → team-create-HBIJ7NHT.js} +36 -34
- package/chunks/{team-delete-DPGGRQBU.js → team-delete-CE7DC53R.js} +6 -6
- package/chunks/{team-plan-approval-C2KLSDGO.js → team-plan-approval-IBJOKS4J.js} +36 -34
- package/chunks/terminal-image-renderer-BOQJPVLB.js +89 -0
- package/chunks/{theme-manager-JQ3ZGBP5.js → theme-manager-NSS7VLUD.js} +37 -35
- package/chunks/{todoWrite-2UO5G6G6.js → todoWrite-YKAA57W2.js} +107 -36
- package/chunks/{tool-search-FAZBFRJZ.js → tool-search-DEAS54VG.js} +13 -12
- package/chunks/{total-session-admission-5CALIVYO.js → total-session-admission-4LWTX3WD.js} +43 -41
- package/chunks/{trustedFolders-KOPSP44S.js → trustedFolders-NF3J2TA7.js} +38 -36
- package/chunks/{update-relaunch-6QL2TICS.js → update-relaunch-WUHRH5V3.js} +5 -5
- package/chunks/{updateCheck-4Q6RIKFW.js → updateCheck-7EG4BLBH.js} +41 -39
- package/chunks/{useAutoAcceptIndicator-Q5BMKZV3.js → useAutoAcceptIndicator-ZRV56GVP.js} +46 -44
- package/chunks/{validateNonInterActiveAuth-GKOC5F6Z.js → validateNonInterActiveAuth-WC2FPE3I.js} +86 -84
- package/chunks/{version-VSATY2LD.js → version-6SS7KCUP.js} +1 -1
- package/chunks/{web-fetch-JCLKL6NL.js → web-fetch-Y5QQMPKA.js} +13 -13
- package/chunks/{web-search-DSQTFUBX.js → web-search-QKKEU723.js} +8 -8
- package/chunks/{workflow-M6QAVKVJ.js → workflow-PWIU6Q2M.js} +418 -304
- package/chunks/{workspace-providers-status-YKLTLMJA.js → workspace-providers-status-B2DM6FNK.js} +45 -43
- package/chunks/{workspace-registration-store-5DMGKU64.js → workspace-registration-store-7Y33TTHJ.js} +2 -2
- package/chunks/{workspace-registry-PTYUSYXX.js → workspace-registry-TSNJKLPC.js} +43 -41
- package/chunks/{workspace-service-25ML3T47.js → workspace-service-4I2QHDX4.js} +50 -48
- package/chunks/{workspace-skills-status-YKZWOYRX.js → workspace-skills-status-HVXNWVGR.js} +44 -42
- package/chunks/{workspace-trust-reconciler-5FI2S3OS.js → workspace-trust-reconciler-RDBBGMWP.js} +49 -47
- package/chunks/{write-file-AY7VLP5X.js → write-file-RQ4DG5RY.js} +36 -34
- package/chunks/{zh-H3YDK5QW.js → zh-72XPUG5P.js} +54 -6
- package/chunks/{zh-TW-JYCP7XUA.js → zh-TW-LTB4SRH3.js} +54 -6
- package/chunks/{zoom-image-S4LJZMD5.js → zoom-image-O5YCB7WN.js} +10 -10
- package/cli.js +32 -48
- package/locales/ca.js +60 -4
- package/locales/de.js +62 -4
- package/locales/en.js +76 -6
- package/locales/fr.js +64 -4
- package/locales/ja.js +61 -4
- package/locales/pt.js +60 -4
- package/locales/ru.js +63 -4
- package/locales/zh-TW.js +67 -6
- package/locales/zh.js +67 -6
- package/package.json +3 -3
- package/web-shell/assets/{arc-xjArKHU2.js → arc-Bd7d781i.js} +1 -1
- package/web-shell/assets/{architectureDiagram-3BPJPVTR-BgrQDNYG.js → architectureDiagram-3BPJPVTR-CpnOJqNE.js} +1 -1
- package/web-shell/assets/{blockDiagram-GPEHLZMM-CXxWC-1_.js → blockDiagram-GPEHLZMM-NxVTiWnk.js} +1 -1
- package/web-shell/assets/{c4Diagram-AAUBKEIU-Dx1tLm3v.js → c4Diagram-AAUBKEIU-BWT75l82.js} +1 -1
- package/web-shell/assets/channel-A434sWK5.js +1 -0
- package/web-shell/assets/{chunk-2J33WTMH-CBxjogVR.js → chunk-2J33WTMH-Dzz03hk6.js} +1 -1
- package/web-shell/assets/{chunk-4BX2VUAB-izb-rY5W.js → chunk-4BX2VUAB-DRF-egfm.js} +1 -1
- package/web-shell/assets/{chunk-55IACEB6-NzLyvSb8.js → chunk-55IACEB6-Co15vq5x.js} +1 -1
- package/web-shell/assets/{chunk-727SXJPM-DVyKb0dl.js → chunk-727SXJPM-DHSUk1J7.js} +1 -1
- package/web-shell/assets/{chunk-AQP2D5EJ-BtqL7NzB.js → chunk-AQP2D5EJ-Br8u_E2R.js} +1 -1
- package/web-shell/assets/{chunk-FMBD7UC4-iNpdKIO0.js → chunk-FMBD7UC4-DXbPTnqF.js} +1 -1
- package/web-shell/assets/{chunk-ND2GUHAM-DI7cbFmX.js → chunk-ND2GUHAM-BleQdi4d.js} +1 -1
- package/web-shell/assets/{chunk-QZHKN3VN-3Y_-xFYs.js → chunk-QZHKN3VN-CqgBf-95.js} +1 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-CwPuhldB.js +1 -0
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-CwPuhldB.js +1 -0
- package/web-shell/assets/{cose-bilkent-S5V4N54A--raRatZn.js → cose-bilkent-S5V4N54A-WS7b13Yg.js} +1 -1
- package/web-shell/assets/{dagre-BM42HDAG-B8SU70mO.js → dagre-BM42HDAG-v_55ki8o.js} +1 -1
- package/web-shell/assets/{diagram-2AECGRRQ-ewgoakXo.js → diagram-2AECGRRQ-DaYAjbdK.js} +1 -1
- package/web-shell/assets/{diagram-5GNKFQAL-Bm_JLTnS.js → diagram-5GNKFQAL-D_Hy-L64.js} +1 -1
- package/web-shell/assets/{diagram-KO2AKTUF-DEIUjUy9.js → diagram-KO2AKTUF-dB06cZyD.js} +1 -1
- package/web-shell/assets/{diagram-LMA3HP47-C2Wmrpj-.js → diagram-LMA3HP47-DzSluD4F.js} +1 -1
- package/web-shell/assets/{diagram-OG6HWLK6-CtYe6bFx.js → diagram-OG6HWLK6-Cvb6CeXQ.js} +1 -1
- package/web-shell/assets/{erDiagram-TEJ5UH35-DfpHcWLV.js → erDiagram-TEJ5UH35-7eB2Hmov.js} +1 -1
- package/web-shell/assets/{flowDiagram-I6XJVG4X-CAiUhio5.js → flowDiagram-I6XJVG4X-B08iGCw_.js} +1 -1
- package/web-shell/assets/{ganttDiagram-6RSMTGT7-CYc7ezr4.js → ganttDiagram-6RSMTGT7-BgsrCHq-.js} +1 -1
- package/web-shell/assets/{gitGraphDiagram-PVQCEYII-70lbkcRS.js → gitGraphDiagram-PVQCEYII-DQLurQ2i.js} +1 -1
- package/web-shell/assets/{index-Ww86nT9f.js → index-B_1Z0Mgr.js} +1 -1
- package/web-shell/assets/index-Bi1dP2mU.css +5 -0
- package/web-shell/assets/index-DJ-z1Oba.js +1756 -0
- package/web-shell/assets/{infoDiagram-5YYISTIA-C7e8DWPa.js → infoDiagram-5YYISTIA-DXZGO8qB.js} +1 -1
- package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-BYLr2op-.js → ishikawaDiagram-YF4QCWOH-g7gbuH2w.js} +1 -1
- package/web-shell/assets/{journeyDiagram-JHISSGLW-hEibAHKX.js → journeyDiagram-JHISSGLW-euefICGn.js} +1 -1
- package/web-shell/assets/{kanban-definition-UN3LZRKU-F2rt8Uhp.js → kanban-definition-UN3LZRKU-Dws8-mjG.js} +1 -1
- package/web-shell/assets/{linear-DPhyNezd.js → linear-C63F0tyh.js} +1 -1
- package/web-shell/assets/{mermaid.core-ZUtnug0n.js → mermaid.core-fLrhp_4-.js} +5 -5
- package/web-shell/assets/{mindmap-definition-RKZ34NQL-DDWcMoi8.js → mindmap-definition-RKZ34NQL-qRkydfT-.js} +1 -1
- package/web-shell/assets/{pieDiagram-4H26LBE5-CTRKzw1_.js → pieDiagram-4H26LBE5-BZ0wQaKN.js} +1 -1
- package/web-shell/assets/{quadrantDiagram-W4KKPZXB-CAEwYG_z.js → quadrantDiagram-W4KKPZXB-Fjq6GbSZ.js} +1 -1
- package/web-shell/assets/{requirementDiagram-4Y6WPE33-CRjnH9D9.js → requirementDiagram-4Y6WPE33-CqWvjLHU.js} +1 -1
- package/web-shell/assets/{sankeyDiagram-5OEKKPKP-LPQT_sOd.js → sankeyDiagram-5OEKKPKP-VcXX6PVZ.js} +1 -1
- package/web-shell/assets/{sequenceDiagram-3UESZ5HK-Ht2Iqvb0.js → sequenceDiagram-3UESZ5HK-BJSRtxFr.js} +1 -1
- package/web-shell/assets/{stateDiagram-AJRCARHV-CIUdqOXu.js → stateDiagram-AJRCARHV-Dt9zUwmZ.js} +1 -1
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-CCxQt56w.js +1 -0
- package/web-shell/assets/{timeline-definition-PNZ67QCA-BcilneZF.js → timeline-definition-PNZ67QCA-DQwlNRws.js} +1 -1
- package/web-shell/assets/{vennDiagram-CIIHVFJN-BljwiiH1.js → vennDiagram-CIIHVFJN-DwxjUEtQ.js} +1 -1
- package/web-shell/assets/{wardley-L42UT6IY-DeKjkYjq.js → wardley-L42UT6IY-D3QdMSpJ.js} +1 -1
- package/web-shell/assets/{wardleyDiagram-YWT4CUSO-L3U1H7KG.js → wardleyDiagram-YWT4CUSO-BddN8oK8.js} +1 -1
- package/web-shell/assets/{xychartDiagram-2RQKCTM6-IJnWsgMT.js → xychartDiagram-2RQKCTM6-BUNuBrRJ.js} +1 -1
- package/web-shell/index.html +2 -2
- package/chunks/chunk-4KP2F2TE.js +0 -82
- package/chunks/chunk-HGT6JR3U.js +0 -177
- package/chunks/nonInteractiveCli-ZJYEOO7U.js +0 -148
- package/web-shell/assets/channel-B1cyk94G.js +0 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-BpBYZoRE.js +0 -1
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-BpBYZoRE.js +0 -1
- package/web-shell/assets/index-C1k3PDuU.css +0 -5
- package/web-shell/assets/index-DZLIXILO.js +0 -1750
- package/web-shell/assets/insert-DmRbh9Rv.svg +0 -1
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-BmqqQZ6w.js +0 -1
|
@@ -0,0 +1,1170 @@
|
|
|
1
|
+
// Force strict mode and setup for ESM
|
|
2
|
+
"use strict";
|
|
3
|
+
import {
|
|
4
|
+
MAX_TERMINAL_IMAGE_BYTES
|
|
5
|
+
} from "./chunk-CFDR3GNL.js";
|
|
6
|
+
import {
|
|
7
|
+
init_esbuild_shims
|
|
8
|
+
} from "./chunk-5O2XNYP6.js";
|
|
9
|
+
import {
|
|
10
|
+
__name
|
|
11
|
+
} from "./chunk-J2S4EL5Y.js";
|
|
12
|
+
|
|
13
|
+
// packages/cli/src/ui/utils/terminal-image-renderer.ts
|
|
14
|
+
init_esbuild_shims();
|
|
15
|
+
import crypto2 from "node:crypto";
|
|
16
|
+
import fs2 from "node:fs";
|
|
17
|
+
import { execFileSync } from "node:child_process";
|
|
18
|
+
|
|
19
|
+
// packages/cli/src/ui/utils/mermaidImageRenderer.ts
|
|
20
|
+
init_esbuild_shims();
|
|
21
|
+
import crypto from "node:crypto";
|
|
22
|
+
import fs from "node:fs";
|
|
23
|
+
import os from "node:os";
|
|
24
|
+
import path from "node:path";
|
|
25
|
+
import { spawn, spawnSync } from "node:child_process";
|
|
26
|
+
var CACHE_LIMIT = 40;
|
|
27
|
+
var PNG_CACHE_LIMIT = 20;
|
|
28
|
+
var CACHE_BYTE_LIMIT = 32 * 1024 * 1024;
|
|
29
|
+
var PNG_CACHE_BYTE_LIMIT = 32 * 1024 * 1024;
|
|
30
|
+
var DEFAULT_RENDER_TIMEOUT_MS = 8e3;
|
|
31
|
+
var DEFAULT_MERMAID_RENDER_WIDTH = 1280;
|
|
32
|
+
var MAX_MERMAID_PNG_BYTES = 8 * 1024 * 1024;
|
|
33
|
+
var MAX_RENDERER_OUTPUT_CHARS = 16 * 1024;
|
|
34
|
+
var MAX_RENDER_TIMEOUT_MS = 6e4;
|
|
35
|
+
var OUTPUT_TRUNCATION_MARKER = "\n... renderer output truncated ...";
|
|
36
|
+
var NPX_MERMAID_CLI = "npx:@mermaid-js/mermaid-cli@11.12.0";
|
|
37
|
+
var PNG_SIGNATURE = "89504e470d0a1a0a";
|
|
38
|
+
var KITTY_PLACEHOLDER = "\u{10EEEE}";
|
|
39
|
+
var RENDERER_ENV_ALLOWLIST = [
|
|
40
|
+
"PATH",
|
|
41
|
+
"PATHEXT",
|
|
42
|
+
"HOME",
|
|
43
|
+
"USERPROFILE",
|
|
44
|
+
"TMPDIR",
|
|
45
|
+
"TMP",
|
|
46
|
+
"TEMP",
|
|
47
|
+
"SystemRoot",
|
|
48
|
+
"WINDIR",
|
|
49
|
+
"COMSPEC",
|
|
50
|
+
"LOCALAPPDATA",
|
|
51
|
+
"APPDATA",
|
|
52
|
+
"CHROME_PATH",
|
|
53
|
+
"PUPPETEER_EXECUTABLE_PATH",
|
|
54
|
+
"PUPPETEER_CACHE_DIR",
|
|
55
|
+
"PLAYWRIGHT_BROWSERS_PATH"
|
|
56
|
+
];
|
|
57
|
+
var KITTY_PLACEHOLDER_DIACRITICS = [
|
|
58
|
+
"\u0305",
|
|
59
|
+
"\u030D",
|
|
60
|
+
"\u030E",
|
|
61
|
+
"\u0310",
|
|
62
|
+
"\u0312",
|
|
63
|
+
"\u033D",
|
|
64
|
+
"\u033E",
|
|
65
|
+
"\u033F",
|
|
66
|
+
"\u0346",
|
|
67
|
+
"\u034A",
|
|
68
|
+
"\u034B",
|
|
69
|
+
"\u034C",
|
|
70
|
+
"\u0350",
|
|
71
|
+
"\u0351",
|
|
72
|
+
"\u0352",
|
|
73
|
+
"\u0357",
|
|
74
|
+
"\u035B",
|
|
75
|
+
"\u0363",
|
|
76
|
+
"\u0364",
|
|
77
|
+
"\u0365",
|
|
78
|
+
"\u0366",
|
|
79
|
+
"\u0367",
|
|
80
|
+
"\u0368",
|
|
81
|
+
"\u0369",
|
|
82
|
+
"\u036A",
|
|
83
|
+
"\u036B",
|
|
84
|
+
"\u036C",
|
|
85
|
+
"\u036D",
|
|
86
|
+
"\u036E",
|
|
87
|
+
"\u036F",
|
|
88
|
+
"\u0483",
|
|
89
|
+
"\u0484",
|
|
90
|
+
"\u0485",
|
|
91
|
+
"\u0486",
|
|
92
|
+
"\u0487",
|
|
93
|
+
"\u0592",
|
|
94
|
+
"\u0593",
|
|
95
|
+
"\u0594",
|
|
96
|
+
"\u0595",
|
|
97
|
+
"\u0597",
|
|
98
|
+
"\u0598",
|
|
99
|
+
"\u0599",
|
|
100
|
+
"\u059C",
|
|
101
|
+
"\u059D",
|
|
102
|
+
"\u059E",
|
|
103
|
+
"\u059F",
|
|
104
|
+
"\u05A0",
|
|
105
|
+
"\u05A1",
|
|
106
|
+
"\u05A8",
|
|
107
|
+
"\u05A9",
|
|
108
|
+
"\u05AB",
|
|
109
|
+
"\u05AC",
|
|
110
|
+
"\u05AF",
|
|
111
|
+
"\u05C4",
|
|
112
|
+
"\u0610",
|
|
113
|
+
"\u0611",
|
|
114
|
+
"\u0612",
|
|
115
|
+
"\u0613",
|
|
116
|
+
"\u0614",
|
|
117
|
+
"\u0615",
|
|
118
|
+
"\u0616",
|
|
119
|
+
"\u0617",
|
|
120
|
+
"\u0657",
|
|
121
|
+
"\u0658",
|
|
122
|
+
"\u0659",
|
|
123
|
+
"\u065A",
|
|
124
|
+
"\u065B",
|
|
125
|
+
"\u065D",
|
|
126
|
+
"\u065E",
|
|
127
|
+
"\u06D6",
|
|
128
|
+
"\u06D7",
|
|
129
|
+
"\u06D8",
|
|
130
|
+
"\u06D9",
|
|
131
|
+
"\u06DA",
|
|
132
|
+
"\u06DB",
|
|
133
|
+
"\u06DC",
|
|
134
|
+
"\u06DF",
|
|
135
|
+
"\u06E0",
|
|
136
|
+
"\u06E1",
|
|
137
|
+
"\u06E2",
|
|
138
|
+
"\u06E4",
|
|
139
|
+
"\u06E7",
|
|
140
|
+
"\u06E8",
|
|
141
|
+
"\u06EB",
|
|
142
|
+
"\u06EC",
|
|
143
|
+
"\u0730",
|
|
144
|
+
"\u0732",
|
|
145
|
+
"\u0733",
|
|
146
|
+
"\u0735",
|
|
147
|
+
"\u0736",
|
|
148
|
+
"\u073A",
|
|
149
|
+
"\u073D",
|
|
150
|
+
"\u073F",
|
|
151
|
+
"\u0740",
|
|
152
|
+
"\u0741",
|
|
153
|
+
"\u0743",
|
|
154
|
+
"\u0745",
|
|
155
|
+
"\u0747",
|
|
156
|
+
"\u0749",
|
|
157
|
+
"\u074A",
|
|
158
|
+
"\u07EB",
|
|
159
|
+
"\u07EC",
|
|
160
|
+
"\u07ED",
|
|
161
|
+
"\u07EE",
|
|
162
|
+
"\u07EF",
|
|
163
|
+
"\u07F0",
|
|
164
|
+
"\u07F1",
|
|
165
|
+
"\u07F3",
|
|
166
|
+
"\u0816",
|
|
167
|
+
"\u0817",
|
|
168
|
+
"\u0818",
|
|
169
|
+
"\u0819",
|
|
170
|
+
"\u081B",
|
|
171
|
+
"\u081C",
|
|
172
|
+
"\u081D",
|
|
173
|
+
"\u081E",
|
|
174
|
+
"\u081F",
|
|
175
|
+
"\u0820",
|
|
176
|
+
"\u0821",
|
|
177
|
+
"\u0822",
|
|
178
|
+
"\u0823",
|
|
179
|
+
"\u0825",
|
|
180
|
+
"\u0826",
|
|
181
|
+
"\u0827",
|
|
182
|
+
"\u0829",
|
|
183
|
+
"\u082A",
|
|
184
|
+
"\u082B",
|
|
185
|
+
"\u082C"
|
|
186
|
+
];
|
|
187
|
+
var cachedResults = /* @__PURE__ */ new Map();
|
|
188
|
+
var cachedPngResults = /* @__PURE__ */ new Map();
|
|
189
|
+
var cachedResultsBytes = 0;
|
|
190
|
+
var cachedPngResultsBytes = 0;
|
|
191
|
+
function detectTerminalImageProtocol(env = process.env) {
|
|
192
|
+
if (env["QWEN_CODE_DISABLE_MERMAID_IMAGES"] === "1") {
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
195
|
+
const forced = env["QWEN_CODE_MERMAID_IMAGE_PROTOCOL"]?.toLowerCase();
|
|
196
|
+
if (forced === "off" || forced === "none" || forced === "0") {
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
if (!process.stdout.isTTY || env["TMUX"] || env["SSH_TTY"] || env["SSH_CLIENT"]) {
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
202
|
+
if (forced) {
|
|
203
|
+
if (forced === "kitty") return "kitty";
|
|
204
|
+
if (forced === "iterm" || forced === "iterm2") return "iterm2";
|
|
205
|
+
}
|
|
206
|
+
const term = env["TERM"]?.toLowerCase() ?? "";
|
|
207
|
+
const termProgram = env["TERM_PROGRAM"]?.toLowerCase() ?? "";
|
|
208
|
+
if (env["KITTY_WINDOW_ID"] || term.includes("kitty") || termProgram.includes("ghostty")) {
|
|
209
|
+
return "kitty";
|
|
210
|
+
}
|
|
211
|
+
if (termProgram === "iterm.app" || termProgram.includes("wezterm")) {
|
|
212
|
+
return "iterm2";
|
|
213
|
+
}
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
216
|
+
__name(detectTerminalImageProtocol, "detectTerminalImageProtocol");
|
|
217
|
+
function encodeITerm2InlineImage(png, widthCells, rows) {
|
|
218
|
+
return `\x1B]1337;File=inline=1;width=${widthCells};height=${rows};preserveAspectRatio=1:${png.toString(
|
|
219
|
+
"base64"
|
|
220
|
+
)}\x07`;
|
|
221
|
+
}
|
|
222
|
+
__name(encodeITerm2InlineImage, "encodeITerm2InlineImage");
|
|
223
|
+
function encodeKittyVirtualImage(png, imageId, widthCells, rows) {
|
|
224
|
+
return encodeKittyImageCommand(
|
|
225
|
+
png,
|
|
226
|
+
`a=T,f=100,i=${imageId},q=2,U=1,c=${widthCells},r=${rows}`
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
__name(encodeKittyVirtualImage, "encodeKittyVirtualImage");
|
|
230
|
+
function encodeKittyImageCommand(png, firstControl) {
|
|
231
|
+
const encoded = png.toString("base64");
|
|
232
|
+
const chunkSize = 4096;
|
|
233
|
+
const chunks = [];
|
|
234
|
+
for (let offset = 0; offset < encoded.length; offset += chunkSize) {
|
|
235
|
+
const chunk = encoded.slice(offset, offset + chunkSize);
|
|
236
|
+
const hasMore = offset + chunkSize < encoded.length;
|
|
237
|
+
const control = offset === 0 ? `${firstControl},m=${hasMore ? 1 : 0}` : `m=${hasMore ? 1 : 0}`;
|
|
238
|
+
chunks.push(`\x1B_G${control};${chunk}\x1B\\`);
|
|
239
|
+
}
|
|
240
|
+
return chunks.join("");
|
|
241
|
+
}
|
|
242
|
+
__name(encodeKittyImageCommand, "encodeKittyImageCommand");
|
|
243
|
+
function buildKittyPlaceholder(imageId, widthCells, rows) {
|
|
244
|
+
const clampedRows = Math.min(rows, KITTY_PLACEHOLDER_DIACRITICS.length);
|
|
245
|
+
const clampedWidth = Math.min(
|
|
246
|
+
widthCells,
|
|
247
|
+
KITTY_PLACEHOLDER_DIACRITICS.length
|
|
248
|
+
);
|
|
249
|
+
const lines = Array.from({ length: clampedRows }, (_, row) => {
|
|
250
|
+
const rowDiacritic = KITTY_PLACEHOLDER_DIACRITICS[row];
|
|
251
|
+
const cells = Array.from({ length: clampedWidth }, (_2, column) => {
|
|
252
|
+
const columnDiacritic = KITTY_PLACEHOLDER_DIACRITICS[column];
|
|
253
|
+
return `${KITTY_PLACEHOLDER}${rowDiacritic}${columnDiacritic}`;
|
|
254
|
+
});
|
|
255
|
+
return cells.join("");
|
|
256
|
+
});
|
|
257
|
+
return {
|
|
258
|
+
color: `#${imageId.toString(16).padStart(6, "0")}`,
|
|
259
|
+
imageId,
|
|
260
|
+
lines
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
__name(buildKittyPlaceholder, "buildKittyPlaceholder");
|
|
264
|
+
function readPngSize(png) {
|
|
265
|
+
if (png.length < 24 || png.subarray(0, 8).toString("hex") !== PNG_SIGNATURE) {
|
|
266
|
+
return null;
|
|
267
|
+
}
|
|
268
|
+
return {
|
|
269
|
+
width: png.readUInt32BE(16),
|
|
270
|
+
height: png.readUInt32BE(20)
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
__name(readPngSize, "readPngSize");
|
|
274
|
+
function isMermaidImageRenderingDisabled(env) {
|
|
275
|
+
return env["QWEN_CODE_DISABLE_MERMAID_IMAGES"] === "1";
|
|
276
|
+
}
|
|
277
|
+
__name(isMermaidImageRenderingDisabled, "isMermaidImageRenderingDisabled");
|
|
278
|
+
function unavailableImageRenderingDisabled() {
|
|
279
|
+
return {
|
|
280
|
+
kind: "unavailable",
|
|
281
|
+
reason: "Mermaid image rendering is disabled via QWEN_CODE_DISABLE_MERMAID_IMAGES."
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
__name(unavailableImageRenderingDisabled, "unavailableImageRenderingDisabled");
|
|
285
|
+
async function renderMermaidImageAsync({
|
|
286
|
+
source,
|
|
287
|
+
contentWidth,
|
|
288
|
+
availableTerminalHeight,
|
|
289
|
+
env = process.env,
|
|
290
|
+
signal
|
|
291
|
+
}) {
|
|
292
|
+
if (isMermaidImageRenderingDisabled(env)) {
|
|
293
|
+
return unavailableImageRenderingDisabled();
|
|
294
|
+
}
|
|
295
|
+
const imageRendering = env["QWEN_CODE_MERMAID_IMAGE_RENDERING"];
|
|
296
|
+
if (imageRendering !== "1" && imageRendering?.toLowerCase() !== "on" && imageRendering?.toLowerCase() !== "true") {
|
|
297
|
+
return {
|
|
298
|
+
kind: "unavailable",
|
|
299
|
+
reason: "Mermaid image rendering is disabled by default. Set QWEN_CODE_MERMAID_IMAGE_RENDERING=1 to enable external renderers.",
|
|
300
|
+
showReason: false
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
const protocol = detectTerminalImageProtocol(env);
|
|
304
|
+
if (protocol === "iterm2") {
|
|
305
|
+
return {
|
|
306
|
+
kind: "unavailable",
|
|
307
|
+
reason: "iTerm2 inline image rendering is disabled in the async TUI path to avoid cursor-position races.",
|
|
308
|
+
showReason: false
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
const chafa = protocol ? null : findExecutable("chafa", env);
|
|
312
|
+
if (!protocol && !chafa) {
|
|
313
|
+
return {
|
|
314
|
+
kind: "unavailable",
|
|
315
|
+
reason: "No supported terminal image protocol or chafa renderer was detected."
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
const mmdc = findMmdc(env);
|
|
319
|
+
if (!mmdc) {
|
|
320
|
+
return {
|
|
321
|
+
kind: "unavailable",
|
|
322
|
+
reason: "Mermaid CLI (mmdc) was not found. Install @mermaid-js/mermaid-cli, set QWEN_CODE_MERMAID_MMD_CLI, or set QWEN_CODE_MERMAID_ALLOW_NPX=1."
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
const cacheKey = createCacheKey(
|
|
326
|
+
source,
|
|
327
|
+
contentWidth,
|
|
328
|
+
availableTerminalHeight,
|
|
329
|
+
protocol ?? `chafa:${chafa}`,
|
|
330
|
+
mmdc,
|
|
331
|
+
env
|
|
332
|
+
);
|
|
333
|
+
const cached = getResultCache(cacheKey);
|
|
334
|
+
if (cached) return cached;
|
|
335
|
+
const pngCacheKey = createPngCacheKey(source, mmdc, env);
|
|
336
|
+
const cachedPng = getPngCache(pngCacheKey);
|
|
337
|
+
let rendered = cachedPng;
|
|
338
|
+
if (!rendered) {
|
|
339
|
+
const nextRendered = await renderPngWithMmdcAsync(
|
|
340
|
+
source,
|
|
341
|
+
mmdc,
|
|
342
|
+
env,
|
|
343
|
+
signal
|
|
344
|
+
);
|
|
345
|
+
rendered = signal?.aborted ? nextRendered : rememberPng(pngCacheKey, nextRendered);
|
|
346
|
+
}
|
|
347
|
+
if (!rendered.ok) {
|
|
348
|
+
if (signal?.aborted) {
|
|
349
|
+
return {
|
|
350
|
+
kind: "unavailable",
|
|
351
|
+
reason: rendered.error
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
return remember(cacheKey, {
|
|
355
|
+
kind: "unavailable",
|
|
356
|
+
reason: rendered.error
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
const pngSize = readPngSize(rendered.png);
|
|
360
|
+
if (!pngSize) {
|
|
361
|
+
return remember(cacheKey, {
|
|
362
|
+
kind: "unavailable",
|
|
363
|
+
reason: "Mermaid CLI did not produce a valid PNG."
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
const imageShape = fitImageToTerminal(
|
|
367
|
+
pngSize,
|
|
368
|
+
contentWidth,
|
|
369
|
+
availableTerminalHeight,
|
|
370
|
+
env
|
|
371
|
+
);
|
|
372
|
+
if (protocol) {
|
|
373
|
+
const imageId = protocol === "kitty" ? createKittyImageId(rendered.png, imageShape) : void 0;
|
|
374
|
+
const sequence = protocol === "kitty" ? encodeKittyVirtualImage(
|
|
375
|
+
rendered.png,
|
|
376
|
+
imageId,
|
|
377
|
+
imageShape.widthCells,
|
|
378
|
+
imageShape.rows
|
|
379
|
+
) : encodeITerm2InlineImage(
|
|
380
|
+
rendered.png,
|
|
381
|
+
imageShape.widthCells,
|
|
382
|
+
imageShape.rows
|
|
383
|
+
);
|
|
384
|
+
return remember(cacheKey, {
|
|
385
|
+
kind: "terminal-image",
|
|
386
|
+
title: `Mermaid diagram image (${protocol})`,
|
|
387
|
+
sequence,
|
|
388
|
+
rows: imageShape.rows,
|
|
389
|
+
protocol,
|
|
390
|
+
placeholder: protocol === "kitty" ? buildKittyPlaceholder(
|
|
391
|
+
imageId,
|
|
392
|
+
imageShape.widthCells,
|
|
393
|
+
imageShape.rows
|
|
394
|
+
) : void 0
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
const ansi = await renderPngWithChafaAsync(
|
|
398
|
+
rendered.png,
|
|
399
|
+
imageShape.widthCells,
|
|
400
|
+
imageShape.rows,
|
|
401
|
+
chafa,
|
|
402
|
+
env,
|
|
403
|
+
signal
|
|
404
|
+
);
|
|
405
|
+
if (!ansi.ok) {
|
|
406
|
+
if (signal?.aborted) {
|
|
407
|
+
return {
|
|
408
|
+
kind: "unavailable",
|
|
409
|
+
reason: ansi.error
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
return remember(cacheKey, {
|
|
413
|
+
kind: "unavailable",
|
|
414
|
+
reason: ansi.error
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
return remember(cacheKey, {
|
|
418
|
+
kind: "ansi",
|
|
419
|
+
title: "Mermaid diagram image (ANSI)",
|
|
420
|
+
lines: ansi.output.split(/\r?\n/).filter((line) => line.length > 0)
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
__name(renderMermaidImageAsync, "renderMermaidImageAsync");
|
|
424
|
+
function createKittyImageId(png, imageShape) {
|
|
425
|
+
const hash = crypto.createHash("sha256").update(png).update("\0").update(String(imageShape.widthCells)).update("\0").update(String(imageShape.rows)).digest();
|
|
426
|
+
const id = hash.readUIntBE(0, 3);
|
|
427
|
+
return id === 0 ? 1 : id;
|
|
428
|
+
}
|
|
429
|
+
__name(createKittyImageId, "createKittyImageId");
|
|
430
|
+
function getResultCache(key) {
|
|
431
|
+
const cached = cachedResults.get(key);
|
|
432
|
+
if (cached) {
|
|
433
|
+
cachedResults.delete(key);
|
|
434
|
+
cachedResults.set(key, cached);
|
|
435
|
+
}
|
|
436
|
+
return cached;
|
|
437
|
+
}
|
|
438
|
+
__name(getResultCache, "getResultCache");
|
|
439
|
+
function getPngCache(key) {
|
|
440
|
+
const cached = cachedPngResults.get(key);
|
|
441
|
+
if (cached) {
|
|
442
|
+
cachedPngResults.delete(key);
|
|
443
|
+
cachedPngResults.set(key, cached);
|
|
444
|
+
}
|
|
445
|
+
return cached;
|
|
446
|
+
}
|
|
447
|
+
__name(getPngCache, "getPngCache");
|
|
448
|
+
function createPngCacheKey(source, mmdc, env) {
|
|
449
|
+
return crypto.createHash("sha256").update(source).update("\0").update(mmdc).update("\0").update(String(getMermaidRenderWidth(env))).digest("hex");
|
|
450
|
+
}
|
|
451
|
+
__name(createPngCacheKey, "createPngCacheKey");
|
|
452
|
+
function createCacheKey(source, contentWidth, availableTerminalHeight, renderer, mmdc, env) {
|
|
453
|
+
return crypto.createHash("sha256").update(source).update("\0").update(String(contentWidth)).update("\0").update(String(availableTerminalHeight ?? "auto")).update("\0").update(renderer).update("\0").update(mmdc).update("\0").update(String(getMermaidCellAspectRatio(env))).digest("hex");
|
|
454
|
+
}
|
|
455
|
+
__name(createCacheKey, "createCacheKey");
|
|
456
|
+
function remember(key, result) {
|
|
457
|
+
const resultBytes = estimateResultBytes(result);
|
|
458
|
+
if (resultBytes > CACHE_BYTE_LIMIT) {
|
|
459
|
+
cachedResults.delete(key);
|
|
460
|
+
return result;
|
|
461
|
+
}
|
|
462
|
+
const existing = cachedResults.get(key);
|
|
463
|
+
if (existing) {
|
|
464
|
+
cachedResultsBytes -= estimateResultBytes(existing);
|
|
465
|
+
}
|
|
466
|
+
cachedResults.set(key, result);
|
|
467
|
+
cachedResultsBytes += resultBytes;
|
|
468
|
+
while (cachedResults.size > CACHE_LIMIT || cachedResultsBytes > CACHE_BYTE_LIMIT) {
|
|
469
|
+
const oldest = cachedResults.keys().next().value;
|
|
470
|
+
if (!oldest) break;
|
|
471
|
+
const oldestResult = cachedResults.get(oldest);
|
|
472
|
+
if (oldestResult) {
|
|
473
|
+
cachedResultsBytes -= estimateResultBytes(oldestResult);
|
|
474
|
+
}
|
|
475
|
+
cachedResults.delete(oldest);
|
|
476
|
+
}
|
|
477
|
+
return result;
|
|
478
|
+
}
|
|
479
|
+
__name(remember, "remember");
|
|
480
|
+
function rememberPng(key, result) {
|
|
481
|
+
const resultBytes = estimatePngResultBytes(result);
|
|
482
|
+
if (resultBytes > PNG_CACHE_BYTE_LIMIT) {
|
|
483
|
+
cachedPngResults.delete(key);
|
|
484
|
+
return result;
|
|
485
|
+
}
|
|
486
|
+
const existing = cachedPngResults.get(key);
|
|
487
|
+
if (existing) {
|
|
488
|
+
cachedPngResultsBytes -= estimatePngResultBytes(existing);
|
|
489
|
+
}
|
|
490
|
+
cachedPngResults.set(key, result);
|
|
491
|
+
cachedPngResultsBytes += resultBytes;
|
|
492
|
+
while (cachedPngResults.size > PNG_CACHE_LIMIT || cachedPngResultsBytes > PNG_CACHE_BYTE_LIMIT) {
|
|
493
|
+
const oldest = cachedPngResults.keys().next().value;
|
|
494
|
+
if (!oldest) break;
|
|
495
|
+
const oldestResult = cachedPngResults.get(oldest);
|
|
496
|
+
if (oldestResult) {
|
|
497
|
+
cachedPngResultsBytes -= estimatePngResultBytes(oldestResult);
|
|
498
|
+
}
|
|
499
|
+
cachedPngResults.delete(oldest);
|
|
500
|
+
}
|
|
501
|
+
return result;
|
|
502
|
+
}
|
|
503
|
+
__name(rememberPng, "rememberPng");
|
|
504
|
+
function estimateResultBytes(result) {
|
|
505
|
+
switch (result.kind) {
|
|
506
|
+
case "terminal-image":
|
|
507
|
+
return Buffer.byteLength(result.sequence, "utf8") + (result.placeholder?.lines.reduce(
|
|
508
|
+
(total, line) => total + Buffer.byteLength(line, "utf8"),
|
|
509
|
+
0
|
|
510
|
+
) ?? 0);
|
|
511
|
+
case "ansi":
|
|
512
|
+
return result.lines.reduce(
|
|
513
|
+
(total, line) => total + Buffer.byteLength(line, "utf8"),
|
|
514
|
+
0
|
|
515
|
+
);
|
|
516
|
+
case "unavailable":
|
|
517
|
+
return Buffer.byteLength(result.reason, "utf8");
|
|
518
|
+
default: {
|
|
519
|
+
const exhaustive = result;
|
|
520
|
+
return exhaustive;
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
__name(estimateResultBytes, "estimateResultBytes");
|
|
525
|
+
function estimatePngResultBytes(result) {
|
|
526
|
+
return result.ok ? result.png.byteLength : Buffer.byteLength(result.error);
|
|
527
|
+
}
|
|
528
|
+
__name(estimatePngResultBytes, "estimatePngResultBytes");
|
|
529
|
+
function findMmdc(env) {
|
|
530
|
+
const explicit = env["QWEN_CODE_MERMAID_MMD_CLI"];
|
|
531
|
+
if (explicit && isExecutable(explicit)) return explicit;
|
|
532
|
+
const mmdc = findExecutable("mmdc", env);
|
|
533
|
+
if (mmdc) return mmdc;
|
|
534
|
+
if (env["QWEN_CODE_MERMAID_ALLOW_NPX"] === "1" && findExecutable("npx", env)) {
|
|
535
|
+
return NPX_MERMAID_CLI;
|
|
536
|
+
}
|
|
537
|
+
return null;
|
|
538
|
+
}
|
|
539
|
+
__name(findMmdc, "findMmdc");
|
|
540
|
+
function findExecutable(command, env) {
|
|
541
|
+
const candidates = [];
|
|
542
|
+
const extensions = process.platform === "win32" ? (env["PATHEXT"] ?? ".EXE;.CMD;.BAT;.COM").split(";").filter(Boolean) : [""];
|
|
543
|
+
const addCandidates = /* @__PURE__ */ __name((dir) => {
|
|
544
|
+
for (const extension of extensions) {
|
|
545
|
+
candidates.push(path.join(dir, `${command}${extension}`));
|
|
546
|
+
}
|
|
547
|
+
}, "addCandidates");
|
|
548
|
+
const allowLocalRenderers = env["QWEN_CODE_MERMAID_ALLOW_LOCAL_RENDERERS"] === "1";
|
|
549
|
+
const localRendererDir = normalizeExecutableDir(
|
|
550
|
+
process.cwd(),
|
|
551
|
+
"node_modules",
|
|
552
|
+
".bin"
|
|
553
|
+
);
|
|
554
|
+
if (allowLocalRenderers) {
|
|
555
|
+
addCandidates(localRendererDir);
|
|
556
|
+
}
|
|
557
|
+
for (const dir of (env["PATH"] ?? "").split(path.delimiter).filter(Boolean)) {
|
|
558
|
+
const normalizedDir = normalizeExecutableDir(dir);
|
|
559
|
+
if (!allowLocalRenderers && (normalizedDir === localRendererDir || normalizedDir.endsWith(`${path.sep}node_modules${path.sep}.bin`))) {
|
|
560
|
+
continue;
|
|
561
|
+
}
|
|
562
|
+
addCandidates(dir);
|
|
563
|
+
}
|
|
564
|
+
return candidates.find(isExecutable) ?? null;
|
|
565
|
+
}
|
|
566
|
+
__name(findExecutable, "findExecutable");
|
|
567
|
+
function normalizeExecutableDir(...segments) {
|
|
568
|
+
const dir = path.resolve(...segments);
|
|
569
|
+
try {
|
|
570
|
+
return fs.realpathSync.native(dir);
|
|
571
|
+
} catch {
|
|
572
|
+
return dir;
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
__name(normalizeExecutableDir, "normalizeExecutableDir");
|
|
576
|
+
function isExecutable(filePath) {
|
|
577
|
+
try {
|
|
578
|
+
fs.accessSync(filePath, fs.constants.X_OK);
|
|
579
|
+
return true;
|
|
580
|
+
} catch {
|
|
581
|
+
return false;
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
__name(isExecutable, "isExecutable");
|
|
585
|
+
async function renderPngWithMmdcAsync(source, mmdc, env, signal) {
|
|
586
|
+
const tempDir = await fs.promises.mkdtemp(
|
|
587
|
+
path.join(os.tmpdir(), "qwen-mermaid-")
|
|
588
|
+
);
|
|
589
|
+
const inputPath = path.join(tempDir, "diagram.mmd");
|
|
590
|
+
const outputPath = path.join(tempDir, "diagram.png");
|
|
591
|
+
const renderWidth = getMermaidRenderWidth(env);
|
|
592
|
+
try {
|
|
593
|
+
await fs.promises.writeFile(inputPath, source, "utf8");
|
|
594
|
+
const mmdcArgs = [
|
|
595
|
+
"-i",
|
|
596
|
+
inputPath,
|
|
597
|
+
"-o",
|
|
598
|
+
outputPath,
|
|
599
|
+
"-b",
|
|
600
|
+
"transparent",
|
|
601
|
+
"-w",
|
|
602
|
+
String(renderWidth)
|
|
603
|
+
];
|
|
604
|
+
const command = mmdc === NPX_MERMAID_CLI ? findExecutable("npx", env) : mmdc;
|
|
605
|
+
const args = mmdc === NPX_MERMAID_CLI ? ["-y", "@mermaid-js/mermaid-cli@11.12.0", ...mmdcArgs] : mmdcArgs;
|
|
606
|
+
const result = await runCommand(command, args, {
|
|
607
|
+
env: createRendererChildEnv(env),
|
|
608
|
+
shell: shouldRunThroughShell(command),
|
|
609
|
+
timeout: getMermaidRenderTimeout(env),
|
|
610
|
+
signal
|
|
611
|
+
});
|
|
612
|
+
if (result.error) {
|
|
613
|
+
return { ok: false, error: result.error };
|
|
614
|
+
}
|
|
615
|
+
if (result.status !== 0) {
|
|
616
|
+
const stderr = result.stderr.trim();
|
|
617
|
+
return {
|
|
618
|
+
ok: false,
|
|
619
|
+
error: stderr || `Mermaid CLI exited with status ${result.status}.`
|
|
620
|
+
};
|
|
621
|
+
}
|
|
622
|
+
let outputSize;
|
|
623
|
+
try {
|
|
624
|
+
outputSize = (await fs.promises.stat(outputPath)).size;
|
|
625
|
+
} catch {
|
|
626
|
+
return { ok: false, error: "Mermaid CLI did not write an output file." };
|
|
627
|
+
}
|
|
628
|
+
if (outputSize > MAX_MERMAID_PNG_BYTES) {
|
|
629
|
+
return {
|
|
630
|
+
ok: false,
|
|
631
|
+
error: `Mermaid CLI output exceeded ${MAX_MERMAID_PNG_BYTES} bytes.`
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
return { ok: true, png: await fs.promises.readFile(outputPath) };
|
|
635
|
+
} finally {
|
|
636
|
+
await fs.promises.rm(tempDir, { recursive: true, force: true });
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
__name(renderPngWithMmdcAsync, "renderPngWithMmdcAsync");
|
|
640
|
+
function shouldRunThroughShell(command) {
|
|
641
|
+
return process.platform === "win32" && /\.(?:cmd|bat)$/i.test(command);
|
|
642
|
+
}
|
|
643
|
+
__name(shouldRunThroughShell, "shouldRunThroughShell");
|
|
644
|
+
function getMermaidRenderWidth(env) {
|
|
645
|
+
const configuredWidth = Number(env["QWEN_CODE_MERMAID_RENDER_WIDTH"]);
|
|
646
|
+
if (Number.isFinite(configuredWidth) && configuredWidth > 0) {
|
|
647
|
+
return Math.max(320, Math.min(1800, Math.round(configuredWidth)));
|
|
648
|
+
}
|
|
649
|
+
return DEFAULT_MERMAID_RENDER_WIDTH;
|
|
650
|
+
}
|
|
651
|
+
__name(getMermaidRenderWidth, "getMermaidRenderWidth");
|
|
652
|
+
function getMermaidRenderTimeout(env) {
|
|
653
|
+
const configuredTimeout = Number(env["QWEN_CODE_MERMAID_RENDER_TIMEOUT_MS"]);
|
|
654
|
+
if (Number.isFinite(configuredTimeout) && configuredTimeout > 0) {
|
|
655
|
+
return Math.min(Math.round(configuredTimeout), MAX_RENDER_TIMEOUT_MS);
|
|
656
|
+
}
|
|
657
|
+
return DEFAULT_RENDER_TIMEOUT_MS;
|
|
658
|
+
}
|
|
659
|
+
__name(getMermaidRenderTimeout, "getMermaidRenderTimeout");
|
|
660
|
+
function createRendererChildEnv(env) {
|
|
661
|
+
const sourceEnv = { ...process.env, ...env };
|
|
662
|
+
const childEnv = {};
|
|
663
|
+
for (const key of RENDERER_ENV_ALLOWLIST) {
|
|
664
|
+
const value = sourceEnv[key];
|
|
665
|
+
if (value !== void 0) {
|
|
666
|
+
childEnv[key] = value;
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
return childEnv;
|
|
670
|
+
}
|
|
671
|
+
__name(createRendererChildEnv, "createRendererChildEnv");
|
|
672
|
+
function getMermaidCellAspectRatio(env) {
|
|
673
|
+
const configuredAspectRatio = Number(
|
|
674
|
+
env["QWEN_CODE_MERMAID_CELL_ASPECT_RATIO"]
|
|
675
|
+
);
|
|
676
|
+
if (Number.isFinite(configuredAspectRatio) && configuredAspectRatio > 0) {
|
|
677
|
+
return Math.max(0.2, Math.min(configuredAspectRatio, 2));
|
|
678
|
+
}
|
|
679
|
+
return 0.5;
|
|
680
|
+
}
|
|
681
|
+
__name(getMermaidCellAspectRatio, "getMermaidCellAspectRatio");
|
|
682
|
+
async function renderPngWithChafaAsync(png, widthCells, rows, chafa, env, signal) {
|
|
683
|
+
const tempDir = await fs.promises.mkdtemp(
|
|
684
|
+
path.join(os.tmpdir(), "qwen-mermaid-")
|
|
685
|
+
);
|
|
686
|
+
const imagePath = path.join(tempDir, "diagram.png");
|
|
687
|
+
try {
|
|
688
|
+
await fs.promises.writeFile(imagePath, png);
|
|
689
|
+
const result = await runCommand(
|
|
690
|
+
chafa,
|
|
691
|
+
[
|
|
692
|
+
"--animate=off",
|
|
693
|
+
"--format=symbols",
|
|
694
|
+
"--symbols=block",
|
|
695
|
+
`--size=${widthCells}x${rows}`,
|
|
696
|
+
imagePath
|
|
697
|
+
],
|
|
698
|
+
{
|
|
699
|
+
env: createRendererChildEnv(env),
|
|
700
|
+
shell: shouldRunThroughShell(chafa),
|
|
701
|
+
timeout: getMermaidRenderTimeout(env),
|
|
702
|
+
signal
|
|
703
|
+
}
|
|
704
|
+
);
|
|
705
|
+
if (result.error) {
|
|
706
|
+
return { ok: false, error: result.error };
|
|
707
|
+
}
|
|
708
|
+
if (result.status !== 0) {
|
|
709
|
+
return {
|
|
710
|
+
ok: false,
|
|
711
|
+
error: result.stderr.trim() || `chafa exited with status ${result.status}.`
|
|
712
|
+
};
|
|
713
|
+
}
|
|
714
|
+
return { ok: true, output: result.stdout };
|
|
715
|
+
} finally {
|
|
716
|
+
await fs.promises.rm(tempDir, { recursive: true, force: true });
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
__name(renderPngWithChafaAsync, "renderPngWithChafaAsync");
|
|
720
|
+
function runCommand(command, args, options) {
|
|
721
|
+
return new Promise((resolve) => {
|
|
722
|
+
if (options.signal?.aborted) {
|
|
723
|
+
resolve({
|
|
724
|
+
status: null,
|
|
725
|
+
stdout: "",
|
|
726
|
+
stderr: "",
|
|
727
|
+
error: "Command cancelled."
|
|
728
|
+
});
|
|
729
|
+
return;
|
|
730
|
+
}
|
|
731
|
+
const child = spawn(command, args, {
|
|
732
|
+
env: options.env,
|
|
733
|
+
shell: options.shell,
|
|
734
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
735
|
+
});
|
|
736
|
+
let stdout = { text: "", truncated: false };
|
|
737
|
+
let stderr = { text: "", truncated: false };
|
|
738
|
+
let settled = false;
|
|
739
|
+
let killTimer;
|
|
740
|
+
let terminationRequested = false;
|
|
741
|
+
const finish = /* @__PURE__ */ __name((result) => {
|
|
742
|
+
if (settled) return;
|
|
743
|
+
settled = true;
|
|
744
|
+
clearTimeout(timer);
|
|
745
|
+
if (!terminationRequested && killTimer) clearTimeout(killTimer);
|
|
746
|
+
options.signal?.removeEventListener("abort", handleAbort);
|
|
747
|
+
resolve(result);
|
|
748
|
+
}, "finish");
|
|
749
|
+
const terminateChild = /* @__PURE__ */ __name(() => {
|
|
750
|
+
terminationRequested = true;
|
|
751
|
+
child.kill("SIGTERM");
|
|
752
|
+
killTimer = setTimeout(() => {
|
|
753
|
+
child.kill("SIGKILL");
|
|
754
|
+
}, 1e3);
|
|
755
|
+
killTimer.unref?.();
|
|
756
|
+
}, "terminateChild");
|
|
757
|
+
const handleAbort = /* @__PURE__ */ __name(() => {
|
|
758
|
+
terminateChild();
|
|
759
|
+
finish({
|
|
760
|
+
status: null,
|
|
761
|
+
stdout: finalizeBoundedRendererOutput(stdout),
|
|
762
|
+
stderr: finalizeBoundedRendererOutput(stderr),
|
|
763
|
+
error: "Command cancelled."
|
|
764
|
+
});
|
|
765
|
+
}, "handleAbort");
|
|
766
|
+
const timer = setTimeout(() => {
|
|
767
|
+
terminateChild();
|
|
768
|
+
finish({
|
|
769
|
+
status: null,
|
|
770
|
+
stdout: finalizeBoundedRendererOutput(stdout),
|
|
771
|
+
stderr: finalizeBoundedRendererOutput(stderr),
|
|
772
|
+
error: `Command timed out after ${options.timeout}ms.`
|
|
773
|
+
});
|
|
774
|
+
}, options.timeout);
|
|
775
|
+
options.signal?.addEventListener("abort", handleAbort, { once: true });
|
|
776
|
+
child.stdout?.setEncoding("utf8");
|
|
777
|
+
child.stderr?.setEncoding("utf8");
|
|
778
|
+
child.stdout?.on("data", (chunk) => {
|
|
779
|
+
stdout = appendBoundedRendererOutput(stdout, chunk);
|
|
780
|
+
});
|
|
781
|
+
child.stderr?.on("data", (chunk) => {
|
|
782
|
+
stderr = appendBoundedRendererOutput(stderr, chunk);
|
|
783
|
+
});
|
|
784
|
+
child.on("error", (error) => {
|
|
785
|
+
finish({
|
|
786
|
+
status: null,
|
|
787
|
+
stdout: finalizeBoundedRendererOutput(stdout),
|
|
788
|
+
stderr: finalizeBoundedRendererOutput(stderr),
|
|
789
|
+
error: error.message
|
|
790
|
+
});
|
|
791
|
+
});
|
|
792
|
+
child.on("close", (status) => {
|
|
793
|
+
finish({
|
|
794
|
+
status,
|
|
795
|
+
stdout: finalizeBoundedRendererOutput(stdout),
|
|
796
|
+
stderr: finalizeBoundedRendererOutput(stderr)
|
|
797
|
+
});
|
|
798
|
+
});
|
|
799
|
+
});
|
|
800
|
+
}
|
|
801
|
+
__name(runCommand, "runCommand");
|
|
802
|
+
function appendBoundedRendererOutput(current, chunk) {
|
|
803
|
+
if (current.truncated) {
|
|
804
|
+
return current;
|
|
805
|
+
}
|
|
806
|
+
const next = current.text + chunk;
|
|
807
|
+
if (next.length <= MAX_RENDERER_OUTPUT_CHARS) {
|
|
808
|
+
return { text: next, truncated: false };
|
|
809
|
+
}
|
|
810
|
+
return {
|
|
811
|
+
text: next.slice(
|
|
812
|
+
0,
|
|
813
|
+
MAX_RENDERER_OUTPUT_CHARS - OUTPUT_TRUNCATION_MARKER.length
|
|
814
|
+
) + OUTPUT_TRUNCATION_MARKER,
|
|
815
|
+
truncated: true
|
|
816
|
+
};
|
|
817
|
+
}
|
|
818
|
+
__name(appendBoundedRendererOutput, "appendBoundedRendererOutput");
|
|
819
|
+
function finalizeBoundedRendererOutput(output) {
|
|
820
|
+
if (!output.truncated || output.text.endsWith(OUTPUT_TRUNCATION_MARKER)) {
|
|
821
|
+
return output.text;
|
|
822
|
+
}
|
|
823
|
+
return output.text.slice(
|
|
824
|
+
0,
|
|
825
|
+
MAX_RENDERER_OUTPUT_CHARS - OUTPUT_TRUNCATION_MARKER.length
|
|
826
|
+
) + OUTPUT_TRUNCATION_MARKER;
|
|
827
|
+
}
|
|
828
|
+
__name(finalizeBoundedRendererOutput, "finalizeBoundedRendererOutput");
|
|
829
|
+
function fitImageToTerminal(size, contentWidth, availableTerminalHeight, env = process.env) {
|
|
830
|
+
const widthCells = Math.max(16, Math.min(contentWidth, 120));
|
|
831
|
+
const naturalRows = Math.ceil(
|
|
832
|
+
size.height / size.width * widthCells * getMermaidCellAspectRatio(env)
|
|
833
|
+
);
|
|
834
|
+
const maxRows = Math.max(4, Math.min(availableTerminalHeight ?? 32, 60));
|
|
835
|
+
return {
|
|
836
|
+
widthCells,
|
|
837
|
+
rows: Math.max(4, Math.min(naturalRows, maxRows))
|
|
838
|
+
};
|
|
839
|
+
}
|
|
840
|
+
__name(fitImageToTerminal, "fitImageToTerminal");
|
|
841
|
+
|
|
842
|
+
// packages/cli/src/ui/utils/terminal-image-renderer.ts
|
|
843
|
+
var CHAFA_TIMEOUT_MS = 8e3;
|
|
844
|
+
var CHAFA_MAX_OUTPUT_BYTES = 2 * 1024 * 1024;
|
|
845
|
+
var MAX_PREVIEW_WIDTH_CELLS = 72;
|
|
846
|
+
var MAX_PREVIEW_ROWS = 24;
|
|
847
|
+
var ESTIMATED_CELL_WIDTH_PX = 8;
|
|
848
|
+
var ESTIMATED_CELL_HEIGHT_PX = 16;
|
|
849
|
+
var MAX_REASON_CHARS = 200;
|
|
850
|
+
var CMD_SHELL_METACHARACTERS = /[&|<>^%"!()\n\r]/;
|
|
851
|
+
var RENDER_CACHE_LIMIT = 40;
|
|
852
|
+
var RENDER_CACHE_BYTE_LIMIT = 32 * 1024 * 1024;
|
|
853
|
+
var renderCache = /* @__PURE__ */ new Map();
|
|
854
|
+
var renderCacheBytes = 0;
|
|
855
|
+
var TRANSMITTED_KEY_LIMIT = 256;
|
|
856
|
+
var transmittedKeys = /* @__PURE__ */ new Set();
|
|
857
|
+
function wasKittyImageWritten(key) {
|
|
858
|
+
return transmittedKeys.has(key);
|
|
859
|
+
}
|
|
860
|
+
__name(wasKittyImageWritten, "wasKittyImageWritten");
|
|
861
|
+
function markKittyImageWritten(key) {
|
|
862
|
+
transmittedKeys.add(key);
|
|
863
|
+
if (transmittedKeys.size > TRANSMITTED_KEY_LIMIT) {
|
|
864
|
+
const oldest = transmittedKeys.values().next().value;
|
|
865
|
+
if (oldest !== void 0) {
|
|
866
|
+
transmittedKeys.delete(oldest);
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
__name(markKittyImageWritten, "markKittyImageWritten");
|
|
871
|
+
function supportsKittyImageProtocol(env = process.env, stdoutIsTTY = process.stdout.isTTY) {
|
|
872
|
+
if (!stdoutIsTTY || env["TMUX"] || env["SSH_TTY"] || env["SSH_CLIENT"]) {
|
|
873
|
+
return false;
|
|
874
|
+
}
|
|
875
|
+
const term = env["TERM"]?.toLowerCase() ?? "";
|
|
876
|
+
const termProgram = env["TERM_PROGRAM"]?.toLowerCase() ?? "";
|
|
877
|
+
if (termProgram === "warpterminal") {
|
|
878
|
+
return false;
|
|
879
|
+
}
|
|
880
|
+
return Boolean(
|
|
881
|
+
env["KITTY_WINDOW_ID"] || term.includes("kitty") || termProgram.includes("ghostty")
|
|
882
|
+
);
|
|
883
|
+
}
|
|
884
|
+
__name(supportsKittyImageProtocol, "supportsKittyImageProtocol");
|
|
885
|
+
function getTerminalImageRenderSupport(env = process.env, stdoutIsTTY = process.stdout.isTTY) {
|
|
886
|
+
if (supportsKittyImageProtocol(env, stdoutIsTTY)) {
|
|
887
|
+
return { available: true };
|
|
888
|
+
}
|
|
889
|
+
return findExecutable("chafa", env) ? { available: true } : {
|
|
890
|
+
available: false,
|
|
891
|
+
reason: "No compatible native image protocol was detected, and chafa is not installed."
|
|
892
|
+
};
|
|
893
|
+
}
|
|
894
|
+
__name(getTerminalImageRenderSupport, "getTerminalImageRenderSupport");
|
|
895
|
+
function containsCmdShellMetacharacters(filePath) {
|
|
896
|
+
return CMD_SHELL_METACHARACTERS.test(filePath);
|
|
897
|
+
}
|
|
898
|
+
__name(containsCmdShellMetacharacters, "containsCmdShellMetacharacters");
|
|
899
|
+
function renderTerminalImage({
|
|
900
|
+
display,
|
|
901
|
+
contentWidth,
|
|
902
|
+
availableTerminalHeight,
|
|
903
|
+
env = process.env,
|
|
904
|
+
stdoutIsTTY = process.stdout.isTTY
|
|
905
|
+
}) {
|
|
906
|
+
let stat;
|
|
907
|
+
try {
|
|
908
|
+
stat = fs2.statSync(display.filePath);
|
|
909
|
+
} catch (error) {
|
|
910
|
+
return {
|
|
911
|
+
kind: "unavailable",
|
|
912
|
+
reason: `Image file is unavailable: ${error instanceof Error ? error.message : String(error)}`
|
|
913
|
+
};
|
|
914
|
+
}
|
|
915
|
+
if (!stat.isFile()) {
|
|
916
|
+
return {
|
|
917
|
+
kind: "unavailable",
|
|
918
|
+
reason: "Image path is not a regular file."
|
|
919
|
+
};
|
|
920
|
+
}
|
|
921
|
+
if (stat.size > MAX_TERMINAL_IMAGE_BYTES) {
|
|
922
|
+
return {
|
|
923
|
+
kind: "unavailable",
|
|
924
|
+
reason: `Image exceeds the ${MAX_TERMINAL_IMAGE_BYTES} byte display limit.`
|
|
925
|
+
};
|
|
926
|
+
}
|
|
927
|
+
const headerSize = readPngHeaderSize(display.filePath);
|
|
928
|
+
if (!headerSize) {
|
|
929
|
+
return { kind: "unavailable", reason: "Image is not a valid PNG." };
|
|
930
|
+
}
|
|
931
|
+
const shape = fitImageToTerminal2(
|
|
932
|
+
headerSize,
|
|
933
|
+
contentWidth,
|
|
934
|
+
availableTerminalHeight
|
|
935
|
+
);
|
|
936
|
+
const useKitty = supportsKittyImageProtocol(env, stdoutIsTTY);
|
|
937
|
+
const chafaPath = useKitty ? null : findExecutable("chafa", env);
|
|
938
|
+
const cacheKey = createRenderCacheKey(
|
|
939
|
+
display.filePath,
|
|
940
|
+
stat,
|
|
941
|
+
shape,
|
|
942
|
+
useKitty,
|
|
943
|
+
chafaPath
|
|
944
|
+
);
|
|
945
|
+
const cached = getCachedRenderResult(cacheKey);
|
|
946
|
+
if (cached) return cached;
|
|
947
|
+
let png;
|
|
948
|
+
try {
|
|
949
|
+
png = fs2.readFileSync(display.filePath);
|
|
950
|
+
} catch (error) {
|
|
951
|
+
return {
|
|
952
|
+
kind: "unavailable",
|
|
953
|
+
reason: `Unable to read image: ${error instanceof Error ? error.message : String(error)}`
|
|
954
|
+
};
|
|
955
|
+
}
|
|
956
|
+
if (png.length > MAX_TERMINAL_IMAGE_BYTES) {
|
|
957
|
+
return {
|
|
958
|
+
kind: "unavailable",
|
|
959
|
+
reason: `Image exceeds the ${MAX_TERMINAL_IMAGE_BYTES} byte display limit.`
|
|
960
|
+
};
|
|
961
|
+
}
|
|
962
|
+
const result = useKitty ? { ...renderKitty(png, shape), key: cacheKey } : renderWithChafa(display.filePath, shape, env, chafaPath);
|
|
963
|
+
if (result.kind !== "unavailable") {
|
|
964
|
+
rememberRenderResult(cacheKey, result);
|
|
965
|
+
}
|
|
966
|
+
return result;
|
|
967
|
+
}
|
|
968
|
+
__name(renderTerminalImage, "renderTerminalImage");
|
|
969
|
+
function readPngHeaderSize(filePath) {
|
|
970
|
+
let fd;
|
|
971
|
+
try {
|
|
972
|
+
fd = fs2.openSync(filePath, "r");
|
|
973
|
+
const header = Buffer.alloc(24);
|
|
974
|
+
const bytesRead = fs2.readSync(fd, header, 0, header.length, 0);
|
|
975
|
+
return bytesRead === header.length ? readPngSize(header) : null;
|
|
976
|
+
} catch {
|
|
977
|
+
return null;
|
|
978
|
+
} finally {
|
|
979
|
+
if (fd !== void 0) {
|
|
980
|
+
try {
|
|
981
|
+
fs2.closeSync(fd);
|
|
982
|
+
} catch {
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
__name(readPngHeaderSize, "readPngHeaderSize");
|
|
988
|
+
function createRenderCacheKey(filePath, stat, shape, useKitty, chafaPath) {
|
|
989
|
+
return [
|
|
990
|
+
filePath,
|
|
991
|
+
stat.mtimeMs,
|
|
992
|
+
stat.size,
|
|
993
|
+
shape.widthCells,
|
|
994
|
+
shape.rows,
|
|
995
|
+
useKitty ? "kitty" : chafaPath ?? "none"
|
|
996
|
+
].join("\0");
|
|
997
|
+
}
|
|
998
|
+
__name(createRenderCacheKey, "createRenderCacheKey");
|
|
999
|
+
function getCachedRenderResult(key) {
|
|
1000
|
+
const cached = renderCache.get(key);
|
|
1001
|
+
if (cached) {
|
|
1002
|
+
renderCache.delete(key);
|
|
1003
|
+
renderCache.set(key, cached);
|
|
1004
|
+
}
|
|
1005
|
+
return cached;
|
|
1006
|
+
}
|
|
1007
|
+
__name(getCachedRenderResult, "getCachedRenderResult");
|
|
1008
|
+
function rememberRenderResult(key, result) {
|
|
1009
|
+
const bytes = estimateRenderResultBytes(result);
|
|
1010
|
+
if (bytes > RENDER_CACHE_BYTE_LIMIT) {
|
|
1011
|
+
renderCache.delete(key);
|
|
1012
|
+
return;
|
|
1013
|
+
}
|
|
1014
|
+
const existing = renderCache.get(key);
|
|
1015
|
+
if (existing) {
|
|
1016
|
+
renderCacheBytes -= estimateRenderResultBytes(existing);
|
|
1017
|
+
}
|
|
1018
|
+
renderCache.set(key, result);
|
|
1019
|
+
renderCacheBytes += bytes;
|
|
1020
|
+
while (renderCache.size > RENDER_CACHE_LIMIT || renderCacheBytes > RENDER_CACHE_BYTE_LIMIT) {
|
|
1021
|
+
const oldest = renderCache.keys().next().value;
|
|
1022
|
+
if (!oldest) break;
|
|
1023
|
+
const oldestResult = renderCache.get(oldest);
|
|
1024
|
+
if (oldestResult) {
|
|
1025
|
+
renderCacheBytes -= estimateRenderResultBytes(oldestResult);
|
|
1026
|
+
}
|
|
1027
|
+
renderCache.delete(oldest);
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
__name(rememberRenderResult, "rememberRenderResult");
|
|
1031
|
+
function estimateRenderResultBytes(result) {
|
|
1032
|
+
switch (result.kind) {
|
|
1033
|
+
case "kitty":
|
|
1034
|
+
return Buffer.byteLength(result.sequence, "utf8") + result.placeholder.lines.reduce(
|
|
1035
|
+
(total, line) => total + Buffer.byteLength(line, "utf8"),
|
|
1036
|
+
0
|
|
1037
|
+
);
|
|
1038
|
+
case "ansi":
|
|
1039
|
+
return result.lines.reduce(
|
|
1040
|
+
(total, line) => total + Buffer.byteLength(line, "utf8"),
|
|
1041
|
+
0
|
|
1042
|
+
);
|
|
1043
|
+
case "unavailable":
|
|
1044
|
+
return Buffer.byteLength(result.reason, "utf8");
|
|
1045
|
+
default: {
|
|
1046
|
+
const exhaustive = result;
|
|
1047
|
+
return exhaustive;
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
__name(estimateRenderResultBytes, "estimateRenderResultBytes");
|
|
1052
|
+
function fitImageToTerminal2(size, contentWidth, availableTerminalHeight) {
|
|
1053
|
+
const maxWidthCells = Math.max(
|
|
1054
|
+
1,
|
|
1055
|
+
Math.min(Math.floor(contentWidth), MAX_PREVIEW_WIDTH_CELLS)
|
|
1056
|
+
);
|
|
1057
|
+
const maxRows = Math.max(
|
|
1058
|
+
1,
|
|
1059
|
+
Math.min(
|
|
1060
|
+
Math.floor(availableTerminalHeight ?? MAX_PREVIEW_ROWS),
|
|
1061
|
+
MAX_PREVIEW_ROWS
|
|
1062
|
+
)
|
|
1063
|
+
);
|
|
1064
|
+
const naturalWidthCells = Math.max(1, size.width / ESTIMATED_CELL_WIDTH_PX);
|
|
1065
|
+
const naturalRows = Math.max(1, size.height / ESTIMATED_CELL_HEIGHT_PX);
|
|
1066
|
+
const scale = Math.min(
|
|
1067
|
+
1,
|
|
1068
|
+
maxWidthCells / naturalWidthCells,
|
|
1069
|
+
maxRows / naturalRows
|
|
1070
|
+
);
|
|
1071
|
+
return {
|
|
1072
|
+
widthCells: Math.max(
|
|
1073
|
+
1,
|
|
1074
|
+
Math.min(maxWidthCells, Math.floor(naturalWidthCells * scale))
|
|
1075
|
+
),
|
|
1076
|
+
rows: Math.max(1, Math.min(maxRows, Math.floor(naturalRows * scale)))
|
|
1077
|
+
};
|
|
1078
|
+
}
|
|
1079
|
+
__name(fitImageToTerminal2, "fitImageToTerminal");
|
|
1080
|
+
function createImageId(png, shape) {
|
|
1081
|
+
const hash = crypto2.createHash("sha256").update(png).update("\0").update(String(shape.widthCells)).update("\0").update(String(shape.rows)).digest();
|
|
1082
|
+
const id = hash.readUIntBE(0, 3);
|
|
1083
|
+
return id === 0 ? 1 : id;
|
|
1084
|
+
}
|
|
1085
|
+
__name(createImageId, "createImageId");
|
|
1086
|
+
function renderKitty(png, shape) {
|
|
1087
|
+
const imageId = createImageId(png, shape);
|
|
1088
|
+
return {
|
|
1089
|
+
kind: "kitty",
|
|
1090
|
+
sequence: encodeKittyVirtualImage(
|
|
1091
|
+
png,
|
|
1092
|
+
imageId,
|
|
1093
|
+
shape.widthCells,
|
|
1094
|
+
shape.rows
|
|
1095
|
+
),
|
|
1096
|
+
placeholder: buildKittyPlaceholder(imageId, shape.widthCells, shape.rows)
|
|
1097
|
+
};
|
|
1098
|
+
}
|
|
1099
|
+
__name(renderKitty, "renderKitty");
|
|
1100
|
+
function renderWithChafa(filePath, shape, env, chafaPath) {
|
|
1101
|
+
if (!chafaPath) {
|
|
1102
|
+
return {
|
|
1103
|
+
kind: "unavailable",
|
|
1104
|
+
reason: "No compatible native image protocol was detected, and chafa is not installed."
|
|
1105
|
+
};
|
|
1106
|
+
}
|
|
1107
|
+
const useShell = shouldRunThroughShell(chafaPath);
|
|
1108
|
+
if (useShell && containsCmdShellMetacharacters(filePath)) {
|
|
1109
|
+
return {
|
|
1110
|
+
kind: "unavailable",
|
|
1111
|
+
reason: "Image path contains characters that cannot be safely passed to the renderer on this platform."
|
|
1112
|
+
};
|
|
1113
|
+
}
|
|
1114
|
+
try {
|
|
1115
|
+
const stdout = execFileSync(
|
|
1116
|
+
chafaPath,
|
|
1117
|
+
[
|
|
1118
|
+
"--animate=off",
|
|
1119
|
+
"--colors=256",
|
|
1120
|
+
"--format=symbols",
|
|
1121
|
+
"--symbols=block",
|
|
1122
|
+
`--size=${shape.widthCells}x${shape.rows}`,
|
|
1123
|
+
filePath
|
|
1124
|
+
],
|
|
1125
|
+
{
|
|
1126
|
+
encoding: "utf8",
|
|
1127
|
+
env: createRendererChildEnv(env),
|
|
1128
|
+
shell: useShell,
|
|
1129
|
+
maxBuffer: CHAFA_MAX_OUTPUT_BYTES,
|
|
1130
|
+
timeout: CHAFA_TIMEOUT_MS
|
|
1131
|
+
}
|
|
1132
|
+
);
|
|
1133
|
+
const lines = stdout.split(/\r?\n/).filter((line) => line.length > 0);
|
|
1134
|
+
return lines.length > 0 ? { kind: "ansi", lines } : { kind: "unavailable", reason: "chafa produced no output." };
|
|
1135
|
+
} catch (error) {
|
|
1136
|
+
const execError = error;
|
|
1137
|
+
const stderr = firstLineBounded(String(execError.stderr ?? "").trim());
|
|
1138
|
+
return {
|
|
1139
|
+
kind: "unavailable",
|
|
1140
|
+
reason: stderr || execError.message || "chafa could not render the image."
|
|
1141
|
+
};
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
__name(renderWithChafa, "renderWithChafa");
|
|
1145
|
+
function firstLineBounded(text) {
|
|
1146
|
+
const firstLine = text.split(/\r?\n/, 1)[0]?.trim() ?? "";
|
|
1147
|
+
return firstLine.length > MAX_REASON_CHARS ? `${firstLine.slice(0, MAX_REASON_CHARS)}\u2026` : firstLine;
|
|
1148
|
+
}
|
|
1149
|
+
__name(firstLineBounded, "firstLineBounded");
|
|
1150
|
+
|
|
1151
|
+
export {
|
|
1152
|
+
renderMermaidImageAsync,
|
|
1153
|
+
TRANSMITTED_KEY_LIMIT,
|
|
1154
|
+
wasKittyImageWritten,
|
|
1155
|
+
markKittyImageWritten,
|
|
1156
|
+
supportsKittyImageProtocol,
|
|
1157
|
+
getTerminalImageRenderSupport,
|
|
1158
|
+
containsCmdShellMetacharacters,
|
|
1159
|
+
renderTerminalImage
|
|
1160
|
+
};
|
|
1161
|
+
/**
|
|
1162
|
+
* @license
|
|
1163
|
+
* Copyright 2025 Google LLC
|
|
1164
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
1165
|
+
*/
|
|
1166
|
+
/**
|
|
1167
|
+
* @license
|
|
1168
|
+
* Copyright 2026 Qwen Team
|
|
1169
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
1170
|
+
*/
|