@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,338 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { cp, mkdir, rm, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { ErrorCode, formatCliError } from '../cli-errors.js';
|
|
5
|
+
import { BROWSER_USE_DEFAULT_PROFILE } from './browser-use-wrapper.js';
|
|
6
|
+
const REGISTRY_VERSION = 1;
|
|
7
|
+
const DEFAULT_APP = 'pibo-chat';
|
|
8
|
+
const DEFAULT_TTL_MINUTES = 8 * 60;
|
|
9
|
+
const DEFAULT_TEMPLATE_PROFILE = 'pibo-auth-template';
|
|
10
|
+
const AUTH_POOL_DIR = 'auth-pool';
|
|
11
|
+
function shellQuote(value) {
|
|
12
|
+
return `'${value.replaceAll("'", "'\\''")}'`;
|
|
13
|
+
}
|
|
14
|
+
function nowIso() {
|
|
15
|
+
return new Date().toISOString();
|
|
16
|
+
}
|
|
17
|
+
function addMinutes(date, minutes) {
|
|
18
|
+
return new Date(date.getTime() + minutes * 60_000);
|
|
19
|
+
}
|
|
20
|
+
function sanitizeIdPart(value) {
|
|
21
|
+
return value
|
|
22
|
+
.trim()
|
|
23
|
+
.toLowerCase()
|
|
24
|
+
.replace(/[^a-z0-9_.-]+/g, '-')
|
|
25
|
+
.replace(/^-+|-+$/g, '') || 'default';
|
|
26
|
+
}
|
|
27
|
+
function registryPath(status) {
|
|
28
|
+
return join(status.homeDir, AUTH_POOL_DIR, 'leases.json');
|
|
29
|
+
}
|
|
30
|
+
function lockDir(status) {
|
|
31
|
+
return join(status.homeDir, AUTH_POOL_DIR, '.leases.lock');
|
|
32
|
+
}
|
|
33
|
+
function appPoolDir(status, app) {
|
|
34
|
+
return join(status.homeDir, AUTH_POOL_DIR, sanitizeIdPart(app));
|
|
35
|
+
}
|
|
36
|
+
function browserUseHome(status) {
|
|
37
|
+
return status.homeDir;
|
|
38
|
+
}
|
|
39
|
+
function authTemplateDir(status) {
|
|
40
|
+
if (process.env.PIBO_BROWSER_USE_AUTH_TEMPLATE_DIR) {
|
|
41
|
+
return process.env.PIBO_BROWSER_USE_AUTH_TEMPLATE_DIR;
|
|
42
|
+
}
|
|
43
|
+
return join(status.homeDir, 'chrome-profiles', DEFAULT_TEMPLATE_PROFILE);
|
|
44
|
+
}
|
|
45
|
+
function defaultTemplateDir(status) {
|
|
46
|
+
const preferred = authTemplateDir(status);
|
|
47
|
+
if (existsSync(preferred))
|
|
48
|
+
return preferred;
|
|
49
|
+
return join(status.homeDir, 'chrome-profiles', BROWSER_USE_DEFAULT_PROFILE);
|
|
50
|
+
}
|
|
51
|
+
function readRegistry(status) {
|
|
52
|
+
const path = registryPath(status);
|
|
53
|
+
if (!existsSync(path))
|
|
54
|
+
return { version: REGISTRY_VERSION, leases: [] };
|
|
55
|
+
const parsed = JSON.parse(readFileSync(path, 'utf-8'));
|
|
56
|
+
if (!parsed || typeof parsed !== 'object' || !Array.isArray(parsed.leases)) {
|
|
57
|
+
throw new Error(`Invalid browser-use lease registry: ${path}`);
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
version: REGISTRY_VERSION,
|
|
61
|
+
leases: parsed.leases,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
async function writeRegistry(status, registry) {
|
|
65
|
+
const path = registryPath(status);
|
|
66
|
+
await mkdir(join(status.homeDir, AUTH_POOL_DIR), { recursive: true });
|
|
67
|
+
await writeFile(path, `${JSON.stringify({ ...registry, version: REGISTRY_VERSION }, null, 2)}\n`);
|
|
68
|
+
}
|
|
69
|
+
async function withRegistryLock(status, action) {
|
|
70
|
+
const lock = lockDir(status);
|
|
71
|
+
await mkdir(join(status.homeDir, AUTH_POOL_DIR), { recursive: true });
|
|
72
|
+
let acquired = false;
|
|
73
|
+
for (let attempt = 0; attempt < 50; attempt += 1) {
|
|
74
|
+
try {
|
|
75
|
+
await mkdir(lock);
|
|
76
|
+
acquired = true;
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
if (error.code !== 'EEXIST')
|
|
81
|
+
throw error;
|
|
82
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if (!acquired) {
|
|
86
|
+
throw new Error('Timed out waiting for browser-use lease registry lock');
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
return await action();
|
|
90
|
+
}
|
|
91
|
+
finally {
|
|
92
|
+
await rm(lock, { recursive: true, force: true });
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function isExpired(lease, now = new Date()) {
|
|
96
|
+
return new Date(lease.expiresAt).getTime() <= now.getTime();
|
|
97
|
+
}
|
|
98
|
+
function safeSessionName(sessionName) {
|
|
99
|
+
return sessionName.replace(/[^A-Za-z0-9_.-]/g, '_');
|
|
100
|
+
}
|
|
101
|
+
function cdpPidFile(status, sessionName) {
|
|
102
|
+
return join(status.homeDir, 'pibo-cdp', `${safeSessionName(sessionName)}.pid`);
|
|
103
|
+
}
|
|
104
|
+
function processIsAlive(pid) {
|
|
105
|
+
try {
|
|
106
|
+
process.kill(pid, 0);
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
function readPid(path) {
|
|
114
|
+
try {
|
|
115
|
+
const value = Number.parseInt(readFileSync(path, 'utf-8'), 10);
|
|
116
|
+
return Number.isFinite(value) && value > 0 ? value : undefined;
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
return undefined;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
function leaseProcessIsAlive(status, lease) {
|
|
123
|
+
const pid = readPid(cdpPidFile(status, lease.sessionName));
|
|
124
|
+
return pid ? processIsAlive(pid) : false;
|
|
125
|
+
}
|
|
126
|
+
function killLeaseProcess(status, lease) {
|
|
127
|
+
const pid = readPid(cdpPidFile(status, lease.sessionName));
|
|
128
|
+
if (!pid)
|
|
129
|
+
return;
|
|
130
|
+
try {
|
|
131
|
+
process.kill(pid, 'SIGTERM');
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
// Process already exited.
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
async function copyTemplateProfile(templateDir, userDataDir) {
|
|
138
|
+
if (!existsSync(templateDir)) {
|
|
139
|
+
throw new Error(formatCliError({
|
|
140
|
+
code: ErrorCode.CLIENT_ERROR,
|
|
141
|
+
type: 'BROWSER_USE_AUTH_TEMPLATE_MISSING',
|
|
142
|
+
message: `Browser-use auth template does not exist: ${templateDir}`,
|
|
143
|
+
suggestion: 'Run `pibo tools browser-use auth-template env`, open the Chat Web App, sign in, then acquire a lease again.',
|
|
144
|
+
}));
|
|
145
|
+
}
|
|
146
|
+
assertTemplateIsNotRunning(templateDir);
|
|
147
|
+
await rm(userDataDir, { recursive: true, force: true });
|
|
148
|
+
await mkdir(userDataDir, { recursive: true });
|
|
149
|
+
await cp(templateDir, userDataDir, {
|
|
150
|
+
recursive: true,
|
|
151
|
+
filter: (source) => {
|
|
152
|
+
const base = source.split(/[\\/]/).pop() ?? '';
|
|
153
|
+
return !base.startsWith('Singleton') && base !== 'DevToolsActivePort';
|
|
154
|
+
},
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
function assertTemplateIsNotRunning(templateDir) {
|
|
158
|
+
for (const fileName of ['SingletonLock', 'SingletonCookie', 'SingletonSocket']) {
|
|
159
|
+
if (!existsSync(join(templateDir, fileName)))
|
|
160
|
+
continue;
|
|
161
|
+
throw new Error(formatCliError({
|
|
162
|
+
code: ErrorCode.CLIENT_ERROR,
|
|
163
|
+
type: 'BROWSER_USE_AUTH_TEMPLATE_RUNNING',
|
|
164
|
+
message: `Browser-use auth template appears to be running: ${templateDir}`,
|
|
165
|
+
details: `Found ${fileName}`,
|
|
166
|
+
suggestion: 'Close the template browser before acquiring leases, or pass --template-dir for a closed template profile.',
|
|
167
|
+
}));
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
function nextSlotNumber(leases, app) {
|
|
171
|
+
const prefix = `${sanitizeIdPart(app)}-slot-`;
|
|
172
|
+
const used = new Set(leases
|
|
173
|
+
.filter((lease) => lease.app === app)
|
|
174
|
+
.map((lease) => Number.parseInt(lease.id.slice(prefix.length), 10))
|
|
175
|
+
.filter((value) => Number.isFinite(value)));
|
|
176
|
+
for (let value = 1; value < 10_000; value += 1) {
|
|
177
|
+
if (!used.has(value))
|
|
178
|
+
return value;
|
|
179
|
+
}
|
|
180
|
+
throw new Error(`No browser-use slots available for ${app}`);
|
|
181
|
+
}
|
|
182
|
+
function createLease(status, app, owner, ttlMinutes, profileName, leases) {
|
|
183
|
+
const slot = nextSlotNumber(leases, app);
|
|
184
|
+
const slotName = `slot-${String(slot).padStart(3, '0')}`;
|
|
185
|
+
const appId = sanitizeIdPart(app);
|
|
186
|
+
const id = `${appId}-${slotName}`;
|
|
187
|
+
const createdAt = nowIso();
|
|
188
|
+
return {
|
|
189
|
+
id,
|
|
190
|
+
app,
|
|
191
|
+
owner,
|
|
192
|
+
sessionName: `pibo-auth-${id}`,
|
|
193
|
+
userDataDir: join(appPoolDir(status, app), slotName),
|
|
194
|
+
profileName,
|
|
195
|
+
status: 'active',
|
|
196
|
+
createdAt,
|
|
197
|
+
updatedAt: createdAt,
|
|
198
|
+
expiresAt: addMinutes(new Date(createdAt), ttlMinutes).toISOString(),
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
function selectReusableLease(status, leases, app) {
|
|
202
|
+
return leases.find((lease) => lease.app === app &&
|
|
203
|
+
(lease.status === 'released' || isExpired(lease)) &&
|
|
204
|
+
!leaseProcessIsAlive(status, lease));
|
|
205
|
+
}
|
|
206
|
+
function printLeaseEnv(status, lease) {
|
|
207
|
+
console.log(`export BROWSER_USE_HOME=${shellQuote(browserUseHome(status))}`);
|
|
208
|
+
console.log(`export PIBO_BROWSER_USE_LEASE_ID=${shellQuote(lease.id)}`);
|
|
209
|
+
console.log(`export PIBO_BROWSER_USE_SESSION=${shellQuote(lease.sessionName)}`);
|
|
210
|
+
console.log(`export PIBO_BROWSER_USE_CHROME_USER_DATA_DIR=${shellQuote(lease.userDataDir)}`);
|
|
211
|
+
console.log(`export PIBO_BROWSER_USE_DEFAULT_PROFILE=${shellQuote(lease.profileName)}`);
|
|
212
|
+
console.log(`# browser-use --session "$PIBO_BROWSER_USE_SESSION" state`);
|
|
213
|
+
}
|
|
214
|
+
function printLeaseJson(status, lease) {
|
|
215
|
+
console.log(JSON.stringify({
|
|
216
|
+
...lease,
|
|
217
|
+
browserUseHome: browserUseHome(status),
|
|
218
|
+
exports: {
|
|
219
|
+
BROWSER_USE_HOME: browserUseHome(status),
|
|
220
|
+
PIBO_BROWSER_USE_LEASE_ID: lease.id,
|
|
221
|
+
PIBO_BROWSER_USE_SESSION: lease.sessionName,
|
|
222
|
+
PIBO_BROWSER_USE_CHROME_USER_DATA_DIR: lease.userDataDir,
|
|
223
|
+
PIBO_BROWSER_USE_DEFAULT_PROFILE: lease.profileName,
|
|
224
|
+
},
|
|
225
|
+
}, null, 2));
|
|
226
|
+
}
|
|
227
|
+
export async function acquireBrowserUseLease(context, options = {}) {
|
|
228
|
+
const app = options.app?.trim() || DEFAULT_APP;
|
|
229
|
+
const owner = options.owner?.trim() || process.env.PIBO_BROWSER_USE_LEASE_OWNER || process.env.USER || 'unknown';
|
|
230
|
+
const ttlMinutes = options.ttlMinutes ?? DEFAULT_TTL_MINUTES;
|
|
231
|
+
const profileName = options.profileName?.trim() || BROWSER_USE_DEFAULT_PROFILE;
|
|
232
|
+
const templateDir = options.templateDir?.trim() || defaultTemplateDir(context.status);
|
|
233
|
+
await withRegistryLock(context.status, async () => {
|
|
234
|
+
const registry = readRegistry(context.status);
|
|
235
|
+
let lease = selectReusableLease(context.status, registry.leases, app);
|
|
236
|
+
if (lease) {
|
|
237
|
+
await copyTemplateProfile(templateDir, lease.userDataDir);
|
|
238
|
+
lease.owner = owner;
|
|
239
|
+
lease.status = 'active';
|
|
240
|
+
lease.profileName = profileName;
|
|
241
|
+
lease.updatedAt = nowIso();
|
|
242
|
+
lease.expiresAt = addMinutes(new Date(), ttlMinutes).toISOString();
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
const activeCount = registry.leases.filter((item) => item.app === app &&
|
|
246
|
+
item.status === 'active' &&
|
|
247
|
+
!isExpired(item)).length;
|
|
248
|
+
if (options.maxSlots !== undefined && activeCount >= options.maxSlots) {
|
|
249
|
+
throw new Error(formatCliError({
|
|
250
|
+
code: ErrorCode.CLIENT_ERROR,
|
|
251
|
+
type: 'BROWSER_USE_AUTH_POOL_EXHAUSTED',
|
|
252
|
+
message: `No browser-use auth slots available for ${app}`,
|
|
253
|
+
details: `active=${activeCount} max=${options.maxSlots}`,
|
|
254
|
+
suggestion: 'Release a lease or rerun with a higher --max-slots value.',
|
|
255
|
+
}));
|
|
256
|
+
}
|
|
257
|
+
lease = createLease(context.status, app, owner, ttlMinutes, profileName, registry.leases);
|
|
258
|
+
await copyTemplateProfile(templateDir, lease.userDataDir);
|
|
259
|
+
registry.leases.push(lease);
|
|
260
|
+
}
|
|
261
|
+
await writeRegistry(context.status, registry);
|
|
262
|
+
if (options.json)
|
|
263
|
+
printLeaseJson(context.status, lease);
|
|
264
|
+
else
|
|
265
|
+
printLeaseEnv(context.status, lease);
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
export async function listBrowserUseLeases(context, json = false) {
|
|
269
|
+
const registry = readRegistry(context.status);
|
|
270
|
+
const rows = registry.leases.map((lease) => ({
|
|
271
|
+
...lease,
|
|
272
|
+
expired: isExpired(lease),
|
|
273
|
+
processAlive: leaseProcessIsAlive(context.status, lease),
|
|
274
|
+
}));
|
|
275
|
+
if (json) {
|
|
276
|
+
console.log(JSON.stringify(rows, null, 2));
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
if (rows.length === 0) {
|
|
280
|
+
console.log('No browser-use auth leases.');
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
for (const row of rows) {
|
|
284
|
+
const state = row.status === 'active' && !row.expired ? 'active' : row.expired ? 'expired' : row.status;
|
|
285
|
+
console.log(`${row.id}\t${state}\t${row.owner}\t${row.sessionName}\t${row.userDataDir}`);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
export async function releaseBrowserUseLease(context, id, options = {}) {
|
|
289
|
+
await withRegistryLock(context.status, async () => {
|
|
290
|
+
const registry = readRegistry(context.status);
|
|
291
|
+
const lease = registry.leases.find((candidate) => candidate.id === id);
|
|
292
|
+
if (!lease) {
|
|
293
|
+
throw new Error(formatCliError({
|
|
294
|
+
code: ErrorCode.CLIENT_ERROR,
|
|
295
|
+
type: 'BROWSER_USE_AUTH_LEASE_NOT_FOUND',
|
|
296
|
+
message: `Browser-use auth lease "${id}" not found`,
|
|
297
|
+
suggestion: 'Run `pibo tools browser-use lease list`.',
|
|
298
|
+
}));
|
|
299
|
+
}
|
|
300
|
+
killLeaseProcess(context.status, lease);
|
|
301
|
+
lease.status = 'released';
|
|
302
|
+
lease.updatedAt = nowIso();
|
|
303
|
+
if (options.deleteProfile) {
|
|
304
|
+
await rm(lease.userDataDir, { recursive: true, force: true });
|
|
305
|
+
}
|
|
306
|
+
await writeRegistry(context.status, registry);
|
|
307
|
+
console.log(`Released ${lease.id}`);
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
export async function reapStaleBrowserUseLeases(context) {
|
|
311
|
+
await withRegistryLock(context.status, async () => {
|
|
312
|
+
const registry = readRegistry(context.status);
|
|
313
|
+
let count = 0;
|
|
314
|
+
for (const lease of registry.leases) {
|
|
315
|
+
if (lease.status !== 'active' || !isExpired(lease))
|
|
316
|
+
continue;
|
|
317
|
+
if (leaseProcessIsAlive(context.status, lease))
|
|
318
|
+
killLeaseProcess(context.status, lease);
|
|
319
|
+
lease.status = 'released';
|
|
320
|
+
lease.updatedAt = nowIso();
|
|
321
|
+
count += 1;
|
|
322
|
+
}
|
|
323
|
+
await writeRegistry(context.status, registry);
|
|
324
|
+
console.log(`Reaped ${count} stale browser-use auth lease${count === 1 ? '' : 's'}`);
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
export function printBrowserUseAuthTemplatePath(status) {
|
|
328
|
+
console.log(authTemplateDir(status));
|
|
329
|
+
}
|
|
330
|
+
export async function printBrowserUseAuthTemplateEnv(status) {
|
|
331
|
+
const templateDir = authTemplateDir(status);
|
|
332
|
+
await mkdir(templateDir, { recursive: true });
|
|
333
|
+
console.log(`export BROWSER_USE_HOME=${shellQuote(browserUseHome(status))}`);
|
|
334
|
+
console.log(`export PIBO_BROWSER_USE_SESSION=${shellQuote('pibo-auth-template')}`);
|
|
335
|
+
console.log(`export PIBO_BROWSER_USE_CHROME_USER_DATA_DIR=${shellQuote(templateDir)}`);
|
|
336
|
+
console.log(`export PIBO_BROWSER_USE_DEFAULT_PROFILE=${shellQuote(BROWSER_USE_DEFAULT_PROFILE)}`);
|
|
337
|
+
console.log(`# browser-use --headed --session "$PIBO_BROWSER_USE_SESSION" open <chat-url>`);
|
|
338
|
+
}
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
import { chmodSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { dirname, join } from 'node:path';
|
|
3
|
+
export const BROWSER_USE_DEFAULT_PROFILE = 'PIBo';
|
|
4
|
+
export const BROWSER_USE_FRESH_PROFILE_FLAG = '--fresh-profile';
|
|
5
|
+
function shellQuote(value) {
|
|
6
|
+
return `'${value.replaceAll("'", "'\\''")}'`;
|
|
7
|
+
}
|
|
8
|
+
function createBrowserUseWrapper(realExecutablePath) {
|
|
9
|
+
return `#!/bin/sh
|
|
10
|
+
set -eu
|
|
11
|
+
|
|
12
|
+
real_browser_use=${shellQuote(realExecutablePath)}
|
|
13
|
+
default_profile=\${PIBO_BROWSER_USE_DEFAULT_PROFILE:-${shellQuote(BROWSER_USE_DEFAULT_PROFILE)}}
|
|
14
|
+
fresh_flag=${shellQuote(BROWSER_USE_FRESH_PROFILE_FLAG)}
|
|
15
|
+
python_cmd=\${PIBO_BROWSER_USE_PYTHON:-$(dirname "$real_browser_use")/python}
|
|
16
|
+
if [ ! -x "$python_cmd" ]; then
|
|
17
|
+
python_cmd=$(command -v python3 || command -v python || printf '%s' "$python_cmd")
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
session=\${PIBO_BROWSER_USE_SESSION:-default}
|
|
21
|
+
explicit_profile=0
|
|
22
|
+
fresh_profile=0
|
|
23
|
+
starts_browser=0
|
|
24
|
+
show_help=0
|
|
25
|
+
headed=0
|
|
26
|
+
sanitized_args=
|
|
27
|
+
|
|
28
|
+
append_arg() {
|
|
29
|
+
if [ "$#" -eq 0 ]; then
|
|
30
|
+
return
|
|
31
|
+
fi
|
|
32
|
+
if [ -z "$sanitized_args" ]; then
|
|
33
|
+
sanitized_args=$(printf '%s\\n' "$1")
|
|
34
|
+
else
|
|
35
|
+
sanitized_args=$(printf '%s\\n%s\\n' "$sanitized_args" "$1")
|
|
36
|
+
fi
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
find_chrome() {
|
|
40
|
+
if [ -n "\${PIBO_BROWSER_USE_CHROME:-}" ]; then
|
|
41
|
+
printf '%s\\n' "$PIBO_BROWSER_USE_CHROME"
|
|
42
|
+
return
|
|
43
|
+
fi
|
|
44
|
+
for candidate in google-chrome chrome chromium chromium-browser /opt/google/chrome/chrome; do
|
|
45
|
+
if command -v "$candidate" >/dev/null 2>&1; then
|
|
46
|
+
command -v "$candidate"
|
|
47
|
+
return
|
|
48
|
+
fi
|
|
49
|
+
if [ -x "$candidate" ]; then
|
|
50
|
+
printf '%s\\n' "$candidate"
|
|
51
|
+
return
|
|
52
|
+
fi
|
|
53
|
+
done
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
resolve_profile_directory() {
|
|
57
|
+
user_data_dir=$1
|
|
58
|
+
profile_name=$2
|
|
59
|
+
|
|
60
|
+
if [ -n "\${PIBO_BROWSER_USE_CHROME_PROFILE_DIRECTORY:-}" ]; then
|
|
61
|
+
printf '%s\\n' "$PIBO_BROWSER_USE_CHROME_PROFILE_DIRECTORY"
|
|
62
|
+
return
|
|
63
|
+
fi
|
|
64
|
+
|
|
65
|
+
"$python_cmd" - "$user_data_dir" "$profile_name" <<'PY'
|
|
66
|
+
import json
|
|
67
|
+
import sys
|
|
68
|
+
from pathlib import Path
|
|
69
|
+
|
|
70
|
+
user_data_dir = Path(sys.argv[1])
|
|
71
|
+
profile_name = sys.argv[2]
|
|
72
|
+
local_state = user_data_dir / "Local State"
|
|
73
|
+
try:
|
|
74
|
+
data = json.loads(local_state.read_text())
|
|
75
|
+
except Exception:
|
|
76
|
+
print(profile_name if (user_data_dir / profile_name).is_dir() else "Default")
|
|
77
|
+
raise SystemExit
|
|
78
|
+
|
|
79
|
+
info_cache = data.get("profile", {}).get("info_cache", {})
|
|
80
|
+
if profile_name in info_cache:
|
|
81
|
+
print(profile_name)
|
|
82
|
+
raise SystemExit
|
|
83
|
+
|
|
84
|
+
profile_name_lower = profile_name.lower()
|
|
85
|
+
for directory, info in info_cache.items():
|
|
86
|
+
if str(info.get("name", directory)).lower() == profile_name_lower:
|
|
87
|
+
print(directory)
|
|
88
|
+
raise SystemExit
|
|
89
|
+
|
|
90
|
+
for directory in info_cache:
|
|
91
|
+
if directory.lower() == profile_name_lower:
|
|
92
|
+
print(directory)
|
|
93
|
+
raise SystemExit
|
|
94
|
+
|
|
95
|
+
print(profile_name if (user_data_dir / profile_name).is_dir() else "Default")
|
|
96
|
+
PY
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
find_free_port() {
|
|
100
|
+
"$python_cmd" - <<'PY'
|
|
101
|
+
import socket
|
|
102
|
+
|
|
103
|
+
with socket.socket() as sock:
|
|
104
|
+
sock.bind(("127.0.0.1", 0))
|
|
105
|
+
print(sock.getsockname()[1])
|
|
106
|
+
PY
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
pibo_cdp_is_ready() {
|
|
110
|
+
"$python_cmd" - "$1" <<'PY'
|
|
111
|
+
import socket
|
|
112
|
+
import sys
|
|
113
|
+
|
|
114
|
+
port = int(sys.argv[1])
|
|
115
|
+
try:
|
|
116
|
+
with socket.create_connection(("127.0.0.1", port), timeout=0.2) as sock:
|
|
117
|
+
sock.sendall(b"GET /json/version HTTP/1.1\\r\\nHost: 127.0.0.1\\r\\nConnection: close\\r\\n\\r\\n")
|
|
118
|
+
data = sock.recv(128)
|
|
119
|
+
raise SystemExit(0 if b"200" in data else 1)
|
|
120
|
+
except Exception:
|
|
121
|
+
raise SystemExit(1)
|
|
122
|
+
PY
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
persistent_chrome_url_if_alive() {
|
|
126
|
+
safe_session=$(printf '%s' "$session" | tr -c 'A-Za-z0-9_.-' '_')
|
|
127
|
+
state_dir=\${BROWSER_USE_HOME:-$HOME/.browser-use}/pibo-cdp
|
|
128
|
+
pid_file=$state_dir/$safe_session.pid
|
|
129
|
+
port_file=$state_dir/$safe_session.port
|
|
130
|
+
|
|
131
|
+
if [ -s "$pid_file" ] && [ -s "$port_file" ]; then
|
|
132
|
+
chrome_pid=$(cat "$pid_file" 2>/dev/null || true)
|
|
133
|
+
chrome_port=$(cat "$port_file" 2>/dev/null || true)
|
|
134
|
+
if [ -n "$chrome_pid" ] && [ -n "$chrome_port" ] && kill -0 "$chrome_pid" 2>/dev/null && pibo_cdp_is_ready "$chrome_port"; then
|
|
135
|
+
printf 'http://127.0.0.1:%s\\n' "$chrome_port"
|
|
136
|
+
return 0
|
|
137
|
+
fi
|
|
138
|
+
fi
|
|
139
|
+
|
|
140
|
+
return 1
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
ensure_persistent_chrome() {
|
|
144
|
+
safe_session=$(printf '%s' "$session" | tr -c 'A-Za-z0-9_.-' '_')
|
|
145
|
+
state_dir=\${BROWSER_USE_HOME:-$HOME/.browser-use}/pibo-cdp
|
|
146
|
+
mkdir -p "$state_dir"
|
|
147
|
+
pid_file=$state_dir/$safe_session.pid
|
|
148
|
+
port_file=$state_dir/$safe_session.port
|
|
149
|
+
log_file=$state_dir/$safe_session.chrome.log
|
|
150
|
+
|
|
151
|
+
if cdp_url=$(persistent_chrome_url_if_alive); then
|
|
152
|
+
printf '%s\\n' "$cdp_url"
|
|
153
|
+
return
|
|
154
|
+
fi
|
|
155
|
+
|
|
156
|
+
chrome_bin=$(find_chrome)
|
|
157
|
+
if [ -z "$chrome_bin" ]; then
|
|
158
|
+
echo "pibo browser-use: could not find Chrome; install Chrome or use $fresh_flag for Browser Use managed Chromium." >&2
|
|
159
|
+
exit 1
|
|
160
|
+
fi
|
|
161
|
+
|
|
162
|
+
user_data_dir=\${PIBO_BROWSER_USE_CHROME_USER_DATA_DIR:-}
|
|
163
|
+
if [ -z "$user_data_dir" ]; then
|
|
164
|
+
user_data_dir=\${BROWSER_USE_HOME:-$HOME/.browser-use}/chrome-profiles/$default_profile
|
|
165
|
+
fi
|
|
166
|
+
|
|
167
|
+
mkdir -p "$user_data_dir"
|
|
168
|
+
profile_directory=$(resolve_profile_directory "$user_data_dir" "$default_profile")
|
|
169
|
+
chrome_port=$(find_free_port)
|
|
170
|
+
headless_arg=
|
|
171
|
+
if [ "$headed" -eq 0 ]; then
|
|
172
|
+
headless_arg=--headless=new
|
|
173
|
+
fi
|
|
174
|
+
if command -v setsid >/dev/null 2>&1; then
|
|
175
|
+
setsid "$chrome_bin" \\
|
|
176
|
+
--user-data-dir="$user_data_dir" \\
|
|
177
|
+
--profile-directory="$profile_directory" \\
|
|
178
|
+
--remote-debugging-port="$chrome_port" \\
|
|
179
|
+
--no-first-run \\
|
|
180
|
+
--no-default-browser-check \\
|
|
181
|
+
--disable-default-apps \\
|
|
182
|
+
--no-sandbox \\
|
|
183
|
+
--disable-setuid-sandbox \\
|
|
184
|
+
--disable-dev-shm-usage \\
|
|
185
|
+
$headless_arg \\
|
|
186
|
+
about:blank >"$log_file" 2>&1 &
|
|
187
|
+
else
|
|
188
|
+
nohup "$chrome_bin" \\
|
|
189
|
+
--user-data-dir="$user_data_dir" \\
|
|
190
|
+
--profile-directory="$profile_directory" \\
|
|
191
|
+
--remote-debugging-port="$chrome_port" \\
|
|
192
|
+
--no-first-run \\
|
|
193
|
+
--no-default-browser-check \\
|
|
194
|
+
--disable-default-apps \\
|
|
195
|
+
--no-sandbox \\
|
|
196
|
+
--disable-setuid-sandbox \\
|
|
197
|
+
--disable-dev-shm-usage \\
|
|
198
|
+
$headless_arg \\
|
|
199
|
+
about:blank >"$log_file" 2>&1 &
|
|
200
|
+
fi
|
|
201
|
+
chrome_pid=$!
|
|
202
|
+
|
|
203
|
+
ready=0
|
|
204
|
+
if [ "\${PIBO_BROWSER_USE_SKIP_CDP_WAIT:-}" = "1" ]; then
|
|
205
|
+
ready=1
|
|
206
|
+
fi
|
|
207
|
+
attempt=0
|
|
208
|
+
while [ "$ready" -ne 1 ] && [ "$attempt" -lt 50 ]; do
|
|
209
|
+
if pibo_cdp_is_ready "$chrome_port"; then
|
|
210
|
+
ready=1
|
|
211
|
+
break
|
|
212
|
+
fi
|
|
213
|
+
if ! kill -0 "$chrome_pid" 2>/dev/null; then
|
|
214
|
+
break
|
|
215
|
+
fi
|
|
216
|
+
attempt=$((attempt + 1))
|
|
217
|
+
sleep 0.1
|
|
218
|
+
done
|
|
219
|
+
|
|
220
|
+
if [ "$ready" -ne 1 ]; then
|
|
221
|
+
echo "pibo browser-use: Chrome did not expose CDP on port $chrome_port." >&2
|
|
222
|
+
sed -n '1,80p' "$log_file" >&2 2>/dev/null || true
|
|
223
|
+
exit 1
|
|
224
|
+
fi
|
|
225
|
+
|
|
226
|
+
printf '%s\\n' "$chrome_pid" > "$pid_file"
|
|
227
|
+
printf '%s\\n' "$chrome_port" > "$port_file"
|
|
228
|
+
printf 'pibo browser-use: started Chrome profile "%s" (%s/%s) on CDP port %s.\\n' "$default_profile" "$user_data_dir" "$profile_directory" "$chrome_port" >&2
|
|
229
|
+
printf 'http://127.0.0.1:%s\\n' "$chrome_port"
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
while [ "$#" -gt 0 ]; do
|
|
233
|
+
arg=$1
|
|
234
|
+
shift
|
|
235
|
+
|
|
236
|
+
case "$arg" in
|
|
237
|
+
"$fresh_flag")
|
|
238
|
+
fresh_profile=1
|
|
239
|
+
continue
|
|
240
|
+
;;
|
|
241
|
+
--help|-h)
|
|
242
|
+
show_help=1
|
|
243
|
+
;;
|
|
244
|
+
--headed)
|
|
245
|
+
headed=1
|
|
246
|
+
;;
|
|
247
|
+
--profile)
|
|
248
|
+
explicit_profile=1
|
|
249
|
+
append_arg "$arg"
|
|
250
|
+
continue
|
|
251
|
+
;;
|
|
252
|
+
--cdp-url)
|
|
253
|
+
explicit_profile=1
|
|
254
|
+
append_arg "$arg"
|
|
255
|
+
if [ "$#" -gt 0 ]; then
|
|
256
|
+
append_arg "$1"
|
|
257
|
+
shift
|
|
258
|
+
fi
|
|
259
|
+
continue
|
|
260
|
+
;;
|
|
261
|
+
--profile=*|--cdp-url=*|--connect|--mcp|--use-cloud|--cloud-profile-id|--cloud-profile-id=*)
|
|
262
|
+
explicit_profile=1
|
|
263
|
+
;;
|
|
264
|
+
--session)
|
|
265
|
+
append_arg "$arg"
|
|
266
|
+
if [ "$#" -gt 0 ]; then
|
|
267
|
+
session=$1
|
|
268
|
+
append_arg "$1"
|
|
269
|
+
shift
|
|
270
|
+
fi
|
|
271
|
+
continue
|
|
272
|
+
;;
|
|
273
|
+
--session=*)
|
|
274
|
+
session=\${arg#--session=}
|
|
275
|
+
;;
|
|
276
|
+
-*)
|
|
277
|
+
;;
|
|
278
|
+
open|click|type|input|scroll|back|screenshot|state|switch|close-tab|keys|select|upload|eval|extract|hover|dblclick|rightclick|cookies|wait|get|python)
|
|
279
|
+
starts_browser=1
|
|
280
|
+
;;
|
|
281
|
+
close|sessions|install|init|setup|doctor|cloud|profile)
|
|
282
|
+
;;
|
|
283
|
+
esac
|
|
284
|
+
|
|
285
|
+
append_arg "$arg"
|
|
286
|
+
done
|
|
287
|
+
|
|
288
|
+
if [ "$show_help" -eq 1 ]; then
|
|
289
|
+
{
|
|
290
|
+
echo "Pibo browser-use wrapper:"
|
|
291
|
+
echo " New browser-use daemon sessions default to persistent Chrome profile \\"$default_profile\\" via CDP."
|
|
292
|
+
echo " Use $fresh_flag to start a fresh temporary browser profile."
|
|
293
|
+
echo ""
|
|
294
|
+
} >&2
|
|
295
|
+
fi
|
|
296
|
+
|
|
297
|
+
set --
|
|
298
|
+
if [ -n "$sanitized_args" ]; then
|
|
299
|
+
while IFS= read -r item; do
|
|
300
|
+
set -- "$@" "$item"
|
|
301
|
+
done <<EOF
|
|
302
|
+
$sanitized_args
|
|
303
|
+
EOF
|
|
304
|
+
fi
|
|
305
|
+
|
|
306
|
+
session_pid_file=\${BROWSER_USE_HOME:-$HOME/.browser-use}/$session.pid
|
|
307
|
+
session_alive=0
|
|
308
|
+
if [ -s "$session_pid_file" ]; then
|
|
309
|
+
session_pid=$(cat "$session_pid_file" 2>/dev/null || true)
|
|
310
|
+
if [ -n "$session_pid" ] && kill -0 "$session_pid" 2>/dev/null; then
|
|
311
|
+
session_alive=1
|
|
312
|
+
fi
|
|
313
|
+
fi
|
|
314
|
+
|
|
315
|
+
if [ "$starts_browser" -eq 1 ] && [ "$explicit_profile" -eq 0 ] && [ "$fresh_profile" -eq 0 ]; then
|
|
316
|
+
if [ "$session_alive" -eq 1 ] && persistent_chrome_url_if_alive >/dev/null; then
|
|
317
|
+
exec "$real_browser_use" "$@"
|
|
318
|
+
fi
|
|
319
|
+
if [ "$session_alive" -eq 1 ]; then
|
|
320
|
+
"$real_browser_use" --session "$session" close >/dev/null 2>&1 || true
|
|
321
|
+
sleep 0.2
|
|
322
|
+
fi
|
|
323
|
+
cdp_url=$(ensure_persistent_chrome)
|
|
324
|
+
exec "$real_browser_use" --cdp-url "$cdp_url" "$@"
|
|
325
|
+
fi
|
|
326
|
+
|
|
327
|
+
exec "$real_browser_use" "$@"
|
|
328
|
+
`;
|
|
329
|
+
}
|
|
330
|
+
export function ensureBrowserUseWrapper(status) {
|
|
331
|
+
if (status.entry.name !== 'browser-use')
|
|
332
|
+
return undefined;
|
|
333
|
+
const wrapperPath = join(status.homeDir, 'bin', 'browser-use');
|
|
334
|
+
mkdirSync(dirname(wrapperPath), { recursive: true });
|
|
335
|
+
writeFileSync(wrapperPath, createBrowserUseWrapper(status.executablePath));
|
|
336
|
+
chmodSync(wrapperPath, 0o755);
|
|
337
|
+
return wrapperPath;
|
|
338
|
+
}
|