code-puppy-core-plugins 0.0.2__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.
- code_puppy_core_plugins/__init__.py +5 -0
- code_puppy_core_plugins/acp/README.md +266 -0
- code_puppy_core_plugins/acp/__init__.py +8 -0
- code_puppy_core_plugins/acp/agent.py +494 -0
- code_puppy_core_plugins/acp/bridge.py +309 -0
- code_puppy_core_plugins/acp/capabilities.py +73 -0
- code_puppy_core_plugins/acp/commands.py +116 -0
- code_puppy_core_plugins/acp/content.py +115 -0
- code_puppy_core_plugins/acp/io_delegation.py +231 -0
- code_puppy_core_plugins/acp/mcp_config.py +66 -0
- code_puppy_core_plugins/acp/permissions.py +159 -0
- code_puppy_core_plugins/acp/persistence.py +197 -0
- code_puppy_core_plugins/acp/register_callbacks.py +110 -0
- code_puppy_core_plugins/acp/replay.py +114 -0
- code_puppy_core_plugins/acp/session.py +329 -0
- code_puppy_core_plugins/acp/session_config.py +179 -0
- code_puppy_core_plugins/acp/state.py +135 -0
- code_puppy_core_plugins/agent_skills/__init__.py +22 -0
- code_puppy_core_plugins/agent_skills/config.py +208 -0
- code_puppy_core_plugins/agent_skills/discovery.py +337 -0
- code_puppy_core_plugins/agent_skills/downloader.py +392 -0
- code_puppy_core_plugins/agent_skills/enabled_skills.py +82 -0
- code_puppy_core_plugins/agent_skills/installer.py +22 -0
- code_puppy_core_plugins/agent_skills/metadata.py +219 -0
- code_puppy_core_plugins/agent_skills/prompt_builder.py +49 -0
- code_puppy_core_plugins/agent_skills/provider.py +52 -0
- code_puppy_core_plugins/agent_skills/register_callbacks.py +309 -0
- code_puppy_core_plugins/agent_skills/remote_catalog.py +322 -0
- code_puppy_core_plugins/agent_skills/skill_catalog.py +257 -0
- code_puppy_core_plugins/agent_skills/skill_commands.py +102 -0
- code_puppy_core_plugins/agent_skills/skills_install_menu.py +698 -0
- code_puppy_core_plugins/agent_skills/skills_menu.py +794 -0
- code_puppy_core_plugins/aws_bedrock/__init__.py +14 -0
- code_puppy_core_plugins/aws_bedrock/config.py +101 -0
- code_puppy_core_plugins/aws_bedrock/register_callbacks.py +243 -0
- code_puppy_core_plugins/aws_bedrock/utils.py +186 -0
- code_puppy_core_plugins/azure_foundry/README.md +238 -0
- code_puppy_core_plugins/azure_foundry/__init__.py +15 -0
- code_puppy_core_plugins/azure_foundry/config.py +126 -0
- code_puppy_core_plugins/azure_foundry/discovery.py +189 -0
- code_puppy_core_plugins/azure_foundry/register_callbacks.py +506 -0
- code_puppy_core_plugins/azure_foundry/token.py +182 -0
- code_puppy_core_plugins/azure_foundry/utils.py +375 -0
- code_puppy_core_plugins/btw/__init__.py +1 -0
- code_puppy_core_plugins/btw/inline_view.py +135 -0
- code_puppy_core_plugins/btw/register_callbacks.py +106 -0
- code_puppy_core_plugins/btw/side_query.py +91 -0
- code_puppy_core_plugins/chatgpt_oauth/IMAGEGEN_SKILL.md +83 -0
- code_puppy_core_plugins/chatgpt_oauth/__init__.py +8 -0
- code_puppy_core_plugins/chatgpt_oauth/config.py +52 -0
- code_puppy_core_plugins/chatgpt_oauth/image_generation.py +253 -0
- code_puppy_core_plugins/chatgpt_oauth/image_tool.py +70 -0
- code_puppy_core_plugins/chatgpt_oauth/oauth_flow.py +461 -0
- code_puppy_core_plugins/chatgpt_oauth/register_callbacks.py +288 -0
- code_puppy_core_plugins/chatgpt_oauth/test_plugin.py +663 -0
- code_puppy_core_plugins/chatgpt_oauth/usage.py +113 -0
- code_puppy_core_plugins/chatgpt_oauth/utils.py +534 -0
- code_puppy_core_plugins/claude_code_hooks/__init__.py +1 -0
- code_puppy_core_plugins/claude_code_hooks/config.py +137 -0
- code_puppy_core_plugins/claude_code_hooks/register_callbacks.py +383 -0
- code_puppy_core_plugins/claude_code_oauth/README.md +167 -0
- code_puppy_core_plugins/claude_code_oauth/SETUP.md +93 -0
- code_puppy_core_plugins/claude_code_oauth/__init__.py +25 -0
- code_puppy_core_plugins/claude_code_oauth/config.py +59 -0
- code_puppy_core_plugins/claude_code_oauth/fast_mode.py +122 -0
- code_puppy_core_plugins/claude_code_oauth/prompt_handler.py +64 -0
- code_puppy_core_plugins/claude_code_oauth/register_callbacks.py +719 -0
- code_puppy_core_plugins/claude_code_oauth/test_plugin.py +285 -0
- code_puppy_core_plugins/claude_code_oauth/token_refresh_heartbeat.py +240 -0
- code_puppy_core_plugins/claude_code_oauth/utils.py +663 -0
- code_puppy_core_plugins/code_puppy_agent/AGENTS_AND_TOOLS.md +155 -0
- code_puppy_core_plugins/code_puppy_agent/MODELS_AND_MCP.md +104 -0
- code_puppy_core_plugins/code_puppy_agent/PLUGINS_AND_CALLBACKS.md +147 -0
- code_puppy_core_plugins/code_puppy_agent/SESSIONS_AND_HISTORY.md +39 -0
- code_puppy_core_plugins/code_puppy_agent/SKILL.md +180 -0
- code_puppy_core_plugins/code_puppy_agent/SKILLS_SYSTEM.md +136 -0
- code_puppy_core_plugins/code_puppy_agent/SYSTEM_PROMPT_CONFIG_AND_I18N.md +160 -0
- code_puppy_core_plugins/code_puppy_agent/__init__.py +5 -0
- code_puppy_core_plugins/code_puppy_agent/register_callbacks.py +46 -0
- code_puppy_core_plugins/computer_use/NativeCapture.swift +123 -0
- code_puppy_core_plugins/computer_use/README.md +109 -0
- code_puppy_core_plugins/computer_use/__init__.py +1 -0
- code_puppy_core_plugins/computer_use/accessibility.py +163 -0
- code_puppy_core_plugins/computer_use/activation.py +75 -0
- code_puppy_core_plugins/computer_use/backend.py +584 -0
- code_puppy_core_plugins/computer_use/backend_types.py +5 -0
- code_puppy_core_plugins/computer_use/capture.py +110 -0
- code_puppy_core_plugins/computer_use/commands.py +62 -0
- code_puppy_core_plugins/computer_use/geometry.py +81 -0
- code_puppy_core_plugins/computer_use/inline_image.py +56 -0
- code_puppy_core_plugins/computer_use/keycodes.py +47 -0
- code_puppy_core_plugins/computer_use/policy.py +144 -0
- code_puppy_core_plugins/computer_use/register_callbacks.py +96 -0
- code_puppy_core_plugins/computer_use/safety.py +18 -0
- code_puppy_core_plugins/computer_use/settle.py +64 -0
- code_puppy_core_plugins/computer_use/state.py +86 -0
- code_puppy_core_plugins/computer_use/tools.py +469 -0
- code_puppy_core_plugins/context_indicator/__init__.py +14 -0
- code_puppy_core_plugins/context_indicator/register_callbacks.py +249 -0
- code_puppy_core_plugins/context_indicator/usage.py +40 -0
- code_puppy_core_plugins/copilot_auth/__init__.py +11 -0
- code_puppy_core_plugins/copilot_auth/config.py +93 -0
- code_puppy_core_plugins/copilot_auth/reasoning_client.py +409 -0
- code_puppy_core_plugins/copilot_auth/register_callbacks.py +460 -0
- code_puppy_core_plugins/copilot_auth/utils.py +587 -0
- code_puppy_core_plugins/customizable_commands/__init__.py +0 -0
- code_puppy_core_plugins/customizable_commands/register_callbacks.py +464 -0
- code_puppy_core_plugins/dbos_durable_exec/__init__.py +1 -0
- code_puppy_core_plugins/dbos_durable_exec/cancel.py +15 -0
- code_puppy_core_plugins/dbos_durable_exec/commands.py +31 -0
- code_puppy_core_plugins/dbos_durable_exec/config.py +31 -0
- code_puppy_core_plugins/dbos_durable_exec/lifecycle.py +83 -0
- code_puppy_core_plugins/dbos_durable_exec/register_callbacks.py +45 -0
- code_puppy_core_plugins/dbos_durable_exec/runtime.py +65 -0
- code_puppy_core_plugins/dbos_durable_exec/startup_lock.py +155 -0
- code_puppy_core_plugins/dbos_durable_exec/workflow_ids.py +16 -0
- code_puppy_core_plugins/dbos_durable_exec/wrapper.py +58 -0
- code_puppy_core_plugins/destructive_command_guard/AGENTS.md +79 -0
- code_puppy_core_plugins/destructive_command_guard/__init__.py +14 -0
- code_puppy_core_plugins/destructive_command_guard/detector.py +374 -0
- code_puppy_core_plugins/destructive_command_guard/register_callbacks.py +165 -0
- code_puppy_core_plugins/emoji_filter/__init__.py +12 -0
- code_puppy_core_plugins/emoji_filter/config.py +26 -0
- code_puppy_core_plugins/emoji_filter/register_callbacks.py +238 -0
- code_puppy_core_plugins/emoji_filter/stripper.py +45 -0
- code_puppy_core_plugins/empty_html_comment_filter/register_callbacks.py +116 -0
- code_puppy_core_plugins/example_custom_command/README.md +328 -0
- code_puppy_core_plugins/example_custom_command/register_callbacks.py +66 -0
- code_puppy_core_plugins/file_permission_handler/__init__.py +4 -0
- code_puppy_core_plugins/file_permission_handler/register_callbacks.py +575 -0
- code_puppy_core_plugins/flux_bootstrap/__init__.py +5 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/_docs/README.md +173 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/_docs/cheatsheet.md +86 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/_docs/pipeline.md +167 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/_docs/synopsis.md +392 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/about.md +51 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/address-feedback.md +129 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/ask.md +211 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/aug.md +181 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/auto-pilot.md +71 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/cheatsheet.md +16 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/commit.md +103 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/config.md +108 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/create-pr.md +195 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/exec.md +221 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/new.md +151 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/qa.md +208 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/rebase.md +180 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/review.md +304 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/split.md +120 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/squash-commits.md +179 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/status.md +46 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/tests.md +155 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/scripts/flux_about.py +154 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/scripts/flux_cheatsheet.py +248 -0
- code_puppy_core_plugins/flux_bootstrap/bundled/scripts/flux_status.py +345 -0
- code_puppy_core_plugins/flux_bootstrap/installer.py +256 -0
- code_puppy_core_plugins/flux_bootstrap/register_callbacks.py +71 -0
- code_puppy_core_plugins/force_push_guard/__init__.py +5 -0
- code_puppy_core_plugins/force_push_guard/detector.py +96 -0
- code_puppy_core_plugins/force_push_guard/register_callbacks.py +161 -0
- code_puppy_core_plugins/fork/__init__.py +7 -0
- code_puppy_core_plugins/fork/register_callbacks.py +445 -0
- code_puppy_core_plugins/frontend_emitter/__init__.py +25 -0
- code_puppy_core_plugins/frontend_emitter/emitter.py +249 -0
- code_puppy_core_plugins/frontend_emitter/register_callbacks.py +412 -0
- code_puppy_core_plugins/frontend_emitter/session_context.py +50 -0
- code_puppy_core_plugins/grok_oauth/__init__.py +6 -0
- code_puppy_core_plugins/grok_oauth/config.py +49 -0
- code_puppy_core_plugins/grok_oauth/oauth_flow.py +213 -0
- code_puppy_core_plugins/grok_oauth/register_callbacks.py +132 -0
- code_puppy_core_plugins/grok_oauth/utils.py +195 -0
- code_puppy_core_plugins/herdr/README.md +168 -0
- code_puppy_core_plugins/herdr/__init__.py +9 -0
- code_puppy_core_plugins/herdr/client.py +339 -0
- code_puppy_core_plugins/herdr/register_callbacks.py +140 -0
- code_puppy_core_plugins/herdr/reporter.py +212 -0
- code_puppy_core_plugins/herdr/smoke.py +143 -0
- code_puppy_core_plugins/herdr/sources.py +133 -0
- code_puppy_core_plugins/hook_creator/__init__.py +1 -0
- code_puppy_core_plugins/hook_creator/register_callbacks.py +33 -0
- code_puppy_core_plugins/hook_manager/__init__.py +1 -0
- code_puppy_core_plugins/hook_manager/config.py +290 -0
- code_puppy_core_plugins/hook_manager/hooks_menu.py +571 -0
- code_puppy_core_plugins/hook_manager/register_callbacks.py +227 -0
- code_puppy_core_plugins/meta_oauth/__init__.py +1 -0
- code_puppy_core_plugins/meta_oauth/config.py +55 -0
- code_puppy_core_plugins/meta_oauth/oauth_flow.py +109 -0
- code_puppy_core_plugins/meta_oauth/register_callbacks.py +154 -0
- code_puppy_core_plugins/meta_oauth/utils.py +252 -0
- code_puppy_core_plugins/namespace_skill_search/README.md +118 -0
- code_puppy_core_plugins/namespace_skill_search/__init__.py +15 -0
- code_puppy_core_plugins/namespace_skill_search/namespaces.py +125 -0
- code_puppy_core_plugins/namespace_skill_search/register_callbacks.py +99 -0
- code_puppy_core_plugins/namespace_skill_search/search_tool.py +158 -0
- code_puppy_core_plugins/no_tools/__init__.py +0 -0
- code_puppy_core_plugins/no_tools/register_callbacks.py +42 -0
- code_puppy_core_plugins/oauth_pasteback.py +110 -0
- code_puppy_core_plugins/oauth_puppy_html.py +194 -0
- code_puppy_core_plugins/obsidian_agent/README.md +52 -0
- code_puppy_core_plugins/obsidian_agent/__init__.py +8 -0
- code_puppy_core_plugins/obsidian_agent/agent_obsidian.py +147 -0
- code_puppy_core_plugins/obsidian_agent/register_callbacks.py +13 -0
- code_puppy_core_plugins/ollama/__init__.py +1 -0
- code_puppy_core_plugins/ollama/register_callbacks.py +127 -0
- code_puppy_core_plugins/ollama_setup/__init__.py +5 -0
- code_puppy_core_plugins/ollama_setup/completer.py +38 -0
- code_puppy_core_plugins/ollama_setup/register_callbacks.py +419 -0
- code_puppy_core_plugins/plugin_list/__init__.py +0 -0
- code_puppy_core_plugins/plugin_list/plugin_contributions.py +348 -0
- code_puppy_core_plugins/plugin_list/plugin_meta.py +67 -0
- code_puppy_core_plugins/plugin_list/plugin_text_utils.py +173 -0
- code_puppy_core_plugins/plugin_list/plugins_menu.py +455 -0
- code_puppy_core_plugins/plugin_list/plugins_menu_layout.py +194 -0
- code_puppy_core_plugins/plugin_list/plugins_menu_render.py +431 -0
- code_puppy_core_plugins/plugin_list/project_trust_flow.py +162 -0
- code_puppy_core_plugins/plugin_list/register_callbacks.py +281 -0
- code_puppy_core_plugins/pop_command/__init__.py +1 -0
- code_puppy_core_plugins/pop_command/register_callbacks.py +191 -0
- code_puppy_core_plugins/prompt_newline/__init__.py +13 -0
- code_puppy_core_plugins/prompt_newline/config.py +21 -0
- code_puppy_core_plugins/prompt_newline/register_callbacks.py +163 -0
- code_puppy_core_plugins/prune/__init__.py +1 -0
- code_puppy_core_plugins/prune/prune_menu.py +308 -0
- code_puppy_core_plugins/prune/prune_model.py +517 -0
- code_puppy_core_plugins/prune/prune_render.py +354 -0
- code_puppy_core_plugins/prune/register_callbacks.py +388 -0
- code_puppy_core_plugins/puppy_kennel/README.md +203 -0
- code_puppy_core_plugins/puppy_kennel/__init__.py +6 -0
- code_puppy_core_plugins/puppy_kennel/commands.py +206 -0
- code_puppy_core_plugins/puppy_kennel/config.py +36 -0
- code_puppy_core_plugins/puppy_kennel/kennel.py +368 -0
- code_puppy_core_plugins/puppy_kennel/packer.py +152 -0
- code_puppy_core_plugins/puppy_kennel/recorder.py +83 -0
- code_puppy_core_plugins/puppy_kennel/register_callbacks.py +109 -0
- code_puppy_core_plugins/puppy_kennel/retriever.py +28 -0
- code_puppy_core_plugins/puppy_kennel/schema.py +78 -0
- code_puppy_core_plugins/puppy_kennel/state.py +68 -0
- code_puppy_core_plugins/puppy_kennel/tools.py +449 -0
- code_puppy_core_plugins/puppy_kennel/wings.py +110 -0
- code_puppy_core_plugins/puppy_spinner/README.md +93 -0
- code_puppy_core_plugins/puppy_spinner/__init__.py +11 -0
- code_puppy_core_plugins/puppy_spinner/builtin_frames.py +172 -0
- code_puppy_core_plugins/puppy_spinner/commands.py +116 -0
- code_puppy_core_plugins/puppy_spinner/picker.py +379 -0
- code_puppy_core_plugins/puppy_spinner/register_callbacks.py +193 -0
- code_puppy_core_plugins/puppy_spinner/spinners.py +444 -0
- code_puppy_core_plugins/quick_resume/__init__.py +0 -0
- code_puppy_core_plugins/quick_resume/register_callbacks.py +77 -0
- code_puppy_core_plugins/review_pr/__init__.py +1 -0
- code_puppy_core_plugins/review_pr/register_callbacks.py +162 -0
- code_puppy_core_plugins/shell_safety/__init__.py +6 -0
- code_puppy_core_plugins/shell_safety/agent_shell_safety.py +69 -0
- code_puppy_core_plugins/shell_safety/command_cache.py +156 -0
- code_puppy_core_plugins/shell_safety/register_callbacks.py +203 -0
- code_puppy_core_plugins/stack_dump/__init__.py +1 -0
- code_puppy_core_plugins/stack_dump/register_callbacks.py +79 -0
- code_puppy_core_plugins/statusline/__init__.py +14 -0
- code_puppy_core_plugins/statusline/config.py +68 -0
- code_puppy_core_plugins/statusline/payload.py +138 -0
- code_puppy_core_plugins/statusline/prompt_patch.py +76 -0
- code_puppy_core_plugins/statusline/register_callbacks.py +45 -0
- code_puppy_core_plugins/statusline/runner.py +122 -0
- code_puppy_core_plugins/statusline/statusline_command.py +197 -0
- code_puppy_core_plugins/steer_queue/__init__.py +10 -0
- code_puppy_core_plugins/steer_queue/queue_menu.py +444 -0
- code_puppy_core_plugins/steer_queue/register_callbacks.py +138 -0
- code_puppy_core_plugins/subagent_panel/README.md +102 -0
- code_puppy_core_plugins/subagent_panel/__init__.py +24 -0
- code_puppy_core_plugins/subagent_panel/coalesce_patch.py +242 -0
- code_puppy_core_plugins/subagent_panel/panel_render.py +145 -0
- code_puppy_core_plugins/subagent_panel/register_callbacks.py +535 -0
- code_puppy_core_plugins/subagent_panel/resume_repaint.py +112 -0
- code_puppy_core_plugins/subagent_panel/state.py +231 -0
- code_puppy_core_plugins/switch_agent_resume/__init__.py +5 -0
- code_puppy_core_plugins/switch_agent_resume/register_callbacks.py +314 -0
- code_puppy_core_plugins/theme/README.md +86 -0
- code_puppy_core_plugins/theme/__init__.py +14 -0
- code_puppy_core_plugins/theme/bundled_palettes.py +346 -0
- code_puppy_core_plugins/theme/content_styles.py +146 -0
- code_puppy_core_plugins/theme/osc_palette.py +178 -0
- code_puppy_core_plugins/theme/picker.py +358 -0
- code_puppy_core_plugins/theme/prompt_toolkit_theme.py +113 -0
- code_puppy_core_plugins/theme/register_callbacks.py +348 -0
- code_puppy_core_plugins/theme/rich_themes.py +202 -0
- code_puppy_core_plugins/theme/themes.py +720 -0
- code_puppy_core_plugins/timestamp_heartbeat/__init__.py +1 -0
- code_puppy_core_plugins/timestamp_heartbeat/register_callbacks.py +114 -0
- code_puppy_core_plugins/token_ratio_learner/__init__.py +5 -0
- code_puppy_core_plugins/token_ratio_learner/ratios.py +208 -0
- code_puppy_core_plugins/token_ratio_learner/register_callbacks.py +213 -0
- code_puppy_core_plugins/universal_constructor/__init__.py +13 -0
- code_puppy_core_plugins/universal_constructor/models.py +138 -0
- code_puppy_core_plugins/universal_constructor/provider.py +62 -0
- code_puppy_core_plugins/universal_constructor/register_callbacks.py +75 -0
- code_puppy_core_plugins/universal_constructor/registry.py +302 -0
- code_puppy_core_plugins/universal_constructor/sandbox.py +584 -0
- code_puppy_core_plugins/wide_completion_menu/__init__.py +6 -0
- code_puppy_core_plugins/wide_completion_menu/register_callbacks.py +165 -0
- code_puppy_core_plugins/wiggum/__init__.py +1 -0
- code_puppy_core_plugins/wiggum/goal_runs.py +91 -0
- code_puppy_core_plugins/wiggum/judge.py +299 -0
- code_puppy_core_plugins/wiggum/judge_config.py +249 -0
- code_puppy_core_plugins/wiggum/judges_menu.py +814 -0
- code_puppy_core_plugins/wiggum/register_callbacks.py +569 -0
- code_puppy_core_plugins/wiggum/state.py +89 -0
- code_puppy_core_plugins/yolo_cli/__init__.py +1 -0
- code_puppy_core_plugins/yolo_cli/register_callbacks.py +41 -0
- code_puppy_core_plugins-0.0.2.dist-info/METADATA +64 -0
- code_puppy_core_plugins-0.0.2.dist-info/RECORD +313 -0
- code_puppy_core_plugins-0.0.2.dist-info/WHEEL +4 -0
- code_puppy_core_plugins-0.0.2.dist-info/entry_points.txt +55 -0
- code_puppy_core_plugins-0.0.2.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tests
|
|
3
|
+
description: Run the test suite, fix regressions introduced by this branch, and leave pre-existing failures untouched
|
|
4
|
+
argument-hint: additional_instructions
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# RUN & FIX TESTS
|
|
8
|
+
|
|
9
|
+
**Argument:** `$ARGUMENTS` (optional additional instructions, e.g. "address all failing tests including pre-existing")
|
|
10
|
+
|
|
11
|
+
Run the project's test suite, fix only regressions introduced by this branch, and leave pre-existing failures untouched.
|
|
12
|
+
|
|
13
|
+
If `$ARGUMENTS` contains additional instructions, apply them — they override default behavior (e.g. fix pre-existing failures too, focus on specific test files).
|
|
14
|
+
|
|
15
|
+
## STEP 1: Setup
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
FLUX_ROOT="${FLUX_ROOT:-$HOME/.flux}"
|
|
19
|
+
FLUX_DIR=$(printf '%s' "$(pwd -P)" | tr -cs 'a-zA-Z0-9' '-')
|
|
20
|
+
FLUX_BASE="$FLUX_ROOT/$FLUX_DIR"
|
|
21
|
+
CONFIG_FILE="$FLUX_BASE/config.env"
|
|
22
|
+
mkdir -p "$FLUX_BASE/todo" "$FLUX_BASE/done" "$FLUX_BASE/review" "$FLUX_BASE/research"
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Source config to get `TEST_CMD`:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
source "$CONFIG_FILE" 2>/dev/null
|
|
29
|
+
echo "TEST_CMD: ${TEST_CMD:-<not set>}"
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
If `TEST_CMD` is empty or config file is missing:
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
Error: TEST_CMD is not configured.
|
|
36
|
+
Run /flux/config to set your test command.
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Stop.
|
|
40
|
+
|
|
41
|
+
## STEP 2: Establish baseline (pre-existing failures)
|
|
42
|
+
|
|
43
|
+
Find the merge base with the default branch to identify which tests were already failing before this branch's changes:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
DEFAULT_BRANCH=$(git remote show origin 2>/dev/null | grep 'HEAD branch' | awk '{print $NF}' || echo "main")
|
|
47
|
+
MERGE_BASE=$(git merge-base HEAD "origin/$DEFAULT_BRANCH" 2>/dev/null)
|
|
48
|
+
echo "MERGE_BASE: $MERGE_BASE"
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Run the test suite against the merge base in a temporary worktree to record pre-existing failures:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
WORKTREE_DIR=$(mktemp -d)
|
|
55
|
+
git worktree add "$WORKTREE_DIR" "$MERGE_BASE" --detach 2>/dev/null
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
If worktree creation fails (e.g. no network, shallow clone), skip baseline and assume all failures are regressions — note this clearly in output.
|
|
59
|
+
|
|
60
|
+
If worktree created: run `$TEST_CMD` inside it, capture failing test names → `BASELINE_FAILURES`. Then clean up:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
git worktree remove "$WORKTREE_DIR" --force 2>/dev/null
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## STEP 3: Run tests on current branch
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
eval "$TEST_CMD" 2>&1
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Capture exit code and full output.
|
|
73
|
+
|
|
74
|
+
- **All tests pass** → print `✅ All tests pass.` and skip to STEP 6.
|
|
75
|
+
- **Failures found** → continue to STEP 4.
|
|
76
|
+
|
|
77
|
+
## STEP 4: Classify failures
|
|
78
|
+
|
|
79
|
+
For each failing test, classify it:
|
|
80
|
+
|
|
81
|
+
| Classification | Criteria | Action |
|
|
82
|
+
| ---------------- | ---------------------------------------------------------- | -------- |
|
|
83
|
+
| **Regression** | Was passing at merge base (not in `BASELINE_FAILURES`) | Fix it |
|
|
84
|
+
| **Pre-existing** | Was already failing at merge base (in `BASELINE_FAILURES`) | Leave it |
|
|
85
|
+
| **Unknown** | Baseline unavailable | Fix it |
|
|
86
|
+
|
|
87
|
+
Print a summary table:
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
Test Results
|
|
91
|
+
────────────────────────────────────────
|
|
92
|
+
Total failures: N
|
|
93
|
+
Regressions: R ← will fix
|
|
94
|
+
Pre-existing: P ← will skip
|
|
95
|
+
Unknown: U ← will fix
|
|
96
|
+
────────────────────────────────────────
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
If there are no regressions or unknowns → print `✅ No regressions introduced by this branch.` and skip to STEP 6.
|
|
100
|
+
|
|
101
|
+
## STEP 5: Fix regressions
|
|
102
|
+
|
|
103
|
+
Fix regressions one at a time. For each:
|
|
104
|
+
|
|
105
|
+
1. Read the failing test and the source it exercises
|
|
106
|
+
2. Determine root cause: did the feature change break the test, or does the test need updating to match intentional new behavior?
|
|
107
|
+
3. Apply the minimal fix — either in source or in the test file
|
|
108
|
+
4. Do NOT expand test scope or add new test cases
|
|
109
|
+
5. Do NOT touch pre-existing failures
|
|
110
|
+
|
|
111
|
+
After fixing all regressions, re-run:
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
eval "$TEST_CMD" 2>&1
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Repeat fix → re-run cycle until all regressions pass (max 3 cycles). If still failing after 3 cycles, stop and report:
|
|
118
|
+
|
|
119
|
+
```
|
|
120
|
+
⚠️ Could not fix the following regressions after 3 attempts:
|
|
121
|
+
- <test name>: <last error>
|
|
122
|
+
|
|
123
|
+
Remaining pre-existing failures (not touched):
|
|
124
|
+
- <test name>
|
|
125
|
+
|
|
126
|
+
Please review manually.
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## STEP 6: Final summary
|
|
130
|
+
|
|
131
|
+
Print:
|
|
132
|
+
|
|
133
|
+
```
|
|
134
|
+
Test Suite Summary
|
|
135
|
+
────────────────────────────────────────
|
|
136
|
+
✅ Regressions fixed: R
|
|
137
|
+
⏭ Pre-existing skipped: P
|
|
138
|
+
❌ Unresolved: U
|
|
139
|
+
────────────────────────────────────────
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
If `U > 0`, recommend the user review those manually before committing.
|
|
143
|
+
|
|
144
|
+
## HARD CONSTRAINT
|
|
145
|
+
|
|
146
|
+
`/flux/tests` MUST NOT use `git commit`, `git push`, `git stash`, `git checkout`, or `git branch`. Only `git merge-base`, `git worktree`, and `git remote` are permitted. MUST NOT modify source files beyond the minimal fix required to resolve a regression. MUST NOT touch pre-existing failures. MUST NOT add new test cases or expand test scope.
|
|
147
|
+
|
|
148
|
+
## Propose next step
|
|
149
|
+
|
|
150
|
+
Then propose the next step: `/flux/commit` (include arguments if needed).
|
|
151
|
+
|
|
152
|
+
Valid `//flux` commands: `/flux/config`, `/flux/new`, `/flux/ask`, `/flux/split`, `/flux/aug`, `/flux/exec`, `/flux/qa`, `/flux/tests`, `/flux/commit`, `/flux/create-pr`, `/flux/review`, `/flux/address-feedback`, `/flux/status`, `/flux/auto-pilot`, `/flux/rebase`. Do NOT suggest any command not on this list.
|
|
153
|
+
|
|
154
|
+
=================
|
|
155
|
+
$ARGUMENTS
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Render the /flux/about overview using Rich's markdown renderer.
|
|
3
|
+
|
|
4
|
+
This is the deterministic, AI-free renderer for /flux/about. The previous
|
|
5
|
+
hand-rolled ANSI version was rough on tables (column widths didn't account
|
|
6
|
+
for ANSI escapes around cell contents). Rich does the heavy lifting properly:
|
|
7
|
+
real tables, syntax-highlighted code fences, headings, bullets -- all aligned.
|
|
8
|
+
|
|
9
|
+
Single source of truth: the overview text lives in about.md. We read it at
|
|
10
|
+
runtime, strip the YAML frontmatter + the AI-only preamble, normalize the
|
|
11
|
+
wibey //cmd refs to /cmd, and hand the rest to ``rich.markdown.Markdown``.
|
|
12
|
+
|
|
13
|
+
Usage:
|
|
14
|
+
flux_about.py [--source PATH] [--width N] [--no-color]
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
import argparse
|
|
20
|
+
import os
|
|
21
|
+
import re
|
|
22
|
+
import sys
|
|
23
|
+
from pathlib import Path
|
|
24
|
+
|
|
25
|
+
from rich.console import Console
|
|
26
|
+
from rich.markdown import Markdown
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _default_source() -> str:
|
|
30
|
+
"""Resolve about.md under code-puppy's (XDG-aware) config dir.
|
|
31
|
+
|
|
32
|
+
Runs inside the code-puppy venv, so importing the canonical resolver is the
|
|
33
|
+
single source of truth for the config location -- honoring XDG overrides
|
|
34
|
+
instead of assuming a hard-coded ~/.code_puppy. Falls back to the legacy
|
|
35
|
+
layout only if that import fails (e.g. run standalone).
|
|
36
|
+
"""
|
|
37
|
+
try:
|
|
38
|
+
from code_puppy.config import CONFIG_DIR
|
|
39
|
+
|
|
40
|
+
return os.path.join(CONFIG_DIR, "commands", "flux", "about.md")
|
|
41
|
+
except Exception:
|
|
42
|
+
return os.path.join(
|
|
43
|
+
os.path.expanduser("~"), ".code_puppy", "commands", "flux", "about.md"
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
DEFAULT_SOURCE = _default_source()
|
|
48
|
+
DEFAULT_WIDTH = 120 # most modern terminals are at least this wide
|
|
49
|
+
|
|
50
|
+
# YAML frontmatter block at the top of the file
|
|
51
|
+
FRONTMATTER_RE = re.compile(r"^---\s*\n(.*?)\n---\s*\n", re.DOTALL)
|
|
52
|
+
# Wibey //cmd -> /cmd, URL-safe (won't touch https://, example.com//, etc.)
|
|
53
|
+
SLASH_CMD_RE = re.compile(r"(?<![:\w/])//(?=\w)")
|
|
54
|
+
# The AI instruction preamble we skip when rendering directly
|
|
55
|
+
PREAMBLE_RE = re.compile(r"^Output the following overview exactly")
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def extract_body(raw: str) -> str:
|
|
59
|
+
"""Strip YAML frontmatter and normalize //cmd -> /cmd."""
|
|
60
|
+
body = FRONTMATTER_RE.sub("", raw, count=1).strip()
|
|
61
|
+
return SLASH_CMD_RE.sub("/", body)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def drop_ai_preamble(body: str) -> str:
|
|
65
|
+
"""Skip the 'Output the following overview exactly...' block + its --- rule.
|
|
66
|
+
|
|
67
|
+
The preamble exists solely to instruct an LLM; when a script is doing the
|
|
68
|
+
rendering it's just noise. If the preamble isn't present (someone edited
|
|
69
|
+
it out) the body is returned unchanged.
|
|
70
|
+
"""
|
|
71
|
+
lines = body.splitlines()
|
|
72
|
+
out: list[str] = []
|
|
73
|
+
skipping = False
|
|
74
|
+
for line in lines:
|
|
75
|
+
if not skipping and PREAMBLE_RE.match(line):
|
|
76
|
+
skipping = True
|
|
77
|
+
continue
|
|
78
|
+
if skipping:
|
|
79
|
+
# The preamble ends at the first standalone --- horizontal rule
|
|
80
|
+
if line.strip() == "---":
|
|
81
|
+
skipping = False
|
|
82
|
+
continue
|
|
83
|
+
out.append(line)
|
|
84
|
+
return "\n".join(out).strip()
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def resolve_width(cli_width: int | None) -> int:
|
|
88
|
+
"""CLI flag wins; else $COLUMNS; else our DEFAULT_WIDTH."""
|
|
89
|
+
if cli_width and cli_width > 0:
|
|
90
|
+
return cli_width
|
|
91
|
+
env_cols = os.environ.get("COLUMNS")
|
|
92
|
+
if env_cols and env_cols.isdigit() and int(env_cols) > 0:
|
|
93
|
+
return int(env_cols)
|
|
94
|
+
return DEFAULT_WIDTH
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def force_utf8_stdout() -> None:
|
|
98
|
+
"""Reconfigure stdout to UTF-8 so emoji survive legacy Windows codepages.
|
|
99
|
+
|
|
100
|
+
Under the exec runner the env already forces UTF-8 (PYTHONIOENCODING);
|
|
101
|
+
this covers standalone runs in a cp1252 console, where printing a single
|
|
102
|
+
emoji would otherwise raise UnicodeEncodeError. Best-effort by design --
|
|
103
|
+
these scripts must never crash on an IO quirk. (Duplicated across the
|
|
104
|
+
flux_* scripts on purpose: each is a standalone, dependency-free file.)
|
|
105
|
+
"""
|
|
106
|
+
try:
|
|
107
|
+
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
|
|
108
|
+
except Exception:
|
|
109
|
+
pass
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def main(argv: list[str] | None = None) -> int:
|
|
113
|
+
force_utf8_stdout()
|
|
114
|
+
parser = argparse.ArgumentParser(description="Render /flux/about overview")
|
|
115
|
+
parser.add_argument(
|
|
116
|
+
"--source",
|
|
117
|
+
default=DEFAULT_SOURCE,
|
|
118
|
+
help=f"Path to about.md (default: {DEFAULT_SOURCE})",
|
|
119
|
+
)
|
|
120
|
+
parser.add_argument(
|
|
121
|
+
"--width",
|
|
122
|
+
type=int,
|
|
123
|
+
default=None,
|
|
124
|
+
help=f"Render width in cols (default: $COLUMNS or {DEFAULT_WIDTH})",
|
|
125
|
+
)
|
|
126
|
+
parser.add_argument("--no-color", action="store_true", help="Disable ANSI color")
|
|
127
|
+
args = parser.parse_args(argv)
|
|
128
|
+
|
|
129
|
+
source = Path(args.source).expanduser()
|
|
130
|
+
if not source.is_file():
|
|
131
|
+
print(f"(about.md not found at {source})")
|
|
132
|
+
return 1
|
|
133
|
+
|
|
134
|
+
raw = source.read_text(encoding="utf-8", errors="replace")
|
|
135
|
+
cleaned = drop_ai_preamble(extract_body(raw))
|
|
136
|
+
|
|
137
|
+
# force_terminal=True makes Rich emit ANSI to our piped stdout (the exec runner
|
|
138
|
+
# captures it); legacy_windows=False stays off the win32 LegacyWindowsTerm path,
|
|
139
|
+
# which both loses that ANSI and crashes encoding emoji on cp1252.
|
|
140
|
+
console = Console(
|
|
141
|
+
force_terminal=True,
|
|
142
|
+
legacy_windows=False,
|
|
143
|
+
color_system=None if args.no_color else "truecolor",
|
|
144
|
+
width=resolve_width(args.width),
|
|
145
|
+
no_color=args.no_color,
|
|
146
|
+
# Avoid stripping the user's content when stdout isn't a real TTY.
|
|
147
|
+
soft_wrap=False,
|
|
148
|
+
)
|
|
149
|
+
console.print(Markdown(cleaned))
|
|
150
|
+
return 0
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
if __name__ == "__main__":
|
|
154
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Render the //flux cheatsheet (pipeline flows) colorized for the terminal.
|
|
3
|
+
|
|
4
|
+
This is the code-puppy equivalent of Wibey's native cheatsheet panel. Wibey
|
|
5
|
+
shows clickable PIPELINE A/B/C/D tabs; code-puppy can't host interactive tabs,
|
|
6
|
+
so this prints all pipelines stacked (or one, via --pipeline).
|
|
7
|
+
|
|
8
|
+
SINGLE SOURCE OF TRUTH: the pipeline definitions are parsed at runtime from
|
|
9
|
+
`pipeline.md` in the flux _docs directory. Editing that doc changes this output
|
|
10
|
+
automatically -- nothing is hardcoded here except presentation.
|
|
11
|
+
|
|
12
|
+
Wibey writes commands as `/flux/<cmd>`; code-puppy's namespaced slash commands
|
|
13
|
+
use a single leading slash, so every command is normalized to `/flux/<cmd>`
|
|
14
|
+
before display -- exactly what a code-puppy user types to run it.
|
|
15
|
+
|
|
16
|
+
The flux _docs directory defaults to code-puppy's config dir (XDG-aware) rather
|
|
17
|
+
than any hard-coded home path; ``--docs`` overrides it. The command wiring
|
|
18
|
+
passes it explicitly via a ``{command:flux/_docs}`` token.
|
|
19
|
+
|
|
20
|
+
Usage:
|
|
21
|
+
flux_cheatsheet.py [--docs DIR] [--pipeline A|B|C|D] [--no-color]
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from __future__ import annotations
|
|
25
|
+
|
|
26
|
+
import argparse
|
|
27
|
+
import os
|
|
28
|
+
import re
|
|
29
|
+
import sys
|
|
30
|
+
from pathlib import Path
|
|
31
|
+
|
|
32
|
+
# --- ANSI palette -----------------------------------------------------------
|
|
33
|
+
RESET = "\033[0m"
|
|
34
|
+
MAGENTA = "\033[1;35m"
|
|
35
|
+
CYAN = "\033[1;36m"
|
|
36
|
+
GREEN = "\033[32m"
|
|
37
|
+
WHITE = "\033[1;37m"
|
|
38
|
+
GREY = "\033[90m"
|
|
39
|
+
|
|
40
|
+
FRAKTUR_F = "\U0001d571" # mathematical bold fraktur capital F
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _default_docs() -> str:
|
|
44
|
+
"""Resolve the flux _docs dir under code-puppy's (XDG-aware) config dir.
|
|
45
|
+
|
|
46
|
+
Runs inside the code-puppy venv, so importing the canonical resolver is the
|
|
47
|
+
single source of truth. Falls back to the legacy ~/.code_puppy layout only
|
|
48
|
+
if that import somehow fails (e.g. run standalone).
|
|
49
|
+
"""
|
|
50
|
+
try:
|
|
51
|
+
from code_puppy.config import CONFIG_DIR
|
|
52
|
+
|
|
53
|
+
return os.path.join(CONFIG_DIR, "commands", "flux", "_docs")
|
|
54
|
+
except Exception:
|
|
55
|
+
return os.path.join(
|
|
56
|
+
os.path.expanduser("~"), ".code_puppy", "commands", "flux", "_docs"
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
DEFAULT_DOCS = _default_docs()
|
|
61
|
+
|
|
62
|
+
# matches `/flux/`, `/flux/`, etc. -> we normalize to `/flux/` (the single-slash
|
|
63
|
+
# namespaced command code-puppy users actually type).
|
|
64
|
+
SLASH_CMD = re.compile(r"/+flux/")
|
|
65
|
+
PIPELINE_HEADING = re.compile(r"^##\s+PIPELINE\s+([A-Za-z0-9]+)\s*:")
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class Theme:
|
|
69
|
+
def __init__(self, enabled: bool) -> None:
|
|
70
|
+
self.enabled = enabled
|
|
71
|
+
|
|
72
|
+
def __call__(self, code: str, text: str) -> str:
|
|
73
|
+
return f"{code}{text}{RESET}" if self.enabled else text
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def strip_slashes(line: str) -> str:
|
|
77
|
+
"""`/flux/new` -> `/flux/new`, `/flux/review <PR#>` -> `/flux/review <PR#>`.
|
|
78
|
+
|
|
79
|
+
Collapses any run of leading slashes to the single-slash namespaced form
|
|
80
|
+
code-puppy dispatches (``/flux/<cmd>``).
|
|
81
|
+
"""
|
|
82
|
+
return SLASH_CMD.sub("/flux/", line)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def parse_pipelines(md_text: str) -> list[tuple[str, str, list[str]]]:
|
|
86
|
+
"""Return [(letter, description, [flow_line, ...]), ...] in document order."""
|
|
87
|
+
lines = md_text.splitlines()
|
|
88
|
+
pipelines: list[tuple[str, str, list[str]]] = []
|
|
89
|
+
|
|
90
|
+
i = 0
|
|
91
|
+
n = len(lines)
|
|
92
|
+
while i < n:
|
|
93
|
+
m = PIPELINE_HEADING.match(lines[i])
|
|
94
|
+
if not m:
|
|
95
|
+
i += 1
|
|
96
|
+
continue
|
|
97
|
+
letter = m.group(1).upper()
|
|
98
|
+
i += 1
|
|
99
|
+
|
|
100
|
+
# find the description: first meaningful line before the code fence
|
|
101
|
+
description = ""
|
|
102
|
+
while i < n and not PIPELINE_HEADING.match(lines[i]):
|
|
103
|
+
stripped = lines[i].strip()
|
|
104
|
+
if stripped.startswith("```"):
|
|
105
|
+
break
|
|
106
|
+
if stripped and stripped != "---" and not stripped.startswith("#"):
|
|
107
|
+
description = stripped
|
|
108
|
+
i += 1
|
|
109
|
+
break
|
|
110
|
+
i += 1
|
|
111
|
+
|
|
112
|
+
# find and capture the first fenced code block = the flow
|
|
113
|
+
flow: list[str] = []
|
|
114
|
+
while i < n and not PIPELINE_HEADING.match(lines[i]):
|
|
115
|
+
if lines[i].strip().startswith("```"):
|
|
116
|
+
i += 1 # enter the fence
|
|
117
|
+
while i < n and not lines[i].strip().startswith("```"):
|
|
118
|
+
flow.append(lines[i])
|
|
119
|
+
i += 1
|
|
120
|
+
i += 1 # exit the fence
|
|
121
|
+
break
|
|
122
|
+
i += 1
|
|
123
|
+
|
|
124
|
+
# trim leading/trailing blank lines inside the flow
|
|
125
|
+
while flow and not flow[0].strip():
|
|
126
|
+
flow.pop(0)
|
|
127
|
+
while flow and not flow[-1].strip():
|
|
128
|
+
flow.pop()
|
|
129
|
+
|
|
130
|
+
pipelines.append((letter, description, flow))
|
|
131
|
+
return pipelines
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def render_flow_line(raw: str, theme: Theme) -> str:
|
|
135
|
+
"""Colorize one flow line: comments dim, command flow green, slashes stripped."""
|
|
136
|
+
if not raw.strip():
|
|
137
|
+
return ""
|
|
138
|
+
if raw.strip().startswith("#"):
|
|
139
|
+
# keep the comment's indentation, dim the text
|
|
140
|
+
return theme(GREY, strip_slashes(raw))
|
|
141
|
+
return theme(GREEN, strip_slashes(raw))
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def render(pipelines: list[tuple[str, str, list[str]]], theme: Theme) -> str:
|
|
145
|
+
width = 60
|
|
146
|
+
out: list[str] = []
|
|
147
|
+
out.append(theme(MAGENTA, f"{FRAKTUR_F} FLUX CHEATSHEET"))
|
|
148
|
+
out.append(theme(MAGENTA, "\u2550" * width))
|
|
149
|
+
|
|
150
|
+
for idx, (letter, desc, flow) in enumerate(pipelines):
|
|
151
|
+
if idx > 0:
|
|
152
|
+
out.append("")
|
|
153
|
+
out.append(theme(GREY, "\u2500" * width))
|
|
154
|
+
out.append("")
|
|
155
|
+
out.append(theme(CYAN, f"PIPELINE {letter}"))
|
|
156
|
+
if desc:
|
|
157
|
+
out.append(theme(WHITE, desc))
|
|
158
|
+
out.append("")
|
|
159
|
+
for line in flow:
|
|
160
|
+
out.append(render_flow_line(line, theme))
|
|
161
|
+
|
|
162
|
+
out.append("")
|
|
163
|
+
out.append(theme(MAGENTA, "\u2550" * width))
|
|
164
|
+
return "\n".join(out)
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def force_utf8_stdout() -> None:
|
|
168
|
+
"""Reconfigure stdout to UTF-8 so emoji survive legacy Windows codepages.
|
|
169
|
+
|
|
170
|
+
Under the exec runner the env already forces UTF-8 (PYTHONIOENCODING);
|
|
171
|
+
this covers standalone runs in a cp1252 console, where printing a single
|
|
172
|
+
emoji or box-drawing glyph would otherwise raise UnicodeEncodeError.
|
|
173
|
+
Best-effort by design -- these scripts must never crash on an IO quirk.
|
|
174
|
+
(Duplicated across the flux_* scripts on purpose: each is a standalone,
|
|
175
|
+
dependency-free file.)
|
|
176
|
+
"""
|
|
177
|
+
try:
|
|
178
|
+
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
|
|
179
|
+
except Exception:
|
|
180
|
+
pass
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def main(argv: list[str] | None = None) -> int:
|
|
184
|
+
force_utf8_stdout()
|
|
185
|
+
parser = argparse.ArgumentParser(description="Render //flux cheatsheet panel")
|
|
186
|
+
parser.add_argument("--docs", default=DEFAULT_DOCS, help="flux _docs directory")
|
|
187
|
+
parser.add_argument(
|
|
188
|
+
"--pipeline",
|
|
189
|
+
default=None,
|
|
190
|
+
help="Show only one pipeline (A, B, C, or D)",
|
|
191
|
+
)
|
|
192
|
+
parser.add_argument(
|
|
193
|
+
"pipeline_pos",
|
|
194
|
+
nargs="?",
|
|
195
|
+
default=None,
|
|
196
|
+
help="Optional positional pipeline filter (a/b/c/d); overrides --pipeline.",
|
|
197
|
+
)
|
|
198
|
+
parser.add_argument("--no-color", action="store_true", help="Disable ANSI color")
|
|
199
|
+
args = parser.parse_args(argv)
|
|
200
|
+
|
|
201
|
+
# Positional pipeline arg (e.g. `flux_cheatsheet.py a`) wins over --pipeline
|
|
202
|
+
# so command-line callers don't have to remember the flag name.
|
|
203
|
+
selected_pipeline = args.pipeline_pos or args.pipeline
|
|
204
|
+
if selected_pipeline is not None:
|
|
205
|
+
normalized = selected_pipeline.strip().upper()
|
|
206
|
+
if normalized not in {"A", "B", "C", "D"}:
|
|
207
|
+
parser.error(
|
|
208
|
+
f"invalid pipeline: {selected_pipeline!r} (choose from A, B, C, D)"
|
|
209
|
+
)
|
|
210
|
+
args.pipeline = normalized
|
|
211
|
+
|
|
212
|
+
docs_dir = Path(args.docs).expanduser()
|
|
213
|
+
pipeline_md = docs_dir / "pipeline.md"
|
|
214
|
+
|
|
215
|
+
# The exec runner pipes stdout + injects FORCE_COLOR=1 (see _run_exec_directive), so
|
|
216
|
+
# color stays on despite isatty()==False. Keep the FORCE_COLOR branch so the
|
|
217
|
+
# cheatsheet doesn't silently go monochrome under the runner.
|
|
218
|
+
color_on = not args.no_color and (
|
|
219
|
+
sys.stdout.isatty() or os.environ.get("FORCE_COLOR")
|
|
220
|
+
)
|
|
221
|
+
theme = Theme(bool(color_on))
|
|
222
|
+
|
|
223
|
+
if not pipeline_md.is_file():
|
|
224
|
+
print(theme(GREY, f"(pipeline doc not found at {pipeline_md})"))
|
|
225
|
+
return 1
|
|
226
|
+
|
|
227
|
+
pipelines = parse_pipelines(
|
|
228
|
+
pipeline_md.read_text(encoding="utf-8", errors="replace")
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
if args.pipeline:
|
|
232
|
+
# Already validated + normalized above
|
|
233
|
+
want = args.pipeline
|
|
234
|
+
pipelines = [p for p in pipelines if p[0] == want]
|
|
235
|
+
if not pipelines:
|
|
236
|
+
print(theme(GREY, f"(no PIPELINE {want} found)"))
|
|
237
|
+
return 1
|
|
238
|
+
|
|
239
|
+
if not pipelines:
|
|
240
|
+
print(theme(GREY, "(no pipelines found in pipeline.md)"))
|
|
241
|
+
return 1
|
|
242
|
+
|
|
243
|
+
print(render(pipelines, theme))
|
|
244
|
+
return 0
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
if __name__ == "__main__":
|
|
248
|
+
raise SystemExit(main())
|