@pasko70/pibo 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.codex/skills/pi-agent-harness/SKILL.md +319 -0
- package/.codex/skills/pi-agent-harness/agents/openai.yaml +4 -0
- package/README.md +318 -0
- package/context/codex-base-prompt.md +144 -0
- package/context/pibo-compaction-prompt.md +100 -0
- package/context/pibo-system-prompt.md +17 -0
- package/dist/apps/chat/agent-profiles.js +26 -0
- package/dist/apps/chat/agent-store.js +336 -0
- package/dist/apps/chat/event-log.js +307 -0
- package/dist/apps/chat/read-model.js +218 -0
- package/dist/apps/chat/rooms.js +321 -0
- package/dist/apps/chat/session-metadata.js +14 -0
- package/dist/apps/chat/stream.js +122 -0
- package/dist/apps/chat/trace.js +1182 -0
- package/dist/apps/chat/web-app.js +2569 -0
- package/dist/apps/chat-ui/assets/apl-BxEMbctQ.js +1 -0
- package/dist/apps/chat-ui/assets/asciiarmor-eFjeGRuZ.js +1 -0
- package/dist/apps/chat-ui/assets/asn1-Cfx-0pt9.js +1 -0
- package/dist/apps/chat-ui/assets/asterisk-B5BHTsBr.js +1 -0
- package/dist/apps/chat-ui/assets/brainfuck-CAA2xofr.js +1 -0
- package/dist/apps/chat-ui/assets/clike-BoDCOLzN.js +1 -0
- package/dist/apps/chat-ui/assets/clojure-kVFSWX0o.js +1 -0
- package/dist/apps/chat-ui/assets/cmake-BUPAhezI.js +1 -0
- package/dist/apps/chat-ui/assets/cobol-BfgHZgup.js +1 -0
- package/dist/apps/chat-ui/assets/coffeescript-G1Pe_1AZ.js +1 -0
- package/dist/apps/chat-ui/assets/commonlisp-B3N0CjHn.js +1 -0
- package/dist/apps/chat-ui/assets/crystal-C15ndaGM.js +1 -0
- package/dist/apps/chat-ui/assets/css-BqOeyZOV.js +1 -0
- package/dist/apps/chat-ui/assets/cypher-KjIKv-wW.js +1 -0
- package/dist/apps/chat-ui/assets/d-BlT5AEC-.js +1 -0
- package/dist/apps/chat-ui/assets/diff-oF98tbqj.js +1 -0
- package/dist/apps/chat-ui/assets/dist--55mTWk3.js +1 -0
- package/dist/apps/chat-ui/assets/dist-B5rcjVCj.js +1 -0
- package/dist/apps/chat-ui/assets/dist-BPv5MdlL.js +1 -0
- package/dist/apps/chat-ui/assets/dist-BZ39rB1W.js +1 -0
- package/dist/apps/chat-ui/assets/dist-BsedZGJo.js +1 -0
- package/dist/apps/chat-ui/assets/dist-BvO6SpaM.js +9 -0
- package/dist/apps/chat-ui/assets/dist-C5YJOwhH.js +1 -0
- package/dist/apps/chat-ui/assets/dist-C5oXtFSP.js +1 -0
- package/dist/apps/chat-ui/assets/dist-CG_gRSwv.js +23 -0
- package/dist/apps/chat-ui/assets/dist-CKM5j-iy.js +1 -0
- package/dist/apps/chat-ui/assets/dist-CUp9us2q.js +1 -0
- package/dist/apps/chat-ui/assets/dist-CZ9T4Cly.js +1 -0
- package/dist/apps/chat-ui/assets/dist-D4HhiFWB.js +6 -0
- package/dist/apps/chat-ui/assets/dist-DHE-yBLH.js +1 -0
- package/dist/apps/chat-ui/assets/dist-DSKQpPaz.js +1 -0
- package/dist/apps/chat-ui/assets/dist-L1B-KWZO.js +1 -0
- package/dist/apps/chat-ui/assets/dist-SVPsM5Oi.js +13 -0
- package/dist/apps/chat-ui/assets/dist-Zqt9kNG9.js +1 -0
- package/dist/apps/chat-ui/assets/dist-_DPv0-QF.js +1 -0
- package/dist/apps/chat-ui/assets/dist-_oM7g0eh.js +11 -0
- package/dist/apps/chat-ui/assets/dist-laadbMWg.js +1 -0
- package/dist/apps/chat-ui/assets/dist-nFui3f-r.js +2 -0
- package/dist/apps/chat-ui/assets/dist-tGfufz3b.js +1 -0
- package/dist/apps/chat-ui/assets/dockerfile-CUaqzcqp.js +1 -0
- package/dist/apps/chat-ui/assets/dtd-VCA9yr61.js +1 -0
- package/dist/apps/chat-ui/assets/dylan-O-V5Dw5W.js +1 -0
- package/dist/apps/chat-ui/assets/ebnf-SPmdBkvT.js +1 -0
- package/dist/apps/chat-ui/assets/ecl-ChfCttfI.js +1 -0
- package/dist/apps/chat-ui/assets/eiffel-cB9EbjeN.js +1 -0
- package/dist/apps/chat-ui/assets/elm-BTiVflBU.js +1 -0
- package/dist/apps/chat-ui/assets/erlang-egf0TXFm.js +1 -0
- package/dist/apps/chat-ui/assets/factor-C2tAxNob.js +1 -0
- package/dist/apps/chat-ui/assets/fcl-BiCjh1tj.js +1 -0
- package/dist/apps/chat-ui/assets/forth-C4kDGW6u.js +1 -0
- package/dist/apps/chat-ui/assets/fortran-DzkLaPnd.js +1 -0
- package/dist/apps/chat-ui/assets/gas-DMOxskQF.js +1 -0
- package/dist/apps/chat-ui/assets/gherkin-BPxBpp-k.js +1 -0
- package/dist/apps/chat-ui/assets/groovy-CkEnc0ZY.js +1 -0
- package/dist/apps/chat-ui/assets/haskell-Dadpo9-w.js +1 -0
- package/dist/apps/chat-ui/assets/haxe-CDNZL9MW.js +1 -0
- package/dist/apps/chat-ui/assets/http-jy9Zxxt3.js +1 -0
- package/dist/apps/chat-ui/assets/idl-CGSB6iiy.js +1 -0
- package/dist/apps/chat-ui/assets/index-BdcqTugD.js +151 -0
- package/dist/apps/chat-ui/assets/index-Dk-opWl3.css +1 -0
- package/dist/apps/chat-ui/assets/javascript-DSlzRUd8.js +1 -0
- package/dist/apps/chat-ui/assets/julia-DTiF9v6R.js +1 -0
- package/dist/apps/chat-ui/assets/livescript-Ci8Xxna6.js +1 -0
- package/dist/apps/chat-ui/assets/lua-eVxIrt9t.js +1 -0
- package/dist/apps/chat-ui/assets/mathematica-Da3grj36.js +1 -0
- package/dist/apps/chat-ui/assets/mbox-BWBMSafM.js +1 -0
- package/dist/apps/chat-ui/assets/mirc-CtHu9S1B.js +1 -0
- package/dist/apps/chat-ui/assets/mllike-wTFlPWXS.js +1 -0
- package/dist/apps/chat-ui/assets/modelica-cKbQ0UXu.js +1 -0
- package/dist/apps/chat-ui/assets/mscgen-C5pXQCMK.js +1 -0
- package/dist/apps/chat-ui/assets/mumps-CKBHkOQq.js +1 -0
- package/dist/apps/chat-ui/assets/nginx-B00AiQel.js +1 -0
- package/dist/apps/chat-ui/assets/nsis-SMDwKltR.js +1 -0
- package/dist/apps/chat-ui/assets/ntriples-B_36EBV0.js +1 -0
- package/dist/apps/chat-ui/assets/octave-BXPjzAif.js +1 -0
- package/dist/apps/chat-ui/assets/oz-Dedpat1M.js +1 -0
- package/dist/apps/chat-ui/assets/pascal-CMcUg72K.js +1 -0
- package/dist/apps/chat-ui/assets/perl-DoVTbnzt.js +1 -0
- package/dist/apps/chat-ui/assets/pig-CULXT1YV.js +1 -0
- package/dist/apps/chat-ui/assets/powershell-Cv5Uhf6b.js +1 -0
- package/dist/apps/chat-ui/assets/properties-CQ1C2P-M.js +1 -0
- package/dist/apps/chat-ui/assets/protobuf-SRlvzrl6.js +1 -0
- package/dist/apps/chat-ui/assets/pug-Bo3wfL-f.js +1 -0
- package/dist/apps/chat-ui/assets/puppet-ClSqCGj6.js +1 -0
- package/dist/apps/chat-ui/assets/python-C2_X1GpX.js +1 -0
- package/dist/apps/chat-ui/assets/q-B_6Gdyzl.js +1 -0
- package/dist/apps/chat-ui/assets/r-BD07NGED.js +1 -0
- package/dist/apps/chat-ui/assets/rolldown-runtime-S-ySWqyJ.js +1 -0
- package/dist/apps/chat-ui/assets/rpm-CRu5Z2Jl.js +1 -0
- package/dist/apps/chat-ui/assets/ruby-dZPnOz8h.js +1 -0
- package/dist/apps/chat-ui/assets/sas-S2t8_sDI.js +1 -0
- package/dist/apps/chat-ui/assets/scheme-WcyFWLW2.js +1 -0
- package/dist/apps/chat-ui/assets/shell-DUelnYSh.js +1 -0
- package/dist/apps/chat-ui/assets/sieve-jDjlVhNh.js +1 -0
- package/dist/apps/chat-ui/assets/simple-mode-CL04yRVp.js +1 -0
- package/dist/apps/chat-ui/assets/smalltalk-ddWDYy10.js +1 -0
- package/dist/apps/chat-ui/assets/solr-C7rQhLuW.js +1 -0
- package/dist/apps/chat-ui/assets/sparql--fPCCgVd.js +1 -0
- package/dist/apps/chat-ui/assets/spreadsheet-DjthqD5G.js +1 -0
- package/dist/apps/chat-ui/assets/sql-D_dieYbr.js +1 -0
- package/dist/apps/chat-ui/assets/stex-rHcFYcA0.js +1 -0
- package/dist/apps/chat-ui/assets/stylus-DxF70RNr.js +1 -0
- package/dist/apps/chat-ui/assets/swift-T0hDoOb-.js +1 -0
- package/dist/apps/chat-ui/assets/tcl-Dlzy1mPk.js +1 -0
- package/dist/apps/chat-ui/assets/textile-Dy5rFZe5.js +1 -0
- package/dist/apps/chat-ui/assets/tiddlywiki-DQP1OymS.js +1 -0
- package/dist/apps/chat-ui/assets/tiki-0vOj3DB2.js +1 -0
- package/dist/apps/chat-ui/assets/toml-DEltN0lI.js +1 -0
- package/dist/apps/chat-ui/assets/troff-CRbBpEqY.js +1 -0
- package/dist/apps/chat-ui/assets/ttcn-M5q1nLKg.js +1 -0
- package/dist/apps/chat-ui/assets/ttcn-cfg-Rmw9NWq9.js +1 -0
- package/dist/apps/chat-ui/assets/turtle-BCDWhJK0.js +1 -0
- package/dist/apps/chat-ui/assets/vb-QQ7LGlOz.js +1 -0
- package/dist/apps/chat-ui/assets/vbscript-BiSEdUzz.js +1 -0
- package/dist/apps/chat-ui/assets/velocity-CzMg5_6w.js +1 -0
- package/dist/apps/chat-ui/assets/verilog-BJOO83gk.js +1 -0
- package/dist/apps/chat-ui/assets/vhdl-ed4zAZAA.js +1 -0
- package/dist/apps/chat-ui/assets/webidl-Ddy6hbV6.js +1 -0
- package/dist/apps/chat-ui/assets/xquery-Bw1zwhh6.js +1 -0
- package/dist/apps/chat-ui/assets/yacas-DZdTXy3s.js +1 -0
- package/dist/apps/chat-ui/assets/z80-DMG02_YV.js +1 -0
- package/dist/apps/chat-ui/index.html +15 -0
- package/dist/apps/context-files-ui/assets/apl-14BqhLYK.js +1 -0
- package/dist/apps/context-files-ui/assets/asciiarmor-WLvjqI7d.js +1 -0
- package/dist/apps/context-files-ui/assets/asn1-Bg4FbdCg.js +1 -0
- package/dist/apps/context-files-ui/assets/asterisk-B2MO-X4d.js +1 -0
- package/dist/apps/context-files-ui/assets/brainfuck-CV9kufud.js +1 -0
- package/dist/apps/context-files-ui/assets/clike-CjmcUpt6.js +1 -0
- package/dist/apps/context-files-ui/assets/clojure-De3QGfx6.js +1 -0
- package/dist/apps/context-files-ui/assets/cmake-i2VDNaRq.js +1 -0
- package/dist/apps/context-files-ui/assets/cobol-BwO6DF08.js +1 -0
- package/dist/apps/context-files-ui/assets/coffeescript-BtivDvRz.js +1 -0
- package/dist/apps/context-files-ui/assets/commonlisp-DFkEQdLP.js +1 -0
- package/dist/apps/context-files-ui/assets/crystal-CU0NkcVL.js +1 -0
- package/dist/apps/context-files-ui/assets/css-CbMZAQ1W.js +1 -0
- package/dist/apps/context-files-ui/assets/cypher-Dke5QOzv.js +1 -0
- package/dist/apps/context-files-ui/assets/d-TPqSVaHM.js +1 -0
- package/dist/apps/context-files-ui/assets/diff-B365LSoZ.js +1 -0
- package/dist/apps/context-files-ui/assets/dist-B5PTVnox.js +1 -0
- package/dist/apps/context-files-ui/assets/dist-B5ZAfwf5.js +1 -0
- package/dist/apps/context-files-ui/assets/dist-BJW3917N.js +11 -0
- package/dist/apps/context-files-ui/assets/dist-BkUONE3N.js +1 -0
- package/dist/apps/context-files-ui/assets/dist-CKQF1zEu.js +1 -0
- package/dist/apps/context-files-ui/assets/dist-CwbH_3RN.js +1 -0
- package/dist/apps/context-files-ui/assets/dist-CxRLRmMx.js +2 -0
- package/dist/apps/context-files-ui/assets/dist-D1KyNDg5.js +13 -0
- package/dist/apps/context-files-ui/assets/dist-DFi2YGux.js +1 -0
- package/dist/apps/context-files-ui/assets/dist-DKoyMSNr.js +1 -0
- package/dist/apps/context-files-ui/assets/dist-DLMjd26T.js +1 -0
- package/dist/apps/context-files-ui/assets/dist-DQXzt2Ng.js +1 -0
- package/dist/apps/context-files-ui/assets/dist-DotDq_kD.js +1 -0
- package/dist/apps/context-files-ui/assets/dist-DyfSeBMu.js +1 -0
- package/dist/apps/context-files-ui/assets/dist-MyZgX9K2.js +9 -0
- package/dist/apps/context-files-ui/assets/dist-QQuDy4KA.js +1 -0
- package/dist/apps/context-files-ui/assets/dist-YwR9dpb-.js +1 -0
- package/dist/apps/context-files-ui/assets/dist-dTBsFYAl.js +1 -0
- package/dist/apps/context-files-ui/assets/dockerfile-CJb2sekW.js +1 -0
- package/dist/apps/context-files-ui/assets/dtd-CBMymJ7O.js +1 -0
- package/dist/apps/context-files-ui/assets/dylan-08Azy1NK.js +1 -0
- package/dist/apps/context-files-ui/assets/ebnf-Dkum_1J8.js +1 -0
- package/dist/apps/context-files-ui/assets/ecl-dhxjHL8y.js +1 -0
- package/dist/apps/context-files-ui/assets/eiffel-C446m6dI.js +1 -0
- package/dist/apps/context-files-ui/assets/elm-po1E9de0.js +1 -0
- package/dist/apps/context-files-ui/assets/erlang-BD5LkVkR.js +1 -0
- package/dist/apps/context-files-ui/assets/factor-B2EMQZkP.js +1 -0
- package/dist/apps/context-files-ui/assets/fcl-DkEOamHd.js +1 -0
- package/dist/apps/context-files-ui/assets/forth-dCg2_HVB.js +1 -0
- package/dist/apps/context-files-ui/assets/fortran-3ZpXLFh1.js +1 -0
- package/dist/apps/context-files-ui/assets/gas-DMmxLZRI.js +1 -0
- package/dist/apps/context-files-ui/assets/gherkin-DUSFg2R6.js +1 -0
- package/dist/apps/context-files-ui/assets/groovy-Cmduloe1.js +1 -0
- package/dist/apps/context-files-ui/assets/haskell-Cyr255R9.js +1 -0
- package/dist/apps/context-files-ui/assets/haxe-BJVKtprM.js +1 -0
- package/dist/apps/context-files-ui/assets/http-DszHFpc-.js +1 -0
- package/dist/apps/context-files-ui/assets/idl-Cati9Nrv.js +1 -0
- package/dist/apps/context-files-ui/assets/index-BwRDoHMC.css +1 -0
- package/dist/apps/context-files-ui/assets/index-GwvjXytt.js +202 -0
- package/dist/apps/context-files-ui/assets/javascript-C5pDVaoP.js +1 -0
- package/dist/apps/context-files-ui/assets/julia-DlqY1cTU.js +1 -0
- package/dist/apps/context-files-ui/assets/livescript-C6p8-2W1.js +1 -0
- package/dist/apps/context-files-ui/assets/lua-BxuTHaF7.js +1 -0
- package/dist/apps/context-files-ui/assets/mathematica-nDHZUMJT.js +1 -0
- package/dist/apps/context-files-ui/assets/mbox-DAaR0Hcz.js +1 -0
- package/dist/apps/context-files-ui/assets/mirc-CCA0FRfl.js +1 -0
- package/dist/apps/context-files-ui/assets/mllike-Cw3Iccsb.js +1 -0
- package/dist/apps/context-files-ui/assets/modelica-Czx80fNR.js +1 -0
- package/dist/apps/context-files-ui/assets/mscgen-BmfuTbzG.js +1 -0
- package/dist/apps/context-files-ui/assets/mumps-Ds_ZaumL.js +1 -0
- package/dist/apps/context-files-ui/assets/nginx-D9M2PQ4U.js +1 -0
- package/dist/apps/context-files-ui/assets/nsis-DOo3SJmd.js +1 -0
- package/dist/apps/context-files-ui/assets/ntriples-DLHGTvHs.js +1 -0
- package/dist/apps/context-files-ui/assets/octave-8jj96JiC.js +1 -0
- package/dist/apps/context-files-ui/assets/oz-BmMq7iC4.js +1 -0
- package/dist/apps/context-files-ui/assets/pascal-BgMr6XpT.js +1 -0
- package/dist/apps/context-files-ui/assets/perl-D6YJObi_.js +1 -0
- package/dist/apps/context-files-ui/assets/pig-nx7uchs8.js +1 -0
- package/dist/apps/context-files-ui/assets/powershell-B4IPkVxR.js +1 -0
- package/dist/apps/context-files-ui/assets/properties-CoavQdLC.js +1 -0
- package/dist/apps/context-files-ui/assets/protobuf-D5EWhcmc.js +1 -0
- package/dist/apps/context-files-ui/assets/pug-QU72BPAa.js +1 -0
- package/dist/apps/context-files-ui/assets/puppet-B_0GFuyD.js +1 -0
- package/dist/apps/context-files-ui/assets/python-Cs7sNzy_.js +1 -0
- package/dist/apps/context-files-ui/assets/q-BIB9pPtI.js +1 -0
- package/dist/apps/context-files-ui/assets/r-CN5s4f3o.js +1 -0
- package/dist/apps/context-files-ui/assets/rpm-Ct_Ck8mQ.js +1 -0
- package/dist/apps/context-files-ui/assets/ruby-BVPradRk.js +1 -0
- package/dist/apps/context-files-ui/assets/sas-DN4j74IF.js +1 -0
- package/dist/apps/context-files-ui/assets/scheme-CvNgHAnh.js +1 -0
- package/dist/apps/context-files-ui/assets/shell-BjiMLAaM.js +1 -0
- package/dist/apps/context-files-ui/assets/sieve-C2U1O5Z4.js +1 -0
- package/dist/apps/context-files-ui/assets/simple-mode-DnMbQuKW.js +1 -0
- package/dist/apps/context-files-ui/assets/smalltalk-DkYwYufV.js +1 -0
- package/dist/apps/context-files-ui/assets/solr-BopnSD-v.js +1 -0
- package/dist/apps/context-files-ui/assets/sparql-Cpg3YQfd.js +1 -0
- package/dist/apps/context-files-ui/assets/spreadsheet-kRxtVt9J.js +1 -0
- package/dist/apps/context-files-ui/assets/sql-DYI2GwJR.js +1 -0
- package/dist/apps/context-files-ui/assets/stex-BCRT8IJ3.js +1 -0
- package/dist/apps/context-files-ui/assets/stylus-CARoeVE9.js +1 -0
- package/dist/apps/context-files-ui/assets/swift-DKNaLAK6.js +1 -0
- package/dist/apps/context-files-ui/assets/tcl-CQyXkgMH.js +1 -0
- package/dist/apps/context-files-ui/assets/textile-Yg_UWn-t.js +1 -0
- package/dist/apps/context-files-ui/assets/tiddlywiki-dqVbkfX4.js +1 -0
- package/dist/apps/context-files-ui/assets/tiki-CC_ic8g0.js +1 -0
- package/dist/apps/context-files-ui/assets/toml-B7gGzVkJ.js +1 -0
- package/dist/apps/context-files-ui/assets/troff-Bq3z6oAu.js +1 -0
- package/dist/apps/context-files-ui/assets/ttcn-GvRgs2AT.js +1 -0
- package/dist/apps/context-files-ui/assets/ttcn-cfg-CGCXz7Vo.js +1 -0
- package/dist/apps/context-files-ui/assets/turtle-CwIpz2yy.js +1 -0
- package/dist/apps/context-files-ui/assets/vb-BmcHUM2C.js +1 -0
- package/dist/apps/context-files-ui/assets/vbscript-Cs9dylre.js +1 -0
- package/dist/apps/context-files-ui/assets/velocity-CBWU0VCy.js +1 -0
- package/dist/apps/context-files-ui/assets/verilog-DVCHmufx.js +1 -0
- package/dist/apps/context-files-ui/assets/vhdl-BGDk4f1d.js +1 -0
- package/dist/apps/context-files-ui/assets/webidl-egXQEWlC.js +1 -0
- package/dist/apps/context-files-ui/assets/xquery-5f0hn7cg.js +1 -0
- package/dist/apps/context-files-ui/assets/yacas-DNs9XkmQ.js +1 -0
- package/dist/apps/context-files-ui/assets/z80-B7Dfb4UO.js +1 -0
- package/dist/apps/context-files-ui/index.html +14 -0
- package/dist/auth/better-auth.js +129 -0
- package/dist/auth/types.js +14 -0
- package/dist/bin/pibo.js +3 -0
- package/dist/channels/types.js +1 -0
- package/dist/cli-errors.js +18 -0
- package/dist/cli.js +264 -0
- package/dist/config/config.js +167 -0
- package/dist/core/base-prompt.js +104 -0
- package/dist/core/codex-compat.js +44 -0
- package/dist/core/compaction-prompt.js +258 -0
- package/dist/core/events.js +1 -0
- package/dist/core/profiles.js +138 -0
- package/dist/core/routed-session.js +538 -0
- package/dist/core/runtime.js +323 -0
- package/dist/core/session-router.js +437 -0
- package/dist/core/system-prompt-template.js +56 -0
- package/dist/core/thinking.js +9 -0
- package/dist/core/workspace.js +5 -0
- package/dist/debug/events.js +92 -0
- package/dist/debug/index.js +631 -0
- package/dist/debug/session.js +200 -0
- package/dist/debug/sql.js +238 -0
- package/dist/debug/stores.js +49 -0
- package/dist/debug/trace.js +245 -0
- package/dist/env.js +32 -0
- package/dist/gateway/client.js +200 -0
- package/dist/gateway/protocol.js +46 -0
- package/dist/gateway/request.js +146 -0
- package/dist/gateway/server.js +221 -0
- package/dist/gateway/tool.js +69 -0
- package/dist/gateway/web.js +80 -0
- package/dist/index.js +23 -0
- package/dist/local/client.js +77 -0
- package/dist/local/extension.js +548 -0
- package/dist/local/tui.js +25 -0
- package/dist/mcp/agent-context.js +123 -0
- package/dist/mcp/client.js +332 -0
- package/dist/mcp/commands/call.js +146 -0
- package/dist/mcp/commands/grep.js +145 -0
- package/dist/mcp/commands/info.js +71 -0
- package/dist/mcp/commands/list.js +94 -0
- package/dist/mcp/config-command.js +217 -0
- package/dist/mcp/config.js +440 -0
- package/dist/mcp/daemon-client.js +266 -0
- package/dist/mcp/daemon.js +327 -0
- package/dist/mcp/errors.js +287 -0
- package/dist/mcp/index.js +431 -0
- package/dist/mcp/output.js +171 -0
- package/dist/mcp/python-runtime.js +131 -0
- package/dist/mcp/registry.js +116 -0
- package/dist/mcp/version.js +5 -0
- package/dist/pi-packages/cli.js +92 -0
- package/dist/pi-packages/installer.js +70 -0
- package/dist/pi-packages/metadata.js +231 -0
- package/dist/pi-packages/runtime.js +61 -0
- package/dist/pi-packages/store.js +175 -0
- package/dist/pi-packages/types.js +1 -0
- package/dist/plugins/better-auth.js +11 -0
- package/dist/plugins/builtin.js +249 -0
- package/dist/plugins/chat-web.js +11 -0
- package/dist/plugins/codex-compat.js +72 -0
- package/dist/plugins/context-files-store.js +354 -0
- package/dist/plugins/context-files.js +999 -0
- package/dist/plugins/core-tools.js +94 -0
- package/dist/plugins/example.js +67 -0
- package/dist/plugins/registry.js +368 -0
- package/dist/plugins/remote-agent.js +9 -0
- package/dist/plugins/types.js +1 -0
- package/dist/plugins/web.js +11 -0
- package/dist/reliability/store.js +759 -0
- package/dist/remote/channel.js +176 -0
- package/dist/remote/client.js +92 -0
- package/dist/remote/examples/tui-controller.js +263 -0
- package/dist/remote/protocol.js +55 -0
- package/dist/remote/session-client.js +189 -0
- package/dist/runs/registry.js +323 -0
- package/dist/runs/tools.js +185 -0
- package/dist/sessions/bindings.js +41 -0
- package/dist/sessions/sqlite-store.js +154 -0
- package/dist/sessions/store.js +125 -0
- package/dist/shared/trace-order.js +83 -0
- package/dist/subagents/tool.js +63 -0
- package/dist/tools/browser-use-cdp.js +207 -0
- package/dist/tools/browser-use-leases.js +338 -0
- package/dist/tools/browser-use-wrapper.js +338 -0
- package/dist/tools/codex-compat.js +85 -0
- package/dist/tools/desktop-env.js +90 -0
- package/dist/tools/guides.js +276 -0
- package/dist/tools/index.js +366 -0
- package/dist/tools/python-runtime.js +154 -0
- package/dist/tools/registry.js +107 -0
- package/dist/tools/web-search.js +137 -0
- package/dist/web/auth.js +10 -0
- package/dist/web/channel.js +151 -0
- package/dist/web/http.js +110 -0
- package/dist/web/types.js +1 -0
- package/package.json +74 -0
- package/src/mcp/LICENSE.mcp-cli +21 -0
|
@@ -0,0 +1,548 @@
|
|
|
1
|
+
import { AssistantMessageComponent, ToolExecutionComponent, UserMessageComponent, } from "@mariozechner/pi-coding-agent";
|
|
2
|
+
import { Container, Spacer } from "@mariozechner/pi-tui";
|
|
3
|
+
import { parsePiboThinkingLevel } from "../core/thinking.js";
|
|
4
|
+
const LOCAL_MESSAGE_TYPE = "pibo.local-routed";
|
|
5
|
+
const STREAMING_WIDGET_KEY = "pibo.local.streaming";
|
|
6
|
+
const BLOCKED_PI_TUI_COMMANDS = new Set([
|
|
7
|
+
"settings",
|
|
8
|
+
"model",
|
|
9
|
+
"scoped-models",
|
|
10
|
+
"export",
|
|
11
|
+
"import",
|
|
12
|
+
"share",
|
|
13
|
+
"copy",
|
|
14
|
+
"name",
|
|
15
|
+
"session",
|
|
16
|
+
"changelog",
|
|
17
|
+
"hotkeys",
|
|
18
|
+
"fork",
|
|
19
|
+
"clone",
|
|
20
|
+
"tree",
|
|
21
|
+
"login",
|
|
22
|
+
"logout",
|
|
23
|
+
"new",
|
|
24
|
+
"compact",
|
|
25
|
+
"reload",
|
|
26
|
+
"debug",
|
|
27
|
+
"resume",
|
|
28
|
+
]);
|
|
29
|
+
const SUBMIT_KEYS = new Set(["\r", "\n"]);
|
|
30
|
+
class LocalStreamingMessageWidget extends Container {
|
|
31
|
+
tui;
|
|
32
|
+
showThinking;
|
|
33
|
+
assistantContent = "";
|
|
34
|
+
thinkingBlocks = [];
|
|
35
|
+
renderTimer;
|
|
36
|
+
constructor(tui, showThinking) {
|
|
37
|
+
super();
|
|
38
|
+
this.tui = tui;
|
|
39
|
+
this.showThinking = showThinking;
|
|
40
|
+
this.rebuild();
|
|
41
|
+
}
|
|
42
|
+
setContent(input) {
|
|
43
|
+
const nextAssistantContent = input.assistantContent ?? this.assistantContent;
|
|
44
|
+
const nextThinkingBlocks = input.thinkingBlocks ?? this.thinkingBlocks;
|
|
45
|
+
const sameThinkingBlocks = nextThinkingBlocks.length === this.thinkingBlocks.length &&
|
|
46
|
+
nextThinkingBlocks.every((block, index) => block === this.thinkingBlocks[index]);
|
|
47
|
+
if (nextAssistantContent === this.assistantContent && sameThinkingBlocks) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
this.assistantContent = nextAssistantContent;
|
|
51
|
+
this.thinkingBlocks = [...nextThinkingBlocks];
|
|
52
|
+
this.rebuild();
|
|
53
|
+
this.scheduleRender();
|
|
54
|
+
}
|
|
55
|
+
refresh() {
|
|
56
|
+
this.rebuild();
|
|
57
|
+
this.scheduleRender();
|
|
58
|
+
}
|
|
59
|
+
dispose() {
|
|
60
|
+
if (this.renderTimer) {
|
|
61
|
+
clearTimeout(this.renderTimer);
|
|
62
|
+
this.renderTimer = undefined;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
rebuild() {
|
|
66
|
+
this.clear();
|
|
67
|
+
if (this.showThinking()) {
|
|
68
|
+
for (const thinkingBlock of this.thinkingBlocks) {
|
|
69
|
+
if (!thinkingBlock.trim())
|
|
70
|
+
continue;
|
|
71
|
+
this.addChild(createLocalMessageComponent(thinkingBlock, { role: "thinking" }));
|
|
72
|
+
this.addChild(new Spacer(1));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
this.addChild(createLocalMessageComponent(this.assistantContent || " ", { role: "assistant" }));
|
|
76
|
+
}
|
|
77
|
+
scheduleRender() {
|
|
78
|
+
if (this.renderTimer)
|
|
79
|
+
return;
|
|
80
|
+
this.renderTimer = setTimeout(() => {
|
|
81
|
+
this.renderTimer = undefined;
|
|
82
|
+
this.tui.requestRender();
|
|
83
|
+
}, 33);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function createSlashCommandMap(capabilities) {
|
|
87
|
+
const commands = new Map();
|
|
88
|
+
for (const action of capabilities.actions) {
|
|
89
|
+
for (const slashCommand of action.slashCommands) {
|
|
90
|
+
if (BLOCKED_PI_TUI_COMMANDS.has(slashCommand))
|
|
91
|
+
continue;
|
|
92
|
+
commands.set(`/${slashCommand}`, action.name);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return commands;
|
|
96
|
+
}
|
|
97
|
+
function getLeadingSlashCommand(text) {
|
|
98
|
+
const trimmed = text.trimStart();
|
|
99
|
+
if (!trimmed.startsWith("/"))
|
|
100
|
+
return undefined;
|
|
101
|
+
const command = trimmed.slice(1).split(/\s+/, 1)[0];
|
|
102
|
+
return command || undefined;
|
|
103
|
+
}
|
|
104
|
+
function isBlockedPiTuiCommandInput(text) {
|
|
105
|
+
const command = getLeadingSlashCommand(text);
|
|
106
|
+
return command !== undefined && BLOCKED_PI_TUI_COMMANDS.has(command);
|
|
107
|
+
}
|
|
108
|
+
function createLocalMessageComponent(content, details) {
|
|
109
|
+
if (details.role === "user") {
|
|
110
|
+
return new UserMessageComponent(content);
|
|
111
|
+
}
|
|
112
|
+
if (details.role === "assistant") {
|
|
113
|
+
return new AssistantMessageComponent(createLocalAssistantMessage([{ type: "text", text: content }]));
|
|
114
|
+
}
|
|
115
|
+
if (details.role === "thinking") {
|
|
116
|
+
return new AssistantMessageComponent(createLocalAssistantMessage([{ type: "thinking", thinking: content }]));
|
|
117
|
+
}
|
|
118
|
+
if (details.role === "tool" && details.tool) {
|
|
119
|
+
return createLocalToolExecutionComponent(details.tool);
|
|
120
|
+
}
|
|
121
|
+
return new AssistantMessageComponent(createLocalAssistantMessage([{ type: "text", text: content }]));
|
|
122
|
+
}
|
|
123
|
+
function createLocalAssistantMessage(content) {
|
|
124
|
+
return {
|
|
125
|
+
role: "assistant",
|
|
126
|
+
content,
|
|
127
|
+
api: "openai-responses",
|
|
128
|
+
provider: "pibo-local",
|
|
129
|
+
model: "pibo-local-routed",
|
|
130
|
+
usage: {
|
|
131
|
+
input: 0,
|
|
132
|
+
output: 0,
|
|
133
|
+
cacheRead: 0,
|
|
134
|
+
cacheWrite: 0,
|
|
135
|
+
totalTokens: 0,
|
|
136
|
+
cost: {
|
|
137
|
+
input: 0,
|
|
138
|
+
output: 0,
|
|
139
|
+
cacheRead: 0,
|
|
140
|
+
cacheWrite: 0,
|
|
141
|
+
total: 0,
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
stopReason: "stop",
|
|
145
|
+
timestamp: Date.now(),
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
function normalizeToolResult(input, isError) {
|
|
149
|
+
if (input && typeof input === "object" && Array.isArray(input.content)) {
|
|
150
|
+
const candidate = input;
|
|
151
|
+
return { content: candidate.content, details: candidate.details, isError };
|
|
152
|
+
}
|
|
153
|
+
return { content: [{ type: "text", text: input === undefined ? "" : String(input) }], isError };
|
|
154
|
+
}
|
|
155
|
+
function createLocalToolExecutionComponent(tool, tui, cwd = process.cwd()) {
|
|
156
|
+
const component = new ToolExecutionComponent(tool.toolName, tool.toolCallId, tool.args, {}, undefined, tui ?? { requestRender() { } }, cwd);
|
|
157
|
+
if (tool.executionStarted)
|
|
158
|
+
component.markExecutionStarted();
|
|
159
|
+
if (tool.argsComplete)
|
|
160
|
+
component.setArgsComplete();
|
|
161
|
+
if (tool.result)
|
|
162
|
+
component.updateResult(tool.result);
|
|
163
|
+
return component;
|
|
164
|
+
}
|
|
165
|
+
function createLocalAutocompleteProvider(current, allowedCommands) {
|
|
166
|
+
return {
|
|
167
|
+
async getSuggestions(lines, cursorLine, cursorCol, options) {
|
|
168
|
+
const suggestions = await current.getSuggestions(lines, cursorLine, cursorCol, options);
|
|
169
|
+
const beforeCursor = (lines[cursorLine] ?? "").slice(0, cursorCol);
|
|
170
|
+
if (!suggestions || !beforeCursor.startsWith("/") || beforeCursor.includes(" ")) {
|
|
171
|
+
return suggestions;
|
|
172
|
+
}
|
|
173
|
+
const items = suggestions.items.filter((item) => allowedCommands.has(item.value));
|
|
174
|
+
return items.length > 0 ? { ...suggestions, items } : null;
|
|
175
|
+
},
|
|
176
|
+
applyCompletion(lines, cursorLine, cursorCol, item, prefix) {
|
|
177
|
+
return current.applyCompletion(lines, cursorLine, cursorCol, item, prefix);
|
|
178
|
+
},
|
|
179
|
+
shouldTriggerFileCompletion: current.shouldTriggerFileCompletion
|
|
180
|
+
? (lines, cursorLine, cursorCol) => current.shouldTriggerFileCompletion(lines, cursorLine, cursorCol)
|
|
181
|
+
: undefined,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
function isSessionStatus(value) {
|
|
185
|
+
if (!value || typeof value !== "object")
|
|
186
|
+
return false;
|
|
187
|
+
const candidate = value;
|
|
188
|
+
return (typeof candidate.piboSessionId === "string" &&
|
|
189
|
+
typeof candidate.queuedMessages === "number" &&
|
|
190
|
+
typeof candidate.processing === "boolean");
|
|
191
|
+
}
|
|
192
|
+
function isThinkingResult(value) {
|
|
193
|
+
if (!value || typeof value !== "object")
|
|
194
|
+
return false;
|
|
195
|
+
const candidate = value;
|
|
196
|
+
return typeof candidate.level === "string" && typeof candidate.supported === "boolean";
|
|
197
|
+
}
|
|
198
|
+
function createExecutionParams(slashCommand, args = "") {
|
|
199
|
+
if (slashCommand !== "/thinking")
|
|
200
|
+
return undefined;
|
|
201
|
+
const level = args.trim();
|
|
202
|
+
return level ? { level: parsePiboThinkingLevel(level) } : undefined;
|
|
203
|
+
}
|
|
204
|
+
function formatExecutionResult(event) {
|
|
205
|
+
if (event.action === "status" && isSessionStatus(event.result)) {
|
|
206
|
+
return `status: session=${event.result.piboSessionId} queued=${event.result.queuedMessages} processing=${event.result.processing} streaming=${event.result.streaming}`;
|
|
207
|
+
}
|
|
208
|
+
if (event.action === "thinking" && isThinkingResult(event.result)) {
|
|
209
|
+
const suffix = event.result.supported ? "" : " (current model does not support thinking)";
|
|
210
|
+
return `thinking: ${event.result.level}${suffix}`;
|
|
211
|
+
}
|
|
212
|
+
if (event.action === "clear_queue" && event.result && typeof event.result === "object") {
|
|
213
|
+
const cleared = event.result.cleared;
|
|
214
|
+
return `clear: removed ${typeof cleared === "number" ? cleared : 0} queued message(s)`;
|
|
215
|
+
}
|
|
216
|
+
return `${event.action}: ${JSON.stringify(event.result)}`;
|
|
217
|
+
}
|
|
218
|
+
function sendTuiMessage(pi, content, details) {
|
|
219
|
+
pi.sendMessage({
|
|
220
|
+
customType: LOCAL_MESSAGE_TYPE,
|
|
221
|
+
content,
|
|
222
|
+
display: true,
|
|
223
|
+
details,
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
function formatConnectedMessage(client, slashCommands) {
|
|
227
|
+
const commands = [...slashCommands.keys()].join(", ") || "none";
|
|
228
|
+
return [
|
|
229
|
+
`Connected to pibo local routed session ${client.piboSession.id}.`,
|
|
230
|
+
`Profile: ${client.piboSession.profile}`,
|
|
231
|
+
`Routed commands: ${commands}`,
|
|
232
|
+
"Only /quit and /thinking-show stay local in routed mode.",
|
|
233
|
+
].join("\n");
|
|
234
|
+
}
|
|
235
|
+
function splitSlashInput(text) {
|
|
236
|
+
const trimmed = text.trim();
|
|
237
|
+
if (!trimmed.startsWith("/"))
|
|
238
|
+
return undefined;
|
|
239
|
+
const match = trimmed.match(/^\/(\S+)(?:\s+([\s\S]*))?$/);
|
|
240
|
+
if (!match)
|
|
241
|
+
return undefined;
|
|
242
|
+
return { slashCommand: `/${match[1]}`, args: match[2] ?? "" };
|
|
243
|
+
}
|
|
244
|
+
export function createLocalRoutedTuiExtension(client, options = {}) {
|
|
245
|
+
return (pi) => {
|
|
246
|
+
let context;
|
|
247
|
+
let assistantBuffer = "";
|
|
248
|
+
let activeThinkingBuffer = "";
|
|
249
|
+
let thinkingBlocks = [];
|
|
250
|
+
let showThinking = options.showThinking === true;
|
|
251
|
+
let autocompleteRefreshed = false;
|
|
252
|
+
let connected = false;
|
|
253
|
+
let unsubscribeEvents;
|
|
254
|
+
let unsubscribeSubmitGuard;
|
|
255
|
+
let streamingWidget;
|
|
256
|
+
const toolStates = new Map();
|
|
257
|
+
const toolWidgets = new Map();
|
|
258
|
+
const slashCommands = createSlashCommandMap(client.capabilities);
|
|
259
|
+
const registeredCommands = new Set();
|
|
260
|
+
pi.registerMessageRenderer(LOCAL_MESSAGE_TYPE, (message) => {
|
|
261
|
+
return createLocalMessageComponent(String(message.content), message.details ?? { role: "system" });
|
|
262
|
+
});
|
|
263
|
+
const setStatus = (text) => {
|
|
264
|
+
context?.ui.setStatus("pibo.local", text);
|
|
265
|
+
};
|
|
266
|
+
const ensureStreamingWidget = () => {
|
|
267
|
+
if (streamingWidget || !context)
|
|
268
|
+
return;
|
|
269
|
+
context.ui.setWidget(STREAMING_WIDGET_KEY, (tui) => {
|
|
270
|
+
streamingWidget = new LocalStreamingMessageWidget(tui, () => showThinking);
|
|
271
|
+
streamingWidget.setContent({
|
|
272
|
+
assistantContent: assistantBuffer,
|
|
273
|
+
thinkingBlocks: getThinkingBlocks(),
|
|
274
|
+
});
|
|
275
|
+
return streamingWidget;
|
|
276
|
+
}, { placement: "aboveEditor" });
|
|
277
|
+
};
|
|
278
|
+
const clearStreamingWidget = () => {
|
|
279
|
+
context?.ui.setWidget(STREAMING_WIDGET_KEY, undefined);
|
|
280
|
+
streamingWidget = undefined;
|
|
281
|
+
};
|
|
282
|
+
const clearToolWidgets = () => {
|
|
283
|
+
for (const toolCallId of toolWidgets.keys()) {
|
|
284
|
+
context?.ui.setWidget(`pibo.local.tool.${toolCallId}`, undefined);
|
|
285
|
+
}
|
|
286
|
+
toolWidgets.clear();
|
|
287
|
+
};
|
|
288
|
+
const getThinkingBlocks = () => {
|
|
289
|
+
return activeThinkingBuffer.trim() ? [...thinkingBlocks, activeThinkingBuffer] : thinkingBlocks;
|
|
290
|
+
};
|
|
291
|
+
const finishActiveThinkingBlock = () => {
|
|
292
|
+
if (activeThinkingBuffer.trim()) {
|
|
293
|
+
thinkingBlocks = [...thinkingBlocks, activeThinkingBuffer];
|
|
294
|
+
}
|
|
295
|
+
activeThinkingBuffer = "";
|
|
296
|
+
};
|
|
297
|
+
const toggleThinkingDisplay = () => {
|
|
298
|
+
showThinking = !showThinking;
|
|
299
|
+
streamingWidget?.refresh();
|
|
300
|
+
sendTuiMessage(pi, `Thinking display: ${showThinking ? "on" : "off"}`, { role: "system" });
|
|
301
|
+
};
|
|
302
|
+
const runRoutedCommand = async (slashCommand, action, args = "") => {
|
|
303
|
+
try {
|
|
304
|
+
const params = createExecutionParams(slashCommand, args);
|
|
305
|
+
sendTuiMessage(pi, args.trim() ? `${slashCommand} ${args.trim()}` : slashCommand, { role: "user" });
|
|
306
|
+
await client.sendExecution(action, params);
|
|
307
|
+
}
|
|
308
|
+
catch (error) {
|
|
309
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
310
|
+
sendTuiMessage(pi, `Local routed request failed: ${message}`, { role: "error" });
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
const ensureToolState = (input) => {
|
|
314
|
+
const existing = toolStates.get(input.toolCallId);
|
|
315
|
+
if (existing) {
|
|
316
|
+
existing.toolName = input.toolName;
|
|
317
|
+
existing.args = input.args;
|
|
318
|
+
return existing;
|
|
319
|
+
}
|
|
320
|
+
const state = {
|
|
321
|
+
toolCallId: input.toolCallId,
|
|
322
|
+
toolName: input.toolName,
|
|
323
|
+
args: input.args,
|
|
324
|
+
argsComplete: false,
|
|
325
|
+
executionStarted: false,
|
|
326
|
+
};
|
|
327
|
+
toolStates.set(input.toolCallId, state);
|
|
328
|
+
return state;
|
|
329
|
+
};
|
|
330
|
+
const ensureToolWidget = (state) => {
|
|
331
|
+
if (toolWidgets.has(state.toolCallId) || !context)
|
|
332
|
+
return toolWidgets.get(state.toolCallId);
|
|
333
|
+
context.ui.setWidget(`pibo.local.tool.${state.toolCallId}`, (tui) => {
|
|
334
|
+
const component = createLocalToolExecutionComponent(state, tui, context?.cwd);
|
|
335
|
+
toolWidgets.set(state.toolCallId, component);
|
|
336
|
+
return component;
|
|
337
|
+
}, { placement: "aboveEditor" });
|
|
338
|
+
return toolWidgets.get(state.toolCallId);
|
|
339
|
+
};
|
|
340
|
+
const persistToolState = (state, event) => {
|
|
341
|
+
context?.ui.setWidget(`pibo.local.tool.${state.toolCallId}`, undefined);
|
|
342
|
+
toolWidgets.delete(state.toolCallId);
|
|
343
|
+
toolStates.delete(state.toolCallId);
|
|
344
|
+
sendTuiMessage(pi, "", { role: "tool", event, tool: { ...state } });
|
|
345
|
+
};
|
|
346
|
+
const handleLocalEvent = (event) => {
|
|
347
|
+
if (event.type === "message_started") {
|
|
348
|
+
assistantBuffer = "";
|
|
349
|
+
activeThinkingBuffer = "";
|
|
350
|
+
thinkingBlocks = [];
|
|
351
|
+
toolStates.clear();
|
|
352
|
+
clearToolWidgets();
|
|
353
|
+
ensureStreamingWidget();
|
|
354
|
+
setStatus("local running");
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
if (event.type === "thinking_started") {
|
|
358
|
+
finishActiveThinkingBlock();
|
|
359
|
+
ensureStreamingWidget();
|
|
360
|
+
streamingWidget?.setContent({ thinkingBlocks: getThinkingBlocks() });
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
if (event.type === "thinking_delta") {
|
|
364
|
+
activeThinkingBuffer += event.text;
|
|
365
|
+
ensureStreamingWidget();
|
|
366
|
+
streamingWidget?.setContent({ thinkingBlocks: getThinkingBlocks() });
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
if (event.type === "thinking_finished") {
|
|
370
|
+
if (event.text !== undefined) {
|
|
371
|
+
activeThinkingBuffer = event.text;
|
|
372
|
+
}
|
|
373
|
+
finishActiveThinkingBlock();
|
|
374
|
+
streamingWidget?.setContent({ thinkingBlocks: getThinkingBlocks() });
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
if (event.type === "assistant_delta") {
|
|
378
|
+
assistantBuffer += event.text;
|
|
379
|
+
ensureStreamingWidget();
|
|
380
|
+
streamingWidget?.setContent({ assistantContent: assistantBuffer });
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
if (event.type === "tool_call") {
|
|
384
|
+
const state = ensureToolState(event);
|
|
385
|
+
state.argsComplete = state.argsComplete || event.argsComplete;
|
|
386
|
+
const widget = ensureToolWidget(state);
|
|
387
|
+
widget?.updateArgs(state.args);
|
|
388
|
+
if (state.argsComplete)
|
|
389
|
+
widget?.setArgsComplete();
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
392
|
+
if (event.type === "tool_execution_started") {
|
|
393
|
+
const state = ensureToolState(event);
|
|
394
|
+
state.executionStarted = true;
|
|
395
|
+
state.argsComplete = true;
|
|
396
|
+
const widget = ensureToolWidget(state);
|
|
397
|
+
widget?.updateArgs(state.args);
|
|
398
|
+
widget?.setArgsComplete();
|
|
399
|
+
widget?.markExecutionStarted();
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
if (event.type === "tool_execution_updated") {
|
|
403
|
+
const state = ensureToolState(event);
|
|
404
|
+
state.executionStarted = true;
|
|
405
|
+
state.result = normalizeToolResult(event.partialResult, false);
|
|
406
|
+
const widget = ensureToolWidget(state);
|
|
407
|
+
widget?.updateResult(state.result, true);
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
if (event.type === "tool_execution_finished") {
|
|
411
|
+
const state = ensureToolState({
|
|
412
|
+
toolCallId: event.toolCallId,
|
|
413
|
+
toolName: event.toolName,
|
|
414
|
+
args: toolStates.get(event.toolCallId)?.args ?? {},
|
|
415
|
+
});
|
|
416
|
+
state.executionStarted = true;
|
|
417
|
+
state.argsComplete = true;
|
|
418
|
+
state.result = normalizeToolResult(event.result, event.isError);
|
|
419
|
+
const widget = toolWidgets.get(state.toolCallId);
|
|
420
|
+
widget?.updateResult(state.result);
|
|
421
|
+
persistToolState(state, event);
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
if (event.type === "assistant_message") {
|
|
425
|
+
finishActiveThinkingBlock();
|
|
426
|
+
const finalThinkingBlocks = getThinkingBlocks();
|
|
427
|
+
clearStreamingWidget();
|
|
428
|
+
if (showThinking && finalThinkingBlocks.length > 0) {
|
|
429
|
+
sendTuiMessage(pi, finalThinkingBlocks.join("\n\n"), { role: "thinking", event });
|
|
430
|
+
}
|
|
431
|
+
sendTuiMessage(pi, event.text || assistantBuffer, { role: "assistant", event });
|
|
432
|
+
assistantBuffer = "";
|
|
433
|
+
thinkingBlocks = [];
|
|
434
|
+
setStatus("local connected");
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
if (event.type === "execution_result") {
|
|
438
|
+
sendTuiMessage(pi, formatExecutionResult(event), { role: "execution", event });
|
|
439
|
+
setStatus("local connected");
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
442
|
+
if (event.type === "session_error") {
|
|
443
|
+
clearStreamingWidget();
|
|
444
|
+
clearToolWidgets();
|
|
445
|
+
sendTuiMessage(pi, `Local routed error: ${event.error}`, { role: "error", event });
|
|
446
|
+
setStatus("local error");
|
|
447
|
+
}
|
|
448
|
+
};
|
|
449
|
+
const ensureConnected = (ctx) => {
|
|
450
|
+
context = ctx;
|
|
451
|
+
if (connected)
|
|
452
|
+
return;
|
|
453
|
+
setStatus("local connecting");
|
|
454
|
+
for (const [slashCommand, action] of slashCommands) {
|
|
455
|
+
const name = slashCommand.slice(1);
|
|
456
|
+
if (registeredCommands.has(name))
|
|
457
|
+
continue;
|
|
458
|
+
registeredCommands.add(name);
|
|
459
|
+
const description = client.capabilities.actions.find((candidate) => candidate.name === action)?.description ??
|
|
460
|
+
`Run routed action "${action}".`;
|
|
461
|
+
pi.registerCommand(name, {
|
|
462
|
+
description,
|
|
463
|
+
async handler(args = "") {
|
|
464
|
+
await runRoutedCommand(slashCommand, action, String(args));
|
|
465
|
+
},
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
if (!registeredCommands.has("thinking-show")) {
|
|
469
|
+
registeredCommands.add("thinking-show");
|
|
470
|
+
pi.registerCommand("thinking-show", {
|
|
471
|
+
description: "Toggle routed thinking token visibility in the local TUI.",
|
|
472
|
+
async handler() {
|
|
473
|
+
toggleThinkingDisplay();
|
|
474
|
+
},
|
|
475
|
+
});
|
|
476
|
+
}
|
|
477
|
+
if (!autocompleteRefreshed) {
|
|
478
|
+
const allowedCommands = new Set([...slashCommands.keys()].map((command) => command.slice(1)));
|
|
479
|
+
allowedCommands.add("quit");
|
|
480
|
+
allowedCommands.add("thinking-show");
|
|
481
|
+
ctx.ui.addAutocompleteProvider((current) => createLocalAutocompleteProvider(current, allowedCommands));
|
|
482
|
+
autocompleteRefreshed = true;
|
|
483
|
+
}
|
|
484
|
+
if (!unsubscribeSubmitGuard) {
|
|
485
|
+
unsubscribeSubmitGuard = ctx.ui.onTerminalInput((data) => {
|
|
486
|
+
if (!SUBMIT_KEYS.has(data))
|
|
487
|
+
return undefined;
|
|
488
|
+
const text = ctx.ui.getEditorText();
|
|
489
|
+
if (!isBlockedPiTuiCommandInput(text))
|
|
490
|
+
return undefined;
|
|
491
|
+
ctx.ui.setEditorText("");
|
|
492
|
+
sendTuiMessage(pi, `Command "${text.trim()}" is not available in local routed mode.`, {
|
|
493
|
+
role: "error",
|
|
494
|
+
});
|
|
495
|
+
return { consume: true };
|
|
496
|
+
});
|
|
497
|
+
}
|
|
498
|
+
unsubscribeEvents = client.onEvent(handleLocalEvent);
|
|
499
|
+
connected = true;
|
|
500
|
+
setStatus("local connected");
|
|
501
|
+
sendTuiMessage(pi, formatConnectedMessage(client, slashCommands), { role: "system" });
|
|
502
|
+
};
|
|
503
|
+
pi.on("session_start", async (_event, ctx) => {
|
|
504
|
+
ensureConnected(ctx);
|
|
505
|
+
});
|
|
506
|
+
pi.on("session_shutdown", () => {
|
|
507
|
+
unsubscribeEvents?.();
|
|
508
|
+
unsubscribeEvents = undefined;
|
|
509
|
+
unsubscribeSubmitGuard?.();
|
|
510
|
+
unsubscribeSubmitGuard = undefined;
|
|
511
|
+
clearStreamingWidget();
|
|
512
|
+
clearToolWidgets();
|
|
513
|
+
connected = false;
|
|
514
|
+
void client.close();
|
|
515
|
+
});
|
|
516
|
+
pi.on("input", async (event, ctx) => {
|
|
517
|
+
const text = event.text.trim();
|
|
518
|
+
if (!text)
|
|
519
|
+
return { action: "continue" };
|
|
520
|
+
if (text === "/quit")
|
|
521
|
+
return { action: "continue" };
|
|
522
|
+
try {
|
|
523
|
+
ensureConnected(ctx);
|
|
524
|
+
if (text === "/thinking-show") {
|
|
525
|
+
toggleThinkingDisplay();
|
|
526
|
+
return { action: "handled" };
|
|
527
|
+
}
|
|
528
|
+
const slashInput = splitSlashInput(text);
|
|
529
|
+
const action = slashInput ? slashCommands.get(slashInput.slashCommand) : undefined;
|
|
530
|
+
if (action) {
|
|
531
|
+
await runRoutedCommand(slashInput.slashCommand, action, slashInput.args);
|
|
532
|
+
return { action: "handled" };
|
|
533
|
+
}
|
|
534
|
+
if (text.startsWith("/")) {
|
|
535
|
+
sendTuiMessage(pi, `Command "${text}" is not available in local routed mode.`, { role: "error" });
|
|
536
|
+
return { action: "handled" };
|
|
537
|
+
}
|
|
538
|
+
sendTuiMessage(pi, text, { role: "user" });
|
|
539
|
+
await client.sendMessage(event.text);
|
|
540
|
+
}
|
|
541
|
+
catch (error) {
|
|
542
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
543
|
+
sendTuiMessage(pi, `Local routed request failed: ${message}`, { role: "error" });
|
|
544
|
+
}
|
|
545
|
+
return { action: "handled" };
|
|
546
|
+
});
|
|
547
|
+
};
|
|
548
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { InitialSessionContextBuilder } from "../core/profiles.js";
|
|
2
|
+
import { runPiboTui } from "../core/runtime.js";
|
|
3
|
+
import { createLocalRoutedTuiClient, } from "./client.js";
|
|
4
|
+
import { createLocalRoutedTuiExtension } from "./extension.js";
|
|
5
|
+
export { LOCAL_TUI_CHANNEL_NAME, LocalRoutedTuiClient, createLocalRoutedTuiClient, } from "./client.js";
|
|
6
|
+
export { createLocalRoutedTuiExtension } from "./extension.js";
|
|
7
|
+
function createLocalControllerProfile() {
|
|
8
|
+
return new InitialSessionContextBuilder("pibo-local-routed-controller")
|
|
9
|
+
.withBuiltinTools("disabled")
|
|
10
|
+
.createSession();
|
|
11
|
+
}
|
|
12
|
+
export async function runLocalRoutedTui(options = {}) {
|
|
13
|
+
const client = createLocalRoutedTuiClient(options);
|
|
14
|
+
try {
|
|
15
|
+
await runPiboTui({
|
|
16
|
+
cwd: options.cwd,
|
|
17
|
+
persistSession: false,
|
|
18
|
+
profile: createLocalControllerProfile(),
|
|
19
|
+
extensionFactories: [createLocalRoutedTuiExtension(client, { showThinking: options.showThinking })],
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
finally {
|
|
23
|
+
await client.close();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { ensureConfigExists, findConfigPath, isHttpServer, } from './config.js';
|
|
3
|
+
import { ErrorCode, formatCliError } from './errors.js';
|
|
4
|
+
export const MCP_SERVER_DESCRIPTION_MAX_LENGTH = 480;
|
|
5
|
+
export const ENABLED_MCP_SERVERS_CONTEXT_PATH = '.pibo/context/enabled-mcp-servers.md';
|
|
6
|
+
export function normalizeMcpServerDescription(value) {
|
|
7
|
+
const description = value.replace(/\s+/g, ' ').trim();
|
|
8
|
+
if (!description) {
|
|
9
|
+
throw new Error(formatCliError({
|
|
10
|
+
code: ErrorCode.CLIENT_ERROR,
|
|
11
|
+
type: 'MCP_DESCRIPTION_REQUIRED',
|
|
12
|
+
message: 'MCP server description is required',
|
|
13
|
+
}));
|
|
14
|
+
}
|
|
15
|
+
if (description.length > MCP_SERVER_DESCRIPTION_MAX_LENGTH) {
|
|
16
|
+
throw new Error(formatCliError({
|
|
17
|
+
code: ErrorCode.CLIENT_ERROR,
|
|
18
|
+
type: 'MCP_DESCRIPTION_TOO_LONG',
|
|
19
|
+
message: `MCP server description must be ${MCP_SERVER_DESCRIPTION_MAX_LENGTH} characters or fewer`,
|
|
20
|
+
}));
|
|
21
|
+
}
|
|
22
|
+
return description;
|
|
23
|
+
}
|
|
24
|
+
export async function listMcpServerInfos(configPath) {
|
|
25
|
+
const path = findConfigPath(configPath);
|
|
26
|
+
if (!path)
|
|
27
|
+
return [];
|
|
28
|
+
const config = await readMcpConfig(path);
|
|
29
|
+
return Object.entries(config.mcpServers).map(([name, server]) => mcpServerInfoFromConfig(name, server));
|
|
30
|
+
}
|
|
31
|
+
export async function setMcpServerDescription(serverName, descriptionInput, configPath) {
|
|
32
|
+
const description = normalizeMcpServerDescription(descriptionInput);
|
|
33
|
+
const path = await ensureConfigExists(configPath);
|
|
34
|
+
const config = await readMcpConfig(path);
|
|
35
|
+
const server = config.mcpServers[serverName];
|
|
36
|
+
if (!server) {
|
|
37
|
+
throw new Error(formatCliError({
|
|
38
|
+
code: ErrorCode.CLIENT_ERROR,
|
|
39
|
+
type: 'SERVER_NOT_FOUND',
|
|
40
|
+
message: `Server "${serverName}" not found in config`,
|
|
41
|
+
details: `Available servers: ${Object.keys(config.mcpServers).join(', ') || '(none)'}`,
|
|
42
|
+
}));
|
|
43
|
+
}
|
|
44
|
+
server.pibo = {
|
|
45
|
+
...(server.pibo ?? {}),
|
|
46
|
+
description,
|
|
47
|
+
descriptionSource: 'user',
|
|
48
|
+
};
|
|
49
|
+
await writeFile(path, `${JSON.stringify(config, null, 2)}\n`);
|
|
50
|
+
return mcpServerInfoFromConfig(serverName, server);
|
|
51
|
+
}
|
|
52
|
+
export async function getMcpAgentContextFile(selectedServerNames, configPath) {
|
|
53
|
+
if (selectedServerNames.length === 0)
|
|
54
|
+
return undefined;
|
|
55
|
+
const infos = await listMcpServerInfos(configPath);
|
|
56
|
+
const infosByName = new Map(infos.map((info) => [info.name, info]));
|
|
57
|
+
const selected = selectedServerNames
|
|
58
|
+
.map((name) => infosByName.get(name))
|
|
59
|
+
.filter((info) => Boolean(info?.description));
|
|
60
|
+
if (selected.length === 0)
|
|
61
|
+
return undefined;
|
|
62
|
+
const sections = selected.flatMap((server) => [
|
|
63
|
+
`## ${server.name}`,
|
|
64
|
+
server.description ?? '',
|
|
65
|
+
'',
|
|
66
|
+
`Discover: \`npm run dev -- mcp info ${server.name}\``,
|
|
67
|
+
`Call: \`npm run dev -- mcp call ${server.name} <tool> '<json>'\``,
|
|
68
|
+
'',
|
|
69
|
+
]);
|
|
70
|
+
return {
|
|
71
|
+
path: ENABLED_MCP_SERVERS_CONTEXT_PATH,
|
|
72
|
+
content: [
|
|
73
|
+
'# Enabled MCP Servers',
|
|
74
|
+
'',
|
|
75
|
+
'These MCP servers are enabled for this agent. Use the MCP CLI for discovery and calls.',
|
|
76
|
+
'',
|
|
77
|
+
...sections,
|
|
78
|
+
].join('\n').trimEnd(),
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
async function readMcpConfig(path) {
|
|
82
|
+
const content = await readFile(path, 'utf-8');
|
|
83
|
+
const parsed = JSON.parse(content);
|
|
84
|
+
if (!parsed ||
|
|
85
|
+
typeof parsed !== 'object' ||
|
|
86
|
+
!('mcpServers' in parsed) ||
|
|
87
|
+
typeof parsed.mcpServers !== 'object' ||
|
|
88
|
+
parsed.mcpServers === null) {
|
|
89
|
+
throw new Error(formatCliError({
|
|
90
|
+
code: ErrorCode.CLIENT_ERROR,
|
|
91
|
+
type: 'CONFIG_MISSING_FIELD',
|
|
92
|
+
message: 'Config file missing required "mcpServers" object',
|
|
93
|
+
details: `File: ${path}`,
|
|
94
|
+
}));
|
|
95
|
+
}
|
|
96
|
+
return parsed;
|
|
97
|
+
}
|
|
98
|
+
function mcpServerInfoFromConfig(name, server) {
|
|
99
|
+
const metadata = normalizeMetadata(server.pibo);
|
|
100
|
+
const description = metadata.description;
|
|
101
|
+
return {
|
|
102
|
+
name,
|
|
103
|
+
transport: isHttpServer(server) ? 'http' : 'stdio',
|
|
104
|
+
...(description ? { description } : {}),
|
|
105
|
+
...(metadata.descriptionSource ? { descriptionSource: metadata.descriptionSource } : {}),
|
|
106
|
+
hasDescription: Boolean(description),
|
|
107
|
+
editable: metadata.descriptionSource !== 'registry',
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
function normalizeMetadata(metadata) {
|
|
111
|
+
if (!metadata || typeof metadata !== 'object')
|
|
112
|
+
return {};
|
|
113
|
+
const description = typeof metadata.description === 'string' && metadata.description.trim()
|
|
114
|
+
? metadata.description.trim()
|
|
115
|
+
: undefined;
|
|
116
|
+
const descriptionSource = metadata.descriptionSource === 'registry' || metadata.descriptionSource === 'user'
|
|
117
|
+
? metadata.descriptionSource
|
|
118
|
+
: undefined;
|
|
119
|
+
return {
|
|
120
|
+
...(description ? { description } : {}),
|
|
121
|
+
...(descriptionSource ? { descriptionSource } : {}),
|
|
122
|
+
};
|
|
123
|
+
}
|