pythinker-code 2.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 (731) hide show
  1. pythinker_code/CHANGELOG.md +16 -0
  2. pythinker_code/__init__.py +0 -0
  3. pythinker_code/__main__.py +92 -0
  4. pythinker_code/acp/AGENTS.md +93 -0
  5. pythinker_code/acp/__init__.py +13 -0
  6. pythinker_code/acp/convert.py +128 -0
  7. pythinker_code/acp/host.py +298 -0
  8. pythinker_code/acp/mcp.py +46 -0
  9. pythinker_code/acp/server.py +497 -0
  10. pythinker_code/acp/session.py +496 -0
  11. pythinker_code/acp/tools.py +167 -0
  12. pythinker_code/acp/types.py +13 -0
  13. pythinker_code/acp/version.py +45 -0
  14. pythinker_code/agents/default/agent.yaml +36 -0
  15. pythinker_code/agents/default/coder.yaml +25 -0
  16. pythinker_code/agents/default/explore.yaml +46 -0
  17. pythinker_code/agents/default/plan.yaml +30 -0
  18. pythinker_code/agents/default/system.md +164 -0
  19. pythinker_code/agents/okabe/agent.yaml +22 -0
  20. pythinker_code/agentspec.py +163 -0
  21. pythinker_code/app.py +820 -0
  22. pythinker_code/approval_runtime/__init__.py +29 -0
  23. pythinker_code/approval_runtime/models.py +42 -0
  24. pythinker_code/approval_runtime/runtime.py +235 -0
  25. pythinker_code/auth/__init__.py +25 -0
  26. pythinker_code/auth/anthropic_direct.py +207 -0
  27. pythinker_code/auth/deepseek.py +192 -0
  28. pythinker_code/auth/lm_studio.py +418 -0
  29. pythinker_code/auth/minimax.py +203 -0
  30. pythinker_code/auth/oauth.py +1122 -0
  31. pythinker_code/auth/ollama.py +293 -0
  32. pythinker_code/auth/openai.py +771 -0
  33. pythinker_code/auth/opencode_go.py +203 -0
  34. pythinker_code/auth/openrouter.py +225 -0
  35. pythinker_code/auth/platforms.py +466 -0
  36. pythinker_code/background/__init__.py +36 -0
  37. pythinker_code/background/agent_runner.py +231 -0
  38. pythinker_code/background/ids.py +19 -0
  39. pythinker_code/background/manager.py +650 -0
  40. pythinker_code/background/models.py +105 -0
  41. pythinker_code/background/store.py +237 -0
  42. pythinker_code/background/summary.py +66 -0
  43. pythinker_code/background/worker.py +209 -0
  44. pythinker_code/cli/__init__.py +1326 -0
  45. pythinker_code/cli/__main__.py +19 -0
  46. pythinker_code/cli/_lazy_group.py +238 -0
  47. pythinker_code/cli/export.py +322 -0
  48. pythinker_code/cli/info.py +62 -0
  49. pythinker_code/cli/mcp.py +349 -0
  50. pythinker_code/cli/plugin.py +351 -0
  51. pythinker_code/cli/toad.py +74 -0
  52. pythinker_code/cli/vis.py +38 -0
  53. pythinker_code/cli/web.py +80 -0
  54. pythinker_code/config.py +453 -0
  55. pythinker_code/constant.py +33 -0
  56. pythinker_code/exception.py +43 -0
  57. pythinker_code/hooks/__init__.py +4 -0
  58. pythinker_code/hooks/config.py +34 -0
  59. pythinker_code/hooks/engine.py +371 -0
  60. pythinker_code/hooks/events.py +190 -0
  61. pythinker_code/hooks/runner.py +89 -0
  62. pythinker_code/llm.py +412 -0
  63. pythinker_code/metadata.py +79 -0
  64. pythinker_code/notifications/__init__.py +33 -0
  65. pythinker_code/notifications/llm.py +77 -0
  66. pythinker_code/notifications/manager.py +145 -0
  67. pythinker_code/notifications/models.py +50 -0
  68. pythinker_code/notifications/notifier.py +41 -0
  69. pythinker_code/notifications/store.py +118 -0
  70. pythinker_code/notifications/wire.py +21 -0
  71. pythinker_code/plugin/__init__.py +124 -0
  72. pythinker_code/plugin/manager.py +153 -0
  73. pythinker_code/plugin/tool.py +173 -0
  74. pythinker_code/prompts/__init__.py +6 -0
  75. pythinker_code/prompts/compact.md +73 -0
  76. pythinker_code/prompts/init.md +21 -0
  77. pythinker_code/py.typed +0 -0
  78. pythinker_code/session.py +319 -0
  79. pythinker_code/session_fork.py +325 -0
  80. pythinker_code/session_state.py +132 -0
  81. pythinker_code/share.py +14 -0
  82. pythinker_code/skill/__init__.py +727 -0
  83. pythinker_code/skill/flow/__init__.py +99 -0
  84. pythinker_code/skill/flow/d2.py +482 -0
  85. pythinker_code/skill/flow/mermaid.py +266 -0
  86. pythinker_code/skills/pythinker-code-help/SKILL.md +54 -0
  87. pythinker_code/skills/skill-creator/SKILL.md +367 -0
  88. pythinker_code/soul/__init__.py +304 -0
  89. pythinker_code/soul/agent.py +520 -0
  90. pythinker_code/soul/approval.py +267 -0
  91. pythinker_code/soul/btw.py +214 -0
  92. pythinker_code/soul/compaction.py +189 -0
  93. pythinker_code/soul/context.py +339 -0
  94. pythinker_code/soul/denwarenji.py +39 -0
  95. pythinker_code/soul/dynamic_injection.py +84 -0
  96. pythinker_code/soul/dynamic_injections/__init__.py +0 -0
  97. pythinker_code/soul/dynamic_injections/auto_mode.py +72 -0
  98. pythinker_code/soul/dynamic_injections/plan_mode.py +239 -0
  99. pythinker_code/soul/message.py +92 -0
  100. pythinker_code/soul/pythinkersoul.py +1613 -0
  101. pythinker_code/soul/slash.py +340 -0
  102. pythinker_code/soul/toolset.py +788 -0
  103. pythinker_code/subagents/__init__.py +21 -0
  104. pythinker_code/subagents/builder.py +42 -0
  105. pythinker_code/subagents/core.py +86 -0
  106. pythinker_code/subagents/git_context.py +172 -0
  107. pythinker_code/subagents/models.py +54 -0
  108. pythinker_code/subagents/output.py +71 -0
  109. pythinker_code/subagents/registry.py +28 -0
  110. pythinker_code/subagents/runner.py +428 -0
  111. pythinker_code/subagents/store.py +196 -0
  112. pythinker_code/telemetry/__init__.py +211 -0
  113. pythinker_code/telemetry/config.py +54 -0
  114. pythinker_code/telemetry/crash.py +157 -0
  115. pythinker_code/telemetry/metrics.py +208 -0
  116. pythinker_code/telemetry/otel.py +240 -0
  117. pythinker_code/telemetry/sentry.py +167 -0
  118. pythinker_code/telemetry/sink.py +189 -0
  119. pythinker_code/tools/AGENTS.md +6 -0
  120. pythinker_code/tools/__init__.py +105 -0
  121. pythinker_code/tools/agent/__init__.py +277 -0
  122. pythinker_code/tools/agent/description.md +41 -0
  123. pythinker_code/tools/ask_user/__init__.py +159 -0
  124. pythinker_code/tools/ask_user/description.md +19 -0
  125. pythinker_code/tools/background/__init__.py +318 -0
  126. pythinker_code/tools/background/list.md +10 -0
  127. pythinker_code/tools/background/output.md +11 -0
  128. pythinker_code/tools/background/stop.md +8 -0
  129. pythinker_code/tools/display.py +46 -0
  130. pythinker_code/tools/dmail/__init__.py +38 -0
  131. pythinker_code/tools/dmail/dmail.md +17 -0
  132. pythinker_code/tools/file/__init__.py +30 -0
  133. pythinker_code/tools/file/glob.md +17 -0
  134. pythinker_code/tools/file/glob.py +160 -0
  135. pythinker_code/tools/file/grep.md +6 -0
  136. pythinker_code/tools/file/grep_local.py +589 -0
  137. pythinker_code/tools/file/plan_mode.py +45 -0
  138. pythinker_code/tools/file/read.md +16 -0
  139. pythinker_code/tools/file/read.py +300 -0
  140. pythinker_code/tools/file/read_media.md +24 -0
  141. pythinker_code/tools/file/read_media.py +217 -0
  142. pythinker_code/tools/file/replace.md +7 -0
  143. pythinker_code/tools/file/replace.py +195 -0
  144. pythinker_code/tools/file/utils.py +257 -0
  145. pythinker_code/tools/file/write.md +5 -0
  146. pythinker_code/tools/file/write.py +177 -0
  147. pythinker_code/tools/plan/__init__.py +327 -0
  148. pythinker_code/tools/plan/description.md +29 -0
  149. pythinker_code/tools/plan/enter.py +190 -0
  150. pythinker_code/tools/plan/enter_description.md +35 -0
  151. pythinker_code/tools/plan/heroes.py +277 -0
  152. pythinker_code/tools/shell/__init__.py +253 -0
  153. pythinker_code/tools/shell/bash.md +35 -0
  154. pythinker_code/tools/shell/powershell.md +30 -0
  155. pythinker_code/tools/test.py +55 -0
  156. pythinker_code/tools/think/__init__.py +21 -0
  157. pythinker_code/tools/think/think.md +1 -0
  158. pythinker_code/tools/todo/__init__.py +168 -0
  159. pythinker_code/tools/todo/set_todo_list.md +23 -0
  160. pythinker_code/tools/utils.py +199 -0
  161. pythinker_code/tools/web/__init__.py +4 -0
  162. pythinker_code/tools/web/fetch.md +1 -0
  163. pythinker_code/tools/web/fetch.py +189 -0
  164. pythinker_code/tools/web/search.md +1 -0
  165. pythinker_code/tools/web/search.py +163 -0
  166. pythinker_code/ui/__init__.py +0 -0
  167. pythinker_code/ui/acp/__init__.py +99 -0
  168. pythinker_code/ui/print/__init__.py +474 -0
  169. pythinker_code/ui/print/visualize.py +185 -0
  170. pythinker_code/ui/shell/__init__.py +1696 -0
  171. pythinker_code/ui/shell/console.py +109 -0
  172. pythinker_code/ui/shell/debug.py +190 -0
  173. pythinker_code/ui/shell/echo.py +17 -0
  174. pythinker_code/ui/shell/export_import.py +117 -0
  175. pythinker_code/ui/shell/keyboard.py +300 -0
  176. pythinker_code/ui/shell/mcp_status.py +113 -0
  177. pythinker_code/ui/shell/model_picker.py +318 -0
  178. pythinker_code/ui/shell/oauth.py +272 -0
  179. pythinker_code/ui/shell/placeholders.py +531 -0
  180. pythinker_code/ui/shell/prompt.py +2278 -0
  181. pythinker_code/ui/shell/replay.py +215 -0
  182. pythinker_code/ui/shell/session_picker.py +227 -0
  183. pythinker_code/ui/shell/setup.py +212 -0
  184. pythinker_code/ui/shell/slash.py +898 -0
  185. pythinker_code/ui/shell/startup.py +32 -0
  186. pythinker_code/ui/shell/task_browser.py +486 -0
  187. pythinker_code/ui/shell/update.py +350 -0
  188. pythinker_code/ui/shell/usage.py +291 -0
  189. pythinker_code/ui/shell/usage_adapters/__init__.py +50 -0
  190. pythinker_code/ui/shell/usage_adapters/anthropic_admin.py +233 -0
  191. pythinker_code/ui/shell/usage_adapters/base.py +72 -0
  192. pythinker_code/ui/shell/usage_adapters/deepseek.py +137 -0
  193. pythinker_code/ui/shell/usage_adapters/minimax.py +236 -0
  194. pythinker_code/ui/shell/usage_adapters/openai_admin.py +225 -0
  195. pythinker_code/ui/shell/usage_adapters/openai_chatgpt.py +241 -0
  196. pythinker_code/ui/shell/usage_adapters/opencode_go.py +232 -0
  197. pythinker_code/ui/shell/usage_adapters/openrouter.py +105 -0
  198. pythinker_code/ui/shell/usage_adapters/pythinker.py +189 -0
  199. pythinker_code/ui/shell/usage_adapters/pythinker_ai.py +50 -0
  200. pythinker_code/ui/shell/usage_render.py +150 -0
  201. pythinker_code/ui/shell/visualize/__init__.py +165 -0
  202. pythinker_code/ui/shell/visualize/_approval_panel.py +505 -0
  203. pythinker_code/ui/shell/visualize/_blocks.py +629 -0
  204. pythinker_code/ui/shell/visualize/_btw_panel.py +224 -0
  205. pythinker_code/ui/shell/visualize/_input_router.py +48 -0
  206. pythinker_code/ui/shell/visualize/_interactive.py +523 -0
  207. pythinker_code/ui/shell/visualize/_live_view.py +826 -0
  208. pythinker_code/ui/shell/visualize/_question_panel.py +586 -0
  209. pythinker_code/ui/theme.py +241 -0
  210. pythinker_code/usage_ratelimit_cache.py +175 -0
  211. pythinker_code/utils/__init__.py +0 -0
  212. pythinker_code/utils/aiohttp.py +24 -0
  213. pythinker_code/utils/aioqueue.py +72 -0
  214. pythinker_code/utils/broadcast.py +37 -0
  215. pythinker_code/utils/changelog.py +108 -0
  216. pythinker_code/utils/clipboard.py +246 -0
  217. pythinker_code/utils/datetime.py +64 -0
  218. pythinker_code/utils/diff.py +135 -0
  219. pythinker_code/utils/editor.py +91 -0
  220. pythinker_code/utils/environment.py +73 -0
  221. pythinker_code/utils/envvar.py +22 -0
  222. pythinker_code/utils/export.py +696 -0
  223. pythinker_code/utils/file_filter.py +375 -0
  224. pythinker_code/utils/frontmatter.py +70 -0
  225. pythinker_code/utils/io.py +27 -0
  226. pythinker_code/utils/logging.py +146 -0
  227. pythinker_code/utils/media_tags.py +29 -0
  228. pythinker_code/utils/message.py +24 -0
  229. pythinker_code/utils/path.py +199 -0
  230. pythinker_code/utils/proctitle.py +33 -0
  231. pythinker_code/utils/proxy.py +31 -0
  232. pythinker_code/utils/pyinstaller.py +45 -0
  233. pythinker_code/utils/rich/__init__.py +33 -0
  234. pythinker_code/utils/rich/columns.py +99 -0
  235. pythinker_code/utils/rich/diff_render.py +481 -0
  236. pythinker_code/utils/rich/markdown.py +900 -0
  237. pythinker_code/utils/rich/markdown_sample.md +108 -0
  238. pythinker_code/utils/rich/markdown_sample_short.md +2 -0
  239. pythinker_code/utils/rich/syntax.py +114 -0
  240. pythinker_code/utils/sensitive.py +54 -0
  241. pythinker_code/utils/server.py +121 -0
  242. pythinker_code/utils/signals.py +43 -0
  243. pythinker_code/utils/slashcmd.py +124 -0
  244. pythinker_code/utils/string.py +41 -0
  245. pythinker_code/utils/subprocess_env.py +73 -0
  246. pythinker_code/utils/term.py +168 -0
  247. pythinker_code/utils/typing.py +20 -0
  248. pythinker_code/vis/__init__.py +0 -0
  249. pythinker_code/vis/api/__init__.py +5 -0
  250. pythinker_code/vis/api/sessions.py +687 -0
  251. pythinker_code/vis/api/statistics.py +209 -0
  252. pythinker_code/vis/api/system.py +19 -0
  253. pythinker_code/vis/app.py +175 -0
  254. pythinker_code/vis/static/assets/highlighted-body-B3W2YXNL-D2MTYyJz.js +1 -0
  255. pythinker_code/vis/static/assets/index-CezafTt_.js +185 -0
  256. pythinker_code/vis/static/assets/index-DSRInNnm.css +1 -0
  257. pythinker_code/vis/static/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2 +0 -0
  258. pythinker_code/vis/static/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2 +0 -0
  259. pythinker_code/vis/static/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2 +0 -0
  260. pythinker_code/vis/static/assets/inter-greek-wght-normal-CkhJZR-_.woff2 +0 -0
  261. pythinker_code/vis/static/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
  262. pythinker_code/vis/static/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
  263. pythinker_code/vis/static/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2 +0 -0
  264. pythinker_code/vis/static/index.html +17 -0
  265. pythinker_code/web/__init__.py +5 -0
  266. pythinker_code/web/api/__init__.py +15 -0
  267. pythinker_code/web/api/config.py +208 -0
  268. pythinker_code/web/api/open_in.py +199 -0
  269. pythinker_code/web/api/sessions.py +1225 -0
  270. pythinker_code/web/app.py +451 -0
  271. pythinker_code/web/auth.py +191 -0
  272. pythinker_code/web/models.py +98 -0
  273. pythinker_code/web/runner/__init__.py +5 -0
  274. pythinker_code/web/runner/messages.py +57 -0
  275. pythinker_code/web/runner/process.py +754 -0
  276. pythinker_code/web/runner/worker.py +97 -0
  277. pythinker_code/web/static/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  278. pythinker_code/web/static/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  279. pythinker_code/web/static/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  280. pythinker_code/web/static/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  281. pythinker_code/web/static/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  282. pythinker_code/web/static/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  283. pythinker_code/web/static/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  284. pythinker_code/web/static/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  285. pythinker_code/web/static/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  286. pythinker_code/web/static/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  287. pythinker_code/web/static/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  288. pythinker_code/web/static/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  289. pythinker_code/web/static/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  290. pythinker_code/web/static/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  291. pythinker_code/web/static/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  292. pythinker_code/web/static/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  293. pythinker_code/web/static/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  294. pythinker_code/web/static/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  295. pythinker_code/web/static/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  296. pythinker_code/web/static/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  297. pythinker_code/web/static/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  298. pythinker_code/web/static/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  299. pythinker_code/web/static/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  300. pythinker_code/web/static/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  301. pythinker_code/web/static/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  302. pythinker_code/web/static/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  303. pythinker_code/web/static/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  304. pythinker_code/web/static/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  305. pythinker_code/web/static/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  306. pythinker_code/web/static/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  307. pythinker_code/web/static/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  308. pythinker_code/web/static/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  309. pythinker_code/web/static/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  310. pythinker_code/web/static/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  311. pythinker_code/web/static/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  312. pythinker_code/web/static/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  313. pythinker_code/web/static/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  314. pythinker_code/web/static/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  315. pythinker_code/web/static/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  316. pythinker_code/web/static/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  317. pythinker_code/web/static/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  318. pythinker_code/web/static/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  319. pythinker_code/web/static/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  320. pythinker_code/web/static/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  321. pythinker_code/web/static/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  322. pythinker_code/web/static/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  323. pythinker_code/web/static/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  324. pythinker_code/web/static/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  325. pythinker_code/web/static/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  326. pythinker_code/web/static/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  327. pythinker_code/web/static/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  328. pythinker_code/web/static/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  329. pythinker_code/web/static/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  330. pythinker_code/web/static/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  331. pythinker_code/web/static/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  332. pythinker_code/web/static/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  333. pythinker_code/web/static/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  334. pythinker_code/web/static/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  335. pythinker_code/web/static/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  336. pythinker_code/web/static/assets/_baseUniq--dyU3g5v.js +1 -0
  337. pythinker_code/web/static/assets/abap-BdImnpbu.js +1 -0
  338. pythinker_code/web/static/assets/actionscript-3-CfeIJUat.js +1 -0
  339. pythinker_code/web/static/assets/ada-bCR0ucgS.js +1 -0
  340. pythinker_code/web/static/assets/andromeeda-C-Jbm3Hp.js +1 -0
  341. pythinker_code/web/static/assets/angular-html-CU67Zn6k.js +1 -0
  342. pythinker_code/web/static/assets/angular-ts-BwZT4LLn.js +1 -0
  343. pythinker_code/web/static/assets/apache-Pmp26Uib.js +1 -0
  344. pythinker_code/web/static/assets/apex-D8_7TLub.js +1 -0
  345. pythinker_code/web/static/assets/apl-dKokRX4l.js +1 -0
  346. pythinker_code/web/static/assets/applescript-Co6uUVPk.js +1 -0
  347. pythinker_code/web/static/assets/ara-BRHolxvo.js +1 -0
  348. pythinker_code/web/static/assets/arc-DkMjLpYa.js +1 -0
  349. pythinker_code/web/static/assets/architectureDiagram-VXUJARFQ-CHWVaGo9.js +36 -0
  350. pythinker_code/web/static/assets/asciidoc-Dv7Oe6Be.js +1 -0
  351. pythinker_code/web/static/assets/asm-D_Q5rh1f.js +1 -0
  352. pythinker_code/web/static/assets/astro-CbQHKStN.js +1 -0
  353. pythinker_code/web/static/assets/aurora-x-D-2ljcwZ.js +1 -0
  354. pythinker_code/web/static/assets/awk-DMzUqQB5.js +1 -0
  355. pythinker_code/web/static/assets/ayu-dark-CmMr59Fi.js +1 -0
  356. pythinker_code/web/static/assets/ballerina-BFfxhgS-.js +1 -0
  357. pythinker_code/web/static/assets/bat-BkioyH1T.js +1 -0
  358. pythinker_code/web/static/assets/beancount-k_qm7-4y.js +1 -0
  359. pythinker_code/web/static/assets/berry-uYugtg8r.js +1 -0
  360. pythinker_code/web/static/assets/bibtex-CHM0blh-.js +1 -0
  361. pythinker_code/web/static/assets/bicep-Bmn6On1c.js +1 -0
  362. pythinker_code/web/static/assets/blade-D4QpJJKB.js +1 -0
  363. pythinker_code/web/static/assets/blockDiagram-VD42YOAC-DzdKe497.js +122 -0
  364. pythinker_code/web/static/assets/bsl-BO_Y6i37.js +1 -0
  365. pythinker_code/web/static/assets/c-BIGW1oBm.js +1 -0
  366. pythinker_code/web/static/assets/c3-VCDPK7BO.js +1 -0
  367. pythinker_code/web/static/assets/c4Diagram-YG6GDRKO-D84Blotg.js +10 -0
  368. pythinker_code/web/static/assets/cadence-Bv_4Rxtq.js +1 -0
  369. pythinker_code/web/static/assets/cairo-KRGpt6FW.js +1 -0
  370. pythinker_code/web/static/assets/catppuccin-frappe-DFWUc33u.js +1 -0
  371. pythinker_code/web/static/assets/catppuccin-latte-C9dUb6Cb.js +1 -0
  372. pythinker_code/web/static/assets/catppuccin-macchiato-DQyhUUbL.js +1 -0
  373. pythinker_code/web/static/assets/catppuccin-mocha-D87Tk5Gz.js +1 -0
  374. pythinker_code/web/static/assets/channel-CllSjjdl.js +1 -0
  375. pythinker_code/web/static/assets/chunk-4BX2VUAB-C9w8wleE.js +1 -0
  376. pythinker_code/web/static/assets/chunk-55IACEB6-YlYJ8HnF.js +1 -0
  377. pythinker_code/web/static/assets/chunk-B4BG7PRW-Bwtz_AHU.js +165 -0
  378. pythinker_code/web/static/assets/chunk-DI55MBZ5-BbEHkl8h.js +220 -0
  379. pythinker_code/web/static/assets/chunk-FMBD7UC4-BKPbvjLC.js +15 -0
  380. pythinker_code/web/static/assets/chunk-QN33PNHL-D73dQvKf.js +1 -0
  381. pythinker_code/web/static/assets/chunk-QZHKN3VN-zGiLKes_.js +1 -0
  382. pythinker_code/web/static/assets/chunk-TZMSLE5B-LHJCi2fy.js +1 -0
  383. pythinker_code/web/static/assets/clarity-D53aC0YG.js +1 -0
  384. pythinker_code/web/static/assets/classDiagram-2ON5EDUG-vX27iZwa.js +1 -0
  385. pythinker_code/web/static/assets/classDiagram-v2-WZHVMYZB-vX27iZwa.js +1 -0
  386. pythinker_code/web/static/assets/clojure-P80f7IUj.js +1 -0
  387. pythinker_code/web/static/assets/clone-DYBkaPm2.js +1 -0
  388. pythinker_code/web/static/assets/cmake-D1j8_8rp.js +1 -0
  389. pythinker_code/web/static/assets/cobol-nwyudZeR.js +1 -0
  390. pythinker_code/web/static/assets/code-block-IT6T5CEO-NtKViZGl.js +2 -0
  391. pythinker_code/web/static/assets/codeowners-Bp6g37R7.js +1 -0
  392. pythinker_code/web/static/assets/codeql-DsOJ9woJ.js +1 -0
  393. pythinker_code/web/static/assets/coffee-Ch7k5sss.js +1 -0
  394. pythinker_code/web/static/assets/common-lisp-Cg-RD9OK.js +1 -0
  395. pythinker_code/web/static/assets/coq-DkFqJrB1.js +1 -0
  396. pythinker_code/web/static/assets/cose-bilkent-S5V4N54A-DialjZpd.js +1 -0
  397. pythinker_code/web/static/assets/cpp-CofmeUqb.js +1 -0
  398. pythinker_code/web/static/assets/crystal-tKQVLTB8.js +1 -0
  399. pythinker_code/web/static/assets/csharp-K5feNrxe.js +1 -0
  400. pythinker_code/web/static/assets/css-DPfMkruS.js +1 -0
  401. pythinker_code/web/static/assets/csv-fuZLfV_i.js +1 -0
  402. pythinker_code/web/static/assets/cue-D82EKSYY.js +1 -0
  403. pythinker_code/web/static/assets/cypher-COkxafJQ.js +1 -0
  404. pythinker_code/web/static/assets/cytoscape.esm-C_Fzpdck.js +321 -0
  405. pythinker_code/web/static/assets/d-85-TOEBH.js +1 -0
  406. pythinker_code/web/static/assets/dagre-6UL2VRFP-DfuvkZZ7.js +4 -0
  407. pythinker_code/web/static/assets/dark-plus-C3mMm8J8.js +1 -0
  408. pythinker_code/web/static/assets/dart-CF10PKvl.js +1 -0
  409. pythinker_code/web/static/assets/dax-CEL-wOlO.js +1 -0
  410. pythinker_code/web/static/assets/defaultLocale-DX6XiGOO.js +1 -0
  411. pythinker_code/web/static/assets/desktop-BmXAJ9_W.js +1 -0
  412. pythinker_code/web/static/assets/diagram-PSM6KHXK-DLGctX3v.js +24 -0
  413. pythinker_code/web/static/assets/diagram-QEK2KX5R-DnxN6S0F.js +43 -0
  414. pythinker_code/web/static/assets/diagram-S2PKOQOG-Caq_Set9.js +24 -0
  415. pythinker_code/web/static/assets/diff-D97Zzqfu.js +1 -0
  416. pythinker_code/web/static/assets/docker-BcOcwvcX.js +1 -0
  417. pythinker_code/web/static/assets/dotenv-Da5cRb03.js +1 -0
  418. pythinker_code/web/static/assets/dracula-BzJJZx-M.js +1 -0
  419. pythinker_code/web/static/assets/dracula-soft-BXkSAIEj.js +1 -0
  420. pythinker_code/web/static/assets/dream-maker-BtqSS_iP.js +1 -0
  421. pythinker_code/web/static/assets/edge-BkV0erSs.js +1 -0
  422. pythinker_code/web/static/assets/elixir-CDX3lj18.js +1 -0
  423. pythinker_code/web/static/assets/elm-DbKCFpqz.js +1 -0
  424. pythinker_code/web/static/assets/emacs-lisp-C9XAeP06.js +1 -0
  425. pythinker_code/web/static/assets/erDiagram-Q2GNP2WA-BgTfALoK.js +60 -0
  426. pythinker_code/web/static/assets/erb-BOJIQeun.js +1 -0
  427. pythinker_code/web/static/assets/erlang-DsQrWhSR.js +1 -0
  428. pythinker_code/web/static/assets/everforest-dark-BgDCqdQA.js +1 -0
  429. pythinker_code/web/static/assets/everforest-light-C8M2exoo.js +1 -0
  430. pythinker_code/web/static/assets/fennel-BYunw83y.js +1 -0
  431. pythinker_code/web/static/assets/fish-BvzEVeQv.js +1 -0
  432. pythinker_code/web/static/assets/flowDiagram-NV44I4VS-QjW_fnGi.js +162 -0
  433. pythinker_code/web/static/assets/fluent-C4IJs8-o.js +1 -0
  434. pythinker_code/web/static/assets/fortran-fixed-form-CkoXwp7k.js +1 -0
  435. pythinker_code/web/static/assets/fortran-free-form-BxgE0vQu.js +1 -0
  436. pythinker_code/web/static/assets/fsharp-CXgrBDvD.js +1 -0
  437. pythinker_code/web/static/assets/ganttDiagram-JELNMOA3-fqi8JFof.js +267 -0
  438. pythinker_code/web/static/assets/gdresource-B7Tvp0Sc.js +1 -0
  439. pythinker_code/web/static/assets/gdscript-DTMYz4Jt.js +1 -0
  440. pythinker_code/web/static/assets/gdshader-DkwncUOv.js +1 -0
  441. pythinker_code/web/static/assets/genie-D0YGMca9.js +1 -0
  442. pythinker_code/web/static/assets/gherkin-DyxjwDmM.js +1 -0
  443. pythinker_code/web/static/assets/git-commit-F4YmCXRG.js +1 -0
  444. pythinker_code/web/static/assets/git-rebase-r7XF79zn.js +1 -0
  445. pythinker_code/web/static/assets/gitGraphDiagram-NY62KEGX-i7o6VQ8x.js +65 -0
  446. pythinker_code/web/static/assets/github-dark-DHJKELXO.js +1 -0
  447. pythinker_code/web/static/assets/github-dark-default-Cuk6v7N8.js +1 -0
  448. pythinker_code/web/static/assets/github-dark-dimmed-DH5Ifo-i.js +1 -0
  449. pythinker_code/web/static/assets/github-dark-high-contrast-E3gJ1_iC.js +1 -0
  450. pythinker_code/web/static/assets/github-light-DAi9KRSo.js +1 -0
  451. pythinker_code/web/static/assets/github-light-default-D7oLnXFd.js +1 -0
  452. pythinker_code/web/static/assets/github-light-high-contrast-BfjtVDDH.js +1 -0
  453. pythinker_code/web/static/assets/gleam-BspZqrRM.js +1 -0
  454. pythinker_code/web/static/assets/glimmer-js-Rg0-pVw9.js +1 -0
  455. pythinker_code/web/static/assets/glimmer-ts-U6CK756n.js +1 -0
  456. pythinker_code/web/static/assets/glsl-DplSGwfg.js +1 -0
  457. pythinker_code/web/static/assets/gn-n2N0HUVH.js +1 -0
  458. pythinker_code/web/static/assets/gnuplot-DdkO51Og.js +1 -0
  459. pythinker_code/web/static/assets/go-Dn2_MT6a.js +1 -0
  460. pythinker_code/web/static/assets/graph-C0vZK2pT.js +1 -0
  461. pythinker_code/web/static/assets/graphql-ChdNCCLP.js +1 -0
  462. pythinker_code/web/static/assets/groovy-gcz8RCvz.js +1 -0
  463. pythinker_code/web/static/assets/gruvbox-dark-hard-CFHQjOhq.js +1 -0
  464. pythinker_code/web/static/assets/gruvbox-dark-medium-GsRaNv29.js +1 -0
  465. pythinker_code/web/static/assets/gruvbox-dark-soft-CVdnzihN.js +1 -0
  466. pythinker_code/web/static/assets/gruvbox-light-hard-CH1njM8p.js +1 -0
  467. pythinker_code/web/static/assets/gruvbox-light-medium-DRw_LuNl.js +1 -0
  468. pythinker_code/web/static/assets/gruvbox-light-soft-hJgmCMqR.js +1 -0
  469. pythinker_code/web/static/assets/hack-CaT9iCJl.js +1 -0
  470. pythinker_code/web/static/assets/haml-B8DHNrY2.js +1 -0
  471. pythinker_code/web/static/assets/handlebars-BL8al0AC.js +1 -0
  472. pythinker_code/web/static/assets/haskell-Df6bDoY_.js +1 -0
  473. pythinker_code/web/static/assets/haxe-CzTSHFRz.js +1 -0
  474. pythinker_code/web/static/assets/hcl-BWvSN4gD.js +1 -0
  475. pythinker_code/web/static/assets/hjson-D5-asLiD.js +1 -0
  476. pythinker_code/web/static/assets/hlsl-D3lLCCz7.js +1 -0
  477. pythinker_code/web/static/assets/houston-DnULxvSX.js +1 -0
  478. pythinker_code/web/static/assets/html-GMplVEZG.js +1 -0
  479. pythinker_code/web/static/assets/html-derivative-BFtXZ54Q.js +1 -0
  480. pythinker_code/web/static/assets/http-jrhK8wxY.js +1 -0
  481. pythinker_code/web/static/assets/hurl-irOxFIW8.js +1 -0
  482. pythinker_code/web/static/assets/hxml-Bvhsp5Yf.js +1 -0
  483. pythinker_code/web/static/assets/hy-DFXneXwc.js +1 -0
  484. pythinker_code/web/static/assets/imba-DGztddWO.js +1 -0
  485. pythinker_code/web/static/assets/index-BYCCk6-K.js +153 -0
  486. pythinker_code/web/static/assets/index-BpoLgcEt.js +1 -0
  487. pythinker_code/web/static/assets/index-Cpy4G3uJ.js +2 -0
  488. pythinker_code/web/static/assets/index-CzV_vCfu.css +1 -0
  489. pythinker_code/web/static/assets/index-DI2oedCt.js +19 -0
  490. pythinker_code/web/static/assets/index-DdIkp80K.js +5 -0
  491. pythinker_code/web/static/assets/infoDiagram-WHAUD3N6-BMPpeZSM.js +2 -0
  492. pythinker_code/web/static/assets/ini-BEwlwnbL.js +1 -0
  493. pythinker_code/web/static/assets/init-Gi6I4Gst.js +1 -0
  494. pythinker_code/web/static/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2 +0 -0
  495. pythinker_code/web/static/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2 +0 -0
  496. pythinker_code/web/static/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2 +0 -0
  497. pythinker_code/web/static/assets/inter-greek-wght-normal-CkhJZR-_.woff2 +0 -0
  498. pythinker_code/web/static/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
  499. pythinker_code/web/static/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
  500. pythinker_code/web/static/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2 +0 -0
  501. pythinker_code/web/static/assets/java-CylS5w8V.js +1 -0
  502. pythinker_code/web/static/assets/javascript-wDzz0qaB.js +1 -0
  503. pythinker_code/web/static/assets/jinja-4LBKfQ-Z.js +1 -0
  504. pythinker_code/web/static/assets/jison-wvAkD_A8.js +1 -0
  505. pythinker_code/web/static/assets/journeyDiagram-XKPGCS4Q-DAM7gngo.js +139 -0
  506. pythinker_code/web/static/assets/json-Cp-IABpG.js +1 -0
  507. pythinker_code/web/static/assets/json5-C9tS-k6U.js +1 -0
  508. pythinker_code/web/static/assets/jsonc-Des-eS-w.js +1 -0
  509. pythinker_code/web/static/assets/jsonl-DcaNXYhu.js +1 -0
  510. pythinker_code/web/static/assets/jsonnet-DFQXde-d.js +1 -0
  511. pythinker_code/web/static/assets/jssm-C2t-YnRu.js +1 -0
  512. pythinker_code/web/static/assets/jsx-g9-lgVsj.js +1 -0
  513. pythinker_code/web/static/assets/julia-CxzCAyBv.js +1 -0
  514. pythinker_code/web/static/assets/kanagawa-dragon-CkXjmgJE.js +1 -0
  515. pythinker_code/web/static/assets/kanagawa-lotus-CfQXZHmo.js +1 -0
  516. pythinker_code/web/static/assets/kanagawa-wave-DWedfzmr.js +1 -0
  517. pythinker_code/web/static/assets/kanban-definition-3W4ZIXB7-ChpBpV0k.js +89 -0
  518. pythinker_code/web/static/assets/katex-D2lIc1rk.css +1 -0
  519. pythinker_code/web/static/assets/kdl-DV7GczEv.js +1 -0
  520. pythinker_code/web/static/assets/kotlin-BdnUsdx6.js +1 -0
  521. pythinker_code/web/static/assets/kusto-DZf3V79B.js +1 -0
  522. pythinker_code/web/static/assets/laserwave-DUszq2jm.js +1 -0
  523. pythinker_code/web/static/assets/latex-B4uzh10-.js +1 -0
  524. pythinker_code/web/static/assets/layout-C3Jp1gKO.js +1 -0
  525. pythinker_code/web/static/assets/lean-BZvkOJ9d.js +1 -0
  526. pythinker_code/web/static/assets/less-B1dDrJ26.js +1 -0
  527. pythinker_code/web/static/assets/light-plus-B7mTdjB0.js +1 -0
  528. pythinker_code/web/static/assets/linear-BGHtL1N4.js +1 -0
  529. pythinker_code/web/static/assets/liquid-DYVedYrR.js +1 -0
  530. pythinker_code/web/static/assets/llvm-BtvRca6l.js +1 -0
  531. pythinker_code/web/static/assets/log-2UxHyX5q.js +1 -0
  532. pythinker_code/web/static/assets/logo-BtOb2qkB.js +1 -0
  533. pythinker_code/web/static/assets/lua-BbnMAYS6.js +1 -0
  534. pythinker_code/web/static/assets/luau-C-HG3fhB.js +1 -0
  535. pythinker_code/web/static/assets/make-CHLpvVh8.js +1 -0
  536. pythinker_code/web/static/assets/markdown-Cvjx9yec.js +1 -0
  537. pythinker_code/web/static/assets/marko-DZsq8hO1.js +1 -0
  538. pythinker_code/web/static/assets/material-theme-D5KoaKCx.js +1 -0
  539. pythinker_code/web/static/assets/material-theme-darker-BfHTSMKl.js +1 -0
  540. pythinker_code/web/static/assets/material-theme-lighter-B0m2ddpp.js +1 -0
  541. pythinker_code/web/static/assets/material-theme-ocean-CyktbL80.js +1 -0
  542. pythinker_code/web/static/assets/material-theme-palenight-Csfq5Kiy.js +1 -0
  543. pythinker_code/web/static/assets/matlab-D7o27uSR.js +1 -0
  544. pythinker_code/web/static/assets/mdc-DUICxH0z.js +1 -0
  545. pythinker_code/web/static/assets/mdx-Cmh6b_Ma.js +1 -0
  546. pythinker_code/web/static/assets/mermaid-VLURNSYL-B2P5VJ9v.css +1 -0
  547. pythinker_code/web/static/assets/mermaid-VLURNSYL-C_HW6koB.js +465 -0
  548. pythinker_code/web/static/assets/mermaid-mWjccvbQ.js +1 -0
  549. pythinker_code/web/static/assets/mermaid.core-CnT4VrPC.js +191 -0
  550. pythinker_code/web/static/assets/min-Dn5VRVmX.js +1 -0
  551. pythinker_code/web/static/assets/min-dark-CafNBF8u.js +1 -0
  552. pythinker_code/web/static/assets/min-light-CTRr51gU.js +1 -0
  553. pythinker_code/web/static/assets/mindmap-definition-VGOIOE7T-x8EwhfIt.js +68 -0
  554. pythinker_code/web/static/assets/mipsasm-CKIfxQSi.js +1 -0
  555. pythinker_code/web/static/assets/mojo-B93PlW-d.js +1 -0
  556. pythinker_code/web/static/assets/monokai-D4h5O-jR.js +1 -0
  557. pythinker_code/web/static/assets/moonbit-Ba13S78F.js +1 -0
  558. pythinker_code/web/static/assets/move-Bu9oaDYs.js +1 -0
  559. pythinker_code/web/static/assets/narrat-DRg8JJMk.js +1 -0
  560. pythinker_code/web/static/assets/nextflow-BrzmwbiE.js +1 -0
  561. pythinker_code/web/static/assets/nginx-DknmC5AR.js +1 -0
  562. pythinker_code/web/static/assets/night-owl-C39BiMTA.js +1 -0
  563. pythinker_code/web/static/assets/nim-CVrawwO9.js +1 -0
  564. pythinker_code/web/static/assets/nix-CwoSXNpI.js +1 -0
  565. pythinker_code/web/static/assets/nord-Ddv68eIx.js +1 -0
  566. pythinker_code/web/static/assets/nushell-C-sUppwS.js +1 -0
  567. pythinker_code/web/static/assets/objective-c-DXmwc3jG.js +1 -0
  568. pythinker_code/web/static/assets/objective-cpp-CLxacb5B.js +1 -0
  569. pythinker_code/web/static/assets/ocaml-C0hk2d4L.js +1 -0
  570. pythinker_code/web/static/assets/one-dark-pro-DVMEJ2y_.js +1 -0
  571. pythinker_code/web/static/assets/one-light-PoHY5YXO.js +1 -0
  572. pythinker_code/web/static/assets/openscad-C4EeE6gA.js +1 -0
  573. pythinker_code/web/static/assets/ordinal-Cboi1Yqb.js +1 -0
  574. pythinker_code/web/static/assets/pascal-D93ZcfNL.js +1 -0
  575. pythinker_code/web/static/assets/perl-C0TMdlhV.js +1 -0
  576. pythinker_code/web/static/assets/php-CDn_0X-4.js +1 -0
  577. pythinker_code/web/static/assets/pieDiagram-ADFJNKIX-DgxBKGz2.js +30 -0
  578. pythinker_code/web/static/assets/pkl-u5AG7uiY.js +1 -0
  579. pythinker_code/web/static/assets/plastic-3e1v2bzS.js +1 -0
  580. pythinker_code/web/static/assets/plsql-ChMvpjG-.js +1 -0
  581. pythinker_code/web/static/assets/po-BTJTHyun.js +1 -0
  582. pythinker_code/web/static/assets/poimandres-CS3Unz2-.js +1 -0
  583. pythinker_code/web/static/assets/polar-C0HS_06l.js +1 -0
  584. pythinker_code/web/static/assets/postcss-CXtECtnM.js +1 -0
  585. pythinker_code/web/static/assets/powerquery-CEu0bR-o.js +1 -0
  586. pythinker_code/web/static/assets/powershell-Dpen1YoG.js +1 -0
  587. pythinker_code/web/static/assets/prisma-Dd19v3D-.js +1 -0
  588. pythinker_code/web/static/assets/prolog-CbFg5uaA.js +1 -0
  589. pythinker_code/web/static/assets/proto-C7zT0LnQ.js +1 -0
  590. pythinker_code/web/static/assets/pug-CGlum2m_.js +1 -0
  591. pythinker_code/web/static/assets/puppet-BMWR74SV.js +1 -0
  592. pythinker_code/web/static/assets/purescript-CklMAg4u.js +1 -0
  593. pythinker_code/web/static/assets/python-B6aJPvgy.js +1 -0
  594. pythinker_code/web/static/assets/qml-3beO22l8.js +1 -0
  595. pythinker_code/web/static/assets/qmldir-C8lEn-DE.js +1 -0
  596. pythinker_code/web/static/assets/qss-IeuSbFQv.js +1 -0
  597. pythinker_code/web/static/assets/quadrantDiagram-AYHSOK5B-DSpe_dqk.js +7 -0
  598. pythinker_code/web/static/assets/r-Dspwwk_N.js +1 -0
  599. pythinker_code/web/static/assets/racket-BqYA7rlc.js +1 -0
  600. pythinker_code/web/static/assets/raku-DXvB9xmW.js +1 -0
  601. pythinker_code/web/static/assets/razor-C1TweQQi.js +1 -0
  602. pythinker_code/web/static/assets/red-bN70gL4F.js +1 -0
  603. pythinker_code/web/static/assets/reg-C-SQnVFl.js +1 -0
  604. pythinker_code/web/static/assets/regexp-CDVJQ6XC.js +1 -0
  605. pythinker_code/web/static/assets/rel-C3B-1QV4.js +1 -0
  606. pythinker_code/web/static/assets/requirementDiagram-UZGBJVZJ-8o9hozL-.js +64 -0
  607. pythinker_code/web/static/assets/riscv-BM1_JUlF.js +1 -0
  608. pythinker_code/web/static/assets/rose-pine-dawn-DHQR4-dF.js +1 -0
  609. pythinker_code/web/static/assets/rose-pine-moon-D4_iv3hh.js +1 -0
  610. pythinker_code/web/static/assets/rose-pine-qdsjHGoJ.js +1 -0
  611. pythinker_code/web/static/assets/rosmsg-BJDFO7_C.js +1 -0
  612. pythinker_code/web/static/assets/rst-B0xPkSld.js +1 -0
  613. pythinker_code/web/static/assets/ruby-BvKwtOVI.js +1 -0
  614. pythinker_code/web/static/assets/rust-B1yitclQ.js +1 -0
  615. pythinker_code/web/static/assets/sankeyDiagram-TZEHDZUN-BLOSUixH.js +10 -0
  616. pythinker_code/web/static/assets/sas-cz2c8ADy.js +1 -0
  617. pythinker_code/web/static/assets/sass-Cj5Yp3dK.js +1 -0
  618. pythinker_code/web/static/assets/scala-C151Ov-r.js +1 -0
  619. pythinker_code/web/static/assets/scheme-C98Dy4si.js +1 -0
  620. pythinker_code/web/static/assets/scss-OYdSNvt2.js +1 -0
  621. pythinker_code/web/static/assets/sdbl-DVxCFoDh.js +1 -0
  622. pythinker_code/web/static/assets/sequenceDiagram-WL72ISMW-6F2G8JTU.js +145 -0
  623. pythinker_code/web/static/assets/shaderlab-Dg9Lc6iA.js +1 -0
  624. pythinker_code/web/static/assets/shellscript-Yzrsuije.js +1 -0
  625. pythinker_code/web/static/assets/shellsession-BADoaaVG.js +1 -0
  626. pythinker_code/web/static/assets/slack-dark-BthQWCQV.js +1 -0
  627. pythinker_code/web/static/assets/slack-ochin-DqwNpetd.js +1 -0
  628. pythinker_code/web/static/assets/smalltalk-BERRCDM3.js +1 -0
  629. pythinker_code/web/static/assets/snazzy-light-Bw305WKR.js +1 -0
  630. pythinker_code/web/static/assets/solarized-dark-DXbdFlpD.js +1 -0
  631. pythinker_code/web/static/assets/solarized-light-L9t79GZl.js +1 -0
  632. pythinker_code/web/static/assets/solidity-rGO070M0.js +1 -0
  633. pythinker_code/web/static/assets/soy-Brmx7dQM.js +1 -0
  634. pythinker_code/web/static/assets/sparql-rVzFXLq3.js +1 -0
  635. pythinker_code/web/static/assets/splunk-BtCnVYZw.js +1 -0
  636. pythinker_code/web/static/assets/sql-BLtJtn59.js +1 -0
  637. pythinker_code/web/static/assets/ssh-config-_ykCGR6B.js +1 -0
  638. pythinker_code/web/static/assets/stata-BH5u7GGu.js +1 -0
  639. pythinker_code/web/static/assets/stateDiagram-FKZM4ZOC-DP8xP0iJ.js +1 -0
  640. pythinker_code/web/static/assets/stateDiagram-v2-4FDKWEC3-1l6-EZNX.js +1 -0
  641. pythinker_code/web/static/assets/stylus-BEDo0Tqx.js +1 -0
  642. pythinker_code/web/static/assets/svelte-zxCyuUbr.js +1 -0
  643. pythinker_code/web/static/assets/swift-Dg5xB15N.js +1 -0
  644. pythinker_code/web/static/assets/synthwave-84-CbfX1IO0.js +1 -0
  645. pythinker_code/web/static/assets/system-verilog-CnnmHF94.js +1 -0
  646. pythinker_code/web/static/assets/systemd-4A_iFExJ.js +1 -0
  647. pythinker_code/web/static/assets/talonscript-CkByrt1z.js +1 -0
  648. pythinker_code/web/static/assets/tasl-QIJgUcNo.js +1 -0
  649. pythinker_code/web/static/assets/tcl-dwOrl1Do.js +1 -0
  650. pythinker_code/web/static/assets/templ-W15q3VgB.js +1 -0
  651. pythinker_code/web/static/assets/terraform-BETggiCN.js +1 -0
  652. pythinker_code/web/static/assets/tex-CvyZ59Mk.js +1 -0
  653. pythinker_code/web/static/assets/timeline-definition-IT6M3QCI-DMgruDfK.js +61 -0
  654. pythinker_code/web/static/assets/tokyo-night-hegEt444.js +1 -0
  655. pythinker_code/web/static/assets/toml-vGWfd6FD.js +1 -0
  656. pythinker_code/web/static/assets/treemap-KMMF4GRG-Bo9ZkrAK.js +128 -0
  657. pythinker_code/web/static/assets/ts-tags-zn1MmPIZ.js +1 -0
  658. pythinker_code/web/static/assets/tsv-B_m7g4N7.js +1 -0
  659. pythinker_code/web/static/assets/tsx-COt5Ahok.js +1 -0
  660. pythinker_code/web/static/assets/turtle-BsS91CYL.js +1 -0
  661. pythinker_code/web/static/assets/twig-CO9l9SDP.js +1 -0
  662. pythinker_code/web/static/assets/typescript-BPQ3VLAy.js +1 -0
  663. pythinker_code/web/static/assets/typespec-BGHnOYBU.js +1 -0
  664. pythinker_code/web/static/assets/typst-DHCkPAjA.js +1 -0
  665. pythinker_code/web/static/assets/v-BcVCzyr7.js +1 -0
  666. pythinker_code/web/static/assets/vala-CsfeWuGM.js +1 -0
  667. pythinker_code/web/static/assets/vb-D17OF-Vu.js +1 -0
  668. pythinker_code/web/static/assets/verilog-BQ8w6xss.js +1 -0
  669. pythinker_code/web/static/assets/vesper-DU1UobuO.js +1 -0
  670. pythinker_code/web/static/assets/vhdl-CeAyd5Ju.js +1 -0
  671. pythinker_code/web/static/assets/viml-CJc9bBzg.js +1 -0
  672. pythinker_code/web/static/assets/vitesse-black-Bkuqu6BP.js +1 -0
  673. pythinker_code/web/static/assets/vitesse-dark-D0r3Knsf.js +1 -0
  674. pythinker_code/web/static/assets/vitesse-light-CVO1_9PV.js +1 -0
  675. pythinker_code/web/static/assets/vue-DN_0RTcg.js +1 -0
  676. pythinker_code/web/static/assets/vue-html-AaS7Mt5G.js +1 -0
  677. pythinker_code/web/static/assets/vue-vine-CQOfvN7w.js +1 -0
  678. pythinker_code/web/static/assets/vyper-CDx5xZoG.js +1 -0
  679. pythinker_code/web/static/assets/wasm-CG6Dc4jp.js +1 -0
  680. pythinker_code/web/static/assets/wasm-MzD3tlZU.js +1 -0
  681. pythinker_code/web/static/assets/wenyan-BV7otONQ.js +1 -0
  682. pythinker_code/web/static/assets/wgsl-Dx-B1_4e.js +1 -0
  683. pythinker_code/web/static/assets/wikitext-BhOHFoWU.js +1 -0
  684. pythinker_code/web/static/assets/wit-5i3qLPDT.js +1 -0
  685. pythinker_code/web/static/assets/wolfram-lXgVvXCa.js +1 -0
  686. pythinker_code/web/static/assets/xml-sdJ4AIDG.js +1 -0
  687. pythinker_code/web/static/assets/xsl-CtQFsRM5.js +1 -0
  688. pythinker_code/web/static/assets/xychartDiagram-PRI3JC2R-GeF2johi.js +7 -0
  689. pythinker_code/web/static/assets/yaml-Buea-lGh.js +1 -0
  690. pythinker_code/web/static/assets/zenscript-DVFEvuxE.js +1 -0
  691. pythinker_code/web/static/assets/zig-VOosw3JB.js +1 -0
  692. pythinker_code/web/static/brand/apple-touch-icon.png +0 -0
  693. pythinker_code/web/static/brand/arctecture.webp +0 -0
  694. pythinker_code/web/static/brand/bimi-logo.svg +46 -0
  695. pythinker_code/web/static/brand/favicon.ico +0 -0
  696. pythinker_code/web/static/brand/fonts/dm-sans-latin-ext.woff2 +0 -0
  697. pythinker_code/web/static/brand/fonts/dm-sans-latin.woff2 +0 -0
  698. pythinker_code/web/static/brand/fonts/instrument-sans-latin-ext.woff2 +0 -0
  699. pythinker_code/web/static/brand/fonts/instrument-sans-latin.woff2 +0 -0
  700. pythinker_code/web/static/brand/fonts/instrument-serif-latin-ext.woff2 +0 -0
  701. pythinker_code/web/static/brand/fonts/instrument-serif-latin.woff2 +0 -0
  702. pythinker_code/web/static/brand/fonts/libre-baskerville-italic-latin-ext.woff2 +0 -0
  703. pythinker_code/web/static/brand/fonts/libre-baskerville-italic-latin.woff2 +0 -0
  704. pythinker_code/web/static/brand/fonts/libre-baskerville-latin-ext.woff2 +0 -0
  705. pythinker_code/web/static/brand/fonts/libre-baskerville-latin.woff2 +0 -0
  706. pythinker_code/web/static/brand/fonts/roboto-latin-ext.woff2 +0 -0
  707. pythinker_code/web/static/brand/fonts/roboto-latin.woff2 +0 -0
  708. pythinker_code/web/static/brand/icon-192.png +0 -0
  709. pythinker_code/web/static/brand/icon-512.png +0 -0
  710. pythinker_code/web/static/brand/icon.svg +1 -0
  711. pythinker_code/web/static/brand/logo.png +0 -0
  712. pythinker_code/web/static/brand/pythinker_animated.svg +79 -0
  713. pythinker_code/web/static/brand/robots.txt +4 -0
  714. pythinker_code/web/static/index.html +15 -0
  715. pythinker_code/web/static/logo.png +0 -0
  716. pythinker_code/web/store/__init__.py +1 -0
  717. pythinker_code/web/store/sessions.py +432 -0
  718. pythinker_code/wire/__init__.py +148 -0
  719. pythinker_code/wire/file.py +151 -0
  720. pythinker_code/wire/jsonrpc.py +263 -0
  721. pythinker_code/wire/protocol.py +2 -0
  722. pythinker_code/wire/root_hub.py +27 -0
  723. pythinker_code/wire/serde.py +26 -0
  724. pythinker_code/wire/server.py +1069 -0
  725. pythinker_code/wire/types.py +698 -0
  726. pythinker_code-2.0.0.dist-info/METADATA +660 -0
  727. pythinker_code-2.0.0.dist-info/RECORD +731 -0
  728. pythinker_code-2.0.0.dist-info/WHEEL +4 -0
  729. pythinker_code-2.0.0.dist-info/entry_points.txt +4 -0
  730. pythinker_code-2.0.0.dist-info/licenses/LICENSE +202 -0
  731. pythinker_code-2.0.0.dist-info/licenses/NOTICE +14 -0
@@ -0,0 +1,586 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import Callable
4
+
5
+ from prompt_toolkit import PromptSession
6
+ from prompt_toolkit.application.run_in_terminal import run_in_terminal
7
+ from prompt_toolkit.buffer import Buffer
8
+ from prompt_toolkit.document import Document
9
+ from prompt_toolkit.formatted_text import ANSI
10
+ from prompt_toolkit.key_binding import KeyPressEvent
11
+ from rich.console import Group, RenderableType
12
+ from rich.markup import escape
13
+ from rich.panel import Panel
14
+ from rich.text import Text
15
+
16
+ from pythinker_code.ui.shell.console import console, render_to_ansi
17
+ from pythinker_code.ui.shell.keyboard import KeyEvent
18
+ from pythinker_code.utils.rich.markdown import Markdown
19
+ from pythinker_code.wire.types import QuestionRequest
20
+
21
+ OTHER_OPTION_LABEL = "Other"
22
+
23
+
24
+ class QuestionRequestPanel:
25
+ """Renders structured questions for the user to answer interactively."""
26
+
27
+ def __init__(self, request: QuestionRequest):
28
+ self.request = request
29
+ self._current_question_index = 0
30
+ self._answers: dict[str, str] = {}
31
+ self._saved_selections: dict[int, tuple[int, set[int]]] = {}
32
+ self._other_drafts: dict[int, str] = {}
33
+ self._selected_index = 0
34
+ self._multi_selected: set[int] = set()
35
+ self._body_text: str = ""
36
+ self.has_expandable_content: bool = False
37
+ self._setup_current_question()
38
+
39
+ def _setup_current_question(self) -> None:
40
+ q = self._current_question
41
+ self._options = [(o.label, o.description) for o in q.options]
42
+ other_label = q.other_label or OTHER_OPTION_LABEL
43
+ other_desc = q.other_description or ""
44
+ self._options.append((other_label, other_desc))
45
+ idx = self._current_question_index
46
+ if idx in self._saved_selections:
47
+ saved_idx, saved_multi = self._saved_selections[idx]
48
+ self._selected_index = min(saved_idx, len(self._options) - 1)
49
+ self._multi_selected = saved_multi
50
+ elif q.question in self._answers:
51
+ answer = self._answers[q.question]
52
+ if q.multi_select:
53
+ answer_labels = [a.strip() for a in answer.split(", ")]
54
+ known_labels = {label for label, _ in self._options[:-1]}
55
+ self._multi_selected = set()
56
+ for i, (label, _) in enumerate(self._options[:-1]):
57
+ if label in answer_labels:
58
+ self._multi_selected.add(i)
59
+ if any(answer_label not in known_labels for answer_label in answer_labels):
60
+ self._multi_selected.add(len(self._options) - 1)
61
+ self._selected_index = min(self._multi_selected) if self._multi_selected else 0
62
+ else:
63
+ for i, (label, _) in enumerate(self._options):
64
+ if label == answer:
65
+ self._selected_index = i
66
+ break
67
+ else:
68
+ self._selected_index = len(self._options) - 1
69
+ self._multi_selected = set()
70
+ else:
71
+ self._selected_index = 0
72
+ self._multi_selected = set()
73
+ self._recompute_body()
74
+
75
+ def _recompute_body(self) -> None:
76
+ body = self._current_question.body
77
+ self._body_text = body.rstrip("\n") if body else ""
78
+ self.has_expandable_content = bool(self._body_text)
79
+
80
+ @property
81
+ def _current_question(self):
82
+ return self.request.questions[self._current_question_index]
83
+
84
+ @property
85
+ def is_other_selected(self) -> bool:
86
+ return self._selected_index == len(self._options) - 1
87
+
88
+ @property
89
+ def is_multi_select(self) -> bool:
90
+ return self._current_question.multi_select
91
+
92
+ @property
93
+ def current_question_text(self) -> str:
94
+ return self._current_question.question
95
+
96
+ def should_prompt_other_input(self) -> bool:
97
+ if not self.is_multi_select:
98
+ return self.is_other_selected
99
+ other_idx = len(self._options) - 1
100
+ return other_idx in self._multi_selected
101
+
102
+ def select_index(self, index: int) -> bool:
103
+ if not (0 <= index < len(self._options)):
104
+ return False
105
+ self._selected_index = index
106
+ return True
107
+
108
+ def render(self, *, other_input_text: str | None = None) -> RenderableType:
109
+ q = self._current_question
110
+ lines: list[RenderableType] = []
111
+
112
+ if len(self.request.questions) > 1:
113
+ tab_parts: list[str] = []
114
+ for i, qi in enumerate(self.request.questions):
115
+ label = escape(qi.header or f"Q{i + 1}")
116
+ if i == self._current_question_index:
117
+ icon, style = "\u25cf", "bold cyan"
118
+ elif qi.question in self._answers:
119
+ icon, style = "\u2713", "green"
120
+ else:
121
+ icon, style = "\u25cb", "grey50"
122
+ tab_parts.append(f"[{style}]({icon}) {label}[/{style}]")
123
+ lines.append(Text.from_markup(" ".join(tab_parts)))
124
+ lines.append(Text(""))
125
+
126
+ lines.append(Text.from_markup(f"[yellow]? {escape(q.question)}[/yellow]"))
127
+ if q.multi_select:
128
+ lines.append(Text(" (SPACE to toggle, ENTER to submit)", style="dim italic"))
129
+ lines.append(Text(""))
130
+
131
+ if self._body_text:
132
+ lines.append(
133
+ Text.from_markup(
134
+ "[bold cyan] \u25b6 Press ctrl-e to view full content[/bold cyan]"
135
+ )
136
+ )
137
+ lines.append(Text(""))
138
+
139
+ show_inline_input = other_input_text is not None and self.is_other_selected
140
+
141
+ for i, (label, description) in enumerate(self._options):
142
+ num = i + 1
143
+ is_other = i == len(self._options) - 1
144
+ if q.multi_select:
145
+ checked = "\u2713" if i in self._multi_selected else " "
146
+ prefix = f"\\[{checked}]"
147
+ if i == self._selected_index:
148
+ option_line = Text.from_markup(f"[cyan]{prefix} {escape(label)}[/cyan]")
149
+ else:
150
+ option_line = Text.from_markup(f"[grey50]{prefix} {escape(label)}[/grey50]")
151
+ else:
152
+ if i == self._selected_index:
153
+ if is_other and show_inline_input:
154
+ input_display = escape(other_input_text) if other_input_text else ""
155
+ option_line = Text.from_markup(
156
+ f"[cyan]\u2192 \\[{num}] {escape(label)}: {input_display}\u2588[/cyan]"
157
+ )
158
+ else:
159
+ option_line = Text.from_markup(
160
+ f"[cyan]\u2192 \\[{num}] {escape(label)}[/cyan]"
161
+ )
162
+ else:
163
+ option_line = Text.from_markup(f"[grey50] \\[{num}] {escape(label)}[/grey50]")
164
+ lines.append(option_line)
165
+
166
+ if description and not (is_other and show_inline_input):
167
+ lines.append(Text(f" {description}", style="dim"))
168
+
169
+ if show_inline_input:
170
+ lines.append(Text(""))
171
+ lines.append(
172
+ Text(" Type your answer, then press Enter to submit.", style="dim italic")
173
+ )
174
+ elif len(self.request.questions) > 1:
175
+ lines.append(Text(""))
176
+ lines.append(
177
+ Text(
178
+ " \u25c4/\u25ba switch question "
179
+ "\u25b2/\u25bc select \u21b5 submit esc exit",
180
+ style="dim",
181
+ )
182
+ )
183
+
184
+ return Panel(
185
+ Group(*lines),
186
+ border_style="grey50",
187
+ title="[bold]question[/bold]",
188
+ title_align="left",
189
+ padding=(0, 1),
190
+ )
191
+
192
+ def save_other_draft(self, text: str) -> None:
193
+ if text:
194
+ self._other_drafts[self._current_question_index] = text
195
+ else:
196
+ self._other_drafts.pop(self._current_question_index, None)
197
+
198
+ def get_other_draft(self) -> str:
199
+ return self._other_drafts.get(self._current_question_index, "")
200
+
201
+ def go_to(self, index: int) -> None:
202
+ if index == self._current_question_index:
203
+ return
204
+ if not (0 <= index < len(self.request.questions)):
205
+ return
206
+ self._saved_selections[self._current_question_index] = (
207
+ self._selected_index,
208
+ set(self._multi_selected),
209
+ )
210
+ self._current_question_index = index
211
+ self._setup_current_question()
212
+
213
+ def next_tab(self) -> None:
214
+ if self._current_question_index < len(self.request.questions) - 1:
215
+ self.go_to(self._current_question_index + 1)
216
+
217
+ def prev_tab(self) -> None:
218
+ if self._current_question_index > 0:
219
+ self.go_to(self._current_question_index - 1)
220
+
221
+ def move_up(self) -> None:
222
+ self._selected_index = (self._selected_index - 1) % len(self._options)
223
+
224
+ def move_down(self) -> None:
225
+ self._selected_index = (self._selected_index + 1) % len(self._options)
226
+
227
+ def toggle_select(self) -> None:
228
+ if not self.is_multi_select:
229
+ return
230
+ if self._selected_index in self._multi_selected:
231
+ self._multi_selected.discard(self._selected_index)
232
+ else:
233
+ self._multi_selected.add(self._selected_index)
234
+
235
+ def submit(self) -> bool:
236
+ q = self._current_question
237
+ if q.multi_select:
238
+ other_idx = len(self._options) - 1
239
+ if other_idx in self._multi_selected:
240
+ return False
241
+ selected_labels = [
242
+ self._options[i][0] for i in sorted(self._multi_selected) if i < len(q.options)
243
+ ]
244
+ if not selected_labels:
245
+ return False
246
+ self._answers[q.question] = ", ".join(selected_labels)
247
+ else:
248
+ if self.is_other_selected:
249
+ return False
250
+ self._answers[q.question] = self._options[self._selected_index][0]
251
+ self._saved_selections.pop(self._current_question_index, None)
252
+ self._other_drafts.pop(self._current_question_index, None)
253
+ return self._advance()
254
+
255
+ def submit_other(self, text: str) -> bool:
256
+ q = self._current_question
257
+ if q.multi_select:
258
+ other_idx = len(self._options) - 1
259
+ selected_labels = [
260
+ self._options[i][0]
261
+ for i in sorted(self._multi_selected)
262
+ if i < len(q.options) and i != other_idx
263
+ ]
264
+ if text:
265
+ selected_labels.append(text)
266
+ self._answers[q.question] = ", ".join(selected_labels) if selected_labels else text
267
+ else:
268
+ self._answers[q.question] = text
269
+ self._saved_selections.pop(self._current_question_index, None)
270
+ self._other_drafts.pop(self._current_question_index, None)
271
+ return self._advance()
272
+
273
+ def _advance(self) -> bool:
274
+ total = len(self.request.questions)
275
+ if len(self._answers) >= total:
276
+ return True
277
+ for offset in range(1, total + 1):
278
+ idx = (self._current_question_index + offset) % total
279
+ if self.request.questions[idx].question not in self._answers:
280
+ self._current_question_index = idx
281
+ self._setup_current_question()
282
+ return False
283
+ return True
284
+
285
+ def get_answers(self) -> dict[str, str]:
286
+ return self._answers
287
+
288
+ def render_full_body(self) -> list[RenderableType]:
289
+ if not self._body_text:
290
+ return []
291
+ return [Markdown(self._body_text)]
292
+
293
+
294
+ def show_question_body_in_pager(panel: QuestionRequestPanel) -> None:
295
+ with console.screen(), console.pager(styles=True):
296
+ console.print(Text.from_markup(f"[yellow]? {escape(panel.current_question_text)}[/yellow]"))
297
+ console.print()
298
+ for renderable in panel.render_full_body():
299
+ console.print(renderable)
300
+
301
+
302
+ async def prompt_other_input(question_text: str) -> str:
303
+ console.print(Text.from_markup(f"\n[yellow]? {escape(question_text)}[/yellow]"))
304
+ console.print(Text(" Enter your answer:", style="dim"))
305
+ try:
306
+ session: PromptSession[str] = PromptSession()
307
+ return (await session.prompt_async(" > ")).strip()
308
+ except (EOFError, KeyboardInterrupt):
309
+ return ""
310
+
311
+
312
+ class QuestionPromptDelegate:
313
+ modal_priority = 10
314
+ _KEY_MAP: dict[str, KeyEvent] = {
315
+ "up": KeyEvent.UP,
316
+ "down": KeyEvent.DOWN,
317
+ "left": KeyEvent.LEFT,
318
+ "right": KeyEvent.RIGHT,
319
+ "tab": KeyEvent.TAB,
320
+ "space": KeyEvent.SPACE,
321
+ "enter": KeyEvent.ENTER,
322
+ "escape": KeyEvent.ESCAPE,
323
+ "c-c": KeyEvent.ESCAPE,
324
+ "c-d": KeyEvent.ESCAPE,
325
+ "1": KeyEvent.NUM_1,
326
+ "2": KeyEvent.NUM_2,
327
+ "3": KeyEvent.NUM_3,
328
+ "4": KeyEvent.NUM_4,
329
+ "5": KeyEvent.NUM_5,
330
+ "6": KeyEvent.NUM_6,
331
+ }
332
+
333
+ def __init__(
334
+ self,
335
+ panel: QuestionRequestPanel,
336
+ *,
337
+ on_advance: Callable[[], QuestionRequestPanel | None],
338
+ on_invalidate: Callable[[], None],
339
+ buffer_text_provider: Callable[[], str] | None = None,
340
+ text_expander: Callable[[str], str] | None = None,
341
+ ) -> None:
342
+ self._panel: QuestionRequestPanel | None = panel
343
+ self._awaiting_other_input = False
344
+ self._on_advance = on_advance
345
+ self._on_invalidate = on_invalidate
346
+ self._buffer_text_provider = buffer_text_provider
347
+ self._text_expander = text_expander
348
+
349
+ @property
350
+ def panel(self) -> QuestionRequestPanel | None:
351
+ return self._panel
352
+
353
+ def set_panel(self, panel: QuestionRequestPanel | None) -> None:
354
+ self._panel = panel
355
+ self._awaiting_other_input = False
356
+
357
+ def _is_inline_other_active(self) -> bool:
358
+ return (
359
+ self._panel is not None
360
+ and self._panel.is_other_selected
361
+ and self._buffer_text_provider is not None
362
+ and not self._panel.is_multi_select
363
+ )
364
+
365
+ def render_running_prompt_body(self, columns: int) -> ANSI:
366
+ if self._panel is None:
367
+ return ANSI("")
368
+ other_input_text: str | None = None
369
+ if self._is_inline_other_active():
370
+ other_input_text = self._buffer_text_provider() if self._buffer_text_provider else ""
371
+ body = render_to_ansi(
372
+ self._panel.render(other_input_text=other_input_text),
373
+ columns=columns,
374
+ ).rstrip("\n")
375
+ return ANSI(body if body else "")
376
+
377
+ def running_prompt_placeholder(self) -> str | None:
378
+ return None
379
+
380
+ def running_prompt_allows_text_input(self) -> bool:
381
+ if self._awaiting_other_input:
382
+ return True
383
+ return self._is_inline_other_active()
384
+
385
+ def running_prompt_hides_input_buffer(self) -> bool:
386
+ return self._panel is not None
387
+
388
+ def running_prompt_accepts_submission(self) -> bool:
389
+ return self._panel is not None
390
+
391
+ def should_handle_running_prompt_key(self, key: str) -> bool:
392
+ if self._panel is None:
393
+ return False
394
+ if key == "c-e":
395
+ return self._panel.has_expandable_content
396
+ if self._awaiting_other_input:
397
+ return key in {"enter", "escape", "c-c", "c-d"}
398
+ if self._is_inline_other_active():
399
+ return key in {"enter", "escape", "c-c", "c-d", "up", "down", "left", "right", "tab"}
400
+ return key in {
401
+ "up",
402
+ "down",
403
+ "left",
404
+ "right",
405
+ "tab",
406
+ "space",
407
+ "enter",
408
+ "escape",
409
+ "c-c",
410
+ "c-d",
411
+ "1",
412
+ "2",
413
+ "3",
414
+ "4",
415
+ "5",
416
+ "6",
417
+ }
418
+
419
+ def handle_running_prompt_key(self, key: str, event: KeyPressEvent) -> None:
420
+ if key == "c-e":
421
+ event.app.create_background_task(self._show_panel_in_pager())
422
+ return
423
+ if self._awaiting_other_input:
424
+ if key == "enter":
425
+ self._submit_other_input(event.current_buffer)
426
+ else:
427
+ self._clear_buffer(event.current_buffer)
428
+ self._awaiting_other_input = False
429
+ if self._panel is not None:
430
+ self._panel.request.resolve({})
431
+ self._advance()
432
+ self._on_invalidate()
433
+ return
434
+
435
+ if self._is_inline_other_active():
436
+ mapped = self._KEY_MAP.get(key)
437
+ if key == "enter" or mapped == KeyEvent.ENTER:
438
+ text = event.current_buffer.text.strip()
439
+ if text:
440
+ self._submit_other_input(event.current_buffer)
441
+ self._on_invalidate()
442
+ return
443
+ if mapped == KeyEvent.ESCAPE:
444
+ self._clear_buffer(event.current_buffer)
445
+ if self._panel is not None:
446
+ self._panel.request.resolve({})
447
+ self._advance()
448
+ self._on_invalidate()
449
+ return
450
+ if mapped in {KeyEvent.UP, KeyEvent.DOWN, KeyEvent.LEFT, KeyEvent.RIGHT, KeyEvent.TAB}:
451
+ self._save_and_clear_buffer(event.current_buffer)
452
+ self._dispatch_keyboard_event(mapped)
453
+ self._restore_draft_to_buffer(event.current_buffer)
454
+ self._on_invalidate()
455
+ return
456
+ return
457
+
458
+ mapped = self._KEY_MAP.get(key)
459
+ if mapped is None:
460
+ return
461
+ if mapped in {KeyEvent.ENTER, KeyEvent.SPACE} and self._should_prompt_other_for_key(mapped):
462
+ text = event.current_buffer.text.strip()
463
+ if text:
464
+ self._submit_other_input(event.current_buffer)
465
+ else:
466
+ self._clear_buffer(event.current_buffer)
467
+ self._awaiting_other_input = True
468
+ self._on_invalidate()
469
+ return
470
+
471
+ if mapped == KeyEvent.ESCAPE:
472
+ if self._panel is not None:
473
+ self._panel.request.resolve({})
474
+ self._advance()
475
+ self._on_invalidate()
476
+ return
477
+
478
+ if self._panel is not None:
479
+ self._save_and_clear_buffer(event.current_buffer)
480
+ self._dispatch_keyboard_event(mapped)
481
+ self._restore_draft_to_buffer(event.current_buffer)
482
+ self._on_invalidate()
483
+
484
+ def _should_prompt_other_for_key(self, key: KeyEvent) -> bool:
485
+ if self._panel is None or not self._panel.should_prompt_other_input():
486
+ return False
487
+ return key == KeyEvent.ENTER or (key == KeyEvent.SPACE and not self._panel.is_multi_select)
488
+
489
+ def _dispatch_keyboard_event(self, event: KeyEvent) -> None:
490
+ panel = self._panel
491
+ if panel is None:
492
+ return
493
+ match event:
494
+ case KeyEvent.UP:
495
+ panel.move_up()
496
+ case KeyEvent.DOWN:
497
+ panel.move_down()
498
+ case KeyEvent.LEFT:
499
+ panel.prev_tab()
500
+ case KeyEvent.RIGHT | KeyEvent.TAB:
501
+ panel.next_tab()
502
+ case KeyEvent.SPACE:
503
+ if panel.is_multi_select:
504
+ panel.toggle_select()
505
+ else:
506
+ self._try_submit()
507
+ case KeyEvent.ENTER:
508
+ self._try_submit()
509
+ case (
510
+ KeyEvent.NUM_1
511
+ | KeyEvent.NUM_2
512
+ | KeyEvent.NUM_3
513
+ | KeyEvent.NUM_4
514
+ | KeyEvent.NUM_5
515
+ | KeyEvent.NUM_6
516
+ ):
517
+ num_map = {
518
+ KeyEvent.NUM_1: 0,
519
+ KeyEvent.NUM_2: 1,
520
+ KeyEvent.NUM_3: 2,
521
+ KeyEvent.NUM_4: 3,
522
+ KeyEvent.NUM_5: 4,
523
+ KeyEvent.NUM_6: 5,
524
+ }
525
+ idx = num_map[event]
526
+ if panel.select_index(idx):
527
+ if panel.is_multi_select:
528
+ panel.toggle_select()
529
+ elif not panel.is_other_selected:
530
+ self._try_submit()
531
+ case _:
532
+ pass
533
+
534
+ def _try_submit(self) -> None:
535
+ if self._panel is None:
536
+ return
537
+ all_done = self._panel.submit()
538
+ if all_done:
539
+ self._panel.request.resolve(self._panel.get_answers())
540
+ self._advance()
541
+
542
+ def _submit_other_input(self, buffer: Buffer) -> None:
543
+ if self._panel is None:
544
+ self._clear_buffer(buffer)
545
+ self._awaiting_other_input = False
546
+ return
547
+ text = buffer.text.strip()
548
+ if self._text_expander is not None:
549
+ text = self._text_expander(text)
550
+ self._clear_buffer(buffer)
551
+ self._awaiting_other_input = False
552
+ all_done = self._panel.submit_other(text)
553
+ if all_done:
554
+ self._panel.request.resolve(self._panel.get_answers())
555
+ self._advance()
556
+
557
+ def _advance(self) -> None:
558
+ next_panel = self._on_advance()
559
+ self._panel = next_panel
560
+ self._awaiting_other_input = False
561
+
562
+ def _save_and_clear_buffer(self, buffer: Buffer) -> None:
563
+ if self._panel is not None and buffer.text:
564
+ self._panel.save_other_draft(buffer.text)
565
+ self._clear_buffer(buffer)
566
+
567
+ def _restore_draft_to_buffer(self, buffer: Buffer) -> None:
568
+ if self._is_inline_other_active() and self._panel is not None:
569
+ draft = self._panel.get_other_draft()
570
+ if draft:
571
+ buffer.set_document(
572
+ Document(text=draft, cursor_position=len(draft)),
573
+ bypass_readonly=True,
574
+ )
575
+
576
+ @staticmethod
577
+ def _clear_buffer(buffer: Buffer) -> None:
578
+ if buffer.text:
579
+ buffer.set_document(Document(text="", cursor_position=0), bypass_readonly=True)
580
+
581
+ async def _show_panel_in_pager(self) -> None:
582
+ if self._panel is None:
583
+ return
584
+ panel = self._panel
585
+ await run_in_terminal(lambda: show_question_body_in_pager(panel))
586
+ self._on_invalidate()