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.
Files changed (436) hide show
  1. painapple_code/__init__.py +30 -0
  2. painapple_code/__main__.py +18 -0
  3. painapple_code/_version.py +24 -0
  4. painapple_code/auth_middleware.py +930 -0
  5. painapple_code/cli/__init__.py +204 -0
  6. painapple_code/cli/deploy/__init__.py +15 -0
  7. painapple_code/cli/deploy/claude_seed.py +41 -0
  8. painapple_code/cli/deploy/config.py +260 -0
  9. painapple_code/cli/deploy/container.py +715 -0
  10. painapple_code/cli/deploy/launch.py +163 -0
  11. painapple_code/cli/deploy/runtime.py +223 -0
  12. painapple_code/cli/lifecycle_cmd.py +443 -0
  13. painapple_code/cli/list_cmd.py +572 -0
  14. painapple_code/cli/manage_cmd.py +670 -0
  15. painapple_code/cli/netinfo.py +125 -0
  16. painapple_code/cli/profiles.py +390 -0
  17. painapple_code/cli/serve_args.py +163 -0
  18. painapple_code/cli/serve_config.py +256 -0
  19. painapple_code/cli/setup_cmd.py +664 -0
  20. painapple_code/cli/ui.py +438 -0
  21. painapple_code/cost_analytics.py +879 -0
  22. painapple_code/data/models.defaults.yaml +18 -0
  23. painapple_code/data/models.yaml +18 -0
  24. painapple_code/data/presets.defaults.json +32 -0
  25. painapple_code/data/strings.yaml +2269 -0
  26. painapple_code/helpers.py +406 -0
  27. painapple_code/paths.py +1514 -0
  28. painapple_code/prompt_explorer.py +984 -0
  29. painapple_code/providers/__init__.py +224 -0
  30. painapple_code/providers/base.py +710 -0
  31. painapple_code/providers/claude/__init__.py +74 -0
  32. painapple_code/providers/claude/capabilities.py +218 -0
  33. painapple_code/providers/claude/errors.py +79 -0
  34. painapple_code/providers/claude/launch.py +50 -0
  35. painapple_code/providers/claude/summary.py +89 -0
  36. painapple_code/providers/claude/translate.py +74 -0
  37. painapple_code/providers/claude_sdk/__init__.py +139 -0
  38. painapple_code/providers/claude_sdk/driver.py +412 -0
  39. painapple_code/providers/codex/__init__.py +87 -0
  40. painapple_code/providers/codex/capabilities.py +321 -0
  41. painapple_code/providers/codex/errors.py +70 -0
  42. painapple_code/providers/codex/launch.py +142 -0
  43. painapple_code/providers/codex/summary.py +196 -0
  44. painapple_code/providers/codex/translate.py +204 -0
  45. painapple_code/providers/codex_app_server/__init__.py +100 -0
  46. painapple_code/providers/codex_app_server/capabilities.py +41 -0
  47. painapple_code/providers/codex_app_server/launch.py +202 -0
  48. painapple_code/providers/codex_app_server/summary.py +291 -0
  49. painapple_code/providers/codex_app_server/translate.py +263 -0
  50. painapple_code/providers/codex_app_server/transport.py +238 -0
  51. painapple_code/routes/__init__.py +0 -0
  52. painapple_code/routes/api_agents.py +441 -0
  53. painapple_code/routes/api_app.py +368 -0
  54. painapple_code/routes/api_app_commit_sections.py +127 -0
  55. painapple_code/routes/api_app_config.py +997 -0
  56. painapple_code/routes/api_app_session_prefs.py +217 -0
  57. painapple_code/routes/api_browser.py +690 -0
  58. painapple_code/routes/api_commands.py +374 -0
  59. painapple_code/routes/api_costs.py +128 -0
  60. painapple_code/routes/api_drafts.py +139 -0
  61. painapple_code/routes/api_exec.py +149 -0
  62. painapple_code/routes/api_files.py +542 -0
  63. painapple_code/routes/api_git.py +657 -0
  64. painapple_code/routes/api_logs.py +649 -0
  65. painapple_code/routes/api_plugins.py +275 -0
  66. painapple_code/routes/api_project_config.py +418 -0
  67. painapple_code/routes/api_prompts.py +231 -0
  68. painapple_code/routes/api_providers.py +53 -0
  69. painapple_code/routes/api_search.py +411 -0
  70. painapple_code/routes/api_session_stash.py +234 -0
  71. painapple_code/routes/api_session_welcome.py +151 -0
  72. painapple_code/routes/api_sessions.py +742 -0
  73. painapple_code/routes/api_shadow.py +323 -0
  74. painapple_code/routes/api_shadow_db.py +512 -0
  75. painapple_code/routes/api_shadow_files.py +332 -0
  76. painapple_code/routes/api_shadow_search.py +476 -0
  77. painapple_code/routes/api_skills.py +610 -0
  78. painapple_code/routes/api_tasks.py +147 -0
  79. painapple_code/routes/api_terminal.py +540 -0
  80. painapple_code/routes/api_upload.py +293 -0
  81. painapple_code/routes/api_viewer.py +229 -0
  82. painapple_code/routes/dependencies.py +109 -0
  83. painapple_code/routes/ws_chat.py +837 -0
  84. painapple_code/server.py +2208 -0
  85. painapple_code/server_logging.py +263 -0
  86. painapple_code/services/__init__.py +0 -0
  87. painapple_code/services/agent_session.py +2738 -0
  88. painapple_code/session_store.py +253 -0
  89. painapple_code/session_store_core.py +879 -0
  90. painapple_code/shadow_db.py +830 -0
  91. painapple_code/shadow_db_plans.py +369 -0
  92. painapple_code/shadow_db_queries.py +595 -0
  93. painapple_code/shadow_db_schema.py +676 -0
  94. painapple_code/shadow_git.py +1296 -0
  95. painapple_code/shadow_git_frontmatter.py +314 -0
  96. painapple_code/shadow_git_sections.py +520 -0
  97. painapple_code/shadow_git_summary.py +462 -0
  98. painapple_code/shadow_parser.py +560 -0
  99. painapple_code/static/css/00-variables.css +276 -0
  100. painapple_code/static/css/01-base.css +245 -0
  101. painapple_code/static/css/02-tooltips.css +36 -0
  102. painapple_code/static/css/09-left-rail.css +448 -0
  103. painapple_code/static/css/10-header.css +777 -0
  104. painapple_code/static/css/11-connection-bar.css +120 -0
  105. painapple_code/static/css/20-messages.css +750 -0
  106. painapple_code/static/css/21-tool-blocks.css +2340 -0
  107. painapple_code/static/css/22-edit-diff.css +619 -0
  108. painapple_code/static/css/23-thinking.css +1584 -0
  109. painapple_code/static/css/24-background-tasks.css +359 -0
  110. painapple_code/static/css/25-context-block.css +252 -0
  111. painapple_code/static/css/26-session-setup.css +144 -0
  112. painapple_code/static/css/30-markdown.css +854 -0
  113. painapple_code/static/css/40-input.css +2418 -0
  114. painapple_code/static/css/41-autocomplete.css +127 -0
  115. painapple_code/static/css/42-activity-strip.css +97 -0
  116. painapple_code/static/css/43-file-autocomplete.css +121 -0
  117. painapple_code/static/css/44-snippets-autocomplete.css +224 -0
  118. painapple_code/static/css/45-selection-bar.css +433 -0
  119. painapple_code/static/css/46-keyboard-bar.css +119 -0
  120. painapple_code/static/css/47-keyboard-longpress.css +116 -0
  121. painapple_code/static/css/47-token-profile.css +106 -0
  122. painapple_code/static/css/50-welcome.css +3095 -0
  123. painapple_code/static/css/51-modals.css +301 -0
  124. painapple_code/static/css/52-utilities.css +77 -0
  125. painapple_code/static/css/53-image-upload.css +456 -0
  126. painapple_code/static/css/54-todo-list.css +102 -0
  127. painapple_code/static/css/55-file-upload.css +113 -0
  128. painapple_code/static/css/56-chat-navigator.css +218 -0
  129. painapple_code/static/css/56-permission-card.css +332 -0
  130. painapple_code/static/css/56-plan-approval.css +204 -0
  131. painapple_code/static/css/56-question-form.css +602 -0
  132. painapple_code/static/css/57-swipe-indicator.css +95 -0
  133. painapple_code/static/css/58-session-families.css +627 -0
  134. painapple_code/static/css/59-about.css +196 -0
  135. painapple_code/static/css/61-log-explorer.css +723 -0
  136. painapple_code/static/css/62-json-tree.css +489 -0
  137. painapple_code/static/css/62-skills-widget.css +650 -0
  138. painapple_code/static/css/63-commands-widget.css +30 -0
  139. painapple_code/static/css/63-plugins-widget.css +174 -0
  140. painapple_code/static/css/63-terminal.css +516 -0
  141. painapple_code/static/css/64-search-files-widget.css +448 -0
  142. painapple_code/static/css/65-snippets-widget.css +426 -0
  143. painapple_code/static/css/66-active-sessions.css +979 -0
  144. painapple_code/static/css/66-agents-widget.css +265 -0
  145. painapple_code/static/css/66-file-explorer-widget.css +855 -0
  146. painapple_code/static/css/66-git-panel.css +791 -0
  147. painapple_code/static/css/66-history-explorer.css +1496 -0
  148. painapple_code/static/css/67-diff-viewer.css +602 -0
  149. painapple_code/static/css/67-editor-view.css +748 -0
  150. painapple_code/static/css/67-file-preview-widget.css +1873 -0
  151. painapple_code/static/css/68-browser-widget.css +337 -0
  152. painapple_code/static/css/68-compare-wizard.css +355 -0
  153. painapple_code/static/css/68-csv-preview.css +106 -0
  154. painapple_code/static/css/68-diff-preview.css +103 -0
  155. painapple_code/static/css/68-helpers-install-widget.css +491 -0
  156. painapple_code/static/css/68-image-annotate.css +346 -0
  157. painapple_code/static/css/68-terminal-view.css +98 -0
  158. painapple_code/static/css/68-uploads-widget.css +229 -0
  159. painapple_code/static/css/69-cost-analytics.css +537 -0
  160. painapple_code/static/css/70-config-panel.css +3736 -0
  161. painapple_code/static/css/70-excalidraw.css +136 -0
  162. painapple_code/static/css/70-prompt-explorer.css +890 -0
  163. painapple_code/static/css/71-chart.css +111 -0
  164. painapple_code/static/css/72-discussion-sidebar.css +678 -0
  165. painapple_code/static/css/74-debug-logs.css +656 -0
  166. painapple_code/static/css/80-open-dialog.css +146 -0
  167. painapple_code/static/css/80-quick-switcher.css +383 -0
  168. painapple_code/static/css/80-widget-system.css +1763 -0
  169. painapple_code/static/css/81-quick-actions.css +1020 -0
  170. painapple_code/static/css/82-context-popover.css +1233 -0
  171. painapple_code/static/css/83-context-menu.css +339 -0
  172. painapple_code/static/css/85-lazy-loading.css +102 -0
  173. painapple_code/static/css/86-zen-mode.css +708 -0
  174. painapple_code/static/css/87-grid-switcher.css +346 -0
  175. painapple_code/static/css/login.css +198 -0
  176. painapple_code/static/dist/app.bundle.js +7177 -0
  177. painapple_code/static/feature-triage.html +446 -0
  178. painapple_code/static/icons/apple-touch-icon.png +0 -0
  179. painapple_code/static/icons/favicon-32.png +0 -0
  180. painapple_code/static/icons/favicon.ico +0 -0
  181. painapple_code/static/icons/icon-128.png +0 -0
  182. painapple_code/static/icons/icon-144.png +0 -0
  183. painapple_code/static/icons/icon-152.png +0 -0
  184. painapple_code/static/icons/icon-180.png +0 -0
  185. painapple_code/static/icons/icon-192.png +0 -0
  186. painapple_code/static/icons/icon-384.png +0 -0
  187. painapple_code/static/icons/icon-512.png +0 -0
  188. painapple_code/static/icons/icon-72.png +0 -0
  189. painapple_code/static/icons/icon-96.png +0 -0
  190. painapple_code/static/js/action-delegate.js +187 -0
  191. painapple_code/static/js/activity-strip.js +193 -0
  192. painapple_code/static/js/app/context-menus.js +619 -0
  193. painapple_code/static/js/app/file-preview.js +163 -0
  194. painapple_code/static/js/app/init-ui.js +574 -0
  195. painapple_code/static/js/app/input-events.js +561 -0
  196. painapple_code/static/js/app/input-resize.js +313 -0
  197. painapple_code/static/js/app/message-actions.js +419 -0
  198. painapple_code/static/js/app/panels.js +210 -0
  199. painapple_code/static/js/app/rendering-delegators.js +246 -0
  200. painapple_code/static/js/app/server-loading.js +365 -0
  201. painapple_code/static/js/app/session-ops.js +287 -0
  202. painapple_code/static/js/app/session-switch.js +443 -0
  203. painapple_code/static/js/app/settings-helpers.js +280 -0
  204. painapple_code/static/js/app/startup-welcome.js +290 -0
  205. painapple_code/static/js/app-context.js +157 -0
  206. painapple_code/static/js/app.js +2134 -0
  207. painapple_code/static/js/auth-fetch.js +46 -0
  208. painapple_code/static/js/background-tasks.js +274 -0
  209. painapple_code/static/js/boot.js +73 -0
  210. painapple_code/static/js/caret-position.js +171 -0
  211. painapple_code/static/js/chat-navigator.js +710 -0
  212. painapple_code/static/js/chat-search.js +323 -0
  213. painapple_code/static/js/command-executor.js +176 -0
  214. painapple_code/static/js/command-store.js +497 -0
  215. painapple_code/static/js/components.js +1414 -0
  216. painapple_code/static/js/config.js +218 -0
  217. painapple_code/static/js/context-menu.js +740 -0
  218. painapple_code/static/js/controllers/chat-controller.js +4252 -0
  219. painapple_code/static/js/controllers/dialog-controller.js +217 -0
  220. painapple_code/static/js/controllers/tab-controller.js +1828 -0
  221. painapple_code/static/js/controllers/thinking-controller.js +915 -0
  222. painapple_code/static/js/diff-utils.js +486 -0
  223. painapple_code/static/js/drafts-pill.js +95 -0
  224. painapple_code/static/js/editor-view.js +815 -0
  225. painapple_code/static/js/effort-settings.js +430 -0
  226. painapple_code/static/js/feature-triage.js +811 -0
  227. painapple_code/static/js/file-autocomplete.js +516 -0
  228. painapple_code/static/js/file-tabs.js +123 -0
  229. painapple_code/static/js/gestures.js +448 -0
  230. painapple_code/static/js/grid-switcher.js +334 -0
  231. painapple_code/static/js/input-handler.js +1472 -0
  232. painapple_code/static/js/keyboard-bar.js +495 -0
  233. painapple_code/static/js/layout-switcher.js +109 -0
  234. painapple_code/static/js/linkify-utils.js +200 -0
  235. painapple_code/static/js/login.js +141 -0
  236. painapple_code/static/js/open-dialog.js +879 -0
  237. painapple_code/static/js/orphan-terminals.js +373 -0
  238. painapple_code/static/js/path-utils.js +179 -0
  239. painapple_code/static/js/perf-marks.js +102 -0
  240. painapple_code/static/js/permission-settings.js +475 -0
  241. painapple_code/static/js/pointer-input.js +59 -0
  242. painapple_code/static/js/preview/json-tree-menu.js +226 -0
  243. painapple_code/static/js/preview/json-tree-toolbar.js +291 -0
  244. painapple_code/static/js/preview/json-tree.js +457 -0
  245. painapple_code/static/js/preview/preview-breadcrumb.js +387 -0
  246. painapple_code/static/js/preview/preview-edit.js +367 -0
  247. painapple_code/static/js/preview/preview-events.js +361 -0
  248. painapple_code/static/js/preview/preview-history.js +567 -0
  249. painapple_code/static/js/preview/preview-inline-edit.js +869 -0
  250. painapple_code/static/js/preview/preview-poll.js +108 -0
  251. painapple_code/static/js/preview/preview-render.js +572 -0
  252. painapple_code/static/js/preview/preview-search.js +421 -0
  253. painapple_code/static/js/preview/preview-state.js +256 -0
  254. painapple_code/static/js/preview/preview-utils.js +251 -0
  255. painapple_code/static/js/preview-plugins/chart-plugin.js +22 -0
  256. painapple_code/static/js/preview-plugins/csv-plugin.js +188 -0
  257. painapple_code/static/js/preview-plugins/diff-plugin.js +258 -0
  258. painapple_code/static/js/preview-plugins/excalidraw-plugin.js +25 -0
  259. painapple_code/static/js/preview-plugins/html-plugin.js +104 -0
  260. painapple_code/static/js/preview-plugins/image-plugin.js +20 -0
  261. painapple_code/static/js/preview-plugins/index.js +34 -0
  262. painapple_code/static/js/preview-plugins/json-plugin.js +99 -0
  263. painapple_code/static/js/preview-plugins/jsonl-plugin.js +152 -0
  264. painapple_code/static/js/preview-plugins/markdown-plugin.js +266 -0
  265. painapple_code/static/js/preview-plugins/panzoom-plugin.js +63 -0
  266. painapple_code/static/js/preview-plugins/plugin-helpers.js +282 -0
  267. painapple_code/static/js/project-color-picker.js +110 -0
  268. painapple_code/static/js/project-colors.js +163 -0
  269. painapple_code/static/js/prompt-favorites.js +187 -0
  270. painapple_code/static/js/quick-actions-menu.js +1736 -0
  271. painapple_code/static/js/quick-actions-registry.js +1239 -0
  272. painapple_code/static/js/quick-switcher/controller.js +294 -0
  273. painapple_code/static/js/quick-switcher/fuzzy-scorer.js +123 -0
  274. painapple_code/static/js/quick-switcher/index.js +30 -0
  275. painapple_code/static/js/quick-switcher/providers/base-provider.js +51 -0
  276. painapple_code/static/js/quick-switcher/providers/command-provider.js +56 -0
  277. painapple_code/static/js/quick-switcher/providers/file-provider.js +291 -0
  278. painapple_code/static/js/quick-switcher/providers/panel-provider.js +132 -0
  279. painapple_code/static/js/quick-switcher/providers/project-provider.js +361 -0
  280. painapple_code/static/js/quick-switcher/providers/read-files-provider.js +104 -0
  281. painapple_code/static/js/quick-switcher/providers/skills-provider.js +129 -0
  282. painapple_code/static/js/quick-switcher/registry.js +69 -0
  283. painapple_code/static/js/quick-switcher/ui/item.js +54 -0
  284. painapple_code/static/js/quick-switcher/ui/picker.js +464 -0
  285. painapple_code/static/js/recent-opens.js +40 -0
  286. painapple_code/static/js/scroll-manager.js +530 -0
  287. painapple_code/static/js/scroll-state-machine.js +359 -0
  288. painapple_code/static/js/selection/action-bar.js +793 -0
  289. painapple_code/static/js/selection/index.js +15 -0
  290. painapple_code/static/js/selection/selection-handler.js +877 -0
  291. painapple_code/static/js/selection/state.js +181 -0
  292. painapple_code/static/js/session/agent-progress.js +202 -0
  293. painapple_code/static/js/session/handle-agent-message.js +481 -0
  294. painapple_code/static/js/session/handle-message.js +550 -0
  295. painapple_code/static/js/session/interactive.js +587 -0
  296. painapple_code/static/js/session/message-store.js +271 -0
  297. painapple_code/static/js/session/messages.js +253 -0
  298. painapple_code/static/js/session/persistence.js +179 -0
  299. painapple_code/static/js/session/restore.js +136 -0
  300. painapple_code/static/js/session/sync.js +333 -0
  301. painapple_code/static/js/session-container-pool.js +371 -0
  302. painapple_code/static/js/session-setup-panel.js +274 -0
  303. painapple_code/static/js/session.js +1047 -0
  304. painapple_code/static/js/shortcut-hints.js +272 -0
  305. painapple_code/static/js/shortcuts.js +1146 -0
  306. painapple_code/static/js/skills-autocomplete.js +262 -0
  307. painapple_code/static/js/snippets-autocomplete.js +738 -0
  308. painapple_code/static/js/stash-refs-view.js +83 -0
  309. painapple_code/static/js/stash-ui.js +768 -0
  310. painapple_code/static/js/stash.js +785 -0
  311. painapple_code/static/js/status-bar.js +1184 -0
  312. painapple_code/static/js/token-profile.js +274 -0
  313. painapple_code/static/js/tool-renderer-blocks.js +1626 -0
  314. painapple_code/static/js/tool-renderer-thinking.js +813 -0
  315. painapple_code/static/js/tool-renderer.js +1500 -0
  316. painapple_code/static/js/tooltips.js +197 -0
  317. painapple_code/static/js/upload-manager.js +1019 -0
  318. painapple_code/static/js/utils.js +521 -0
  319. painapple_code/static/js/welcome/api.js +363 -0
  320. painapple_code/static/js/welcome/cards.js +626 -0
  321. painapple_code/static/js/welcome/context-menu.js +585 -0
  322. painapple_code/static/js/welcome/families.js +801 -0
  323. painapple_code/static/js/welcome/preview.js +234 -0
  324. painapple_code/static/js/welcome/state.js +129 -0
  325. painapple_code/static/js/welcome.js +1874 -0
  326. painapple_code/static/js/widget-system/base-widget.js +717 -0
  327. painapple_code/static/js/widget-system/device-manager.js +178 -0
  328. painapple_code/static/js/widget-system/event-bus.js +152 -0
  329. painapple_code/static/js/widget-system/icons.js +120 -0
  330. painapple_code/static/js/widget-system/index.js +49 -0
  331. painapple_code/static/js/widget-system/init.js +54 -0
  332. painapple_code/static/js/widget-system/types/bottom-sheet.js +307 -0
  333. painapple_code/static/js/widget-system/types/floating.js +915 -0
  334. painapple_code/static/js/widget-system/types/index.js +40 -0
  335. painapple_code/static/js/widget-system/types/modal.js +147 -0
  336. painapple_code/static/js/widget-system/types/sidebar.js +158 -0
  337. painapple_code/static/js/widget-system/types/tab.js +146 -0
  338. painapple_code/static/js/widget-system/types/top-sheet.js +203 -0
  339. painapple_code/static/js/widget-system/widget-manager.js +1187 -0
  340. painapple_code/static/js/widgets/about-widget.js +260 -0
  341. painapple_code/static/js/widgets/active-sessions-widget.js +760 -0
  342. painapple_code/static/js/widgets/agents-widget.js +897 -0
  343. painapple_code/static/js/widgets/browser-widget.js +579 -0
  344. painapple_code/static/js/widgets/commands-widget.js +694 -0
  345. painapple_code/static/js/widgets/config/commit-sections.js +449 -0
  346. painapple_code/static/js/widgets/config/dir-autocomplete.js +224 -0
  347. painapple_code/static/js/widgets/config/gestures.js +161 -0
  348. painapple_code/static/js/widgets/config/models-tab.js +988 -0
  349. painapple_code/static/js/widgets/config/quick-actions-tab.js +882 -0
  350. painapple_code/static/js/widgets/config/shortcut-editor.js +587 -0
  351. painapple_code/static/js/widgets/config/state.js +517 -0
  352. painapple_code/static/js/widgets/config/system-controls.js +90 -0
  353. painapple_code/static/js/widgets/config-widget.js +1535 -0
  354. painapple_code/static/js/widgets/cost-analytics-widget.js +621 -0
  355. painapple_code/static/js/widgets/debug-widget.js +693 -0
  356. painapple_code/static/js/widgets/diff-viewer-widget.js +1420 -0
  357. painapple_code/static/js/widgets/discussion-widget.js +1107 -0
  358. painapple_code/static/js/widgets/file-explorer-widget.js +2166 -0
  359. painapple_code/static/js/widgets/file-preview-widget.js +861 -0
  360. painapple_code/static/js/widgets/git-widget.js +794 -0
  361. painapple_code/static/js/widgets/helpers-install-widget.js +720 -0
  362. painapple_code/static/js/widgets/history-explorer-widget.js +1804 -0
  363. painapple_code/static/js/widgets/image-annotate-widget.js +951 -0
  364. painapple_code/static/js/widgets/image-preview-widget.js +692 -0
  365. painapple_code/static/js/widgets/index.js +176 -0
  366. painapple_code/static/js/widgets/log-explorer-widget.js +1057 -0
  367. painapple_code/static/js/widgets/plugins-widget.js +305 -0
  368. painapple_code/static/js/widgets/prompt-explorer-widget.js +1119 -0
  369. painapple_code/static/js/widgets/search-files-widget.js +529 -0
  370. painapple_code/static/js/widgets/skills-widget.js +843 -0
  371. painapple_code/static/js/widgets/snippets-widget.js +479 -0
  372. painapple_code/static/js/widgets/sub-agents-widget.js +333 -0
  373. painapple_code/static/js/widgets/tasks-widget.js +379 -0
  374. painapple_code/static/js/widgets/terminal/connection.js +283 -0
  375. painapple_code/static/js/widgets/terminal/gestures.js +357 -0
  376. painapple_code/static/js/widgets/terminal/init.js +642 -0
  377. painapple_code/static/js/widgets/terminal/link-providers.js +532 -0
  378. painapple_code/static/js/widgets/terminal/osc52.js +213 -0
  379. painapple_code/static/js/widgets/terminal/render.js +159 -0
  380. painapple_code/static/js/widgets/terminal/size.js +54 -0
  381. painapple_code/static/js/widgets/terminal/state.js +211 -0
  382. painapple_code/static/js/widgets/terminal/wrap-utils.js +101 -0
  383. painapple_code/static/js/widgets/terminal-widget.js +793 -0
  384. painapple_code/static/js/widgets/uploads-widget.js +461 -0
  385. painapple_code/static/js/widgets/zen-widget.js +1001 -0
  386. painapple_code/static/login.html +51 -0
  387. painapple_code/static/manifest.json +73 -0
  388. painapple_code/static/sw.js +293 -0
  389. painapple_code/static/vendor/LICENSES.txt +769 -0
  390. painapple_code/static/vendor/README.md +103 -0
  391. painapple_code/static/vendor/codemirror.js +35 -0
  392. painapple_code/static/vendor/codemirror.js.LEGAL.txt +304 -0
  393. painapple_code/static/vendor/github-markdown-dark.min.css +1124 -0
  394. painapple_code/static/vendor/highlight-github-dark.min.css +10 -0
  395. painapple_code/static/vendor/highlight-lang-dockerfile.min.js +8 -0
  396. painapple_code/static/vendor/highlight-lang-nginx.min.js +21 -0
  397. painapple_code/static/vendor/highlight-lang-properties.min.js +10 -0
  398. painapple_code/static/vendor/highlight-lang-scala.min.js +28 -0
  399. painapple_code/static/vendor/highlight.min.js +1213 -0
  400. painapple_code/static/vendor/marked.min.js +6 -0
  401. painapple_code/static/vendor/purify.min.js +3 -0
  402. painapple_code/static/vendor/xterm-addon-fit.js +2 -0
  403. painapple_code/static/vendor/xterm.css +209 -0
  404. painapple_code/static/vendor/xterm.js +2 -0
  405. painapple_code/static/web-client.html +635 -0
  406. painapple_code/subprocess_registry.py +535 -0
  407. painapple_code/tls_cert.py +79 -0
  408. painapple_code/tools/agents/shadow-git-helper.md +400 -0
  409. painapple_code/tools/excalidraw-to-svg.js +143 -0
  410. painapple_code/tools/install-helpers.sh +148 -0
  411. painapple_code/tools/shadow-git +320 -0
  412. painapple_code/tools/shadow-query +120 -0
  413. painapple_code/tools/vegalite-to-svg.js +79 -0
  414. painapple_code/turn_query.py +766 -0
  415. painapple_code/turn_tracker.py +221 -0
  416. painapple_code/utils/__init__.py +0 -0
  417. painapple_code/utils/agent_cli.py +306 -0
  418. painapple_code/utils/chart.py +103 -0
  419. painapple_code/utils/excalidraw.py +107 -0
  420. painapple_code/utils/file_lock.py +162 -0
  421. painapple_code/utils/file_paths.py +648 -0
  422. painapple_code/utils/generate_icons.py +251 -0
  423. painapple_code/utils/proc.py +205 -0
  424. painapple_code/utils/pty_backend.py +59 -0
  425. painapple_code/utils/pty_posix.py +160 -0
  426. painapple_code/utils/pty_windows.py +245 -0
  427. painapple_code/utils/token_profiles.py +91 -0
  428. painapple_code/viewer_templates.py +657 -0
  429. painapple_code/welcome_search.py +879 -0
  430. painapple_code-1.0.0.dist-info/METADATA +292 -0
  431. painapple_code-1.0.0.dist-info/RECORD +436 -0
  432. painapple_code-1.0.0.dist-info/WHEEL +5 -0
  433. painapple_code-1.0.0.dist-info/entry_points.txt +2 -0
  434. painapple_code-1.0.0.dist-info/licenses/LICENSE +661 -0
  435. painapple_code-1.0.0.dist-info/licenses/THIRD_PARTY_NOTICES.md +261 -0
  436. 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
+ /&quot;$/, // "
168
+ /&#x27;$/, // ' (hex)
169
+ /&#39;$/, // ' (decimal)
170
+ /&apos;$/, // ' (named)
171
+ /&#x22;$/, // " (hex)
172
+ /&#34;$/, // " (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
+ })();