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.
- pythinker_code/CHANGELOG.md +16 -0
- pythinker_code/__init__.py +0 -0
- pythinker_code/__main__.py +92 -0
- pythinker_code/acp/AGENTS.md +93 -0
- pythinker_code/acp/__init__.py +13 -0
- pythinker_code/acp/convert.py +128 -0
- pythinker_code/acp/host.py +298 -0
- pythinker_code/acp/mcp.py +46 -0
- pythinker_code/acp/server.py +497 -0
- pythinker_code/acp/session.py +496 -0
- pythinker_code/acp/tools.py +167 -0
- pythinker_code/acp/types.py +13 -0
- pythinker_code/acp/version.py +45 -0
- pythinker_code/agents/default/agent.yaml +36 -0
- pythinker_code/agents/default/coder.yaml +25 -0
- pythinker_code/agents/default/explore.yaml +46 -0
- pythinker_code/agents/default/plan.yaml +30 -0
- pythinker_code/agents/default/system.md +164 -0
- pythinker_code/agents/okabe/agent.yaml +22 -0
- pythinker_code/agentspec.py +163 -0
- pythinker_code/app.py +820 -0
- pythinker_code/approval_runtime/__init__.py +29 -0
- pythinker_code/approval_runtime/models.py +42 -0
- pythinker_code/approval_runtime/runtime.py +235 -0
- pythinker_code/auth/__init__.py +25 -0
- pythinker_code/auth/anthropic_direct.py +207 -0
- pythinker_code/auth/deepseek.py +192 -0
- pythinker_code/auth/lm_studio.py +418 -0
- pythinker_code/auth/minimax.py +203 -0
- pythinker_code/auth/oauth.py +1122 -0
- pythinker_code/auth/ollama.py +293 -0
- pythinker_code/auth/openai.py +771 -0
- pythinker_code/auth/opencode_go.py +203 -0
- pythinker_code/auth/openrouter.py +225 -0
- pythinker_code/auth/platforms.py +466 -0
- pythinker_code/background/__init__.py +36 -0
- pythinker_code/background/agent_runner.py +231 -0
- pythinker_code/background/ids.py +19 -0
- pythinker_code/background/manager.py +650 -0
- pythinker_code/background/models.py +105 -0
- pythinker_code/background/store.py +237 -0
- pythinker_code/background/summary.py +66 -0
- pythinker_code/background/worker.py +209 -0
- pythinker_code/cli/__init__.py +1326 -0
- pythinker_code/cli/__main__.py +19 -0
- pythinker_code/cli/_lazy_group.py +238 -0
- pythinker_code/cli/export.py +322 -0
- pythinker_code/cli/info.py +62 -0
- pythinker_code/cli/mcp.py +349 -0
- pythinker_code/cli/plugin.py +351 -0
- pythinker_code/cli/toad.py +74 -0
- pythinker_code/cli/vis.py +38 -0
- pythinker_code/cli/web.py +80 -0
- pythinker_code/config.py +453 -0
- pythinker_code/constant.py +33 -0
- pythinker_code/exception.py +43 -0
- pythinker_code/hooks/__init__.py +4 -0
- pythinker_code/hooks/config.py +34 -0
- pythinker_code/hooks/engine.py +371 -0
- pythinker_code/hooks/events.py +190 -0
- pythinker_code/hooks/runner.py +89 -0
- pythinker_code/llm.py +412 -0
- pythinker_code/metadata.py +79 -0
- pythinker_code/notifications/__init__.py +33 -0
- pythinker_code/notifications/llm.py +77 -0
- pythinker_code/notifications/manager.py +145 -0
- pythinker_code/notifications/models.py +50 -0
- pythinker_code/notifications/notifier.py +41 -0
- pythinker_code/notifications/store.py +118 -0
- pythinker_code/notifications/wire.py +21 -0
- pythinker_code/plugin/__init__.py +124 -0
- pythinker_code/plugin/manager.py +153 -0
- pythinker_code/plugin/tool.py +173 -0
- pythinker_code/prompts/__init__.py +6 -0
- pythinker_code/prompts/compact.md +73 -0
- pythinker_code/prompts/init.md +21 -0
- pythinker_code/py.typed +0 -0
- pythinker_code/session.py +319 -0
- pythinker_code/session_fork.py +325 -0
- pythinker_code/session_state.py +132 -0
- pythinker_code/share.py +14 -0
- pythinker_code/skill/__init__.py +727 -0
- pythinker_code/skill/flow/__init__.py +99 -0
- pythinker_code/skill/flow/d2.py +482 -0
- pythinker_code/skill/flow/mermaid.py +266 -0
- pythinker_code/skills/pythinker-code-help/SKILL.md +54 -0
- pythinker_code/skills/skill-creator/SKILL.md +367 -0
- pythinker_code/soul/__init__.py +304 -0
- pythinker_code/soul/agent.py +520 -0
- pythinker_code/soul/approval.py +267 -0
- pythinker_code/soul/btw.py +214 -0
- pythinker_code/soul/compaction.py +189 -0
- pythinker_code/soul/context.py +339 -0
- pythinker_code/soul/denwarenji.py +39 -0
- pythinker_code/soul/dynamic_injection.py +84 -0
- pythinker_code/soul/dynamic_injections/__init__.py +0 -0
- pythinker_code/soul/dynamic_injections/auto_mode.py +72 -0
- pythinker_code/soul/dynamic_injections/plan_mode.py +239 -0
- pythinker_code/soul/message.py +92 -0
- pythinker_code/soul/pythinkersoul.py +1613 -0
- pythinker_code/soul/slash.py +340 -0
- pythinker_code/soul/toolset.py +788 -0
- pythinker_code/subagents/__init__.py +21 -0
- pythinker_code/subagents/builder.py +42 -0
- pythinker_code/subagents/core.py +86 -0
- pythinker_code/subagents/git_context.py +172 -0
- pythinker_code/subagents/models.py +54 -0
- pythinker_code/subagents/output.py +71 -0
- pythinker_code/subagents/registry.py +28 -0
- pythinker_code/subagents/runner.py +428 -0
- pythinker_code/subagents/store.py +196 -0
- pythinker_code/telemetry/__init__.py +211 -0
- pythinker_code/telemetry/config.py +54 -0
- pythinker_code/telemetry/crash.py +157 -0
- pythinker_code/telemetry/metrics.py +208 -0
- pythinker_code/telemetry/otel.py +240 -0
- pythinker_code/telemetry/sentry.py +167 -0
- pythinker_code/telemetry/sink.py +189 -0
- pythinker_code/tools/AGENTS.md +6 -0
- pythinker_code/tools/__init__.py +105 -0
- pythinker_code/tools/agent/__init__.py +277 -0
- pythinker_code/tools/agent/description.md +41 -0
- pythinker_code/tools/ask_user/__init__.py +159 -0
- pythinker_code/tools/ask_user/description.md +19 -0
- pythinker_code/tools/background/__init__.py +318 -0
- pythinker_code/tools/background/list.md +10 -0
- pythinker_code/tools/background/output.md +11 -0
- pythinker_code/tools/background/stop.md +8 -0
- pythinker_code/tools/display.py +46 -0
- pythinker_code/tools/dmail/__init__.py +38 -0
- pythinker_code/tools/dmail/dmail.md +17 -0
- pythinker_code/tools/file/__init__.py +30 -0
- pythinker_code/tools/file/glob.md +17 -0
- pythinker_code/tools/file/glob.py +160 -0
- pythinker_code/tools/file/grep.md +6 -0
- pythinker_code/tools/file/grep_local.py +589 -0
- pythinker_code/tools/file/plan_mode.py +45 -0
- pythinker_code/tools/file/read.md +16 -0
- pythinker_code/tools/file/read.py +300 -0
- pythinker_code/tools/file/read_media.md +24 -0
- pythinker_code/tools/file/read_media.py +217 -0
- pythinker_code/tools/file/replace.md +7 -0
- pythinker_code/tools/file/replace.py +195 -0
- pythinker_code/tools/file/utils.py +257 -0
- pythinker_code/tools/file/write.md +5 -0
- pythinker_code/tools/file/write.py +177 -0
- pythinker_code/tools/plan/__init__.py +327 -0
- pythinker_code/tools/plan/description.md +29 -0
- pythinker_code/tools/plan/enter.py +190 -0
- pythinker_code/tools/plan/enter_description.md +35 -0
- pythinker_code/tools/plan/heroes.py +277 -0
- pythinker_code/tools/shell/__init__.py +253 -0
- pythinker_code/tools/shell/bash.md +35 -0
- pythinker_code/tools/shell/powershell.md +30 -0
- pythinker_code/tools/test.py +55 -0
- pythinker_code/tools/think/__init__.py +21 -0
- pythinker_code/tools/think/think.md +1 -0
- pythinker_code/tools/todo/__init__.py +168 -0
- pythinker_code/tools/todo/set_todo_list.md +23 -0
- pythinker_code/tools/utils.py +199 -0
- pythinker_code/tools/web/__init__.py +4 -0
- pythinker_code/tools/web/fetch.md +1 -0
- pythinker_code/tools/web/fetch.py +189 -0
- pythinker_code/tools/web/search.md +1 -0
- pythinker_code/tools/web/search.py +163 -0
- pythinker_code/ui/__init__.py +0 -0
- pythinker_code/ui/acp/__init__.py +99 -0
- pythinker_code/ui/print/__init__.py +474 -0
- pythinker_code/ui/print/visualize.py +185 -0
- pythinker_code/ui/shell/__init__.py +1696 -0
- pythinker_code/ui/shell/console.py +109 -0
- pythinker_code/ui/shell/debug.py +190 -0
- pythinker_code/ui/shell/echo.py +17 -0
- pythinker_code/ui/shell/export_import.py +117 -0
- pythinker_code/ui/shell/keyboard.py +300 -0
- pythinker_code/ui/shell/mcp_status.py +113 -0
- pythinker_code/ui/shell/model_picker.py +318 -0
- pythinker_code/ui/shell/oauth.py +272 -0
- pythinker_code/ui/shell/placeholders.py +531 -0
- pythinker_code/ui/shell/prompt.py +2278 -0
- pythinker_code/ui/shell/replay.py +215 -0
- pythinker_code/ui/shell/session_picker.py +227 -0
- pythinker_code/ui/shell/setup.py +212 -0
- pythinker_code/ui/shell/slash.py +898 -0
- pythinker_code/ui/shell/startup.py +32 -0
- pythinker_code/ui/shell/task_browser.py +486 -0
- pythinker_code/ui/shell/update.py +350 -0
- pythinker_code/ui/shell/usage.py +291 -0
- pythinker_code/ui/shell/usage_adapters/__init__.py +50 -0
- pythinker_code/ui/shell/usage_adapters/anthropic_admin.py +233 -0
- pythinker_code/ui/shell/usage_adapters/base.py +72 -0
- pythinker_code/ui/shell/usage_adapters/deepseek.py +137 -0
- pythinker_code/ui/shell/usage_adapters/minimax.py +236 -0
- pythinker_code/ui/shell/usage_adapters/openai_admin.py +225 -0
- pythinker_code/ui/shell/usage_adapters/openai_chatgpt.py +241 -0
- pythinker_code/ui/shell/usage_adapters/opencode_go.py +232 -0
- pythinker_code/ui/shell/usage_adapters/openrouter.py +105 -0
- pythinker_code/ui/shell/usage_adapters/pythinker.py +189 -0
- pythinker_code/ui/shell/usage_adapters/pythinker_ai.py +50 -0
- pythinker_code/ui/shell/usage_render.py +150 -0
- pythinker_code/ui/shell/visualize/__init__.py +165 -0
- pythinker_code/ui/shell/visualize/_approval_panel.py +505 -0
- pythinker_code/ui/shell/visualize/_blocks.py +629 -0
- pythinker_code/ui/shell/visualize/_btw_panel.py +224 -0
- pythinker_code/ui/shell/visualize/_input_router.py +48 -0
- pythinker_code/ui/shell/visualize/_interactive.py +523 -0
- pythinker_code/ui/shell/visualize/_live_view.py +826 -0
- pythinker_code/ui/shell/visualize/_question_panel.py +586 -0
- pythinker_code/ui/theme.py +241 -0
- pythinker_code/usage_ratelimit_cache.py +175 -0
- pythinker_code/utils/__init__.py +0 -0
- pythinker_code/utils/aiohttp.py +24 -0
- pythinker_code/utils/aioqueue.py +72 -0
- pythinker_code/utils/broadcast.py +37 -0
- pythinker_code/utils/changelog.py +108 -0
- pythinker_code/utils/clipboard.py +246 -0
- pythinker_code/utils/datetime.py +64 -0
- pythinker_code/utils/diff.py +135 -0
- pythinker_code/utils/editor.py +91 -0
- pythinker_code/utils/environment.py +73 -0
- pythinker_code/utils/envvar.py +22 -0
- pythinker_code/utils/export.py +696 -0
- pythinker_code/utils/file_filter.py +375 -0
- pythinker_code/utils/frontmatter.py +70 -0
- pythinker_code/utils/io.py +27 -0
- pythinker_code/utils/logging.py +146 -0
- pythinker_code/utils/media_tags.py +29 -0
- pythinker_code/utils/message.py +24 -0
- pythinker_code/utils/path.py +199 -0
- pythinker_code/utils/proctitle.py +33 -0
- pythinker_code/utils/proxy.py +31 -0
- pythinker_code/utils/pyinstaller.py +45 -0
- pythinker_code/utils/rich/__init__.py +33 -0
- pythinker_code/utils/rich/columns.py +99 -0
- pythinker_code/utils/rich/diff_render.py +481 -0
- pythinker_code/utils/rich/markdown.py +900 -0
- pythinker_code/utils/rich/markdown_sample.md +108 -0
- pythinker_code/utils/rich/markdown_sample_short.md +2 -0
- pythinker_code/utils/rich/syntax.py +114 -0
- pythinker_code/utils/sensitive.py +54 -0
- pythinker_code/utils/server.py +121 -0
- pythinker_code/utils/signals.py +43 -0
- pythinker_code/utils/slashcmd.py +124 -0
- pythinker_code/utils/string.py +41 -0
- pythinker_code/utils/subprocess_env.py +73 -0
- pythinker_code/utils/term.py +168 -0
- pythinker_code/utils/typing.py +20 -0
- pythinker_code/vis/__init__.py +0 -0
- pythinker_code/vis/api/__init__.py +5 -0
- pythinker_code/vis/api/sessions.py +687 -0
- pythinker_code/vis/api/statistics.py +209 -0
- pythinker_code/vis/api/system.py +19 -0
- pythinker_code/vis/app.py +175 -0
- pythinker_code/vis/static/assets/highlighted-body-B3W2YXNL-D2MTYyJz.js +1 -0
- pythinker_code/vis/static/assets/index-CezafTt_.js +185 -0
- pythinker_code/vis/static/assets/index-DSRInNnm.css +1 -0
- pythinker_code/vis/static/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2 +0 -0
- pythinker_code/vis/static/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2 +0 -0
- pythinker_code/vis/static/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2 +0 -0
- pythinker_code/vis/static/assets/inter-greek-wght-normal-CkhJZR-_.woff2 +0 -0
- pythinker_code/vis/static/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
- pythinker_code/vis/static/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
- pythinker_code/vis/static/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2 +0 -0
- pythinker_code/vis/static/index.html +17 -0
- pythinker_code/web/__init__.py +5 -0
- pythinker_code/web/api/__init__.py +15 -0
- pythinker_code/web/api/config.py +208 -0
- pythinker_code/web/api/open_in.py +199 -0
- pythinker_code/web/api/sessions.py +1225 -0
- pythinker_code/web/app.py +451 -0
- pythinker_code/web/auth.py +191 -0
- pythinker_code/web/models.py +98 -0
- pythinker_code/web/runner/__init__.py +5 -0
- pythinker_code/web/runner/messages.py +57 -0
- pythinker_code/web/runner/process.py +754 -0
- pythinker_code/web/runner/worker.py +97 -0
- pythinker_code/web/static/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- pythinker_code/web/static/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- pythinker_code/web/static/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- pythinker_code/web/static/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- pythinker_code/web/static/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- pythinker_code/web/static/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- pythinker_code/web/static/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- pythinker_code/web/static/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- pythinker_code/web/static/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- pythinker_code/web/static/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- pythinker_code/web/static/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- pythinker_code/web/static/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- pythinker_code/web/static/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- pythinker_code/web/static/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- pythinker_code/web/static/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- pythinker_code/web/static/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- pythinker_code/web/static/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- pythinker_code/web/static/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- pythinker_code/web/static/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- pythinker_code/web/static/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- pythinker_code/web/static/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- pythinker_code/web/static/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- pythinker_code/web/static/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- pythinker_code/web/static/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- pythinker_code/web/static/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- pythinker_code/web/static/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- pythinker_code/web/static/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- pythinker_code/web/static/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- pythinker_code/web/static/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- pythinker_code/web/static/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- pythinker_code/web/static/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- pythinker_code/web/static/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- pythinker_code/web/static/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- pythinker_code/web/static/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- pythinker_code/web/static/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- pythinker_code/web/static/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- pythinker_code/web/static/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- pythinker_code/web/static/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- pythinker_code/web/static/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- pythinker_code/web/static/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- pythinker_code/web/static/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- pythinker_code/web/static/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- pythinker_code/web/static/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- pythinker_code/web/static/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- pythinker_code/web/static/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- pythinker_code/web/static/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- pythinker_code/web/static/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- pythinker_code/web/static/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- pythinker_code/web/static/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- pythinker_code/web/static/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- pythinker_code/web/static/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- pythinker_code/web/static/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- pythinker_code/web/static/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- pythinker_code/web/static/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- pythinker_code/web/static/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- pythinker_code/web/static/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- pythinker_code/web/static/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- pythinker_code/web/static/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- pythinker_code/web/static/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- pythinker_code/web/static/assets/_baseUniq--dyU3g5v.js +1 -0
- pythinker_code/web/static/assets/abap-BdImnpbu.js +1 -0
- pythinker_code/web/static/assets/actionscript-3-CfeIJUat.js +1 -0
- pythinker_code/web/static/assets/ada-bCR0ucgS.js +1 -0
- pythinker_code/web/static/assets/andromeeda-C-Jbm3Hp.js +1 -0
- pythinker_code/web/static/assets/angular-html-CU67Zn6k.js +1 -0
- pythinker_code/web/static/assets/angular-ts-BwZT4LLn.js +1 -0
- pythinker_code/web/static/assets/apache-Pmp26Uib.js +1 -0
- pythinker_code/web/static/assets/apex-D8_7TLub.js +1 -0
- pythinker_code/web/static/assets/apl-dKokRX4l.js +1 -0
- pythinker_code/web/static/assets/applescript-Co6uUVPk.js +1 -0
- pythinker_code/web/static/assets/ara-BRHolxvo.js +1 -0
- pythinker_code/web/static/assets/arc-DkMjLpYa.js +1 -0
- pythinker_code/web/static/assets/architectureDiagram-VXUJARFQ-CHWVaGo9.js +36 -0
- pythinker_code/web/static/assets/asciidoc-Dv7Oe6Be.js +1 -0
- pythinker_code/web/static/assets/asm-D_Q5rh1f.js +1 -0
- pythinker_code/web/static/assets/astro-CbQHKStN.js +1 -0
- pythinker_code/web/static/assets/aurora-x-D-2ljcwZ.js +1 -0
- pythinker_code/web/static/assets/awk-DMzUqQB5.js +1 -0
- pythinker_code/web/static/assets/ayu-dark-CmMr59Fi.js +1 -0
- pythinker_code/web/static/assets/ballerina-BFfxhgS-.js +1 -0
- pythinker_code/web/static/assets/bat-BkioyH1T.js +1 -0
- pythinker_code/web/static/assets/beancount-k_qm7-4y.js +1 -0
- pythinker_code/web/static/assets/berry-uYugtg8r.js +1 -0
- pythinker_code/web/static/assets/bibtex-CHM0blh-.js +1 -0
- pythinker_code/web/static/assets/bicep-Bmn6On1c.js +1 -0
- pythinker_code/web/static/assets/blade-D4QpJJKB.js +1 -0
- pythinker_code/web/static/assets/blockDiagram-VD42YOAC-DzdKe497.js +122 -0
- pythinker_code/web/static/assets/bsl-BO_Y6i37.js +1 -0
- pythinker_code/web/static/assets/c-BIGW1oBm.js +1 -0
- pythinker_code/web/static/assets/c3-VCDPK7BO.js +1 -0
- pythinker_code/web/static/assets/c4Diagram-YG6GDRKO-D84Blotg.js +10 -0
- pythinker_code/web/static/assets/cadence-Bv_4Rxtq.js +1 -0
- pythinker_code/web/static/assets/cairo-KRGpt6FW.js +1 -0
- pythinker_code/web/static/assets/catppuccin-frappe-DFWUc33u.js +1 -0
- pythinker_code/web/static/assets/catppuccin-latte-C9dUb6Cb.js +1 -0
- pythinker_code/web/static/assets/catppuccin-macchiato-DQyhUUbL.js +1 -0
- pythinker_code/web/static/assets/catppuccin-mocha-D87Tk5Gz.js +1 -0
- pythinker_code/web/static/assets/channel-CllSjjdl.js +1 -0
- pythinker_code/web/static/assets/chunk-4BX2VUAB-C9w8wleE.js +1 -0
- pythinker_code/web/static/assets/chunk-55IACEB6-YlYJ8HnF.js +1 -0
- pythinker_code/web/static/assets/chunk-B4BG7PRW-Bwtz_AHU.js +165 -0
- pythinker_code/web/static/assets/chunk-DI55MBZ5-BbEHkl8h.js +220 -0
- pythinker_code/web/static/assets/chunk-FMBD7UC4-BKPbvjLC.js +15 -0
- pythinker_code/web/static/assets/chunk-QN33PNHL-D73dQvKf.js +1 -0
- pythinker_code/web/static/assets/chunk-QZHKN3VN-zGiLKes_.js +1 -0
- pythinker_code/web/static/assets/chunk-TZMSLE5B-LHJCi2fy.js +1 -0
- pythinker_code/web/static/assets/clarity-D53aC0YG.js +1 -0
- pythinker_code/web/static/assets/classDiagram-2ON5EDUG-vX27iZwa.js +1 -0
- pythinker_code/web/static/assets/classDiagram-v2-WZHVMYZB-vX27iZwa.js +1 -0
- pythinker_code/web/static/assets/clojure-P80f7IUj.js +1 -0
- pythinker_code/web/static/assets/clone-DYBkaPm2.js +1 -0
- pythinker_code/web/static/assets/cmake-D1j8_8rp.js +1 -0
- pythinker_code/web/static/assets/cobol-nwyudZeR.js +1 -0
- pythinker_code/web/static/assets/code-block-IT6T5CEO-NtKViZGl.js +2 -0
- pythinker_code/web/static/assets/codeowners-Bp6g37R7.js +1 -0
- pythinker_code/web/static/assets/codeql-DsOJ9woJ.js +1 -0
- pythinker_code/web/static/assets/coffee-Ch7k5sss.js +1 -0
- pythinker_code/web/static/assets/common-lisp-Cg-RD9OK.js +1 -0
- pythinker_code/web/static/assets/coq-DkFqJrB1.js +1 -0
- pythinker_code/web/static/assets/cose-bilkent-S5V4N54A-DialjZpd.js +1 -0
- pythinker_code/web/static/assets/cpp-CofmeUqb.js +1 -0
- pythinker_code/web/static/assets/crystal-tKQVLTB8.js +1 -0
- pythinker_code/web/static/assets/csharp-K5feNrxe.js +1 -0
- pythinker_code/web/static/assets/css-DPfMkruS.js +1 -0
- pythinker_code/web/static/assets/csv-fuZLfV_i.js +1 -0
- pythinker_code/web/static/assets/cue-D82EKSYY.js +1 -0
- pythinker_code/web/static/assets/cypher-COkxafJQ.js +1 -0
- pythinker_code/web/static/assets/cytoscape.esm-C_Fzpdck.js +321 -0
- pythinker_code/web/static/assets/d-85-TOEBH.js +1 -0
- pythinker_code/web/static/assets/dagre-6UL2VRFP-DfuvkZZ7.js +4 -0
- pythinker_code/web/static/assets/dark-plus-C3mMm8J8.js +1 -0
- pythinker_code/web/static/assets/dart-CF10PKvl.js +1 -0
- pythinker_code/web/static/assets/dax-CEL-wOlO.js +1 -0
- pythinker_code/web/static/assets/defaultLocale-DX6XiGOO.js +1 -0
- pythinker_code/web/static/assets/desktop-BmXAJ9_W.js +1 -0
- pythinker_code/web/static/assets/diagram-PSM6KHXK-DLGctX3v.js +24 -0
- pythinker_code/web/static/assets/diagram-QEK2KX5R-DnxN6S0F.js +43 -0
- pythinker_code/web/static/assets/diagram-S2PKOQOG-Caq_Set9.js +24 -0
- pythinker_code/web/static/assets/diff-D97Zzqfu.js +1 -0
- pythinker_code/web/static/assets/docker-BcOcwvcX.js +1 -0
- pythinker_code/web/static/assets/dotenv-Da5cRb03.js +1 -0
- pythinker_code/web/static/assets/dracula-BzJJZx-M.js +1 -0
- pythinker_code/web/static/assets/dracula-soft-BXkSAIEj.js +1 -0
- pythinker_code/web/static/assets/dream-maker-BtqSS_iP.js +1 -0
- pythinker_code/web/static/assets/edge-BkV0erSs.js +1 -0
- pythinker_code/web/static/assets/elixir-CDX3lj18.js +1 -0
- pythinker_code/web/static/assets/elm-DbKCFpqz.js +1 -0
- pythinker_code/web/static/assets/emacs-lisp-C9XAeP06.js +1 -0
- pythinker_code/web/static/assets/erDiagram-Q2GNP2WA-BgTfALoK.js +60 -0
- pythinker_code/web/static/assets/erb-BOJIQeun.js +1 -0
- pythinker_code/web/static/assets/erlang-DsQrWhSR.js +1 -0
- pythinker_code/web/static/assets/everforest-dark-BgDCqdQA.js +1 -0
- pythinker_code/web/static/assets/everforest-light-C8M2exoo.js +1 -0
- pythinker_code/web/static/assets/fennel-BYunw83y.js +1 -0
- pythinker_code/web/static/assets/fish-BvzEVeQv.js +1 -0
- pythinker_code/web/static/assets/flowDiagram-NV44I4VS-QjW_fnGi.js +162 -0
- pythinker_code/web/static/assets/fluent-C4IJs8-o.js +1 -0
- pythinker_code/web/static/assets/fortran-fixed-form-CkoXwp7k.js +1 -0
- pythinker_code/web/static/assets/fortran-free-form-BxgE0vQu.js +1 -0
- pythinker_code/web/static/assets/fsharp-CXgrBDvD.js +1 -0
- pythinker_code/web/static/assets/ganttDiagram-JELNMOA3-fqi8JFof.js +267 -0
- pythinker_code/web/static/assets/gdresource-B7Tvp0Sc.js +1 -0
- pythinker_code/web/static/assets/gdscript-DTMYz4Jt.js +1 -0
- pythinker_code/web/static/assets/gdshader-DkwncUOv.js +1 -0
- pythinker_code/web/static/assets/genie-D0YGMca9.js +1 -0
- pythinker_code/web/static/assets/gherkin-DyxjwDmM.js +1 -0
- pythinker_code/web/static/assets/git-commit-F4YmCXRG.js +1 -0
- pythinker_code/web/static/assets/git-rebase-r7XF79zn.js +1 -0
- pythinker_code/web/static/assets/gitGraphDiagram-NY62KEGX-i7o6VQ8x.js +65 -0
- pythinker_code/web/static/assets/github-dark-DHJKELXO.js +1 -0
- pythinker_code/web/static/assets/github-dark-default-Cuk6v7N8.js +1 -0
- pythinker_code/web/static/assets/github-dark-dimmed-DH5Ifo-i.js +1 -0
- pythinker_code/web/static/assets/github-dark-high-contrast-E3gJ1_iC.js +1 -0
- pythinker_code/web/static/assets/github-light-DAi9KRSo.js +1 -0
- pythinker_code/web/static/assets/github-light-default-D7oLnXFd.js +1 -0
- pythinker_code/web/static/assets/github-light-high-contrast-BfjtVDDH.js +1 -0
- pythinker_code/web/static/assets/gleam-BspZqrRM.js +1 -0
- pythinker_code/web/static/assets/glimmer-js-Rg0-pVw9.js +1 -0
- pythinker_code/web/static/assets/glimmer-ts-U6CK756n.js +1 -0
- pythinker_code/web/static/assets/glsl-DplSGwfg.js +1 -0
- pythinker_code/web/static/assets/gn-n2N0HUVH.js +1 -0
- pythinker_code/web/static/assets/gnuplot-DdkO51Og.js +1 -0
- pythinker_code/web/static/assets/go-Dn2_MT6a.js +1 -0
- pythinker_code/web/static/assets/graph-C0vZK2pT.js +1 -0
- pythinker_code/web/static/assets/graphql-ChdNCCLP.js +1 -0
- pythinker_code/web/static/assets/groovy-gcz8RCvz.js +1 -0
- pythinker_code/web/static/assets/gruvbox-dark-hard-CFHQjOhq.js +1 -0
- pythinker_code/web/static/assets/gruvbox-dark-medium-GsRaNv29.js +1 -0
- pythinker_code/web/static/assets/gruvbox-dark-soft-CVdnzihN.js +1 -0
- pythinker_code/web/static/assets/gruvbox-light-hard-CH1njM8p.js +1 -0
- pythinker_code/web/static/assets/gruvbox-light-medium-DRw_LuNl.js +1 -0
- pythinker_code/web/static/assets/gruvbox-light-soft-hJgmCMqR.js +1 -0
- pythinker_code/web/static/assets/hack-CaT9iCJl.js +1 -0
- pythinker_code/web/static/assets/haml-B8DHNrY2.js +1 -0
- pythinker_code/web/static/assets/handlebars-BL8al0AC.js +1 -0
- pythinker_code/web/static/assets/haskell-Df6bDoY_.js +1 -0
- pythinker_code/web/static/assets/haxe-CzTSHFRz.js +1 -0
- pythinker_code/web/static/assets/hcl-BWvSN4gD.js +1 -0
- pythinker_code/web/static/assets/hjson-D5-asLiD.js +1 -0
- pythinker_code/web/static/assets/hlsl-D3lLCCz7.js +1 -0
- pythinker_code/web/static/assets/houston-DnULxvSX.js +1 -0
- pythinker_code/web/static/assets/html-GMplVEZG.js +1 -0
- pythinker_code/web/static/assets/html-derivative-BFtXZ54Q.js +1 -0
- pythinker_code/web/static/assets/http-jrhK8wxY.js +1 -0
- pythinker_code/web/static/assets/hurl-irOxFIW8.js +1 -0
- pythinker_code/web/static/assets/hxml-Bvhsp5Yf.js +1 -0
- pythinker_code/web/static/assets/hy-DFXneXwc.js +1 -0
- pythinker_code/web/static/assets/imba-DGztddWO.js +1 -0
- pythinker_code/web/static/assets/index-BYCCk6-K.js +153 -0
- pythinker_code/web/static/assets/index-BpoLgcEt.js +1 -0
- pythinker_code/web/static/assets/index-Cpy4G3uJ.js +2 -0
- pythinker_code/web/static/assets/index-CzV_vCfu.css +1 -0
- pythinker_code/web/static/assets/index-DI2oedCt.js +19 -0
- pythinker_code/web/static/assets/index-DdIkp80K.js +5 -0
- pythinker_code/web/static/assets/infoDiagram-WHAUD3N6-BMPpeZSM.js +2 -0
- pythinker_code/web/static/assets/ini-BEwlwnbL.js +1 -0
- pythinker_code/web/static/assets/init-Gi6I4Gst.js +1 -0
- pythinker_code/web/static/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2 +0 -0
- pythinker_code/web/static/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2 +0 -0
- pythinker_code/web/static/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2 +0 -0
- pythinker_code/web/static/assets/inter-greek-wght-normal-CkhJZR-_.woff2 +0 -0
- pythinker_code/web/static/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
- pythinker_code/web/static/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
- pythinker_code/web/static/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2 +0 -0
- pythinker_code/web/static/assets/java-CylS5w8V.js +1 -0
- pythinker_code/web/static/assets/javascript-wDzz0qaB.js +1 -0
- pythinker_code/web/static/assets/jinja-4LBKfQ-Z.js +1 -0
- pythinker_code/web/static/assets/jison-wvAkD_A8.js +1 -0
- pythinker_code/web/static/assets/journeyDiagram-XKPGCS4Q-DAM7gngo.js +139 -0
- pythinker_code/web/static/assets/json-Cp-IABpG.js +1 -0
- pythinker_code/web/static/assets/json5-C9tS-k6U.js +1 -0
- pythinker_code/web/static/assets/jsonc-Des-eS-w.js +1 -0
- pythinker_code/web/static/assets/jsonl-DcaNXYhu.js +1 -0
- pythinker_code/web/static/assets/jsonnet-DFQXde-d.js +1 -0
- pythinker_code/web/static/assets/jssm-C2t-YnRu.js +1 -0
- pythinker_code/web/static/assets/jsx-g9-lgVsj.js +1 -0
- pythinker_code/web/static/assets/julia-CxzCAyBv.js +1 -0
- pythinker_code/web/static/assets/kanagawa-dragon-CkXjmgJE.js +1 -0
- pythinker_code/web/static/assets/kanagawa-lotus-CfQXZHmo.js +1 -0
- pythinker_code/web/static/assets/kanagawa-wave-DWedfzmr.js +1 -0
- pythinker_code/web/static/assets/kanban-definition-3W4ZIXB7-ChpBpV0k.js +89 -0
- pythinker_code/web/static/assets/katex-D2lIc1rk.css +1 -0
- pythinker_code/web/static/assets/kdl-DV7GczEv.js +1 -0
- pythinker_code/web/static/assets/kotlin-BdnUsdx6.js +1 -0
- pythinker_code/web/static/assets/kusto-DZf3V79B.js +1 -0
- pythinker_code/web/static/assets/laserwave-DUszq2jm.js +1 -0
- pythinker_code/web/static/assets/latex-B4uzh10-.js +1 -0
- pythinker_code/web/static/assets/layout-C3Jp1gKO.js +1 -0
- pythinker_code/web/static/assets/lean-BZvkOJ9d.js +1 -0
- pythinker_code/web/static/assets/less-B1dDrJ26.js +1 -0
- pythinker_code/web/static/assets/light-plus-B7mTdjB0.js +1 -0
- pythinker_code/web/static/assets/linear-BGHtL1N4.js +1 -0
- pythinker_code/web/static/assets/liquid-DYVedYrR.js +1 -0
- pythinker_code/web/static/assets/llvm-BtvRca6l.js +1 -0
- pythinker_code/web/static/assets/log-2UxHyX5q.js +1 -0
- pythinker_code/web/static/assets/logo-BtOb2qkB.js +1 -0
- pythinker_code/web/static/assets/lua-BbnMAYS6.js +1 -0
- pythinker_code/web/static/assets/luau-C-HG3fhB.js +1 -0
- pythinker_code/web/static/assets/make-CHLpvVh8.js +1 -0
- pythinker_code/web/static/assets/markdown-Cvjx9yec.js +1 -0
- pythinker_code/web/static/assets/marko-DZsq8hO1.js +1 -0
- pythinker_code/web/static/assets/material-theme-D5KoaKCx.js +1 -0
- pythinker_code/web/static/assets/material-theme-darker-BfHTSMKl.js +1 -0
- pythinker_code/web/static/assets/material-theme-lighter-B0m2ddpp.js +1 -0
- pythinker_code/web/static/assets/material-theme-ocean-CyktbL80.js +1 -0
- pythinker_code/web/static/assets/material-theme-palenight-Csfq5Kiy.js +1 -0
- pythinker_code/web/static/assets/matlab-D7o27uSR.js +1 -0
- pythinker_code/web/static/assets/mdc-DUICxH0z.js +1 -0
- pythinker_code/web/static/assets/mdx-Cmh6b_Ma.js +1 -0
- pythinker_code/web/static/assets/mermaid-VLURNSYL-B2P5VJ9v.css +1 -0
- pythinker_code/web/static/assets/mermaid-VLURNSYL-C_HW6koB.js +465 -0
- pythinker_code/web/static/assets/mermaid-mWjccvbQ.js +1 -0
- pythinker_code/web/static/assets/mermaid.core-CnT4VrPC.js +191 -0
- pythinker_code/web/static/assets/min-Dn5VRVmX.js +1 -0
- pythinker_code/web/static/assets/min-dark-CafNBF8u.js +1 -0
- pythinker_code/web/static/assets/min-light-CTRr51gU.js +1 -0
- pythinker_code/web/static/assets/mindmap-definition-VGOIOE7T-x8EwhfIt.js +68 -0
- pythinker_code/web/static/assets/mipsasm-CKIfxQSi.js +1 -0
- pythinker_code/web/static/assets/mojo-B93PlW-d.js +1 -0
- pythinker_code/web/static/assets/monokai-D4h5O-jR.js +1 -0
- pythinker_code/web/static/assets/moonbit-Ba13S78F.js +1 -0
- pythinker_code/web/static/assets/move-Bu9oaDYs.js +1 -0
- pythinker_code/web/static/assets/narrat-DRg8JJMk.js +1 -0
- pythinker_code/web/static/assets/nextflow-BrzmwbiE.js +1 -0
- pythinker_code/web/static/assets/nginx-DknmC5AR.js +1 -0
- pythinker_code/web/static/assets/night-owl-C39BiMTA.js +1 -0
- pythinker_code/web/static/assets/nim-CVrawwO9.js +1 -0
- pythinker_code/web/static/assets/nix-CwoSXNpI.js +1 -0
- pythinker_code/web/static/assets/nord-Ddv68eIx.js +1 -0
- pythinker_code/web/static/assets/nushell-C-sUppwS.js +1 -0
- pythinker_code/web/static/assets/objective-c-DXmwc3jG.js +1 -0
- pythinker_code/web/static/assets/objective-cpp-CLxacb5B.js +1 -0
- pythinker_code/web/static/assets/ocaml-C0hk2d4L.js +1 -0
- pythinker_code/web/static/assets/one-dark-pro-DVMEJ2y_.js +1 -0
- pythinker_code/web/static/assets/one-light-PoHY5YXO.js +1 -0
- pythinker_code/web/static/assets/openscad-C4EeE6gA.js +1 -0
- pythinker_code/web/static/assets/ordinal-Cboi1Yqb.js +1 -0
- pythinker_code/web/static/assets/pascal-D93ZcfNL.js +1 -0
- pythinker_code/web/static/assets/perl-C0TMdlhV.js +1 -0
- pythinker_code/web/static/assets/php-CDn_0X-4.js +1 -0
- pythinker_code/web/static/assets/pieDiagram-ADFJNKIX-DgxBKGz2.js +30 -0
- pythinker_code/web/static/assets/pkl-u5AG7uiY.js +1 -0
- pythinker_code/web/static/assets/plastic-3e1v2bzS.js +1 -0
- pythinker_code/web/static/assets/plsql-ChMvpjG-.js +1 -0
- pythinker_code/web/static/assets/po-BTJTHyun.js +1 -0
- pythinker_code/web/static/assets/poimandres-CS3Unz2-.js +1 -0
- pythinker_code/web/static/assets/polar-C0HS_06l.js +1 -0
- pythinker_code/web/static/assets/postcss-CXtECtnM.js +1 -0
- pythinker_code/web/static/assets/powerquery-CEu0bR-o.js +1 -0
- pythinker_code/web/static/assets/powershell-Dpen1YoG.js +1 -0
- pythinker_code/web/static/assets/prisma-Dd19v3D-.js +1 -0
- pythinker_code/web/static/assets/prolog-CbFg5uaA.js +1 -0
- pythinker_code/web/static/assets/proto-C7zT0LnQ.js +1 -0
- pythinker_code/web/static/assets/pug-CGlum2m_.js +1 -0
- pythinker_code/web/static/assets/puppet-BMWR74SV.js +1 -0
- pythinker_code/web/static/assets/purescript-CklMAg4u.js +1 -0
- pythinker_code/web/static/assets/python-B6aJPvgy.js +1 -0
- pythinker_code/web/static/assets/qml-3beO22l8.js +1 -0
- pythinker_code/web/static/assets/qmldir-C8lEn-DE.js +1 -0
- pythinker_code/web/static/assets/qss-IeuSbFQv.js +1 -0
- pythinker_code/web/static/assets/quadrantDiagram-AYHSOK5B-DSpe_dqk.js +7 -0
- pythinker_code/web/static/assets/r-Dspwwk_N.js +1 -0
- pythinker_code/web/static/assets/racket-BqYA7rlc.js +1 -0
- pythinker_code/web/static/assets/raku-DXvB9xmW.js +1 -0
- pythinker_code/web/static/assets/razor-C1TweQQi.js +1 -0
- pythinker_code/web/static/assets/red-bN70gL4F.js +1 -0
- pythinker_code/web/static/assets/reg-C-SQnVFl.js +1 -0
- pythinker_code/web/static/assets/regexp-CDVJQ6XC.js +1 -0
- pythinker_code/web/static/assets/rel-C3B-1QV4.js +1 -0
- pythinker_code/web/static/assets/requirementDiagram-UZGBJVZJ-8o9hozL-.js +64 -0
- pythinker_code/web/static/assets/riscv-BM1_JUlF.js +1 -0
- pythinker_code/web/static/assets/rose-pine-dawn-DHQR4-dF.js +1 -0
- pythinker_code/web/static/assets/rose-pine-moon-D4_iv3hh.js +1 -0
- pythinker_code/web/static/assets/rose-pine-qdsjHGoJ.js +1 -0
- pythinker_code/web/static/assets/rosmsg-BJDFO7_C.js +1 -0
- pythinker_code/web/static/assets/rst-B0xPkSld.js +1 -0
- pythinker_code/web/static/assets/ruby-BvKwtOVI.js +1 -0
- pythinker_code/web/static/assets/rust-B1yitclQ.js +1 -0
- pythinker_code/web/static/assets/sankeyDiagram-TZEHDZUN-BLOSUixH.js +10 -0
- pythinker_code/web/static/assets/sas-cz2c8ADy.js +1 -0
- pythinker_code/web/static/assets/sass-Cj5Yp3dK.js +1 -0
- pythinker_code/web/static/assets/scala-C151Ov-r.js +1 -0
- pythinker_code/web/static/assets/scheme-C98Dy4si.js +1 -0
- pythinker_code/web/static/assets/scss-OYdSNvt2.js +1 -0
- pythinker_code/web/static/assets/sdbl-DVxCFoDh.js +1 -0
- pythinker_code/web/static/assets/sequenceDiagram-WL72ISMW-6F2G8JTU.js +145 -0
- pythinker_code/web/static/assets/shaderlab-Dg9Lc6iA.js +1 -0
- pythinker_code/web/static/assets/shellscript-Yzrsuije.js +1 -0
- pythinker_code/web/static/assets/shellsession-BADoaaVG.js +1 -0
- pythinker_code/web/static/assets/slack-dark-BthQWCQV.js +1 -0
- pythinker_code/web/static/assets/slack-ochin-DqwNpetd.js +1 -0
- pythinker_code/web/static/assets/smalltalk-BERRCDM3.js +1 -0
- pythinker_code/web/static/assets/snazzy-light-Bw305WKR.js +1 -0
- pythinker_code/web/static/assets/solarized-dark-DXbdFlpD.js +1 -0
- pythinker_code/web/static/assets/solarized-light-L9t79GZl.js +1 -0
- pythinker_code/web/static/assets/solidity-rGO070M0.js +1 -0
- pythinker_code/web/static/assets/soy-Brmx7dQM.js +1 -0
- pythinker_code/web/static/assets/sparql-rVzFXLq3.js +1 -0
- pythinker_code/web/static/assets/splunk-BtCnVYZw.js +1 -0
- pythinker_code/web/static/assets/sql-BLtJtn59.js +1 -0
- pythinker_code/web/static/assets/ssh-config-_ykCGR6B.js +1 -0
- pythinker_code/web/static/assets/stata-BH5u7GGu.js +1 -0
- pythinker_code/web/static/assets/stateDiagram-FKZM4ZOC-DP8xP0iJ.js +1 -0
- pythinker_code/web/static/assets/stateDiagram-v2-4FDKWEC3-1l6-EZNX.js +1 -0
- pythinker_code/web/static/assets/stylus-BEDo0Tqx.js +1 -0
- pythinker_code/web/static/assets/svelte-zxCyuUbr.js +1 -0
- pythinker_code/web/static/assets/swift-Dg5xB15N.js +1 -0
- pythinker_code/web/static/assets/synthwave-84-CbfX1IO0.js +1 -0
- pythinker_code/web/static/assets/system-verilog-CnnmHF94.js +1 -0
- pythinker_code/web/static/assets/systemd-4A_iFExJ.js +1 -0
- pythinker_code/web/static/assets/talonscript-CkByrt1z.js +1 -0
- pythinker_code/web/static/assets/tasl-QIJgUcNo.js +1 -0
- pythinker_code/web/static/assets/tcl-dwOrl1Do.js +1 -0
- pythinker_code/web/static/assets/templ-W15q3VgB.js +1 -0
- pythinker_code/web/static/assets/terraform-BETggiCN.js +1 -0
- pythinker_code/web/static/assets/tex-CvyZ59Mk.js +1 -0
- pythinker_code/web/static/assets/timeline-definition-IT6M3QCI-DMgruDfK.js +61 -0
- pythinker_code/web/static/assets/tokyo-night-hegEt444.js +1 -0
- pythinker_code/web/static/assets/toml-vGWfd6FD.js +1 -0
- pythinker_code/web/static/assets/treemap-KMMF4GRG-Bo9ZkrAK.js +128 -0
- pythinker_code/web/static/assets/ts-tags-zn1MmPIZ.js +1 -0
- pythinker_code/web/static/assets/tsv-B_m7g4N7.js +1 -0
- pythinker_code/web/static/assets/tsx-COt5Ahok.js +1 -0
- pythinker_code/web/static/assets/turtle-BsS91CYL.js +1 -0
- pythinker_code/web/static/assets/twig-CO9l9SDP.js +1 -0
- pythinker_code/web/static/assets/typescript-BPQ3VLAy.js +1 -0
- pythinker_code/web/static/assets/typespec-BGHnOYBU.js +1 -0
- pythinker_code/web/static/assets/typst-DHCkPAjA.js +1 -0
- pythinker_code/web/static/assets/v-BcVCzyr7.js +1 -0
- pythinker_code/web/static/assets/vala-CsfeWuGM.js +1 -0
- pythinker_code/web/static/assets/vb-D17OF-Vu.js +1 -0
- pythinker_code/web/static/assets/verilog-BQ8w6xss.js +1 -0
- pythinker_code/web/static/assets/vesper-DU1UobuO.js +1 -0
- pythinker_code/web/static/assets/vhdl-CeAyd5Ju.js +1 -0
- pythinker_code/web/static/assets/viml-CJc9bBzg.js +1 -0
- pythinker_code/web/static/assets/vitesse-black-Bkuqu6BP.js +1 -0
- pythinker_code/web/static/assets/vitesse-dark-D0r3Knsf.js +1 -0
- pythinker_code/web/static/assets/vitesse-light-CVO1_9PV.js +1 -0
- pythinker_code/web/static/assets/vue-DN_0RTcg.js +1 -0
- pythinker_code/web/static/assets/vue-html-AaS7Mt5G.js +1 -0
- pythinker_code/web/static/assets/vue-vine-CQOfvN7w.js +1 -0
- pythinker_code/web/static/assets/vyper-CDx5xZoG.js +1 -0
- pythinker_code/web/static/assets/wasm-CG6Dc4jp.js +1 -0
- pythinker_code/web/static/assets/wasm-MzD3tlZU.js +1 -0
- pythinker_code/web/static/assets/wenyan-BV7otONQ.js +1 -0
- pythinker_code/web/static/assets/wgsl-Dx-B1_4e.js +1 -0
- pythinker_code/web/static/assets/wikitext-BhOHFoWU.js +1 -0
- pythinker_code/web/static/assets/wit-5i3qLPDT.js +1 -0
- pythinker_code/web/static/assets/wolfram-lXgVvXCa.js +1 -0
- pythinker_code/web/static/assets/xml-sdJ4AIDG.js +1 -0
- pythinker_code/web/static/assets/xsl-CtQFsRM5.js +1 -0
- pythinker_code/web/static/assets/xychartDiagram-PRI3JC2R-GeF2johi.js +7 -0
- pythinker_code/web/static/assets/yaml-Buea-lGh.js +1 -0
- pythinker_code/web/static/assets/zenscript-DVFEvuxE.js +1 -0
- pythinker_code/web/static/assets/zig-VOosw3JB.js +1 -0
- pythinker_code/web/static/brand/apple-touch-icon.png +0 -0
- pythinker_code/web/static/brand/arctecture.webp +0 -0
- pythinker_code/web/static/brand/bimi-logo.svg +46 -0
- pythinker_code/web/static/brand/favicon.ico +0 -0
- pythinker_code/web/static/brand/fonts/dm-sans-latin-ext.woff2 +0 -0
- pythinker_code/web/static/brand/fonts/dm-sans-latin.woff2 +0 -0
- pythinker_code/web/static/brand/fonts/instrument-sans-latin-ext.woff2 +0 -0
- pythinker_code/web/static/brand/fonts/instrument-sans-latin.woff2 +0 -0
- pythinker_code/web/static/brand/fonts/instrument-serif-latin-ext.woff2 +0 -0
- pythinker_code/web/static/brand/fonts/instrument-serif-latin.woff2 +0 -0
- pythinker_code/web/static/brand/fonts/libre-baskerville-italic-latin-ext.woff2 +0 -0
- pythinker_code/web/static/brand/fonts/libre-baskerville-italic-latin.woff2 +0 -0
- pythinker_code/web/static/brand/fonts/libre-baskerville-latin-ext.woff2 +0 -0
- pythinker_code/web/static/brand/fonts/libre-baskerville-latin.woff2 +0 -0
- pythinker_code/web/static/brand/fonts/roboto-latin-ext.woff2 +0 -0
- pythinker_code/web/static/brand/fonts/roboto-latin.woff2 +0 -0
- pythinker_code/web/static/brand/icon-192.png +0 -0
- pythinker_code/web/static/brand/icon-512.png +0 -0
- pythinker_code/web/static/brand/icon.svg +1 -0
- pythinker_code/web/static/brand/logo.png +0 -0
- pythinker_code/web/static/brand/pythinker_animated.svg +79 -0
- pythinker_code/web/static/brand/robots.txt +4 -0
- pythinker_code/web/static/index.html +15 -0
- pythinker_code/web/static/logo.png +0 -0
- pythinker_code/web/store/__init__.py +1 -0
- pythinker_code/web/store/sessions.py +432 -0
- pythinker_code/wire/__init__.py +148 -0
- pythinker_code/wire/file.py +151 -0
- pythinker_code/wire/jsonrpc.py +263 -0
- pythinker_code/wire/protocol.py +2 -0
- pythinker_code/wire/root_hub.py +27 -0
- pythinker_code/wire/serde.py +26 -0
- pythinker_code/wire/server.py +1069 -0
- pythinker_code/wire/types.py +698 -0
- pythinker_code-2.0.0.dist-info/METADATA +660 -0
- pythinker_code-2.0.0.dist-info/RECORD +731 -0
- pythinker_code-2.0.0.dist-info/WHEEL +4 -0
- pythinker_code-2.0.0.dist-info/entry_points.txt +4 -0
- pythinker_code-2.0.0.dist-info/licenses/LICENSE +202 -0
- pythinker_code-2.0.0.dist-info/licenses/NOTICE +14 -0
|
@@ -0,0 +1,698 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
from typing import Any, Literal, TypeGuard, cast
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel, Field, field_serializer, field_validator, model_validator
|
|
7
|
+
from pythinker_core.chat_provider import TokenUsage
|
|
8
|
+
from pythinker_core.message import (
|
|
9
|
+
AudioURLPart,
|
|
10
|
+
ContentPart,
|
|
11
|
+
ImageURLPart,
|
|
12
|
+
TextPart,
|
|
13
|
+
ThinkPart,
|
|
14
|
+
ToolCall,
|
|
15
|
+
ToolCallPart,
|
|
16
|
+
VideoURLPart,
|
|
17
|
+
)
|
|
18
|
+
from pythinker_core.tooling import (
|
|
19
|
+
BriefDisplayBlock,
|
|
20
|
+
DisplayBlock,
|
|
21
|
+
ToolResult,
|
|
22
|
+
ToolReturnValue,
|
|
23
|
+
UnknownDisplayBlock,
|
|
24
|
+
)
|
|
25
|
+
from pythinker_core.utils.typing import JsonType
|
|
26
|
+
|
|
27
|
+
from pythinker_code.tools.display import (
|
|
28
|
+
BackgroundTaskDisplayBlock,
|
|
29
|
+
DiffDisplayBlock,
|
|
30
|
+
ShellDisplayBlock,
|
|
31
|
+
TodoDisplayBlock,
|
|
32
|
+
TodoDisplayItem,
|
|
33
|
+
)
|
|
34
|
+
from pythinker_code.utils.typing import flatten_union
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class TurnBegin(BaseModel):
|
|
38
|
+
"""
|
|
39
|
+
Indicates the beginning of a new agent turn.
|
|
40
|
+
This event must be sent before any other event in the turn.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
user_input: str | list[ContentPart]
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class SteerInput(BaseModel):
|
|
47
|
+
"""
|
|
48
|
+
Indicates that the user appended follow-up input to the current running turn.
|
|
49
|
+
This event is emitted after the current step finishes and the input is appended
|
|
50
|
+
to context, before the next step begins.
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
user_input: str | list[ContentPart]
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class TurnEnd(BaseModel):
|
|
57
|
+
"""
|
|
58
|
+
Indicates the end of the current agent turn.
|
|
59
|
+
This event must be sent after all other events in the turn.
|
|
60
|
+
If the turn is interrupted, this event may be omitted.
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
pass
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class StepBegin(BaseModel):
|
|
67
|
+
"""
|
|
68
|
+
Indicates the beginning of a new agent step.
|
|
69
|
+
This event must be sent before any other event in the step.
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
n: int
|
|
73
|
+
"""The step number."""
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class StepInterrupted(BaseModel):
|
|
77
|
+
"""Indicates the current step was interrupted, either by user intervention or an error."""
|
|
78
|
+
|
|
79
|
+
pass
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class CompactionBegin(BaseModel):
|
|
83
|
+
"""
|
|
84
|
+
Indicates that a compaction just began.
|
|
85
|
+
This event must be sent during a step, which means, between `StepBegin` and the next
|
|
86
|
+
`StepBegin` or `StepInterrupted`. And, there must be a `CompactionEnd` directly following
|
|
87
|
+
this event.
|
|
88
|
+
"""
|
|
89
|
+
|
|
90
|
+
pass
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class CompactionEnd(BaseModel):
|
|
94
|
+
"""
|
|
95
|
+
Indicates that a compaction just ended.
|
|
96
|
+
This event must be sent directly after a `CompactionBegin` event.
|
|
97
|
+
"""
|
|
98
|
+
|
|
99
|
+
pass
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
class HookTriggered(BaseModel):
|
|
103
|
+
"""A batch of hooks has been triggered and is now executing."""
|
|
104
|
+
|
|
105
|
+
event: str
|
|
106
|
+
"""The hook event type, e.g. 'PreToolUse', 'Stop'."""
|
|
107
|
+
target: str = ""
|
|
108
|
+
"""What the hooks are targeting: tool name for tool hooks,
|
|
109
|
+
agent name for subagent hooks, etc."""
|
|
110
|
+
hook_count: int = 1
|
|
111
|
+
"""Number of matched hooks running in parallel."""
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
class HookResolved(BaseModel):
|
|
115
|
+
"""A batch of hooks has finished executing."""
|
|
116
|
+
|
|
117
|
+
event: str
|
|
118
|
+
"""The hook event type, e.g. 'PreToolUse', 'Stop'."""
|
|
119
|
+
target: str = ""
|
|
120
|
+
"""Same as HookTriggered.target."""
|
|
121
|
+
action: Literal["allow", "block"] = "allow"
|
|
122
|
+
"""Aggregate decision: 'block' if any hook blocked, 'allow' otherwise."""
|
|
123
|
+
reason: str = ""
|
|
124
|
+
"""Reason for blocking. Empty if allowed."""
|
|
125
|
+
duration_ms: int = 0
|
|
126
|
+
"""Wall-clock time for the entire batch, in milliseconds."""
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
class MCPLoadingBegin(BaseModel):
|
|
130
|
+
"""Indicates that MCP tool loading is in progress."""
|
|
131
|
+
|
|
132
|
+
pass
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
class MCPLoadingEnd(BaseModel):
|
|
136
|
+
"""Indicates that MCP tool loading has finished."""
|
|
137
|
+
|
|
138
|
+
pass
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
class MCPServerSnapshot(BaseModel):
|
|
142
|
+
"""A snapshot of one MCP server during startup."""
|
|
143
|
+
|
|
144
|
+
name: str
|
|
145
|
+
status: Literal["pending", "connecting", "connected", "failed", "unauthorized"]
|
|
146
|
+
tools: tuple[str, ...] = ()
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
class MCPStatusSnapshot(BaseModel):
|
|
150
|
+
"""A snapshot of MCP startup progress."""
|
|
151
|
+
|
|
152
|
+
loading: bool
|
|
153
|
+
connected: int
|
|
154
|
+
total: int
|
|
155
|
+
tools: int
|
|
156
|
+
servers: tuple[MCPServerSnapshot, ...] = ()
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
class StatusUpdate(BaseModel):
|
|
160
|
+
"""
|
|
161
|
+
An update on the current status of the soul.
|
|
162
|
+
None fields indicate no change from the previous status.
|
|
163
|
+
"""
|
|
164
|
+
|
|
165
|
+
context_usage: float | None = None
|
|
166
|
+
"""The usage of the context, in percentage."""
|
|
167
|
+
context_tokens: int | None = None
|
|
168
|
+
"""The number of tokens currently in the context."""
|
|
169
|
+
max_context_tokens: int | None = None
|
|
170
|
+
"""The maximum number of tokens the context can hold."""
|
|
171
|
+
token_usage: TokenUsage | None = None
|
|
172
|
+
"""The token usage statistics of the current step."""
|
|
173
|
+
message_id: str | None = None
|
|
174
|
+
"""The message ID of the current step."""
|
|
175
|
+
plan_mode: bool | None = None
|
|
176
|
+
"""Whether plan mode (read-only) is active. None means no change."""
|
|
177
|
+
mcp_status: MCPStatusSnapshot | None = None
|
|
178
|
+
"""The current MCP startup snapshot. None means no change."""
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
class Notification(BaseModel):
|
|
182
|
+
"""A generic system notification for UI and client consumption."""
|
|
183
|
+
|
|
184
|
+
id: str
|
|
185
|
+
category: str
|
|
186
|
+
type: str
|
|
187
|
+
source_kind: str
|
|
188
|
+
source_id: str
|
|
189
|
+
title: str
|
|
190
|
+
body: str
|
|
191
|
+
severity: str
|
|
192
|
+
created_at: float
|
|
193
|
+
payload: dict[str, JsonType] = Field(default_factory=dict)
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
class PlanDisplay(BaseModel):
|
|
197
|
+
"""Displays a plan's content inline in the chat with special formatting."""
|
|
198
|
+
|
|
199
|
+
content: str
|
|
200
|
+
"""The full markdown content of the plan."""
|
|
201
|
+
file_path: str
|
|
202
|
+
"""The path to the plan file for reference."""
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
class BtwBegin(BaseModel):
|
|
206
|
+
"""Indicates that a side question (/btw) has started processing."""
|
|
207
|
+
|
|
208
|
+
id: str
|
|
209
|
+
"""Unique ID to pair with the corresponding BtwEnd."""
|
|
210
|
+
question: str
|
|
211
|
+
"""The user's original side question text."""
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
class BtwEnd(BaseModel):
|
|
215
|
+
"""Indicates that a side question (/btw) has finished."""
|
|
216
|
+
|
|
217
|
+
id: str
|
|
218
|
+
"""Unique ID matching the BtwBegin."""
|
|
219
|
+
response: str | None = None
|
|
220
|
+
"""The LLM's response text, or None if it failed."""
|
|
221
|
+
error: str | None = None
|
|
222
|
+
"""Error message if the side question failed."""
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
class SubagentEvent(BaseModel):
|
|
226
|
+
"""
|
|
227
|
+
An event from a subagent.
|
|
228
|
+
"""
|
|
229
|
+
|
|
230
|
+
parent_tool_call_id: str | None = None
|
|
231
|
+
"""The ID of the parent Agent tool call associated with this subagent."""
|
|
232
|
+
agent_id: str | None = None
|
|
233
|
+
"""The subagent instance ID."""
|
|
234
|
+
subagent_type: str | None = None
|
|
235
|
+
"""The built-in subagent type used by this instance."""
|
|
236
|
+
event: Event
|
|
237
|
+
"""The event from the subagent."""
|
|
238
|
+
# TODO: maybe restrict the event types? to exclude approval request, etc.
|
|
239
|
+
|
|
240
|
+
@model_validator(mode="before")
|
|
241
|
+
@classmethod
|
|
242
|
+
def _compat_legacy_fields(cls, value: Any) -> Any:
|
|
243
|
+
if not isinstance(value, dict):
|
|
244
|
+
return value
|
|
245
|
+
data = dict(cast(dict[str, Any], value))
|
|
246
|
+
if "parent_tool_call_id" not in data and "task_tool_call_id" in data:
|
|
247
|
+
data["parent_tool_call_id"] = data["task_tool_call_id"]
|
|
248
|
+
return data
|
|
249
|
+
|
|
250
|
+
@field_serializer("event", when_used="json")
|
|
251
|
+
def _serialize_event(self, event: Event) -> dict[str, Any]:
|
|
252
|
+
envelope = WireMessageEnvelope.from_wire_message(event)
|
|
253
|
+
return envelope.model_dump(mode="json")
|
|
254
|
+
|
|
255
|
+
@field_validator("event", mode="before")
|
|
256
|
+
@classmethod
|
|
257
|
+
def _validate_event(cls, value: Any) -> Event:
|
|
258
|
+
if is_wire_message(value):
|
|
259
|
+
if is_event(value):
|
|
260
|
+
return value
|
|
261
|
+
raise ValueError("SubagentEvent event must be an Event")
|
|
262
|
+
|
|
263
|
+
if not isinstance(value, dict):
|
|
264
|
+
raise ValueError("SubagentEvent event must be a dict")
|
|
265
|
+
event_type = cast(dict[str, Any], value).get("type")
|
|
266
|
+
event_payload = cast(dict[str, Any], value).get("payload")
|
|
267
|
+
envelope = WireMessageEnvelope.model_validate(
|
|
268
|
+
{"type": event_type, "payload": event_payload}
|
|
269
|
+
)
|
|
270
|
+
event = envelope.to_wire_message()
|
|
271
|
+
if not is_event(event):
|
|
272
|
+
raise ValueError("SubagentEvent event must be an Event")
|
|
273
|
+
return event
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
class ApprovalResponse(BaseModel):
|
|
277
|
+
"""
|
|
278
|
+
Indicates that an approval request has been resolved.
|
|
279
|
+
"""
|
|
280
|
+
|
|
281
|
+
type Kind = Literal["approve", "approve_for_session", "reject"]
|
|
282
|
+
|
|
283
|
+
request_id: str
|
|
284
|
+
"""The ID of the resolved approval request."""
|
|
285
|
+
response: Kind
|
|
286
|
+
"""The response to the approval request."""
|
|
287
|
+
feedback: str = ""
|
|
288
|
+
"""Optional user feedback when rejecting (e.g. instructions for the model)."""
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
class ApprovalRequest(BaseModel):
|
|
292
|
+
"""
|
|
293
|
+
A request for user approval before proceeding with an action.
|
|
294
|
+
"""
|
|
295
|
+
|
|
296
|
+
id: str
|
|
297
|
+
tool_call_id: str
|
|
298
|
+
sender: str
|
|
299
|
+
action: str
|
|
300
|
+
description: str
|
|
301
|
+
source_kind: Literal["foreground_turn", "background_agent"] | None = None
|
|
302
|
+
source_id: str | None = None
|
|
303
|
+
agent_id: str | None = None
|
|
304
|
+
subagent_type: str | None = None
|
|
305
|
+
source_description: str | None = None
|
|
306
|
+
display: list[DisplayBlock] = Field(default_factory=list[DisplayBlock])
|
|
307
|
+
"""Defaults to an empty list for backwards-compatible wire.jsonl loading."""
|
|
308
|
+
|
|
309
|
+
# Note that the above fields are just a copy of `pythinker_code.soul.approval.Request`, but
|
|
310
|
+
# we cannot directly use that class here because we want to avoid dependency from Wire
|
|
311
|
+
# to Soul.
|
|
312
|
+
|
|
313
|
+
def __init__(self, **kwargs: Any) -> None:
|
|
314
|
+
super().__init__(**kwargs)
|
|
315
|
+
self._future: asyncio.Future[ApprovalResponse.Kind] | None = None
|
|
316
|
+
self._feedback: str = ""
|
|
317
|
+
|
|
318
|
+
def _get_future(self) -> asyncio.Future[ApprovalResponse.Kind]:
|
|
319
|
+
if self._future is None:
|
|
320
|
+
self._future = asyncio.get_event_loop().create_future()
|
|
321
|
+
return self._future
|
|
322
|
+
|
|
323
|
+
async def wait(self) -> ApprovalResponse.Kind:
|
|
324
|
+
"""
|
|
325
|
+
Wait for the request to be resolved or cancelled.
|
|
326
|
+
|
|
327
|
+
Returns:
|
|
328
|
+
ApprovalResponse.Kind: The response to the approval request.
|
|
329
|
+
"""
|
|
330
|
+
return await self._get_future()
|
|
331
|
+
|
|
332
|
+
def resolve(self, response: ApprovalResponse.Kind, feedback: str = "") -> None:
|
|
333
|
+
"""
|
|
334
|
+
Resolve the approval request with the given response.
|
|
335
|
+
This will cause the `wait()` method to return the response.
|
|
336
|
+
"""
|
|
337
|
+
self._feedback = feedback
|
|
338
|
+
future = self._get_future()
|
|
339
|
+
if not future.done():
|
|
340
|
+
future.set_result(response)
|
|
341
|
+
|
|
342
|
+
@property
|
|
343
|
+
def feedback(self) -> str:
|
|
344
|
+
"""User feedback text provided with a rejection, if any."""
|
|
345
|
+
return self._feedback
|
|
346
|
+
|
|
347
|
+
@property
|
|
348
|
+
def resolved(self) -> bool:
|
|
349
|
+
"""Whether the request is resolved."""
|
|
350
|
+
return self._future is not None and self._future.done()
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
class QuestionOption(BaseModel):
|
|
354
|
+
"""A single option for a question."""
|
|
355
|
+
|
|
356
|
+
label: str
|
|
357
|
+
"""The display text for this option."""
|
|
358
|
+
description: str = ""
|
|
359
|
+
"""Explanation of what this option means."""
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
class QuestionItem(BaseModel):
|
|
363
|
+
"""A single question to ask the user."""
|
|
364
|
+
|
|
365
|
+
question: str
|
|
366
|
+
"""The complete question text."""
|
|
367
|
+
header: str = ""
|
|
368
|
+
"""Short label displayed as a tag (max 12 chars)."""
|
|
369
|
+
options: list[QuestionOption]
|
|
370
|
+
"""The available choices for this question (2-4 options)."""
|
|
371
|
+
multi_select: bool = False
|
|
372
|
+
"""Whether multiple options can be selected."""
|
|
373
|
+
body: str = ""
|
|
374
|
+
"""Optional body content (markdown) displayed above options."""
|
|
375
|
+
other_label: str = ""
|
|
376
|
+
"""Custom label for the synthetic 'Other' free-text option. Empty uses default."""
|
|
377
|
+
other_description: str = ""
|
|
378
|
+
"""Custom description for the synthetic 'Other' option. Empty uses default."""
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
class QuestionResponse(BaseModel):
|
|
382
|
+
"""Response to a question request."""
|
|
383
|
+
|
|
384
|
+
request_id: str
|
|
385
|
+
"""The ID of the resolved question request."""
|
|
386
|
+
answers: dict[str, str]
|
|
387
|
+
"""Mapping from question text to selected option label(s). Multi-select answers are
|
|
388
|
+
comma-separated."""
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
class QuestionNotSupported(Exception):
|
|
392
|
+
"""Raised when the connected client does not support interactive questions."""
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
class QuestionRequest(BaseModel):
|
|
396
|
+
"""
|
|
397
|
+
A request to ask the user structured questions during execution.
|
|
398
|
+
"""
|
|
399
|
+
|
|
400
|
+
id: str
|
|
401
|
+
"""The unique request ID."""
|
|
402
|
+
tool_call_id: str
|
|
403
|
+
"""The ID of the tool call that initiated this question."""
|
|
404
|
+
questions: list[QuestionItem]
|
|
405
|
+
"""The questions to ask the user (1-4 questions)."""
|
|
406
|
+
|
|
407
|
+
def __init__(self, **kwargs: Any) -> None:
|
|
408
|
+
super().__init__(**kwargs)
|
|
409
|
+
self._future: asyncio.Future[dict[str, str]] | None = None
|
|
410
|
+
|
|
411
|
+
def _get_future(self) -> asyncio.Future[dict[str, str]]:
|
|
412
|
+
if self._future is None:
|
|
413
|
+
self._future = asyncio.get_event_loop().create_future()
|
|
414
|
+
return self._future
|
|
415
|
+
|
|
416
|
+
async def wait(self) -> dict[str, str]:
|
|
417
|
+
"""
|
|
418
|
+
Wait for the question to be answered.
|
|
419
|
+
|
|
420
|
+
Returns:
|
|
421
|
+
dict[str, str]: Mapping from question text to answer.
|
|
422
|
+
"""
|
|
423
|
+
return await self._get_future()
|
|
424
|
+
|
|
425
|
+
def resolve(self, answers: dict[str, str]) -> None:
|
|
426
|
+
"""
|
|
427
|
+
Resolve the question request with the given answers.
|
|
428
|
+
This will cause the `wait()` method to return the answers.
|
|
429
|
+
"""
|
|
430
|
+
future = self._get_future()
|
|
431
|
+
if not future.done():
|
|
432
|
+
future.set_result(answers)
|
|
433
|
+
|
|
434
|
+
def set_exception(self, exc: BaseException) -> None:
|
|
435
|
+
"""Resolve the question request with an exception."""
|
|
436
|
+
future = self._get_future()
|
|
437
|
+
if not future.done():
|
|
438
|
+
future.set_exception(exc)
|
|
439
|
+
|
|
440
|
+
@property
|
|
441
|
+
def resolved(self) -> bool:
|
|
442
|
+
"""Whether the question request is resolved."""
|
|
443
|
+
return self._future is not None and self._future.done()
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
class ToolCallRequest(BaseModel):
|
|
447
|
+
"""
|
|
448
|
+
A tool call request routed to the Wire client for execution.
|
|
449
|
+
"""
|
|
450
|
+
|
|
451
|
+
id: str
|
|
452
|
+
"""The ID of the tool call."""
|
|
453
|
+
name: str
|
|
454
|
+
"""The name of the tool to call."""
|
|
455
|
+
arguments: str | None
|
|
456
|
+
"""Arguments of the tool call in JSON string format."""
|
|
457
|
+
|
|
458
|
+
def __init__(self, **kwargs: Any) -> None:
|
|
459
|
+
super().__init__(**kwargs)
|
|
460
|
+
self._future: asyncio.Future[ToolReturnValue] | None = None
|
|
461
|
+
|
|
462
|
+
def _get_future(self) -> asyncio.Future[ToolReturnValue]:
|
|
463
|
+
if self._future is None:
|
|
464
|
+
self._future = asyncio.get_event_loop().create_future()
|
|
465
|
+
return self._future
|
|
466
|
+
|
|
467
|
+
@staticmethod
|
|
468
|
+
def from_tool_call(tool_call: ToolCall) -> ToolCallRequest:
|
|
469
|
+
return ToolCallRequest(
|
|
470
|
+
id=tool_call.id,
|
|
471
|
+
name=tool_call.function.name,
|
|
472
|
+
arguments=tool_call.function.arguments,
|
|
473
|
+
)
|
|
474
|
+
|
|
475
|
+
async def wait(self) -> ToolReturnValue:
|
|
476
|
+
"""
|
|
477
|
+
Wait for the tool call to be resolved or cancelled.
|
|
478
|
+
|
|
479
|
+
Returns:
|
|
480
|
+
ToolReturnValue: The tool execution result.
|
|
481
|
+
"""
|
|
482
|
+
return await self._get_future()
|
|
483
|
+
|
|
484
|
+
def resolve(self, result: ToolReturnValue) -> None:
|
|
485
|
+
"""
|
|
486
|
+
Resolve the tool call with the given result.
|
|
487
|
+
This will cause the `wait()` method to return the result.
|
|
488
|
+
"""
|
|
489
|
+
future = self._get_future()
|
|
490
|
+
if not future.done():
|
|
491
|
+
future.set_result(result)
|
|
492
|
+
|
|
493
|
+
@property
|
|
494
|
+
def resolved(self) -> bool:
|
|
495
|
+
"""Whether the tool call is resolved."""
|
|
496
|
+
return self._future is not None and self._future.done()
|
|
497
|
+
|
|
498
|
+
|
|
499
|
+
type Event = (
|
|
500
|
+
TurnBegin
|
|
501
|
+
| SteerInput
|
|
502
|
+
| TurnEnd
|
|
503
|
+
| StepBegin
|
|
504
|
+
| StepInterrupted
|
|
505
|
+
| HookTriggered
|
|
506
|
+
| HookResolved
|
|
507
|
+
| CompactionBegin
|
|
508
|
+
| CompactionEnd
|
|
509
|
+
| MCPLoadingBegin
|
|
510
|
+
| MCPLoadingEnd
|
|
511
|
+
| StatusUpdate
|
|
512
|
+
| Notification
|
|
513
|
+
| ContentPart
|
|
514
|
+
| ToolCall
|
|
515
|
+
| ToolCallPart
|
|
516
|
+
| ToolResult
|
|
517
|
+
| ApprovalResponse
|
|
518
|
+
| SubagentEvent
|
|
519
|
+
| PlanDisplay
|
|
520
|
+
| BtwBegin
|
|
521
|
+
| BtwEnd
|
|
522
|
+
)
|
|
523
|
+
"""Any event, including control flow and content/tooling events."""
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
class HookResponse(BaseModel):
|
|
527
|
+
"""
|
|
528
|
+
Client response to a HookRequest.
|
|
529
|
+
"""
|
|
530
|
+
|
|
531
|
+
request_id: str
|
|
532
|
+
"""The ID of the HookRequest being responded to."""
|
|
533
|
+
action: Literal["allow", "block"] = "allow"
|
|
534
|
+
"""The decision: allow the action or block it."""
|
|
535
|
+
reason: str = ""
|
|
536
|
+
"""Reason for blocking. Empty if allowed."""
|
|
537
|
+
|
|
538
|
+
|
|
539
|
+
class HookRequest(BaseModel):
|
|
540
|
+
"""
|
|
541
|
+
A request for the wire client to handle a hook event.
|
|
542
|
+
The client runs its own logic and responds with allow/block.
|
|
543
|
+
"""
|
|
544
|
+
|
|
545
|
+
type Action = Literal["allow", "block"]
|
|
546
|
+
|
|
547
|
+
id: str
|
|
548
|
+
"""Unique request ID."""
|
|
549
|
+
subscription_id: str = ""
|
|
550
|
+
"""Which subscription triggered this request."""
|
|
551
|
+
event: str
|
|
552
|
+
"""The hook event type, e.g. 'PreToolUse', 'Stop'."""
|
|
553
|
+
target: str = ""
|
|
554
|
+
"""What triggered the hook: tool name, agent name, etc."""
|
|
555
|
+
input_data: dict[str, Any] = Field(default_factory=dict)
|
|
556
|
+
"""Full event payload (same as what shell hooks get on stdin)."""
|
|
557
|
+
|
|
558
|
+
def __init__(self, **kwargs: Any) -> None:
|
|
559
|
+
super().__init__(**kwargs)
|
|
560
|
+
self._future: asyncio.Future[tuple[HookRequest.Action, str]] | None = None
|
|
561
|
+
|
|
562
|
+
def _get_future(self) -> asyncio.Future[tuple[HookRequest.Action, str]]:
|
|
563
|
+
if self._future is None:
|
|
564
|
+
self._future = asyncio.get_event_loop().create_future()
|
|
565
|
+
return self._future
|
|
566
|
+
|
|
567
|
+
async def wait(self) -> tuple[Action, str]:
|
|
568
|
+
"""Wait for client response. Returns (action, reason)."""
|
|
569
|
+
return await self._get_future()
|
|
570
|
+
|
|
571
|
+
def resolve(self, action: Action, reason: str = "") -> None:
|
|
572
|
+
"""Resolve with client's decision."""
|
|
573
|
+
future = self._get_future()
|
|
574
|
+
if not future.done():
|
|
575
|
+
future.set_result((action, reason))
|
|
576
|
+
|
|
577
|
+
@property
|
|
578
|
+
def resolved(self) -> bool:
|
|
579
|
+
return self._future is not None and self._future.done()
|
|
580
|
+
|
|
581
|
+
|
|
582
|
+
type Request = ApprovalRequest | ToolCallRequest | QuestionRequest | HookRequest
|
|
583
|
+
"""Any request. Request is a message that expects a response."""
|
|
584
|
+
|
|
585
|
+
type WireMessage = Event | Request
|
|
586
|
+
"""Any message sent over the `Wire`."""
|
|
587
|
+
|
|
588
|
+
|
|
589
|
+
_EVENT_TYPES = cast(tuple[type[Event], ...], flatten_union(Event))
|
|
590
|
+
_REQUEST_TYPES = cast(tuple[type[Request], ...], flatten_union(Request))
|
|
591
|
+
_WIRE_MESSAGE_TYPES = cast(tuple[type[WireMessage], ...], flatten_union(WireMessage))
|
|
592
|
+
|
|
593
|
+
|
|
594
|
+
def is_event(msg: Any) -> TypeGuard[Event]:
|
|
595
|
+
"""Check if the message is an Event."""
|
|
596
|
+
return isinstance(msg, _EVENT_TYPES)
|
|
597
|
+
|
|
598
|
+
|
|
599
|
+
def is_request(msg: Any) -> TypeGuard[Request]:
|
|
600
|
+
"""Check if the message is a Request."""
|
|
601
|
+
return isinstance(msg, _REQUEST_TYPES)
|
|
602
|
+
|
|
603
|
+
|
|
604
|
+
def is_wire_message(msg: Any) -> TypeGuard[WireMessage]:
|
|
605
|
+
"""Check if the message is a WireMessage."""
|
|
606
|
+
return isinstance(msg, _WIRE_MESSAGE_TYPES)
|
|
607
|
+
|
|
608
|
+
|
|
609
|
+
_NAME_TO_WIRE_MESSAGE_TYPE: dict[str, type[WireMessage]] = {
|
|
610
|
+
cls.__name__: cls for cls in _WIRE_MESSAGE_TYPES
|
|
611
|
+
}
|
|
612
|
+
# for backwards compatibility with Wire v1
|
|
613
|
+
_NAME_TO_WIRE_MESSAGE_TYPE["ApprovalRequestResolved"] = ApprovalResponse
|
|
614
|
+
|
|
615
|
+
|
|
616
|
+
class WireMessageEnvelope(BaseModel):
|
|
617
|
+
type: str
|
|
618
|
+
payload: dict[str, JsonType]
|
|
619
|
+
|
|
620
|
+
@classmethod
|
|
621
|
+
def from_wire_message(cls, msg: WireMessage) -> WireMessageEnvelope:
|
|
622
|
+
typename: str | None = None
|
|
623
|
+
for name, typ in _NAME_TO_WIRE_MESSAGE_TYPE.items():
|
|
624
|
+
if issubclass(type(msg), typ):
|
|
625
|
+
typename = name
|
|
626
|
+
break
|
|
627
|
+
assert typename is not None, f"Unknown wire message type: {type(msg)}"
|
|
628
|
+
return cls(
|
|
629
|
+
type=typename,
|
|
630
|
+
payload=msg.model_dump(mode="json"),
|
|
631
|
+
)
|
|
632
|
+
|
|
633
|
+
def to_wire_message(self) -> WireMessage:
|
|
634
|
+
"""
|
|
635
|
+
Convert the envelope back into a `WireMessage`.
|
|
636
|
+
|
|
637
|
+
Raises:
|
|
638
|
+
ValueError: If the message type is unknown or the payload is invalid.
|
|
639
|
+
"""
|
|
640
|
+
msg_type = _NAME_TO_WIRE_MESSAGE_TYPE.get(self.type)
|
|
641
|
+
if msg_type is None:
|
|
642
|
+
raise ValueError(f"Unknown wire message type: {self.type}")
|
|
643
|
+
return msg_type.model_validate(self.payload)
|
|
644
|
+
|
|
645
|
+
|
|
646
|
+
__all__ = [
|
|
647
|
+
# `WireMessage` variants
|
|
648
|
+
"TurnBegin",
|
|
649
|
+
"SteerInput",
|
|
650
|
+
"TurnEnd",
|
|
651
|
+
"StepBegin",
|
|
652
|
+
"StepInterrupted",
|
|
653
|
+
"CompactionBegin",
|
|
654
|
+
"CompactionEnd",
|
|
655
|
+
"MCPLoadingBegin",
|
|
656
|
+
"MCPLoadingEnd",
|
|
657
|
+
"StatusUpdate",
|
|
658
|
+
"MCPServerSnapshot",
|
|
659
|
+
"MCPStatusSnapshot",
|
|
660
|
+
"Notification",
|
|
661
|
+
"ContentPart",
|
|
662
|
+
"ToolCall",
|
|
663
|
+
"ToolCallPart",
|
|
664
|
+
"ToolResult",
|
|
665
|
+
"ApprovalResponse",
|
|
666
|
+
"SubagentEvent",
|
|
667
|
+
"PlanDisplay",
|
|
668
|
+
"BtwBegin",
|
|
669
|
+
"BtwEnd",
|
|
670
|
+
"ApprovalRequest",
|
|
671
|
+
"ToolCallRequest",
|
|
672
|
+
"QuestionOption",
|
|
673
|
+
"QuestionItem",
|
|
674
|
+
"QuestionResponse",
|
|
675
|
+
"QuestionRequest",
|
|
676
|
+
"QuestionNotSupported",
|
|
677
|
+
# helpers
|
|
678
|
+
"WireMessageEnvelope",
|
|
679
|
+
# `StatusUpdate`-related
|
|
680
|
+
"TokenUsage",
|
|
681
|
+
# `ContentPart` types
|
|
682
|
+
"TextPart",
|
|
683
|
+
"ThinkPart",
|
|
684
|
+
"ImageURLPart",
|
|
685
|
+
"AudioURLPart",
|
|
686
|
+
"VideoURLPart",
|
|
687
|
+
# `ToolResult`-related
|
|
688
|
+
"ToolReturnValue",
|
|
689
|
+
# `DisplayBlock` types
|
|
690
|
+
"DisplayBlock",
|
|
691
|
+
"UnknownDisplayBlock",
|
|
692
|
+
"BriefDisplayBlock",
|
|
693
|
+
"DiffDisplayBlock",
|
|
694
|
+
"TodoDisplayBlock",
|
|
695
|
+
"TodoDisplayItem",
|
|
696
|
+
"ShellDisplayBlock",
|
|
697
|
+
"BackgroundTaskDisplayBlock",
|
|
698
|
+
]
|