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,200 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared utilities for linkification
|
|
3
|
+
*
|
|
4
|
+
* File path patterns: Used by components.js for markdown rendering
|
|
5
|
+
* (positions can't be used for markdown because parsing transforms the text)
|
|
6
|
+
*
|
|
7
|
+
* URL patterns: Used by both components.js and tool-renderer.js
|
|
8
|
+
*
|
|
9
|
+
* Note: tool-renderer.js uses server-provided fileLinks positions for file paths,
|
|
10
|
+
* so it only needs the URL patterns from this module.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
// Known file extensions for linkification
|
|
14
|
+
// IMPORTANT: Longer extensions MUST come before shorter prefixes (css before c, hpp before h, etc.)
|
|
15
|
+
// otherwise regex alternation will match the shorter one first (e.g., .c instead of .css)
|
|
16
|
+
export const FILE_EXTENSIONS = 'dockerignore|gitignore|graphql|makefile|prisma|svelte|astro|cmake|scss|sass|less|html|json|yaml|toml|bash|lock|conf|cpp|css|csv|cfg|hpp|htm|ini|jsx|log|sql|tsx|vue|xml|yml|env|txt|zsh|go|js|kt|md|py|rb|rs|sh|ts|c|h|java|swift';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Build regex pattern for file paths (requires at least one /)
|
|
20
|
+
* Matches: src/app.js, ./config.yaml, ../utils/helper.py, /home/user/file.txt
|
|
21
|
+
*/
|
|
22
|
+
export function buildPathPattern() {
|
|
23
|
+
return new RegExp(
|
|
24
|
+
'(' +
|
|
25
|
+
'(?:~/|\\.{0,2}/)?' + // Optional ~/ or ./ or ../ or /
|
|
26
|
+
'(?:[\\w@.-]+/)' + // At least one directory with /
|
|
27
|
+
'(?:[\\w@.-]+/)*' + // Additional directories
|
|
28
|
+
'[\\w@.-]+' + // Final filename
|
|
29
|
+
'(?:\\.(?:' + FILE_EXTENSIONS + '))?' + // Optional extension
|
|
30
|
+
')' +
|
|
31
|
+
'(:\\d+(?:[-:]\\d+)?|#L\\d+(?:-L\\d+)?)?', // Optional :line or #Lline (GitHub-style)
|
|
32
|
+
'g'
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Build regex pattern for standalone filenames (no path separator)
|
|
38
|
+
* Allows common filename characters including hyphens and numeric prefixes.
|
|
39
|
+
*
|
|
40
|
+
* Matches: server.py, app.js, CLAUDE.md, git-widget.js, app.test.ts, 21-tool-blocks.css
|
|
41
|
+
* Rejects: 1.2.3 (pure version numbers) via validation function
|
|
42
|
+
*
|
|
43
|
+
* Note: False positives (files that don't exist) are handled by click-time
|
|
44
|
+
* resolution - the preview will show "File not found" which is acceptable UX.
|
|
45
|
+
*/
|
|
46
|
+
export function buildStandalonePattern() {
|
|
47
|
+
return new RegExp(
|
|
48
|
+
// Word boundary start - not preceded by word char, dot, or slash
|
|
49
|
+
'(?<![\\w./])' +
|
|
50
|
+
// Filename: starts with letter, underscore, or digit
|
|
51
|
+
// Allows hyphens, underscores, alphanumeric, and dots
|
|
52
|
+
'(' +
|
|
53
|
+
'[A-Za-z0-9_]' + // Start with letter, digit, or underscore
|
|
54
|
+
'[A-Za-z0-9_-]*' + // Followed by alphanumeric, underscore, or hyphen
|
|
55
|
+
'(?:\\.[A-Za-z0-9_-]+)*' + // Optional .middle.parts (also allow hyphens)
|
|
56
|
+
'\\.(?:' + FILE_EXTENSIONS + ')' + // Required .extension
|
|
57
|
+
')' +
|
|
58
|
+
'(:\\d+(?:[-:]\\d+)?|#L\\d+(?:-L\\d+)?)?' + // Optional :line or #Lline (GitHub-style)
|
|
59
|
+
'(?![\\w.])', // Word boundary end (not followed by word char or dot)
|
|
60
|
+
'g'
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Validate a standalone filename match to filter out false positives.
|
|
66
|
+
* Called after regex match for additional filtering.
|
|
67
|
+
*
|
|
68
|
+
* Note: We allow hyphenated filenames (git-widget.js, my-component.ts) since
|
|
69
|
+
* these are common in modern projects. Click-time resolution handles files
|
|
70
|
+
* that don't exist by showing "File not found" in the preview.
|
|
71
|
+
*
|
|
72
|
+
* @param {string} filename - The matched filename (e.g., "server.py")
|
|
73
|
+
* @param {string} precedingText - Text before the match for context
|
|
74
|
+
* @returns {boolean} - True if this looks like a real file reference
|
|
75
|
+
*/
|
|
76
|
+
export function isValidStandaloneFile(filename, precedingText = '') {
|
|
77
|
+
// Reject version patterns like "1.0.0" or "v1.0"
|
|
78
|
+
if (/^\d+\.\d+/.test(filename)) {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Reject if preceded by "v" or "version" (version indicator)
|
|
83
|
+
// e.g., "version 1.0.0", "v2.0.0"
|
|
84
|
+
if (/(?:^|[^a-zA-Z])v(?:ersion)?\s*$/i.test(precedingText)) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Reject all-caps single words that are likely acronyms/constants
|
|
89
|
+
// But allow things like "README.md", "CHANGELOG.md"
|
|
90
|
+
const namePart = filename.split('.')[0];
|
|
91
|
+
if (/^[A-Z]{1,3}$/.test(namePart)) {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Parse line info string into structured options for file preview.
|
|
100
|
+
*
|
|
101
|
+
* Supported formats:
|
|
102
|
+
* - :42 → { line: 42 }
|
|
103
|
+
* - :42:5 → { line: 42, col: 5 }
|
|
104
|
+
* - :42-50 → { start: 42, end: 50 }
|
|
105
|
+
* - #L42 → { line: 42 }
|
|
106
|
+
* - #L42-L50 → { start: 42, end: 50 }
|
|
107
|
+
* - (empty) → null
|
|
108
|
+
*
|
|
109
|
+
* @param {string} lineInfo - Line info string (e.g., ':219-220', ':42', ':42:5')
|
|
110
|
+
* @returns {object|null} - Parsed line info or null if empty/invalid
|
|
111
|
+
*/
|
|
112
|
+
export function parseLineInfo(lineInfo) {
|
|
113
|
+
if (!lineInfo) return null;
|
|
114
|
+
|
|
115
|
+
// Handle GitHub-style: #L42 or #L42-L50
|
|
116
|
+
const githubMatch = lineInfo.match(/^#L(\d+)(?:-L(\d+))?$/);
|
|
117
|
+
if (githubMatch) {
|
|
118
|
+
const line = parseInt(githubMatch[1], 10);
|
|
119
|
+
if (githubMatch[2]) {
|
|
120
|
+
return { start: line, end: parseInt(githubMatch[2], 10) };
|
|
121
|
+
}
|
|
122
|
+
return { line };
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Handle standard: :42, :42:5, :42-50
|
|
126
|
+
const standardMatch = lineInfo.match(/^:(\d+)(?:([-:])(\d+))?$/);
|
|
127
|
+
if (standardMatch) {
|
|
128
|
+
const first = parseInt(standardMatch[1], 10);
|
|
129
|
+
if (standardMatch[3]) {
|
|
130
|
+
const separator = standardMatch[2];
|
|
131
|
+
const second = parseInt(standardMatch[3], 10);
|
|
132
|
+
if (separator === '-') {
|
|
133
|
+
// Line range: :42-50
|
|
134
|
+
return { start: first, end: second };
|
|
135
|
+
} else {
|
|
136
|
+
// Line with column: :42:5
|
|
137
|
+
return { line: first, col: second };
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return { line: first };
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Build URL pattern for linkification (higher priority than file paths)
|
|
148
|
+
*/
|
|
149
|
+
export function buildUrlPattern() {
|
|
150
|
+
return /https?:\/\/[^\s<>"')\]]+/gi;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Clean trailing punctuation and HTML entities from a URL match.
|
|
155
|
+
* Handles both literal punctuation and HTML-encoded quotes that appear
|
|
156
|
+
* when linkifying after marked.js has processed the text.
|
|
157
|
+
* @param {string} url - The matched URL
|
|
158
|
+
* @returns {{url: string, trimmed: number}} - Cleaned URL and chars trimmed
|
|
159
|
+
*/
|
|
160
|
+
export function cleanUrlTrailingPunct(url) {
|
|
161
|
+
let trimmed = 0;
|
|
162
|
+
|
|
163
|
+
// First, strip HTML quote entities that marked.js may have added
|
|
164
|
+
// These appear when URLs are inside code blocks or quoted strings
|
|
165
|
+
// Order matters: check longer patterns first
|
|
166
|
+
const htmlEntities = [
|
|
167
|
+
/"$/, // "
|
|
168
|
+
/'$/, // ' (hex)
|
|
169
|
+
/'$/, // ' (decimal)
|
|
170
|
+
/'$/, // ' (named)
|
|
171
|
+
/"$/, // " (hex)
|
|
172
|
+
/"$/, // " (decimal)
|
|
173
|
+
];
|
|
174
|
+
|
|
175
|
+
// Keep stripping entities until none match
|
|
176
|
+
let changed = true;
|
|
177
|
+
while (changed) {
|
|
178
|
+
changed = false;
|
|
179
|
+
for (const pattern of htmlEntities) {
|
|
180
|
+
const match = url.match(pattern);
|
|
181
|
+
if (match) {
|
|
182
|
+
url = url.slice(0, -match[0].length);
|
|
183
|
+
trimmed += match[0].length;
|
|
184
|
+
changed = true;
|
|
185
|
+
break; // Restart from beginning of patterns
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Then strip regular trailing punctuation
|
|
191
|
+
const trailingPunct = /[.,;:!?)]+$/;
|
|
192
|
+
const match = url.match(trailingPunct);
|
|
193
|
+
if (match) {
|
|
194
|
+
return {
|
|
195
|
+
url: url.slice(0, -match[0].length),
|
|
196
|
+
trimmed: trimmed + match[0].length
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
return { url, trimmed };
|
|
200
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Login page behaviour. Extracted from an inline <script> in login.html so
|
|
3
|
+
* the CSP can keep script-src free of 'unsafe-inline'.
|
|
4
|
+
*
|
|
5
|
+
* Config arrives in the <script type="application/json" id="login-config">
|
|
6
|
+
* data block the server fills in — a non-JS type is never executed, so CSP
|
|
7
|
+
* does not gate it.
|
|
8
|
+
*/
|
|
9
|
+
(function () {
|
|
10
|
+
const form = document.getElementById('login-form');
|
|
11
|
+
const input = document.getElementById('password');
|
|
12
|
+
const error = document.getElementById('error');
|
|
13
|
+
const revealCmd = document.getElementById('reveal-cmd');
|
|
14
|
+
|
|
15
|
+
// Pick an environment-appropriate "reveal password" command. The server
|
|
16
|
+
// fills the #login-config data block with the detected environment and
|
|
17
|
+
// the resolved auth-config path (correct for local, Docker and the
|
|
18
|
+
// Codespaces Feature's /workspaces/.painapple-code/auth.yaml alike).
|
|
19
|
+
function loginConfig() {
|
|
20
|
+
try {
|
|
21
|
+
const el = document.getElementById('login-config');
|
|
22
|
+
const raw = el && el.textContent && el.textContent.trim();
|
|
23
|
+
const cfg = raw ? JSON.parse(raw) : null;
|
|
24
|
+
if (cfg && typeof cfg === 'object') return cfg;
|
|
25
|
+
} catch (e) { /* fall through to defaults */ }
|
|
26
|
+
return {};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
(function setupRevealCmd() {
|
|
30
|
+
const cfg = loginConfig();
|
|
31
|
+
const env = cfg.environment || 'local';
|
|
32
|
+
const path = cfg.configPath || '~/.config/painapple-code/config.yaml';
|
|
33
|
+
const awkCmd = "awk '/^password:/ {print $2}' " + path;
|
|
34
|
+
// `painapple password` is the better answer where it applies: one
|
|
35
|
+
// memorable verb instead of a copy-exactly one-liner, and it prints
|
|
36
|
+
// the api_token and ready-made ?tkn= login URLs alongside the
|
|
37
|
+
// password. But it resolves the DEFAULT config path with no
|
|
38
|
+
// --auth-config-file equivalent, so on an instance running a custom
|
|
39
|
+
// config it would print a DIFFERENT instance's credential — worse
|
|
40
|
+
// than awk, because it looks like it worked. The server tells us
|
|
41
|
+
// whether the two agree; when they don't, awk against the real path
|
|
42
|
+
// is the only command that can't lie.
|
|
43
|
+
const shellCmd = cfg.configIsDefault ? 'painapple password' : awkCmd;
|
|
44
|
+
const CMDS = {
|
|
45
|
+
local: shellCmd,
|
|
46
|
+
codespaces: shellCmd,
|
|
47
|
+
devcontainer: shellCmd,
|
|
48
|
+
docker: "docker exec painapple-code " + awkCmd,
|
|
49
|
+
podman: "podman exec painapple-code " + awkCmd,
|
|
50
|
+
container: "painapple password --in-docker",
|
|
51
|
+
kubernetes: "kubectl exec deploy/painapple-code -- " + awkCmd,
|
|
52
|
+
};
|
|
53
|
+
const LABELS = {
|
|
54
|
+
docker: 'Reveal the password from the Docker host:',
|
|
55
|
+
podman: 'Reveal the password from the host:',
|
|
56
|
+
container: 'Reveal the password from the host:',
|
|
57
|
+
kubernetes: 'Reveal the password from the cluster:',
|
|
58
|
+
};
|
|
59
|
+
// A launcher can inject the exact command (it knows the host-side
|
|
60
|
+
// container name / store / engine this page can't). Prefer it
|
|
61
|
+
// verbatim; otherwise fall back to the per-environment guess.
|
|
62
|
+
const cmd = cfg.revealCmd || CMDS[env] || awkCmd;
|
|
63
|
+
revealCmd.setAttribute('data-cmd', cmd);
|
|
64
|
+
const code = revealCmd.querySelector('code');
|
|
65
|
+
if (code) code.textContent = cmd;
|
|
66
|
+
const label = document.getElementById('reveal-label');
|
|
67
|
+
const labelText = cfg.revealCmd ? 'Reveal the password from the host:' : LABELS[env];
|
|
68
|
+
if (label && labelText) label.textContent = labelText;
|
|
69
|
+
})();
|
|
70
|
+
|
|
71
|
+
const rawNext = new URLSearchParams(location.search).get('next') || '';
|
|
72
|
+
|
|
73
|
+
let copyResetTimer = null;
|
|
74
|
+
revealCmd.addEventListener('click', async function () {
|
|
75
|
+
const cmd = revealCmd.getAttribute('data-cmd');
|
|
76
|
+
const status = revealCmd.querySelector('.login-cmd-status');
|
|
77
|
+
let ok = false;
|
|
78
|
+
try {
|
|
79
|
+
if (navigator.clipboard && navigator.clipboard.writeText) {
|
|
80
|
+
await navigator.clipboard.writeText(cmd);
|
|
81
|
+
ok = true;
|
|
82
|
+
} else {
|
|
83
|
+
const ta = document.createElement('textarea');
|
|
84
|
+
ta.value = cmd;
|
|
85
|
+
ta.setAttribute('readonly', '');
|
|
86
|
+
ta.style.position = 'absolute';
|
|
87
|
+
ta.style.left = '-9999px';
|
|
88
|
+
document.body.appendChild(ta);
|
|
89
|
+
ta.select();
|
|
90
|
+
ok = document.execCommand('copy');
|
|
91
|
+
document.body.removeChild(ta);
|
|
92
|
+
}
|
|
93
|
+
} catch (_) { ok = false; }
|
|
94
|
+
|
|
95
|
+
revealCmd.classList.toggle('copied', ok);
|
|
96
|
+
revealCmd.classList.toggle('copy-failed', !ok);
|
|
97
|
+
status.textContent = ok ? 'Copied' : 'Press ⌘C';
|
|
98
|
+
clearTimeout(copyResetTimer);
|
|
99
|
+
copyResetTimer = setTimeout(function () {
|
|
100
|
+
revealCmd.classList.remove('copied', 'copy-failed');
|
|
101
|
+
status.textContent = 'Copy';
|
|
102
|
+
}, 1600);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
form.addEventListener('submit', async function (e) {
|
|
106
|
+
e.preventDefault();
|
|
107
|
+
error.hidden = true;
|
|
108
|
+
input.classList.remove('shake');
|
|
109
|
+
|
|
110
|
+
const pw = input.value;
|
|
111
|
+
if (!pw) return;
|
|
112
|
+
|
|
113
|
+
try {
|
|
114
|
+
const r = await fetch('/api/login', {
|
|
115
|
+
method: 'POST',
|
|
116
|
+
headers: { 'content-type': 'application/json' },
|
|
117
|
+
body: JSON.stringify({ password: pw, next: rawNext }),
|
|
118
|
+
credentials: 'same-origin',
|
|
119
|
+
});
|
|
120
|
+
if (r.ok) {
|
|
121
|
+
const body = await r.json();
|
|
122
|
+
// Redirect only to the server-sanitized next — never
|
|
123
|
+
// location.search directly.
|
|
124
|
+
location.href = body.next || '/app';
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (r.status === 401) {
|
|
128
|
+
error.textContent = 'Incorrect password';
|
|
129
|
+
} else {
|
|
130
|
+
error.textContent = 'Login failed (' + r.status + ')';
|
|
131
|
+
}
|
|
132
|
+
error.hidden = false;
|
|
133
|
+
input.classList.add('shake');
|
|
134
|
+
input.select();
|
|
135
|
+
} catch (err) {
|
|
136
|
+
error.textContent = 'Network error';
|
|
137
|
+
error.hidden = false;
|
|
138
|
+
input.classList.add('shake');
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
})();
|