painapple-code 1.0.0__py3-none-any.whl
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/__init__.py +30 -0
- painapple_code/__main__.py +18 -0
- painapple_code/_version.py +24 -0
- painapple_code/auth_middleware.py +930 -0
- painapple_code/cli/__init__.py +204 -0
- painapple_code/cli/deploy/__init__.py +15 -0
- painapple_code/cli/deploy/claude_seed.py +41 -0
- painapple_code/cli/deploy/config.py +260 -0
- painapple_code/cli/deploy/container.py +715 -0
- painapple_code/cli/deploy/launch.py +163 -0
- painapple_code/cli/deploy/runtime.py +223 -0
- painapple_code/cli/lifecycle_cmd.py +443 -0
- painapple_code/cli/list_cmd.py +572 -0
- painapple_code/cli/manage_cmd.py +670 -0
- painapple_code/cli/netinfo.py +125 -0
- painapple_code/cli/profiles.py +390 -0
- painapple_code/cli/serve_args.py +163 -0
- painapple_code/cli/serve_config.py +256 -0
- painapple_code/cli/setup_cmd.py +664 -0
- painapple_code/cli/ui.py +438 -0
- painapple_code/cost_analytics.py +879 -0
- painapple_code/data/models.defaults.yaml +18 -0
- painapple_code/data/models.yaml +18 -0
- painapple_code/data/presets.defaults.json +32 -0
- painapple_code/data/strings.yaml +2269 -0
- painapple_code/helpers.py +406 -0
- painapple_code/paths.py +1514 -0
- painapple_code/prompt_explorer.py +984 -0
- painapple_code/providers/__init__.py +224 -0
- painapple_code/providers/base.py +710 -0
- painapple_code/providers/claude/__init__.py +74 -0
- painapple_code/providers/claude/capabilities.py +218 -0
- painapple_code/providers/claude/errors.py +79 -0
- painapple_code/providers/claude/launch.py +50 -0
- painapple_code/providers/claude/summary.py +89 -0
- painapple_code/providers/claude/translate.py +74 -0
- painapple_code/providers/claude_sdk/__init__.py +139 -0
- painapple_code/providers/claude_sdk/driver.py +412 -0
- painapple_code/providers/codex/__init__.py +87 -0
- painapple_code/providers/codex/capabilities.py +321 -0
- painapple_code/providers/codex/errors.py +70 -0
- painapple_code/providers/codex/launch.py +142 -0
- painapple_code/providers/codex/summary.py +196 -0
- painapple_code/providers/codex/translate.py +204 -0
- painapple_code/providers/codex_app_server/__init__.py +100 -0
- painapple_code/providers/codex_app_server/capabilities.py +41 -0
- painapple_code/providers/codex_app_server/launch.py +202 -0
- painapple_code/providers/codex_app_server/summary.py +291 -0
- painapple_code/providers/codex_app_server/translate.py +263 -0
- painapple_code/providers/codex_app_server/transport.py +238 -0
- painapple_code/routes/__init__.py +0 -0
- painapple_code/routes/api_agents.py +441 -0
- painapple_code/routes/api_app.py +368 -0
- painapple_code/routes/api_app_commit_sections.py +127 -0
- painapple_code/routes/api_app_config.py +997 -0
- painapple_code/routes/api_app_session_prefs.py +217 -0
- painapple_code/routes/api_browser.py +690 -0
- painapple_code/routes/api_commands.py +374 -0
- painapple_code/routes/api_costs.py +128 -0
- painapple_code/routes/api_drafts.py +139 -0
- painapple_code/routes/api_exec.py +149 -0
- painapple_code/routes/api_files.py +542 -0
- painapple_code/routes/api_git.py +657 -0
- painapple_code/routes/api_logs.py +649 -0
- painapple_code/routes/api_plugins.py +275 -0
- painapple_code/routes/api_project_config.py +418 -0
- painapple_code/routes/api_prompts.py +231 -0
- painapple_code/routes/api_providers.py +53 -0
- painapple_code/routes/api_search.py +411 -0
- painapple_code/routes/api_session_stash.py +234 -0
- painapple_code/routes/api_session_welcome.py +151 -0
- painapple_code/routes/api_sessions.py +742 -0
- painapple_code/routes/api_shadow.py +323 -0
- painapple_code/routes/api_shadow_db.py +512 -0
- painapple_code/routes/api_shadow_files.py +332 -0
- painapple_code/routes/api_shadow_search.py +476 -0
- painapple_code/routes/api_skills.py +610 -0
- painapple_code/routes/api_tasks.py +147 -0
- painapple_code/routes/api_terminal.py +540 -0
- painapple_code/routes/api_upload.py +293 -0
- painapple_code/routes/api_viewer.py +229 -0
- painapple_code/routes/dependencies.py +109 -0
- painapple_code/routes/ws_chat.py +837 -0
- painapple_code/server.py +2208 -0
- painapple_code/server_logging.py +263 -0
- painapple_code/services/__init__.py +0 -0
- painapple_code/services/agent_session.py +2738 -0
- painapple_code/session_store.py +253 -0
- painapple_code/session_store_core.py +879 -0
- painapple_code/shadow_db.py +830 -0
- painapple_code/shadow_db_plans.py +369 -0
- painapple_code/shadow_db_queries.py +595 -0
- painapple_code/shadow_db_schema.py +676 -0
- painapple_code/shadow_git.py +1296 -0
- painapple_code/shadow_git_frontmatter.py +314 -0
- painapple_code/shadow_git_sections.py +520 -0
- painapple_code/shadow_git_summary.py +462 -0
- painapple_code/shadow_parser.py +560 -0
- painapple_code/static/css/00-variables.css +276 -0
- painapple_code/static/css/01-base.css +245 -0
- painapple_code/static/css/02-tooltips.css +36 -0
- painapple_code/static/css/09-left-rail.css +448 -0
- painapple_code/static/css/10-header.css +777 -0
- painapple_code/static/css/11-connection-bar.css +120 -0
- painapple_code/static/css/20-messages.css +750 -0
- painapple_code/static/css/21-tool-blocks.css +2340 -0
- painapple_code/static/css/22-edit-diff.css +619 -0
- painapple_code/static/css/23-thinking.css +1584 -0
- painapple_code/static/css/24-background-tasks.css +359 -0
- painapple_code/static/css/25-context-block.css +252 -0
- painapple_code/static/css/26-session-setup.css +144 -0
- painapple_code/static/css/30-markdown.css +854 -0
- painapple_code/static/css/40-input.css +2418 -0
- painapple_code/static/css/41-autocomplete.css +127 -0
- painapple_code/static/css/42-activity-strip.css +97 -0
- painapple_code/static/css/43-file-autocomplete.css +121 -0
- painapple_code/static/css/44-snippets-autocomplete.css +224 -0
- painapple_code/static/css/45-selection-bar.css +433 -0
- painapple_code/static/css/46-keyboard-bar.css +119 -0
- painapple_code/static/css/47-keyboard-longpress.css +116 -0
- painapple_code/static/css/47-token-profile.css +106 -0
- painapple_code/static/css/50-welcome.css +3095 -0
- painapple_code/static/css/51-modals.css +301 -0
- painapple_code/static/css/52-utilities.css +77 -0
- painapple_code/static/css/53-image-upload.css +456 -0
- painapple_code/static/css/54-todo-list.css +102 -0
- painapple_code/static/css/55-file-upload.css +113 -0
- painapple_code/static/css/56-chat-navigator.css +218 -0
- painapple_code/static/css/56-permission-card.css +332 -0
- painapple_code/static/css/56-plan-approval.css +204 -0
- painapple_code/static/css/56-question-form.css +602 -0
- painapple_code/static/css/57-swipe-indicator.css +95 -0
- painapple_code/static/css/58-session-families.css +627 -0
- painapple_code/static/css/59-about.css +196 -0
- painapple_code/static/css/61-log-explorer.css +723 -0
- painapple_code/static/css/62-json-tree.css +489 -0
- painapple_code/static/css/62-skills-widget.css +650 -0
- painapple_code/static/css/63-commands-widget.css +30 -0
- painapple_code/static/css/63-plugins-widget.css +174 -0
- painapple_code/static/css/63-terminal.css +516 -0
- painapple_code/static/css/64-search-files-widget.css +448 -0
- painapple_code/static/css/65-snippets-widget.css +426 -0
- painapple_code/static/css/66-active-sessions.css +979 -0
- painapple_code/static/css/66-agents-widget.css +265 -0
- painapple_code/static/css/66-file-explorer-widget.css +855 -0
- painapple_code/static/css/66-git-panel.css +791 -0
- painapple_code/static/css/66-history-explorer.css +1496 -0
- painapple_code/static/css/67-diff-viewer.css +602 -0
- painapple_code/static/css/67-editor-view.css +748 -0
- painapple_code/static/css/67-file-preview-widget.css +1873 -0
- painapple_code/static/css/68-browser-widget.css +337 -0
- painapple_code/static/css/68-compare-wizard.css +355 -0
- painapple_code/static/css/68-csv-preview.css +106 -0
- painapple_code/static/css/68-diff-preview.css +103 -0
- painapple_code/static/css/68-helpers-install-widget.css +491 -0
- painapple_code/static/css/68-image-annotate.css +346 -0
- painapple_code/static/css/68-terminal-view.css +98 -0
- painapple_code/static/css/68-uploads-widget.css +229 -0
- painapple_code/static/css/69-cost-analytics.css +537 -0
- painapple_code/static/css/70-config-panel.css +3736 -0
- painapple_code/static/css/70-excalidraw.css +136 -0
- painapple_code/static/css/70-prompt-explorer.css +890 -0
- painapple_code/static/css/71-chart.css +111 -0
- painapple_code/static/css/72-discussion-sidebar.css +678 -0
- painapple_code/static/css/74-debug-logs.css +656 -0
- painapple_code/static/css/80-open-dialog.css +146 -0
- painapple_code/static/css/80-quick-switcher.css +383 -0
- painapple_code/static/css/80-widget-system.css +1763 -0
- painapple_code/static/css/81-quick-actions.css +1020 -0
- painapple_code/static/css/82-context-popover.css +1233 -0
- painapple_code/static/css/83-context-menu.css +339 -0
- painapple_code/static/css/85-lazy-loading.css +102 -0
- painapple_code/static/css/86-zen-mode.css +708 -0
- painapple_code/static/css/87-grid-switcher.css +346 -0
- painapple_code/static/css/login.css +198 -0
- painapple_code/static/dist/app.bundle.js +7177 -0
- painapple_code/static/feature-triage.html +446 -0
- painapple_code/static/icons/apple-touch-icon.png +0 -0
- painapple_code/static/icons/favicon-32.png +0 -0
- painapple_code/static/icons/favicon.ico +0 -0
- painapple_code/static/icons/icon-128.png +0 -0
- painapple_code/static/icons/icon-144.png +0 -0
- painapple_code/static/icons/icon-152.png +0 -0
- painapple_code/static/icons/icon-180.png +0 -0
- painapple_code/static/icons/icon-192.png +0 -0
- painapple_code/static/icons/icon-384.png +0 -0
- painapple_code/static/icons/icon-512.png +0 -0
- painapple_code/static/icons/icon-72.png +0 -0
- painapple_code/static/icons/icon-96.png +0 -0
- painapple_code/static/js/action-delegate.js +187 -0
- painapple_code/static/js/activity-strip.js +193 -0
- painapple_code/static/js/app/context-menus.js +619 -0
- painapple_code/static/js/app/file-preview.js +163 -0
- painapple_code/static/js/app/init-ui.js +574 -0
- painapple_code/static/js/app/input-events.js +561 -0
- painapple_code/static/js/app/input-resize.js +313 -0
- painapple_code/static/js/app/message-actions.js +419 -0
- painapple_code/static/js/app/panels.js +210 -0
- painapple_code/static/js/app/rendering-delegators.js +246 -0
- painapple_code/static/js/app/server-loading.js +365 -0
- painapple_code/static/js/app/session-ops.js +287 -0
- painapple_code/static/js/app/session-switch.js +443 -0
- painapple_code/static/js/app/settings-helpers.js +280 -0
- painapple_code/static/js/app/startup-welcome.js +290 -0
- painapple_code/static/js/app-context.js +157 -0
- painapple_code/static/js/app.js +2134 -0
- painapple_code/static/js/auth-fetch.js +46 -0
- painapple_code/static/js/background-tasks.js +274 -0
- painapple_code/static/js/boot.js +73 -0
- painapple_code/static/js/caret-position.js +171 -0
- painapple_code/static/js/chat-navigator.js +710 -0
- painapple_code/static/js/chat-search.js +323 -0
- painapple_code/static/js/command-executor.js +176 -0
- painapple_code/static/js/command-store.js +497 -0
- painapple_code/static/js/components.js +1414 -0
- painapple_code/static/js/config.js +218 -0
- painapple_code/static/js/context-menu.js +740 -0
- painapple_code/static/js/controllers/chat-controller.js +4252 -0
- painapple_code/static/js/controllers/dialog-controller.js +217 -0
- painapple_code/static/js/controllers/tab-controller.js +1828 -0
- painapple_code/static/js/controllers/thinking-controller.js +915 -0
- painapple_code/static/js/diff-utils.js +486 -0
- painapple_code/static/js/drafts-pill.js +95 -0
- painapple_code/static/js/editor-view.js +815 -0
- painapple_code/static/js/effort-settings.js +430 -0
- painapple_code/static/js/feature-triage.js +811 -0
- painapple_code/static/js/file-autocomplete.js +516 -0
- painapple_code/static/js/file-tabs.js +123 -0
- painapple_code/static/js/gestures.js +448 -0
- painapple_code/static/js/grid-switcher.js +334 -0
- painapple_code/static/js/input-handler.js +1472 -0
- painapple_code/static/js/keyboard-bar.js +495 -0
- painapple_code/static/js/layout-switcher.js +109 -0
- painapple_code/static/js/linkify-utils.js +200 -0
- painapple_code/static/js/login.js +141 -0
- painapple_code/static/js/open-dialog.js +879 -0
- painapple_code/static/js/orphan-terminals.js +373 -0
- painapple_code/static/js/path-utils.js +179 -0
- painapple_code/static/js/perf-marks.js +102 -0
- painapple_code/static/js/permission-settings.js +475 -0
- painapple_code/static/js/pointer-input.js +59 -0
- painapple_code/static/js/preview/json-tree-menu.js +226 -0
- painapple_code/static/js/preview/json-tree-toolbar.js +291 -0
- painapple_code/static/js/preview/json-tree.js +457 -0
- painapple_code/static/js/preview/preview-breadcrumb.js +387 -0
- painapple_code/static/js/preview/preview-edit.js +367 -0
- painapple_code/static/js/preview/preview-events.js +361 -0
- painapple_code/static/js/preview/preview-history.js +567 -0
- painapple_code/static/js/preview/preview-inline-edit.js +869 -0
- painapple_code/static/js/preview/preview-poll.js +108 -0
- painapple_code/static/js/preview/preview-render.js +572 -0
- painapple_code/static/js/preview/preview-search.js +421 -0
- painapple_code/static/js/preview/preview-state.js +256 -0
- painapple_code/static/js/preview/preview-utils.js +251 -0
- painapple_code/static/js/preview-plugins/chart-plugin.js +22 -0
- painapple_code/static/js/preview-plugins/csv-plugin.js +188 -0
- painapple_code/static/js/preview-plugins/diff-plugin.js +258 -0
- painapple_code/static/js/preview-plugins/excalidraw-plugin.js +25 -0
- painapple_code/static/js/preview-plugins/html-plugin.js +104 -0
- painapple_code/static/js/preview-plugins/image-plugin.js +20 -0
- painapple_code/static/js/preview-plugins/index.js +34 -0
- painapple_code/static/js/preview-plugins/json-plugin.js +99 -0
- painapple_code/static/js/preview-plugins/jsonl-plugin.js +152 -0
- painapple_code/static/js/preview-plugins/markdown-plugin.js +266 -0
- painapple_code/static/js/preview-plugins/panzoom-plugin.js +63 -0
- painapple_code/static/js/preview-plugins/plugin-helpers.js +282 -0
- painapple_code/static/js/project-color-picker.js +110 -0
- painapple_code/static/js/project-colors.js +163 -0
- painapple_code/static/js/prompt-favorites.js +187 -0
- painapple_code/static/js/quick-actions-menu.js +1736 -0
- painapple_code/static/js/quick-actions-registry.js +1239 -0
- painapple_code/static/js/quick-switcher/controller.js +294 -0
- painapple_code/static/js/quick-switcher/fuzzy-scorer.js +123 -0
- painapple_code/static/js/quick-switcher/index.js +30 -0
- painapple_code/static/js/quick-switcher/providers/base-provider.js +51 -0
- painapple_code/static/js/quick-switcher/providers/command-provider.js +56 -0
- painapple_code/static/js/quick-switcher/providers/file-provider.js +291 -0
- painapple_code/static/js/quick-switcher/providers/panel-provider.js +132 -0
- painapple_code/static/js/quick-switcher/providers/project-provider.js +361 -0
- painapple_code/static/js/quick-switcher/providers/read-files-provider.js +104 -0
- painapple_code/static/js/quick-switcher/providers/skills-provider.js +129 -0
- painapple_code/static/js/quick-switcher/registry.js +69 -0
- painapple_code/static/js/quick-switcher/ui/item.js +54 -0
- painapple_code/static/js/quick-switcher/ui/picker.js +464 -0
- painapple_code/static/js/recent-opens.js +40 -0
- painapple_code/static/js/scroll-manager.js +530 -0
- painapple_code/static/js/scroll-state-machine.js +359 -0
- painapple_code/static/js/selection/action-bar.js +793 -0
- painapple_code/static/js/selection/index.js +15 -0
- painapple_code/static/js/selection/selection-handler.js +877 -0
- painapple_code/static/js/selection/state.js +181 -0
- painapple_code/static/js/session/agent-progress.js +202 -0
- painapple_code/static/js/session/handle-agent-message.js +481 -0
- painapple_code/static/js/session/handle-message.js +550 -0
- painapple_code/static/js/session/interactive.js +587 -0
- painapple_code/static/js/session/message-store.js +271 -0
- painapple_code/static/js/session/messages.js +253 -0
- painapple_code/static/js/session/persistence.js +179 -0
- painapple_code/static/js/session/restore.js +136 -0
- painapple_code/static/js/session/sync.js +333 -0
- painapple_code/static/js/session-container-pool.js +371 -0
- painapple_code/static/js/session-setup-panel.js +274 -0
- painapple_code/static/js/session.js +1047 -0
- painapple_code/static/js/shortcut-hints.js +272 -0
- painapple_code/static/js/shortcuts.js +1146 -0
- painapple_code/static/js/skills-autocomplete.js +262 -0
- painapple_code/static/js/snippets-autocomplete.js +738 -0
- painapple_code/static/js/stash-refs-view.js +83 -0
- painapple_code/static/js/stash-ui.js +768 -0
- painapple_code/static/js/stash.js +785 -0
- painapple_code/static/js/status-bar.js +1184 -0
- painapple_code/static/js/token-profile.js +274 -0
- painapple_code/static/js/tool-renderer-blocks.js +1626 -0
- painapple_code/static/js/tool-renderer-thinking.js +813 -0
- painapple_code/static/js/tool-renderer.js +1500 -0
- painapple_code/static/js/tooltips.js +197 -0
- painapple_code/static/js/upload-manager.js +1019 -0
- painapple_code/static/js/utils.js +521 -0
- painapple_code/static/js/welcome/api.js +363 -0
- painapple_code/static/js/welcome/cards.js +626 -0
- painapple_code/static/js/welcome/context-menu.js +585 -0
- painapple_code/static/js/welcome/families.js +801 -0
- painapple_code/static/js/welcome/preview.js +234 -0
- painapple_code/static/js/welcome/state.js +129 -0
- painapple_code/static/js/welcome.js +1874 -0
- painapple_code/static/js/widget-system/base-widget.js +717 -0
- painapple_code/static/js/widget-system/device-manager.js +178 -0
- painapple_code/static/js/widget-system/event-bus.js +152 -0
- painapple_code/static/js/widget-system/icons.js +120 -0
- painapple_code/static/js/widget-system/index.js +49 -0
- painapple_code/static/js/widget-system/init.js +54 -0
- painapple_code/static/js/widget-system/types/bottom-sheet.js +307 -0
- painapple_code/static/js/widget-system/types/floating.js +915 -0
- painapple_code/static/js/widget-system/types/index.js +40 -0
- painapple_code/static/js/widget-system/types/modal.js +147 -0
- painapple_code/static/js/widget-system/types/sidebar.js +158 -0
- painapple_code/static/js/widget-system/types/tab.js +146 -0
- painapple_code/static/js/widget-system/types/top-sheet.js +203 -0
- painapple_code/static/js/widget-system/widget-manager.js +1187 -0
- painapple_code/static/js/widgets/about-widget.js +260 -0
- painapple_code/static/js/widgets/active-sessions-widget.js +760 -0
- painapple_code/static/js/widgets/agents-widget.js +897 -0
- painapple_code/static/js/widgets/browser-widget.js +579 -0
- painapple_code/static/js/widgets/commands-widget.js +694 -0
- painapple_code/static/js/widgets/config/commit-sections.js +449 -0
- painapple_code/static/js/widgets/config/dir-autocomplete.js +224 -0
- painapple_code/static/js/widgets/config/gestures.js +161 -0
- painapple_code/static/js/widgets/config/models-tab.js +988 -0
- painapple_code/static/js/widgets/config/quick-actions-tab.js +882 -0
- painapple_code/static/js/widgets/config/shortcut-editor.js +587 -0
- painapple_code/static/js/widgets/config/state.js +517 -0
- painapple_code/static/js/widgets/config/system-controls.js +90 -0
- painapple_code/static/js/widgets/config-widget.js +1535 -0
- painapple_code/static/js/widgets/cost-analytics-widget.js +621 -0
- painapple_code/static/js/widgets/debug-widget.js +693 -0
- painapple_code/static/js/widgets/diff-viewer-widget.js +1420 -0
- painapple_code/static/js/widgets/discussion-widget.js +1107 -0
- painapple_code/static/js/widgets/file-explorer-widget.js +2166 -0
- painapple_code/static/js/widgets/file-preview-widget.js +861 -0
- painapple_code/static/js/widgets/git-widget.js +794 -0
- painapple_code/static/js/widgets/helpers-install-widget.js +720 -0
- painapple_code/static/js/widgets/history-explorer-widget.js +1804 -0
- painapple_code/static/js/widgets/image-annotate-widget.js +951 -0
- painapple_code/static/js/widgets/image-preview-widget.js +692 -0
- painapple_code/static/js/widgets/index.js +176 -0
- painapple_code/static/js/widgets/log-explorer-widget.js +1057 -0
- painapple_code/static/js/widgets/plugins-widget.js +305 -0
- painapple_code/static/js/widgets/prompt-explorer-widget.js +1119 -0
- painapple_code/static/js/widgets/search-files-widget.js +529 -0
- painapple_code/static/js/widgets/skills-widget.js +843 -0
- painapple_code/static/js/widgets/snippets-widget.js +479 -0
- painapple_code/static/js/widgets/sub-agents-widget.js +333 -0
- painapple_code/static/js/widgets/tasks-widget.js +379 -0
- painapple_code/static/js/widgets/terminal/connection.js +283 -0
- painapple_code/static/js/widgets/terminal/gestures.js +357 -0
- painapple_code/static/js/widgets/terminal/init.js +642 -0
- painapple_code/static/js/widgets/terminal/link-providers.js +532 -0
- painapple_code/static/js/widgets/terminal/osc52.js +213 -0
- painapple_code/static/js/widgets/terminal/render.js +159 -0
- painapple_code/static/js/widgets/terminal/size.js +54 -0
- painapple_code/static/js/widgets/terminal/state.js +211 -0
- painapple_code/static/js/widgets/terminal/wrap-utils.js +101 -0
- painapple_code/static/js/widgets/terminal-widget.js +793 -0
- painapple_code/static/js/widgets/uploads-widget.js +461 -0
- painapple_code/static/js/widgets/zen-widget.js +1001 -0
- painapple_code/static/login.html +51 -0
- painapple_code/static/manifest.json +73 -0
- painapple_code/static/sw.js +293 -0
- painapple_code/static/vendor/LICENSES.txt +769 -0
- painapple_code/static/vendor/README.md +103 -0
- painapple_code/static/vendor/codemirror.js +35 -0
- painapple_code/static/vendor/codemirror.js.LEGAL.txt +304 -0
- painapple_code/static/vendor/github-markdown-dark.min.css +1124 -0
- painapple_code/static/vendor/highlight-github-dark.min.css +10 -0
- painapple_code/static/vendor/highlight-lang-dockerfile.min.js +8 -0
- painapple_code/static/vendor/highlight-lang-nginx.min.js +21 -0
- painapple_code/static/vendor/highlight-lang-properties.min.js +10 -0
- painapple_code/static/vendor/highlight-lang-scala.min.js +28 -0
- painapple_code/static/vendor/highlight.min.js +1213 -0
- painapple_code/static/vendor/marked.min.js +6 -0
- painapple_code/static/vendor/purify.min.js +3 -0
- painapple_code/static/vendor/xterm-addon-fit.js +2 -0
- painapple_code/static/vendor/xterm.css +209 -0
- painapple_code/static/vendor/xterm.js +2 -0
- painapple_code/static/web-client.html +635 -0
- painapple_code/subprocess_registry.py +535 -0
- painapple_code/tls_cert.py +79 -0
- painapple_code/tools/agents/shadow-git-helper.md +400 -0
- painapple_code/tools/excalidraw-to-svg.js +143 -0
- painapple_code/tools/install-helpers.sh +148 -0
- painapple_code/tools/shadow-git +320 -0
- painapple_code/tools/shadow-query +120 -0
- painapple_code/tools/vegalite-to-svg.js +79 -0
- painapple_code/turn_query.py +766 -0
- painapple_code/turn_tracker.py +221 -0
- painapple_code/utils/__init__.py +0 -0
- painapple_code/utils/agent_cli.py +306 -0
- painapple_code/utils/chart.py +103 -0
- painapple_code/utils/excalidraw.py +107 -0
- painapple_code/utils/file_lock.py +162 -0
- painapple_code/utils/file_paths.py +648 -0
- painapple_code/utils/generate_icons.py +251 -0
- painapple_code/utils/proc.py +205 -0
- painapple_code/utils/pty_backend.py +59 -0
- painapple_code/utils/pty_posix.py +160 -0
- painapple_code/utils/pty_windows.py +245 -0
- painapple_code/utils/token_profiles.py +91 -0
- painapple_code/viewer_templates.py +657 -0
- painapple_code/welcome_search.py +879 -0
- painapple_code-1.0.0.dist-info/METADATA +292 -0
- painapple_code-1.0.0.dist-info/RECORD +436 -0
- painapple_code-1.0.0.dist-info/WHEEL +5 -0
- painapple_code-1.0.0.dist-info/entry_points.txt +2 -0
- painapple_code-1.0.0.dist-info/licenses/LICENSE +661 -0
- painapple_code-1.0.0.dist-info/licenses/THIRD_PARTY_NOTICES.md +261 -0
- painapple_code-1.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session preview bottom sheet — quick peek at a session's recent messages
|
|
3
|
+
* without opening it as a full tab.
|
|
4
|
+
*
|
|
5
|
+
* The preview is a separate DOM subtree appended to the welcome container;
|
|
6
|
+
* `updatePreviewUI` swaps it in/out without re-rendering the entire welcome
|
|
7
|
+
* screen, so the surrounding card grid keeps its scroll position.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { CONFIG } from '../config.js';
|
|
11
|
+
import { escapeHtml, formatRelativeTime } from '../utils.js';
|
|
12
|
+
import { state, saveWelcomeState } from './state.js';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Load session messages for preview.
|
|
16
|
+
*/
|
|
17
|
+
async function loadPreviewMessages(sessionId) {
|
|
18
|
+
try {
|
|
19
|
+
const response = await fetch(`${CONFIG.API_BASE}/api/sessions/${sessionId}/logs/messages?limit=10`);
|
|
20
|
+
if (!response.ok) throw new Error('Failed to load messages');
|
|
21
|
+
const data = await response.json();
|
|
22
|
+
return data.messages || [];
|
|
23
|
+
} catch (e) {
|
|
24
|
+
console.error('Failed to load preview messages:', e);
|
|
25
|
+
return [];
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Render the session preview bottom sheet.
|
|
31
|
+
*/
|
|
32
|
+
function renderPreviewSheet(session, messages, isLoading) {
|
|
33
|
+
if (!session) return '';
|
|
34
|
+
|
|
35
|
+
const name = session.name || session.project || 'Session';
|
|
36
|
+
const timeAgo = formatRelativeTime(session.last_activity || session.created_at);
|
|
37
|
+
const tags = session.tags || [];
|
|
38
|
+
const summary = session.summary || '';
|
|
39
|
+
|
|
40
|
+
return `
|
|
41
|
+
<div class="session-preview-overlay" data-action="close-preview"></div>
|
|
42
|
+
<div class="session-preview-sheet">
|
|
43
|
+
<div class="preview-header">
|
|
44
|
+
<div class="preview-title">
|
|
45
|
+
<span class="preview-name">${escapeHtml(name)}</span>
|
|
46
|
+
<span class="preview-project">${escapeHtml(session.project || '')}</span>
|
|
47
|
+
</div>
|
|
48
|
+
<button class="preview-close" data-action="close-preview">
|
|
49
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
50
|
+
<line x1="18" y1="6" x2="6" y2="18"/>
|
|
51
|
+
<line x1="6" y1="6" x2="18" y2="18"/>
|
|
52
|
+
</svg>
|
|
53
|
+
</button>
|
|
54
|
+
</div>
|
|
55
|
+
|
|
56
|
+
<div class="preview-meta">
|
|
57
|
+
<span class="preview-time">${timeAgo}</span>
|
|
58
|
+
${tags.length > 0 ? `
|
|
59
|
+
<div class="preview-tags">
|
|
60
|
+
${tags.slice(0, 4).map(t => `<span class="welcome-tag">${escapeHtml(t)}</span>`).join('')}
|
|
61
|
+
</div>
|
|
62
|
+
` : ''}
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
${summary ? `<div class="preview-summary">${escapeHtml(summary)}</div>` : ''}
|
|
66
|
+
|
|
67
|
+
<div class="preview-messages">
|
|
68
|
+
<div class="preview-messages-header">Recent Messages</div>
|
|
69
|
+
${isLoading ? `
|
|
70
|
+
<div class="preview-loading">
|
|
71
|
+
<div class="loading-spinner"></div>
|
|
72
|
+
<span>Loading...</span>
|
|
73
|
+
</div>
|
|
74
|
+
` : messages.length > 0 ? `
|
|
75
|
+
<div class="preview-messages-list">
|
|
76
|
+
${messages.slice(0, 8).map(msg => `
|
|
77
|
+
<div class="preview-message preview-message--${msg.role || 'unknown'}">
|
|
78
|
+
<span class="preview-msg-role">${msg.role || 'message'}</span>
|
|
79
|
+
<span class="preview-msg-text">${escapeHtml(truncateText(msg.content || '', 120))}</span>
|
|
80
|
+
</div>
|
|
81
|
+
`).join('')}
|
|
82
|
+
</div>
|
|
83
|
+
` : `
|
|
84
|
+
<div class="preview-empty">No messages yet</div>
|
|
85
|
+
`}
|
|
86
|
+
</div>
|
|
87
|
+
|
|
88
|
+
<div class="preview-actions">
|
|
89
|
+
<button class="welcome-btn welcome-btn--primary" data-action="preview-open">
|
|
90
|
+
Open Session
|
|
91
|
+
</button>
|
|
92
|
+
<button class="welcome-btn welcome-btn--secondary" data-action="preview-open-new-tab">
|
|
93
|
+
Open in New Tab
|
|
94
|
+
</button>
|
|
95
|
+
<button class="welcome-btn welcome-btn--fork" data-action="preview-fork">
|
|
96
|
+
Fork
|
|
97
|
+
</button>
|
|
98
|
+
</div>
|
|
99
|
+
</div>
|
|
100
|
+
`;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Truncate text to max length with ellipsis.
|
|
105
|
+
*/
|
|
106
|
+
function truncateText(text, maxLength) {
|
|
107
|
+
if (!text) return '';
|
|
108
|
+
// Remove newlines and extra whitespace
|
|
109
|
+
text = text.replace(/\s+/g, ' ').trim();
|
|
110
|
+
if (text.length <= maxLength) return text;
|
|
111
|
+
return text.slice(0, maxLength) + '...';
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Show session preview.
|
|
116
|
+
*/
|
|
117
|
+
export async function showPreview(session, container) {
|
|
118
|
+
state.previewSession = session;
|
|
119
|
+
state.previewMessages = null;
|
|
120
|
+
state.previewLoading = true;
|
|
121
|
+
|
|
122
|
+
// Render loading state
|
|
123
|
+
updatePreviewUI(container);
|
|
124
|
+
|
|
125
|
+
// Load messages
|
|
126
|
+
const messages = await loadPreviewMessages(session.session_id);
|
|
127
|
+
state.previewMessages = messages;
|
|
128
|
+
state.previewLoading = false;
|
|
129
|
+
|
|
130
|
+
// Re-render with messages
|
|
131
|
+
updatePreviewUI(container);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Update preview UI without re-rendering entire welcome screen.
|
|
136
|
+
*/
|
|
137
|
+
export function updatePreviewUI(container) {
|
|
138
|
+
// Remove existing preview
|
|
139
|
+
const existingPreview = container.querySelector('.session-preview-overlay');
|
|
140
|
+
const existingSheet = container.querySelector('.session-preview-sheet');
|
|
141
|
+
if (existingPreview) existingPreview.remove();
|
|
142
|
+
if (existingSheet) existingSheet.remove();
|
|
143
|
+
|
|
144
|
+
// Add new preview if session is set
|
|
145
|
+
if (state.previewSession) {
|
|
146
|
+
const previewHtml = renderPreviewSheet(
|
|
147
|
+
state.previewSession,
|
|
148
|
+
state.previewMessages || [],
|
|
149
|
+
state.previewLoading
|
|
150
|
+
);
|
|
151
|
+
container.insertAdjacentHTML('beforeend', previewHtml);
|
|
152
|
+
attachPreviewListeners(container);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Close the preview.
|
|
158
|
+
*/
|
|
159
|
+
export function closePreview(container) {
|
|
160
|
+
state.previewSession = null;
|
|
161
|
+
state.previewMessages = null;
|
|
162
|
+
state.previewLoading = false;
|
|
163
|
+
updatePreviewUI(container);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Close session preview if open (exported for global Escape handling).
|
|
168
|
+
* @returns {boolean} True if preview was closed
|
|
169
|
+
*/
|
|
170
|
+
export function closeSessionPreview() {
|
|
171
|
+
if (!state.previewSession) return false;
|
|
172
|
+
const container = document.getElementById('welcome-container');
|
|
173
|
+
if (!container) return false;
|
|
174
|
+
closePreview(container);
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Attach preview event listeners.
|
|
180
|
+
*/
|
|
181
|
+
export function attachPreviewListeners(container) {
|
|
182
|
+
// Close preview on click
|
|
183
|
+
container.querySelectorAll('[data-action="close-preview"]').forEach(el => {
|
|
184
|
+
el.addEventListener('click', () => closePreview(container));
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
// Close preview on Escape key
|
|
188
|
+
const escapeHandler = (e) => {
|
|
189
|
+
if (e.key === 'Escape' && state.previewSession) {
|
|
190
|
+
e.preventDefault();
|
|
191
|
+
e.stopPropagation();
|
|
192
|
+
closePreview(container);
|
|
193
|
+
document.removeEventListener('keydown', escapeHandler);
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
document.addEventListener('keydown', escapeHandler);
|
|
197
|
+
|
|
198
|
+
// Open session (current tab)
|
|
199
|
+
container.querySelector('[data-action="preview-open"]')?.addEventListener('click', () => {
|
|
200
|
+
const session = state.previewSession;
|
|
201
|
+
if (session) {
|
|
202
|
+
// Save state before opening (for "back to sessions" feature)
|
|
203
|
+
saveWelcomeState(container);
|
|
204
|
+
closePreview(container);
|
|
205
|
+
window.dispatchEvent(new CustomEvent('welcome:open-session', {
|
|
206
|
+
detail: { sessionId: session.session_id, projectPath: session.project_path, fromWelcome: true }
|
|
207
|
+
}));
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
// Open in new tab (no back button needed since we stay on welcome)
|
|
212
|
+
container.querySelector('[data-action="preview-open-new-tab"]')?.addEventListener('click', () => {
|
|
213
|
+
const session = state.previewSession;
|
|
214
|
+
if (session) {
|
|
215
|
+
closePreview(container);
|
|
216
|
+
window.dispatchEvent(new CustomEvent('welcome:open-session-new-tab', {
|
|
217
|
+
detail: { sessionId: session.session_id, projectPath: session.project_path }
|
|
218
|
+
}));
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
// Fork
|
|
223
|
+
container.querySelector('[data-action="preview-fork"]')?.addEventListener('click', () => {
|
|
224
|
+
const session = state.previewSession;
|
|
225
|
+
if (session) {
|
|
226
|
+
// Save state before forking
|
|
227
|
+
saveWelcomeState(container);
|
|
228
|
+
closePreview(container);
|
|
229
|
+
window.dispatchEvent(new CustomEvent('welcome:fork-session', {
|
|
230
|
+
detail: { sessionId: session.session_id, projectPath: session.project_path, fromWelcome: true }
|
|
231
|
+
}));
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared state + mutable cross-module refs for the welcome-screen split.
|
|
3
|
+
*
|
|
4
|
+
* Imported by:
|
|
5
|
+
* - welcome.js (orchestrator, public API, main render, event handlers)
|
|
6
|
+
* - cards.js (session/family/fork/favorite card renderers)
|
|
7
|
+
* - families.js (family build/grouping + compact render + task mode)
|
|
8
|
+
* - preview.js (session preview bottom sheet)
|
|
9
|
+
* - context-menu.js (long press + session/project context menus)
|
|
10
|
+
* - api.js (data loaders, mutations, project filter)
|
|
11
|
+
*
|
|
12
|
+
* Everyone reads/writes the same `state` object directly. The Sets
|
|
13
|
+
* (`expandedGroups` etc.) are mutated in place so const re-export works.
|
|
14
|
+
* Mutable scalars live as `.value`/property holders on small objects so
|
|
15
|
+
* cross-module mutations are visible — top-level `let` only propagates
|
|
16
|
+
* within its own module.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
20
|
+
// CORE STATE OBJECT
|
|
21
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
22
|
+
|
|
23
|
+
export const state = {
|
|
24
|
+
forSessionId: null, // Which session/tab this state belongs to
|
|
25
|
+
sessions: [],
|
|
26
|
+
familyMap: new Map(), // rootId -> family object (built from sessions)
|
|
27
|
+
favorites: [], // Favorited sessions (loaded separately)
|
|
28
|
+
favoritesSet: new Set(), // Set of favorited session IDs for quick lookup
|
|
29
|
+
searchResults: null, // Used by task mode
|
|
30
|
+
searchQuery: '', // Used by task mode
|
|
31
|
+
projects: [],
|
|
32
|
+
isSearching: false,
|
|
33
|
+
showProjectPicker: false,
|
|
34
|
+
selectedProject: null,
|
|
35
|
+
quickSearchFilter: '', // Quick inline search filter text
|
|
36
|
+
quickSearchActive: false, // Whether inline search input is showing
|
|
37
|
+
selectedResultIndex: -1, // Keyboard navigation selection (-1 = none)
|
|
38
|
+
selectableItems: [], // Combined list of projects + sessions for keyboard nav
|
|
39
|
+
taskMode: false, // True when showing task-related sessions
|
|
40
|
+
pendingTask: null, // The task message waiting to be sent
|
|
41
|
+
// Preview state
|
|
42
|
+
previewSession: null, // Session being previewed
|
|
43
|
+
previewMessages: null, // Messages loaded for preview
|
|
44
|
+
previewLoading: false, // Loading state for preview
|
|
45
|
+
// Context menu state
|
|
46
|
+
contextMenuSession: null, // Session for context menu
|
|
47
|
+
contextMenuPos: null, // {x, y} position
|
|
48
|
+
contextMenuContainer: null, // Container reference for callbacks
|
|
49
|
+
// Project filter state
|
|
50
|
+
projectFilter: null, // {path, name} - active project filter
|
|
51
|
+
projectContextMenu: null, // {path, name, x, y} - project context menu state
|
|
52
|
+
// Session status tracking
|
|
53
|
+
openSessionIds: new Set(), // store_ids of sessions open in tabs
|
|
54
|
+
runningSessionIds: new Set(), // store_ids of sessions where Claude is running
|
|
55
|
+
// Workspace dirs (sibling project candidates)
|
|
56
|
+
workspaceDirs: [],
|
|
57
|
+
workspaceRoot: null,
|
|
58
|
+
unvisitedExpanded: false, // Toggled by the "+N more" / "Show less" chip
|
|
59
|
+
projectsExpanded: false, // Same, for the visited-projects chip row
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
63
|
+
// MODULE-LEVEL UI STATE
|
|
64
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
65
|
+
|
|
66
|
+
// Project group expansion (task mode + welcome screen).
|
|
67
|
+
export const expandedGroups = new Set();
|
|
68
|
+
|
|
69
|
+
// Family expansion (show forks for a session family).
|
|
70
|
+
export const expandedFamilies = new Set();
|
|
71
|
+
|
|
72
|
+
// "Show all forks" — fully expand a family beyond the first 5.
|
|
73
|
+
export const fullyExpandedFamilies = new Set();
|
|
74
|
+
|
|
75
|
+
// Recent sessions limit (mutable; "Load more" button bumps it).
|
|
76
|
+
export const RECENT_INCREMENT = 5;
|
|
77
|
+
export const recentLimit = { value: 10 };
|
|
78
|
+
|
|
79
|
+
// Favorites list limit (mutable; "Show all favorites" button bumps it to all).
|
|
80
|
+
export const FAVORITES_DEFAULT_LIMIT = 3;
|
|
81
|
+
export const favoritesLimit = { value: FAVORITES_DEFAULT_LIMIT };
|
|
82
|
+
|
|
83
|
+
// Long-press detection refs. Set by context-menu.js, read by event handlers
|
|
84
|
+
// in welcome.js. Wrapped in an object so cross-module mutation is visible.
|
|
85
|
+
export const longPress = {
|
|
86
|
+
timer: null,
|
|
87
|
+
triggered: false,
|
|
88
|
+
timestamp: 0,
|
|
89
|
+
suppressNextClick: false,
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// Context-menu open timestamp (for iOS click-suppression).
|
|
93
|
+
export const contextMenuOpenTime = { value: 0 };
|
|
94
|
+
|
|
95
|
+
// Saved welcome state (for "back to sessions" feature).
|
|
96
|
+
// Mutated in welcome.js (clearSavedWelcomeState/restoreWelcomeState) and
|
|
97
|
+
// in saveWelcomeState below.
|
|
98
|
+
export const savedWelcomeState = { value: null };
|
|
99
|
+
|
|
100
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
101
|
+
// HELPERS
|
|
102
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Check if a session is favorited (used by card renderers + context menu).
|
|
106
|
+
*/
|
|
107
|
+
export function isFavorite(sessionId) {
|
|
108
|
+
return state.favoritesSet.has(sessionId);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Save the current welcome screen state before opening a session.
|
|
113
|
+
* Lives here (not welcome.js) so preview.js / context-menu.js can call it
|
|
114
|
+
* without a circular import back to the orchestrator.
|
|
115
|
+
*/
|
|
116
|
+
export function saveWelcomeState(container) {
|
|
117
|
+
const welcomeEl = container.querySelector('.welcome-screen');
|
|
118
|
+
const searchInput = document.querySelector('.input-area textarea');
|
|
119
|
+
|
|
120
|
+
savedWelcomeState.value = {
|
|
121
|
+
taskMode: state.taskMode,
|
|
122
|
+
pendingTask: state.pendingTask,
|
|
123
|
+
searchResults: state.searchResults,
|
|
124
|
+
scrollTop: welcomeEl?.scrollTop || 0,
|
|
125
|
+
inputValue: searchInput?.value || '',
|
|
126
|
+
timestamp: Date.now(),
|
|
127
|
+
expandedGroups: Array.from(expandedGroups),
|
|
128
|
+
};
|
|
129
|
+
}
|