gong-code 0.1.0
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 +38 -0
- package/dist/SKILL-22jccbka.md +1 -0
- package/dist/chunk-01wdn84e.js +8 -0
- package/dist/chunk-04bc74vz.js +243 -0
- package/dist/chunk-05t2vqsb.js +490 -0
- package/dist/chunk-0727wret.js +159 -0
- package/dist/chunk-07rervty.js +200 -0
- package/dist/chunk-0b9nxvyg.js +478 -0
- package/dist/chunk-0e428b73.js +600 -0
- package/dist/chunk-0hqfheht.js +3439 -0
- package/dist/chunk-0pnk52c2.js +116 -0
- package/dist/chunk-0sbddf6m.js +68 -0
- package/dist/chunk-0vf7xb84.js +176 -0
- package/dist/chunk-0yz17yjy.js +1061 -0
- package/dist/chunk-0zscb6c7.js +10 -0
- package/dist/chunk-10p21kq6.js +378 -0
- package/dist/chunk-17k78pmz.js +120 -0
- package/dist/chunk-19jvvqzp.js +1390 -0
- package/dist/chunk-1d5czqnr.js +173 -0
- package/dist/chunk-1gjysfnf.js +13876 -0
- package/dist/chunk-1jjfv0wd.js +467 -0
- package/dist/chunk-1jjzp2pa.js +617 -0
- package/dist/chunk-1m38dj2k.js +155 -0
- package/dist/chunk-1pgttway.js +211 -0
- package/dist/chunk-1vvnx0gb.js +8035 -0
- package/dist/chunk-1ztm9yps.js +49145 -0
- package/dist/chunk-208x1t0m.js +88 -0
- package/dist/chunk-20xqs3yk.js +843 -0
- package/dist/chunk-2b2c0wnn.js +584 -0
- package/dist/chunk-2g07117j.js +541 -0
- package/dist/chunk-2g6p2t3w.js +780 -0
- package/dist/chunk-2kjeaeg7.js +28 -0
- package/dist/chunk-2n0s2dhc.js +12 -0
- package/dist/chunk-2p0hvt8k.js +785 -0
- package/dist/chunk-2qmxg9y7.js +40174 -0
- package/dist/chunk-2qpy8kne.js +28 -0
- package/dist/chunk-2rgbf62a.js +40 -0
- package/dist/chunk-2tx0s41y.js +150 -0
- package/dist/chunk-2x8zk5cz.js +101 -0
- package/dist/chunk-2yqy25z4.js +48 -0
- package/dist/chunk-318g78ty.js +552 -0
- package/dist/chunk-31gfg8tz.js +290 -0
- package/dist/chunk-32n0s532.js +1317 -0
- package/dist/chunk-35dw2r9g.js +137 -0
- package/dist/chunk-36b5zqvn.js +1865 -0
- package/dist/chunk-38kpx69j.js +97 -0
- package/dist/chunk-3b01vp8p.js +815 -0
- package/dist/chunk-3f76a1ek.js +317 -0
- package/dist/chunk-3fd1hkhh.js +4254 -0
- package/dist/chunk-3ffxa7zj.js +8 -0
- package/dist/chunk-3gcj7w95.js +8 -0
- package/dist/chunk-3jf3k40v.js +970 -0
- package/dist/chunk-3k51qfp9.js +9301 -0
- package/dist/chunk-3mhygd2v.js +1180 -0
- package/dist/chunk-3p6y0gvb.js +117 -0
- package/dist/chunk-3r60xdt5.js +93 -0
- package/dist/chunk-43agf6xv.js +8 -0
- package/dist/chunk-46zr418r.js +15 -0
- package/dist/chunk-48k2bs4w.js +118 -0
- package/dist/chunk-4p987a4z.js +84 -0
- package/dist/chunk-4px25pe0.js +776 -0
- package/dist/chunk-4s93jyky.js +113 -0
- package/dist/chunk-4xv8bedf.js +58 -0
- package/dist/chunk-4y382mzd.js +346 -0
- package/dist/chunk-52dzw4bc.js +246 -0
- package/dist/chunk-52qqmh5g.js +110 -0
- package/dist/chunk-53grnhp7.js +8 -0
- package/dist/chunk-59craaxx.js +4249 -0
- package/dist/chunk-5b833jqs.js +96 -0
- package/dist/chunk-5cp2q9sh.js +58 -0
- package/dist/chunk-5dbaxmts.js +87 -0
- package/dist/chunk-5f5sxgp0.js +96 -0
- package/dist/chunk-5mkfderj.js +195 -0
- package/dist/chunk-5qw0mpvq.js +389 -0
- package/dist/chunk-5rxmszm8.js +48 -0
- package/dist/chunk-5ygxa3hr.js +65 -0
- package/dist/chunk-61d5dqq2.js +71 -0
- package/dist/chunk-6350958y.js +272 -0
- package/dist/chunk-65z8hg8j.js +1337 -0
- package/dist/chunk-6aq85gdq.js +8 -0
- package/dist/chunk-6cjh9exg.js +40751 -0
- package/dist/chunk-6e41p5m6.js +187 -0
- package/dist/chunk-6jb6xcnq.js +10511 -0
- package/dist/chunk-6jta29r1.js +20 -0
- package/dist/chunk-6q7f2rrv.js +4757 -0
- package/dist/chunk-6sg0ec6v.js +41 -0
- package/dist/chunk-6v0rhx4e.js +328 -0
- package/dist/chunk-6x5mz95v.js +751 -0
- package/dist/chunk-6xqp51qr.js +87 -0
- package/dist/chunk-6xvyx1s9.js +6957 -0
- package/dist/chunk-6ywh7wgp.js +468 -0
- package/dist/chunk-75ne77gm.js +1920 -0
- package/dist/chunk-77cb06js.js +602 -0
- package/dist/chunk-78n9kfp8.js +1645 -0
- package/dist/chunk-7be87rww.js +277 -0
- package/dist/chunk-7e1qjk3s.js +125 -0
- package/dist/chunk-7e7nxnss.js +360 -0
- package/dist/chunk-7g8156qp.js +55 -0
- package/dist/chunk-7nz71s42.js +3353 -0
- package/dist/chunk-7r078t2x.js +113 -0
- package/dist/chunk-7shx41hj.js +3094 -0
- package/dist/chunk-7yexhdjs.js +216 -0
- package/dist/chunk-83kmfcjv.js +256 -0
- package/dist/chunk-846rr9n1.js +107 -0
- package/dist/chunk-84ncsm1r.js +183 -0
- package/dist/chunk-867x8aq0.js +8936 -0
- package/dist/chunk-8byh30kb.js +1947 -0
- package/dist/chunk-8c8f6gnt.js +432 -0
- package/dist/chunk-8gtdseev.js +454 -0
- package/dist/chunk-8jfh9rq6.js +642 -0
- package/dist/chunk-8n4n4m67.js +800 -0
- package/dist/chunk-8za61tze.js +847 -0
- package/dist/chunk-9029sbq1.js +57 -0
- package/dist/chunk-94dm5rrm.js +673 -0
- package/dist/chunk-9bs8n985.js +329 -0
- package/dist/chunk-9c23776j.js +763 -0
- package/dist/chunk-9e93g81n.js +298 -0
- package/dist/chunk-9f3d61y7.js +548 -0
- package/dist/chunk-9gc3andd.js +422 -0
- package/dist/chunk-9kn3tgpb.js +130 -0
- package/dist/chunk-9m5rn7hk.js +61 -0
- package/dist/chunk-9p4hsd6a.js +50 -0
- package/dist/chunk-9qasfk8n.js +758 -0
- package/dist/chunk-9snp5mn2.js +533 -0
- package/dist/chunk-9tcvras3.js +2331 -0
- package/dist/chunk-a0186ngk.js +57 -0
- package/dist/chunk-a2m8f0aj.js +268 -0
- package/dist/chunk-a2rcafav.js +716 -0
- package/dist/chunk-a9hjdzar.js +160 -0
- package/dist/chunk-aak6ts5n.js +526 -0
- package/dist/chunk-aca3w84n.js +267 -0
- package/dist/chunk-ae76ded0.js +30 -0
- package/dist/chunk-afnjhn3j.js +21933 -0
- package/dist/chunk-ahj70tf0.js +880 -0
- package/dist/chunk-apjsxssq.js +169 -0
- package/dist/chunk-av49wjj1.js +43 -0
- package/dist/chunk-axggebfy.js +206 -0
- package/dist/chunk-az7jpbv8.js +16 -0
- package/dist/chunk-azz7sep6.js +328 -0
- package/dist/chunk-b4tpz2g1.js +93 -0
- package/dist/chunk-bczf2eyq.js +115 -0
- package/dist/chunk-bd95f637.js +208 -0
- package/dist/chunk-bdhdmkya.js +10 -0
- package/dist/chunk-bp0ynk17.js +32 -0
- package/dist/chunk-bq75gxjs.js +90 -0
- package/dist/chunk-btk5jaq6.js +10464 -0
- package/dist/chunk-bv4c48a5.js +120 -0
- package/dist/chunk-byfb105n.js +341 -0
- package/dist/chunk-c0bdmy7w.js +4223 -0
- package/dist/chunk-c20aqkz8.js +641 -0
- package/dist/chunk-c4jg3s2c.js +163 -0
- package/dist/chunk-c61q5cer.js +258 -0
- package/dist/chunk-c9f761sy.js +386 -0
- package/dist/chunk-ca6jkz06.js +157 -0
- package/dist/chunk-ccyg9ap9.js +171374 -0
- package/dist/chunk-cfej8cc7.js +371 -0
- package/dist/chunk-cjqxdnf9.js +23 -0
- package/dist/chunk-ckrs789w.js +8 -0
- package/dist/chunk-cqeq13wg.js +48 -0
- package/dist/chunk-crfj3w5e.js +22821 -0
- package/dist/chunk-ct5x6z7g.js +8066 -0
- package/dist/chunk-cv5h8n8c.js +101 -0
- package/dist/chunk-cwe8h159.js +1563 -0
- package/dist/chunk-cwm234zz.js +908 -0
- package/dist/chunk-d1jkfp45.js +1580 -0
- package/dist/chunk-d3hb1qdr.js +126 -0
- package/dist/chunk-d70d0zer.js +713 -0
- package/dist/chunk-d91tx29f.js +105 -0
- package/dist/chunk-d952pymh.js +20 -0
- package/dist/chunk-d9af3z8k.js +720 -0
- package/dist/chunk-da1n53c2.js +47 -0
- package/dist/chunk-df5c1x8m.js +732 -0
- package/dist/chunk-dkv64xys.js +71 -0
- package/dist/chunk-dm7166v6.js +251 -0
- package/dist/chunk-dr0y5a61.js +258 -0
- package/dist/chunk-drzb0rrd.js +306 -0
- package/dist/chunk-dw1v1q7w.js +37 -0
- package/dist/chunk-e224qet4.js +348 -0
- package/dist/chunk-e50ckbv0.js +1099 -0
- package/dist/chunk-e5gn6by6.js +1165 -0
- package/dist/chunk-e7m3f74m.js +37 -0
- package/dist/chunk-e8ghgwaj.js +295 -0
- package/dist/chunk-ed8k4ya2.js +41 -0
- package/dist/chunk-eh0vnqdz.js +76 -0
- package/dist/chunk-epwrzr35.js +4301 -0
- package/dist/chunk-er9h6sw5.js +5379 -0
- package/dist/chunk-eta5aekm.js +79 -0
- package/dist/chunk-ev5gxscq.js +63 -0
- package/dist/chunk-evp72hv5.js +212 -0
- package/dist/chunk-ex41stfq.js +127 -0
- package/dist/chunk-ezpa510h.js +62 -0
- package/dist/chunk-f0fm6dey.js +477 -0
- package/dist/chunk-f239sbhc.js +152 -0
- package/dist/chunk-f2bj47xf.js +109 -0
- package/dist/chunk-f4t24rq4.js +258 -0
- package/dist/chunk-f9ghvzy8.js +106 -0
- package/dist/chunk-f9rahzgr.js +99 -0
- package/dist/chunk-ff75qzty.js +521 -0
- package/dist/chunk-fj0ctt6q.js +264 -0
- package/dist/chunk-fj7wxdt3.js +221 -0
- package/dist/chunk-fnnpqv92.js +714 -0
- package/dist/chunk-fpd3zzx1.js +26696 -0
- package/dist/chunk-fqv2cn76.js +227 -0
- package/dist/chunk-fqw9j3bj.js +439 -0
- package/dist/chunk-frbcqhz0.js +4984 -0
- package/dist/chunk-fzkj59sg.js +174 -0
- package/dist/chunk-fzpzbpbw.js +248 -0
- package/dist/chunk-g52cpmd1.js +686 -0
- package/dist/chunk-g98m2qe6.js +31 -0
- package/dist/chunk-g9zgq4vy.js +715 -0
- package/dist/chunk-gbpt7tm8.js +687 -0
- package/dist/chunk-gg52jka8.js +373 -0
- package/dist/chunk-gjttphax.js +5793 -0
- package/dist/chunk-gs7vjaas.js +65 -0
- package/dist/chunk-gv8n85j2.js +8 -0
- package/dist/chunk-gxdwm6pt.js +650 -0
- package/dist/chunk-gy8wajg2.js +1014 -0
- package/dist/chunk-gz3647m0.js +200 -0
- package/dist/chunk-gzg07mqh.js +16 -0
- package/dist/chunk-h3zc60tq.js +44 -0
- package/dist/chunk-h4p1qt16.js +74 -0
- package/dist/chunk-h8219f18.js +282 -0
- package/dist/chunk-h9agq92v.js +331 -0
- package/dist/chunk-hhjtpwbj.js +16 -0
- package/dist/chunk-hpgpwzra.js +548 -0
- package/dist/chunk-hsnjvn19.js +80 -0
- package/dist/chunk-hsp9qrry.js +417 -0
- package/dist/chunk-hwz6aq2m.js +3939 -0
- package/dist/chunk-hzph0hbh.js +272 -0
- package/dist/chunk-hzqkss6v.js +153 -0
- package/dist/chunk-j0t31f39.js +1149 -0
- package/dist/chunk-j1qm6n1v.js +30 -0
- package/dist/chunk-j6e4b522.js +81 -0
- package/dist/chunk-j7qfbvxk.js +84 -0
- package/dist/chunk-j7qv3hvm.js +1635 -0
- package/dist/chunk-j8mxc6k6.js +213 -0
- package/dist/chunk-jevj87jn.js +224 -0
- package/dist/chunk-jk2ps88q.js +815 -0
- package/dist/chunk-jz7tbdyv.js +1599 -0
- package/dist/chunk-k36jpjvh.js +300 -0
- package/dist/chunk-k4nmrt3w.js +61 -0
- package/dist/chunk-kavn03r9.js +16606 -0
- package/dist/chunk-kkgav8dm.js +54 -0
- package/dist/chunk-kkq26g5c.js +33 -0
- package/dist/chunk-kp6nepx4.js +106 -0
- package/dist/chunk-ksefybc8.js +1551 -0
- package/dist/chunk-kv147680.js +3436 -0
- package/dist/chunk-kya46axt.js +833 -0
- package/dist/chunk-kyz233ny.js +227 -0
- package/dist/chunk-kzs75xmj.js +143 -0
- package/dist/chunk-m0vrez9w.js +266 -0
- package/dist/chunk-m1wadav3.js +118 -0
- package/dist/chunk-m4rfx3cj.js +221 -0
- package/dist/chunk-mc9zaggs.js +6374 -0
- package/dist/chunk-mcg5ttj4.js +105 -0
- package/dist/chunk-mf4r7918.js +63 -0
- package/dist/chunk-mh9khrt4.js +286 -0
- package/dist/chunk-mhc4szw7.js +22 -0
- package/dist/chunk-mkq0yzp0.js +38 -0
- package/dist/chunk-mr58jv4w.js +256 -0
- package/dist/chunk-mrrx3bmt.js +168 -0
- package/dist/chunk-mtyk3zz6.js +87 -0
- package/dist/chunk-mvgxntv6.js +62 -0
- package/dist/chunk-mwnjydcm.js +102 -0
- package/dist/chunk-mwxt0m3f.js +862 -0
- package/dist/chunk-mz1pxck8.js +998 -0
- package/dist/chunk-n3agghys.js +214 -0
- package/dist/chunk-n6q02ya9.js +442 -0
- package/dist/chunk-nt3y91vh.js +443 -0
- package/dist/chunk-nt837qt9.js +21 -0
- package/dist/chunk-ntgmegfs.js +39 -0
- package/dist/chunk-nwk16bbd.js +30 -0
- package/dist/chunk-p367ay90.js +672 -0
- package/dist/chunk-p7m3x9qk.js +48 -0
- package/dist/chunk-pagmjwp5.js +132 -0
- package/dist/chunk-pbd4r8ek.js +161 -0
- package/dist/chunk-pdkpssgv.js +2422 -0
- package/dist/chunk-pf6z1e35.js +32 -0
- package/dist/chunk-pfzejvpt.js +213 -0
- package/dist/chunk-pktxyhvk.js +400 -0
- package/dist/chunk-pp5xhveq.js +124 -0
- package/dist/chunk-ppnd7a8x.js +38 -0
- package/dist/chunk-pqh2w7dr.js +2202 -0
- package/dist/chunk-pr878d0z.js +240 -0
- package/dist/chunk-psf0y7hy.js +140 -0
- package/dist/chunk-pz2zz2f7.js +1586 -0
- package/dist/chunk-q0xkrxy8.js +890 -0
- package/dist/chunk-q5b0kpr3.js +14369 -0
- package/dist/chunk-q7z3t531.js +334 -0
- package/dist/chunk-qdjjtgwt.js +3183 -0
- package/dist/chunk-qezv7msv.js +26 -0
- package/dist/chunk-qmxn7f86.js +2643 -0
- package/dist/chunk-qqc3b97c.js +15 -0
- package/dist/chunk-qwrp63wh.js +145 -0
- package/dist/chunk-qyvqbst3.js +537 -0
- package/dist/chunk-qztvd4hd.js +465 -0
- package/dist/chunk-r0bvez4y.js +235 -0
- package/dist/chunk-r3z0896k.js +2831 -0
- package/dist/chunk-r4cxb6t7.js +32 -0
- package/dist/chunk-rb8k68m7.js +118 -0
- package/dist/chunk-rdprgm4t.js +42 -0
- package/dist/chunk-rex82hys.js +1710 -0
- package/dist/chunk-rjjakkw2.js +2560 -0
- package/dist/chunk-rka6gcv3.js +304 -0
- package/dist/chunk-rkz12ghm.js +144 -0
- package/dist/chunk-rnc7m1qs.js +436 -0
- package/dist/chunk-rx6z23h0.js +165 -0
- package/dist/chunk-s76582j1.js +28 -0
- package/dist/chunk-sez03qd9.js +7140 -0
- package/dist/chunk-sjvdn2ep.js +130 -0
- package/dist/chunk-smwhyy8p.js +115 -0
- package/dist/chunk-snw7nh0d.js +695 -0
- package/dist/chunk-sqx9c057.js +193 -0
- package/dist/chunk-sscms68s.js +16 -0
- package/dist/chunk-stknnmsb.js +272 -0
- package/dist/chunk-sywdxbs6.js +853 -0
- package/dist/chunk-syxy4pf2.js +782 -0
- package/dist/chunk-t0hpqsqn.js +6157 -0
- package/dist/chunk-tjm70vnw.js +123 -0
- package/dist/chunk-trzh0msn.js +154 -0
- package/dist/chunk-v1z17cpg.js +723 -0
- package/dist/chunk-vsfj449x.js +333 -0
- package/dist/chunk-vvkq20tt.js +287 -0
- package/dist/chunk-vxgdzx6p.js +338 -0
- package/dist/chunk-vxqhjyfz.js +15 -0
- package/dist/chunk-vzsstfmb.js +80 -0
- package/dist/chunk-w1jew5sn.js +69 -0
- package/dist/chunk-w3kwr76v.js +789 -0
- package/dist/chunk-w40netr9.js +59 -0
- package/dist/chunk-w99cpfdg.js +559 -0
- package/dist/chunk-wacn14d2.js +271 -0
- package/dist/chunk-wbhrqrq3.js +3033 -0
- package/dist/chunk-wfg9g0p7.js +17612 -0
- package/dist/chunk-wj3vjsbx.js +93 -0
- package/dist/chunk-wjhq855a.js +372 -0
- package/dist/chunk-wr06gqxh.js +114 -0
- package/dist/chunk-ws0z2y1g.js +195 -0
- package/dist/chunk-wt62wqcj.js +98 -0
- package/dist/chunk-wx4v7ddx.js +42 -0
- package/dist/chunk-wy0t3vb2.js +6101 -0
- package/dist/chunk-wysz7qk4.js +280 -0
- package/dist/chunk-x63fx1vd.js +192 -0
- package/dist/chunk-x8b7vft8.js +132 -0
- package/dist/chunk-x8jhkgxb.js +346 -0
- package/dist/chunk-x9z4q5k5.js +275 -0
- package/dist/chunk-xjd7e9jq.js +126 -0
- package/dist/chunk-xjr0n27e.js +42 -0
- package/dist/chunk-xpwyw7cd.js +24 -0
- package/dist/chunk-xw4ycnyz.js +37 -0
- package/dist/chunk-y66bqywr.js +17303 -0
- package/dist/chunk-ycarry7d.js +157 -0
- package/dist/chunk-ycr0hp6v.js +1486 -0
- package/dist/chunk-yqmaw6hf.js +496 -0
- package/dist/chunk-yrtm7d23.js +602 -0
- package/dist/chunk-yts879rw.js +48 -0
- package/dist/chunk-yvmhx96e.js +347 -0
- package/dist/chunk-ywq00rg4.js +246 -0
- package/dist/chunk-yygeg5mj.js +752 -0
- package/dist/chunk-z0exw850.js +726 -0
- package/dist/chunk-z2dp53wn.js +17 -0
- package/dist/chunk-z4rzc9nd.js +103 -0
- package/dist/chunk-zb0akt77.js +684 -0
- package/dist/chunk-zb2xrj5t.js +1789 -0
- package/dist/chunk-zbptn0ky.js +423 -0
- package/dist/chunk-zd45wbmf.js +1090 -0
- package/dist/chunk-zjkvspz9.js +2050 -0
- package/dist/chunk-zke1sp3x.js +1524 -0
- package/dist/chunk-zv2cvfsv.js +58 -0
- package/dist/chunk-zy4tmqst.js +644 -0
- package/dist/chunk-zygzzzvk.js +192 -0
- package/dist/cli-21v3v6ny.md +1 -0
- package/dist/cli.js +246 -0
- package/dist/server-n5f2q89z.md +1 -0
- package/package.json +161 -0
|
@@ -0,0 +1,4984 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
HybridTransport,
|
|
4
|
+
WebSocketTransport
|
|
5
|
+
} from "./chunk-g52cpmd1.js";
|
|
6
|
+
import {
|
|
7
|
+
CCRClient,
|
|
8
|
+
CCRInitError,
|
|
9
|
+
SSETransport
|
|
10
|
+
} from "./chunk-3mhygd2v.js";
|
|
11
|
+
import {
|
|
12
|
+
StructuredIO,
|
|
13
|
+
buildSystemInitMessage,
|
|
14
|
+
exports_MessageSelector,
|
|
15
|
+
exports_cronJitterConfig,
|
|
16
|
+
exports_cronScheduler,
|
|
17
|
+
extractInboundMessageFields,
|
|
18
|
+
init_MessageSelector,
|
|
19
|
+
init_cronJitterConfig,
|
|
20
|
+
init_cronScheduler,
|
|
21
|
+
ndjsonSafeStringify,
|
|
22
|
+
outputSchema,
|
|
23
|
+
permissionPromptToolResultToPermissionDecision,
|
|
24
|
+
processUserInput,
|
|
25
|
+
reconcileMarketplaces,
|
|
26
|
+
sdkCompatToolName
|
|
27
|
+
} from "./chunk-qdjjtgwt.js";
|
|
28
|
+
import {
|
|
29
|
+
detectAndUninstallDelistedPlugins
|
|
30
|
+
} from "./chunk-5dbaxmts.js";
|
|
31
|
+
import {
|
|
32
|
+
restoreAgentFromSession,
|
|
33
|
+
restoreSessionStateFromLog,
|
|
34
|
+
skillChangeDetector
|
|
35
|
+
} from "./chunk-8gtdseev.js";
|
|
36
|
+
import"./chunk-nt837qt9.js";
|
|
37
|
+
import {
|
|
38
|
+
externalMetadataToAppState
|
|
39
|
+
} from "./chunk-kyz233ny.js";
|
|
40
|
+
import {
|
|
41
|
+
getSessionState,
|
|
42
|
+
notifySessionMetadataChanged,
|
|
43
|
+
notifySessionStateChanged,
|
|
44
|
+
setPermissionModeChangedListener,
|
|
45
|
+
setSessionMetadataChangedListener,
|
|
46
|
+
setSessionStateChangedListener
|
|
47
|
+
} from "./chunk-k4nmrt3w.js";
|
|
48
|
+
import"./chunk-x8b7vft8.js";
|
|
49
|
+
import {
|
|
50
|
+
getPollIntervalConfig
|
|
51
|
+
} from "./chunk-w40netr9.js";
|
|
52
|
+
import"./chunk-f239sbhc.js";
|
|
53
|
+
import {
|
|
54
|
+
init_toolPool,
|
|
55
|
+
mergeAndFilterTools
|
|
56
|
+
} from "./chunk-pf6z1e35.js";
|
|
57
|
+
import {
|
|
58
|
+
init_settingsSync
|
|
59
|
+
} from "./chunk-hsnjvn19.js";
|
|
60
|
+
import {
|
|
61
|
+
init_refresh,
|
|
62
|
+
refreshActivePlugins
|
|
63
|
+
} from "./chunk-psf0y7hy.js";
|
|
64
|
+
import {
|
|
65
|
+
init_mappers,
|
|
66
|
+
localCommandOutputToSDKAssistantMessage,
|
|
67
|
+
toInternalMessages,
|
|
68
|
+
toSDKCompactMetadata,
|
|
69
|
+
toSDKRateLimitInfo
|
|
70
|
+
} from "./chunk-fqv2cn76.js";
|
|
71
|
+
import {
|
|
72
|
+
generateSessionTitle,
|
|
73
|
+
init_sessionTitle
|
|
74
|
+
} from "./chunk-xjd7e9jq.js";
|
|
75
|
+
import {
|
|
76
|
+
ChannelMessageNotificationSchema,
|
|
77
|
+
findChannelEntry,
|
|
78
|
+
gateChannelServer,
|
|
79
|
+
init_channelAllowlist,
|
|
80
|
+
init_channelNotification,
|
|
81
|
+
wrapChannelMessage
|
|
82
|
+
} from "./chunk-drzb0rrd.js";
|
|
83
|
+
import"./chunk-zy4tmqst.js";
|
|
84
|
+
import {
|
|
85
|
+
init_sideQuestion,
|
|
86
|
+
runSideQuestion
|
|
87
|
+
} from "./chunk-wt62wqcj.js";
|
|
88
|
+
import"./chunk-kkq26g5c.js";
|
|
89
|
+
import {
|
|
90
|
+
EMPTY_USAGE,
|
|
91
|
+
getSessionIngressAuthToken,
|
|
92
|
+
init_sessionIngressAuth
|
|
93
|
+
} from "./chunk-jevj87jn.js";
|
|
94
|
+
import"./chunk-qztvd4hd.js";
|
|
95
|
+
import {
|
|
96
|
+
ElicitRequestSchema,
|
|
97
|
+
ElicitationCompleteNotificationSchema,
|
|
98
|
+
init_types
|
|
99
|
+
} from "./chunk-q0xkrxy8.js";
|
|
100
|
+
import"./chunk-52dzw4bc.js";
|
|
101
|
+
import"./chunk-n6q02ya9.js";
|
|
102
|
+
import {
|
|
103
|
+
READ_FILE_STATE_CACHE_SIZE,
|
|
104
|
+
cloneFileStateCache,
|
|
105
|
+
createFileStateCacheWithSizeLimit,
|
|
106
|
+
init_fileStateCache,
|
|
107
|
+
mergeFileStateCaches
|
|
108
|
+
} from "./chunk-b4tpz2g1.js";
|
|
109
|
+
import"./chunk-n3agghys.js";
|
|
110
|
+
import"./chunk-f9rahzgr.js";
|
|
111
|
+
import"./chunk-ex41stfq.js";
|
|
112
|
+
import"./chunk-8n4n4m67.js";
|
|
113
|
+
import"./chunk-xjr0n27e.js";
|
|
114
|
+
import"./chunk-0yz17yjy.js";
|
|
115
|
+
import"./chunk-9m5rn7hk.js";
|
|
116
|
+
import"./chunk-19jvvqzp.js";
|
|
117
|
+
import"./chunk-2n0s2dhc.js";
|
|
118
|
+
import"./chunk-epwrzr35.js";
|
|
119
|
+
import"./chunk-1ztm9yps.js";
|
|
120
|
+
import {
|
|
121
|
+
init_json,
|
|
122
|
+
safeParseJSON
|
|
123
|
+
} from "./chunk-78n9kfp8.js";
|
|
124
|
+
import {
|
|
125
|
+
expandPath,
|
|
126
|
+
init_path
|
|
127
|
+
} from "./chunk-j8mxc6k6.js";
|
|
128
|
+
import"./chunk-z0exw850.js";
|
|
129
|
+
import {
|
|
130
|
+
hasActiveInProcessTeammates,
|
|
131
|
+
hasWorkingInProcessTeammates,
|
|
132
|
+
init_teammate,
|
|
133
|
+
isTeamLead,
|
|
134
|
+
uniq,
|
|
135
|
+
waitForTeammatesToBecomeIdle
|
|
136
|
+
} from "./chunk-3jf3k40v.js";
|
|
137
|
+
import"./chunk-yvmhx96e.js";
|
|
138
|
+
import {
|
|
139
|
+
init_v4
|
|
140
|
+
} from "./chunk-qezv7msv.js";
|
|
141
|
+
import"./chunk-sscms68s.js";
|
|
142
|
+
import"./chunk-7e1qjk3s.js";
|
|
143
|
+
import {
|
|
144
|
+
exports_external,
|
|
145
|
+
lazySchema
|
|
146
|
+
} from "./chunk-1gjysfnf.js";
|
|
147
|
+
import"./chunk-vxgdzx6p.js";
|
|
148
|
+
import"./chunk-kv147680.js";
|
|
149
|
+
import"./chunk-2p0hvt8k.js";
|
|
150
|
+
import"./chunk-ycr0hp6v.js";
|
|
151
|
+
import"./chunk-zb2xrj5t.js";
|
|
152
|
+
import"./chunk-9029sbq1.js";
|
|
153
|
+
import {
|
|
154
|
+
init_analytics,
|
|
155
|
+
logEvent
|
|
156
|
+
} from "./chunk-ezpa510h.js";
|
|
157
|
+
import"./chunk-kp6nepx4.js";
|
|
158
|
+
import"./chunk-1jjzp2pa.js";
|
|
159
|
+
import"./chunk-w1jew5sn.js";
|
|
160
|
+
import"./chunk-g98m2qe6.js";
|
|
161
|
+
import"./chunk-sez03qd9.js";
|
|
162
|
+
import {
|
|
163
|
+
LOCAL_COMMAND_STDERR_TAG,
|
|
164
|
+
LOCAL_COMMAND_STDOUT_TAG,
|
|
165
|
+
TEAMMATE_MESSAGE_TAG,
|
|
166
|
+
getInMemoryErrors,
|
|
167
|
+
init_log,
|
|
168
|
+
init_xml,
|
|
169
|
+
logError,
|
|
170
|
+
logMCPDebug
|
|
171
|
+
} from "./chunk-vsfj449x.js";
|
|
172
|
+
import"./chunk-r4cxb6t7.js";
|
|
173
|
+
import {
|
|
174
|
+
getCwd,
|
|
175
|
+
init_cwd
|
|
176
|
+
} from "./chunk-bp0ynk17.js";
|
|
177
|
+
import"./chunk-7yexhdjs.js";
|
|
178
|
+
import {
|
|
179
|
+
errorMessage,
|
|
180
|
+
getFsImplementation,
|
|
181
|
+
init_cleanupRegistry,
|
|
182
|
+
init_debug,
|
|
183
|
+
init_errors,
|
|
184
|
+
init_fsOperations,
|
|
185
|
+
init_slowOperations,
|
|
186
|
+
isDebugMode,
|
|
187
|
+
jsonParse,
|
|
188
|
+
jsonStringify,
|
|
189
|
+
logForDebugging,
|
|
190
|
+
registerCleanup,
|
|
191
|
+
toError
|
|
192
|
+
} from "./chunk-rex82hys.js";
|
|
193
|
+
import {
|
|
194
|
+
getClaudeConfigHomeDir,
|
|
195
|
+
init_envUtils,
|
|
196
|
+
isBareMode,
|
|
197
|
+
isEnvDefinedFalsy,
|
|
198
|
+
isEnvTruthy
|
|
199
|
+
} from "./chunk-4s93jyky.js";
|
|
200
|
+
import"./chunk-318g78ty.js";
|
|
201
|
+
import"./chunk-c0bdmy7w.js";
|
|
202
|
+
import"./chunk-syxy4pf2.js";
|
|
203
|
+
import {
|
|
204
|
+
__require,
|
|
205
|
+
__toCommonJS,
|
|
206
|
+
__toESM
|
|
207
|
+
} from "./chunk-eta5aekm.js";
|
|
208
|
+
import"./chunk-gz3647m0.js";
|
|
209
|
+
import {
|
|
210
|
+
getBridgeAccessToken,
|
|
211
|
+
getBridgeBaseUrl,
|
|
212
|
+
init_bridgeConfig
|
|
213
|
+
} from "./chunk-eh0vnqdz.js";
|
|
214
|
+
import"./chunk-31gfg8tz.js";
|
|
215
|
+
import {
|
|
216
|
+
collectContextData,
|
|
217
|
+
init_context_noninteractive
|
|
218
|
+
} from "./chunk-7e7nxnss.js";
|
|
219
|
+
import {
|
|
220
|
+
DEFAULT_OUTPUT_STYLE_NAME,
|
|
221
|
+
EFFORT_LEVELS,
|
|
222
|
+
OAuthService,
|
|
223
|
+
SHELL_TOOL_NAMES,
|
|
224
|
+
SYNTHETIC_MESSAGES,
|
|
225
|
+
SYNTHETIC_OUTPUT_TOOL_NAME,
|
|
226
|
+
SandboxManager,
|
|
227
|
+
accumulateUsage,
|
|
228
|
+
applySettingsChange,
|
|
229
|
+
areMcpConfigsEqual,
|
|
230
|
+
asSessionId,
|
|
231
|
+
asSystemPrompt,
|
|
232
|
+
assembleToolPool,
|
|
233
|
+
atomicWriteToZipCache,
|
|
234
|
+
buildBridgeConnectUrl,
|
|
235
|
+
categorizeRetryableAPIError,
|
|
236
|
+
checkGroveForNonInteractive,
|
|
237
|
+
cleanupSessionPluginCache,
|
|
238
|
+
clearCommandsCache,
|
|
239
|
+
clearMarketplacesCache,
|
|
240
|
+
clearPluginCache,
|
|
241
|
+
clearServerCache,
|
|
242
|
+
commandBelongsToServer,
|
|
243
|
+
connectToServer,
|
|
244
|
+
countToolCalls,
|
|
245
|
+
createAbortController,
|
|
246
|
+
createCombinedAbortSignal,
|
|
247
|
+
createModelSwitchBreadcrumbs,
|
|
248
|
+
createSyntheticOutputTool,
|
|
249
|
+
dequeue,
|
|
250
|
+
dequeueAllMatching,
|
|
251
|
+
doesMessageExistInSession,
|
|
252
|
+
drainSdkEvents,
|
|
253
|
+
enqueue,
|
|
254
|
+
executeNotificationHooks,
|
|
255
|
+
exports_prompt,
|
|
256
|
+
extractReadFilesFromMessages,
|
|
257
|
+
fetchToolsForClient,
|
|
258
|
+
fileHistoryCanRestore,
|
|
259
|
+
fileHistoryEnabled,
|
|
260
|
+
fileHistoryGetDiffStats,
|
|
261
|
+
fileHistoryMakeSnapshot,
|
|
262
|
+
fileHistoryRewind,
|
|
263
|
+
filterMcpServersByPolicy,
|
|
264
|
+
filterToolsByDenyRules,
|
|
265
|
+
filterToolsByServer,
|
|
266
|
+
finalizePendingAsyncHooks,
|
|
267
|
+
findUnresolvedToolUse,
|
|
268
|
+
flushSessionStorage,
|
|
269
|
+
formatDescriptionWithSource,
|
|
270
|
+
fromArray,
|
|
271
|
+
getAllMcpConfigs,
|
|
272
|
+
getAllOutputStyles,
|
|
273
|
+
getCommandName,
|
|
274
|
+
getCommands,
|
|
275
|
+
getCommandsByMaxPriority,
|
|
276
|
+
getDeclaredMarketplaces,
|
|
277
|
+
getLastCacheSafeParams,
|
|
278
|
+
getMarketplaceJsonRelativePath,
|
|
279
|
+
getMcpConfigByName,
|
|
280
|
+
getModelOptions,
|
|
281
|
+
getPluginZipCachePath,
|
|
282
|
+
getRemoteSessionUrl,
|
|
283
|
+
getRunningTasks,
|
|
284
|
+
getScratchpadDir,
|
|
285
|
+
getSlashCommandToolSkills,
|
|
286
|
+
getSystemContext,
|
|
287
|
+
getSystemPrompt,
|
|
288
|
+
getUserContext,
|
|
289
|
+
getZipCacheKnownMarketplacesPath,
|
|
290
|
+
getZipCacheMarketplacesDir,
|
|
291
|
+
getZipCachePluginsDir,
|
|
292
|
+
gracefulShutdown,
|
|
293
|
+
gracefulShutdownSync,
|
|
294
|
+
handleOrphanedPermission,
|
|
295
|
+
hasCommandsInQueue,
|
|
296
|
+
hasPermissionsToUseTool,
|
|
297
|
+
headlessProfilerCheckpoint,
|
|
298
|
+
headlessProfilerStartTurn,
|
|
299
|
+
hydrateFromCCRv2InternalEvents,
|
|
300
|
+
hydrateRemoteSession,
|
|
301
|
+
init_AsyncHookRegistry,
|
|
302
|
+
init_Shell,
|
|
303
|
+
init_SyntheticOutputTool,
|
|
304
|
+
init_Tool,
|
|
305
|
+
init_abortController,
|
|
306
|
+
init_applySettingsChange,
|
|
307
|
+
init_auth as init_auth2,
|
|
308
|
+
init_auth1 as init_auth3,
|
|
309
|
+
init_bridgeStatusUtil,
|
|
310
|
+
init_changeDetector,
|
|
311
|
+
init_claude,
|
|
312
|
+
init_claudeAiLimits,
|
|
313
|
+
init_client,
|
|
314
|
+
init_combinedAbortSignal,
|
|
315
|
+
init_commands1 as init_commands,
|
|
316
|
+
init_config as init_config2,
|
|
317
|
+
init_context,
|
|
318
|
+
init_conversationRecovery,
|
|
319
|
+
init_cost_tracker,
|
|
320
|
+
init_effort,
|
|
321
|
+
init_elicitationHandler,
|
|
322
|
+
init_errors as init_errors2,
|
|
323
|
+
init_fileHistory,
|
|
324
|
+
init_filesApi,
|
|
325
|
+
init_filesystem,
|
|
326
|
+
init_forkedAgent,
|
|
327
|
+
init_framework,
|
|
328
|
+
init_generators,
|
|
329
|
+
init_gracefulShutdown,
|
|
330
|
+
init_grove,
|
|
331
|
+
init_headlessProfiler,
|
|
332
|
+
init_hookEvents,
|
|
333
|
+
init_hookHelpers,
|
|
334
|
+
init_hooks1 as init_hooks,
|
|
335
|
+
init_ids,
|
|
336
|
+
init_loadAgentsDir,
|
|
337
|
+
init_logging,
|
|
338
|
+
init_marketplaceManager,
|
|
339
|
+
init_memdir,
|
|
340
|
+
init_messageQueueManager,
|
|
341
|
+
init_messages,
|
|
342
|
+
init_modelOptions,
|
|
343
|
+
init_oauth,
|
|
344
|
+
init_outputStyles,
|
|
345
|
+
init_outputsScanner,
|
|
346
|
+
init_permissionSetup,
|
|
347
|
+
init_permissions,
|
|
348
|
+
init_pluginIdentifier,
|
|
349
|
+
init_pluginLoader,
|
|
350
|
+
init_policyLimits,
|
|
351
|
+
init_prompt,
|
|
352
|
+
init_prompt1 as init_prompt2,
|
|
353
|
+
init_prompt2 as init_prompt3,
|
|
354
|
+
init_prompt3 as init_prompt4,
|
|
355
|
+
init_prompt7 as init_prompt5,
|
|
356
|
+
init_promptSuggestion,
|
|
357
|
+
init_prompts1 as init_prompts,
|
|
358
|
+
init_query,
|
|
359
|
+
init_queryHelpers,
|
|
360
|
+
init_queryProfiler,
|
|
361
|
+
init_remoteManagedSettings,
|
|
362
|
+
init_sandbox_adapter,
|
|
363
|
+
init_sdkEventQueue,
|
|
364
|
+
init_sessionStart,
|
|
365
|
+
init_sessionStorage,
|
|
366
|
+
init_shellToolUtils,
|
|
367
|
+
init_stopTask,
|
|
368
|
+
init_teammateMailbox,
|
|
369
|
+
init_thinking,
|
|
370
|
+
init_tools1 as init_tools,
|
|
371
|
+
init_utils,
|
|
372
|
+
init_uuid,
|
|
373
|
+
init_vscodeSdkMcp,
|
|
374
|
+
init_zipCache,
|
|
375
|
+
installOAuthTokens,
|
|
376
|
+
isBackgroundTask,
|
|
377
|
+
isBuiltInAgent,
|
|
378
|
+
isBypassPermissionsModeDisabled,
|
|
379
|
+
isMarketplaceSourceSupportedByZipCache,
|
|
380
|
+
isMcpServerDisabled,
|
|
381
|
+
isPluginZipCacheEnabled,
|
|
382
|
+
isPolicyAllowed,
|
|
383
|
+
isQualifiedForGrove,
|
|
384
|
+
isResultSuccessful,
|
|
385
|
+
isScratchpadEnabled,
|
|
386
|
+
isShutdownApproved,
|
|
387
|
+
isShuttingDown,
|
|
388
|
+
loadAllPluginsCacheOnly,
|
|
389
|
+
loadConversationForResume,
|
|
390
|
+
loadKnownMarketplacesConfigSafe,
|
|
391
|
+
loadMemoryPrompt,
|
|
392
|
+
logHeadlessProfilerTurn,
|
|
393
|
+
logQueryProfileReport,
|
|
394
|
+
logSuggestionOutcome,
|
|
395
|
+
logSuggestionSuppressed,
|
|
396
|
+
markMessagesAsRead,
|
|
397
|
+
modelSupportsAdaptiveThinking,
|
|
398
|
+
modelSupportsEffort,
|
|
399
|
+
modelSupportsMaxEffort,
|
|
400
|
+
normalizeMessage,
|
|
401
|
+
notifyCommandLifecycle,
|
|
402
|
+
parseAgentsFromJson,
|
|
403
|
+
parsePluginIdentifier,
|
|
404
|
+
peek,
|
|
405
|
+
performMCPOAuthFlow,
|
|
406
|
+
processSessionStartHooks,
|
|
407
|
+
processSetupHooks,
|
|
408
|
+
query,
|
|
409
|
+
readUnreadMessages,
|
|
410
|
+
reconnectMcpServerImpl,
|
|
411
|
+
recordTranscript,
|
|
412
|
+
registerHookEventHandler,
|
|
413
|
+
registerSeedMarketplaces,
|
|
414
|
+
registerStructuredOutputEnforcement,
|
|
415
|
+
resetSessionFilePointer,
|
|
416
|
+
resolveAppliedEffort,
|
|
417
|
+
restoreSessionMetadata,
|
|
418
|
+
revokeServerTokens,
|
|
419
|
+
runElicitationHooks,
|
|
420
|
+
runElicitationResultHooks,
|
|
421
|
+
saveAgentSetting,
|
|
422
|
+
saveAiGeneratedTitle,
|
|
423
|
+
setCommandLifecycleListener,
|
|
424
|
+
setCwd,
|
|
425
|
+
setInternalEventReader,
|
|
426
|
+
setInternalEventWriter,
|
|
427
|
+
setMcpServerEnabled,
|
|
428
|
+
settingsChangeDetector,
|
|
429
|
+
setupSdkMcpClients,
|
|
430
|
+
setupVscodeSdkMcp,
|
|
431
|
+
shouldEnableThinkingByDefault,
|
|
432
|
+
startQueryProfile,
|
|
433
|
+
statusListeners,
|
|
434
|
+
stopTask,
|
|
435
|
+
subscribeToCommandQueue,
|
|
436
|
+
takeInitialUserMessage,
|
|
437
|
+
toolMatchesName,
|
|
438
|
+
transitionPermissionMode,
|
|
439
|
+
tryGenerateSuggestion,
|
|
440
|
+
updateUsage,
|
|
441
|
+
validateUuid,
|
|
442
|
+
waitForRemoteManagedSettingsToLoad
|
|
443
|
+
} from "./chunk-ccyg9ap9.js";
|
|
444
|
+
import"./chunk-846rr9n1.js";
|
|
445
|
+
import {
|
|
446
|
+
init_commitAttribution
|
|
447
|
+
} from "./chunk-fnnpqv92.js";
|
|
448
|
+
import"./chunk-2yqy25z4.js";
|
|
449
|
+
import"./chunk-zygzzzvk.js";
|
|
450
|
+
import"./chunk-evp72hv5.js";
|
|
451
|
+
import"./chunk-jz7tbdyv.js";
|
|
452
|
+
import"./chunk-vxqhjyfz.js";
|
|
453
|
+
import"./chunk-mf4r7918.js";
|
|
454
|
+
import {
|
|
455
|
+
init_tasks,
|
|
456
|
+
init_teamHelpers,
|
|
457
|
+
removeTeammateFromTeamFile,
|
|
458
|
+
unassignTeammateTasks
|
|
459
|
+
} from "./chunk-sywdxbs6.js";
|
|
460
|
+
import"./chunk-cjqxdnf9.js";
|
|
461
|
+
import"./chunk-9qasfk8n.js";
|
|
462
|
+
import {
|
|
463
|
+
resolveThemeSetting
|
|
464
|
+
} from "./chunk-fpd3zzx1.js";
|
|
465
|
+
import"./chunk-bv4c48a5.js";
|
|
466
|
+
import"./chunk-6jta29r1.js";
|
|
467
|
+
import"./chunk-z4rzc9nd.js";
|
|
468
|
+
import"./chunk-9bs8n985.js";
|
|
469
|
+
import"./chunk-6xqp51qr.js";
|
|
470
|
+
import"./chunk-35dw2r9g.js";
|
|
471
|
+
import {
|
|
472
|
+
AwsAuthStatusManager,
|
|
473
|
+
KnownMarketplacesFileSchema,
|
|
474
|
+
TASK_STOP_TOOL_NAME,
|
|
475
|
+
WORKLOAD_CRON,
|
|
476
|
+
ensureModelStringsInitialized,
|
|
477
|
+
getAPIProvider,
|
|
478
|
+
getAccountInformation,
|
|
479
|
+
getDefaultMainLoopModel,
|
|
480
|
+
getFastModeState,
|
|
481
|
+
getFeatureValue_CACHED_MAY_BE_STALE,
|
|
482
|
+
getGlobalConfig,
|
|
483
|
+
getMainLoopModel,
|
|
484
|
+
getMcpPrefix,
|
|
485
|
+
getSettingsWithSources,
|
|
486
|
+
getSettings_DEPRECATED,
|
|
487
|
+
hasAutoMemPathOverride,
|
|
488
|
+
init_auth,
|
|
489
|
+
init_awsAuthStatusManager,
|
|
490
|
+
init_betas1 as init_betas,
|
|
491
|
+
init_config1 as init_config,
|
|
492
|
+
init_fastMode,
|
|
493
|
+
init_growthbook,
|
|
494
|
+
init_last,
|
|
495
|
+
init_mcpStringUtils,
|
|
496
|
+
init_model,
|
|
497
|
+
init_modelStrings,
|
|
498
|
+
init_omit,
|
|
499
|
+
init_paths,
|
|
500
|
+
init_providers,
|
|
501
|
+
init_reject,
|
|
502
|
+
init_schemas,
|
|
503
|
+
init_settings1 as init_settings,
|
|
504
|
+
init_stringUtils,
|
|
505
|
+
init_uniqBy,
|
|
506
|
+
init_workloadContext,
|
|
507
|
+
initializeGrowthBook,
|
|
508
|
+
isFastModeAvailable,
|
|
509
|
+
isFastModeEnabled,
|
|
510
|
+
isFastModeSupportedByModel,
|
|
511
|
+
last_default,
|
|
512
|
+
modelDisplayString,
|
|
513
|
+
modelSupportsAutoMode,
|
|
514
|
+
omit_default,
|
|
515
|
+
parseUserSpecifiedModel,
|
|
516
|
+
reject_default,
|
|
517
|
+
runWithWorkload,
|
|
518
|
+
sleep,
|
|
519
|
+
uniqBy_default
|
|
520
|
+
} from "./chunk-y66bqywr.js";
|
|
521
|
+
import"./chunk-nwk16bbd.js";
|
|
522
|
+
import"./chunk-rx6z23h0.js";
|
|
523
|
+
import {
|
|
524
|
+
init_strip_ansi,
|
|
525
|
+
stripAnsi
|
|
526
|
+
} from "./chunk-df5c1x8m.js";
|
|
527
|
+
import"./chunk-qwrp63wh.js";
|
|
528
|
+
import {
|
|
529
|
+
init_diagLogs,
|
|
530
|
+
logForDiagnosticsNoPII,
|
|
531
|
+
withDiagnosticsTiming
|
|
532
|
+
} from "./chunk-65z8hg8j.js";
|
|
533
|
+
import {
|
|
534
|
+
registerProcessOutputErrorHandlers,
|
|
535
|
+
writeToStdout
|
|
536
|
+
} from "./chunk-5cp2q9sh.js";
|
|
537
|
+
import {
|
|
538
|
+
getAllowedChannels,
|
|
539
|
+
getFlagSettingsInline,
|
|
540
|
+
getInitJsonSchema,
|
|
541
|
+
getMainThreadAgentType,
|
|
542
|
+
getModelUsage,
|
|
543
|
+
getSessionId,
|
|
544
|
+
getTotalAPIDuration,
|
|
545
|
+
getTotalCostUSD,
|
|
546
|
+
init_state,
|
|
547
|
+
isSessionPersistenceDisabled,
|
|
548
|
+
registerHookCallbacks,
|
|
549
|
+
setAllowedChannels,
|
|
550
|
+
setFlagSettingsInline,
|
|
551
|
+
setInitJsonSchema,
|
|
552
|
+
setMainLoopModelOverride,
|
|
553
|
+
setMainThreadAgentType,
|
|
554
|
+
setSdkAgentProgressSummariesEnabled,
|
|
555
|
+
switchSession
|
|
556
|
+
} from "./chunk-rjjakkw2.js";
|
|
557
|
+
import"./chunk-0sbddf6m.js";
|
|
558
|
+
import {
|
|
559
|
+
axios_default,
|
|
560
|
+
init_axios
|
|
561
|
+
} from "./chunk-q5b0kpr3.js";
|
|
562
|
+
|
|
563
|
+
// src/cli/print.ts
|
|
564
|
+
init_settingsSync();
|
|
565
|
+
init_remoteManagedSettings();
|
|
566
|
+
import { readFile as readFile2, stat } from "fs/promises";
|
|
567
|
+
import { dirname } from "path";
|
|
568
|
+
|
|
569
|
+
// src/cli/remoteIO.ts
|
|
570
|
+
init_state();
|
|
571
|
+
import { PassThrough } from "stream";
|
|
572
|
+
import { URL as URL3 } from "url";
|
|
573
|
+
init_cleanupRegistry();
|
|
574
|
+
init_debug();
|
|
575
|
+
init_diagLogs();
|
|
576
|
+
init_envUtils();
|
|
577
|
+
init_errors();
|
|
578
|
+
init_gracefulShutdown();
|
|
579
|
+
init_log();
|
|
580
|
+
init_sessionIngressAuth();
|
|
581
|
+
init_sessionStorage();
|
|
582
|
+
|
|
583
|
+
// src/cli/transports/transportUtils.ts
|
|
584
|
+
init_envUtils();
|
|
585
|
+
import { URL as URL2 } from "url";
|
|
586
|
+
function getTransportForUrl(url, headers = {}, sessionId, refreshHeaders) {
|
|
587
|
+
if (isEnvTruthy(process.env.CLAUDE_CODE_USE_CCR_V2)) {
|
|
588
|
+
const sseUrl = new URL2(url.href);
|
|
589
|
+
if (sseUrl.protocol === "wss:") {
|
|
590
|
+
sseUrl.protocol = "https:";
|
|
591
|
+
} else if (sseUrl.protocol === "ws:") {
|
|
592
|
+
sseUrl.protocol = "http:";
|
|
593
|
+
}
|
|
594
|
+
sseUrl.pathname = sseUrl.pathname.replace(/\/$/, "") + "/worker/events/stream";
|
|
595
|
+
return new SSETransport(sseUrl, headers, sessionId, refreshHeaders);
|
|
596
|
+
}
|
|
597
|
+
if (url.protocol === "ws:" || url.protocol === "wss:") {
|
|
598
|
+
if (isEnvTruthy(process.env.CLAUDE_CODE_POST_FOR_SESSION_INGRESS_V2)) {
|
|
599
|
+
return new HybridTransport(url, headers, sessionId, refreshHeaders);
|
|
600
|
+
}
|
|
601
|
+
return new WebSocketTransport(url, headers, sessionId, refreshHeaders);
|
|
602
|
+
} else {
|
|
603
|
+
throw new Error(`Unsupported protocol: ${url.protocol}`);
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
// src/cli/remoteIO.ts
|
|
608
|
+
class RemoteIO extends StructuredIO {
|
|
609
|
+
url;
|
|
610
|
+
transport;
|
|
611
|
+
inputStream;
|
|
612
|
+
isBridge = false;
|
|
613
|
+
isDebug = false;
|
|
614
|
+
ccrClient = null;
|
|
615
|
+
keepAliveTimer = null;
|
|
616
|
+
constructor(streamUrl, initialPrompt, replayUserMessages) {
|
|
617
|
+
const inputStream = new PassThrough({ encoding: "utf8" });
|
|
618
|
+
super(inputStream, replayUserMessages);
|
|
619
|
+
this.inputStream = inputStream;
|
|
620
|
+
this.url = new URL3(streamUrl);
|
|
621
|
+
const headers = {};
|
|
622
|
+
const sessionToken = getSessionIngressAuthToken();
|
|
623
|
+
if (sessionToken) {
|
|
624
|
+
headers["Authorization"] = `Bearer ${sessionToken}`;
|
|
625
|
+
} else {
|
|
626
|
+
logForDebugging("[remote-io] No session ingress token available", {
|
|
627
|
+
level: "error"
|
|
628
|
+
});
|
|
629
|
+
}
|
|
630
|
+
const erVersion = process.env.CLAUDE_CODE_ENVIRONMENT_RUNNER_VERSION;
|
|
631
|
+
if (erVersion) {
|
|
632
|
+
headers["x-environment-runner-version"] = erVersion;
|
|
633
|
+
}
|
|
634
|
+
const refreshHeaders = () => {
|
|
635
|
+
const h = {};
|
|
636
|
+
const freshToken = getSessionIngressAuthToken();
|
|
637
|
+
if (freshToken) {
|
|
638
|
+
h["Authorization"] = `Bearer ${freshToken}`;
|
|
639
|
+
}
|
|
640
|
+
const freshErVersion = process.env.CLAUDE_CODE_ENVIRONMENT_RUNNER_VERSION;
|
|
641
|
+
if (freshErVersion) {
|
|
642
|
+
h["x-environment-runner-version"] = freshErVersion;
|
|
643
|
+
}
|
|
644
|
+
return h;
|
|
645
|
+
};
|
|
646
|
+
this.transport = getTransportForUrl(this.url, headers, getSessionId(), refreshHeaders);
|
|
647
|
+
this.isBridge = process.env.CLAUDE_CODE_ENVIRONMENT_KIND === "bridge";
|
|
648
|
+
this.isDebug = isDebugMode();
|
|
649
|
+
this.transport.setOnData((data) => {
|
|
650
|
+
this.inputStream.write(data);
|
|
651
|
+
if (this.isBridge && this.isDebug) {
|
|
652
|
+
writeToStdout(data.endsWith(`
|
|
653
|
+
`) ? data : data + `
|
|
654
|
+
`);
|
|
655
|
+
}
|
|
656
|
+
});
|
|
657
|
+
this.transport.setOnClose(() => {
|
|
658
|
+
this.inputStream.end();
|
|
659
|
+
});
|
|
660
|
+
if (isEnvTruthy(process.env.CLAUDE_CODE_USE_CCR_V2)) {
|
|
661
|
+
if (!(this.transport instanceof SSETransport)) {
|
|
662
|
+
throw new Error("CCR v2 requires SSETransport; check getTransportForUrl");
|
|
663
|
+
}
|
|
664
|
+
this.ccrClient = new CCRClient(this.transport, this.url);
|
|
665
|
+
const init = this.ccrClient.initialize();
|
|
666
|
+
this.restoredWorkerState = init.catch(() => null);
|
|
667
|
+
init.catch((error) => {
|
|
668
|
+
logForDiagnosticsNoPII("error", "cli_worker_lifecycle_init_failed", {
|
|
669
|
+
reason: error instanceof CCRInitError ? error.reason : "unknown"
|
|
670
|
+
});
|
|
671
|
+
logError(new Error(`CCRClient initialization failed: ${errorMessage(error)}`));
|
|
672
|
+
gracefulShutdown(1, "other");
|
|
673
|
+
});
|
|
674
|
+
registerCleanup(async () => this.ccrClient?.close());
|
|
675
|
+
setInternalEventWriter((eventType, payload, options) => this.ccrClient.writeInternalEvent(eventType, payload, options));
|
|
676
|
+
setInternalEventReader(() => this.ccrClient.readInternalEvents(), () => this.ccrClient.readSubagentInternalEvents());
|
|
677
|
+
const LIFECYCLE_TO_DELIVERY = {
|
|
678
|
+
started: "processing",
|
|
679
|
+
completed: "processed"
|
|
680
|
+
};
|
|
681
|
+
setCommandLifecycleListener((uuid, state) => {
|
|
682
|
+
this.ccrClient?.reportDelivery(uuid, LIFECYCLE_TO_DELIVERY[state]);
|
|
683
|
+
});
|
|
684
|
+
setSessionStateChangedListener((state, details) => {
|
|
685
|
+
this.ccrClient?.reportState(state, details);
|
|
686
|
+
});
|
|
687
|
+
setSessionMetadataChangedListener((metadata) => {
|
|
688
|
+
this.ccrClient?.reportMetadata(metadata);
|
|
689
|
+
});
|
|
690
|
+
}
|
|
691
|
+
this.transport.connect();
|
|
692
|
+
const keepAliveIntervalMs = getPollIntervalConfig().session_keepalive_interval_v2_ms;
|
|
693
|
+
if (this.isBridge && keepAliveIntervalMs > 0) {
|
|
694
|
+
this.keepAliveTimer = setInterval(() => {
|
|
695
|
+
logForDebugging("[remote-io] keep_alive sent");
|
|
696
|
+
this.write({ type: "keep_alive" }).catch((err) => {
|
|
697
|
+
logForDebugging(`[remote-io] keep_alive write failed: ${errorMessage(err)}`);
|
|
698
|
+
});
|
|
699
|
+
}, keepAliveIntervalMs);
|
|
700
|
+
this.keepAliveTimer.unref?.();
|
|
701
|
+
}
|
|
702
|
+
registerCleanup(async () => this.close());
|
|
703
|
+
if (initialPrompt) {
|
|
704
|
+
const stream = this.inputStream;
|
|
705
|
+
(async () => {
|
|
706
|
+
for await (const chunk of initialPrompt) {
|
|
707
|
+
stream.write(String(chunk).replace(/\n$/, "") + `
|
|
708
|
+
`);
|
|
709
|
+
}
|
|
710
|
+
})();
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
flushInternalEvents() {
|
|
714
|
+
return this.ccrClient?.flushInternalEvents() ?? Promise.resolve();
|
|
715
|
+
}
|
|
716
|
+
get internalEventsPending() {
|
|
717
|
+
return this.ccrClient?.internalEventsPending ?? 0;
|
|
718
|
+
}
|
|
719
|
+
async write(message) {
|
|
720
|
+
if (this.ccrClient) {
|
|
721
|
+
await this.ccrClient.writeEvent(message);
|
|
722
|
+
} else {
|
|
723
|
+
await this.transport.write(message);
|
|
724
|
+
}
|
|
725
|
+
if (this.isBridge) {
|
|
726
|
+
if (message.type === "control_request" || this.isDebug) {
|
|
727
|
+
writeToStdout(ndjsonSafeStringify(message) + `
|
|
728
|
+
`);
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
close() {
|
|
733
|
+
if (this.keepAliveTimer) {
|
|
734
|
+
clearInterval(this.keepAliveTimer);
|
|
735
|
+
this.keepAliveTimer = null;
|
|
736
|
+
}
|
|
737
|
+
this.transport.close();
|
|
738
|
+
this.inputStream.end();
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
// src/cli/print.ts
|
|
743
|
+
init_commands();
|
|
744
|
+
|
|
745
|
+
// src/utils/streamlinedTransform.ts
|
|
746
|
+
init_prompt2();
|
|
747
|
+
init_prompt3();
|
|
748
|
+
init_prompt();
|
|
749
|
+
init_prompt4();
|
|
750
|
+
init_messages();
|
|
751
|
+
init_shellToolUtils();
|
|
752
|
+
init_stringUtils();
|
|
753
|
+
var COMMAND_TOOLS = [...SHELL_TOOL_NAMES, "Tmux", TASK_STOP_TOOL_NAME];
|
|
754
|
+
|
|
755
|
+
// src/utils/streamJsonStdoutGuard.ts
|
|
756
|
+
init_cleanupRegistry();
|
|
757
|
+
init_debug();
|
|
758
|
+
var STDOUT_GUARD_MARKER = "[stdout-guard]";
|
|
759
|
+
var installed = false;
|
|
760
|
+
var buffer = "";
|
|
761
|
+
var originalWrite = null;
|
|
762
|
+
function isJsonLine(line) {
|
|
763
|
+
if (line.length === 0) {
|
|
764
|
+
return true;
|
|
765
|
+
}
|
|
766
|
+
try {
|
|
767
|
+
JSON.parse(line);
|
|
768
|
+
return true;
|
|
769
|
+
} catch {
|
|
770
|
+
return false;
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
function installStreamJsonStdoutGuard() {
|
|
774
|
+
if (installed) {
|
|
775
|
+
return;
|
|
776
|
+
}
|
|
777
|
+
installed = true;
|
|
778
|
+
originalWrite = process.stdout.write.bind(process.stdout);
|
|
779
|
+
process.stdout.write = function(chunk, encodingOrCb, cb) {
|
|
780
|
+
const text = typeof chunk === "string" ? chunk : Buffer.from(chunk).toString("utf-8");
|
|
781
|
+
buffer += text;
|
|
782
|
+
let newlineIdx;
|
|
783
|
+
let wrote = true;
|
|
784
|
+
while ((newlineIdx = buffer.indexOf(`
|
|
785
|
+
`)) !== -1) {
|
|
786
|
+
const line = buffer.slice(0, newlineIdx);
|
|
787
|
+
buffer = buffer.slice(newlineIdx + 1);
|
|
788
|
+
if (isJsonLine(line)) {
|
|
789
|
+
wrote = originalWrite(line + `
|
|
790
|
+
`);
|
|
791
|
+
} else {
|
|
792
|
+
process.stderr.write(`${STDOUT_GUARD_MARKER} ${line}
|
|
793
|
+
`);
|
|
794
|
+
logForDebugging(`streamJsonStdoutGuard diverted non-JSON stdout line: ${line.slice(0, 200)}`);
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
const callback = typeof encodingOrCb === "function" ? encodingOrCb : cb;
|
|
798
|
+
if (callback) {
|
|
799
|
+
queueMicrotask(() => callback());
|
|
800
|
+
}
|
|
801
|
+
return wrote;
|
|
802
|
+
};
|
|
803
|
+
registerCleanup(async () => {
|
|
804
|
+
if (buffer.length > 0) {
|
|
805
|
+
if (originalWrite && isJsonLine(buffer)) {
|
|
806
|
+
originalWrite(buffer + `
|
|
807
|
+
`);
|
|
808
|
+
} else {
|
|
809
|
+
process.stderr.write(`${STDOUT_GUARD_MARKER} ${buffer}
|
|
810
|
+
`);
|
|
811
|
+
}
|
|
812
|
+
buffer = "";
|
|
813
|
+
}
|
|
814
|
+
if (originalWrite) {
|
|
815
|
+
process.stdout.write = originalWrite;
|
|
816
|
+
originalWrite = null;
|
|
817
|
+
}
|
|
818
|
+
installed = false;
|
|
819
|
+
});
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
// src/cli/print.ts
|
|
823
|
+
init_tools();
|
|
824
|
+
init_uniqBy();
|
|
825
|
+
init_toolPool();
|
|
826
|
+
init_analytics();
|
|
827
|
+
init_growthbook();
|
|
828
|
+
init_debug();
|
|
829
|
+
init_diagLogs();
|
|
830
|
+
init_Tool();
|
|
831
|
+
init_loadAgentsDir();
|
|
832
|
+
init_messageQueueManager();
|
|
833
|
+
init_log();
|
|
834
|
+
init_logging();
|
|
835
|
+
init_conversationRecovery();
|
|
836
|
+
init_channelNotification();
|
|
837
|
+
init_channelAllowlist();
|
|
838
|
+
init_pluginIdentifier();
|
|
839
|
+
init_uuid();
|
|
840
|
+
init_generators();
|
|
841
|
+
|
|
842
|
+
// src/QueryEngine.ts
|
|
843
|
+
init_last();
|
|
844
|
+
init_state();
|
|
845
|
+
init_claude();
|
|
846
|
+
init_logging();
|
|
847
|
+
init_strip_ansi();
|
|
848
|
+
init_commands();
|
|
849
|
+
init_xml();
|
|
850
|
+
init_cost_tracker();
|
|
851
|
+
init_memdir();
|
|
852
|
+
init_paths();
|
|
853
|
+
init_query();
|
|
854
|
+
init_errors2();
|
|
855
|
+
init_Tool();
|
|
856
|
+
init_SyntheticOutputTool();
|
|
857
|
+
init_abortController();
|
|
858
|
+
init_config();
|
|
859
|
+
init_cwd();
|
|
860
|
+
init_envUtils();
|
|
861
|
+
init_fastMode();
|
|
862
|
+
init_fileHistory();
|
|
863
|
+
init_fileStateCache();
|
|
864
|
+
init_headlessProfiler();
|
|
865
|
+
init_hookHelpers();
|
|
866
|
+
init_log();
|
|
867
|
+
init_messages();
|
|
868
|
+
init_model();
|
|
869
|
+
init_pluginLoader();
|
|
870
|
+
import { randomUUID } from "crypto";
|
|
871
|
+
|
|
872
|
+
// src/utils/queryContext.ts
|
|
873
|
+
init_prompts();
|
|
874
|
+
init_context();
|
|
875
|
+
init_abortController();
|
|
876
|
+
init_model();
|
|
877
|
+
init_thinking();
|
|
878
|
+
async function fetchSystemPromptParts({
|
|
879
|
+
tools,
|
|
880
|
+
mainLoopModel,
|
|
881
|
+
additionalWorkingDirectories,
|
|
882
|
+
mcpClients,
|
|
883
|
+
customSystemPrompt
|
|
884
|
+
}) {
|
|
885
|
+
const [defaultSystemPrompt, userContext, systemContext] = await Promise.all([
|
|
886
|
+
customSystemPrompt !== undefined ? Promise.resolve([]) : getSystemPrompt(tools, mainLoopModel, additionalWorkingDirectories, mcpClients),
|
|
887
|
+
getUserContext(),
|
|
888
|
+
customSystemPrompt !== undefined ? Promise.resolve({}) : getSystemContext()
|
|
889
|
+
]);
|
|
890
|
+
return { defaultSystemPrompt, userContext, systemContext };
|
|
891
|
+
}
|
|
892
|
+
async function buildSideQuestionFallbackParams({
|
|
893
|
+
tools,
|
|
894
|
+
commands,
|
|
895
|
+
mcpClients,
|
|
896
|
+
messages,
|
|
897
|
+
readFileState,
|
|
898
|
+
getAppState,
|
|
899
|
+
setAppState,
|
|
900
|
+
customSystemPrompt,
|
|
901
|
+
appendSystemPrompt,
|
|
902
|
+
thinkingConfig,
|
|
903
|
+
agents
|
|
904
|
+
}) {
|
|
905
|
+
const mainLoopModel = getMainLoopModel();
|
|
906
|
+
const appState = getAppState();
|
|
907
|
+
const { defaultSystemPrompt, userContext, systemContext } = await fetchSystemPromptParts({
|
|
908
|
+
tools,
|
|
909
|
+
mainLoopModel,
|
|
910
|
+
additionalWorkingDirectories: Array.from(appState.toolPermissionContext.additionalWorkingDirectories.keys()),
|
|
911
|
+
mcpClients,
|
|
912
|
+
customSystemPrompt
|
|
913
|
+
});
|
|
914
|
+
const systemPrompt = asSystemPrompt([
|
|
915
|
+
...customSystemPrompt !== undefined ? [customSystemPrompt] : defaultSystemPrompt,
|
|
916
|
+
...appendSystemPrompt ? [appendSystemPrompt] : []
|
|
917
|
+
]);
|
|
918
|
+
const last = messages.at(-1);
|
|
919
|
+
const forkContextMessages = last?.type === "assistant" && last.message.stop_reason === null ? messages.slice(0, -1) : messages;
|
|
920
|
+
const toolUseContext = {
|
|
921
|
+
options: {
|
|
922
|
+
commands,
|
|
923
|
+
debug: false,
|
|
924
|
+
mainLoopModel,
|
|
925
|
+
tools,
|
|
926
|
+
verbose: false,
|
|
927
|
+
thinkingConfig: thinkingConfig ?? (shouldEnableThinkingByDefault() !== false ? { type: "adaptive" } : { type: "disabled" }),
|
|
928
|
+
mcpClients,
|
|
929
|
+
mcpResources: {},
|
|
930
|
+
isNonInteractiveSession: true,
|
|
931
|
+
agentDefinitions: { activeAgents: agents, allAgents: [] },
|
|
932
|
+
customSystemPrompt,
|
|
933
|
+
appendSystemPrompt
|
|
934
|
+
},
|
|
935
|
+
abortController: createAbortController(),
|
|
936
|
+
readFileState,
|
|
937
|
+
getAppState,
|
|
938
|
+
setAppState,
|
|
939
|
+
messages: forkContextMessages,
|
|
940
|
+
setInProgressToolUseIDs: () => {},
|
|
941
|
+
setResponseLength: () => {},
|
|
942
|
+
updateFileHistoryState: () => {},
|
|
943
|
+
updateAttributionState: () => {}
|
|
944
|
+
};
|
|
945
|
+
return {
|
|
946
|
+
systemPrompt,
|
|
947
|
+
userContext,
|
|
948
|
+
systemContext,
|
|
949
|
+
toolUseContext,
|
|
950
|
+
forkContextMessages
|
|
951
|
+
};
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
// src/QueryEngine.ts
|
|
955
|
+
init_Shell();
|
|
956
|
+
init_sessionStorage();
|
|
957
|
+
init_thinking();
|
|
958
|
+
init_mappers();
|
|
959
|
+
init_filesystem();
|
|
960
|
+
init_queryHelpers();
|
|
961
|
+
var messageSelector = () => (init_MessageSelector(), __toCommonJS(exports_MessageSelector));
|
|
962
|
+
var getCoordinatorUserContext = () => ({});
|
|
963
|
+
class QueryEngine {
|
|
964
|
+
config;
|
|
965
|
+
mutableMessages;
|
|
966
|
+
abortController;
|
|
967
|
+
permissionDenials;
|
|
968
|
+
totalUsage;
|
|
969
|
+
hasHandledOrphanedPermission = false;
|
|
970
|
+
readFileState;
|
|
971
|
+
discoveredSkillNames = new Set;
|
|
972
|
+
loadedNestedMemoryPaths = new Set;
|
|
973
|
+
constructor(config) {
|
|
974
|
+
this.config = config;
|
|
975
|
+
this.mutableMessages = config.initialMessages ?? [];
|
|
976
|
+
this.abortController = config.abortController ?? createAbortController();
|
|
977
|
+
this.permissionDenials = [];
|
|
978
|
+
this.readFileState = config.readFileCache;
|
|
979
|
+
this.totalUsage = EMPTY_USAGE;
|
|
980
|
+
}
|
|
981
|
+
async* submitMessage(prompt, options) {
|
|
982
|
+
const {
|
|
983
|
+
cwd,
|
|
984
|
+
commands,
|
|
985
|
+
tools,
|
|
986
|
+
mcpClients,
|
|
987
|
+
verbose = false,
|
|
988
|
+
thinkingConfig,
|
|
989
|
+
maxTurns,
|
|
990
|
+
maxBudgetUsd,
|
|
991
|
+
taskBudget,
|
|
992
|
+
canUseTool,
|
|
993
|
+
customSystemPrompt,
|
|
994
|
+
appendSystemPrompt,
|
|
995
|
+
userSpecifiedModel,
|
|
996
|
+
fallbackModel,
|
|
997
|
+
jsonSchema,
|
|
998
|
+
getAppState,
|
|
999
|
+
setAppState,
|
|
1000
|
+
replayUserMessages = false,
|
|
1001
|
+
includePartialMessages = false,
|
|
1002
|
+
agents = [],
|
|
1003
|
+
setSDKStatus,
|
|
1004
|
+
orphanedPermission
|
|
1005
|
+
} = this.config;
|
|
1006
|
+
this.discoveredSkillNames.clear();
|
|
1007
|
+
setCwd(cwd);
|
|
1008
|
+
const persistSession = !isSessionPersistenceDisabled();
|
|
1009
|
+
const startTime = Date.now();
|
|
1010
|
+
const wrappedCanUseTool = async (tool, input, toolUseContext, assistantMessage, toolUseID, forceDecision) => {
|
|
1011
|
+
const result2 = await canUseTool(tool, input, toolUseContext, assistantMessage, toolUseID, forceDecision);
|
|
1012
|
+
if (result2.behavior !== "allow") {
|
|
1013
|
+
this.permissionDenials.push({
|
|
1014
|
+
type: "permission_denial",
|
|
1015
|
+
tool_name: sdkCompatToolName(tool.name),
|
|
1016
|
+
tool_use_id: toolUseID,
|
|
1017
|
+
tool_input: input
|
|
1018
|
+
});
|
|
1019
|
+
}
|
|
1020
|
+
return result2;
|
|
1021
|
+
};
|
|
1022
|
+
const initialAppState = getAppState();
|
|
1023
|
+
const initialMainLoopModel = userSpecifiedModel ? parseUserSpecifiedModel(userSpecifiedModel) : getMainLoopModel();
|
|
1024
|
+
const initialThinkingConfig = thinkingConfig ? thinkingConfig : shouldEnableThinkingByDefault() !== false ? { type: "adaptive" } : { type: "disabled" };
|
|
1025
|
+
headlessProfilerCheckpoint("before_getSystemPrompt");
|
|
1026
|
+
const customPrompt = typeof customSystemPrompt === "string" ? customSystemPrompt : undefined;
|
|
1027
|
+
const {
|
|
1028
|
+
defaultSystemPrompt,
|
|
1029
|
+
userContext: baseUserContext,
|
|
1030
|
+
systemContext
|
|
1031
|
+
} = await fetchSystemPromptParts({
|
|
1032
|
+
tools,
|
|
1033
|
+
mainLoopModel: initialMainLoopModel,
|
|
1034
|
+
additionalWorkingDirectories: Array.from(initialAppState.toolPermissionContext.additionalWorkingDirectories.keys()),
|
|
1035
|
+
mcpClients,
|
|
1036
|
+
customSystemPrompt: customPrompt
|
|
1037
|
+
});
|
|
1038
|
+
headlessProfilerCheckpoint("after_getSystemPrompt");
|
|
1039
|
+
const userContext = {
|
|
1040
|
+
...baseUserContext,
|
|
1041
|
+
...getCoordinatorUserContext(mcpClients, isScratchpadEnabled() ? getScratchpadDir() : undefined)
|
|
1042
|
+
};
|
|
1043
|
+
const memoryMechanicsPrompt = customPrompt !== undefined && hasAutoMemPathOverride() ? await loadMemoryPrompt() : null;
|
|
1044
|
+
const systemPrompt = asSystemPrompt([
|
|
1045
|
+
...customPrompt !== undefined ? [customPrompt] : defaultSystemPrompt,
|
|
1046
|
+
...memoryMechanicsPrompt ? [memoryMechanicsPrompt] : [],
|
|
1047
|
+
...appendSystemPrompt ? [appendSystemPrompt] : []
|
|
1048
|
+
]);
|
|
1049
|
+
const hasStructuredOutputTool = tools.some((t) => toolMatchesName(t, SYNTHETIC_OUTPUT_TOOL_NAME));
|
|
1050
|
+
if (jsonSchema && hasStructuredOutputTool) {
|
|
1051
|
+
registerStructuredOutputEnforcement(setAppState, getSessionId());
|
|
1052
|
+
}
|
|
1053
|
+
let processUserInputContext = {
|
|
1054
|
+
messages: this.mutableMessages,
|
|
1055
|
+
setMessages: (fn) => {
|
|
1056
|
+
this.mutableMessages = fn(this.mutableMessages);
|
|
1057
|
+
},
|
|
1058
|
+
onChangeAPIKey: () => {},
|
|
1059
|
+
handleElicitation: this.config.handleElicitation,
|
|
1060
|
+
options: {
|
|
1061
|
+
commands,
|
|
1062
|
+
debug: false,
|
|
1063
|
+
tools,
|
|
1064
|
+
verbose,
|
|
1065
|
+
mainLoopModel: initialMainLoopModel,
|
|
1066
|
+
thinkingConfig: initialThinkingConfig,
|
|
1067
|
+
mcpClients,
|
|
1068
|
+
mcpResources: {},
|
|
1069
|
+
ideInstallationStatus: null,
|
|
1070
|
+
isNonInteractiveSession: true,
|
|
1071
|
+
customSystemPrompt,
|
|
1072
|
+
appendSystemPrompt,
|
|
1073
|
+
agentDefinitions: { activeAgents: agents, allAgents: [] },
|
|
1074
|
+
theme: resolveThemeSetting(getGlobalConfig().theme),
|
|
1075
|
+
maxBudgetUsd
|
|
1076
|
+
},
|
|
1077
|
+
getAppState,
|
|
1078
|
+
setAppState,
|
|
1079
|
+
abortController: this.abortController,
|
|
1080
|
+
readFileState: this.readFileState,
|
|
1081
|
+
nestedMemoryAttachmentTriggers: new Set,
|
|
1082
|
+
loadedNestedMemoryPaths: this.loadedNestedMemoryPaths,
|
|
1083
|
+
dynamicSkillDirTriggers: new Set,
|
|
1084
|
+
discoveredSkillNames: this.discoveredSkillNames,
|
|
1085
|
+
setInProgressToolUseIDs: () => {},
|
|
1086
|
+
setResponseLength: () => {},
|
|
1087
|
+
updateFileHistoryState: (updater) => {
|
|
1088
|
+
setAppState((prev) => {
|
|
1089
|
+
const updated = updater(prev.fileHistory);
|
|
1090
|
+
if (updated === prev.fileHistory)
|
|
1091
|
+
return prev;
|
|
1092
|
+
return { ...prev, fileHistory: updated };
|
|
1093
|
+
});
|
|
1094
|
+
},
|
|
1095
|
+
updateAttributionState: (updater) => {
|
|
1096
|
+
setAppState((prev) => {
|
|
1097
|
+
const updated = updater(prev.attribution);
|
|
1098
|
+
if (updated === prev.attribution)
|
|
1099
|
+
return prev;
|
|
1100
|
+
return { ...prev, attribution: updated };
|
|
1101
|
+
});
|
|
1102
|
+
},
|
|
1103
|
+
setSDKStatus
|
|
1104
|
+
};
|
|
1105
|
+
if (orphanedPermission && !this.hasHandledOrphanedPermission) {
|
|
1106
|
+
this.hasHandledOrphanedPermission = true;
|
|
1107
|
+
for await (const message of handleOrphanedPermission(orphanedPermission, tools, this.mutableMessages, processUserInputContext)) {
|
|
1108
|
+
yield message;
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
const {
|
|
1112
|
+
messages: messagesFromUserInput,
|
|
1113
|
+
shouldQuery,
|
|
1114
|
+
allowedTools,
|
|
1115
|
+
model: modelFromUserInput,
|
|
1116
|
+
resultText
|
|
1117
|
+
} = await processUserInput({
|
|
1118
|
+
input: prompt,
|
|
1119
|
+
mode: "prompt",
|
|
1120
|
+
setToolJSX: () => {},
|
|
1121
|
+
context: {
|
|
1122
|
+
...processUserInputContext,
|
|
1123
|
+
messages: this.mutableMessages
|
|
1124
|
+
},
|
|
1125
|
+
messages: this.mutableMessages,
|
|
1126
|
+
uuid: options?.uuid,
|
|
1127
|
+
isMeta: options?.isMeta,
|
|
1128
|
+
querySource: "sdk"
|
|
1129
|
+
});
|
|
1130
|
+
this.mutableMessages.push(...messagesFromUserInput);
|
|
1131
|
+
const messages = [...this.mutableMessages];
|
|
1132
|
+
if (persistSession && messagesFromUserInput.length > 0) {
|
|
1133
|
+
const transcriptPromise = recordTranscript(messages);
|
|
1134
|
+
if (isBareMode()) {} else {
|
|
1135
|
+
await transcriptPromise;
|
|
1136
|
+
if (isEnvTruthy(process.env.CLAUDE_CODE_EAGER_FLUSH) || isEnvTruthy(process.env.CLAUDE_CODE_IS_COWORK)) {
|
|
1137
|
+
await flushSessionStorage();
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
const replayableMessages = messagesFromUserInput.filter((msg) => msg.type === "user" && !msg.isMeta && !msg.toolUseResult && messageSelector().selectableUserMessagesFilter(msg) || msg.type === "system" && msg.subtype === "compact_boundary");
|
|
1142
|
+
const messagesToAck = replayUserMessages ? replayableMessages : [];
|
|
1143
|
+
setAppState((prev) => ({
|
|
1144
|
+
...prev,
|
|
1145
|
+
toolPermissionContext: {
|
|
1146
|
+
...prev.toolPermissionContext,
|
|
1147
|
+
alwaysAllowRules: {
|
|
1148
|
+
...prev.toolPermissionContext.alwaysAllowRules,
|
|
1149
|
+
command: allowedTools
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
}));
|
|
1153
|
+
const mainLoopModel = modelFromUserInput ?? initialMainLoopModel;
|
|
1154
|
+
processUserInputContext = {
|
|
1155
|
+
messages,
|
|
1156
|
+
setMessages: () => {},
|
|
1157
|
+
onChangeAPIKey: () => {},
|
|
1158
|
+
handleElicitation: this.config.handleElicitation,
|
|
1159
|
+
options: {
|
|
1160
|
+
commands,
|
|
1161
|
+
debug: false,
|
|
1162
|
+
tools,
|
|
1163
|
+
verbose,
|
|
1164
|
+
mainLoopModel,
|
|
1165
|
+
thinkingConfig: initialThinkingConfig,
|
|
1166
|
+
mcpClients,
|
|
1167
|
+
mcpResources: {},
|
|
1168
|
+
ideInstallationStatus: null,
|
|
1169
|
+
isNonInteractiveSession: true,
|
|
1170
|
+
customSystemPrompt,
|
|
1171
|
+
appendSystemPrompt,
|
|
1172
|
+
theme: resolveThemeSetting(getGlobalConfig().theme),
|
|
1173
|
+
agentDefinitions: { activeAgents: agents, allAgents: [] },
|
|
1174
|
+
maxBudgetUsd
|
|
1175
|
+
},
|
|
1176
|
+
getAppState,
|
|
1177
|
+
setAppState,
|
|
1178
|
+
abortController: this.abortController,
|
|
1179
|
+
readFileState: this.readFileState,
|
|
1180
|
+
nestedMemoryAttachmentTriggers: new Set,
|
|
1181
|
+
loadedNestedMemoryPaths: this.loadedNestedMemoryPaths,
|
|
1182
|
+
dynamicSkillDirTriggers: new Set,
|
|
1183
|
+
discoveredSkillNames: this.discoveredSkillNames,
|
|
1184
|
+
setInProgressToolUseIDs: () => {},
|
|
1185
|
+
setResponseLength: () => {},
|
|
1186
|
+
updateFileHistoryState: processUserInputContext.updateFileHistoryState,
|
|
1187
|
+
updateAttributionState: processUserInputContext.updateAttributionState,
|
|
1188
|
+
setSDKStatus
|
|
1189
|
+
};
|
|
1190
|
+
headlessProfilerCheckpoint("before_skills_plugins");
|
|
1191
|
+
const [skills, { enabled: enabledPlugins }] = await Promise.all([
|
|
1192
|
+
getSlashCommandToolSkills(getCwd()),
|
|
1193
|
+
loadAllPluginsCacheOnly()
|
|
1194
|
+
]);
|
|
1195
|
+
headlessProfilerCheckpoint("after_skills_plugins");
|
|
1196
|
+
yield buildSystemInitMessage({
|
|
1197
|
+
tools,
|
|
1198
|
+
mcpClients,
|
|
1199
|
+
model: mainLoopModel,
|
|
1200
|
+
permissionMode: initialAppState.toolPermissionContext.mode,
|
|
1201
|
+
commands,
|
|
1202
|
+
agents,
|
|
1203
|
+
skills,
|
|
1204
|
+
plugins: enabledPlugins,
|
|
1205
|
+
fastMode: initialAppState.fastMode
|
|
1206
|
+
});
|
|
1207
|
+
headlessProfilerCheckpoint("system_message_yielded");
|
|
1208
|
+
if (!shouldQuery) {
|
|
1209
|
+
for (const msg of messagesFromUserInput) {
|
|
1210
|
+
if (msg.type === "user" && typeof msg.message.content === "string" && (msg.message.content.includes(`<${LOCAL_COMMAND_STDOUT_TAG}>`) || msg.message.content.includes(`<${LOCAL_COMMAND_STDERR_TAG}>`) || msg.isCompactSummary)) {
|
|
1211
|
+
yield {
|
|
1212
|
+
type: "user",
|
|
1213
|
+
message: {
|
|
1214
|
+
...msg.message,
|
|
1215
|
+
content: stripAnsi(msg.message.content)
|
|
1216
|
+
},
|
|
1217
|
+
session_id: getSessionId(),
|
|
1218
|
+
parent_tool_use_id: null,
|
|
1219
|
+
uuid: msg.uuid,
|
|
1220
|
+
timestamp: msg.timestamp,
|
|
1221
|
+
isReplay: !msg.isCompactSummary,
|
|
1222
|
+
isSynthetic: msg.isMeta || msg.isVisibleInTranscriptOnly
|
|
1223
|
+
};
|
|
1224
|
+
}
|
|
1225
|
+
if (msg.type === "system" && msg.subtype === "local_command" && typeof msg.content === "string" && (msg.content.includes(`<${LOCAL_COMMAND_STDOUT_TAG}>`) || msg.content.includes(`<${LOCAL_COMMAND_STDERR_TAG}>`))) {
|
|
1226
|
+
yield localCommandOutputToSDKAssistantMessage(msg.content, msg.uuid);
|
|
1227
|
+
}
|
|
1228
|
+
if (msg.type === "system" && msg.subtype === "compact_boundary") {
|
|
1229
|
+
const compactMsg = msg;
|
|
1230
|
+
yield {
|
|
1231
|
+
type: "system",
|
|
1232
|
+
subtype: "compact_boundary",
|
|
1233
|
+
session_id: getSessionId(),
|
|
1234
|
+
uuid: msg.uuid,
|
|
1235
|
+
compact_metadata: toSDKCompactMetadata(compactMsg.compactMetadata)
|
|
1236
|
+
};
|
|
1237
|
+
}
|
|
1238
|
+
}
|
|
1239
|
+
if (persistSession) {
|
|
1240
|
+
await recordTranscript(messages);
|
|
1241
|
+
if (isEnvTruthy(process.env.CLAUDE_CODE_EAGER_FLUSH) || isEnvTruthy(process.env.CLAUDE_CODE_IS_COWORK)) {
|
|
1242
|
+
await flushSessionStorage();
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
yield {
|
|
1246
|
+
type: "result",
|
|
1247
|
+
subtype: "success",
|
|
1248
|
+
is_error: false,
|
|
1249
|
+
duration_ms: Date.now() - startTime,
|
|
1250
|
+
duration_api_ms: getTotalAPIDuration(),
|
|
1251
|
+
num_turns: messages.length - 1,
|
|
1252
|
+
result: resultText ?? "",
|
|
1253
|
+
stop_reason: null,
|
|
1254
|
+
session_id: getSessionId(),
|
|
1255
|
+
total_cost_usd: getTotalCostUSD(),
|
|
1256
|
+
usage: this.totalUsage,
|
|
1257
|
+
modelUsage: getModelUsage(),
|
|
1258
|
+
permission_denials: this.permissionDenials,
|
|
1259
|
+
fast_mode_state: getFastModeState(mainLoopModel, initialAppState.fastMode),
|
|
1260
|
+
uuid: randomUUID()
|
|
1261
|
+
};
|
|
1262
|
+
return;
|
|
1263
|
+
}
|
|
1264
|
+
if (fileHistoryEnabled() && persistSession) {
|
|
1265
|
+
messagesFromUserInput.filter(messageSelector().selectableUserMessagesFilter).forEach((message) => {
|
|
1266
|
+
fileHistoryMakeSnapshot((updater) => {
|
|
1267
|
+
setAppState((prev) => ({
|
|
1268
|
+
...prev,
|
|
1269
|
+
fileHistory: updater(prev.fileHistory)
|
|
1270
|
+
}));
|
|
1271
|
+
}, message.uuid);
|
|
1272
|
+
});
|
|
1273
|
+
}
|
|
1274
|
+
let currentMessageUsage = EMPTY_USAGE;
|
|
1275
|
+
let turnCount = 1;
|
|
1276
|
+
let hasAcknowledgedInitialMessages = false;
|
|
1277
|
+
let structuredOutputFromTool;
|
|
1278
|
+
let lastStopReason = null;
|
|
1279
|
+
const errorLogWatermark = getInMemoryErrors().at(-1);
|
|
1280
|
+
const initialStructuredOutputCalls = jsonSchema ? countToolCalls(this.mutableMessages, SYNTHETIC_OUTPUT_TOOL_NAME) : 0;
|
|
1281
|
+
for await (const message of query({
|
|
1282
|
+
messages,
|
|
1283
|
+
systemPrompt,
|
|
1284
|
+
userContext,
|
|
1285
|
+
systemContext,
|
|
1286
|
+
canUseTool: wrappedCanUseTool,
|
|
1287
|
+
toolUseContext: processUserInputContext,
|
|
1288
|
+
fallbackModel,
|
|
1289
|
+
querySource: "sdk",
|
|
1290
|
+
maxTurns,
|
|
1291
|
+
taskBudget
|
|
1292
|
+
})) {
|
|
1293
|
+
if (message.type === "assistant" || message.type === "user" || message.type === "system" && message.subtype === "compact_boundary") {
|
|
1294
|
+
if (persistSession && message.type === "system" && message.subtype === "compact_boundary") {
|
|
1295
|
+
const compactMsg = message;
|
|
1296
|
+
const tailUuid = compactMsg.compactMetadata?.preservedSegment?.tailUuid;
|
|
1297
|
+
if (tailUuid) {
|
|
1298
|
+
const tailIdx = this.mutableMessages.findLastIndex((m) => m.uuid === tailUuid);
|
|
1299
|
+
if (tailIdx !== -1) {
|
|
1300
|
+
await recordTranscript(this.mutableMessages.slice(0, tailIdx + 1));
|
|
1301
|
+
}
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1304
|
+
messages.push(message);
|
|
1305
|
+
if (persistSession) {
|
|
1306
|
+
if (message.type === "assistant") {
|
|
1307
|
+
recordTranscript(messages);
|
|
1308
|
+
} else {
|
|
1309
|
+
await recordTranscript(messages);
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
if (!hasAcknowledgedInitialMessages && messagesToAck.length > 0) {
|
|
1313
|
+
hasAcknowledgedInitialMessages = true;
|
|
1314
|
+
for (const msgToAck of messagesToAck) {
|
|
1315
|
+
if (msgToAck.type === "user") {
|
|
1316
|
+
yield {
|
|
1317
|
+
type: "user",
|
|
1318
|
+
message: msgToAck.message,
|
|
1319
|
+
session_id: getSessionId(),
|
|
1320
|
+
parent_tool_use_id: null,
|
|
1321
|
+
uuid: msgToAck.uuid,
|
|
1322
|
+
timestamp: msgToAck.timestamp,
|
|
1323
|
+
isReplay: true
|
|
1324
|
+
};
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1328
|
+
}
|
|
1329
|
+
if (message.type === "user") {
|
|
1330
|
+
turnCount++;
|
|
1331
|
+
}
|
|
1332
|
+
switch (message.type) {
|
|
1333
|
+
case "tombstone":
|
|
1334
|
+
break;
|
|
1335
|
+
case "assistant": {
|
|
1336
|
+
const msg = message;
|
|
1337
|
+
const stopReason = msg.message?.stop_reason;
|
|
1338
|
+
if (stopReason != null) {
|
|
1339
|
+
lastStopReason = stopReason;
|
|
1340
|
+
}
|
|
1341
|
+
this.mutableMessages.push(msg);
|
|
1342
|
+
yield* normalizeMessage(msg);
|
|
1343
|
+
break;
|
|
1344
|
+
}
|
|
1345
|
+
case "progress": {
|
|
1346
|
+
const msg = message;
|
|
1347
|
+
this.mutableMessages.push(msg);
|
|
1348
|
+
if (persistSession) {
|
|
1349
|
+
messages.push(msg);
|
|
1350
|
+
recordTranscript(messages);
|
|
1351
|
+
}
|
|
1352
|
+
yield* normalizeMessage(msg);
|
|
1353
|
+
break;
|
|
1354
|
+
}
|
|
1355
|
+
case "user": {
|
|
1356
|
+
const msg = message;
|
|
1357
|
+
this.mutableMessages.push(msg);
|
|
1358
|
+
yield* normalizeMessage(msg);
|
|
1359
|
+
break;
|
|
1360
|
+
}
|
|
1361
|
+
case "stream_event": {
|
|
1362
|
+
const event = message.event;
|
|
1363
|
+
if (event.type === "message_start") {
|
|
1364
|
+
currentMessageUsage = EMPTY_USAGE;
|
|
1365
|
+
const eventMessage = event.message;
|
|
1366
|
+
currentMessageUsage = updateUsage(currentMessageUsage, eventMessage.usage);
|
|
1367
|
+
}
|
|
1368
|
+
if (event.type === "message_delta") {
|
|
1369
|
+
currentMessageUsage = updateUsage(currentMessageUsage, event.usage);
|
|
1370
|
+
const delta = event.delta;
|
|
1371
|
+
if (delta.stop_reason != null) {
|
|
1372
|
+
lastStopReason = delta.stop_reason;
|
|
1373
|
+
}
|
|
1374
|
+
}
|
|
1375
|
+
if (event.type === "message_stop") {
|
|
1376
|
+
this.totalUsage = accumulateUsage(this.totalUsage, currentMessageUsage);
|
|
1377
|
+
}
|
|
1378
|
+
if (includePartialMessages) {
|
|
1379
|
+
yield {
|
|
1380
|
+
type: "stream_event",
|
|
1381
|
+
event,
|
|
1382
|
+
session_id: getSessionId(),
|
|
1383
|
+
parent_tool_use_id: null,
|
|
1384
|
+
uuid: randomUUID()
|
|
1385
|
+
};
|
|
1386
|
+
}
|
|
1387
|
+
break;
|
|
1388
|
+
}
|
|
1389
|
+
case "attachment": {
|
|
1390
|
+
const msg = message;
|
|
1391
|
+
this.mutableMessages.push(msg);
|
|
1392
|
+
if (persistSession) {
|
|
1393
|
+
messages.push(msg);
|
|
1394
|
+
recordTranscript(messages);
|
|
1395
|
+
}
|
|
1396
|
+
const attachment = msg.attachment;
|
|
1397
|
+
if (attachment.type === "structured_output") {
|
|
1398
|
+
structuredOutputFromTool = attachment.data;
|
|
1399
|
+
} else if (attachment.type === "max_turns_reached") {
|
|
1400
|
+
if (persistSession) {
|
|
1401
|
+
if (isEnvTruthy(process.env.CLAUDE_CODE_EAGER_FLUSH) || isEnvTruthy(process.env.CLAUDE_CODE_IS_COWORK)) {
|
|
1402
|
+
await flushSessionStorage();
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
yield {
|
|
1406
|
+
type: "result",
|
|
1407
|
+
subtype: "error_max_turns",
|
|
1408
|
+
duration_ms: Date.now() - startTime,
|
|
1409
|
+
duration_api_ms: getTotalAPIDuration(),
|
|
1410
|
+
is_error: true,
|
|
1411
|
+
num_turns: attachment.turnCount,
|
|
1412
|
+
stop_reason: lastStopReason,
|
|
1413
|
+
session_id: getSessionId(),
|
|
1414
|
+
total_cost_usd: getTotalCostUSD(),
|
|
1415
|
+
usage: this.totalUsage,
|
|
1416
|
+
modelUsage: getModelUsage(),
|
|
1417
|
+
permission_denials: this.permissionDenials,
|
|
1418
|
+
fast_mode_state: getFastModeState(mainLoopModel, initialAppState.fastMode),
|
|
1419
|
+
uuid: randomUUID(),
|
|
1420
|
+
errors: [
|
|
1421
|
+
`Reached maximum number of turns (${attachment.maxTurns})`
|
|
1422
|
+
]
|
|
1423
|
+
};
|
|
1424
|
+
return;
|
|
1425
|
+
} else if (replayUserMessages && attachment.type === "queued_command") {
|
|
1426
|
+
yield {
|
|
1427
|
+
type: "user",
|
|
1428
|
+
message: {
|
|
1429
|
+
role: "user",
|
|
1430
|
+
content: attachment.prompt
|
|
1431
|
+
},
|
|
1432
|
+
session_id: getSessionId(),
|
|
1433
|
+
parent_tool_use_id: null,
|
|
1434
|
+
uuid: attachment.source_uuid || msg.uuid,
|
|
1435
|
+
timestamp: msg.timestamp,
|
|
1436
|
+
isReplay: true
|
|
1437
|
+
};
|
|
1438
|
+
}
|
|
1439
|
+
break;
|
|
1440
|
+
}
|
|
1441
|
+
case "stream_request_start":
|
|
1442
|
+
break;
|
|
1443
|
+
case "system": {
|
|
1444
|
+
const msg = message;
|
|
1445
|
+
const snipResult = this.config.snipReplay?.(msg, this.mutableMessages);
|
|
1446
|
+
if (snipResult !== undefined) {
|
|
1447
|
+
if (snipResult.executed) {
|
|
1448
|
+
this.mutableMessages.length = 0;
|
|
1449
|
+
this.mutableMessages.push(...snipResult.messages);
|
|
1450
|
+
}
|
|
1451
|
+
break;
|
|
1452
|
+
}
|
|
1453
|
+
this.mutableMessages.push(msg);
|
|
1454
|
+
if (msg.subtype === "compact_boundary" && msg.compactMetadata) {
|
|
1455
|
+
const compactMsg = msg;
|
|
1456
|
+
const mutableBoundaryIdx = this.mutableMessages.length - 1;
|
|
1457
|
+
if (mutableBoundaryIdx > 0) {
|
|
1458
|
+
this.mutableMessages.splice(0, mutableBoundaryIdx);
|
|
1459
|
+
}
|
|
1460
|
+
const localBoundaryIdx = messages.length - 1;
|
|
1461
|
+
if (localBoundaryIdx > 0) {
|
|
1462
|
+
messages.splice(0, localBoundaryIdx);
|
|
1463
|
+
}
|
|
1464
|
+
yield {
|
|
1465
|
+
type: "system",
|
|
1466
|
+
subtype: "compact_boundary",
|
|
1467
|
+
session_id: getSessionId(),
|
|
1468
|
+
uuid: msg.uuid,
|
|
1469
|
+
compact_metadata: toSDKCompactMetadata(compactMsg.compactMetadata)
|
|
1470
|
+
};
|
|
1471
|
+
}
|
|
1472
|
+
if (msg.subtype === "api_error") {
|
|
1473
|
+
const apiErrorMsg = msg;
|
|
1474
|
+
yield {
|
|
1475
|
+
type: "system",
|
|
1476
|
+
subtype: "api_retry",
|
|
1477
|
+
attempt: apiErrorMsg.retryAttempt,
|
|
1478
|
+
max_retries: apiErrorMsg.maxRetries,
|
|
1479
|
+
retry_delay_ms: apiErrorMsg.retryInMs,
|
|
1480
|
+
error_status: apiErrorMsg.error.status ?? null,
|
|
1481
|
+
error: categorizeRetryableAPIError(apiErrorMsg.error),
|
|
1482
|
+
session_id: getSessionId(),
|
|
1483
|
+
uuid: msg.uuid
|
|
1484
|
+
};
|
|
1485
|
+
}
|
|
1486
|
+
break;
|
|
1487
|
+
}
|
|
1488
|
+
case "tool_use_summary": {
|
|
1489
|
+
const msg = message;
|
|
1490
|
+
yield {
|
|
1491
|
+
type: "tool_use_summary",
|
|
1492
|
+
summary: msg.summary,
|
|
1493
|
+
preceding_tool_use_ids: msg.precedingToolUseIds,
|
|
1494
|
+
session_id: getSessionId(),
|
|
1495
|
+
uuid: msg.uuid
|
|
1496
|
+
};
|
|
1497
|
+
break;
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
if (maxBudgetUsd !== undefined && getTotalCostUSD() >= maxBudgetUsd) {
|
|
1501
|
+
if (persistSession) {
|
|
1502
|
+
if (isEnvTruthy(process.env.CLAUDE_CODE_EAGER_FLUSH) || isEnvTruthy(process.env.CLAUDE_CODE_IS_COWORK)) {
|
|
1503
|
+
await flushSessionStorage();
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
yield {
|
|
1507
|
+
type: "result",
|
|
1508
|
+
subtype: "error_max_budget_usd",
|
|
1509
|
+
duration_ms: Date.now() - startTime,
|
|
1510
|
+
duration_api_ms: getTotalAPIDuration(),
|
|
1511
|
+
is_error: true,
|
|
1512
|
+
num_turns: turnCount,
|
|
1513
|
+
stop_reason: lastStopReason,
|
|
1514
|
+
session_id: getSessionId(),
|
|
1515
|
+
total_cost_usd: getTotalCostUSD(),
|
|
1516
|
+
usage: this.totalUsage,
|
|
1517
|
+
modelUsage: getModelUsage(),
|
|
1518
|
+
permission_denials: this.permissionDenials,
|
|
1519
|
+
fast_mode_state: getFastModeState(mainLoopModel, initialAppState.fastMode),
|
|
1520
|
+
uuid: randomUUID(),
|
|
1521
|
+
errors: [`Reached maximum budget ($${maxBudgetUsd})`]
|
|
1522
|
+
};
|
|
1523
|
+
return;
|
|
1524
|
+
}
|
|
1525
|
+
if (message.type === "user" && jsonSchema) {
|
|
1526
|
+
const currentCalls = countToolCalls(this.mutableMessages, SYNTHETIC_OUTPUT_TOOL_NAME);
|
|
1527
|
+
const callsThisQuery = currentCalls - initialStructuredOutputCalls;
|
|
1528
|
+
const maxRetries = parseInt(process.env.MAX_STRUCTURED_OUTPUT_RETRIES || "5", 10);
|
|
1529
|
+
if (callsThisQuery >= maxRetries) {
|
|
1530
|
+
if (persistSession) {
|
|
1531
|
+
if (isEnvTruthy(process.env.CLAUDE_CODE_EAGER_FLUSH) || isEnvTruthy(process.env.CLAUDE_CODE_IS_COWORK)) {
|
|
1532
|
+
await flushSessionStorage();
|
|
1533
|
+
}
|
|
1534
|
+
}
|
|
1535
|
+
yield {
|
|
1536
|
+
type: "result",
|
|
1537
|
+
subtype: "error_max_structured_output_retries",
|
|
1538
|
+
duration_ms: Date.now() - startTime,
|
|
1539
|
+
duration_api_ms: getTotalAPIDuration(),
|
|
1540
|
+
is_error: true,
|
|
1541
|
+
num_turns: turnCount,
|
|
1542
|
+
stop_reason: lastStopReason,
|
|
1543
|
+
session_id: getSessionId(),
|
|
1544
|
+
total_cost_usd: getTotalCostUSD(),
|
|
1545
|
+
usage: this.totalUsage,
|
|
1546
|
+
modelUsage: getModelUsage(),
|
|
1547
|
+
permission_denials: this.permissionDenials,
|
|
1548
|
+
fast_mode_state: getFastModeState(mainLoopModel, initialAppState.fastMode),
|
|
1549
|
+
uuid: randomUUID(),
|
|
1550
|
+
errors: [
|
|
1551
|
+
`Failed to provide valid structured output after ${maxRetries} attempts`
|
|
1552
|
+
]
|
|
1553
|
+
};
|
|
1554
|
+
return;
|
|
1555
|
+
}
|
|
1556
|
+
}
|
|
1557
|
+
}
|
|
1558
|
+
const result = messages.findLast((m) => m.type === "assistant" || m.type === "user");
|
|
1559
|
+
const edeResultType = result?.type ?? "undefined";
|
|
1560
|
+
const edeLastContentType = result?.type === "assistant" ? last_default(result.message.content)?.type ?? "none" : "n/a";
|
|
1561
|
+
if (persistSession) {
|
|
1562
|
+
if (isEnvTruthy(process.env.CLAUDE_CODE_EAGER_FLUSH) || isEnvTruthy(process.env.CLAUDE_CODE_IS_COWORK)) {
|
|
1563
|
+
await flushSessionStorage();
|
|
1564
|
+
}
|
|
1565
|
+
}
|
|
1566
|
+
if (!isResultSuccessful(result, lastStopReason)) {
|
|
1567
|
+
yield {
|
|
1568
|
+
type: "result",
|
|
1569
|
+
subtype: "error_during_execution",
|
|
1570
|
+
duration_ms: Date.now() - startTime,
|
|
1571
|
+
duration_api_ms: getTotalAPIDuration(),
|
|
1572
|
+
is_error: true,
|
|
1573
|
+
num_turns: turnCount,
|
|
1574
|
+
stop_reason: lastStopReason,
|
|
1575
|
+
session_id: getSessionId(),
|
|
1576
|
+
total_cost_usd: getTotalCostUSD(),
|
|
1577
|
+
usage: this.totalUsage,
|
|
1578
|
+
modelUsage: getModelUsage(),
|
|
1579
|
+
permission_denials: this.permissionDenials,
|
|
1580
|
+
fast_mode_state: getFastModeState(mainLoopModel, initialAppState.fastMode),
|
|
1581
|
+
uuid: randomUUID(),
|
|
1582
|
+
errors: (() => {
|
|
1583
|
+
const all = getInMemoryErrors();
|
|
1584
|
+
const start = errorLogWatermark ? all.lastIndexOf(errorLogWatermark) + 1 : 0;
|
|
1585
|
+
return [
|
|
1586
|
+
`[ede_diagnostic] result_type=${edeResultType} last_content_type=${edeLastContentType} stop_reason=${lastStopReason}`,
|
|
1587
|
+
...all.slice(start).map((_) => _.error)
|
|
1588
|
+
];
|
|
1589
|
+
})()
|
|
1590
|
+
};
|
|
1591
|
+
return;
|
|
1592
|
+
}
|
|
1593
|
+
let textResult = "";
|
|
1594
|
+
let isApiError = false;
|
|
1595
|
+
if (result.type === "assistant") {
|
|
1596
|
+
const lastContent = last_default(result.message.content);
|
|
1597
|
+
if (lastContent?.type === "text" && !SYNTHETIC_MESSAGES.has(lastContent.text)) {
|
|
1598
|
+
textResult = lastContent.text;
|
|
1599
|
+
}
|
|
1600
|
+
isApiError = Boolean(result.isApiErrorMessage);
|
|
1601
|
+
}
|
|
1602
|
+
yield {
|
|
1603
|
+
type: "result",
|
|
1604
|
+
subtype: "success",
|
|
1605
|
+
is_error: isApiError,
|
|
1606
|
+
duration_ms: Date.now() - startTime,
|
|
1607
|
+
duration_api_ms: getTotalAPIDuration(),
|
|
1608
|
+
num_turns: turnCount,
|
|
1609
|
+
result: textResult,
|
|
1610
|
+
stop_reason: lastStopReason,
|
|
1611
|
+
session_id: getSessionId(),
|
|
1612
|
+
total_cost_usd: getTotalCostUSD(),
|
|
1613
|
+
usage: this.totalUsage,
|
|
1614
|
+
modelUsage: getModelUsage(),
|
|
1615
|
+
permission_denials: this.permissionDenials,
|
|
1616
|
+
structured_output: structuredOutputFromTool,
|
|
1617
|
+
fast_mode_state: getFastModeState(mainLoopModel, initialAppState.fastMode),
|
|
1618
|
+
uuid: randomUUID()
|
|
1619
|
+
};
|
|
1620
|
+
}
|
|
1621
|
+
interrupt() {
|
|
1622
|
+
this.abortController.abort();
|
|
1623
|
+
}
|
|
1624
|
+
getMessages() {
|
|
1625
|
+
return this.mutableMessages;
|
|
1626
|
+
}
|
|
1627
|
+
getReadFileState() {
|
|
1628
|
+
return this.readFileState;
|
|
1629
|
+
}
|
|
1630
|
+
getSessionId() {
|
|
1631
|
+
return getSessionId();
|
|
1632
|
+
}
|
|
1633
|
+
setModel(model) {
|
|
1634
|
+
this.config.userSpecifiedModel = model;
|
|
1635
|
+
}
|
|
1636
|
+
}
|
|
1637
|
+
async function* ask({
|
|
1638
|
+
commands,
|
|
1639
|
+
prompt,
|
|
1640
|
+
promptUuid,
|
|
1641
|
+
isMeta,
|
|
1642
|
+
cwd,
|
|
1643
|
+
tools,
|
|
1644
|
+
mcpClients,
|
|
1645
|
+
verbose = false,
|
|
1646
|
+
thinkingConfig,
|
|
1647
|
+
maxTurns,
|
|
1648
|
+
maxBudgetUsd,
|
|
1649
|
+
taskBudget,
|
|
1650
|
+
canUseTool,
|
|
1651
|
+
mutableMessages = [],
|
|
1652
|
+
getReadFileCache,
|
|
1653
|
+
setReadFileCache,
|
|
1654
|
+
customSystemPrompt,
|
|
1655
|
+
appendSystemPrompt,
|
|
1656
|
+
userSpecifiedModel,
|
|
1657
|
+
fallbackModel,
|
|
1658
|
+
jsonSchema,
|
|
1659
|
+
getAppState,
|
|
1660
|
+
setAppState,
|
|
1661
|
+
abortController,
|
|
1662
|
+
replayUserMessages = false,
|
|
1663
|
+
includePartialMessages = false,
|
|
1664
|
+
handleElicitation,
|
|
1665
|
+
agents = [],
|
|
1666
|
+
setSDKStatus,
|
|
1667
|
+
orphanedPermission
|
|
1668
|
+
}) {
|
|
1669
|
+
const engine = new QueryEngine({
|
|
1670
|
+
cwd,
|
|
1671
|
+
tools,
|
|
1672
|
+
commands,
|
|
1673
|
+
mcpClients,
|
|
1674
|
+
agents: agents ?? [],
|
|
1675
|
+
canUseTool,
|
|
1676
|
+
getAppState,
|
|
1677
|
+
setAppState,
|
|
1678
|
+
initialMessages: mutableMessages,
|
|
1679
|
+
readFileCache: cloneFileStateCache(getReadFileCache()),
|
|
1680
|
+
customSystemPrompt,
|
|
1681
|
+
appendSystemPrompt,
|
|
1682
|
+
userSpecifiedModel,
|
|
1683
|
+
fallbackModel,
|
|
1684
|
+
thinkingConfig,
|
|
1685
|
+
maxTurns,
|
|
1686
|
+
maxBudgetUsd,
|
|
1687
|
+
taskBudget,
|
|
1688
|
+
jsonSchema,
|
|
1689
|
+
verbose,
|
|
1690
|
+
handleElicitation,
|
|
1691
|
+
replayUserMessages,
|
|
1692
|
+
includePartialMessages,
|
|
1693
|
+
setSDKStatus,
|
|
1694
|
+
abortController,
|
|
1695
|
+
orphanedPermission,
|
|
1696
|
+
...{}
|
|
1697
|
+
});
|
|
1698
|
+
try {
|
|
1699
|
+
yield* engine.submitMessage(prompt, {
|
|
1700
|
+
uuid: promptUuid,
|
|
1701
|
+
isMeta
|
|
1702
|
+
});
|
|
1703
|
+
} finally {
|
|
1704
|
+
setReadFileCache(engine.getReadFileState());
|
|
1705
|
+
}
|
|
1706
|
+
}
|
|
1707
|
+
|
|
1708
|
+
// src/cli/print.ts
|
|
1709
|
+
init_fileStateCache();
|
|
1710
|
+
init_path();
|
|
1711
|
+
init_queryHelpers();
|
|
1712
|
+
init_hookEvents();
|
|
1713
|
+
|
|
1714
|
+
// src/utils/filePersistence/filePersistence.ts
|
|
1715
|
+
init_analytics();
|
|
1716
|
+
init_filesApi();
|
|
1717
|
+
init_cwd();
|
|
1718
|
+
init_errors();
|
|
1719
|
+
init_log();
|
|
1720
|
+
init_sessionIngressAuth();
|
|
1721
|
+
init_outputsScanner();
|
|
1722
|
+
|
|
1723
|
+
// src/cli/print.ts
|
|
1724
|
+
init_AsyncHookRegistry();
|
|
1725
|
+
init_gracefulShutdown();
|
|
1726
|
+
init_cleanupRegistry();
|
|
1727
|
+
|
|
1728
|
+
// src/utils/idleTimeout.ts
|
|
1729
|
+
init_debug();
|
|
1730
|
+
init_gracefulShutdown();
|
|
1731
|
+
function createIdleTimeoutManager(isIdle) {
|
|
1732
|
+
const exitAfterStopDelay = process.env.CLAUDE_CODE_EXIT_AFTER_STOP_DELAY;
|
|
1733
|
+
const delayMs = exitAfterStopDelay ? parseInt(exitAfterStopDelay, 10) : null;
|
|
1734
|
+
const isValidDelay = delayMs && !isNaN(delayMs) && delayMs > 0;
|
|
1735
|
+
let timer = null;
|
|
1736
|
+
let lastIdleTime = 0;
|
|
1737
|
+
return {
|
|
1738
|
+
start() {
|
|
1739
|
+
if (timer) {
|
|
1740
|
+
clearTimeout(timer);
|
|
1741
|
+
timer = null;
|
|
1742
|
+
}
|
|
1743
|
+
if (isValidDelay) {
|
|
1744
|
+
lastIdleTime = Date.now();
|
|
1745
|
+
timer = setTimeout(() => {
|
|
1746
|
+
const idleDuration = Date.now() - lastIdleTime;
|
|
1747
|
+
if (isIdle() && idleDuration >= delayMs) {
|
|
1748
|
+
logForDebugging(`Exiting after ${delayMs}ms of idle time`);
|
|
1749
|
+
gracefulShutdownSync();
|
|
1750
|
+
}
|
|
1751
|
+
}, delayMs);
|
|
1752
|
+
}
|
|
1753
|
+
},
|
|
1754
|
+
stop() {
|
|
1755
|
+
if (timer) {
|
|
1756
|
+
clearTimeout(timer);
|
|
1757
|
+
timer = null;
|
|
1758
|
+
}
|
|
1759
|
+
}
|
|
1760
|
+
};
|
|
1761
|
+
}
|
|
1762
|
+
|
|
1763
|
+
// src/cli/print.ts
|
|
1764
|
+
init_cwd();
|
|
1765
|
+
init_omit();
|
|
1766
|
+
init_reject();
|
|
1767
|
+
init_policyLimits();
|
|
1768
|
+
init_bridgeStatusUtil();
|
|
1769
|
+
import { cwd } from "process";
|
|
1770
|
+
|
|
1771
|
+
// src/bridge/inboundAttachments.ts
|
|
1772
|
+
init_axios();
|
|
1773
|
+
init_v4();
|
|
1774
|
+
init_state();
|
|
1775
|
+
init_debug();
|
|
1776
|
+
init_envUtils();
|
|
1777
|
+
init_bridgeConfig();
|
|
1778
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
1779
|
+
import { mkdir, writeFile } from "fs/promises";
|
|
1780
|
+
import { basename, join } from "path";
|
|
1781
|
+
var DOWNLOAD_TIMEOUT_MS = 30000;
|
|
1782
|
+
function debug(msg) {
|
|
1783
|
+
logForDebugging(`[bridge:inbound-attach] ${msg}`);
|
|
1784
|
+
}
|
|
1785
|
+
var attachmentSchema = lazySchema(() => exports_external.object({
|
|
1786
|
+
file_uuid: exports_external.string(),
|
|
1787
|
+
file_name: exports_external.string()
|
|
1788
|
+
}));
|
|
1789
|
+
var attachmentsArraySchema = lazySchema(() => exports_external.array(attachmentSchema()));
|
|
1790
|
+
function extractInboundAttachments(msg) {
|
|
1791
|
+
if (typeof msg !== "object" || msg === null || !("file_attachments" in msg)) {
|
|
1792
|
+
return [];
|
|
1793
|
+
}
|
|
1794
|
+
const parsed = attachmentsArraySchema().safeParse(msg.file_attachments);
|
|
1795
|
+
return parsed.success ? parsed.data : [];
|
|
1796
|
+
}
|
|
1797
|
+
function sanitizeFileName(name) {
|
|
1798
|
+
const base = basename(name).replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
1799
|
+
return base || "attachment";
|
|
1800
|
+
}
|
|
1801
|
+
function uploadsDir() {
|
|
1802
|
+
return join(getClaudeConfigHomeDir(), "uploads", getSessionId());
|
|
1803
|
+
}
|
|
1804
|
+
async function resolveOne(att) {
|
|
1805
|
+
const token = getBridgeAccessToken();
|
|
1806
|
+
if (!token) {
|
|
1807
|
+
debug("skip: no oauth token");
|
|
1808
|
+
return;
|
|
1809
|
+
}
|
|
1810
|
+
let data;
|
|
1811
|
+
try {
|
|
1812
|
+
const url = `${getBridgeBaseUrl()}/api/oauth/files/${encodeURIComponent(att.file_uuid)}/content`;
|
|
1813
|
+
const response = await axios_default.get(url, {
|
|
1814
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
1815
|
+
responseType: "arraybuffer",
|
|
1816
|
+
timeout: DOWNLOAD_TIMEOUT_MS,
|
|
1817
|
+
validateStatus: () => true
|
|
1818
|
+
});
|
|
1819
|
+
if (response.status !== 200) {
|
|
1820
|
+
debug(`fetch ${att.file_uuid} failed: status=${response.status}`);
|
|
1821
|
+
return;
|
|
1822
|
+
}
|
|
1823
|
+
data = Buffer.from(response.data);
|
|
1824
|
+
} catch (e) {
|
|
1825
|
+
debug(`fetch ${att.file_uuid} threw: ${e}`);
|
|
1826
|
+
return;
|
|
1827
|
+
}
|
|
1828
|
+
const safeName = sanitizeFileName(att.file_name);
|
|
1829
|
+
const prefix = (att.file_uuid.slice(0, 8) || randomUUID2().slice(0, 8)).replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
1830
|
+
const dir = uploadsDir();
|
|
1831
|
+
const outPath = join(dir, `${prefix}-${safeName}`);
|
|
1832
|
+
try {
|
|
1833
|
+
await mkdir(dir, { recursive: true });
|
|
1834
|
+
await writeFile(outPath, data);
|
|
1835
|
+
} catch (e) {
|
|
1836
|
+
debug(`write ${outPath} failed: ${e}`);
|
|
1837
|
+
return;
|
|
1838
|
+
}
|
|
1839
|
+
debug(`resolved ${att.file_uuid} \u2192 ${outPath} (${data.length} bytes)`);
|
|
1840
|
+
return outPath;
|
|
1841
|
+
}
|
|
1842
|
+
async function resolveInboundAttachments(attachments) {
|
|
1843
|
+
if (attachments.length === 0)
|
|
1844
|
+
return "";
|
|
1845
|
+
debug(`resolving ${attachments.length} attachment(s)`);
|
|
1846
|
+
const paths = await Promise.all(attachments.map(resolveOne));
|
|
1847
|
+
const ok = paths.filter((p) => p !== undefined);
|
|
1848
|
+
if (ok.length === 0)
|
|
1849
|
+
return "";
|
|
1850
|
+
return ok.map((p) => `@"${p}"`).join(" ") + " ";
|
|
1851
|
+
}
|
|
1852
|
+
function prependPathRefs(content, prefix) {
|
|
1853
|
+
if (!prefix)
|
|
1854
|
+
return content;
|
|
1855
|
+
if (typeof content === "string")
|
|
1856
|
+
return prefix + content;
|
|
1857
|
+
const i = content.findLastIndex((b) => b.type === "text");
|
|
1858
|
+
if (i !== -1) {
|
|
1859
|
+
const b = content[i];
|
|
1860
|
+
if (b.type === "text") {
|
|
1861
|
+
return [
|
|
1862
|
+
...content.slice(0, i),
|
|
1863
|
+
{ ...b, text: prefix + b.text },
|
|
1864
|
+
...content.slice(i + 1)
|
|
1865
|
+
];
|
|
1866
|
+
}
|
|
1867
|
+
}
|
|
1868
|
+
return [...content, { type: "text", text: prefix.trimEnd() }];
|
|
1869
|
+
}
|
|
1870
|
+
async function resolveAndPrepend(msg, content) {
|
|
1871
|
+
const attachments = extractInboundAttachments(msg);
|
|
1872
|
+
if (attachments.length === 0)
|
|
1873
|
+
return content;
|
|
1874
|
+
const prefix = await resolveInboundAttachments(attachments);
|
|
1875
|
+
return prependPathRefs(content, prefix);
|
|
1876
|
+
}
|
|
1877
|
+
|
|
1878
|
+
// src/cli/print.ts
|
|
1879
|
+
init_permissions();
|
|
1880
|
+
init_json();
|
|
1881
|
+
init_abortController();
|
|
1882
|
+
init_combinedAbortSignal();
|
|
1883
|
+
init_sessionTitle();
|
|
1884
|
+
init_sideQuestion();
|
|
1885
|
+
init_sessionStart();
|
|
1886
|
+
init_outputStyles();
|
|
1887
|
+
init_xml();
|
|
1888
|
+
init_settings();
|
|
1889
|
+
init_changeDetector();
|
|
1890
|
+
init_applySettingsChange();
|
|
1891
|
+
init_fastMode();
|
|
1892
|
+
init_permissionSetup();
|
|
1893
|
+
init_promptSuggestion();
|
|
1894
|
+
init_forkedAgent();
|
|
1895
|
+
init_auth();
|
|
1896
|
+
init_oauth();
|
|
1897
|
+
init_auth2();
|
|
1898
|
+
init_providers();
|
|
1899
|
+
init_awsAuthStatusManager();
|
|
1900
|
+
init_state();
|
|
1901
|
+
init_SyntheticOutputTool();
|
|
1902
|
+
|
|
1903
|
+
// src/utils/sessionUrl.ts
|
|
1904
|
+
init_uuid();
|
|
1905
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
1906
|
+
function parseSessionIdentifier(resumeIdentifier) {
|
|
1907
|
+
if (resumeIdentifier.toLowerCase().endsWith(".jsonl")) {
|
|
1908
|
+
return {
|
|
1909
|
+
sessionId: randomUUID3(),
|
|
1910
|
+
ingressUrl: null,
|
|
1911
|
+
isUrl: false,
|
|
1912
|
+
jsonlFile: resumeIdentifier,
|
|
1913
|
+
isJsonlFile: true
|
|
1914
|
+
};
|
|
1915
|
+
}
|
|
1916
|
+
if (validateUuid(resumeIdentifier)) {
|
|
1917
|
+
return {
|
|
1918
|
+
sessionId: resumeIdentifier,
|
|
1919
|
+
ingressUrl: null,
|
|
1920
|
+
isUrl: false,
|
|
1921
|
+
jsonlFile: null,
|
|
1922
|
+
isJsonlFile: false
|
|
1923
|
+
};
|
|
1924
|
+
}
|
|
1925
|
+
try {
|
|
1926
|
+
const url = new URL(resumeIdentifier);
|
|
1927
|
+
return {
|
|
1928
|
+
sessionId: randomUUID3(),
|
|
1929
|
+
ingressUrl: url.href,
|
|
1930
|
+
isUrl: true,
|
|
1931
|
+
jsonlFile: null,
|
|
1932
|
+
isJsonlFile: false
|
|
1933
|
+
};
|
|
1934
|
+
} catch {}
|
|
1935
|
+
return null;
|
|
1936
|
+
}
|
|
1937
|
+
|
|
1938
|
+
// src/cli/print.ts
|
|
1939
|
+
init_sessionStorage();
|
|
1940
|
+
init_commitAttribution();
|
|
1941
|
+
init_client();
|
|
1942
|
+
init_config2();
|
|
1943
|
+
init_auth3();
|
|
1944
|
+
init_elicitationHandler();
|
|
1945
|
+
init_hooks();
|
|
1946
|
+
init_types();
|
|
1947
|
+
init_mcpStringUtils();
|
|
1948
|
+
init_utils();
|
|
1949
|
+
init_vscodeSdkMcp();
|
|
1950
|
+
init_config2();
|
|
1951
|
+
init_grove();
|
|
1952
|
+
init_mappers();
|
|
1953
|
+
init_messages();
|
|
1954
|
+
init_context_noninteractive();
|
|
1955
|
+
init_xml();
|
|
1956
|
+
init_claudeAiLimits();
|
|
1957
|
+
init_model();
|
|
1958
|
+
init_modelOptions();
|
|
1959
|
+
init_effort();
|
|
1960
|
+
init_thinking();
|
|
1961
|
+
init_betas();
|
|
1962
|
+
init_modelStrings();
|
|
1963
|
+
init_state();
|
|
1964
|
+
init_workloadContext();
|
|
1965
|
+
init_fileHistory();
|
|
1966
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
1967
|
+
init_sandbox_adapter();
|
|
1968
|
+
init_headlessProfiler();
|
|
1969
|
+
init_queryProfiler();
|
|
1970
|
+
init_ids();
|
|
1971
|
+
init_slowOperations();
|
|
1972
|
+
init_commands();
|
|
1973
|
+
init_envUtils();
|
|
1974
|
+
|
|
1975
|
+
// src/utils/plugins/headlessPluginInstall.ts
|
|
1976
|
+
init_analytics();
|
|
1977
|
+
init_cleanupRegistry();
|
|
1978
|
+
init_debug();
|
|
1979
|
+
init_diagLogs();
|
|
1980
|
+
init_fsOperations();
|
|
1981
|
+
init_log();
|
|
1982
|
+
init_marketplaceManager();
|
|
1983
|
+
init_pluginLoader();
|
|
1984
|
+
init_zipCache();
|
|
1985
|
+
|
|
1986
|
+
// src/utils/plugins/zipCacheAdapters.ts
|
|
1987
|
+
init_debug();
|
|
1988
|
+
init_slowOperations();
|
|
1989
|
+
init_marketplaceManager();
|
|
1990
|
+
init_schemas();
|
|
1991
|
+
init_zipCache();
|
|
1992
|
+
import { readFile } from "fs/promises";
|
|
1993
|
+
import { join as join2 } from "path";
|
|
1994
|
+
async function readZipCacheKnownMarketplaces() {
|
|
1995
|
+
try {
|
|
1996
|
+
const content = await readFile(getZipCacheKnownMarketplacesPath(), "utf-8");
|
|
1997
|
+
const parsed = KnownMarketplacesFileSchema().safeParse(jsonParse(content));
|
|
1998
|
+
if (!parsed.success) {
|
|
1999
|
+
logForDebugging(`Invalid known_marketplaces.json in zip cache: ${parsed.error.message}`, { level: "error" });
|
|
2000
|
+
return {};
|
|
2001
|
+
}
|
|
2002
|
+
return parsed.data;
|
|
2003
|
+
} catch {
|
|
2004
|
+
return {};
|
|
2005
|
+
}
|
|
2006
|
+
}
|
|
2007
|
+
async function writeZipCacheKnownMarketplaces(data) {
|
|
2008
|
+
await atomicWriteToZipCache(getZipCacheKnownMarketplacesPath(), jsonStringify(data, null, 2));
|
|
2009
|
+
}
|
|
2010
|
+
async function saveMarketplaceJsonToZipCache(marketplaceName, installLocation) {
|
|
2011
|
+
const zipCachePath = getPluginZipCachePath();
|
|
2012
|
+
if (!zipCachePath) {
|
|
2013
|
+
return;
|
|
2014
|
+
}
|
|
2015
|
+
const content = await readMarketplaceJsonContent(installLocation);
|
|
2016
|
+
if (content !== null) {
|
|
2017
|
+
const relPath = getMarketplaceJsonRelativePath(marketplaceName);
|
|
2018
|
+
await atomicWriteToZipCache(join2(zipCachePath, relPath), content);
|
|
2019
|
+
}
|
|
2020
|
+
}
|
|
2021
|
+
async function readMarketplaceJsonContent(dir) {
|
|
2022
|
+
const candidates = [
|
|
2023
|
+
join2(dir, ".claude-plugin", "marketplace.json"),
|
|
2024
|
+
join2(dir, "marketplace.json"),
|
|
2025
|
+
dir
|
|
2026
|
+
];
|
|
2027
|
+
for (const candidate of candidates) {
|
|
2028
|
+
try {
|
|
2029
|
+
return await readFile(candidate, "utf-8");
|
|
2030
|
+
} catch {}
|
|
2031
|
+
}
|
|
2032
|
+
return null;
|
|
2033
|
+
}
|
|
2034
|
+
async function syncMarketplacesToZipCache() {
|
|
2035
|
+
const knownMarketplaces = await loadKnownMarketplacesConfigSafe();
|
|
2036
|
+
for (const [name, entry] of Object.entries(knownMarketplaces)) {
|
|
2037
|
+
if (!entry.installLocation)
|
|
2038
|
+
continue;
|
|
2039
|
+
try {
|
|
2040
|
+
await saveMarketplaceJsonToZipCache(name, entry.installLocation);
|
|
2041
|
+
} catch (error) {
|
|
2042
|
+
logForDebugging(`Failed to save marketplace JSON for ${name}: ${error}`);
|
|
2043
|
+
}
|
|
2044
|
+
}
|
|
2045
|
+
const zipCacheKnownMarketplaces = await readZipCacheKnownMarketplaces();
|
|
2046
|
+
const mergedKnownMarketplaces = {
|
|
2047
|
+
...zipCacheKnownMarketplaces,
|
|
2048
|
+
...knownMarketplaces
|
|
2049
|
+
};
|
|
2050
|
+
await writeZipCacheKnownMarketplaces(mergedKnownMarketplaces);
|
|
2051
|
+
}
|
|
2052
|
+
|
|
2053
|
+
// src/utils/plugins/headlessPluginInstall.ts
|
|
2054
|
+
async function installPluginsForHeadless() {
|
|
2055
|
+
const zipCacheMode = isPluginZipCacheEnabled();
|
|
2056
|
+
logForDebugging(`installPluginsForHeadless: starting${zipCacheMode ? " (zip cache mode)" : ""}`);
|
|
2057
|
+
const seedChanged = await registerSeedMarketplaces();
|
|
2058
|
+
if (seedChanged) {
|
|
2059
|
+
clearMarketplacesCache();
|
|
2060
|
+
clearPluginCache("headlessPluginInstall: seed marketplaces registered");
|
|
2061
|
+
}
|
|
2062
|
+
if (zipCacheMode) {
|
|
2063
|
+
await getFsImplementation().mkdir(getZipCacheMarketplacesDir());
|
|
2064
|
+
await getFsImplementation().mkdir(getZipCachePluginsDir());
|
|
2065
|
+
}
|
|
2066
|
+
const declaredCount = Object.keys(getDeclaredMarketplaces()).length;
|
|
2067
|
+
const metrics = {
|
|
2068
|
+
marketplaces_installed: 0,
|
|
2069
|
+
delisted_count: 0
|
|
2070
|
+
};
|
|
2071
|
+
let pluginsChanged = seedChanged;
|
|
2072
|
+
try {
|
|
2073
|
+
if (declaredCount === 0) {
|
|
2074
|
+
logForDebugging("installPluginsForHeadless: no marketplaces declared");
|
|
2075
|
+
} else {
|
|
2076
|
+
const reconcileResult = await withDiagnosticsTiming("headless_marketplace_reconcile", () => reconcileMarketplaces({
|
|
2077
|
+
skip: zipCacheMode ? (_name, source) => !isMarketplaceSourceSupportedByZipCache(source) : undefined,
|
|
2078
|
+
onProgress: (event) => {
|
|
2079
|
+
if (event.type === "installed") {
|
|
2080
|
+
logForDebugging(`installPluginsForHeadless: installed marketplace ${event.name}`);
|
|
2081
|
+
} else if (event.type === "failed") {
|
|
2082
|
+
logForDebugging(`installPluginsForHeadless: failed to install marketplace ${event.name}: ${event.error}`);
|
|
2083
|
+
}
|
|
2084
|
+
}
|
|
2085
|
+
}), (r) => ({
|
|
2086
|
+
installed_count: r.installed.length,
|
|
2087
|
+
updated_count: r.updated.length,
|
|
2088
|
+
failed_count: r.failed.length,
|
|
2089
|
+
skipped_count: r.skipped.length
|
|
2090
|
+
}));
|
|
2091
|
+
if (reconcileResult.skipped.length > 0) {
|
|
2092
|
+
logForDebugging(`installPluginsForHeadless: skipped ${reconcileResult.skipped.length} marketplace(s) unsupported by zip cache: ${reconcileResult.skipped.join(", ")}`);
|
|
2093
|
+
}
|
|
2094
|
+
const marketplacesChanged = reconcileResult.installed.length + reconcileResult.updated.length;
|
|
2095
|
+
if (marketplacesChanged > 0) {
|
|
2096
|
+
clearMarketplacesCache();
|
|
2097
|
+
clearPluginCache("headlessPluginInstall: marketplaces reconciled");
|
|
2098
|
+
pluginsChanged = true;
|
|
2099
|
+
}
|
|
2100
|
+
metrics.marketplaces_installed = marketplacesChanged;
|
|
2101
|
+
}
|
|
2102
|
+
if (zipCacheMode) {
|
|
2103
|
+
await syncMarketplacesToZipCache();
|
|
2104
|
+
}
|
|
2105
|
+
const newlyDelisted = await detectAndUninstallDelistedPlugins();
|
|
2106
|
+
metrics.delisted_count = newlyDelisted.length;
|
|
2107
|
+
if (newlyDelisted.length > 0) {
|
|
2108
|
+
pluginsChanged = true;
|
|
2109
|
+
}
|
|
2110
|
+
if (pluginsChanged) {
|
|
2111
|
+
clearPluginCache("headlessPluginInstall: plugins changed");
|
|
2112
|
+
}
|
|
2113
|
+
if (zipCacheMode) {
|
|
2114
|
+
registerCleanup(cleanupSessionPluginCache);
|
|
2115
|
+
}
|
|
2116
|
+
return pluginsChanged;
|
|
2117
|
+
} catch (error) {
|
|
2118
|
+
logError(error);
|
|
2119
|
+
return false;
|
|
2120
|
+
} finally {
|
|
2121
|
+
logEvent("tengu_headless_plugin_install", metrics);
|
|
2122
|
+
}
|
|
2123
|
+
}
|
|
2124
|
+
|
|
2125
|
+
// src/cli/print.ts
|
|
2126
|
+
init_refresh();
|
|
2127
|
+
init_pluginLoader();
|
|
2128
|
+
init_teammate();
|
|
2129
|
+
init_teammateMailbox();
|
|
2130
|
+
init_teamHelpers();
|
|
2131
|
+
init_tasks();
|
|
2132
|
+
init_framework();
|
|
2133
|
+
init_stopTask();
|
|
2134
|
+
init_sdkEventQueue();
|
|
2135
|
+
init_growthbook();
|
|
2136
|
+
init_errors();
|
|
2137
|
+
init_paths();
|
|
2138
|
+
var cronSchedulerModule = (init_cronScheduler(), __toCommonJS(exports_cronScheduler));
|
|
2139
|
+
var cronJitterConfigModule = (init_cronJitterConfig(), __toCommonJS(exports_cronJitterConfig));
|
|
2140
|
+
var cronGate = (init_prompt5(), __toCommonJS(exports_prompt));
|
|
2141
|
+
var SHUTDOWN_TEAM_PROMPT = `<system-reminder>
|
|
2142
|
+
You are running in non-interactive mode and cannot return a response to the user until your team is shut down.
|
|
2143
|
+
|
|
2144
|
+
You MUST shut down your team before preparing your final response:
|
|
2145
|
+
1. Use requestShutdown to ask each team member to shut down gracefully
|
|
2146
|
+
2. Wait for shutdown approvals
|
|
2147
|
+
3. Use the cleanup operation to clean up the team
|
|
2148
|
+
4. Only then provide your final response to the user
|
|
2149
|
+
|
|
2150
|
+
The user cannot receive your response until the team is completely shut down.
|
|
2151
|
+
</system-reminder>
|
|
2152
|
+
|
|
2153
|
+
Shut down your team and prepare your final response for the user.`;
|
|
2154
|
+
var MAX_RECEIVED_UUIDS = 1e4;
|
|
2155
|
+
var receivedMessageUuids = new Set;
|
|
2156
|
+
var receivedMessageUuidsOrder = [];
|
|
2157
|
+
function trackReceivedMessageUuid(uuid) {
|
|
2158
|
+
if (receivedMessageUuids.has(uuid)) {
|
|
2159
|
+
return false;
|
|
2160
|
+
}
|
|
2161
|
+
receivedMessageUuids.add(uuid);
|
|
2162
|
+
receivedMessageUuidsOrder.push(uuid);
|
|
2163
|
+
if (receivedMessageUuidsOrder.length > MAX_RECEIVED_UUIDS) {
|
|
2164
|
+
const toEvict = receivedMessageUuidsOrder.splice(0, receivedMessageUuidsOrder.length - MAX_RECEIVED_UUIDS);
|
|
2165
|
+
for (const old of toEvict) {
|
|
2166
|
+
receivedMessageUuids.delete(old);
|
|
2167
|
+
}
|
|
2168
|
+
}
|
|
2169
|
+
return true;
|
|
2170
|
+
}
|
|
2171
|
+
function toBlocks(v) {
|
|
2172
|
+
return typeof v === "string" ? [{ type: "text", text: v }] : v;
|
|
2173
|
+
}
|
|
2174
|
+
function joinPromptValues(values) {
|
|
2175
|
+
if (values.length === 1)
|
|
2176
|
+
return values[0];
|
|
2177
|
+
if (values.every((v) => typeof v === "string")) {
|
|
2178
|
+
return values.join(`
|
|
2179
|
+
`);
|
|
2180
|
+
}
|
|
2181
|
+
return values.flatMap(toBlocks);
|
|
2182
|
+
}
|
|
2183
|
+
function canBatchWith(head, next) {
|
|
2184
|
+
return next !== undefined && next.mode === "prompt" && next.workload === head.workload && next.isMeta === head.isMeta;
|
|
2185
|
+
}
|
|
2186
|
+
async function runHeadless(inputPrompt, getAppState, setAppState, commands, tools, sdkMcpConfigs, agents, options) {
|
|
2187
|
+
if (process.env.USER_TYPE === "ant" && isEnvTruthy(process.env.CLAUDE_CODE_EXIT_AFTER_FIRST_RENDER)) {
|
|
2188
|
+
process.stderr.write(`
|
|
2189
|
+
Startup time: ${Math.round(process.uptime() * 1000)}ms
|
|
2190
|
+
`);
|
|
2191
|
+
process.exit(0);
|
|
2192
|
+
}
|
|
2193
|
+
if (false) {}
|
|
2194
|
+
settingsChangeDetector.subscribe((source) => {
|
|
2195
|
+
applySettingsChange(source, setAppState);
|
|
2196
|
+
if (isFastModeEnabled()) {
|
|
2197
|
+
setAppState((prev) => {
|
|
2198
|
+
const s = prev.settings;
|
|
2199
|
+
const fastMode = s.fastMode === true && !s.fastModePerSessionOptIn;
|
|
2200
|
+
return { ...prev, fastMode };
|
|
2201
|
+
});
|
|
2202
|
+
}
|
|
2203
|
+
});
|
|
2204
|
+
if (false) {}
|
|
2205
|
+
if (typeof Bun !== "undefined") {
|
|
2206
|
+
const gcTimer = setInterval(Bun.gc, 1000);
|
|
2207
|
+
gcTimer.unref();
|
|
2208
|
+
}
|
|
2209
|
+
headlessProfilerStartTurn();
|
|
2210
|
+
headlessProfilerCheckpoint("runHeadless_entry");
|
|
2211
|
+
if (await isQualifiedForGrove()) {
|
|
2212
|
+
await checkGroveForNonInteractive();
|
|
2213
|
+
}
|
|
2214
|
+
headlessProfilerCheckpoint("after_grove_check");
|
|
2215
|
+
initializeGrowthBook();
|
|
2216
|
+
if (options.resumeSessionAt && !options.resume) {
|
|
2217
|
+
process.stderr.write(`Error: --resume-session-at requires --resume
|
|
2218
|
+
`);
|
|
2219
|
+
gracefulShutdownSync(1);
|
|
2220
|
+
return;
|
|
2221
|
+
}
|
|
2222
|
+
if (options.rewindFiles && !options.resume) {
|
|
2223
|
+
process.stderr.write(`Error: --rewind-files requires --resume
|
|
2224
|
+
`);
|
|
2225
|
+
gracefulShutdownSync(1);
|
|
2226
|
+
return;
|
|
2227
|
+
}
|
|
2228
|
+
if (options.rewindFiles && inputPrompt) {
|
|
2229
|
+
process.stderr.write(`Error: --rewind-files is a standalone operation and cannot be used with a prompt
|
|
2230
|
+
`);
|
|
2231
|
+
gracefulShutdownSync(1);
|
|
2232
|
+
return;
|
|
2233
|
+
}
|
|
2234
|
+
const structuredIO = getStructuredIO(inputPrompt, options);
|
|
2235
|
+
if (options.outputFormat === "stream-json") {
|
|
2236
|
+
installStreamJsonStdoutGuard();
|
|
2237
|
+
}
|
|
2238
|
+
const sandboxUnavailableReason = SandboxManager.getSandboxUnavailableReason();
|
|
2239
|
+
if (sandboxUnavailableReason) {
|
|
2240
|
+
if (SandboxManager.isSandboxRequired()) {
|
|
2241
|
+
process.stderr.write(`
|
|
2242
|
+
Error: sandbox required but unavailable: ${sandboxUnavailableReason}
|
|
2243
|
+
` + ` sandbox.failIfUnavailable is set \u2014 refusing to start without a working sandbox.
|
|
2244
|
+
|
|
2245
|
+
`);
|
|
2246
|
+
gracefulShutdownSync(1);
|
|
2247
|
+
return;
|
|
2248
|
+
}
|
|
2249
|
+
process.stderr.write(`
|
|
2250
|
+
\u26A0 Sandbox disabled: ${sandboxUnavailableReason}
|
|
2251
|
+
` + ` Commands will run WITHOUT sandboxing. Network and filesystem restrictions will NOT be enforced.
|
|
2252
|
+
|
|
2253
|
+
`);
|
|
2254
|
+
} else if (SandboxManager.isSandboxingEnabled()) {
|
|
2255
|
+
try {
|
|
2256
|
+
await SandboxManager.initialize(structuredIO.createSandboxAskCallback());
|
|
2257
|
+
} catch (err) {
|
|
2258
|
+
process.stderr.write(`
|
|
2259
|
+
\u274C Sandbox Error: ${errorMessage(err)}
|
|
2260
|
+
`);
|
|
2261
|
+
gracefulShutdownSync(1, "other");
|
|
2262
|
+
return;
|
|
2263
|
+
}
|
|
2264
|
+
}
|
|
2265
|
+
if (options.outputFormat === "stream-json" && options.verbose) {
|
|
2266
|
+
registerHookEventHandler((event) => {
|
|
2267
|
+
const message = (() => {
|
|
2268
|
+
switch (event.type) {
|
|
2269
|
+
case "started":
|
|
2270
|
+
return {
|
|
2271
|
+
type: "system",
|
|
2272
|
+
subtype: "hook_started",
|
|
2273
|
+
hook_id: event.hookId,
|
|
2274
|
+
hook_name: event.hookName,
|
|
2275
|
+
hook_event: event.hookEvent,
|
|
2276
|
+
uuid: randomUUID4(),
|
|
2277
|
+
session_id: getSessionId()
|
|
2278
|
+
};
|
|
2279
|
+
case "progress":
|
|
2280
|
+
return {
|
|
2281
|
+
type: "system",
|
|
2282
|
+
subtype: "hook_progress",
|
|
2283
|
+
hook_id: event.hookId,
|
|
2284
|
+
hook_name: event.hookName,
|
|
2285
|
+
hook_event: event.hookEvent,
|
|
2286
|
+
stdout: event.stdout,
|
|
2287
|
+
stderr: event.stderr,
|
|
2288
|
+
output: event.output,
|
|
2289
|
+
uuid: randomUUID4(),
|
|
2290
|
+
session_id: getSessionId()
|
|
2291
|
+
};
|
|
2292
|
+
case "response":
|
|
2293
|
+
return {
|
|
2294
|
+
type: "system",
|
|
2295
|
+
subtype: "hook_response",
|
|
2296
|
+
hook_id: event.hookId,
|
|
2297
|
+
hook_name: event.hookName,
|
|
2298
|
+
hook_event: event.hookEvent,
|
|
2299
|
+
output: event.output,
|
|
2300
|
+
stdout: event.stdout,
|
|
2301
|
+
stderr: event.stderr,
|
|
2302
|
+
exit_code: event.exitCode,
|
|
2303
|
+
outcome: event.outcome,
|
|
2304
|
+
uuid: randomUUID4(),
|
|
2305
|
+
session_id: getSessionId()
|
|
2306
|
+
};
|
|
2307
|
+
}
|
|
2308
|
+
})();
|
|
2309
|
+
structuredIO.write(message);
|
|
2310
|
+
});
|
|
2311
|
+
}
|
|
2312
|
+
if (options.setupTrigger) {
|
|
2313
|
+
await processSetupHooks(options.setupTrigger);
|
|
2314
|
+
}
|
|
2315
|
+
headlessProfilerCheckpoint("before_loadInitialMessages");
|
|
2316
|
+
const appState = getAppState();
|
|
2317
|
+
const {
|
|
2318
|
+
messages: initialMessages,
|
|
2319
|
+
turnInterruptionState,
|
|
2320
|
+
agentSetting: resumedAgentSetting
|
|
2321
|
+
} = await loadInitialMessages(setAppState, {
|
|
2322
|
+
continue: options.continue,
|
|
2323
|
+
teleport: options.teleport,
|
|
2324
|
+
resume: options.resume,
|
|
2325
|
+
resumeSessionAt: options.resumeSessionAt,
|
|
2326
|
+
forkSession: options.forkSession,
|
|
2327
|
+
outputFormat: options.outputFormat,
|
|
2328
|
+
sessionStartHooksPromise: options.sessionStartHooksPromise,
|
|
2329
|
+
restoredWorkerState: structuredIO.restoredWorkerState
|
|
2330
|
+
});
|
|
2331
|
+
const hookInitialUserMessage = takeInitialUserMessage();
|
|
2332
|
+
if (hookInitialUserMessage) {
|
|
2333
|
+
structuredIO.prependUserMessage(hookInitialUserMessage);
|
|
2334
|
+
}
|
|
2335
|
+
if (!options.agent && !getMainThreadAgentType() && resumedAgentSetting) {
|
|
2336
|
+
const { agentDefinition: restoredAgent } = restoreAgentFromSession(resumedAgentSetting, undefined, { activeAgents: agents, allAgents: agents });
|
|
2337
|
+
if (restoredAgent) {
|
|
2338
|
+
setAppState((prev) => ({ ...prev, agent: restoredAgent.agentType }));
|
|
2339
|
+
if (!options.systemPrompt && !isBuiltInAgent(restoredAgent)) {
|
|
2340
|
+
const agentSystemPrompt = restoredAgent.getSystemPrompt();
|
|
2341
|
+
if (agentSystemPrompt) {
|
|
2342
|
+
options.systemPrompt = agentSystemPrompt;
|
|
2343
|
+
}
|
|
2344
|
+
}
|
|
2345
|
+
saveAgentSetting(restoredAgent.agentType);
|
|
2346
|
+
}
|
|
2347
|
+
}
|
|
2348
|
+
if (initialMessages.length === 0 && process.exitCode !== undefined) {
|
|
2349
|
+
return;
|
|
2350
|
+
}
|
|
2351
|
+
if (options.rewindFiles) {
|
|
2352
|
+
const targetMessage = initialMessages.find((m) => m.uuid === options.rewindFiles);
|
|
2353
|
+
if (!targetMessage || targetMessage.type !== "user") {
|
|
2354
|
+
process.stderr.write(`Error: --rewind-files requires a user message UUID, but ${options.rewindFiles} is not a user message in this session
|
|
2355
|
+
`);
|
|
2356
|
+
gracefulShutdownSync(1);
|
|
2357
|
+
return;
|
|
2358
|
+
}
|
|
2359
|
+
const currentAppState = getAppState();
|
|
2360
|
+
const result = await handleRewindFiles(options.rewindFiles, currentAppState, setAppState, false);
|
|
2361
|
+
if (!result.canRewind) {
|
|
2362
|
+
process.stderr.write(`Error: ${result.error || "Unexpected error"}
|
|
2363
|
+
`);
|
|
2364
|
+
gracefulShutdownSync(1);
|
|
2365
|
+
return;
|
|
2366
|
+
}
|
|
2367
|
+
process.stdout.write(`Files rewound to state at message ${options.rewindFiles}
|
|
2368
|
+
`);
|
|
2369
|
+
gracefulShutdownSync(0);
|
|
2370
|
+
return;
|
|
2371
|
+
}
|
|
2372
|
+
const hasValidResumeSessionId = typeof options.resume === "string" && (Boolean(validateUuid(options.resume)) || options.resume.endsWith(".jsonl"));
|
|
2373
|
+
const isUsingSdkUrl = Boolean(options.sdkUrl);
|
|
2374
|
+
if (!inputPrompt && !hasValidResumeSessionId && !isUsingSdkUrl) {
|
|
2375
|
+
process.stderr.write(`Error: Input must be provided either through stdin or as a prompt argument when using --print
|
|
2376
|
+
`);
|
|
2377
|
+
gracefulShutdownSync(1);
|
|
2378
|
+
return;
|
|
2379
|
+
}
|
|
2380
|
+
if (options.outputFormat === "stream-json" && !options.verbose) {
|
|
2381
|
+
process.stderr.write(`Error: When using --print, --output-format=stream-json requires --verbose
|
|
2382
|
+
`);
|
|
2383
|
+
gracefulShutdownSync(1);
|
|
2384
|
+
return;
|
|
2385
|
+
}
|
|
2386
|
+
const allowedMcpTools = filterToolsByDenyRules(appState.mcp.tools, appState.toolPermissionContext);
|
|
2387
|
+
let filteredTools = [...tools, ...allowedMcpTools];
|
|
2388
|
+
const effectivePermissionPromptToolName = options.sdkUrl ? "stdio" : options.permissionPromptToolName;
|
|
2389
|
+
const onPermissionPrompt = (details) => {
|
|
2390
|
+
if (false) {}
|
|
2391
|
+
notifySessionStateChanged("requires_action", details);
|
|
2392
|
+
};
|
|
2393
|
+
const canUseTool = getCanUseToolFn(effectivePermissionPromptToolName, structuredIO, () => getAppState().mcp.tools, onPermissionPrompt);
|
|
2394
|
+
if (options.permissionPromptToolName) {
|
|
2395
|
+
filteredTools = filteredTools.filter((tool) => !toolMatchesName(tool, options.permissionPromptToolName));
|
|
2396
|
+
}
|
|
2397
|
+
registerProcessOutputErrorHandlers();
|
|
2398
|
+
headlessProfilerCheckpoint("after_loadInitialMessages");
|
|
2399
|
+
await ensureModelStringsInitialized();
|
|
2400
|
+
headlessProfilerCheckpoint("after_modelStrings");
|
|
2401
|
+
const needsFullArray = options.outputFormat === "json" && options.verbose;
|
|
2402
|
+
const messages = [];
|
|
2403
|
+
let lastMessage;
|
|
2404
|
+
const transformToStreamlined = null;
|
|
2405
|
+
headlessProfilerCheckpoint("before_runHeadlessStreaming");
|
|
2406
|
+
for await (const message of runHeadlessStreaming(structuredIO, appState.mcp.clients, [...commands, ...appState.mcp.commands], filteredTools, initialMessages, canUseTool, sdkMcpConfigs, getAppState, setAppState, agents, options, turnInterruptionState)) {
|
|
2407
|
+
if (transformToStreamlined) {
|
|
2408
|
+
const transformed = transformToStreamlined(message);
|
|
2409
|
+
if (transformed) {
|
|
2410
|
+
await structuredIO.write(transformed);
|
|
2411
|
+
}
|
|
2412
|
+
} else if (options.outputFormat === "stream-json" && options.verbose) {
|
|
2413
|
+
await structuredIO.write(message);
|
|
2414
|
+
}
|
|
2415
|
+
if (message.type !== "control_response" && message.type !== "control_request" && message.type !== "control_cancel_request" && !(message.type === "system" && (message.subtype === "session_state_changed" || message.subtype === "task_notification" || message.subtype === "task_started" || message.subtype === "task_progress" || message.subtype === "post_turn_summary")) && message.type !== "stream_event" && message.type !== "keep_alive" && message.type !== "streamlined_text" && message.type !== "streamlined_tool_use_summary" && message.type !== "prompt_suggestion") {
|
|
2416
|
+
if (needsFullArray) {
|
|
2417
|
+
messages.push(message);
|
|
2418
|
+
}
|
|
2419
|
+
lastMessage = message;
|
|
2420
|
+
}
|
|
2421
|
+
}
|
|
2422
|
+
switch (options.outputFormat) {
|
|
2423
|
+
case "json":
|
|
2424
|
+
if (!lastMessage || lastMessage.type !== "result") {
|
|
2425
|
+
throw new Error("No messages returned");
|
|
2426
|
+
}
|
|
2427
|
+
if (options.verbose) {
|
|
2428
|
+
writeToStdout(jsonStringify(messages) + `
|
|
2429
|
+
`);
|
|
2430
|
+
break;
|
|
2431
|
+
}
|
|
2432
|
+
writeToStdout(jsonStringify(lastMessage) + `
|
|
2433
|
+
`);
|
|
2434
|
+
break;
|
|
2435
|
+
case "stream-json":
|
|
2436
|
+
break;
|
|
2437
|
+
default:
|
|
2438
|
+
if (!lastMessage || lastMessage.type !== "result") {
|
|
2439
|
+
throw new Error("No messages returned");
|
|
2440
|
+
}
|
|
2441
|
+
switch (lastMessage.subtype) {
|
|
2442
|
+
case "success":
|
|
2443
|
+
writeToStdout(lastMessage.result.endsWith(`
|
|
2444
|
+
`) ? lastMessage.result : lastMessage.result + `
|
|
2445
|
+
`);
|
|
2446
|
+
break;
|
|
2447
|
+
case "error_during_execution":
|
|
2448
|
+
writeToStdout(`Execution error`);
|
|
2449
|
+
break;
|
|
2450
|
+
case "error_max_turns":
|
|
2451
|
+
writeToStdout(`Error: Reached max turns (${options.maxTurns})`);
|
|
2452
|
+
break;
|
|
2453
|
+
case "error_max_budget_usd":
|
|
2454
|
+
writeToStdout(`Error: Exceeded USD budget (${options.maxBudgetUsd})`);
|
|
2455
|
+
break;
|
|
2456
|
+
case "error_max_structured_output_retries":
|
|
2457
|
+
writeToStdout(`Error: Failed to provide valid structured output after maximum retries`);
|
|
2458
|
+
}
|
|
2459
|
+
}
|
|
2460
|
+
logHeadlessProfilerTurn();
|
|
2461
|
+
if (false) {}
|
|
2462
|
+
gracefulShutdownSync(lastMessage?.type === "result" && lastMessage?.is_error ? 1 : 0);
|
|
2463
|
+
}
|
|
2464
|
+
function runHeadlessStreaming(structuredIO, mcpClients, commands, tools, initialMessages, canUseTool, sdkMcpConfigs, getAppState, setAppState, agents, options, turnInterruptionState) {
|
|
2465
|
+
let running = false;
|
|
2466
|
+
let runPhase;
|
|
2467
|
+
let inputClosed = false;
|
|
2468
|
+
let shutdownPromptInjected = false;
|
|
2469
|
+
let heldBackResult = null;
|
|
2470
|
+
let abortController;
|
|
2471
|
+
const output = structuredIO.outbound;
|
|
2472
|
+
const sigintHandler = () => {
|
|
2473
|
+
logForDiagnosticsNoPII("info", "shutdown_signal", { signal: "SIGINT" });
|
|
2474
|
+
if (abortController && !abortController.signal.aborted) {
|
|
2475
|
+
abortController.abort();
|
|
2476
|
+
}
|
|
2477
|
+
gracefulShutdown(0);
|
|
2478
|
+
};
|
|
2479
|
+
process.on("SIGINT", sigintHandler);
|
|
2480
|
+
registerCleanup(async () => {
|
|
2481
|
+
const bg = {};
|
|
2482
|
+
for (const t of getRunningTasks(getAppState())) {
|
|
2483
|
+
if (isBackgroundTask(t))
|
|
2484
|
+
bg[t.type] = (bg[t.type] ?? 0) + 1;
|
|
2485
|
+
}
|
|
2486
|
+
logForDiagnosticsNoPII("info", "run_state_at_shutdown", {
|
|
2487
|
+
run_active: running,
|
|
2488
|
+
run_phase: runPhase,
|
|
2489
|
+
worker_status: getSessionState(),
|
|
2490
|
+
internal_events_pending: structuredIO.internalEventsPending,
|
|
2491
|
+
bg_tasks: bg
|
|
2492
|
+
});
|
|
2493
|
+
});
|
|
2494
|
+
setPermissionModeChangedListener((newMode) => {
|
|
2495
|
+
if (newMode === "default" || newMode === "acceptEdits" || newMode === "bypassPermissions" || newMode === "plan" || newMode === false || newMode === "dontAsk") {
|
|
2496
|
+
output.enqueue({
|
|
2497
|
+
type: "system",
|
|
2498
|
+
subtype: "status",
|
|
2499
|
+
status: null,
|
|
2500
|
+
permissionMode: newMode,
|
|
2501
|
+
uuid: randomUUID4(),
|
|
2502
|
+
session_id: getSessionId()
|
|
2503
|
+
});
|
|
2504
|
+
}
|
|
2505
|
+
});
|
|
2506
|
+
const suggestionState = {
|
|
2507
|
+
abortController: null,
|
|
2508
|
+
inflightPromise: null,
|
|
2509
|
+
lastEmitted: null,
|
|
2510
|
+
pendingSuggestion: null,
|
|
2511
|
+
pendingLastEmittedEntry: null
|
|
2512
|
+
};
|
|
2513
|
+
let unsubscribeAuthStatus;
|
|
2514
|
+
if (options.enableAuthStatus) {
|
|
2515
|
+
const authStatusManager = AwsAuthStatusManager.getInstance();
|
|
2516
|
+
unsubscribeAuthStatus = authStatusManager.subscribe((status) => {
|
|
2517
|
+
output.enqueue({
|
|
2518
|
+
type: "auth_status",
|
|
2519
|
+
isAuthenticating: status.isAuthenticating,
|
|
2520
|
+
output: status.output,
|
|
2521
|
+
error: status.error,
|
|
2522
|
+
uuid: randomUUID4(),
|
|
2523
|
+
session_id: getSessionId()
|
|
2524
|
+
});
|
|
2525
|
+
});
|
|
2526
|
+
}
|
|
2527
|
+
const rateLimitListener = (limits) => {
|
|
2528
|
+
const rateLimitInfo = toSDKRateLimitInfo(limits);
|
|
2529
|
+
if (rateLimitInfo) {
|
|
2530
|
+
output.enqueue({
|
|
2531
|
+
type: "rate_limit_event",
|
|
2532
|
+
rate_limit_info: rateLimitInfo,
|
|
2533
|
+
uuid: randomUUID4(),
|
|
2534
|
+
session_id: getSessionId()
|
|
2535
|
+
});
|
|
2536
|
+
}
|
|
2537
|
+
};
|
|
2538
|
+
statusListeners.add(rateLimitListener);
|
|
2539
|
+
const mutableMessages = initialMessages;
|
|
2540
|
+
let readFileState = extractReadFilesFromMessages(initialMessages, cwd(), READ_FILE_STATE_CACHE_SIZE);
|
|
2541
|
+
const pendingSeeds = createFileStateCacheWithSizeLimit(READ_FILE_STATE_CACHE_SIZE);
|
|
2542
|
+
const resumeInterruptedTurnEnv = process.env.CLAUDE_CODE_RESUME_INTERRUPTED_TURN;
|
|
2543
|
+
if (turnInterruptionState && turnInterruptionState.kind !== "none" && resumeInterruptedTurnEnv) {
|
|
2544
|
+
logForDebugging(`[print.ts] Auto-resuming interrupted turn (kind: ${turnInterruptionState.kind})`);
|
|
2545
|
+
removeInterruptedMessage(mutableMessages, turnInterruptionState.message);
|
|
2546
|
+
enqueue({
|
|
2547
|
+
mode: "prompt",
|
|
2548
|
+
value: turnInterruptionState.message.message.content,
|
|
2549
|
+
uuid: randomUUID4()
|
|
2550
|
+
});
|
|
2551
|
+
}
|
|
2552
|
+
const modelOptions = getModelOptions();
|
|
2553
|
+
const modelInfos = modelOptions.map((option) => {
|
|
2554
|
+
const modelId = option.value === null ? "default" : option.value;
|
|
2555
|
+
const resolvedModel = modelId === "default" ? getDefaultMainLoopModel() : parseUserSpecifiedModel(modelId);
|
|
2556
|
+
const hasEffort = modelSupportsEffort(resolvedModel);
|
|
2557
|
+
const hasAdaptiveThinking = modelSupportsAdaptiveThinking(resolvedModel);
|
|
2558
|
+
const hasFastMode = isFastModeSupportedByModel(option.value);
|
|
2559
|
+
const hasAutoMode = modelSupportsAutoMode(resolvedModel);
|
|
2560
|
+
return {
|
|
2561
|
+
name: modelId,
|
|
2562
|
+
value: modelId,
|
|
2563
|
+
displayName: option.label,
|
|
2564
|
+
description: option.description,
|
|
2565
|
+
...hasEffort && {
|
|
2566
|
+
supportsEffort: true,
|
|
2567
|
+
supportedEffortLevels: modelSupportsMaxEffort(resolvedModel) ? [...EFFORT_LEVELS] : EFFORT_LEVELS.filter((l) => l !== "max")
|
|
2568
|
+
},
|
|
2569
|
+
...hasAdaptiveThinking && { supportsAdaptiveThinking: true },
|
|
2570
|
+
...hasFastMode && { supportsFastMode: true },
|
|
2571
|
+
...hasAutoMode && { supportsAutoMode: true }
|
|
2572
|
+
};
|
|
2573
|
+
});
|
|
2574
|
+
let activeUserSpecifiedModel = options.userSpecifiedModel;
|
|
2575
|
+
function injectModelSwitchBreadcrumbs(modelArg, resolvedModel) {
|
|
2576
|
+
const breadcrumbs = createModelSwitchBreadcrumbs(modelArg, modelDisplayString(resolvedModel));
|
|
2577
|
+
mutableMessages.push(...breadcrumbs);
|
|
2578
|
+
for (const crumb of breadcrumbs) {
|
|
2579
|
+
if (typeof crumb.message.content === "string" && crumb.message.content.includes(`<${LOCAL_COMMAND_STDOUT_TAG}>`)) {
|
|
2580
|
+
output.enqueue({
|
|
2581
|
+
type: "user",
|
|
2582
|
+
content: crumb.message.content,
|
|
2583
|
+
message: crumb.message,
|
|
2584
|
+
session_id: getSessionId(),
|
|
2585
|
+
parent_tool_use_id: null,
|
|
2586
|
+
uuid: crumb.uuid,
|
|
2587
|
+
timestamp: crumb.timestamp,
|
|
2588
|
+
isReplay: true
|
|
2589
|
+
});
|
|
2590
|
+
}
|
|
2591
|
+
}
|
|
2592
|
+
}
|
|
2593
|
+
let sdkClients = [];
|
|
2594
|
+
let sdkTools = [];
|
|
2595
|
+
const elicitationRegistered = new Set;
|
|
2596
|
+
function registerElicitationHandlers(clients) {
|
|
2597
|
+
for (const connection of clients) {
|
|
2598
|
+
if (connection.type !== "connected" || elicitationRegistered.has(connection.name)) {
|
|
2599
|
+
continue;
|
|
2600
|
+
}
|
|
2601
|
+
if (connection.config.type === "sdk") {
|
|
2602
|
+
continue;
|
|
2603
|
+
}
|
|
2604
|
+
const serverName = connection.name;
|
|
2605
|
+
try {
|
|
2606
|
+
connection.client.setRequestHandler(ElicitRequestSchema, async (request, extra) => {
|
|
2607
|
+
logMCPDebug(serverName, `Elicitation request received in print mode: ${jsonStringify(request)}`);
|
|
2608
|
+
const mode = request.params.mode === "url" ? "url" : "form";
|
|
2609
|
+
logEvent("tengu_mcp_elicitation_shown", {
|
|
2610
|
+
mode
|
|
2611
|
+
});
|
|
2612
|
+
const hookResponse = await runElicitationHooks(serverName, request.params, extra.signal);
|
|
2613
|
+
if (hookResponse) {
|
|
2614
|
+
logMCPDebug(serverName, `Elicitation resolved by hook: ${jsonStringify(hookResponse)}`);
|
|
2615
|
+
logEvent("tengu_mcp_elicitation_response", {
|
|
2616
|
+
mode,
|
|
2617
|
+
action: hookResponse.action
|
|
2618
|
+
});
|
|
2619
|
+
return hookResponse;
|
|
2620
|
+
}
|
|
2621
|
+
const url = "url" in request.params ? request.params.url : undefined;
|
|
2622
|
+
const requestedSchema = "requestedSchema" in request.params ? request.params.requestedSchema : undefined;
|
|
2623
|
+
const elicitationId = "elicitationId" in request.params ? request.params.elicitationId : undefined;
|
|
2624
|
+
const rawResult = await structuredIO.handleElicitation(serverName, request.params.message, requestedSchema, extra.signal, mode, url, elicitationId);
|
|
2625
|
+
const result = await runElicitationResultHooks(serverName, rawResult, extra.signal, mode, elicitationId);
|
|
2626
|
+
logEvent("tengu_mcp_elicitation_response", {
|
|
2627
|
+
mode,
|
|
2628
|
+
action: result.action
|
|
2629
|
+
});
|
|
2630
|
+
return result;
|
|
2631
|
+
});
|
|
2632
|
+
connection.client.setNotificationHandler(ElicitationCompleteNotificationSchema, (notification) => {
|
|
2633
|
+
const { elicitationId } = notification.params;
|
|
2634
|
+
logMCPDebug(serverName, `Elicitation completion notification: ${elicitationId}`);
|
|
2635
|
+
executeNotificationHooks({
|
|
2636
|
+
message: `MCP server "${serverName}" confirmed elicitation ${elicitationId} complete`,
|
|
2637
|
+
notificationType: "elicitation_complete"
|
|
2638
|
+
});
|
|
2639
|
+
output.enqueue({
|
|
2640
|
+
type: "system",
|
|
2641
|
+
subtype: "elicitation_complete",
|
|
2642
|
+
mcp_server_name: serverName,
|
|
2643
|
+
elicitation_id: elicitationId,
|
|
2644
|
+
uuid: randomUUID4(),
|
|
2645
|
+
session_id: getSessionId()
|
|
2646
|
+
});
|
|
2647
|
+
});
|
|
2648
|
+
elicitationRegistered.add(serverName);
|
|
2649
|
+
} catch {}
|
|
2650
|
+
}
|
|
2651
|
+
}
|
|
2652
|
+
async function updateSdkMcp() {
|
|
2653
|
+
const currentServerNames = new Set(Object.keys(sdkMcpConfigs));
|
|
2654
|
+
const connectedServerNames = new Set(sdkClients.map((c) => c.name));
|
|
2655
|
+
const hasNewServers = Array.from(currentServerNames).some((name) => !connectedServerNames.has(name));
|
|
2656
|
+
const hasRemovedServers = Array.from(connectedServerNames).some((name) => !currentServerNames.has(name));
|
|
2657
|
+
const hasPendingSdkClients = sdkClients.some((c) => c.type === "pending");
|
|
2658
|
+
const hasFailedSdkClients = sdkClients.some((c) => c.type === "failed");
|
|
2659
|
+
const haveServersChanged = hasNewServers || hasRemovedServers || hasPendingSdkClients || hasFailedSdkClients;
|
|
2660
|
+
if (haveServersChanged) {
|
|
2661
|
+
for (const client of sdkClients) {
|
|
2662
|
+
if (!currentServerNames.has(client.name)) {
|
|
2663
|
+
if (client.type === "connected") {
|
|
2664
|
+
await client.cleanup();
|
|
2665
|
+
}
|
|
2666
|
+
}
|
|
2667
|
+
}
|
|
2668
|
+
const sdkSetup = await setupSdkMcpClients(sdkMcpConfigs, (serverName, message) => structuredIO.sendMcpMessage(serverName, message));
|
|
2669
|
+
sdkClients = sdkSetup.clients;
|
|
2670
|
+
sdkTools = sdkSetup.tools;
|
|
2671
|
+
const allSdkNames = uniq([...connectedServerNames, ...currentServerNames]);
|
|
2672
|
+
setAppState((prev) => ({
|
|
2673
|
+
...prev,
|
|
2674
|
+
mcp: {
|
|
2675
|
+
...prev.mcp,
|
|
2676
|
+
tools: [
|
|
2677
|
+
...prev.mcp.tools.filter((t) => !allSdkNames.some((name) => t.name.startsWith(getMcpPrefix(name)))),
|
|
2678
|
+
...sdkTools
|
|
2679
|
+
]
|
|
2680
|
+
}
|
|
2681
|
+
}));
|
|
2682
|
+
setupVscodeSdkMcp(sdkClients);
|
|
2683
|
+
}
|
|
2684
|
+
}
|
|
2685
|
+
updateSdkMcp();
|
|
2686
|
+
let dynamicMcpState = {
|
|
2687
|
+
clients: [],
|
|
2688
|
+
tools: [],
|
|
2689
|
+
configs: {}
|
|
2690
|
+
};
|
|
2691
|
+
const buildAllTools = (appState) => {
|
|
2692
|
+
const assembledTools = assembleToolPool(appState.toolPermissionContext, appState.mcp.tools);
|
|
2693
|
+
let allTools = uniqBy_default(mergeAndFilterTools([...tools, ...sdkTools, ...dynamicMcpState.tools], assembledTools, appState.toolPermissionContext.mode), "name");
|
|
2694
|
+
if (options.permissionPromptToolName) {
|
|
2695
|
+
allTools = allTools.filter((tool) => !toolMatchesName(tool, options.permissionPromptToolName));
|
|
2696
|
+
}
|
|
2697
|
+
const initJsonSchema = getInitJsonSchema();
|
|
2698
|
+
if (initJsonSchema && !options.jsonSchema) {
|
|
2699
|
+
const syntheticOutputResult = createSyntheticOutputTool(initJsonSchema);
|
|
2700
|
+
if ("tool" in syntheticOutputResult) {
|
|
2701
|
+
allTools = [...allTools, syntheticOutputResult.tool];
|
|
2702
|
+
}
|
|
2703
|
+
}
|
|
2704
|
+
return allTools;
|
|
2705
|
+
};
|
|
2706
|
+
let bridgeHandle = null;
|
|
2707
|
+
let bridgeLastForwardedIndex = 0;
|
|
2708
|
+
function forwardMessagesToBridge() {
|
|
2709
|
+
if (!bridgeHandle)
|
|
2710
|
+
return;
|
|
2711
|
+
const startIndex = Math.min(bridgeLastForwardedIndex, mutableMessages.length);
|
|
2712
|
+
const newMessages = mutableMessages.slice(startIndex).filter((m) => m.type === "user" || m.type === "assistant");
|
|
2713
|
+
bridgeLastForwardedIndex = mutableMessages.length;
|
|
2714
|
+
if (newMessages.length > 0) {
|
|
2715
|
+
bridgeHandle.writeMessages(newMessages);
|
|
2716
|
+
}
|
|
2717
|
+
}
|
|
2718
|
+
let mcpChangesPromise = Promise.resolve({
|
|
2719
|
+
response: {
|
|
2720
|
+
added: [],
|
|
2721
|
+
removed: [],
|
|
2722
|
+
errors: {}
|
|
2723
|
+
},
|
|
2724
|
+
sdkServersChanged: false
|
|
2725
|
+
});
|
|
2726
|
+
function applyMcpServerChanges(servers) {
|
|
2727
|
+
const doWork = async () => {
|
|
2728
|
+
const oldSdkClientNames = new Set(sdkClients.map((c) => c.name));
|
|
2729
|
+
const result = await handleMcpSetServers(servers, { configs: sdkMcpConfigs, clients: sdkClients, tools: sdkTools }, dynamicMcpState, setAppState);
|
|
2730
|
+
for (const key of Object.keys(sdkMcpConfigs)) {
|
|
2731
|
+
delete sdkMcpConfigs[key];
|
|
2732
|
+
}
|
|
2733
|
+
Object.assign(sdkMcpConfigs, result.newSdkState.configs);
|
|
2734
|
+
sdkClients = result.newSdkState.clients;
|
|
2735
|
+
sdkTools = result.newSdkState.tools;
|
|
2736
|
+
dynamicMcpState = result.newDynamicState;
|
|
2737
|
+
if (result.sdkServersChanged) {
|
|
2738
|
+
const newSdkClientNames = new Set(sdkClients.map((c) => c.name));
|
|
2739
|
+
const allSdkNames = uniq([...oldSdkClientNames, ...newSdkClientNames]);
|
|
2740
|
+
setAppState((prev) => ({
|
|
2741
|
+
...prev,
|
|
2742
|
+
mcp: {
|
|
2743
|
+
...prev.mcp,
|
|
2744
|
+
tools: [
|
|
2745
|
+
...prev.mcp.tools.filter((t) => !allSdkNames.some((name) => t.name.startsWith(getMcpPrefix(name)))),
|
|
2746
|
+
...sdkTools
|
|
2747
|
+
]
|
|
2748
|
+
}
|
|
2749
|
+
}));
|
|
2750
|
+
}
|
|
2751
|
+
return {
|
|
2752
|
+
response: result.response,
|
|
2753
|
+
sdkServersChanged: result.sdkServersChanged
|
|
2754
|
+
};
|
|
2755
|
+
};
|
|
2756
|
+
mcpChangesPromise = mcpChangesPromise.then(doWork, doWork);
|
|
2757
|
+
return mcpChangesPromise;
|
|
2758
|
+
}
|
|
2759
|
+
function buildMcpServerStatuses() {
|
|
2760
|
+
const currentAppState = getAppState();
|
|
2761
|
+
const currentMcpClients = currentAppState.mcp.clients;
|
|
2762
|
+
const allMcpTools = uniqBy_default([...currentAppState.mcp.tools, ...dynamicMcpState.tools], "name");
|
|
2763
|
+
const existingNames = new Set([
|
|
2764
|
+
...currentMcpClients.map((c) => c.name),
|
|
2765
|
+
...sdkClients.map((c) => c.name)
|
|
2766
|
+
]);
|
|
2767
|
+
return [
|
|
2768
|
+
...currentMcpClients,
|
|
2769
|
+
...sdkClients,
|
|
2770
|
+
...dynamicMcpState.clients.filter((c) => !existingNames.has(c.name))
|
|
2771
|
+
].map((connection) => {
|
|
2772
|
+
let config;
|
|
2773
|
+
if (connection.config.type === "sse" || connection.config.type === "http") {
|
|
2774
|
+
config = {
|
|
2775
|
+
type: connection.config.type,
|
|
2776
|
+
url: connection.config.url,
|
|
2777
|
+
headers: connection.config.headers,
|
|
2778
|
+
oauth: connection.config.oauth
|
|
2779
|
+
};
|
|
2780
|
+
} else if (connection.config.type === "claudeai-proxy") {
|
|
2781
|
+
config = {
|
|
2782
|
+
type: "claudeai-proxy",
|
|
2783
|
+
url: connection.config.url,
|
|
2784
|
+
id: connection.config.id
|
|
2785
|
+
};
|
|
2786
|
+
} else if (connection.config.type === "stdio" || connection.config.type === undefined) {
|
|
2787
|
+
const stdioConfig = connection.config;
|
|
2788
|
+
config = {
|
|
2789
|
+
type: "stdio",
|
|
2790
|
+
command: stdioConfig.command,
|
|
2791
|
+
args: stdioConfig.args
|
|
2792
|
+
};
|
|
2793
|
+
}
|
|
2794
|
+
const serverTools = connection.type === "connected" ? filterToolsByServer(allMcpTools, connection.name).map((tool) => ({
|
|
2795
|
+
name: tool.mcpInfo?.toolName ?? tool.name,
|
|
2796
|
+
annotations: {
|
|
2797
|
+
readOnly: tool.isReadOnly({}) || undefined,
|
|
2798
|
+
destructive: tool.isDestructive?.({}) || undefined,
|
|
2799
|
+
openWorld: tool.isOpenWorld?.({}) || undefined
|
|
2800
|
+
}
|
|
2801
|
+
})) : undefined;
|
|
2802
|
+
let capabilities;
|
|
2803
|
+
if (false) {}
|
|
2804
|
+
return {
|
|
2805
|
+
name: connection.name,
|
|
2806
|
+
status: connection.type,
|
|
2807
|
+
serverInfo: connection.type === "connected" ? connection.serverInfo : undefined,
|
|
2808
|
+
error: connection.type === "failed" ? connection.error : undefined,
|
|
2809
|
+
config,
|
|
2810
|
+
scope: connection.config.scope,
|
|
2811
|
+
tools: serverTools,
|
|
2812
|
+
capabilities
|
|
2813
|
+
};
|
|
2814
|
+
});
|
|
2815
|
+
}
|
|
2816
|
+
async function installPluginsAndApplyMcpInBackground() {
|
|
2817
|
+
try {
|
|
2818
|
+
await Promise.all([
|
|
2819
|
+
Promise.resolve(),
|
|
2820
|
+
withDiagnosticsTiming("headless_managed_settings_wait", () => waitForRemoteManagedSettingsToLoad())
|
|
2821
|
+
]);
|
|
2822
|
+
const pluginsInstalled = await installPluginsForHeadless();
|
|
2823
|
+
if (pluginsInstalled) {
|
|
2824
|
+
await applyPluginMcpDiff();
|
|
2825
|
+
}
|
|
2826
|
+
} catch (error) {
|
|
2827
|
+
logError(error);
|
|
2828
|
+
}
|
|
2829
|
+
}
|
|
2830
|
+
let pluginInstallPromise = null;
|
|
2831
|
+
if (!isBareMode()) {
|
|
2832
|
+
if (isEnvTruthy(process.env.CLAUDE_CODE_SYNC_PLUGIN_INSTALL)) {
|
|
2833
|
+
pluginInstallPromise = installPluginsAndApplyMcpInBackground();
|
|
2834
|
+
} else {
|
|
2835
|
+
installPluginsAndApplyMcpInBackground();
|
|
2836
|
+
}
|
|
2837
|
+
}
|
|
2838
|
+
const idleTimeout = createIdleTimeoutManager(() => !running);
|
|
2839
|
+
let currentCommands = commands;
|
|
2840
|
+
let currentAgents = agents;
|
|
2841
|
+
async function refreshPluginState() {
|
|
2842
|
+
const { agentDefinitions: freshAgentDefs } = await refreshActivePlugins(setAppState);
|
|
2843
|
+
currentCommands = await getCommands(cwd());
|
|
2844
|
+
const sdkAgents = currentAgents.filter((a) => a.source === "flagSettings");
|
|
2845
|
+
currentAgents = [...freshAgentDefs.allAgents, ...sdkAgents];
|
|
2846
|
+
}
|
|
2847
|
+
async function applyPluginMcpDiff() {
|
|
2848
|
+
const { servers: newConfigs } = await getAllMcpConfigs();
|
|
2849
|
+
const supportedConfigs = {};
|
|
2850
|
+
for (const [name, config] of Object.entries(newConfigs)) {
|
|
2851
|
+
const type = config.type;
|
|
2852
|
+
if (type === undefined || type === "stdio" || type === "sse" || type === "http" || type === "sdk") {
|
|
2853
|
+
supportedConfigs[name] = config;
|
|
2854
|
+
}
|
|
2855
|
+
}
|
|
2856
|
+
for (const [name, config] of Object.entries(sdkMcpConfigs)) {
|
|
2857
|
+
if (config.type === "sdk" && !(name in supportedConfigs)) {
|
|
2858
|
+
supportedConfigs[name] = config;
|
|
2859
|
+
}
|
|
2860
|
+
}
|
|
2861
|
+
const { response, sdkServersChanged } = await applyMcpServerChanges(supportedConfigs);
|
|
2862
|
+
if (sdkServersChanged) {
|
|
2863
|
+
updateSdkMcp();
|
|
2864
|
+
}
|
|
2865
|
+
logForDebugging(`Headless MCP refresh: added=${response.added.length}, removed=${response.removed.length}`);
|
|
2866
|
+
}
|
|
2867
|
+
const unsubscribeSkillChanges = skillChangeDetector.subscribe(() => {
|
|
2868
|
+
clearCommandsCache();
|
|
2869
|
+
getCommands(cwd()).then((newCommands) => {
|
|
2870
|
+
currentCommands = newCommands;
|
|
2871
|
+
});
|
|
2872
|
+
});
|
|
2873
|
+
const scheduleProactiveTick = undefined;
|
|
2874
|
+
subscribeToCommandQueue(() => {
|
|
2875
|
+
if (abortController && getCommandsByMaxPriority("now").length > 0) {
|
|
2876
|
+
abortController.abort("interrupt");
|
|
2877
|
+
}
|
|
2878
|
+
});
|
|
2879
|
+
const run = async () => {
|
|
2880
|
+
if (running) {
|
|
2881
|
+
return;
|
|
2882
|
+
}
|
|
2883
|
+
running = true;
|
|
2884
|
+
runPhase = undefined;
|
|
2885
|
+
notifySessionStateChanged("running");
|
|
2886
|
+
idleTimeout.stop();
|
|
2887
|
+
headlessProfilerCheckpoint("run_entry");
|
|
2888
|
+
await updateSdkMcp();
|
|
2889
|
+
headlessProfilerCheckpoint("after_updateSdkMcp");
|
|
2890
|
+
if (pluginInstallPromise) {
|
|
2891
|
+
const timeoutMs = parseInt(process.env.CLAUDE_CODE_SYNC_PLUGIN_INSTALL_TIMEOUT_MS || "", 10);
|
|
2892
|
+
if (timeoutMs > 0) {
|
|
2893
|
+
const timeout = sleep(timeoutMs).then(() => "timeout");
|
|
2894
|
+
const result = await Promise.race([pluginInstallPromise, timeout]);
|
|
2895
|
+
if (result === "timeout") {
|
|
2896
|
+
logError(new Error(`CLAUDE_CODE_SYNC_PLUGIN_INSTALL: plugin installation timed out after ${timeoutMs}ms`));
|
|
2897
|
+
logEvent("tengu_sync_plugin_install_timeout", {
|
|
2898
|
+
timeout_ms: timeoutMs
|
|
2899
|
+
});
|
|
2900
|
+
}
|
|
2901
|
+
} else {
|
|
2902
|
+
await pluginInstallPromise;
|
|
2903
|
+
}
|
|
2904
|
+
pluginInstallPromise = null;
|
|
2905
|
+
await refreshPluginState();
|
|
2906
|
+
const { setupPluginHookHotReload } = await import("./chunk-07rervty.js");
|
|
2907
|
+
setupPluginHookHotReload();
|
|
2908
|
+
}
|
|
2909
|
+
const isMainThread = (cmd) => cmd.agentId === undefined;
|
|
2910
|
+
try {
|
|
2911
|
+
let command;
|
|
2912
|
+
let waitingForAgents = false;
|
|
2913
|
+
const drainCommandQueue = async () => {
|
|
2914
|
+
while (command = dequeue(isMainThread)) {
|
|
2915
|
+
if (command.mode !== "prompt" && command.mode !== "orphaned-permission" && command.mode !== "task-notification") {
|
|
2916
|
+
throw new Error("only prompt commands are supported in streaming mode");
|
|
2917
|
+
}
|
|
2918
|
+
const batch = [command];
|
|
2919
|
+
if (command.mode === "prompt") {
|
|
2920
|
+
while (canBatchWith(command, peek(isMainThread))) {
|
|
2921
|
+
batch.push(dequeue(isMainThread));
|
|
2922
|
+
}
|
|
2923
|
+
if (batch.length > 1) {
|
|
2924
|
+
command = {
|
|
2925
|
+
...command,
|
|
2926
|
+
value: joinPromptValues(batch.map((c) => c.value)),
|
|
2927
|
+
uuid: batch.findLast((c) => c.uuid)?.uuid ?? command.uuid
|
|
2928
|
+
};
|
|
2929
|
+
}
|
|
2930
|
+
}
|
|
2931
|
+
const batchUuids = batch.map((c) => c.uuid).filter((u) => u !== undefined);
|
|
2932
|
+
if (options.replayUserMessages && batch.length > 1) {
|
|
2933
|
+
for (const c of batch) {
|
|
2934
|
+
if (c.uuid && c.uuid !== command.uuid) {
|
|
2935
|
+
output.enqueue({
|
|
2936
|
+
type: "user",
|
|
2937
|
+
content: c.value,
|
|
2938
|
+
message: { role: "user", content: c.value },
|
|
2939
|
+
session_id: getSessionId(),
|
|
2940
|
+
parent_tool_use_id: null,
|
|
2941
|
+
uuid: c.uuid,
|
|
2942
|
+
isReplay: true
|
|
2943
|
+
});
|
|
2944
|
+
}
|
|
2945
|
+
}
|
|
2946
|
+
}
|
|
2947
|
+
const appState = getAppState();
|
|
2948
|
+
const allMcpClients = [
|
|
2949
|
+
...appState.mcp.clients,
|
|
2950
|
+
...sdkClients,
|
|
2951
|
+
...dynamicMcpState.clients
|
|
2952
|
+
];
|
|
2953
|
+
registerElicitationHandlers(allMcpClients);
|
|
2954
|
+
for (const client of allMcpClients) {
|
|
2955
|
+
reregisterChannelHandlerAfterReconnect(client);
|
|
2956
|
+
}
|
|
2957
|
+
const allTools = buildAllTools(appState);
|
|
2958
|
+
for (const uuid of batchUuids) {
|
|
2959
|
+
notifyCommandLifecycle(uuid, "started");
|
|
2960
|
+
}
|
|
2961
|
+
if (command.mode === "task-notification") {
|
|
2962
|
+
const notificationText = typeof command.value === "string" ? command.value : "";
|
|
2963
|
+
const taskIdMatch = notificationText.match(/<task-id>([^<]+)<\/task-id>/);
|
|
2964
|
+
const toolUseIdMatch = notificationText.match(/<tool-use-id>([^<]+)<\/tool-use-id>/);
|
|
2965
|
+
const outputFileMatch = notificationText.match(/<output-file>([^<]+)<\/output-file>/);
|
|
2966
|
+
const statusMatch = notificationText.match(/<status>([^<]+)<\/status>/);
|
|
2967
|
+
const summaryMatch = notificationText.match(/<summary>([^<]+)<\/summary>/);
|
|
2968
|
+
const isValidStatus = (s) => s === "completed" || s === "failed" || s === "stopped" || s === "killed";
|
|
2969
|
+
const rawStatus = statusMatch?.[1];
|
|
2970
|
+
const status = isValidStatus(rawStatus) ? rawStatus === "killed" ? "stopped" : rawStatus : "completed";
|
|
2971
|
+
const usageMatch = notificationText.match(/<usage>([\s\S]*?)<\/usage>/);
|
|
2972
|
+
const usageContent = usageMatch?.[1] ?? "";
|
|
2973
|
+
const totalTokensMatch = usageContent.match(/<total_tokens>(\d+)<\/total_tokens>/);
|
|
2974
|
+
const toolUsesMatch = usageContent.match(/<tool_uses>(\d+)<\/tool_uses>/);
|
|
2975
|
+
const durationMsMatch = usageContent.match(/<duration_ms>(\d+)<\/duration_ms>/);
|
|
2976
|
+
if (statusMatch) {
|
|
2977
|
+
output.enqueue({
|
|
2978
|
+
type: "system",
|
|
2979
|
+
subtype: "task_notification",
|
|
2980
|
+
task_id: taskIdMatch?.[1] ?? "",
|
|
2981
|
+
tool_use_id: toolUseIdMatch?.[1],
|
|
2982
|
+
status,
|
|
2983
|
+
output_file: outputFileMatch?.[1] ?? "",
|
|
2984
|
+
summary: summaryMatch?.[1] ?? "",
|
|
2985
|
+
usage: totalTokensMatch && toolUsesMatch ? {
|
|
2986
|
+
total_tokens: parseInt(totalTokensMatch[1], 10),
|
|
2987
|
+
tool_uses: parseInt(toolUsesMatch[1], 10),
|
|
2988
|
+
duration_ms: durationMsMatch ? parseInt(durationMsMatch[1], 10) : 0
|
|
2989
|
+
} : undefined,
|
|
2990
|
+
session_id: getSessionId(),
|
|
2991
|
+
uuid: randomUUID4()
|
|
2992
|
+
});
|
|
2993
|
+
}
|
|
2994
|
+
}
|
|
2995
|
+
const input = command.value;
|
|
2996
|
+
if (structuredIO instanceof RemoteIO && command.mode === "prompt") {
|
|
2997
|
+
logEvent("tengu_bridge_message_received", {
|
|
2998
|
+
is_repl: false
|
|
2999
|
+
});
|
|
3000
|
+
}
|
|
3001
|
+
suggestionState.abortController?.abort();
|
|
3002
|
+
suggestionState.abortController = null;
|
|
3003
|
+
suggestionState.pendingSuggestion = null;
|
|
3004
|
+
suggestionState.pendingLastEmittedEntry = null;
|
|
3005
|
+
if (suggestionState.lastEmitted) {
|
|
3006
|
+
if (command.mode === "prompt") {
|
|
3007
|
+
const inputText = typeof input === "string" ? input : input.find((b) => b.type === "text")?.text;
|
|
3008
|
+
if (typeof inputText === "string") {
|
|
3009
|
+
logSuggestionOutcome(suggestionState.lastEmitted.text, inputText, suggestionState.lastEmitted.emittedAt, suggestionState.lastEmitted.promptId, suggestionState.lastEmitted.generationRequestId);
|
|
3010
|
+
}
|
|
3011
|
+
suggestionState.lastEmitted = null;
|
|
3012
|
+
}
|
|
3013
|
+
}
|
|
3014
|
+
abortController = createAbortController();
|
|
3015
|
+
const turnStartTime = undefined;
|
|
3016
|
+
headlessProfilerCheckpoint("before_ask");
|
|
3017
|
+
startQueryProfile();
|
|
3018
|
+
const cmd = command;
|
|
3019
|
+
await runWithWorkload(cmd.workload ?? options.workload, async () => {
|
|
3020
|
+
for await (const message of ask({
|
|
3021
|
+
commands: uniqBy_default([...currentCommands, ...appState.mcp.commands], "name"),
|
|
3022
|
+
prompt: input,
|
|
3023
|
+
promptUuid: cmd.uuid,
|
|
3024
|
+
isMeta: cmd.isMeta,
|
|
3025
|
+
cwd: cwd(),
|
|
3026
|
+
tools: allTools,
|
|
3027
|
+
verbose: options.verbose,
|
|
3028
|
+
mcpClients: allMcpClients,
|
|
3029
|
+
thinkingConfig: options.thinkingConfig,
|
|
3030
|
+
maxTurns: options.maxTurns,
|
|
3031
|
+
maxBudgetUsd: options.maxBudgetUsd,
|
|
3032
|
+
taskBudget: options.taskBudget,
|
|
3033
|
+
canUseTool,
|
|
3034
|
+
userSpecifiedModel: activeUserSpecifiedModel,
|
|
3035
|
+
fallbackModel: options.fallbackModel,
|
|
3036
|
+
jsonSchema: getInitJsonSchema() ?? options.jsonSchema,
|
|
3037
|
+
mutableMessages,
|
|
3038
|
+
getReadFileCache: () => pendingSeeds.size === 0 ? readFileState : mergeFileStateCaches(readFileState, pendingSeeds),
|
|
3039
|
+
setReadFileCache: (cache) => {
|
|
3040
|
+
readFileState = cache;
|
|
3041
|
+
for (const [path, seed] of pendingSeeds.entries()) {
|
|
3042
|
+
const existing = readFileState.get(path);
|
|
3043
|
+
if (!existing || seed.timestamp > existing.timestamp) {
|
|
3044
|
+
readFileState.set(path, seed);
|
|
3045
|
+
}
|
|
3046
|
+
}
|
|
3047
|
+
pendingSeeds.clear();
|
|
3048
|
+
},
|
|
3049
|
+
customSystemPrompt: options.systemPrompt,
|
|
3050
|
+
appendSystemPrompt: options.appendSystemPrompt,
|
|
3051
|
+
getAppState,
|
|
3052
|
+
setAppState,
|
|
3053
|
+
abortController,
|
|
3054
|
+
replayUserMessages: options.replayUserMessages,
|
|
3055
|
+
includePartialMessages: options.includePartialMessages,
|
|
3056
|
+
handleElicitation: (serverName, params, elicitSignal) => structuredIO.handleElicitation(serverName, params.message, undefined, elicitSignal, params.mode, params.url, "elicitationId" in params ? params.elicitationId : undefined),
|
|
3057
|
+
agents: currentAgents,
|
|
3058
|
+
orphanedPermission: cmd.orphanedPermission,
|
|
3059
|
+
setSDKStatus: (status) => {
|
|
3060
|
+
output.enqueue({
|
|
3061
|
+
type: "system",
|
|
3062
|
+
subtype: "status",
|
|
3063
|
+
status,
|
|
3064
|
+
session_id: getSessionId(),
|
|
3065
|
+
uuid: randomUUID4()
|
|
3066
|
+
});
|
|
3067
|
+
}
|
|
3068
|
+
})) {
|
|
3069
|
+
forwardMessagesToBridge();
|
|
3070
|
+
if (message.type === "result") {
|
|
3071
|
+
for (const event of drainSdkEvents()) {
|
|
3072
|
+
output.enqueue(event);
|
|
3073
|
+
}
|
|
3074
|
+
const currentState = getAppState();
|
|
3075
|
+
if (getRunningTasks(currentState).some((t) => (t.type === "local_agent" || t.type === "local_workflow") && isBackgroundTask(t))) {
|
|
3076
|
+
heldBackResult = message;
|
|
3077
|
+
} else {
|
|
3078
|
+
heldBackResult = null;
|
|
3079
|
+
output.enqueue(message);
|
|
3080
|
+
}
|
|
3081
|
+
} else {
|
|
3082
|
+
for (const event of drainSdkEvents()) {
|
|
3083
|
+
output.enqueue(event);
|
|
3084
|
+
}
|
|
3085
|
+
output.enqueue(message);
|
|
3086
|
+
}
|
|
3087
|
+
}
|
|
3088
|
+
});
|
|
3089
|
+
for (const uuid of batchUuids) {
|
|
3090
|
+
notifyCommandLifecycle(uuid, "completed");
|
|
3091
|
+
}
|
|
3092
|
+
forwardMessagesToBridge();
|
|
3093
|
+
bridgeHandle?.sendResult();
|
|
3094
|
+
if (false) {}
|
|
3095
|
+
if (options.promptSuggestions && !isEnvDefinedFalsy(process.env.CLAUDE_CODE_ENABLE_PROMPT_SUGGESTION)) {
|
|
3096
|
+
const state = suggestionState;
|
|
3097
|
+
state.abortController?.abort();
|
|
3098
|
+
const localAbort = new AbortController;
|
|
3099
|
+
suggestionState.abortController = localAbort;
|
|
3100
|
+
const cacheSafeParams = getLastCacheSafeParams();
|
|
3101
|
+
if (!cacheSafeParams) {
|
|
3102
|
+
logSuggestionSuppressed("sdk_no_params", undefined, undefined, "sdk");
|
|
3103
|
+
} else {
|
|
3104
|
+
const ref = { promise: null };
|
|
3105
|
+
ref.promise = (async () => {
|
|
3106
|
+
try {
|
|
3107
|
+
const result = await tryGenerateSuggestion(localAbort, mutableMessages, getAppState, cacheSafeParams, "sdk");
|
|
3108
|
+
if (!result || localAbort.signal.aborted)
|
|
3109
|
+
return;
|
|
3110
|
+
const suggestionMsg = {
|
|
3111
|
+
type: "prompt_suggestion",
|
|
3112
|
+
suggestion: result.suggestion,
|
|
3113
|
+
uuid: randomUUID4(),
|
|
3114
|
+
session_id: getSessionId()
|
|
3115
|
+
};
|
|
3116
|
+
const lastEmittedEntry = {
|
|
3117
|
+
text: result.suggestion,
|
|
3118
|
+
emittedAt: Date.now(),
|
|
3119
|
+
promptId: result.promptId,
|
|
3120
|
+
generationRequestId: result.generationRequestId
|
|
3121
|
+
};
|
|
3122
|
+
if (heldBackResult) {
|
|
3123
|
+
suggestionState.pendingSuggestion = suggestionMsg;
|
|
3124
|
+
suggestionState.pendingLastEmittedEntry = {
|
|
3125
|
+
text: lastEmittedEntry.text,
|
|
3126
|
+
promptId: lastEmittedEntry.promptId,
|
|
3127
|
+
generationRequestId: lastEmittedEntry.generationRequestId
|
|
3128
|
+
};
|
|
3129
|
+
} else {
|
|
3130
|
+
suggestionState.lastEmitted = lastEmittedEntry;
|
|
3131
|
+
output.enqueue(suggestionMsg);
|
|
3132
|
+
}
|
|
3133
|
+
} catch (error) {
|
|
3134
|
+
if (error instanceof Error && (error.name === "AbortError" || error.name === "APIUserAbortError")) {
|
|
3135
|
+
logSuggestionSuppressed("aborted", undefined, undefined, "sdk");
|
|
3136
|
+
return;
|
|
3137
|
+
}
|
|
3138
|
+
logError(toError(error));
|
|
3139
|
+
} finally {
|
|
3140
|
+
if (suggestionState.inflightPromise === ref.promise) {
|
|
3141
|
+
suggestionState.inflightPromise = null;
|
|
3142
|
+
}
|
|
3143
|
+
}
|
|
3144
|
+
})();
|
|
3145
|
+
suggestionState.inflightPromise = ref.promise;
|
|
3146
|
+
}
|
|
3147
|
+
}
|
|
3148
|
+
logHeadlessProfilerTurn();
|
|
3149
|
+
logQueryProfileReport();
|
|
3150
|
+
headlessProfilerStartTurn();
|
|
3151
|
+
}
|
|
3152
|
+
};
|
|
3153
|
+
do {
|
|
3154
|
+
for (const event of drainSdkEvents()) {
|
|
3155
|
+
output.enqueue(event);
|
|
3156
|
+
}
|
|
3157
|
+
runPhase = "draining_commands";
|
|
3158
|
+
await drainCommandQueue();
|
|
3159
|
+
waitingForAgents = false;
|
|
3160
|
+
{
|
|
3161
|
+
const state = getAppState();
|
|
3162
|
+
const hasRunningBg = getRunningTasks(state).some((t) => isBackgroundTask(t) && t.type !== "in_process_teammate");
|
|
3163
|
+
const hasMainThreadQueued = peek(isMainThread) !== undefined;
|
|
3164
|
+
if (hasRunningBg || hasMainThreadQueued) {
|
|
3165
|
+
waitingForAgents = true;
|
|
3166
|
+
if (!hasMainThreadQueued) {
|
|
3167
|
+
runPhase = "waiting_for_agents";
|
|
3168
|
+
await sleep(100);
|
|
3169
|
+
}
|
|
3170
|
+
}
|
|
3171
|
+
}
|
|
3172
|
+
} while (waitingForAgents);
|
|
3173
|
+
if (heldBackResult) {
|
|
3174
|
+
output.enqueue(heldBackResult);
|
|
3175
|
+
heldBackResult = null;
|
|
3176
|
+
if (suggestionState.pendingSuggestion) {
|
|
3177
|
+
output.enqueue(suggestionState.pendingSuggestion);
|
|
3178
|
+
if (suggestionState.pendingLastEmittedEntry) {
|
|
3179
|
+
suggestionState.lastEmitted = {
|
|
3180
|
+
...suggestionState.pendingLastEmittedEntry,
|
|
3181
|
+
emittedAt: Date.now()
|
|
3182
|
+
};
|
|
3183
|
+
suggestionState.pendingLastEmittedEntry = null;
|
|
3184
|
+
}
|
|
3185
|
+
suggestionState.pendingSuggestion = null;
|
|
3186
|
+
}
|
|
3187
|
+
}
|
|
3188
|
+
} catch (error) {
|
|
3189
|
+
try {
|
|
3190
|
+
await structuredIO.write({
|
|
3191
|
+
type: "result",
|
|
3192
|
+
subtype: "error_during_execution",
|
|
3193
|
+
duration_ms: 0,
|
|
3194
|
+
duration_api_ms: 0,
|
|
3195
|
+
is_error: true,
|
|
3196
|
+
num_turns: 0,
|
|
3197
|
+
stop_reason: null,
|
|
3198
|
+
session_id: getSessionId(),
|
|
3199
|
+
total_cost_usd: 0,
|
|
3200
|
+
usage: EMPTY_USAGE,
|
|
3201
|
+
modelUsage: {},
|
|
3202
|
+
permission_denials: [],
|
|
3203
|
+
uuid: randomUUID4(),
|
|
3204
|
+
errors: [
|
|
3205
|
+
errorMessage(error),
|
|
3206
|
+
...getInMemoryErrors().map((_) => _.error)
|
|
3207
|
+
]
|
|
3208
|
+
});
|
|
3209
|
+
} catch {}
|
|
3210
|
+
suggestionState.abortController?.abort();
|
|
3211
|
+
gracefulShutdownSync(1);
|
|
3212
|
+
return;
|
|
3213
|
+
} finally {
|
|
3214
|
+
runPhase = "finally_flush";
|
|
3215
|
+
await structuredIO.flushInternalEvents();
|
|
3216
|
+
runPhase = "finally_post_flush";
|
|
3217
|
+
if (!isShuttingDown()) {
|
|
3218
|
+
notifySessionStateChanged("idle");
|
|
3219
|
+
for (const event of drainSdkEvents()) {
|
|
3220
|
+
output.enqueue(event);
|
|
3221
|
+
}
|
|
3222
|
+
}
|
|
3223
|
+
running = false;
|
|
3224
|
+
idleTimeout.start();
|
|
3225
|
+
}
|
|
3226
|
+
if (false) {}
|
|
3227
|
+
if (peek(isMainThread) !== undefined) {
|
|
3228
|
+
run();
|
|
3229
|
+
return;
|
|
3230
|
+
}
|
|
3231
|
+
{
|
|
3232
|
+
const currentAppState = getAppState();
|
|
3233
|
+
const teamContext = currentAppState.teamContext;
|
|
3234
|
+
if (teamContext && isTeamLead(teamContext)) {
|
|
3235
|
+
const agentName = "team-lead";
|
|
3236
|
+
const POLL_INTERVAL_MS = 500;
|
|
3237
|
+
while (true) {
|
|
3238
|
+
const refreshedState = getAppState();
|
|
3239
|
+
const hasActiveTeammates = hasActiveInProcessTeammates(refreshedState) || refreshedState.teamContext && Object.keys(refreshedState.teamContext.teammates).length > 0;
|
|
3240
|
+
if (!hasActiveTeammates) {
|
|
3241
|
+
logForDebugging("[print.ts] No more active teammates, stopping poll");
|
|
3242
|
+
break;
|
|
3243
|
+
}
|
|
3244
|
+
const unread = await readUnreadMessages(agentName, refreshedState.teamContext?.teamName);
|
|
3245
|
+
if (unread.length > 0) {
|
|
3246
|
+
logForDebugging(`[print.ts] Team-lead found ${unread.length} unread messages`);
|
|
3247
|
+
await markMessagesAsRead(agentName, refreshedState.teamContext?.teamName);
|
|
3248
|
+
const teamName = refreshedState.teamContext?.teamName;
|
|
3249
|
+
for (const m of unread) {
|
|
3250
|
+
const shutdownApproval = isShutdownApproved(m.text);
|
|
3251
|
+
if (shutdownApproval && teamName) {
|
|
3252
|
+
const teammateToRemove = shutdownApproval.from;
|
|
3253
|
+
logForDebugging(`[print.ts] Processing shutdown_approved from ${teammateToRemove}`);
|
|
3254
|
+
const teammateId = refreshedState.teamContext?.teammates ? Object.entries(refreshedState.teamContext.teammates).find(([, t]) => t.name === teammateToRemove)?.[0] : undefined;
|
|
3255
|
+
if (teammateId) {
|
|
3256
|
+
removeTeammateFromTeamFile(teamName, {
|
|
3257
|
+
agentId: teammateId,
|
|
3258
|
+
name: teammateToRemove
|
|
3259
|
+
});
|
|
3260
|
+
logForDebugging(`[print.ts] Removed ${teammateToRemove} from team file`);
|
|
3261
|
+
await unassignTeammateTasks(teamName, teammateId, teammateToRemove, "shutdown");
|
|
3262
|
+
setAppState((prev) => {
|
|
3263
|
+
if (!prev.teamContext?.teammates)
|
|
3264
|
+
return prev;
|
|
3265
|
+
if (!(teammateId in prev.teamContext.teammates))
|
|
3266
|
+
return prev;
|
|
3267
|
+
const { [teammateId]: _, ...remainingTeammates } = prev.teamContext.teammates;
|
|
3268
|
+
return {
|
|
3269
|
+
...prev,
|
|
3270
|
+
teamContext: {
|
|
3271
|
+
...prev.teamContext,
|
|
3272
|
+
teammates: remainingTeammates
|
|
3273
|
+
}
|
|
3274
|
+
};
|
|
3275
|
+
});
|
|
3276
|
+
}
|
|
3277
|
+
}
|
|
3278
|
+
}
|
|
3279
|
+
const formatted = unread.map((m) => `<${TEAMMATE_MESSAGE_TAG} teammate_id="${m.from}"${m.color ? ` color="${m.color}"` : ""}>
|
|
3280
|
+
${m.text}
|
|
3281
|
+
</${TEAMMATE_MESSAGE_TAG}>`).join(`
|
|
3282
|
+
|
|
3283
|
+
`);
|
|
3284
|
+
enqueue({
|
|
3285
|
+
mode: "prompt",
|
|
3286
|
+
value: formatted,
|
|
3287
|
+
uuid: randomUUID4()
|
|
3288
|
+
});
|
|
3289
|
+
run();
|
|
3290
|
+
return;
|
|
3291
|
+
}
|
|
3292
|
+
if (inputClosed && !shutdownPromptInjected) {
|
|
3293
|
+
shutdownPromptInjected = true;
|
|
3294
|
+
logForDebugging("[print.ts] Input closed with active teammates, injecting shutdown prompt");
|
|
3295
|
+
enqueue({
|
|
3296
|
+
mode: "prompt",
|
|
3297
|
+
value: SHUTDOWN_TEAM_PROMPT,
|
|
3298
|
+
uuid: randomUUID4()
|
|
3299
|
+
});
|
|
3300
|
+
run();
|
|
3301
|
+
return;
|
|
3302
|
+
}
|
|
3303
|
+
await sleep(POLL_INTERVAL_MS);
|
|
3304
|
+
}
|
|
3305
|
+
}
|
|
3306
|
+
}
|
|
3307
|
+
if (inputClosed) {
|
|
3308
|
+
const hasActiveSwarm = await (async () => {
|
|
3309
|
+
const currentAppState = getAppState();
|
|
3310
|
+
if (hasWorkingInProcessTeammates(currentAppState)) {
|
|
3311
|
+
await waitForTeammatesToBecomeIdle(setAppState, currentAppState);
|
|
3312
|
+
}
|
|
3313
|
+
const refreshedAppState = getAppState();
|
|
3314
|
+
const refreshedTeamContext = refreshedAppState.teamContext;
|
|
3315
|
+
const hasTeamMembersNotCleanedUp = refreshedTeamContext && Object.keys(refreshedTeamContext.teammates).length > 0;
|
|
3316
|
+
return hasTeamMembersNotCleanedUp || hasActiveInProcessTeammates(refreshedAppState);
|
|
3317
|
+
})();
|
|
3318
|
+
if (hasActiveSwarm) {
|
|
3319
|
+
enqueue({
|
|
3320
|
+
mode: "prompt",
|
|
3321
|
+
value: SHUTDOWN_TEAM_PROMPT,
|
|
3322
|
+
uuid: randomUUID4()
|
|
3323
|
+
});
|
|
3324
|
+
run();
|
|
3325
|
+
} else {
|
|
3326
|
+
if (suggestionState.inflightPromise) {
|
|
3327
|
+
await Promise.race([suggestionState.inflightPromise, sleep(5000)]);
|
|
3328
|
+
}
|
|
3329
|
+
suggestionState.abortController?.abort();
|
|
3330
|
+
suggestionState.abortController = null;
|
|
3331
|
+
await finalizePendingAsyncHooks();
|
|
3332
|
+
unsubscribeSkillChanges();
|
|
3333
|
+
unsubscribeAuthStatus?.();
|
|
3334
|
+
statusListeners.delete(rateLimitListener);
|
|
3335
|
+
output.done();
|
|
3336
|
+
}
|
|
3337
|
+
}
|
|
3338
|
+
};
|
|
3339
|
+
if (false) {}
|
|
3340
|
+
let cronScheduler = null;
|
|
3341
|
+
if (cronGate.isKairosCronEnabled()) {
|
|
3342
|
+
cronScheduler = cronSchedulerModule.createCronScheduler({
|
|
3343
|
+
onFire: (prompt) => {
|
|
3344
|
+
if (inputClosed)
|
|
3345
|
+
return;
|
|
3346
|
+
enqueue({
|
|
3347
|
+
mode: "prompt",
|
|
3348
|
+
value: prompt,
|
|
3349
|
+
uuid: randomUUID4(),
|
|
3350
|
+
priority: "later",
|
|
3351
|
+
isMeta: true,
|
|
3352
|
+
workload: WORKLOAD_CRON
|
|
3353
|
+
});
|
|
3354
|
+
run();
|
|
3355
|
+
},
|
|
3356
|
+
isLoading: () => running || inputClosed,
|
|
3357
|
+
getJitterConfig: cronJitterConfigModule?.getCronJitterConfig,
|
|
3358
|
+
isKilled: () => !cronGate?.isKairosCronEnabled()
|
|
3359
|
+
});
|
|
3360
|
+
cronScheduler.start();
|
|
3361
|
+
}
|
|
3362
|
+
const sendControlResponseSuccess = function(message, response) {
|
|
3363
|
+
output.enqueue({
|
|
3364
|
+
type: "control_response",
|
|
3365
|
+
response: {
|
|
3366
|
+
subtype: "success",
|
|
3367
|
+
request_id: message.request_id,
|
|
3368
|
+
response
|
|
3369
|
+
}
|
|
3370
|
+
});
|
|
3371
|
+
};
|
|
3372
|
+
const sendControlResponseError = function(message, errorMessage2) {
|
|
3373
|
+
output.enqueue({
|
|
3374
|
+
type: "control_response",
|
|
3375
|
+
response: {
|
|
3376
|
+
subtype: "error",
|
|
3377
|
+
request_id: message.request_id,
|
|
3378
|
+
error: errorMessage2
|
|
3379
|
+
}
|
|
3380
|
+
});
|
|
3381
|
+
};
|
|
3382
|
+
const handledOrphanedToolUseIds = new Set;
|
|
3383
|
+
structuredIO.setUnexpectedResponseCallback(async (message) => {
|
|
3384
|
+
await handleOrphanedPermissionResponse({
|
|
3385
|
+
message,
|
|
3386
|
+
setAppState,
|
|
3387
|
+
handledToolUseIds: handledOrphanedToolUseIds,
|
|
3388
|
+
onEnqueued: () => {
|
|
3389
|
+
run();
|
|
3390
|
+
}
|
|
3391
|
+
});
|
|
3392
|
+
});
|
|
3393
|
+
const activeOAuthFlows = new Map;
|
|
3394
|
+
const oauthCallbackSubmitters = new Map;
|
|
3395
|
+
const oauthManualCallbackUsed = new Set;
|
|
3396
|
+
const oauthAuthPromises = new Map;
|
|
3397
|
+
let claudeOAuth = null;
|
|
3398
|
+
(async () => {
|
|
3399
|
+
let initialized = false;
|
|
3400
|
+
logForDiagnosticsNoPII("info", "cli_message_loop_started");
|
|
3401
|
+
for await (const message of structuredIO.structuredInput) {
|
|
3402
|
+
const eventId = "uuid" in message ? message.uuid : undefined;
|
|
3403
|
+
if (eventId && message.type !== "user" && message.type !== "control_response") {
|
|
3404
|
+
notifyCommandLifecycle(eventId, "completed");
|
|
3405
|
+
}
|
|
3406
|
+
if (message.type === "control_request") {
|
|
3407
|
+
if (message.request.subtype === "interrupt") {
|
|
3408
|
+
if (false) {}
|
|
3409
|
+
if (abortController) {
|
|
3410
|
+
abortController.abort();
|
|
3411
|
+
}
|
|
3412
|
+
suggestionState.abortController?.abort();
|
|
3413
|
+
suggestionState.abortController = null;
|
|
3414
|
+
suggestionState.lastEmitted = null;
|
|
3415
|
+
suggestionState.pendingSuggestion = null;
|
|
3416
|
+
sendControlResponseSuccess(message);
|
|
3417
|
+
} else if (message.request.subtype === "end_session") {
|
|
3418
|
+
logForDebugging(`[print.ts] end_session received, reason=${message.request.reason ?? "unspecified"}`);
|
|
3419
|
+
if (abortController) {
|
|
3420
|
+
abortController.abort();
|
|
3421
|
+
}
|
|
3422
|
+
suggestionState.abortController?.abort();
|
|
3423
|
+
suggestionState.abortController = null;
|
|
3424
|
+
suggestionState.lastEmitted = null;
|
|
3425
|
+
suggestionState.pendingSuggestion = null;
|
|
3426
|
+
sendControlResponseSuccess(message);
|
|
3427
|
+
break;
|
|
3428
|
+
} else if (message.request.subtype === "initialize") {
|
|
3429
|
+
if (message.request.sdkMcpServers && message.request.sdkMcpServers.length > 0) {
|
|
3430
|
+
for (const serverName of message.request.sdkMcpServers) {
|
|
3431
|
+
sdkMcpConfigs[serverName] = {
|
|
3432
|
+
type: "sdk",
|
|
3433
|
+
name: serverName
|
|
3434
|
+
};
|
|
3435
|
+
}
|
|
3436
|
+
}
|
|
3437
|
+
await handleInitializeRequest(message.request, message.request_id, initialized, output, commands, modelInfos, structuredIO, !!options.enableAuthStatus, options, agents, getAppState);
|
|
3438
|
+
if (message.request.promptSuggestions) {
|
|
3439
|
+
setAppState((prev) => {
|
|
3440
|
+
if (prev.promptSuggestionEnabled)
|
|
3441
|
+
return prev;
|
|
3442
|
+
return { ...prev, promptSuggestionEnabled: true };
|
|
3443
|
+
});
|
|
3444
|
+
}
|
|
3445
|
+
if (message.request.agentProgressSummaries && getFeatureValue_CACHED_MAY_BE_STALE("tengu_slate_prism", true)) {
|
|
3446
|
+
setSdkAgentProgressSummariesEnabled(true);
|
|
3447
|
+
}
|
|
3448
|
+
initialized = true;
|
|
3449
|
+
if (hasCommandsInQueue()) {
|
|
3450
|
+
run();
|
|
3451
|
+
}
|
|
3452
|
+
} else if (message.request.subtype === "set_permission_mode") {
|
|
3453
|
+
const m = message.request;
|
|
3454
|
+
setAppState((prev) => ({
|
|
3455
|
+
...prev,
|
|
3456
|
+
toolPermissionContext: handleSetPermissionMode(m, message.request_id, prev.toolPermissionContext, output),
|
|
3457
|
+
isUltraplanMode: m.ultraplan ?? prev.isUltraplanMode
|
|
3458
|
+
}));
|
|
3459
|
+
} else if (message.request.subtype === "set_model") {
|
|
3460
|
+
const requestedModel = message.request.model ?? "default";
|
|
3461
|
+
const model = requestedModel === "default" ? getDefaultMainLoopModel() : requestedModel;
|
|
3462
|
+
activeUserSpecifiedModel = model;
|
|
3463
|
+
setMainLoopModelOverride(model);
|
|
3464
|
+
notifySessionMetadataChanged({ model });
|
|
3465
|
+
injectModelSwitchBreadcrumbs(requestedModel, model);
|
|
3466
|
+
sendControlResponseSuccess(message);
|
|
3467
|
+
} else if (message.request.subtype === "set_max_thinking_tokens") {
|
|
3468
|
+
if (message.request.max_thinking_tokens === null) {
|
|
3469
|
+
options.thinkingConfig = undefined;
|
|
3470
|
+
} else if (message.request.max_thinking_tokens === 0) {
|
|
3471
|
+
options.thinkingConfig = { type: "disabled" };
|
|
3472
|
+
} else {
|
|
3473
|
+
options.thinkingConfig = {
|
|
3474
|
+
type: "enabled",
|
|
3475
|
+
budgetTokens: message.request.max_thinking_tokens
|
|
3476
|
+
};
|
|
3477
|
+
}
|
|
3478
|
+
sendControlResponseSuccess(message);
|
|
3479
|
+
} else if (message.request.subtype === "mcp_status") {
|
|
3480
|
+
sendControlResponseSuccess(message, {
|
|
3481
|
+
mcpServers: buildMcpServerStatuses()
|
|
3482
|
+
});
|
|
3483
|
+
} else if (message.request.subtype === "get_context_usage") {
|
|
3484
|
+
try {
|
|
3485
|
+
const appState = getAppState();
|
|
3486
|
+
const data = await collectContextData({
|
|
3487
|
+
messages: mutableMessages,
|
|
3488
|
+
getAppState,
|
|
3489
|
+
options: {
|
|
3490
|
+
mainLoopModel: getMainLoopModel(),
|
|
3491
|
+
tools: buildAllTools(appState),
|
|
3492
|
+
agentDefinitions: appState.agentDefinitions,
|
|
3493
|
+
customSystemPrompt: options.systemPrompt,
|
|
3494
|
+
appendSystemPrompt: options.appendSystemPrompt
|
|
3495
|
+
}
|
|
3496
|
+
});
|
|
3497
|
+
sendControlResponseSuccess(message, { ...data });
|
|
3498
|
+
} catch (error) {
|
|
3499
|
+
sendControlResponseError(message, errorMessage(error));
|
|
3500
|
+
}
|
|
3501
|
+
} else if (message.request.subtype === "mcp_message") {
|
|
3502
|
+
const mcpRequest = message.request;
|
|
3503
|
+
const sdkClient = sdkClients.find((client) => client.name === mcpRequest.server_name);
|
|
3504
|
+
if (sdkClient && sdkClient.type === "connected" && sdkClient.client?.transport?.onmessage) {
|
|
3505
|
+
sdkClient.client.transport.onmessage(mcpRequest.message);
|
|
3506
|
+
}
|
|
3507
|
+
sendControlResponseSuccess(message);
|
|
3508
|
+
} else if (message.request.subtype === "rewind_files") {
|
|
3509
|
+
const appState = getAppState();
|
|
3510
|
+
const result = await handleRewindFiles(message.request.user_message_id, appState, setAppState, message.request.dry_run ?? false);
|
|
3511
|
+
if (result.canRewind || message.request.dry_run) {
|
|
3512
|
+
sendControlResponseSuccess(message, result);
|
|
3513
|
+
} else {
|
|
3514
|
+
sendControlResponseError(message, result.error ?? "Unexpected error");
|
|
3515
|
+
}
|
|
3516
|
+
} else if (message.request.subtype === "cancel_async_message") {
|
|
3517
|
+
const targetUuid = message.request.message_uuid;
|
|
3518
|
+
const removed = dequeueAllMatching((cmd) => cmd.uuid === targetUuid);
|
|
3519
|
+
sendControlResponseSuccess(message, {
|
|
3520
|
+
cancelled: removed.length > 0
|
|
3521
|
+
});
|
|
3522
|
+
} else if (message.request.subtype === "seed_read_state") {
|
|
3523
|
+
try {
|
|
3524
|
+
const normalizedPath = expandPath(message.request.path);
|
|
3525
|
+
const diskMtime = Math.floor((await stat(normalizedPath)).mtimeMs);
|
|
3526
|
+
if (diskMtime <= message.request.mtime) {
|
|
3527
|
+
const raw = await readFile2(normalizedPath, "utf-8");
|
|
3528
|
+
const content = (raw.charCodeAt(0) === 65279 ? raw.slice(1) : raw).replaceAll(`\r
|
|
3529
|
+
`, `
|
|
3530
|
+
`);
|
|
3531
|
+
pendingSeeds.set(normalizedPath, {
|
|
3532
|
+
content,
|
|
3533
|
+
timestamp: diskMtime,
|
|
3534
|
+
offset: undefined,
|
|
3535
|
+
limit: undefined
|
|
3536
|
+
});
|
|
3537
|
+
}
|
|
3538
|
+
} catch {}
|
|
3539
|
+
sendControlResponseSuccess(message);
|
|
3540
|
+
} else if (message.request.subtype === "mcp_set_servers") {
|
|
3541
|
+
const { response, sdkServersChanged } = await applyMcpServerChanges(message.request.servers);
|
|
3542
|
+
sendControlResponseSuccess(message, response);
|
|
3543
|
+
if (sdkServersChanged) {
|
|
3544
|
+
updateSdkMcp();
|
|
3545
|
+
}
|
|
3546
|
+
} else if (message.request.subtype === "reload_plugins") {
|
|
3547
|
+
try {
|
|
3548
|
+
if (false) {}
|
|
3549
|
+
const r = await refreshActivePlugins(setAppState);
|
|
3550
|
+
const sdkAgents = currentAgents.filter((a) => a.source === "flagSettings");
|
|
3551
|
+
currentAgents = [...r.agentDefinitions.allAgents, ...sdkAgents];
|
|
3552
|
+
let plugins = [];
|
|
3553
|
+
const [cmdsR, mcpR, pluginsR] = await Promise.allSettled([
|
|
3554
|
+
getCommands(cwd()),
|
|
3555
|
+
applyPluginMcpDiff(),
|
|
3556
|
+
loadAllPluginsCacheOnly()
|
|
3557
|
+
]);
|
|
3558
|
+
if (cmdsR.status === "fulfilled") {
|
|
3559
|
+
currentCommands = cmdsR.value;
|
|
3560
|
+
} else {
|
|
3561
|
+
logError(cmdsR.reason);
|
|
3562
|
+
}
|
|
3563
|
+
if (mcpR.status === "rejected") {
|
|
3564
|
+
logError(mcpR.reason);
|
|
3565
|
+
}
|
|
3566
|
+
if (pluginsR.status === "fulfilled") {
|
|
3567
|
+
plugins = pluginsR.value.enabled.map((p) => ({
|
|
3568
|
+
name: p.name,
|
|
3569
|
+
path: p.path,
|
|
3570
|
+
source: p.source
|
|
3571
|
+
}));
|
|
3572
|
+
} else {
|
|
3573
|
+
logError(pluginsR.reason);
|
|
3574
|
+
}
|
|
3575
|
+
sendControlResponseSuccess(message, {
|
|
3576
|
+
commands: currentCommands.filter((cmd) => cmd.userInvocable !== false).map((cmd) => ({
|
|
3577
|
+
name: getCommandName(cmd),
|
|
3578
|
+
description: formatDescriptionWithSource(cmd),
|
|
3579
|
+
argumentHint: cmd.argumentHint || ""
|
|
3580
|
+
})),
|
|
3581
|
+
agents: currentAgents.map((a) => ({
|
|
3582
|
+
name: a.agentType,
|
|
3583
|
+
description: a.whenToUse,
|
|
3584
|
+
model: a.model === "inherit" ? undefined : a.model
|
|
3585
|
+
})),
|
|
3586
|
+
plugins,
|
|
3587
|
+
mcpServers: buildMcpServerStatuses(),
|
|
3588
|
+
error_count: r.error_count
|
|
3589
|
+
});
|
|
3590
|
+
} catch (error) {
|
|
3591
|
+
sendControlResponseError(message, errorMessage(error));
|
|
3592
|
+
}
|
|
3593
|
+
} else if (message.request.subtype === "mcp_reconnect") {
|
|
3594
|
+
const currentAppState = getAppState();
|
|
3595
|
+
const { serverName } = message.request;
|
|
3596
|
+
elicitationRegistered.delete(serverName);
|
|
3597
|
+
const config = getMcpConfigByName(serverName) ?? mcpClients.find((c) => c.name === serverName)?.config ?? sdkClients.find((c) => c.name === serverName)?.config ?? dynamicMcpState.clients.find((c) => c.name === serverName)?.config ?? currentAppState.mcp.clients.find((c) => c.name === serverName)?.config ?? null;
|
|
3598
|
+
if (!config) {
|
|
3599
|
+
sendControlResponseError(message, `Server not found: ${serverName}`);
|
|
3600
|
+
} else {
|
|
3601
|
+
const result = await reconnectMcpServerImpl(serverName, config);
|
|
3602
|
+
const prefix = getMcpPrefix(serverName);
|
|
3603
|
+
setAppState((prev) => ({
|
|
3604
|
+
...prev,
|
|
3605
|
+
mcp: {
|
|
3606
|
+
...prev.mcp,
|
|
3607
|
+
clients: prev.mcp.clients.map((c) => c.name === serverName ? result.client : c),
|
|
3608
|
+
tools: [
|
|
3609
|
+
...reject_default(prev.mcp.tools, (t) => t.name?.startsWith(prefix)),
|
|
3610
|
+
...result.tools
|
|
3611
|
+
],
|
|
3612
|
+
commands: [
|
|
3613
|
+
...reject_default(prev.mcp.commands, (c) => commandBelongsToServer(c, serverName)),
|
|
3614
|
+
...result.commands
|
|
3615
|
+
],
|
|
3616
|
+
resources: result.resources && result.resources.length > 0 ? { ...prev.mcp.resources, [serverName]: result.resources } : omit_default(prev.mcp.resources, serverName)
|
|
3617
|
+
}
|
|
3618
|
+
}));
|
|
3619
|
+
dynamicMcpState = {
|
|
3620
|
+
...dynamicMcpState,
|
|
3621
|
+
clients: [
|
|
3622
|
+
...dynamicMcpState.clients.filter((c) => c.name !== serverName),
|
|
3623
|
+
result.client
|
|
3624
|
+
],
|
|
3625
|
+
tools: [
|
|
3626
|
+
...dynamicMcpState.tools.filter((t) => !t.name?.startsWith(prefix)),
|
|
3627
|
+
...result.tools
|
|
3628
|
+
]
|
|
3629
|
+
};
|
|
3630
|
+
if (result.client.type === "connected") {
|
|
3631
|
+
registerElicitationHandlers([result.client]);
|
|
3632
|
+
reregisterChannelHandlerAfterReconnect(result.client);
|
|
3633
|
+
sendControlResponseSuccess(message);
|
|
3634
|
+
} else {
|
|
3635
|
+
const errorMessage2 = result.client.type === "failed" ? result.client.error ?? "Connection failed" : `Server status: ${result.client.type}`;
|
|
3636
|
+
sendControlResponseError(message, errorMessage2);
|
|
3637
|
+
}
|
|
3638
|
+
}
|
|
3639
|
+
} else if (message.request.subtype === "mcp_toggle") {
|
|
3640
|
+
const currentAppState = getAppState();
|
|
3641
|
+
const { serverName, enabled } = message.request;
|
|
3642
|
+
elicitationRegistered.delete(serverName);
|
|
3643
|
+
const config = getMcpConfigByName(serverName) ?? mcpClients.find((c) => c.name === serverName)?.config ?? sdkClients.find((c) => c.name === serverName)?.config ?? dynamicMcpState.clients.find((c) => c.name === serverName)?.config ?? currentAppState.mcp.clients.find((c) => c.name === serverName)?.config ?? null;
|
|
3644
|
+
if (!config) {
|
|
3645
|
+
sendControlResponseError(message, `Server not found: ${serverName}`);
|
|
3646
|
+
} else if (!enabled) {
|
|
3647
|
+
setMcpServerEnabled(serverName, false);
|
|
3648
|
+
const client = [
|
|
3649
|
+
...mcpClients,
|
|
3650
|
+
...sdkClients,
|
|
3651
|
+
...dynamicMcpState.clients,
|
|
3652
|
+
...currentAppState.mcp.clients
|
|
3653
|
+
].find((c) => c.name === serverName);
|
|
3654
|
+
if (client && client.type === "connected") {
|
|
3655
|
+
await clearServerCache(serverName, config);
|
|
3656
|
+
}
|
|
3657
|
+
const prefix = getMcpPrefix(serverName);
|
|
3658
|
+
setAppState((prev) => ({
|
|
3659
|
+
...prev,
|
|
3660
|
+
mcp: {
|
|
3661
|
+
...prev.mcp,
|
|
3662
|
+
clients: prev.mcp.clients.map((c) => c.name === serverName ? { name: serverName, type: "disabled", config } : c),
|
|
3663
|
+
tools: reject_default(prev.mcp.tools, (t) => t.name?.startsWith(prefix)),
|
|
3664
|
+
commands: reject_default(prev.mcp.commands, (c) => commandBelongsToServer(c, serverName)),
|
|
3665
|
+
resources: omit_default(prev.mcp.resources, serverName)
|
|
3666
|
+
}
|
|
3667
|
+
}));
|
|
3668
|
+
sendControlResponseSuccess(message);
|
|
3669
|
+
} else {
|
|
3670
|
+
setMcpServerEnabled(serverName, true);
|
|
3671
|
+
const result = await reconnectMcpServerImpl(serverName, config);
|
|
3672
|
+
const prefix = getMcpPrefix(serverName);
|
|
3673
|
+
setAppState((prev) => ({
|
|
3674
|
+
...prev,
|
|
3675
|
+
mcp: {
|
|
3676
|
+
...prev.mcp,
|
|
3677
|
+
clients: prev.mcp.clients.map((c) => c.name === serverName ? result.client : c),
|
|
3678
|
+
tools: [
|
|
3679
|
+
...reject_default(prev.mcp.tools, (t) => t.name?.startsWith(prefix)),
|
|
3680
|
+
...result.tools
|
|
3681
|
+
],
|
|
3682
|
+
commands: [
|
|
3683
|
+
...reject_default(prev.mcp.commands, (c) => commandBelongsToServer(c, serverName)),
|
|
3684
|
+
...result.commands
|
|
3685
|
+
],
|
|
3686
|
+
resources: result.resources && result.resources.length > 0 ? { ...prev.mcp.resources, [serverName]: result.resources } : omit_default(prev.mcp.resources, serverName)
|
|
3687
|
+
}
|
|
3688
|
+
}));
|
|
3689
|
+
if (result.client.type === "connected") {
|
|
3690
|
+
registerElicitationHandlers([result.client]);
|
|
3691
|
+
reregisterChannelHandlerAfterReconnect(result.client);
|
|
3692
|
+
sendControlResponseSuccess(message);
|
|
3693
|
+
} else {
|
|
3694
|
+
const errorMessage2 = result.client.type === "failed" ? result.client.error ?? "Connection failed" : `Server status: ${result.client.type}`;
|
|
3695
|
+
sendControlResponseError(message, errorMessage2);
|
|
3696
|
+
}
|
|
3697
|
+
}
|
|
3698
|
+
} else if (message.request.subtype === "channel_enable") {
|
|
3699
|
+
const currentAppState = getAppState();
|
|
3700
|
+
handleChannelEnable(message.request_id, message.request.serverName, [
|
|
3701
|
+
...currentAppState.mcp.clients,
|
|
3702
|
+
...sdkClients,
|
|
3703
|
+
...dynamicMcpState.clients
|
|
3704
|
+
], output);
|
|
3705
|
+
} else if (message.request.subtype === "mcp_authenticate") {
|
|
3706
|
+
const { serverName } = message.request;
|
|
3707
|
+
const currentAppState = getAppState();
|
|
3708
|
+
const config = getMcpConfigByName(serverName) ?? mcpClients.find((c) => c.name === serverName)?.config ?? currentAppState.mcp.clients.find((c) => c.name === serverName)?.config ?? null;
|
|
3709
|
+
if (!config) {
|
|
3710
|
+
sendControlResponseError(message, `Server not found: ${serverName}`);
|
|
3711
|
+
} else if (config.type !== "sse" && config.type !== "http") {
|
|
3712
|
+
sendControlResponseError(message, `Server type "${config.type}" does not support OAuth authentication`);
|
|
3713
|
+
} else {
|
|
3714
|
+
try {
|
|
3715
|
+
activeOAuthFlows.get(serverName)?.abort();
|
|
3716
|
+
const controller = new AbortController;
|
|
3717
|
+
activeOAuthFlows.set(serverName, controller);
|
|
3718
|
+
let resolveAuthUrl;
|
|
3719
|
+
const authUrlPromise = new Promise((resolve) => {
|
|
3720
|
+
resolveAuthUrl = resolve;
|
|
3721
|
+
});
|
|
3722
|
+
const oauthPromise = performMCPOAuthFlow(serverName, config, (url) => resolveAuthUrl(url), controller.signal, {
|
|
3723
|
+
skipBrowserOpen: true,
|
|
3724
|
+
onWaitingForCallback: (submit) => {
|
|
3725
|
+
oauthCallbackSubmitters.set(serverName, submit);
|
|
3726
|
+
}
|
|
3727
|
+
});
|
|
3728
|
+
const authUrl = await Promise.race([
|
|
3729
|
+
authUrlPromise,
|
|
3730
|
+
oauthPromise.then(() => null)
|
|
3731
|
+
]);
|
|
3732
|
+
if (authUrl) {
|
|
3733
|
+
sendControlResponseSuccess(message, {
|
|
3734
|
+
authUrl,
|
|
3735
|
+
requiresUserAction: true
|
|
3736
|
+
});
|
|
3737
|
+
} else {
|
|
3738
|
+
sendControlResponseSuccess(message, {
|
|
3739
|
+
requiresUserAction: false
|
|
3740
|
+
});
|
|
3741
|
+
}
|
|
3742
|
+
oauthAuthPromises.set(serverName, oauthPromise);
|
|
3743
|
+
const fullFlowPromise = oauthPromise.then(async () => {
|
|
3744
|
+
if (isMcpServerDisabled(serverName)) {
|
|
3745
|
+
return;
|
|
3746
|
+
}
|
|
3747
|
+
if (oauthManualCallbackUsed.has(serverName)) {
|
|
3748
|
+
return;
|
|
3749
|
+
}
|
|
3750
|
+
const result = await reconnectMcpServerImpl(serverName, config);
|
|
3751
|
+
const prefix = getMcpPrefix(serverName);
|
|
3752
|
+
setAppState((prev) => ({
|
|
3753
|
+
...prev,
|
|
3754
|
+
mcp: {
|
|
3755
|
+
...prev.mcp,
|
|
3756
|
+
clients: prev.mcp.clients.map((c) => c.name === serverName ? result.client : c),
|
|
3757
|
+
tools: [
|
|
3758
|
+
...reject_default(prev.mcp.tools, (t) => t.name?.startsWith(prefix)),
|
|
3759
|
+
...result.tools
|
|
3760
|
+
],
|
|
3761
|
+
commands: [
|
|
3762
|
+
...reject_default(prev.mcp.commands, (c) => commandBelongsToServer(c, serverName)),
|
|
3763
|
+
...result.commands
|
|
3764
|
+
],
|
|
3765
|
+
resources: result.resources && result.resources.length > 0 ? {
|
|
3766
|
+
...prev.mcp.resources,
|
|
3767
|
+
[serverName]: result.resources
|
|
3768
|
+
} : omit_default(prev.mcp.resources, serverName)
|
|
3769
|
+
}
|
|
3770
|
+
}));
|
|
3771
|
+
dynamicMcpState = {
|
|
3772
|
+
...dynamicMcpState,
|
|
3773
|
+
clients: [
|
|
3774
|
+
...dynamicMcpState.clients.filter((c) => c.name !== serverName),
|
|
3775
|
+
result.client
|
|
3776
|
+
],
|
|
3777
|
+
tools: [
|
|
3778
|
+
...dynamicMcpState.tools.filter((t) => !t.name?.startsWith(prefix)),
|
|
3779
|
+
...result.tools
|
|
3780
|
+
]
|
|
3781
|
+
};
|
|
3782
|
+
}).catch((error) => {
|
|
3783
|
+
logForDebugging(`MCP OAuth failed for ${serverName}: ${error}`, { level: "error" });
|
|
3784
|
+
}).finally(() => {
|
|
3785
|
+
if (activeOAuthFlows.get(serverName) === controller) {
|
|
3786
|
+
activeOAuthFlows.delete(serverName);
|
|
3787
|
+
oauthCallbackSubmitters.delete(serverName);
|
|
3788
|
+
oauthManualCallbackUsed.delete(serverName);
|
|
3789
|
+
oauthAuthPromises.delete(serverName);
|
|
3790
|
+
}
|
|
3791
|
+
});
|
|
3792
|
+
} catch (error) {
|
|
3793
|
+
sendControlResponseError(message, errorMessage(error));
|
|
3794
|
+
}
|
|
3795
|
+
}
|
|
3796
|
+
} else if (message.request.subtype === "mcp_oauth_callback_url") {
|
|
3797
|
+
const { serverName, callbackUrl } = message.request;
|
|
3798
|
+
const submit = oauthCallbackSubmitters.get(serverName);
|
|
3799
|
+
if (submit) {
|
|
3800
|
+
let hasCodeOrError = false;
|
|
3801
|
+
try {
|
|
3802
|
+
const parsed = new URL(callbackUrl);
|
|
3803
|
+
hasCodeOrError = parsed.searchParams.has("code") || parsed.searchParams.has("error");
|
|
3804
|
+
} catch {}
|
|
3805
|
+
if (!hasCodeOrError) {
|
|
3806
|
+
sendControlResponseError(message, "Invalid callback URL: missing authorization code. Please paste the full redirect URL including the code parameter.");
|
|
3807
|
+
} else {
|
|
3808
|
+
oauthManualCallbackUsed.add(serverName);
|
|
3809
|
+
submit(callbackUrl);
|
|
3810
|
+
const authPromise = oauthAuthPromises.get(serverName);
|
|
3811
|
+
if (authPromise) {
|
|
3812
|
+
try {
|
|
3813
|
+
await authPromise;
|
|
3814
|
+
sendControlResponseSuccess(message);
|
|
3815
|
+
} catch (error) {
|
|
3816
|
+
sendControlResponseError(message, error instanceof Error ? error.message : "OAuth authentication failed");
|
|
3817
|
+
}
|
|
3818
|
+
} else {
|
|
3819
|
+
sendControlResponseSuccess(message);
|
|
3820
|
+
}
|
|
3821
|
+
}
|
|
3822
|
+
} else {
|
|
3823
|
+
sendControlResponseError(message, `No active OAuth flow for server: ${serverName}`);
|
|
3824
|
+
}
|
|
3825
|
+
} else if (message.request.subtype === "claude_authenticate") {
|
|
3826
|
+
const { loginWithClaudeAi } = message.request;
|
|
3827
|
+
claudeOAuth?.service.cleanup();
|
|
3828
|
+
logEvent("tengu_oauth_flow_start", {
|
|
3829
|
+
loginWithClaudeAi: loginWithClaudeAi ?? true
|
|
3830
|
+
});
|
|
3831
|
+
const service = new OAuthService;
|
|
3832
|
+
let urlResolver;
|
|
3833
|
+
const urlPromise = new Promise((resolve) => {
|
|
3834
|
+
urlResolver = resolve;
|
|
3835
|
+
});
|
|
3836
|
+
const flow = service.startOAuthFlow(async (manualUrl, automaticUrl) => {
|
|
3837
|
+
urlResolver({ manualUrl, automaticUrl });
|
|
3838
|
+
}, {
|
|
3839
|
+
loginWithClaudeAi: loginWithClaudeAi ?? true,
|
|
3840
|
+
skipBrowserOpen: true
|
|
3841
|
+
}).then(async (tokens) => {
|
|
3842
|
+
await installOAuthTokens(tokens);
|
|
3843
|
+
logEvent("tengu_oauth_success", {
|
|
3844
|
+
loginWithClaudeAi: loginWithClaudeAi ?? true
|
|
3845
|
+
});
|
|
3846
|
+
}).finally(() => {
|
|
3847
|
+
service.cleanup();
|
|
3848
|
+
if (claudeOAuth?.service === service) {
|
|
3849
|
+
claudeOAuth = null;
|
|
3850
|
+
}
|
|
3851
|
+
});
|
|
3852
|
+
claudeOAuth = { service, flow };
|
|
3853
|
+
flow.catch((err) => logForDebugging(`claude_authenticate flow ended: ${err}`, {
|
|
3854
|
+
level: "info"
|
|
3855
|
+
}));
|
|
3856
|
+
try {
|
|
3857
|
+
const { manualUrl, automaticUrl } = await Promise.race([
|
|
3858
|
+
urlPromise,
|
|
3859
|
+
flow.then(() => {
|
|
3860
|
+
throw new Error("OAuth flow completed without producing auth URLs");
|
|
3861
|
+
})
|
|
3862
|
+
]);
|
|
3863
|
+
sendControlResponseSuccess(message, {
|
|
3864
|
+
manualUrl,
|
|
3865
|
+
automaticUrl
|
|
3866
|
+
});
|
|
3867
|
+
} catch (error) {
|
|
3868
|
+
sendControlResponseError(message, errorMessage(error));
|
|
3869
|
+
}
|
|
3870
|
+
} else if (message.request.subtype === "claude_oauth_callback" || message.request.subtype === "claude_oauth_wait_for_completion") {
|
|
3871
|
+
if (!claudeOAuth) {
|
|
3872
|
+
sendControlResponseError(message, "No active claude_authenticate flow");
|
|
3873
|
+
} else {
|
|
3874
|
+
if (message.request.subtype === "claude_oauth_callback") {
|
|
3875
|
+
claudeOAuth.service.handleManualAuthCodeInput({
|
|
3876
|
+
authorizationCode: message.request.authorizationCode,
|
|
3877
|
+
state: message.request.state
|
|
3878
|
+
});
|
|
3879
|
+
}
|
|
3880
|
+
const { flow } = claudeOAuth;
|
|
3881
|
+
flow.then(() => {
|
|
3882
|
+
const accountInfo = getAccountInformation();
|
|
3883
|
+
sendControlResponseSuccess(message, {
|
|
3884
|
+
account: {
|
|
3885
|
+
email: accountInfo?.email,
|
|
3886
|
+
organization: accountInfo?.organization,
|
|
3887
|
+
subscriptionType: accountInfo?.subscription,
|
|
3888
|
+
tokenSource: accountInfo?.tokenSource,
|
|
3889
|
+
apiKeySource: accountInfo?.apiKeySource,
|
|
3890
|
+
apiProvider: getAPIProvider()
|
|
3891
|
+
}
|
|
3892
|
+
});
|
|
3893
|
+
}, (error) => sendControlResponseError(message, errorMessage(error)));
|
|
3894
|
+
}
|
|
3895
|
+
} else if (message.request.subtype === "mcp_clear_auth") {
|
|
3896
|
+
const { serverName } = message.request;
|
|
3897
|
+
const currentAppState = getAppState();
|
|
3898
|
+
const config = getMcpConfigByName(serverName) ?? mcpClients.find((c) => c.name === serverName)?.config ?? currentAppState.mcp.clients.find((c) => c.name === serverName)?.config ?? null;
|
|
3899
|
+
if (!config) {
|
|
3900
|
+
sendControlResponseError(message, `Server not found: ${serverName}`);
|
|
3901
|
+
} else if (config.type !== "sse" && config.type !== "http") {
|
|
3902
|
+
sendControlResponseError(message, `Cannot clear auth for server type "${config.type}"`);
|
|
3903
|
+
} else {
|
|
3904
|
+
await revokeServerTokens(serverName, config);
|
|
3905
|
+
const result = await reconnectMcpServerImpl(serverName, config);
|
|
3906
|
+
const prefix = getMcpPrefix(serverName);
|
|
3907
|
+
setAppState((prev) => ({
|
|
3908
|
+
...prev,
|
|
3909
|
+
mcp: {
|
|
3910
|
+
...prev.mcp,
|
|
3911
|
+
clients: prev.mcp.clients.map((c) => c.name === serverName ? result.client : c),
|
|
3912
|
+
tools: [
|
|
3913
|
+
...reject_default(prev.mcp.tools, (t) => t.name?.startsWith(prefix)),
|
|
3914
|
+
...result.tools
|
|
3915
|
+
],
|
|
3916
|
+
commands: [
|
|
3917
|
+
...reject_default(prev.mcp.commands, (c) => commandBelongsToServer(c, serverName)),
|
|
3918
|
+
...result.commands
|
|
3919
|
+
],
|
|
3920
|
+
resources: result.resources && result.resources.length > 0 ? {
|
|
3921
|
+
...prev.mcp.resources,
|
|
3922
|
+
[serverName]: result.resources
|
|
3923
|
+
} : omit_default(prev.mcp.resources, serverName)
|
|
3924
|
+
}
|
|
3925
|
+
}));
|
|
3926
|
+
sendControlResponseSuccess(message, {});
|
|
3927
|
+
}
|
|
3928
|
+
} else if (message.request.subtype === "apply_flag_settings") {
|
|
3929
|
+
const prevModel = getMainLoopModel();
|
|
3930
|
+
const existing = getFlagSettingsInline() ?? {};
|
|
3931
|
+
const incoming = message.request.settings;
|
|
3932
|
+
const merged = { ...existing, ...incoming };
|
|
3933
|
+
for (const key of Object.keys(merged)) {
|
|
3934
|
+
if (merged[key] === null) {
|
|
3935
|
+
delete merged[key];
|
|
3936
|
+
}
|
|
3937
|
+
}
|
|
3938
|
+
setFlagSettingsInline(merged);
|
|
3939
|
+
settingsChangeDetector.notifyChange("flagSettings");
|
|
3940
|
+
if ("model" in incoming) {
|
|
3941
|
+
if (incoming.model != null) {
|
|
3942
|
+
setMainLoopModelOverride(String(incoming.model));
|
|
3943
|
+
} else {
|
|
3944
|
+
setMainLoopModelOverride(undefined);
|
|
3945
|
+
}
|
|
3946
|
+
}
|
|
3947
|
+
const newModel = getMainLoopModel();
|
|
3948
|
+
if (newModel !== prevModel) {
|
|
3949
|
+
activeUserSpecifiedModel = newModel;
|
|
3950
|
+
const modelArg = incoming.model ? String(incoming.model) : "default";
|
|
3951
|
+
notifySessionMetadataChanged({ model: newModel });
|
|
3952
|
+
injectModelSwitchBreadcrumbs(modelArg, newModel);
|
|
3953
|
+
}
|
|
3954
|
+
sendControlResponseSuccess(message);
|
|
3955
|
+
} else if (message.request.subtype === "get_settings") {
|
|
3956
|
+
const currentAppState = getAppState();
|
|
3957
|
+
const model = getMainLoopModel();
|
|
3958
|
+
const effort = modelSupportsEffort(model) ? resolveAppliedEffort(model, currentAppState.effortValue) : undefined;
|
|
3959
|
+
sendControlResponseSuccess(message, {
|
|
3960
|
+
...getSettingsWithSources(),
|
|
3961
|
+
applied: {
|
|
3962
|
+
model,
|
|
3963
|
+
effort: typeof effort === "string" ? effort : null
|
|
3964
|
+
}
|
|
3965
|
+
});
|
|
3966
|
+
} else if (message.request.subtype === "stop_task") {
|
|
3967
|
+
const { task_id: taskId } = message.request;
|
|
3968
|
+
try {
|
|
3969
|
+
await stopTask(taskId, {
|
|
3970
|
+
getAppState,
|
|
3971
|
+
setAppState
|
|
3972
|
+
});
|
|
3973
|
+
sendControlResponseSuccess(message, {});
|
|
3974
|
+
} catch (error) {
|
|
3975
|
+
sendControlResponseError(message, errorMessage(error));
|
|
3976
|
+
}
|
|
3977
|
+
} else if (message.request.subtype === "generate_session_title") {
|
|
3978
|
+
const { description, persist } = message.request;
|
|
3979
|
+
const titleSignal = (abortController && !abortController.signal.aborted ? abortController : createAbortController()).signal;
|
|
3980
|
+
(async () => {
|
|
3981
|
+
try {
|
|
3982
|
+
const title = await generateSessionTitle(description, titleSignal);
|
|
3983
|
+
if (title && persist) {
|
|
3984
|
+
try {
|
|
3985
|
+
saveAiGeneratedTitle(getSessionId(), title);
|
|
3986
|
+
} catch (e) {
|
|
3987
|
+
logError(e);
|
|
3988
|
+
}
|
|
3989
|
+
}
|
|
3990
|
+
sendControlResponseSuccess(message, { title });
|
|
3991
|
+
} catch (e) {
|
|
3992
|
+
sendControlResponseError(message, errorMessage(e));
|
|
3993
|
+
}
|
|
3994
|
+
})();
|
|
3995
|
+
} else if (message.request.subtype === "side_question") {
|
|
3996
|
+
const { question } = message.request;
|
|
3997
|
+
(async () => {
|
|
3998
|
+
try {
|
|
3999
|
+
const saved = getLastCacheSafeParams();
|
|
4000
|
+
const cacheSafeParams = saved ? {
|
|
4001
|
+
...saved,
|
|
4002
|
+
toolUseContext: {
|
|
4003
|
+
...saved.toolUseContext,
|
|
4004
|
+
abortController: createAbortController()
|
|
4005
|
+
}
|
|
4006
|
+
} : await buildSideQuestionFallbackParams({
|
|
4007
|
+
tools: buildAllTools(getAppState()),
|
|
4008
|
+
commands: currentCommands,
|
|
4009
|
+
mcpClients: [
|
|
4010
|
+
...getAppState().mcp.clients,
|
|
4011
|
+
...sdkClients,
|
|
4012
|
+
...dynamicMcpState.clients
|
|
4013
|
+
],
|
|
4014
|
+
messages: mutableMessages,
|
|
4015
|
+
readFileState,
|
|
4016
|
+
getAppState,
|
|
4017
|
+
setAppState,
|
|
4018
|
+
customSystemPrompt: options.systemPrompt,
|
|
4019
|
+
appendSystemPrompt: options.appendSystemPrompt,
|
|
4020
|
+
thinkingConfig: options.thinkingConfig,
|
|
4021
|
+
agents: currentAgents
|
|
4022
|
+
});
|
|
4023
|
+
const result = await runSideQuestion({
|
|
4024
|
+
question,
|
|
4025
|
+
cacheSafeParams
|
|
4026
|
+
});
|
|
4027
|
+
sendControlResponseSuccess(message, { response: result.response });
|
|
4028
|
+
} catch (e) {
|
|
4029
|
+
sendControlResponseError(message, errorMessage(e));
|
|
4030
|
+
}
|
|
4031
|
+
})();
|
|
4032
|
+
} else if (false) {} else if (message.request.subtype === "remote_control") {
|
|
4033
|
+
if (message.request.enabled) {
|
|
4034
|
+
if (bridgeHandle) {
|
|
4035
|
+
sendControlResponseSuccess(message, {
|
|
4036
|
+
session_url: getRemoteSessionUrl(bridgeHandle.bridgeSessionId, bridgeHandle.sessionIngressUrl),
|
|
4037
|
+
connect_url: buildBridgeConnectUrl(bridgeHandle.environmentId, bridgeHandle.sessionIngressUrl),
|
|
4038
|
+
environment_id: bridgeHandle.environmentId
|
|
4039
|
+
});
|
|
4040
|
+
} else {
|
|
4041
|
+
let bridgeFailureDetail;
|
|
4042
|
+
try {
|
|
4043
|
+
const { initReplBridge } = await import("./chunk-zke1sp3x.js");
|
|
4044
|
+
const handle = await initReplBridge({
|
|
4045
|
+
onInboundMessage(msg) {
|
|
4046
|
+
const fields = extractInboundMessageFields(msg);
|
|
4047
|
+
if (!fields)
|
|
4048
|
+
return;
|
|
4049
|
+
const { content, uuid } = fields;
|
|
4050
|
+
enqueue({
|
|
4051
|
+
value: content,
|
|
4052
|
+
mode: "prompt",
|
|
4053
|
+
uuid,
|
|
4054
|
+
skipSlashCommands: true
|
|
4055
|
+
});
|
|
4056
|
+
run();
|
|
4057
|
+
},
|
|
4058
|
+
onPermissionResponse(response) {
|
|
4059
|
+
structuredIO.injectControlResponse(response);
|
|
4060
|
+
},
|
|
4061
|
+
onInterrupt() {
|
|
4062
|
+
abortController?.abort();
|
|
4063
|
+
},
|
|
4064
|
+
onSetModel(model) {
|
|
4065
|
+
const resolved = model === "default" ? getDefaultMainLoopModel() : model;
|
|
4066
|
+
activeUserSpecifiedModel = resolved;
|
|
4067
|
+
setMainLoopModelOverride(resolved);
|
|
4068
|
+
},
|
|
4069
|
+
onSetMaxThinkingTokens(maxTokens) {
|
|
4070
|
+
if (maxTokens === null) {
|
|
4071
|
+
options.thinkingConfig = undefined;
|
|
4072
|
+
} else if (maxTokens === 0) {
|
|
4073
|
+
options.thinkingConfig = { type: "disabled" };
|
|
4074
|
+
} else {
|
|
4075
|
+
options.thinkingConfig = {
|
|
4076
|
+
type: "enabled",
|
|
4077
|
+
budgetTokens: maxTokens
|
|
4078
|
+
};
|
|
4079
|
+
}
|
|
4080
|
+
},
|
|
4081
|
+
onStateChange(state, detail) {
|
|
4082
|
+
if (state === "failed") {
|
|
4083
|
+
bridgeFailureDetail = detail;
|
|
4084
|
+
}
|
|
4085
|
+
logForDebugging(`[bridge:sdk] State change: ${state}${detail ? ` \u2014 ${detail}` : ""}`);
|
|
4086
|
+
output.enqueue({
|
|
4087
|
+
type: "system",
|
|
4088
|
+
subtype: "bridge_state",
|
|
4089
|
+
state,
|
|
4090
|
+
detail,
|
|
4091
|
+
uuid: randomUUID4(),
|
|
4092
|
+
session_id: getSessionId()
|
|
4093
|
+
});
|
|
4094
|
+
},
|
|
4095
|
+
initialMessages: mutableMessages.length > 0 ? mutableMessages : undefined
|
|
4096
|
+
});
|
|
4097
|
+
if (!handle) {
|
|
4098
|
+
sendControlResponseError(message, bridgeFailureDetail ?? "Remote Control initialization failed");
|
|
4099
|
+
} else {
|
|
4100
|
+
bridgeHandle = handle;
|
|
4101
|
+
bridgeLastForwardedIndex = mutableMessages.length;
|
|
4102
|
+
structuredIO.setOnControlRequestSent((request) => {
|
|
4103
|
+
handle.sendControlRequest(request);
|
|
4104
|
+
});
|
|
4105
|
+
structuredIO.setOnControlRequestResolved((requestId) => {
|
|
4106
|
+
handle.sendControlCancelRequest(requestId);
|
|
4107
|
+
});
|
|
4108
|
+
sendControlResponseSuccess(message, {
|
|
4109
|
+
session_url: getRemoteSessionUrl(handle.bridgeSessionId, handle.sessionIngressUrl),
|
|
4110
|
+
connect_url: buildBridgeConnectUrl(handle.environmentId, handle.sessionIngressUrl),
|
|
4111
|
+
environment_id: handle.environmentId
|
|
4112
|
+
});
|
|
4113
|
+
}
|
|
4114
|
+
} catch (err) {
|
|
4115
|
+
sendControlResponseError(message, errorMessage(err));
|
|
4116
|
+
}
|
|
4117
|
+
}
|
|
4118
|
+
} else {
|
|
4119
|
+
if (bridgeHandle) {
|
|
4120
|
+
structuredIO.setOnControlRequestSent(undefined);
|
|
4121
|
+
structuredIO.setOnControlRequestResolved(undefined);
|
|
4122
|
+
await bridgeHandle.teardown();
|
|
4123
|
+
bridgeHandle = null;
|
|
4124
|
+
}
|
|
4125
|
+
sendControlResponseSuccess(message);
|
|
4126
|
+
}
|
|
4127
|
+
} else {
|
|
4128
|
+
sendControlResponseError(message, `Unsupported control request subtype: ${message.request.subtype}`);
|
|
4129
|
+
}
|
|
4130
|
+
continue;
|
|
4131
|
+
} else if (message.type === "control_response") {
|
|
4132
|
+
if (options.replayUserMessages) {
|
|
4133
|
+
output.enqueue(message);
|
|
4134
|
+
}
|
|
4135
|
+
continue;
|
|
4136
|
+
} else if (message.type === "keep_alive") {
|
|
4137
|
+
continue;
|
|
4138
|
+
} else if (message.type === "update_environment_variables") {
|
|
4139
|
+
continue;
|
|
4140
|
+
} else if (message.type === "assistant" || message.type === "system") {
|
|
4141
|
+
const internalMsgs = toInternalMessages([message]);
|
|
4142
|
+
mutableMessages.push(...internalMsgs);
|
|
4143
|
+
if (message.type === "assistant" && options.replayUserMessages) {
|
|
4144
|
+
output.enqueue(message);
|
|
4145
|
+
}
|
|
4146
|
+
continue;
|
|
4147
|
+
}
|
|
4148
|
+
if (message.type !== "user") {
|
|
4149
|
+
continue;
|
|
4150
|
+
}
|
|
4151
|
+
initialized = true;
|
|
4152
|
+
if (message.uuid) {
|
|
4153
|
+
const sessionId = getSessionId();
|
|
4154
|
+
const existsInSession = await doesMessageExistInSession(sessionId, message.uuid);
|
|
4155
|
+
if (existsInSession || receivedMessageUuids.has(message.uuid)) {
|
|
4156
|
+
logForDebugging(`Skipping duplicate user message: ${message.uuid}`);
|
|
4157
|
+
if (options.replayUserMessages) {
|
|
4158
|
+
logForDebugging(`Sending acknowledgment for duplicate user message: ${message.uuid}`);
|
|
4159
|
+
output.enqueue({
|
|
4160
|
+
type: "user",
|
|
4161
|
+
content: message.message?.content ?? "",
|
|
4162
|
+
message: message.message,
|
|
4163
|
+
session_id: sessionId,
|
|
4164
|
+
parent_tool_use_id: null,
|
|
4165
|
+
uuid: message.uuid,
|
|
4166
|
+
timestamp: message.timestamp,
|
|
4167
|
+
isReplay: true
|
|
4168
|
+
});
|
|
4169
|
+
}
|
|
4170
|
+
if (existsInSession) {
|
|
4171
|
+
notifyCommandLifecycle(message.uuid, "completed");
|
|
4172
|
+
}
|
|
4173
|
+
continue;
|
|
4174
|
+
}
|
|
4175
|
+
trackReceivedMessageUuid(message.uuid);
|
|
4176
|
+
}
|
|
4177
|
+
enqueue({
|
|
4178
|
+
mode: "prompt",
|
|
4179
|
+
value: await resolveAndPrepend(message, message.message.content),
|
|
4180
|
+
uuid: message.uuid,
|
|
4181
|
+
priority: message.priority
|
|
4182
|
+
});
|
|
4183
|
+
if (false) {}
|
|
4184
|
+
run();
|
|
4185
|
+
}
|
|
4186
|
+
inputClosed = true;
|
|
4187
|
+
cronScheduler?.stop();
|
|
4188
|
+
if (!running) {
|
|
4189
|
+
if (suggestionState.inflightPromise) {
|
|
4190
|
+
await Promise.race([suggestionState.inflightPromise, sleep(5000)]);
|
|
4191
|
+
}
|
|
4192
|
+
suggestionState.abortController?.abort();
|
|
4193
|
+
suggestionState.abortController = null;
|
|
4194
|
+
await finalizePendingAsyncHooks();
|
|
4195
|
+
unsubscribeSkillChanges();
|
|
4196
|
+
unsubscribeAuthStatus?.();
|
|
4197
|
+
statusListeners.delete(rateLimitListener);
|
|
4198
|
+
output.done();
|
|
4199
|
+
}
|
|
4200
|
+
})();
|
|
4201
|
+
return output;
|
|
4202
|
+
}
|
|
4203
|
+
function createCanUseToolWithPermissionPrompt(permissionPromptTool) {
|
|
4204
|
+
const canUseTool = async (tool, input, toolUseContext, assistantMessage, toolUseId, forceDecision) => {
|
|
4205
|
+
const mainPermissionResult = forceDecision ?? await hasPermissionsToUseTool(tool, input, toolUseContext, assistantMessage, toolUseId);
|
|
4206
|
+
if (mainPermissionResult.behavior === "allow" || mainPermissionResult.behavior === "deny") {
|
|
4207
|
+
return mainPermissionResult;
|
|
4208
|
+
}
|
|
4209
|
+
const { signal: combinedSignal, cleanup: cleanupAbortListener } = createCombinedAbortSignal(toolUseContext.abortController.signal);
|
|
4210
|
+
if (combinedSignal.aborted) {
|
|
4211
|
+
cleanupAbortListener();
|
|
4212
|
+
return {
|
|
4213
|
+
behavior: "deny",
|
|
4214
|
+
message: "Permission prompt was aborted.",
|
|
4215
|
+
decisionReason: {
|
|
4216
|
+
type: "permissionPromptTool",
|
|
4217
|
+
permissionPromptToolName: tool.name,
|
|
4218
|
+
toolResult: undefined
|
|
4219
|
+
}
|
|
4220
|
+
};
|
|
4221
|
+
}
|
|
4222
|
+
const abortPromise = new Promise((resolve) => {
|
|
4223
|
+
combinedSignal.addEventListener("abort", () => resolve("aborted"), {
|
|
4224
|
+
once: true
|
|
4225
|
+
});
|
|
4226
|
+
});
|
|
4227
|
+
const toolCallPromise = permissionPromptTool.call({
|
|
4228
|
+
tool_name: tool.name,
|
|
4229
|
+
input,
|
|
4230
|
+
tool_use_id: toolUseId
|
|
4231
|
+
}, toolUseContext, canUseTool, assistantMessage);
|
|
4232
|
+
const raceResult = await Promise.race([toolCallPromise, abortPromise]);
|
|
4233
|
+
cleanupAbortListener();
|
|
4234
|
+
if (raceResult === "aborted" || combinedSignal.aborted) {
|
|
4235
|
+
return {
|
|
4236
|
+
behavior: "deny",
|
|
4237
|
+
message: "Permission prompt was aborted.",
|
|
4238
|
+
decisionReason: {
|
|
4239
|
+
type: "permissionPromptTool",
|
|
4240
|
+
permissionPromptToolName: tool.name,
|
|
4241
|
+
toolResult: undefined
|
|
4242
|
+
}
|
|
4243
|
+
};
|
|
4244
|
+
}
|
|
4245
|
+
const result = raceResult;
|
|
4246
|
+
const permissionToolResultBlockParam = permissionPromptTool.mapToolResultToToolResultBlockParam(result.data, "1");
|
|
4247
|
+
if (!permissionToolResultBlockParam.content || !Array.isArray(permissionToolResultBlockParam.content) || !permissionToolResultBlockParam.content[0] || permissionToolResultBlockParam.content[0].type !== "text" || typeof permissionToolResultBlockParam.content[0].text !== "string") {
|
|
4248
|
+
throw new Error('Permission prompt tool returned an invalid result. Expected a single text block param with type="text" and a string text value.');
|
|
4249
|
+
}
|
|
4250
|
+
return permissionPromptToolResultToPermissionDecision(outputSchema().parse(safeParseJSON(permissionToolResultBlockParam.content[0].text)), permissionPromptTool, input, toolUseContext);
|
|
4251
|
+
};
|
|
4252
|
+
return canUseTool;
|
|
4253
|
+
}
|
|
4254
|
+
function getCanUseToolFn(permissionPromptToolName, structuredIO, getMcpTools, onPermissionPrompt) {
|
|
4255
|
+
if (permissionPromptToolName === "stdio") {
|
|
4256
|
+
return structuredIO.createCanUseTool(onPermissionPrompt);
|
|
4257
|
+
}
|
|
4258
|
+
if (!permissionPromptToolName) {
|
|
4259
|
+
return async (tool, input, toolUseContext, assistantMessage, toolUseId, forceDecision) => forceDecision ?? await hasPermissionsToUseTool(tool, input, toolUseContext, assistantMessage, toolUseId);
|
|
4260
|
+
}
|
|
4261
|
+
let resolved = null;
|
|
4262
|
+
return async (tool, input, toolUseContext, assistantMessage, toolUseId, forceDecision) => {
|
|
4263
|
+
if (!resolved) {
|
|
4264
|
+
const mcpTools = getMcpTools();
|
|
4265
|
+
const permissionPromptTool = mcpTools.find((t) => toolMatchesName(t, permissionPromptToolName));
|
|
4266
|
+
if (!permissionPromptTool) {
|
|
4267
|
+
const error = `Error: MCP tool ${permissionPromptToolName} (passed via --permission-prompt-tool) not found. Available MCP tools: ${mcpTools.map((t) => t.name).join(", ") || "none"}`;
|
|
4268
|
+
process.stderr.write(`${error}
|
|
4269
|
+
`);
|
|
4270
|
+
gracefulShutdownSync(1);
|
|
4271
|
+
throw new Error(error);
|
|
4272
|
+
}
|
|
4273
|
+
if (!permissionPromptTool.inputJSONSchema) {
|
|
4274
|
+
const error = `Error: tool ${permissionPromptToolName} (passed via --permission-prompt-tool) must be an MCP tool`;
|
|
4275
|
+
process.stderr.write(`${error}
|
|
4276
|
+
`);
|
|
4277
|
+
gracefulShutdownSync(1);
|
|
4278
|
+
throw new Error(error);
|
|
4279
|
+
}
|
|
4280
|
+
resolved = createCanUseToolWithPermissionPrompt(permissionPromptTool);
|
|
4281
|
+
}
|
|
4282
|
+
return resolved(tool, input, toolUseContext, assistantMessage, toolUseId, forceDecision);
|
|
4283
|
+
};
|
|
4284
|
+
}
|
|
4285
|
+
async function handleInitializeRequest(request, requestId, initialized, output, commands, modelInfos, structuredIO, enableAuthStatus, options, agents, getAppState) {
|
|
4286
|
+
if (initialized) {
|
|
4287
|
+
output.enqueue({
|
|
4288
|
+
type: "control_response",
|
|
4289
|
+
response: {
|
|
4290
|
+
subtype: "error",
|
|
4291
|
+
error: "Already initialized",
|
|
4292
|
+
request_id: requestId,
|
|
4293
|
+
pending_permission_requests: structuredIO.getPendingPermissionRequests()
|
|
4294
|
+
}
|
|
4295
|
+
});
|
|
4296
|
+
return;
|
|
4297
|
+
}
|
|
4298
|
+
if (request.systemPrompt !== undefined) {
|
|
4299
|
+
options.systemPrompt = request.systemPrompt;
|
|
4300
|
+
}
|
|
4301
|
+
if (request.appendSystemPrompt !== undefined) {
|
|
4302
|
+
options.appendSystemPrompt = request.appendSystemPrompt;
|
|
4303
|
+
}
|
|
4304
|
+
if (request.promptSuggestions !== undefined) {
|
|
4305
|
+
options.promptSuggestions = request.promptSuggestions;
|
|
4306
|
+
}
|
|
4307
|
+
if (request.agents) {
|
|
4308
|
+
const stdinAgents = parseAgentsFromJson(request.agents, "flagSettings");
|
|
4309
|
+
agents.push(...stdinAgents);
|
|
4310
|
+
}
|
|
4311
|
+
if (options.agent) {
|
|
4312
|
+
const alreadyResolved = getMainThreadAgentType() === options.agent;
|
|
4313
|
+
const mainThreadAgent = agents.find((a) => a.agentType === options.agent);
|
|
4314
|
+
if (mainThreadAgent && !alreadyResolved) {
|
|
4315
|
+
setMainThreadAgentType(mainThreadAgent.agentType);
|
|
4316
|
+
if (!options.systemPrompt && !isBuiltInAgent(mainThreadAgent)) {
|
|
4317
|
+
const agentSystemPrompt = mainThreadAgent.getSystemPrompt();
|
|
4318
|
+
if (agentSystemPrompt) {
|
|
4319
|
+
options.systemPrompt = agentSystemPrompt;
|
|
4320
|
+
}
|
|
4321
|
+
}
|
|
4322
|
+
if (!options.userSpecifiedModel && mainThreadAgent.model && mainThreadAgent.model !== "inherit") {
|
|
4323
|
+
const agentModel = parseUserSpecifiedModel(mainThreadAgent.model);
|
|
4324
|
+
setMainLoopModelOverride(agentModel);
|
|
4325
|
+
}
|
|
4326
|
+
if (mainThreadAgent.initialPrompt) {
|
|
4327
|
+
structuredIO.prependUserMessage(mainThreadAgent.initialPrompt);
|
|
4328
|
+
}
|
|
4329
|
+
} else if (mainThreadAgent?.initialPrompt) {
|
|
4330
|
+
structuredIO.prependUserMessage(mainThreadAgent.initialPrompt);
|
|
4331
|
+
}
|
|
4332
|
+
}
|
|
4333
|
+
const settings = getSettings_DEPRECATED();
|
|
4334
|
+
const outputStyle = settings?.outputStyle || DEFAULT_OUTPUT_STYLE_NAME;
|
|
4335
|
+
const availableOutputStyles = await getAllOutputStyles(getCwd());
|
|
4336
|
+
const accountInfo = getAccountInformation();
|
|
4337
|
+
if (request.hooks) {
|
|
4338
|
+
const hooks = {};
|
|
4339
|
+
for (const [event, matchers] of Object.entries(request.hooks)) {
|
|
4340
|
+
hooks[event] = matchers.map((matcher) => {
|
|
4341
|
+
const callbacks = matcher.hookCallbackIds.map((callbackId) => {
|
|
4342
|
+
return structuredIO.createHookCallback(callbackId, matcher.timeout);
|
|
4343
|
+
});
|
|
4344
|
+
return {
|
|
4345
|
+
matcher: matcher.matcher,
|
|
4346
|
+
hooks: callbacks
|
|
4347
|
+
};
|
|
4348
|
+
});
|
|
4349
|
+
}
|
|
4350
|
+
registerHookCallbacks(hooks);
|
|
4351
|
+
}
|
|
4352
|
+
if (request.jsonSchema) {
|
|
4353
|
+
setInitJsonSchema(request.jsonSchema);
|
|
4354
|
+
}
|
|
4355
|
+
const initResponse = {
|
|
4356
|
+
commands: commands.filter((cmd) => cmd.userInvocable !== false).map((cmd) => ({
|
|
4357
|
+
name: getCommandName(cmd),
|
|
4358
|
+
description: formatDescriptionWithSource(cmd),
|
|
4359
|
+
argumentHint: cmd.argumentHint || ""
|
|
4360
|
+
})),
|
|
4361
|
+
agents: agents.map((agent) => ({
|
|
4362
|
+
name: agent.agentType,
|
|
4363
|
+
description: agent.whenToUse,
|
|
4364
|
+
model: agent.model === "inherit" ? undefined : agent.model
|
|
4365
|
+
})),
|
|
4366
|
+
output_style: outputStyle,
|
|
4367
|
+
available_output_styles: Object.keys(availableOutputStyles),
|
|
4368
|
+
models: modelInfos,
|
|
4369
|
+
account: {
|
|
4370
|
+
email: accountInfo?.email,
|
|
4371
|
+
organization: accountInfo?.organization,
|
|
4372
|
+
subscriptionType: accountInfo?.subscription,
|
|
4373
|
+
tokenSource: accountInfo?.tokenSource,
|
|
4374
|
+
apiKeySource: accountInfo?.apiKeySource,
|
|
4375
|
+
apiProvider: getAPIProvider()
|
|
4376
|
+
},
|
|
4377
|
+
pid: process.pid
|
|
4378
|
+
};
|
|
4379
|
+
if (isFastModeEnabled() && isFastModeAvailable()) {
|
|
4380
|
+
const appState = getAppState();
|
|
4381
|
+
initResponse.fast_mode_state = getFastModeState(options.userSpecifiedModel ?? null, appState.fastMode);
|
|
4382
|
+
}
|
|
4383
|
+
output.enqueue({
|
|
4384
|
+
type: "control_response",
|
|
4385
|
+
response: {
|
|
4386
|
+
subtype: "success",
|
|
4387
|
+
request_id: requestId,
|
|
4388
|
+
response: initResponse
|
|
4389
|
+
}
|
|
4390
|
+
});
|
|
4391
|
+
if (enableAuthStatus) {
|
|
4392
|
+
const authStatusManager = AwsAuthStatusManager.getInstance();
|
|
4393
|
+
const status = authStatusManager.getStatus();
|
|
4394
|
+
if (status) {
|
|
4395
|
+
output.enqueue({
|
|
4396
|
+
type: "auth_status",
|
|
4397
|
+
isAuthenticating: status.isAuthenticating,
|
|
4398
|
+
output: status.output,
|
|
4399
|
+
error: status.error,
|
|
4400
|
+
uuid: randomUUID4(),
|
|
4401
|
+
session_id: getSessionId()
|
|
4402
|
+
});
|
|
4403
|
+
}
|
|
4404
|
+
}
|
|
4405
|
+
}
|
|
4406
|
+
async function handleRewindFiles(userMessageId, appState, setAppState, dryRun) {
|
|
4407
|
+
if (!fileHistoryEnabled()) {
|
|
4408
|
+
return { canRewind: false, error: "File rewinding is not enabled.", filesChanged: [] };
|
|
4409
|
+
}
|
|
4410
|
+
if (!fileHistoryCanRestore(appState.fileHistory, userMessageId)) {
|
|
4411
|
+
return {
|
|
4412
|
+
canRewind: false,
|
|
4413
|
+
error: "No file checkpoint found for this message.",
|
|
4414
|
+
filesChanged: []
|
|
4415
|
+
};
|
|
4416
|
+
}
|
|
4417
|
+
if (dryRun) {
|
|
4418
|
+
const diffStats = await fileHistoryGetDiffStats(appState.fileHistory, userMessageId);
|
|
4419
|
+
return {
|
|
4420
|
+
canRewind: true,
|
|
4421
|
+
filesChanged: diffStats?.filesChanged,
|
|
4422
|
+
insertions: diffStats?.insertions,
|
|
4423
|
+
deletions: diffStats?.deletions
|
|
4424
|
+
};
|
|
4425
|
+
}
|
|
4426
|
+
try {
|
|
4427
|
+
await fileHistoryRewind((updater) => setAppState((prev) => ({
|
|
4428
|
+
...prev,
|
|
4429
|
+
fileHistory: updater(prev.fileHistory)
|
|
4430
|
+
})), userMessageId);
|
|
4431
|
+
} catch (error) {
|
|
4432
|
+
return {
|
|
4433
|
+
canRewind: false,
|
|
4434
|
+
error: `Failed to rewind: ${errorMessage(error)}`,
|
|
4435
|
+
filesChanged: []
|
|
4436
|
+
};
|
|
4437
|
+
}
|
|
4438
|
+
return { canRewind: true, filesChanged: [] };
|
|
4439
|
+
}
|
|
4440
|
+
function handleSetPermissionMode(request, requestId, toolPermissionContext, output) {
|
|
4441
|
+
if (request.mode === "bypassPermissions") {
|
|
4442
|
+
if (isBypassPermissionsModeDisabled()) {
|
|
4443
|
+
output.enqueue({
|
|
4444
|
+
type: "control_response",
|
|
4445
|
+
response: {
|
|
4446
|
+
subtype: "error",
|
|
4447
|
+
request_id: requestId,
|
|
4448
|
+
error: "Cannot set permission mode to bypassPermissions because it is disabled by settings or configuration"
|
|
4449
|
+
}
|
|
4450
|
+
});
|
|
4451
|
+
return toolPermissionContext;
|
|
4452
|
+
}
|
|
4453
|
+
if (!toolPermissionContext.isBypassPermissionsModeAvailable) {
|
|
4454
|
+
output.enqueue({
|
|
4455
|
+
type: "control_response",
|
|
4456
|
+
response: {
|
|
4457
|
+
subtype: "error",
|
|
4458
|
+
request_id: requestId,
|
|
4459
|
+
error: "Cannot set permission mode to bypassPermissions because the session was not launched with --dangerously-skip-permissions"
|
|
4460
|
+
}
|
|
4461
|
+
});
|
|
4462
|
+
return toolPermissionContext;
|
|
4463
|
+
}
|
|
4464
|
+
}
|
|
4465
|
+
if (false) {}
|
|
4466
|
+
output.enqueue({
|
|
4467
|
+
type: "control_response",
|
|
4468
|
+
response: {
|
|
4469
|
+
subtype: "success",
|
|
4470
|
+
request_id: requestId,
|
|
4471
|
+
response: {
|
|
4472
|
+
mode: request.mode
|
|
4473
|
+
}
|
|
4474
|
+
}
|
|
4475
|
+
});
|
|
4476
|
+
return {
|
|
4477
|
+
...transitionPermissionMode(toolPermissionContext.mode, request.mode, toolPermissionContext),
|
|
4478
|
+
mode: request.mode
|
|
4479
|
+
};
|
|
4480
|
+
}
|
|
4481
|
+
function handleChannelEnable(requestId, serverName, connectionPool, output) {
|
|
4482
|
+
const respondError = (error) => output.enqueue({
|
|
4483
|
+
type: "control_response",
|
|
4484
|
+
response: { subtype: "error", request_id: requestId, error }
|
|
4485
|
+
});
|
|
4486
|
+
if (true) {
|
|
4487
|
+
return respondError("channels feature not available in this build");
|
|
4488
|
+
}
|
|
4489
|
+
const connection = connectionPool.find((c) => c.name === serverName && c.type === "connected");
|
|
4490
|
+
if (!connection || connection.type !== "connected") {
|
|
4491
|
+
return respondError(`server ${serverName} is not connected`);
|
|
4492
|
+
}
|
|
4493
|
+
const pluginSource = connection.config.pluginSource;
|
|
4494
|
+
const parsed = pluginSource ? parsePluginIdentifier(pluginSource) : undefined;
|
|
4495
|
+
if (!parsed?.marketplace) {
|
|
4496
|
+
return respondError(`server ${serverName} is not plugin-sourced; channel_enable requires a marketplace plugin`);
|
|
4497
|
+
}
|
|
4498
|
+
const entry = {
|
|
4499
|
+
kind: "plugin",
|
|
4500
|
+
name: parsed.name,
|
|
4501
|
+
marketplace: parsed.marketplace
|
|
4502
|
+
};
|
|
4503
|
+
const prior = getAllowedChannels();
|
|
4504
|
+
const already = prior.some((e) => e.kind === "plugin" && e.name === entry.name && e.marketplace === entry.marketplace);
|
|
4505
|
+
if (!already)
|
|
4506
|
+
setAllowedChannels([...prior, entry]);
|
|
4507
|
+
const gate = gateChannelServer(serverName, connection.capabilities, pluginSource);
|
|
4508
|
+
if (gate.action === "skip") {
|
|
4509
|
+
if (!already)
|
|
4510
|
+
setAllowedChannels(prior);
|
|
4511
|
+
return respondError(gate.reason);
|
|
4512
|
+
}
|
|
4513
|
+
const pluginId = `${entry.name}@${entry.marketplace}`;
|
|
4514
|
+
logMCPDebug(serverName, "Channel notifications registered");
|
|
4515
|
+
logEvent("tengu_mcp_channel_enable", { plugin: pluginId });
|
|
4516
|
+
connection.client.setNotificationHandler(ChannelMessageNotificationSchema(), async (notification) => {
|
|
4517
|
+
const { content, meta } = notification.params;
|
|
4518
|
+
logMCPDebug(serverName, `notifications/claude/channel: ${content.slice(0, 80)}`);
|
|
4519
|
+
logEvent("tengu_mcp_channel_message", {
|
|
4520
|
+
content_length: content.length,
|
|
4521
|
+
meta_key_count: Object.keys(meta ?? {}).length,
|
|
4522
|
+
entry_kind: "plugin",
|
|
4523
|
+
is_dev: false,
|
|
4524
|
+
plugin: pluginId
|
|
4525
|
+
});
|
|
4526
|
+
enqueue({
|
|
4527
|
+
mode: "prompt",
|
|
4528
|
+
value: wrapChannelMessage(serverName, content, meta),
|
|
4529
|
+
priority: "next",
|
|
4530
|
+
isMeta: true,
|
|
4531
|
+
origin: { kind: "channel", server: serverName },
|
|
4532
|
+
skipSlashCommands: true
|
|
4533
|
+
});
|
|
4534
|
+
});
|
|
4535
|
+
output.enqueue({
|
|
4536
|
+
type: "control_response",
|
|
4537
|
+
response: {
|
|
4538
|
+
subtype: "success",
|
|
4539
|
+
request_id: requestId,
|
|
4540
|
+
response: undefined
|
|
4541
|
+
}
|
|
4542
|
+
});
|
|
4543
|
+
}
|
|
4544
|
+
function reregisterChannelHandlerAfterReconnect(connection) {
|
|
4545
|
+
if (true)
|
|
4546
|
+
return;
|
|
4547
|
+
if (connection.type !== "connected")
|
|
4548
|
+
return;
|
|
4549
|
+
const gate = gateChannelServer(connection.name, connection.capabilities, connection.config.pluginSource);
|
|
4550
|
+
if (gate.action !== "register")
|
|
4551
|
+
return;
|
|
4552
|
+
const entry = findChannelEntry(connection.name, getAllowedChannels());
|
|
4553
|
+
const pluginId = entry?.kind === "plugin" ? `${entry.name}@${entry.marketplace}` : undefined;
|
|
4554
|
+
logMCPDebug(connection.name, "Channel notifications re-registered after reconnect");
|
|
4555
|
+
connection.client.setNotificationHandler(ChannelMessageNotificationSchema(), async (notification) => {
|
|
4556
|
+
const { content, meta } = notification.params;
|
|
4557
|
+
logMCPDebug(connection.name, `notifications/claude/channel: ${content.slice(0, 80)}`);
|
|
4558
|
+
logEvent("tengu_mcp_channel_message", {
|
|
4559
|
+
content_length: content.length,
|
|
4560
|
+
meta_key_count: Object.keys(meta ?? {}).length,
|
|
4561
|
+
entry_kind: entry?.kind,
|
|
4562
|
+
is_dev: entry?.dev ?? false,
|
|
4563
|
+
plugin: pluginId
|
|
4564
|
+
});
|
|
4565
|
+
enqueue({
|
|
4566
|
+
mode: "prompt",
|
|
4567
|
+
value: wrapChannelMessage(connection.name, content, meta),
|
|
4568
|
+
priority: "next",
|
|
4569
|
+
isMeta: true,
|
|
4570
|
+
origin: { kind: "channel", server: connection.name },
|
|
4571
|
+
skipSlashCommands: true
|
|
4572
|
+
});
|
|
4573
|
+
});
|
|
4574
|
+
}
|
|
4575
|
+
function emitLoadError(message, outputFormat) {
|
|
4576
|
+
if (outputFormat === "stream-json") {
|
|
4577
|
+
const errorResult = {
|
|
4578
|
+
type: "result",
|
|
4579
|
+
subtype: "error_during_execution",
|
|
4580
|
+
duration_ms: 0,
|
|
4581
|
+
duration_api_ms: 0,
|
|
4582
|
+
is_error: true,
|
|
4583
|
+
num_turns: 0,
|
|
4584
|
+
stop_reason: null,
|
|
4585
|
+
session_id: getSessionId(),
|
|
4586
|
+
total_cost_usd: 0,
|
|
4587
|
+
usage: EMPTY_USAGE,
|
|
4588
|
+
modelUsage: {},
|
|
4589
|
+
permission_denials: [],
|
|
4590
|
+
uuid: randomUUID4(),
|
|
4591
|
+
errors: [message]
|
|
4592
|
+
};
|
|
4593
|
+
process.stdout.write(jsonStringify(errorResult) + `
|
|
4594
|
+
`);
|
|
4595
|
+
} else {
|
|
4596
|
+
process.stderr.write(message + `
|
|
4597
|
+
`);
|
|
4598
|
+
}
|
|
4599
|
+
}
|
|
4600
|
+
function removeInterruptedMessage(messages, interruptedUserMessage) {
|
|
4601
|
+
const idx = messages.findIndex((m) => m.uuid === interruptedUserMessage.uuid);
|
|
4602
|
+
if (idx !== -1) {
|
|
4603
|
+
messages.splice(idx, 2);
|
|
4604
|
+
}
|
|
4605
|
+
}
|
|
4606
|
+
async function loadInitialMessages(setAppState, options) {
|
|
4607
|
+
const persistSession = !isSessionPersistenceDisabled();
|
|
4608
|
+
if (options.continue) {
|
|
4609
|
+
try {
|
|
4610
|
+
logEvent("tengu_continue_print", {});
|
|
4611
|
+
const result = await loadConversationForResume(undefined, undefined);
|
|
4612
|
+
if (result) {
|
|
4613
|
+
if (false) {}
|
|
4614
|
+
if (!options.forkSession) {
|
|
4615
|
+
if (result.sessionId) {
|
|
4616
|
+
switchSession(asSessionId(result.sessionId), result.fullPath ? dirname(result.fullPath) : null);
|
|
4617
|
+
if (persistSession) {
|
|
4618
|
+
await resetSessionFilePointer();
|
|
4619
|
+
}
|
|
4620
|
+
}
|
|
4621
|
+
}
|
|
4622
|
+
restoreSessionStateFromLog(result, setAppState);
|
|
4623
|
+
restoreSessionMetadata(options.forkSession ? { ...result, worktreeSession: undefined } : result);
|
|
4624
|
+
if (false) {}
|
|
4625
|
+
return {
|
|
4626
|
+
messages: result.messages,
|
|
4627
|
+
turnInterruptionState: result.turnInterruptionState,
|
|
4628
|
+
agentSetting: result.agentSetting
|
|
4629
|
+
};
|
|
4630
|
+
}
|
|
4631
|
+
} catch (error) {
|
|
4632
|
+
logError(error);
|
|
4633
|
+
gracefulShutdownSync(1);
|
|
4634
|
+
return { messages: [] };
|
|
4635
|
+
}
|
|
4636
|
+
}
|
|
4637
|
+
if (options.teleport) {
|
|
4638
|
+
try {
|
|
4639
|
+
if (!isPolicyAllowed("allow_remote_sessions")) {
|
|
4640
|
+
throw new Error("Remote sessions are disabled by your organization's policy.");
|
|
4641
|
+
}
|
|
4642
|
+
logEvent("tengu_teleport_print", {});
|
|
4643
|
+
if (typeof options.teleport !== "string") {
|
|
4644
|
+
throw new Error("No session ID provided for teleport");
|
|
4645
|
+
}
|
|
4646
|
+
const {
|
|
4647
|
+
checkOutTeleportedSessionBranch,
|
|
4648
|
+
processMessagesForTeleportResume,
|
|
4649
|
+
teleportResumeCodeSession,
|
|
4650
|
+
validateGitState
|
|
4651
|
+
} = await import("./chunk-07rervty.js");
|
|
4652
|
+
await validateGitState();
|
|
4653
|
+
const teleportResult = await teleportResumeCodeSession(options.teleport);
|
|
4654
|
+
const { branchError } = await checkOutTeleportedSessionBranch(teleportResult.branch);
|
|
4655
|
+
return {
|
|
4656
|
+
messages: processMessagesForTeleportResume(teleportResult.log, branchError)
|
|
4657
|
+
};
|
|
4658
|
+
} catch (error) {
|
|
4659
|
+
logError(error);
|
|
4660
|
+
gracefulShutdownSync(1);
|
|
4661
|
+
return { messages: [] };
|
|
4662
|
+
}
|
|
4663
|
+
}
|
|
4664
|
+
if (options.resume) {
|
|
4665
|
+
try {
|
|
4666
|
+
logEvent("tengu_resume_print", {});
|
|
4667
|
+
const parsedSessionId = parseSessionIdentifier(typeof options.resume === "string" ? options.resume : "");
|
|
4668
|
+
if (!parsedSessionId) {
|
|
4669
|
+
let errorMessage2 = "Error: --resume requires a valid session ID when used with --print. Usage: claude -p --resume <session-id>";
|
|
4670
|
+
if (typeof options.resume === "string") {
|
|
4671
|
+
errorMessage2 += `. Session IDs must be in UUID format (e.g., 550e8400-e29b-41d4-a716-446655440000). Provided value "${options.resume}" is not a valid UUID`;
|
|
4672
|
+
}
|
|
4673
|
+
emitLoadError(errorMessage2, options.outputFormat);
|
|
4674
|
+
gracefulShutdownSync(1);
|
|
4675
|
+
return { messages: [] };
|
|
4676
|
+
}
|
|
4677
|
+
if (isEnvTruthy(process.env.CLAUDE_CODE_USE_CCR_V2)) {
|
|
4678
|
+
const [, metadata] = await Promise.all([
|
|
4679
|
+
hydrateFromCCRv2InternalEvents(parsedSessionId.sessionId),
|
|
4680
|
+
options.restoredWorkerState
|
|
4681
|
+
]);
|
|
4682
|
+
if (metadata) {
|
|
4683
|
+
setAppState(externalMetadataToAppState(metadata));
|
|
4684
|
+
if (typeof metadata.model === "string") {
|
|
4685
|
+
setMainLoopModelOverride(metadata.model);
|
|
4686
|
+
}
|
|
4687
|
+
}
|
|
4688
|
+
} else if (parsedSessionId.isUrl && parsedSessionId.ingressUrl && isEnvTruthy(process.env.ENABLE_SESSION_PERSISTENCE)) {
|
|
4689
|
+
await hydrateRemoteSession(parsedSessionId.sessionId, parsedSessionId.ingressUrl);
|
|
4690
|
+
}
|
|
4691
|
+
const result = await loadConversationForResume(parsedSessionId.sessionId, parsedSessionId.jsonlFile || undefined);
|
|
4692
|
+
if (!result || result.messages.length === 0) {
|
|
4693
|
+
if (parsedSessionId.isUrl || isEnvTruthy(process.env.CLAUDE_CODE_USE_CCR_V2)) {
|
|
4694
|
+
return {
|
|
4695
|
+
messages: await (options.sessionStartHooksPromise ?? processSessionStartHooks("startup"))
|
|
4696
|
+
};
|
|
4697
|
+
} else {
|
|
4698
|
+
emitLoadError(`No conversation found with session ID: ${parsedSessionId.sessionId}`, options.outputFormat);
|
|
4699
|
+
gracefulShutdownSync(1);
|
|
4700
|
+
return { messages: [] };
|
|
4701
|
+
}
|
|
4702
|
+
}
|
|
4703
|
+
if (options.resumeSessionAt) {
|
|
4704
|
+
const index = result.messages.findIndex((m) => m.uuid === options.resumeSessionAt);
|
|
4705
|
+
if (index < 0) {
|
|
4706
|
+
emitLoadError(`No message found with message.uuid of: ${options.resumeSessionAt}`, options.outputFormat);
|
|
4707
|
+
gracefulShutdownSync(1);
|
|
4708
|
+
return { messages: [] };
|
|
4709
|
+
}
|
|
4710
|
+
result.messages = index >= 0 ? result.messages.slice(0, index + 1) : [];
|
|
4711
|
+
}
|
|
4712
|
+
if (false) {}
|
|
4713
|
+
if (!options.forkSession && result.sessionId) {
|
|
4714
|
+
switchSession(asSessionId(result.sessionId), result.fullPath ? dirname(result.fullPath) : null);
|
|
4715
|
+
if (persistSession) {
|
|
4716
|
+
await resetSessionFilePointer();
|
|
4717
|
+
}
|
|
4718
|
+
}
|
|
4719
|
+
restoreSessionStateFromLog(result, setAppState);
|
|
4720
|
+
restoreSessionMetadata(options.forkSession ? { ...result, worktreeSession: undefined } : result);
|
|
4721
|
+
if (false) {}
|
|
4722
|
+
return {
|
|
4723
|
+
messages: result.messages,
|
|
4724
|
+
turnInterruptionState: result.turnInterruptionState,
|
|
4725
|
+
agentSetting: result.agentSetting
|
|
4726
|
+
};
|
|
4727
|
+
} catch (error) {
|
|
4728
|
+
logError(error);
|
|
4729
|
+
const errorMessage2 = error instanceof Error ? `Failed to resume session: ${error.message}` : "Failed to resume session with --print mode";
|
|
4730
|
+
emitLoadError(errorMessage2, options.outputFormat);
|
|
4731
|
+
gracefulShutdownSync(1);
|
|
4732
|
+
return { messages: [] };
|
|
4733
|
+
}
|
|
4734
|
+
}
|
|
4735
|
+
return {
|
|
4736
|
+
messages: await (options.sessionStartHooksPromise ?? processSessionStartHooks("startup"))
|
|
4737
|
+
};
|
|
4738
|
+
}
|
|
4739
|
+
function getStructuredIO(inputPrompt, options) {
|
|
4740
|
+
let inputStream;
|
|
4741
|
+
if (typeof inputPrompt === "string") {
|
|
4742
|
+
if (inputPrompt.trim() !== "") {
|
|
4743
|
+
inputStream = fromArray([
|
|
4744
|
+
jsonStringify({
|
|
4745
|
+
type: "user",
|
|
4746
|
+
content: inputPrompt,
|
|
4747
|
+
uuid: "",
|
|
4748
|
+
session_id: "",
|
|
4749
|
+
message: {
|
|
4750
|
+
role: "user",
|
|
4751
|
+
content: inputPrompt
|
|
4752
|
+
},
|
|
4753
|
+
parent_tool_use_id: null
|
|
4754
|
+
})
|
|
4755
|
+
]);
|
|
4756
|
+
} else {
|
|
4757
|
+
inputStream = fromArray([]);
|
|
4758
|
+
}
|
|
4759
|
+
} else {
|
|
4760
|
+
inputStream = inputPrompt;
|
|
4761
|
+
}
|
|
4762
|
+
return options.sdkUrl ? new RemoteIO(options.sdkUrl, inputStream, options.replayUserMessages) : new StructuredIO(inputStream, options.replayUserMessages);
|
|
4763
|
+
}
|
|
4764
|
+
async function handleOrphanedPermissionResponse({
|
|
4765
|
+
message,
|
|
4766
|
+
setAppState,
|
|
4767
|
+
onEnqueued,
|
|
4768
|
+
handledToolUseIds
|
|
4769
|
+
}) {
|
|
4770
|
+
const responseInner = message.response;
|
|
4771
|
+
if (responseInner?.subtype === "success" && responseInner.response?.toolUseID && typeof responseInner.response.toolUseID === "string") {
|
|
4772
|
+
const permissionResult = responseInner.response;
|
|
4773
|
+
const toolUseID = permissionResult.toolUseID;
|
|
4774
|
+
if (!toolUseID) {
|
|
4775
|
+
return false;
|
|
4776
|
+
}
|
|
4777
|
+
logForDebugging(`handleOrphanedPermissionResponse: received orphaned control_response for toolUseID=${toolUseID} request_id=${responseInner.request_id}`);
|
|
4778
|
+
if (handledToolUseIds.has(toolUseID)) {
|
|
4779
|
+
logForDebugging(`handleOrphanedPermissionResponse: skipping duplicate orphaned permission for toolUseID=${toolUseID} (already handled)`);
|
|
4780
|
+
return false;
|
|
4781
|
+
}
|
|
4782
|
+
const assistantMessage = await findUnresolvedToolUse(toolUseID);
|
|
4783
|
+
if (!assistantMessage) {
|
|
4784
|
+
logForDebugging(`handleOrphanedPermissionResponse: no unresolved tool_use found for toolUseID=${toolUseID} (already resolved in transcript)`);
|
|
4785
|
+
return false;
|
|
4786
|
+
}
|
|
4787
|
+
handledToolUseIds.add(toolUseID);
|
|
4788
|
+
logForDebugging(`handleOrphanedPermissionResponse: enqueuing orphaned permission for toolUseID=${toolUseID} messageID=${assistantMessage.message.id}`);
|
|
4789
|
+
enqueue({
|
|
4790
|
+
mode: "orphaned-permission",
|
|
4791
|
+
value: [],
|
|
4792
|
+
orphanedPermission: {
|
|
4793
|
+
permissionResult,
|
|
4794
|
+
assistantMessage
|
|
4795
|
+
}
|
|
4796
|
+
});
|
|
4797
|
+
onEnqueued?.();
|
|
4798
|
+
return true;
|
|
4799
|
+
}
|
|
4800
|
+
return false;
|
|
4801
|
+
}
|
|
4802
|
+
function toScopedConfig(config) {
|
|
4803
|
+
return { ...config, scope: "dynamic" };
|
|
4804
|
+
}
|
|
4805
|
+
async function handleMcpSetServers(servers, sdkState, dynamicState, setAppState) {
|
|
4806
|
+
const { allowed: allowedServers, blocked } = filterMcpServersByPolicy(servers);
|
|
4807
|
+
const policyErrors = {};
|
|
4808
|
+
for (const name of blocked) {
|
|
4809
|
+
policyErrors[name] = "Blocked by enterprise policy (allowedMcpServers/deniedMcpServers)";
|
|
4810
|
+
}
|
|
4811
|
+
const sdkServers = {};
|
|
4812
|
+
const processServers = {};
|
|
4813
|
+
for (const [name, config] of Object.entries(allowedServers)) {
|
|
4814
|
+
if (config.type === "sdk") {
|
|
4815
|
+
sdkServers[name] = config;
|
|
4816
|
+
} else {
|
|
4817
|
+
processServers[name] = config;
|
|
4818
|
+
}
|
|
4819
|
+
}
|
|
4820
|
+
const currentSdkNames = new Set(Object.keys(sdkState.configs));
|
|
4821
|
+
const newSdkNames = new Set(Object.keys(sdkServers));
|
|
4822
|
+
const sdkAdded = [];
|
|
4823
|
+
const sdkRemoved = [];
|
|
4824
|
+
const newSdkConfigs = { ...sdkState.configs };
|
|
4825
|
+
let newSdkClients = [...sdkState.clients];
|
|
4826
|
+
let newSdkTools = [...sdkState.tools];
|
|
4827
|
+
for (const name of currentSdkNames) {
|
|
4828
|
+
if (!newSdkNames.has(name)) {
|
|
4829
|
+
const client = newSdkClients.find((c) => c.name === name);
|
|
4830
|
+
if (client && client.type === "connected") {
|
|
4831
|
+
await client.cleanup();
|
|
4832
|
+
}
|
|
4833
|
+
newSdkClients = newSdkClients.filter((c) => c.name !== name);
|
|
4834
|
+
const prefix = `mcp__${name}__`;
|
|
4835
|
+
newSdkTools = newSdkTools.filter((t) => !t.name.startsWith(prefix));
|
|
4836
|
+
delete newSdkConfigs[name];
|
|
4837
|
+
sdkRemoved.push(name);
|
|
4838
|
+
}
|
|
4839
|
+
}
|
|
4840
|
+
for (const [name, config] of Object.entries(sdkServers)) {
|
|
4841
|
+
if (!currentSdkNames.has(name)) {
|
|
4842
|
+
newSdkConfigs[name] = config;
|
|
4843
|
+
const pendingClient = {
|
|
4844
|
+
type: "pending",
|
|
4845
|
+
name,
|
|
4846
|
+
config: { ...config, scope: "dynamic" }
|
|
4847
|
+
};
|
|
4848
|
+
newSdkClients = [...newSdkClients, pendingClient];
|
|
4849
|
+
sdkAdded.push(name);
|
|
4850
|
+
}
|
|
4851
|
+
}
|
|
4852
|
+
const processResult = await reconcileMcpServers(processServers, dynamicState, setAppState);
|
|
4853
|
+
return {
|
|
4854
|
+
response: {
|
|
4855
|
+
added: [...sdkAdded, ...processResult.response.added],
|
|
4856
|
+
removed: [...sdkRemoved, ...processResult.response.removed],
|
|
4857
|
+
errors: { ...policyErrors, ...processResult.response.errors }
|
|
4858
|
+
},
|
|
4859
|
+
newSdkState: {
|
|
4860
|
+
configs: newSdkConfigs,
|
|
4861
|
+
clients: newSdkClients,
|
|
4862
|
+
tools: newSdkTools
|
|
4863
|
+
},
|
|
4864
|
+
newDynamicState: processResult.newState,
|
|
4865
|
+
sdkServersChanged: sdkAdded.length > 0 || sdkRemoved.length > 0
|
|
4866
|
+
};
|
|
4867
|
+
}
|
|
4868
|
+
async function reconcileMcpServers(desiredConfigs, currentState, setAppState) {
|
|
4869
|
+
const currentNames = new Set(Object.keys(currentState.configs));
|
|
4870
|
+
const desiredNames = new Set(Object.keys(desiredConfigs));
|
|
4871
|
+
const toRemove = [...currentNames].filter((n) => !desiredNames.has(n));
|
|
4872
|
+
const toAdd = [...desiredNames].filter((n) => !currentNames.has(n));
|
|
4873
|
+
const toCheck = [...currentNames].filter((n) => desiredNames.has(n));
|
|
4874
|
+
const toReplace = toCheck.filter((name) => {
|
|
4875
|
+
const currentConfig = currentState.configs[name];
|
|
4876
|
+
const desiredConfigRaw = desiredConfigs[name];
|
|
4877
|
+
if (!currentConfig || !desiredConfigRaw)
|
|
4878
|
+
return true;
|
|
4879
|
+
const desiredConfig = toScopedConfig(desiredConfigRaw);
|
|
4880
|
+
return !areMcpConfigsEqual(currentConfig, desiredConfig);
|
|
4881
|
+
});
|
|
4882
|
+
const removed = [];
|
|
4883
|
+
const added = [];
|
|
4884
|
+
const errors = {};
|
|
4885
|
+
let newClients = [...currentState.clients];
|
|
4886
|
+
let newTools = [...currentState.tools];
|
|
4887
|
+
for (const name of [...toRemove, ...toReplace]) {
|
|
4888
|
+
const client = newClients.find((c) => c.name === name);
|
|
4889
|
+
const config = currentState.configs[name];
|
|
4890
|
+
if (client && config) {
|
|
4891
|
+
if (client.type === "connected") {
|
|
4892
|
+
try {
|
|
4893
|
+
await client.cleanup();
|
|
4894
|
+
} catch (e) {
|
|
4895
|
+
logError(e);
|
|
4896
|
+
}
|
|
4897
|
+
}
|
|
4898
|
+
await clearServerCache(name, config);
|
|
4899
|
+
}
|
|
4900
|
+
const prefix = `mcp__${name}__`;
|
|
4901
|
+
newTools = newTools.filter((t) => !t.name.startsWith(prefix));
|
|
4902
|
+
newClients = newClients.filter((c) => c.name !== name);
|
|
4903
|
+
if (toRemove.includes(name)) {
|
|
4904
|
+
removed.push(name);
|
|
4905
|
+
}
|
|
4906
|
+
}
|
|
4907
|
+
for (const name of [...toAdd, ...toReplace]) {
|
|
4908
|
+
const config = desiredConfigs[name];
|
|
4909
|
+
if (!config)
|
|
4910
|
+
continue;
|
|
4911
|
+
const scopedConfig = toScopedConfig(config);
|
|
4912
|
+
if (config.type === "sdk") {
|
|
4913
|
+
added.push(name);
|
|
4914
|
+
continue;
|
|
4915
|
+
}
|
|
4916
|
+
try {
|
|
4917
|
+
const client = await connectToServer(name, scopedConfig);
|
|
4918
|
+
newClients.push(client);
|
|
4919
|
+
if (client.type === "connected") {
|
|
4920
|
+
const serverTools = await fetchToolsForClient(client);
|
|
4921
|
+
newTools.push(...serverTools);
|
|
4922
|
+
} else if (client.type === "failed") {
|
|
4923
|
+
errors[name] = client.error || "Connection failed";
|
|
4924
|
+
}
|
|
4925
|
+
added.push(name);
|
|
4926
|
+
} catch (e) {
|
|
4927
|
+
const err = toError(e);
|
|
4928
|
+
errors[name] = err.message;
|
|
4929
|
+
logError(err);
|
|
4930
|
+
}
|
|
4931
|
+
}
|
|
4932
|
+
const newConfigs = {};
|
|
4933
|
+
for (const name of desiredNames) {
|
|
4934
|
+
const config = desiredConfigs[name];
|
|
4935
|
+
if (config) {
|
|
4936
|
+
newConfigs[name] = toScopedConfig(config);
|
|
4937
|
+
}
|
|
4938
|
+
}
|
|
4939
|
+
const newState = {
|
|
4940
|
+
clients: newClients,
|
|
4941
|
+
tools: newTools,
|
|
4942
|
+
configs: newConfigs
|
|
4943
|
+
};
|
|
4944
|
+
setAppState((prev) => {
|
|
4945
|
+
const allDynamicServerNames = new Set([
|
|
4946
|
+
...Object.keys(currentState.configs),
|
|
4947
|
+
...Object.keys(newConfigs)
|
|
4948
|
+
]);
|
|
4949
|
+
const nonDynamicTools = prev.mcp.tools.filter((t) => {
|
|
4950
|
+
for (const serverName of allDynamicServerNames) {
|
|
4951
|
+
if (t.name.startsWith(`mcp__${serverName}__`)) {
|
|
4952
|
+
return false;
|
|
4953
|
+
}
|
|
4954
|
+
}
|
|
4955
|
+
return true;
|
|
4956
|
+
});
|
|
4957
|
+
const nonDynamicClients = prev.mcp.clients.filter((c) => {
|
|
4958
|
+
return !allDynamicServerNames.has(c.name);
|
|
4959
|
+
});
|
|
4960
|
+
return {
|
|
4961
|
+
...prev,
|
|
4962
|
+
mcp: {
|
|
4963
|
+
...prev.mcp,
|
|
4964
|
+
tools: [...nonDynamicTools, ...newTools],
|
|
4965
|
+
clients: [...nonDynamicClients, ...newClients]
|
|
4966
|
+
}
|
|
4967
|
+
};
|
|
4968
|
+
});
|
|
4969
|
+
return {
|
|
4970
|
+
response: { added, removed, errors },
|
|
4971
|
+
newState
|
|
4972
|
+
};
|
|
4973
|
+
}
|
|
4974
|
+
export {
|
|
4975
|
+
runHeadless,
|
|
4976
|
+
removeInterruptedMessage,
|
|
4977
|
+
reconcileMcpServers,
|
|
4978
|
+
joinPromptValues,
|
|
4979
|
+
handleOrphanedPermissionResponse,
|
|
4980
|
+
handleMcpSetServers,
|
|
4981
|
+
getCanUseToolFn,
|
|
4982
|
+
createCanUseToolWithPermissionPrompt,
|
|
4983
|
+
canBatchWith
|
|
4984
|
+
};
|