@chainingintention/pi-web-cn 2.202610.5 → 2.202611.1
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 +4 -2
- package/dist/bin/pi-web-server.sh +91 -0
- package/dist/bin/pi-web-sessiond.sh +91 -0
- package/dist/bin/pi-web.sh +91 -0
- package/dist/cli.js +33 -29
- package/dist/cli.js.map +1 -1
- package/dist/client/assets/3d-Dr68X8h8.svg +1 -0
- package/dist/client/assets/PiWebApp-D9e-Nrxi.js +3952 -0
- package/dist/client/assets/SettingsDialog-BvlvoXvD.js +1129 -0
- package/dist/client/assets/abap-uAHVFerN.svg +1 -0
- package/dist/client/assets/abc-CXjdSXsv.svg +1 -0
- package/dist/client/assets/actionscript-BCkIwjgm.svg +1 -0
- package/dist/client/assets/ada-GL6JWmc_.svg +1 -0
- package/dist/client/assets/adobe-illustrator-DhGvkpwi.svg +1 -0
- package/dist/client/assets/adobe-photoshop-0hmnA7cm.svg +1 -0
- package/dist/client/assets/adobe-swc-myFGSGFT.svg +1 -0
- package/dist/client/assets/adonis-SdGYdzCA.svg +1 -0
- package/dist/client/assets/advpl-BWLgf_Ky.svg +1 -0
- package/dist/client/assets/advpl-include-DYgH3R0u.svg +1 -0
- package/dist/client/assets/advpl-ptm-C5Y5ffZi.svg +1 -0
- package/dist/client/assets/advpl-tlpp-BAlVwpPL.svg +1 -0
- package/dist/client/assets/agent-DAWBwR7s.svg +1 -0
- package/dist/client/assets/amplify-BAWPaFFb.svg +1 -0
- package/dist/client/assets/android-TigHCxTb.svg +1 -0
- package/dist/client/assets/angular-D2ijCUIg.svg +1 -0
- package/dist/client/assets/angular-component-eczQQRE6.svg +1 -0
- package/dist/client/assets/angular-directive-C_jq8cjP.svg +1 -0
- package/dist/client/assets/angular-guard-B4iC5rXF.svg +1 -0
- package/dist/client/assets/angular-interceptor-CJvi6DuQ.svg +1 -0
- package/dist/client/assets/angular-pipe-BQZMATB_.svg +1 -0
- package/dist/client/assets/angular-service-DHYn6jIk.svg +1 -0
- package/dist/client/assets/antlr-DkzdiGgY.svg +1 -0
- package/dist/client/assets/apiblueprint-BDRvCIBM.svg +1 -0
- package/dist/client/assets/apollo-BAVoyYDs.svg +1 -0
- package/dist/client/assets/applescript-Bm_R8YT0.svg +1 -0
- package/dist/client/assets/apps-script-6efl-CXu.svg +1 -0
- package/dist/client/assets/appveyor-6B1suIBr.svg +1 -0
- package/dist/client/assets/appwrite-D7AlK8SW.svg +1 -0
- package/dist/client/assets/architecture-CtuqF8rD.svg +1 -0
- package/dist/client/assets/arduino-DFxCIupZ.svg +1 -0
- package/dist/client/assets/asciidoc-DUAdVwVP.svg +1 -0
- package/dist/client/assets/assembly-BKikEKKy.svg +1 -0
- package/dist/client/assets/astro-Bivf18eC.svg +1 -0
- package/dist/client/assets/astro-config-Cr5suFul.svg +1 -0
- package/dist/client/assets/astyle-BiqOWu-0.svg +1 -0
- package/dist/client/assets/audio-B4FatEUD.svg +1 -0
- package/dist/client/assets/aurelia-CnUjHPcZ.svg +1 -0
- package/dist/client/assets/authors-DdaDoKVR.svg +1 -0
- package/dist/client/assets/auto-BOO_fhxh.svg +1 -0
- package/dist/client/assets/autohotkey-D87F33UG.svg +1 -0
- package/dist/client/assets/autoit-DQTGS66r.svg +1 -0
- package/dist/client/assets/azure-DMSkMABH.svg +1 -0
- package/dist/client/assets/azure-pipelines-CcGJw3Rl.svg +1 -0
- package/dist/client/assets/babel-DFMbiqHA.svg +1 -0
- package/dist/client/assets/ballerina-BT8MyHl8.svg +1 -0
- package/dist/client/assets/bashly-settings-Ch9mIpw9.svg +1 -0
- package/dist/client/assets/bazel-CPXexffJ.svg +1 -0
- package/dist/client/assets/bbx-CB-6IYxw.svg +1 -0
- package/dist/client/assets/beancount-DR_GSwds.svg +1 -0
- package/dist/client/assets/bench-js-DOHd4EZB.svg +1 -0
- package/dist/client/assets/bench-jsx-CLJJl81D.svg +1 -0
- package/dist/client/assets/bench-ts-BM8GsfrF.svg +1 -0
- package/dist/client/assets/bibliography-D3emS1pd.svg +1 -0
- package/dist/client/assets/bibtex-style-CVY4tTiP.svg +1 -0
- package/dist/client/assets/bicep-BMMGt18P.svg +1 -0
- package/dist/client/assets/biome-Bf2373dl.svg +1 -0
- package/dist/client/assets/bitbucket-BQr8Az5R.svg +1 -0
- package/dist/client/assets/bithound-BOh7-s-G.svg +1 -0
- package/dist/client/assets/blender-B7Vz8gxa.svg +1 -0
- package/dist/client/assets/blink-DVWcfhba.svg +1 -0
- package/dist/client/assets/blitz-B4hhOxPa.svg +1 -0
- package/dist/client/assets/bower-CkFcC1Ou.svg +1 -0
- package/dist/client/assets/brainfuck-BXozg9z7.svg +1 -0
- package/dist/client/assets/browserlist-CUbhNMS9.svg +1 -0
- package/dist/client/assets/bruno-CoSNrNfv.svg +1 -0
- package/dist/client/assets/buck-BRuOl0ko.svg +1 -0
- package/dist/client/assets/bucklescript-TfoVgTnq.svg +1 -0
- package/dist/client/assets/buildkite-BrDKWLhW.svg +1 -0
- package/dist/client/assets/bun-CZtgPBjt.svg +1 -0
- package/dist/client/assets/c-CCkhSkL9.svg +1 -0
- package/dist/client/assets/c3-J0cVtsWq.svg +1 -0
- package/dist/client/assets/cabal-CQb4_DnV.svg +1 -0
- package/dist/client/assets/caddy-ywaArsUF.svg +1 -0
- package/dist/client/assets/cadence-BRBsaulT.svg +1 -0
- package/dist/client/assets/cairo-Cls19dwE.svg +1 -0
- package/dist/client/assets/cake-DpuWz3gE.svg +1 -0
- package/dist/client/assets/capacitor-CugB3p3d.svg +1 -0
- package/dist/client/assets/capnp-DtxOZ2_z.svg +1 -0
- package/dist/client/assets/cbx-QvSmyWq4.svg +1 -0
- package/dist/client/assets/cds-Bi3ghsEA.svg +1 -0
- package/dist/client/assets/certificate-B5QPOK_C.svg +1 -0
- package/dist/client/assets/changelog-mhp3hE32.svg +1 -0
- package/dist/client/assets/chess-4hVz24Rg.svg +1 -0
- package/dist/client/assets/chromatic-DRZoj4Hg.svg +1 -0
- package/dist/client/assets/chrome-ox3b9yI4.svg +1 -0
- package/dist/client/assets/circleci-DubwoSEv.svg +1 -0
- package/dist/client/assets/citation-ldCt-JF8.svg +1 -0
- package/dist/client/assets/clangd-bL8W2_13.svg +1 -0
- package/dist/client/assets/claude-DypBvzkn.svg +1 -0
- package/dist/client/assets/cline-Dd7x4bMT.svg +1 -0
- package/dist/client/assets/clojure-wfCfR06G.svg +1 -0
- package/dist/client/assets/cloudfoundry-BS-9yLUv.svg +1 -0
- package/dist/client/assets/cmake-B7q-R28A.svg +1 -0
- package/dist/client/assets/coala-D4YHPVOS.svg +1 -0
- package/dist/client/assets/cobol-wDz3o6g-.svg +1 -0
- package/dist/client/assets/coconut-C7cPswso.svg +1 -0
- package/dist/client/assets/code-climate-BJrwzyOv.svg +1 -0
- package/dist/client/assets/codecov-CXg1oY95.svg +1 -0
- package/dist/client/assets/codeowners-D_rztV49.svg +1 -0
- package/dist/client/assets/coderabbit-ai-DGoTDlyw.svg +1 -0
- package/dist/client/assets/coffee-D5JGmA63.svg +1 -0
- package/dist/client/assets/coldfusion-DhOnvVS_.svg +1 -0
- package/dist/client/assets/coloredpetrinets-DY894G_S.svg +1 -0
- package/dist/client/assets/command-Df3AkI2A.svg +1 -0
- package/dist/client/assets/commitizen-9SU1u7to.svg +1 -0
- package/dist/client/assets/commitlint-3vvjpxJt.svg +1 -0
- package/dist/client/assets/composerShortcuts-BggqvE9J.js +31 -0
- package/dist/client/assets/concourse-DAGkX2vY.svg +1 -0
- package/dist/client/assets/conduct-2Bm8RK0N.svg +1 -0
- package/dist/client/assets/console-pcgGAn8Z.svg +1 -0
- package/dist/client/assets/contentlayer-vXTwXOHk.svg +1 -0
- package/dist/client/assets/context-CebLrksE.svg +1 -0
- package/dist/client/assets/contributing-DLcmDS34.svg +1 -0
- package/dist/client/assets/controller-Doc75EnV.svg +1 -0
- package/dist/client/assets/copilot-DBlNrZ6L.svg +1 -0
- package/dist/client/assets/cpp-DT2939hp.svg +1 -0
- package/dist/client/assets/craco-BySmcQ23.svg +1 -0
- package/dist/client/assets/credits-GALyqcNu.svg +1 -0
- package/dist/client/assets/crystal-BbNQlJLs.svg +1 -0
- package/dist/client/assets/csharp-D5ZKsaqY.svg +1 -0
- package/dist/client/assets/css-JKwEyWYb.svg +1 -0
- package/dist/client/assets/css-map-Ctu4D9Ve.svg +1 -0
- package/dist/client/assets/cucumber-B3ZYwjRe.svg +1 -0
- package/dist/client/assets/cuda-CRW2z42A.svg +1 -0
- package/dist/client/assets/cue-ni2TTLiZ.svg +1 -0
- package/dist/client/assets/cursor-CJahHGg2.svg +1 -0
- package/dist/client/assets/cypress-DR0JRbfI.svg +1 -0
- package/dist/client/assets/d-B87zyVMx.svg +1 -0
- package/dist/client/assets/dart-Dx2oVcaR.svg +1 -0
- package/dist/client/assets/dart_generated-Wk58pte9.svg +1 -0
- package/dist/client/assets/database-B_oKaDcf.svg +1 -0
- package/dist/client/assets/deepsource-DUTIJ9mv.svg +1 -0
- package/dist/client/assets/denizenscript-BJc2vgOS.svg +1 -0
- package/dist/client/assets/deno-CyFvrzCm.svg +1 -0
- package/dist/client/assets/dependabot-BgJkJLU3.svg +1 -0
- package/dist/client/assets/dependencies-update-CdGy9ujO.svg +1 -0
- package/dist/client/assets/dhall-Dmhh82EO.svg +1 -0
- package/dist/client/assets/diff-6SXDCokN.svg +1 -0
- package/dist/client/assets/dinophp-D9hQnqAR.svg +1 -0
- package/dist/client/assets/disc-h_dLNGEL.svg +1 -0
- package/dist/client/assets/django-N1UNAXk1.svg +1 -0
- package/dist/client/assets/dll-1DkaBp0q.svg +1 -0
- package/dist/client/assets/docker-CfHcr61D.svg +1 -0
- package/dist/client/assets/doctex-installer-Cs7SA-ct.svg +1 -0
- package/dist/client/assets/document-o-3iA9GQ.svg +1 -0
- package/dist/client/assets/dotjs-DIyH7Gzv.svg +1 -0
- package/dist/client/assets/drawio-2RVDLi9g.svg +1 -0
- package/dist/client/assets/drizzle-hhBCZx1t.svg +1 -0
- package/dist/client/assets/drone-KvQ2n-xY.svg +1 -0
- package/dist/client/assets/dtx-DdGk8fFj.svg +1 -0
- package/dist/client/assets/duc-CHcAZQos.svg +1 -0
- package/dist/client/assets/dune-DuGO6qDA.svg +1 -0
- package/dist/client/assets/edge-ChHKXrYp.svg +1 -0
- package/dist/client/assets/editorconfig-BUzUAwRX.svg +1 -0
- package/dist/client/assets/ejs-D_Li05n3.svg +1 -0
- package/dist/client/assets/elixir-75mYTx2s.svg +1 -0
- package/dist/client/assets/elm-DE_LIp02.svg +1 -0
- package/dist/client/assets/email-G8mUttGa.svg +1 -0
- package/dist/client/assets/ember-B1y9-Oks.svg +1 -0
- package/dist/client/assets/epub-DPvrBCNf.svg +1 -0
- package/dist/client/assets/erlang-DosS6spf.svg +1 -0
- package/dist/client/assets/esbuild-DV6xNZ-T.svg +1 -0
- package/dist/client/assets/eslint-IU_g232-.svg +1 -0
- package/dist/client/assets/excalidraw-BllKd-7L.svg +1 -0
- package/dist/client/assets/exe-SfcXmkQy.svg +1 -0
- package/dist/client/assets/expo-B4PonO4I.svg +1 -0
- package/dist/client/assets/external-Bawe0tSn.js +1 -0
- package/dist/client/assets/fastlane-C4SZDg50.svg +1 -0
- package/dist/client/assets/favicon-VsCcG-A-.svg +1 -0
- package/dist/client/assets/figma-C8Gjq2Xj.svg +1 -0
- package/dist/client/assets/file-BEIHQH8Q.svg +256 -0
- package/dist/client/assets/firebase-DHIO0glR.svg +1 -0
- package/dist/client/assets/flash-Dck7x_rj.svg +1 -0
- package/dist/client/assets/flow-DD4KQiTg.svg +1 -0
- package/dist/client/assets/font-ChbWr8nk.svg +1 -0
- package/dist/client/assets/forth-C3qwGqMh.svg +1 -0
- package/dist/client/assets/fortran-B0jORJ3v.svg +1 -0
- package/dist/client/assets/foxpro-D3Wp1B1h.svg +1 -0
- package/dist/client/assets/freemarker-BLonnh3h.svg +1 -0
- package/dist/client/assets/fsharp-QwwPC8x_.svg +1 -0
- package/dist/client/assets/fusebox-DqjzyXyI.svg +1 -0
- package/dist/client/assets/gamemaker-C82Pt646.svg +1 -0
- package/dist/client/assets/garden-BUsWpFKW.svg +1 -0
- package/dist/client/assets/gatsby-OA1TADMJ.svg +1 -0
- package/dist/client/assets/gcp-CW2RG_Wp.svg +1 -0
- package/dist/client/assets/gemfile-1RY6BqSx.svg +1 -0
- package/dist/client/assets/gemini-CIgUY8Tg.svg +1 -0
- package/dist/client/assets/gemini-ai-Bwe7HeFb.svg +1 -0
- package/dist/client/assets/git-BEMs8TOZ.svg +1 -0
- package/dist/client/assets/gitlab-zt07_Oa4.svg +1 -0
- package/dist/client/assets/gitpod-BtZJQuF0.svg +1 -0
- package/dist/client/assets/gleam-CKPcrRAD.svg +1 -0
- package/dist/client/assets/gnuplot-BvFqM0ms.svg +1 -0
- package/dist/client/assets/go-ByY4sxRu.svg +1 -0
- package/dist/client/assets/go-mod-CB6BWQDr.svg +1 -0
- package/dist/client/assets/godot-C1EmL4jR.svg +1 -0
- package/dist/client/assets/godot-assets-D-FMsuJX.svg +1 -0
- package/dist/client/assets/google-BnrMOJ4V.svg +1 -0
- package/dist/client/assets/gradle-zsQ12U1q.svg +1 -0
- package/dist/client/assets/grafana-alloy-D2DQ33BM.svg +1 -0
- package/dist/client/assets/grain-5NkvKROL.svg +1 -0
- package/dist/client/assets/graphcool-CInCTIdE.svg +1 -0
- package/dist/client/assets/graphql-DnNt2maR.svg +1 -0
- package/dist/client/assets/gridsome-C2H5SpaD.svg +1 -0
- package/dist/client/assets/groovy-B93RxI7a.svg +1 -0
- package/dist/client/assets/grunt-cwitasVS.svg +1 -0
- package/dist/client/assets/gulp-BIZ8EAl0.svg +1 -0
- package/dist/client/assets/h-1bd73y8t.svg +1 -0
- package/dist/client/assets/hack-Bsd1y9bu.svg +1 -0
- package/dist/client/assets/hadolint-D1aEtESc.svg +1 -0
- package/dist/client/assets/haml-BKq8hU-U.svg +1 -0
- package/dist/client/assets/handlebars-Dem98Ago.svg +1 -0
- package/dist/client/assets/happo-B64XokX0.svg +1 -0
- package/dist/client/assets/hardhat-ByFzkuf4.svg +1 -0
- package/dist/client/assets/harmonix-CUh3S11M.svg +1 -0
- package/dist/client/assets/haskell-C6GxEwdX.svg +1 -0
- package/dist/client/assets/haxe-DdxZWPQy.svg +1 -0
- package/dist/client/assets/hcl-BJiZ3gWE.svg +1 -0
- package/dist/client/assets/helm-CF4Mi35z.svg +1 -0
- package/dist/client/assets/heroku-B6vPz_TJ.svg +1 -0
- package/dist/client/assets/hex-BuGJuqn1.svg +1 -0
- package/dist/client/assets/hip-DB4xe1Ab.svg +1 -0
- package/dist/client/assets/histoire-BMTufysg.svg +1 -0
- package/dist/client/assets/hjson-Dl4ZTgK4.svg +1 -0
- package/dist/client/assets/horusec-z6vyrVAy.svg +1 -0
- package/dist/client/assets/hosts-BydfWJ9z.svg +1 -0
- package/dist/client/assets/hpp-HerxyIaC.svg +1 -0
- package/dist/client/assets/html-BNRzQ3jk.svg +1 -0
- package/dist/client/assets/http-Cp7RCu8F.svg +1 -0
- package/dist/client/assets/huff-t3uGT10D.svg +1 -0
- package/dist/client/assets/hurl-S3Fvmz3R.svg +1 -0
- package/dist/client/assets/husky-A0ALYNcp.svg +1 -0
- package/dist/client/assets/i18n-BezCQ09L.svg +1 -0
- package/dist/client/assets/idris-CfHPjxcM.svg +1 -0
- package/dist/client/assets/ifanr-cloud-DnqgZYHA.svg +1 -0
- package/dist/client/assets/image-DYZiZ4CP.svg +1 -0
- package/dist/client/assets/imba-C1Q6aK1I.svg +1 -0
- package/dist/client/assets/index-0z4D-18M.js +2 -0
- package/dist/client/assets/installation-p19cVXO7.svg +1 -0
- package/dist/client/assets/instructions-CaWEzdge.svg +1 -0
- package/dist/client/assets/ionic-Xp-47Icg.svg +1 -0
- package/dist/client/assets/istanbul-DJKvMwnq.svg +1 -0
- package/dist/client/assets/jar-BaN44U3v.svg +1 -0
- package/dist/client/assets/java-QyMrrPma.svg +1 -0
- package/dist/client/assets/javaclass-BU8_3KBR.svg +1 -0
- package/dist/client/assets/javascript-CQjpTQab.svg +1 -0
- package/dist/client/assets/javascript-map-BQGiWnDM.svg +1 -0
- package/dist/client/assets/jenkins-Bf7aNz-w.svg +1 -0
- package/dist/client/assets/jest-BgbiFFEd.svg +1 -0
- package/dist/client/assets/jinja-4WR9tA6i.svg +1 -0
- package/dist/client/assets/jsconfig-ZAi6fTF1.svg +1 -0
- package/dist/client/assets/json-NsberLUP.svg +1 -0
- package/dist/client/assets/json_schema-sOuobP_H.svg +1 -0
- package/dist/client/assets/jsr-CWVSPSyV.svg +1 -0
- package/dist/client/assets/julia-DCKDSo9T.svg +1 -0
- package/dist/client/assets/jupyter-BKV2q0IB.svg +1 -0
- package/dist/client/assets/just-WQgcj-TR.svg +1 -0
- package/dist/client/assets/karma-Dm3AtiMd.svg +1 -0
- package/dist/client/assets/kcl-CyzArNE1.svg +1 -0
- package/dist/client/assets/key-CrFjkQiv.svg +1 -0
- package/dist/client/assets/keystatic-BECeLiHJ.svg +1 -0
- package/dist/client/assets/kivy-baDYR7ar.svg +1 -0
- package/dist/client/assets/kl-Dy3qeUbd.svg +1 -0
- package/dist/client/assets/knip-BWpBMXqu.svg +1 -0
- package/dist/client/assets/kotlin-DcjME28v.svg +1 -0
- package/dist/client/assets/kubernetes-B5EEXb3e.svg +1 -0
- package/dist/client/assets/kusto-CIjvTfRW.svg +1 -0
- package/dist/client/assets/label-AKZOJqFh.svg +1 -0
- package/dist/client/assets/laravel-DWauj5w4.svg +1 -0
- package/dist/client/assets/latexmk-DQ0u8QMa.svg +1 -0
- package/dist/client/assets/lbx-BMCQe48q.svg +1 -0
- package/dist/client/assets/lean-COOrALn9.svg +1 -0
- package/dist/client/assets/lefthook-DClcp3br.svg +1 -0
- package/dist/client/assets/lerna-BsWY3uYS.svg +1 -0
- package/dist/client/assets/less-0c0PeB1Z.svg +1 -0
- package/dist/client/assets/liara-CSN9sJzE.svg +1 -0
- package/dist/client/assets/lib-B-NXM8aC.svg +1 -0
- package/dist/client/assets/license-DmydDYqK.svg +1 -0
- package/dist/client/assets/lighthouse-CtbIoCdK.svg +1 -0
- package/dist/client/assets/lilypond-CBSm3LFL.svg +1 -0
- package/dist/client/assets/lintstaged-Bj1Eddi5.svg +1 -0
- package/dist/client/assets/liquid-ClnkrScY.svg +1 -0
- package/dist/client/assets/lisp-CMn3epg5.svg +1 -0
- package/dist/client/assets/lit-CJ6w1GHF.js +2 -0
- package/dist/client/assets/livescript-B5PkWD8e.svg +1 -0
- package/dist/client/assets/lock-DRloBj1S.svg +1 -0
- package/dist/client/assets/log-Db6NwxHZ.svg +1 -0
- package/dist/client/assets/lolcode-C6q6fY1O.svg +1 -0
- package/dist/client/assets/lottie-ExyLYhtq.svg +1 -0
- package/dist/client/assets/lua-CUh_Iwk8.svg +1 -0
- package/dist/client/assets/luau-De_4eP_9.svg +1 -0
- package/dist/client/assets/lynx-B49IBNBN.svg +1 -0
- package/dist/client/assets/lyric-Bm3UlVp3.svg +1 -0
- package/dist/client/assets/macaulay2-0YotwNnE.svg +1 -0
- package/dist/client/assets/main-DDgPZEYp.js +2 -0
- package/dist/client/assets/makefile-B2WlY55Y.svg +1 -0
- package/dist/client/assets/markdoc-DjROVW5I.svg +1 -0
- package/dist/client/assets/markdoc-config-BpVRhg1B.svg +1 -0
- package/dist/client/assets/markdown-Bm_LLmmi.svg +1 -0
- package/dist/client/assets/markdownlint-D4M2LXbH.svg +1 -0
- package/dist/client/assets/markojs-BohUrSLp.svg +1 -0
- package/dist/client/assets/mathematica-BGWNQXSR.svg +1 -0
- package/dist/client/assets/maven-BffVB5hm.svg +1 -0
- package/dist/client/assets/mdsvex-Dc9CFJJa.svg +1 -0
- package/dist/client/assets/mdx-D6qa5U8C.svg +1 -0
- package/dist/client/assets/mercurial-BDoD6ubd.svg +1 -0
- package/dist/client/assets/merlin-D5wTXfO4.svg +1 -0
- package/dist/client/assets/mermaid-BTscZDRS.svg +1 -0
- package/dist/client/assets/meson-dcvm8lmo.svg +1 -0
- package/dist/client/assets/metro-XIyWX0Go.svg +1 -0
- package/dist/client/assets/minecraft-CE8xXE3-.svg +1 -0
- package/dist/client/assets/minecraft-fabric-wG6LwgIf.svg +1 -0
- package/dist/client/assets/mint-Cb-YXACo.svg +1 -0
- package/dist/client/assets/mist-DAm4UkTw.svg +1 -0
- package/dist/client/assets/mjml-C_r30C5E.svg +1 -0
- package/dist/client/assets/mocha-BF5_j65C.svg +1 -0
- package/dist/client/assets/modernizr-89IMS8eL.svg +1 -0
- package/dist/client/assets/mojo-CscjT2Jm.svg +1 -0
- package/dist/client/assets/moon-_L_nTq1_.svg +1 -0
- package/dist/client/assets/moonscript-Ayut2PrD.svg +1 -0
- package/dist/client/assets/mrpack-BVpGpKVf.svg +1 -0
- package/dist/client/assets/mxml-B21Nbdgw.svg +1 -0
- package/dist/client/assets/nano-staged-CAVSFkY8.svg +1 -0
- package/dist/client/assets/ndst-DpYLiHkx.svg +1 -0
- package/dist/client/assets/nest-CUu_iPqI.svg +1 -0
- package/dist/client/assets/netlify-Bb7vRMfV.svg +1 -0
- package/dist/client/assets/next-2gAImGWJ.svg +1 -0
- package/dist/client/assets/nextflow-dPJG5e3G.svg +1 -0
- package/dist/client/assets/nginx-Ss9U_SJ3.svg +1 -0
- package/dist/client/assets/nim-CXHB5kuH.svg +1 -0
- package/dist/client/assets/nix-DoxxkZ2k.svg +1 -0
- package/dist/client/assets/nodejs-Czg5JT6z.svg +1 -0
- package/dist/client/assets/nodemon-CprsexAJ.svg +1 -0
- package/dist/client/assets/npm-BSKPS9CC.svg +1 -0
- package/dist/client/assets/nuget-D_mqKH22.svg +1 -0
- package/dist/client/assets/nunjucks-CSL1En7R.svg +1 -0
- package/dist/client/assets/nuxt-BszScKzK.svg +1 -0
- package/dist/client/assets/nx-CTIqtdbG.svg +1 -0
- package/dist/client/assets/objective-c-3E5wWl6u.svg +1 -0
- package/dist/client/assets/objective-cpp-DjpoLOMo.svg +1 -0
- package/dist/client/assets/ocaml-T4fLeZFT.svg +1 -0
- package/dist/client/assets/odin-DlWnbZWN.svg +1 -0
- package/dist/client/assets/onnx-C6WInyrb.svg +1 -0
- package/dist/client/assets/opa-D5GoZW5M.svg +1 -0
- package/dist/client/assets/opam-3IZadro4.svg +1 -0
- package/dist/client/assets/openapi-DjlVyoOp.svg +1 -0
- package/dist/client/assets/opencode-BaYncWio.svg +1 -0
- package/dist/client/assets/opentofu-jFw9lQBP.svg +1 -0
- package/dist/client/assets/otne-SLiO8whA.svg +1 -0
- package/dist/client/assets/oxc-DN6_023j.svg +1 -0
- package/dist/client/assets/packship-UyLXQ_8n.svg +1 -0
- package/dist/client/assets/palette-C0GOsJgu.svg +1 -0
- package/dist/client/assets/panda-D469wGns.svg +1 -0
- package/dist/client/assets/parcel-BrXQSBYb.svg +1 -0
- package/dist/client/assets/pascal-oxGvvJ_x.svg +1 -0
- package/dist/client/assets/pawn-BvapPd-t.svg +1 -0
- package/dist/client/assets/payload-Cks6N40-.svg +1 -0
- package/dist/client/assets/pdf-DtjgBDdX.svg +1 -0
- package/dist/client/assets/pdm-CbwhGqOl.svg +1 -0
- package/dist/client/assets/peg-BJdFn78b.svg +1 -0
- package/dist/client/assets/percy-CWbuYL05.svg +1 -0
- package/dist/client/assets/perl-DUX0zwsQ.svg +1 -0
- package/dist/client/assets/php-5lebFt-d.svg +1 -0
- package/dist/client/assets/php-cs-fixer-D3Vv91zO.svg +1 -0
- package/dist/client/assets/phpstan-D9FJYotS.svg +1 -0
- package/dist/client/assets/phpunit-BlNyjrEw.svg +1 -0
- package/dist/client/assets/pinejs-CDuWmsOY.svg +1 -0
- package/dist/client/assets/pipeline-CCHJ-CIC.svg +1 -0
- package/dist/client/assets/pkl-CzHZDqdt.svg +1 -0
- package/dist/client/assets/plastic-CvMMB3c5.svg +1 -0
- package/dist/client/assets/playwright-C8c_RKic.svg +1 -0
- package/dist/client/assets/plop-D4uymN-_.svg +1 -0
- package/dist/client/assets/pm2-ecosystem-Cv28zGx9.svg +1 -0
- package/dist/client/assets/pnpm-ndvMXYUu.svg +1 -0
- package/dist/client/assets/poetry-ClZfXo_0.svg +1 -0
- package/dist/client/assets/postcss-g3C3DDoi.svg +1 -0
- package/dist/client/assets/posthtml-BkDCsIkz.svg +1 -0
- package/dist/client/assets/powerpoint-CCXYfzLu.svg +1 -0
- package/dist/client/assets/powershell-DnXi9Rjx.svg +1 -0
- package/dist/client/assets/pre-commit-DXbl2unR.svg +1 -0
- package/dist/client/assets/preload-helper-CRzLMJPS.js +1 -0
- package/dist/client/assets/prettier-DFxlFAp4.svg +1 -0
- package/dist/client/assets/prisma-BgG1MIwh.svg +1 -0
- package/dist/client/assets/processing-B1bs0VmW.svg +1 -0
- package/dist/client/assets/prolog-CxwCfnlm.svg +1 -0
- package/dist/client/assets/prompt-7jgVTNou.svg +1 -0
- package/dist/client/assets/proto-Bv4-L0XU.svg +1 -0
- package/dist/client/assets/protractor-CJWv1lK-.svg +1 -0
- package/dist/client/assets/pug-BXlORXuH.svg +1 -0
- package/dist/client/assets/puppet-CKCVJvZX.svg +1 -0
- package/dist/client/assets/puppeteer-DDZkfQNZ.svg +1 -0
- package/dist/client/assets/purescript-CUdIfJrp.svg +1 -0
- package/dist/client/assets/python-misc-BZ5TXfdG.svg +1 -0
- package/dist/client/assets/python-oHA753pt.svg +1 -0
- package/dist/client/assets/pytorch-f0udCMaw.svg +1 -0
- package/dist/client/assets/qsharp-BaFNvoXS.svg +1 -0
- package/dist/client/assets/quarto-zhC7oGOB.svg +1 -0
- package/dist/client/assets/quasar-BXE2pW5w.svg +1 -0
- package/dist/client/assets/quokka-DrMOw93T.svg +1 -0
- package/dist/client/assets/r-AQewf3lz.svg +1 -0
- package/dist/client/assets/racket-BCyLzvrP.svg +1 -0
- package/dist/client/assets/raml-WDbT4cRb.svg +1 -0
- package/dist/client/assets/razor-BAUCpTxC.svg +1 -0
- package/dist/client/assets/rbxmk-CZ9pB7X6.svg +1 -0
- package/dist/client/assets/rc-BDgxm_A8.svg +1 -0
- package/dist/client/assets/react-CdMrIyLK.svg +1 -0
- package/dist/client/assets/react_ts-9WeLJBIj.svg +1 -0
- package/dist/client/assets/readme-BSIQKZwq.svg +1 -0
- package/dist/client/assets/reason-m9vOqeqw.svg +1 -0
- package/dist/client/assets/red-Dzf3O8j4.svg +1 -0
- package/dist/client/assets/regedit-DJzxfiQN.svg +1 -0
- package/dist/client/assets/remark-C55cxr93.svg +1 -0
- package/dist/client/assets/remix-Bk2h4zH7.svg +1 -0
- package/dist/client/assets/renovate-zzi8oRFv.svg +1 -0
- package/dist/client/assets/replit-BpeMxcBh.svg +1 -0
- package/dist/client/assets/requiredTerminalPlugin-ZZOwUcbr.js +3 -0
- package/dist/client/assets/rescript-interface-a87dYX5u.svg +1 -0
- package/dist/client/assets/rescript-qPAwtDLa.svg +1 -0
- package/dist/client/assets/restql-CnZcZpny.svg +1 -0
- package/dist/client/assets/riot-DjRzaRVp.svg +1 -0
- package/dist/client/assets/roadmap-DWpVc5P5.svg +1 -0
- package/dist/client/assets/roblox-Bv5zbklC.svg +1 -0
- package/dist/client/assets/robot-Cto_i8jo.svg +1 -0
- package/dist/client/assets/robots-COnOCAqh.svg +1 -0
- package/dist/client/assets/rocket-CAmUpMm6.svg +1 -0
- package/dist/client/assets/rolldown-Cy_4AzVW.svg +1 -0
- package/dist/client/assets/rollup-2ZkmBeWV.svg +1 -0
- package/dist/client/assets/rome-Cq3lb2xY.svg +1 -0
- package/dist/client/assets/routing-BNxHhbXZ.svg +1 -0
- package/dist/client/assets/rspec-CoEmfx5H.svg +1 -0
- package/dist/client/assets/rstack-DzJ3cPXM.svg +1 -0
- package/dist/client/assets/rubocop-CokGq15J.svg +1 -0
- package/dist/client/assets/ruby-DTGQ4xCM.svg +1 -0
- package/dist/client/assets/ruff-BN0KpNzC.svg +1 -0
- package/dist/client/assets/rust-B122pUHY.svg +1 -0
- package/dist/client/assets/salt-B8j0OVNV.svg +1 -0
- package/dist/client/assets/san-C0UnyaU4.svg +1 -0
- package/dist/client/assets/sas-RNoBA0-Y.svg +1 -0
- package/dist/client/assets/sass-B7y5mYt_.svg +1 -0
- package/dist/client/assets/sbt-DosCci-d.svg +1 -0
- package/dist/client/assets/scala-CsGkKwl5.svg +1 -0
- package/dist/client/assets/scheme-CS2UbTis.svg +1 -0
- package/dist/client/assets/scons-CyqfFgvx.svg +1 -0
- package/dist/client/assets/screwdriver-DjTKuDz7.svg +1 -0
- package/dist/client/assets/search-fq7VxV09.svg +1 -0
- package/dist/client/assets/semantic-release-BbLzZX96.svg +1 -0
- package/dist/client/assets/semgrep-Cl6VUQtd.svg +1 -0
- package/dist/client/assets/sentry-MrouyD-P.svg +1 -0
- package/dist/client/assets/sequelize-BQWikTCs.svg +1 -0
- package/dist/client/assets/serverless-C7Jdn6_T.svg +1 -0
- package/dist/client/assets/settings-CtzL1evz.svg +1 -0
- package/dist/client/assets/shader-BZXKDeiD.svg +1 -0
- package/dist/client/assets/shellcheck-BgWOclub.svg +1 -0
- package/dist/client/assets/simulink-yQnKyx__.svg +1 -0
- package/dist/client/assets/siyuan-CPWD86-6.svg +1 -0
- package/dist/client/assets/sketch-NbltjaPf.svg +1 -0
- package/dist/client/assets/skill-BThvgH87.svg +1 -0
- package/dist/client/assets/slim-CTjdZAfz.svg +1 -0
- package/dist/client/assets/slint-B0xbkqgr.svg +1 -0
- package/dist/client/assets/slug-CWkQgR9s.svg +1 -0
- package/dist/client/assets/smarty-BXDiLQNt.svg +1 -0
- package/dist/client/assets/sml-DMkoWEN5.svg +1 -0
- package/dist/client/assets/snakemake-xG7xUrdI.svg +1 -0
- package/dist/client/assets/snapcraft-zvgAcZ4p.svg +1 -0
- package/dist/client/assets/snowpack-l0uHt304.svg +1 -0
- package/dist/client/assets/snyk-DCW3rtvv.svg +1 -0
- package/dist/client/assets/solidity-C4TQWJKU.svg +1 -0
- package/dist/client/assets/sonarcloud-ClLIXGyx.svg +1 -0
- package/dist/client/assets/spwn-31WG9ftR.svg +1 -0
- package/dist/client/assets/stackblitz-ZX6aBRKb.svg +1 -0
- package/dist/client/assets/stan-CPcUXbxB.svg +1 -0
- package/dist/client/assets/steadybit-BZtlLY-3.svg +1 -0
- package/dist/client/assets/stencil-D0FNO32O.svg +1 -0
- package/dist/client/assets/stitches-BYlEJvuz.svg +1 -0
- package/dist/client/assets/storybook-KxGhpZYa.svg +1 -0
- package/dist/client/assets/stryker-CYflxT_R.svg +1 -0
- package/dist/client/assets/sty-C4HqHV4z.svg +1 -0
- package/dist/client/assets/stylable-Bi9Gr97T.svg +1 -0
- package/dist/client/assets/styleSources-CdF2T_pj.js +1 -0
- package/dist/client/assets/stylelint-JSbd-yhE.svg +1 -0
- package/dist/client/assets/styles-BwN5rgmt.js +10 -0
- package/dist/client/assets/styles-DK4aKhCE.js +1 -0
- package/dist/client/assets/stylus-ZoqbP9jE.svg +1 -0
- package/dist/client/assets/sublime-DFvp_Ess.svg +1 -0
- package/dist/client/assets/subtitles-BNOc1mEf.svg +1 -0
- package/dist/client/assets/supabase-CX7cap86.svg +1 -0
- package/dist/client/assets/svelte-B8HKO6BX.svg +1 -0
- package/dist/client/assets/svelte_js-C_RKcwSP.svg +1 -0
- package/dist/client/assets/svelte_ts-APH7lcVp.svg +1 -0
- package/dist/client/assets/svg-DVy7iktw.svg +1 -0
- package/dist/client/assets/svgo-CJXaeDEN.svg +1 -0
- package/dist/client/assets/svgr-Dn8OFGar.svg +1 -0
- package/dist/client/assets/swagger-Dqyrwr4g.svg +1 -0
- package/dist/client/assets/sway-C1Kkif7r.svg +1 -0
- package/dist/client/assets/swc-BUhoW8cb.svg +1 -0
- package/dist/client/assets/swift-D4_pkWil.svg +1 -0
- package/dist/client/assets/syncpack-DtZ994Gf.svg +1 -0
- package/dist/client/assets/table-YhsaNNk_.svg +1 -0
- package/dist/client/assets/tailwindcss-DODJSdj1.svg +1 -0
- package/dist/client/assets/tape-DGYhnMht.svg +1 -0
- package/dist/client/assets/taskfile-f5DM79_-.svg +1 -0
- package/dist/client/assets/tauri-DBBtDoCo.svg +1 -0
- package/dist/client/assets/taze-BPR9LgXp.svg +1 -0
- package/dist/client/assets/tcl-CiAJKGaA.svg +1 -0
- package/dist/client/assets/teal-WyfAQok0.svg +1 -0
- package/dist/client/assets/templ-BHla0pe-.svg +1 -0
- package/dist/client/assets/template-qJWiB5gQ.svg +1 -0
- package/dist/client/assets/terraform-R86_iPhv.svg +1 -0
- package/dist/client/assets/test-js-A34KrdbK.svg +1 -0
- package/dist/client/assets/test-jsx-C2PQBkQP.svg +1 -0
- package/dist/client/assets/test-ts-fdt299ek.svg +1 -0
- package/dist/client/assets/tex-DpewR4UN.svg +1 -0
- package/dist/client/assets/textlint-pjwsbDhs.svg +1 -0
- package/dist/client/assets/themeCatalog-B3yda95n.js +1 -0
- package/dist/client/assets/themePreference-BBiJxLjs.js +1 -0
- package/dist/client/assets/themeStartup-0b02tNrh.js +2 -0
- package/dist/client/assets/tilt-Dwon5dv-.svg +1 -0
- package/dist/client/assets/tldraw-BnDJmluq.svg +1 -0
- package/dist/client/assets/tobi-CQ-666uh.svg +1 -0
- package/dist/client/assets/tobimake-DzDbTYW1.svg +1 -0
- package/dist/client/assets/toc-nUTycYjl.svg +1 -0
- package/dist/client/assets/todo-CpcorlsE.svg +1 -0
- package/dist/client/assets/toml-DvUt-GOd.svg +1 -0
- package/dist/client/assets/toon-CGe9RDKY.svg +1 -0
- package/dist/client/assets/travis-CH6zNy43.svg +1 -0
- package/dist/client/assets/tree-epW9JaxP.svg +1 -0
- package/dist/client/assets/trigger-CqdxCyG0.svg +1 -0
- package/dist/client/assets/tsconfig-ROp_YdWL.svg +1 -0
- package/dist/client/assets/tsdoc-BEXcYgLD.svg +1 -0
- package/dist/client/assets/tsdown-B96z16my.svg +1 -0
- package/dist/client/assets/tsil-D-U9yWS8.svg +1 -0
- package/dist/client/assets/tune-DISlqKNZ.svg +1 -0
- package/dist/client/assets/turborepo-CWNwoZtI.svg +1 -0
- package/dist/client/assets/twig-CA70AYNK.svg +1 -0
- package/dist/client/assets/twine-BPJsGZd2.svg +1 -0
- package/dist/client/assets/typedoc-FY7jFoGW.svg +1 -0
- package/dist/client/assets/typescript-DjjXqw-n.svg +1 -0
- package/dist/client/assets/typescript-def-CTN5WM5i.svg +1 -0
- package/dist/client/assets/typst-CnDSkp_i.svg +1 -0
- package/dist/client/assets/uiua-BOsurlxn.svg +1 -0
- package/dist/client/assets/umi-DYOjFi8w.svg +1 -0
- package/dist/client/assets/uml-CYijxuna.svg +1 -0
- package/dist/client/assets/unity-CRNCEoK6.svg +1 -0
- package/dist/client/assets/unlicense-DG_b3BEE.svg +1 -0
- package/dist/client/assets/unocss-MqLuLfeL.svg +1 -0
- package/dist/client/assets/url-hE4h5p6b.svg +1 -0
- package/dist/client/assets/uv-DRTOVSi_.svg +1 -0
- package/dist/client/assets/vagrant-YnxMTuKe.svg +1 -0
- package/dist/client/assets/vala-m_i2ZWns.svg +1 -0
- package/dist/client/assets/vanilla-extract-76H6-A4R.svg +1 -0
- package/dist/client/assets/varnish-CX3oiNcp.svg +1 -0
- package/dist/client/assets/vedic-D6-oQUka.svg +1 -0
- package/dist/client/assets/velite-nLLNxKBA.svg +1 -0
- package/dist/client/assets/velocity-CSvfE9yM.svg +1 -0
- package/dist/client/assets/vercel-CgKLo9IO.svg +1 -0
- package/dist/client/assets/verdaccio-gsdiCbvv.svg +1 -0
- package/dist/client/assets/verified-BFLtqroG.svg +1 -0
- package/dist/client/assets/verilog-CbZvRaae.svg +1 -0
- package/dist/client/assets/verse-D_RZ0Bz0.svg +1 -0
- package/dist/client/assets/vfl-8CAM-hjs.svg +1 -0
- package/dist/client/assets/video-qxpJXkH6.svg +1 -0
- package/dist/client/assets/vim-CB8qTVuS.svg +1 -0
- package/dist/client/assets/virtual-Hoc2XbZN.svg +1 -0
- package/dist/client/assets/visualstudio-BHj2x5q7.svg +1 -0
- package/dist/client/assets/vite-JKzchVew.svg +1 -0
- package/dist/client/assets/vitest-Cl4_wKFu.svg +1 -0
- package/dist/client/assets/vlang-C3-DMUIm.svg +1 -0
- package/dist/client/assets/vscode-BtTXhPua.svg +1 -0
- package/dist/client/assets/vue-BlenztPP.svg +1 -0
- package/dist/client/assets/vue-config-o7yPAADv.svg +1 -0
- package/dist/client/assets/wakatime-DNz7qcxZ.svg +1 -0
- package/dist/client/assets/wallaby-C0UIkEOa.svg +1 -0
- package/dist/client/assets/wally-Ds1quKSG.svg +1 -0
- package/dist/client/assets/warp-B3X5Zoeh.svg +1 -0
- package/dist/client/assets/watchman-7EFq9LSa.svg +1 -0
- package/dist/client/assets/webassembly-Bs4UtU2T.svg +1 -0
- package/dist/client/assets/webhint-B4I6V0Ee.svg +1 -0
- package/dist/client/assets/webpack-zo2uWGOg.svg +1 -0
- package/dist/client/assets/wepy-Cho54Qlr.svg +1 -0
- package/dist/client/assets/werf-BW9FiKe5.svg +1 -0
- package/dist/client/assets/windicss-C_8y516i.svg +1 -0
- package/dist/client/assets/wolframlanguage-D6C1WBYh.svg +1 -0
- package/dist/client/assets/word-BcPLm6YH.svg +1 -0
- package/dist/client/assets/wrangler-CjgAkoTg.svg +1 -0
- package/dist/client/assets/wxt-c6drtC9H.svg +1 -0
- package/dist/client/assets/xaml-DE72OHNQ.svg +1 -0
- package/dist/client/assets/xmake-4WNmmIJj.svg +1 -0
- package/dist/client/assets/xml-S4aCxoUr.svg +1 -0
- package/dist/client/assets/yaml-DPTMsOTP.svg +1 -0
- package/dist/client/assets/yang-N-7dP4WI.svg +1 -0
- package/dist/client/assets/yarn-Cios8OFX.svg +1 -0
- package/dist/client/assets/zeabur-kqbNXTTH.svg +1 -0
- package/dist/client/assets/zig-CdphsgLN.svg +1 -0
- package/dist/client/assets/zip-GDnEynqi.svg +1 -0
- package/dist/client/assets/zizmor-IsFFdy6W.svg +1 -0
- package/dist/client/index.html +12 -6
- package/dist/config.js +233 -87
- package/dist/config.js.map +1 -1
- package/dist/configSessionNamingMigration.js +63 -0
- package/dist/configSessionNamingMigration.js.map +1 -0
- package/dist/nativeServices/serviceDoctor.js +3 -3
- package/dist/nativeServices/serviceDoctor.js.map +1 -1
- package/dist/nativeServices/servicePlan.js +53 -23
- package/dist/nativeServices/servicePlan.js.map +1 -1
- package/dist/nativeServices/serviceProbe.js +27 -7
- package/dist/nativeServices/serviceProbe.js.map +1 -1
- package/dist/pi-packages/relays/markdownDocument.js +8 -9
- package/dist/pi-packages/relays/pi-web-plugin.js +11 -11
- package/dist/pi-packages/relays/relays.messages.js +38 -0
- package/dist/pi-packages/relays/relaysLocalization.js +19 -0
- package/dist/pi-packages/relays/relaysPanelElement.js +151 -96
- package/dist/pi-packages/scheduled-tasks/browser/pi-web-plugin.js +1135 -0
- package/dist/pi-packages/scheduled-tasks/domain.js +63 -0
- package/dist/pi-packages/scheduled-tasks/extensions/index.js +710 -0
- package/dist/pi-packages/scheduled-tasks/package.json +30 -0
- package/dist/pi-packages/scheduled-tasks/scheduler.js +89 -0
- package/dist/pi-packages/scheduled-tasks/server-plugin.js +9872 -0
- package/dist/pi-packages/scheduled-tasks/service.js +178 -0
- package/dist/pi-packages/scheduled-tasks/skills/scheduled-tasks/SKILL.md +30 -0
- package/dist/pi-packages/scheduled-tasks/sqlite.js +18 -0
- package/dist/pi-packages/scheduled-tasks/store.js +230 -0
- package/dist/pi-packages/scheduled-tasks/vite.browser.config.mjs +16 -0
- package/dist/pi-packages/scheduled-tasks/vite.companion.config.mjs +17 -0
- package/dist/pi-packages/scheduled-tasks/vite.config.mjs +17 -0
- package/dist/pi-packages/session-naming/config.js +78 -0
- package/dist/pi-packages/session-naming/extensions/index.js +74 -0
- package/dist/pi-packages/session-naming/generator.js +76 -0
- package/dist/pi-packages/session-naming/package.json +15 -0
- package/dist/pi-packages/workflows/browser/pi-web-plugin.js +10 -7
- package/dist/pi-packages/workflows/browser/workflows.messages.js +32 -0
- package/dist/pi-packages/workflows/browser/worktreeDialog.js +71 -50
- package/dist/pi-packages/workflows/server-plugin.js +137 -23
- package/dist/pi-web-plugins/audio/audioElement.js +61 -0
- package/dist/pi-web-plugins/audio/audioFormats.js +18 -0
- package/dist/pi-web-plugins/audio/byteRange.js +21 -0
- package/dist/pi-web-plugins/audio/package.json +10 -0
- package/dist/pi-web-plugins/audio/pi-web-plugin.js +39 -0
- package/dist/pi-web-plugins/audio/server.js +71 -0
- package/dist/pi-web-plugins/code-highlight/browser/pi-web-plugin.js +4 -4
- package/dist/pi-web-plugins/custom-ui-codex/codex.css +8 -0
- package/dist/pi-web-plugins/custom-ui-codex/fileIcons.js +30 -0
- package/dist/pi-web-plugins/custom-ui-codex/package.json +8 -1
- package/dist/pi-web-plugins/custom-ui-codex/pi-web-plugin.js +8 -8
- package/dist/pi-web-plugins/files/browser/pi-web-plugin.js +236 -259
- package/dist/pi-web-plugins/git/browser/git-panel.js +138 -59
- package/dist/pi-web-plugins/git/browser/git.messages.js +47 -0
- package/dist/pi-web-plugins/git/browser/gitFileIcon.js +71 -0
- package/dist/pi-web-plugins/git/browser/pi-web-plugin.js +21 -4
- package/dist/pi-web-plugins/git/server-plugin.js +5 -3
- package/dist/pi-web-plugins/info/info.messages.js +66 -0
- package/dist/pi-web-plugins/info/infoInternals.js +217 -217
- package/dist/pi-web-plugins/info/pi-web-plugin.js +19 -14
- package/dist/pi-web-plugins/language-spanish/catalogs.js +1896 -0
- package/dist/pi-web-plugins/language-spanish/package.json +14 -0
- package/dist/pi-web-plugins/language-spanish/pi-web-plugin.js +90 -0
- package/dist/pi-web-plugins/language-swedish/catalogs.js +1896 -0
- package/dist/pi-web-plugins/language-swedish/package.json +14 -0
- package/dist/pi-web-plugins/language-swedish/pi-web-plugin.js +89 -0
- package/dist/pi-web-plugins/mermaid/browser/pi-web-plugin.js +4 -4
- package/dist/pi-web-plugins/terminal/browser/pi-web-plugin.js +71 -66
- package/dist/pi-web-plugins/terminal/bunPtyProvider.js +109 -0
- package/dist/pi-web-plugins/terminal/nodePtyProvider.js +75 -0
- package/dist/pi-web-plugins/terminal/nodePtySpawnHelper.js +36 -0
- package/dist/pi-web-plugins/terminal/ptyComposition.js +12 -0
- package/dist/pi-web-plugins/terminal/ptyProvider.js +2 -0
- package/dist/pi-web-plugins/terminal/server-plugin.js +42 -14
- package/dist/pi-web-plugins/terminal/terminalService.js +218 -76
- package/dist/pi-web-plugins/themes/assets/graphite.css +56 -0
- package/dist/pi-web-plugins/themes/assets/paper.css +56 -0
- package/dist/pi-web-plugins/themes/package.json +21 -0
- package/dist/pi-web-plugins/updates/pi-web-plugin.js +200 -155
- package/dist/pi-web-plugins/updates/updates.messages.js +59 -0
- package/dist/pi-web-plugins/updates/updatesLogic.js +27 -29
- package/dist/pi-web-plugins/workspace-tasks/config.js +18 -19
- package/dist/pi-web-plugins/workspace-tasks/pi-web-plugin.js +13 -8
- package/dist/pi-web-plugins/workspace-tasks/tasks.messages.js +45 -0
- package/dist/pi-web-plugins/workspace-tasks/tasksLocalization.js +33 -0
- package/dist/pi-web-plugins/workspace-tasks/tasksPanelElement.js +56 -42
- package/dist/pi-web-plugins/workspace-tasks/workspaceTasksClient.js +7 -33
- package/dist/pi-web-plugins/zh-cn/catalogs.json +1803 -0
- package/dist/pi-web-plugins/zh-cn/main.json +5 -1
- package/dist/pi-web-plugins/zh-cn/management-errors.json +6 -0
- package/dist/pi-web-plugins/zh-cn/pi-web-plugin.js +13 -4
- package/dist/pi-web-plugins/zh-cn/server.json +1 -1
- package/dist/piWebVersionReport.js +2 -0
- package/dist/piWebVersionReport.js.map +1 -1
- package/dist/plugin-api.d.ts +194 -9
- package/dist/runtimePreflight.js +14 -0
- package/dist/runtimePreflight.js.map +1 -0
- package/dist/server/activity/workspaceActivityService.js +18 -1
- package/dist/server/activity/workspaceActivityService.js.map +1 -1
- package/dist/server/app.js +45 -10
- package/dist/server/app.js.map +1 -1
- package/dist/server/configRoutes.js +117 -139
- package/dist/server/configRoutes.js.map +1 -1
- package/dist/server/configUpdates.js +104 -0
- package/dist/server/configUpdates.js.map +1 -0
- package/dist/server/deploymentIdentity.js +12 -10
- package/dist/server/deploymentIdentity.js.map +1 -1
- package/dist/server/deploymentIdentityRoutes.js +2 -1
- package/dist/server/deploymentIdentityRoutes.js.map +1 -1
- package/dist/server/diagnostics/nodePtyNativeModule.js +0 -18
- package/dist/server/diagnostics/nodePtyNativeModule.js.map +1 -1
- package/dist/server/diagnostics/terminalPrerequisites.js +54 -0
- package/dist/server/diagnostics/terminalPrerequisites.js.map +1 -0
- package/dist/server/index.js +9 -0
- package/dist/server/index.js.map +1 -1
- package/dist/server/knownAutoInstallPiPackages.js +6 -0
- package/dist/server/knownAutoInstallPiPackages.js.map +1 -1
- package/dist/server/knownPiPackages.js +4 -4
- package/dist/server/knownPiPackages.js.map +1 -1
- package/dist/server/machines/machineClient.js +39 -17
- package/dist/server/machines/machineClient.js.map +1 -1
- package/dist/server/machines/machinePluginProxyRoutes.js +3 -1
- package/dist/server/machines/machinePluginProxyRoutes.js.map +1 -1
- package/dist/server/machines/machineProxyRoutes.js +60 -9
- package/dist/server/machines/machineProxyRoutes.js.map +1 -1
- package/dist/server/machines/machineService.js +81 -13
- package/dist/server/machines/machineService.js.map +1 -1
- package/dist/server/machines/machineStore.js.map +1 -1
- package/dist/server/managementEmbed.js +4 -1
- package/dist/server/managementEmbed.js.map +1 -1
- package/dist/server/managementEntryRoutes.js +51 -0
- package/dist/server/managementEntryRoutes.js.map +1 -0
- package/dist/server/managementEntryTickets.js +46 -0
- package/dist/server/managementEntryTickets.js.map +1 -0
- package/dist/server/managementTransportLimits.js +5 -0
- package/dist/server/managementTransportLimits.js.map +1 -0
- package/dist/server/navigationPreferenceRoutes.js +20 -1
- package/dist/server/navigationPreferenceRoutes.js.map +1 -1
- package/dist/server/normalAuth.js +3 -1
- package/dist/server/normalAuth.js.map +1 -1
- package/dist/server/notices/serverNoticeStore.js +4 -0
- package/dist/server/notices/serverNoticeStore.js.map +1 -1
- package/dist/server/piPackageService.js +15 -1
- package/dist/server/piPackageService.js.map +1 -1
- package/dist/server/piWebPluginCatalog.js +23 -11
- package/dist/server/piWebPluginCatalog.js.map +1 -1
- package/dist/server/piWebPluginLifecycle.js +14 -4
- package/dist/server/piWebPluginLifecycle.js.map +1 -1
- package/dist/server/piWebPluginService.js +11 -5
- package/dist/server/piWebPluginService.js.map +1 -1
- package/dist/server/piWebStatus.js +12 -10
- package/dist/server/piWebStatus.js.map +1 -1
- package/dist/server/piWebStatusCache.js +3 -1
- package/dist/server/piWebStatusCache.js.map +1 -1
- package/dist/server/plugins/pluginBackendRegistry.js +229 -4
- package/dist/server/plugins/pluginBackendRegistry.js.map +1 -1
- package/dist/server/plugins/pluginBackendResourceProxyRoutes.js +40 -0
- package/dist/server/plugins/pluginBackendResourceProxyRoutes.js.map +1 -0
- package/dist/server/plugins/pluginBackendResourceResponse.js +84 -0
- package/dist/server/plugins/pluginBackendResourceResponse.js.map +1 -0
- package/dist/server/plugins/projectPluginSettings.js +9 -2
- package/dist/server/plugins/projectPluginSettings.js.map +1 -1
- package/dist/server/plugins/serverPluginCatalogCapability.js +7 -2
- package/dist/server/plugins/serverPluginCatalogCapability.js.map +1 -1
- package/dist/server/plugins/serverPluginPiSessionsCapability.js +16 -3
- package/dist/server/plugins/serverPluginPiSessionsCapability.js.map +1 -1
- package/dist/server/plugins/serverPluginRuntime.js +25 -9
- package/dist/server/plugins/serverPluginRuntime.js.map +1 -1
- package/dist/server/plugins/serverPluginSessionLifecycleCapability.js +87 -0
- package/dist/server/plugins/serverPluginSessionLifecycleCapability.js.map +1 -0
- package/dist/server/requestLogging.js +1 -1
- package/dist/server/requestLogging.js.map +1 -1
- package/dist/server/sessiond/agentHttpDispatcher.js +14 -7
- package/dist/server/sessiond/agentHttpDispatcher.js.map +1 -1
- package/dist/server/sessiond/autoInstallPiPackageSources.js +54 -0
- package/dist/server/sessiond/autoInstallPiPackageSources.js.map +1 -0
- package/dist/server/sessiond/autoInstallPiPackages.js +77 -30
- package/dist/server/sessiond/autoInstallPiPackages.js.map +1 -1
- package/dist/server/sessiond/pluginBackendChannelRoutes.js +3 -13
- package/dist/server/sessiond/pluginBackendChannelRoutes.js.map +1 -1
- package/dist/server/sessiond/pluginBackendResourceRoutes.js +62 -0
- package/dist/server/sessiond/pluginBackendResourceRoutes.js.map +1 -0
- package/dist/server/sessiond/pluginSessionLifecycleRoutes.js +45 -0
- package/dist/server/sessiond/pluginSessionLifecycleRoutes.js.map +1 -0
- package/dist/server/sessiond/sessionProxyRoutes.js +55 -11
- package/dist/server/sessiond/sessionProxyRoutes.js.map +1 -1
- package/dist/server/sessiond/sessionServiceDependencies.js +3 -0
- package/dist/server/sessiond/sessionServiceDependencies.js.map +1 -1
- package/dist/server/sessiond.js +46 -15
- package/dist/server/sessiond.js.map +1 -1
- package/dist/server/sessions/askUserDomain.js +24 -2
- package/dist/server/sessions/askUserDomain.js.map +1 -1
- package/dist/server/sessions/askUserTool.js +1 -1
- package/dist/server/sessions/askUserTool.js.map +1 -1
- package/dist/server/sessions/dockerEnvironmentFacts.js +10 -9
- package/dist/server/sessions/dockerEnvironmentFacts.js.map +1 -1
- package/dist/server/sessions/mcpOAuthCredentialAdapter.js +4 -4
- package/dist/server/sessions/mcpOAuthCredentialAdapter.js.map +1 -1
- package/dist/server/sessions/piSessionService.js +490 -257
- package/dist/server/sessions/piSessionService.js.map +1 -1
- package/dist/server/sessions/requestHumanInterventionTool.js +27 -0
- package/dist/server/sessions/requestHumanInterventionTool.js.map +1 -0
- package/dist/server/sessions/sendSessionMessageTool.js +32 -0
- package/dist/server/sessions/sendSessionMessageTool.js.map +1 -0
- package/dist/server/sessions/sessionActivityCoordinator.js.map +1 -1
- package/dist/server/sessions/sessionCleanup.js +18 -1
- package/dist/server/sessions/sessionCleanup.js.map +1 -1
- package/dist/server/sessions/sessionCommandService.js +58 -52
- package/dist/server/sessions/sessionCommandService.js.map +1 -1
- package/dist/server/sessions/sessionContentSearch.js +103 -30
- package/dist/server/sessions/sessionContentSearch.js.map +1 -1
- package/dist/server/sessions/sessionIntervention.js +29 -0
- package/dist/server/sessions/sessionIntervention.js.map +1 -0
- package/dist/server/sessions/sessionNameGenerator.js +0 -60
- package/dist/server/sessions/sessionNameGenerator.js.map +1 -1
- package/dist/server/sessions/sessionNotificationStore.js +2 -1
- package/dist/server/sessions/sessionNotificationStore.js.map +1 -1
- package/dist/server/sessions/sessionRoutes.js +25 -1
- package/dist/server/sessions/sessionRoutes.js.map +1 -1
- package/dist/server/sessions/sessionSummaryScanner.js +8 -0
- package/dist/server/sessions/sessionSummaryScanner.js.map +1 -1
- package/dist/server/sessions/sessionTreeProjection.js +108 -97
- package/dist/server/sessions/sessionTreeProjection.js.map +1 -1
- package/dist/server/sessions/sessionUiEvents.js +2 -0
- package/dist/server/sessions/sessionUiEvents.js.map +1 -1
- package/dist/server/sessions/sessionUnreadStore.js +11 -1
- package/dist/server/sessions/sessionUnreadStore.js.map +1 -1
- package/dist/server/sessions/spawnSubsessionTool.js +66 -15
- package/dist/server/sessions/spawnSubsessionTool.js.map +1 -1
- package/dist/server/sessions/subsessionCompletionDelivery.js +6 -3
- package/dist/server/sessions/subsessionCompletionDelivery.js.map +1 -1
- package/dist/server/sessions/subsessionCompletionInbox.js +6 -9
- package/dist/server/sessions/subsessionCompletionInbox.js.map +1 -1
- package/dist/server/status/machineStatusService.js +15 -3
- package/dist/server/status/machineStatusService.js.map +1 -1
- package/dist/server/storage/navigationPreferenceStore.js +11 -0
- package/dist/server/storage/navigationPreferenceStore.js.map +1 -1
- package/dist/server/storage/sessionPinStore.js +95 -0
- package/dist/server/storage/sessionPinStore.js.map +1 -0
- package/dist/server/terminals/maintenanceExecutionContext.js +18 -0
- package/dist/server/terminals/maintenanceExecutionContext.js.map +1 -0
- package/dist/server/terminals/maintenanceTerminalCapability.js +25 -0
- package/dist/server/terminals/maintenanceTerminalCapability.js.map +1 -0
- package/dist/server/terminals/requiredTerminalService.js.map +1 -1
- package/dist/server/terminals/terminalStatusRoutes.js +22 -0
- package/dist/server/terminals/terminalStatusRoutes.js.map +1 -0
- package/dist/server/themeBootstrap.js +123 -0
- package/dist/server/themeBootstrap.js.map +1 -0
- package/dist/server/themeCatalog.js +206 -0
- package/dist/server/themeCatalog.js.map +1 -0
- package/dist/server/themeMetadata.js +74 -0
- package/dist/server/themeMetadata.js.map +1 -0
- package/dist/server/webSocketBridge.js +16 -12
- package/dist/server/webSocketBridge.js.map +1 -1
- package/dist/server/webSocketPayloadLimit.js +17 -0
- package/dist/server/webSocketPayloadLimit.js.map +1 -0
- package/dist/server/workspaces/effectivePathAccess.js +1 -1
- package/dist/server/workspaces/effectivePathAccess.js.map +1 -1
- package/dist/server/workspaces/projectPiWebConfig.js +30 -7
- package/dist/server/workspaces/projectPiWebConfig.js.map +1 -1
- package/dist/server/workspaces/sessionDaemonWorkspaceCatalog.js +2 -0
- package/dist/server/workspaces/sessionDaemonWorkspaceCatalog.js.map +1 -1
- package/dist/server/workspaces/workspaceProviderRegistry.js +6 -2
- package/dist/server/workspaces/workspaceProviderRegistry.js.map +1 -1
- package/dist/server/workspaces/workspaceRemovalService.js +6 -4
- package/dist/server/workspaces/workspaceRemovalService.js.map +1 -1
- package/dist/server-plugin-api.d.ts +39 -1
- package/dist/server-plugin-api.js +18 -3
- package/dist/server-plugin-api.js.map +1 -1
- package/dist/sessiond/sessionDaemonClient.js +7 -1
- package/dist/sessiond/sessionDaemonClient.js.map +1 -1
- package/dist/sessiond/sessionDaemonTerminalStatus.js +27 -0
- package/dist/sessiond/sessionDaemonTerminalStatus.js.map +1 -0
- package/dist/shared/apiTypes.js +4 -0
- package/dist/shared/apiTypes.js.map +1 -1
- package/dist/shared/capabilities.js +6 -0
- package/dist/shared/capabilities.js.map +1 -1
- package/dist/shared/commandOutputPresentation.js +17 -0
- package/dist/shared/commandOutputPresentation.js.map +1 -0
- package/dist/shared/commandResultPresentation.js +51 -0
- package/dist/shared/commandResultPresentation.js.map +1 -0
- package/dist/shared/configResolution.js +99 -0
- package/dist/shared/configResolution.js.map +1 -0
- package/dist/shared/defaultLocalization.js +60 -0
- package/dist/shared/defaultLocalization.js.map +1 -0
- package/dist/shared/federatedRoutes.js +11 -1
- package/dist/shared/federatedRoutes.js.map +1 -1
- package/dist/shared/installationName.js +21 -0
- package/dist/shared/installationName.js.map +1 -0
- package/dist/shared/localization.d.ts +55 -0
- package/dist/shared/localization.js +4 -0
- package/dist/shared/machineStatus.js +2 -0
- package/dist/shared/machineStatus.js.map +1 -1
- package/dist/shared/piWebConfigParsing.js +16 -30
- package/dist/shared/piWebConfigParsing.js.map +1 -1
- package/dist/shared/piWebRuntime.js +17 -0
- package/dist/shared/piWebRuntime.js.map +1 -0
- package/dist/shared/piWebStatusParsing.js +5 -0
- package/dist/shared/piWebStatusParsing.js.map +1 -1
- package/dist/shared/pluginApiTypes.d.ts +35 -7
- package/dist/shared/pluginBackendProtocol.js +24 -0
- package/dist/shared/pluginBackendProtocol.js.map +1 -1
- package/dist/shared/pluginCatalogTypes.d.ts +8 -0
- package/dist/shared/pluginCatalogTypes.js +15 -0
- package/dist/shared/pluginCatalogTypes.js.map +1 -1
- package/dist/shared/pluginResourceMetadata.js +58 -0
- package/dist/shared/pluginResourceMetadata.js.map +1 -0
- package/dist/shared/pluginSessionLifecycleTypes.d.ts +24 -0
- package/dist/shared/pluginSessionLifecycleTypes.js +56 -0
- package/dist/shared/pluginSessionLifecycleTypes.js.map +1 -0
- package/dist/shared/serverNoticePresentation.d.ts +9 -0
- package/dist/shared/serverNoticePresentation.js +12 -0
- package/dist/shared/serverNoticePresentation.js.map +1 -0
- package/dist/shared/sessionActivityPresentation.js +73 -0
- package/dist/shared/sessionActivityPresentation.js.map +1 -0
- package/dist/shared/sessionNotificationPresentation.js +16 -0
- package/dist/shared/sessionNotificationPresentation.js.map +1 -0
- package/dist/shared/terminalCommandRun.js +4 -0
- package/dist/shared/terminalCommandRun.js.map +1 -1
- package/dist/shared/terminalServiceStatus.js +14 -0
- package/dist/shared/terminalServiceStatus.js.map +1 -0
- package/dist/shared/terminalTitlePresentation.d.ts +10 -0
- package/dist/shared/terminalTitlePresentation.js +13 -0
- package/dist/shared/terminalTitlePresentation.js.map +1 -0
- package/dist/shared/themeCatalog.js +2 -0
- package/dist/shared/themeCatalog.js.map +1 -0
- package/dist/shared/themePreference.js +1 -0
- package/dist/shared/themePreference.js.map +1 -1
- package/dist/shared/thinkingLevels.d.ts +29 -0
- package/dist/shared/thinkingLevels.js +6 -4
- package/dist/shared/thinkingLevels.js.map +1 -1
- package/dist/shared/versionCheckPolicy.js +10 -0
- package/dist/shared/versionCheckPolicy.js.map +1 -0
- package/dist/shared/workspaceRemovalPresentation.d.ts +8 -0
- package/dist/shared/workspaceRemovalPresentation.js +10 -0
- package/dist/shared/workspaceRemovalPresentation.js.map +1 -0
- package/docs/README.md +7 -3
- package/docs/assets/pi-web-desktop-graphite.png +0 -0
- package/docs/assets/pi-web-desktop-paper.png +0 -0
- package/docs/assets/pi-web-desktop-pi-web-dark.png +0 -0
- package/docs/assets/pi-web-desktop-pi-web-light.png +0 -0
- package/docs/assets/pi-web-desktop.png +0 -0
- package/docs/assets/pi-web-mobile-graphite.png +0 -0
- package/docs/assets/pi-web-mobile-paper.png +0 -0
- package/docs/assets/pi-web-mobile-pi-web-dark.png +0 -0
- package/docs/assets/pi-web-mobile-pi-web-light.png +0 -0
- package/docs/assets/pi-web-mobile-themes.gif +0 -0
- package/docs/assets/pi-web-mobile.png +0 -0
- package/docs/assets/pi-web-tablet-graphite.png +0 -0
- package/docs/assets/pi-web-tablet-paper.png +0 -0
- package/docs/assets/pi-web-tablet-pi-web-dark.png +0 -0
- package/docs/assets/pi-web-tablet-pi-web-light.png +0 -0
- package/docs/assets/pi-web-tablet-themes.gif +0 -0
- package/docs/assets/pi-web-tablet.png +0 -0
- package/docs/assets/pi-web-themes.gif +0 -0
- package/docs/config.md +193 -55
- package/docs/plugins.md +350 -21
- package/docs/scheduled-tasks.md +127 -0
- package/package.json +43 -19
- package/dist/client/assets/CommandPicker-8oDe6AaV.js +0 -70
- package/dist/client/assets/PiWebApp-TCQVYghs.js +0 -3761
- package/dist/client/assets/SettingsDialog-DFUpwUyp.js +0 -1015
- package/dist/client/assets/index-DzMPXVth.js +0 -2
- package/dist/client/assets/managementEmbed-Bx8Mwzdw.js +0 -2
- package/dist/client/assets/preload-helper-XpATwJ5c.js +0 -1
- package/dist/pi-packages/captains-log/README.md +0 -11
- package/dist/pi-packages/captains-log/dist/browser/channelProtocol.js +0 -29
- package/dist/pi-packages/captains-log/dist/browser/index.js +0 -143
- package/dist/pi-packages/captains-log/dist/browser/markdown.js +0 -68
- package/dist/pi-packages/captains-log/dist/browser/panel.js +0 -148
- package/dist/pi-packages/captains-log/dist/browser/protocol.js +0 -26
- package/dist/pi-packages/captains-log/dist/companion.js +0 -126
- package/dist/pi-packages/captains-log/dist/roundtrip.js +0 -62
- package/dist/pi-packages/captains-log/dist/server.js +0 -210
- package/dist/pi-packages/captains-log/dist/store.js +0 -75
- package/dist/pi-packages/captains-log/docs/usage.md +0 -29
- package/dist/pi-packages/captains-log/i18n.js +0 -7
- package/dist/pi-packages/captains-log/package.json +0 -35
- package/dist/pi-packages/captains-log/tsconfig.json +0 -21
- package/dist/pi-packages/captains-log/vite.config.mjs +0 -28
- package/examples/session-bridge-plugin/README.md +0 -20
- package/examples/session-bridge-plugin/docs/usage.md +0 -54
- package/examples/session-bridge-plugin/package.json +0 -26
- package/examples/session-bridge-plugin/src/browser/index.ts +0 -87
- package/examples/session-bridge-plugin/src/browser/protocol.ts +0 -24
- package/examples/session-bridge-plugin/src/companion.ts +0 -65
- package/examples/session-bridge-plugin/src/reviewRun.ts +0 -39
- package/examples/session-bridge-plugin/src/server.ts +0 -85
- package/examples/session-bridge-plugin/src/store.ts +0 -80
- package/examples/session-bridge-plugin/tsconfig.json +0 -21
- /package/dist/{client/assets/classic-CyM97Akm.css → pi-web-plugins/themes/assets/classic.css} +0 -0
- /package/dist/{client/assets/pi-web-dark-D_KtbM95.css → pi-web-plugins/themes/assets/pi-web-dark.css} +0 -0
- /package/dist/{client/assets/pi-web-light-DSNLMIBI.css → pi-web-plugins/themes/assets/pi-web-light.css} +0 -0
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { parsePersistedChildSubsessionLink, parsePersistedParentSubsessionLink } from "./subsessionProvenance.js";
|
|
2
2
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
3
3
|
import { createHash, randomUUID } from "node:crypto";
|
|
4
|
+
import { sessionNotificationSources } from "../../shared/sessionNotificationPresentation.js";
|
|
5
|
+
import { runtimeActivityFallbackLabel } from "../../shared/sessionActivityPresentation.js";
|
|
6
|
+
const STARTUP_PHASE_RUNTIME = "Starting the Pi session";
|
|
7
|
+
const STARTUP_PHASE_EXTENSIONS = "Loading session extensions";
|
|
8
|
+
const STARTUP_CONCURRENT_CATALOG_REFRESH = "provider model lists are refreshing";
|
|
4
9
|
import { readSessionUiMetadata, requireSessionUiMetadata, SESSION_UI_METADATA_CUSTOM_TYPE } from "./sessionMetadata.js";
|
|
5
10
|
import { UserFacingError, createTranslator, userFacingErrorMessage } from "../../shared/i18n.js";
|
|
6
11
|
import { realpathSync, statSync } from "node:fs";
|
|
@@ -26,7 +31,7 @@ import { SessionActivityMarker } from "./sessionActivityMarker.js";
|
|
|
26
31
|
import { projectSessionTree } from "./sessionTreeProjection.js";
|
|
27
32
|
import { SessionArchiveStore } from "./sessionArchiveStore.js";
|
|
28
33
|
import { findArchiveCandidateByExactId, planSessionArchiveTree } from "./sessionArchiveTree.js";
|
|
29
|
-
import {
|
|
34
|
+
import { requireInitialSessionName } from "./sessionNameGenerator.js";
|
|
30
35
|
import { computeEditPreview } from "./editPreview.js";
|
|
31
36
|
import { attachmentsToInlineImages, saveAttachmentsToWorkspace } from "./attachmentService.js";
|
|
32
37
|
import { loadEffectiveProjectAttachmentsConfig } from "../workspaces/projectPiWebConfig.js";
|
|
@@ -37,16 +42,18 @@ import { resolveWebProjectTrusted } from "./projectTrust.js";
|
|
|
37
42
|
import { createPiSessionManagerGateway } from "./piSessionManagerGateway.js";
|
|
38
43
|
import { SessionPinStore } from "./sessionPinStore.js";
|
|
39
44
|
import { SessionActivityCoordinator } from "./sessionActivityCoordinator.js";
|
|
40
|
-
import { searchSessionContent } from "./sessionContentSearch.js";
|
|
45
|
+
import { compileSessionContentQuery, searchSessionContent } from "./sessionContentSearch.js";
|
|
41
46
|
import { createLocalOnlyModelRuntime, modelRuntimeAuthPath } from "./authService.js";
|
|
42
47
|
import { canonicalizeStoredCwd, cwdPathsEqual } from "../workingDirectory.js";
|
|
43
48
|
import { clearSessionFileParent, readSessionHeaderSummary } from "./sessionFileHeader.js";
|
|
44
|
-
import { isManagedAgentsFile, workbenchAccessHandle } from "../managementEmbed.js";
|
|
49
|
+
import { assertManagedCwd, isManagedAgentsFile, workbenchAccessHandle } from "../managementEmbed.js";
|
|
45
50
|
import { managementPrivilegeRequested, managementPrivileges, managementUsesNormalPermissions } from "../managementPrivileges.js";
|
|
46
51
|
import { DEFAULT_EXTENSION_DIALOGS_TIMEOUT_MS, piWebDataDir } from "../../config.js";
|
|
47
52
|
import { createScopedSettingsManager, resolveSettingsScopeDirectory } from "./projectSettingsScope.js";
|
|
48
53
|
import { parseSessionDefaults, parseSessionDefaultsUpdate } from "../../shared/sessionDefaults.js";
|
|
49
54
|
import { createAskUserToolDefinition } from "./askUserTool.js";
|
|
55
|
+
import { createRequestHumanInterventionToolDefinition } from "./requestHumanInterventionTool.js";
|
|
56
|
+
import { requestsHumanIntervention, SESSION_INTERVENTION_CUSTOM_TYPE, sessionInterventionRequired } from "./sessionIntervention.js";
|
|
50
57
|
import { createAskUserOutcome, renderAskUserAnswersText, resolveAskUserRequest } from "./askUserDomain.js";
|
|
51
58
|
import { createSubsessionCompletionDelivery } from "./subsessionCompletionDelivery.js";
|
|
52
59
|
import { completionReceiptIds, persistedSubsessionCompletions, renderSubsessionCompletions, SUBSESSION_COMPLETION_ENTRY_TYPE, SUBSESSION_NOTIFICATION_CUSTOM_TYPE, SUBSESSION_RECEIPT_ENTRY_TYPE, SubsessionCompletionInbox } from "./subsessionCompletionInbox.js";
|
|
@@ -56,6 +63,7 @@ import { ExtensionDialogWaiters, effectiveExtensionDialogTimeoutMs, extensionDia
|
|
|
56
63
|
import { createSpawnSessionToolDefinition } from "./spawnSessionTool.js";
|
|
57
64
|
import { createSubsessionToolDefinitions } from "./spawnSubsessionTool.js";
|
|
58
65
|
import { buildTranscriptView } from "./subsessionTranscript.js";
|
|
66
|
+
import { createSendSessionMessageToolDefinition } from "./sendSessionMessageTool.js";
|
|
59
67
|
import { planSessionCleanup, summarizeSessionCleanupExecution } from "./sessionCleanup.js";
|
|
60
68
|
import { createManagedAgentToolOptions, createManagedBashToolDefinition, createManagedPythonToolDefinition } from "./managementAgentTools.js";
|
|
61
69
|
import { PI_PERMISSION_SYSTEM_POLICY_AGENT_DIR, managementAgentToolNames, privilegedManagementToolNames, withRuntimeCreationEnvironment, writeManagementPermissionSystemPolicy } from "./managementPermissionSystem.js";
|
|
@@ -311,7 +319,8 @@ export function collectRuntimeWarnings(runtime) {
|
|
|
311
319
|
/**
|
|
312
320
|
* Verbatim TUI wording for the Anthropic subscription-auth billing notice. Kept
|
|
313
321
|
* character-for-character in sync with `ANTHROPIC_SUBSCRIPTION_AUTH_WARNING` in
|
|
314
|
-
* the SDK's interactive mode
|
|
322
|
+
* the SDK's interactive mode as the wire fallback. Browser presentation metadata
|
|
323
|
+
* allows translation without matching this English string.
|
|
315
324
|
*/
|
|
316
325
|
const ANTHROPIC_SUBSCRIPTION_AUTH_WARNING = "Anthropic subscription auth is active. Third-party harness usage draws from extra usage and is billed per token, not your Claude plan limits. Manage extra usage at https://claude.ai/settings/usage.";
|
|
317
326
|
/** Mirror of the SDK TUI `isAnthropicSubscriptionAuthKey` (subscription API keys start with `sk-ant-oat`). */
|
|
@@ -352,6 +361,7 @@ export function anthropicSubscriptionWarning(session, authPath) {
|
|
|
352
361
|
return {
|
|
353
362
|
severity: "warning",
|
|
354
363
|
message: ANTHROPIC_SUBSCRIPTION_AUTH_WARNING,
|
|
364
|
+
presentation: { kind: "anthropicSubscriptionAuth" },
|
|
355
365
|
source: "anthropic",
|
|
356
366
|
dismiss: { id: ANTHROPIC_EXTRA_USAGE_DISMISS_ID },
|
|
357
367
|
};
|
|
@@ -438,11 +448,11 @@ async function createNormalPermissionSessionServices(options) {
|
|
|
438
448
|
});
|
|
439
449
|
return { services, projectTrustDiagnostics };
|
|
440
450
|
}
|
|
441
|
-
function createDefaultRuntimeFactory(sessionEvents, normalModelRuntimeForCwd, managementModelRuntime, resolveSettingsScope, sessionManagers, spawn, subsessions, askUserEnabled = false, workbench, logger = noopLogger, managementAudit, managementProjectIdForCwd, appendSystemPromptSections = [], managementAllowPrivileged = false) {
|
|
451
|
+
function createDefaultRuntimeFactory(sessionEvents, normalModelRuntimeForCwd, managementModelRuntime, resolveSettingsScope, sessionManagers, spawn, subsessions, askUserEnabled = false, workbench, logger = noopLogger, managementAudit, managementProjectIdForCwd, appendSystemPromptSections = [], managementAllowPrivileged = false, messaging) {
|
|
442
452
|
return async ({ cwd, agentDir, sessionManager, sessionStartEvent, managementContext, initialModel, initialThinkingLevel, delegationToolsEnabled }) => {
|
|
443
453
|
const scopedModelRuntime = managementContext === undefined ? await normalModelRuntimeForCwd(cwd) : await managementModelRuntime();
|
|
444
454
|
if (managementContext !== undefined) {
|
|
445
|
-
return createManagementRuntimeFactory(scopedModelRuntime, resolveSettingsScope, sessionManagers, spawn, subsessions, askUserEnabled, managementContext, workbench, logger, managementAudit, managementProjectIdForCwd, managementAllowPrivileged, appendSystemPromptSections)({
|
|
455
|
+
return createManagementRuntimeFactory(scopedModelRuntime, resolveSettingsScope, sessionManagers, spawn, subsessions, askUserEnabled, managementContext, workbench, logger, managementAudit, managementProjectIdForCwd, managementAllowPrivileged, appendSystemPromptSections, messaging)({
|
|
446
456
|
cwd,
|
|
447
457
|
agentDir,
|
|
448
458
|
sessionManager,
|
|
@@ -454,6 +464,8 @@ function createDefaultRuntimeFactory(sessionEvents, normalModelRuntimeForCwd, ma
|
|
|
454
464
|
}
|
|
455
465
|
// Resource loaders may read process.env; wait for managed overrides to be restored.
|
|
456
466
|
return withRuntimeCreationEnvironment({}, async () => {
|
|
467
|
+
const parentSessionFile = sessionManager.getHeader()?.parentSession;
|
|
468
|
+
const parentHeader = parentSessionFile === undefined ? undefined : await readSessionHeaderSummary(parentSessionFile);
|
|
457
469
|
const projectTrustRequiring = hasTrustRequiringProjectResources(cwd);
|
|
458
470
|
const settingsManager = await createScopedSettingsManager({
|
|
459
471
|
cwd,
|
|
@@ -473,7 +485,10 @@ function createDefaultRuntimeFactory(sessionEvents, normalModelRuntimeForCwd, ma
|
|
|
473
485
|
modelRuntime: scopedModelRuntime,
|
|
474
486
|
settingsManager,
|
|
475
487
|
projectTrustRequiring,
|
|
476
|
-
appendSystemPromptSections
|
|
488
|
+
appendSystemPromptSections: [
|
|
489
|
+
...appendSystemPromptSections,
|
|
490
|
+
...(parentHeader === undefined ? [] : [`<pi_web_session_context>\nParent session ID: ${parentHeader.id}\n</pi_web_session_context>`]),
|
|
491
|
+
],
|
|
477
492
|
eventBus,
|
|
478
493
|
mcpScope: { directory: mcpOAuthStorageDirectory(await resolveSettingsScope(cwd, "normal")) },
|
|
479
494
|
extensionFactories: [sessionDispatch, ...(subsessions === undefined ? [] : [createSubsessionCompletionDelivery(subsessions)])],
|
|
@@ -488,7 +503,7 @@ function createDefaultRuntimeFactory(sessionEvents, normalModelRuntimeForCwd, ma
|
|
|
488
503
|
const resolvedDelegationToolsEnabled = delegationToolsEnabled
|
|
489
504
|
?? await sessionAllowsDelegationTools(sessionManager, sessionManagers);
|
|
490
505
|
dispatchEnabled = resolvedDelegationToolsEnabled;
|
|
491
|
-
const customTools = createPiWebCustomToolDefinitions(cwd, resolvedDelegationToolsEnabled, spawn, subsessions, askUserEnabled);
|
|
506
|
+
const customTools = createPiWebCustomToolDefinitions(cwd, resolvedDelegationToolsEnabled, spawn, subsessions, askUserEnabled, messaging);
|
|
492
507
|
const result = await createAgentSessionFromServices({
|
|
493
508
|
services,
|
|
494
509
|
sessionManager,
|
|
@@ -505,7 +520,7 @@ function createDefaultRuntimeFactory(sessionEvents, normalModelRuntimeForCwd, ma
|
|
|
505
520
|
});
|
|
506
521
|
};
|
|
507
522
|
}
|
|
508
|
-
function createManagementRuntimeFactory(modelRuntime, resolveSettingsScope, sessionManagers, spawn, subsessions, askUserEnabled, managementContext, workbench, logger, managementAudit, managementProjectIdForCwd, managementAllowPrivileged = false, appendSystemPromptSections = []) {
|
|
523
|
+
function createManagementRuntimeFactory(modelRuntime, resolveSettingsScope, sessionManagers, spawn, subsessions, askUserEnabled, managementContext, workbench, logger, managementAudit, managementProjectIdForCwd, managementAllowPrivileged = false, appendSystemPromptSections = [], messaging) {
|
|
509
524
|
return async ({ cwd, agentDir, sessionManager, sessionStartEvent, initialModel, initialThinkingLevel, delegationToolsEnabled }) => {
|
|
510
525
|
const normalPermissions = managementUsesNormalPermissions(managementContext, { allowPrivileged: managementAllowPrivileged });
|
|
511
526
|
const privileges = managementPrivileges(managementContext, { allowPrivileged: managementAllowPrivileged });
|
|
@@ -541,10 +556,16 @@ function createManagementRuntimeFactory(modelRuntime, resolveSettingsScope, sess
|
|
|
541
556
|
const scopedSpawn = spawn === undefined
|
|
542
557
|
? undefined
|
|
543
558
|
: (input) => spawn({ ...input, managementContext });
|
|
559
|
+
const scopedMessaging = messaging === undefined ? undefined : {
|
|
560
|
+
send: (input) => messaging.send(input, managementContext),
|
|
561
|
+
};
|
|
544
562
|
const scopedSubsessions = subsessions === undefined
|
|
545
563
|
? undefined
|
|
546
564
|
: {
|
|
547
565
|
spawn: (input) => subsessions.spawn({ ...input, managementContext }),
|
|
566
|
+
archive: (parentSessionId, sessionId, parentSessionFile) => subsessions.archive(parentSessionId, sessionId, parentSessionFile, managementContext),
|
|
567
|
+
stop: (parentSessionId, sessionId, parentSessionFile) => subsessions.stop(parentSessionId, sessionId, parentSessionFile, managementContext),
|
|
568
|
+
resume: (parentSessionId, sessionId, prompt, parentSessionFile) => subsessions.resume(parentSessionId, sessionId, prompt, parentSessionFile, managementContext),
|
|
548
569
|
list: (parentSessionId, parentSessionFile) => subsessions.list(parentSessionId, parentSessionFile, managementContext),
|
|
549
570
|
join: (parentSessionId, parentSessionFile, toolCallId) => subsessions.join(parentSessionId, parentSessionFile, toolCallId, managementContext),
|
|
550
571
|
prepare: (parentSessionId, parentSessionFile) => subsessions.prepare(parentSessionId, parentSessionFile, managementContext),
|
|
@@ -560,6 +581,8 @@ function createManagementRuntimeFactory(modelRuntime, resolveSettingsScope, sess
|
|
|
560
581
|
...(scopedSubsessions === undefined ? [] : [createSubsessionCompletionDelivery(scopedSubsessions)]),
|
|
561
582
|
];
|
|
562
583
|
const controlledManagementTools = [
|
|
584
|
+
defineTool(createRequestHumanInterventionToolDefinition()),
|
|
585
|
+
...(scopedMessaging === undefined ? [] : [defineTool(createSendSessionMessageToolDefinition(cwd, scopedMessaging))]),
|
|
563
586
|
...(resolvedDelegationToolsEnabled && scopedSpawn !== undefined ? [defineTool(createSpawnSessionToolDefinition(cwd, { spawn: scopedSpawn }))] : []),
|
|
564
587
|
...(resolvedDelegationToolsEnabled && scopedSubsessions !== undefined ? createSubsessionToolDefinitions(cwd, scopedSubsessions).map((tool) => defineTool(tool)) : []),
|
|
565
588
|
...(askUserEnabled ? [createAskUserToolDefinition()] : []),
|
|
@@ -621,7 +644,7 @@ function createManagementRuntimeFactory(modelRuntime, resolveSettingsScope, sess
|
|
|
621
644
|
...(initialThinkingLevel === undefined ? {} : { initialThinkingLevel }),
|
|
622
645
|
});
|
|
623
646
|
services.diagnostics.push(...modelOptions.diagnostics);
|
|
624
|
-
const customTools = normalPermissions ? createPiWebCustomToolDefinitions(cwd, resolvedDelegationToolsEnabled, scopedSpawn, scopedSubsessions, askUserEnabled) : [
|
|
647
|
+
const customTools = normalPermissions ? createPiWebCustomToolDefinitions(cwd, resolvedDelegationToolsEnabled, scopedSpawn, scopedSubsessions, askUserEnabled, scopedMessaging) : [
|
|
625
648
|
...managedAgentToolDefinitions(cwd, createManagedAgentToolOptions(cwd)),
|
|
626
649
|
createManagedPythonToolDefinition(cwd, managementContext, { network: privileges.network }),
|
|
627
650
|
createManagedBashToolDefinition(cwd, managementContext, { network: privileges.network, hostFilesystem: privileges.bash }),
|
|
@@ -651,9 +674,11 @@ function createManagementRuntimeFactory(modelRuntime, resolveSettingsScope, sess
|
|
|
651
674
|
});
|
|
652
675
|
};
|
|
653
676
|
}
|
|
654
|
-
export function createPiWebCustomToolDefinitions(cwd, delegationEnabled, spawn, subsessions, askUserEnabled = false) {
|
|
677
|
+
export function createPiWebCustomToolDefinitions(cwd, delegationEnabled, spawn, subsessions, askUserEnabled = false, messaging) {
|
|
655
678
|
return [
|
|
656
679
|
...managedAgentToolDefinitions(cwd),
|
|
680
|
+
defineTool(createRequestHumanInterventionToolDefinition()),
|
|
681
|
+
...(messaging === undefined ? [] : [defineTool(createSendSessionMessageToolDefinition(cwd, messaging))]),
|
|
657
682
|
...(delegationEnabled && spawn !== undefined ? [defineTool(createSpawnSessionToolDefinition(cwd, { spawn }))] : []),
|
|
658
683
|
...(delegationEnabled && subsessions !== undefined ? createSubsessionToolDefinitions(cwd, subsessions).map((tool) => defineTool(tool)) : []),
|
|
659
684
|
...(askUserEnabled ? [createAskUserToolDefinition()] : []),
|
|
@@ -686,7 +711,7 @@ function createPiWebEditToolDefinition(cwd, options) {
|
|
|
686
711
|
async execute(toolCallId, params, signal, onUpdate, ctx) {
|
|
687
712
|
const preview = await computeEditPreview(params.path, params.edits, cwd);
|
|
688
713
|
if (signal?.aborted !== true) {
|
|
689
|
-
onUpdate?.({ content: [{ type: "text", text: "Edit preview computed." }], details: { preview } });
|
|
714
|
+
onUpdate?.({ content: [{ type: "text", text: "Edit preview computed." }], details: { preview, presentation: { kind: "editPreviewComputed" } } });
|
|
690
715
|
}
|
|
691
716
|
return editTool.execute(toolCallId, params, signal, onUpdate, ctx);
|
|
692
717
|
},
|
|
@@ -705,12 +730,19 @@ export class PiSessionService {
|
|
|
705
730
|
this.activities = new SessionActivityCoordinator();
|
|
706
731
|
/** Runtime-identity gate held while Pi may await abandoned-branch summarization. */
|
|
707
732
|
this.treeNavigations = new WeakSet();
|
|
733
|
+
this.publishedSessionNames = new WeakMap();
|
|
734
|
+
/**
|
|
735
|
+
* Bare live leaf selected without an appended summary entry. Recording that
|
|
736
|
+
* leaf distinguishes the unpersisted move from a later runtime append that
|
|
737
|
+
* can anchor the selected branch on disk.
|
|
738
|
+
*/
|
|
708
739
|
this.unpersistedTreeBranchLeaves = new WeakMap();
|
|
709
740
|
/** Counts async operations that may append an entry before they settle. */
|
|
710
741
|
this.sessionEntryMutationCounts = new WeakMap();
|
|
711
742
|
this.manualCompactionEnded = new WeakSet();
|
|
712
743
|
this.extensionCommandExecution = new AsyncLocalStorage();
|
|
713
744
|
this.runtimeMessageCounts = new WeakMap();
|
|
745
|
+
this.interventionStates = new WeakMap();
|
|
714
746
|
this.snapshotMessageCounts = new WeakMap();
|
|
715
747
|
this.pendingPromptEchoes = new WeakMap();
|
|
716
748
|
this.publishedAssistantPartials = new WeakMap();
|
|
@@ -730,7 +762,6 @@ export class PiSessionService {
|
|
|
730
762
|
this.subsessionStoppedParents = new WeakSet();
|
|
731
763
|
this.subsessionDeliveringParents = new WeakSet();
|
|
732
764
|
this.subsessionDeliveryScheduled = new WeakSet();
|
|
733
|
-
this.deferredGeneratedSessionNames = new WeakMap();
|
|
734
765
|
this.compactionPromptQueues = new Map();
|
|
735
766
|
this.compactionDrainTimers = new Map();
|
|
736
767
|
this.authLossWarnings = new Set();
|
|
@@ -760,6 +791,7 @@ export class PiSessionService {
|
|
|
760
791
|
this.mcpAuthOwners = new WeakMap();
|
|
761
792
|
this.notificationGenerationBySession = new WeakMap();
|
|
762
793
|
this.idleSessionFileResolutions = new WeakMap();
|
|
794
|
+
this.unreadEligibilityRevision = 0;
|
|
763
795
|
/** The parked extension Promise resolvers behind the store's open dialogs. */
|
|
764
796
|
this.dialogWaiters = new ExtensionDialogWaiters();
|
|
765
797
|
this.pendingUnreadMutations = [];
|
|
@@ -768,6 +800,7 @@ export class PiSessionService {
|
|
|
768
800
|
this.t = deps.translator ?? loadNodeTranslator("server");
|
|
769
801
|
this.managementAllowPrivileged = deps.managementAllowPrivileged === true;
|
|
770
802
|
this.archiveStore = deps.archiveStore ?? new SessionArchiveStore();
|
|
803
|
+
this.sessionPins = deps.sessionPins;
|
|
771
804
|
this.pinStore = deps.pinStore ?? new SessionPinStore(join(deps.dataDir ?? piWebDataDir(), "session-pins.json"));
|
|
772
805
|
this.agentDir = deps.agentDir ?? getAgentDir();
|
|
773
806
|
this.dataDir = deps.dataDir ?? piWebDataDir();
|
|
@@ -789,6 +822,7 @@ export class PiSessionService {
|
|
|
789
822
|
? resolveDefaultModelRuntime
|
|
790
823
|
: () => Promise.resolve(managementModelRuntime);
|
|
791
824
|
this.spawnTargets = deps.spawnTargets;
|
|
825
|
+
this.messageTargets = deps.sessionMessagesEnabled === false ? undefined : deps.messageTargets ?? deps.spawnTargets;
|
|
792
826
|
this.logger = deps.logger ?? noopLogger;
|
|
793
827
|
this.normalToolAudit = deps.normalToolAudit;
|
|
794
828
|
this.managementAudit = deps.managementAudit;
|
|
@@ -813,20 +847,24 @@ export class PiSessionService {
|
|
|
813
847
|
this.sessionEvents = deps.sessionEvents ?? new PiSessionEventConnections();
|
|
814
848
|
this.createRuntime = deps.createRuntime ?? createDefaultRuntimeFactory(this.sessionEvents, this.normalModelRuntimeForCwd, this.managementModelRuntime, (cwd, mode) => this.resolveSettingsScopeDirectory(cwd, mode), this.sessionManager, this.spawnTargets === undefined ? undefined : (input) => this.spawnSession(input), !subsessionsActive ? undefined : {
|
|
815
849
|
spawn: (input) => this.spawnSubsession(input),
|
|
850
|
+
archive: (parentSessionId, sessionId, parentSessionFile, context) => this.archiveSubsession(parentSessionId, sessionId, parentSessionFile, context),
|
|
851
|
+
stop: (parentSessionId, sessionId, parentSessionFile, context) => this.stopSubsession(parentSessionId, sessionId, parentSessionFile, context),
|
|
852
|
+
resume: (parentSessionId, sessionId, prompt, parentSessionFile, context) => this.resumeSubsession(parentSessionId, sessionId, prompt, parentSessionFile, context),
|
|
816
853
|
list: (parentSessionId, parentSessionFile, managementContext) => this.listSubsessions(parentSessionId, parentSessionFile, managementContext),
|
|
817
854
|
join: (parentSessionId, parentSessionFile, toolCallId, managementContext) => this.joinSubsessions(parentSessionId, parentSessionFile, toolCallId, managementContext),
|
|
818
855
|
prepare: (parentSessionId, parentSessionFile, managementContext) => this.prepareSubsessionDelivery(parentSessionId, parentSessionFile, managementContext),
|
|
819
856
|
check: (parentSessionId, sessionId, parentSessionFile, toolCallId, managementContext) => this.checkSubsession(parentSessionId, sessionId, parentSessionFile, toolCallId, managementContext),
|
|
820
857
|
read: (parentSessionId, sessionId, query, parentSessionFile, toolCallId, managementContext) => this.readSubsession(parentSessionId, sessionId, query, parentSessionFile, toolCallId, managementContext),
|
|
821
|
-
}, deps.askUserEnabled === true, deps.workbench, this.logger, this.managementAudit, this.managementProjectIdForCwd, deps.appendSystemPromptSections ?? [], deps.managementAllowPrivileged === true);
|
|
858
|
+
}, deps.askUserEnabled === true, deps.workbench, this.logger, this.managementAudit, this.managementProjectIdForCwd, deps.appendSystemPromptSections ?? [], deps.managementAllowPrivileged === true, this.messageTargets === undefined ? undefined : { send: (input, context) => this.sendSessionMessage(input, context) });
|
|
822
859
|
this.createAgentRuntime = deps.createAgentRuntime ?? defaultCreateAgentRuntime;
|
|
823
860
|
this.workspaceActivity = deps.workspaceActivity;
|
|
824
861
|
this.heartbeat = setInterval(() => { this.publishHeartbeats(); }, deps.heartbeatIntervalMs ?? 2000);
|
|
825
862
|
this.commandService = new SessionCommandService((sessionId, eventScope) => this.getActiveForCommand(sessionId, eventScope), (sessionId, text, eventScope) => this.submitCommandPrompt(sessionId, text, eventScope), events, {
|
|
863
|
+
onSessionNameChanged: (session) => { this.publishSessionName(session); },
|
|
826
864
|
onCompactionStart: (session) => {
|
|
827
865
|
this.beginSessionEntryMutation(session, this.t("session.action.compact", "compact the session"));
|
|
828
866
|
this.manualCompactionEnded.delete(session);
|
|
829
|
-
this.publishActivity(session,
|
|
867
|
+
this.publishActivity(session, { kind: "compacting" }, "active");
|
|
830
868
|
this.publishStatus(session);
|
|
831
869
|
},
|
|
832
870
|
onCompactionEnd: (session, result, detail) => {
|
|
@@ -866,43 +904,25 @@ export class PiSessionService {
|
|
|
866
904
|
return previewResponseFromPlan(await this.cleanupPlan(request));
|
|
867
905
|
}
|
|
868
906
|
async cleanup(request, context) {
|
|
869
|
-
const scope = eventScopeFromManagementContext(context);
|
|
870
907
|
const plan = await this.cleanupPlan(request);
|
|
871
908
|
if (plan.deleteRecords.length > 0 && this.archiveStore.deleteArchived === undefined && this.archiveStore.deleteArchivedMany === undefined)
|
|
872
909
|
throw new Error(this.t("session.archiveDeleteUnsupported", "The archive store does not support deletion"));
|
|
873
|
-
const
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
const
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
}
|
|
883
|
-
await this.closeActive(input.sessionId, { kind: "clear", reason: "archive" }, scope);
|
|
884
|
-
readyArchiveInputs.push(input);
|
|
885
|
-
}
|
|
886
|
-
await this.archiveStoreArchiveMany(readyArchiveInputs);
|
|
887
|
-
archiveInputs.push(...readyArchiveInputs);
|
|
888
|
-
await this.forgetUnreadSessions(readyArchiveInputs, scope);
|
|
889
|
-
for (const record of plan.deleteRecords) {
|
|
890
|
-
if (this.activeSessionHasWork(record.sessionId)) {
|
|
891
|
-
skippedBusySessionIds.add(record.sessionId);
|
|
892
|
-
continue;
|
|
893
|
-
}
|
|
894
|
-
await this.closeActive(record.sessionId, { kind: "clear", reason: "delete" }, scope);
|
|
895
|
-
readyDeleteRecords.push(record);
|
|
896
|
-
}
|
|
897
|
-
const deletedSessionIds = new Set(await this.archiveStoreDeleteArchivedMany(readyDeleteRecords.map((record) => record.sessionId)));
|
|
898
|
-
deleteRecords.push(...readyDeleteRecords.filter((record) => deletedSessionIds.has(record.sessionId)));
|
|
899
|
-
await this.forgetUnreadSessions(deleteRecords, scope);
|
|
910
|
+
const archived = await this.executeArchiveBatch(plan.archiveInputs, context);
|
|
911
|
+
if (archived.failures.length > 0)
|
|
912
|
+
throw new Error(archived.failures.map((failure) => `${failure.sessionId}: ${failure.error}`).join("; "));
|
|
913
|
+
const deleted = await this.executeDeleteArchivedBatch(plan.deleteRecords, context);
|
|
914
|
+
if (deleted.failures.length > 0)
|
|
915
|
+
throw new Error(deleted.failures.map((failure) => `${failure.sessionId}: ${failure.error}`).join("; "));
|
|
916
|
+
const archiveInputs = archived.successes;
|
|
917
|
+
const deleteRecords = deleted.successes;
|
|
918
|
+
const skippedBusySessionIds = new Set([...plan.skippedBusySessionIds, ...archived.skippedBusySessionIds, ...deleted.skippedBusySessionIds]);
|
|
900
919
|
return summarizeSessionCleanupExecution({
|
|
901
920
|
archiveInputs,
|
|
902
921
|
deleteRecords,
|
|
903
922
|
thresholds: plan.thresholds,
|
|
904
923
|
generatedAt: plan.generatedAt,
|
|
905
924
|
skippedBusySessionIds: [...skippedBusySessionIds],
|
|
925
|
+
...(plan.skippedPinnedSessionIds === undefined ? {} : { skippedPinnedSessionIds: plan.skippedPinnedSessionIds }),
|
|
906
926
|
});
|
|
907
927
|
}
|
|
908
928
|
async dispose() {
|
|
@@ -956,6 +976,18 @@ export class PiSessionService {
|
|
|
956
976
|
});
|
|
957
977
|
await this.publishUnreadMutations([]);
|
|
958
978
|
}
|
|
979
|
+
/** Recover cold-session intervention flags without opening agent runtimes. */
|
|
980
|
+
async restoreInterventionState() {
|
|
981
|
+
const [sessions, archives] = await Promise.all([this.sessionManager.listAll(), this.archiveStore.list()]);
|
|
982
|
+
const archived = new Set(archives.map((record) => record.sessionId));
|
|
983
|
+
for (const session of sessions) {
|
|
984
|
+
if (!await normalSessionReadAllowed(session.cwd, this.projectPathForCwd, this.managementProjectRoot))
|
|
985
|
+
continue;
|
|
986
|
+
if (archived.has(session.id) || this.activeForLookup({ id: session.id, cwd: session.cwd }) !== undefined)
|
|
987
|
+
continue;
|
|
988
|
+
this.workspaceActivity?.applySessionIntervention(session.cwd, session.id, session.interventionRequired === true);
|
|
989
|
+
}
|
|
990
|
+
}
|
|
959
991
|
async list(cwd, managementContext) {
|
|
960
992
|
return (await this.listWorkspaceSessions(cwd, managementContext)).sessions;
|
|
961
993
|
}
|
|
@@ -971,17 +1003,28 @@ export class PiSessionService {
|
|
|
971
1003
|
if (normalizedQuery === "")
|
|
972
1004
|
return { results: [], matchCount: 0, truncated: false };
|
|
973
1005
|
const maxMatches = 200;
|
|
974
|
-
const
|
|
975
|
-
const
|
|
1006
|
+
const listing = await this.listWorkspaceSessions(cwd, managementContext);
|
|
1007
|
+
const matchText = compileSessionContentQuery(normalizedQuery);
|
|
1008
|
+
const candidates = [];
|
|
976
1009
|
let matchCount = 0;
|
|
977
|
-
for (const session of sessions) {
|
|
978
|
-
const
|
|
979
|
-
const
|
|
980
|
-
const view = searchSessionContent(messages, normalizedQuery, Math.max(1, remaining));
|
|
1010
|
+
for (const session of listing.sessions) {
|
|
1011
|
+
const messages = await this.searchableSessionHistory(session, listing, managementContext);
|
|
1012
|
+
const view = searchSessionContent(messages, matchText, maxMatches);
|
|
981
1013
|
matchCount += view.matchCount;
|
|
982
|
-
|
|
983
|
-
|
|
1014
|
+
candidates.push(...view.matches.map((match) => ({ session, match })));
|
|
1015
|
+
candidates.sort((left, right) => left.match.rank - right.match.rank);
|
|
1016
|
+
candidates.length = Math.min(candidates.length, maxMatches);
|
|
1017
|
+
}
|
|
1018
|
+
const grouped = new Map();
|
|
1019
|
+
for (const { session, match } of candidates) {
|
|
1020
|
+
let result = grouped.get(session.id);
|
|
1021
|
+
if (result === undefined) {
|
|
1022
|
+
result = { session, matches: [] };
|
|
1023
|
+
grouped.set(session.id, result);
|
|
1024
|
+
}
|
|
1025
|
+
result.matches.push({ messageIndex: match.messageIndex, role: match.role, excerpts: match.excerpts, occurrenceCount: match.occurrenceCount });
|
|
984
1026
|
}
|
|
1027
|
+
const results = [...grouped.values()];
|
|
985
1028
|
return { results, matchCount, truncated: matchCount > maxMatches };
|
|
986
1029
|
}
|
|
987
1030
|
async listPinned(cwd, managementContext) {
|
|
@@ -1025,11 +1068,17 @@ export class PiSessionService {
|
|
|
1025
1068
|
const listed = unarchivedById.get(session.sessionId);
|
|
1026
1069
|
const tracked = this.subsessionLinkForActiveChild(session) !== undefined;
|
|
1027
1070
|
if (listed !== undefined) {
|
|
1028
|
-
|
|
1029
|
-
|
|
1071
|
+
// Match the file too: a clone with the same id must not inherit a
|
|
1072
|
+
// live runtime's classification. Disk rows otherwise use the scanner.
|
|
1073
|
+
if (session.sessionFile !== undefined && sessionPathsEqual(listed.path, session.sessionFile)) {
|
|
1074
|
+
if (tracked)
|
|
1075
|
+
listed.agentSubsession = true;
|
|
1076
|
+
listed.interventionRequired = this.statusFromSession(session).interventionRequired === true;
|
|
1077
|
+
}
|
|
1030
1078
|
continue;
|
|
1031
1079
|
}
|
|
1032
1080
|
const info = clientSessionFromActiveSession(session);
|
|
1081
|
+
info.interventionRequired = this.statusFromSession(session).interventionRequired === true;
|
|
1033
1082
|
if (tracked)
|
|
1034
1083
|
info.agentSubsession = true;
|
|
1035
1084
|
unarchivedById.set(session.sessionId, info);
|
|
@@ -1040,6 +1089,10 @@ export class PiSessionService {
|
|
|
1040
1089
|
if (managementContext === undefined) {
|
|
1041
1090
|
await this.publishUnreadMutations(this.unreadForScope(eventScopeFromManagementContext(managementContext)).reconcileCwd(canonicalizeStoredCwd(cwd), reconcilableSessionIds));
|
|
1042
1091
|
}
|
|
1092
|
+
for (const session of unarchivedSessions) {
|
|
1093
|
+
if (this.activeForLookup({ id: session.id, cwd }, managementContext) === undefined)
|
|
1094
|
+
this.workspaceActivity?.applySessionIntervention(cwd, session.id, session.interventionRequired === true, eventScopeFromManagementContext(managementContext));
|
|
1095
|
+
}
|
|
1043
1096
|
const archivedSessions = archivedForCwd
|
|
1044
1097
|
.map((record) => clientSessionFromArchivedRecord(record, sessionsById.get(record.sessionId)))
|
|
1045
1098
|
.filter(isDefined)
|
|
@@ -1074,18 +1127,41 @@ export class PiSessionService {
|
|
|
1074
1127
|
continue;
|
|
1075
1128
|
const row = rows.get(session.sessionId);
|
|
1076
1129
|
// A disk clone with the same id must not inherit another file's runtime.
|
|
1077
|
-
if (row !== undefined && (session.sessionFile === undefined || !sessionPathsEqual(row.path, session.sessionFile)))
|
|
1130
|
+
if (row !== undefined && (row.path === undefined || session.sessionFile === undefined || !sessionPathsEqual(row.path, session.sessionFile)))
|
|
1078
1131
|
continue;
|
|
1079
1132
|
runtimes.set(session.sessionId, session);
|
|
1080
|
-
|
|
1133
|
+
const headerCreated = session.sessionManager.getHeader?.()?.timestamp;
|
|
1134
|
+
const metadata = readSessionUiMetadata(session.sessionManager.getEntries?.() ?? session.sessionManager.getBranch());
|
|
1135
|
+
const created = row?.created ?? (headerCreated !== undefined && Number.isFinite(Date.parse(headerCreated)) ? new Date(headerCreated).toISOString() : undefined);
|
|
1136
|
+
// Scanner dates match native cleanup eligibility. A hosted-only runtime's
|
|
1137
|
+
// header records creation, not its most recent activity.
|
|
1138
|
+
rows.set(session.sessionId, {
|
|
1139
|
+
id: session.sessionId,
|
|
1140
|
+
cwd: session.sessionManager.getCwd(),
|
|
1141
|
+
...(session.sessionName === undefined ? {} : { name: session.sessionName }),
|
|
1142
|
+
...(metadata === undefined ? {} : { metadata }),
|
|
1143
|
+
...(created === undefined ? {} : { created }),
|
|
1144
|
+
...(row?.modified === undefined ? {} : { modified: row.modified }),
|
|
1145
|
+
});
|
|
1081
1146
|
}
|
|
1082
1147
|
const entriesById = new Map(entries.map((entry) => [entry.id, entry]));
|
|
1083
1148
|
for (const record of archived) {
|
|
1084
|
-
const
|
|
1085
|
-
|
|
1086
|
-
|
|
1149
|
+
const entry = entriesById.get(record.sessionId);
|
|
1150
|
+
const created = record.created ?? entry?.created.toISOString();
|
|
1151
|
+
const modified = record.modified ?? entry?.modified.toISOString();
|
|
1152
|
+
// Legacy records may lack transcript/path fields required by the client
|
|
1153
|
+
// list helper; their archive identity and known dates are still usable.
|
|
1154
|
+
const row = clientSessionFromArchivedRecord(record, entry) ?? {
|
|
1155
|
+
id: record.sessionId,
|
|
1156
|
+
cwd: record.cwd,
|
|
1157
|
+
...(created === undefined ? {} : { created }),
|
|
1158
|
+
...(modified === undefined ? {} : { modified }),
|
|
1159
|
+
archived: true,
|
|
1160
|
+
archivedAt: record.archivedAt,
|
|
1161
|
+
};
|
|
1162
|
+
rows.set(row.id, row);
|
|
1087
1163
|
}
|
|
1088
|
-
return [...rows.values()].sort((a, b) => Date.parse(b.modified) - Date.parse(a.modified)).map((row) => {
|
|
1164
|
+
return [...rows.values()].sort((a, b) => (b.modified === undefined ? 0 : Date.parse(b.modified)) - (a.modified === undefined ? 0 : Date.parse(a.modified))).map((row) => {
|
|
1089
1165
|
const runtime = runtimes.get(row.id);
|
|
1090
1166
|
return Object.freeze({
|
|
1091
1167
|
id: row.id,
|
|
@@ -1093,6 +1169,9 @@ export class PiSessionService {
|
|
|
1093
1169
|
...(row.name === undefined ? {} : { name: row.name }),
|
|
1094
1170
|
...(row.metadata === undefined ? {} : { metadata: structuredClone(row.metadata) }),
|
|
1095
1171
|
archived: row.archived === true,
|
|
1172
|
+
created: row.created ?? null,
|
|
1173
|
+
modified: row.modified ?? null,
|
|
1174
|
+
archivedAt: row.archived === true ? row.archivedAt ?? null : null,
|
|
1096
1175
|
runtime: runtime === undefined ? "not-hosted" : this.hasActiveWork(runtime) ? "busy" : "idle",
|
|
1097
1176
|
});
|
|
1098
1177
|
});
|
|
@@ -1108,24 +1187,56 @@ export class PiSessionService {
|
|
|
1108
1187
|
return Object.freeze({ id: created.id });
|
|
1109
1188
|
}
|
|
1110
1189
|
/** Atomically start and prompt one visible normal-mode, non-delegating session. */
|
|
1111
|
-
async startOneShotRun(cwd, text, signal) {
|
|
1190
|
+
async startOneShotRun(cwd, text, signal, options = {}) {
|
|
1112
1191
|
const promptText = requirePromptText(text, this.t);
|
|
1113
|
-
return this.startManagedSession(cwd, signal, promptText);
|
|
1192
|
+
return this.startManagedSession(cwd, signal, promptText, options);
|
|
1114
1193
|
}
|
|
1115
|
-
async startManagedSession(cwd, signal, promptText) {
|
|
1194
|
+
async startManagedSession(cwd, signal, promptText, options = {}) {
|
|
1116
1195
|
signal.throwIfAborted();
|
|
1117
|
-
await this.normalModelRuntimeForCwd(cwd);
|
|
1118
|
-
|
|
1196
|
+
const modelRuntime = await this.normalModelRuntimeForCwd(cwd);
|
|
1197
|
+
let initialModel;
|
|
1198
|
+
if (options.model !== undefined) {
|
|
1199
|
+
await modelRuntime.refresh({ allowNetwork: false });
|
|
1200
|
+
signal.throwIfAborted();
|
|
1201
|
+
// Catalog membership alone does not mean the provider still has credentials
|
|
1202
|
+
// or is configured. Host overrides must be available after the refresh.
|
|
1203
|
+
initialModel = modelRuntime.getAvailableSnapshot().find((model) => modelScopeId(model) === options.model);
|
|
1204
|
+
if (initialModel === undefined) {
|
|
1205
|
+
throw Object.assign(new Error(`Model unavailable: ${options.model}`), { code: "PI_SESSION_MODEL_UNAVAILABLE" });
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
1208
|
+
const active = await this.create(this.sessionManager.create(cwd), cwd, {
|
|
1209
|
+
startupIntent: "create", creationProvenance: "host-one-shot", startupSignal: signal,
|
|
1210
|
+
...(initialModel === undefined ? {} : { initialModel }),
|
|
1211
|
+
});
|
|
1119
1212
|
const { session } = active.runtime;
|
|
1120
1213
|
try {
|
|
1121
1214
|
signal.throwIfAborted();
|
|
1122
|
-
|
|
1123
|
-
|
|
1215
|
+
// Startup extensions may change the model. Never submit with a fallback
|
|
1216
|
+
// when the caller requested an exact model.
|
|
1217
|
+
if (options.model !== undefined && (session.model === undefined || modelScopeId(session.model) !== options.model)) {
|
|
1218
|
+
throw Object.assign(new Error(`Requested model is not active: ${options.model}`), { code: "PI_SESSION_MODEL_UNAVAILABLE" });
|
|
1219
|
+
}
|
|
1220
|
+
if (options.thinkingLevel !== undefined) {
|
|
1221
|
+
// Do not pass requested thinking into startup: the SDK can silently
|
|
1222
|
+
// clamp it before we have the actual model's supported levels.
|
|
1223
|
+
if (!session.getAvailableThinkingLevels().includes(options.thinkingLevel)) {
|
|
1224
|
+
throw Object.assign(new Error(`Thinking level unavailable: ${options.thinkingLevel}`), { code: "PI_SESSION_THINKING_UNAVAILABLE" });
|
|
1225
|
+
}
|
|
1226
|
+
session.setThinkingLevel(options.thinkingLevel);
|
|
1227
|
+
if (session.thinkingLevel !== options.thinkingLevel) {
|
|
1228
|
+
throw Object.assign(new Error(`Thinking level was not applied: ${options.thinkingLevel}`), { code: "PI_SESSION_THINKING_UNAVAILABLE" });
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1231
|
+
const settings = {
|
|
1232
|
+
...(session.model === undefined ? {} : { model: modelScopeId(session.model) }),
|
|
1233
|
+
thinkingLevel: session.thinkingLevel,
|
|
1234
|
+
};
|
|
1124
1235
|
const created = this.announceCreatedSession(active, cwd);
|
|
1125
1236
|
// Publication transfers lifetime ownership to normal hosting. Plugin
|
|
1126
1237
|
// cancellation after this point must not abort this or later user work.
|
|
1127
1238
|
const completion = promptText === undefined ? Promise.resolve() : this.submitInitialRunPrompt(session, promptText);
|
|
1128
|
-
return Object.freeze({ id: created.id, completion });
|
|
1239
|
+
return Object.freeze({ id: created.id, completion, ...settings });
|
|
1129
1240
|
}
|
|
1130
1241
|
catch (error) {
|
|
1131
1242
|
try {
|
|
@@ -1518,6 +1629,96 @@ export class PiSessionService {
|
|
|
1518
1629
|
...(outcome.answer === undefined ? {} : { answer: outcome.answer }),
|
|
1519
1630
|
}, this.eventScopeForSession(session));
|
|
1520
1631
|
}
|
|
1632
|
+
/** Interrupt a direct child's current run without closing its conversation. */
|
|
1633
|
+
async stopSubsession(parentSessionId, sessionId, parentSessionFile, managementContext) {
|
|
1634
|
+
const child = await this.openSubsession(parentSessionId, sessionId, parentSessionFile, managementContext);
|
|
1635
|
+
const cwd = child.sessionManager.getCwd();
|
|
1636
|
+
await this.abort({ id: sessionId, cwd }, managementContext);
|
|
1637
|
+
return { sessionId, cwd, status: this.subsessionStatus(child) };
|
|
1638
|
+
}
|
|
1639
|
+
/** Start another run in a direct child's conversation, without prompt expansion. */
|
|
1640
|
+
async resumeSubsession(parentSessionId, sessionId, prompt, parentSessionFile, managementContext) {
|
|
1641
|
+
const child = await this.openSubsession(parentSessionId, sessionId, parentSessionFile, managementContext);
|
|
1642
|
+
const cwd = child.sessionManager.getCwd();
|
|
1643
|
+
await this.assertWritable({ id: sessionId, cwd }, managementContext);
|
|
1644
|
+
this.assertTreeNavigationInactive(child, "resume a subsession");
|
|
1645
|
+
if (this.hasActiveWork(child))
|
|
1646
|
+
throw new Error("Subsession is already working");
|
|
1647
|
+
const text = requirePromptText(prompt ?? "Continue your previous task from the current conversation and workspace state. Check any interrupted work before repeating it.", this.t);
|
|
1648
|
+
void this.beginPromptSubmission(child, text, undefined, [], true, { expandPromptTemplates: false }).catch(() => undefined);
|
|
1649
|
+
return { sessionId, cwd, status: "working" };
|
|
1650
|
+
}
|
|
1651
|
+
/** Archive a direct child using the same idle-only operation as the browser. */
|
|
1652
|
+
async archiveSubsession(parentSessionId, sessionId, parentSessionFile, managementContext) {
|
|
1653
|
+
const child = await this.openSubsession(parentSessionId, sessionId, parentSessionFile, managementContext);
|
|
1654
|
+
await this.archive({ id: sessionId, cwd: child.sessionManager.getCwd() }, managementContext);
|
|
1655
|
+
}
|
|
1656
|
+
/** Send content, not control authority, to a named session in the same project. */
|
|
1657
|
+
async sendSessionMessage(input, managementContext) {
|
|
1658
|
+
if (this.messageTargets === undefined)
|
|
1659
|
+
throw new Error("Session messaging is unavailable");
|
|
1660
|
+
const message = requirePromptText(input.message, this.t);
|
|
1661
|
+
if (managementContext === undefined)
|
|
1662
|
+
await this.assertNormalSessionReadAccess(input.sendingCwd);
|
|
1663
|
+
else
|
|
1664
|
+
await this.getActive({ id: input.sendingSessionId, cwd: input.sendingCwd }, managementContext);
|
|
1665
|
+
const active = this.activeForLookup(input.sessionId, managementContext);
|
|
1666
|
+
const target = active === undefined
|
|
1667
|
+
? (await this.sessionManager.listAll()).find((entry) => entry.id === input.sessionId)
|
|
1668
|
+
: { id: input.sessionId, cwd: active.runtime.cwd };
|
|
1669
|
+
if (target === undefined)
|
|
1670
|
+
throw new Error("Session not found");
|
|
1671
|
+
if (active === undefined && this.activeSessionsForId(input.sessionId).some((entry) => cwdPathsEqual(entry.runtime.cwd, target.cwd)))
|
|
1672
|
+
throw new Error("Session not found");
|
|
1673
|
+
const decision = await this.messageTargets.resolveSpawnTarget(input.sendingCwd, target.cwd, eventScopeFromManagementContext(managementContext));
|
|
1674
|
+
if (!decision.allowed)
|
|
1675
|
+
throw new Error("Session messaging is limited to sessions in the same registered project");
|
|
1676
|
+
if (managementContext === undefined)
|
|
1677
|
+
await this.assertNormalSessionReadAccess(decision.cwd);
|
|
1678
|
+
else {
|
|
1679
|
+
if (this.managementProjectRoot === undefined)
|
|
1680
|
+
throw new Error("Managed session messaging requires a project root");
|
|
1681
|
+
await assertManagedCwd(this.managementProjectRoot, managementContext, decision.cwd, { create: false });
|
|
1682
|
+
}
|
|
1683
|
+
const ref = { id: input.sessionId, cwd: decision.cwd };
|
|
1684
|
+
await this.assertWritable(ref, managementContext);
|
|
1685
|
+
const session = await this.getOrOpen(ref, managementContext);
|
|
1686
|
+
this.assertTreeNavigationInactive(session, "receive a session message");
|
|
1687
|
+
const delivery = this.hasActiveWork(session) ? "queued" : "started";
|
|
1688
|
+
let agentStarted = false;
|
|
1689
|
+
const unsubscribe = session.subscribe((event) => {
|
|
1690
|
+
if (getString(event, "type") === "agent_start")
|
|
1691
|
+
agentStarted = true;
|
|
1692
|
+
});
|
|
1693
|
+
// A custom-message turn may run for minutes. Never wait for its answer in
|
|
1694
|
+
// the sender: reciprocal messages must not deadlock their tool calls.
|
|
1695
|
+
void this.runSessionEntryMutation(session, "receive a session message", async () => {
|
|
1696
|
+
if (session.isCompacting || session.isBashRunning)
|
|
1697
|
+
await session.waitForIdle();
|
|
1698
|
+
if (!this.isCurrentActiveSession(session))
|
|
1699
|
+
throw new Error("Session was closed before message delivery");
|
|
1700
|
+
await session.sendCustomMessage({
|
|
1701
|
+
customType: "session.message",
|
|
1702
|
+
content: `Message from session ${input.sendingSessionId}:\n\n${message}`,
|
|
1703
|
+
display: true,
|
|
1704
|
+
details: { sendingSessionId: input.sendingSessionId },
|
|
1705
|
+
}, { triggerTurn: true, deliverAs: "steer" });
|
|
1706
|
+
}).catch((error) => {
|
|
1707
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
1708
|
+
this.logger.info({ sessionId: input.sessionId, sendingSessionId: input.sendingSessionId, error: detail }, "session message delivery failed");
|
|
1709
|
+
if (!this.isCurrentActiveSession(session))
|
|
1710
|
+
return;
|
|
1711
|
+
this.publishActivity(session, { kind: "error" }, "error", detail);
|
|
1712
|
+
const scope = this.eventScopeForSession(session);
|
|
1713
|
+
this.events.publish(session.sessionId, { type: "session.error", message: detail }, scope);
|
|
1714
|
+
if (!agentStarted && this.subsessionLinkForActiveChild(session) !== undefined)
|
|
1715
|
+
this.subsessionNotifyArmed.set(activeSessionKey(session.sessionId, scope), true);
|
|
1716
|
+
this.updateSubsessionTracking(session);
|
|
1717
|
+
this.publishStatus(session);
|
|
1718
|
+
}).finally(unsubscribe);
|
|
1719
|
+
this.logger.info({ sendingSessionId: input.sendingSessionId, sessionId: input.sessionId, delivery }, "session message accepted");
|
|
1720
|
+
return { sessionId: input.sessionId, delivery };
|
|
1721
|
+
}
|
|
1521
1722
|
/** Summaries of the tracked subsessions spawned by `parentSessionId`. */
|
|
1522
1723
|
async listSubsessions(parentSessionId, parentSessionFile, managementContext) {
|
|
1523
1724
|
const parentFile = nonEmptyString(parentSessionFile);
|
|
@@ -2015,13 +2216,17 @@ export class PiSessionService {
|
|
|
2015
2216
|
}));
|
|
2016
2217
|
return { listing, sessions: matches.filter(isDefined) };
|
|
2017
2218
|
}
|
|
2018
|
-
searchableSessionHistory(session, listing, managementContext) {
|
|
2219
|
+
async searchableSessionHistory(session, listing, managementContext) {
|
|
2019
2220
|
const eventScope = eventScopeFromManagementContext(managementContext);
|
|
2020
2221
|
const active = this.activeForSessionIdAndScope(session.id, eventScope);
|
|
2021
2222
|
if (active !== undefined && cwdPathsEqual(active.runtime.cwd, session.cwd))
|
|
2022
2223
|
return historyMessages(active.runtime.session);
|
|
2023
2224
|
const path = listing.archivedById.get(session.id)?.archivePath ?? listing.entriesById.get(session.id)?.path;
|
|
2024
|
-
|
|
2225
|
+
if (path === undefined)
|
|
2226
|
+
return [];
|
|
2227
|
+
if (this.sessionManager.readBranch !== undefined)
|
|
2228
|
+
return historyMessagesFromEntries(await this.sessionManager.readBranch(path) ?? []);
|
|
2229
|
+
return historyMessagesFromManager(this.sessionManager.open(path));
|
|
2025
2230
|
}
|
|
2026
2231
|
async streamSnapshot(ref, managementContext) {
|
|
2027
2232
|
const session = await this.getOrOpen(ref, managementContext);
|
|
@@ -2159,7 +2364,7 @@ export class PiSessionService {
|
|
|
2159
2364
|
if (model === undefined)
|
|
2160
2365
|
throw new Error(this.t("model.notFound", "Model not found: {value0}/{value1}", { value0: provider, value1: modelId }));
|
|
2161
2366
|
await this.runSessionEntryMutation(session, this.t("server.main.130226a572df", "change models"), () => session.setModel(model));
|
|
2162
|
-
this.publishActivity(session,
|
|
2367
|
+
this.publishActivity(session, { kind: "model", value: model.id }, "idle", model.provider);
|
|
2163
2368
|
this.publishStatus(session);
|
|
2164
2369
|
return this.statusFromSession(session);
|
|
2165
2370
|
}
|
|
@@ -2173,7 +2378,7 @@ export class PiSessionService {
|
|
|
2173
2378
|
});
|
|
2174
2379
|
if (result === undefined)
|
|
2175
2380
|
throw new Error(session.scopedModels.length > 0 ? this.t("model.oneScoped", "Only one scoped model is available") : this.t("model.oneAvailable", "Only one model is available"));
|
|
2176
|
-
this.publishActivity(session,
|
|
2381
|
+
this.publishActivity(session, { kind: "model", value: result.model.id }, "idle", result.model.provider);
|
|
2177
2382
|
this.publishStatus(session);
|
|
2178
2383
|
return this.statusFromSession(session);
|
|
2179
2384
|
}
|
|
@@ -2195,7 +2400,7 @@ export class PiSessionService {
|
|
|
2195
2400
|
session.setThinkingLevel(match);
|
|
2196
2401
|
return Promise.resolve();
|
|
2197
2402
|
});
|
|
2198
|
-
this.publishActivity(session,
|
|
2403
|
+
this.publishActivity(session, { kind: "thinking", value: session.thinkingLevel }, "idle");
|
|
2199
2404
|
this.publishStatus(session);
|
|
2200
2405
|
return this.statusFromSession(session);
|
|
2201
2406
|
}
|
|
@@ -2205,7 +2410,7 @@ export class PiSessionService {
|
|
|
2205
2410
|
const level = await this.runSessionEntryMutation(session, this.t("session.action.changeThinking", "change the thinking level"), () => Promise.resolve(session.cycleThinkingLevel()));
|
|
2206
2411
|
if (level === undefined)
|
|
2207
2412
|
throw new Error(this.t("model.thinkingUnsupported", "The current model does not support thinking"));
|
|
2208
|
-
this.publishActivity(session,
|
|
2413
|
+
this.publishActivity(session, { kind: "thinking", value: level }, "idle");
|
|
2209
2414
|
this.publishStatus(session);
|
|
2210
2415
|
return this.statusFromSession(session);
|
|
2211
2416
|
}
|
|
@@ -2241,11 +2446,10 @@ export class PiSessionService {
|
|
|
2241
2446
|
await this.assertWritable(ref, options?.managementContext);
|
|
2242
2447
|
const session = await this.getOrOpen(ref, options?.managementContext);
|
|
2243
2448
|
this.assertTreeNavigationInactive(session, this.t("server.main.94306b2fc35c", "send a prompt"));
|
|
2244
|
-
this.maybeGenerateSessionName(session, promptText);
|
|
2245
2449
|
const isQueued = session.isStreaming || session.isCompacting;
|
|
2246
2450
|
const behavior = isQueued ? requestedBehavior ?? "followUp" : undefined;
|
|
2247
2451
|
if (isQueued && images.length === 0 && this.hasQueuedMessageText(session, promptText)) {
|
|
2248
|
-
this.publishActivity(session,
|
|
2452
|
+
this.publishActivity(session, { kind: "duplicateQueuedMessage" }, "active");
|
|
2249
2453
|
this.publishStatus(session);
|
|
2250
2454
|
return;
|
|
2251
2455
|
}
|
|
@@ -2267,7 +2471,7 @@ export class PiSessionService {
|
|
|
2267
2471
|
beginPromptSubmission(session, text, behavior, images = [], echoUserMessage = true, options = {}) {
|
|
2268
2472
|
if (options.auditUserPrompt !== false)
|
|
2269
2473
|
this.auditUserPrompt(session, text);
|
|
2270
|
-
this.publishActivity(session, behavior === "steer" ?
|
|
2474
|
+
this.publishActivity(session, behavior === "steer" ? { kind: "steeringQueued" } : behavior === "followUp" ? { kind: "messageQueued" } : { kind: "promptAccepted" }, "active");
|
|
2271
2475
|
const eventScope = this.eventScopeForSession(session);
|
|
2272
2476
|
const echoes = this.pendingPromptEchoes.get(session) ?? [];
|
|
2273
2477
|
const userCount = historyMessagesFromEntries(session.sessionManager.getBranch()).filter((message) => isRecord(message) && message["role"] === "user").length;
|
|
@@ -2308,7 +2512,7 @@ export class PiSessionService {
|
|
|
2308
2512
|
void promptPromise.catch((error) => {
|
|
2309
2513
|
this.subsessionStoppedParents.add(session);
|
|
2310
2514
|
const message = error instanceof Error ? error.message : String(error);
|
|
2311
|
-
this.publishActivity(session,
|
|
2515
|
+
this.publishActivity(session, { kind: "error" }, "error", message);
|
|
2312
2516
|
this.events.publish(session.sessionId, { type: "session.error", message }, eventScope);
|
|
2313
2517
|
if (this.isCurrentActiveSession(session)) {
|
|
2314
2518
|
const link = this.subsessionLinkForActiveChild(session);
|
|
@@ -2372,7 +2576,7 @@ export class PiSessionService {
|
|
|
2372
2576
|
const queue = this.compactionPromptQueues.get(sessionKey) ?? [];
|
|
2373
2577
|
queue.push({ kind, text, ...(images.length > 0 ? { images } : {}), ...(echoUserMessage ? {} : { echoUserMessage: false }) });
|
|
2374
2578
|
this.compactionPromptQueues.set(sessionKey, queue);
|
|
2375
|
-
this.publishActivity(session,
|
|
2579
|
+
this.publishActivity(session, { kind: "queuedDuringCompaction" }, "active");
|
|
2376
2580
|
this.publishStatus(session);
|
|
2377
2581
|
}
|
|
2378
2582
|
async saveAttachments(ref, attachments, folder, managementContext) {
|
|
@@ -2386,8 +2590,8 @@ export class PiSessionService {
|
|
|
2386
2590
|
return saveAttachmentsToWorkspace(cwd, parsed, effectiveFolder === undefined ? {} : { folder: effectiveFolder });
|
|
2387
2591
|
}
|
|
2388
2592
|
async workspaceAttachmentsConfig(cwd) {
|
|
2389
|
-
const
|
|
2390
|
-
return loadEffectiveProjectAttachmentsConfig(cwd,
|
|
2593
|
+
const response = this.config === undefined ? undefined : await this.config.read();
|
|
2594
|
+
return loadEffectiveProjectAttachmentsConfig(cwd, response?.effectiveConfig ?? {}, response?.enforcedSettings);
|
|
2391
2595
|
}
|
|
2392
2596
|
async shell(ref, text, managementContext) {
|
|
2393
2597
|
await this.assertWritable(ref, managementContext);
|
|
@@ -2401,11 +2605,11 @@ export class PiSessionService {
|
|
|
2401
2605
|
if (session.isBashRunning)
|
|
2402
2606
|
throw new Error(this.t("shell.alreadyRunning", "A bash command is already running"));
|
|
2403
2607
|
const eventScope = active.eventScope;
|
|
2404
|
-
this.publishActivity(session,
|
|
2608
|
+
this.publishActivity(session, { kind: "runningBash" }, "active", command);
|
|
2405
2609
|
this.events.publish(session.sessionId, { type: "shell.start", command, excludeFromContext: isExcluded }, eventScope);
|
|
2406
2610
|
void this.runSessionEntryMutation(session, this.t("session.action.shell", "run a shell command"), () => session.executeBash(command, (chunk) => {
|
|
2407
2611
|
this.events.publish(session.sessionId, { type: "shell.chunk", chunk }, eventScope);
|
|
2408
|
-
this.publishActivity(session,
|
|
2612
|
+
this.publishActivity(session, { kind: "runningBash" }, "active", command);
|
|
2409
2613
|
this.publishStatus(session);
|
|
2410
2614
|
}, { excludeFromContext: isExcluded })).then((result) => {
|
|
2411
2615
|
this.events.publish(session.sessionId, {
|
|
@@ -2416,13 +2620,13 @@ export class PiSessionService {
|
|
|
2416
2620
|
truncated: result.truncated,
|
|
2417
2621
|
...(result.fullOutputPath === undefined ? {} : { fullOutputPath: result.fullOutputPath }),
|
|
2418
2622
|
}, eventScope);
|
|
2419
|
-
this.publishActivity(session,
|
|
2623
|
+
this.publishActivity(session, { kind: "bashComplete" }, result.exitCode === 0 ? "idle" : "error", command);
|
|
2420
2624
|
this.publishStatus(session);
|
|
2421
2625
|
}).catch((error) => {
|
|
2422
2626
|
const message = userFacingErrorMessage(error, this.t);
|
|
2423
2627
|
this.events.publish(session.sessionId, { type: "shell.end", output: message, isError: true }, eventScope);
|
|
2424
2628
|
this.events.publish(session.sessionId, { type: "session.error", message }, eventScope);
|
|
2425
|
-
this.publishActivity(session,
|
|
2629
|
+
this.publishActivity(session, { kind: "bashFailed" }, "error", message);
|
|
2426
2630
|
this.publishStatus(session);
|
|
2427
2631
|
});
|
|
2428
2632
|
}
|
|
@@ -2469,7 +2673,7 @@ export class PiSessionService {
|
|
|
2469
2673
|
if (retainCustomMessage && options.summarize === true)
|
|
2470
2674
|
throw new Error(this.t("session.checkpointSummary", "Retaining a custom-message checkpoint requires navigation without a branch summary"));
|
|
2471
2675
|
const activeEditableTargetParentId = retainCustomMessage ? undefined : activeEditableTreeTargetParentId(session.sessionManager, targetId, oldLeafId);
|
|
2472
|
-
this.publishActivity(session, options.summarize === true ?
|
|
2676
|
+
this.publishActivity(session, options.summarize === true ? { kind: "summarizingBranch" } : { kind: "navigatingTree" }, "active");
|
|
2473
2677
|
this.publishStatus(session);
|
|
2474
2678
|
let result = retainCustomMessage
|
|
2475
2679
|
? await navigateTreeRetainingCustomMessage(session.sessionManager, targetId, checkpointTail["parentId"], () => navigateTree(targetId, options))
|
|
@@ -2490,7 +2694,7 @@ export class PiSessionService {
|
|
|
2490
2694
|
}
|
|
2491
2695
|
if (result.cancelled) {
|
|
2492
2696
|
if (this.isCurrentActiveSession(session)) {
|
|
2493
|
-
this.publishActivity(session, result.aborted === true ?
|
|
2697
|
+
this.publishActivity(session, result.aborted === true ? { kind: "branchSummaryAborted" } : { kind: "treeNavigationCancelled" }, "idle");
|
|
2494
2698
|
}
|
|
2495
2699
|
return { cancelled: true, ...(result.aborted === undefined ? {} : { aborted: result.aborted }) };
|
|
2496
2700
|
}
|
|
@@ -2505,13 +2709,13 @@ export class PiSessionService {
|
|
|
2505
2709
|
this.setSuggestedInput(session, result.editorText);
|
|
2506
2710
|
this.events.publish(session.sessionId, { type: "session.tree.changed" }, this.eventScopeForSession(session));
|
|
2507
2711
|
if (this.isCurrentActiveSession(session))
|
|
2508
|
-
this.publishActivity(session,
|
|
2712
|
+
this.publishActivity(session, { kind: "treeNavigated" }, "idle");
|
|
2509
2713
|
return { cancelled: false, ...(result.editorText === undefined ? {} : { editorText: result.editorText }) };
|
|
2510
2714
|
}
|
|
2511
2715
|
catch (error) {
|
|
2512
2716
|
const message = userFacingErrorMessage(error, this.t);
|
|
2513
2717
|
if (this.isCurrentActiveSession(session)) {
|
|
2514
|
-
this.publishActivity(session,
|
|
2718
|
+
this.publishActivity(session, { kind: "treeNavigationFailed" }, "error", message);
|
|
2515
2719
|
this.events.publish(session.sessionId, { type: "session.error", message }, this.eventScopeForSession(session));
|
|
2516
2720
|
}
|
|
2517
2721
|
throw error;
|
|
@@ -2524,7 +2728,6 @@ export class PiSessionService {
|
|
|
2524
2728
|
this.publishStatus(session);
|
|
2525
2729
|
}
|
|
2526
2730
|
else {
|
|
2527
|
-
this.deferredGeneratedSessionNames.delete(session);
|
|
2528
2731
|
this.subsessionInbox(session.sessionId, session.sessionFile, this.eventScopeForSession(session)).releaseClaims();
|
|
2529
2732
|
}
|
|
2530
2733
|
}
|
|
@@ -2551,7 +2754,7 @@ export class PiSessionService {
|
|
|
2551
2754
|
const sourceSessionId = session.sessionId;
|
|
2552
2755
|
const sourceEventScope = this.eventScopeForSession(session);
|
|
2553
2756
|
const sourceCwd = session.sessionManager.getCwd();
|
|
2554
|
-
this.publishActivity(session,
|
|
2757
|
+
this.publishActivity(session, { kind: "forking" }, "active");
|
|
2555
2758
|
this.publishStatus(session);
|
|
2556
2759
|
try {
|
|
2557
2760
|
const entryId = request.retainCheckpoint === true ? messageHistoryTargetId(session.sessionManager.getBranch(), request.entryId) : request.entryId;
|
|
@@ -2564,7 +2767,7 @@ export class PiSessionService {
|
|
|
2564
2767
|
throw new Error(this.t("server.main.0246b6af6843", "Session fork is unavailable"));
|
|
2565
2768
|
if (result.session === undefined) {
|
|
2566
2769
|
if (this.isCurrentActiveSession(session)) {
|
|
2567
|
-
this.publishActivity(session,
|
|
2770
|
+
this.publishActivity(session, { kind: "forkCancelled" }, "idle");
|
|
2568
2771
|
this.publishStatus(session);
|
|
2569
2772
|
}
|
|
2570
2773
|
return { cancelled: true };
|
|
@@ -2574,7 +2777,7 @@ export class PiSessionService {
|
|
|
2574
2777
|
this.setSuggestedInput(forked, result.promptDraft);
|
|
2575
2778
|
this.events.publish(sourceSessionId, { type: "session.tree.changed" }, sourceEventScope);
|
|
2576
2779
|
if (forked !== undefined && this.isCurrentActiveSession(forked)) {
|
|
2577
|
-
this.publishActivity(forked,
|
|
2780
|
+
this.publishActivity(forked, { kind: "forked" }, "idle");
|
|
2578
2781
|
this.publishStatus(forked);
|
|
2579
2782
|
}
|
|
2580
2783
|
if (result.session.id !== sourceSessionId)
|
|
@@ -2588,7 +2791,7 @@ export class PiSessionService {
|
|
|
2588
2791
|
catch (error) {
|
|
2589
2792
|
const message = userFacingErrorMessage(error, this.t);
|
|
2590
2793
|
if (this.isCurrentActiveSession(session)) {
|
|
2591
|
-
this.publishActivity(session,
|
|
2794
|
+
this.publishActivity(session, { kind: "forkFailed" }, "error", message);
|
|
2592
2795
|
this.events.publish(session.sessionId, { type: "session.error", message }, sourceEventScope);
|
|
2593
2796
|
this.publishStatus(session);
|
|
2594
2797
|
}
|
|
@@ -2599,7 +2802,7 @@ export class PiSessionService {
|
|
|
2599
2802
|
const sessionKey = activeSessionKey(sessionId, eventScope);
|
|
2600
2803
|
if (this.activities.get(sessionKey)?.phase === "active") {
|
|
2601
2804
|
const at = new Date().toISOString();
|
|
2602
|
-
const stored = { phase: "idle", label:
|
|
2805
|
+
const stored = { phase: "idle", label: "idle", at, runtimePresentation: { kind: "idle" } };
|
|
2603
2806
|
this.activities.set(sessionKey, stored);
|
|
2604
2807
|
const activity = { sessionId, ...stored };
|
|
2605
2808
|
this.events.publish(sessionId, { type: "activity.update", activity }, eventScope);
|
|
@@ -2615,6 +2818,7 @@ export class PiSessionService {
|
|
|
2615
2818
|
const archiveInput = await this.archiveInputForSession(session);
|
|
2616
2819
|
await this.closeActiveSession(active);
|
|
2617
2820
|
await this.archiveStore.archive(archiveInput);
|
|
2821
|
+
this.workspaceActivity?.removeSession(archiveInput.sessionId, archiveInput.cwd, active.eventScope);
|
|
2618
2822
|
await this.forgetUnreadSessions([archiveInput], active.eventScope);
|
|
2619
2823
|
});
|
|
2620
2824
|
}
|
|
@@ -2658,43 +2862,10 @@ export class PiSessionService {
|
|
|
2658
2862
|
failures.push({ sessionId: resolvedSessionId, error: errorMessage(error, this.t) });
|
|
2659
2863
|
}
|
|
2660
2864
|
}
|
|
2661
|
-
const
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
failures.push({ sessionId: item.input.sessionId, error: this.t("session.stopBeforeArchive", "Stop current session activity before archiving") });
|
|
2666
|
-
continue;
|
|
2667
|
-
}
|
|
2668
|
-
readyPlanItems.push(active === undefined ? item : { ...item, active });
|
|
2669
|
-
}
|
|
2670
|
-
const readyInputs = [];
|
|
2671
|
-
const archivedSessionIds = [...alreadyArchivedSessionIds];
|
|
2672
|
-
await this.runTreeExclusiveOperation(readyPlanItems.map(({ input, active }) => ({
|
|
2673
|
-
sessionId: input.sessionId,
|
|
2674
|
-
...(active === undefined ? {} : { session: active.runtime.session, runtime: active.runtime }),
|
|
2675
|
-
})), this.t("session.stopBeforeArchive", "Stop current session activity before archiving"), async () => {
|
|
2676
|
-
for (const item of readyPlanItems) {
|
|
2677
|
-
try {
|
|
2678
|
-
if (item.active !== undefined)
|
|
2679
|
-
await this.closeActiveSession(item.active);
|
|
2680
|
-
else
|
|
2681
|
-
await this.closeActiveInScope(item.input.sessionId, eventScopeFromManagementContext(managementContext));
|
|
2682
|
-
readyInputs.push(item.input);
|
|
2683
|
-
}
|
|
2684
|
-
catch (error) {
|
|
2685
|
-
failures.push({ sessionId: item.input.sessionId, error: errorMessage(error, this.t) });
|
|
2686
|
-
}
|
|
2687
|
-
}
|
|
2688
|
-
try {
|
|
2689
|
-
const archived = await this.archiveStoreArchiveMany(readyInputs);
|
|
2690
|
-
archivedSessionIds.push(...archived.map((record) => record.sessionId));
|
|
2691
|
-
unreadArchivedIdentities.push(...archived);
|
|
2692
|
-
}
|
|
2693
|
-
catch (error) {
|
|
2694
|
-
for (const input of readyInputs)
|
|
2695
|
-
failures.push({ sessionId: input.sessionId, error: errorMessage(error, this.t) });
|
|
2696
|
-
}
|
|
2697
|
-
});
|
|
2865
|
+
const execution = await this.executeArchiveBatch(planItems.map((item) => item.input), managementContext);
|
|
2866
|
+
failures.push(...execution.failures);
|
|
2867
|
+
failures.push(...execution.skippedBusySessionIds.map((sessionId) => ({ sessionId, error: this.t("session.stopBeforeArchive", "Stop current session activity before archiving") })));
|
|
2868
|
+
const archivedSessionIds = [...alreadyArchivedSessionIds, ...execution.successes.map((input) => input.sessionId)];
|
|
2698
2869
|
await this.forgetUnreadSessions(unreadArchivedIdentities, eventScopeFromManagementContext(managementContext));
|
|
2699
2870
|
return {
|
|
2700
2871
|
archived: true,
|
|
@@ -2722,7 +2893,9 @@ export class PiSessionService {
|
|
|
2722
2893
|
}
|
|
2723
2894
|
for (const input of archiveInputs)
|
|
2724
2895
|
await this.closeActiveInScope(input.sessionId, eventScopeFromManagementContext(managementContext));
|
|
2725
|
-
await this.archiveStoreArchiveMany(archiveInputs);
|
|
2896
|
+
const archived = await this.archiveStoreArchiveMany(archiveInputs);
|
|
2897
|
+
for (const record of archived)
|
|
2898
|
+
this.workspaceActivity?.removeSession(record.sessionId, record.cwd, eventScopeFromManagementContext(managementContext));
|
|
2726
2899
|
});
|
|
2727
2900
|
await this.forgetUnreadSessions(plan.targets.map((target) => ({ sessionId: target.id, cwd: target.cwd })), eventScopeFromManagementContext(managementContext));
|
|
2728
2901
|
return {
|
|
@@ -2735,10 +2908,15 @@ export class PiSessionService {
|
|
|
2735
2908
|
async restore(ref, managementContext) {
|
|
2736
2909
|
const archived = await this.getArchived(ref);
|
|
2737
2910
|
if (archived === undefined)
|
|
2738
|
-
throw new Error(
|
|
2739
|
-
|
|
2740
|
-
await this.
|
|
2741
|
-
|
|
2911
|
+
throw new Error("Session not found");
|
|
2912
|
+
const active = this.activeForLookup({ id: archived.sessionId, cwd: archived.cwd }, managementContext);
|
|
2913
|
+
await this.runTreeExclusiveOperation([{ sessionId: archived.sessionId, ...(active === undefined ? {} : { session: active.runtime.session, runtime: active.runtime }) }], "Stop current session activity before restoring archived session", async () => {
|
|
2914
|
+
await this.closeActiveInScope(archived.sessionId, eventScopeFromManagementContext(managementContext));
|
|
2915
|
+
await this.archiveStore.restore(archived.sessionId);
|
|
2916
|
+
const restored = (await this.sessionManager.list(archived.cwd)).find((entry) => entry.id === archived.sessionId);
|
|
2917
|
+
this.workspaceActivity?.applySessionIntervention(archived.cwd, archived.sessionId, restored?.interventionRequired === true, eventScopeFromManagementContext(managementContext));
|
|
2918
|
+
await this.forgetUnreadSessions([archived], eventScopeFromManagementContext(managementContext));
|
|
2919
|
+
});
|
|
2742
2920
|
}
|
|
2743
2921
|
async deleteArchived(ref, managementContext) {
|
|
2744
2922
|
const record = await this.getArchived(ref);
|
|
@@ -2770,27 +2948,10 @@ export class PiSessionService {
|
|
|
2770
2948
|
}
|
|
2771
2949
|
planItems.push({ record });
|
|
2772
2950
|
}
|
|
2773
|
-
const
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
readyRecords.push(item.record);
|
|
2778
|
-
}
|
|
2779
|
-
catch (error) {
|
|
2780
|
-
failures.push({ sessionId: item.record.sessionId, error: errorMessage(error, this.t) });
|
|
2781
|
-
}
|
|
2782
|
-
}
|
|
2783
|
-
const deleteIds = readyRecords.map((record) => record.sessionId);
|
|
2784
|
-
let deletedSessionIds = [];
|
|
2785
|
-
try {
|
|
2786
|
-
deletedSessionIds = await this.archiveStoreDeleteArchivedMany(deleteIds);
|
|
2787
|
-
}
|
|
2788
|
-
catch (error) {
|
|
2789
|
-
for (const sessionId of deleteIds)
|
|
2790
|
-
failures.push({ sessionId, error: errorMessage(error, this.t) });
|
|
2791
|
-
}
|
|
2792
|
-
const deletedIdSet = new Set(deletedSessionIds);
|
|
2793
|
-
await this.forgetUnreadSessions(readyRecords.filter((record) => deletedIdSet.has(record.sessionId)), eventScopeFromManagementContext(managementContext));
|
|
2951
|
+
const execution = await this.executeDeleteArchivedBatch(planItems.map((item) => item.record), managementContext);
|
|
2952
|
+
failures.push(...execution.failures);
|
|
2953
|
+
failures.push(...execution.skippedBusySessionIds.map((sessionId) => ({ sessionId, error: this.t("session.stopBeforeDeleteArchive", "Stop current session activity before deleting archived session") })));
|
|
2954
|
+
const deletedSessionIds = execution.successes.map((record) => record.sessionId);
|
|
2794
2955
|
return {
|
|
2795
2956
|
deleted: true,
|
|
2796
2957
|
deletedSessionIds,
|
|
@@ -2860,11 +3021,11 @@ export class PiSessionService {
|
|
|
2860
3021
|
this.abortRunScopedExtensionDialogs(active.runtime.session);
|
|
2861
3022
|
try {
|
|
2862
3023
|
await this.abortSessionOperations(active.runtime.session);
|
|
2863
|
-
this.publishActivity(active.runtime.session,
|
|
3024
|
+
this.publishActivity(active.runtime.session, { kind: "stopped" }, "idle");
|
|
2864
3025
|
}
|
|
2865
3026
|
catch (error) {
|
|
2866
3027
|
const message = userFacingErrorMessage(error, this.t);
|
|
2867
|
-
this.publishActivity(active.runtime.session,
|
|
3028
|
+
this.publishActivity(active.runtime.session, { kind: "stopFailed" }, "error", message);
|
|
2868
3029
|
throw error;
|
|
2869
3030
|
}
|
|
2870
3031
|
finally {
|
|
@@ -3025,6 +3186,58 @@ export class PiSessionService {
|
|
|
3025
3186
|
const entries = await Promise.all(uniqueCwds.map(async (cwd) => [cwd, await this.sessionManager.list(cwd)]));
|
|
3026
3187
|
return new Map(entries);
|
|
3027
3188
|
}
|
|
3189
|
+
executeArchiveBatch(inputs, context) {
|
|
3190
|
+
return this.executeSessionLifecycleBatch(inputs, "archive", async (ready) => (await this.archiveStoreArchiveMany(ready)).map((record) => record.sessionId), context);
|
|
3191
|
+
}
|
|
3192
|
+
executeDeleteArchivedBatch(records, context) {
|
|
3193
|
+
return this.executeSessionLifecycleBatch(records, "delete", (ready) => this.archiveStoreDeleteArchivedMany(ready.map((record) => record.sessionId)), context);
|
|
3194
|
+
}
|
|
3195
|
+
async executeSessionLifecycleBatch(items, reason, persist, context) {
|
|
3196
|
+
const scope = eventScopeFromManagementContext(context);
|
|
3197
|
+
const result = { successes: [], failures: [], skippedBusySessionIds: [] };
|
|
3198
|
+
const targets = [];
|
|
3199
|
+
const idleItems = [];
|
|
3200
|
+
// Check and reserve synchronously before any teardown can yield. Identity
|
|
3201
|
+
// reservations also protect unloaded sessions for the full persistence span.
|
|
3202
|
+
for (const item of items) {
|
|
3203
|
+
const active = this.activeForLookup({ id: item.sessionId, cwd: item.cwd }, context);
|
|
3204
|
+
if (this.isTreeExclusiveSessionIdentityActive(item.sessionId)
|
|
3205
|
+
|| (active !== undefined && this.hasActiveWork(active.runtime.session))) {
|
|
3206
|
+
result.skippedBusySessionIds.push(item.sessionId);
|
|
3207
|
+
continue;
|
|
3208
|
+
}
|
|
3209
|
+
idleItems.push(item);
|
|
3210
|
+
targets.push({ sessionId: item.sessionId, ...(active === undefined ? {} : { session: active.runtime.session, runtime: active.runtime }) });
|
|
3211
|
+
}
|
|
3212
|
+
await this.runTreeExclusiveOperation(targets, "Stop current session activity before changing session lifecycle", async () => {
|
|
3213
|
+
const ready = [];
|
|
3214
|
+
for (const item of idleItems) {
|
|
3215
|
+
try {
|
|
3216
|
+
await this.closeActive(item.sessionId, { kind: "clear", reason }, scope);
|
|
3217
|
+
ready.push(item);
|
|
3218
|
+
}
|
|
3219
|
+
catch (error) {
|
|
3220
|
+
result.failures.push({ sessionId: item.sessionId, error: errorMessage(error) });
|
|
3221
|
+
}
|
|
3222
|
+
}
|
|
3223
|
+
try {
|
|
3224
|
+
const persistedIds = await persist(ready);
|
|
3225
|
+
const readyById = new Map(ready.map((item) => [item.sessionId, item]));
|
|
3226
|
+
result.successes = persistedIds.flatMap((sessionId) => {
|
|
3227
|
+
const item = readyById.get(sessionId);
|
|
3228
|
+
return item === undefined ? [] : [item];
|
|
3229
|
+
});
|
|
3230
|
+
}
|
|
3231
|
+
catch (error) {
|
|
3232
|
+
for (const item of ready)
|
|
3233
|
+
result.failures.push({ sessionId: item.sessionId, error: errorMessage(error) });
|
|
3234
|
+
}
|
|
3235
|
+
for (const item of result.successes)
|
|
3236
|
+
this.workspaceActivity?.removeSession(item.sessionId, item.cwd, scope);
|
|
3237
|
+
await this.forgetUnreadSessions(result.successes, scope);
|
|
3238
|
+
});
|
|
3239
|
+
return result;
|
|
3240
|
+
}
|
|
3028
3241
|
async archiveStoreArchiveMany(inputs) {
|
|
3029
3242
|
if (inputs.length === 0)
|
|
3030
3243
|
return [];
|
|
@@ -3048,6 +3261,9 @@ export class PiSessionService {
|
|
|
3048
3261
|
return [...sessionIds];
|
|
3049
3262
|
}
|
|
3050
3263
|
async cleanupPlan(request) {
|
|
3264
|
+
if (request.skipPinned === true && this.sessionPins === undefined)
|
|
3265
|
+
throw new Error("Authoritative session pin store is unavailable");
|
|
3266
|
+
const excludedPinnedSessionIds = request.skipPinned === true ? await this.sessionPins?.pinnedSessionIds() : undefined;
|
|
3051
3267
|
const [sessions, archivedRecords, scopedSessions] = await Promise.all([
|
|
3052
3268
|
this.sessionManager.listAll(),
|
|
3053
3269
|
this.archiveStore.list(),
|
|
@@ -3060,6 +3276,7 @@ export class PiSessionService {
|
|
|
3060
3276
|
archivedRecords,
|
|
3061
3277
|
activeSessions: this.cleanupActiveSessionStatuses(),
|
|
3062
3278
|
thresholds: request.thresholds,
|
|
3279
|
+
...(excludedPinnedSessionIds === undefined ? {} : { excludedPinnedSessionIds }),
|
|
3063
3280
|
...(request.projectCwds === undefined ? {} : { projectCwds: request.projectCwds }),
|
|
3064
3281
|
now: this.now(),
|
|
3065
3282
|
});
|
|
@@ -3191,6 +3408,10 @@ export class PiSessionService {
|
|
|
3191
3408
|
this.events.mediaIndex.forgetSession({ id: sessionId, cwd: active.runtime.session.sessionManager.getCwd(), eventScope: active.eventScope });
|
|
3192
3409
|
this.activities.delete(activeSessionKey(sessionId, active.eventScope));
|
|
3193
3410
|
this.workspaceActivity?.removeSession(sessionId, active.runtime.session.sessionManager.getCwd(), active.eventScope);
|
|
3411
|
+
const session = active.runtime.session;
|
|
3412
|
+
if (sessionFileExists(session.sessionFile) && this.interventionRequired(session)) {
|
|
3413
|
+
this.workspaceActivity?.applySessionIntervention(session.sessionManager.getCwd(), sessionId, true, active.eventScope);
|
|
3414
|
+
}
|
|
3194
3415
|
this.clearAuthLossWarningsForSession(sessionId);
|
|
3195
3416
|
this.clearCompactionPromptQueue(active.runtime.session);
|
|
3196
3417
|
// Disarm subsession notification before teardown so the abort below cannot
|
|
@@ -3445,7 +3666,7 @@ export class PiSessionService {
|
|
|
3445
3666
|
operation.error(message);
|
|
3446
3667
|
return;
|
|
3447
3668
|
}
|
|
3448
|
-
this.publishActivity(session,
|
|
3669
|
+
this.publishActivity(session, { kind: "extensionError" }, "error", message);
|
|
3449
3670
|
this.events.publish(session.sessionId, { type: "session.error", message }, owner.eventScope);
|
|
3450
3671
|
},
|
|
3451
3672
|
});
|
|
@@ -3501,7 +3722,7 @@ export class PiSessionService {
|
|
|
3501
3722
|
if (current !== undefined && this.isCurrentActiveSession(current)) {
|
|
3502
3723
|
const message = userFacingErrorMessage(error, this.t);
|
|
3503
3724
|
current.extensionRunner.getUIContext().notify(message, "error");
|
|
3504
|
-
this.publishActivity(current,
|
|
3725
|
+
this.publishActivity(current, { kind: "extensionCallbackFailed" }, "error", message);
|
|
3505
3726
|
this.events.publish(current.sessionId, { type: "session.error", message }, this.eventScopeForSession(current));
|
|
3506
3727
|
}
|
|
3507
3728
|
throw error;
|
|
@@ -3554,12 +3775,17 @@ export class PiSessionService {
|
|
|
3554
3775
|
}
|
|
3555
3776
|
this.reconcileRuntimeMessageCount(session);
|
|
3556
3777
|
this.restoreSubsessionReceipts(session);
|
|
3778
|
+
this.interventionStates.set(session, sessionInterventionRequired(session.sessionManager.getEntries?.() ?? session.sessionManager.getBranch()));
|
|
3779
|
+
this.publishedSessionNames.set(session, { sessionId: session.sessionId, name: session.sessionName });
|
|
3557
3780
|
const unsubscribe = session.subscribe((event) => {
|
|
3558
3781
|
const eventType = getString(event, "type");
|
|
3782
|
+
if (eventType === "session_info_changed")
|
|
3783
|
+
this.publishSessionName(session);
|
|
3559
3784
|
const message = getProperty(event, "message");
|
|
3560
3785
|
const entry = getProperty(event, "entry");
|
|
3561
3786
|
const inbox = this.subsessionInbox(session.sessionId, session.sessionFile, active.eventScope);
|
|
3562
3787
|
if (eventType === "agent_start") {
|
|
3788
|
+
this.setInterventionRequired(session, false);
|
|
3563
3789
|
this.restoreSubsessionReceipts(session, false);
|
|
3564
3790
|
this.subsessionStoppedParents.delete(session);
|
|
3565
3791
|
}
|
|
@@ -3574,6 +3800,8 @@ export class PiSessionService {
|
|
|
3574
3800
|
if (eventType === "agent_settled")
|
|
3575
3801
|
this.scheduleSubsessionDelivery(session);
|
|
3576
3802
|
const role = getString(message, "role");
|
|
3803
|
+
if (eventType === "message_end" && requestsHumanIntervention(message))
|
|
3804
|
+
this.setInterventionRequired(session, true);
|
|
3577
3805
|
if ((eventType === "message_end" && (role === "user" || role === "assistant" || role === "toolResult" || role === "system"))
|
|
3578
3806
|
|| (eventType === "entry_appended" && getString(entry, "type") === "message")) {
|
|
3579
3807
|
this.runtimeMessageCounts.set(session, this.runtimeMessageCount(session) + 1);
|
|
@@ -3630,18 +3858,21 @@ export class PiSessionService {
|
|
|
3630
3858
|
const aborted = getBoolean(event, "aborted") === true;
|
|
3631
3859
|
const errorMessage = getString(event, "errorMessage");
|
|
3632
3860
|
const automatic = getString(event, "reason") !== "manual";
|
|
3633
|
-
const
|
|
3634
|
-
?
|
|
3635
|
-
: errorMessage === undefined ? undefined :
|
|
3861
|
+
const presentation = aborted
|
|
3862
|
+
? { kind: automatic ? "automaticCompactionCancelled" : "compactionCancelled" }
|
|
3863
|
+
: errorMessage === undefined ? undefined : { kind: "compactionFailed" };
|
|
3864
|
+
const message = presentation === undefined ? undefined : sessionNotificationSources[presentation.kind];
|
|
3636
3865
|
if (!aborted && errorMessage !== undefined) {
|
|
3637
3866
|
this.events.publish(session.sessionId, { type: "session.diagnostic", message: errorMessage }, this.eventScopeForSession(session));
|
|
3638
3867
|
}
|
|
3639
|
-
this.publishActivity(session, aborted
|
|
3868
|
+
this.publishActivity(session, aborted
|
|
3869
|
+
? { kind: "compactionCancelled", detailKind: automatic ? "automaticCompactionCancelled" : "compactionCancelled" }
|
|
3870
|
+
: errorMessage === undefined ? { kind: "compactionComplete" } : { kind: "compactionFailed", detailKind: "compactionFailed" }, !aborted && errorMessage !== undefined ? "error" : "idle", message);
|
|
3640
3871
|
// Successful compaction already has a canonical summary in the transcript.
|
|
3641
3872
|
// Keep cancellation/failure feedback in the refresh-safe session inbox only.
|
|
3642
3873
|
const generation = this.notificationGenerationBySession.get(session);
|
|
3643
3874
|
if (message !== undefined && generation !== undefined) {
|
|
3644
|
-
this.publishNotificationMutations(this.notificationsForSession(session).addNotification(generation, message, aborted ? "info" : "error").mutations);
|
|
3875
|
+
this.publishNotificationMutations(this.notificationsForSession(session).addNotification(generation, message, aborted ? "info" : "error", presentation).mutations);
|
|
3645
3876
|
}
|
|
3646
3877
|
}
|
|
3647
3878
|
scheduleCompactionQueueDrain(session, delayMs = 0) {
|
|
@@ -3719,43 +3950,6 @@ export class PiSessionService {
|
|
|
3719
3950
|
clearTimeout(timer);
|
|
3720
3951
|
this.compactionDrainTimers.clear();
|
|
3721
3952
|
}
|
|
3722
|
-
maybeGenerateSessionName(session, firstMessage) {
|
|
3723
|
-
if (session.sessionName !== undefined || session.messages.length !== 0 || session.isStreaming || session.isCompacting)
|
|
3724
|
-
return;
|
|
3725
|
-
void this.generateSessionName(session, firstMessage).then((name) => {
|
|
3726
|
-
if (name === undefined)
|
|
3727
|
-
this.logger.info({ sessionId: session.sessionId }, "Session naming returned no title; using the first-message fallback");
|
|
3728
|
-
this.applyGeneratedSessionName(session, name ?? fallbackSessionName(firstMessage));
|
|
3729
|
-
}).catch((error) => {
|
|
3730
|
-
const errorCategory = error instanceof Error && (error.name === "AbortError" || error.name === "TimeoutError") ? "timeout" : "generation";
|
|
3731
|
-
this.logger.info({ sessionId: session.sessionId, errorCategory }, "Session naming failed; using the first-message fallback");
|
|
3732
|
-
this.applyGeneratedSessionName(session, fallbackSessionName(firstMessage));
|
|
3733
|
-
});
|
|
3734
|
-
}
|
|
3735
|
-
async generateSessionName(session, firstMessage) {
|
|
3736
|
-
// One request keeps its settings even if the operator edits the config while it runs.
|
|
3737
|
-
const naming = this.config === undefined ? {} : (await this.config.read()).effectiveConfig.sessionNaming ?? {};
|
|
3738
|
-
let model = session.model;
|
|
3739
|
-
if (naming.model !== undefined) {
|
|
3740
|
-
const parsed = parseModelSpec(naming.model);
|
|
3741
|
-
model = parsed === undefined ? undefined : session.modelRuntime.getModel(parsed.provider, parsed.modelId);
|
|
3742
|
-
if (model === undefined)
|
|
3743
|
-
throw new Error("Configured session naming model is unavailable");
|
|
3744
|
-
}
|
|
3745
|
-
if (model === undefined)
|
|
3746
|
-
return undefined;
|
|
3747
|
-
return generateShortSessionName(session.agent.streamFunction, model, firstMessage, naming);
|
|
3748
|
-
}
|
|
3749
|
-
applyGeneratedSessionName(session, name) {
|
|
3750
|
-
if (name === undefined || session.sessionName !== undefined)
|
|
3751
|
-
return;
|
|
3752
|
-
if (this.treeNavigations.has(session)) {
|
|
3753
|
-
this.deferredGeneratedSessionNames.set(session, name);
|
|
3754
|
-
return;
|
|
3755
|
-
}
|
|
3756
|
-
session.setSessionName(name);
|
|
3757
|
-
this.publishSessionName(session);
|
|
3758
|
-
}
|
|
3759
3953
|
applyAuthChange(change) {
|
|
3760
3954
|
const changedRuntime = change.modelRuntime;
|
|
3761
3955
|
for (const active of this.active.values()) {
|
|
@@ -3786,7 +3980,8 @@ export class PiSessionService {
|
|
|
3786
3980
|
this.events.publish(session.sessionId, {
|
|
3787
3981
|
type: "command.output",
|
|
3788
3982
|
level: "error",
|
|
3789
|
-
message:
|
|
3983
|
+
message: `Authentication for ${model.provider}/${model.id} was removed. Use /model to select another model.`,
|
|
3984
|
+
presentation: { kind: "modelAuthRemoved", provider: model.provider, model: model.id },
|
|
3790
3985
|
}, eventScope);
|
|
3791
3986
|
}
|
|
3792
3987
|
clearAuthLossWarningsForSession(sessionId) {
|
|
@@ -3796,6 +3991,10 @@ export class PiSessionService {
|
|
|
3796
3991
|
}
|
|
3797
3992
|
}
|
|
3798
3993
|
publishSessionName(session) {
|
|
3994
|
+
const previous = this.publishedSessionNames.get(session);
|
|
3995
|
+
if (previous?.sessionId === session.sessionId && previous.name === session.sessionName)
|
|
3996
|
+
return;
|
|
3997
|
+
this.publishedSessionNames.set(session, { sessionId: session.sessionId, name: session.sessionName });
|
|
3799
3998
|
const event = session.sessionName === undefined
|
|
3800
3999
|
? { type: "session.name", sessionId: session.sessionId }
|
|
3801
4000
|
: { type: "session.name", sessionId: session.sessionId, name: session.sessionName };
|
|
@@ -3819,25 +4018,25 @@ export class PiSessionService {
|
|
|
3819
4018
|
}
|
|
3820
4019
|
this.publishStatus(session);
|
|
3821
4020
|
if (activity?.phase === "active")
|
|
3822
|
-
this.publishActivity(session, activity.
|
|
4021
|
+
this.publishActivity(session, activity.runtimePresentation, "active", activity.detail);
|
|
3823
4022
|
else
|
|
3824
|
-
this.publishActivity(session, this.
|
|
4023
|
+
this.publishActivity(session, this.activityPresentationFromStatus(session), "active");
|
|
3825
4024
|
}
|
|
3826
4025
|
}
|
|
3827
|
-
|
|
4026
|
+
activityPresentationFromStatus(session) {
|
|
3828
4027
|
if (this.treeNavigations.has(session))
|
|
3829
|
-
return
|
|
4028
|
+
return { kind: "navigatingTree" };
|
|
3830
4029
|
if (this.isSessionEntryMutationActive(session))
|
|
3831
|
-
return
|
|
4030
|
+
return { kind: "updatingSession" };
|
|
3832
4031
|
if (session.isCompacting)
|
|
3833
|
-
return
|
|
4032
|
+
return { kind: "compacting" };
|
|
3834
4033
|
if (session.isBashRunning)
|
|
3835
|
-
return
|
|
4034
|
+
return { kind: "runningBash" };
|
|
3836
4035
|
if (session.isStreaming)
|
|
3837
|
-
return
|
|
4036
|
+
return { kind: "agentRunning" };
|
|
3838
4037
|
if (this.pendingMessageCount(session) > 0)
|
|
3839
|
-
return
|
|
3840
|
-
return
|
|
4038
|
+
return { kind: "queued" };
|
|
4039
|
+
return { kind: "active" };
|
|
3841
4040
|
}
|
|
3842
4041
|
hasActiveWork(session) {
|
|
3843
4042
|
const execution = this.extensionCommandExecution.getStore();
|
|
@@ -3942,56 +4141,56 @@ export class PiSessionService {
|
|
|
3942
4141
|
if (eventType === undefined)
|
|
3943
4142
|
return;
|
|
3944
4143
|
if (eventType === "agent_start") {
|
|
3945
|
-
this.publishActivity(session,
|
|
4144
|
+
this.publishActivity(session, { kind: "agentRunning" }, "active");
|
|
3946
4145
|
return;
|
|
3947
4146
|
}
|
|
3948
4147
|
if (eventType === "agent_end") {
|
|
3949
|
-
this.publishActivity(session,
|
|
4148
|
+
this.publishActivity(session, { kind: "idle" }, "idle");
|
|
3950
4149
|
const eventScope = this.eventScopeForSession(session);
|
|
3951
4150
|
const sessionKey = activeSessionKey(session.sessionId, eventScope);
|
|
3952
4151
|
this.activities.scheduleSettledRefresh(sessionKey, () => {
|
|
3953
4152
|
if (this.active.get(sessionKey)?.runtime.session !== session)
|
|
3954
4153
|
return;
|
|
3955
|
-
this.publishActivity(session,
|
|
4154
|
+
this.publishActivity(session, { kind: "idle" }, "idle");
|
|
3956
4155
|
this.publishStatus(session);
|
|
3957
4156
|
}, 250);
|
|
3958
4157
|
return;
|
|
3959
4158
|
}
|
|
3960
4159
|
if (eventType === "turn_end") {
|
|
3961
|
-
this.publishActivity(session,
|
|
4160
|
+
this.publishActivity(session, { kind: "turnComplete" }, "idle");
|
|
3962
4161
|
return;
|
|
3963
4162
|
}
|
|
3964
4163
|
if (eventType === "message_start") {
|
|
3965
|
-
this.publishActivity(session,
|
|
4164
|
+
this.publishActivity(session, { kind: "messageStarted" }, "active");
|
|
3966
4165
|
return;
|
|
3967
4166
|
}
|
|
3968
4167
|
if (eventType === "message_end") {
|
|
3969
|
-
this.publishActivity(session,
|
|
4168
|
+
this.publishActivity(session, { kind: "messageComplete" }, "idle");
|
|
3970
4169
|
return;
|
|
3971
4170
|
}
|
|
3972
4171
|
if (eventType === "message_update") {
|
|
3973
|
-
this.publishActivity(session,
|
|
4172
|
+
this.publishActivity(session, { kind: "receivingResponse" }, "active");
|
|
3974
4173
|
return;
|
|
3975
4174
|
}
|
|
3976
4175
|
if (eventType === "tool_execution_start") {
|
|
3977
|
-
this.publishActivity(session,
|
|
4176
|
+
this.publishActivity(session, { kind: "runningTool" }, "active", getString(event, "toolName"));
|
|
3978
4177
|
return;
|
|
3979
4178
|
}
|
|
3980
4179
|
if (eventType === "tool_execution_end") {
|
|
3981
4180
|
const isError = getBoolean(event, "isError") === true;
|
|
3982
|
-
this.publishActivity(session, isError ?
|
|
4181
|
+
this.publishActivity(session, isError ? { kind: "toolFailed" } : { kind: "toolComplete" }, isError ? "error" : "idle", getString(event, "toolName"));
|
|
3983
4182
|
return;
|
|
3984
4183
|
}
|
|
3985
4184
|
if (eventType === "bash_execution_start") {
|
|
3986
|
-
this.publishActivity(session,
|
|
4185
|
+
this.publishActivity(session, { kind: "runningBash" }, "active");
|
|
3987
4186
|
return;
|
|
3988
4187
|
}
|
|
3989
4188
|
if (eventType === "bash_execution_end") {
|
|
3990
|
-
this.publishActivity(session,
|
|
4189
|
+
this.publishActivity(session, { kind: "bashComplete" }, "idle");
|
|
3991
4190
|
return;
|
|
3992
4191
|
}
|
|
3993
4192
|
if (this.hasActiveWork(session))
|
|
3994
|
-
this.publishActivity(session,
|
|
4193
|
+
this.publishActivity(session, { kind: "event", value: eventType }, "active");
|
|
3995
4194
|
}
|
|
3996
4195
|
auditToolExecutionEvent(active, event) {
|
|
3997
4196
|
const eventType = getString(event, "type");
|
|
@@ -4088,23 +4287,23 @@ export class PiSessionService {
|
|
|
4088
4287
|
const sessionId = sessionManager.getSessionId();
|
|
4089
4288
|
if (sessionId === "")
|
|
4090
4289
|
return { report: noop, end: noop };
|
|
4091
|
-
const label = intent === "create" ?
|
|
4290
|
+
const label = intent === "create" ? "Creating session" : "Opening session";
|
|
4092
4291
|
return {
|
|
4093
|
-
report: (
|
|
4292
|
+
report: (stage) => {
|
|
4293
|
+
const catalogRefreshing = this.catalogRefreshStatus?.isRefreshInFlight() === true;
|
|
4294
|
+
const phase = stage === "runtime" ? STARTUP_PHASE_RUNTIME : STARTUP_PHASE_EXTENSIONS;
|
|
4295
|
+
const detail = catalogRefreshing ? `${phase} · ${STARTUP_CONCURRENT_CATALOG_REFRESH}` : phase;
|
|
4296
|
+
this.publishStartupProgress(sessionId, startupToken, label, "active", detail, eventScope, { intent, stage, catalogRefreshing });
|
|
4297
|
+
},
|
|
4094
4298
|
end: () => {
|
|
4095
4299
|
// A real activity published during the window (an extension error, say)
|
|
4096
4300
|
// is the truth about this session and must survive the clear.
|
|
4097
4301
|
if (this.activities.get(activeSessionKey(sessionId, eventScope)) !== undefined)
|
|
4098
4302
|
return;
|
|
4099
|
-
this.publishStartupProgress(sessionId, startupToken,
|
|
4303
|
+
this.publishStartupProgress(sessionId, startupToken, "Idle", "idle", undefined, eventScope);
|
|
4100
4304
|
},
|
|
4101
4305
|
};
|
|
4102
4306
|
}
|
|
4103
|
-
startupDetail(phase) {
|
|
4104
|
-
return this.catalogRefreshStatus?.isRefreshInFlight() === true
|
|
4105
|
-
? `${phase} · ${this.t("startup.catalogRefresh", "Provider model catalog is refreshing")}`
|
|
4106
|
-
: phase;
|
|
4107
|
-
}
|
|
4108
4307
|
/**
|
|
4109
4308
|
* Report startup progress on the global channel only, echoing the caller's
|
|
4110
4309
|
* correlation token so a waiting browser row recognises its own construction.
|
|
@@ -4118,17 +4317,21 @@ export class PiSessionService {
|
|
|
4118
4317
|
* that sets the marker, and because it writes no `activities` entry no later
|
|
4119
4318
|
* heartbeat re-publication can carry it.
|
|
4120
4319
|
*/
|
|
4121
|
-
publishStartupProgress(sessionId, startupToken, label, phase, detail, eventScope) {
|
|
4320
|
+
publishStartupProgress(sessionId, startupToken, label, phase, detail, eventScope, startupPresentation) {
|
|
4122
4321
|
const at = new Date().toISOString();
|
|
4123
|
-
const activity =
|
|
4322
|
+
const activity = { sessionId, phase, label, at, startup: true,
|
|
4323
|
+
...(detail === undefined ? {} : { detail }),
|
|
4324
|
+
...(startupPresentation === undefined ? {} : { startupPresentation }),
|
|
4325
|
+
};
|
|
4124
4326
|
this.events.publishGlobal(startupToken === undefined ? { type: "session.startup", activity } : { type: "session.startup", startupToken, activity }, eventScope);
|
|
4125
4327
|
}
|
|
4126
|
-
publishActivity(session,
|
|
4328
|
+
publishActivity(session, runtimePresentation, phase, detail) {
|
|
4127
4329
|
const at = new Date().toISOString();
|
|
4128
|
-
const
|
|
4330
|
+
const label = runtimeActivityFallbackLabel(runtimePresentation);
|
|
4331
|
+
const stored = { phase, label, at, runtimePresentation, ...(detail === undefined ? {} : { detail }) };
|
|
4129
4332
|
const eventScope = this.eventScopeForSession(session);
|
|
4130
4333
|
this.activities.set(activeSessionKey(session.sessionId, eventScope), stored);
|
|
4131
|
-
const activity =
|
|
4334
|
+
const activity = { sessionId: session.sessionId, ...stored };
|
|
4132
4335
|
this.workspaceActivity?.applySessionActivity(session.sessionManager.getCwd(), activity, eventScope);
|
|
4133
4336
|
this.events.publish(session.sessionId, { type: "activity.update", activity }, eventScope);
|
|
4134
4337
|
this.events.publishGlobal({ type: "activity.update", activity }, eventScope);
|
|
@@ -4153,6 +4356,26 @@ export class PiSessionService {
|
|
|
4153
4356
|
if (path !== undefined)
|
|
4154
4357
|
this.managementMediaFiles.add(path);
|
|
4155
4358
|
}
|
|
4359
|
+
interventionRequired(session) {
|
|
4360
|
+
return this.interventionStates.get(session)
|
|
4361
|
+
?? sessionInterventionRequired(session.sessionManager.getEntries?.() ?? session.sessionManager.getBranch());
|
|
4362
|
+
}
|
|
4363
|
+
setInterventionRequired(session, required) {
|
|
4364
|
+
const previous = this.interventionRequired(session);
|
|
4365
|
+
if (previous === required)
|
|
4366
|
+
return;
|
|
4367
|
+
if (session.sessionManager.appendCustomEntry === undefined)
|
|
4368
|
+
throw new Error("Session manager cannot persist intervention state");
|
|
4369
|
+
// Update before append: the SDK emits entry_appended synchronously.
|
|
4370
|
+
this.interventionStates.set(session, required);
|
|
4371
|
+
try {
|
|
4372
|
+
session.sessionManager.appendCustomEntry(SESSION_INTERVENTION_CUSTOM_TYPE, { version: 1, required });
|
|
4373
|
+
}
|
|
4374
|
+
catch (error) {
|
|
4375
|
+
this.interventionStates.set(session, previous);
|
|
4376
|
+
throw error;
|
|
4377
|
+
}
|
|
4378
|
+
}
|
|
4156
4379
|
publishStatus(session) {
|
|
4157
4380
|
this.rememberManagementMediaFile(session, this.eventScopeForSession(session));
|
|
4158
4381
|
void this.refreshActivityMarker(session);
|
|
@@ -4170,7 +4393,7 @@ export class PiSessionService {
|
|
|
4170
4393
|
if (current?.phase !== "active" || this.hasActiveWork(session))
|
|
4171
4394
|
return;
|
|
4172
4395
|
const at = new Date().toISOString();
|
|
4173
|
-
const stored = { phase: "idle", label:
|
|
4396
|
+
const stored = { phase: "idle", label: "idle", at, runtimePresentation: { kind: "idle" } };
|
|
4174
4397
|
this.activities.set(activeSessionKey(session.sessionId, eventScope), stored);
|
|
4175
4398
|
const activity = { sessionId: session.sessionId, ...stored };
|
|
4176
4399
|
this.events.publish(session.sessionId, { type: "activity.update", activity }, eventScope);
|
|
@@ -4241,6 +4464,7 @@ export class PiSessionService {
|
|
|
4241
4464
|
sessionId: session.sessionId,
|
|
4242
4465
|
persisted: sessionFileExists(session.sessionFile),
|
|
4243
4466
|
recentlyActiveElsewhere: this.eventScopeForSession(session) === NORMAL_SESSION_EVENT_SCOPE && this.activityMarker.isActiveElsewhere(session.sessionFile),
|
|
4467
|
+
interventionRequired: this.interventionRequired(session) || pendingDialogs.length > 0,
|
|
4244
4468
|
...(model === undefined ? {} : { model }),
|
|
4245
4469
|
thinkingLevel: session.thinkingLevel,
|
|
4246
4470
|
isStreaming: session.isStreaming,
|
|
@@ -4322,8 +4546,22 @@ export class PiSessionService {
|
|
|
4322
4546
|
return this.unreadForScope(eventScope).durableCatalogSnapshot();
|
|
4323
4547
|
}
|
|
4324
4548
|
async reconcileUnreadWorkspaces(cwds) {
|
|
4549
|
+
this.unreadEligibilityRevision += 1;
|
|
4325
4550
|
await this.publishUnreadMutations(this.unreadStore.reconcileWorkspaces(cwds));
|
|
4326
4551
|
}
|
|
4552
|
+
async markUnread(sessionId, cwd, context) {
|
|
4553
|
+
const canonicalCwd = canonicalizeStoredCwd(cwd);
|
|
4554
|
+
const eligibilityRevision = this.unreadEligibilityRevision;
|
|
4555
|
+
const rows = await this.list(canonicalCwd, context);
|
|
4556
|
+
const row = rows.find((candidate) => candidate.id === sessionId && cwdPathsEqual(candidate.cwd, canonicalCwd));
|
|
4557
|
+
if (eligibilityRevision !== this.unreadEligibilityRevision
|
|
4558
|
+
|| row === undefined || row.archived === true || row.persisted !== true || row.agentSubsession === true) {
|
|
4559
|
+
throw new Error("Session is not eligible to be marked unread");
|
|
4560
|
+
}
|
|
4561
|
+
const store = this.unreadForScope(eventScopeFromManagementContext(context));
|
|
4562
|
+
await this.publishUnreadMutations(store.markUnread(sessionId, canonicalCwd));
|
|
4563
|
+
return store.durableCatalogSnapshot();
|
|
4564
|
+
}
|
|
4327
4565
|
async acknowledgeUnread(sessionId, request, context) {
|
|
4328
4566
|
const store = this.unreadForScope(eventScopeFromManagementContext(context));
|
|
4329
4567
|
const result = store.acknowledge(sessionId, {
|
|
@@ -4353,7 +4591,7 @@ export class PiSessionService {
|
|
|
4353
4591
|
if (this.hasActiveWork(session))
|
|
4354
4592
|
throw new Error(this.t("session.stopBeforeReload", "Stop current session activity before reloading"));
|
|
4355
4593
|
await this.runTreeExclusiveOperation([{ sessionId: session.sessionId, session }], this.t("session.stopBeforeReload", "Stop current session activity before reloading"), async () => {
|
|
4356
|
-
this.publishActivity(session,
|
|
4594
|
+
this.publishActivity(session, { kind: "reloading" }, "active");
|
|
4357
4595
|
const priorGeneration = this.notificationGenerationBySession.get(session);
|
|
4358
4596
|
let candidateGeneration;
|
|
4359
4597
|
const reloadBoundary = { beforeSessionStart: false };
|
|
@@ -4373,7 +4611,7 @@ export class PiSessionService {
|
|
|
4373
4611
|
if (candidateGeneration !== undefined) {
|
|
4374
4612
|
this.publishNotificationMutations(this.notificationsForSession(session).commitReplacement(candidateGeneration));
|
|
4375
4613
|
}
|
|
4376
|
-
this.publishActivity(session,
|
|
4614
|
+
this.publishActivity(session, { kind: "reloaded" }, "idle");
|
|
4377
4615
|
this.publishStatus(session);
|
|
4378
4616
|
}
|
|
4379
4617
|
catch (error) {
|
|
@@ -4384,7 +4622,7 @@ export class PiSessionService {
|
|
|
4384
4622
|
this.notificationGenerationBySession.set(session, candidateGeneration);
|
|
4385
4623
|
}
|
|
4386
4624
|
const message = error instanceof Error ? error.message : String(error);
|
|
4387
|
-
this.publishActivity(session,
|
|
4625
|
+
this.publishActivity(session, { kind: "reloadFailed" }, "error", message);
|
|
4388
4626
|
this.events.publish(session.sessionId, { type: "session.error", message }, this.eventScopeForSession(session));
|
|
4389
4627
|
this.publishStatus(session);
|
|
4390
4628
|
throw error;
|
|
@@ -4404,7 +4642,7 @@ export class PiSessionService {
|
|
|
4404
4642
|
return [...this.active.values()].some((active) => active.runtime.session === session);
|
|
4405
4643
|
}
|
|
4406
4644
|
async createSessionRuntime(sessionManager, cwd, options, startup) {
|
|
4407
|
-
startup.report(
|
|
4645
|
+
startup.report("runtime");
|
|
4408
4646
|
options.startupSignal?.throwIfAborted();
|
|
4409
4647
|
// Ordinary local sessions (undefined provenance) keep the current rule.
|
|
4410
4648
|
// Only an explicit host one-shot forces delegation off; do not treat every
|
|
@@ -4471,7 +4709,7 @@ export class PiSessionService {
|
|
|
4471
4709
|
await this.recoverSubsessionTrackingForOpenedSession(runtime.session);
|
|
4472
4710
|
}
|
|
4473
4711
|
startupSignal?.throwIfAborted();
|
|
4474
|
-
startup.report(
|
|
4712
|
+
startup.report("extensions");
|
|
4475
4713
|
// Startup hooks emit through the same scoped stream as hosted turns.
|
|
4476
4714
|
this.bindRuntime(active);
|
|
4477
4715
|
await this.bindSessionExtensions(runtime.session, notificationGeneration, active, startupSignal);
|
|
@@ -4626,12 +4864,15 @@ export class PiSessionService {
|
|
|
4626
4864
|
const nextCwd = canonicalizeStoredCwd(next.sessionManager.getCwd());
|
|
4627
4865
|
if (previous.sessionId === next.sessionId && cwdPathsEqual(previousCwd, nextCwd))
|
|
4628
4866
|
return;
|
|
4867
|
+
this.unreadEligibilityRevision += 1;
|
|
4629
4868
|
await this.publishUnreadMutations(store.forgetSession(previous.sessionId, previousCwd));
|
|
4630
4869
|
}
|
|
4631
4870
|
forgetUnreadActivity(session) {
|
|
4632
4871
|
this.unreadForScope(this.eventScopeForSession(session)).forgetActivity(session.sessionId, canonicalizeStoredCwd(session.sessionManager.getCwd()));
|
|
4633
4872
|
}
|
|
4634
4873
|
async forgetUnreadSessions(identities, scope = NORMAL_SESSION_EVENT_SCOPE) {
|
|
4874
|
+
if (identities.length > 0)
|
|
4875
|
+
this.unreadEligibilityRevision += 1;
|
|
4635
4876
|
const mutations = [];
|
|
4636
4877
|
for (const identity of identities) {
|
|
4637
4878
|
mutations.push(...this.unreadForScope(scope).forgetSession(identity.sessionId, canonicalizeStoredCwd(identity.cwd)));
|
|
@@ -4735,16 +4976,6 @@ export class PiSessionService {
|
|
|
4735
4976
|
this.unreadPublicationRetryDelayMs = this.unreadPublicationRetryInitialMs;
|
|
4736
4977
|
}
|
|
4737
4978
|
flushDeferredTreeNavigationWork(session) {
|
|
4738
|
-
const generatedName = this.deferredGeneratedSessionNames.get(session);
|
|
4739
|
-
this.deferredGeneratedSessionNames.delete(session);
|
|
4740
|
-
if (generatedName !== undefined) {
|
|
4741
|
-
try {
|
|
4742
|
-
this.applyGeneratedSessionName(session, generatedName);
|
|
4743
|
-
}
|
|
4744
|
-
catch (error) {
|
|
4745
|
-
this.logger.info({ sessionId: session.sessionId, error: error instanceof Error ? error.message : String(error) }, "failed to apply deferred session name");
|
|
4746
|
-
}
|
|
4747
|
-
}
|
|
4748
4979
|
this.restoreSubsessionReceipts(session);
|
|
4749
4980
|
this.scheduleSubsessionDelivery(session);
|
|
4750
4981
|
}
|
|
@@ -4883,8 +5114,8 @@ export class PiSessionService {
|
|
|
4883
5114
|
}, 0);
|
|
4884
5115
|
}
|
|
4885
5116
|
assertMcpModeAllowed(managementContext) {
|
|
4886
|
-
if (VERSION !== "1.3.0")
|
|
4887
|
-
throw new UserFacingError("mcpAuth.sdkUnsupported", "Dedicated MCP authentication requires Pi 1.3.0");
|
|
5117
|
+
if (VERSION !== "1.3.0" && VERSION !== "1.4.0")
|
|
5118
|
+
throw new UserFacingError("mcpAuth.sdkUnsupported", "Dedicated MCP authentication requires Pi 1.3.0 or 1.4.0");
|
|
4888
5119
|
if (managementContext !== undefined && !managementUsesNormalPermissions(managementContext, { allowPrivileged: this.managementAllowPrivileged })) {
|
|
4889
5120
|
throw new UserFacingError("mcpAuth.restrictedManagement", "MCP authentication is unavailable in restricted management mode");
|
|
4890
5121
|
}
|
|
@@ -5034,6 +5265,7 @@ function previewResponseFromPlan(plan) {
|
|
|
5034
5265
|
projects: plan.projects,
|
|
5035
5266
|
totals: plan.totals,
|
|
5036
5267
|
...(plan.skippedBusySessionIds.length === 0 ? {} : { skippedBusySessionIds: plan.skippedBusySessionIds }),
|
|
5268
|
+
...(plan.skippedPinnedSessionIds === undefined ? {} : { skippedPinnedSessionIds: plan.skippedPinnedSessionIds }),
|
|
5037
5269
|
};
|
|
5038
5270
|
}
|
|
5039
5271
|
function uniqueBulkSessionRefs(refs) {
|
|
@@ -5121,6 +5353,7 @@ function clientSessionFromListEntry(session) {
|
|
|
5121
5353
|
modified: session.modified.toISOString(),
|
|
5122
5354
|
messageCount: session.messageCount,
|
|
5123
5355
|
firstMessage: clientSessionFirstMessagePreview(session.firstMessage),
|
|
5356
|
+
...(session.interventionRequired === true ? { interventionRequired: true } : {}),
|
|
5124
5357
|
...(session.parentSessionPath === undefined ? {} : { parentSessionPath: session.parentSessionPath }),
|
|
5125
5358
|
};
|
|
5126
5359
|
}
|