@huicai/cli 2026.814.0 → 2026.1021.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/LICENSE +391 -32
- package/README.md +139 -8
- package/bin/huicai.js +155 -74
- package/bin/update.js +97 -0
- package/package.json +27 -8
- package/skills/ab-testing/trigger-cases.json +30 -0
- package/skills/academic-writing/trigger-cases.json +30 -0
- package/skills/accounting-ops/trigger-cases.json +30 -0
- package/skills/ai-agent/trigger-cases.json +30 -0
- package/skills/ai-aiops/trigger-cases.json +30 -0
- package/skills/ai-coding/SKILL.md +2 -0
- package/skills/ai-coding/trigger-cases.json +30 -0
- package/skills/ai-compliance/trigger-cases.json +30 -0
- package/skills/ai-eval/trigger-cases.json +30 -0
- package/skills/ai-llm-app/trigger-cases.json +30 -0
- package/skills/ai-mlops/trigger-cases.json +30 -0
- package/skills/ai-multimodal/trigger-cases.json +30 -0
- package/skills/ai-prompt/trigger-cases.json +30 -0
- package/skills/ai-rag/trigger-cases.json +30 -0
- package/skills/anomaly-detection/trigger-cases.json +30 -0
- package/skills/api-design/trigger-cases.json +31 -0
- package/skills/api-integration/trigger-cases.json +31 -0
- package/skills/arch-design/trigger-cases.json +12 -0
- package/skills/arch-diagram/SKILL.md +118 -0
- package/skills/arch-diagram/trigger-cases.json +30 -0
- package/skills/arch-distributed/trigger-cases.json +30 -0
- package/skills/arch-multitenant/trigger-cases.json +30 -0
- package/skills/audio-brief/SKILL.md +65 -0
- package/skills/audio-brief/trigger-cases.json +30 -0
- package/skills/audit-assist/trigger-cases.json +30 -0
- package/skills/audit-chain/trigger-cases.json +31 -0
- package/skills/banking-credit/trigger-cases.json +30 -0
- package/skills/brand-design/trigger-cases.json +30 -0
- package/skills/business-plan/trigger-cases.json +30 -0
- package/skills/capital-ops/trigger-cases.json +30 -0
- package/skills/cicd-pipeline/trigger-cases.json +31 -0
- package/skills/code-archaeology/SKILL.md +55 -0
- package/skills/code-archaeology/trigger-cases.json +9 -0
- package/skills/code-quality/SKILL.md +138 -0
- package/skills/code-quality/references/languages.md +107 -0
- package/skills/code-quality/scripts/__pycache__/code_battery.cpython-312.pyc +0 -0
- package/skills/code-quality/scripts/__pycache__/code_check.cpython-312.pyc +0 -0
- package/skills/code-quality/scripts/__pycache__/code_check.cpython-313.pyc +0 -0
- package/skills/code-quality/scripts/__pycache__/code_csharp.cpython-312.pyc +0 -0
- package/skills/code-quality/scripts/__pycache__/code_csharp.cpython-313.pyc +0 -0
- package/skills/code-quality/scripts/__pycache__/code_fix.cpython-312.pyc +0 -0
- package/skills/code-quality/scripts/__pycache__/code_fix.cpython-313.pyc +0 -0
- package/skills/code-quality/scripts/__pycache__/code_java.cpython-312.pyc +0 -0
- package/skills/code-quality/scripts/__pycache__/code_java.cpython-313.pyc +0 -0
- package/skills/code-quality/scripts/__pycache__/code_jsts.cpython-312.pyc +0 -0
- package/skills/code-quality/scripts/__pycache__/code_jsts.cpython-313.pyc +0 -0
- package/skills/code-quality/scripts/__pycache__/code_lens.cpython-312.pyc +0 -0
- package/skills/code-quality/scripts/__pycache__/code_lens.cpython-313.pyc +0 -0
- package/skills/code-quality/scripts/__pycache__/code_python.cpython-312.pyc +0 -0
- package/skills/code-quality/scripts/__pycache__/code_python.cpython-313.pyc +0 -0
- package/skills/code-quality/scripts/__pycache__/code_testplan.cpython-312.pyc +0 -0
- package/skills/code-quality/scripts/code_battery.py +1072 -0
- package/skills/code-quality/scripts/code_check.py +1269 -0
- package/skills/code-quality/scripts/code_csharp.py +371 -0
- package/skills/code-quality/scripts/code_fix.py +201 -0
- package/skills/code-quality/scripts/code_java.py +695 -0
- package/skills/code-quality/scripts/code_jsts.py +313 -0
- package/skills/code-quality/scripts/code_lens.py +1079 -0
- package/skills/code-quality/scripts/code_python.py +536 -0
- package/skills/code-quality/scripts/code_testplan.py +239 -0
- package/skills/code-quality/trigger-cases.json +45 -0
- package/skills/code-review/SKILL.md +24 -0
- package/skills/code-review/trigger-cases.json +35 -0
- package/skills/commit-and-pr/trigger-cases.json +31 -0
- package/skills/content-creation/trigger-cases.json +30 -0
- package/skills/corporate-governance/trigger-cases.json +30 -0
- package/skills/crawl-chain/trigger-cases.json +31 -0
- package/skills/customer-service/trigger-cases.json +30 -0
- package/skills/data-analysis/trigger-cases.json +30 -0
- package/skills/data-chain/SKILL.md +1 -1
- package/skills/data-chain/trigger-cases.json +31 -0
- package/skills/data-governance/trigger-cases.json +30 -0
- package/skills/data-report-pro/trigger-cases.json +30 -0
- package/skills/data-streaming/trigger-cases.json +30 -0
- package/skills/data-wrangling/SKILL.md +1 -1
- package/skills/data-wrangling/trigger-cases.json +30 -0
- package/skills/db-es/trigger-cases.json +30 -0
- package/skills/db-migration/trigger-cases.json +30 -0
- package/skills/db-mysql/trigger-cases.json +30 -0
- package/skills/db-postgres/trigger-cases.json +30 -0
- package/skills/db-redis/trigger-cases.json +30 -0
- package/skills/debug-root-cause/trigger-cases.json +30 -0
- package/skills/dependency-audit/SKILL.md +56 -0
- package/skills/dependency-audit/trigger-cases.json +7 -0
- package/skills/dependency-upgrade/trigger-cases.json +31 -0
- package/skills/dev-cpp/trigger-cases.json +30 -0
- package/skills/dev-cross-platform/trigger-cases.json +30 -0
- package/skills/dev-csharp/SKILL.md +23 -0
- package/skills/dev-csharp/trigger-cases.json +30 -0
- package/skills/dev-frontend/SKILL.md +19 -0
- package/skills/dev-frontend/trigger-cases.json +30 -0
- package/skills/dev-go/trigger-cases.json +30 -0
- package/skills/dev-harmony/trigger-cases.json +30 -0
- package/skills/dev-java/SKILL.md +20 -0
- package/skills/dev-java/trigger-cases.json +30 -0
- package/skills/dev-mobile/trigger-cases.json +30 -0
- package/skills/dev-node/trigger-cases.json +30 -0
- package/skills/dev-php/trigger-cases.json +30 -0
- package/skills/dev-python/SKILL.md +21 -0
- package/skills/dev-python/trigger-cases.json +30 -0
- package/skills/dev-rust/trigger-cases.json +30 -0
- package/skills/dev-toolchain/trigger-cases.json +31 -0
- package/skills/doc-chain/trigger-cases.json +31 -0
- package/skills/doc-compare/trigger-cases.json +30 -0
- package/skills/docx-author/SKILL.md +127 -25
- package/skills/docx-author/scripts/__pycache__/docx_battery.cpython-312.pyc +0 -0
- package/skills/docx-author/scripts/__pycache__/docx_build.cpython-312.pyc +0 -0
- package/skills/docx-author/scripts/__pycache__/docx_check.cpython-312.pyc +0 -0
- package/skills/docx-author/scripts/__pycache__/docx_layout.cpython-312.pyc +0 -0
- package/skills/docx-author/scripts/__pycache__/zh_prose.cpython-312.pyc +0 -0
- package/skills/docx-author/scripts/docx_battery.py +586 -0
- package/skills/docx-author/scripts/docx_build.py +995 -0
- package/skills/docx-author/scripts/docx_check.py +1306 -0
- package/skills/docx-author/scripts/docx_doc.py +14 -154
- package/skills/docx-author/scripts/docx_layout.py +490 -0
- package/skills/docx-author/scripts/zh_prose.py +639 -0
- package/skills/docx-author/trigger-cases.json +58 -0
- package/skills/echo-brief/SKILL.md +84 -0
- package/skills/echo-brief/references/echo-format.md +68 -0
- package/skills/echo-brief/trigger-cases.json +40 -0
- package/skills/ecommerce-ops/trigger-cases.json +30 -0
- package/skills/education-training/trigger-cases.json +30 -0
- package/skills/ehs-safety/trigger-cases.json +30 -0
- package/skills/email-writing/trigger-cases.json +30 -0
- package/skills/eng-ai/trigger-cases.json +30 -0
- package/skills/eng-architecture/trigger-cases.json +31 -0
- package/skills/eng-automation/trigger-cases.json +31 -0
- package/skills/eng-collaboration/trigger-cases.json +30 -0
- package/skills/eng-complex-env/trigger-cases.json +30 -0
- package/skills/eng-data-platform/trigger-cases.json +31 -0
- package/skills/eng-database/trigger-cases.json +31 -0
- package/skills/eng-develop/SKILL.md +9 -1
- package/skills/eng-develop/references/dod-checklist.md +3 -0
- package/skills/eng-develop/references/engineering-workflow.md +37 -0
- package/skills/eng-develop/trigger-cases.json +30 -0
- package/skills/eng-docs/SKILL.md +24 -0
- package/skills/eng-docs/trigger-cases.json +30 -0
- package/skills/eng-efficiency/trigger-cases.json +30 -0
- package/skills/eng-infra/trigger-cases.json +30 -0
- package/skills/eng-integration/trigger-cases.json +31 -0
- package/skills/eng-legacy/trigger-cases.json +31 -0
- package/skills/eng-observability/trigger-cases.json +31 -0
- package/skills/eng-ops/trigger-cases.json +31 -0
- package/skills/eng-performance/trigger-cases.json +31 -0
- package/skills/eng-planning/trigger-cases.json +31 -0
- package/skills/eng-quality/SKILL.md +8 -0
- package/skills/eng-quality/trigger-cases.json +31 -0
- package/skills/eng-release/trigger-cases.json +31 -0
- package/skills/eng-reliability/trigger-cases.json +31 -0
- package/skills/eng-requirements/trigger-cases.json +12 -0
- package/skills/eng-research/trigger-cases.json +30 -0
- package/skills/eng-security/trigger-cases.json +31 -0
- package/skills/eng-ux/trigger-cases.json +30 -0
- package/skills/engineering-chain/trigger-cases.json +30 -0
- package/skills/env-offline/trigger-cases.json +31 -0
- package/skills/env-private-deploy/trigger-cases.json +31 -0
- package/skills/env-xinchuang/trigger-cases.json +31 -0
- package/skills/equipment-tpm/trigger-cases.json +30 -0
- package/skills/esg-report/trigger-cases.json +30 -0
- package/skills/event-management/trigger-cases.json +30 -0
- package/skills/excel-analysis-chain/SKILL.md +17 -4
- package/skills/excel-analysis-chain/trigger-cases.json +31 -0
- package/skills/explain-codebase/trigger-cases.json +11 -0
- package/skills/file-ingest/trigger-cases.json +30 -0
- package/skills/finance-analysis/trigger-cases.json +31 -0
- package/skills/finance-chain/trigger-cases.json +31 -0
- package/skills/financial-modeling/trigger-cases.json +31 -0
- package/skills/find-simplifications/SKILL.md +43 -0
- package/skills/find-simplifications/trigger-cases.json +23 -0
- package/skills/foreign-trade/trigger-cases.json +30 -0
- package/skills/funnel-cohort/trigger-cases.json +30 -0
- package/skills/gov-document/trigger-cases.json +30 -0
- package/skills/gui-change-evidence/SKILL.md +47 -0
- package/skills/gui-change-evidence/trigger-cases.json +23 -0
- package/skills/hr-chain/trigger-cases.json +31 -0
- package/skills/hr-operations/trigger-cases.json +30 -0
- package/skills/info-disclosure/trigger-cases.json +31 -0
- package/skills/infra-gateway/trigger-cases.json +31 -0
- package/skills/infra-k8s/trigger-cases.json +31 -0
- package/skills/infra-mq/trigger-cases.json +30 -0
- package/skills/insurance-advisory/trigger-cases.json +30 -0
- package/skills/internal-audit/trigger-cases.json +30 -0
- package/skills/ip-management/trigger-cases.json +31 -0
- package/skills/ipo-listing/trigger-cases.json +31 -0
- package/skills/it-audit/trigger-cases.json +31 -0
- package/skills/itsm-ops/trigger-cases.json +31 -0
- package/skills/knowledge-sop/trigger-cases.json +31 -0
- package/skills/legal-chain/trigger-cases.json +31 -0
- package/skills/legal-contract/trigger-cases.json +30 -0
- package/skills/litigation-support/trigger-cases.json +31 -0
- package/skills/logistics-warehouse/trigger-cases.json +30 -0
- package/skills/long-doc-analysis/trigger-cases.json +31 -0
- package/skills/management-accounting/trigger-cases.json +30 -0
- package/skills/manufacturing-chain/trigger-cases.json +31 -0
- package/skills/manufacturing-quality/trigger-cases.json +30 -0
- package/skills/marketing-analytics/trigger-cases.json +31 -0
- package/skills/marketing-chain/trigger-cases.json +31 -0
- package/skills/meeting-minutes/trigger-cases.json +30 -0
- package/skills/metrics-system/trigger-cases.json +31 -0
- package/skills/negotiation-prep/trigger-cases.json +30 -0
- package/skills/obs-prometheus/trigger-cases.json +31 -0
- package/skills/office-automation/trigger-cases.json +31 -0
- package/skills/okr-review/trigger-cases.json +30 -0
- package/skills/ops-fleet/trigger-cases.json +31 -0
- package/skills/ops-linux/trigger-cases.json +31 -0
- package/skills/optimization-solver/trigger-cases.json +30 -0
- package/skills/patent-disclosure/SKILL.md +105 -0
- package/skills/patent-disclosure/references/figures.md +110 -0
- package/skills/patent-disclosure/references/outline.md +162 -0
- package/skills/patent-disclosure/scripts/patent_docx.py +230 -0
- package/skills/patent-disclosure/trigger-cases.json +31 -0
- package/skills/patent-drafting/SKILL.md +108 -0
- package/skills/patent-drafting/trigger-cases.json +31 -0
- package/skills/patent-portfolio/SKILL.md +81 -0
- package/skills/patent-portfolio/trigger-cases.json +31 -0
- package/skills/pdf-toolkit/trigger-cases.json +31 -0
- package/skills/perf-optimize/trigger-cases.json +31 -0
- package/skills/pivot-crosstab/trigger-cases.json +30 -0
- package/skills/policy-analysis/trigger-cases.json +31 -0
- package/skills/portfolio-analysis/trigger-cases.json +31 -0
- package/skills/ppt-chain/SKILL.md +14 -6
- package/skills/ppt-chain/trigger-cases.json +31 -0
- package/skills/pptx-author/SKILL.md +86 -33
- package/skills/pptx-author/scripts/__pycache__/pptx_check.cpython-312.pyc +0 -0
- package/skills/pptx-author/scripts/__pycache__/pptx_deck.cpython-312.pyc +0 -0
- package/skills/pptx-author/scripts/__pycache__/pptx_layout.cpython-312.pyc +0 -0
- package/skills/pptx-author/scripts/pptx_battery.py +178 -0
- package/skills/pptx-author/scripts/pptx_build.py +119 -0
- package/skills/pptx-author/scripts/pptx_check.py +1182 -0
- package/skills/pptx-author/scripts/pptx_deck.py +736 -145
- package/skills/pptx-author/scripts/pptx_layout.py +384 -0
- package/skills/pptx-author/trigger-cases.json +15 -0
- package/skills/pr-comms/trigger-cases.json +30 -0
- package/skills/procurement-supply/trigger-cases.json +31 -0
- package/skills/product-design/trigger-cases.json +31 -0
- package/skills/production-planning/trigger-cases.json +31 -0
- package/skills/project-management/trigger-cases.json +31 -0
- package/skills/project-proposal/trigger-cases.json +31 -0
- package/skills/prose-standard/SKILL.md +53 -0
- package/skills/prose-standard/trigger-cases.json +23 -0
- package/skills/qa-api-automation/trigger-cases.json +31 -0
- package/skills/qa-mobile-automation/trigger-cases.json +31 -0
- package/skills/qa-ui-automation/trigger-cases.json +31 -0
- package/skills/quant-analysis/trigger-cases.json +31 -0
- package/skills/rag-triage/SKILL.md +64 -0
- package/skills/rag-triage/evals.json +57 -0
- package/skills/rag-triage/references/triage-playbook.md +75 -0
- package/skills/rag-triage/trigger-cases.json +31 -0
- package/skills/real-estate-property/trigger-cases.json +30 -0
- package/skills/refactor-safely/SKILL.md +1 -1
- package/skills/refactor-safely/trigger-cases.json +30 -0
- package/skills/regression-forecast/trigger-cases.json +31 -0
- package/skills/release-checklist/trigger-cases.json +31 -0
- package/skills/report-craft/SKILL.md +76 -0
- package/skills/report-craft/references/feasibility.md +118 -0
- package/skills/report-craft/references/review-checklist.md +51 -0
- package/skills/report-craft/references/visuals.md +114 -0
- package/skills/report-craft/references/writing.md +80 -0
- package/skills/report-craft/scripts/__pycache__/chart_render.cpython-312.pyc +0 -0
- package/skills/report-craft/scripts/__pycache__/fin_model.cpython-312.pyc +0 -0
- package/skills/report-craft/scripts/__pycache__/project_facts.cpython-312.pyc +0 -0
- package/skills/report-craft/scripts/chart_render.py +1222 -0
- package/skills/report-craft/scripts/fin_model.py +602 -0
- package/skills/report-craft/scripts/project_facts.py +580 -0
- package/skills/report-craft/scripts/report_battery.py +349 -0
- package/skills/report-craft/trigger-cases.json +15 -0
- package/skills/retail-store-ops/trigger-cases.json +30 -0
- package/skills/risk-compliance/trigger-cases.json +31 -0
- package/skills/scope-creep/SKILL.md +45 -0
- package/skills/scope-creep/trigger-cases.json +7 -0
- package/skills/sec-auth/trigger-cases.json +31 -0
- package/skills/sec-compliance/trigger-cases.json +31 -0
- package/skills/securities-chain/trigger-cases.json +31 -0
- package/skills/securities-research/trigger-cases.json +31 -0
- package/skills/security-audit/trigger-cases.json +31 -0
- package/skills/slides-html/SKILL.md +25 -10
- package/skills/slides-html/trigger-cases.json +11 -0
- package/skills/sql-analysis/SKILL.md +110 -0
- package/skills/sql-analysis/trigger-cases.json +34 -0
- package/skills/sql-tuning/trigger-cases.json +31 -0
- package/skills/statistical-testing/trigger-cases.json +31 -0
- package/skills/strategy-planning/trigger-cases.json +30 -0
- package/skills/supply-chain/trigger-cases.json +31 -0
- package/skills/tax-compliance/trigger-cases.json +30 -0
- package/skills/tech-doc/SKILL.md +262 -0
- package/skills/tech-doc/scripts/__pycache__/archive_battery.cpython-312.pyc +0 -0
- package/skills/tech-doc/scripts/__pycache__/archive_build.cpython-312.pyc +0 -0
- package/skills/tech-doc/scripts/__pycache__/archive_check.cpython-312.pyc +0 -0
- package/skills/tech-doc/scripts/__pycache__/archive_spec.cpython-312.pyc +0 -0
- package/skills/tech-doc/scripts/__pycache__/doc_templates.cpython-312.pyc +0 -0
- package/skills/tech-doc/scripts/archive_battery.py +860 -0
- package/skills/tech-doc/scripts/archive_build.py +599 -0
- package/skills/tech-doc/scripts/archive_check.py +1307 -0
- package/skills/tech-doc/scripts/archive_spec.py +499 -0
- package/skills/tech-doc/scripts/doc_templates.py +624 -0
- package/skills/tech-doc/trigger-cases.json +57 -0
- package/skills/tech-research/trigger-cases.json +31 -0
- package/skills/tender-bidding/trigger-cases.json +31 -0
- package/skills/translation-pro/trigger-cases.json +30 -0
- package/skills/treasury-mgmt/trigger-cases.json +31 -0
- package/skills/trim-cot-leakage/SKILL.md +58 -0
- package/skills/trim-cot-leakage/trigger-cases.json +23 -0
- package/skills/web-craft/SKILL.md +103 -0
- package/skills/web-craft/references/craft-checklist.md +75 -0
- package/skills/web-craft/references/design-direction.md +122 -0
- package/skills/web-craft/references/h5-mobile.md +100 -0
- package/skills/web-craft/references/motion.md +136 -0
- package/skills/web-craft/references/recipes.md +74 -0
- package/skills/web-craft/templates/wedding-invitation.html +1180 -0
- package/skills/web-craft/trigger-cases.json +14 -0
- package/skills/web-scraping/trigger-cases.json +34 -0
- package/skills/web-search/SKILL.md +11 -10
- package/skills/web-search/trigger-cases.json +31 -0
- package/skills/weekly-report/SKILL.md +134 -0
- package/skills/weekly-report/trigger-cases.json +11 -0
- package/skills/write-tests/trigger-cases.json +31 -0
- package/skills/xlsx-analysis/SKILL.md +143 -77
- package/skills/xlsx-analysis/scripts/__pycache__/data_profile.cpython-312.pyc +0 -0
- package/skills/xlsx-analysis/scripts/__pycache__/xlsx_build.cpython-312.pyc +0 -0
- package/skills/xlsx-analysis/scripts/__pycache__/xlsx_check.cpython-312.pyc +0 -0
- package/skills/xlsx-analysis/scripts/__pycache__/xlsx_layout.cpython-312.pyc +0 -0
- package/skills/xlsx-analysis/scripts/__pycache__/xlsx_toolkit.cpython-312.pyc +0 -0
- package/skills/xlsx-analysis/scripts/data_profile.py +391 -0
- package/skills/xlsx-analysis/scripts/xlsx_battery.py +389 -0
- package/skills/xlsx-analysis/scripts/xlsx_build.py +522 -0
- package/skills/xlsx-analysis/scripts/xlsx_check.py +924 -0
- package/skills/xlsx-analysis/scripts/xlsx_layout.py +235 -0
- package/skills/xlsx-analysis/scripts/xlsx_style.py +28 -66
- package/skills/xlsx-analysis/scripts/xlsx_toolkit.py +61 -5
- package/skills/xlsx-analysis/trigger-cases.json +59 -0
- package/squads/hc-defense.md +47 -0
- package/squads/hc-rdarchive.md +110 -0
- package/squads/hc-redteam.md +50 -0
- package/squads/hc-weekly.md +125 -0
- package/src/account.js +1 -1
- package/src/acp.js +1 -0
- package/src/advisor.js +1 -1
- package/src/agent.js +1 -1
- package/src/api.js +1 -1
- package/src/archaeology.js +1 -0
- package/src/ask-ui.js +1 -0
- package/src/assets-import.js +1 -1
- package/src/autofix.js +1 -1
- package/src/automation-tools.js +1 -1
- package/src/automation.js +1 -1
- package/src/autorun.js +1 -1
- package/src/banner.js +1 -1
- package/src/capability-probe.js +1 -0
- package/src/checkpoints.js +1 -1
- package/src/code-tools.js +1 -0
- package/src/codeindex.js +1 -1
- package/src/codemode.js +1 -0
- package/src/command-bridge.js +1 -0
- package/src/command-ui.js +1 -0
- package/src/commands.js +1 -1
- package/src/compaction.js +1 -1
- package/src/computer.js +1 -1
- package/src/config.js +1 -1
- package/src/consult.js +1 -1
- package/src/context-report.js +1 -1
- package/src/context-window.js +1 -0
- package/src/context.js +1 -1
- package/src/crew.js +1 -0
- package/src/crush.js +1 -0
- package/src/daemon.js +1 -1
- package/src/decisions.js +1 -1
- package/src/depaudit.js +1 -0
- package/src/device.js +1 -1
- package/src/diagram-draw.js +1 -0
- package/src/diagram-layouts.js +1 -0
- package/src/diagram-raster.js +1 -0
- package/src/diagram.js +1 -0
- package/src/dictation.js +1 -0
- package/src/diffview.js +1 -1
- package/src/doctor.js +1 -1
- package/src/docx-tools.js +1 -0
- package/src/engineering.js +1 -0
- package/src/errkind.js +1 -1
- package/src/evidence.js +1 -0
- package/src/executors.js +1 -1
- package/src/expert-catalog.js +1 -1
- package/src/experts-store.js +1 -1
- package/src/experts.js +1 -1
- package/src/external-agents.js +1 -0
- package/src/forks.js +1 -1
- package/src/fs-observe.js +1 -0
- package/src/gitflow.js +1 -1
- package/src/goalround.js +1 -0
- package/src/hooks.js +1 -1
- package/src/ide.js +1 -1
- package/src/input.js +1 -1
- package/src/insights.js +1 -1
- package/src/jobs.js +1 -0
- package/src/kbsync.js +1 -1
- package/src/lsp.js +1 -0
- package/src/mcp-apps.js +1 -0
- package/src/mcp.js +1 -1
- package/src/memory.js +1 -1
- package/src/notify.js +1 -1
- package/src/permissions.js +1 -1
- package/src/plan-limits.js +1 -0
- package/src/policy.js +1 -0
- package/src/pptx-tools.js +1 -0
- package/src/presence.js +1 -1
- package/src/privatedir.js +1 -0
- package/src/pyruntime.js +1 -1
- package/src/radar.js +1 -0
- package/src/render.js +1 -1
- package/src/repl.js +1 -1
- package/src/report-tools.js +1 -0
- package/src/routing.js +1 -0
- package/src/sandbox-probe.js +1 -0
- package/src/sandbox-win-launcher.mjs +156 -0
- package/src/sandbox.js +1 -0
- package/src/scan.js +1 -1
- package/src/schedule.js +1 -1
- package/src/scopecreep.js +1 -0
- package/src/sdk.js +1 -0
- package/src/selection.js +1 -0
- package/src/session-events.js +1 -0
- package/src/session.js +1 -1
- package/src/sessionindex.js +1 -0
- package/src/sessionlog.js +1 -0
- package/src/skill-catalog.js +1 -0
- package/src/skill-lint.js +1 -0
- package/src/skill-optimize.js +1 -0
- package/src/skill-scan.js +1 -0
- package/src/skills.js +1 -1
- package/src/spill.js +1 -0
- package/src/squad.js +1 -1
- package/src/subagent.js +1 -1
- package/src/surface-state.js +1 -0
- package/src/tapd.js +1 -0
- package/src/terminal-select.js +1 -0
- package/src/terminal.js +1 -0
- package/src/test-runner.js +1 -0
- package/src/todo.js +1 -1
- package/src/toolpipe.js +1 -0
- package/src/tools.js +1 -1
- package/src/toon.js +1 -0
- package/src/transcript.js +1 -1
- package/src/tui/app.js +1 -1
- package/src/tui/command-menu.js +1 -0
- package/src/tui/progress.js +1 -0
- package/src/tui/scroll.js +1 -0
- package/src/tui/welcome.js +1 -0
- package/src/tui/workbench.js +1 -0
- package/src/ui-spec.js +1 -0
- package/src/uitree.js +1 -0
- package/src/uninstall.js +1 -1
- package/src/vision.js +1 -1
- package/src/visual.js +1 -1
- package/src/voice-form.js +1 -0
- package/src/voice.js +1 -0
- package/src/watch.js +1 -1
- package/src/web-audit.js +1 -0
- package/src/web-cdp.js +1 -0
- package/src/web-inspect.js +1 -0
- package/src/websearch.js +1 -0
- package/src/weekly.js +1 -0
- package/src/workflow.js +1 -0
- package/src/worklog.js +1 -0
- package/src/xlsx-tools.js +1 -0
- package/ui/command-picker.js +79 -0
- package/skills/ab-testing/scripts/__pycache__/ab_test.cpython-312.pyc +0 -0
- package/skills/accounting-ops/scripts/__pycache__/acct_tools.cpython-312.pyc +0 -0
- package/skills/anomaly-detection/scripts/__pycache__/anomaly.cpython-312.pyc +0 -0
- package/skills/audit-assist/scripts/__pycache__/audit_sampling.cpython-312.pyc +0 -0
- package/skills/banking-credit/scripts/__pycache__/credit_metrics.cpython-312.pyc +0 -0
- package/skills/data-report-pro/scripts/__pycache__/bigdata.cpython-312.pyc +0 -0
- package/skills/data-wrangling/scripts/__pycache__/join_tools.cpython-312.pyc +0 -0
- package/skills/ecommerce-ops/scripts/__pycache__/gmv_decompose.cpython-312.pyc +0 -0
- package/skills/funnel-cohort/scripts/__pycache__/funnel.cpython-312.pyc +0 -0
- package/skills/management-accounting/scripts/__pycache__/costing.cpython-312.pyc +0 -0
- package/skills/manufacturing-quality/scripts/__pycache__/spc.cpython-312.pyc +0 -0
- package/skills/marketing-analytics/scripts/__pycache__/rfm.cpython-312.pyc +0 -0
- package/skills/optimization-solver/scripts/__pycache__/solver.cpython-312.pyc +0 -0
- package/skills/pivot-crosstab/scripts/__pycache__/pivot_tools.cpython-312.pyc +0 -0
- package/skills/portfolio-analysis/scripts/__pycache__/portfolio.cpython-312.pyc +0 -0
- package/skills/procurement-supply/scripts/__pycache__/supply.cpython-312.pyc +0 -0
- package/skills/production-planning/scripts/__pycache__/mrp_capacity.cpython-312.pyc +0 -0
- package/skills/project-management/scripts/__pycache__/cpm.cpython-312.pyc +0 -0
- package/skills/quant-analysis/scripts/__pycache__/quant.cpython-312.pyc +0 -0
- package/skills/real-estate-property/scripts/__pycache__/property_calc.cpython-312.pyc +0 -0
- package/skills/regression-forecast/scripts/__pycache__/regress.cpython-312.pyc +0 -0
- package/skills/securities-research/scripts/__pycache__/valuation.cpython-312.pyc +0 -0
- package/skills/statistical-testing/scripts/__pycache__/stat_tests.cpython-312.pyc +0 -0
- package/skills/treasury-mgmt/scripts/__pycache__/cashflow_forecast.cpython-312.pyc +0 -0
package/bin/huicai.js
CHANGED
|
@@ -12,6 +12,12 @@ import { startRepl, runOnce } from '../src/repl.js';
|
|
|
12
12
|
import { buildSystemPrompt } from '../src/context.js';
|
|
13
13
|
import * as sessions from '../src/session.js';
|
|
14
14
|
import { loadLocalSkills, skillDirs, writeSkillToDir, readSkillDirForPush } from '../src/skills.js';
|
|
15
|
+
import { scanSkillPackage, formatScanReport } from '../src/skill-scan.js';
|
|
16
|
+
import { refreshPlan, isPlanLimitError } from '../src/plan-limits.js';
|
|
17
|
+
import fs from 'node:fs';
|
|
18
|
+
import { lintSkillLibrary } from '../src/skill-lint.js';
|
|
19
|
+
import { tokenize } from '../src/codeindex.js';
|
|
20
|
+
import { createUpdater, displayVersion } from './update.js';
|
|
15
21
|
|
|
16
22
|
// 版本从 package.json 读取(versionDisplay 年月日展示式,与 VSCode 扩展、IDEA 插件一致);勿手改,用 scripts/next-version.cjs
|
|
17
23
|
const _pkg = createRequire(import.meta.url)('../package.json');
|
|
@@ -63,6 +69,9 @@ function parse(argv) {
|
|
|
63
69
|
case '--overwrite':
|
|
64
70
|
flags.overwrite = true;
|
|
65
71
|
break;
|
|
72
|
+
case '--force-unsafe':
|
|
73
|
+
flags.forceUnsafe = true;
|
|
74
|
+
break;
|
|
66
75
|
case '--paste':
|
|
67
76
|
flags.paste = true;
|
|
68
77
|
break;
|
|
@@ -111,62 +120,63 @@ function parse(argv) {
|
|
|
111
120
|
|
|
112
121
|
function usage() {
|
|
113
122
|
process.stdout.write(`
|
|
114
|
-
${c.bold('huicai')} — 终端智能体,以
|
|
123
|
+
${c.bold('huicai')} — 终端智能体,以HuiCai_AI平台为模型后端,在本机执行工具。
|
|
115
124
|
|
|
116
125
|
用法:
|
|
117
|
-
huicai
|
|
126
|
+
huicai进入交互式会话(当前目录)
|
|
118
127
|
huicai "帮我修复登录bug" 进入会话并先执行该指令
|
|
119
128
|
huicai -p "运行测试并总结" 一次性执行后退出(脚本/CI;写/执行需 --yolo)
|
|
120
129
|
cat err.log | huicai -p "分析这段日志" 管道内容自动作为上下文
|
|
121
130
|
huicai --agent <id> 采用某已发布智能体的人格(工具仍在本机执行)
|
|
122
131
|
huicai -c ["prompt"] 继续当前目录最近一次会话
|
|
123
|
-
huicai -r
|
|
132
|
+
huicai -r从当前目录历史会话中选择恢复
|
|
124
133
|
huicai resume <id> 恢复指定会话
|
|
125
|
-
huicai sessions [-a] 列出历史会话(-a
|
|
126
|
-
huicai login
|
|
127
|
-
huicai login --paste
|
|
128
|
-
huicai logout
|
|
129
|
-
huicai models
|
|
130
|
-
huicai usage
|
|
131
|
-
huicai skills
|
|
132
|
-
huicai daemon
|
|
134
|
+
huicai sessions [-a] 列出历史会话(-a跨目录全部)
|
|
135
|
+
huicai login浏览器授权登录(内置平台地址,无需输入网关)
|
|
136
|
+
huicai login --paste无浏览器环境:手动粘贴API令牌
|
|
137
|
+
huicai logout退出登录(清除本机保存的令牌)
|
|
138
|
+
huicai models列出可用模型
|
|
139
|
+
huicai usage查看Token用量窗口(5小时/7天,按会员等级)
|
|
140
|
+
huicai skills列出本地 + 平台技能(Agent Skills)
|
|
141
|
+
huicai daemon调度守护:按cron真正运行 /schedule登记的定时任务
|
|
133
142
|
huicai watch ["*.js"] [-p] 文件监听:变更即触发一个智能体任务(如保存即跑测试)
|
|
134
|
-
huicai pr [commit] 自动提交并开
|
|
135
|
-
huicai kb-sync <id> [ref] 配合
|
|
136
|
-
huicai skills
|
|
137
|
-
huicai skills
|
|
138
|
-
huicai
|
|
139
|
-
huicai
|
|
140
|
-
huicai
|
|
143
|
+
huicai pr [commit] 自动提交并开PR(生成规范commit→建分支→push→gh开PR)
|
|
144
|
+
huicai kb-sync <id> [ref] 配合git diff增量同步知识库,保鲜RAG(--dry试运行)
|
|
145
|
+
huicai skills lint校验本地技能(结构 + 触发路由;离线,不改文件)
|
|
146
|
+
huicai skills pull [name] 平台技能 → 本地(默认 ~/.huicai/skills;--project放入项目)
|
|
147
|
+
huicai skills push <name> 本地技能 → 平台(默认同名跳过;--overwrite覆盖)
|
|
148
|
+
huicai python [setup] 托管Python运行时:状态/预装/整包打包(pack)/重置(数据分析与办公文档的地基)
|
|
149
|
+
huicai uninstall [--yes] 清理本机所有CLI数据(~/.huicai:配置/令牌/会话/记忆/技能…)
|
|
150
|
+
huicai help显示本帮助
|
|
141
151
|
|
|
142
152
|
选项:
|
|
143
153
|
-m, --model <id> 指定模型(覆盖配置)
|
|
144
|
-
--agent <id> 采用平台智能体人格(分享令牌或
|
|
154
|
+
--agent <id> 采用平台智能体人格(分享令牌或agent-xxx)
|
|
145
155
|
--consult <ref> 混合模式:本机驱动模型 + 平台智能体/工作流/数字人/专家团(agent-/workflow-/datahuman-/squad-xxx)作咨询工具
|
|
146
|
-
-c, --continue
|
|
147
|
-
-r, --resume
|
|
156
|
+
-c, --continue继续最近一次会话(当前目录)
|
|
157
|
+
-r, --resume选择并恢复历史会话(当前目录)
|
|
148
158
|
--base <url> 覆盖内置平台地址(自建 / 联调用)
|
|
149
|
-
--key <sk-...> API
|
|
159
|
+
--key <sk-...> API令牌(覆盖配置)
|
|
150
160
|
--cwd <dir> 指定工作目录(默认当前目录)
|
|
151
|
-
--yolo
|
|
152
|
-
--tui / --plain
|
|
153
|
-
-p, --print
|
|
154
|
-
--output-format <fmt> -p
|
|
161
|
+
--yolo自动放行写/执行工具(谨慎)
|
|
162
|
+
--tui / --plain全屏工作台 / 普通REPL(默认TTY下全屏,非TTY使用普通模式)
|
|
163
|
+
-p, --print一次性非交互模式
|
|
164
|
+
--output-format <fmt> -p输出格式:text(默认)| json(结构化,脚本集成)
|
|
155
165
|
--max-turns <n> 单回合最大工具轮数(默认 60)
|
|
156
166
|
--system-prompt <s> 完全替换系统提示词(-p/新会话)
|
|
157
167
|
--append-system-prompt <s> 在系统提示词末尾追加指示
|
|
158
|
-
-h, --help
|
|
159
|
-
-v, --version
|
|
168
|
+
-h, --help帮助
|
|
169
|
+
-v, --version版本
|
|
160
170
|
|
|
161
171
|
交互技巧:
|
|
162
|
-
/help
|
|
163
|
-
模型 -m auto
|
|
164
|
-
自定义命令:.huicai/commands/<名>.md($ARGUMENTS
|
|
172
|
+
/help查看命令 · @文件 引用文件(PDF/Word/Excel等自动解析为文本、图片作为视觉输入) · !命令 直通shell(输出进上下文)
|
|
173
|
+
模型 -m auto或 /model auto:按账号自动选择可用模型(与VSCode扩展一致)
|
|
174
|
+
自定义命令:.huicai/commands/<名>.md($ARGUMENTS为参数占位符)
|
|
165
175
|
权限规则:.huicai/settings.json {"permissions":{"allow":["run_bash(git *)"]}}
|
|
166
176
|
|
|
167
|
-
会话默认自动保存到 ~/.huicai/sessions(按项目目录归属),随时可 -c/-r
|
|
177
|
+
会话默认自动保存到 ~/.huicai/sessions(按项目目录归属),随时可 -c/-r恢复。
|
|
168
178
|
|
|
169
|
-
配置: ${CONFIG_PATH}(或环境变量
|
|
179
|
+
配置: ${CONFIG_PATH}(或环境变量HUICAI_BASE_URL / HUICAI_API_KEY / HUICAI_MODEL / HUICAI_MAX_TURNS)
|
|
170
180
|
`);
|
|
171
181
|
}
|
|
172
182
|
|
|
@@ -178,17 +188,17 @@ async function login(flags = {}) {
|
|
|
178
188
|
let key = cur.apiKey;
|
|
179
189
|
if (!flags.paste) {
|
|
180
190
|
// 默认:直接打开浏览器授权(设备码流),无需任何输入
|
|
181
|
-
process.stdout.write(c.bold('\n登录
|
|
191
|
+
process.stdout.write(c.bold('\n登录huicai') + c.gray(` · ${normBase}`) + '\n');
|
|
182
192
|
try {
|
|
183
193
|
key = await deviceLogin(normBase);
|
|
184
194
|
} catch (e) {
|
|
185
|
-
process.stdout.write(c.yellow(`浏览器授权未完成(${e.message}),可改用
|
|
195
|
+
process.stdout.write(c.yellow(`浏览器授权未完成(${e.message}),可改用huicai login --paste手动粘贴令牌。`) + '\n');
|
|
186
196
|
return;
|
|
187
197
|
}
|
|
188
198
|
} else {
|
|
189
199
|
// 显式 --paste:无浏览器环境下手动粘贴令牌
|
|
190
200
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
191
|
-
key = (await new Promise((r) => rl.question(`API
|
|
201
|
+
key = (await new Promise((r) => rl.question(`API令牌 (sk-huicai-…)${cur.apiKey ? ' [回车保留已保存]' : ''}: `, r))).trim()
|
|
192
202
|
|| cur.apiKey;
|
|
193
203
|
rl.close();
|
|
194
204
|
if (!key) {
|
|
@@ -220,15 +230,15 @@ async function login(flags = {}) {
|
|
|
220
230
|
saveConfig({ baseUrl: normBase, apiKey: key, model });
|
|
221
231
|
if (tokenOk) {
|
|
222
232
|
process.stdout.write(c.green('登录成功') + (model ? c.gray(` · 默认模型 ${model}`) : '') + '\n');
|
|
223
|
-
process.stdout.write(c.gray(`已保存到 ${CONFIG_PATH},直接运行
|
|
233
|
+
process.stdout.write(c.gray(`已保存到 ${CONFIG_PATH},直接运行huicai开始。`) + '\n');
|
|
224
234
|
} else {
|
|
225
|
-
process.stdout.write(c.yellow(`令牌已保存到 ${CONFIG_PATH},但校验未通过——请重试
|
|
235
|
+
process.stdout.write(c.yellow(`令牌已保存到 ${CONFIG_PATH},但校验未通过——请重试huicai login或联系管理员。`) + '\n');
|
|
226
236
|
}
|
|
227
237
|
}
|
|
228
238
|
|
|
229
239
|
function validateAuth(config) {
|
|
230
|
-
if (!config.baseUrl) return c.red('未配置平台地址。运行 `huicai login` 或设置
|
|
231
|
-
if (!config.apiKey) return c.red('未配置
|
|
240
|
+
if (!config.baseUrl) return c.red('未配置平台地址。运行 `huicai login` 或设置HUICAI_BASE_URL。');
|
|
241
|
+
if (!config.apiKey) return c.red('未配置API令牌。运行 `huicai login` 或设置HUICAI_API_KEY。');
|
|
232
242
|
return null;
|
|
233
243
|
}
|
|
234
244
|
|
|
@@ -280,7 +290,7 @@ async function cmdUsage(config) {
|
|
|
280
290
|
process.stderr.write(c.red('拉取用量失败:平台未返回用量数据(请确认平台已支持 /v1/usage)') + '\n');
|
|
281
291
|
process.exit(1);
|
|
282
292
|
}
|
|
283
|
-
process.stdout.write(c.bold('Token
|
|
293
|
+
process.stdout.write(c.bold('Token用量窗口(按会员等级)') + '\n');
|
|
284
294
|
process.stdout.write(' 近 5 小时:' + fmt(u.used5h, u.limit5h) + '\n');
|
|
285
295
|
process.stdout.write(' 近 7 天 :' + fmt(u.used7d, u.limit7d) + '\n');
|
|
286
296
|
if (!u.allowed && u.message) {
|
|
@@ -308,7 +318,7 @@ async function cmdPython(config, rest) {
|
|
|
308
318
|
if (action === 'status') {
|
|
309
319
|
const s = py.runtimeStatus(config);
|
|
310
320
|
const mark = (ok) => (ok ? c.green('✓') : c.yellow('•'));
|
|
311
|
-
process.stdout.write(c.bold('托管
|
|
321
|
+
process.stdout.write(c.bold('托管Python运行时') + c.gray('(' + s.dir + ')') + '\n');
|
|
312
322
|
process.stdout.write(` ${mark(s.uv)} uv ${s.uv ? '已就绪' + (s.uvVersion ? '(' + s.uvVersion + ')' : '') : '未安装'}\n`);
|
|
313
323
|
process.stdout.write(` ${mark(s.python)} CPython ${s.python ? s.pythonVersion + ' 已就绪' : '未安装'}\n`);
|
|
314
324
|
process.stdout.write(` ${mark(s.venv)} 虚拟环境 ${s.venv ? s.venvPython : '未创建'}\n`);
|
|
@@ -319,7 +329,7 @@ async function cmdPython(config, rest) {
|
|
|
319
329
|
const mir = [s.mirrors.bundle && '整包=' + s.mirrors.bundle, s.mirrors.uv && 'uv=' + s.mirrors.uv,
|
|
320
330
|
s.mirrors.python && 'python=' + s.mirrors.python, s.mirrors.pypi && 'PyPI=' + s.mirrors.pypi].filter(Boolean);
|
|
321
331
|
if (mir.length) process.stdout.write(c.gray(' 镜像:' + mir.join(' ')) + '\n');
|
|
322
|
-
if (!s.ready) process.stdout.write(c.gray(' (huicai python setup
|
|
332
|
+
if (!s.ready) process.stdout.write(c.gray(' (huicai python setup立即安装;或首次数据分析任务时自动安装)') + '\n');
|
|
323
333
|
return;
|
|
324
334
|
}
|
|
325
335
|
|
|
@@ -349,7 +359,7 @@ async function cmdPython(config, rest) {
|
|
|
349
359
|
const r = await py.packRuntime({ outDir, config, log: (line) => process.stdout.write(c.gray(' ' + line) + '\n') });
|
|
350
360
|
process.stdout.write(c.green('✅ 整包完成:') + r.file + c.gray(`(${Math.round(r.size / 1024 / 1024)}MB)`) + '\n');
|
|
351
361
|
process.stdout.write(c.gray(' 清单已更新:' + r.manifest) + '\n');
|
|
352
|
-
process.stdout.write(c.gray(' 托管到静态目录后配置
|
|
362
|
+
process.stdout.write(c.gray(' 托管到静态目录后配置HUICAI_PYRT_BUNDLE=<基址> 即启用整包直下') + '\n');
|
|
353
363
|
} catch (e) {
|
|
354
364
|
process.stderr.write(c.red('打包失败:' + e.message) + '\n');
|
|
355
365
|
process.exit(1);
|
|
@@ -363,11 +373,11 @@ async function cmdPython(config, rest) {
|
|
|
363
373
|
process.exit(1);
|
|
364
374
|
}
|
|
365
375
|
py.resetRuntime();
|
|
366
|
-
process.stdout.write(c.green('✅ 已清空托管
|
|
376
|
+
process.stdout.write(c.green('✅ 已清空托管Python运行时(下次使用时自动重装)') + '\n');
|
|
367
377
|
return;
|
|
368
378
|
}
|
|
369
379
|
|
|
370
|
-
process.stderr.write(c.red(`未知子命令:python ${action}(可用:status / setup / pack [--out
|
|
380
|
+
process.stderr.write(c.red(`未知子命令:python ${action}(可用:status / setup / pack [--out目录] / reset --yes)`) + '\n');
|
|
371
381
|
process.exit(1);
|
|
372
382
|
}
|
|
373
383
|
|
|
@@ -375,6 +385,7 @@ async function cmdPython(config, rest) {
|
|
|
375
385
|
* skills 子命令:本地技能与平台云端技能库的查看/同步。
|
|
376
386
|
* huicai skills 列出本地 + 平台技能
|
|
377
387
|
* huicai skills pull [name] 平台 → 本地(默认 ~/.huicai/skills;--project 放入项目 .huicai/skills)
|
|
388
|
+
* 落盘前过安全扫描;扫出严重风险即拦截,--force-unsafe 可强行拉取
|
|
378
389
|
* huicai skills push <name|目录> 本地 → 平台(默认同名跳过;--overwrite 覆盖)
|
|
379
390
|
*/
|
|
380
391
|
async function cmdSkills(config, args, flags, cwd) {
|
|
@@ -382,9 +393,9 @@ async function cmdSkills(config, args, flags, cwd) {
|
|
|
382
393
|
const locals = loadLocalSkills(cwd);
|
|
383
394
|
|
|
384
395
|
if (action === 'list') {
|
|
385
|
-
process.stdout.write(c.bold('本地技能') + c.gray('(.huicai/skills
|
|
396
|
+
process.stdout.write(c.bold('本地技能') + c.gray('(.huicai/skills与 ~/.huicai/skills)') + '\n');
|
|
386
397
|
if (!locals.length) {
|
|
387
|
-
process.stdout.write(c.gray(' (无。huicai skills pull
|
|
398
|
+
process.stdout.write(c.gray(' (无。huicai skills pull可从平台拉取)') + '\n');
|
|
388
399
|
} else {
|
|
389
400
|
for (const s of locals) {
|
|
390
401
|
process.stdout.write(` ${s.name}${s.version ? c.gray(' v' + s.version) : ''}`
|
|
@@ -394,7 +405,7 @@ async function cmdSkills(config, args, flags, cwd) {
|
|
|
394
405
|
}
|
|
395
406
|
const problem = validateAuth(config);
|
|
396
407
|
if (problem) {
|
|
397
|
-
process.stdout.write(c.gray('(未登录,跳过平台技能列表;huicai login
|
|
408
|
+
process.stdout.write(c.gray('(未登录,跳过平台技能列表;huicai login后可pull/push)') + '\n');
|
|
398
409
|
return;
|
|
399
410
|
}
|
|
400
411
|
try {
|
|
@@ -417,6 +428,30 @@ async function cmdSkills(config, args, flags, cwd) {
|
|
|
417
428
|
return;
|
|
418
429
|
}
|
|
419
430
|
|
|
431
|
+
// 校验(纯本地、离线,放在登录门禁之前)
|
|
432
|
+
if (action === 'lint') {
|
|
433
|
+
const roots = args.slice(1).filter((a) => !a.startsWith('--'));
|
|
434
|
+
const targets = roots.length ? roots : skillDirs(cwd).filter((d) => fs.existsSync(d));
|
|
435
|
+
if (!targets.length) {
|
|
436
|
+
process.stdout.write(c.gray('没有可校验的技能库(项目 .huicai/skills与 ~/.huicai/skills都不存在)') + '\n');
|
|
437
|
+
return;
|
|
438
|
+
}
|
|
439
|
+
const rep = lintSkillLibrary(targets, tokenize, { strict: !!flags.strict });
|
|
440
|
+
for (const r of rep.results) {
|
|
441
|
+
if (!r.errors.length && !r.warnings.length) continue;
|
|
442
|
+
process.stdout.write(`${r.errors.length ? c.red('✗') : c.yellow('·')} ${r.name}\n`);
|
|
443
|
+
for (const m of r.errors) process.stdout.write(' ' + c.red('错误 ') + m + '\n');
|
|
444
|
+
for (const m of r.warnings) process.stdout.write(' ' + c.yellow('警告 ') + m + '\n');
|
|
445
|
+
}
|
|
446
|
+
for (const m of rep.route.errors) process.stdout.write(c.red('✗ 触发路由 ') + m + '\n');
|
|
447
|
+
for (const m of rep.route.warnings) process.stdout.write(c.yellow('· 触发路由 ') + m + '\n');
|
|
448
|
+
const { skills, errors, warnings } = rep.counts;
|
|
449
|
+
const verdict = errors ? c.red('未通过') : c.green('通过');
|
|
450
|
+
process.stdout.write(`${verdict} — ${skills} 个技能,${errors} 个错误,${warnings} 个警告\n`);
|
|
451
|
+
if (errors) process.exit(1);
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
|
|
420
455
|
const problem = validateAuth(config);
|
|
421
456
|
if (problem) {
|
|
422
457
|
process.stderr.write(problem + '\n');
|
|
@@ -433,13 +468,41 @@ async function cmdSkills(config, args, flags, cwd) {
|
|
|
433
468
|
process.stderr.write(c.red(wanted ? `平台上没有技能:${wanted}` : '平台上没有可拉取的文档技能') + '\n');
|
|
434
469
|
process.exit(1);
|
|
435
470
|
}
|
|
471
|
+
let blocked = 0;
|
|
472
|
+
// 拉到本地的新技能占会员「技能插件」额度(覆盖已有的同名技能不占):先取最新上限,装满即停
|
|
473
|
+
await refreshPlan(config);
|
|
474
|
+
let limited = '';
|
|
475
|
+
let unpulled = 0;
|
|
436
476
|
for (const s of targets) {
|
|
477
|
+
const isNew = !fs.existsSync(path.join(baseDir, String(s.name || '').replace(/[^a-zA-Z0-9_-]/g, '-'), 'SKILL.md'));
|
|
478
|
+
if (limited && isNew) { unpulled++; continue; }
|
|
437
479
|
const detail = await getPlatformSkill(config.baseUrl, config.apiKey, s.id);
|
|
438
|
-
|
|
480
|
+
// 落盘前先过安全扫描(P0-A)。这条路径直接调 writeSkillToDir、不走 installSkillPackage,
|
|
481
|
+
// 所以闸门必须在这里再挡一道——否则 CLI 就是一扇没装门的侧门。
|
|
482
|
+
const scan = scanSkillPackage({ name: s.name, content: detail?.content, files: detail?.files || [] });
|
|
483
|
+
if (scan.verdict === 'blocked' && !flags.forceUnsafe) {
|
|
484
|
+
blocked++;
|
|
485
|
+
process.stderr.write(c.red(`已拦截 ${s.name}:安全扫描发现严重风险,未落盘`) + '\n');
|
|
486
|
+
process.stderr.write(formatScanReport(scan) + '\n');
|
|
487
|
+
process.stderr.write(c.gray('逐条审阅确无问题后,可加 --force-unsafe重试。') + '\n');
|
|
488
|
+
continue;
|
|
489
|
+
}
|
|
490
|
+
let dir;
|
|
491
|
+
try {
|
|
492
|
+
dir = writeSkillToDir(baseDir, detail);
|
|
493
|
+
} catch (e) {
|
|
494
|
+
if (!isPlanLimitError(e)) throw e;
|
|
495
|
+
limited = e.message;
|
|
496
|
+
unpulled++;
|
|
497
|
+
continue;
|
|
498
|
+
}
|
|
499
|
+
const warnNote = scan.counts.warn ? c.yellow(`(安全扫描 ${scan.counts.warn} 项警告)`) : '';
|
|
439
500
|
process.stdout.write(c.green('已拉取 ') + s.name
|
|
440
|
-
+ c.gray(`(${detail.files?.length || 0} 附件)→ ${dir}`) + '\n');
|
|
501
|
+
+ c.gray(`(${detail.files?.length || 0} 附件)→ ${dir}`) + warnNote + '\n');
|
|
441
502
|
}
|
|
442
|
-
process.
|
|
503
|
+
if (blocked) process.stderr.write(c.red(`共 ${blocked} 个技能因安全扫描未被拉取。`) + '\n');
|
|
504
|
+
if (limited) process.stderr.write(c.red(`${limited}(${unpulled} 个技能未拉取)`) + '\n');
|
|
505
|
+
process.stdout.write(c.gray('新会话中生效(系统提示词注入技能目录,load_skill按需载入)。') + '\n');
|
|
443
506
|
} catch (e) {
|
|
444
507
|
process.stderr.write(c.red('拉取失败:' + e.message) + '\n');
|
|
445
508
|
process.exit(1);
|
|
@@ -460,7 +523,7 @@ async function cmdSkills(config, args, flags, cwd) {
|
|
|
460
523
|
try {
|
|
461
524
|
payload = readSkillDirForPush(dir);
|
|
462
525
|
} catch (e) {
|
|
463
|
-
process.stderr.write(c.red(`读取技能失败(目录须含
|
|
526
|
+
process.stderr.write(c.red(`读取技能失败(目录须含SKILL.md):${e.message}`) + '\n');
|
|
464
527
|
process.exit(1);
|
|
465
528
|
}
|
|
466
529
|
try {
|
|
@@ -468,7 +531,7 @@ async function cmdSkills(config, args, flags, cwd) {
|
|
|
468
531
|
...payload, conflict: flags.overwrite ? 'overwrite' : 'skip',
|
|
469
532
|
});
|
|
470
533
|
const label = r.status === 'imported' ? '已推送(新建)'
|
|
471
|
-
: r.status === 'overwritten' ? '已推送(覆盖同名)' : '已跳过:平台已有同名技能(--overwrite
|
|
534
|
+
: r.status === 'overwritten' ? '已推送(覆盖同名)' : '已跳过:平台已有同名技能(--overwrite可覆盖)';
|
|
472
535
|
process.stdout.write((r.status === 'skipped' ? c.yellow(label) : c.green(label))
|
|
473
536
|
+ c.gray(` · ${payload.filename} → ${config.baseUrl}`) + '\n');
|
|
474
537
|
for (const w of r.warnings || []) {
|
|
@@ -527,15 +590,16 @@ async function main() {
|
|
|
527
590
|
process.stdout.write(c.gray('卸载命令本体:npm uninstall -g @huicai/cli') + '\n');
|
|
528
591
|
return;
|
|
529
592
|
}
|
|
530
|
-
process.stdout.write('将永久删除以下
|
|
593
|
+
process.stdout.write('将永久删除以下HuiCai CLI本机数据(' + info.dir + ',共 ' + fmtSize(info.total) + '):\n');
|
|
531
594
|
for (const e of info.entries) {
|
|
532
|
-
process.stdout.write(' - ' + e.name + (e.kind === 'dir' ? '/' : '')
|
|
595
|
+
process.stdout.write(' - ' + e.name + (e.kind === 'dir' ? '/' : '')
|
|
596
|
+
+ c.gray(' ' + fmtSize(e.size) + (e.label ? ' ' + e.label : '')) + '\n');
|
|
533
597
|
}
|
|
534
598
|
process.stdout.write(c.gray(' 含登录令牌、会话历史、长期记忆、技能与自定义命令等,删除不可撤销。') + '\n');
|
|
535
599
|
const yes = positional.includes('--yes') || positional.includes('-y') || flags.yolo;
|
|
536
600
|
if (!yes) {
|
|
537
601
|
if (!process.stdin.isTTY) {
|
|
538
|
-
process.stderr.write(c.red('非交互环境:请加 --yes
|
|
602
|
+
process.stderr.write(c.red('非交互环境:请加 --yes确认删除。') + '\n');
|
|
539
603
|
process.exit(1);
|
|
540
604
|
}
|
|
541
605
|
const ans = await new Promise((resolve) => {
|
|
@@ -548,8 +612,8 @@ async function main() {
|
|
|
548
612
|
}
|
|
549
613
|
}
|
|
550
614
|
const r = purgeData();
|
|
551
|
-
process.stdout.write(c.green('✅ 已清理所有
|
|
552
|
-
process.stdout.write(c.gray('卸载命令本体:npm uninstall -g @huicai/cli(其
|
|
615
|
+
process.stdout.write(c.green('✅ 已清理所有HuiCai CLI本机数据:' + r.dir) + '\n');
|
|
616
|
+
process.stdout.write(c.gray('卸载命令本体:npm uninstall -g @huicai/cli(其preuninstall钩子也会自动清理本目录)') + '\n');
|
|
553
617
|
return;
|
|
554
618
|
}
|
|
555
619
|
|
|
@@ -588,6 +652,15 @@ async function main() {
|
|
|
588
652
|
return;
|
|
589
653
|
}
|
|
590
654
|
|
|
655
|
+
if (sub === 'acp') {
|
|
656
|
+
// ACP 服务端:编辑器/自动化客户端经 JSON-RPC over stdio 长驻驱动惠彩。
|
|
657
|
+
// 与 -p 的分工:那个跑完就退出,这个在同一段上下文里连续对话。
|
|
658
|
+
// 注意 stdout 从这一刻起被协议帧独占(acp.js 启动时会把杂音改道 stderr)。
|
|
659
|
+
const { runAcpServer } = await import('../src/acp.js');
|
|
660
|
+
await runAcpServer({ config, cwd, yolo: flags.yolo });
|
|
661
|
+
return;
|
|
662
|
+
}
|
|
663
|
+
|
|
591
664
|
if (sub === 'daemon') {
|
|
592
665
|
// 内置调度守护:按 cron 真正运行 /schedule 登记的任务(Ctrl-C 退出)
|
|
593
666
|
const { runDaemon } = await import('../src/daemon.js');
|
|
@@ -641,7 +714,7 @@ async function main() {
|
|
|
641
714
|
if (!kbId) {
|
|
642
715
|
process.stderr.write(c.red('用法:huicai kb-sync <知识库ID> [ref] [--dry]') + '\n'
|
|
643
716
|
+ c.gray(' 例:huicai kb-sync 12 # 同步本地未提交改动到知识库 12') + '\n'
|
|
644
|
-
+ c.gray(' huicai kb-sync 12 origin/main # 同步相对
|
|
717
|
+
+ c.gray(' huicai kb-sync 12 origin/main # 同步相对origin/main的改动(CI常用)') + '\n');
|
|
645
718
|
process.exit(1);
|
|
646
719
|
}
|
|
647
720
|
const authProblem = validateAuth(config);
|
|
@@ -660,12 +733,12 @@ async function main() {
|
|
|
660
733
|
}
|
|
661
734
|
if (r.dry) {
|
|
662
735
|
for (const f of r.preview) process.stdout.write((f.deleted ? c.red(' − ') : c.green(' + ')) + f.path + '\n');
|
|
663
|
-
process.stdout.write(c.gray(`试运行:${r.added} 新增/修改,${r.removed} 删除${r.skipped ? `,跳过 ${r.skipped}` : ''}(加 --dry
|
|
736
|
+
process.stdout.write(c.gray(`试运行:${r.added} 新增/修改,${r.removed} 删除${r.skipped ? `,跳过 ${r.skipped}` : ''}(加 --dry之外的调用即实际同步)`) + '\n');
|
|
664
737
|
return;
|
|
665
738
|
}
|
|
666
739
|
process.stdout.write(c.green('✅ 知识库已保鲜:') + r.message + '\n');
|
|
667
740
|
} catch (e) {
|
|
668
|
-
process.stderr.write(c.red('✗ kb-sync
|
|
741
|
+
process.stderr.write(c.red('✗ kb-sync失败:' + e.message) + '\n');
|
|
669
742
|
process.exit(1);
|
|
670
743
|
}
|
|
671
744
|
return;
|
|
@@ -694,7 +767,7 @@ async function main() {
|
|
|
694
767
|
// --consult:混合模式——把平台伪模型作为 consult_platform 工具(本机原始驱动 + 平台编排咨询)
|
|
695
768
|
if (flags.consult) {
|
|
696
769
|
if (!/^(agent|workflow|datahuman|squad)-/.test(flags.consult)) {
|
|
697
|
-
process.stderr.write(c.red('--consult
|
|
770
|
+
process.stderr.write(c.red('--consult需平台伪模型id:agent-xxx / workflow-xxx / datahuman-xxx(分享码见分享窗口)') + '\n');
|
|
698
771
|
process.exit(1);
|
|
699
772
|
}
|
|
700
773
|
config.consult = flags.consult;
|
|
@@ -774,24 +847,32 @@ async function main() {
|
|
|
774
847
|
}
|
|
775
848
|
|
|
776
849
|
// 交互式:默认富 TUI(ink,需已安装依赖 + TTY);--plain 强制普通 REPL;TUI 不可用则自动回退
|
|
850
|
+
const updater = process.stdin.isTTY && process.stdout.isTTY ? createUpdater({ current: _pkg.version }) : null;
|
|
851
|
+
const finishUpdate = (result) => {
|
|
852
|
+
updater?.dispose();
|
|
853
|
+
if (result?.updated) process.stdout.write(c.green(`已更新到 v${displayVersion(result.updated)},请重新运行 huicai。登录、历史与配置已保留。\n`));
|
|
854
|
+
};
|
|
777
855
|
// 偏好顺序:命令行 --tui/--plain > 配置 tui(rich/plain) > auto(TTY 下用 TUI)
|
|
778
|
-
const wantTui = flags.
|
|
779
|
-
|
|
856
|
+
const wantTui = !flags.plain && process.stdout.isTTY && process.stdin.isTTY && process.env.TERM !== 'dumb'
|
|
857
|
+
&& (flags.tui || config.tui !== 'plain');
|
|
780
858
|
if (wantTui) {
|
|
781
|
-
let
|
|
859
|
+
let runInk;
|
|
782
860
|
try {
|
|
783
|
-
|
|
784
|
-
ran = (await runInk({ config, cwd, session, yolo: flags.yolo, initialPrompt: prompt || null, version: VERSION })) || {};
|
|
861
|
+
({ runInk } = await import('../src/tui/app.js'));
|
|
785
862
|
} catch (e) {
|
|
786
|
-
process.stderr.write(c.gray('(未启用
|
|
863
|
+
process.stderr.write(c.gray('(未启用TUI:' + e.message + ',回退普通模式)') + '\n');
|
|
787
864
|
}
|
|
788
|
-
//
|
|
789
|
-
|
|
865
|
+
// Only dependency loading may fall back. A runtime failure must never replay
|
|
866
|
+
// the initial prompt after it may already have edited files or run commands.
|
|
867
|
+
if (runInk) {
|
|
868
|
+
const ran = await runInk({ config, cwd, session, yolo: flags.yolo, initialPrompt: prompt || null, version: VERSION, updater });
|
|
869
|
+
finishUpdate(ran);
|
|
790
870
|
await reloginIfNeeded(ran, flags);
|
|
791
871
|
return;
|
|
792
872
|
}
|
|
793
873
|
}
|
|
794
|
-
const r = await startRepl({ config, cwd, yolo: flags.yolo, initialPrompt: prompt || null, session, version: VERSION });
|
|
874
|
+
const r = await startRepl({ config, cwd, yolo: flags.yolo, initialPrompt: prompt || null, session, version: VERSION, updater });
|
|
875
|
+
finishUpdate(r);
|
|
795
876
|
await reloginIfNeeded(r, flags);
|
|
796
877
|
}
|
|
797
878
|
|
|
@@ -834,7 +915,7 @@ async function pickSession(cwd) {
|
|
|
834
915
|
function cmdSessions(cwd, all) {
|
|
835
916
|
const list = sessions.listSessions(all ? null : cwd);
|
|
836
917
|
if (!list.length) {
|
|
837
|
-
process.stdout.write(all ? '暂无历史会话。\n' : '当前目录暂无历史会话(-a/--all
|
|
918
|
+
process.stdout.write(all ? '暂无历史会话。\n' : '当前目录暂无历史会话(-a/--all查看全部)。\n');
|
|
838
919
|
return;
|
|
839
920
|
}
|
|
840
921
|
for (const s of list) {
|
|
@@ -843,7 +924,7 @@ function cmdSessions(cwd, all) {
|
|
|
843
924
|
);
|
|
844
925
|
if (all) process.stdout.write(c.gray(` ${s.cwd || ''}`) + '\n');
|
|
845
926
|
}
|
|
846
|
-
process.stdout.write(c.gray('\n恢复:huicai resume <id> 或
|
|
927
|
+
process.stdout.write(c.gray('\n恢复:huicai resume <id> 或huicai -c(最近一次)\n'));
|
|
847
928
|
}
|
|
848
929
|
|
|
849
930
|
main().catch((e) => {
|
package/bin/update.js
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
// CLI 更新只由入口启用;IDE 内嵌核心不会自行安装全局软件。
|
|
2
|
+
import { execFile } from 'node:child_process';
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
import { promisify } from 'node:util';
|
|
7
|
+
const exec = promisify(execFile);
|
|
8
|
+
const PACKAGE = '@huicai/cli';
|
|
9
|
+
const stable = (v) => typeof v === 'string' && /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/.test(v);
|
|
10
|
+
export function newer(a, b) {
|
|
11
|
+
if (!stable(a) || !stable(b)) return false;
|
|
12
|
+
const aa = a.split('.').map(BigInt), bb = b.split('.').map(BigInt);
|
|
13
|
+
for (let i = 0; i < 3; i++) if (aa[i] !== bb[i]) return aa[i] > bb[i];
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
export function displayVersion(v) {
|
|
17
|
+
const [year, md, patch] = v.split('.').map(Number);
|
|
18
|
+
const month = Math.floor(md / 100), day = md % 100;
|
|
19
|
+
return year >= 2020 && month >= 1 && month <= 12 && day >= 1 && day <= 31
|
|
20
|
+
? `${year}.${String(month).padStart(2, '0')}.${String(day).padStart(2, '0')}${patch ? '.' + patch : ''}` : v;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// 直接执行 npm 的 JS 入口,兼容 Windows,避免 cmd/shell 插值及命令注入。
|
|
24
|
+
export function npmExecutable(env = process.env) {
|
|
25
|
+
const dirs = [path.dirname(process.execPath), ...(env.PATH || '').split(path.delimiter)];
|
|
26
|
+
for (const dir of dirs) {
|
|
27
|
+
for (const file of ['npm', 'node_modules/npm/bin/npm-cli.js', '../lib/node_modules/npm/bin/npm-cli.js']) {
|
|
28
|
+
try {
|
|
29
|
+
const resolved = fs.realpathSync(path.resolve(dir, file));
|
|
30
|
+
if (resolved.endsWith('npm-cli.js')) return resolved;
|
|
31
|
+
} catch { /* 继续查找同一 Node 安装或 PATH 中的 npm */ }
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
throw new Error('未找到 npm,请安装 Node.js 附带的 npm 后重试。');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function createUpdater({ current, packageRoot = fileURLToPath(new URL('..', import.meta.url)), env = process.env, run = exec } = {}) {
|
|
38
|
+
const controller = new AbortController();
|
|
39
|
+
let installing;
|
|
40
|
+
let installAbort;
|
|
41
|
+
const npm = async (args, timeout = 10000, signal = controller.signal) => {
|
|
42
|
+
const result = await run(process.execPath, [npmExecutable(env), ...args], {
|
|
43
|
+
env: { ...env, HUICAI_UPDATING: '1', npm_config_update_notifier: 'false' },
|
|
44
|
+
cwd: path.dirname(process.execPath), timeout, maxBuffer: 1024 * 1024,
|
|
45
|
+
signal, windowsHide: true,
|
|
46
|
+
});
|
|
47
|
+
return result.stdout.trim();
|
|
48
|
+
};
|
|
49
|
+
const check = npm(['view', PACKAGE + '@latest', 'version', '--json', '--fetch-retries=0', '--fetch-timeout=6000'])
|
|
50
|
+
.then((raw) => JSON.parse(raw)).then((version) => newer(version, current) ? version : null)
|
|
51
|
+
.catch(() => null); // 后台检测断网、未发布或损坏响应时静默,不影响启动。
|
|
52
|
+
return {
|
|
53
|
+
check,
|
|
54
|
+
dispose: () => { controller.abort(); installAbort?.abort(); },
|
|
55
|
+
menu: (version) => ({ title: `HuiCai AI 有新版本 v${displayVersion(version)}`, current: 'later', searchable: false,
|
|
56
|
+
options: [{ value: 'update', label: '更新到最新版本', description: '自动安装;保留登录、历史与配置,完成后重新运行 huicai' },
|
|
57
|
+
{ value: 'later', label: '稍后', description: '继续当前会话,下次启动时再提醒' }] }),
|
|
58
|
+
install(version, { signal } = {}) {
|
|
59
|
+
if (installing) return installing;
|
|
60
|
+
installAbort = new AbortController();
|
|
61
|
+
const abort = () => installAbort?.abort();
|
|
62
|
+
signal?.addEventListener('abort', abort, { once: true });
|
|
63
|
+
if (signal?.aborted || controller.signal.aborted) installAbort.abort();
|
|
64
|
+
const installSignal = installAbort.signal;
|
|
65
|
+
installing = (async () => {
|
|
66
|
+
if (!newer(version, current)) throw new Error('无有效的新版本,已停止安装。');
|
|
67
|
+
// npm 7+ 不执行卸载钩子;旧 npm 可能在替换包时误删 ~/.huicai。
|
|
68
|
+
const npmVersion = await npm(['--version'], 10000, installSignal);
|
|
69
|
+
if (!/^\d+\./.test(npmVersion) || Number(npmVersion.split('.')[0]) < 7) throw new Error('自动更新需要 npm 7 或更新版本,请先升级 npm。');
|
|
70
|
+
let prefix;
|
|
71
|
+
const root = fs.realpathSync(packageRoot);
|
|
72
|
+
const suffix = path.join('lib', 'node_modules', '@huicai', 'cli');
|
|
73
|
+
const windowsSuffix = path.join('node_modules', '@huicai', 'cli');
|
|
74
|
+
// 已全局安装时固定原安装位置,避免 PATH 上另一个 npm 更新到错误目录。
|
|
75
|
+
if (root.endsWith(path.sep + suffix)) prefix = root.slice(0, -suffix.length);
|
|
76
|
+
else if (process.platform === 'win32' && root.endsWith(path.sep + windowsSuffix)) prefix = root.slice(0, -windowsSuffix.length);
|
|
77
|
+
else prefix = await npm(['prefix', '--global'], 10000, installSignal);
|
|
78
|
+
await npm(['install', '--global', '--prefix', prefix, PACKAGE + '@' + version,
|
|
79
|
+
'--no-audit', '--no-fund', '--fetch-retries=1', '--fetch-timeout=30000'], 300000, installSignal);
|
|
80
|
+
const installedRoot = path.join(prefix, ...(process.platform === 'win32' ? [] : ['lib']), 'node_modules', '@huicai', 'cli');
|
|
81
|
+
const installed = JSON.parse(fs.readFileSync(path.join(installedRoot, 'package.json'), 'utf8'));
|
|
82
|
+
if (installed.version !== version) throw new Error('安装后的版本校验未通过,请重试。');
|
|
83
|
+
// 用真实的新入口确认可启动,而非仅凭 npm 的退出码报告成功。
|
|
84
|
+
await run(process.execPath, [path.join(installedRoot, 'bin', 'huicai.js'), '--version'], {
|
|
85
|
+
env, timeout: 15000, maxBuffer: 65536, windowsHide: true, signal: installSignal,
|
|
86
|
+
});
|
|
87
|
+
return version;
|
|
88
|
+
})().catch((error) => {
|
|
89
|
+
installing = null;
|
|
90
|
+
if (installSignal.aborted) throw new Error('更新已中断,可输入 /update 重试。');
|
|
91
|
+
const denied = /EACCES|EPERM/.test(String(error.stderr || error.message));
|
|
92
|
+
throw new Error(denied ? '安装目录没有写入权限,请使用可写的 npm 全局目录后重试。' : '更新未完成,请检查网络或 npm 配置后重试。' + (error.message?.startsWith('Command failed') ? '' : ` ${error.message}`));
|
|
93
|
+
}).finally(() => { signal?.removeEventListener('abort', abort); installAbort = null; });
|
|
94
|
+
return installing;
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
}
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@huicai/cli",
|
|
3
|
-
"version": "2026.
|
|
4
|
-
"versionDisplay": "2026.
|
|
5
|
-
"description": "在终端运行的智能体
|
|
3
|
+
"version": "2026.1021.0",
|
|
4
|
+
"versionDisplay": "2026.10.21",
|
|
5
|
+
"description": "在终端运行的智能体CLI:以HuiCai_AI平台的OpenAI兼容 /v1 为模型后端,在用户本机执行文件/命令工具。",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
8
8
|
"huicai": "bin/huicai.js"
|
|
@@ -11,21 +11,32 @@
|
|
|
11
11
|
"node": ">=18"
|
|
12
12
|
},
|
|
13
13
|
"files": [
|
|
14
|
+
"LICENSE",
|
|
15
|
+
"README.md",
|
|
14
16
|
"bin",
|
|
15
|
-
"src",
|
|
16
17
|
"skills",
|
|
17
18
|
"squads",
|
|
18
|
-
"
|
|
19
|
-
"
|
|
19
|
+
"src",
|
|
20
|
+
"ui"
|
|
20
21
|
],
|
|
21
22
|
"scripts": {
|
|
22
23
|
"start": "node bin/huicai.js",
|
|
23
24
|
"check": "node --check bin/huicai.js",
|
|
25
|
+
"gates": "node scripts/gates/run-gates.cjs local",
|
|
26
|
+
"gates:prepush": "node scripts/gates/run-gates.cjs pre-push",
|
|
27
|
+
"gates:ci": "node scripts/gates/run-gates.cjs ci",
|
|
28
|
+
"gen:catalogs": "node scripts/gates/gen-tool-catalog.cjs --write && node scripts/gates/gen-command-catalog.cjs --write",
|
|
24
29
|
"test": "node --test --test-concurrency=1 test/*.test.mjs",
|
|
25
30
|
"version:next": "node scripts/next-version.cjs",
|
|
26
31
|
"pack:release": "node scripts/pack-release.cjs",
|
|
27
32
|
"preuninstall": "node bin/preuninstall.cjs",
|
|
28
|
-
"prepublishOnly": "
|
|
33
|
+
"prepublishOnly": "npm run gates:ci",
|
|
34
|
+
"battery:weekly": "node scripts/weekly-battery.mjs",
|
|
35
|
+
"battery:web": "node scripts/web-battery.mjs",
|
|
36
|
+
"battery:report": "node scripts/report-battery.mjs",
|
|
37
|
+
"mutest:weekly": "node scripts/weekly-mutest.mjs",
|
|
38
|
+
"lint:skills": "node scripts/skill-lint.cjs --strict --quiet",
|
|
39
|
+
"optimize:skill": "node scripts/skill-optimize.cjs"
|
|
29
40
|
},
|
|
30
41
|
"keywords": [
|
|
31
42
|
"cli",
|
|
@@ -51,6 +62,14 @@
|
|
|
51
62
|
},
|
|
52
63
|
"dependencies": {
|
|
53
64
|
"ink": "^7.1.0",
|
|
54
|
-
"react": "^19.2.7"
|
|
65
|
+
"react": "^19.2.7",
|
|
66
|
+
"string-width": "^7.2.0",
|
|
67
|
+
"strip-ansi": "^7.2.0",
|
|
68
|
+
"wrap-ansi": "^9.0.2"
|
|
69
|
+
},
|
|
70
|
+
"optionalDependencies": {
|
|
71
|
+
"@deepseek-ai/node-addon-landlock-run": "^0.1.0",
|
|
72
|
+
"koffi": "^2.9.0",
|
|
73
|
+
"node-pty": "^1.1.0"
|
|
55
74
|
}
|
|
56
75
|
}
|