@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,189 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { connect } from "node:net";
|
|
3
|
+
import { DEFAULT_REMOTE_AGENT_HOST, DEFAULT_REMOTE_AGENT_PORT, encodeRemoteAgentFrame, } from "./protocol.js";
|
|
4
|
+
function parseJsonLine(line) {
|
|
5
|
+
try {
|
|
6
|
+
return JSON.parse(line);
|
|
7
|
+
}
|
|
8
|
+
catch {
|
|
9
|
+
return undefined;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
function isBinding(value) {
|
|
13
|
+
if (!value || typeof value !== "object")
|
|
14
|
+
return false;
|
|
15
|
+
const candidate = value;
|
|
16
|
+
return typeof candidate.sessionKey === "string" && typeof candidate.originalProfile === "string";
|
|
17
|
+
}
|
|
18
|
+
function isCapabilities(value) {
|
|
19
|
+
if (!value || typeof value !== "object")
|
|
20
|
+
return false;
|
|
21
|
+
const candidate = value;
|
|
22
|
+
return Array.isArray(candidate.actions);
|
|
23
|
+
}
|
|
24
|
+
export function createRemoteSlashCommandMap(capabilities) {
|
|
25
|
+
const commands = new Map();
|
|
26
|
+
for (const action of capabilities.actions) {
|
|
27
|
+
for (const slashCommand of action.slashCommands) {
|
|
28
|
+
commands.set(`/${slashCommand}`, action.name);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return commands;
|
|
32
|
+
}
|
|
33
|
+
export class RemoteAgentSessionClient {
|
|
34
|
+
socket;
|
|
35
|
+
binding;
|
|
36
|
+
capabilities;
|
|
37
|
+
eventListeners = new Set();
|
|
38
|
+
pendingResponses = new Map();
|
|
39
|
+
buffer = "";
|
|
40
|
+
constructor(socket, attached) {
|
|
41
|
+
this.socket = socket;
|
|
42
|
+
this.binding = attached.binding;
|
|
43
|
+
this.capabilities = attached.capabilities;
|
|
44
|
+
this.socket.on("data", (chunk) => this.handleData(String(chunk)));
|
|
45
|
+
this.socket.once("close", () => this.rejectPendingResponses(new Error("Remote agent connection closed")));
|
|
46
|
+
this.socket.once("error", (error) => this.rejectPendingResponses(error));
|
|
47
|
+
}
|
|
48
|
+
static async connect(options = {}) {
|
|
49
|
+
const resolvedOptions = {
|
|
50
|
+
host: options.host ?? DEFAULT_REMOTE_AGENT_HOST,
|
|
51
|
+
port: options.port ?? DEFAULT_REMOTE_AGENT_PORT,
|
|
52
|
+
sessionName: options.sessionName ?? "default",
|
|
53
|
+
profile: options.profile ?? "pibo-minimal",
|
|
54
|
+
};
|
|
55
|
+
const socket = connect({ host: resolvedOptions.host, port: resolvedOptions.port });
|
|
56
|
+
socket.setEncoding("utf-8");
|
|
57
|
+
await new Promise((resolve, reject) => {
|
|
58
|
+
socket.once("connect", resolve);
|
|
59
|
+
socket.once("error", reject);
|
|
60
|
+
});
|
|
61
|
+
const attached = await attachRemoteAgent(socket, resolvedOptions);
|
|
62
|
+
return new RemoteAgentSessionClient(socket, attached);
|
|
63
|
+
}
|
|
64
|
+
onEvent(listener) {
|
|
65
|
+
this.eventListeners.add(listener);
|
|
66
|
+
return () => this.eventListeners.delete(listener);
|
|
67
|
+
}
|
|
68
|
+
getSlashCommands() {
|
|
69
|
+
return createRemoteSlashCommandMap(this.capabilities);
|
|
70
|
+
}
|
|
71
|
+
sendMessage(text) {
|
|
72
|
+
return this.sendInput({ type: "message", text });
|
|
73
|
+
}
|
|
74
|
+
sendExecution(action, params) {
|
|
75
|
+
return this.sendInput(params === undefined ? { type: "execution", action } : { type: "execution", action, params });
|
|
76
|
+
}
|
|
77
|
+
close() {
|
|
78
|
+
this.socket.end();
|
|
79
|
+
}
|
|
80
|
+
sendInput(input) {
|
|
81
|
+
return this.sendRequest({ type: "remote_input", id: randomUUID(), input });
|
|
82
|
+
}
|
|
83
|
+
sendRequest(frame) {
|
|
84
|
+
if (this.socket.destroyed) {
|
|
85
|
+
return Promise.reject(new Error("Remote agent connection is closed"));
|
|
86
|
+
}
|
|
87
|
+
return new Promise((resolve, reject) => {
|
|
88
|
+
this.pendingResponses.set(frame.id, { resolve, reject });
|
|
89
|
+
this.socket.write(encodeRemoteAgentFrame(frame));
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
handleData(chunk) {
|
|
93
|
+
this.buffer += chunk;
|
|
94
|
+
let newlineIndex = this.buffer.indexOf("\n");
|
|
95
|
+
while (newlineIndex !== -1) {
|
|
96
|
+
const line = this.buffer.slice(0, newlineIndex).trim();
|
|
97
|
+
this.buffer = this.buffer.slice(newlineIndex + 1);
|
|
98
|
+
this.handleFrame(line ? parseJsonLine(line) : undefined);
|
|
99
|
+
newlineIndex = this.buffer.indexOf("\n");
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
handleFrame(frame) {
|
|
103
|
+
if (!frame)
|
|
104
|
+
return;
|
|
105
|
+
if (frame.type === "remote_res") {
|
|
106
|
+
const pending = this.pendingResponses.get(frame.id);
|
|
107
|
+
if (!pending)
|
|
108
|
+
return;
|
|
109
|
+
this.pendingResponses.delete(frame.id);
|
|
110
|
+
if (frame.ok) {
|
|
111
|
+
pending.resolve(frame);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
pending.reject(new Error(frame.error?.message ?? "Remote request failed"));
|
|
115
|
+
}
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
if (frame.type === "remote_event") {
|
|
119
|
+
for (const listener of this.eventListeners) {
|
|
120
|
+
listener(frame.payload);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
rejectPendingResponses(error) {
|
|
125
|
+
for (const pending of this.pendingResponses.values()) {
|
|
126
|
+
pending.reject(error);
|
|
127
|
+
}
|
|
128
|
+
this.pendingResponses.clear();
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
async function attachRemoteAgent(socket, options) {
|
|
132
|
+
const id = randomUUID();
|
|
133
|
+
return await new Promise((resolve, reject) => {
|
|
134
|
+
let buffer = "";
|
|
135
|
+
const cleanup = () => {
|
|
136
|
+
socket.off("data", onData);
|
|
137
|
+
socket.off("error", onError);
|
|
138
|
+
socket.off("close", onClose);
|
|
139
|
+
};
|
|
140
|
+
const onError = (error) => {
|
|
141
|
+
cleanup();
|
|
142
|
+
reject(error);
|
|
143
|
+
};
|
|
144
|
+
const onClose = () => {
|
|
145
|
+
cleanup();
|
|
146
|
+
reject(new Error("Remote agent connection closed before attach completed"));
|
|
147
|
+
};
|
|
148
|
+
const onData = (chunk) => {
|
|
149
|
+
buffer += String(chunk);
|
|
150
|
+
let newlineIndex = buffer.indexOf("\n");
|
|
151
|
+
while (newlineIndex !== -1) {
|
|
152
|
+
const line = buffer.slice(0, newlineIndex).trim();
|
|
153
|
+
buffer = buffer.slice(newlineIndex + 1);
|
|
154
|
+
const frame = line ? parseJsonLine(line) : undefined;
|
|
155
|
+
if (frame?.type === "remote_res" && frame.id === id) {
|
|
156
|
+
cleanup();
|
|
157
|
+
if (!frame.ok) {
|
|
158
|
+
reject(new Error(frame.error?.message ?? "Remote attach failed"));
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
const payload = frame.payload;
|
|
162
|
+
if (!isBinding(payload?.binding)) {
|
|
163
|
+
reject(new Error("Remote attach response did not include a binding"));
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
if (!isCapabilities(payload.capabilities)) {
|
|
167
|
+
reject(new Error("Remote attach response did not include capabilities"));
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
resolve({
|
|
171
|
+
binding: payload.binding,
|
|
172
|
+
capabilities: payload.capabilities,
|
|
173
|
+
});
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
newlineIndex = buffer.indexOf("\n");
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
socket.on("data", onData);
|
|
180
|
+
socket.once("error", onError);
|
|
181
|
+
socket.once("close", onClose);
|
|
182
|
+
socket.write(encodeRemoteAgentFrame({
|
|
183
|
+
type: "remote_attach",
|
|
184
|
+
id,
|
|
185
|
+
sessionName: options.sessionName,
|
|
186
|
+
profile: options.profile,
|
|
187
|
+
}));
|
|
188
|
+
});
|
|
189
|
+
}
|
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
const DEFAULT_CONSUMED_TERMINAL_TTL_MS = 5 * 60 * 1000;
|
|
3
|
+
const DEFAULT_DETACHED_TERMINAL_TTL_MS = 60 * 1000;
|
|
4
|
+
function now() {
|
|
5
|
+
return new Date().toISOString();
|
|
6
|
+
}
|
|
7
|
+
function snapshot(record) {
|
|
8
|
+
const output = {
|
|
9
|
+
runId: record.runId,
|
|
10
|
+
kind: record.kind,
|
|
11
|
+
ownerPiboSessionId: record.ownerPiboSessionId,
|
|
12
|
+
status: record.status,
|
|
13
|
+
completionPolicy: record.completionPolicy,
|
|
14
|
+
consumed: record.consumed,
|
|
15
|
+
toolName: record.toolName,
|
|
16
|
+
createdAt: record.createdAt,
|
|
17
|
+
updatedAt: record.updatedAt,
|
|
18
|
+
};
|
|
19
|
+
if (record.summary)
|
|
20
|
+
output.summary = record.summary;
|
|
21
|
+
if (record.completedAt)
|
|
22
|
+
output.completedAt = record.completedAt;
|
|
23
|
+
return output;
|
|
24
|
+
}
|
|
25
|
+
function terminal(status) {
|
|
26
|
+
return status === "completed" || status === "failed" || status === "cancelled";
|
|
27
|
+
}
|
|
28
|
+
export class PiboRunRegistry {
|
|
29
|
+
options;
|
|
30
|
+
runs = new Map();
|
|
31
|
+
waiters = new Map();
|
|
32
|
+
constructor(options = {}) {
|
|
33
|
+
this.options = options;
|
|
34
|
+
if (this.options.store) {
|
|
35
|
+
this.options.store.recoverInterruptedRuns();
|
|
36
|
+
for (const record of this.options.store.listRuns({ includeConsumed: true, includeDetached: true })) {
|
|
37
|
+
this.runs.set(record.runId, recordFromStored(record));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
startToolRun(input) {
|
|
42
|
+
this.prune();
|
|
43
|
+
if (this.options.store) {
|
|
44
|
+
const stored = this.options.store.createRun({
|
|
45
|
+
ownerPiboSessionId: input.ownerPiboSessionId,
|
|
46
|
+
toolName: input.toolName,
|
|
47
|
+
completionPolicy: input.completionPolicy ?? "tracked",
|
|
48
|
+
params: input.params,
|
|
49
|
+
retryable: input.retryable ?? false,
|
|
50
|
+
maxAttempts: input.maxAttempts ?? 1,
|
|
51
|
+
});
|
|
52
|
+
const record = recordFromStored(stored);
|
|
53
|
+
this.runs.set(record.runId, record);
|
|
54
|
+
return snapshot(record);
|
|
55
|
+
}
|
|
56
|
+
const timestamp = now();
|
|
57
|
+
const runId = `run_${randomUUID()}`;
|
|
58
|
+
const record = {
|
|
59
|
+
runId,
|
|
60
|
+
kind: "tool",
|
|
61
|
+
ownerPiboSessionId: input.ownerPiboSessionId,
|
|
62
|
+
status: "running",
|
|
63
|
+
completionPolicy: input.completionPolicy ?? "tracked",
|
|
64
|
+
consumed: false,
|
|
65
|
+
toolName: input.toolName,
|
|
66
|
+
createdAt: timestamp,
|
|
67
|
+
updatedAt: timestamp,
|
|
68
|
+
summary: `${input.toolName} run is running.`,
|
|
69
|
+
retryable: input.retryable ?? false,
|
|
70
|
+
maxAttempts: Math.max(1, input.maxAttempts ?? 1),
|
|
71
|
+
};
|
|
72
|
+
this.runs.set(runId, record);
|
|
73
|
+
return snapshot(record);
|
|
74
|
+
}
|
|
75
|
+
complete(runId, result) {
|
|
76
|
+
const record = this.runs.get(runId);
|
|
77
|
+
if (!record || terminal(record.status))
|
|
78
|
+
return undefined;
|
|
79
|
+
record.status = "completed";
|
|
80
|
+
record.result = result;
|
|
81
|
+
record.summary = `${record.toolName} run completed.`;
|
|
82
|
+
this.finish(record);
|
|
83
|
+
this.options.store?.updateRun(runId, record);
|
|
84
|
+
if (record.jobId)
|
|
85
|
+
this.options.store?.ack(record.jobId, `run-registry:${process.pid}`);
|
|
86
|
+
return snapshot(record);
|
|
87
|
+
}
|
|
88
|
+
fail(runId, error) {
|
|
89
|
+
const record = this.runs.get(runId);
|
|
90
|
+
if (!record || terminal(record.status))
|
|
91
|
+
return undefined;
|
|
92
|
+
record.status = "failed";
|
|
93
|
+
record.error = error;
|
|
94
|
+
record.summary = `${record.toolName} run failed.`;
|
|
95
|
+
this.finish(record);
|
|
96
|
+
this.options.store?.updateRun(runId, record);
|
|
97
|
+
if (record.jobId)
|
|
98
|
+
this.options.store?.fail(record.jobId, `run-registry:${process.pid}`, error);
|
|
99
|
+
return snapshot(record);
|
|
100
|
+
}
|
|
101
|
+
list(ownerPiboSessionId, options = {}) {
|
|
102
|
+
this.prune();
|
|
103
|
+
return [...this.runs.values()]
|
|
104
|
+
.filter((record) => record.ownerPiboSessionId === ownerPiboSessionId)
|
|
105
|
+
.filter((record) => options.includeConsumed || !record.consumed)
|
|
106
|
+
.filter((record) => options.includeDetached || record.completionPolicy !== "detached")
|
|
107
|
+
.map(snapshot);
|
|
108
|
+
}
|
|
109
|
+
status(ownerPiboSessionId, runId) {
|
|
110
|
+
return snapshot(this.requireOwned(ownerPiboSessionId, runId));
|
|
111
|
+
}
|
|
112
|
+
async wait(ownerPiboSessionId, runId, timeoutMs) {
|
|
113
|
+
const record = this.requireOwned(ownerPiboSessionId, runId);
|
|
114
|
+
if (terminal(record.status))
|
|
115
|
+
return { ...snapshot(record), timedOut: false };
|
|
116
|
+
const boundedTimeoutMs = Math.max(0, Math.min(timeoutMs, 300000));
|
|
117
|
+
const completed = await new Promise((resolve) => {
|
|
118
|
+
const timeout = setTimeout(() => {
|
|
119
|
+
removeWaiter();
|
|
120
|
+
resolve(undefined);
|
|
121
|
+
}, boundedTimeoutMs);
|
|
122
|
+
const waiter = {
|
|
123
|
+
resolve: (updated) => {
|
|
124
|
+
clearTimeout(timeout);
|
|
125
|
+
resolve(updated);
|
|
126
|
+
},
|
|
127
|
+
};
|
|
128
|
+
const removeWaiter = () => {
|
|
129
|
+
const waiters = this.waiters.get(runId);
|
|
130
|
+
if (!waiters)
|
|
131
|
+
return;
|
|
132
|
+
const index = waiters.indexOf(waiter);
|
|
133
|
+
if (index >= 0)
|
|
134
|
+
waiters.splice(index, 1);
|
|
135
|
+
if (waiters.length === 0)
|
|
136
|
+
this.waiters.delete(runId);
|
|
137
|
+
};
|
|
138
|
+
const waiters = this.waiters.get(runId) ?? [];
|
|
139
|
+
waiters.push(waiter);
|
|
140
|
+
this.waiters.set(runId, waiters);
|
|
141
|
+
});
|
|
142
|
+
if (!completed)
|
|
143
|
+
return { ...snapshot(record), timedOut: true };
|
|
144
|
+
return { ...snapshot(completed), timedOut: false };
|
|
145
|
+
}
|
|
146
|
+
read(ownerPiboSessionId, runId) {
|
|
147
|
+
const record = this.requireOwned(ownerPiboSessionId, runId);
|
|
148
|
+
if (terminal(record.status)) {
|
|
149
|
+
record.consumed = true;
|
|
150
|
+
record.updatedAt = now();
|
|
151
|
+
this.options.store?.updateRun(runId, record);
|
|
152
|
+
}
|
|
153
|
+
const output = { ...snapshot(record) };
|
|
154
|
+
if (record.result)
|
|
155
|
+
output.result = record.result;
|
|
156
|
+
if (record.error)
|
|
157
|
+
output.error = record.error;
|
|
158
|
+
return output;
|
|
159
|
+
}
|
|
160
|
+
cancel(ownerPiboSessionId, runId) {
|
|
161
|
+
const record = this.requireOwned(ownerPiboSessionId, runId);
|
|
162
|
+
if (!terminal(record.status)) {
|
|
163
|
+
record.status = "cancelled";
|
|
164
|
+
record.summary = `${record.toolName} run cancelled.`;
|
|
165
|
+
this.finish(record);
|
|
166
|
+
if (record.jobId)
|
|
167
|
+
this.options.store?.fail(record.jobId, `run-registry:${process.pid}`, "Run was cancelled.");
|
|
168
|
+
}
|
|
169
|
+
record.consumed = true;
|
|
170
|
+
record.updatedAt = now();
|
|
171
|
+
this.options.store?.updateRun(runId, record);
|
|
172
|
+
return snapshot(record);
|
|
173
|
+
}
|
|
174
|
+
ack(ownerPiboSessionId, runId) {
|
|
175
|
+
const record = this.requireOwned(ownerPiboSessionId, runId);
|
|
176
|
+
record.acknowledgedStatus = record.status;
|
|
177
|
+
if (terminal(record.status))
|
|
178
|
+
record.consumed = true;
|
|
179
|
+
record.updatedAt = now();
|
|
180
|
+
this.options.store?.updateRun(runId, record);
|
|
181
|
+
return snapshot(record);
|
|
182
|
+
}
|
|
183
|
+
createNotification(ownerPiboSessionId, options = {}) {
|
|
184
|
+
const records = [...this.runs.values()].filter((record) => this.needsNotification(record, ownerPiboSessionId, options));
|
|
185
|
+
if (records.length === 0)
|
|
186
|
+
return undefined;
|
|
187
|
+
for (const record of records) {
|
|
188
|
+
record.notifiedStatus = record.status;
|
|
189
|
+
this.options.store?.updateRun(record.runId, record);
|
|
190
|
+
}
|
|
191
|
+
const notification = {
|
|
192
|
+
completed: [],
|
|
193
|
+
failed: [],
|
|
194
|
+
cancelled: [],
|
|
195
|
+
running: [],
|
|
196
|
+
};
|
|
197
|
+
for (const record of records) {
|
|
198
|
+
const item = snapshot(record);
|
|
199
|
+
if (record.status === "completed")
|
|
200
|
+
notification.completed.push(item);
|
|
201
|
+
else if (record.status === "failed")
|
|
202
|
+
notification.failed.push(item);
|
|
203
|
+
else if (record.status === "cancelled")
|
|
204
|
+
notification.cancelled.push(item);
|
|
205
|
+
else
|
|
206
|
+
notification.running.push(item);
|
|
207
|
+
}
|
|
208
|
+
return notification;
|
|
209
|
+
}
|
|
210
|
+
hasPendingNotification(ownerPiboSessionId, options = {}) {
|
|
211
|
+
return [...this.runs.values()].some((record) => this.needsNotification(record, ownerPiboSessionId, options));
|
|
212
|
+
}
|
|
213
|
+
cancelOwnerRuns(ownerPiboSessionId, reason = "Owner Pibo session was disposed.") {
|
|
214
|
+
const cancelled = [];
|
|
215
|
+
for (const record of this.runs.values()) {
|
|
216
|
+
if (record.ownerPiboSessionId !== ownerPiboSessionId || terminal(record.status))
|
|
217
|
+
continue;
|
|
218
|
+
record.status = "cancelled";
|
|
219
|
+
record.error = reason;
|
|
220
|
+
record.consumed = true;
|
|
221
|
+
record.summary = `${record.toolName} run cancelled.`;
|
|
222
|
+
this.finish(record);
|
|
223
|
+
this.options.store?.updateRun(record.runId, record);
|
|
224
|
+
if (record.jobId)
|
|
225
|
+
this.options.store?.fail(record.jobId, `run-registry:${process.pid}`, reason);
|
|
226
|
+
cancelled.push(snapshot(record));
|
|
227
|
+
}
|
|
228
|
+
return cancelled;
|
|
229
|
+
}
|
|
230
|
+
cancelAll(reason = "Run registry was disposed.") {
|
|
231
|
+
const cancelled = [];
|
|
232
|
+
for (const record of this.runs.values()) {
|
|
233
|
+
if (terminal(record.status))
|
|
234
|
+
continue;
|
|
235
|
+
record.status = "cancelled";
|
|
236
|
+
record.error = reason;
|
|
237
|
+
record.consumed = true;
|
|
238
|
+
record.summary = `${record.toolName} run cancelled.`;
|
|
239
|
+
this.finish(record);
|
|
240
|
+
this.options.store?.updateRun(record.runId, record);
|
|
241
|
+
if (record.jobId)
|
|
242
|
+
this.options.store?.fail(record.jobId, `run-registry:${process.pid}`, reason);
|
|
243
|
+
cancelled.push(snapshot(record));
|
|
244
|
+
}
|
|
245
|
+
return cancelled;
|
|
246
|
+
}
|
|
247
|
+
prune(options = {}) {
|
|
248
|
+
const nowMs = options.nowMs ?? Date.now();
|
|
249
|
+
const consumedTerminalTtlMs = options.consumedTerminalTtlMs ??
|
|
250
|
+
this.options.consumedTerminalTtlMs ??
|
|
251
|
+
DEFAULT_CONSUMED_TERMINAL_TTL_MS;
|
|
252
|
+
const detachedTerminalTtlMs = options.detachedTerminalTtlMs ??
|
|
253
|
+
this.options.detachedTerminalTtlMs ??
|
|
254
|
+
DEFAULT_DETACHED_TERMINAL_TTL_MS;
|
|
255
|
+
let pruned = 0;
|
|
256
|
+
for (const [runId, record] of this.runs) {
|
|
257
|
+
if (!terminal(record.status) || !record.completedAt)
|
|
258
|
+
continue;
|
|
259
|
+
const ageMs = nowMs - Date.parse(record.completedAt);
|
|
260
|
+
const shouldPrune = (record.completionPolicy === "detached" && ageMs >= detachedTerminalTtlMs) ||
|
|
261
|
+
(record.completionPolicy === "tracked" && record.consumed && ageMs >= consumedTerminalTtlMs);
|
|
262
|
+
if (!shouldPrune)
|
|
263
|
+
continue;
|
|
264
|
+
this.runs.delete(runId);
|
|
265
|
+
pruned += 1;
|
|
266
|
+
}
|
|
267
|
+
if (this.options.store) {
|
|
268
|
+
this.options.store.pruneRuns({ consumedTerminalTtlMs, detachedTerminalTtlMs, nowMs });
|
|
269
|
+
}
|
|
270
|
+
return pruned;
|
|
271
|
+
}
|
|
272
|
+
requireOwned(ownerPiboSessionId, runId) {
|
|
273
|
+
const record = this.runs.get(runId);
|
|
274
|
+
if (!record || record.ownerPiboSessionId !== ownerPiboSessionId) {
|
|
275
|
+
throw new Error(`Unknown run "${runId}" for session "${ownerPiboSessionId}"`);
|
|
276
|
+
}
|
|
277
|
+
return record;
|
|
278
|
+
}
|
|
279
|
+
needsNotification(record, ownerPiboSessionId, options = {}) {
|
|
280
|
+
return (record.ownerPiboSessionId === ownerPiboSessionId &&
|
|
281
|
+
record.completionPolicy === "tracked" &&
|
|
282
|
+
!record.consumed &&
|
|
283
|
+
record.acknowledgedStatus !== record.status &&
|
|
284
|
+
(options.includeAlreadyNotified || record.notifiedStatus !== record.status));
|
|
285
|
+
}
|
|
286
|
+
finish(record) {
|
|
287
|
+
const timestamp = now();
|
|
288
|
+
record.updatedAt = timestamp;
|
|
289
|
+
record.completedAt = timestamp;
|
|
290
|
+
this.resolveWaiters(record);
|
|
291
|
+
}
|
|
292
|
+
resolveWaiters(record) {
|
|
293
|
+
const waiters = this.waiters.get(record.runId);
|
|
294
|
+
if (!waiters)
|
|
295
|
+
return;
|
|
296
|
+
this.waiters.delete(record.runId);
|
|
297
|
+
for (const waiter of waiters) {
|
|
298
|
+
waiter.resolve(record);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
function recordFromStored(record) {
|
|
303
|
+
return {
|
|
304
|
+
runId: record.runId,
|
|
305
|
+
kind: record.kind,
|
|
306
|
+
ownerPiboSessionId: record.ownerPiboSessionId,
|
|
307
|
+
status: record.status,
|
|
308
|
+
completionPolicy: record.completionPolicy,
|
|
309
|
+
consumed: record.consumed,
|
|
310
|
+
toolName: record.toolName,
|
|
311
|
+
createdAt: record.createdAt,
|
|
312
|
+
updatedAt: record.updatedAt,
|
|
313
|
+
summary: record.summary,
|
|
314
|
+
completedAt: record.completedAt,
|
|
315
|
+
result: record.result,
|
|
316
|
+
error: record.error,
|
|
317
|
+
notifiedStatus: record.notifiedStatus,
|
|
318
|
+
acknowledgedStatus: record.acknowledgedStatus,
|
|
319
|
+
jobId: record.jobId,
|
|
320
|
+
retryable: record.retryable,
|
|
321
|
+
maxAttempts: record.maxAttempts,
|
|
322
|
+
};
|
|
323
|
+
}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { StringEnum, Type } from "@mariozechner/pi-ai";
|
|
2
|
+
import { defineTool } from "@mariozechner/pi-coding-agent";
|
|
3
|
+
function resultText(prefix, value) {
|
|
4
|
+
return `${prefix}\n${JSON.stringify(value, null, 2)}`;
|
|
5
|
+
}
|
|
6
|
+
function textFromToolResult(result) {
|
|
7
|
+
if (!Array.isArray(result.content))
|
|
8
|
+
return undefined;
|
|
9
|
+
const text = result.content
|
|
10
|
+
.map((part) => {
|
|
11
|
+
if (!part || typeof part !== "object")
|
|
12
|
+
return "";
|
|
13
|
+
const candidate = part;
|
|
14
|
+
return candidate.type === "text" && typeof candidate.text === "string" ? candidate.text : "";
|
|
15
|
+
})
|
|
16
|
+
.filter(Boolean)
|
|
17
|
+
.join("\n");
|
|
18
|
+
return text || undefined;
|
|
19
|
+
}
|
|
20
|
+
function requireTool(tools, name) {
|
|
21
|
+
const tool = tools.find((candidate) => candidate.name === name);
|
|
22
|
+
if (!tool) {
|
|
23
|
+
throw new Error(`Unknown or non-yieldable tool "${name}"`);
|
|
24
|
+
}
|
|
25
|
+
return tool;
|
|
26
|
+
}
|
|
27
|
+
export function createRunToolDefinitions(yieldableTools, controller) {
|
|
28
|
+
const toolNames = yieldableTools.map((tool) => tool.name);
|
|
29
|
+
return [
|
|
30
|
+
defineTool({
|
|
31
|
+
name: "pibo_run_start",
|
|
32
|
+
label: "Pibo Run Start",
|
|
33
|
+
description: "Start a yieldable tool as a yielded run. Use tracked when the result may matter later; use detached only for intentional fire-and-forget work.",
|
|
34
|
+
promptSnippet: "Use pibo_run_start to run a yieldable tool in the background. It returns a runId. Use pibo_run_read for completed results and pibo_run_wait/status/list/cancel/ack to manage runs.",
|
|
35
|
+
executionMode: "parallel",
|
|
36
|
+
parameters: Type.Object({
|
|
37
|
+
toolName: StringEnum(toolNames, { description: "Yieldable tool name to start" }),
|
|
38
|
+
arguments: Type.Any({ description: "Arguments object for the selected tool" }),
|
|
39
|
+
completionPolicy: Type.Optional(StringEnum(["tracked", "detached"], {
|
|
40
|
+
description: "tracked reminds this agent about completion; detached is fire-and-forget and creates no automatic reminders.",
|
|
41
|
+
default: "tracked",
|
|
42
|
+
})),
|
|
43
|
+
}),
|
|
44
|
+
async execute(toolCallId, params, signal, onUpdate, ctx) {
|
|
45
|
+
const tool = requireTool(yieldableTools, params.toolName);
|
|
46
|
+
const run = controller.startToolRun({
|
|
47
|
+
toolName: tool.name,
|
|
48
|
+
params: params.arguments,
|
|
49
|
+
completionPolicy: params.completionPolicy,
|
|
50
|
+
async execute() {
|
|
51
|
+
const result = await tool.execute(toolCallId, params.arguments, signal, onUpdate, ctx);
|
|
52
|
+
const resultObject = result;
|
|
53
|
+
const text = textFromToolResult(resultObject);
|
|
54
|
+
if (resultObject.isError === true) {
|
|
55
|
+
throw new Error(text ?? `${tool.name} returned an error result.`);
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
text,
|
|
59
|
+
details: resultObject.details ?? result,
|
|
60
|
+
};
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
return {
|
|
64
|
+
content: [{ type: "text", text: resultText(`Started yielded run ${run.runId}.`, run) }],
|
|
65
|
+
details: run,
|
|
66
|
+
};
|
|
67
|
+
},
|
|
68
|
+
}),
|
|
69
|
+
defineTool({
|
|
70
|
+
name: "pibo_run_list",
|
|
71
|
+
label: "Pibo Run List",
|
|
72
|
+
description: "List yielded runs owned by this agent session.",
|
|
73
|
+
promptSnippet: "Use pibo_run_list to inspect yielded runs owned by this session.",
|
|
74
|
+
executionMode: "parallel",
|
|
75
|
+
parameters: Type.Object({
|
|
76
|
+
includeConsumed: Type.Optional(Type.Boolean({ description: "Include already read, cancelled, or acknowledged runs" })),
|
|
77
|
+
includeDetached: Type.Optional(Type.Boolean({ description: "Include fire-and-forget detached runs" })),
|
|
78
|
+
}),
|
|
79
|
+
async execute(_toolCallId, params) {
|
|
80
|
+
const runs = controller.listRuns({
|
|
81
|
+
includeConsumed: params.includeConsumed,
|
|
82
|
+
includeDetached: params.includeDetached,
|
|
83
|
+
});
|
|
84
|
+
return {
|
|
85
|
+
content: [{ type: "text", text: resultText("Runs:", { runs }) }],
|
|
86
|
+
details: { runs },
|
|
87
|
+
};
|
|
88
|
+
},
|
|
89
|
+
}),
|
|
90
|
+
defineTool({
|
|
91
|
+
name: "pibo_run_status",
|
|
92
|
+
label: "Pibo Run Status",
|
|
93
|
+
description: "Read compact status for one yielded run.",
|
|
94
|
+
promptSnippet: "Use pibo_run_status to inspect one yielded run without reading its full result.",
|
|
95
|
+
executionMode: "parallel",
|
|
96
|
+
parameters: Type.Object({
|
|
97
|
+
runId: Type.String({ description: "Run id returned by pibo_run_start" }),
|
|
98
|
+
}),
|
|
99
|
+
async execute(_toolCallId, params) {
|
|
100
|
+
const run = controller.getRunStatus(params.runId);
|
|
101
|
+
return {
|
|
102
|
+
content: [{ type: "text", text: resultText(`Run ${run.runId} status: ${run.status}.`, run) }],
|
|
103
|
+
details: run,
|
|
104
|
+
};
|
|
105
|
+
},
|
|
106
|
+
}),
|
|
107
|
+
defineTool({
|
|
108
|
+
name: "pibo_run_wait",
|
|
109
|
+
label: "Pibo Run Wait",
|
|
110
|
+
description: "Wait a bounded time for a yielded run. Timeout is normal and does not mean failure.",
|
|
111
|
+
promptSnippet: "Use pibo_run_wait when blocked on a run. Timeout is normal; call again or continue other work.",
|
|
112
|
+
executionMode: "parallel",
|
|
113
|
+
parameters: Type.Object({
|
|
114
|
+
runId: Type.String({ description: "Run id returned by pibo_run_start" }),
|
|
115
|
+
timeoutMs: Type.Optional(Type.Number({ description: "Maximum wait time in milliseconds, clamped to 300000" })),
|
|
116
|
+
}),
|
|
117
|
+
async execute(_toolCallId, params) {
|
|
118
|
+
const run = await controller.waitForRun(params.runId, params.timeoutMs ?? 30000);
|
|
119
|
+
return {
|
|
120
|
+
content: [
|
|
121
|
+
{
|
|
122
|
+
type: "text",
|
|
123
|
+
text: resultText(run.timedOut
|
|
124
|
+
? `Run ${run.runId} is still ${run.status}; wait timed out.`
|
|
125
|
+
: `Run ${run.runId} reached ${run.status}.`, run),
|
|
126
|
+
},
|
|
127
|
+
],
|
|
128
|
+
details: run,
|
|
129
|
+
};
|
|
130
|
+
},
|
|
131
|
+
}),
|
|
132
|
+
defineTool({
|
|
133
|
+
name: "pibo_run_read",
|
|
134
|
+
label: "Pibo Run Read",
|
|
135
|
+
description: "Read the terminal result or error for a yielded run.",
|
|
136
|
+
promptSnippet: "Use pibo_run_read to retrieve a completed or failed run result. Reading terminal tracked runs consumes reminders.",
|
|
137
|
+
executionMode: "parallel",
|
|
138
|
+
parameters: Type.Object({
|
|
139
|
+
runId: Type.String({ description: "Run id returned by pibo_run_start" }),
|
|
140
|
+
}),
|
|
141
|
+
async execute(_toolCallId, params) {
|
|
142
|
+
const run = controller.readRun(params.runId);
|
|
143
|
+
const text = run.result?.text ?? run.error ?? `Run ${run.runId} is ${run.status}; no terminal result is available yet.`;
|
|
144
|
+
return {
|
|
145
|
+
content: [{ type: "text", text }],
|
|
146
|
+
details: run,
|
|
147
|
+
};
|
|
148
|
+
},
|
|
149
|
+
}),
|
|
150
|
+
defineTool({
|
|
151
|
+
name: "pibo_run_cancel",
|
|
152
|
+
label: "Pibo Run Cancel",
|
|
153
|
+
description: "Cancel a yielded run if possible and suppress future reminders.",
|
|
154
|
+
promptSnippet: "Use pibo_run_cancel when a yielded run is no longer needed.",
|
|
155
|
+
executionMode: "parallel",
|
|
156
|
+
parameters: Type.Object({
|
|
157
|
+
runId: Type.String({ description: "Run id returned by pibo_run_start" }),
|
|
158
|
+
}),
|
|
159
|
+
async execute(_toolCallId, params) {
|
|
160
|
+
const run = await controller.cancelRun(params.runId);
|
|
161
|
+
return {
|
|
162
|
+
content: [{ type: "text", text: resultText(`Cancelled run ${run.runId}.`, run) }],
|
|
163
|
+
details: run,
|
|
164
|
+
};
|
|
165
|
+
},
|
|
166
|
+
}),
|
|
167
|
+
defineTool({
|
|
168
|
+
name: "pibo_run_ack",
|
|
169
|
+
label: "Pibo Run Ack",
|
|
170
|
+
description: "Acknowledge a yielded run update and suppress reminders for its current state.",
|
|
171
|
+
promptSnippet: "Use pibo_run_ack when you intentionally do not need to read a completed result or do not need more reminders for the current running state.",
|
|
172
|
+
executionMode: "parallel",
|
|
173
|
+
parameters: Type.Object({
|
|
174
|
+
runId: Type.String({ description: "Run id returned by pibo_run_start" }),
|
|
175
|
+
}),
|
|
176
|
+
async execute(_toolCallId, params) {
|
|
177
|
+
const run = controller.ackRun(params.runId);
|
|
178
|
+
return {
|
|
179
|
+
content: [{ type: "text", text: resultText(`Acknowledged run ${run.runId}.`, run) }],
|
|
180
|
+
details: run,
|
|
181
|
+
};
|
|
182
|
+
},
|
|
183
|
+
}),
|
|
184
|
+
];
|
|
185
|
+
}
|