minimal-agent 0.9.0 → 0.10.0
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.
- package/README.md +11 -8
- package/package.json +34 -1
- package/plugins/cron-runner/.claude-plugin/plugin.json +5 -0
- package/plugins/cron-runner/commands/cron.md +26 -0
- package/plugins/cron-runner/commands/crons.md +7 -0
- package/plugins/cron-runner/plugin.js +34 -0
- package/plugins/cron-runner/src/commands.js +348 -0
- package/plugins/cron-runner/src/cronTime.js +148 -0
- package/plugins/cron-runner/src/lock.js +68 -0
- package/plugins/cron-runner/src/runs.js +89 -0
- package/plugins/cron-runner/src/scheduleEngine.js +72 -0
- package/plugins/cron-runner/src/scheduler.js +355 -0
- package/plugins/cron-runner/src/schema.js +140 -0
- package/plugins/cron-runner/src/service.js +167 -0
- package/plugins/cron-runner/src/store.js +298 -0
- package/plugins/cron-runner/src/types.js +1 -0
- package/plugins/workflow-runner/commands/workflow.md +4 -4
- package/plugins/workflow-runner/commands/workflows.md +1 -1
- package/plugins/workflow-runner/plugin.js +2 -1
- package/plugins/workflow-runner/src/agentCommon.js +172 -9
- package/plugins/workflow-runner/src/dslManifest.js +72 -0
- package/plugins/workflow-runner/src/expressions.js +150 -13
- package/plugins/workflow-runner/src/index.js +39 -8
- package/plugins/workflow-runner/src/loader.js +216 -64
- package/plugins/workflow-runner/src/multimodal.js +37 -0
- package/plugins/workflow-runner/src/recovery.js +26 -24
- package/plugins/workflow-runner/src/runner.js +693 -287
- package/plugins/workflow-runner/src/stepExecutors/agent.js +126 -37
- package/plugins/workflow-runner/src/stepExecutors/assert.js +3 -2
- package/plugins/workflow-runner/src/stepExecutors/llm.js +38 -30
- package/plugins/workflow-runner/src/stepExecutors/skill.js +27 -38
- package/plugins/workflow-runner/src/stepExecutors/tool.js +56 -3
- package/plugins/workflow-runner/src/stepExecutors/verify.js +19 -10
- package/plugins/workflow-runner/src/taskIdentity.js +185 -30
- package/plugins/workflow-runner/src/types.js +18 -7
- package/plugins/workflow-runner/src/workflowState.js +355 -55
- package/skills/ai-image/SKILL.md +89 -0
- package/skills/ai-image/scripts/generate.mjs +497 -0
- package/skills/ai-image/scripts/generate_from_plan.mjs +469 -0
- package/skills/ai-image/scripts/generate_from_plan_test.mjs +223 -0
- package/skills/ai-image/scripts/generate_test.mjs +74 -0
- package/skills/browser-automation/SKILL.md +47 -0
- package/skills/docx/SKILL.md +25 -3
- package/skills/docx/scripts/office/helpers/__pycache__/__init__.cpython-314.pyc +0 -0
- package/skills/docx/scripts/office/helpers/__pycache__/merge_runs.cpython-314.pyc +0 -0
- package/skills/docx/scripts/office/helpers/__pycache__/simplify_redlines.cpython-314.pyc +0 -0
- package/skills/docx/scripts/office/validators/__pycache__/__init__.cpython-314.pyc +0 -0
- package/skills/docx/scripts/office/validators/__pycache__/base.cpython-314.pyc +0 -0
- package/skills/docx/scripts/office/validators/__pycache__/docx.cpython-314.pyc +0 -0
- package/skills/docx/scripts/office/validators/__pycache__/pptx.cpython-314.pyc +0 -0
- package/skills/docx/scripts/office/validators/__pycache__/redlining.cpython-314.pyc +0 -0
- package/skills/docx/scripts/opc_check.py +253 -0
- package/skills/image-gen-openrouter/SKILL.md +10 -2
- package/skills/image-stats/SKILL.md +65 -0
- package/skills/image-stats/scripts/__pycache__/image_stats.cpython-314.pyc +0 -0
- package/skills/image-stats/scripts/__pycache__/image_stats_test.cpython-314.pyc +0 -0
- package/skills/image-stats/scripts/image_stats.py +368 -0
- package/skills/image-stats/scripts/image_stats_test.py +181 -0
- package/skills/pptx/SKILL.md +123 -95
- package/skills/pptx/design.md +82 -0
- package/skills/pptx/examples/README.md +29 -0
- package/skills/pptx/examples/hybrid_example.mjs +107 -0
- package/skills/pptx/examples/hybrid_example.pptx +0 -0
- package/skills/pptx/pptxgenjs.md +41 -0
- package/skills/pptx/scripts/deck_helpers.mjs +224 -0
- package/skills/pptx/scripts/layout_lint.py +293 -0
- package/skills/pptx/scripts/layout_lint_test.py +160 -0
- package/skills/pptx/scripts/opc_check.py +339 -0
- package/skills/pptx/scripts/svg_fallback.mjs +145 -0
- package/skills/pptx/svg.md +67 -0
- package/skills/tts-zh/SKILL.md +19 -2
- package/skills/ui-design/SKILL.md +158 -0
- package/skills/ui-design/claude_design.md +309 -0
- package/skills/ui-design/evals/evals.json +254 -0
- package/skills/ui-design/references/aesthetic-direction.md +83 -0
- package/skills/ui-design/references/claude-design-protocol.md +36 -0
- package/skills/ui-design/references/design-context.md +53 -0
- package/skills/ui-design/references/design-execution-playbook.md +82 -0
- package/skills/ui-design/references/export-pptx.md +124 -0
- package/skills/ui-design/references/layout-composition.md +654 -0
- package/skills/ui-design/references/preview-feedback.md +37 -0
- package/skills/ui-design/references/source-image-layout.md +189 -0
- package/skills/ui-design/references/starter-components.md +78 -0
- package/skills/ui-design/references/vi-aegis-vector.md +144 -0
- package/skills/ui-design/references/vi-amber-prism.md +133 -0
- package/skills/ui-design/references/vi-aqua-glass.md +200 -0
- package/skills/ui-design/references/vi-comfort-vision.md +147 -0
- package/skills/ui-design/references/vi-ember-prism.md +140 -0
- package/skills/ui-design/references/vi-nebula-console.md +151 -0
- package/skills/ui-design/references/vi-obsidian-optics.md +139 -0
- package/skills/ui-design/references/vi-obsidian-xui.md +143 -0
- package/skills/ui-design/references/vi-precision-horizon-dark.md +117 -0
- package/skills/ui-design/references/vi-precision-horizon.md +215 -0
- package/skills/ui-design/references/vi-solar-relay.md +130 -0
- package/skills/ui-design/references/vi-template-workflow.md +48 -0
- package/skills/ui-design/references/vi-verdant-grid.md +141 -0
- package/skills/ui-design/references/vi-violet-meridian.md +172 -0
- package/skills/ui-design/scripts/__pycache__/assemble_material.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/assemble_material_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/chart_sanity_check.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/check_language_policy.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/check_ui_artifact.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/check_ui_artifact_pptx_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/deck_pages_check.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/deck_pages_check_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/deck_visual_style_check.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/deck_visual_style_check_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/design_budget_check.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/design_budget_check_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/design_repair_hints.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/design_repair_hints_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/design_style_check.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/design_style_check_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/draft_coverage_check.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/extract_source_assets.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/extract_source_assets_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/generated_image_review_collect.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/generated_image_review_collect_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/image_plan_lint.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/image_plan_lint_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/image_prompt_rewrite.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/image_prompt_rewrite_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/layout_balance.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/layout_balance_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/normalize_design_json.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/normalize_design_json_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/plan_source_layout.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/plan_source_layout_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/resolve_source_hint.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/resolve_source_hint_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/resolve_source_input.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/resolve_source_input_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/scaffold_ui_artifact.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/source_usage_check.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/source_usage_check_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/text_readability_pixel.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/visual_quality_gate.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/__pycache__/visual_quality_gate_test.cpython-314.pyc +0 -0
- package/skills/ui-design/scripts/assemble_material.py +217 -0
- package/skills/ui-design/scripts/assemble_material_test.py +149 -0
- package/skills/ui-design/scripts/browser_check_ui_artifact.mjs +221 -0
- package/skills/ui-design/scripts/chart_sanity_check.py +261 -0
- package/skills/ui-design/scripts/chart_sanity_check_test.py +165 -0
- package/skills/ui-design/scripts/check_language_policy.py +351 -0
- package/skills/ui-design/scripts/check_ui_artifact.py +435 -0
- package/skills/ui-design/scripts/check_ui_artifact_pptx_test.py +251 -0
- package/skills/ui-design/scripts/deck_pages_check.py +158 -0
- package/skills/ui-design/scripts/deck_pages_check_test.py +134 -0
- package/skills/ui-design/scripts/deck_visual_style_check.py +767 -0
- package/skills/ui-design/scripts/deck_visual_style_check_test.py +713 -0
- package/skills/ui-design/scripts/design_budget_check.py +271 -0
- package/skills/ui-design/scripts/design_budget_check_test.py +183 -0
- package/skills/ui-design/scripts/design_repair_hints.py +162 -0
- package/skills/ui-design/scripts/design_repair_hints_test.py +54 -0
- package/skills/ui-design/scripts/design_style_check.py +397 -0
- package/skills/ui-design/scripts/design_style_check_test.py +233 -0
- package/skills/ui-design/scripts/draft_coverage_check.py +184 -0
- package/skills/ui-design/scripts/draft_coverage_check_test.py +131 -0
- package/skills/ui-design/scripts/export_pptx_from_html.mjs +2367 -0
- package/skills/ui-design/scripts/extract_source_assets.py +607 -0
- package/skills/ui-design/scripts/extract_source_assets_test.py +256 -0
- package/skills/ui-design/scripts/generated_image_review_collect.py +206 -0
- package/skills/ui-design/scripts/generated_image_review_collect_test.py +91 -0
- package/skills/ui-design/scripts/image_plan_lint.py +571 -0
- package/skills/ui-design/scripts/image_plan_lint_test.py +515 -0
- package/skills/ui-design/scripts/image_prompt_rewrite.py +713 -0
- package/skills/ui-design/scripts/image_prompt_rewrite_test.py +966 -0
- package/skills/ui-design/scripts/layout_balance.py +881 -0
- package/skills/ui-design/scripts/layout_balance_test.py +927 -0
- package/skills/ui-design/scripts/normalize_design_json.py +272 -0
- package/skills/ui-design/scripts/normalize_design_json_test.py +119 -0
- package/skills/ui-design/scripts/plan_source_layout.py +1450 -0
- package/skills/ui-design/scripts/plan_source_layout_test.py +1136 -0
- package/skills/ui-design/scripts/resolve_source_input.py +270 -0
- package/skills/ui-design/scripts/resolve_source_input_test.py +98 -0
- package/skills/ui-design/scripts/scaffold_ui_artifact.py +377 -0
- package/skills/ui-design/scripts/source_usage_check.py +581 -0
- package/skills/ui-design/scripts/source_usage_check_test.py +427 -0
- package/skills/ui-design/scripts/text_readability_pixel.py +340 -0
- package/skills/ui-design/scripts/text_readability_pixel_test.py +219 -0
- package/skills/ui-design/scripts/visual_quality_gate.py +301 -0
- package/skills/ui-design/scripts/visual_quality_gate_test.py +233 -0
- package/skills/ui-design/tests/e2e/prompts/deck.md +19 -0
- package/skills/ui-design/tests/e2e/prompts/webpage.md +17 -0
- package/skills/ui-design/tests/e2e/render_check.mjs +101 -0
- package/skills/ui-design/tests/e2e/rubric.json +54 -0
- package/skills/ui-design/tests/e2e/runs/aegis-vector-preview-1/checks/browser-check.json +49 -0
- package/skills/ui-design/tests/e2e/runs/aegis-vector-preview-1/checks/language-check.txt +12 -0
- package/skills/ui-design/tests/e2e/runs/aegis-vector-preview-1/checks/static-check.txt +15 -0
- package/skills/ui-design/tests/e2e/runs/aegis-vector-preview-1/outputs/index.html +837 -0
- package/skills/ui-design/tests/e2e/runs/aegis-vector-preview-1/prompt.md +12 -0
- package/skills/ui-design/tests/e2e/runs/aegis-vector-preview-1/review.md +21 -0
- package/skills/ui-design/tests/e2e/runs/aegis-vector-preview-1/screenshots/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/aegis-vector-preview-1/screenshots/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/outputs/homepage.html +373 -0
- package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/outputs/platform.html +378 -0
- package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/prompt.md +13 -0
- package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/review.md +26 -0
- package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/screenshots/homepage/browser-check.json +49 -0
- package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/screenshots/homepage/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/screenshots/homepage/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/screenshots/platform/browser-check.json +49 -0
- package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/screenshots/platform/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/amber-prism-screenshot-check-1/screenshots/platform/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-iteration-1/checks/static-check.txt +2 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-iteration-1/outputs/index.html +656 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-iteration-1/prompt.md +12 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-iteration-1/render_check.mjs +67 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-iteration-2/checks/static-check.txt +2 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-iteration-2/outputs/index.html +587 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-iteration-2/prompt.md +12 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-iteration-2/review.md +36 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-volcano-refresh-1/checks/browser-check.json +49 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-volcano-refresh-1/checks/language-check.txt +8 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-volcano-refresh-1/checks/static-check.txt +16 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-volcano-refresh-1/outputs/index.html +739 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-volcano-refresh-1/prompt.md +11 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-volcano-refresh-1/review.md +22 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-volcano-refresh-1/screenshots/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/aqua-glass-volcano-refresh-1/screenshots/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/comfort-vision-preview-1/checks/browser-check.json +52 -0
- package/skills/ui-design/tests/e2e/runs/comfort-vision-preview-1/outputs/index.html +641 -0
- package/skills/ui-design/tests/e2e/runs/comfort-vision-preview-1/screenshots/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/comfort-vision-preview-1/screenshots/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/ember-prism-red-preview-1/outputs/index.html +467 -0
- package/skills/ui-design/tests/e2e/runs/ember-prism-red-preview-1/screenshots/browser-check.json +49 -0
- package/skills/ui-design/tests/e2e/runs/ember-prism-red-preview-1/screenshots/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/ember-prism-red-preview-1/screenshots/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/outputs/homepage.html +373 -0
- package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/outputs/platform.html +378 -0
- package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/prompt.md +13 -0
- package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/review.md +26 -0
- package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/screenshots/homepage/browser-check.json +49 -0
- package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/screenshots/homepage/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/screenshots/homepage/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/screenshots/platform/browser-check.json +49 -0
- package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/screenshots/platform/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/ember-prism-screenshot-check-1/screenshots/platform/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/checks/browser-check.json +49 -0
- package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/checks/language-check.txt +4 -0
- package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/checks/static-check.txt +2 -0
- package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/execution_notes.md +10 -0
- package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/outputs/index.html +587 -0
- package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/prompt.md +14 -0
- package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/review.md +13 -0
- package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/screenshots/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/empty-agent-protocol-check/screenshots/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/iteration-1/deck/checks/browser-check.json +24 -0
- package/skills/ui-design/tests/e2e/runs/iteration-1/deck/checks/static-check.txt +2 -0
- package/skills/ui-design/tests/e2e/runs/iteration-1/deck/execution_notes.md +21 -0
- package/skills/ui-design/tests/e2e/runs/iteration-1/deck/outputs/deck.html +451 -0
- package/skills/ui-design/tests/e2e/runs/iteration-1/deck/screenshots/slide-01.png +0 -0
- package/skills/ui-design/tests/e2e/runs/iteration-1/deck/screenshots/slide-02.png +0 -0
- package/skills/ui-design/tests/e2e/runs/iteration-1/review.md +79 -0
- package/skills/ui-design/tests/e2e/runs/iteration-1/webpage/checks/browser-check.json +26 -0
- package/skills/ui-design/tests/e2e/runs/iteration-1/webpage/checks/static-check.txt +2 -0
- package/skills/ui-design/tests/e2e/runs/iteration-1/webpage/execution_notes.md +20 -0
- package/skills/ui-design/tests/e2e/runs/iteration-1/webpage/outputs/index.html +534 -0
- package/skills/ui-design/tests/e2e/runs/iteration-1/webpage/screenshots/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/iteration-1/webpage/screenshots/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/checks/browser-check.json +64 -0
- package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/checks/language-check.txt +7 -0
- package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/checks/quick-validate.txt +1 -0
- package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/checks/static-console.txt +2 -0
- package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/checks/static-homepage.txt +2 -0
- package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/outputs/console.html +600 -0
- package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/outputs/homepage.html +556 -0
- package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/prompt.md +29 -0
- package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/review.md +57 -0
- package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/screenshots/console-desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/screenshots/console-mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/screenshots/homepage-desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/nebula-console-iteration-1/screenshots/homepage-mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/checks/browser-check.json +33 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/checks/language-check.txt +6 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/checks/quick-validate.txt +1 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/checks/static-check.txt +2 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/outputs/index.html +682 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/prompt.md +13 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/review.md +59 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/screenshots/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-optics-iteration-1/screenshots/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/outputs/page-01.html +466 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/outputs/page-02.html +433 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/prompt.md +13 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/screenshots/page-01/browser-check.json +49 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/screenshots/page-01/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/screenshots/page-01/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/screenshots/page-02/browser-check.json +49 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/screenshots/page-02/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/obsidian-xui-screenshot-check-1/screenshots/page-02/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/checks/browser-check.json +49 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/checks/language-check.txt +3 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/checks/static-check.txt +2 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/execution_notes.md +24 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/outputs/index.html +723 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/prompt.md +15 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/review.md +26 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/screenshots/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-1/screenshots/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/checks/browser-dark.json +49 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/checks/browser-light.json +49 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/checks/language-check.txt +11 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/checks/static-dark.txt +2 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/checks/static-light.txt +3 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/execution_notes.md +23 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/outputs/dark.html +392 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/outputs/light.html +476 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/prompt.md +23 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/review.md +41 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/screenshots/dark/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/screenshots/dark/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/screenshots/light/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/precision-horizon-iteration-2/screenshots/light/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/checks/browser-check.json +54 -0
- package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/checks/language-check.txt +5 -0
- package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/checks/quick-validate.txt +1 -0
- package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/checks/static-check.txt +2 -0
- package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/outputs/index.html +765 -0
- package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/prompt.md +15 -0
- package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/review.md +59 -0
- package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/screenshots/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/solar-relay-iteration-1/screenshots/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/verdant-grid-preview-1/outputs/index.html +508 -0
- package/skills/ui-design/tests/e2e/runs/verdant-grid-preview-1/screenshots/browser-check.json +49 -0
- package/skills/ui-design/tests/e2e/runs/verdant-grid-preview-1/screenshots/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/verdant-grid-preview-1/screenshots/mobile.png +0 -0
- package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/checks/browser-check.json +54 -0
- package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/checks/language-check.txt +6 -0
- package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/checks/quick-validate.txt +1 -0
- package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/checks/static-check.txt +2 -0
- package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/outputs/index.html +788 -0
- package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/prompt.md +14 -0
- package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/review.md +60 -0
- package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/screenshots/desktop.png +0 -0
- package/skills/ui-design/tests/e2e/runs/violet-meridian-iteration-1/screenshots/mobile.png +0 -0
- package/skills/video-compose/SKILL.md +8 -1
- package/skills/web-crawler/SKILL.md +70 -0
- package/skills/web-crawler/scripts/crawl.mjs +538 -0
- package/skills/web-crawler/scripts/crawl.test.mjs +204 -0
- package/skills/xlsx/SKILL.md +12 -0
- package/skills/xlsx/scripts/opc_check.py +253 -0
- package/src/advisorState.js +22 -0
- package/src/askBridge.js +87 -3
- package/src/bootstrap/workingDir.js +12 -1
- package/src/cli/args.js +17 -1
- package/src/cli/configMenu.js +236 -0
- package/src/cli/configWizard.js +7 -5
- package/src/cli/print.js +37 -4
- package/src/cli/streamJson.js +77 -24
- package/src/cli/wizards/advisorWizard.js +147 -0
- package/src/cli/wizards/fieldForm.js +149 -0
- package/src/cli/wizards/imageWizard.js +60 -0
- package/src/cli/wizards/openRouterWizard.js +23 -0
- package/src/cli/wizards/providerPresets.js +95 -0
- package/src/cli/wizards/providerWizard.js +219 -0
- package/src/cli/wizards/searchWizard.js +23 -0
- package/src/cli/wizards/ttsWizard.js +34 -0
- package/src/config/configFile.js +441 -83
- package/src/config/configService.js +446 -0
- package/src/config.js +24 -64
- package/src/context/agentHome.js +9 -0
- package/src/context/archive.js +3 -2
- package/src/context/compact.js +8 -5
- package/src/context/contextLock.js +81 -0
- package/src/context/persistContext.js +30 -11
- package/src/context/reactiveCompact.js +4 -2
- package/src/context/recentDirs.js +21 -61
- package/src/context/sessionPath.js +97 -23
- package/src/context/sessionRegistry.js +303 -24
- package/src/context/tokenCounter.js +18 -0
- package/src/context/workspaceIndex.js +731 -0
- package/src/infra/verification.js +3 -2
- package/src/llm/client.js +293 -206
- package/src/llm/providers/anthropicFormat.js +241 -0
- package/src/llm/providers/openaiFormat.js +190 -0
- package/src/loop.js +211 -27
- package/src/main.js +61 -11
- package/src/messageQueue.js +97 -0
- package/src/multimodal.js +203 -0
- package/src/plugin-sdk.js +15 -0
- package/src/plugins/commandRouter.js +3 -0
- package/src/plugins/hookEngine.js +5 -1
- package/src/plugins/pluginLifecycle.js +28 -0
- package/src/plugins/pluginRunner.js +40 -0
- package/src/plugins/transcript.js +4 -3
- package/src/prompts/pluginList.js +2 -2
- package/src/prompts/projectInstructions.js +3 -3
- package/src/prompts/promptAssembly.js +133 -109
- package/src/prompts/skillList.js +12 -22
- package/src/session/runAgentTurn.js +70 -0
- package/src/session/runTurn.js +41 -6
- package/src/toolGate.js +17 -0
- package/src/tools/advisor/advisor.js +379 -0
- package/src/tools/agent/agent.js +555 -0
- package/src/tools/agent/agentTypes.js +59 -0
- package/src/tools/agent/coordinator.js +93 -0
- package/src/tools/agent/worktree.js +270 -0
- package/src/tools/ask/ask.js +7 -2
- package/src/tools/bash/bash.js +112 -18
- package/src/tools/download/download.js +144 -0
- package/src/tools/edit/edit.js +1 -0
- package/src/tools/edit/multi-edit.js +1 -0
- package/src/tools/genimage/genimage.js +242 -0
- package/src/tools/genspeech/genspeech.js +67 -0
- package/src/tools/glob/glob.js +1 -0
- package/src/tools/grep/grep.js +3 -0
- package/src/tools/grep/rgPath.js +2 -0
- package/src/tools/index.js +25 -2
- package/src/tools/read/read.js +1 -0
- package/src/tools/shared/killTree.js +52 -0
- package/src/tools/toolProgressBridge.js +48 -0
- package/src/tools/webbrowser/agentBrowserPath.js +258 -0
- package/src/tools/webbrowser/browser.js +59 -42
- package/src/tools/webbrowser/browserControl.js +118 -0
- package/src/tools/webbrowser/browserDaemon.js +97 -0
- package/src/tools/webbrowser/browserService.js +27 -0
- package/src/tools/webbrowser/browserStream.js +119 -0
- package/src/tools/webbrowser/webbrowser.js +699 -130
- package/src/tools/webfetch/webfetch.js +1 -0
- package/src/tools/websearch/websearch.js +134 -51
- package/src/tools/write/write.js +1 -0
- package/src/ui/App.js +249 -22
- package/src/ui/AskQuestion.js +19 -17
- package/src/ui/InputBox.js +34 -9
- package/src/ui/LiveArea.js +112 -19
- package/src/ui/MessageList.js +100 -14
- package/src/ui/ModelPicker.js +56 -0
- package/src/ui/QueuedMessagesBanner.js +14 -0
- package/src/ui/Root.js +18 -10
- package/src/ui/SessionPicker.js +102 -0
- package/src/ui/StatusLine.js +13 -4
- package/src/ui/WorkspacePicker.js +55 -0
- package/src/ui/figures.js +44 -0
- package/src/ui/hooks/askSlot.js +82 -0
- package/src/ui/hooks/useChat.js +345 -64
- package/src/ui/hooks/usePasteHandler.js +11 -1
- package/src/ui/hooks/useTextBuffer.js +1 -3
- package/src/ui/liveViewport.js +5 -1
- package/src/ui/markdown.js +206 -0
- package/src/ui/textBuffer.js +0 -7
- package/src/ui/theme.js +32 -0
- package/src/utils/debugLog.js +0 -4
- package/src/utils/resourcePaths.js +2 -2
- package/src/utils/stripThink.js +50 -0
- package/src/web/browserBridge.js +447 -0
- package/src/web/protocol.js +19 -0
- package/workflows/adaptive-research.yaml +9 -2
- package/workflows/book-review-short.yaml +31 -7
- package/workflows/e2e-write-greet.yaml +3 -0
- package/workflows/illustrate.yaml +227 -0
- package/workflows/plan.yaml +437 -207
- package/workflows/ppt.yaml +1659 -0
- package/workflows/ralph-loop.yaml +142 -112
- package/workflows/schema.json +81 -23
- package/workflows/webppt.yaml +496 -0
- package/workflows/word.yaml +710 -0
- package/workflows/youtube-shorts.yaml +38 -10
- package/MINIMAL-TRACE.md +0 -77
- package/plugins/workflow-runner/src/voteHelpers.js +0 -110
- package/skills/config/SKILL.md +0 -123
- package/skills/frontend-design/LICENSE.txt +0 -177
- package/skills/frontend-design/SKILL.md +0 -42
- package/skills/pptx/scripts/office/__pycache__/soffice.cpython-314.pyc +0 -0
- package/src/ui/ProgressPanel.js +0 -54
- package/src/ui/StreamingBlock.js +0 -11
- package/src/ui/ToolStatus.js +0 -11
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
resolve_source_input.py —— PPT 工作流素材入口解析。
|
|
5
|
+
|
|
6
|
+
用途:
|
|
7
|
+
- inputs.source 明确给了路径:验证并返回该路径。
|
|
8
|
+
- inputs.source 为空,但用户自然语言里说了「下载目录里的某 Word 文件」:
|
|
9
|
+
在 Downloads / Desktop / cwd 内做受限搜索,找到唯一候选。
|
|
10
|
+
- 明确提到素材文件却找不到或多候选:写报告并退出非 0,避免下游伪装成纯 topic。
|
|
11
|
+
|
|
12
|
+
只做受限目录搜索,不全盘扫描。
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
import argparse
|
|
16
|
+
import json
|
|
17
|
+
import os
|
|
18
|
+
import re
|
|
19
|
+
import sys
|
|
20
|
+
import unicodedata
|
|
21
|
+
from dataclasses import dataclass
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
SUPPORTED_EXTS = (
|
|
25
|
+
".doc", ".docx", ".ppt", ".pptx", ".pdf", ".xlsx", ".xls", ".csv", ".tsv",
|
|
26
|
+
".png", ".jpg", ".jpeg", ".gif", ".webp", ".bmp", ".tif", ".tiff",
|
|
27
|
+
)
|
|
28
|
+
WORD_EXTS = (".doc", ".docx")
|
|
29
|
+
FILE_HINT_PATTERNS = (
|
|
30
|
+
r"[/\\]",
|
|
31
|
+
r"\.(doc|docx|ppt|pptx|pdf|xlsx|xls|csv|tsv|png|jpe?g|webp|gif)\b",
|
|
32
|
+
r"下载目录|Downloads|download",
|
|
33
|
+
r"桌面|Desktop|desktop",
|
|
34
|
+
r"Word\s*文件|word\s*文件|老\s*Word|老\s*word",
|
|
35
|
+
r"PPT\s*文件|ppt\s*文件|PowerPoint",
|
|
36
|
+
r"PDF\s*文件|pdf\s*文件",
|
|
37
|
+
r"源文件|素材文件|材料文件|文档文件",
|
|
38
|
+
)
|
|
39
|
+
STOP_WORDS = {
|
|
40
|
+
"用", "我", "电脑", "下载", "目录", "里面", "里的", "word", "Word", "WORD",
|
|
41
|
+
"文件", "作为", "基础", "生成", "一套", "专业", "中文", "PPT", "ppt",
|
|
42
|
+
"整体感", "不要", "卡片", "堆叠", "的", "和", "把",
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@dataclass
|
|
47
|
+
class Candidate:
|
|
48
|
+
path: str
|
|
49
|
+
score: int
|
|
50
|
+
reason: str
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _norm(text: str) -> str:
|
|
54
|
+
text = unicodedata.normalize("NFKC", text or "")
|
|
55
|
+
return re.sub(r"\s+", "", text).lower()
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def _tokens(text: str) -> list[str]:
|
|
59
|
+
raw = unicodedata.normalize("NFKC", text or "")
|
|
60
|
+
parts = re.split(r"[\s/\\,,。;;::\"'“”‘’()()【】\[\]<>《》|]+", raw)
|
|
61
|
+
out: list[str] = []
|
|
62
|
+
for p in parts:
|
|
63
|
+
p = p.strip()
|
|
64
|
+
if not p or p in STOP_WORDS:
|
|
65
|
+
continue
|
|
66
|
+
if len(p) <= 1 and not re.search(r"[\u4e00-\u9fff]", p):
|
|
67
|
+
continue
|
|
68
|
+
out.append(p)
|
|
69
|
+
return out
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def mentions_source(topic: str, source: str) -> bool:
|
|
73
|
+
if source.strip():
|
|
74
|
+
return True
|
|
75
|
+
return any(re.search(pat, topic or "", re.I) for pat in FILE_HINT_PATTERNS)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def search_roots(cwd: str, home: str, topic: str) -> list[str]:
|
|
79
|
+
roots = [cwd]
|
|
80
|
+
if "下载目录" in topic or "Downloads" in topic or "download" in topic.lower():
|
|
81
|
+
roots.insert(0, os.path.join(home, "Downloads"))
|
|
82
|
+
else:
|
|
83
|
+
roots.append(os.path.join(home, "Downloads"))
|
|
84
|
+
if "桌面" in topic or "Desktop" in topic or "desktop" in topic.lower():
|
|
85
|
+
roots.insert(0, os.path.join(home, "Desktop"))
|
|
86
|
+
else:
|
|
87
|
+
roots.append(os.path.join(home, "Desktop"))
|
|
88
|
+
seen = set()
|
|
89
|
+
out = []
|
|
90
|
+
for r in roots:
|
|
91
|
+
r = os.path.abspath(os.path.expanduser(r))
|
|
92
|
+
if r not in seen and os.path.isdir(r):
|
|
93
|
+
seen.add(r)
|
|
94
|
+
out.append(r)
|
|
95
|
+
return out
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def list_files(root: str, max_depth: int = 2) -> list[str]:
|
|
99
|
+
root = os.path.abspath(root)
|
|
100
|
+
files: list[str] = []
|
|
101
|
+
for cur, dirs, names in os.walk(root):
|
|
102
|
+
depth = os.path.relpath(cur, root).count(os.sep)
|
|
103
|
+
if depth >= max_depth:
|
|
104
|
+
dirs[:] = []
|
|
105
|
+
dirs[:] = [
|
|
106
|
+
d for d in dirs
|
|
107
|
+
if not d.startswith(".")
|
|
108
|
+
and d not in {
|
|
109
|
+
"node_modules", ".git", "vendor", "build", "out", "dist",
|
|
110
|
+
"coverage", ".cache", "tmp", "temp",
|
|
111
|
+
}
|
|
112
|
+
]
|
|
113
|
+
for name in names:
|
|
114
|
+
if name.startswith("~$") or name.startswith("."):
|
|
115
|
+
continue
|
|
116
|
+
if name.lower().endswith(SUPPORTED_EXTS):
|
|
117
|
+
files.append(os.path.join(cur, name))
|
|
118
|
+
return sorted(files)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def score_candidate(path: str, topic: str, source: str) -> Candidate | None:
|
|
122
|
+
base = os.path.basename(path)
|
|
123
|
+
ext = os.path.splitext(base)[1].lower()
|
|
124
|
+
norm_base = _norm(os.path.splitext(base)[0])
|
|
125
|
+
norm_topic = _norm(topic)
|
|
126
|
+
score = 0
|
|
127
|
+
reasons = []
|
|
128
|
+
|
|
129
|
+
if source.strip():
|
|
130
|
+
return Candidate(path, 10_000, "显式 source 路径")
|
|
131
|
+
|
|
132
|
+
toks = _tokens(topic)
|
|
133
|
+
for tok in toks:
|
|
134
|
+
nt = _norm(tok)
|
|
135
|
+
if not nt or nt in STOP_WORDS:
|
|
136
|
+
continue
|
|
137
|
+
if nt in norm_base:
|
|
138
|
+
add = max(2, min(20, len(nt)))
|
|
139
|
+
score += add
|
|
140
|
+
reasons.append(tok)
|
|
141
|
+
|
|
142
|
+
if ext in WORD_EXTS and re.search(r"word|doc|文档|文件", topic, re.I):
|
|
143
|
+
score += 20
|
|
144
|
+
reasons.append("Word 类型匹配")
|
|
145
|
+
elif ext in (".ppt", ".pptx") and re.search(r"ppt|幻灯|课件", topic, re.I):
|
|
146
|
+
score += 14
|
|
147
|
+
reasons.append("PPT 类型匹配")
|
|
148
|
+
elif ext in (".pdf",) and "pdf" in norm_topic:
|
|
149
|
+
score += 12
|
|
150
|
+
reasons.append("PDF 类型匹配")
|
|
151
|
+
|
|
152
|
+
# 长中文片段包含是强证据。
|
|
153
|
+
chinese_chunks = re.findall(r"[\u4e00-\u9fffA-Za-z0-9_]{4,}", topic)
|
|
154
|
+
for ch in chinese_chunks:
|
|
155
|
+
nch = _norm(ch)
|
|
156
|
+
if len(nch) >= 6 and nch in norm_base:
|
|
157
|
+
score += 30
|
|
158
|
+
reasons.append(ch)
|
|
159
|
+
|
|
160
|
+
if score <= 0:
|
|
161
|
+
return None
|
|
162
|
+
return Candidate(path, score, "、".join(reasons[:5]) or "文件名相似")
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def resolve_source(source: str, topic: str, cwd: str, home: str) -> dict:
|
|
166
|
+
source = (source or "").strip()
|
|
167
|
+
topic = topic or ""
|
|
168
|
+
explicit = bool(source)
|
|
169
|
+
wants_source = mentions_source(topic, source)
|
|
170
|
+
|
|
171
|
+
if explicit:
|
|
172
|
+
path = os.path.abspath(os.path.expanduser(source))
|
|
173
|
+
ok = os.path.exists(path)
|
|
174
|
+
return {
|
|
175
|
+
"ok": ok,
|
|
176
|
+
"explicit": True,
|
|
177
|
+
"requires_source": True,
|
|
178
|
+
"resolved_path": path if ok else None,
|
|
179
|
+
"candidates": [path] if ok else [],
|
|
180
|
+
"message": "显式 source 路径有效" if ok else f"显式 source 路径不存在:{path}",
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
candidates: list[Candidate] = []
|
|
184
|
+
seen_paths = set()
|
|
185
|
+
explicit_dir_hint = any(x in topic for x in ("下载目录", "Downloads", "桌面", "Desktop"))
|
|
186
|
+
if wants_source:
|
|
187
|
+
for root in search_roots(cwd, home, topic):
|
|
188
|
+
before = len(candidates)
|
|
189
|
+
for f in list_files(root):
|
|
190
|
+
real = os.path.realpath(f)
|
|
191
|
+
if real in seen_paths:
|
|
192
|
+
continue
|
|
193
|
+
seen_paths.add(real)
|
|
194
|
+
cand = score_candidate(f, topic, source)
|
|
195
|
+
if cand:
|
|
196
|
+
candidates.append(cand)
|
|
197
|
+
# 用户明确说了下载目录/桌面时,命中该优先目录即可停止,
|
|
198
|
+
# 避免继续扫大型仓库 cwd 导致入口阶段卡顿。
|
|
199
|
+
if explicit_dir_hint and len(candidates) > before:
|
|
200
|
+
break
|
|
201
|
+
candidates.sort(key=lambda c: (-c.score, len(c.path), c.path))
|
|
202
|
+
|
|
203
|
+
if not wants_source:
|
|
204
|
+
return {
|
|
205
|
+
"ok": True,
|
|
206
|
+
"explicit": False,
|
|
207
|
+
"requires_source": False,
|
|
208
|
+
"resolved_path": None,
|
|
209
|
+
"candidates": [],
|
|
210
|
+
"message": "未检测到明确素材文件指令,允许扫描 cwd 或纯 topic 路径",
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if not candidates:
|
|
214
|
+
return {
|
|
215
|
+
"ok": False,
|
|
216
|
+
"explicit": False,
|
|
217
|
+
"requires_source": True,
|
|
218
|
+
"resolved_path": None,
|
|
219
|
+
"candidates": [],
|
|
220
|
+
"message": "用户提到素材文件,但在 Downloads/Desktop/cwd 未找到匹配候选",
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
top = candidates[0]
|
|
224
|
+
tied = [c for c in candidates if c.score == top.score]
|
|
225
|
+
if len(tied) > 1:
|
|
226
|
+
return {
|
|
227
|
+
"ok": False,
|
|
228
|
+
"explicit": False,
|
|
229
|
+
"requires_source": True,
|
|
230
|
+
"resolved_path": None,
|
|
231
|
+
"candidates": [{"path": c.path, "score": c.score, "reason": c.reason} for c in tied[:10]],
|
|
232
|
+
"message": "用户提到素材文件,但存在多个同分候选,请显式传 --input source",
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return {
|
|
236
|
+
"ok": True,
|
|
237
|
+
"explicit": False,
|
|
238
|
+
"requires_source": True,
|
|
239
|
+
"resolved_path": top.path,
|
|
240
|
+
"candidates": [{"path": c.path, "score": c.score, "reason": c.reason} for c in candidates[:10]],
|
|
241
|
+
"message": f"按自然语言解析到素材:{top.path}",
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
def main() -> int:
|
|
246
|
+
parser = argparse.ArgumentParser(description="解析 PPT 工作流输入里的素材路径")
|
|
247
|
+
parser.add_argument("--source", default="", help="用户显式传入的素材路径")
|
|
248
|
+
parser.add_argument("--topic", default="", help="用户原始自然语言指令")
|
|
249
|
+
parser.add_argument("--cwd", default=".", help="工作流 cwd")
|
|
250
|
+
parser.add_argument("--out", default="./build/source_resolution.json", help="解析报告输出路径")
|
|
251
|
+
parser.add_argument("--home", default=os.path.expanduser("~"), help="测试用 home 覆盖")
|
|
252
|
+
args = parser.parse_args()
|
|
253
|
+
|
|
254
|
+
result = resolve_source(args.source, args.topic, args.cwd, args.home)
|
|
255
|
+
os.makedirs(os.path.dirname(os.path.abspath(args.out)), exist_ok=True)
|
|
256
|
+
with open(args.out, "w", encoding="utf-8") as f:
|
|
257
|
+
json.dump(result, f, ensure_ascii=False, indent=2)
|
|
258
|
+
print(result["message"])
|
|
259
|
+
if result.get("ok"):
|
|
260
|
+
if result.get("resolved_path"):
|
|
261
|
+
print(f"RESOLVED_SOURCE={result['resolved_path']}")
|
|
262
|
+
return 0
|
|
263
|
+
print("SOURCE_RESOLUTION_FAILED", file=sys.stderr)
|
|
264
|
+
for c in result.get("candidates", []):
|
|
265
|
+
print(f"- {c}", file=sys.stderr)
|
|
266
|
+
return 2
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
if __name__ == "__main__":
|
|
270
|
+
sys.exit(main())
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
import json
|
|
5
|
+
import os
|
|
6
|
+
import subprocess
|
|
7
|
+
import sys
|
|
8
|
+
import tempfile
|
|
9
|
+
import unittest
|
|
10
|
+
|
|
11
|
+
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
|
12
|
+
import resolve_source_input as rs # noqa: E402
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class TestResolveSourceInput(unittest.TestCase):
|
|
16
|
+
def test_explicit_absolute_path_wins(self):
|
|
17
|
+
tmp = tempfile.mkdtemp(prefix="resolve-source-")
|
|
18
|
+
doc = os.path.join(tmp, "材料.docx")
|
|
19
|
+
open(doc, "wb").close()
|
|
20
|
+
out = rs.resolve_source(doc, "随便做个 PPT", tmp, tmp)
|
|
21
|
+
self.assertTrue(out["ok"])
|
|
22
|
+
self.assertTrue(out["explicit"])
|
|
23
|
+
self.assertEqual(out["resolved_path"], doc)
|
|
24
|
+
|
|
25
|
+
def test_downloads_chinese_word_hint_finds_doc(self):
|
|
26
|
+
home = tempfile.mkdtemp(prefix="resolve-home-")
|
|
27
|
+
downloads = os.path.join(home, "Downloads")
|
|
28
|
+
os.makedirs(downloads)
|
|
29
|
+
doc = os.path.join(downloads, "航空器制造组装360度全景影像档案系统方案 20250328_副本.doc")
|
|
30
|
+
open(doc, "wb").close()
|
|
31
|
+
topic = "用我电脑下载目录里面的航空器制造组装360度全景影像档案系统方案 20250328_副本 Word 文件作为基础生成 PPT"
|
|
32
|
+
out = rs.resolve_source("", topic, tempfile.mkdtemp(prefix="resolve-cwd-"), home)
|
|
33
|
+
self.assertTrue(out["ok"], out)
|
|
34
|
+
self.assertTrue(out["requires_source"])
|
|
35
|
+
self.assertEqual(out["resolved_path"], doc)
|
|
36
|
+
|
|
37
|
+
def test_multiple_candidates_do_not_guess(self):
|
|
38
|
+
home = tempfile.mkdtemp(prefix="resolve-home-")
|
|
39
|
+
downloads = os.path.join(home, "Downloads")
|
|
40
|
+
os.makedirs(downloads)
|
|
41
|
+
open(os.path.join(downloads, "方案.doc"), "wb").close()
|
|
42
|
+
open(os.path.join(downloads, "方案.docx"), "wb").close()
|
|
43
|
+
out = rs.resolve_source("", "用下载目录里的方案 Word 文件做 PPT", tempfile.mkdtemp(), home)
|
|
44
|
+
self.assertFalse(out["ok"])
|
|
45
|
+
self.assertIn("多个", out["message"])
|
|
46
|
+
|
|
47
|
+
def test_missing_mentioned_source_fails(self):
|
|
48
|
+
home = tempfile.mkdtemp(prefix="resolve-home-")
|
|
49
|
+
os.makedirs(os.path.join(home, "Downloads"))
|
|
50
|
+
out = rs.resolve_source("", "用下载目录里的不存在 Word 文件做 PPT", tempfile.mkdtemp(), home)
|
|
51
|
+
self.assertFalse(out["ok"])
|
|
52
|
+
self.assertTrue(out["requires_source"])
|
|
53
|
+
|
|
54
|
+
def test_generic_material_topic_does_not_force_file_lookup(self):
|
|
55
|
+
out = rs.resolve_source(
|
|
56
|
+
"",
|
|
57
|
+
"帮我做一套关于素材管理平台的 PPT,不要联网",
|
|
58
|
+
tempfile.mkdtemp(prefix="resolve-cwd-"),
|
|
59
|
+
tempfile.mkdtemp(prefix="resolve-home-"),
|
|
60
|
+
)
|
|
61
|
+
self.assertTrue(out["ok"], out)
|
|
62
|
+
self.assertFalse(out["requires_source"])
|
|
63
|
+
self.assertIsNone(out["resolved_path"])
|
|
64
|
+
|
|
65
|
+
def test_cli_writes_report(self):
|
|
66
|
+
tmp = tempfile.mkdtemp(prefix="resolve-cli-")
|
|
67
|
+
home = os.path.join(tmp, "home")
|
|
68
|
+
downloads = os.path.join(home, "Downloads")
|
|
69
|
+
os.makedirs(downloads)
|
|
70
|
+
doc = os.path.join(downloads, "项目方案.doc")
|
|
71
|
+
open(doc, "wb").close()
|
|
72
|
+
report = os.path.join(tmp, "source_resolution.json")
|
|
73
|
+
script = os.path.join(os.path.dirname(os.path.abspath(__file__)), "resolve_source_input.py")
|
|
74
|
+
res = subprocess.run(
|
|
75
|
+
[
|
|
76
|
+
sys.executable,
|
|
77
|
+
script,
|
|
78
|
+
"--topic",
|
|
79
|
+
"用下载目录里面的项目方案 Word 文件做 PPT",
|
|
80
|
+
"--cwd",
|
|
81
|
+
tmp,
|
|
82
|
+
"--home",
|
|
83
|
+
home,
|
|
84
|
+
"--out",
|
|
85
|
+
report,
|
|
86
|
+
],
|
|
87
|
+
text=True,
|
|
88
|
+
stdout=subprocess.PIPE,
|
|
89
|
+
stderr=subprocess.PIPE,
|
|
90
|
+
)
|
|
91
|
+
self.assertEqual(res.returncode, 0, res.stderr)
|
|
92
|
+
with open(report, encoding="utf-8") as f:
|
|
93
|
+
data = json.load(f)
|
|
94
|
+
self.assertEqual(data["resolved_path"], doc)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
if __name__ == "__main__":
|
|
98
|
+
unittest.main(verbosity=2)
|