@qwen-code/qwen-code 0.21.8 → 0.21.9
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/README.md +2 -1
- package/bundled/qc-helper/docs/configuration/settings.md +32 -30
- package/bundled/qc-helper/docs/extension/introduction.md +15 -1
- package/bundled/qc-helper/docs/features/code-review.md +2 -0
- package/bundled/qc-helper/docs/qwen-serve-deploy-local.md +1 -1
- package/bundled/qc-helper/docs/qwen-serve.md +42 -39
- package/bundled/review/SKILL.md +11 -7
- package/chunks/{MaxSizedBox-7PM6BGJ5.js → MaxSizedBox-6BZANW7X.js} +9 -9
- package/chunks/{StandaloneSessionPicker-3UQHM7GV.js → StandaloneSessionPicker-VDC5KE7T.js} +28 -25
- package/chunks/{acpAgent-5UWLFV6V.js → acpAgent-F2NSBCUF.js} +1433 -706
- package/chunks/{agent-624T2BLO.js → agent-VOHJOEBB.js} +8 -8
- package/chunks/{agent-headless-2EE5J2KX.js → agent-headless-J5NFOPHP.js} +8 -8
- package/chunks/{bridge-JENKGFFP.js → bridge-NQIZZLAS.js} +13 -13
- package/chunks/{channel-management-service-DDWUPHMU.js → channel-management-service-PHELKOW2.js} +4 -4
- package/chunks/{channel-settings-store-SA6JZSPH.js → channel-settings-store-VIY2OENO.js} +17 -15
- package/chunks/{channel-worker-group-E67EN3RV.js → channel-worker-group-MSHT6CWR.js} +6 -6
- package/chunks/{channel-worker-manager-SW4C45CF.js → channel-worker-manager-XXD3GDSK.js} +6 -6
- package/chunks/{channel-worker-supervisor-5SRD24FG.js → channel-worker-supervisor-IVSDIMI4.js} +4 -4
- package/chunks/{chunk-S3Y3GBFD.js → chunk-23VQTELM.js} +2 -2
- package/chunks/{chunk-XZKQT2B2.js → chunk-3WDYBTTI.js} +5 -5
- package/chunks/{chunk-YEF7XEO2.js → chunk-3XVDTHBJ.js} +3 -3
- package/chunks/{chunk-IBYULW65.js → chunk-46YJDYCU.js} +145 -10
- package/chunks/chunk-4JRM2BSM.js +48 -0
- package/chunks/{chunk-L4N6TIP7.js → chunk-4TRQPFDP.js} +4 -2
- package/chunks/{chunk-5ZGR6RKJ.js → chunk-4XQNB3KN.js} +3 -3
- package/chunks/chunk-5EJZE3FP.js +140 -0
- package/chunks/{chunk-XHD7CRP2.js → chunk-5RBDAGC6.js} +2 -2
- package/chunks/{chunk-KJZ26VBX.js → chunk-67EWJE77.js} +1 -1
- package/chunks/{chunk-TE3ZAJE7.js → chunk-6Q5ABMTU.js} +1 -1
- package/chunks/{chunk-U5SLIG7E.js → chunk-7AEPJGL4.js} +1 -1
- package/chunks/{chunk-OHKJVAKG.js → chunk-7GOYZQPR.js} +20 -1977
- package/chunks/{chunk-3SE7J4DR.js → chunk-7S4JBJLU.js} +3 -3
- package/chunks/{chunk-TKSZJ5BV.js → chunk-AKJQSWV4.js} +3 -3
- package/chunks/{chunk-E4ZBKMSF.js → chunk-ATMO54WE.js} +6 -6
- package/chunks/{chunk-KKDVZLGL.js → chunk-BAMN6XSD.js} +1 -1
- package/chunks/{chunk-IUQ52YJK.js → chunk-BIRWP6LU.js} +1 -1
- package/chunks/{chunk-AKA24BGO.js → chunk-BT6GQIEJ.js} +1 -1
- package/chunks/{chunk-ZCLLJARV.js → chunk-BZP4QPNK.js} +10 -10
- package/chunks/{chunk-2M5N3DHY.js → chunk-CMOBWHWW.js} +1 -1
- package/chunks/{chunk-WV5J6Q6N.js → chunk-D7BXVKSF.js} +1 -1
- package/chunks/{chunk-NLREQJFK.js → chunk-DA4HRSBW.js} +15 -0
- package/chunks/{chunk-GOEVOFQI.js → chunk-DH5YXSIF.js} +3 -3
- package/chunks/{chunk-DIWZNWZT.js → chunk-DX3RGJMS.js} +13 -2
- package/chunks/{chunk-PLFATELK.js → chunk-DZUO626D.js} +1 -1
- package/chunks/{chunk-NGYI5EF5.js → chunk-E2FPSSKP.js} +8 -8
- package/chunks/{chunk-ZPLALRXZ.js → chunk-FBMCDU63.js} +4 -137
- package/chunks/{chunk-2ILAOM2I.js → chunk-FCLHHEUK.js} +17 -16
- package/chunks/{chunk-SNRT2TJJ.js → chunk-G2TX5ZXC.js} +3 -3
- package/chunks/{chunk-C5VWPTGT.js → chunk-GAKGOXTC.js} +1 -1
- package/chunks/{chunk-QQWD7LZV.js → chunk-HADWBW5R.js} +4 -4
- package/chunks/{chunk-77QVBFCU.js → chunk-HZGBKOX3.js} +3 -3
- package/chunks/{chunk-RPWVIXDB.js → chunk-I5VM3SKY.js} +4 -4
- package/chunks/{chunk-7VUERJHS.js → chunk-II6G3EY6.js} +325 -104
- package/chunks/{chunk-FN6YXJOP.js → chunk-IOEZE2YT.js} +1 -1
- package/chunks/chunk-JUWS2Z5K.js +1995 -0
- package/chunks/{chunk-VXZ5HAOV.js → chunk-K4ADGWHU.js} +1 -1
- package/chunks/{chunk-YOM7DEGB.js → chunk-KSAFZ5TA.js} +2 -2
- package/chunks/{chunk-KAQCJO6Y.js → chunk-KTKYGS2P.js} +35 -9
- package/chunks/{chunk-GBDINRIL.js → chunk-KTQGGPGV.js} +3 -3
- package/chunks/{chunk-6M26GBKX.js → chunk-L2AFWWJE.js} +42 -3
- package/chunks/{chunk-QXVSWG66.js → chunk-LHEC5V6G.js} +2 -2
- package/chunks/{chunk-J26HHFI5.js → chunk-LP2QGNSP.js} +32 -2
- package/chunks/{chunk-HWX5HPUG.js → chunk-LZZLUCRS.js} +108 -11
- package/chunks/{chunk-KTJFU7RT.js → chunk-MFDYOYZZ.js} +2 -2
- package/chunks/{chunk-3WNQOYHQ.js → chunk-MHP476D3.js} +74 -31
- package/chunks/{chunk-Y4TETC74.js → chunk-MTCYGTWH.js} +4 -4
- package/chunks/{chunk-EN2TKTFH.js → chunk-NV3F44FL.js} +6 -2
- package/chunks/{chunk-BF52U4XJ.js → chunk-OGDIJKHK.js} +1 -1
- package/chunks/{chunk-7DVT4LVV.js → chunk-OGNFHGIG.js} +3 -3
- package/chunks/{chunk-IYES5WOT.js → chunk-P2FK2HBV.js} +2 -2
- package/chunks/{chunk-2M4K4KYS.js → chunk-P3RBMQ4P.js} +4 -4
- package/chunks/{chunk-FYAXKJK7.js → chunk-P4ZEZSJZ.js} +692 -106
- package/chunks/{chunk-UFALT4LK.js → chunk-PBRVUF5B.js} +1 -1
- package/chunks/{chunk-LKRMNRSN.js → chunk-PDPFQ2FO.js} +2 -0
- package/chunks/{chunk-6TR7CFXH.js → chunk-PNBBJOCP.js} +1 -1
- package/chunks/{chunk-M3STHEMM.js → chunk-PVOGHGSF.js} +5 -5
- package/chunks/{chunk-4WU6NY7F.js → chunk-QSNSL4R4.js} +2 -2
- package/chunks/{chunk-DQSDACD2.js → chunk-RBHQXGDK.js} +1 -1
- package/chunks/{chunk-ZHA242R4.js → chunk-RVSTTOJ4.js} +2 -2
- package/chunks/{chunk-EIVICVHM.js → chunk-SCAZZ3Q4.js} +4 -4
- package/chunks/{chunk-BF224XHL.js → chunk-T5RLUXWJ.js} +2 -2
- package/chunks/{chunk-B52AWKBB.js → chunk-T6HEQR2Q.js} +16 -5
- package/chunks/{chunk-FWBXMANW.js → chunk-THIKWITR.js} +3 -3
- package/chunks/{chunk-WG6542MA.js → chunk-TQCYNLNJ.js} +1 -1
- package/chunks/chunk-TQOF5KBL.js +71 -0
- package/chunks/{chunk-NPUXXRJI.js → chunk-TZ6KJ44L.js} +1 -1
- package/chunks/{chunk-YHJFF7KH.js → chunk-UJUM2SRN.js} +147 -47
- package/chunks/{chunk-4ALIARFY.js → chunk-UYAUA63Q.js} +1 -1
- package/chunks/chunk-VFMASYQA.js +389 -0
- package/chunks/chunk-VGHZT6JR.js +51 -0
- package/chunks/{chunk-ZWBUH5UP.js → chunk-VKJ4KTPJ.js} +1 -1
- package/chunks/{chunk-QGHSP65Z.js → chunk-VNNWAZSI.js} +2 -2
- package/chunks/{chunk-757GB46F.js → chunk-W3FSZSF2.js} +1 -1
- package/chunks/{chunk-GQCEQPYQ.js → chunk-WGK4TSB7.js} +3 -3
- package/chunks/{chunk-PG62DFWD.js → chunk-WP5VOXF7.js} +6 -127
- package/chunks/{chunk-NVRDQFCX.js → chunk-XTY5DN4Y.js} +1 -1
- package/chunks/{chunk-GXSNGY5M.js → chunk-XX7QFP34.js} +1677 -1307
- package/chunks/{chunk-3PY4LPJF.js → chunk-YGT2AUJ7.js} +84 -4
- package/chunks/{chunk-4DU3NCHG.js → chunk-YTFDX4PR.js} +8 -3
- package/chunks/{chunk-OA4JVLSA.js → chunk-Z7VOMGDC.js} +22 -1
- package/chunks/{chunk-DX5W5AON.js → chunk-ZBXGWQ4S.js} +3 -3
- package/chunks/chunk-ZLBIFIMV.js +1099 -0
- package/chunks/{chunk-HA3SAB64.js → chunk-ZOSTTOUJ.js} +1 -1
- package/chunks/{chunk-VWMUDKLC.js → chunk-ZTQSOV56.js} +4 -4
- package/chunks/{computer-use-ESQYJ3JY.js → computer-use-PMZ7ICGY.js} +8 -8
- package/chunks/{config-utils-XQHBJP7G.js → config-utils-ULCSRMWD.js} +4 -4
- package/chunks/{contextCommand-CX3YF4ZE.js → contextCommand-GEZU7YHE.js} +11 -10
- package/chunks/{core-runtime-DIAU7JMG.js → core-runtime-HRJI2MN6.js} +8 -8
- package/chunks/{create-sub-session-HDPD6HOA.js → create-sub-session-VBNVI4YU.js} +9 -9
- package/chunks/{daemon-VZBGJUNL.js → daemon-POSQPD3G.js} +115 -7
- package/chunks/{daemon-status-provider-H6O4UQ4F.js → daemon-status-provider-N4CRQKFI.js} +18 -18
- package/chunks/{daemon-trust-policy-BNUXG6MT.js → daemon-trust-policy-BHO3JUHM.js} +16 -14
- package/chunks/{daemon-trust-policy-monitor-E4EQ7GF4.js → daemon-trust-policy-monitor-YEKJ2726.js} +16 -14
- package/chunks/{deferred-core-runtime-CBMSHPAU.js → deferred-core-runtime-SH57E3J3.js} +8 -8
- package/chunks/{dist-KVISB2O2.js → dist-3NTTUAHT.js} +1 -1
- package/chunks/{dist-RCH3I7SS.js → dist-6BMOAE3Z.js} +2 -2
- package/chunks/{dist-IRL7WA5Z.js → dist-B2CGTW6T.js} +1 -1
- package/chunks/{dist-TUSWNE2I.js → dist-EWW3J4HQ.js} +1 -1
- package/chunks/{dist-HIACTZEK.js → dist-EZE3V3Q7.js} +1 -1
- package/chunks/{dist-EEEQGCZA.js → dist-J47AXBZC.js} +1 -1
- package/chunks/{dist-MKX5OSFF.js → dist-OTUO3AS2.js} +4 -1088
- package/chunks/{dist-MBF3I5MX.js → dist-Z3CS4OVP.js} +1 -1
- package/chunks/{earlyInputCapture-UIOP7OIN.js → earlyInputCapture-B2JJ2HME.js} +8 -8
- package/chunks/{edit-ITMZYFKA.js → edit-7FTXENAN.js} +10 -8
- package/chunks/{enter-worktree-S4PL5UV6.js → enter-worktree-JPHV2PBG.js} +8 -8
- package/chunks/{enterPlanMode-YV52NNJT.js → enterPlanMode-CGBJ3AHJ.js} +8 -8
- package/chunks/{environment-NGOWPRZV.js → environment-LXASZAHD.js} +11 -11
- package/chunks/{errors-BU26DTDX.js → errors-XIGVT2AD.js} +10 -10
- package/chunks/{exit-worktree-XRM6LH5F.js → exit-worktree-DKSGXW65.js} +8 -8
- package/chunks/{exitPlanMode-ZLI5F7KR.js → exitPlanMode-THFL2HYN.js} +8 -8
- package/chunks/{fast-path-UJWORIED.js → fast-path-4NXAT5UL.js} +4 -3
- package/chunks/{fast-path-settings-37WQD5B2.js → fast-path-settings-RPAVBD7P.js} +2 -2
- package/chunks/{gemini-ZSKNDUMU.js → gemini-B3N6FACU.js} +56 -60
- package/chunks/{geminiContentGenerator-YGEXOEKD.js → geminiContentGenerator-YYFE2HIE.js} +1 -1
- package/chunks/{glob-7KZG44BR.js → glob-BPHSCFJP.js} +8 -8
- package/chunks/{grep-6ZFC7RJ5.js → grep-ROZIRFLU.js} +8 -8
- package/chunks/{handleAutoUpdate-KSEL3TQS.js → handleAutoUpdate-WV6SPZQB.js} +13 -12
- package/chunks/{i18n-ZIUXBW5V.js → i18n-YWJWPQKD.js} +13 -11
- package/chunks/{image-gen-AUIZJJNK.js → image-gen-SISRZ6FS.js} +1 -1
- package/chunks/{initializer-7AHY3N6Q.js → initializer-66OAD6GO.js} +16 -14
- package/chunks/{installationInfo-VGBXMYLY.js → installationInfo-3YUGIP36.js} +9 -9
- package/chunks/{list-PSFKQHLB.js → list-VEYR66XB.js} +19 -17
- package/chunks/{loadedSettingsAdapter-FTMRCTOF.js → loadedSettingsAdapter-V2JCPCYD.js} +16 -14
- package/chunks/{loggingContentGenerator-MZAN52UV.js → loggingContentGenerator-RBLNDREC.js} +6 -6
- package/chunks/main-PXAUXNF2.js +8 -0
- package/chunks/{managed-npm-update-O4NHK45X.js → managed-npm-update-C5ID5R4R.js} +9 -9
- package/chunks/{mcp-6CFP2AYQ.js → mcp-OZ54NZJQ.js} +16 -14
- package/chunks/{monitor-DAKD6OU4.js → monitor-7Y4TVFTK.js} +18 -14
- package/chunks/{nonInteractiveCli-RC7VIUZL.js → nonInteractiveCli-QEK4LHAC.js} +51 -49
- package/chunks/{notebook-edit-474DPMRL.js → notebook-edit-OG35EBGY.js} +9 -8
- package/chunks/{openaiContentGenerator-2NFY2MWO.js → openaiContentGenerator-443BNRPJ.js} +5 -5
- package/chunks/{pidfile-KBFVDNQP.js → pidfile-ZK4OLRZA.js} +8 -8
- package/chunks/{processUtils-6GRYH4Y3.js → processUtils-4YGB4RUZ.js} +2 -2
- package/chunks/{qwenContentGenerator-KAHU6IZY.js → qwenContentGenerator-D5C2LCSZ.js} +9 -9
- package/chunks/{qwenOAuth2-RRQTCP4W.js → qwenOAuth2-Z4YQBMYN.js} +1 -1
- package/chunks/{read-file-3M6WXDXP.js → read-file-EXTJLWMU.js} +4 -4
- package/chunks/{resumeHistoryUtils-D6TAY3HX.js → resumeHistoryUtils-UPCGRJUL.js} +13 -12
- package/chunks/{ripGrep-PLPENT3E.js → ripGrep-QBVIRCU4.js} +8 -8
- package/chunks/{run-qwen-serve-ZAFIJKJC.js → run-qwen-serve-ZYGJNE3E.js} +169 -68
- package/chunks/{runtime-ZED7CYOZ.js → runtime-BZZ4LWCP.js} +21 -19
- package/chunks/{scheduler-MD3AL2W5.js → scheduler-YNQNOU2E.js} +135 -15
- package/chunks/{sdk-exporters-http-KHAB5JSD.js → sdk-exporters-http-XVTZQRCE.js} +2 -2
- package/chunks/{sdk-impl-KD7FSTC3.js → sdk-impl-7W7AKCS4.js} +7 -3
- package/chunks/{serve-E3VUDRZN.js → serve-LJHAXDCH.js} +18 -14
- package/chunks/{server-OWMEMAKR.js → server-ADMLELR6.js} +1229 -1098
- package/chunks/{session-HZ57QK7K.js → session-YKZXFFTM.js} +55 -53
- package/chunks/{settings-V7BR3RKP.js → settings-EQBUAQ7Y.js} +15 -13
- package/chunks/{shell-23OMNMW6.js → shell-3QZOJGTT.js} +8 -8
- package/chunks/{skill-6HBDYZRS.js → skill-UWSSMXE7.js} +5 -5
- package/chunks/{skill-settings-HWJLTU7M.js → skill-settings-T6MLB7NU.js} +15 -13
- package/chunks/{spawnChannel-N6KKUW5B.js → spawnChannel-VS7ZFUFP.js} +11 -11
- package/chunks/{standalone-update-QGIKHATD.js → standalone-update-2W26SRRO.js} +11 -10
- package/chunks/{startInteractiveUI-GX2CRL42.js → startInteractiveUI-CVS7K3D6.js} +86 -75
- package/chunks/{team-create-CFFKU7KL.js → team-create-4WFTNNUL.js} +8 -8
- package/chunks/{team-plan-approval-6EFOKR6A.js → team-plan-approval-DBYI33S3.js} +8 -8
- package/chunks/{terminal-image-renderer-TLDNACQY.js → terminal-image-renderer-S5WPPQKH.js} +8 -8
- package/chunks/{theme-manager-5LJ3H7VO.js → theme-manager-LI2RIOVR.js} +8 -8
- package/chunks/{tool-search-UJV3A24H.js → tool-search-4773EUQ4.js} +4 -4
- package/chunks/{total-session-admission-D63QYXGO.js → total-session-admission-PAY5CH2Z.js} +16 -15
- package/chunks/{trustedFolders-KZCOB53W.js → trustedFolders-FRSLE674.js} +9 -9
- package/chunks/{types-ML3TRJQ5.js → types-WYCFCEHR.js} +5 -3
- package/chunks/{update-relaunch-IFILM3SA.js → update-relaunch-ZSFQTU6M.js} +5 -5
- package/chunks/{updateCheck-YZ2CRCFC.js → updateCheck-AXWSO7KA.js} +12 -11
- package/chunks/{useAutoAcceptIndicator-AXEVNA3Q.js → useAutoAcceptIndicator-VHLXIA7U.js} +18 -16
- package/chunks/{validateNonInterActiveAuth-3WTOJFWA.js → validateNonInterActiveAuth-PDJECMFU.js} +48 -46
- package/chunks/{version-GXK7OHZY.js → version-RBN764QS.js} +1 -1
- package/chunks/{web-fetch-ILB4GAVR.js → web-fetch-7BJK42AF.js} +4 -4
- package/chunks/{web-search-HKRPGPZZ.js → web-search-L2CILQXV.js} +4 -3
- package/chunks/{workflow-FXIPRQQA.js → workflow-5VH2R74I.js} +170 -137
- package/chunks/{workspace-providers-status-NYHC7HSR.js → workspace-providers-status-OZTQ6JFH.js} +19 -17
- package/chunks/{workspace-registration-store-AKEB7OMW.js → workspace-registration-store-IX5RJQS5.js} +1 -1
- package/chunks/{workspace-registry-CDAS5TVZ.js → workspace-registry-73N4BGG4.js} +16 -15
- package/chunks/{workspace-service-PAMUKMAV.js → workspace-service-I5RUPSNV.js} +26 -22
- package/chunks/{workspace-skills-status-YQSHCCMS.js → workspace-skills-status-DMK6VYDO.js} +17 -15
- package/chunks/{workspace-trust-reconciler-RPTXOIY2.js → workspace-trust-reconciler-QX4RL3TC.js} +24 -21
- package/chunks/{write-file-CGS57TS4.js → write-file-UGDD5UTS.js} +8 -8
- package/chunks/{zoom-image-E7D72GYV.js → zoom-image-ZAHEO3YP.js} +4 -4
- package/cli.js +12 -12
- package/package.json +3 -3
- package/web-shell/assets/{arc-DybZaz32.js → arc-CHY4saMJ.js} +1 -1
- package/web-shell/assets/{architectureDiagram-3BPJPVTR-jN3qBd19.js → architectureDiagram-3BPJPVTR-Bu6CwvHj.js} +1 -1
- package/web-shell/assets/{blockDiagram-GPEHLZMM-Ct5DZPrj.js → blockDiagram-GPEHLZMM-XGt6iGf_.js} +1 -1
- package/web-shell/assets/{c4Diagram-AAUBKEIU-CUAFMlUG.js → c4Diagram-AAUBKEIU-CBbYl19W.js} +1 -1
- package/web-shell/assets/channel-B40srHOa.js +1 -0
- package/web-shell/assets/{chunk-2J33WTMH-CuV8n90B.js → chunk-2J33WTMH-BEhmVrdx.js} +1 -1
- package/web-shell/assets/{chunk-4BX2VUAB-BUzl_kls.js → chunk-4BX2VUAB-fQLyE0Bg.js} +1 -1
- package/web-shell/assets/{chunk-55IACEB6-BnDBLX6A.js → chunk-55IACEB6-yGdtyx4a.js} +1 -1
- package/web-shell/assets/{chunk-727SXJPM-B83uTOjm.js → chunk-727SXJPM-DYbX2GLo.js} +1 -1
- package/web-shell/assets/{chunk-AQP2D5EJ-DM3HLgpT.js → chunk-AQP2D5EJ-DyKTEsYn.js} +1 -1
- package/web-shell/assets/{chunk-FMBD7UC4-CSQ5hgyb.js → chunk-FMBD7UC4-D8Uy_GzX.js} +1 -1
- package/web-shell/assets/{chunk-ND2GUHAM-BWOF4SxX.js → chunk-ND2GUHAM-C8wNR2K7.js} +1 -1
- package/web-shell/assets/{chunk-QZHKN3VN-BsOH9LMi.js → chunk-QZHKN3VN-BnybNxnt.js} +1 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-qumcXQW_.js +1 -0
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-qumcXQW_.js +1 -0
- package/web-shell/assets/{cose-bilkent-S5V4N54A-IENqH2iJ.js → cose-bilkent-S5V4N54A-jq4uiFRp.js} +1 -1
- package/web-shell/assets/{dagre-BM42HDAG--dyzDTGo.js → dagre-BM42HDAG-Bs7oye1U.js} +1 -1
- package/web-shell/assets/{diagram-2AECGRRQ-BE7Dcqof.js → diagram-2AECGRRQ-BHGGJNyM.js} +1 -1
- package/web-shell/assets/{diagram-5GNKFQAL-Cr8-5OTj.js → diagram-5GNKFQAL-BJezVLGT.js} +1 -1
- package/web-shell/assets/{diagram-KO2AKTUF-Bzey3uAY.js → diagram-KO2AKTUF-5JzQN_rL.js} +1 -1
- package/web-shell/assets/{diagram-LMA3HP47-sErl28Xb.js → diagram-LMA3HP47-BlPYOgY9.js} +1 -1
- package/web-shell/assets/{diagram-OG6HWLK6-Dq30ATIo.js → diagram-OG6HWLK6-CtMHEaFK.js} +1 -1
- package/web-shell/assets/{erDiagram-TEJ5UH35-BkCoEfVW.js → erDiagram-TEJ5UH35-CRNdq2AB.js} +1 -1
- package/web-shell/assets/{flowDiagram-I6XJVG4X-DHwO0rrI.js → flowDiagram-I6XJVG4X-De1WwLzu.js} +1 -1
- package/web-shell/assets/{ganttDiagram-6RSMTGT7-s7vAPxWq.js → ganttDiagram-6RSMTGT7-YbWfL5Zn.js} +1 -1
- package/web-shell/assets/{gitGraphDiagram-PVQCEYII-CQxhwPOU.js → gitGraphDiagram-PVQCEYII-DzCN8bmd.js} +1 -1
- package/web-shell/assets/index-BDOGGGaN.css +5 -0
- package/web-shell/assets/{index-CF4wApWp.js → index-CocPvF9Q.js} +1 -1
- package/web-shell/assets/index-DSH2KrMc.js +1771 -0
- package/web-shell/assets/{infoDiagram-5YYISTIA-BnFrD0bq.js → infoDiagram-5YYISTIA-DLHoopnE.js} +1 -1
- package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-Bf9zK5NK.js → ishikawaDiagram-YF4QCWOH-XnbU04SS.js} +1 -1
- package/web-shell/assets/{journeyDiagram-JHISSGLW-CyGAhsxi.js → journeyDiagram-JHISSGLW-CipPyEeJ.js} +1 -1
- package/web-shell/assets/{kanban-definition-UN3LZRKU-CbsK5akB.js → kanban-definition-UN3LZRKU-DrSeyE5d.js} +1 -1
- package/web-shell/assets/{linear-cQsF4P8D.js → linear-LrBKnAo_.js} +1 -1
- package/web-shell/assets/{mermaid.core-Z4HVqrKY.js → mermaid.core-C3U9UVmf.js} +5 -5
- package/web-shell/assets/{mindmap-definition-RKZ34NQL-CYnrBo_f.js → mindmap-definition-RKZ34NQL-DqRWgC9H.js} +1 -1
- package/web-shell/assets/{pieDiagram-4H26LBE5-CBzOfhrs.js → pieDiagram-4H26LBE5-BNXY5p6H.js} +1 -1
- package/web-shell/assets/{quadrantDiagram-W4KKPZXB-D4LK1Ebn.js → quadrantDiagram-W4KKPZXB-Ccj9QzE4.js} +1 -1
- package/web-shell/assets/{requirementDiagram-4Y6WPE33-Bzti2Lcj.js → requirementDiagram-4Y6WPE33-CjPM2_gx.js} +1 -1
- package/web-shell/assets/{sankeyDiagram-5OEKKPKP-yTBw5Z2s.js → sankeyDiagram-5OEKKPKP-C0RsvKbj.js} +1 -1
- package/web-shell/assets/{sequenceDiagram-3UESZ5HK-D07UVRiZ.js → sequenceDiagram-3UESZ5HK-ClN1P5z7.js} +1 -1
- package/web-shell/assets/{stateDiagram-AJRCARHV-UE_lHsTn.js → stateDiagram-AJRCARHV-By0eiB2Y.js} +1 -1
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-Ds0WlK3F.js +1 -0
- package/web-shell/assets/{timeline-definition-PNZ67QCA-DRvYdiTs.js → timeline-definition-PNZ67QCA-g_iaSQgv.js} +1 -1
- package/web-shell/assets/{vennDiagram-CIIHVFJN-CQLIXs0u.js → vennDiagram-CIIHVFJN-y9ZqJ-TD.js} +1 -1
- package/web-shell/assets/{wardley-L42UT6IY-JZz_Xqse.js → wardley-L42UT6IY-BVVfaxpF.js} +1 -1
- package/web-shell/assets/{wardleyDiagram-YWT4CUSO--i7BiJwB.js → wardleyDiagram-YWT4CUSO-D3ooZKZT.js} +1 -1
- package/web-shell/assets/{xychartDiagram-2RQKCTM6-Bkc-bW0S.js → xychartDiagram-2RQKCTM6-6GXrY6M1.js} +1 -1
- package/web-shell/index.html +2 -2
- package/chunks/chunk-RXFQM6FQ.js +0 -42
- package/chunks/chunk-UA5H3DS2.js +0 -203
- package/web-shell/assets/channel-BMwLrwLW.js +0 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-BGDv98jY.js +0 -1
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-BGDv98jY.js +0 -1
- package/web-shell/assets/index-Bckpjr-I.css +0 -5
- package/web-shell/assets/index-DwEr9HEW.js +0 -1768
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-DC6xgXjX.js +0 -1
- /package/chunks/{chunk-VXZBKKQR.js → chunk-NTTBXH7U.js} +0 -0
- /package/chunks/{chunk-GRC5HGPI.js → chunk-OIBUG24X.js} +0 -0
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
// Force strict mode and setup for ESM
|
|
2
2
|
"use strict";
|
|
3
|
+
import {
|
|
4
|
+
deriveWebSocketBase,
|
|
5
|
+
openQwenAsrRealtimeStream,
|
|
6
|
+
openVoiceStream,
|
|
7
|
+
openVoiceStreamWithRetry
|
|
8
|
+
} from "./chunk-Q3JQ7OSU.js";
|
|
3
9
|
import {
|
|
4
10
|
GENERATION_MAX_PROMPT_BYTES,
|
|
5
11
|
LIVE_SESSION_SOURCE_PREFIX,
|
|
@@ -11,7 +17,6 @@ import {
|
|
|
11
17
|
isCompatibleLiveSessionSource,
|
|
12
18
|
isReservedLiveSessionSource,
|
|
13
19
|
isValidServerName,
|
|
14
|
-
loadSettingsCached,
|
|
15
20
|
normalizeChannelDelivery,
|
|
16
21
|
parseChannelDelivery,
|
|
17
22
|
readLoadableLiveConversationMetadata,
|
|
@@ -21,13 +26,7 @@ import {
|
|
|
21
26
|
shouldSuppressRememberErrorDetails,
|
|
22
27
|
workspaceMemoryFailureCode,
|
|
23
28
|
workspaceMemoryFailureDiagnostics
|
|
24
|
-
} from "./chunk-
|
|
25
|
-
import {
|
|
26
|
-
deriveWebSocketBase,
|
|
27
|
-
openQwenAsrRealtimeStream,
|
|
28
|
-
openVoiceStream,
|
|
29
|
-
openVoiceStreamWithRetry
|
|
30
|
-
} from "./chunk-Q3JQ7OSU.js";
|
|
29
|
+
} from "./chunk-FBMCDU63.js";
|
|
31
30
|
import {
|
|
32
31
|
SetupGithubError,
|
|
33
32
|
collectSessionData,
|
|
@@ -39,12 +38,12 @@ import {
|
|
|
39
38
|
toJson,
|
|
40
39
|
toJsonl,
|
|
41
40
|
toMarkdown
|
|
42
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-P3RBMQ4P.js";
|
|
43
42
|
import {
|
|
44
43
|
OBSERVED_CONTACT_MAX_FRESH_WITHIN_SECONDS,
|
|
45
44
|
ObservedChannelContactStore
|
|
46
45
|
} from "./chunk-OWMAZHIX.js";
|
|
47
|
-
import "./chunk-
|
|
46
|
+
import "./chunk-UYAUA63Q.js";
|
|
48
47
|
import {
|
|
49
48
|
escapeAnsiCtrlCodes
|
|
50
49
|
} from "./chunk-4NFY2S7N.js";
|
|
@@ -108,46 +107,14 @@ import {
|
|
|
108
107
|
setRateLimiter,
|
|
109
108
|
unsafeRevealSecret,
|
|
110
109
|
validateMcpRuntimeServerName
|
|
111
|
-
} from "./chunk-
|
|
110
|
+
} from "./chunk-KTKYGS2P.js";
|
|
111
|
+
import "./chunk-VGHZT6JR.js";
|
|
112
112
|
import {
|
|
113
|
-
isLoopbackBind
|
|
114
|
-
|
|
113
|
+
isLoopbackBind,
|
|
114
|
+
normalizeSessionIdForLookup,
|
|
115
|
+
parseCallerSuppliedSessionId
|
|
116
|
+
} from "./chunk-TQOF5KBL.js";
|
|
115
117
|
import "./chunk-HGCQ5SE7.js";
|
|
116
|
-
import {
|
|
117
|
-
createTotalSessionAdmissionController
|
|
118
|
-
} from "./chunk-AKA24BGO.js";
|
|
119
|
-
import {
|
|
120
|
-
WorkspaceGenerationClosedError,
|
|
121
|
-
createSingleWorkspaceRegistry,
|
|
122
|
-
createWorkspaceSessionOwnerIndex
|
|
123
|
-
} from "./chunk-2M5N3DHY.js";
|
|
124
|
-
import "./chunk-GRC5HGPI.js";
|
|
125
|
-
import {
|
|
126
|
-
assertValidChannelSecretUpdates
|
|
127
|
-
} from "./chunk-4WU6NY7F.js";
|
|
128
|
-
import {
|
|
129
|
-
createWorkspaceProvidersStatusProvider
|
|
130
|
-
} from "./chunk-XZKQT2B2.js";
|
|
131
|
-
import {
|
|
132
|
-
getAuthTypeFromEnv,
|
|
133
|
-
resolveCliGenerationConfig
|
|
134
|
-
} from "./chunk-GBDINRIL.js";
|
|
135
|
-
import {
|
|
136
|
-
createWorkspaceSkillsStatusProvider
|
|
137
|
-
} from "./chunk-DX5W5AON.js";
|
|
138
|
-
import "./chunk-BGXZBI5B.js";
|
|
139
|
-
import {
|
|
140
|
-
isServeDebugMode,
|
|
141
|
-
mountWebShellAssets,
|
|
142
|
-
mountWebShellSpaFallback
|
|
143
|
-
} from "./chunk-SOORFWKY.js";
|
|
144
|
-
import {
|
|
145
|
-
require_express
|
|
146
|
-
} from "./chunk-GDXET5XU.js";
|
|
147
|
-
import {
|
|
148
|
-
evaluateDaemonWorkspaceTrust,
|
|
149
|
-
readDaemonTrustPolicySnapshot
|
|
150
|
-
} from "./chunk-SNRT2TJJ.js";
|
|
151
118
|
import {
|
|
152
119
|
EMPTY_WORKSPACE_VOICE_UPDATE_ERROR,
|
|
153
120
|
MAX_WORKSPACE_SKILL_NAME_LENGTH,
|
|
@@ -161,14 +128,14 @@ import {
|
|
|
161
128
|
validateWorkspaceSkillName,
|
|
162
129
|
validateWorkspaceVoiceState,
|
|
163
130
|
voiceSettingsScopeToWire
|
|
164
|
-
} from "./chunk-
|
|
131
|
+
} from "./chunk-46YJDYCU.js";
|
|
165
132
|
import {
|
|
166
133
|
PermissionRulesValidationError,
|
|
167
134
|
buildPermissionSettings,
|
|
168
135
|
isPermissionRuleType,
|
|
169
136
|
normalizePermissionRules,
|
|
170
137
|
readPermissionRuleSet
|
|
171
|
-
} from "./chunk-
|
|
138
|
+
} from "./chunk-BAMN6XSD.js";
|
|
172
139
|
import {
|
|
173
140
|
assertVoiceBaseUrlNetworkAllowed,
|
|
174
141
|
isStreamingVoiceModel,
|
|
@@ -176,46 +143,92 @@ import {
|
|
|
176
143
|
resolveVoiceTranscriptionConfig,
|
|
177
144
|
sanitizeVoiceErrorMessage,
|
|
178
145
|
transcribeVoiceAudio
|
|
179
|
-
} from "./chunk-
|
|
146
|
+
} from "./chunk-RBHQXGDK.js";
|
|
180
147
|
import {
|
|
181
148
|
isVoiceEnabled,
|
|
182
149
|
isVoiceMode,
|
|
183
150
|
readVoiceModel
|
|
184
|
-
} from "./chunk-
|
|
151
|
+
} from "./chunk-GAKGOXTC.js";
|
|
185
152
|
import "./chunk-AOHJKPKL.js";
|
|
153
|
+
import {
|
|
154
|
+
createTotalSessionAdmissionController
|
|
155
|
+
} from "./chunk-BT6GQIEJ.js";
|
|
156
|
+
import {
|
|
157
|
+
WorkspaceGenerationClosedError,
|
|
158
|
+
createSingleWorkspaceRegistry,
|
|
159
|
+
createWorkspaceSessionOwnerIndex
|
|
160
|
+
} from "./chunk-CMOBWHWW.js";
|
|
161
|
+
import "./chunk-OIBUG24X.js";
|
|
162
|
+
import {
|
|
163
|
+
MAX_SESSION_RESTORE_TIMEOUT_MS,
|
|
164
|
+
resolveSessionRestoreTimeoutMs,
|
|
165
|
+
restoreRetryAfterSeconds
|
|
166
|
+
} from "./chunk-4JRM2BSM.js";
|
|
167
|
+
import {
|
|
168
|
+
assertValidChannelSecretUpdates
|
|
169
|
+
} from "./chunk-QSNSL4R4.js";
|
|
170
|
+
import {
|
|
171
|
+
createDaemonStatusProvider
|
|
172
|
+
} from "./chunk-ZTQSOV56.js";
|
|
173
|
+
import "./chunk-NTTBXH7U.js";
|
|
174
|
+
import "./chunk-7S4JBJLU.js";
|
|
175
|
+
import "./chunk-3SH53ANB.js";
|
|
176
|
+
import {
|
|
177
|
+
createWorkspaceProvidersStatusProvider
|
|
178
|
+
} from "./chunk-3WDYBTTI.js";
|
|
179
|
+
import {
|
|
180
|
+
getAuthTypeFromEnv,
|
|
181
|
+
resolveCliGenerationConfig
|
|
182
|
+
} from "./chunk-KTQGGPGV.js";
|
|
183
|
+
import {
|
|
184
|
+
snapshotProcessEnv
|
|
185
|
+
} from "./chunk-23VQTELM.js";
|
|
186
|
+
import {
|
|
187
|
+
createWorkspaceSkillsStatusProvider
|
|
188
|
+
} from "./chunk-ZBXGWQ4S.js";
|
|
189
|
+
import "./chunk-BGXZBI5B.js";
|
|
186
190
|
import "./chunk-Z4X5MTRT.js";
|
|
187
191
|
import {
|
|
188
192
|
WorkspacePermissionRulesSessionRequiredError,
|
|
189
193
|
WorkspaceSettingsPartialPersistError,
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
194
|
+
mapWorkspaceSkillToggleError
|
|
195
|
+
} from "./chunk-Z7VOMGDC.js";
|
|
196
|
+
import {
|
|
197
|
+
isServeDebugMode,
|
|
198
|
+
mountWebShellAssets,
|
|
199
|
+
mountWebShellSpaFallback
|
|
200
|
+
} from "./chunk-SOORFWKY.js";
|
|
201
|
+
import {
|
|
202
|
+
require_express
|
|
203
|
+
} from "./chunk-GDXET5XU.js";
|
|
204
|
+
import {
|
|
205
|
+
evaluateDaemonWorkspaceTrust,
|
|
206
|
+
readDaemonTrustPolicySnapshot
|
|
207
|
+
} from "./chunk-G2TX5ZXC.js";
|
|
193
208
|
import {
|
|
194
209
|
daemonObservedContactsPath,
|
|
195
210
|
loadChannelsConfig
|
|
196
|
-
} from "./chunk-
|
|
197
|
-
import "./chunk-
|
|
211
|
+
} from "./chunk-ATMO54WE.js";
|
|
212
|
+
import "./chunk-HADWBW5R.js";
|
|
198
213
|
import "./chunk-57OAHC2Y.js";
|
|
214
|
+
import {
|
|
215
|
+
parseChannelWebhookConfigLenient
|
|
216
|
+
} from "./chunk-LHEC5V6G.js";
|
|
217
|
+
import "./chunk-67EWJE77.js";
|
|
218
|
+
import {
|
|
219
|
+
supportedChannelCatalog
|
|
220
|
+
} from "./chunk-E2FPSSKP.js";
|
|
199
221
|
import {
|
|
200
222
|
LIVE_HOST_BUNDLE_ID,
|
|
201
223
|
LIVE_HOST_PROTOCOL_VERSION,
|
|
202
224
|
LIVE_INPUT_AUDIO_EPOCH_BYTES
|
|
203
225
|
} from "./chunk-NKLP3DCK.js";
|
|
204
|
-
import {
|
|
205
|
-
createDaemonStatusProvider
|
|
206
|
-
} from "./chunk-VWMUDKLC.js";
|
|
207
|
-
import "./chunk-VXZBKKQR.js";
|
|
208
|
-
import "./chunk-3SE7J4DR.js";
|
|
209
|
-
import "./chunk-3SH53ANB.js";
|
|
210
|
-
import {
|
|
211
|
-
snapshotProcessEnv
|
|
212
|
-
} from "./chunk-S3Y3GBFD.js";
|
|
213
226
|
import {
|
|
214
227
|
SessionArtifactAuthorizationError,
|
|
215
228
|
SessionArtifactValidationError,
|
|
216
229
|
createAcpSessionBridge,
|
|
217
230
|
parseSessionSource
|
|
218
|
-
} from "./chunk-
|
|
231
|
+
} from "./chunk-P4ZEZSJZ.js";
|
|
219
232
|
import {
|
|
220
233
|
EVENT_SCHEMA_VERSION,
|
|
221
234
|
EventBus,
|
|
@@ -223,22 +236,16 @@ import {
|
|
|
223
236
|
} from "./chunk-MZSJ43WV.js";
|
|
224
237
|
import "./chunk-XCGIMOLN.js";
|
|
225
238
|
import "./chunk-OCPBI7J5.js";
|
|
226
|
-
import "./chunk-
|
|
239
|
+
import "./chunk-I5VM3SKY.js";
|
|
227
240
|
import {
|
|
228
241
|
STATUS_SCHEMA_VERSION,
|
|
242
|
+
SessionRestoreTimeoutError,
|
|
229
243
|
createIdleWorkspaceMemoryStatus,
|
|
230
244
|
mapDomainErrorToErrorKind
|
|
231
|
-
} from "./chunk-
|
|
245
|
+
} from "./chunk-DA4HRSBW.js";
|
|
232
246
|
import "./chunk-K6KS3LTN.js";
|
|
233
247
|
import "./chunk-FC4KQFCS.js";
|
|
234
248
|
import "./chunk-T3CHYWJZ.js";
|
|
235
|
-
import {
|
|
236
|
-
parseChannelWebhookConfigLenient
|
|
237
|
-
} from "./chunk-QXVSWG66.js";
|
|
238
|
-
import "./chunk-KJZ26VBX.js";
|
|
239
|
-
import {
|
|
240
|
-
supportedChannelCatalog
|
|
241
|
-
} from "./chunk-NGYI5EF5.js";
|
|
242
249
|
import "./chunk-V6WHFGST.js";
|
|
243
250
|
import {
|
|
244
251
|
MAX_REGISTERED_WORKSPACES,
|
|
@@ -247,12 +254,14 @@ import {
|
|
|
247
254
|
WorkspaceRegistrationStoreLimitError,
|
|
248
255
|
normalizeWorkspaceDisplayName,
|
|
249
256
|
workspaceRegistrationId
|
|
250
|
-
} from "./chunk-
|
|
257
|
+
} from "./chunk-W3FSZSF2.js";
|
|
251
258
|
import {
|
|
259
|
+
REQUESTED_SESSION_ID_META_KEY,
|
|
252
260
|
gradeActiveWorkCoverage
|
|
253
261
|
} from "./chunk-M2PNLYGY.js";
|
|
254
262
|
import {
|
|
255
263
|
BranchWhilePromptActiveError,
|
|
264
|
+
BridgeChannelQuarantinedError,
|
|
256
265
|
CancelSentinelCollisionError,
|
|
257
266
|
CdWhilePromptActiveError,
|
|
258
267
|
InvalidClientIdError,
|
|
@@ -283,7 +292,7 @@ import {
|
|
|
283
292
|
WorkspaceInitRaceError,
|
|
284
293
|
WorkspaceInitSymlinkError,
|
|
285
294
|
WorkspaceMismatchError
|
|
286
|
-
} from "./chunk-
|
|
295
|
+
} from "./chunk-LP2QGNSP.js";
|
|
287
296
|
import {
|
|
288
297
|
MAX_WORKSPACE_PATH_LENGTH,
|
|
289
298
|
canonicalizeWorkspace,
|
|
@@ -302,19 +311,19 @@ import {
|
|
|
302
311
|
} from "./chunk-YP5KH5Y7.js";
|
|
303
312
|
import {
|
|
304
313
|
normalizeWorkerDiagnostic
|
|
305
|
-
} from "./chunk-
|
|
314
|
+
} from "./chunk-PBRVUF5B.js";
|
|
306
315
|
import {
|
|
307
316
|
normalizeServeChannelSelection
|
|
308
317
|
} from "./chunk-ALMR3E6Q.js";
|
|
309
318
|
import "./chunk-HIBNSEJE.js";
|
|
310
|
-
import "./chunk-BKHCW2BI.js";
|
|
311
319
|
import {
|
|
312
320
|
redactLogCredentials
|
|
313
321
|
} from "./chunk-M5GB774H.js";
|
|
322
|
+
import "./chunk-BKHCW2BI.js";
|
|
314
323
|
import "./chunk-5HBA2Z7V.js";
|
|
315
324
|
import {
|
|
316
325
|
sanitizeLogText
|
|
317
|
-
} from "./chunk-
|
|
326
|
+
} from "./chunk-DX3RGJMS.js";
|
|
318
327
|
import "./chunk-UDXSXLER.js";
|
|
319
328
|
import {
|
|
320
329
|
getDialogSettingKeys,
|
|
@@ -325,23 +334,26 @@ import {
|
|
|
325
334
|
getWritableScopes,
|
|
326
335
|
loadSettings,
|
|
327
336
|
validateSettingValue
|
|
328
|
-
} from "./chunk-
|
|
337
|
+
} from "./chunk-JUWS2Z5K.js";
|
|
338
|
+
import "./chunk-7GOYZQPR.js";
|
|
329
339
|
import "./chunk-RKUWKYED.js";
|
|
330
340
|
import "./chunk-GOXKNSDZ.js";
|
|
331
341
|
import "./chunk-IDS7MSUP.js";
|
|
332
342
|
import {
|
|
333
|
-
SUPPORTED_LANGUAGES,
|
|
334
343
|
detectSystemLanguage,
|
|
335
|
-
resolveLanguageSetting
|
|
344
|
+
resolveLanguageSetting
|
|
345
|
+
} from "./chunk-WP5VOXF7.js";
|
|
346
|
+
import {
|
|
347
|
+
SUPPORTED_LANGUAGES,
|
|
336
348
|
resolveSupportedLanguage
|
|
337
|
-
} from "./chunk-
|
|
338
|
-
import "./chunk-
|
|
339
|
-
import "./chunk-
|
|
340
|
-
import "./chunk-
|
|
349
|
+
} from "./chunk-5EJZE3FP.js";
|
|
350
|
+
import "./chunk-T6HEQR2Q.js";
|
|
351
|
+
import "./chunk-VFMASYQA.js";
|
|
352
|
+
import "./chunk-IOEZE2YT.js";
|
|
341
353
|
import "./chunk-VJNBRRZG.js";
|
|
342
354
|
import {
|
|
343
355
|
getWorkspaceTrustStatus
|
|
344
|
-
} from "./chunk-
|
|
356
|
+
} from "./chunk-ZOSTTOUJ.js";
|
|
345
357
|
import "./chunk-NPQ5ZKRP.js";
|
|
346
358
|
import {
|
|
347
359
|
isWithinRoot as isWithinRoot2
|
|
@@ -421,7 +433,7 @@ import {
|
|
|
421
433
|
writeWorkspaceContextFile,
|
|
422
434
|
writeWorktreeSession,
|
|
423
435
|
writeWorktreeSessionMarker
|
|
424
|
-
} from "./chunk-
|
|
436
|
+
} from "./chunk-XX7QFP34.js";
|
|
425
437
|
import "./chunk-GOFAQQZA.js";
|
|
426
438
|
import "./chunk-5M6IDOMF.js";
|
|
427
439
|
import "./chunk-TWPJO254.js";
|
|
@@ -434,7 +446,7 @@ import "./chunk-MVUQRLOH.js";
|
|
|
434
446
|
import "./chunk-XCWO3SMQ.js";
|
|
435
447
|
import "./chunk-7MH4J33A.js";
|
|
436
448
|
import "./chunk-6PVPNMXU.js";
|
|
437
|
-
import "./chunk-
|
|
449
|
+
import "./chunk-K4ADGWHU.js";
|
|
438
450
|
import {
|
|
439
451
|
nextFireTime,
|
|
440
452
|
parseCron
|
|
@@ -462,7 +474,7 @@ import "./chunk-67N6HB5H.js";
|
|
|
462
474
|
import {
|
|
463
475
|
APPROVAL_MODES
|
|
464
476
|
} from "./chunk-WAUGQKUU.js";
|
|
465
|
-
import "./chunk-
|
|
477
|
+
import "./chunk-DZUO626D.js";
|
|
466
478
|
import {
|
|
467
479
|
addDaemonRequestAttribute,
|
|
468
480
|
captureDaemonTelemetryContext,
|
|
@@ -474,7 +486,7 @@ import {
|
|
|
474
486
|
recordDaemonHttpResponse,
|
|
475
487
|
runWithDaemonTelemetryContext,
|
|
476
488
|
withDaemonRequestSpan
|
|
477
|
-
} from "./chunk-
|
|
489
|
+
} from "./chunk-4TRQPFDP.js";
|
|
478
490
|
import "./chunk-SAH4BD2J.js";
|
|
479
491
|
import "./chunk-CPG6P4GG.js";
|
|
480
492
|
import "./chunk-S6LOFUVP.js";
|
|
@@ -521,23 +533,23 @@ import {
|
|
|
521
533
|
isWithinRoot,
|
|
522
534
|
parseLineTolerant,
|
|
523
535
|
read
|
|
524
|
-
} from "./chunk-
|
|
536
|
+
} from "./chunk-YGT2AUJ7.js";
|
|
525
537
|
import "./chunk-WOJZWRAZ.js";
|
|
526
538
|
import "./chunk-VGC4I5JJ.js";
|
|
527
539
|
import "./chunk-FVKHVJZQ.js";
|
|
528
540
|
import "./chunk-COBO5EBO.js";
|
|
529
541
|
import "./chunk-6ZRFAKXK.js";
|
|
530
542
|
import "./chunk-PYQADEFD.js";
|
|
531
|
-
import "./chunk-
|
|
543
|
+
import "./chunk-PVOGHGSF.js";
|
|
532
544
|
import "./chunk-F6WFNA7U.js";
|
|
533
545
|
import "./chunk-46UV252V.js";
|
|
534
546
|
import "./chunk-ZBVS26BY.js";
|
|
535
547
|
import "./chunk-KKBPOU75.js";
|
|
536
548
|
import "./chunk-EUNWC2VS.js";
|
|
537
549
|
import "./chunk-FOGU3LJX.js";
|
|
538
|
-
import "./chunk-
|
|
550
|
+
import "./chunk-L2AFWWJE.js";
|
|
539
551
|
import "./chunk-W4RQUHY3.js";
|
|
540
|
-
import "./chunk-
|
|
552
|
+
import "./chunk-PDPFQ2FO.js";
|
|
541
553
|
import {
|
|
542
554
|
FatalConfigError,
|
|
543
555
|
Storage,
|
|
@@ -1225,26 +1237,165 @@ function createWorkspaceFileSystemFactory(deps) {
|
|
|
1225
1237
|
});
|
|
1226
1238
|
const lowFs = new StandardFileSystemService();
|
|
1227
1239
|
const pathLocks = deps.pathLocks ?? new PathMutexRegistry();
|
|
1240
|
+
const forRequest = /* @__PURE__ */ __name((ctx) => new WorkspaceFileSystemImpl({
|
|
1241
|
+
primaryWorkspace,
|
|
1242
|
+
workspaces,
|
|
1243
|
+
trusted: deps.trusted,
|
|
1244
|
+
audit,
|
|
1245
|
+
ctx,
|
|
1246
|
+
lowFs,
|
|
1247
|
+
pathLocks,
|
|
1248
|
+
generationGuard: deps.generationGuard
|
|
1249
|
+
}), "forRequest");
|
|
1228
1250
|
return {
|
|
1229
1251
|
assertCanWrite() {
|
|
1230
1252
|
deps.generationGuard?.assertOpen();
|
|
1231
1253
|
assertTrustedForIntent(deps.trusted, "write");
|
|
1232
1254
|
},
|
|
1233
|
-
forRequest
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
audit,
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1255
|
+
forRequest,
|
|
1256
|
+
async writeSameHostToolText(ctx, request2) {
|
|
1257
|
+
try {
|
|
1258
|
+
deps.generationGuard?.assertOpen();
|
|
1259
|
+
} catch (err) {
|
|
1260
|
+
throw recordSameHostToolWriteDenied(audit, ctx, request2.path, err);
|
|
1261
|
+
}
|
|
1262
|
+
let resolved;
|
|
1263
|
+
try {
|
|
1264
|
+
resolved = await resolveWithinWorkspace(
|
|
1265
|
+
request2.path,
|
|
1266
|
+
workspaces.map((workspace) => workspace.path),
|
|
1267
|
+
"write"
|
|
1268
|
+
);
|
|
1269
|
+
deps.generationGuard?.assertOpen();
|
|
1270
|
+
} catch (err) {
|
|
1271
|
+
if (!(err instanceof FsError && err.kind === "path_outside_workspace")) {
|
|
1272
|
+
throw recordSameHostToolWriteDenied(audit, ctx, request2.path, err);
|
|
1273
|
+
}
|
|
1274
|
+
try {
|
|
1275
|
+
await writeSameHostToolTextOutsideWorkspace({
|
|
1276
|
+
request: request2,
|
|
1277
|
+
trusted: deps.trusted,
|
|
1278
|
+
audit,
|
|
1279
|
+
ctx,
|
|
1280
|
+
pathLocks,
|
|
1281
|
+
generationGuard: deps.generationGuard
|
|
1282
|
+
});
|
|
1283
|
+
return;
|
|
1284
|
+
} catch (outsideErr) {
|
|
1285
|
+
throw recordSameHostToolWriteDenied(
|
|
1286
|
+
audit,
|
|
1287
|
+
ctx,
|
|
1288
|
+
request2.path,
|
|
1289
|
+
outsideErr
|
|
1290
|
+
);
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
1293
|
+
try {
|
|
1294
|
+
await forRequest(ctx).writeTextOverwrite(resolved, request2.content);
|
|
1295
|
+
} catch (err) {
|
|
1296
|
+
if (isWorkspaceGenerationClosedError(err)) {
|
|
1297
|
+
recordSameHostToolWriteDenied(audit, ctx, request2.path, err);
|
|
1298
|
+
}
|
|
1299
|
+
throw err;
|
|
1300
|
+
}
|
|
1244
1301
|
}
|
|
1245
1302
|
};
|
|
1246
1303
|
}
|
|
1247
1304
|
__name(createWorkspaceFileSystemFactory, "createWorkspaceFileSystemFactory");
|
|
1305
|
+
async function writeSameHostToolTextOutsideWorkspace(deps) {
|
|
1306
|
+
const start = performance.now();
|
|
1307
|
+
deps.generationGuard?.assertOpen();
|
|
1308
|
+
assertTrustedForIntent(deps.trusted, "write");
|
|
1309
|
+
enforceWriteSize(Buffer.byteLength(deps.request.content, "utf-8"));
|
|
1310
|
+
const target = await resolveSameHostToolWriteTarget(deps.request.path);
|
|
1311
|
+
await deps.pathLocks.runExclusive(target, async () => {
|
|
1312
|
+
deps.generationGuard?.assertOpen();
|
|
1313
|
+
const meta = mergeWriteMeta(void 0, deps.request.meta ?? {});
|
|
1314
|
+
const content = meta.bom && deps.request.content.charCodeAt(0) === 65279 ? deps.request.content.slice(1) : deps.request.content;
|
|
1315
|
+
const result = await atomicWriteTextResolvedFile({
|
|
1316
|
+
target,
|
|
1317
|
+
content,
|
|
1318
|
+
mode: "overwrite",
|
|
1319
|
+
meta,
|
|
1320
|
+
assertGenerationOpen: /* @__PURE__ */ __name(() => deps.generationGuard?.assertOpen(), "assertGenerationOpen")
|
|
1321
|
+
});
|
|
1322
|
+
deps.audit.recordAccess(deps.ctx, {
|
|
1323
|
+
intent: "write",
|
|
1324
|
+
absolute: target,
|
|
1325
|
+
durationMs: performance.now() - start,
|
|
1326
|
+
sizeBytes: result.sizeBytes
|
|
1327
|
+
});
|
|
1328
|
+
});
|
|
1329
|
+
}
|
|
1330
|
+
__name(writeSameHostToolTextOutsideWorkspace, "writeSameHostToolTextOutsideWorkspace");
|
|
1331
|
+
async function resolveSameHostToolWriteTarget(input) {
|
|
1332
|
+
if (!path4.isAbsolute(input)) {
|
|
1333
|
+
throw new FsError(
|
|
1334
|
+
"path_outside_workspace",
|
|
1335
|
+
`same-host external tool write requires an absolute path: ${input}`
|
|
1336
|
+
);
|
|
1337
|
+
}
|
|
1338
|
+
if (hasSuspiciousPathPattern(input)) {
|
|
1339
|
+
throw new FsError(
|
|
1340
|
+
"path_outside_workspace",
|
|
1341
|
+
`path contains suspicious pattern: ${input}`
|
|
1342
|
+
);
|
|
1343
|
+
}
|
|
1344
|
+
let leaf;
|
|
1345
|
+
try {
|
|
1346
|
+
leaf = await fsp2.lstat(input);
|
|
1347
|
+
} catch (err) {
|
|
1348
|
+
if (err?.code !== "ENOENT") {
|
|
1349
|
+
throw err;
|
|
1350
|
+
}
|
|
1351
|
+
const parent = await fsp2.realpath(path4.dirname(input));
|
|
1352
|
+
const parentStat = await fsp2.lstat(parent);
|
|
1353
|
+
if (!parentStat.isDirectory()) {
|
|
1354
|
+
throw new FsError(
|
|
1355
|
+
"parse_error",
|
|
1356
|
+
`parent path is not a directory: ${parent}`
|
|
1357
|
+
);
|
|
1358
|
+
}
|
|
1359
|
+
return path4.join(parent, path4.basename(input));
|
|
1360
|
+
}
|
|
1361
|
+
if (leaf.isSymbolicLink()) {
|
|
1362
|
+
throw new FsError(
|
|
1363
|
+
"symlink_escape",
|
|
1364
|
+
`path is a symlink and cannot be overwritten: ${input}`,
|
|
1365
|
+
{ hint: "resolve the target explicitly before writing" }
|
|
1366
|
+
);
|
|
1367
|
+
}
|
|
1368
|
+
if (!leaf.isFile()) {
|
|
1369
|
+
throw new FsError("parse_error", `path is not a regular file: ${input}`);
|
|
1370
|
+
}
|
|
1371
|
+
const canonical = await fsp2.realpath(input);
|
|
1372
|
+
const canonicalStat = await fsp2.lstat(canonical);
|
|
1373
|
+
if (!canonicalStat.isFile()) {
|
|
1374
|
+
throw new FsError(
|
|
1375
|
+
"parse_error",
|
|
1376
|
+
`canonical path is not a regular file: ${canonical}`
|
|
1377
|
+
);
|
|
1378
|
+
}
|
|
1379
|
+
assertSameFile(leaf, canonicalStat, input, "write");
|
|
1380
|
+
return canonical;
|
|
1381
|
+
}
|
|
1382
|
+
__name(resolveSameHostToolWriteTarget, "resolveSameHostToolWriteTarget");
|
|
1383
|
+
function isWorkspaceGenerationClosedError(error2) {
|
|
1384
|
+
return error2 instanceof Error && "code" in error2 && error2.code === "workspace_generation_closed";
|
|
1385
|
+
}
|
|
1386
|
+
__name(isWorkspaceGenerationClosedError, "isWorkspaceGenerationClosedError");
|
|
1387
|
+
function recordSameHostToolWriteDenied(audit, ctx, input, error2) {
|
|
1388
|
+
const fsError = wrapAsFsError(error2);
|
|
1389
|
+
audit.recordDenied(ctx, {
|
|
1390
|
+
intent: "write",
|
|
1391
|
+
input,
|
|
1392
|
+
errorKind: fsError.kind,
|
|
1393
|
+
hint: fsError.hint,
|
|
1394
|
+
message: fsError.message
|
|
1395
|
+
});
|
|
1396
|
+
return isWorkspaceGenerationClosedError(error2) && error2 instanceof Error ? error2 : fsError;
|
|
1397
|
+
}
|
|
1398
|
+
__name(recordSameHostToolWriteDenied, "recordSameHostToolWriteDenied");
|
|
1248
1399
|
function assertNoNestedWorkspaces(workspaces) {
|
|
1249
1400
|
for (let i = 0; i < workspaces.length; i++) {
|
|
1250
1401
|
const a = workspaces[i];
|
|
@@ -5168,6 +5319,214 @@ function mountWorkspaceQualifiedMemoryRememberRoutes(app, deps) {
|
|
|
5168
5319
|
}
|
|
5169
5320
|
__name(mountWorkspaceQualifiedMemoryRememberRoutes, "mountWorkspaceQualifiedMemoryRememberRoutes");
|
|
5170
5321
|
|
|
5322
|
+
// packages/cli/src/serve/session-id-admission.ts
|
|
5323
|
+
init_esbuild_shims();
|
|
5324
|
+
import { access } from "node:fs/promises";
|
|
5325
|
+
var RequestedSessionIdAdmissionError = class extends Error {
|
|
5326
|
+
constructor(code, sessionId, message, details = {}) {
|
|
5327
|
+
super(message);
|
|
5328
|
+
this.code = code;
|
|
5329
|
+
this.sessionId = sessionId;
|
|
5330
|
+
this.details = details;
|
|
5331
|
+
}
|
|
5332
|
+
static {
|
|
5333
|
+
__name(this, "RequestedSessionIdAdmissionError");
|
|
5334
|
+
}
|
|
5335
|
+
name = "RequestedSessionIdAdmissionError";
|
|
5336
|
+
};
|
|
5337
|
+
async function persistedSessionExists(sessionService, sessionId) {
|
|
5338
|
+
if (await sessionService.getSessionLocation(sessionId) !== void 0) {
|
|
5339
|
+
return true;
|
|
5340
|
+
}
|
|
5341
|
+
if (await sessionService.findSessionIdIgnoringCase?.(sessionId) !== void 0) {
|
|
5342
|
+
return true;
|
|
5343
|
+
}
|
|
5344
|
+
for (const state of ["active", "archived"]) {
|
|
5345
|
+
try {
|
|
5346
|
+
await access(
|
|
5347
|
+
sessionService.getWorktreeSessionPathForArchiveState(sessionId, state)
|
|
5348
|
+
);
|
|
5349
|
+
return true;
|
|
5350
|
+
} catch (error2) {
|
|
5351
|
+
if (error2.code !== "ENOENT") throw error2;
|
|
5352
|
+
}
|
|
5353
|
+
}
|
|
5354
|
+
return false;
|
|
5355
|
+
}
|
|
5356
|
+
__name(persistedSessionExists, "persistedSessionExists");
|
|
5357
|
+
function createRequestedSessionIdAdmission({
|
|
5358
|
+
archiveCoordinator,
|
|
5359
|
+
getBridges,
|
|
5360
|
+
getPersistenceTargets,
|
|
5361
|
+
getBridgeWorkspaceId
|
|
5362
|
+
}) {
|
|
5363
|
+
const pending = /* @__PURE__ */ new Map();
|
|
5364
|
+
const liveOwners = /* @__PURE__ */ __name((sessionId) => {
|
|
5365
|
+
const owners = [];
|
|
5366
|
+
let bridges;
|
|
5367
|
+
try {
|
|
5368
|
+
bridges = getBridges();
|
|
5369
|
+
} catch {
|
|
5370
|
+
throw new RequestedSessionIdAdmissionError(
|
|
5371
|
+
"session_id_admission_unavailable",
|
|
5372
|
+
sessionId,
|
|
5373
|
+
`Unable to enumerate live bridges for session "${sessionId}".`,
|
|
5374
|
+
{ retryable: true }
|
|
5375
|
+
);
|
|
5376
|
+
}
|
|
5377
|
+
for (const bridge of new Set(bridges)) {
|
|
5378
|
+
try {
|
|
5379
|
+
const summary = bridge.getSessionSummary(sessionId);
|
|
5380
|
+
owners.push({
|
|
5381
|
+
bridge,
|
|
5382
|
+
workspaceCwd: summary.workspaceCwd,
|
|
5383
|
+
workspaceId: getBridgeWorkspaceId?.(bridge)
|
|
5384
|
+
});
|
|
5385
|
+
} catch (error2) {
|
|
5386
|
+
if (error2 instanceof SessionNotFoundError) continue;
|
|
5387
|
+
throw new RequestedSessionIdAdmissionError(
|
|
5388
|
+
"session_id_admission_unavailable",
|
|
5389
|
+
sessionId,
|
|
5390
|
+
`Unable to verify whether session "${sessionId}" is already live.`,
|
|
5391
|
+
{ retryable: true }
|
|
5392
|
+
);
|
|
5393
|
+
}
|
|
5394
|
+
}
|
|
5395
|
+
return owners;
|
|
5396
|
+
}, "liveOwners");
|
|
5397
|
+
const conflict = /* @__PURE__ */ __name((sessionId, conflictKind, workspaceCwd) => new RequestedSessionIdAdmissionError(
|
|
5398
|
+
"session_id_conflict",
|
|
5399
|
+
sessionId,
|
|
5400
|
+
`Session "${sessionId}" already exists or is being created.`,
|
|
5401
|
+
{
|
|
5402
|
+
conflict: conflictKind,
|
|
5403
|
+
...workspaceCwd ? { liveWorkspaceCwd: workspaceCwd } : {}
|
|
5404
|
+
}
|
|
5405
|
+
), "conflict");
|
|
5406
|
+
const workspaceConflict = /* @__PURE__ */ __name((sessionId, target, conflictKind, liveWorkspaceCwd, liveWorkspaceId) => new RequestedSessionIdAdmissionError(
|
|
5407
|
+
"session_workspace_conflict",
|
|
5408
|
+
sessionId,
|
|
5409
|
+
`Session "${sessionId}" is already live or restoring in another workspace runtime.`,
|
|
5410
|
+
{
|
|
5411
|
+
conflict: conflictKind,
|
|
5412
|
+
workspaceCwd: target.workspaceCwd,
|
|
5413
|
+
...target.workspaceId ? { workspaceId: target.workspaceId } : {},
|
|
5414
|
+
...liveWorkspaceCwd ? { liveWorkspaceCwd } : {},
|
|
5415
|
+
...liveWorkspaceId ? { liveWorkspaceId } : {}
|
|
5416
|
+
}
|
|
5417
|
+
), "workspaceConflict");
|
|
5418
|
+
const createReservation = /* @__PURE__ */ __name((sessionId, state) => {
|
|
5419
|
+
let released = false;
|
|
5420
|
+
return {
|
|
5421
|
+
release() {
|
|
5422
|
+
if (released) return;
|
|
5423
|
+
released = true;
|
|
5424
|
+
if (pending.get(sessionId) !== state) return;
|
|
5425
|
+
if (state.kind === "restore" && state.count > 1) {
|
|
5426
|
+
state.count--;
|
|
5427
|
+
return;
|
|
5428
|
+
}
|
|
5429
|
+
pending.delete(sessionId);
|
|
5430
|
+
}
|
|
5431
|
+
};
|
|
5432
|
+
}, "createReservation");
|
|
5433
|
+
return {
|
|
5434
|
+
async reserveCreate(rawSessionId, target) {
|
|
5435
|
+
const sessionId = normalizeSessionIdForLookup(rawSessionId);
|
|
5436
|
+
const live = liveOwners(sessionId)[0];
|
|
5437
|
+
if (live) throw conflict(sessionId, "live", live.workspaceCwd);
|
|
5438
|
+
if (pending.has(sessionId)) throw conflict(sessionId, "pending");
|
|
5439
|
+
const state = { kind: "create", target };
|
|
5440
|
+
pending.set(sessionId, state);
|
|
5441
|
+
const reservation = createReservation(sessionId, state);
|
|
5442
|
+
try {
|
|
5443
|
+
let persisted;
|
|
5444
|
+
try {
|
|
5445
|
+
persisted = await archiveCoordinator.runSharedMany(
|
|
5446
|
+
[sessionId],
|
|
5447
|
+
async () => {
|
|
5448
|
+
const targets = [
|
|
5449
|
+
...new Map(
|
|
5450
|
+
getPersistenceTargets().map((entry) => [
|
|
5451
|
+
`${entry.runtimeBaseDir}\0${entry.workspaceCwd}`,
|
|
5452
|
+
entry
|
|
5453
|
+
])
|
|
5454
|
+
).values()
|
|
5455
|
+
];
|
|
5456
|
+
const results = await Promise.all(
|
|
5457
|
+
targets.map(async (entry) => {
|
|
5458
|
+
const sessionService = new SessionService(
|
|
5459
|
+
entry.workspaceCwd,
|
|
5460
|
+
{ runtimeBaseDir: entry.runtimeBaseDir }
|
|
5461
|
+
);
|
|
5462
|
+
return {
|
|
5463
|
+
entry,
|
|
5464
|
+
exists: await persistedSessionExists(
|
|
5465
|
+
sessionService,
|
|
5466
|
+
sessionId
|
|
5467
|
+
)
|
|
5468
|
+
};
|
|
5469
|
+
})
|
|
5470
|
+
);
|
|
5471
|
+
return results.find((result) => result.exists)?.entry;
|
|
5472
|
+
}
|
|
5473
|
+
);
|
|
5474
|
+
} catch {
|
|
5475
|
+
throw new RequestedSessionIdAdmissionError(
|
|
5476
|
+
"session_id_admission_unavailable",
|
|
5477
|
+
sessionId,
|
|
5478
|
+
`Unable to verify persisted state for session "${sessionId}".`,
|
|
5479
|
+
{ retryable: true }
|
|
5480
|
+
);
|
|
5481
|
+
}
|
|
5482
|
+
if (persisted) {
|
|
5483
|
+
throw conflict(sessionId, "persisted", persisted.workspaceCwd);
|
|
5484
|
+
}
|
|
5485
|
+
return reservation;
|
|
5486
|
+
} catch (error2) {
|
|
5487
|
+
reservation.release();
|
|
5488
|
+
throw error2;
|
|
5489
|
+
}
|
|
5490
|
+
},
|
|
5491
|
+
reserveRestore(rawSessionId, target) {
|
|
5492
|
+
const sessionId = normalizeSessionIdForLookup(rawSessionId);
|
|
5493
|
+
const foreignLive = liveOwners(sessionId).find(
|
|
5494
|
+
(owner) => owner.bridge !== target.bridge
|
|
5495
|
+
);
|
|
5496
|
+
if (foreignLive) {
|
|
5497
|
+
throw workspaceConflict(
|
|
5498
|
+
sessionId,
|
|
5499
|
+
target,
|
|
5500
|
+
"live",
|
|
5501
|
+
foreignLive.workspaceCwd,
|
|
5502
|
+
foreignLive.workspaceId
|
|
5503
|
+
);
|
|
5504
|
+
}
|
|
5505
|
+
const existing = pending.get(sessionId);
|
|
5506
|
+
if (existing?.kind === "create") {
|
|
5507
|
+
throw conflict(sessionId, "pending");
|
|
5508
|
+
}
|
|
5509
|
+
if (existing?.kind === "restore") {
|
|
5510
|
+
if (existing.target.bridge !== target.bridge) {
|
|
5511
|
+
throw workspaceConflict(
|
|
5512
|
+
sessionId,
|
|
5513
|
+
target,
|
|
5514
|
+
"pending",
|
|
5515
|
+
existing.target.workspaceCwd,
|
|
5516
|
+
existing.target.workspaceId
|
|
5517
|
+
);
|
|
5518
|
+
}
|
|
5519
|
+
existing.count++;
|
|
5520
|
+
return createReservation(sessionId, existing);
|
|
5521
|
+
}
|
|
5522
|
+
const state = { kind: "restore", target, count: 1 };
|
|
5523
|
+
pending.set(sessionId, state);
|
|
5524
|
+
return createReservation(sessionId, state);
|
|
5525
|
+
}
|
|
5526
|
+
};
|
|
5527
|
+
}
|
|
5528
|
+
__name(createRequestedSessionIdAdmission, "createRequestedSessionIdAdmission");
|
|
5529
|
+
|
|
5171
5530
|
// packages/cli/src/serve/workspace-memory.ts
|
|
5172
5531
|
init_esbuild_shims();
|
|
5173
5532
|
import { promises as fs2 } from "node:fs";
|
|
@@ -8215,6 +8574,9 @@ var TRUSTED_WORKSPACE_METHODS = /* @__PURE__ */ new Set([
|
|
|
8215
8574
|
`${QWEN_METHOD_NS}workspace/session_groups/delete`
|
|
8216
8575
|
]);
|
|
8217
8576
|
var WORKSPACE_GENERATION_MUTATION_METHODS = /* @__PURE__ */ new Set([
|
|
8577
|
+
"session/new",
|
|
8578
|
+
"session/load",
|
|
8579
|
+
"session/resume",
|
|
8218
8580
|
`${QWEN_METHOD_NS}workspace/init`,
|
|
8219
8581
|
`${QWEN_METHOD_NS}workspace/trust/request`,
|
|
8220
8582
|
`${QWEN_METHOD_NS}workspace/permissions/set`,
|
|
@@ -8263,6 +8625,23 @@ var AcpParamError = class extends Error {
|
|
|
8263
8625
|
__name(this, "AcpParamError");
|
|
8264
8626
|
}
|
|
8265
8627
|
};
|
|
8628
|
+
var InvalidRequestedSessionIdError = class extends Error {
|
|
8629
|
+
static {
|
|
8630
|
+
__name(this, "InvalidRequestedSessionIdError");
|
|
8631
|
+
}
|
|
8632
|
+
};
|
|
8633
|
+
var RequestedSessionIdNotHonoredError = class extends Error {
|
|
8634
|
+
constructor(requestedSessionId, actualSessionId) {
|
|
8635
|
+
super(
|
|
8636
|
+
`The ACP agent returned session "${actualSessionId}" instead of requested session "${requestedSessionId}".`
|
|
8637
|
+
);
|
|
8638
|
+
this.requestedSessionId = requestedSessionId;
|
|
8639
|
+
this.actualSessionId = actualSessionId;
|
|
8640
|
+
}
|
|
8641
|
+
static {
|
|
8642
|
+
__name(this, "RequestedSessionIdNotHonoredError");
|
|
8643
|
+
}
|
|
8644
|
+
};
|
|
8266
8645
|
function parseOptionalPositiveInteger(value, fallback, max) {
|
|
8267
8646
|
if (value === void 0) return fallback;
|
|
8268
8647
|
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 1 || value > max) {
|
|
@@ -8373,6 +8752,38 @@ function pickSessionArtifactInput(params) {
|
|
|
8373
8752
|
}
|
|
8374
8753
|
__name(pickSessionArtifactInput, "pickSessionArtifactInput");
|
|
8375
8754
|
function toRpcError(err) {
|
|
8755
|
+
if (err instanceof InvalidRequestedSessionIdError) {
|
|
8756
|
+
return {
|
|
8757
|
+
code: RPC.INVALID_PARAMS,
|
|
8758
|
+
message: err.message,
|
|
8759
|
+
data: { httpStatus: 400, errorKind: "invalid_session_id" }
|
|
8760
|
+
};
|
|
8761
|
+
}
|
|
8762
|
+
if (err instanceof RequestedSessionIdAdmissionError) {
|
|
8763
|
+
const unavailable = err.code === "session_id_admission_unavailable";
|
|
8764
|
+
return {
|
|
8765
|
+
code: unavailable ? RPC.INTERNAL_ERROR : RPC.INVALID_PARAMS,
|
|
8766
|
+
message: err.message,
|
|
8767
|
+
data: {
|
|
8768
|
+
httpStatus: unavailable ? 503 : 409,
|
|
8769
|
+
errorKind: err.code,
|
|
8770
|
+
sessionId: err.sessionId,
|
|
8771
|
+
...err.details
|
|
8772
|
+
}
|
|
8773
|
+
};
|
|
8774
|
+
}
|
|
8775
|
+
if (err instanceof RequestedSessionIdNotHonoredError) {
|
|
8776
|
+
return {
|
|
8777
|
+
code: RPC.INTERNAL_ERROR,
|
|
8778
|
+
message: err.message,
|
|
8779
|
+
data: {
|
|
8780
|
+
httpStatus: 500,
|
|
8781
|
+
errorKind: "session_id_not_honored",
|
|
8782
|
+
requestedSessionId: err.requestedSessionId,
|
|
8783
|
+
actualSessionId: err.actualSessionId
|
|
8784
|
+
}
|
|
8785
|
+
};
|
|
8786
|
+
}
|
|
8376
8787
|
if (err instanceof DaemonDrainingError) {
|
|
8377
8788
|
return {
|
|
8378
8789
|
code: RPC.INTERNAL_ERROR,
|
|
@@ -8495,6 +8906,56 @@ function toRpcError(err) {
|
|
|
8495
8906
|
}
|
|
8496
8907
|
const name = err instanceof Error ? err.name : "";
|
|
8497
8908
|
switch (name) {
|
|
8909
|
+
case "SessionRestoreTimeoutError": {
|
|
8910
|
+
const restoreError = err;
|
|
8911
|
+
return {
|
|
8912
|
+
code: RPC.INTERNAL_ERROR,
|
|
8913
|
+
message: restoreError.message,
|
|
8914
|
+
data: {
|
|
8915
|
+
code: "session_restore_timeout",
|
|
8916
|
+
errorKind: "restore_timeout",
|
|
8917
|
+
httpStatus: 504,
|
|
8918
|
+
retryable: true,
|
|
8919
|
+
retryAfterSeconds: restoreRetryAfterSeconds(restoreError.timeoutMs),
|
|
8920
|
+
sessionId: restoreError.sessionId,
|
|
8921
|
+
action: restoreError.action,
|
|
8922
|
+
timeoutMs: restoreError.timeoutMs
|
|
8923
|
+
}
|
|
8924
|
+
};
|
|
8925
|
+
}
|
|
8926
|
+
case "RestoreInProgressError": {
|
|
8927
|
+
const fenceError = err;
|
|
8928
|
+
return {
|
|
8929
|
+
code: RPC.INTERNAL_ERROR,
|
|
8930
|
+
message: fenceError.message,
|
|
8931
|
+
data: {
|
|
8932
|
+
code: "restore_in_progress",
|
|
8933
|
+
errorKind: "restore_in_progress",
|
|
8934
|
+
httpStatus: 409,
|
|
8935
|
+
retryable: true,
|
|
8936
|
+
reason: fenceError.reason,
|
|
8937
|
+
retryAfterSeconds: fenceError.retryAfterSeconds,
|
|
8938
|
+
sessionId: fenceError.sessionId,
|
|
8939
|
+
activeAction: fenceError.activeAction,
|
|
8940
|
+
requestedAction: fenceError.requestedAction
|
|
8941
|
+
}
|
|
8942
|
+
};
|
|
8943
|
+
}
|
|
8944
|
+
case "BridgeChannelQuarantinedError": {
|
|
8945
|
+
const unavailableError = err;
|
|
8946
|
+
return {
|
|
8947
|
+
code: RPC.INTERNAL_ERROR,
|
|
8948
|
+
message: unavailableError.message,
|
|
8949
|
+
data: {
|
|
8950
|
+
code: "acp_channel_unavailable",
|
|
8951
|
+
errorKind: "acp_channel_unavailable",
|
|
8952
|
+
httpStatus: 503,
|
|
8953
|
+
retryable: true,
|
|
8954
|
+
reason: unavailableError.reason,
|
|
8955
|
+
retryAfterSeconds: unavailableError.retryAfterSeconds
|
|
8956
|
+
}
|
|
8957
|
+
};
|
|
8958
|
+
}
|
|
8498
8959
|
case "SessionArchivedError":
|
|
8499
8960
|
return {
|
|
8500
8961
|
code: RPC.INTERNAL_ERROR,
|
|
@@ -8588,12 +9049,16 @@ function rpcErrorFrame(id, err) {
|
|
|
8588
9049
|
__name(rpcErrorFrame, "rpcErrorFrame");
|
|
8589
9050
|
var ACP_PROTOCOL_VERSION = 1;
|
|
8590
9051
|
var AcpDispatcher = class {
|
|
8591
|
-
constructor(bridge, boundWorkspace, getEnv, workspace, workspaceRememberLane, fsFactory, deviceFlowRegistry, sessionShellCommandEnabled = false, registry, archiveCoordinator = new SessionArchiveCoordinator(), isWorkspaceTrusted = () => true, captureGenerationAssertion = () => void 0, liveSessionIsolation, sessionRuntimeBaseDir = Storage.getRuntimeBaseDir()) {
|
|
9052
|
+
constructor(bridge, boundWorkspace, getEnv, workspace, workspaceRememberLane, requestedSessionIdAdmission, fsFactory, deviceFlowRegistry, sessionShellCommandEnabled = false, registry, archiveCoordinator = new SessionArchiveCoordinator(), isWorkspaceTrusted = () => true, captureGenerationAssertion = () => void 0, liveSessionIsolation, sessionRuntimeBaseDir = Storage.getRuntimeBaseDir(), getSessionRuntimeContext = () => ({
|
|
9053
|
+
bridge,
|
|
9054
|
+
sessionRuntimeBaseDir
|
|
9055
|
+
})) {
|
|
8592
9056
|
this.bridge = bridge;
|
|
8593
9057
|
this.boundWorkspace = boundWorkspace;
|
|
8594
9058
|
this.getEnv = getEnv;
|
|
8595
9059
|
this.workspace = workspace;
|
|
8596
9060
|
this.workspaceRememberLane = workspaceRememberLane;
|
|
9061
|
+
this.requestedSessionIdAdmission = requestedSessionIdAdmission;
|
|
8597
9062
|
this.fsFactory = fsFactory;
|
|
8598
9063
|
this.deviceFlowRegistry = deviceFlowRegistry;
|
|
8599
9064
|
this.sessionShellCommandEnabled = sessionShellCommandEnabled;
|
|
@@ -8603,26 +9068,31 @@ var AcpDispatcher = class {
|
|
|
8603
9068
|
this.captureGenerationAssertion = captureGenerationAssertion;
|
|
8604
9069
|
this.liveSessionIsolation = liveSessionIsolation;
|
|
8605
9070
|
this.sessionRuntimeBaseDir = sessionRuntimeBaseDir;
|
|
9071
|
+
this.getSessionRuntimeContext = getSessionRuntimeContext;
|
|
8606
9072
|
this.agentManager = createDaemonSubagentManager(boundWorkspace);
|
|
8607
9073
|
}
|
|
8608
9074
|
static {
|
|
8609
9075
|
__name(this, "AcpDispatcher");
|
|
8610
9076
|
}
|
|
8611
9077
|
agentManager;
|
|
8612
|
-
|
|
9078
|
+
removeOrphanSession(sessionId, removePersistedSession = false, runtime = this.getSessionRuntimeContext()) {
|
|
8613
9079
|
const cleanup = removePersistedSession ? deleteDaemonSessionIfOrphan({
|
|
8614
9080
|
sessionId,
|
|
8615
9081
|
service: new SessionService(this.boundWorkspace, {
|
|
8616
|
-
runtimeBaseDir:
|
|
9082
|
+
runtimeBaseDir: runtime.sessionRuntimeBaseDir
|
|
8617
9083
|
}),
|
|
8618
|
-
bridge:
|
|
9084
|
+
bridge: runtime.bridge,
|
|
8619
9085
|
coordinator: this.archiveCoordinator
|
|
8620
|
-
}) :
|
|
8621
|
-
|
|
8622
|
-
|
|
9086
|
+
}) : runtime.bridge.killSession(sessionId, { requireZeroAttaches: true });
|
|
9087
|
+
return cleanup.catch((err) => {
|
|
9088
|
+
writeStderrLine(
|
|
8623
9089
|
`qwen serve: /acp orphan killSession(${logSafe(sessionId)}) failed: ${logSafe(errMsg(err))}`
|
|
8624
|
-
)
|
|
8625
|
-
|
|
9090
|
+
);
|
|
9091
|
+
return void 0;
|
|
9092
|
+
});
|
|
9093
|
+
}
|
|
9094
|
+
killOrphanSession(sessionId, removePersistedSession = false, runtime) {
|
|
9095
|
+
void this.removeOrphanSession(sessionId, removePersistedSession, runtime);
|
|
8626
9096
|
}
|
|
8627
9097
|
/**
|
|
8628
9098
|
* Build the `WorkspaceRequestContext` for workspace-scoped operations
|
|
@@ -8726,9 +9196,9 @@ var AcpDispatcher = class {
|
|
|
8726
9196
|
* child's own session state. Returned in `session/new` and as the result
|
|
8727
9197
|
* of `session/set_config_option`. Best-effort — `undefined` on error.
|
|
8728
9198
|
*/
|
|
8729
|
-
async configOptionsFor(sessionId) {
|
|
9199
|
+
async configOptionsFor(sessionId, bridge = this.bridge) {
|
|
8730
9200
|
try {
|
|
8731
|
-
const ctx = await
|
|
9201
|
+
const ctx = await bridge.getSessionContextStatus(sessionId);
|
|
8732
9202
|
const co = ctx?.state?.configOptions;
|
|
8733
9203
|
return Array.isArray(co) ? co : void 0;
|
|
8734
9204
|
} catch (err) {
|
|
@@ -8922,7 +9392,13 @@ var AcpDispatcher = class {
|
|
|
8922
9392
|
}
|
|
8923
9393
|
if (!isRequest(msg) && !isNotification(msg)) return;
|
|
8924
9394
|
const method = msg.method;
|
|
8925
|
-
const params =
|
|
9395
|
+
const params = {
|
|
9396
|
+
...isObject(msg.params) ? msg.params : {}
|
|
9397
|
+
};
|
|
9398
|
+
if (typeof params["sessionId"] === "string") {
|
|
9399
|
+
params["sessionId"] = normalizeSessionIdForLookup(params["sessionId"]);
|
|
9400
|
+
}
|
|
9401
|
+
const normalizedSessionHeader = sessionHeader ? normalizeSessionIdForLookup(sessionHeader) : void 0;
|
|
8926
9402
|
const id = isRequest(msg) ? msg.id : void 0;
|
|
8927
9403
|
const generationScoped = TRUSTED_WORKSPACE_METHODS.has(method) || WORKSPACE_GENERATION_MUTATION_METHODS.has(method);
|
|
8928
9404
|
const assertGenerationOpen = generationScoped ? this.captureGenerationAssertion() : void 0;
|
|
@@ -8945,7 +9421,7 @@ var AcpDispatcher = class {
|
|
|
8945
9421
|
}
|
|
8946
9422
|
return;
|
|
8947
9423
|
}
|
|
8948
|
-
if (
|
|
9424
|
+
if (normalizedSessionHeader && typeof params["sessionId"] === "string" && params["sessionId"] !== normalizedSessionHeader) {
|
|
8949
9425
|
if (id !== void 0) {
|
|
8950
9426
|
conn.sendConn(
|
|
8951
9427
|
error(
|
|
@@ -8963,6 +9439,16 @@ var AcpDispatcher = class {
|
|
|
8963
9439
|
this.replyConn(conn, id, {});
|
|
8964
9440
|
return;
|
|
8965
9441
|
case "session/new": {
|
|
9442
|
+
const meta = isObject(params["_meta"]) ? params["_meta"] : void 0;
|
|
9443
|
+
const parsedSessionId = parseCallerSuppliedSessionId(
|
|
9444
|
+
meta?.[REQUESTED_SESSION_ID_META_KEY]
|
|
9445
|
+
);
|
|
9446
|
+
if (parsedSessionId.kind === "invalid") {
|
|
9447
|
+
throw new InvalidRequestedSessionIdError(
|
|
9448
|
+
`\`_meta["${REQUESTED_SESSION_ID_META_KEY}"]\` must be an RFC UUID v1-v5`
|
|
9449
|
+
);
|
|
9450
|
+
}
|
|
9451
|
+
const requestedSessionId = parsedSessionId.kind === "valid" ? parsedSessionId.sessionId : void 0;
|
|
8966
9452
|
const cwd = this.parseSessionWorkspaceCwd(params);
|
|
8967
9453
|
if (this.liveSessionIsolation) {
|
|
8968
9454
|
if (id !== void 0) {
|
|
@@ -8977,6 +9463,7 @@ var AcpDispatcher = class {
|
|
|
8977
9463
|
}
|
|
8978
9464
|
return;
|
|
8979
9465
|
}
|
|
9466
|
+
const sessionRuntime = this.getSessionRuntimeContext();
|
|
8980
9467
|
const source = parseSessionSource(
|
|
8981
9468
|
params["sourceType"],
|
|
8982
9469
|
params["sourceId"]
|
|
@@ -8999,39 +9486,89 @@ var AcpDispatcher = class {
|
|
|
8999
9486
|
}
|
|
9000
9487
|
return;
|
|
9001
9488
|
}
|
|
9002
|
-
const
|
|
9003
|
-
|
|
9004
|
-
|
|
9005
|
-
|
|
9006
|
-
|
|
9007
|
-
|
|
9008
|
-
|
|
9009
|
-
|
|
9010
|
-
|
|
9011
|
-
|
|
9012
|
-
|
|
9013
|
-
|
|
9014
|
-
|
|
9015
|
-
|
|
9016
|
-
|
|
9489
|
+
const reservation = requestedSessionId ? await this.requestedSessionIdAdmission.reserveCreate(
|
|
9490
|
+
requestedSessionId,
|
|
9491
|
+
{
|
|
9492
|
+
bridge: sessionRuntime.bridge,
|
|
9493
|
+
workspaceCwd: cwd,
|
|
9494
|
+
...sessionRuntime.workspaceId ? { workspaceId: sessionRuntime.workspaceId } : {}
|
|
9495
|
+
}
|
|
9496
|
+
) : void 0;
|
|
9497
|
+
try {
|
|
9498
|
+
assertGenerationOpen?.();
|
|
9499
|
+
const session = await sessionRuntime.bridge.spawnOrAttach({
|
|
9500
|
+
workspaceCwd: cwd,
|
|
9501
|
+
clientId: conn.clientId,
|
|
9502
|
+
sessionScope: "thread",
|
|
9503
|
+
...source,
|
|
9504
|
+
...requestedSessionId ? { sessionId: requestedSessionId } : {}
|
|
9505
|
+
});
|
|
9506
|
+
const rollbackSession = /* @__PURE__ */ __name(async () => {
|
|
9507
|
+
if (session.attached) {
|
|
9508
|
+
await sessionRuntime.bridge.detachClient(session.sessionId, session.clientId).catch(() => {
|
|
9509
|
+
});
|
|
9510
|
+
} else {
|
|
9511
|
+
await this.removeOrphanSession(
|
|
9512
|
+
session.sessionId,
|
|
9513
|
+
true,
|
|
9514
|
+
sessionRuntime
|
|
9515
|
+
);
|
|
9516
|
+
}
|
|
9517
|
+
}, "rollbackSession");
|
|
9518
|
+
try {
|
|
9519
|
+
assertGenerationOpen?.();
|
|
9520
|
+
} catch (error2) {
|
|
9521
|
+
await rollbackSession();
|
|
9522
|
+
throw error2;
|
|
9523
|
+
}
|
|
9524
|
+
if (requestedSessionId !== void 0 && session.sessionId !== requestedSessionId) {
|
|
9525
|
+
await rollbackSession();
|
|
9526
|
+
throw new RequestedSessionIdNotHonoredError(
|
|
9527
|
+
requestedSessionId,
|
|
9528
|
+
session.sessionId
|
|
9529
|
+
);
|
|
9530
|
+
}
|
|
9531
|
+
if (conn.destroyed) {
|
|
9532
|
+
this.killOrphanSession(session.sessionId, true, sessionRuntime);
|
|
9533
|
+
return;
|
|
9534
|
+
}
|
|
9535
|
+
const configOptions = await this.configOptionsFor(
|
|
9536
|
+
session.sessionId,
|
|
9537
|
+
sessionRuntime.bridge
|
|
9538
|
+
);
|
|
9539
|
+
try {
|
|
9540
|
+
assertGenerationOpen?.();
|
|
9541
|
+
} catch (error2) {
|
|
9542
|
+
await rollbackSession();
|
|
9543
|
+
throw error2;
|
|
9544
|
+
}
|
|
9545
|
+
if (conn.destroyed) {
|
|
9546
|
+
this.killOrphanSession(session.sessionId, true, sessionRuntime);
|
|
9547
|
+
return;
|
|
9548
|
+
}
|
|
9549
|
+
conn.getOrCreateSession(session.sessionId).clientId = session.clientId;
|
|
9550
|
+
conn.ownSession(session.sessionId);
|
|
9551
|
+
const models = this.extractModelState(configOptions);
|
|
9552
|
+
const modes = this.extractModeState(configOptions);
|
|
9553
|
+
this.replyConn(conn, id, {
|
|
9554
|
+
sessionId: session.sessionId,
|
|
9555
|
+
...session.sourceType ? { sourceType: session.sourceType } : {},
|
|
9556
|
+
...session.sourceId !== void 0 ? { sourceId: session.sourceId } : {},
|
|
9557
|
+
...session.sourcePersisted !== void 0 ? { sourcePersisted: session.sourcePersisted } : {},
|
|
9558
|
+
...configOptions ? { configOptions } : {},
|
|
9559
|
+
...models ? { models } : {},
|
|
9560
|
+
...modes ? { modes } : {}
|
|
9561
|
+
});
|
|
9017
9562
|
return;
|
|
9563
|
+
} finally {
|
|
9564
|
+
reservation?.release();
|
|
9018
9565
|
}
|
|
9019
|
-
const models = this.extractModelState(configOptions);
|
|
9020
|
-
const modes = this.extractModeState(configOptions);
|
|
9021
|
-
this.replyConn(conn, id, {
|
|
9022
|
-
sessionId: session.sessionId,
|
|
9023
|
-
...session.sourceType ? { sourceType: session.sourceType } : {},
|
|
9024
|
-
...session.sourceId !== void 0 ? { sourceId: session.sourceId } : {},
|
|
9025
|
-
...session.sourcePersisted !== void 0 ? { sourcePersisted: session.sourcePersisted } : {},
|
|
9026
|
-
...configOptions ? { configOptions } : {},
|
|
9027
|
-
...models ? { models } : {},
|
|
9028
|
-
...modes ? { modes } : {}
|
|
9029
|
-
});
|
|
9030
|
-
return;
|
|
9031
9566
|
}
|
|
9032
9567
|
case "session/load":
|
|
9033
9568
|
case "session/resume": {
|
|
9034
|
-
const sessionId =
|
|
9569
|
+
const sessionId = normalizeSessionIdForLookup(
|
|
9570
|
+
String(params["sessionId"] ?? "")
|
|
9571
|
+
);
|
|
9035
9572
|
if (!sessionId) {
|
|
9036
9573
|
if (id !== void 0) {
|
|
9037
9574
|
conn.sendConn(
|
|
@@ -9053,134 +9590,183 @@ var AcpDispatcher = class {
|
|
|
9053
9590
|
return;
|
|
9054
9591
|
}
|
|
9055
9592
|
const cwd = this.parseSessionWorkspaceCwd(params);
|
|
9056
|
-
const
|
|
9057
|
-
|
|
9058
|
-
|
|
9059
|
-
|
|
9060
|
-
|
|
9061
|
-
|
|
9062
|
-
|
|
9063
|
-
|
|
9064
|
-
|
|
9065
|
-
|
|
9066
|
-
|
|
9067
|
-
|
|
9068
|
-
|
|
9069
|
-
|
|
9070
|
-
|
|
9071
|
-
|
|
9072
|
-
|
|
9073
|
-
|
|
9074
|
-
clientId: conn.clientId,
|
|
9075
|
-
historyReplay: "response",
|
|
9076
|
-
...metadata
|
|
9077
|
-
}) : await this.bridge.resumeSession({
|
|
9078
|
-
sessionId,
|
|
9079
|
-
workspaceCwd: cwd,
|
|
9080
|
-
clientId: conn.clientId,
|
|
9081
|
-
...metadata
|
|
9082
|
-
});
|
|
9083
|
-
if (liveConversationCwd === void 0) {
|
|
9084
|
-
return session;
|
|
9085
|
-
}
|
|
9086
|
-
if (session.hasActivePrompt) {
|
|
9087
|
-
if (session.currentCwd === liveConversationCwd) return session;
|
|
9088
|
-
try {
|
|
9089
|
-
if (session.clientId) {
|
|
9090
|
-
await this.bridge.detachClient(
|
|
9091
|
-
session.sessionId,
|
|
9092
|
-
session.clientId
|
|
9093
|
-
);
|
|
9094
|
-
}
|
|
9095
|
-
} catch {
|
|
9096
|
-
}
|
|
9097
|
-
throw new Error(
|
|
9098
|
-
"Active Live session is outside its isolated conversation directory."
|
|
9593
|
+
const sessionRuntime = this.getSessionRuntimeContext();
|
|
9594
|
+
const reservation = this.requestedSessionIdAdmission.reserveRestore(
|
|
9595
|
+
sessionId,
|
|
9596
|
+
{
|
|
9597
|
+
bridge: sessionRuntime.bridge,
|
|
9598
|
+
workspaceCwd: cwd,
|
|
9599
|
+
...sessionRuntime.workspaceId ? { workspaceId: sessionRuntime.workspaceId } : {}
|
|
9600
|
+
}
|
|
9601
|
+
);
|
|
9602
|
+
try {
|
|
9603
|
+
const restored = await this.archiveCoordinator.runSharedMany(
|
|
9604
|
+
[sessionId],
|
|
9605
|
+
async () => {
|
|
9606
|
+
assertGenerationOpen?.();
|
|
9607
|
+
await assertSessionLoadable(
|
|
9608
|
+
cwd,
|
|
9609
|
+
sessionId,
|
|
9610
|
+
sessionRuntime.sessionRuntimeBaseDir
|
|
9099
9611
|
);
|
|
9100
|
-
|
|
9101
|
-
|
|
9102
|
-
|
|
9103
|
-
|
|
9104
|
-
|
|
9105
|
-
|
|
9612
|
+
const sessionService = new SessionService(cwd, {
|
|
9613
|
+
runtimeBaseDir: sessionRuntime.sessionRuntimeBaseDir
|
|
9614
|
+
});
|
|
9615
|
+
const metadata = this.liveSessionIsolation ? await readLoadableLiveConversationMetadata(
|
|
9616
|
+
sessionId,
|
|
9617
|
+
(candidateId) => sessionService.readCreationMetadata(candidateId)
|
|
9618
|
+
) : await sessionService.readCreationMetadata(sessionId);
|
|
9619
|
+
if (metadata === void 0) {
|
|
9620
|
+
throw new SessionNotFoundError(sessionId);
|
|
9621
|
+
}
|
|
9622
|
+
const liveConversationCwd = this.liveSessionIsolation ? await this.liveSessionIsolation.materializeConversationDirectory(
|
|
9623
|
+
sessionId
|
|
9624
|
+
) : void 0;
|
|
9625
|
+
assertGenerationOpen?.();
|
|
9626
|
+
const session = method === "session/load" ? await sessionRuntime.bridge.loadSession({
|
|
9627
|
+
sessionId,
|
|
9628
|
+
workspaceCwd: cwd,
|
|
9629
|
+
clientId: conn.clientId,
|
|
9630
|
+
historyReplay: "response",
|
|
9631
|
+
...metadata
|
|
9632
|
+
}) : await sessionRuntime.bridge.resumeSession({
|
|
9633
|
+
sessionId,
|
|
9634
|
+
workspaceCwd: cwd,
|
|
9635
|
+
clientId: conn.clientId,
|
|
9636
|
+
...metadata
|
|
9106
9637
|
});
|
|
9107
|
-
if (
|
|
9638
|
+
if (liveConversationCwd === void 0) {
|
|
9639
|
+
return session;
|
|
9640
|
+
}
|
|
9641
|
+
if (session.hasActivePrompt) {
|
|
9642
|
+
if (session.currentCwd === liveConversationCwd)
|
|
9643
|
+
return session;
|
|
9644
|
+
try {
|
|
9645
|
+
if (session.clientId) {
|
|
9646
|
+
await sessionRuntime.bridge.detachClient(
|
|
9647
|
+
session.sessionId,
|
|
9648
|
+
session.clientId
|
|
9649
|
+
);
|
|
9650
|
+
}
|
|
9651
|
+
} catch {
|
|
9652
|
+
}
|
|
9108
9653
|
throw new Error(
|
|
9109
|
-
"Live
|
|
9654
|
+
"Active Live session is outside its isolated conversation directory."
|
|
9110
9655
|
);
|
|
9111
9656
|
}
|
|
9112
|
-
session.currentCwd = changed.newCwd;
|
|
9113
|
-
} catch (error2) {
|
|
9114
9657
|
try {
|
|
9115
|
-
|
|
9116
|
-
|
|
9117
|
-
|
|
9118
|
-
|
|
9658
|
+
const changed = await sessionRuntime.bridge.changeSessionCwd(
|
|
9659
|
+
sessionId,
|
|
9660
|
+
{
|
|
9661
|
+
path: liveConversationCwd,
|
|
9662
|
+
allowedRoots: [cwd],
|
|
9663
|
+
managedRelocation: "live-conversation"
|
|
9664
|
+
}
|
|
9665
|
+
);
|
|
9666
|
+
if (changed.newCwd !== liveConversationCwd) {
|
|
9667
|
+
throw new Error(
|
|
9668
|
+
"Live conversation directory relocation was rejected."
|
|
9119
9669
|
);
|
|
9120
|
-
} else if (!session.attached) {
|
|
9121
|
-
await this.bridge.killSession(session.sessionId, {
|
|
9122
|
-
requireZeroAttaches: true
|
|
9123
|
-
});
|
|
9124
9670
|
}
|
|
9125
|
-
|
|
9671
|
+
session.currentCwd = changed.newCwd;
|
|
9672
|
+
} catch (error2) {
|
|
9673
|
+
try {
|
|
9674
|
+
if (session.attached && session.clientId) {
|
|
9675
|
+
await sessionRuntime.bridge.detachClient(
|
|
9676
|
+
session.sessionId,
|
|
9677
|
+
session.clientId
|
|
9678
|
+
);
|
|
9679
|
+
} else if (!session.attached) {
|
|
9680
|
+
await sessionRuntime.bridge.killSession(
|
|
9681
|
+
session.sessionId,
|
|
9682
|
+
{
|
|
9683
|
+
requireZeroAttaches: true
|
|
9684
|
+
}
|
|
9685
|
+
);
|
|
9686
|
+
}
|
|
9687
|
+
} catch {
|
|
9688
|
+
}
|
|
9689
|
+
throw error2;
|
|
9126
9690
|
}
|
|
9127
|
-
|
|
9691
|
+
return session;
|
|
9692
|
+
}
|
|
9693
|
+
);
|
|
9694
|
+
const rollbackRestore = /* @__PURE__ */ __name(async () => {
|
|
9695
|
+
if (restored.attached) {
|
|
9696
|
+
await sessionRuntime.bridge.detachClient(sessionId, restored.clientId).catch(() => {
|
|
9697
|
+
});
|
|
9698
|
+
} else {
|
|
9699
|
+
await sessionRuntime.bridge.killSession(sessionId, { requireZeroAttaches: true }).catch(() => {
|
|
9700
|
+
});
|
|
9128
9701
|
}
|
|
9129
|
-
|
|
9702
|
+
}, "rollbackRestore");
|
|
9703
|
+
try {
|
|
9704
|
+
assertGenerationOpen?.();
|
|
9705
|
+
} catch (error2) {
|
|
9706
|
+
await rollbackRestore();
|
|
9707
|
+
throw error2;
|
|
9130
9708
|
}
|
|
9131
|
-
|
|
9132
|
-
|
|
9133
|
-
|
|
9134
|
-
const cleanup = restored.attached ? this.bridge.detachClient(sessionId, restored.clientId) : this.bridge.killSession(sessionId, {
|
|
9135
|
-
requireZeroAttaches: true
|
|
9136
|
-
});
|
|
9137
|
-
void cleanup.catch(
|
|
9138
|
-
(err) => writeStderrLine(
|
|
9139
|
-
`qwen serve: /acp orphan ${restored.attached ? "detach" : "kill"}(${logSafe(sessionId)}) teardown-race: ${logSafe(errMsg(err))}`
|
|
9140
|
-
)
|
|
9709
|
+
const loadConfigOptions = await this.configOptionsFor(
|
|
9710
|
+
sessionId,
|
|
9711
|
+
sessionRuntime.bridge
|
|
9141
9712
|
);
|
|
9142
|
-
|
|
9143
|
-
|
|
9144
|
-
|
|
9145
|
-
|
|
9146
|
-
|
|
9147
|
-
|
|
9713
|
+
const loadModels = this.extractModelState(loadConfigOptions);
|
|
9714
|
+
const loadModes = this.extractModeState(loadConfigOptions);
|
|
9715
|
+
const loadState = restored.state ?? {};
|
|
9716
|
+
const loadMeta = isObject(loadState._meta) ? loadState._meta : void 0;
|
|
9717
|
+
const loadQwenMeta = isObject(loadMeta?.[QWEN_META_KEY]) ? loadMeta[QWEN_META_KEY] : void 0;
|
|
9718
|
+
const replayStatus = method === "session/load" && restored.partial === true ? {
|
|
9719
|
+
partial: true,
|
|
9720
|
+
...typeof restored.replayError === "string" ? { replayError: restored.replayError } : {}
|
|
9721
|
+
} : void 0;
|
|
9722
|
+
try {
|
|
9723
|
+
assertGenerationOpen?.();
|
|
9724
|
+
} catch (error2) {
|
|
9725
|
+
await rollbackRestore();
|
|
9726
|
+
throw error2;
|
|
9727
|
+
}
|
|
9728
|
+
const closeRaced = conn.closingSessions.has(sessionId);
|
|
9729
|
+
if (conn.destroyed || closeRaced) {
|
|
9730
|
+
void rollbackRestore().catch(
|
|
9731
|
+
(err) => writeStderrLine(
|
|
9732
|
+
`qwen serve: /acp orphan ${restored.attached ? "detach" : "kill"}(${logSafe(sessionId)}) teardown-race: ${logSafe(errMsg(err))}`
|
|
9148
9733
|
)
|
|
9149
9734
|
);
|
|
9735
|
+
if (closeRaced && !conn.destroyed && id !== void 0) {
|
|
9736
|
+
conn.sendConn(
|
|
9737
|
+
error(
|
|
9738
|
+
id,
|
|
9739
|
+
RPC.INTERNAL_ERROR,
|
|
9740
|
+
`session ${sessionId} was closed during load; retry`
|
|
9741
|
+
)
|
|
9742
|
+
);
|
|
9743
|
+
}
|
|
9744
|
+
return;
|
|
9150
9745
|
}
|
|
9746
|
+
conn.getOrCreateSession(sessionId).clientId = restored.clientId;
|
|
9747
|
+
if (method === "session/load") {
|
|
9748
|
+
conn.markInitialReplayPending(sessionId);
|
|
9749
|
+
}
|
|
9750
|
+
conn.ownSession(sessionId);
|
|
9751
|
+
this.replyConn(conn, id, {
|
|
9752
|
+
...loadState,
|
|
9753
|
+
...replayStatus ? {
|
|
9754
|
+
_meta: {
|
|
9755
|
+
...loadMeta ?? {},
|
|
9756
|
+
[QWEN_META_KEY]: {
|
|
9757
|
+
...loadQwenMeta ?? {},
|
|
9758
|
+
sessionLoadReplay: replayStatus
|
|
9759
|
+
}
|
|
9760
|
+
}
|
|
9761
|
+
} : {},
|
|
9762
|
+
...loadConfigOptions ? { configOptions: loadConfigOptions } : {},
|
|
9763
|
+
...loadModels ? { models: loadModels } : {},
|
|
9764
|
+
...loadModes ? { modes: loadModes } : {}
|
|
9765
|
+
});
|
|
9151
9766
|
return;
|
|
9767
|
+
} finally {
|
|
9768
|
+
reservation.release();
|
|
9152
9769
|
}
|
|
9153
|
-
conn.getOrCreateSession(sessionId).clientId = restored.clientId;
|
|
9154
|
-
if (method === "session/load") {
|
|
9155
|
-
conn.markInitialReplayPending(sessionId);
|
|
9156
|
-
}
|
|
9157
|
-
conn.ownSession(sessionId);
|
|
9158
|
-
const loadConfigOptions = await this.configOptionsFor(sessionId);
|
|
9159
|
-
const loadModels = this.extractModelState(loadConfigOptions);
|
|
9160
|
-
const loadModes = this.extractModeState(loadConfigOptions);
|
|
9161
|
-
const loadState = restored.state ?? {};
|
|
9162
|
-
const loadMeta = isObject(loadState._meta) ? loadState._meta : void 0;
|
|
9163
|
-
const loadQwenMeta = isObject(loadMeta?.[QWEN_META_KEY]) ? loadMeta[QWEN_META_KEY] : void 0;
|
|
9164
|
-
const replayStatus = method === "session/load" && restored.partial === true ? {
|
|
9165
|
-
partial: true,
|
|
9166
|
-
...typeof restored.replayError === "string" ? { replayError: restored.replayError } : {}
|
|
9167
|
-
} : void 0;
|
|
9168
|
-
this.replyConn(conn, id, {
|
|
9169
|
-
...loadState,
|
|
9170
|
-
...replayStatus ? {
|
|
9171
|
-
_meta: {
|
|
9172
|
-
...loadMeta ?? {},
|
|
9173
|
-
[QWEN_META_KEY]: {
|
|
9174
|
-
...loadQwenMeta ?? {},
|
|
9175
|
-
sessionLoadReplay: replayStatus
|
|
9176
|
-
}
|
|
9177
|
-
}
|
|
9178
|
-
} : {},
|
|
9179
|
-
...loadConfigOptions ? { configOptions: loadConfigOptions } : {},
|
|
9180
|
-
...loadModels ? { models: loadModels } : {},
|
|
9181
|
-
...loadModes ? { modes: loadModes } : {}
|
|
9182
|
-
});
|
|
9183
|
-
return;
|
|
9184
9770
|
}
|
|
9185
9771
|
case "session/list": {
|
|
9186
9772
|
const workspaceCwd = this.parseBoundWorkspaceParam(params);
|
|
@@ -13765,7 +14351,7 @@ function isActiveDrainCorrelation(registry, conn, message) {
|
|
|
13765
14351
|
return false;
|
|
13766
14352
|
}
|
|
13767
14353
|
const params = message.params !== null && typeof message.params === "object" ? message.params : void 0;
|
|
13768
|
-
return typeof params?.sessionId === "string" && conn.ownsSession(params.sessionId);
|
|
14354
|
+
return typeof params?.sessionId === "string" && conn.ownsSession(normalizeSessionIdForLookup(params.sessionId));
|
|
13769
14355
|
}
|
|
13770
14356
|
__name(isActiveDrainCorrelation, "isActiveDrainCorrelation");
|
|
13771
14357
|
var PLURAL_WS_PREFIX = "/workspaces/";
|
|
@@ -13942,6 +14528,9 @@ function mountAcpHttp(app, bridge, opts) {
|
|
|
13942
14528
|
const enabled = opts.enabled ?? resolveAcpHttpEnabled();
|
|
13943
14529
|
if (!enabled) return void 0;
|
|
13944
14530
|
const daemonEnv = opts.daemonEnv ?? process.env;
|
|
14531
|
+
const primarySessionRuntimeBaseDir = opts.workspaceRegistry?.primary.sessionRuntimeBaseDir ?? Storage.getRuntimeBaseDir();
|
|
14532
|
+
const archiveCoordinator = opts.archiveCoordinator ?? new SessionArchiveCoordinator();
|
|
14533
|
+
const requestedSessionIdAdmission = opts.requestedSessionIdAdmission;
|
|
13945
14534
|
const getPrimaryEnv = /* @__PURE__ */ __name(() => opts.workspaceRegistry ? runtimeEffectiveEnv(opts.workspaceRegistry.primary, daemonEnv) : daemonEnv, "getPrimaryEnv");
|
|
13946
14535
|
const path15 = opts.path ?? "/acp";
|
|
13947
14536
|
const dispatcherRef = {};
|
|
@@ -14095,11 +14684,12 @@ function mountAcpHttp(app, bridge, opts) {
|
|
|
14095
14684
|
getPrimaryEnv,
|
|
14096
14685
|
opts.workspace,
|
|
14097
14686
|
opts.workspaceRememberLane,
|
|
14687
|
+
requestedSessionIdAdmission,
|
|
14098
14688
|
opts.fsFactory,
|
|
14099
14689
|
opts.deviceFlowRegistry,
|
|
14100
14690
|
opts.sessionShellCommandEnabled === true,
|
|
14101
14691
|
registry,
|
|
14102
|
-
|
|
14692
|
+
archiveCoordinator,
|
|
14103
14693
|
opts.isPrimaryWorkspaceTrusted ?? (() => {
|
|
14104
14694
|
const entry = opts.workspaceRegistry?.primaryEntry;
|
|
14105
14695
|
return entry ? entry.state === "active" && entry.current?.runtime.trusted === true : true;
|
|
@@ -14109,7 +14699,18 @@ function mountAcpHttp(app, bridge, opts) {
|
|
|
14109
14699
|
return guard ? () => guard.assertOpen() : void 0;
|
|
14110
14700
|
},
|
|
14111
14701
|
void 0,
|
|
14112
|
-
|
|
14702
|
+
primarySessionRuntimeBaseDir,
|
|
14703
|
+
() => {
|
|
14704
|
+
const runtime = opts.workspaceRegistry?.primary;
|
|
14705
|
+
return runtime ? {
|
|
14706
|
+
bridge: runtime.bridge,
|
|
14707
|
+
sessionRuntimeBaseDir: runtime.sessionRuntimeBaseDir,
|
|
14708
|
+
workspaceId: runtime.workspaceId
|
|
14709
|
+
} : {
|
|
14710
|
+
bridge,
|
|
14711
|
+
sessionRuntimeBaseDir: primarySessionRuntimeBaseDir
|
|
14712
|
+
};
|
|
14713
|
+
}
|
|
14113
14714
|
);
|
|
14114
14715
|
dispatcherRef.current = dispatcher;
|
|
14115
14716
|
const primaryMount = {
|
|
@@ -14289,7 +14890,8 @@ function mountAcpHttp(app, bridge, opts) {
|
|
|
14289
14890
|
res.status(404).json({ error: "Unknown Acp-Connection-Id" });
|
|
14290
14891
|
return;
|
|
14291
14892
|
}
|
|
14292
|
-
const
|
|
14893
|
+
const rawSessionId = headerOf(req, ACP_SESSION_HEADER);
|
|
14894
|
+
const sessionId = rawSessionId ? normalizeSessionIdForLookup(rawSessionId) : void 0;
|
|
14293
14895
|
if (!sessionId) {
|
|
14294
14896
|
const connId = conn.connectionId;
|
|
14295
14897
|
const stream2 = new SseStream(
|
|
@@ -14396,12 +14998,17 @@ function mountAcpHttp(app, bridge, opts) {
|
|
|
14396
14998
|
rt.bridge,
|
|
14397
14999
|
rt.workspaceCwd
|
|
14398
15000
|
);
|
|
15001
|
+
const registeredGeneration = opts.workspaceRegistry?.getEntryByWorkspaceId(
|
|
15002
|
+
rt.workspaceId
|
|
15003
|
+
)?.current;
|
|
15004
|
+
const generationGuard = registeredGeneration?.runtime === rt ? registeredGeneration.guard : rt.generationGuard;
|
|
14399
15005
|
const secondaryDispatcher = new AcpDispatcher(
|
|
14400
15006
|
rt.bridge,
|
|
14401
15007
|
rt.workspaceCwd,
|
|
14402
15008
|
() => runtimeEffectiveEnv(rt, daemonEnv),
|
|
14403
15009
|
rt.workspaceService,
|
|
14404
15010
|
workspaceRememberLane,
|
|
15011
|
+
requestedSessionIdAdmission,
|
|
14405
15012
|
rt.routeFileSystemFactory,
|
|
14406
15013
|
// Phase 4: secondary mounts share the daemon-global device-flow registry
|
|
14407
15014
|
// (single instance per daemon; OAuth credentials are global state). The
|
|
@@ -14411,14 +15018,16 @@ function mountAcpHttp(app, bridge, opts) {
|
|
|
14411
15018
|
opts.deviceFlowRegistry,
|
|
14412
15019
|
opts.sessionShellCommandEnabled === true,
|
|
14413
15020
|
secondaryRegistry,
|
|
14414
|
-
|
|
15021
|
+
archiveCoordinator,
|
|
14415
15022
|
() => rt.trusted,
|
|
14416
|
-
() =>
|
|
14417
|
-
const guard = rt.generationGuard;
|
|
14418
|
-
return guard ? () => guard.assertOpen() : void 0;
|
|
14419
|
-
},
|
|
15023
|
+
() => generationGuard ? () => generationGuard.assertOpen() : void 0,
|
|
14420
15024
|
rt.provenance === "live-conversation" ? opts.liveSessionIsolation : void 0,
|
|
14421
|
-
rt.sessionRuntimeBaseDir
|
|
15025
|
+
rt.sessionRuntimeBaseDir,
|
|
15026
|
+
() => ({
|
|
15027
|
+
bridge: rt.bridge,
|
|
15028
|
+
sessionRuntimeBaseDir: rt.sessionRuntimeBaseDir,
|
|
15029
|
+
workspaceId: rt.workspaceId
|
|
15030
|
+
})
|
|
14422
15031
|
);
|
|
14423
15032
|
secondaryDispatcherRef.current = secondaryDispatcher;
|
|
14424
15033
|
return {
|
|
@@ -15056,7 +15665,8 @@ function mountAcpHttp(app, bridge, opts) {
|
|
|
15056
15665
|
return;
|
|
15057
15666
|
}
|
|
15058
15667
|
if (isRequest(message) && message.params && typeof message.params === "object") {
|
|
15059
|
-
const
|
|
15668
|
+
const rawSid = message.params["sessionId"];
|
|
15669
|
+
const sid = typeof rawSid === "string" ? normalizeSessionIdForLookup(rawSid) : rawSid;
|
|
15060
15670
|
if (typeof sid === "string" && conn.ownsSession(sid)) {
|
|
15061
15671
|
const binding = conn.sessions.get(sid);
|
|
15062
15672
|
if (binding && !binding.stream && conn.connStream && !conn.connStream.isClosed) {
|
|
@@ -15955,667 +16565,10 @@ function registerDaemonStatusRoutes(app, deps) {
|
|
|
15955
16565
|
}
|
|
15956
16566
|
__name(registerDaemonStatusRoutes, "registerDaemonStatusRoutes");
|
|
15957
16567
|
|
|
15958
|
-
// packages/cli/src/serve/routes/health
|
|
15959
|
-
init_esbuild_shims();
|
|
15960
|
-
|
|
15961
|
-
// packages/cli/src/serve/demo.ts
|
|
16568
|
+
// packages/cli/src/serve/routes/health.ts
|
|
15962
16569
|
init_esbuild_shims();
|
|
15963
|
-
function
|
|
15964
|
-
|
|
15965
|
-
/* html */
|
|
15966
|
-
`<!DOCTYPE html>
|
|
15967
|
-
<html lang="en">
|
|
15968
|
-
<head>
|
|
15969
|
-
<meta charset="utf-8" />
|
|
15970
|
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
15971
|
-
<title>Qwen Serve Demo</title>
|
|
15972
|
-
<style>
|
|
15973
|
-
:root { --bg: #1a1a2e; --surface: #16213e; --border: #0f3460; --accent: #e94560; --text: #eee; --text2: #aab; --ok: #4ade80; --warn: #fbbf24; --err: #f87171; }
|
|
15974
|
-
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
15975
|
-
body { font-family: 'SF Mono', 'Menlo', 'Consolas', monospace; font-size: 13px; background: var(--bg); color: var(--text); min-height: 100vh; }
|
|
15976
|
-
.header { background: var(--surface); border-bottom: 1px solid var(--border); padding: 12px 20px; display: flex; align-items: center; gap: 12px; }
|
|
15977
|
-
.header h1 { font-size: 16px; font-weight: 600; }
|
|
15978
|
-
.header .badge { font-size: 11px; background: var(--accent); color: #fff; padding: 2px 8px; border-radius: 10px; }
|
|
15979
|
-
.header .status { margin-left: auto; display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text2); }
|
|
15980
|
-
.header .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--err); }
|
|
15981
|
-
.header .dot.ok { background: var(--ok); }
|
|
15982
|
-
.container { display: grid; grid-template-columns: 340px 1fr; height: calc(100vh - 49px); }
|
|
15983
|
-
.sidebar { background: var(--surface); border-right: 1px solid var(--border); overflow-y: auto; padding: 12px; display: flex; flex-direction: column; gap: 12px; }
|
|
15984
|
-
.panel { background: var(--bg); border: 1px solid var(--border); border-radius: 6px; padding: 12px; }
|
|
15985
|
-
.panel h3 { font-size: 12px; color: var(--accent); margin-bottom: 8px; text-transform: uppercase; letter-spacing: 0.5px; }
|
|
15986
|
-
.panel label { display: block; font-size: 11px; color: var(--text2); margin-bottom: 3px; }
|
|
15987
|
-
.panel input, .panel textarea { width: 100%; background: var(--surface); border: 1px solid var(--border); color: var(--text); padding: 6px 8px; border-radius: 4px; font-family: inherit; font-size: 12px; margin-bottom: 8px; }
|
|
15988
|
-
.panel input:focus, .panel textarea:focus { outline: none; border-color: var(--accent); }
|
|
15989
|
-
.panel textarea { resize: vertical; min-height: 60px; }
|
|
15990
|
-
.btn { display: inline-flex; align-items: center; gap: 4px; padding: 6px 14px; border: 1px solid var(--border); border-radius: 4px; background: var(--surface); color: var(--text); font-family: inherit; font-size: 12px; cursor: pointer; transition: all 0.15s; }
|
|
15991
|
-
.btn:hover { border-color: var(--accent); color: var(--accent); }
|
|
15992
|
-
.btn.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
|
|
15993
|
-
.btn.primary:hover { opacity: 0.85; }
|
|
15994
|
-
.btn:disabled { opacity: 0.4; cursor: not-allowed; }
|
|
15995
|
-
.btn-row { display: flex; gap: 6px; flex-wrap: wrap; }
|
|
15996
|
-
.main { display: flex; flex-direction: column; overflow: hidden; }
|
|
15997
|
-
.tabs { display: flex; background: var(--surface); border-bottom: 1px solid var(--border); }
|
|
15998
|
-
.tab { padding: 8px 16px; font-size: 12px; color: var(--text2); cursor: pointer; border-bottom: 2px solid transparent; }
|
|
15999
|
-
.tab.active { color: var(--accent); border-bottom-color: var(--accent); }
|
|
16000
|
-
.tab-content { flex: 1; overflow: hidden; display: none; flex-direction: column; }
|
|
16001
|
-
.tab-content.active { display: flex; }
|
|
16002
|
-
.log { flex: 1; overflow-y: auto; padding: 12px; font-size: 12px; line-height: 1.6; }
|
|
16003
|
-
.log-entry { padding: 3px 0; border-bottom: 1px solid rgba(255,255,255,0.03); word-break: break-all; }
|
|
16004
|
-
.log-entry .ts { color: var(--text2); margin-right: 8px; font-size: 11px; }
|
|
16005
|
-
.log-entry .tag { display: inline-block; padding: 0 5px; border-radius: 3px; font-size: 10px; margin-right: 6px; }
|
|
16006
|
-
.tag-info { background: #1e40af; color: #93c5fd; }
|
|
16007
|
-
.tag-event { background: #065f46; color: #6ee7b7; }
|
|
16008
|
-
.tag-error { background: #7f1d1d; color: #fca5a5; }
|
|
16009
|
-
.tag-response { background: #713f12; color: #fde68a; }
|
|
16010
|
-
.tag-thought { background: #4c1d95; color: #c4b5fd; }
|
|
16011
|
-
.tag-message { background: #164e63; color: #67e8f9; }
|
|
16012
|
-
.chat { flex: 1; overflow-y: auto; padding: 16px; }
|
|
16013
|
-
.chat-msg { margin-bottom: 12px; max-width: 85%; }
|
|
16014
|
-
.chat-msg.user { margin-left: auto; }
|
|
16015
|
-
.chat-msg .bubble { padding: 8px 12px; border-radius: 8px; line-height: 1.5; white-space: pre-wrap; }
|
|
16016
|
-
.chat-msg.user .bubble { background: var(--accent); color: #fff; border-bottom-right-radius: 2px; }
|
|
16017
|
-
.chat-msg.assistant .bubble { background: var(--surface); border: 1px solid var(--border); border-bottom-left-radius: 2px; }
|
|
16018
|
-
.chat-msg .meta { font-size: 10px; color: var(--text2); margin-top: 3px; }
|
|
16019
|
-
.chat-input { display: flex; gap: 8px; padding: 12px; border-top: 1px solid var(--border); background: var(--surface); }
|
|
16020
|
-
.chat-input input { flex: 1; }
|
|
16021
|
-
.session-info { font-size: 11px; color: var(--text2); padding: 4px 0; }
|
|
16022
|
-
.session-info span { color: var(--ok); }
|
|
16023
|
-
.empty-hint { color: var(--text2); text-align: center; padding: 40px 20px; font-size: 12px; }
|
|
16024
|
-
.permission-card { background: var(--surface); border: 1px solid var(--warn); border-radius: 6px; padding: 10px 12px; margin: 8px 0; }
|
|
16025
|
-
.permission-card h4 { color: var(--warn); font-size: 12px; margin-bottom: 6px; }
|
|
16026
|
-
.permission-card .opt-btn { margin-right: 4px; margin-top: 4px; }
|
|
16027
|
-
</style>
|
|
16028
|
-
</head>
|
|
16029
|
-
<body>
|
|
16030
|
-
|
|
16031
|
-
<div class="header">
|
|
16032
|
-
<h1>Qwen Serve</h1>
|
|
16033
|
-
<span class="badge">Demo</span>
|
|
16034
|
-
<div class="status">
|
|
16035
|
-
<span class="dot" id="statusDot"></span>
|
|
16036
|
-
<span id="statusText">Connecting...</span>
|
|
16037
|
-
</div>
|
|
16038
|
-
</div>
|
|
16039
|
-
|
|
16040
|
-
<div class="container">
|
|
16041
|
-
<div class="sidebar">
|
|
16042
|
-
<div class="panel">
|
|
16043
|
-
<h3>Session</h3>
|
|
16044
|
-
<label>Working Directory (cwd)</label>
|
|
16045
|
-
<input type="text" id="cwdInput" placeholder="/path/to/project" />
|
|
16046
|
-
<div class="btn-row">
|
|
16047
|
-
<button class="btn primary" id="btnCreateSession">Create / Attach</button>
|
|
16048
|
-
<button class="btn" id="btnListSessions">List</button>
|
|
16049
|
-
</div>
|
|
16050
|
-
<div class="session-info" id="sessionInfo" style="display:none">
|
|
16051
|
-
Session: <span id="sessionIdDisplay"></span>
|
|
16052
|
-
</div>
|
|
16053
|
-
</div>
|
|
16054
|
-
|
|
16055
|
-
<div class="panel">
|
|
16056
|
-
<h3>Prompt</h3>
|
|
16057
|
-
<textarea id="promptInput" placeholder="Type your prompt here..."></textarea>
|
|
16058
|
-
<div class="btn-row">
|
|
16059
|
-
<button class="btn primary" id="btnSendPrompt" disabled>Send</button>
|
|
16060
|
-
<button class="btn" id="btnCancel" disabled>Cancel</button>
|
|
16061
|
-
</div>
|
|
16062
|
-
</div>
|
|
16063
|
-
|
|
16064
|
-
<div class="panel">
|
|
16065
|
-
<h3>Model</h3>
|
|
16066
|
-
<input type="text" id="modelInput" placeholder="Model ID (e.g. qwen3-coder)" />
|
|
16067
|
-
<button class="btn" id="btnSetModel" disabled>Switch Model</button>
|
|
16068
|
-
</div>
|
|
16069
|
-
|
|
16070
|
-
<div class="panel">
|
|
16071
|
-
<h3>Auth Token</h3>
|
|
16072
|
-
<label>Bearer Token (if --token is set)</label>
|
|
16073
|
-
<input type="password" id="tokenInput" placeholder="Optional bearer token" />
|
|
16074
|
-
</div>
|
|
16075
|
-
|
|
16076
|
-
<div class="panel">
|
|
16077
|
-
<h3>Quick Actions</h3>
|
|
16078
|
-
<div class="btn-row">
|
|
16079
|
-
<button class="btn" id="btnHealth">Health</button>
|
|
16080
|
-
<button class="btn" id="btnHealthDeep">Health (deep)</button>
|
|
16081
|
-
<button class="btn" id="btnCaps">Capabilities</button>
|
|
16082
|
-
</div>
|
|
16083
|
-
</div>
|
|
16084
|
-
|
|
16085
|
-
<div class="panel" id="permissionPanel" style="display:none">
|
|
16086
|
-
<h3>Pending Permissions</h3>
|
|
16087
|
-
<div id="permissionList"></div>
|
|
16088
|
-
</div>
|
|
16089
|
-
</div>
|
|
16090
|
-
|
|
16091
|
-
<div class="main">
|
|
16092
|
-
<div class="tabs">
|
|
16093
|
-
<div class="tab active" data-tab="chat">Chat</div>
|
|
16094
|
-
<div class="tab" data-tab="events">Events</div>
|
|
16095
|
-
<div class="tab" data-tab="requests">API Log</div>
|
|
16096
|
-
</div>
|
|
16097
|
-
|
|
16098
|
-
<div class="tab-content active" id="tab-chat">
|
|
16099
|
-
<div class="chat" id="chatArea">
|
|
16100
|
-
<div class="empty-hint">Create a session to start chatting</div>
|
|
16101
|
-
</div>
|
|
16102
|
-
<div class="chat-input">
|
|
16103
|
-
<input type="text" id="chatInput" placeholder="Send a message..." disabled />
|
|
16104
|
-
<button class="btn primary" id="btnChatSend" disabled>Send</button>
|
|
16105
|
-
</div>
|
|
16106
|
-
</div>
|
|
16107
|
-
|
|
16108
|
-
<div class="tab-content" id="tab-events">
|
|
16109
|
-
<div class="log" id="eventLog"></div>
|
|
16110
|
-
</div>
|
|
16111
|
-
|
|
16112
|
-
<div class="tab-content" id="tab-requests">
|
|
16113
|
-
<div class="log" id="requestLog"></div>
|
|
16114
|
-
</div>
|
|
16115
|
-
</div>
|
|
16116
|
-
</div>
|
|
16117
|
-
|
|
16118
|
-
<script>
|
|
16119
|
-
(function() {
|
|
16120
|
-
const BASE = '';
|
|
16121
|
-
let sessionId = null;
|
|
16122
|
-
let eventSource = null;
|
|
16123
|
-
let currentAssistantBubble = null;
|
|
16124
|
-
let currentThought = '';
|
|
16125
|
-
|
|
16126
|
-
// --- DOM refs ---
|
|
16127
|
-
const $ = (s) => document.querySelector(s);
|
|
16128
|
-
const statusDot = $('#statusDot');
|
|
16129
|
-
const statusText = $('#statusText');
|
|
16130
|
-
const cwdInput = $('#cwdInput');
|
|
16131
|
-
const promptInput = $('#promptInput');
|
|
16132
|
-
const modelInput = $('#modelInput');
|
|
16133
|
-
const tokenInput = $('#tokenInput');
|
|
16134
|
-
const chatArea = $('#chatArea');
|
|
16135
|
-
const chatInput = $('#chatInput');
|
|
16136
|
-
const eventLog = $('#eventLog');
|
|
16137
|
-
const requestLog = $('#requestLog');
|
|
16138
|
-
const sessionInfo = $('#sessionInfo');
|
|
16139
|
-
const sessionIdDisplay = $('#sessionIdDisplay');
|
|
16140
|
-
const permissionPanel = $('#permissionPanel');
|
|
16141
|
-
const permissionList = $('#permissionList');
|
|
16142
|
-
|
|
16143
|
-
// --- Tabs ---
|
|
16144
|
-
document.querySelectorAll('.tab').forEach(tab => {
|
|
16145
|
-
tab.addEventListener('click', () => {
|
|
16146
|
-
document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
|
|
16147
|
-
document.querySelectorAll('.tab-content').forEach(t => t.classList.remove('active'));
|
|
16148
|
-
tab.classList.add('active');
|
|
16149
|
-
$('#tab-' + tab.dataset.tab).classList.add('active');
|
|
16150
|
-
});
|
|
16151
|
-
});
|
|
16152
|
-
|
|
16153
|
-
// --- Logging ---
|
|
16154
|
-
function ts() {
|
|
16155
|
-
return new Date().toLocaleTimeString('en-US', { hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit' });
|
|
16156
|
-
}
|
|
16157
|
-
const MAX_LOG_ENTRIES = 500;
|
|
16158
|
-
function addLog(container, tag, tagClass, msg) {
|
|
16159
|
-
const el = document.createElement('div');
|
|
16160
|
-
el.className = 'log-entry';
|
|
16161
|
-
const text = typeof msg === 'object' ? JSON.stringify(msg, null, 2) : msg;
|
|
16162
|
-
const tsSpan = document.createElement('span');
|
|
16163
|
-
tsSpan.className = 'ts';
|
|
16164
|
-
tsSpan.textContent = ts();
|
|
16165
|
-
const tagSpan = document.createElement('span');
|
|
16166
|
-
tagSpan.className = 'tag ' + tagClass;
|
|
16167
|
-
tagSpan.textContent = tag;
|
|
16168
|
-
el.appendChild(tsSpan);
|
|
16169
|
-
el.appendChild(tagSpan);
|
|
16170
|
-
el.appendChild(document.createTextNode(text));
|
|
16171
|
-
container.appendChild(el);
|
|
16172
|
-
while (container.children.length > MAX_LOG_ENTRIES) {
|
|
16173
|
-
container.removeChild(container.firstChild);
|
|
16174
|
-
}
|
|
16175
|
-
container.scrollTop = container.scrollHeight;
|
|
16176
|
-
}
|
|
16177
|
-
function logEvent(tag, msg) { addLog(eventLog, tag, 'tag-event', msg); }
|
|
16178
|
-
function logRequest(tag, msg) { addLog(requestLog, tag, 'tag-info', msg); }
|
|
16179
|
-
function logResponse(tag, msg) { addLog(requestLog, tag, 'tag-response', msg); }
|
|
16180
|
-
function logError(tag, msg) { addLog(requestLog, tag, 'tag-error', msg); }
|
|
16181
|
-
|
|
16182
|
-
function escHtml(s) {
|
|
16183
|
-
const d = document.createElement('div');
|
|
16184
|
-
d.textContent = String(s);
|
|
16185
|
-
return d.innerHTML;
|
|
16186
|
-
}
|
|
16187
|
-
|
|
16188
|
-
// --- 401 token hint ---
|
|
16189
|
-
let tokenHintTimer = null;
|
|
16190
|
-
function highlightTokenInput(msg) {
|
|
16191
|
-
tokenInput.style.borderColor = 'var(--warn)';
|
|
16192
|
-
tokenInput.focus();
|
|
16193
|
-
// Show hint text below the input
|
|
16194
|
-
let hint = document.getElementById('tokenHint');
|
|
16195
|
-
if (!hint) {
|
|
16196
|
-
hint = document.createElement('div');
|
|
16197
|
-
hint.id = 'tokenHint';
|
|
16198
|
-
hint.style.cssText = 'font-size:11px;color:var(--warn);margin-top:-4px;margin-bottom:4px;';
|
|
16199
|
-
tokenInput.parentNode.insertBefore(hint, tokenInput.nextSibling);
|
|
16200
|
-
}
|
|
16201
|
-
hint.textContent = msg;
|
|
16202
|
-
if (tokenHintTimer) clearTimeout(tokenHintTimer);
|
|
16203
|
-
tokenHintTimer = setTimeout(() => {
|
|
16204
|
-
tokenInput.style.borderColor = '';
|
|
16205
|
-
hint.textContent = '';
|
|
16206
|
-
}, 6000);
|
|
16207
|
-
}
|
|
16208
|
-
|
|
16209
|
-
// --- API helpers ---
|
|
16210
|
-
function authHeaders() {
|
|
16211
|
-
const token = tokenInput.value.trim();
|
|
16212
|
-
return token ? { 'Authorization': 'Bearer ' + token } : {};
|
|
16213
|
-
}
|
|
16214
|
-
|
|
16215
|
-
async function api(method, path, body) {
|
|
16216
|
-
const opts = { method, headers: { ...authHeaders() } };
|
|
16217
|
-
if (body !== undefined) {
|
|
16218
|
-
opts.headers['Content-Type'] = 'application/json';
|
|
16219
|
-
opts.body = JSON.stringify(body);
|
|
16220
|
-
}
|
|
16221
|
-
logRequest(method, path + (body ? ' ' + JSON.stringify(body) : ''));
|
|
16222
|
-
try {
|
|
16223
|
-
const res = await fetch(BASE + path, opts);
|
|
16224
|
-
const text = await res.text();
|
|
16225
|
-
let data;
|
|
16226
|
-
try { data = JSON.parse(text); } catch { data = text; }
|
|
16227
|
-
if (!res.ok) {
|
|
16228
|
-
logError(res.status, JSON.stringify(data));
|
|
16229
|
-
if (res.status === 401) {
|
|
16230
|
-
highlightTokenInput('API returned 401 \u2014 enter your bearer token below');
|
|
16231
|
-
}
|
|
16232
|
-
return { ok: false, status: res.status, data };
|
|
16233
|
-
}
|
|
16234
|
-
logResponse(res.status, JSON.stringify(data));
|
|
16235
|
-
return { ok: true, status: res.status, data };
|
|
16236
|
-
} catch (err) {
|
|
16237
|
-
logError('ERR', err.message);
|
|
16238
|
-
return { ok: false, status: 0, data: { error: err.message } };
|
|
16239
|
-
}
|
|
16240
|
-
}
|
|
16241
|
-
|
|
16242
|
-
// --- Health check on load ---
|
|
16243
|
-
async function checkHealth() {
|
|
16244
|
-
const r = await api('GET', '/health');
|
|
16245
|
-
if (r.ok) {
|
|
16246
|
-
statusDot.classList.add('ok');
|
|
16247
|
-
statusText.textContent = 'Connected';
|
|
16248
|
-
} else {
|
|
16249
|
-
statusDot.classList.remove('ok');
|
|
16250
|
-
statusText.textContent = 'Disconnected';
|
|
16251
|
-
}
|
|
16252
|
-
}
|
|
16253
|
-
|
|
16254
|
-
// --- Session ---
|
|
16255
|
-
async function createSession() {
|
|
16256
|
-
const cwd = cwdInput.value.trim();
|
|
16257
|
-
if (!cwd) { alert('Please enter a working directory'); return; }
|
|
16258
|
-
const r = await api('POST', '/session', { cwd });
|
|
16259
|
-
if (r.ok) {
|
|
16260
|
-
sessionId = r.data.sessionId;
|
|
16261
|
-
sessionInfo.style.display = 'block';
|
|
16262
|
-
sessionIdDisplay.textContent = sessionId;
|
|
16263
|
-
enablePrompt(true);
|
|
16264
|
-
chatArea.innerHTML = '';
|
|
16265
|
-
currentAssistantBubble = null;
|
|
16266
|
-
pendingPerms.clear();
|
|
16267
|
-
renderPermissions();
|
|
16268
|
-
if (r.data.attached) {
|
|
16269
|
-
addChatMeta('Attached to existing session');
|
|
16270
|
-
} else {
|
|
16271
|
-
addChatMeta('New session created');
|
|
16272
|
-
}
|
|
16273
|
-
connectSSE();
|
|
16274
|
-
} else {
|
|
16275
|
-
const msg = r.data.error || 'session creation failed (' + r.status + ')';
|
|
16276
|
-
addChatMeta('Error: ' + msg);
|
|
16277
|
-
if (r.status === 401) highlightTokenInput('Token required or invalid');
|
|
16278
|
-
}
|
|
16279
|
-
}
|
|
16280
|
-
|
|
16281
|
-
function enablePrompt(on) {
|
|
16282
|
-
$('#btnSendPrompt').disabled = !on;
|
|
16283
|
-
$('#btnCancel').disabled = !on;
|
|
16284
|
-
$('#btnSetModel').disabled = !on;
|
|
16285
|
-
chatInput.disabled = !on;
|
|
16286
|
-
$('#btnChatSend').disabled = !on;
|
|
16287
|
-
}
|
|
16288
|
-
|
|
16289
|
-
// --- SSE ---
|
|
16290
|
-
function connectSSE() {
|
|
16291
|
-
if (eventSource) { eventSource.close(); }
|
|
16292
|
-
const url = BASE + '/session/' + sessionId + '/events';
|
|
16293
|
-
logEvent('SSE', 'Connecting to ' + url);
|
|
16294
|
-
|
|
16295
|
-
// Use fetch-based SSE to avoid Origin header issues with EventSource
|
|
16296
|
-
const abort = new AbortController();
|
|
16297
|
-
eventSource = { close: () => abort.abort() };
|
|
16298
|
-
|
|
16299
|
-
(async function readSSE() {
|
|
16300
|
-
try {
|
|
16301
|
-
const hdrs = authHeaders();
|
|
16302
|
-
const res = await fetch(url, { signal: abort.signal, headers: hdrs });
|
|
16303
|
-
if (!res.ok) {
|
|
16304
|
-
logEvent('SSE-ERR', 'HTTP ' + res.status);
|
|
16305
|
-
statusDot.classList.remove('ok');
|
|
16306
|
-
statusText.textContent = 'SSE failed (' + res.status + ')';
|
|
16307
|
-
enablePrompt(false);
|
|
16308
|
-
if (res.status === 401) {
|
|
16309
|
-
highlightTokenInput('SSE returned 401 \u2014 enter your bearer token and recreate the session');
|
|
16310
|
-
}
|
|
16311
|
-
return;
|
|
16312
|
-
}
|
|
16313
|
-
const reader = res.body.getReader();
|
|
16314
|
-
const decoder = new TextDecoder();
|
|
16315
|
-
let buffer = '';
|
|
16316
|
-
let currentEvent = {};
|
|
16317
|
-
|
|
16318
|
-
while (true) {
|
|
16319
|
-
const { done, value } = await reader.read();
|
|
16320
|
-
if (done) break;
|
|
16321
|
-
buffer += decoder.decode(value, { stream: true });
|
|
16322
|
-
|
|
16323
|
-
const lines = buffer.split('\\n');
|
|
16324
|
-
buffer = lines.pop();
|
|
16325
|
-
|
|
16326
|
-
for (const line of lines) {
|
|
16327
|
-
if (line.startsWith('data: ')) {
|
|
16328
|
-
currentEvent.data = line.slice(6);
|
|
16329
|
-
} else if (line.startsWith('event: ')) {
|
|
16330
|
-
currentEvent.event = line.slice(7);
|
|
16331
|
-
} else if (line.startsWith('id: ')) {
|
|
16332
|
-
currentEvent.id = line.slice(4);
|
|
16333
|
-
} else if (line === '') {
|
|
16334
|
-
if (currentEvent.data) {
|
|
16335
|
-
handleSSEMessage(currentEvent);
|
|
16336
|
-
}
|
|
16337
|
-
currentEvent = {};
|
|
16338
|
-
}
|
|
16339
|
-
}
|
|
16340
|
-
}
|
|
16341
|
-
// Process any remaining buffered data
|
|
16342
|
-
if (currentEvent.data) handleSSEMessage(currentEvent);
|
|
16343
|
-
statusDot.classList.remove('ok');
|
|
16344
|
-
statusText.textContent = 'SSE stream ended';
|
|
16345
|
-
enablePrompt(false);
|
|
16346
|
-
logEvent('SSE', 'Stream ended by server');
|
|
16347
|
-
} catch (err) {
|
|
16348
|
-
if (err.name !== 'AbortError') {
|
|
16349
|
-
logEvent('SSE-ERR', err.message);
|
|
16350
|
-
statusDot.classList.remove('ok');
|
|
16351
|
-
statusText.textContent = 'SSE error';
|
|
16352
|
-
enablePrompt(false);
|
|
16353
|
-
}
|
|
16354
|
-
}
|
|
16355
|
-
})();
|
|
16356
|
-
}
|
|
16357
|
-
|
|
16358
|
-
function handleSSEMessage(msg) {
|
|
16359
|
-
let data;
|
|
16360
|
-
try { data = JSON.parse(msg.data); } catch { data = msg.data; }
|
|
16361
|
-
const type = data.type || msg.event || 'unknown';
|
|
16362
|
-
|
|
16363
|
-
if (type === 'session_update' && data.data) {
|
|
16364
|
-
const update = data.data.update || data.data;
|
|
16365
|
-
const kind = update.sessionUpdate;
|
|
16366
|
-
|
|
16367
|
-
if (kind === 'agent_message_chunk') {
|
|
16368
|
-
const text = update.content?.text || '';
|
|
16369
|
-
if (text) appendAssistantChunk(text);
|
|
16370
|
-
if (update._meta?.usage) {
|
|
16371
|
-
const u = update._meta.usage;
|
|
16372
|
-
addChatMeta('tokens: in=' + u.inputTokens + ' out=' + u.outputTokens + ' | ' + (update._meta.durationMs || 0) + 'ms');
|
|
16373
|
-
currentAssistantBubble = null;
|
|
16374
|
-
}
|
|
16375
|
-
logEvent('MSG', text || '(usage meta)');
|
|
16376
|
-
} else if (kind === 'agent_thought_chunk') {
|
|
16377
|
-
const text = update.content?.text || '';
|
|
16378
|
-
currentThought += text;
|
|
16379
|
-
logEvent('THINK', text);
|
|
16380
|
-
} else {
|
|
16381
|
-
logEvent(kind || type, JSON.stringify(update));
|
|
16382
|
-
}
|
|
16383
|
-
} else if (type === 'permission_request') {
|
|
16384
|
-
handlePermissionRequest(data);
|
|
16385
|
-
logEvent('PERM', JSON.stringify(data.data));
|
|
16386
|
-
} else if (type === 'permission_resolved') {
|
|
16387
|
-
logEvent('PERM-OK', JSON.stringify(data.data));
|
|
16388
|
-
removePermission(data.data?.requestId);
|
|
16389
|
-
} else if (type === 'session_died') {
|
|
16390
|
-
addChatMeta('Session died: ' + JSON.stringify(data.data));
|
|
16391
|
-
logEvent('DIED', JSON.stringify(data.data));
|
|
16392
|
-
enablePrompt(false);
|
|
16393
|
-
} else if (type === 'model_switched') {
|
|
16394
|
-
addChatMeta('Model switched: ' + JSON.stringify(data.data));
|
|
16395
|
-
logEvent('MODEL', JSON.stringify(data.data));
|
|
16396
|
-
} else {
|
|
16397
|
-
logEvent(type, JSON.stringify(data));
|
|
16398
|
-
}
|
|
16399
|
-
}
|
|
16400
|
-
|
|
16401
|
-
// --- Chat UI ---
|
|
16402
|
-
function addUserMessage(text) {
|
|
16403
|
-
currentAssistantBubble = null;
|
|
16404
|
-
currentThought = '';
|
|
16405
|
-
const el = document.createElement('div');
|
|
16406
|
-
el.className = 'chat-msg user';
|
|
16407
|
-
el.innerHTML = '<div class="bubble">' + escHtml(text) + '</div>';
|
|
16408
|
-
chatArea.appendChild(el);
|
|
16409
|
-
chatArea.scrollTop = chatArea.scrollHeight;
|
|
16410
|
-
}
|
|
16411
|
-
|
|
16412
|
-
function appendAssistantChunk(text) {
|
|
16413
|
-
if (!currentAssistantBubble) {
|
|
16414
|
-
if (currentThought) {
|
|
16415
|
-
const te = document.createElement('div');
|
|
16416
|
-
te.className = 'chat-msg assistant';
|
|
16417
|
-
te.innerHTML = '<div class="bubble" style="color:var(--text2);font-style:italic;border-color:var(--border)">Thinking: ' + escHtml(currentThought) + '</div>';
|
|
16418
|
-
chatArea.appendChild(te);
|
|
16419
|
-
currentThought = '';
|
|
16420
|
-
}
|
|
16421
|
-
const el = document.createElement('div');
|
|
16422
|
-
el.className = 'chat-msg assistant';
|
|
16423
|
-
el.innerHTML = '<div class="bubble"></div>';
|
|
16424
|
-
chatArea.appendChild(el);
|
|
16425
|
-
currentAssistantBubble = el.querySelector('.bubble');
|
|
16426
|
-
}
|
|
16427
|
-
currentAssistantBubble.textContent += text;
|
|
16428
|
-
chatArea.scrollTop = chatArea.scrollHeight;
|
|
16429
|
-
}
|
|
16430
|
-
|
|
16431
|
-
function addChatMeta(text) {
|
|
16432
|
-
const el = document.createElement('div');
|
|
16433
|
-
el.className = 'chat-msg assistant';
|
|
16434
|
-
el.innerHTML = '<div class="meta">' + escHtml(text) + '</div>';
|
|
16435
|
-
chatArea.appendChild(el);
|
|
16436
|
-
chatArea.scrollTop = chatArea.scrollHeight;
|
|
16437
|
-
}
|
|
16438
|
-
|
|
16439
|
-
// --- Prompt ---
|
|
16440
|
-
let promptInFlight = false;
|
|
16441
|
-
async function sendPrompt(text) {
|
|
16442
|
-
if (!sessionId || !text.trim() || promptInFlight) return;
|
|
16443
|
-
promptInFlight = true;
|
|
16444
|
-
enablePrompt(false);
|
|
16445
|
-
addUserMessage(text.trim());
|
|
16446
|
-
promptInput.value = '';
|
|
16447
|
-
chatInput.value = '';
|
|
16448
|
-
try {
|
|
16449
|
-
const r = await api('POST', '/session/' + sessionId + '/prompt', {
|
|
16450
|
-
prompt: [{ type: 'text', text: text.trim() }]
|
|
16451
|
-
});
|
|
16452
|
-
if (r.ok) {
|
|
16453
|
-
addChatMeta('stopReason: ' + (r.data.stopReason || 'unknown'));
|
|
16454
|
-
} else {
|
|
16455
|
-
addChatMeta('Error: ' + (r.data.error || 'prompt failed (' + r.status + ')'));
|
|
16456
|
-
}
|
|
16457
|
-
} finally {
|
|
16458
|
-
promptInFlight = false;
|
|
16459
|
-
if (sessionId) enablePrompt(true);
|
|
16460
|
-
}
|
|
16461
|
-
}
|
|
16462
|
-
|
|
16463
|
-
// --- Permission handling ---
|
|
16464
|
-
const pendingPerms = new Map();
|
|
16465
|
-
|
|
16466
|
-
function handlePermissionRequest(data) {
|
|
16467
|
-
const req = data.data;
|
|
16468
|
-
const requestId = req?.requestId;
|
|
16469
|
-
if (!requestId) return;
|
|
16470
|
-
pendingPerms.set(requestId, req);
|
|
16471
|
-
renderPermissions();
|
|
16472
|
-
|
|
16473
|
-
addChatMeta('Permission requested: ' + requestId);
|
|
16474
|
-
}
|
|
16475
|
-
|
|
16476
|
-
function removePermission(requestId) {
|
|
16477
|
-
pendingPerms.delete(requestId);
|
|
16478
|
-
renderPermissions();
|
|
16479
|
-
}
|
|
16480
|
-
|
|
16481
|
-
function renderPermissions() {
|
|
16482
|
-
if (pendingPerms.size === 0) {
|
|
16483
|
-
permissionPanel.style.display = 'none';
|
|
16484
|
-
return;
|
|
16485
|
-
}
|
|
16486
|
-
permissionPanel.style.display = 'block';
|
|
16487
|
-
permissionList.innerHTML = '';
|
|
16488
|
-
for (const [id, req] of pendingPerms) {
|
|
16489
|
-
const card = document.createElement('div');
|
|
16490
|
-
card.className = 'permission-card';
|
|
16491
|
-
|
|
16492
|
-
const h4 = document.createElement('h4');
|
|
16493
|
-
h4.textContent = req.tool?.name || 'Permission';
|
|
16494
|
-
card.appendChild(h4);
|
|
16495
|
-
|
|
16496
|
-
const idDiv = document.createElement('div');
|
|
16497
|
-
idDiv.style.cssText = 'font-size:11px;color:var(--text2);margin-bottom:6px';
|
|
16498
|
-
idDiv.textContent = id;
|
|
16499
|
-
card.appendChild(idDiv);
|
|
16500
|
-
|
|
16501
|
-
// Show toolCall context (command, input, path, etc.) when available
|
|
16502
|
-
const tc = req.toolCall || req.tool;
|
|
16503
|
-
if (tc) {
|
|
16504
|
-
const detail = document.createElement('pre');
|
|
16505
|
-
detail.style.cssText = 'font-size:11px;color:var(--text2);margin-bottom:6px;white-space:pre-wrap;word-break:break-all;max-height:120px;overflow-y:auto;background:var(--bg);padding:6px;border-radius:4px;border:1px solid var(--border)';
|
|
16506
|
-
const parts = [];
|
|
16507
|
-
if (tc.command) parts.push('command: ' + tc.command);
|
|
16508
|
-
if (tc.input) parts.push('input: ' + (typeof tc.input === 'string' ? tc.input : JSON.stringify(tc.input, null, 2)));
|
|
16509
|
-
if (tc.path) parts.push('path: ' + tc.path);
|
|
16510
|
-
if (tc.diff) parts.push('diff: ' + tc.diff);
|
|
16511
|
-
if (tc.serverUrl) parts.push('url: ' + tc.serverUrl);
|
|
16512
|
-
if (parts.length === 0 && tc.name) parts.push('tool: ' + tc.name);
|
|
16513
|
-
if (parts.length > 0) {
|
|
16514
|
-
detail.textContent = parts.join('\\n');
|
|
16515
|
-
card.appendChild(detail);
|
|
16516
|
-
}
|
|
16517
|
-
}
|
|
16518
|
-
|
|
16519
|
-
function makePermBtn(reqId, optId, label, isCancel) {
|
|
16520
|
-
const btn = document.createElement('button');
|
|
16521
|
-
btn.className = 'btn opt-btn';
|
|
16522
|
-
btn.textContent = label;
|
|
16523
|
-
btn.dataset.req = reqId;
|
|
16524
|
-
if (isCancel) {
|
|
16525
|
-
btn.dataset.cancel = '1';
|
|
16526
|
-
btn.style.borderColor = 'var(--err)';
|
|
16527
|
-
btn.style.color = 'var(--err)';
|
|
16528
|
-
} else {
|
|
16529
|
-
btn.dataset.opt = optId;
|
|
16530
|
-
}
|
|
16531
|
-
btn.addEventListener('click', async () => {
|
|
16532
|
-
let outcome;
|
|
16533
|
-
if (isCancel) {
|
|
16534
|
-
outcome = { outcome: 'cancelled' };
|
|
16535
|
-
} else {
|
|
16536
|
-
outcome = { outcome: 'selected', optionId: optId };
|
|
16537
|
-
}
|
|
16538
|
-
const result = await api('POST', '/permission/' + reqId, { outcome });
|
|
16539
|
-
if (result.ok) {
|
|
16540
|
-
removePermission(reqId);
|
|
16541
|
-
} else {
|
|
16542
|
-
logError('PERM-ERR', 'Failed to resolve permission ' + reqId + ': ' + JSON.stringify(result.data));
|
|
16543
|
-
}
|
|
16544
|
-
});
|
|
16545
|
-
return btn;
|
|
16546
|
-
}
|
|
16547
|
-
|
|
16548
|
-
if (req.options && Array.isArray(req.options)) {
|
|
16549
|
-
for (const opt of req.options) {
|
|
16550
|
-
card.appendChild(makePermBtn(id, opt.optionId, opt.name || opt.optionId, false));
|
|
16551
|
-
}
|
|
16552
|
-
}
|
|
16553
|
-
card.appendChild(makePermBtn(id, null, 'Cancel', true));
|
|
16554
|
-
permissionList.appendChild(card);
|
|
16555
|
-
}
|
|
16556
|
-
}
|
|
16557
|
-
|
|
16558
|
-
// --- Button bindings ---
|
|
16559
|
-
$('#btnCreateSession').addEventListener('click', createSession);
|
|
16560
|
-
$('#btnListSessions').addEventListener('click', async () => {
|
|
16561
|
-
const cwd = cwdInput.value.trim();
|
|
16562
|
-
if (!cwd) { alert('Enter a cwd first'); return; }
|
|
16563
|
-
await api('GET', '/workspace/' + encodeURIComponent(cwd) + '/sessions');
|
|
16564
|
-
});
|
|
16565
|
-
$('#btnSendPrompt').addEventListener('click', () => sendPrompt(promptInput.value));
|
|
16566
|
-
$('#btnChatSend').addEventListener('click', () => sendPrompt(chatInput.value));
|
|
16567
|
-
chatInput.addEventListener('keydown', (e) => {
|
|
16568
|
-
if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); sendPrompt(chatInput.value); }
|
|
16569
|
-
});
|
|
16570
|
-
promptInput.addEventListener('keydown', (e) => {
|
|
16571
|
-
if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); sendPrompt(promptInput.value); }
|
|
16572
|
-
});
|
|
16573
|
-
$('#btnCancel').addEventListener('click', async () => {
|
|
16574
|
-
if (!sessionId) return;
|
|
16575
|
-
await api('POST', '/session/' + sessionId + '/cancel', {});
|
|
16576
|
-
});
|
|
16577
|
-
$('#btnSetModel').addEventListener('click', async () => {
|
|
16578
|
-
if (!sessionId) return;
|
|
16579
|
-
const mid = modelInput.value.trim();
|
|
16580
|
-
if (!mid) { alert('Enter a model ID'); return; }
|
|
16581
|
-
await api('POST', '/session/' + sessionId + '/model', { modelId: mid });
|
|
16582
|
-
});
|
|
16583
|
-
$('#btnHealth').addEventListener('click', () => api('GET', '/health'));
|
|
16584
|
-
$('#btnHealthDeep').addEventListener('click', () => api('GET', '/health?deep=1'));
|
|
16585
|
-
$('#btnCaps').addEventListener('click', () => api('GET', '/capabilities'));
|
|
16586
|
-
|
|
16587
|
-
// --- Init ---
|
|
16588
|
-
checkHealth();
|
|
16589
|
-
})();
|
|
16590
|
-
</script>
|
|
16591
|
-
</body>
|
|
16592
|
-
</html>`
|
|
16593
|
-
);
|
|
16594
|
-
}
|
|
16595
|
-
__name(getDemoHtml, "getDemoHtml");
|
|
16596
|
-
|
|
16597
|
-
// packages/cli/src/serve/routes/health-demo.ts
|
|
16598
|
-
function createHealthDemoRoutes(deps) {
|
|
16599
|
-
const {
|
|
16600
|
-
opts,
|
|
16601
|
-
getPort,
|
|
16602
|
-
workspaceRegistry,
|
|
16603
|
-
getActiveSseCount: getActiveSseCount2,
|
|
16604
|
-
getRateLimiter
|
|
16605
|
-
} = deps;
|
|
16606
|
-
const demoHandler = /* @__PURE__ */ __name((_req, res) => {
|
|
16607
|
-
try {
|
|
16608
|
-
res.type("html").set("X-Frame-Options", "DENY").set(
|
|
16609
|
-
"Content-Security-Policy",
|
|
16610
|
-
"default-src 'none'; script-src 'unsafe-inline'; style-src 'unsafe-inline'; connect-src 'self'; frame-ancestors 'none'"
|
|
16611
|
-
).send(getDemoHtml(getPort()));
|
|
16612
|
-
} catch (err) {
|
|
16613
|
-
writeStderrLine(
|
|
16614
|
-
`qwen serve: /demo render failed: ${err instanceof Error ? err.message : String(err)}`
|
|
16615
|
-
);
|
|
16616
|
-
res.status(500).json({ error: "Failed to render demo page" });
|
|
16617
|
-
}
|
|
16618
|
-
}, "demoHandler");
|
|
16570
|
+
function createHealthRoutes(deps) {
|
|
16571
|
+
const { opts, workspaceRegistry, getActiveSseCount: getActiveSseCount2, getRateLimiter } = deps;
|
|
16619
16572
|
const healthHandler = /* @__PURE__ */ __name((req, res) => {
|
|
16620
16573
|
if (!isDeepHealthQuery(req.query["deep"])) {
|
|
16621
16574
|
res.status(200).json({ status: "ok" });
|
|
@@ -16705,11 +16658,10 @@ function createHealthDemoRoutes(deps) {
|
|
|
16705
16658
|
exposeHealthPreAuth,
|
|
16706
16659
|
register(app) {
|
|
16707
16660
|
app.get("/health", healthHandler);
|
|
16708
|
-
app.get("/demo", demoHandler);
|
|
16709
16661
|
}
|
|
16710
16662
|
};
|
|
16711
16663
|
}
|
|
16712
|
-
__name(
|
|
16664
|
+
__name(createHealthRoutes, "createHealthRoutes");
|
|
16713
16665
|
|
|
16714
16666
|
// packages/cli/src/serve/routes/workspace-auth.ts
|
|
16715
16667
|
init_esbuild_shims();
|
|
@@ -22430,7 +22382,6 @@ __name(createWorkspaceRuntimeSessionService, "createWorkspaceRuntimeSessionServi
|
|
|
22430
22382
|
var GIT_RESERVED_BRANCH = "HEAD";
|
|
22431
22383
|
var MAX_BRANCH_NAME_BYTES = 1e3;
|
|
22432
22384
|
var MAX_BRANCH_COMPONENT_BYTES = 200;
|
|
22433
|
-
var HTTP_SESSION_ID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
22434
22385
|
var WORKSPACE_TRANSCRIPT_RESPONSE_MAX_BYTES = 2 * SESSION_TRANSCRIPT_MAX_EXPANDED_PAGE_BYTES;
|
|
22435
22386
|
var WORKSPACE_TRANSCRIPT_CURSOR_MAX_BYTES = 64 * 1024;
|
|
22436
22387
|
var TRANSCRIPT_CURSOR_TOO_LARGE_REPLAY_ERROR = "Transcript pagination state exceeds the safe limit";
|
|
@@ -22590,15 +22541,6 @@ function shouldPreserveTranscriptResolutionError(err) {
|
|
|
22590
22541
|
return err instanceof SessionArchivedError || err instanceof SessionConflictError || err instanceof SessionNotFoundError;
|
|
22591
22542
|
}
|
|
22592
22543
|
__name(shouldPreserveTranscriptResolutionError, "shouldPreserveTranscriptResolutionError");
|
|
22593
|
-
function isSessionLive(bridge, sessionId) {
|
|
22594
|
-
try {
|
|
22595
|
-
bridge.getSessionSummary(sessionId);
|
|
22596
|
-
return true;
|
|
22597
|
-
} catch (err) {
|
|
22598
|
-
return !(err instanceof SessionNotFoundError);
|
|
22599
|
-
}
|
|
22600
|
-
}
|
|
22601
|
-
__name(isSessionLive, "isSessionLive");
|
|
22602
22544
|
function parseOptionalApprovalMode(body, res) {
|
|
22603
22545
|
const rawApprovalMode = body["approvalMode"];
|
|
22604
22546
|
if (rawApprovalMode === void 0) {
|
|
@@ -22628,12 +22570,27 @@ function registerSessionRoutes(app, deps) {
|
|
|
22628
22570
|
sessionShellCommandEnabled,
|
|
22629
22571
|
virtualSubagentSessions
|
|
22630
22572
|
} = deps;
|
|
22573
|
+
const requestedSessionIdAdmission = deps.requestedSessionIdAdmission ?? createRequestedSessionIdAdmission({
|
|
22574
|
+
archiveCoordinator,
|
|
22575
|
+
getBridges: /* @__PURE__ */ __name(() => workspaceRegistry.listManaged().map((runtime) => runtime.bridge), "getBridges"),
|
|
22576
|
+
getPersistenceTargets: /* @__PURE__ */ __name(() => workspaceRegistry.listManaged().map((runtime) => ({
|
|
22577
|
+
workspaceCwd: runtime.workspaceCwd,
|
|
22578
|
+
runtimeBaseDir: runtime.sessionRuntimeBaseDir
|
|
22579
|
+
})), "getPersistenceTargets"),
|
|
22580
|
+
getBridgeWorkspaceId: /* @__PURE__ */ __name((bridge2) => workspaceRegistry.listEntries().find((entry) => entry.current?.runtime.bridge === bridge2)?.workspaceId, "getBridgeWorkspaceId")
|
|
22581
|
+
});
|
|
22582
|
+
const captureRuntimeGenerationAssertion = /* @__PURE__ */ __name((runtime) => {
|
|
22583
|
+
const registeredGeneration = workspaceRegistry.getEntryByWorkspaceId(
|
|
22584
|
+
runtime.workspaceId
|
|
22585
|
+
)?.current;
|
|
22586
|
+
const guard = registeredGeneration?.runtime === runtime ? registeredGeneration.guard : runtime.generationGuard;
|
|
22587
|
+
return guard ? () => guard.assertOpen() : void 0;
|
|
22588
|
+
}, "captureRuntimeGenerationAssertion");
|
|
22631
22589
|
const LANGUAGE_CODES = deps.languageCodes;
|
|
22632
22590
|
const transcriptCursorMasterKey = crypto3.randomBytes(32);
|
|
22633
22591
|
const transcriptCursorCodecs = /* @__PURE__ */ new Map();
|
|
22634
22592
|
const activeBranchSessions = /* @__PURE__ */ new Map();
|
|
22635
22593
|
const inFlightBranchWorkspaces = /* @__PURE__ */ new Set();
|
|
22636
|
-
const inFlightSessionIds = /* @__PURE__ */ new Set();
|
|
22637
22594
|
const clearBranchSessionEntry = /* @__PURE__ */ __name((sessionId) => {
|
|
22638
22595
|
for (const [cwd, sid] of activeBranchSessions) {
|
|
22639
22596
|
if (sid === sessionId) {
|
|
@@ -22695,6 +22652,20 @@ function registerSessionRoutes(app, deps) {
|
|
|
22695
22652
|
...details
|
|
22696
22653
|
});
|
|
22697
22654
|
}, "logSessionRoutingFailure");
|
|
22655
|
+
const sendRequestedSessionIdAdmissionError = /* @__PURE__ */ __name((res, error2, route) => {
|
|
22656
|
+
const resolutionKind = error2.code === "session_workspace_conflict" ? "workspace_conflict" : error2.code;
|
|
22657
|
+
logSessionRoutingFailure(route, resolutionKind, {
|
|
22658
|
+
sessionId: error2.sessionId,
|
|
22659
|
+
...error2.details
|
|
22660
|
+
});
|
|
22661
|
+
const status = error2.code === "session_id_admission_unavailable" ? 503 : 409;
|
|
22662
|
+
res.status(status).json({
|
|
22663
|
+
error: error2.message,
|
|
22664
|
+
code: error2.code,
|
|
22665
|
+
sessionId: error2.sessionId,
|
|
22666
|
+
...error2.details
|
|
22667
|
+
});
|
|
22668
|
+
}, "sendRequestedSessionIdAdmissionError");
|
|
22698
22669
|
const sendWorkspaceMismatch2 = /* @__PURE__ */ __name((res, requestedWorkspace) => {
|
|
22699
22670
|
const runtimes = workspaceRegistry.list();
|
|
22700
22671
|
if (runtimes.length > 1) {
|
|
@@ -22959,7 +22930,6 @@ function registerSessionRoutes(app, deps) {
|
|
|
22959
22930
|
sendUntrustedSessionOwner(res, route, sessionId, runtime);
|
|
22960
22931
|
return false;
|
|
22961
22932
|
}, "assertTrustedSessionOwner");
|
|
22962
|
-
const inFlightRestoreOwners = /* @__PURE__ */ new Map();
|
|
22963
22933
|
const sendSessionWorkspaceConflict = /* @__PURE__ */ __name((res, route, sessionId, runtime, liveRuntime) => {
|
|
22964
22934
|
logSessionRoutingFailure(route, "workspace_conflict", {
|
|
22965
22935
|
sessionId,
|
|
@@ -22978,33 +22948,6 @@ function registerSessionRoutes(app, deps) {
|
|
|
22978
22948
|
liveWorkspaceId: liveRuntime.workspaceId
|
|
22979
22949
|
});
|
|
22980
22950
|
}, "sendSessionWorkspaceConflict");
|
|
22981
|
-
const enterRestoreOwner = /* @__PURE__ */ __name((res, route, sessionId, runtime) => {
|
|
22982
|
-
const existing = inFlightRestoreOwners.get(sessionId);
|
|
22983
|
-
if (existing && existing.workspaceCwd !== runtime.workspaceCwd) {
|
|
22984
|
-
sendSessionWorkspaceConflict(res, route, sessionId, runtime, existing);
|
|
22985
|
-
return void 0;
|
|
22986
|
-
}
|
|
22987
|
-
if (existing) {
|
|
22988
|
-
existing.count += 1;
|
|
22989
|
-
} else {
|
|
22990
|
-
inFlightRestoreOwners.set(sessionId, {
|
|
22991
|
-
workspaceId: runtime.workspaceId,
|
|
22992
|
-
workspaceCwd: runtime.workspaceCwd,
|
|
22993
|
-
count: 1
|
|
22994
|
-
});
|
|
22995
|
-
}
|
|
22996
|
-
let released = false;
|
|
22997
|
-
return () => {
|
|
22998
|
-
if (released) return;
|
|
22999
|
-
released = true;
|
|
23000
|
-
const current = inFlightRestoreOwners.get(sessionId);
|
|
23001
|
-
if (!current || current.workspaceCwd !== runtime.workspaceCwd) return;
|
|
23002
|
-
current.count -= 1;
|
|
23003
|
-
if (current.count <= 0) {
|
|
23004
|
-
inFlightRestoreOwners.delete(sessionId);
|
|
23005
|
-
}
|
|
23006
|
-
};
|
|
23007
|
-
}, "enterRestoreOwner");
|
|
23008
22951
|
const resolveRuntimeForSessionRestore = /* @__PURE__ */ __name((body, res, route, sessionId) => {
|
|
23009
22952
|
const cwd = parseOptionalWorkspaceCwd(body, boundWorkspace, res);
|
|
23010
22953
|
if (cwd === void 0) return void 0;
|
|
@@ -23255,6 +23198,7 @@ function registerSessionRoutes(app, deps) {
|
|
|
23255
23198
|
});
|
|
23256
23199
|
return;
|
|
23257
23200
|
}
|
|
23201
|
+
const assertRuntimeGenerationOpen = captureRuntimeGenerationAssertion(runtime);
|
|
23258
23202
|
const modelServiceId = typeof body["modelServiceId"] === "string" ? body["modelServiceId"] : void 0;
|
|
23259
23203
|
const rawSessionScope = body["sessionScope"];
|
|
23260
23204
|
let sessionScope;
|
|
@@ -23287,52 +23231,39 @@ function registerSessionRoutes(app, deps) {
|
|
|
23287
23231
|
}
|
|
23288
23232
|
const clientId = parseClientIdHeader(req, res);
|
|
23289
23233
|
if (clientId === null) return;
|
|
23290
|
-
const
|
|
23291
|
-
|
|
23292
|
-
|
|
23293
|
-
|
|
23294
|
-
|
|
23295
|
-
|
|
23296
|
-
|
|
23297
|
-
|
|
23298
|
-
|
|
23299
|
-
|
|
23300
|
-
|
|
23301
|
-
|
|
23302
|
-
|
|
23303
|
-
|
|
23304
|
-
|
|
23305
|
-
|
|
23306
|
-
|
|
23307
|
-
|
|
23308
|
-
|
|
23309
|
-
|
|
23310
|
-
|
|
23311
|
-
|
|
23312
|
-
|
|
23313
|
-
|
|
23314
|
-
|
|
23315
|
-
|
|
23316
|
-
)) {
|
|
23317
|
-
res.status(409).json({
|
|
23318
|
-
error: `Session "${requestedSessionId}" already exists`,
|
|
23319
|
-
code: "session_id_conflict"
|
|
23320
|
-
});
|
|
23321
|
-
return;
|
|
23322
|
-
}
|
|
23323
|
-
if (inFlightSessionIds.has(requestedSessionId)) {
|
|
23324
|
-
res.status(409).json({
|
|
23325
|
-
error: `Session "${requestedSessionId}" creation already in progress`,
|
|
23326
|
-
code: "session_id_conflict"
|
|
23327
|
-
});
|
|
23328
|
-
return;
|
|
23234
|
+
const parsedSessionId = parseCallerSuppliedSessionId(body["sessionId"]);
|
|
23235
|
+
if (parsedSessionId.kind === "invalid") {
|
|
23236
|
+
res.status(400).json({
|
|
23237
|
+
error: '`sessionId` must be an RFC UUID v1-v5 (e.g. "550e8400-e29b-41d4-a716-446655440000")',
|
|
23238
|
+
code: "invalid_session_id"
|
|
23239
|
+
});
|
|
23240
|
+
return;
|
|
23241
|
+
}
|
|
23242
|
+
const requestedSessionId = parsedSessionId.kind === "valid" ? parsedSessionId.sessionId : void 0;
|
|
23243
|
+
let sessionIdReservation;
|
|
23244
|
+
if (requestedSessionId !== void 0) {
|
|
23245
|
+
try {
|
|
23246
|
+
sessionIdReservation = await requestedSessionIdAdmission.reserveCreate(
|
|
23247
|
+
requestedSessionId,
|
|
23248
|
+
{
|
|
23249
|
+
bridge: runtime.bridge,
|
|
23250
|
+
workspaceCwd,
|
|
23251
|
+
workspaceId: runtime.workspaceId
|
|
23252
|
+
}
|
|
23253
|
+
);
|
|
23254
|
+
} catch (error2) {
|
|
23255
|
+
if (error2 instanceof RequestedSessionIdAdmissionError) {
|
|
23256
|
+
sendRequestedSessionIdAdmissionError(res, error2, "POST /session");
|
|
23257
|
+
return;
|
|
23258
|
+
}
|
|
23259
|
+
throw error2;
|
|
23329
23260
|
}
|
|
23330
|
-
inFlightSessionIds.add(requestedSessionId);
|
|
23331
23261
|
}
|
|
23332
23262
|
let branchMeta;
|
|
23333
23263
|
let branchBaseCommit;
|
|
23334
23264
|
let worktreeMeta;
|
|
23335
23265
|
try {
|
|
23266
|
+
assertRuntimeGenerationOpen?.();
|
|
23336
23267
|
const rawBranch = body["branch"];
|
|
23337
23268
|
if (rawBranch !== void 0 && rawBranch !== null) {
|
|
23338
23269
|
if (body["worktree"] !== void 0 && body["worktree"] !== null) {
|
|
@@ -23440,6 +23371,7 @@ function registerSessionRoutes(app, deps) {
|
|
|
23440
23371
|
});
|
|
23441
23372
|
return;
|
|
23442
23373
|
}
|
|
23374
|
+
assertRuntimeGenerationOpen?.();
|
|
23443
23375
|
inFlightBranchWorkspaces.add(workspaceCwd);
|
|
23444
23376
|
try {
|
|
23445
23377
|
await createBranch(workspaceCwd, branchName);
|
|
@@ -23509,6 +23441,7 @@ function registerSessionRoutes(app, deps) {
|
|
|
23509
23441
|
return;
|
|
23510
23442
|
}
|
|
23511
23443
|
const baseBranch = await wtService.getCurrentBranch().catch(() => void 0);
|
|
23444
|
+
assertRuntimeGenerationOpen?.();
|
|
23512
23445
|
const wtResult = await wtService.createUserWorktree(slug, baseBranch);
|
|
23513
23446
|
if (!wtResult.success || !wtResult.worktree) {
|
|
23514
23447
|
res.status(500).json({
|
|
@@ -23527,6 +23460,7 @@ function registerSessionRoutes(app, deps) {
|
|
|
23527
23460
|
if (requestedSessionId !== void 0) {
|
|
23528
23461
|
sessionScope = "thread";
|
|
23529
23462
|
}
|
|
23463
|
+
assertRuntimeGenerationOpen?.();
|
|
23530
23464
|
const session = await runtime.bridge.spawnOrAttach({
|
|
23531
23465
|
workspaceCwd,
|
|
23532
23466
|
modelServiceId,
|
|
@@ -23556,6 +23490,9 @@ function registerSessionRoutes(app, deps) {
|
|
|
23556
23490
|
coordinator: archiveCoordinator
|
|
23557
23491
|
})
|
|
23558
23492
|
).catch(() => false);
|
|
23493
|
+
} else {
|
|
23494
|
+
await runtime.bridge.detachClient(session.sessionId, session.clientId).catch(() => {
|
|
23495
|
+
});
|
|
23559
23496
|
}
|
|
23560
23497
|
if (worktreeMeta) {
|
|
23561
23498
|
await new GitWorktreeService(workspaceCwd).removeUserWorktree(worktreeMeta.slug, { deleteBranch: true }).catch(() => {
|
|
@@ -23576,7 +23513,7 @@ function registerSessionRoutes(app, deps) {
|
|
|
23576
23513
|
return;
|
|
23577
23514
|
}
|
|
23578
23515
|
try {
|
|
23579
|
-
|
|
23516
|
+
assertRuntimeGenerationOpen?.();
|
|
23580
23517
|
} catch (error2) {
|
|
23581
23518
|
if (!session.attached) {
|
|
23582
23519
|
try {
|
|
@@ -23747,9 +23684,7 @@ function registerSessionRoutes(app, deps) {
|
|
|
23747
23684
|
}
|
|
23748
23685
|
sendBridgeError2(res, err, { route: "POST /session" });
|
|
23749
23686
|
} finally {
|
|
23750
|
-
|
|
23751
|
-
inFlightSessionIds.delete(requestedSessionId);
|
|
23752
|
-
}
|
|
23687
|
+
sessionIdReservation?.release();
|
|
23753
23688
|
}
|
|
23754
23689
|
});
|
|
23755
23690
|
const restoreSessionHandler = /* @__PURE__ */ __name((action) => async (req, res) => {
|
|
@@ -23820,27 +23755,29 @@ function registerSessionRoutes(app, deps) {
|
|
|
23820
23755
|
}
|
|
23821
23756
|
if (resolvedRuntime === void 0) return;
|
|
23822
23757
|
const { runtime, workspaceCwd } = resolvedRuntime;
|
|
23823
|
-
const
|
|
23824
|
-
res,
|
|
23825
|
-
route,
|
|
23826
|
-
sessionId,
|
|
23827
|
-
runtime
|
|
23828
|
-
);
|
|
23829
|
-
if (!releaseRestoreOwner) return;
|
|
23758
|
+
const assertRuntimeGenerationOpen = captureRuntimeGenerationAssertion(runtime);
|
|
23830
23759
|
const approvalMode = parseOptionalApprovalMode(body, res);
|
|
23831
|
-
if (approvalMode === null)
|
|
23832
|
-
releaseRestoreOwner();
|
|
23833
|
-
return;
|
|
23834
|
-
}
|
|
23760
|
+
if (approvalMode === null) return;
|
|
23835
23761
|
const historyPageSize = action === "load" ? parseHistoryPageSize(body ?? {}, res) : void 0;
|
|
23836
|
-
if (historyPageSize === null)
|
|
23837
|
-
releaseRestoreOwner();
|
|
23838
|
-
return;
|
|
23839
|
-
}
|
|
23762
|
+
if (historyPageSize === null) return;
|
|
23840
23763
|
const clientId = parseClientIdHeader(req, res);
|
|
23841
|
-
if (clientId === null)
|
|
23842
|
-
|
|
23843
|
-
|
|
23764
|
+
if (clientId === null) return;
|
|
23765
|
+
let sessionIdReservation;
|
|
23766
|
+
try {
|
|
23767
|
+
sessionIdReservation = requestedSessionIdAdmission.reserveRestore(
|
|
23768
|
+
sessionId,
|
|
23769
|
+
{
|
|
23770
|
+
bridge: runtime.bridge,
|
|
23771
|
+
workspaceCwd,
|
|
23772
|
+
workspaceId: runtime.workspaceId
|
|
23773
|
+
}
|
|
23774
|
+
);
|
|
23775
|
+
} catch (error2) {
|
|
23776
|
+
if (error2 instanceof RequestedSessionIdAdmissionError) {
|
|
23777
|
+
sendRequestedSessionIdAdmissionError(res, error2, route);
|
|
23778
|
+
return;
|
|
23779
|
+
}
|
|
23780
|
+
throw error2;
|
|
23844
23781
|
}
|
|
23845
23782
|
try {
|
|
23846
23783
|
const session = await archiveCoordinator.runSharedMany(
|
|
@@ -23867,7 +23804,7 @@ function registerSessionRoutes(app, deps) {
|
|
|
23867
23804
|
}
|
|
23868
23805
|
liveConversationCwd = await materialize(sessionId);
|
|
23869
23806
|
}
|
|
23870
|
-
|
|
23807
|
+
assertRuntimeGenerationOpen?.();
|
|
23871
23808
|
const restored = action === "load" ? await runtime.bridge.loadSession({
|
|
23872
23809
|
sessionId,
|
|
23873
23810
|
workspaceCwd,
|
|
@@ -23939,7 +23876,7 @@ function registerSessionRoutes(app, deps) {
|
|
|
23939
23876
|
}
|
|
23940
23877
|
);
|
|
23941
23878
|
try {
|
|
23942
|
-
|
|
23879
|
+
assertRuntimeGenerationOpen?.();
|
|
23943
23880
|
} catch (error2) {
|
|
23944
23881
|
if (!session.attached) {
|
|
23945
23882
|
await runtime.bridge.killSession(session.sessionId, { requireZeroAttaches: true }).catch(() => {
|
|
@@ -24041,7 +23978,7 @@ function registerSessionRoutes(app, deps) {
|
|
|
24041
23978
|
sessionId
|
|
24042
23979
|
});
|
|
24043
23980
|
} finally {
|
|
24044
|
-
|
|
23981
|
+
sessionIdReservation.release();
|
|
24045
23982
|
}
|
|
24046
23983
|
}, "restoreSessionHandler");
|
|
24047
23984
|
app.post("/session/:id/load", mutate(), restoreSessionHandler("load"));
|
|
@@ -27361,7 +27298,7 @@ function collectBoundSessionIds(tasks) {
|
|
|
27361
27298
|
return ids;
|
|
27362
27299
|
}
|
|
27363
27300
|
__name(collectBoundSessionIds, "collectBoundSessionIds");
|
|
27364
|
-
var KEEPALIVE_REVIVE_TIMEOUT_MS =
|
|
27301
|
+
var KEEPALIVE_REVIVE_TIMEOUT_MS = 7e4;
|
|
27365
27302
|
var KEEPALIVE_SPAWN_TIMEOUT_MS = 3e4;
|
|
27366
27303
|
var MAX_REVIVE_BACKOFF_MS = 30 * 6e4;
|
|
27367
27304
|
async function bindAndNameSessions(bridge, boundWorkspace, tasks, renamed, spawnTimeoutMs, binding, cleanupSession) {
|
|
@@ -27607,7 +27544,7 @@ function startScheduledTaskKeepalive(opts) {
|
|
|
27607
27544
|
};
|
|
27608
27545
|
}
|
|
27609
27546
|
__name(startScheduledTaskKeepalive, "startScheduledTaskKeepalive");
|
|
27610
|
-
var REHYDRATE_LOAD_TIMEOUT_MS =
|
|
27547
|
+
var REHYDRATE_LOAD_TIMEOUT_MS = 7e4;
|
|
27611
27548
|
var REHYDRATE_MAX_CONCURRENCY = 4;
|
|
27612
27549
|
async function rehydrateScheduledTaskSessions(deps) {
|
|
27613
27550
|
const { bridge, boundWorkspace } = deps;
|
|
@@ -27666,6 +27603,7 @@ async function rehydrateScheduledTaskSessions(deps) {
|
|
|
27666
27603
|
}
|
|
27667
27604
|
__name(rehydrateScheduledTaskSessions, "rehydrateScheduledTaskSessions");
|
|
27668
27605
|
function withTimeout(p, ms, label) {
|
|
27606
|
+
if (ms > MAX_SESSION_RESTORE_TIMEOUT_MS) return p;
|
|
27669
27607
|
return new Promise((resolve5, reject) => {
|
|
27670
27608
|
const timer = setTimeout(() => {
|
|
27671
27609
|
reject(new Error(`${label} timed out after ${ms}ms`));
|
|
@@ -28232,6 +28170,7 @@ function registerCapabilitiesRoutes(app, deps) {
|
|
|
28232
28170
|
maxPendingPromptsPerSession: advertisedMaxPendingPromptsPerSession(
|
|
28233
28171
|
deps.maxPendingPromptsPerSession
|
|
28234
28172
|
),
|
|
28173
|
+
sessionRestoreTimeoutMs: deps.sessionRestoreTimeoutMs,
|
|
28235
28174
|
...multiWorkspace ? {
|
|
28236
28175
|
maxSessionsPerWorkspace: advertisedMaxSessions(
|
|
28237
28176
|
deps.maxSessionsPerWorkspace
|
|
@@ -29056,6 +28995,25 @@ function bridgeErrorExtraContext(ctx) {
|
|
|
29056
28995
|
return extra;
|
|
29057
28996
|
}
|
|
29058
28997
|
__name(bridgeErrorExtraContext, "bridgeErrorExtraContext");
|
|
28998
|
+
function recordExpectedBridgeError(err, ctx, daemonLog) {
|
|
28999
|
+
recordDaemonBridgeError(err);
|
|
29000
|
+
recordDaemonError(void 0, err, {
|
|
29001
|
+
...ctx?.route ? { "http.route": ctx.route } : {},
|
|
29002
|
+
...ctx?.sessionId ? { "session.id": ctx.sessionId } : {}
|
|
29003
|
+
});
|
|
29004
|
+
emitDaemonLog("Daemon bridge request failed.", {
|
|
29005
|
+
...ctx?.route ? { "http.route": ctx.route } : {},
|
|
29006
|
+
...ctx?.sessionId ? { "session.id": ctx.sessionId } : {},
|
|
29007
|
+
"error.type": err.name,
|
|
29008
|
+
"error.message": err.message.slice(0, 1024)
|
|
29009
|
+
});
|
|
29010
|
+
daemonLog?.warn(err.message, {
|
|
29011
|
+
...ctx?.route ? { route: ctx.route } : {},
|
|
29012
|
+
...ctx?.sessionId ? { sessionId: ctx.sessionId } : {},
|
|
29013
|
+
errorType: err.name
|
|
29014
|
+
});
|
|
29015
|
+
}
|
|
29016
|
+
__name(recordExpectedBridgeError, "recordExpectedBridgeError");
|
|
29059
29017
|
function sendPermissionVoteError(res, err, ctx, daemonLog) {
|
|
29060
29018
|
if (err instanceof InvalidPermissionOptionError) {
|
|
29061
29019
|
res.status(400).json({
|
|
@@ -29097,6 +29055,33 @@ function sendPermissionVoteError(res, err, ctx, daemonLog) {
|
|
|
29097
29055
|
}
|
|
29098
29056
|
__name(sendPermissionVoteError, "sendPermissionVoteError");
|
|
29099
29057
|
function sendBridgeError(res, err, ctx, daemonLog) {
|
|
29058
|
+
if (err instanceof SessionRestoreTimeoutError) {
|
|
29059
|
+
recordExpectedBridgeError(err, ctx, daemonLog);
|
|
29060
|
+
res.set("Retry-After", String(restoreRetryAfterSeconds(err.timeoutMs)));
|
|
29061
|
+
res.status(504).json({
|
|
29062
|
+
error: err.message,
|
|
29063
|
+
code: "session_restore_timeout",
|
|
29064
|
+
errorKind: "restore_timeout",
|
|
29065
|
+
retryable: true,
|
|
29066
|
+
sessionId: err.sessionId,
|
|
29067
|
+
action: err.action,
|
|
29068
|
+
timeoutMs: err.timeoutMs
|
|
29069
|
+
});
|
|
29070
|
+
return;
|
|
29071
|
+
}
|
|
29072
|
+
if (err instanceof BridgeChannelQuarantinedError) {
|
|
29073
|
+
recordExpectedBridgeError(err, ctx, daemonLog);
|
|
29074
|
+
res.set("Retry-After", String(err.retryAfterSeconds));
|
|
29075
|
+
res.status(503).json({
|
|
29076
|
+
error: err.message,
|
|
29077
|
+
code: "acp_channel_unavailable",
|
|
29078
|
+
errorKind: "acp_channel_unavailable",
|
|
29079
|
+
retryable: true,
|
|
29080
|
+
reason: err.reason,
|
|
29081
|
+
retryAfterSeconds: err.retryAfterSeconds
|
|
29082
|
+
});
|
|
29083
|
+
return;
|
|
29084
|
+
}
|
|
29100
29085
|
if (err instanceof DaemonDrainingError) {
|
|
29101
29086
|
res.status(503).json({
|
|
29102
29087
|
error: err.message,
|
|
@@ -29114,22 +29099,9 @@ function sendBridgeError(res, err, ctx, daemonLog) {
|
|
|
29114
29099
|
});
|
|
29115
29100
|
return;
|
|
29116
29101
|
}
|
|
29117
|
-
|
|
29118
|
-
|
|
29119
|
-
|
|
29120
|
-
code: "skill_not_found",
|
|
29121
|
-
skillName: err.skillName
|
|
29122
|
-
});
|
|
29123
|
-
return;
|
|
29124
|
-
}
|
|
29125
|
-
if (err instanceof WorkspaceSkillNotToggleableError) {
|
|
29126
|
-
res.status(409).json({
|
|
29127
|
-
error: err.message,
|
|
29128
|
-
code: err.reason === "inactive_extension" ? "skill_inactive_extension" : "skill_not_toggleable",
|
|
29129
|
-
skillName: err.skillName,
|
|
29130
|
-
reason: err.reason,
|
|
29131
|
-
...err.lockedScope ? { lockedScope: err.lockedScope } : {}
|
|
29132
|
-
});
|
|
29102
|
+
const skillError = mapWorkspaceSkillToggleError(err);
|
|
29103
|
+
if (skillError) {
|
|
29104
|
+
res.status(skillError.code === "skill_not_found" ? 404 : 409).json(skillError);
|
|
29133
29105
|
return;
|
|
29134
29106
|
}
|
|
29135
29107
|
if (err instanceof InvalidSessionTranscriptCursorError) {
|
|
@@ -29395,10 +29367,12 @@ function sendBridgeError(res, err, ctx, daemonLog) {
|
|
|
29395
29367
|
return;
|
|
29396
29368
|
}
|
|
29397
29369
|
if (err instanceof RestoreInProgressError) {
|
|
29398
|
-
res.set("Retry-After",
|
|
29370
|
+
res.set("Retry-After", String(err.retryAfterSeconds));
|
|
29399
29371
|
res.status(409).json({
|
|
29400
29372
|
error: err.message,
|
|
29401
29373
|
code: "restore_in_progress",
|
|
29374
|
+
reason: err.reason,
|
|
29375
|
+
retryable: true,
|
|
29402
29376
|
sessionId: err.sessionId,
|
|
29403
29377
|
activeAction: err.activeAction,
|
|
29404
29378
|
requestedAction: err.requestedAction
|
|
@@ -35408,6 +35382,26 @@ __name(registerWorkspaceQualifiedToolsRoutes, "registerWorkspaceQualifiedToolsRo
|
|
|
35408
35382
|
|
|
35409
35383
|
// packages/cli/src/serve/routes/workspace-skills.ts
|
|
35410
35384
|
init_esbuild_shims();
|
|
35385
|
+
var MAX_WORKSPACE_SKILL_BATCH_SIZE = 100;
|
|
35386
|
+
function rejectSkillNameTooLong(skillName, res) {
|
|
35387
|
+
if (skillName.length <= MAX_WORKSPACE_SKILL_NAME_LENGTH) return false;
|
|
35388
|
+
res.status(400).json({
|
|
35389
|
+
error: `Skill name exceeds ${MAX_WORKSPACE_SKILL_NAME_LENGTH}-character limit`,
|
|
35390
|
+
code: "invalid_skill_name"
|
|
35391
|
+
});
|
|
35392
|
+
return true;
|
|
35393
|
+
}
|
|
35394
|
+
__name(rejectSkillNameTooLong, "rejectSkillNameTooLong");
|
|
35395
|
+
function parseEnabledFlag(body, res) {
|
|
35396
|
+
const enabled = body["enabled"];
|
|
35397
|
+
if (typeof enabled === "boolean") return { enabled };
|
|
35398
|
+
res.status(400).json({
|
|
35399
|
+
error: "`enabled` is required and must be a boolean",
|
|
35400
|
+
code: "invalid_enabled_flag"
|
|
35401
|
+
});
|
|
35402
|
+
return void 0;
|
|
35403
|
+
}
|
|
35404
|
+
__name(parseEnabledFlag, "parseEnabledFlag");
|
|
35411
35405
|
function parseSkillToggleRequest(req, res, safeBody2) {
|
|
35412
35406
|
const rawSkillName = req.params["name"];
|
|
35413
35407
|
if (!rawSkillName || typeof rawSkillName !== "string") {
|
|
@@ -35425,24 +35419,42 @@ function parseSkillToggleRequest(req, res, safeBody2) {
|
|
|
35425
35419
|
});
|
|
35426
35420
|
return void 0;
|
|
35427
35421
|
}
|
|
35428
|
-
if (skillName
|
|
35422
|
+
if (rejectSkillNameTooLong(skillName, res)) return void 0;
|
|
35423
|
+
const flag = parseEnabledFlag(safeBody2(req), res);
|
|
35424
|
+
return flag ? { skillName, enabled: flag.enabled } : void 0;
|
|
35425
|
+
}
|
|
35426
|
+
__name(parseSkillToggleRequest, "parseSkillToggleRequest");
|
|
35427
|
+
function parseSkillBatchToggleRequest(req, res, safeBody2) {
|
|
35428
|
+
const body = safeBody2(req);
|
|
35429
|
+
const rawSkillNames = body["skillNames"];
|
|
35430
|
+
if (!Array.isArray(rawSkillNames) || rawSkillNames.length === 0 || rawSkillNames.length > MAX_WORKSPACE_SKILL_BATCH_SIZE || !rawSkillNames.every((name) => typeof name === "string")) {
|
|
35429
35431
|
res.status(400).json({
|
|
35430
|
-
error:
|
|
35431
|
-
code: "
|
|
35432
|
+
error: `\`skillNames\` must be a non-empty string array (max ${MAX_WORKSPACE_SKILL_BATCH_SIZE})`,
|
|
35433
|
+
code: "invalid_skill_names"
|
|
35432
35434
|
});
|
|
35433
35435
|
return void 0;
|
|
35434
35436
|
}
|
|
35435
|
-
const
|
|
35436
|
-
|
|
35437
|
-
|
|
35438
|
-
|
|
35439
|
-
|
|
35440
|
-
|
|
35441
|
-
|
|
35437
|
+
const skillNames = [];
|
|
35438
|
+
const seen = /* @__PURE__ */ new Set();
|
|
35439
|
+
for (const rawSkillName of rawSkillNames) {
|
|
35440
|
+
const skillName = rawSkillName.trim();
|
|
35441
|
+
if (skillName.length === 0) {
|
|
35442
|
+
res.status(400).json({
|
|
35443
|
+
error: "Skill names must not be empty",
|
|
35444
|
+
code: "invalid_skill_name"
|
|
35445
|
+
});
|
|
35446
|
+
return void 0;
|
|
35447
|
+
}
|
|
35448
|
+
if (rejectSkillNameTooLong(skillName, res)) return void 0;
|
|
35449
|
+
const normalizedName = skillName.toLowerCase();
|
|
35450
|
+
if (seen.has(normalizedName)) continue;
|
|
35451
|
+
seen.add(normalizedName);
|
|
35452
|
+
skillNames.push(skillName);
|
|
35442
35453
|
}
|
|
35443
|
-
|
|
35454
|
+
const flag = parseEnabledFlag(body, res);
|
|
35455
|
+
return flag ? { skillNames, enabled: flag.enabled } : void 0;
|
|
35444
35456
|
}
|
|
35445
|
-
__name(
|
|
35457
|
+
__name(parseSkillBatchToggleRequest, "parseSkillBatchToggleRequest");
|
|
35446
35458
|
function parseSkillScope(value, res) {
|
|
35447
35459
|
if (value === "workspace" || value === "global") return value;
|
|
35448
35460
|
res.status(400).json({
|
|
@@ -35462,13 +35474,7 @@ function parseSkillInstallRequest(req, res, safeBody2) {
|
|
|
35462
35474
|
});
|
|
35463
35475
|
return void 0;
|
|
35464
35476
|
}
|
|
35465
|
-
if (name.trim()
|
|
35466
|
-
res.status(400).json({
|
|
35467
|
-
error: `Skill name exceeds ${MAX_WORKSPACE_SKILL_NAME_LENGTH}-character limit`,
|
|
35468
|
-
code: "invalid_skill_name"
|
|
35469
|
-
});
|
|
35470
|
-
return void 0;
|
|
35471
|
-
}
|
|
35477
|
+
if (rejectSkillNameTooLong(name.trim(), res)) return void 0;
|
|
35472
35478
|
const scope = parseSkillScope(body["scope"], res);
|
|
35473
35479
|
if (!scope) return void 0;
|
|
35474
35480
|
const rawSource = body["source"];
|
|
@@ -35522,6 +35528,7 @@ function registerWorkspaceSkillsRoutes(app, deps) {
|
|
|
35522
35528
|
deps.workspaceRuntime.workspaceCwd
|
|
35523
35529
|
);
|
|
35524
35530
|
const route = "POST /workspace/skills/:name/enable";
|
|
35531
|
+
const batchRoute = "POST /workspace/skills/enable";
|
|
35525
35532
|
app.post(
|
|
35526
35533
|
"/workspace/skills/install",
|
|
35527
35534
|
deps.mutate({ strict: true }),
|
|
@@ -35575,6 +35582,27 @@ function registerWorkspaceSkillsRoutes(app, deps) {
|
|
|
35575
35582
|
}
|
|
35576
35583
|
}
|
|
35577
35584
|
);
|
|
35585
|
+
app.post(
|
|
35586
|
+
"/workspace/skills/enable",
|
|
35587
|
+
deps.mutate({ strict: true }),
|
|
35588
|
+
async (req, res) => {
|
|
35589
|
+
if (!requireTrustedWorkspaceRuntime(deps.workspaceRuntime, res)) return;
|
|
35590
|
+
const input = parseSkillBatchToggleRequest(req, res, deps.safeBody);
|
|
35591
|
+
if (!input) return;
|
|
35592
|
+
const clientId = deps.parseAndValidateClientId(req, res);
|
|
35593
|
+
if (clientId === null) return;
|
|
35594
|
+
try {
|
|
35595
|
+
const result = await deps.workspaceRuntime.workspaceService.setWorkspaceSkillsEnabled(
|
|
35596
|
+
buildWorkspaceCtx(batchRoute, clientId),
|
|
35597
|
+
input.skillNames,
|
|
35598
|
+
input.enabled
|
|
35599
|
+
);
|
|
35600
|
+
res.status(200).json(result);
|
|
35601
|
+
} catch (err) {
|
|
35602
|
+
deps.sendBridgeError(res, err, { route: batchRoute });
|
|
35603
|
+
}
|
|
35604
|
+
}
|
|
35605
|
+
);
|
|
35578
35606
|
app.post(
|
|
35579
35607
|
"/workspace/skills/:name/enable",
|
|
35580
35608
|
deps.mutate({ strict: true }),
|
|
@@ -35600,6 +35628,7 @@ function registerWorkspaceSkillsRoutes(app, deps) {
|
|
|
35600
35628
|
__name(registerWorkspaceSkillsRoutes, "registerWorkspaceSkillsRoutes");
|
|
35601
35629
|
function registerWorkspaceQualifiedSkillsRoutes(app, deps) {
|
|
35602
35630
|
const route = "POST /workspaces/:workspace/skills/:name/enable";
|
|
35631
|
+
const batchRoute = "POST /workspaces/:workspace/skills/enable";
|
|
35603
35632
|
app.post(
|
|
35604
35633
|
"/workspaces/:workspace/skills/install",
|
|
35605
35634
|
deps.mutate({ strict: true }),
|
|
@@ -35671,6 +35700,36 @@ function registerWorkspaceQualifiedSkillsRoutes(app, deps) {
|
|
|
35671
35700
|
}
|
|
35672
35701
|
}
|
|
35673
35702
|
);
|
|
35703
|
+
app.post(
|
|
35704
|
+
"/workspaces/:workspace/skills/enable",
|
|
35705
|
+
deps.mutate({ strict: true }),
|
|
35706
|
+
async (req, res) => {
|
|
35707
|
+
const runtime = resolveWorkspaceRuntimeFromParam(
|
|
35708
|
+
deps.workspaceRegistry,
|
|
35709
|
+
req,
|
|
35710
|
+
res
|
|
35711
|
+
);
|
|
35712
|
+
if (!runtime || !requireTrustedWorkspaceRuntime(runtime, res)) return;
|
|
35713
|
+
const input = parseSkillBatchToggleRequest(req, res, deps.safeBody);
|
|
35714
|
+
if (!input) return;
|
|
35715
|
+
const clientId = parseAndValidateWorkspaceClientId(
|
|
35716
|
+
req,
|
|
35717
|
+
res,
|
|
35718
|
+
runtime.bridge
|
|
35719
|
+
);
|
|
35720
|
+
if (clientId === null) return;
|
|
35721
|
+
try {
|
|
35722
|
+
const result = await runtime.workspaceService.setWorkspaceSkillsEnabled(
|
|
35723
|
+
createBuildWorkspaceCtx(runtime.workspaceCwd)(batchRoute, clientId),
|
|
35724
|
+
input.skillNames,
|
|
35725
|
+
input.enabled
|
|
35726
|
+
);
|
|
35727
|
+
res.status(200).json(result);
|
|
35728
|
+
} catch (err) {
|
|
35729
|
+
deps.sendBridgeError(res, err, { route: batchRoute });
|
|
35730
|
+
}
|
|
35731
|
+
}
|
|
35732
|
+
);
|
|
35674
35733
|
app.post(
|
|
35675
35734
|
"/workspaces/:workspace/skills/:name/enable",
|
|
35676
35735
|
deps.mutate({ strict: true }),
|
|
@@ -39265,11 +39324,13 @@ var execFileAsync3 = promisify3(execFile3);
|
|
|
39265
39324
|
var LIVE_HOST_BUNDLE_ID2 = "com.alibaba.qwen-code.live-host";
|
|
39266
39325
|
var LIVE_HOST_TEAM_IDENTIFIER = "NF4574S59H";
|
|
39267
39326
|
var LIVE_HOST_APP_PATH = "/Applications/Qwen Live Host.app";
|
|
39327
|
+
var LIVE_HOST_OSS_BASE_URL = "https://qwen-code-assets.oss-cn-hangzhou.aliyuncs.com/live-host";
|
|
39268
39328
|
var LIVE_HOST_RELEASE_BASE_URL = "https://github.com/QwenLM/qwen-code/releases/download/live-host-latest";
|
|
39269
39329
|
var LIVE_HOST_MANIFEST_NAME = "Qwen-Live-Host-manifest.json";
|
|
39330
|
+
var LIVE_HOST_MANIFEST_FETCH_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
39331
|
+
var LIVE_HOST_DOWNLOAD_TIMEOUT_MS = 60 * 60 * 1e3;
|
|
39270
39332
|
var LIVE_HOST_APP_NAME = "Qwen Live Host.app";
|
|
39271
39333
|
var MAX_DOWNLOAD_BYTES = 512 * 1024 * 1024;
|
|
39272
|
-
var FETCH_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
39273
39334
|
var COMMAND_TIMEOUT_MS = 2 * 60 * 1e3;
|
|
39274
39335
|
var SHA256_PATTERN = /^[a-f0-9]{64}$/;
|
|
39275
39336
|
var VERSION_PATTERN = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/;
|
|
@@ -39385,11 +39446,24 @@ async function inspectInstalledHost() {
|
|
|
39385
39446
|
}
|
|
39386
39447
|
}
|
|
39387
39448
|
__name(inspectInstalledHost, "inspectInstalledHost");
|
|
39388
|
-
|
|
39389
|
-
|
|
39390
|
-
`${
|
|
39391
|
-
{
|
|
39392
|
-
|
|
39449
|
+
function resolveLiveHostManifestUrls() {
|
|
39450
|
+
return [
|
|
39451
|
+
`${LIVE_HOST_OSS_BASE_URL}/latest/${LIVE_HOST_MANIFEST_NAME}`,
|
|
39452
|
+
`${LIVE_HOST_RELEASE_BASE_URL}/${LIVE_HOST_MANIFEST_NAME}`
|
|
39453
|
+
];
|
|
39454
|
+
}
|
|
39455
|
+
__name(resolveLiveHostManifestUrls, "resolveLiveHostManifestUrls");
|
|
39456
|
+
function resolveLiveHostAssetUrls(version, assetName) {
|
|
39457
|
+
return [
|
|
39458
|
+
`${LIVE_HOST_OSS_BASE_URL}/v${version}/${assetName}`,
|
|
39459
|
+
`${LIVE_HOST_RELEASE_BASE_URL}/${assetName}`
|
|
39460
|
+
];
|
|
39461
|
+
}
|
|
39462
|
+
__name(resolveLiveHostAssetUrls, "resolveLiveHostAssetUrls");
|
|
39463
|
+
async function fetchManifest(url, fetchImpl) {
|
|
39464
|
+
const response = await fetchImpl(url, {
|
|
39465
|
+
signal: AbortSignal.timeout(LIVE_HOST_MANIFEST_FETCH_TIMEOUT_MS)
|
|
39466
|
+
});
|
|
39393
39467
|
if (!response.ok) {
|
|
39394
39468
|
await response.body?.cancel().catch(() => {
|
|
39395
39469
|
});
|
|
@@ -39398,9 +39472,9 @@ async function fetchManifest() {
|
|
|
39398
39472
|
return parseLiveHostReleaseManifest(await response.json());
|
|
39399
39473
|
}
|
|
39400
39474
|
__name(fetchManifest, "fetchManifest");
|
|
39401
|
-
async function downloadAsset(asset, destination, onProgress) {
|
|
39402
|
-
const response = await
|
|
39403
|
-
signal: AbortSignal.timeout(
|
|
39475
|
+
async function downloadAsset(asset, url, destination, onProgress, fetchImpl) {
|
|
39476
|
+
const response = await fetchImpl(url, {
|
|
39477
|
+
signal: AbortSignal.timeout(LIVE_HOST_DOWNLOAD_TIMEOUT_MS)
|
|
39404
39478
|
});
|
|
39405
39479
|
if (!response.ok || !response.body) {
|
|
39406
39480
|
await response.body?.cancel().catch(() => {
|
|
@@ -39437,13 +39511,36 @@ async function downloadAsset(asset, destination, onProgress) {
|
|
|
39437
39511
|
}
|
|
39438
39512
|
}
|
|
39439
39513
|
__name(downloadAsset, "downloadAsset");
|
|
39514
|
+
async function downloadLiveHostRelease(currentArchitecture, destination, onProgress, fetchImpl = fetch) {
|
|
39515
|
+
const manifestUrls = resolveLiveHostManifestUrls();
|
|
39516
|
+
const labels = ["OSS", "GitHub"];
|
|
39517
|
+
const errors = [];
|
|
39518
|
+
for (let index = 0; index < manifestUrls.length; index += 1) {
|
|
39519
|
+
try {
|
|
39520
|
+
await fsp5.rm(destination, { force: true });
|
|
39521
|
+
const manifest = await fetchManifest(manifestUrls[index], fetchImpl);
|
|
39522
|
+
const asset = manifest.assets[currentArchitecture];
|
|
39523
|
+
const assetUrl = resolveLiveHostAssetUrls(manifest.version, asset.name)[index];
|
|
39524
|
+
await downloadAsset(asset, assetUrl, destination, onProgress, fetchImpl);
|
|
39525
|
+
return { manifest, asset };
|
|
39526
|
+
} catch (error2) {
|
|
39527
|
+
errors.push(
|
|
39528
|
+
new Error(`${labels[index]}: ${errorMessage3(error2)}`, { cause: error2 })
|
|
39529
|
+
);
|
|
39530
|
+
}
|
|
39531
|
+
}
|
|
39532
|
+
await fsp5.rm(destination, { force: true });
|
|
39533
|
+
throw new AggregateError(
|
|
39534
|
+
errors,
|
|
39535
|
+
`Qwen Live Host download failed. ${errors.map((error2) => error2.message).join(" ")}`
|
|
39536
|
+
);
|
|
39537
|
+
}
|
|
39538
|
+
__name(downloadLiveHostRelease, "downloadLiveHostRelease");
|
|
39440
39539
|
async function installLatestHost(currentArchitecture, onStatus) {
|
|
39441
|
-
const manifest = await fetchManifest();
|
|
39442
|
-
const asset = manifest.assets[currentArchitecture];
|
|
39443
39540
|
const temporaryDirectory = await fsp5.mkdtemp(
|
|
39444
39541
|
path14.join(os2.tmpdir(), "qwen-live-host-")
|
|
39445
39542
|
);
|
|
39446
|
-
const archivePath = path14.join(temporaryDirectory,
|
|
39543
|
+
const archivePath = path14.join(temporaryDirectory, "Qwen-Live-Host.zip");
|
|
39447
39544
|
const extractedPath = path14.join(temporaryDirectory, "extracted");
|
|
39448
39545
|
const candidatePath = path14.join(extractedPath, LIVE_HOST_APP_NAME);
|
|
39449
39546
|
const stagingPath = `/Applications/.Qwen Live Host.install-${randomUUID11()}.app`;
|
|
@@ -39452,9 +39549,13 @@ async function installLatestHost(currentArchitecture, onStatus) {
|
|
|
39452
39549
|
let installedCandidate = false;
|
|
39453
39550
|
try {
|
|
39454
39551
|
onStatus({ state: "downloading", progress: 0 });
|
|
39455
|
-
|
|
39456
|
-
|
|
39457
|
-
|
|
39552
|
+
const { manifest } = await downloadLiveHostRelease(
|
|
39553
|
+
currentArchitecture,
|
|
39554
|
+
archivePath,
|
|
39555
|
+
(progress) => {
|
|
39556
|
+
onStatus({ state: "downloading", progress });
|
|
39557
|
+
}
|
|
39558
|
+
);
|
|
39458
39559
|
onStatus({ state: "verifying" });
|
|
39459
39560
|
await fsp5.mkdir(extractedPath, { mode: 448 });
|
|
39460
39561
|
await run("/usr/bin/ditto", ["-x", "-k", archivePath, extractedPath]);
|
|
@@ -42286,6 +42387,7 @@ function getRuntimeEffectiveEnv(metadata) {
|
|
|
42286
42387
|
}
|
|
42287
42388
|
__name(getRuntimeEffectiveEnv, "getRuntimeEffectiveEnv");
|
|
42288
42389
|
var DEFAULT_SESSION_IDLE_TIMEOUT_MS = 30 * 6e4;
|
|
42390
|
+
var SCHEDULED_TASK_RESTORE_HEADROOM_MS = 1e4;
|
|
42289
42391
|
var KEEPALIVE_MIN_INTERVAL_MS = 3e4;
|
|
42290
42392
|
var KEEPALIVE_MAX_INTERVAL_MS = 10 * 6e4;
|
|
42291
42393
|
function computeKeepaliveIntervalMs(idleTimeoutMs) {
|
|
@@ -42327,11 +42429,18 @@ function createLiveWorkspaceDelegate(getTarget) {
|
|
|
42327
42429
|
}
|
|
42328
42430
|
__name(createLiveWorkspaceDelegate, "createLiveWorkspaceDelegate");
|
|
42329
42431
|
function createServeApp(opts, getPort = () => opts.port, deps = {}) {
|
|
42432
|
+
const sessionRestoreTimeoutMs = resolveSessionRestoreTimeoutMs(opts);
|
|
42433
|
+
const scheduledTaskRestoreTimeoutMs = sessionRestoreTimeoutMs + SCHEDULED_TASK_RESTORE_HEADROOM_MS > MAX_SESSION_RESTORE_TIMEOUT_MS ? MAX_SESSION_RESTORE_TIMEOUT_MS + 1 : sessionRestoreTimeoutMs + SCHEDULED_TASK_RESTORE_HEADROOM_MS;
|
|
42330
42434
|
if (deps.workspaceRuntimeRemoval && !deps.voiceCoordinator) {
|
|
42331
42435
|
throw new Error(
|
|
42332
42436
|
"createServeApp: deps.workspaceRuntimeRemoval requires the matching deps.voiceCoordinator."
|
|
42333
42437
|
);
|
|
42334
42438
|
}
|
|
42439
|
+
if ((deps.workspaceTrustHotReloadAvailable === true || deps.workspaceRuntimeRemoval !== void 0) && deps.getSessionBridges === void 0) {
|
|
42440
|
+
throw new Error(
|
|
42441
|
+
"createServeApp: runtime replacement/removal requires deps.getSessionBridges so session-id admission can inspect draining generations."
|
|
42442
|
+
);
|
|
42443
|
+
}
|
|
42335
42444
|
const app = (0, import_express5.default)();
|
|
42336
42445
|
const injectedWorkspaceRegistry = deps.workspaceRegistry;
|
|
42337
42446
|
const boundWorkspace = injectedWorkspaceRegistry?.primary.workspaceCwd ?? deps.boundWorkspace ?? canonicalizeWorkspace(opts.workspace ?? process.cwd());
|
|
@@ -42503,6 +42612,7 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
|
|
|
42503
42612
|
maxJournalEvents: opts.maxJournalEvents,
|
|
42504
42613
|
maxJournalBytes: opts.maxJournalBytes,
|
|
42505
42614
|
initializeTimeoutMs: opts.initializeTimeoutMs,
|
|
42615
|
+
sessionRestoreTimeoutMs,
|
|
42506
42616
|
permissionResponseTimeoutMs: opts.permissionResponseTimeoutMs,
|
|
42507
42617
|
boundWorkspace,
|
|
42508
42618
|
sessionShellCommandEnabled,
|
|
@@ -42510,9 +42620,12 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
|
|
|
42510
42620
|
// that don't inject `deps.bridge` get daemon env + preflight cells.
|
|
42511
42621
|
statusProvider,
|
|
42512
42622
|
delegateReadTextFileToClient: false,
|
|
42513
|
-
// Final ACP text writes remain delegated
|
|
42623
|
+
// Final ACP text writes remain delegated. Workspace writes use WFS;
|
|
42624
|
+
// marked same-host tool writes may use the factory's host writer.
|
|
42514
42625
|
// Unexpected delegated reads still fail closed at the WFS boundary.
|
|
42515
|
-
fileSystem: createBridgeFileSystemAdapter(fsFactory
|
|
42626
|
+
fileSystem: createBridgeFileSystemAdapter(fsFactory, {
|
|
42627
|
+
allowSameHostToolWritesOutsideWorkspace: deps.fsFactory === void 0
|
|
42628
|
+
}),
|
|
42516
42629
|
// Reverse tool channel: answer the child's `client_mcp/message`
|
|
42517
42630
|
// ext-method by reaching the WS connection that hosts the named server.
|
|
42518
42631
|
clientMcpSender: clientMcpSenderRegistry.lookup
|
|
@@ -42578,6 +42691,11 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
|
|
|
42578
42691
|
"setWorkspaceSkillEnabled requires persistDisabledSkills in ServeAppDeps"
|
|
42579
42692
|
);
|
|
42580
42693
|
}),
|
|
42694
|
+
persistDisabledSkillsBatch: deps.persistDisabledSkillsBatch ?? (async () => {
|
|
42695
|
+
throw new Error(
|
|
42696
|
+
"setWorkspaceSkillsEnabled requires persistDisabledSkillsBatch in ServeAppDeps"
|
|
42697
|
+
);
|
|
42698
|
+
}),
|
|
42581
42699
|
queryWorkspaceStatus: /* @__PURE__ */ __name((method, idle) => bridge.queryWorkspaceStatus(method, idle), "queryWorkspaceStatus"),
|
|
42582
42700
|
invokeWorkspaceCommand: /* @__PURE__ */ __name((method, params, invokeOpts) => bridge.invokeWorkspaceCommand(method, params, invokeOpts), "invokeWorkspaceCommand"),
|
|
42583
42701
|
preheatAcpChild: /* @__PURE__ */ __name(() => bridge.preheat(), "preheatAcpChild"),
|
|
@@ -42613,6 +42731,15 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
|
|
|
42613
42731
|
} : {}
|
|
42614
42732
|
);
|
|
42615
42733
|
app.locals.workspaceRegistry = workspaceRegistry;
|
|
42734
|
+
const requestedSessionIdAdmission = createRequestedSessionIdAdmission({
|
|
42735
|
+
archiveCoordinator,
|
|
42736
|
+
getBridges: deps.getSessionBridges ?? (() => workspaceRegistry.listManaged().map((runtime) => runtime.bridge)),
|
|
42737
|
+
getPersistenceTargets: /* @__PURE__ */ __name(() => workspaceRegistry.listManaged().map((runtime) => ({
|
|
42738
|
+
workspaceCwd: runtime.workspaceCwd,
|
|
42739
|
+
runtimeBaseDir: runtime.sessionRuntimeBaseDir
|
|
42740
|
+
})), "getPersistenceTargets"),
|
|
42741
|
+
getBridgeWorkspaceId: /* @__PURE__ */ __name((bridge2) => workspaceRegistry.listEntries().find((entry) => entry.current?.runtime.bridge === bridge2)?.workspaceId, "getBridgeWorkspaceId")
|
|
42742
|
+
});
|
|
42616
42743
|
primaryTrustRegistry = workspaceRegistry;
|
|
42617
42744
|
const primaryRuntime = createLiveWorkspaceDelegate(
|
|
42618
42745
|
() => workspaceRegistry.primary
|
|
@@ -42935,15 +43062,14 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
|
|
|
42935
43062
|
mount: false,
|
|
42936
43063
|
workspaceQualifiedAcpEnabled
|
|
42937
43064
|
});
|
|
42938
|
-
const
|
|
43065
|
+
const healthRoutes = createHealthRoutes({
|
|
42939
43066
|
opts,
|
|
42940
|
-
getPort,
|
|
42941
43067
|
workspaceRegistry,
|
|
42942
43068
|
getActiveSseCount,
|
|
42943
43069
|
getRateLimiter: /* @__PURE__ */ __name(() => rateLimiter, "getRateLimiter")
|
|
42944
43070
|
});
|
|
42945
|
-
if (
|
|
42946
|
-
|
|
43071
|
+
if (healthRoutes.exposeHealthPreAuth) {
|
|
43072
|
+
healthRoutes.register(app);
|
|
42947
43073
|
}
|
|
42948
43074
|
installAccessLogMiddleware(app, daemonLog);
|
|
42949
43075
|
const webShellDir = opts.serveWebShell !== false ? deps.webShellDir : void 0;
|
|
@@ -42990,8 +43116,8 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
|
|
|
42990
43116
|
if (rateLimiter) {
|
|
42991
43117
|
app.use(rateLimiter.middleware);
|
|
42992
43118
|
}
|
|
42993
|
-
if (!
|
|
42994
|
-
|
|
43119
|
+
if (!healthRoutes.exposeHealthPreAuth) {
|
|
43120
|
+
healthRoutes.register(app);
|
|
42995
43121
|
}
|
|
42996
43122
|
installJsonBodyParser(app);
|
|
42997
43123
|
const mutate = createMutationGate({
|
|
@@ -43066,6 +43192,7 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
|
|
|
43066
43192
|
maxSessionsPerWorkspace: opts.maxSessions,
|
|
43067
43193
|
maxTotalSessions: opts.maxTotalSessions,
|
|
43068
43194
|
maxPendingPromptsPerSession: opts.maxPendingPromptsPerSession,
|
|
43195
|
+
sessionRestoreTimeoutMs,
|
|
43069
43196
|
languageCodes
|
|
43070
43197
|
});
|
|
43071
43198
|
if (liveVoiceSurfaceAvailable) {
|
|
@@ -43477,6 +43604,7 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
|
|
|
43477
43604
|
bridge: primaryBridge,
|
|
43478
43605
|
workspaceRegistry,
|
|
43479
43606
|
archiveCoordinator,
|
|
43607
|
+
requestedSessionIdAdmission,
|
|
43480
43608
|
mutate,
|
|
43481
43609
|
sendBridgeError: sendBridgeError2,
|
|
43482
43610
|
daemonLog,
|
|
@@ -43643,6 +43771,7 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
|
|
|
43643
43771
|
() => rehydrateScheduledTaskSessions({
|
|
43644
43772
|
bridge: runtime.bridge,
|
|
43645
43773
|
boundWorkspace: runtime.workspaceCwd,
|
|
43774
|
+
loadTimeoutMs: scheduledTaskRestoreTimeoutMs,
|
|
43646
43775
|
onTasksRead: /* @__PURE__ */ __name((tasks) => registerScheduledTaskAuthorizations(runtime.workspaceCwd, tasks), "onTasksRead"),
|
|
43647
43776
|
onError: /* @__PURE__ */ __name((sessionId, err) => {
|
|
43648
43777
|
process.stderr.write(
|
|
@@ -43673,6 +43802,7 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
|
|
|
43673
43802
|
bridge: runtime.bridge,
|
|
43674
43803
|
boundWorkspace: runtime.workspaceCwd,
|
|
43675
43804
|
intervalMs: keepaliveIntervalMs,
|
|
43805
|
+
reviveTimeoutMs: scheduledTaskRestoreTimeoutMs,
|
|
43676
43806
|
runtimeBaseDir: runtime.sessionRuntimeBaseDir,
|
|
43677
43807
|
cleanupSession: /* @__PURE__ */ __name((sessionId) => cleanupSession(runtime, sessionId), "cleanupSession"),
|
|
43678
43808
|
onTasksRead: /* @__PURE__ */ __name((tasks) => registerScheduledTaskAuthorizations(runtime.workspaceCwd, tasks), "onTasksRead")
|
|
@@ -43717,6 +43847,7 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
|
|
|
43717
43847
|
workspaceRegistry,
|
|
43718
43848
|
isPrimaryWorkspaceTrusted,
|
|
43719
43849
|
archiveCoordinator,
|
|
43850
|
+
requestedSessionIdAdmission,
|
|
43720
43851
|
workspace: primaryWorkspace,
|
|
43721
43852
|
fsFactory: primaryRouteFileSystemFactory,
|
|
43722
43853
|
deviceFlowRegistry,
|