painapple-code 1.1.2__tar.gz → 1.1.3__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.
- {painapple_code-1.1.2 → painapple_code-1.1.3}/CHANGELOG.md +8 -0
- {painapple_code-1.1.2/src/painapple_code.egg-info → painapple_code-1.1.3}/PKG-INFO +1 -1
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/getting-started/security.md +1 -1
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/guides/permissions-and-thinking.md +1 -1
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/guides/providers.md +1 -1
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/_version.py +3 -3
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/providers/codex_app_server/__init__.py +1 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/providers/codex_app_server/launch.py +14 -2
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/providers/codex_app_server/transport.py +97 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/services/agent_session.py +17 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/dist/app.bundle.js +4 -2
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/command-executor.js +17 -3
- {painapple_code-1.1.2 → painapple_code-1.1.3/src/painapple_code.egg-info}/PKG-INFO +1 -1
- painapple_code-1.1.3/src/painapple_code.egg-info/scm_version.json +8 -0
- painapple_code-1.1.2/src/painapple_code.egg-info/scm_version.json +0 -8
- {painapple_code-1.1.2 → painapple_code-1.1.3}/.devcontainer/devcontainer.json +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/.dockerignore +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/.gitignore +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/CONTRIBUTING.md +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/Dockerfile +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/LICENSE +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/MANIFEST.in +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/README.dockerhub.md +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/README.md +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/SECURITY.md +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/THIRD_PARTY_NOTICES.md +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/build-frontend.sh +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docker-compose.yml +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docker-entrypoint.sh +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/assets/annotate-editor.png +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/assets/browser-widget.png +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/assets/comments-stash.gif +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/assets/cost-analytics.png +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/assets/favicon.png +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/assets/input-autocomplete.gif +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/assets/logo.png +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/assets/markdown-quick-edit.gif +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/assets/overview.png +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/assets/prompt-history.png +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/assets/quick-switcher.gif +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/assets/quick-switcher.png +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/assets/settings-appearance.png +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/assets/settings-claude.png +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/assets/shadow-journal.png +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/assets/snippets-picker.png +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/assets/terminal.gif +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/assets/turn-summary-bar-expanded.png +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/assets/turn-summary-bar.png +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/assets/welcome-screen.png +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/assets/zen-mode.png +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/changelog.md +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/features.md +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/getting-started/first-run.md +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/getting-started/install-devcontainer.md +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/getting-started/install-docker.md +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/getting-started/install-pip.md +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/getting-started/requirements.md +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/guides/analytics-and-history.md +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/guides/claude-artifacts.md +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/guides/customization.md +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/guides/files.md +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/guides/git-and-diffs.md +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/guides/images-and-annotation.md +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/guides/input-and-commands.md +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/guides/ipad-and-mobile.md +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/guides/sessions.md +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/guides/shadow-git.md +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/guides/stash-and-discussions.md +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/guides/terminal.md +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/guides/welcome-screen.md +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/guides/zen-mode.md +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/index.md +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/reference/api.md +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/reference/commands.md +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/reference/data-storage.md +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/reference/keyboard-shortcuts.md +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/reference/optional-helpers.md +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/reference/profiles.md +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/reference/server-cli.md +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/mkdocs.yml +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/painapple-docker.sh +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/pyproject.toml +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/requirements-docs.txt +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/requirements.txt +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/setup.cfg +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/setup.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/__init__.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/__main__.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/auth_middleware.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/cli/__init__.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/cli/deploy/__init__.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/cli/deploy/claude_seed.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/cli/deploy/config.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/cli/deploy/container.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/cli/deploy/launch.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/cli/deploy/runtime.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/cli/lifecycle_cmd.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/cli/list_cmd.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/cli/manage_cmd.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/cli/netinfo.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/cli/profiles.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/cli/serve_args.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/cli/serve_config.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/cli/setup_cmd.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/cli/ui.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/cost_analytics.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/data/models.defaults.yaml +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/data/models.yaml +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/data/presets.defaults.json +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/data/strings.yaml +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/helpers.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/paths.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/prompt_explorer.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/providers/__init__.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/providers/base.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/providers/claude/__init__.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/providers/claude/capabilities.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/providers/claude/errors.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/providers/claude/launch.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/providers/claude/summary.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/providers/claude/translate.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/providers/claude_sdk/__init__.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/providers/claude_sdk/driver.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/providers/codex/__init__.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/providers/codex/capabilities.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/providers/codex/errors.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/providers/codex/translate.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/providers/codex_app_server/capabilities.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/providers/codex_app_server/summary.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/providers/codex_app_server/translate.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/routes/__init__.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/routes/api_agents.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/routes/api_app.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/routes/api_app_commit_sections.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/routes/api_app_config.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/routes/api_app_session_prefs.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/routes/api_browser.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/routes/api_commands.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/routes/api_costs.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/routes/api_drafts.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/routes/api_exec.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/routes/api_files.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/routes/api_git.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/routes/api_logs.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/routes/api_plugins.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/routes/api_project_config.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/routes/api_prompts.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/routes/api_providers.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/routes/api_search.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/routes/api_session_stash.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/routes/api_session_welcome.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/routes/api_sessions.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/routes/api_shadow.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/routes/api_shadow_db.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/routes/api_shadow_files.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/routes/api_shadow_search.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/routes/api_skills.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/routes/api_tasks.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/routes/api_terminal.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/routes/api_upload.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/routes/api_viewer.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/routes/dependencies.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/routes/ws_chat.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/server.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/server_logging.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/services/__init__.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/session_store.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/session_store_core.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/shadow_db.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/shadow_db_plans.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/shadow_db_queries.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/shadow_db_schema.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/shadow_git.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/shadow_git_frontmatter.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/shadow_git_sections.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/shadow_git_summary.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/shadow_parser.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/00-variables.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/01-base.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/02-tooltips.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/09-left-rail.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/10-header.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/11-connection-bar.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/20-messages.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/21-tool-blocks.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/22-edit-diff.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/23-thinking.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/24-background-tasks.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/25-context-block.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/26-session-setup.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/30-markdown.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/40-input.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/41-autocomplete.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/42-activity-strip.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/43-file-autocomplete.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/44-snippets-autocomplete.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/45-selection-bar.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/46-keyboard-bar.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/47-keyboard-longpress.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/47-token-profile.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/50-welcome.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/51-modals.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/52-utilities.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/53-image-upload.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/54-todo-list.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/55-file-upload.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/56-chat-navigator.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/56-permission-card.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/56-plan-approval.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/56-question-form.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/57-swipe-indicator.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/58-session-families.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/59-about.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/61-log-explorer.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/62-json-tree.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/62-skills-widget.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/63-commands-widget.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/63-plugins-widget.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/63-terminal.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/64-search-files-widget.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/65-snippets-widget.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/66-active-sessions.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/66-agents-widget.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/66-file-explorer-widget.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/66-git-panel.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/66-history-explorer.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/67-diff-viewer.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/67-editor-view.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/67-file-preview-widget.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/68-browser-widget.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/68-compare-wizard.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/68-csv-preview.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/68-diff-preview.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/68-helpers-install-widget.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/68-image-annotate.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/68-terminal-view.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/68-uploads-widget.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/69-cost-analytics.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/70-config-panel.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/70-excalidraw.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/70-prompt-explorer.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/71-chart.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/72-discussion-sidebar.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/74-debug-logs.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/80-open-dialog.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/80-quick-switcher.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/80-widget-system.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/81-quick-actions.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/82-context-popover.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/83-context-menu.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/85-lazy-loading.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/86-zen-mode.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/87-grid-switcher.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/css/login.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/feature-triage.html +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/icons/apple-touch-icon.png +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/icons/favicon-32.png +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/icons/favicon.ico +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/icons/icon-128.png +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/icons/icon-144.png +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/icons/icon-152.png +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/icons/icon-180.png +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/icons/icon-192.png +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/icons/icon-384.png +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/icons/icon-512.png +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/icons/icon-72.png +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/icons/icon-96.png +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/action-delegate.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/activity-strip.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/app/context-menus.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/app/file-preview.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/app/init-ui.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/app/input-events.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/app/input-resize.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/app/message-actions.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/app/panels.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/app/rendering-delegators.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/app/server-loading.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/app/session-ops.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/app/session-switch.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/app/settings-helpers.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/app/startup-welcome.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/app-context.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/app.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/auth-fetch.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/background-tasks.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/boot.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/caret-position.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/chat-navigator.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/chat-search.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/command-store.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/components.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/config.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/context-menu.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/controllers/chat-controller.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/controllers/dialog-controller.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/controllers/tab-controller.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/controllers/thinking-controller.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/diff-utils.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/drafts-pill.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/editor-view.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/effort-settings.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/feature-triage.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/file-autocomplete.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/file-tabs.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/gestures.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/grid-switcher.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/input-handler.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/keyboard-bar.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/layout-switcher.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/linkify-utils.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/login.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/open-dialog.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/orphan-terminals.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/path-utils.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/perf-marks.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/permission-settings.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/pointer-input.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/preview/json-tree-menu.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/preview/json-tree-toolbar.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/preview/json-tree.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/preview/preview-breadcrumb.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/preview/preview-edit.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/preview/preview-events.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/preview/preview-history.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/preview/preview-inline-edit.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/preview/preview-poll.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/preview/preview-render.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/preview/preview-search.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/preview/preview-state.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/preview/preview-utils.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/preview-plugins/chart-plugin.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/preview-plugins/csv-plugin.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/preview-plugins/diff-plugin.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/preview-plugins/excalidraw-plugin.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/preview-plugins/html-plugin.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/preview-plugins/image-plugin.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/preview-plugins/index.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/preview-plugins/json-plugin.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/preview-plugins/jsonl-plugin.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/preview-plugins/markdown-plugin.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/preview-plugins/panzoom-plugin.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/preview-plugins/plugin-helpers.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/project-color-picker.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/project-colors.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/prompt-favorites.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/quick-actions-menu.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/quick-actions-registry.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/quick-switcher/controller.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/quick-switcher/fuzzy-scorer.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/quick-switcher/index.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/quick-switcher/providers/base-provider.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/quick-switcher/providers/command-provider.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/quick-switcher/providers/file-provider.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/quick-switcher/providers/panel-provider.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/quick-switcher/providers/project-provider.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/quick-switcher/providers/read-files-provider.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/quick-switcher/providers/skills-provider.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/quick-switcher/registry.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/quick-switcher/ui/item.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/quick-switcher/ui/picker.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/recent-opens.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/scroll-manager.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/scroll-state-machine.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/selection/action-bar.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/selection/index.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/selection/selection-handler.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/selection/state.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/session/agent-progress.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/session/handle-agent-message.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/session/handle-message.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/session/interactive.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/session/message-store.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/session/messages.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/session/persistence.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/session/restore.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/session/sync.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/session-container-pool.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/session-setup-panel.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/session.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/shortcut-hints.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/shortcuts.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/skills-autocomplete.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/snippets-autocomplete.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/stash-refs-view.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/stash-ui.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/stash.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/status-bar.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/token-profile.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/tool-renderer-blocks.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/tool-renderer-thinking.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/tool-renderer.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/tooltips.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/upload-manager.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/utils.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/welcome/api.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/welcome/cards.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/welcome/context-menu.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/welcome/families.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/welcome/preview.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/welcome/state.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/welcome.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widget-system/base-widget.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widget-system/device-manager.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widget-system/event-bus.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widget-system/icons.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widget-system/index.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widget-system/init.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widget-system/types/bottom-sheet.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widget-system/types/floating.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widget-system/types/index.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widget-system/types/modal.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widget-system/types/sidebar.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widget-system/types/tab.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widget-system/types/top-sheet.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widget-system/widget-manager.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/about-widget.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/active-sessions-widget.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/agents-widget.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/browser-widget.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/commands-widget.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/config/commit-sections.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/config/dir-autocomplete.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/config/gestures.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/config/models-tab.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/config/quick-actions-tab.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/config/shortcut-editor.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/config/state.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/config/system-controls.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/config-widget.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/cost-analytics-widget.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/debug-widget.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/diff-viewer-widget.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/discussion-widget.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/file-explorer-widget.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/file-preview-widget.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/git-widget.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/helpers-install-widget.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/history-explorer-widget.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/image-annotate-widget.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/image-preview-widget.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/index.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/log-explorer-widget.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/plugins-widget.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/prompt-explorer-widget.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/search-files-widget.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/skills-widget.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/snippets-widget.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/sub-agents-widget.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/tasks-widget.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/terminal/connection.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/terminal/gestures.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/terminal/init.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/terminal/link-providers.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/terminal/osc52.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/terminal/render.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/terminal/size.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/terminal/state.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/terminal/wrap-utils.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/terminal-widget.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/uploads-widget.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/widgets/zen-widget.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/login.html +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/manifest.json +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/sw.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/vendor/LICENSES.txt +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/vendor/README.md +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/vendor/codemirror.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/vendor/codemirror.js.LEGAL.txt +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/vendor/github-markdown-dark.min.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/vendor/highlight-github-dark.min.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/vendor/highlight-lang-dockerfile.min.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/vendor/highlight-lang-nginx.min.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/vendor/highlight-lang-properties.min.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/vendor/highlight-lang-scala.min.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/vendor/highlight.min.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/vendor/marked.min.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/vendor/purify.min.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/vendor/xterm-addon-fit.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/vendor/xterm.css +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/vendor/xterm.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/web-client.html +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/subprocess_registry.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/tls_cert.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/tools/agents/shadow-git-helper.md +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/tools/excalidraw-to-svg.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/tools/install-helpers.sh +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/tools/shadow-git +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/tools/shadow-query +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/tools/term-bin/pbcopy +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/tools/vegalite-to-svg.js +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/turn_query.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/turn_tracker.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/utils/__init__.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/utils/agent_cli.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/utils/bash_file_ops.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/utils/chart.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/utils/excalidraw.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/utils/file_lock.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/utils/file_paths.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/utils/generate_icons.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/utils/proc.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/utils/pty_backend.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/utils/pty_posix.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/utils/pty_windows.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/utils/token_profiles.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/viewer_templates.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/welcome_search.py +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code.egg-info/SOURCES.txt +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code.egg-info/dependency_links.txt +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code.egg-info/entry_points.txt +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code.egg-info/requires.txt +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code.egg-info/scm_file_list.json +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code.egg-info/top_level.txt +0 -0
- {painapple_code-1.1.2 → painapple_code-1.1.3}/start.sh +0 -0
|
@@ -2,6 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
Notable changes are documented here per release. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versions follow [SemVer](https://semver.org/), and the git tag is the single source of truth for the version (the PyPI wheel, the Docker image tag, and `__version__` all derive from it).
|
|
4
4
|
|
|
5
|
+
## 1.1.3 — 2026-10-01
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- Codex sessions now ask for MCP tool approvals with the same in-chat permission card Claude sessions use — Allow / Deny, plus "always allow" for this session or for good. Previously Codex rejected every MCP tool call that needed approval (anything not marked read-only).
|
|
10
|
+
- Switching a Codex session's permission mode (e.g. to Full access, the equivalent of `codex --yolo`) now takes effect for the existing conversation; before, a resumed Codex thread kept the sandbox it was started with, even across server restarts.
|
|
11
|
+
- Failed `!` bang commands show the stderr explaining the failure instead of a bare "Exit code: N", and output written to both stdout and stderr is no longer cut down to stdout.
|
|
12
|
+
|
|
5
13
|
## 1.1.2 — 2026-09-30
|
|
6
14
|
|
|
7
15
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: painapple-code
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.3
|
|
4
4
|
Summary: Self-hosted remote UI for Claude Code that journals every turn - background AI summaries become shadow-git commits and a queryable DuckDB history
|
|
5
5
|
Author-email: Michał Booth-Wrotkowski <michal@boothw.com>
|
|
6
6
|
License-Expression: AGPL-3.0-or-later
|
|
@@ -21,7 +21,7 @@ The modes available on the default provider (set per session via the button next
|
|
|
21
21
|
| **Auto** | `auto` | Claude's AI classifier gates each tool call |
|
|
22
22
|
| **YOLO** | `bypassPermissions` | Full access |
|
|
23
23
|
|
|
24
|
-
Three caveats. First, the approval cards only protect you while you're the one clicking them — in **YOLO** and **Auto** nothing asks, and those are the modes that give Claude the most freedom. Second, the cards
|
|
24
|
+
Three caveats. First, the approval cards only protect you while you're the one clicking them — in **YOLO** and **Auto** nothing asks, and those are the modes that give Claude the most freedom. Second, on the Codex provider the cards cover only MCP tool calls (Codex asks before running an MCP tool that isn't marked read-only); everything else is governed by Codex's own sandbox tiers. Third — and this is the point of this whole section — the boundary that actually holds is the one *below* the agent: the OS user, the container, the VM. A permission mode is the agent cooperating, not a sandbox. See the [permissions guide](../guides/permissions-and-thinking.md) for the full story.
|
|
25
25
|
|
|
26
26
|
## Terminal
|
|
27
27
|
|
|
@@ -28,7 +28,7 @@ The **"always allow"** options on a card are the CLI's own "don't ask again" sug
|
|
|
28
28
|
The default mode is **Ask** — reads run freely, but every edit and command waits for your approval on a card. Prefer **Accept Edits** to wave edits through and only get carded for commands, **YOLO** or **Auto** to let Claude just work, or **Don't Ask** to auto-deny anything your allow rules don't already cover. **Plan** stays read-only.
|
|
29
29
|
|
|
30
30
|
!!! note "Other providers"
|
|
31
|
-
Sessions can also run on OpenAI Codex — see [AI providers](providers.md) for picking one per session (or pinning a server-wide default with `--default-provider`). The same pass-through applies: Codex doesn't use these modes at all, so the button maps to the Codex CLI's own **sandbox tiers** (Read-only / Workspace write / Full access), enforced by Codex.
|
|
31
|
+
Sessions can also run on OpenAI Codex — see [AI providers](providers.md) for picking one per session (or pinning a server-wide default with `--default-provider`). The same pass-through applies: Codex doesn't use these modes at all, so the button maps to the Codex CLI's own **sandbox tiers** (Read-only / Workspace write / Full access), enforced by Codex. One thing still asks: before running an MCP tool that isn't marked read-only, Codex requests approval, and that shows up as the same in-chat card (with "always allow" for this session or for good). **Full access** behaves like `codex --yolo` and runs MCP tools without asking.
|
|
32
32
|
|
|
33
33
|
!!! note "Auto mode is a research preview"
|
|
34
34
|
Auto is the CLI's `--permission-mode auto`, where a classifier model on Claude Code's side gates each call. It needs a recent CLI and model (Sonnet 4.6+/Opus 4.6+ on the Anthropic API; Team/Enterprise plans need an org owner to enable it). Also, headless auto sessions abort after 3 consecutive classifier blocks (or 20 total) — if Claude keeps getting blocked, the turn ends rather than looping.
|
|
@@ -33,7 +33,7 @@ The **default provider** for new sessions is set with the **Make default** butto
|
|
|
33
33
|
Each provider self-describes its capabilities, and the UI follows:
|
|
34
34
|
|
|
35
35
|
- **Models** — the model picker shows the *active provider's* catalog. Claude's comes from the server's editable `models.yaml`; Codex's mirrors the Codex CLI's own model list (so it updates when Codex does). Per-provider default models are configured in Settings → Providers.
|
|
36
|
-
- **Permission modes** — the Claude provider speaks Claude's modes (Plan / Ask / Don't Ask / Accept Edits / Auto / YOLO — see [Permission modes](permissions-and-thinking.md)); the Codex provider maps to Codex **sandbox tiers**: Read-only, Workspace write, and Full access.
|
|
36
|
+
- **Permission modes** — the Claude provider speaks Claude's modes (Plan / Ask / Don't Ask / Accept Edits / Auto / YOLO — see [Permission modes](permissions-and-thinking.md)); the Codex provider maps to Codex **sandbox tiers**: Read-only, Workspace write, and Full access. Codex's MCP tool approvals render as the same in-chat permission cards; Full access skips them, like `codex --yolo`.
|
|
37
37
|
- **Effort** — the effort gauge renders each provider's own scale. Claude has five levels (low → max); Codex levels come from its model catalog and can reach `xhigh` / `ultra` on recent models, with the picker narrowing to what the selected model supports.
|
|
38
38
|
- **Cost** — Codex reports tokens only, no dollar figure, so the `$` cost readouts hide on Codex sessions and the turn bar shows token counts.
|
|
39
39
|
- **Continue in the CLI** — the **Continue in CLI** quick action is provider-aware: a Claude session gives you `claude -r <id>`, a Codex session `codex exec resume <id>`.
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '1.1.
|
|
22
|
-
__version_tuple__ = version_tuple = (1, 1,
|
|
21
|
+
__version__ = version = '1.1.3'
|
|
22
|
+
__version_tuple__ = version_tuple = (1, 1, 3)
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'g0c414ec'
|
|
@@ -88,6 +88,7 @@ class CodexAppServerProvider(
|
|
|
88
88
|
persistent_process=True, # one app-server process, many turns
|
|
89
89
|
forward_plain_stderr=False, # app-server logs human progress to stderr
|
|
90
90
|
transport="jsonrpc", # the session layer drives a transport driver
|
|
91
|
+
interactive_permissions=True, # MCP tool approvals → permission card
|
|
91
92
|
)
|
|
92
93
|
|
|
93
94
|
def make_transport(self, process, opts, session):
|
|
@@ -74,8 +74,20 @@ class _LaunchMixin:
|
|
|
74
74
|
return params
|
|
75
75
|
|
|
76
76
|
def thread_resume_params(self, opts: LaunchOptions, thread_id: str, cwd: str) -> dict:
|
|
77
|
-
"""Params for `thread/resume` (continue an existing thread by id).
|
|
78
|
-
|
|
77
|
+
"""Params for `thread/resume` (continue an existing thread by id).
|
|
78
|
+
|
|
79
|
+
Sandbox/approval MUST ride along: without them the app-server keeps the
|
|
80
|
+
thread's ORIGINAL sandbox from its rollout, so a mode change (which
|
|
81
|
+
respawns + resumes) never took effect — a thread started in
|
|
82
|
+
workspace-write still gated MCP tools after switching to
|
|
83
|
+
danger-full-access (codex --yolo), even across restarts.
|
|
84
|
+
"""
|
|
85
|
+
params: dict = {
|
|
86
|
+
"threadId": thread_id,
|
|
87
|
+
"cwd": cwd,
|
|
88
|
+
"sandbox": _SANDBOX_BY_MODE.get(opts.permission_mode or "", _DEFAULT_SANDBOX),
|
|
89
|
+
"approvalPolicy": "never",
|
|
90
|
+
}
|
|
79
91
|
model = self._wire_model(opts.model)
|
|
80
92
|
if model:
|
|
81
93
|
params["model"] = model
|
|
@@ -21,6 +21,7 @@ from __future__ import annotations
|
|
|
21
21
|
import asyncio
|
|
22
22
|
import json
|
|
23
23
|
import logging
|
|
24
|
+
import re
|
|
24
25
|
|
|
25
26
|
from painapple_code.session_store import SessionStore
|
|
26
27
|
|
|
@@ -44,6 +45,21 @@ _APPROVAL_DENY = {
|
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
|
|
48
|
+
# MCP tool approvals. Codex asks before running an MCP tool that isn't
|
|
49
|
+
# annotated read-only — even under `approvalPolicy="never"`, which only governs
|
|
50
|
+
# shell/patch escalations — by sending an `mcpServer/elicitation/request` whose
|
|
51
|
+
# `_meta.codex_approval_kind` is "mcp_tool_call". An unanswered/errored request
|
|
52
|
+
# makes codex reject the call ("user rejected MCP tool call"), so these are
|
|
53
|
+
# round-tripped to the client's permission card instead. `_meta.persist` lists
|
|
54
|
+
# the remember-scopes codex will honour ("session", "always"); echoing one back
|
|
55
|
+
# in the accept response's `_meta.persist` stops it asking again.
|
|
56
|
+
_MCP_APPROVAL_KIND = "mcp_tool_call"
|
|
57
|
+
_MCP_TOOL_RE = re.compile(r'run tool "([^"]+)"')
|
|
58
|
+
# codex persist scope → the permission card's suggestion `destination`
|
|
59
|
+
# (reusing the addRules row shape the Claude card already renders/labels).
|
|
60
|
+
_PERSIST_DESTINATION = {"session": "session", "always": "userSettings"}
|
|
61
|
+
|
|
62
|
+
|
|
47
63
|
def _client_version() -> str:
|
|
48
64
|
try:
|
|
49
65
|
from painapple_code import __version__
|
|
@@ -66,6 +82,12 @@ class JsonRpcTransport:
|
|
|
66
82
|
self._thread_id = None # codex thread id (== session.session_id)
|
|
67
83
|
self._active_turn_id = None # in-flight turn id (turn/interrupt needs it)
|
|
68
84
|
self._send_lock = asyncio.Lock() # serialize handshake/thread/turn sends
|
|
85
|
+
# Set by the session layer: async callable(permission_request dict) that
|
|
86
|
+
# surfaces an approval card to the client. None → approvals are declined.
|
|
87
|
+
self.on_permission_request = None
|
|
88
|
+
# permission request_id → (JSON-RPC request id, [persist scope per
|
|
89
|
+
# suggestion index]) for approvals awaiting the user's decision.
|
|
90
|
+
self._pending_approvals: dict = {}
|
|
69
91
|
|
|
70
92
|
# --- low-level JSON-RPC I/O ------------------------------------------
|
|
71
93
|
|
|
@@ -133,6 +155,13 @@ class JsonRpcTransport:
|
|
|
133
155
|
self._active_turn_id = turn["id"]
|
|
134
156
|
elif method == "turn/completed":
|
|
135
157
|
self._active_turn_id = None
|
|
158
|
+
elif method == "serverRequest/resolved":
|
|
159
|
+
# Codex settled a request itself (turn interrupted / thread closed)
|
|
160
|
+
# — retire any approval card still waiting on it.
|
|
161
|
+
rid = (native.get("params") or {}).get("requestId")
|
|
162
|
+
request_id = f"codex-mcp-{rid}"
|
|
163
|
+
if request_id in self._pending_approvals:
|
|
164
|
+
asyncio.create_task(self._expire_approval(request_id))
|
|
136
165
|
return True # notification → translate
|
|
137
166
|
|
|
138
167
|
async def initialize(self) -> None:
|
|
@@ -226,6 +255,9 @@ class JsonRpcTransport:
|
|
|
226
255
|
async def _answer_server_request(self, native: dict) -> None:
|
|
227
256
|
method = native.get("method", "")
|
|
228
257
|
rid = native.get("id")
|
|
258
|
+
if method == "mcpServer/elicitation/request":
|
|
259
|
+
await self._handle_elicitation(rid, native.get("params") or {})
|
|
260
|
+
return
|
|
229
261
|
deny = _APPROVAL_DENY.get(method)
|
|
230
262
|
if deny is not None:
|
|
231
263
|
await self._write({"jsonrpc": "2.0", "id": rid, "result": deny})
|
|
@@ -236,3 +268,68 @@ class JsonRpcTransport:
|
|
|
236
268
|
"jsonrpc": "2.0", "id": rid,
|
|
237
269
|
"error": {"code": -32601, "message": f"{method} not handled"},
|
|
238
270
|
})
|
|
271
|
+
|
|
272
|
+
# --- MCP tool approvals ------------------------------------------------
|
|
273
|
+
|
|
274
|
+
async def _handle_elicitation(self, rid, params: dict) -> None:
|
|
275
|
+
"""Surface an MCP tool approval as a permission card.
|
|
276
|
+
|
|
277
|
+
Only codex's own tool-call approvals are routed to the user. A genuine
|
|
278
|
+
MCP-server elicitation (a form/URL the server wants filled in) has no
|
|
279
|
+
UI here yet, so it's declined — explicitly, so codex doesn't hang.
|
|
280
|
+
"""
|
|
281
|
+
meta = params.get("_meta") or {}
|
|
282
|
+
if (meta.get("codex_approval_kind") != _MCP_APPROVAL_KIND
|
|
283
|
+
or self.on_permission_request is None):
|
|
284
|
+
logger.info(f"codex elicitation from {params.get('serverName')!r} "
|
|
285
|
+
f"declined (kind={meta.get('codex_approval_kind')!r})")
|
|
286
|
+
await self._write({"jsonrpc": "2.0", "id": rid,
|
|
287
|
+
"result": {"action": "decline", "content": None}})
|
|
288
|
+
return
|
|
289
|
+
|
|
290
|
+
server = params.get("serverName") or "mcp"
|
|
291
|
+
message = params.get("message") or ""
|
|
292
|
+
m = _MCP_TOOL_RE.search(message)
|
|
293
|
+
tool_name = f"mcp__{server}__{m.group(1)}" if m else f"mcp__{server}"
|
|
294
|
+
persist = [p for p in (meta.get("persist") or []) if p in _PERSIST_DESTINATION]
|
|
295
|
+
request_id = f"codex-mcp-{rid}"
|
|
296
|
+
self._pending_approvals[request_id] = (rid, persist)
|
|
297
|
+
tool_input = meta.get("tool_params")
|
|
298
|
+
await self.on_permission_request({
|
|
299
|
+
"type": "permission_request",
|
|
300
|
+
"request_id": request_id,
|
|
301
|
+
"tool_name": tool_name,
|
|
302
|
+
"input": tool_input if isinstance(tool_input, dict) else {},
|
|
303
|
+
"description": message or None,
|
|
304
|
+
"suggestions": [
|
|
305
|
+
{"type": "addRules", "rules": [{"tool_name": tool_name}],
|
|
306
|
+
"destination": _PERSIST_DESTINATION[p]}
|
|
307
|
+
for p in persist
|
|
308
|
+
],
|
|
309
|
+
})
|
|
310
|
+
|
|
311
|
+
async def _expire_approval(self, request_id: str) -> None:
|
|
312
|
+
self._pending_approvals.pop(request_id, None)
|
|
313
|
+
self.session._pending_permission_requests.pop(request_id, None)
|
|
314
|
+
# ok=False → the client marks the card expired (same as a dead process).
|
|
315
|
+
await self.session.safe_send({"type": "permission_resolved",
|
|
316
|
+
"request_id": request_id, "ok": False})
|
|
317
|
+
|
|
318
|
+
def owns_permission(self, request_id) -> bool:
|
|
319
|
+
return request_id in self._pending_approvals
|
|
320
|
+
|
|
321
|
+
async def respond_permission(self, request_id: str, data: dict) -> bool:
|
|
322
|
+
"""Answer a pending MCP approval with the user's decision."""
|
|
323
|
+
entry = self._pending_approvals.pop(request_id, None)
|
|
324
|
+
if entry is None:
|
|
325
|
+
return False
|
|
326
|
+
rid, persist = entry
|
|
327
|
+
if data.get("behavior") == "allow":
|
|
328
|
+
result: dict = {"action": "accept", "content": None}
|
|
329
|
+
idx = data.get("suggestion_index")
|
|
330
|
+
if isinstance(idx, int) and 0 <= idx < len(persist):
|
|
331
|
+
result["_meta"] = {"persist": persist[idx]}
|
|
332
|
+
else:
|
|
333
|
+
result = {"action": "decline", "content": None}
|
|
334
|
+
await self._write({"jsonrpc": "2.0", "id": rid, "result": result})
|
|
335
|
+
return True
|
|
@@ -866,6 +866,11 @@ class AgentManager:
|
|
|
866
866
|
session.process, launch_opts, session
|
|
867
867
|
)
|
|
868
868
|
if session._transport is not None:
|
|
869
|
+
if hasattr(session._transport, "on_permission_request"):
|
|
870
|
+
# Transport-native approvals (Codex MCP tool calls)
|
|
871
|
+
# ride the same permission-card flow as claude-sdk.
|
|
872
|
+
session._transport.on_permission_request = (
|
|
873
|
+
lambda msg, _s=session: self._handle_permission_request(_s, msg))
|
|
869
874
|
await session._transport.initialize()
|
|
870
875
|
|
|
871
876
|
return True
|
|
@@ -2486,6 +2491,18 @@ class AgentManager:
|
|
|
2486
2491
|
return False
|
|
2487
2492
|
if not session.process or not session.is_running:
|
|
2488
2493
|
return False
|
|
2494
|
+
transport = session._transport
|
|
2495
|
+
if transport is not None and getattr(transport, "owns_permission", lambda _r: False)(request_id):
|
|
2496
|
+
# JSON-RPC transport answers its own server request (Codex MCP
|
|
2497
|
+
# approval) — nothing goes to stdin as a line frame.
|
|
2498
|
+
try:
|
|
2499
|
+
ok = await transport.respond_permission(request_id, data)
|
|
2500
|
+
except Exception as e:
|
|
2501
|
+
logger.error(f"Error sending transport permission response: {e}")
|
|
2502
|
+
return False
|
|
2503
|
+
session._pending_permission_requests.pop(request_id, None)
|
|
2504
|
+
session.touch()
|
|
2505
|
+
return ok
|
|
2489
2506
|
request = session._pending_permission_requests[request_id]
|
|
2490
2507
|
frame = {
|
|
2491
2508
|
"type": "permission_response",
|
|
@@ -7032,8 +7032,10 @@ ${m?`<div class="${b}">${w}</div>`:'<div class="tool-output" style="color: var(-
|
|
|
7032
7032
|
</svg>
|
|
7033
7033
|
</span>
|
|
7034
7034
|
</div>
|
|
7035
|
-
`}renderTabs(){let e=this.getAllTabs().map(s=>s.data?s.type==="session"?this._renderSessionTab(s.data):this._renderWidgetTab(s.data):"").join("");this._saveTabOrder(),this.els.tabs.innerHTML=e,this._installTabDelegation(),requestAnimationFrame(()=>{requestAnimationFrame(()=>{this.updateOverflowIndicator(),this.scrollActiveTabIntoView()})})}_installTabDelegation(){if(this._tabDelegationInstalled)return;this._tabDelegationInstalled=!0;let e=this.els.tabs,s=document.querySelector(".header-overview-btn");s&&s.addEventListener("click",m=>{m.stopPropagation(),this.toggleTabsOverview(s)});let i=this.els.tabsViewport||e.parentElement;i?.querySelector(".tabs-overflow-left")?.addEventListener("click",m=>{m.stopPropagation(),e.scrollBy({left:-e.clientWidth*.8,behavior:"smooth"})}),i?.querySelector(".tabs-overflow-right")?.addEventListener("click",m=>{m.stopPropagation(),e.scrollBy({left:e.clientWidth*.8,behavior:"smooth"})}),e.addEventListener("click",m=>{if(this._suppressClickUntil){let k=Date.now()<this._suppressClickUntil;if(this._suppressClickUntil=0,k){m.stopPropagation();return}}let v=m.target.closest(".tab");if(!v)return;let w=v.dataset.type,b=v.dataset.id,_=m.target.closest(".tab-pin-btn");if(_){m.stopPropagation(),this.toggleTabPin(_.dataset.unpinKind,_.dataset.unpin,!1);return}if(m.target.closest(".close-btn")){let k=m.target.closest(".close-btn").dataset.close;if(w==="session"){let $=this.sessionManager.get(k);$&&this.ctx._app.closeSession($)}else w==="widget"&&this.closeWidgetTab(k)}else if(w==="session"){let k=this.sessionManager.get(b);k&&this.switchToSession(k)}else w==="widget"&&this.switchToWidgetTab(b)}),this._installMouseDrag(e);let n=null,o=null,a=null,r=!1,c=!1,d=0,p=l(()=>{o&&(document.removeEventListener("click",o,{capture:!0}),o=null)},"removeClickBlocker"),h=l(()=>{o=l(m=>{m.preventDefault(),m.stopPropagation(),m.stopImmediatePropagation(),p()},"clickBlocker"),document.addEventListener("click",o,{capture:!0,once:!0})},"installClickBlocker"),f=l(()=>{n&&(clearTimeout(n),n=null),a?.classList.remove("dragging"),a=null,r=!1,c=!1},"resetTouchDrag");e.addEventListener("touchstart",m=>{let v=m.target.closest(".tab");v&&(p(),a=v,r=!1,c=!1,d=m.touches[0].clientX,n=setTimeout(()=>{n=null,r=!0,v.classList.add("dragging")},400))},{passive:!0}),e.addEventListener("touchmove",m=>{if(r&&a){m.preventDefault(),c=!0,this._dragReposition(e,a,m.touches[0].clientX);return}n&&(clearTimeout(n),n=null)},{passive:!1}),e.addEventListener("touchend",m=>{let v=a,w=r,b=c;if(f(),!(!v||!w))if(m.preventDefault(),m.stopPropagation(),h(),setTimeout(p,400),b)this.applyDomOrder();else{let _=v.getBoundingClientRect(),k=this.ctx._app.buildTabContextMenu(v);k.length>0&&this.ctx._app.contextMenu.show(d,_.bottom+4,k)}},{passive:!1}),e.addEventListener("touchcancel",()=>{f()},{passive:!0}),e.addEventListener("scroll",()=>{this.updateOverflowIndicator()})}_installMouseDrag(e){let s=null,i=!1,n=0,o=0,a=l(c=>{if(s){if(!i){if(Math.abs(c.clientX-n)<6&&Math.abs(c.clientY-o)<6)return;i=!0,s.classList.add("dragging"),e.classList.add("tabs-drag-active")}this._dragReposition(e,s,c.clientX)}},"onMove"),r=l(()=>{document.removeEventListener("pointermove",a),document.removeEventListener("pointerup",r),document.removeEventListener("pointercancel",r),i&&s&&(s.classList.remove("dragging"),e.classList.remove("tabs-drag-active"),this._suppressClickUntil=Date.now()+150,this.applyDomOrder()),s=null,i=!1},"onUp");e.addEventListener("pointerdown",c=>{if(c.pointerType==="touch"||c.button!==0)return;let d=c.target.closest(".tab");!d||c.target.closest(".close-btn")||(s=d,i=!1,n=c.clientX,o=c.clientY,document.addEventListener("pointermove",a),document.addEventListener("pointerup",r),document.addEventListener("pointercancel",r))})}updateOverflowIndicator(){let e=this.els.tabs;if(!e)return;let s=this.els.tabsViewport||e.parentElement,i=s?.querySelector(".tabs-overflow-left"),n=s?.querySelector(".tabs-overflow-right");if(!i&&!n)return;let o=e.querySelectorAll(".tab"),a=e.scrollWidth-e.clientWidth>1;if(o.length===0||!a){i&&(i.style.display="none"),n&&(n.style.display="none");return}let r=e.getBoundingClientRect(),c=0,d=0;o.forEach(p=>{let h=p.getBoundingClientRect();h.right<r.left+20&&c++,h.left>r.right-20&&d++}),i&&(c>0?(i.textContent=`+${c}`,i.style.display="flex"):i.style.display="none"),n&&(d>0?(n.textContent=`+${d}`,n.style.display="flex"):n.style.display="none")}closeActiveTab(){this.activeMode==="widget"&&this.activeWidgetTabId&&this.closeWidgetTab(this.activeWidgetTabId)}};G();V();yl();var cu=class{static{l(this,"CommandExecutor")}constructor(e){this.ctx=e}get app(){return this.ctx._app}get activeSession(){return this.ctx.session}handleSlashCommand(e){let s=e.split(" "),i=s[0],n=s.slice(1).join(" "),o=ji.find(p=>p.cmd===i);if(o&&this.app[o.action]){o.hasArgs?this.app[o.action](n):this.app[o.action]();return}let a=Ri(),r=this.activeSession?.cwd||this.app.cwd||null,c=a.getCommand(i,r);if(c){this.executeCustomCommand(c,n);return}this.app.autocomplete?.agentCommands?.find(p=>p.cmd===i)||i.startsWith("/")?this.app.sendMessage(e):this.activeSession?.addSystemLog(`Unknown command: ${e}`)}async executeCustomCommand(e,s){let i=Ri(),n={input:s,cwd:this.activeSession?.cwd||this.app.cwd||"",session:this.activeSession?.id||""};if(e.type===ze.PROMPT){let o=i.expandVariables(e.prompt,n);this.app.sendMessage(o)}else if(e.type===ze.SHELL){let o=i.expandVariables(e.shell,n);await this.executeShellCommand(o)}}async executeShellCommand(e,s={}){let{saveToRecent:i=!1,toolType:n="shell"}=s;if(!e.trim()||!this.activeSession)return;let o=this.activeSession.cwd||".";if(i){let r=ue.get("recent-shell",[]).filter(c=>c!==e);r.unshift(e),ue.set("recent-shell",r.slice(0,10))}try{let a=await fetch(`${S.API_BASE}/api/exec`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({command:e,cwd:o})}),r=await a.json();if(!a.ok){this.activeSession.addSystemLog(`Error: ${r.detail}`,"error");return}let c=
|
|
7036
|
-
|
|
7035
|
+
`}renderTabs(){let e=this.getAllTabs().map(s=>s.data?s.type==="session"?this._renderSessionTab(s.data):this._renderWidgetTab(s.data):"").join("");this._saveTabOrder(),this.els.tabs.innerHTML=e,this._installTabDelegation(),requestAnimationFrame(()=>{requestAnimationFrame(()=>{this.updateOverflowIndicator(),this.scrollActiveTabIntoView()})})}_installTabDelegation(){if(this._tabDelegationInstalled)return;this._tabDelegationInstalled=!0;let e=this.els.tabs,s=document.querySelector(".header-overview-btn");s&&s.addEventListener("click",m=>{m.stopPropagation(),this.toggleTabsOverview(s)});let i=this.els.tabsViewport||e.parentElement;i?.querySelector(".tabs-overflow-left")?.addEventListener("click",m=>{m.stopPropagation(),e.scrollBy({left:-e.clientWidth*.8,behavior:"smooth"})}),i?.querySelector(".tabs-overflow-right")?.addEventListener("click",m=>{m.stopPropagation(),e.scrollBy({left:e.clientWidth*.8,behavior:"smooth"})}),e.addEventListener("click",m=>{if(this._suppressClickUntil){let k=Date.now()<this._suppressClickUntil;if(this._suppressClickUntil=0,k){m.stopPropagation();return}}let v=m.target.closest(".tab");if(!v)return;let w=v.dataset.type,b=v.dataset.id,_=m.target.closest(".tab-pin-btn");if(_){m.stopPropagation(),this.toggleTabPin(_.dataset.unpinKind,_.dataset.unpin,!1);return}if(m.target.closest(".close-btn")){let k=m.target.closest(".close-btn").dataset.close;if(w==="session"){let $=this.sessionManager.get(k);$&&this.ctx._app.closeSession($)}else w==="widget"&&this.closeWidgetTab(k)}else if(w==="session"){let k=this.sessionManager.get(b);k&&this.switchToSession(k)}else w==="widget"&&this.switchToWidgetTab(b)}),this._installMouseDrag(e);let n=null,o=null,a=null,r=!1,c=!1,d=0,p=l(()=>{o&&(document.removeEventListener("click",o,{capture:!0}),o=null)},"removeClickBlocker"),h=l(()=>{o=l(m=>{m.preventDefault(),m.stopPropagation(),m.stopImmediatePropagation(),p()},"clickBlocker"),document.addEventListener("click",o,{capture:!0,once:!0})},"installClickBlocker"),f=l(()=>{n&&(clearTimeout(n),n=null),a?.classList.remove("dragging"),a=null,r=!1,c=!1},"resetTouchDrag");e.addEventListener("touchstart",m=>{let v=m.target.closest(".tab");v&&(p(),a=v,r=!1,c=!1,d=m.touches[0].clientX,n=setTimeout(()=>{n=null,r=!0,v.classList.add("dragging")},400))},{passive:!0}),e.addEventListener("touchmove",m=>{if(r&&a){m.preventDefault(),c=!0,this._dragReposition(e,a,m.touches[0].clientX);return}n&&(clearTimeout(n),n=null)},{passive:!1}),e.addEventListener("touchend",m=>{let v=a,w=r,b=c;if(f(),!(!v||!w))if(m.preventDefault(),m.stopPropagation(),h(),setTimeout(p,400),b)this.applyDomOrder();else{let _=v.getBoundingClientRect(),k=this.ctx._app.buildTabContextMenu(v);k.length>0&&this.ctx._app.contextMenu.show(d,_.bottom+4,k)}},{passive:!1}),e.addEventListener("touchcancel",()=>{f()},{passive:!0}),e.addEventListener("scroll",()=>{this.updateOverflowIndicator()})}_installMouseDrag(e){let s=null,i=!1,n=0,o=0,a=l(c=>{if(s){if(!i){if(Math.abs(c.clientX-n)<6&&Math.abs(c.clientY-o)<6)return;i=!0,s.classList.add("dragging"),e.classList.add("tabs-drag-active")}this._dragReposition(e,s,c.clientX)}},"onMove"),r=l(()=>{document.removeEventListener("pointermove",a),document.removeEventListener("pointerup",r),document.removeEventListener("pointercancel",r),i&&s&&(s.classList.remove("dragging"),e.classList.remove("tabs-drag-active"),this._suppressClickUntil=Date.now()+150,this.applyDomOrder()),s=null,i=!1},"onUp");e.addEventListener("pointerdown",c=>{if(c.pointerType==="touch"||c.button!==0)return;let d=c.target.closest(".tab");!d||c.target.closest(".close-btn")||(s=d,i=!1,n=c.clientX,o=c.clientY,document.addEventListener("pointermove",a),document.addEventListener("pointerup",r),document.addEventListener("pointercancel",r))})}updateOverflowIndicator(){let e=this.els.tabs;if(!e)return;let s=this.els.tabsViewport||e.parentElement,i=s?.querySelector(".tabs-overflow-left"),n=s?.querySelector(".tabs-overflow-right");if(!i&&!n)return;let o=e.querySelectorAll(".tab"),a=e.scrollWidth-e.clientWidth>1;if(o.length===0||!a){i&&(i.style.display="none"),n&&(n.style.display="none");return}let r=e.getBoundingClientRect(),c=0,d=0;o.forEach(p=>{let h=p.getBoundingClientRect();h.right<r.left+20&&c++,h.left>r.right-20&&d++}),i&&(c>0?(i.textContent=`+${c}`,i.style.display="flex"):i.style.display="none"),n&&(d>0?(n.textContent=`+${d}`,n.style.display="flex"):n.style.display="none")}closeActiveTab(){this.activeMode==="widget"&&this.activeWidgetTabId&&this.closeWidgetTab(this.activeWidgetTabId)}};G();V();yl();var cu=class{static{l(this,"CommandExecutor")}constructor(e){this.ctx=e}get app(){return this.ctx._app}get activeSession(){return this.ctx.session}handleSlashCommand(e){let s=e.split(" "),i=s[0],n=s.slice(1).join(" "),o=ji.find(p=>p.cmd===i);if(o&&this.app[o.action]){o.hasArgs?this.app[o.action](n):this.app[o.action]();return}let a=Ri(),r=this.activeSession?.cwd||this.app.cwd||null,c=a.getCommand(i,r);if(c){this.executeCustomCommand(c,n);return}this.app.autocomplete?.agentCommands?.find(p=>p.cmd===i)||i.startsWith("/")?this.app.sendMessage(e):this.activeSession?.addSystemLog(`Unknown command: ${e}`)}async executeCustomCommand(e,s){let i=Ri(),n={input:s,cwd:this.activeSession?.cwd||this.app.cwd||"",session:this.activeSession?.id||""};if(e.type===ze.PROMPT){let o=i.expandVariables(e.prompt,n);this.app.sendMessage(o)}else if(e.type===ze.SHELL){let o=i.expandVariables(e.shell,n);await this.executeShellCommand(o)}}async executeShellCommand(e,s={}){let{saveToRecent:i=!1,toolType:n="shell"}=s;if(!e.trim()||!this.activeSession)return;let o=this.activeSession.cwd||".";if(i){let r=ue.get("recent-shell",[]).filter(c=>c!==e);r.unshift(e),ue.set("recent-shell",r.slice(0,10))}try{let a=await fetch(`${S.API_BASE}/api/exec`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({command:e,cwd:o})}),r=await a.json();if(!a.ok){this.activeSession.addSystemLog(`Error: ${r.detail}`,"error");return}let c=[r.stdout,r.stderr].map(f=>(f||"").replace(/\s+$/,"")).filter(Boolean).join(`
|
|
7036
|
+
`),d=c||"(no output)",p=d.slice(0,3e3)+(d.length>3e3?`
|
|
7037
|
+
...(truncated)`:""),h=r.exit_code!==0;if(this.activeSession.addMessage({role:"tool",toolType:n,toolName:"Shell",toolInput:{command:e},toolOutput:p,toolError:h?`${c?p+`
|
|
7038
|
+
`:""}Exit code: ${r.exit_code}`:null}),this.activeSession.pendingBangOutputs||(this.activeSession.pendingBangOutputs=[]),this.activeSession.pendingBangOutputs.push({command:e,output:d.slice(0,3e3),exitCode:r.exit_code}),n==="bang"){let f=this.activeSession.pendingBangOutputs.length,m=this.app.els?.messageInput;m&&(m.placeholder=`${f} command${f>1?"s":""} buffered. Type message and press Enter...`)}}catch(a){console.error("Shell execution error:",a),this.activeSession.addSystemLog(`Failed to execute: ${a.message}`,"error")}}async handleBangCommand(e){let s=e.slice(1).trim();s&&this.activeSession&&await this.executeShellCommand(s,{saveToRecent:!0,toolType:"bang"})}};N();G();V();$e();var dm=class{static{l(this,"OrphanTerminalsManager")}constructor(){this.btn=null,this.badge=null,this.dropdown=null,this.list=null,this.bulkActions=null,this.orphans=[],this.isOpen=!1}init(){this.btn=document.getElementById("orphan-terminals-btn"),this.badge=document.getElementById("orphan-badge"),this.dropdown=document.getElementById("orphan-dropdown"),this.list=document.getElementById("orphan-list"),this.bulkActions=document.getElementById("orphan-bulk-actions");let e=document.getElementById("orphan-refresh-btn"),s=document.getElementById("orphan-tab-all-btn"),i=document.getElementById("orphan-kill-all-btn");if(!this.btn||!this.dropdown){console.warn("Orphan terminals UI elements not found");return}this.btn.addEventListener("click",n=>{n.target.closest(".orphan-terminals-dropdown")||this.toggle()}),e&&e.addEventListener("click",n=>{n.stopPropagation(),this.refresh()}),s&&s.addEventListener("click",n=>{n.stopPropagation(),this.tabAll()}),i&&i.addEventListener("click",n=>{n.stopPropagation(),this.killAll()}),document.addEventListener("click",n=>{this.isOpen&&!this.btn.contains(n.target)&&this.close()}),document.addEventListener("keydown",n=>{n.key==="Escape"&&this.isOpen&&this.close()}),this.refresh(),setInterval(()=>this.refreshBadge(),3e4)}toggle(){this.isOpen?this.close():this.open()}open(){this.isOpen=!0,this.dropdown.classList.add("visible"),this.refresh()}close(){this.isOpen=!1,this.dropdown.classList.remove("visible")}async refresh(){try{let e=await this.fetchOrphans();this.orphans=e,this.updateBadge(),this.renderList()}catch(e){console.error("Failed to fetch orphaned terminals:",e),this.list.innerHTML=`<div class="orphan-dropdown-empty">${u.orphan_terminals.failed_load}</div>`}}async refreshBadge(){try{let e=await this.fetchOrphans();this.orphans=e,this.updateBadge()}catch{}}async fetchOrphans(){let e=await fetch(`${S.API_BASE}/api/terminals`);if(!e.ok)throw new Error(`HTTP ${e.status}`);let i=(await e.json()).terminals||[],n=this.getConnectedSessionIds();return i.filter(o=>!n.has(o.session))}getConnectedSessionIds(){let e=new Set,s=Ae.getTabIds();for(let i of s){let n=Ae.getTabState(i);n?.sessionId&&e.add(n.sessionId)}return e}updateBadge(){let e=this.orphans.filter(s=>s.alive).length;this.badge&&(this.badge.textContent=e>0?e:"",this.badge.dataset.count=e),this.bulkActions&&(this.bulkActions.style.display=this.orphans.length>0?"flex":"none")}renderList(){if(this.list){if(this.orphans.length===0){this.list.innerHTML=`<div class="orphan-dropdown-empty">${u.orphan_terminals.empty}</div>`;return}this.list.innerHTML=this.orphans.map(e=>`
|
|
7037
7039
|
<div class="orphan-terminal-item" data-session="${g(e.session)}">
|
|
7038
7040
|
<div class="orphan-terminal-info">
|
|
7039
7041
|
<span class="orphan-terminal-pid">PID ${e.pid||"?"}</span>
|
{painapple_code-1.1.2 → painapple_code-1.1.3}/src/painapple_code/static/js/command-executor.js
RENAMED
|
@@ -124,14 +124,28 @@ export class CommandExecutor {
|
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
// Show output in UI as a tool block
|
|
127
|
-
|
|
127
|
+
// Both streams, not `stdout || stderr` — a command that writes to
|
|
128
|
+
// both (progress on stderr, result on stdout) lost its stderr.
|
|
129
|
+
const combined = [data.stdout, data.stderr]
|
|
130
|
+
.map(s => (s || '').replace(/\s+$/, ''))
|
|
131
|
+
.filter(Boolean)
|
|
132
|
+
.join('\n');
|
|
133
|
+
const output = combined || '(no output)';
|
|
134
|
+
const shown = output.slice(0, 3000) + (output.length > 3000 ? '\n...(truncated)' : '');
|
|
135
|
+
// The Bash renderer shows toolError INSTEAD of toolOutput on error
|
|
136
|
+
// (Claude's Bash tool puts the full failure text there), so the
|
|
137
|
+
// output must ride in toolError too — a bare "Exit code: N" hid
|
|
138
|
+
// the stderr that explains the failure.
|
|
139
|
+
const failed = data.exit_code !== 0;
|
|
128
140
|
this.activeSession.addMessage({
|
|
129
141
|
role: 'tool',
|
|
130
142
|
toolType: toolType,
|
|
131
143
|
toolName: 'Shell',
|
|
132
144
|
toolInput: { command: shellCmd },
|
|
133
|
-
toolOutput:
|
|
134
|
-
toolError:
|
|
145
|
+
toolOutput: shown,
|
|
146
|
+
toolError: failed
|
|
147
|
+
? `${combined ? shown + '\n' : ''}Exit code: ${data.exit_code}`
|
|
148
|
+
: null
|
|
135
149
|
});
|
|
136
150
|
|
|
137
151
|
// Add to pending outputs for next Claude message
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: painapple-code
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.3
|
|
4
4
|
Summary: Self-hosted remote UI for Claude Code that journals every turn - background AI summaries become shadow-git commits and a queryable DuckDB history
|
|
5
5
|
Author-email: Michał Booth-Wrotkowski <michal@boothw.com>
|
|
6
6
|
License-Expression: AGPL-3.0-or-later
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/assets/turn-summary-bar-expanded.png
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{painapple_code-1.1.2 → painapple_code-1.1.3}/docs-site/getting-started/install-devcontainer.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|