codex-partner 0.0.4__tar.gz → 0.0.6__tar.gz
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.
- {codex_partner-0.0.4 → codex_partner-0.0.6}/PKG-INFO +57 -5
- {codex_partner-0.0.4 → codex_partner-0.0.6}/README.md +53 -4
- {codex_partner-0.0.4 → codex_partner-0.0.6}/app.py +151 -18
- {codex_partner-0.0.4 → codex_partner-0.0.6}/codex_partner/__init__.py +1 -1
- {codex_partner-0.0.4 → codex_partner-0.0.6}/codex_partner/activity_graph.py +2 -1
- {codex_partner-0.0.4 → codex_partner-0.0.6}/codex_partner/app_server.py +4 -1
- {codex_partner-0.0.4 → codex_partner-0.0.6}/codex_partner/database.py +5 -4
- {codex_partner-0.0.4 → codex_partner-0.0.6}/codex_partner/discovery.py +4 -2
- codex_partner-0.0.6/codex_partner/platform_support.py +74 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/codex_partner/ssh_auth.py +6 -1
- {codex_partner-0.0.4 → codex_partner-0.0.6}/codex_partner.egg-info/PKG-INFO +57 -5
- {codex_partner-0.0.4 → codex_partner-0.0.6}/codex_partner.egg-info/SOURCES.txt +2 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/codex_partner.egg-info/requires.txt +3 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/pyproject.toml +4 -1
- codex_partner-0.0.6/tests/test_platform_support.py +62 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/tests/test_running_state.py +53 -28
- {codex_partner-0.0.4 → codex_partner-0.0.6}/codex_partner/__main__.py +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/codex_partner/cli.py +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/codex_partner/commands.py +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/codex_partner/schemas.py +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/codex_partner.egg-info/dependency_links.txt +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/codex_partner.egg-info/entry_points.txt +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/codex_partner.egg-info/top_level.txt +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/setup.cfg +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/__init__.py +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/app.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/chat-worker.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/conversation.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/core.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/default-user-avatar.webp +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/editor.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/exploration-tree.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/history-pagination.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/index.html +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/mascot-dance.css +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/mascot-dance.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/settings.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/styles.css +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/LICENSE +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/ace.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/ext-modelist.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-abap.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-abc.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-actionscript.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-ada.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-alda.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-apache_conf.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-apex.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-applescript.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-aql.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-asciidoc.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-asl.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-assembly_arm32.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-assembly_x86.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-astro.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-autohotkey.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-basic.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-batchfile.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-bibtex.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-c9search.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-c_cpp.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-cedar.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-cedarschema.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-cirru.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-clojure.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-clue.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-cobol.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-coffee.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-coldfusion.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-crystal.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-csharp.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-csound_document.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-csound_orchestra.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-csound_score.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-csp.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-css.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-csv.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-curly.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-cuttlefish.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-d.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-dart.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-diff.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-django.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-dockerfile.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-dot.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-drools.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-edifact.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-eiffel.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-ejs.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-elixir.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-elm.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-erlang.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-flix.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-forth.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-fortran.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-fsharp.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-fsl.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-ftl.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-gcode.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-gherkin.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-gitignore.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-glsl.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-gobstones.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-golang.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-graphqlschema.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-groovy.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-groq.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-haml.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-handlebars.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-haskell.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-haskell_cabal.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-haxe.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-hjson.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-html.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-html_elixir.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-html_ruby.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-ini.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-io.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-ion.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-jack.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-jade.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-java.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-javascript.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-jexl.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-json.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-json5.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-jsoniq.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-jsp.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-jssm.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-jsx.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-julia.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-kotlin.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-latex.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-latte.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-less.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-liquid.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-lisp.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-livescript.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-logiql.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-logtalk.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-lsl.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-lua.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-luapage.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-lucene.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-makefile.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-mariadb.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-markdown.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-mask.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-matlab.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-maze.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-mediawiki.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-mel.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-mips.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-mixal.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-mushcode.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-mysql.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-nasal.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-nginx.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-nim.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-nix.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-nsis.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-nunjucks.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-objectivec.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-ocaml.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-odin.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-partiql.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-pascal.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-perl.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-pgsql.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-php.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-php_laravel_blade.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-pig.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-plain_text.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-plsql.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-powershell.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-praat.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-prisma.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-prolog.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-properties.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-protobuf.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-prql.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-puppet.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-python.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-qml.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-r.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-raku.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-razor.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-rdoc.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-red.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-redshift.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-rhtml.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-robot.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-rst.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-ruby.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-rust.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-sac.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-sass.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-scad.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-scala.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-scheme.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-scrypt.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-scss.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-sh.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-sjs.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-slim.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-smarty.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-smithy.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-snippets.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-soy_template.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-space.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-sparql.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-sql.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-sqlserver.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-stylus.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-svg.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-swift.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-tcl.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-terraform.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-tex.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-text.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-textile.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-toml.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-tsv.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-tsx.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-turtle.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-twig.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-typescript.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-vala.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-vbscript.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-velocity.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-verilog.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-vhdl.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-visualforce.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-vue.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-wollok.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-xml.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-xquery.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-yaml.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-zeek.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/mode-zig.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/ace/theme-tomorrow_night_eighties.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/i18next/LICENSE +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/i18next/i18next.min.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/LICENSE +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_AMS-Regular.ttf +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_AMS-Regular.woff +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_AMS-Regular.woff2 +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Caligraphic-Bold.ttf +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Caligraphic-Bold.woff +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Caligraphic-Regular.ttf +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Caligraphic-Regular.woff +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Fraktur-Bold.ttf +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Fraktur-Bold.woff +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Fraktur-Regular.ttf +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Fraktur-Regular.woff +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Main-Bold.ttf +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Main-Bold.woff +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Main-Bold.woff2 +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Main-BoldItalic.ttf +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Main-BoldItalic.woff +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Main-Italic.ttf +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Main-Italic.woff +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Main-Italic.woff2 +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Main-Regular.ttf +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Main-Regular.woff +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Main-Regular.woff2 +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Math-BoldItalic.ttf +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Math-BoldItalic.woff +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Math-Italic.ttf +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Math-Italic.woff +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Math-Italic.woff2 +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_SansSerif-Bold.ttf +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_SansSerif-Bold.woff +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_SansSerif-Italic.ttf +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_SansSerif-Italic.woff +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_SansSerif-Regular.ttf +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_SansSerif-Regular.woff +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Script-Regular.ttf +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Script-Regular.woff +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Script-Regular.woff2 +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Size1-Regular.ttf +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Size1-Regular.woff +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Size1-Regular.woff2 +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Size2-Regular.ttf +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Size2-Regular.woff +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Size2-Regular.woff2 +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Size3-Regular.ttf +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Size3-Regular.woff +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Size3-Regular.woff2 +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Size4-Regular.ttf +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Size4-Regular.woff +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Size4-Regular.woff2 +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Typewriter-Regular.ttf +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Typewriter-Regular.woff +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/katex.min.css +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/katex/katex.min.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/markdown-it/LICENSE +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/markdown-it/markdown-it.min.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/markdown-it-texmath/LICENSE +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/markdown-it-texmath/texmath.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/toastui-editor/LICENSE +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/toastui-editor/toastui-editor-dark.css +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/toastui-editor/toastui-editor.css +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/toastui-editor/toastui-editor.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/toastui-editor/zh-cn.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/xterm/LICENSE +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/xterm/addons/fit.LICENSE +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/xterm/addons/fit.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/xterm/addons/unicode11.LICENSE +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/xterm/addons/unicode11.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/xterm/addons/web-links.LICENSE +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/xterm/addons/web-links.js +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/xterm/xterm.css +0 -0
- {codex_partner-0.0.4 → codex_partner-0.0.6}/static/vendor/xterm/xterm.js +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codex-partner
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.6
|
|
4
4
|
Summary: A self-hosted web interface for managing persistent Codex tasks.
|
|
5
5
|
Project-URL: Homepage, https://github.com/froststeam/Codex-Partner
|
|
6
6
|
Project-URL: Repository, https://github.com/froststeam/Codex-Partner.git
|
|
@@ -9,6 +9,8 @@ Keywords: codex,agent,task-management,self-hosted
|
|
|
9
9
|
Classifier: Development Status :: 3 - Alpha
|
|
10
10
|
Classifier: Environment :: Web Environment
|
|
11
11
|
Classifier: Framework :: FastAPI
|
|
12
|
+
Classifier: Operating System :: MacOS
|
|
13
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
12
14
|
Classifier: Operating System :: POSIX :: Linux
|
|
13
15
|
Classifier: Programming Language :: Python :: 3
|
|
14
16
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
@@ -20,6 +22,7 @@ Requires-Dist: uvicorn[standard]>=0.27
|
|
|
20
22
|
Requires-Dist: tomli>=2.0; python_version < "3.11"
|
|
21
23
|
Requires-Dist: PyYAML>=6.0
|
|
22
24
|
Requires-Dist: pexpect>=4.8; platform_system != "Windows"
|
|
25
|
+
Requires-Dist: pywinpty>=2.0.13; platform_system == "Windows"
|
|
23
26
|
Requires-Dist: python-dotenv>=1.0
|
|
24
27
|
Requires-Dist: Pillow>=10.0
|
|
25
28
|
|
|
@@ -46,6 +49,18 @@ Codex Partner is a self-hosted control panel for long-running Codex work. It kee
|
|
|
46
49
|
- Codex memories, Skills, archive, recycle bin, and SSH workspace support
|
|
47
50
|
- Default YOLO mode for newly created sessions
|
|
48
51
|
|
|
52
|
+
## Platform support
|
|
53
|
+
|
|
54
|
+
Codex Partner runs natively on Linux, macOS, and Windows with Python 3.10 or newer.
|
|
55
|
+
|
|
56
|
+
| Platform | Codex sessions | Workspace tools | Browser terminal | Background service |
|
|
57
|
+
| --- | --- | --- | --- | --- |
|
|
58
|
+
| Linux | Yes | Yes | POSIX PTY | systemd user service |
|
|
59
|
+
| macOS | Yes | Yes | zsh/bash PTY | Run directly or use launchd |
|
|
60
|
+
| Windows 10/11 | Yes | Yes | PowerShell through ConPTY | Run directly or use Task Scheduler |
|
|
61
|
+
|
|
62
|
+
Windows terminal support uses `pywinpty`, which is installed automatically. Key-based remote SSH works when the OpenSSH client is installed. Browser password prompts for remote SSH are not available on native Windows; configure an SSH key first.
|
|
63
|
+
|
|
49
64
|
## Install
|
|
50
65
|
|
|
51
66
|
Requires Python 3.10+ and an authenticated [Codex CLI](https://github.com/openai/codex).
|
|
@@ -69,12 +84,49 @@ codex-partner
|
|
|
69
84
|
|
|
70
85
|
Open <http://127.0.0.1:8787>.
|
|
71
86
|
|
|
72
|
-
For access from other devices, set `CODEX_DASHBOARD_HOST=0.0.0.0
|
|
87
|
+
Linux keeps SSH browser authentication enabled by default. macOS and Windows default to unauthenticated loopback access because desktop installations normally do not run an SSH server. For access from other devices, set `CODEX_DASHBOARD_HOST=0.0.0.0`, configure `CODEX_DASHBOARD_AUTH=ssh`, and put HTTPS in front of the service. When authentication is handled by a reverse proxy, explicitly set `CODEX_DASHBOARD_AUTH=none`; Codex Partner rejects a non-loopback bind with an implicit unauthenticated default.
|
|
88
|
+
|
|
89
|
+
### macOS
|
|
90
|
+
|
|
91
|
+
Install Python and Node.js with Homebrew if they are not already available, then install and authenticate Codex:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
brew install python node
|
|
95
|
+
npm install --global @openai/codex
|
|
96
|
+
codex login
|
|
97
|
+
python3 -m pip install --user --upgrade codex-partner
|
|
98
|
+
python3 -m codex_partner
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Open <http://127.0.0.1:8787>. Application data defaults to `~/Library/Application Support/CodexPartner`; native Codex state remains in `~/.codex`.
|
|
102
|
+
|
|
103
|
+
### Windows
|
|
104
|
+
|
|
105
|
+
Run these commands in PowerShell. Install Python and Node.js first if they are not already available:
|
|
106
|
+
|
|
107
|
+
```powershell
|
|
108
|
+
winget install --id Python.Python.3.12 -e
|
|
109
|
+
winget install --id OpenJS.NodeJS.LTS -e
|
|
110
|
+
npm install --global @openai/codex
|
|
111
|
+
codex login
|
|
112
|
+
py -m pip install --user --upgrade codex-partner
|
|
113
|
+
py -m codex_partner
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Open <http://127.0.0.1:8787>. Application data defaults to `%LOCALAPPDATA%\CodexPartner`; native Codex state remains in `%USERPROFILE%\.codex`. If `codex` is not found after installing Node.js, close and reopen PowerShell so its `PATH` is refreshed.
|
|
117
|
+
|
|
118
|
+
For local desktop use, keep the default `127.0.0.1` bind address. To set options for one PowerShell session:
|
|
119
|
+
|
|
120
|
+
```powershell
|
|
121
|
+
$env:CODEX_DASHBOARD_PORT = "8787"
|
|
122
|
+
$env:CODEX_DASHBOARD_AUTH = "none"
|
|
123
|
+
py -m codex_partner
|
|
124
|
+
```
|
|
73
125
|
|
|
74
126
|
## Docker
|
|
75
127
|
|
|
76
128
|
```bash
|
|
77
|
-
docker build -t codex-partner:0.0.
|
|
129
|
+
docker build -t codex-partner:0.0.6 .
|
|
78
130
|
docker run -d --name codex-partner \
|
|
79
131
|
-p 8787:8787 \
|
|
80
132
|
--add-host=host.docker.internal:host-gateway \
|
|
@@ -83,11 +135,11 @@ docker run -d --name codex-partner \
|
|
|
83
135
|
-v codex-partner-data:/var/lib/codex-partner \
|
|
84
136
|
-v codex-home:/home/codex/.codex \
|
|
85
137
|
-v codex-workspace:/workspace \
|
|
86
|
-
codex-partner:0.0.
|
|
138
|
+
codex-partner:0.0.6
|
|
87
139
|
docker exec -it codex-partner codex login
|
|
88
140
|
```
|
|
89
141
|
|
|
90
|
-
## systemd
|
|
142
|
+
## Linux systemd
|
|
91
143
|
|
|
92
144
|
After completing the source installation above, stop the foreground process and install the user service:
|
|
93
145
|
|
|
@@ -21,6 +21,18 @@ Codex Partner is a self-hosted control panel for long-running Codex work. It kee
|
|
|
21
21
|
- Codex memories, Skills, archive, recycle bin, and SSH workspace support
|
|
22
22
|
- Default YOLO mode for newly created sessions
|
|
23
23
|
|
|
24
|
+
## Platform support
|
|
25
|
+
|
|
26
|
+
Codex Partner runs natively on Linux, macOS, and Windows with Python 3.10 or newer.
|
|
27
|
+
|
|
28
|
+
| Platform | Codex sessions | Workspace tools | Browser terminal | Background service |
|
|
29
|
+
| --- | --- | --- | --- | --- |
|
|
30
|
+
| Linux | Yes | Yes | POSIX PTY | systemd user service |
|
|
31
|
+
| macOS | Yes | Yes | zsh/bash PTY | Run directly or use launchd |
|
|
32
|
+
| Windows 10/11 | Yes | Yes | PowerShell through ConPTY | Run directly or use Task Scheduler |
|
|
33
|
+
|
|
34
|
+
Windows terminal support uses `pywinpty`, which is installed automatically. Key-based remote SSH works when the OpenSSH client is installed. Browser password prompts for remote SSH are not available on native Windows; configure an SSH key first.
|
|
35
|
+
|
|
24
36
|
## Install
|
|
25
37
|
|
|
26
38
|
Requires Python 3.10+ and an authenticated [Codex CLI](https://github.com/openai/codex).
|
|
@@ -44,12 +56,49 @@ codex-partner
|
|
|
44
56
|
|
|
45
57
|
Open <http://127.0.0.1:8787>.
|
|
46
58
|
|
|
47
|
-
For access from other devices, set `CODEX_DASHBOARD_HOST=0.0.0.0
|
|
59
|
+
Linux keeps SSH browser authentication enabled by default. macOS and Windows default to unauthenticated loopback access because desktop installations normally do not run an SSH server. For access from other devices, set `CODEX_DASHBOARD_HOST=0.0.0.0`, configure `CODEX_DASHBOARD_AUTH=ssh`, and put HTTPS in front of the service. When authentication is handled by a reverse proxy, explicitly set `CODEX_DASHBOARD_AUTH=none`; Codex Partner rejects a non-loopback bind with an implicit unauthenticated default.
|
|
60
|
+
|
|
61
|
+
### macOS
|
|
62
|
+
|
|
63
|
+
Install Python and Node.js with Homebrew if they are not already available, then install and authenticate Codex:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
brew install python node
|
|
67
|
+
npm install --global @openai/codex
|
|
68
|
+
codex login
|
|
69
|
+
python3 -m pip install --user --upgrade codex-partner
|
|
70
|
+
python3 -m codex_partner
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Open <http://127.0.0.1:8787>. Application data defaults to `~/Library/Application Support/CodexPartner`; native Codex state remains in `~/.codex`.
|
|
74
|
+
|
|
75
|
+
### Windows
|
|
76
|
+
|
|
77
|
+
Run these commands in PowerShell. Install Python and Node.js first if they are not already available:
|
|
78
|
+
|
|
79
|
+
```powershell
|
|
80
|
+
winget install --id Python.Python.3.12 -e
|
|
81
|
+
winget install --id OpenJS.NodeJS.LTS -e
|
|
82
|
+
npm install --global @openai/codex
|
|
83
|
+
codex login
|
|
84
|
+
py -m pip install --user --upgrade codex-partner
|
|
85
|
+
py -m codex_partner
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Open <http://127.0.0.1:8787>. Application data defaults to `%LOCALAPPDATA%\CodexPartner`; native Codex state remains in `%USERPROFILE%\.codex`. If `codex` is not found after installing Node.js, close and reopen PowerShell so its `PATH` is refreshed.
|
|
89
|
+
|
|
90
|
+
For local desktop use, keep the default `127.0.0.1` bind address. To set options for one PowerShell session:
|
|
91
|
+
|
|
92
|
+
```powershell
|
|
93
|
+
$env:CODEX_DASHBOARD_PORT = "8787"
|
|
94
|
+
$env:CODEX_DASHBOARD_AUTH = "none"
|
|
95
|
+
py -m codex_partner
|
|
96
|
+
```
|
|
48
97
|
|
|
49
98
|
## Docker
|
|
50
99
|
|
|
51
100
|
```bash
|
|
52
|
-
docker build -t codex-partner:0.0.
|
|
101
|
+
docker build -t codex-partner:0.0.6 .
|
|
53
102
|
docker run -d --name codex-partner \
|
|
54
103
|
-p 8787:8787 \
|
|
55
104
|
--add-host=host.docker.internal:host-gateway \
|
|
@@ -58,11 +107,11 @@ docker run -d --name codex-partner \
|
|
|
58
107
|
-v codex-partner-data:/var/lib/codex-partner \
|
|
59
108
|
-v codex-home:/home/codex/.codex \
|
|
60
109
|
-v codex-workspace:/workspace \
|
|
61
|
-
codex-partner:0.0.
|
|
110
|
+
codex-partner:0.0.6
|
|
62
111
|
docker exec -it codex-partner codex login
|
|
63
112
|
```
|
|
64
113
|
|
|
65
|
-
## systemd
|
|
114
|
+
## Linux systemd
|
|
66
115
|
|
|
67
116
|
After completing the source installation above, stop the foreground process and install the user service:
|
|
68
117
|
|
|
@@ -7,7 +7,6 @@ import binascii
|
|
|
7
7
|
import codecs
|
|
8
8
|
import errno
|
|
9
9
|
import getpass
|
|
10
|
-
import fcntl
|
|
11
10
|
import glob
|
|
12
11
|
import hashlib
|
|
13
12
|
import io
|
|
@@ -16,7 +15,6 @@ import json
|
|
|
16
15
|
import mimetypes
|
|
17
16
|
import os
|
|
18
17
|
import posixpath
|
|
19
|
-
import pty
|
|
20
18
|
import platform
|
|
21
19
|
import re
|
|
22
20
|
import signal
|
|
@@ -27,7 +25,6 @@ import sqlite3
|
|
|
27
25
|
import socket
|
|
28
26
|
import struct
|
|
29
27
|
import subprocess
|
|
30
|
-
import termios
|
|
31
28
|
import time
|
|
32
29
|
import uuid
|
|
33
30
|
import urllib.error
|
|
@@ -43,7 +40,20 @@ from fastapi.responses import FileResponse, JSONResponse, StreamingResponse
|
|
|
43
40
|
from starlette.middleware.gzip import GZipMiddleware
|
|
44
41
|
from dotenv import load_dotenv
|
|
45
42
|
import yaml
|
|
46
|
-
|
|
43
|
+
try:
|
|
44
|
+
import fcntl
|
|
45
|
+
import pty
|
|
46
|
+
import termios
|
|
47
|
+
except ImportError: # Native Windows has no POSIX PTY APIs.
|
|
48
|
+
fcntl = pty = termios = None
|
|
49
|
+
try:
|
|
50
|
+
import pexpect
|
|
51
|
+
except ImportError: # Password-driven SSH prompts are optional on Windows.
|
|
52
|
+
pexpect = None
|
|
53
|
+
try:
|
|
54
|
+
from winpty import PtyProcess as WindowsPtyProcess
|
|
55
|
+
except ImportError: # Installed through the Windows-only pywinpty dependency.
|
|
56
|
+
WindowsPtyProcess = None
|
|
47
57
|
from PIL import Image, ImageOps, ImageSequence, UnidentifiedImageError
|
|
48
58
|
|
|
49
59
|
from codex_partner import APP_NAME, APP_VERSION
|
|
@@ -59,6 +69,14 @@ from codex_partner.discovery import (
|
|
|
59
69
|
official_candidates,
|
|
60
70
|
vscode_candidates,
|
|
61
71
|
)
|
|
72
|
+
from codex_partner.platform_support import (
|
|
73
|
+
IS_WINDOWS,
|
|
74
|
+
default_auth_mode,
|
|
75
|
+
default_data_dir,
|
|
76
|
+
local_shell_command,
|
|
77
|
+
prepare_subprocess_command,
|
|
78
|
+
validate_bind_auth,
|
|
79
|
+
)
|
|
62
80
|
from codex_partner.schemas import (
|
|
63
81
|
ApprovalResolveIn,
|
|
64
82
|
AvatarIn,
|
|
@@ -91,12 +109,12 @@ except ModuleNotFoundError: # Python 3.10
|
|
|
91
109
|
ROOT = Path(__file__).resolve().parent
|
|
92
110
|
load_dotenv(ROOT / ".env", override=False)
|
|
93
111
|
STATIC = ROOT / "static"
|
|
94
|
-
DATA_DIR =
|
|
112
|
+
DATA_DIR = default_data_dir(ROOT)
|
|
95
113
|
DATA_DIR.mkdir(parents=True, exist_ok=True)
|
|
96
114
|
DB_PATH = DATA_DIR / "dashboard.sqlite3"
|
|
97
115
|
CODEX_HOME = Path(os.getenv("CODEX_HOME", str(Path.home() / ".codex"))).expanduser().resolve()
|
|
98
116
|
CODEX_MEMORY_DIR = CODEX_HOME / "memories"
|
|
99
|
-
AUTH_MODE = os.getenv("CODEX_DASHBOARD_AUTH",
|
|
117
|
+
AUTH_MODE = os.getenv("CODEX_DASHBOARD_AUTH", default_auth_mode()).strip().lower()
|
|
100
118
|
if AUTH_MODE not in {"ssh", "none"}:
|
|
101
119
|
raise RuntimeError("CODEX_DASHBOARD_AUTH must be 'ssh' or 'none'")
|
|
102
120
|
AUTH_COOKIE = "codex_partner_session"
|
|
@@ -128,6 +146,7 @@ def configured_port(name: str, default: int) -> int:
|
|
|
128
146
|
|
|
129
147
|
|
|
130
148
|
DASHBOARD_HOST = os.getenv("CODEX_DASHBOARD_HOST", "127.0.0.1").strip() or "127.0.0.1"
|
|
149
|
+
validate_bind_auth(DASHBOARD_HOST, AUTH_MODE, "CODEX_DASHBOARD_AUTH" in os.environ)
|
|
131
150
|
DASHBOARD_PORT = configured_port("CODEX_DASHBOARD_PORT", 8787)
|
|
132
151
|
AUTH_SSH_PORT = configured_port("CODEX_DASHBOARD_AUTH_SSH_PORT", 22)
|
|
133
152
|
SSH_BIN = shutil.which("ssh") or "ssh"
|
|
@@ -135,7 +154,12 @@ SSH_CONFIG = Path.home() / ".ssh/config"
|
|
|
135
154
|
SSH_FIXED_HOST = os.getenv("CODEX_DASHBOARD_SSH_HOST", "").strip()
|
|
136
155
|
SSH_FIXED_USER = os.getenv("CODEX_DASHBOARD_SSH_USER", "").strip()
|
|
137
156
|
SSH_FIXED_PORT = configured_port("CODEX_DASHBOARD_SSH_PORT", 22)
|
|
138
|
-
|
|
157
|
+
if os.getenv("XDG_RUNTIME_DIR"):
|
|
158
|
+
SSH_RUNTIME_DIR = Path(os.environ["XDG_RUNTIME_DIR"]) / "codex-dashboard-ssh"
|
|
159
|
+
elif hasattr(os, "getuid") and platform.system() == "Linux":
|
|
160
|
+
SSH_RUNTIME_DIR = Path(f"/run/user/{os.getuid()}") / "codex-dashboard-ssh"
|
|
161
|
+
else:
|
|
162
|
+
SSH_RUNTIME_DIR = DATA_DIR / "ssh-runtime"
|
|
139
163
|
try:
|
|
140
164
|
SSH_RUNTIME_DIR.mkdir(parents=True, exist_ok=True, mode=0o700)
|
|
141
165
|
SSH_RUNTIME_DIR.chmod(0o700)
|
|
@@ -207,7 +231,7 @@ def codex_management_snapshot() -> dict[str, Any]:
|
|
|
207
231
|
if CODEX_AVAILABLE:
|
|
208
232
|
try:
|
|
209
233
|
result = subprocess.run(
|
|
210
|
-
[CODEX_BIN, "--version"],
|
|
234
|
+
prepare_subprocess_command([CODEX_BIN, "--version"]),
|
|
211
235
|
stdin=subprocess.DEVNULL,
|
|
212
236
|
stdout=subprocess.PIPE,
|
|
213
237
|
stderr=subprocess.STDOUT,
|
|
@@ -1154,8 +1178,23 @@ def rollout_writer_pids(path: str, refresh: bool = False) -> set[int]:
|
|
|
1154
1178
|
try:
|
|
1155
1179
|
processes = os.scandir("/proc")
|
|
1156
1180
|
except OSError:
|
|
1181
|
+
lsof = shutil.which("lsof")
|
|
1182
|
+
if lsof:
|
|
1183
|
+
try:
|
|
1184
|
+
result = subprocess.run(
|
|
1185
|
+
[lsof, "-t", "--", target],
|
|
1186
|
+
capture_output=True,
|
|
1187
|
+
text=True,
|
|
1188
|
+
encoding="utf-8",
|
|
1189
|
+
errors="replace",
|
|
1190
|
+
timeout=2,
|
|
1191
|
+
check=False,
|
|
1192
|
+
)
|
|
1193
|
+
writers = {int(value) for value in result.stdout.splitlines() if value.isdigit()}
|
|
1194
|
+
except (OSError, subprocess.SubprocessError, ValueError):
|
|
1195
|
+
pass
|
|
1157
1196
|
rollout_writer_cache[target] = (stamp, writers)
|
|
1158
|
-
return writers
|
|
1197
|
+
return set(writers)
|
|
1159
1198
|
with processes:
|
|
1160
1199
|
for process in processes:
|
|
1161
1200
|
if not process.name.isdigit():
|
|
@@ -1826,7 +1865,7 @@ def ssh_config_aliases(path: Path = SSH_CONFIG, seen: Optional[set[Path]] = None
|
|
|
1826
1865
|
return []
|
|
1827
1866
|
for line in lines:
|
|
1828
1867
|
try:
|
|
1829
|
-
parts = shlex.split(line, comments=True, posix=
|
|
1868
|
+
parts = shlex.split(line, comments=True, posix=not IS_WINDOWS)
|
|
1830
1869
|
except ValueError:
|
|
1831
1870
|
continue
|
|
1832
1871
|
if not parts:
|
|
@@ -1995,6 +2034,8 @@ exit 1
|
|
|
1995
2034
|
|
|
1996
2035
|
|
|
1997
2036
|
def password_ssh_connect(host: str, password: str) -> tuple[bool, str]:
|
|
2037
|
+
if pexpect is None:
|
|
2038
|
+
return False, "SSH password authentication is unavailable on this platform"
|
|
1998
2039
|
args = [
|
|
1999
2040
|
*ssh_options(host, batch=False),
|
|
2000
2041
|
"-o", "ConnectTimeout=10",
|
|
@@ -3613,7 +3654,7 @@ def appserver_turn_inputs(task: dict, message: str) -> list[dict[str, Any]]:
|
|
|
3613
3654
|
continue
|
|
3614
3655
|
seen.add((kind, path))
|
|
3615
3656
|
if kind == "mention":
|
|
3616
|
-
inputs.append({"type": "mention", "name":
|
|
3657
|
+
inputs.append({"type": "mention", "name": Path(path).name, "path": path})
|
|
3617
3658
|
else:
|
|
3618
3659
|
item: dict[str, Any] = {"type": kind, "path": path}
|
|
3619
3660
|
if kind == "localImage":
|
|
@@ -3867,6 +3908,13 @@ async def close_terminal_session(terminal_id: str) -> None:
|
|
|
3867
3908
|
if not session:
|
|
3868
3909
|
return
|
|
3869
3910
|
session["closed"] = True
|
|
3911
|
+
windows_pty = session.get("windows_pty")
|
|
3912
|
+
if windows_pty is not None:
|
|
3913
|
+
try:
|
|
3914
|
+
await asyncio.to_thread(lambda: windows_pty.close(force=True))
|
|
3915
|
+
except Exception:
|
|
3916
|
+
pass
|
|
3917
|
+
return
|
|
3870
3918
|
fd, pid = session.get("fd"), session.get("pid")
|
|
3871
3919
|
loop = session.get("loop")
|
|
3872
3920
|
if loop and fd is not None:
|
|
@@ -3905,6 +3953,81 @@ def set_terminal_size(fd: int, cols: int, rows: int) -> None:
|
|
|
3905
3953
|
fcntl.ioctl(fd, termios.TIOCSWINSZ, struct.pack("HHHH", rows, cols, 0, 0))
|
|
3906
3954
|
|
|
3907
3955
|
|
|
3956
|
+
async def windows_terminal_socket(websocket: WebSocket, task_id: str, cwd: str, ssh_host: str) -> None:
|
|
3957
|
+
if WindowsPtyProcess is None:
|
|
3958
|
+
await websocket.send_json({"type": "error", "message": "Windows terminal support requires pywinpty"})
|
|
3959
|
+
await websocket.close(code=1011)
|
|
3960
|
+
return
|
|
3961
|
+
env = os.environ.copy()
|
|
3962
|
+
env.update({"TERM": "xterm-256color", "COLORTERM": "truecolor"})
|
|
3963
|
+
if ssh_host:
|
|
3964
|
+
remote_command = f"cd -- {shlex.quote(cwd)} && exec \"${{SHELL:-/bin/sh}}\" -il"
|
|
3965
|
+
command = [*ssh_options(ssh_host, batch=True, tty=True), ssh_destination(ssh_host), remote_command]
|
|
3966
|
+
shell_label = f"ssh:{ssh_host}"
|
|
3967
|
+
else:
|
|
3968
|
+
command, shell_label = local_shell_command()
|
|
3969
|
+
try:
|
|
3970
|
+
spawn_cwd = cwd if not ssh_host else str(DEFAULT_WORKSPACE)
|
|
3971
|
+
process = await asyncio.to_thread(WindowsPtyProcess.spawn, command, cwd=spawn_cwd, env=env)
|
|
3972
|
+
except Exception as exc:
|
|
3973
|
+
await websocket.send_json({"type": "error", "message": f"terminal start failed: {exc}"})
|
|
3974
|
+
await websocket.close(code=1011)
|
|
3975
|
+
return
|
|
3976
|
+
|
|
3977
|
+
terminal_id = str(uuid.uuid4())
|
|
3978
|
+
session = {"windows_pty": process, "task_id": task_id, "closed": False}
|
|
3979
|
+
terminal_sessions[terminal_id] = session
|
|
3980
|
+
await websocket.send_json({"type": "ready", "terminal_id": terminal_id, "cwd": cwd, "shell": shell_label})
|
|
3981
|
+
|
|
3982
|
+
async def pump_output() -> None:
|
|
3983
|
+
while not session["closed"]:
|
|
3984
|
+
try:
|
|
3985
|
+
data = await asyncio.to_thread(process.read, 65536)
|
|
3986
|
+
except (EOFError, OSError):
|
|
3987
|
+
data = ""
|
|
3988
|
+
if data:
|
|
3989
|
+
await websocket.send_json({"type": "output", "data": data})
|
|
3990
|
+
continue
|
|
3991
|
+
await websocket.send_json({"type": "exit", "code": getattr(process, "exitstatus", None)})
|
|
3992
|
+
return
|
|
3993
|
+
|
|
3994
|
+
async def receive_input() -> None:
|
|
3995
|
+
while True:
|
|
3996
|
+
incoming = await websocket.receive_json()
|
|
3997
|
+
kind = incoming.get("type")
|
|
3998
|
+
if kind == "input":
|
|
3999
|
+
value = incoming.get("data", incoming.get("input", ""))
|
|
4000
|
+
if isinstance(value, str) and value:
|
|
4001
|
+
await asyncio.to_thread(process.write, value)
|
|
4002
|
+
elif kind == "resize":
|
|
4003
|
+
try:
|
|
4004
|
+
cols = max(20, min(int(incoming.get("cols", 120)), 400))
|
|
4005
|
+
rows = max(4, min(int(incoming.get("rows", 32)), 160))
|
|
4006
|
+
await asyncio.to_thread(process.setwinsize, rows, cols)
|
|
4007
|
+
except (OSError, ValueError, TypeError):
|
|
4008
|
+
continue
|
|
4009
|
+
elif kind == "ping":
|
|
4010
|
+
await websocket.send_json({"type": "pong"})
|
|
4011
|
+
elif kind == "close":
|
|
4012
|
+
return
|
|
4013
|
+
|
|
4014
|
+
pump_task = asyncio.create_task(pump_output())
|
|
4015
|
+
receive_task = asyncio.create_task(receive_input())
|
|
4016
|
+
try:
|
|
4017
|
+
_done, pending = await asyncio.wait({pump_task, receive_task}, return_when=asyncio.FIRST_COMPLETED)
|
|
4018
|
+
for waiter in pending:
|
|
4019
|
+
waiter.cancel()
|
|
4020
|
+
await asyncio.gather(*pending, return_exceptions=True)
|
|
4021
|
+
except WebSocketDisconnect:
|
|
4022
|
+
pass
|
|
4023
|
+
finally:
|
|
4024
|
+
for waiter in (pump_task, receive_task):
|
|
4025
|
+
if not waiter.done():
|
|
4026
|
+
waiter.cancel()
|
|
4027
|
+
await asyncio.gather(pump_task, receive_task, return_exceptions=True)
|
|
4028
|
+
await close_terminal_session(terminal_id)
|
|
4029
|
+
|
|
4030
|
+
|
|
3908
4031
|
@app.websocket("/ws/terminal/{task_id}")
|
|
3909
4032
|
async def terminal_socket(websocket: WebSocket, task_id: str):
|
|
3910
4033
|
if not websocket_auth_session(websocket):
|
|
@@ -3921,11 +4044,17 @@ async def terminal_socket(websocket: WebSocket, task_id: str):
|
|
|
3921
4044
|
await websocket.close(code=4428, reason="SSH login required")
|
|
3922
4045
|
return
|
|
3923
4046
|
await websocket.accept()
|
|
3924
|
-
terminal_id = str(uuid.uuid4())
|
|
3925
4047
|
cwd = task["workspace"] if ssh_host else (task["workspace"] if Path(task["workspace"]).is_dir() else str(DEFAULT_WORKSPACE))
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
4048
|
+
if IS_WINDOWS:
|
|
4049
|
+
await windows_terminal_socket(websocket, task_id, cwd, ssh_host)
|
|
4050
|
+
return
|
|
4051
|
+
terminal_id = str(uuid.uuid4())
|
|
4052
|
+
shell_command, local_shell = local_shell_command()
|
|
4053
|
+
shell = f"ssh:{ssh_host}" if ssh_host else local_shell
|
|
4054
|
+
if pty is None or fcntl is None or termios is None:
|
|
4055
|
+
await websocket.send_json({"type": "error", "message": "PTY support is unavailable on this platform"})
|
|
4056
|
+
await websocket.close(code=1011)
|
|
4057
|
+
return
|
|
3929
4058
|
pid, fd = pty.fork()
|
|
3930
4059
|
if pid == 0:
|
|
3931
4060
|
try:
|
|
@@ -3937,7 +4066,7 @@ async def terminal_socket(websocket: WebSocket, task_id: str):
|
|
|
3937
4066
|
os.execvpe(command[0], command, env)
|
|
3938
4067
|
else:
|
|
3939
4068
|
os.chdir(cwd)
|
|
3940
|
-
os.execvpe(
|
|
4069
|
+
os.execvpe(shell_command[0], shell_command, env)
|
|
3941
4070
|
except Exception as exc:
|
|
3942
4071
|
os.write(2, f"terminal start failed: {exc}\n".encode())
|
|
3943
4072
|
os._exit(127)
|
|
@@ -4473,7 +4602,7 @@ async def install_codex(force: bool = False, _: Any = Depends(auth)):
|
|
|
4473
4602
|
env["PATH"] = os.pathsep.join((str(Path(npm).parent), str(extra_bin), env.get("PATH", "")))
|
|
4474
4603
|
try:
|
|
4475
4604
|
process = await asyncio.create_subprocess_exec(
|
|
4476
|
-
*command,
|
|
4605
|
+
*prepare_subprocess_command(command),
|
|
4477
4606
|
stdout=asyncio.subprocess.PIPE,
|
|
4478
4607
|
stderr=asyncio.subprocess.STDOUT,
|
|
4479
4608
|
env=env,
|
|
@@ -5655,6 +5784,8 @@ async def supervise(task: dict, session_id: str, providers: list[Optional[dict]]
|
|
|
5655
5784
|
cwd = None
|
|
5656
5785
|
env.pop("OPENAI_API_KEY", None)
|
|
5657
5786
|
env.pop("OPENAI_BASE_URL", None)
|
|
5787
|
+
else:
|
|
5788
|
+
spawn_cmd = prepare_subprocess_command(spawn_cmd)
|
|
5658
5789
|
process = await asyncio.create_subprocess_exec(*spawn_cmd, cwd=cwd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.STDOUT, env=env)
|
|
5659
5790
|
async with running_lock:
|
|
5660
5791
|
running[task_id] = process
|
|
@@ -6249,7 +6380,7 @@ def git_diff_summary(task: dict) -> str:
|
|
|
6249
6380
|
sections = []
|
|
6250
6381
|
for index, command in enumerate(commands):
|
|
6251
6382
|
try:
|
|
6252
|
-
completed = ssh_capture(task["ssh_host"], shlex.join(command), 12) if task.get("ssh_host") else subprocess.run(command, capture_output=True, text=True, timeout=8, check=False)
|
|
6383
|
+
completed = ssh_capture(task["ssh_host"], shlex.join(command), 12) if task.get("ssh_host") else subprocess.run(prepare_subprocess_command(command), capture_output=True, text=True, timeout=8, check=False)
|
|
6253
6384
|
except (OSError, subprocess.TimeoutExpired) as exc:
|
|
6254
6385
|
return f"无法读取 Git 变更:{exc}"
|
|
6255
6386
|
output = (completed.stdout or completed.stderr).strip()
|
|
@@ -6805,6 +6936,8 @@ async def supervise_operation(task: dict, session_id: str, cmd: list[str]) -> No
|
|
|
6805
6936
|
connection = await require_ssh_connection(task["ssh_host"], codex=True)
|
|
6806
6937
|
spawn_cmd = [*ssh_options(task["ssh_host"], batch=True), ssh_destination(task["ssh_host"]), shlex.join([connection["codex_bin"], *cmd[1:]])]
|
|
6807
6938
|
cwd = None
|
|
6939
|
+
else:
|
|
6940
|
+
spawn_cmd = prepare_subprocess_command(spawn_cmd)
|
|
6808
6941
|
process = await asyncio.create_subprocess_exec(*spawn_cmd, cwd=cwd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.STDOUT, env=os.environ.copy())
|
|
6809
6942
|
async with running_lock:
|
|
6810
6943
|
running[task_id] = process
|
|
@@ -132,7 +132,8 @@ def event_key(event: dict[str, Any]) -> str:
|
|
|
132
132
|
for key in ("type", "turn_id", "turnId", "item_id", "id", "status", "phase")
|
|
133
133
|
)
|
|
134
134
|
body = payload.get("text") or payload.get("command") or payload.get("tool") or ""
|
|
135
|
-
|
|
135
|
+
source = f"{event.get('ts', '')}:{identity}:{body}"
|
|
136
|
+
return f"live:{fingerprint(source)}"
|
|
136
137
|
|
|
137
138
|
|
|
138
139
|
def semantic_event(event: dict[str, Any]) -> bool:
|
|
@@ -4,6 +4,8 @@ import asyncio
|
|
|
4
4
|
import json
|
|
5
5
|
from typing import Any, Awaitable, Callable, Optional
|
|
6
6
|
|
|
7
|
+
from .platform_support import prepare_subprocess_command
|
|
8
|
+
|
|
7
9
|
|
|
8
10
|
NotificationHandler = Callable[[str, dict], Awaitable[None]]
|
|
9
11
|
|
|
@@ -55,8 +57,9 @@ class AppServerClient:
|
|
|
55
57
|
await asyncio.wait_for(self.process.wait(), 1)
|
|
56
58
|
except Exception:
|
|
57
59
|
pass
|
|
60
|
+
command = prepare_subprocess_command(self.command)
|
|
58
61
|
self.process = await asyncio.create_subprocess_exec(
|
|
59
|
-
*
|
|
62
|
+
*command,
|
|
60
63
|
stdin=asyncio.subprocess.PIPE,
|
|
61
64
|
stdout=asyncio.subprocess.PIPE,
|
|
62
65
|
stderr=asyncio.subprocess.DEVNULL,
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import sqlite3
|
|
4
4
|
import threading
|
|
5
|
+
from contextlib import closing
|
|
5
6
|
from pathlib import Path
|
|
6
7
|
from typing import Callable, Optional
|
|
7
8
|
|
|
@@ -27,7 +28,7 @@ class Database:
|
|
|
27
28
|
return connection
|
|
28
29
|
|
|
29
30
|
def initialize(self) -> None:
|
|
30
|
-
with self.lock, self.connect() as connection:
|
|
31
|
+
with self.lock, closing(self.connect()) as connection:
|
|
31
32
|
connection.executescript(
|
|
32
33
|
"""
|
|
33
34
|
CREATE TABLE IF NOT EXISTS tasks (
|
|
@@ -262,15 +263,15 @@ class Database:
|
|
|
262
263
|
)
|
|
263
264
|
|
|
264
265
|
def one(self, sql: str, args: tuple = ()) -> Optional[dict]:
|
|
265
|
-
with self.lock, self.connect() as connection:
|
|
266
|
+
with self.lock, closing(self.connect()) as connection:
|
|
266
267
|
row = connection.execute(sql, args).fetchone()
|
|
267
268
|
return dict(row) if row else None
|
|
268
269
|
|
|
269
270
|
def all(self, sql: str, args: tuple = ()) -> list[dict]:
|
|
270
|
-
with self.lock, self.connect() as connection:
|
|
271
|
+
with self.lock, closing(self.connect()) as connection:
|
|
271
272
|
return [dict(row) for row in connection.execute(sql, args).fetchall()]
|
|
272
273
|
|
|
273
274
|
def execute(self, sql: str, args: tuple = ()) -> None:
|
|
274
|
-
with self.lock, self.connect() as connection:
|
|
275
|
+
with self.lock, closing(self.connect()) as connection:
|
|
275
276
|
connection.execute(sql, args)
|
|
276
277
|
connection.commit()
|
|
@@ -8,6 +8,8 @@ import subprocess
|
|
|
8
8
|
from pathlib import Path
|
|
9
9
|
from typing import Callable, Optional
|
|
10
10
|
|
|
11
|
+
from .platform_support import prepare_subprocess_command
|
|
12
|
+
|
|
11
13
|
|
|
12
14
|
def executable_works(candidate: str) -> bool:
|
|
13
15
|
path = Path(candidate).expanduser()
|
|
@@ -15,7 +17,7 @@ def executable_works(candidate: str) -> bool:
|
|
|
15
17
|
return False
|
|
16
18
|
try:
|
|
17
19
|
result = subprocess.run(
|
|
18
|
-
[str(path), "--version"],
|
|
20
|
+
prepare_subprocess_command([str(path), "--version"]),
|
|
19
21
|
stdin=subprocess.DEVNULL,
|
|
20
22
|
stdout=subprocess.DEVNULL,
|
|
21
23
|
stderr=subprocess.DEVNULL,
|
|
@@ -122,7 +124,7 @@ def install_plan(system: str, npm: str, package: str) -> dict:
|
|
|
122
124
|
if not supported:
|
|
123
125
|
reason = f"暂不支持在 {system} 上自动安装 Codex"
|
|
124
126
|
elif not npm:
|
|
125
|
-
reason = "未找到 npm;请先安装 Node.js LTS
|
|
127
|
+
reason = "未找到 npm;请先安装 Node.js LTS,然后重试"
|
|
126
128
|
else:
|
|
127
129
|
reason = ""
|
|
128
130
|
display = subprocess.list2cmdline(command) if os.name == "nt" else shlex.join(command)
|