@whyshu/argent-engine 0.0.0-stage → 0.6.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/MANIFEST.json +307 -0
- package/engine/VERSION +1 -0
- package/engine/agents/catalog.json +454 -0
- package/engine/configs/_aliases.proposed.json +651 -0
- package/engine/configs/_migration-plan.proposed.json +899 -0
- package/engine/configs/account.json +272 -0
- package/engine/configs/advanced.json +205 -0
- package/engine/configs/host.json +149 -0
- package/engine/configs/hr.json +27 -0
- package/engine/configs/notify.json +264 -0
- package/engine/core/cli/argent.mjs +277 -0
- package/engine/core/contracts/argent.contracts.json +1065 -0
- package/engine/core/contracts/verbs.schema.json +2539 -0
- package/engine/core/lib/argent-datadir.mjs +223 -0
- package/engine/core/lib/audit.mjs +187 -0
- package/engine/core/lib/claim.mjs +258 -0
- package/engine/core/lib/config-catalog.mjs +1172 -0
- package/engine/core/lib/doctor-customer.mjs +577 -0
- package/engine/core/lib/flow-list.mjs +138 -0
- package/engine/core/lib/flow-registry.mjs +48 -0
- package/engine/core/lib/init.mjs +247 -0
- package/engine/core/lib/ledger.mjs +124 -0
- package/engine/core/lib/license-activate.mjs +813 -0
- package/engine/core/lib/license-device.mjs +314 -0
- package/engine/core/lib/license-file.mjs +349 -0
- package/engine/core/lib/license-guard.mjs +123 -0
- package/engine/core/lib/license-ops.mjs +1645 -0
- package/engine/core/lib/license-verdict.mjs +133 -0
- package/engine/core/lib/license.mjs +577 -0
- package/engine/core/lib/notify/dedup.mjs +101 -0
- package/engine/core/lib/notify/feishu.mjs +38 -0
- package/engine/core/lib/notify/index.mjs +95 -0
- package/engine/core/lib/notify/verb.mjs +327 -0
- package/engine/core/lib/notify/webhook.mjs +135 -0
- package/engine/core/lib/notify/wecom.mjs +36 -0
- package/engine/core/lib/python.mjs +145 -0
- package/engine/core/lib/sop.mjs +116 -0
- package/engine/core/lib/versions.mjs +205 -0
- package/engine/core/mcp/client.mjs +67 -0
- package/engine/core/mcp/http.mjs +138 -0
- package/engine/core/mcp/server.mjs +702 -0
- package/engine/scripts/_engine_rules_probe.py +15 -0
- package/engine/scripts/analyze-full-day.py +568 -0
- package/engine/scripts/archive/feishu-bridge.js +246 -0
- package/engine/scripts/argent-agents.mjs +527 -0
- package/engine/scripts/argent-capabilities.mjs +776 -0
- package/engine/scripts/argent-catalog.mjs +186 -0
- package/engine/scripts/argent-datadir.py +62 -0
- package/engine/scripts/argent-doctor.mjs +624 -0
- package/engine/scripts/argent-env-write.mjs +302 -0
- package/engine/scripts/argent-schedule.mjs +620 -0
- package/engine/scripts/argent-setup-check.mjs +369 -0
- package/engine/scripts/argent-upgrade.mjs +1046 -0
- package/engine/scripts/base-bootstrap.sh +575 -0
- package/engine/scripts/billing-mode-daily.sh +12 -0
- package/engine/scripts/build-engine-package.mjs +123 -0
- package/engine/scripts/capability-packs.lock.json +484 -0
- package/engine/scripts/capability_pack.py +1242 -0
- package/engine/scripts/check-1.0-criteria.mjs +355 -0
- package/engine/scripts/check-agent-catalog.mjs +141 -0
- package/engine/scripts/check-billing-mode.sh +377 -0
- package/engine/scripts/check-child-sessions.mjs +83 -0
- package/engine/scripts/check-config-catalog.mjs +677 -0
- package/engine/scripts/check-docs-drift.mjs +522 -0
- package/engine/scripts/check-dsh-web-expose.sh +98 -0
- package/engine/scripts/check-judgment-drift.mjs +403 -0
- package/engine/scripts/check-license.mjs +199 -0
- package/engine/scripts/check-model-auth.py +443 -0
- package/engine/scripts/check-pack-closure.mjs +661 -0
- package/engine/scripts/check-portable-symbols.mjs +116 -0
- package/engine/scripts/check-preset-landing.mjs +124 -0
- package/engine/scripts/check-production-home.mjs +602 -0
- package/engine/scripts/check-role-mapping.mjs +461 -0
- package/engine/scripts/check-sample-redaction.mjs +320 -0
- package/engine/scripts/check-skill-classification.mjs +188 -0
- package/engine/scripts/check-sop-consistency.mjs +431 -0
- package/engine/scripts/check-test-env-safety.mjs +627 -0
- package/engine/scripts/check-version-consistency.mjs +452 -0
- package/engine/scripts/ci-run.sh +558 -0
- package/engine/scripts/config-explain.mjs +278 -0
- package/engine/scripts/configure-provider.rb +29 -0
- package/engine/scripts/customer-config-migrate.mjs +179 -0
- package/engine/scripts/customer-preflight.py +892 -0
- package/engine/scripts/customer-readiness.sh +134 -0
- package/engine/scripts/daily-report-inbox.py +242 -0
- package/engine/scripts/daily-report-reconcile.mjs +312 -0
- package/engine/scripts/daily-report.mjs +1310 -0
- package/engine/scripts/daily-report.sh +46 -0
- package/engine/scripts/data/lip-product-dict.json +306 -0
- package/engine/scripts/deliver-customer.mjs +932 -0
- package/engine/scripts/delivery-faces.txt +31 -0
- package/engine/scripts/desktop-trial.sh +146 -0
- package/engine/scripts/dev-window.sh +260 -0
- package/engine/scripts/drill-clean-machine.sh +315 -0
- package/engine/scripts/dsh-api-client.mjs +215 -0
- package/engine/scripts/dsh-backup-scope.sh +83 -0
- package/engine/scripts/dsh-offline-pack.mjs +77 -0
- package/engine/scripts/dsh-overlay-pin.sh +87 -0
- package/engine/scripts/dsh-plane.mjs +153 -0
- package/engine/scripts/dsh-portforward.py +223 -0
- package/engine/scripts/dsh-preflight.mjs +179 -0
- package/engine/scripts/dsh-release-watch-daily.sh +19 -0
- package/engine/scripts/dsh-release-watch.mjs +458 -0
- package/engine/scripts/dsh-remote-check.sh +99 -0
- package/engine/scripts/dsh-restart.sh +179 -0
- package/engine/scripts/dsh-restore.sh +111 -0
- package/engine/scripts/dsh-scope-rewire.mjs +803 -0
- package/engine/scripts/dsh-snapshot.mjs +116 -0
- package/engine/scripts/dsh-upgrade-readiness.mjs +165 -0
- package/engine/scripts/dsh-upgrade.mjs +612 -0
- package/engine/scripts/dsh-url.sh +86 -0
- package/engine/scripts/dsh-web-launch.mjs +155 -0
- package/engine/scripts/ensure-store-windows.py +509 -0
- package/engine/scripts/entitlements.py +458 -0
- package/engine/scripts/env_probe.py +411 -0
- package/engine/scripts/feishu-card.mjs +252 -0
- package/engine/scripts/fix-skill-frontmatter.py +209 -0
- package/engine/scripts/flow-auto-retry.py +454 -0
- package/engine/scripts/flow-requirements.json +720 -0
- package/engine/scripts/flow-scaffold.py +275 -0
- package/engine/scripts/flow-timers-plist.sh +86 -0
- package/engine/scripts/flow-timers.sh +182 -0
- package/engine/scripts/flow-trigger-wake.mjs +284 -0
- package/engine/scripts/flow-trigger.sh +571 -0
- package/engine/scripts/flow_billing.py +354 -0
- package/engine/scripts/flow_capability_stats.py +314 -0
- package/engine/scripts/flow_case.py +194 -0
- package/engine/scripts/flow_claim.py +497 -0
- package/engine/scripts/flow_config.py +1024 -0
- package/engine/scripts/flow_failure.py +588 -0
- package/engine/scripts/flow_learn.py +105 -0
- package/engine/scripts/flow_ledger.py +235 -0
- package/engine/scripts/flow_policy.py +238 -0
- package/engine/scripts/flow_preflight.py +339 -0
- package/engine/scripts/flow_registry.py +341 -0
- package/engine/scripts/flow_retry.py +304 -0
- package/engine/scripts/flow_return_to_ops.py +191 -0
- package/engine/scripts/flow_source.py +315 -0
- package/engine/scripts/flow_sources/__init__.py +53 -0
- package/engine/scripts/flow_sources/cases_json.py +106 -0
- package/engine/scripts/flow_sources/common.py +428 -0
- package/engine/scripts/flow_sources/feishu_base.py +273 -0
- package/engine/scripts/flow_stale.py +185 -0
- package/engine/scripts/flow_status_reconcile.py +344 -0
- package/engine/scripts/flow_triage.py +849 -0
- package/engine/scripts/flow_write_verify.py +496 -0
- package/engine/scripts/fulfillment.js +586 -0
- package/engine/scripts/gen-agent-bundles.mjs +276 -0
- package/engine/scripts/gen-preset-rows.mjs +259 -0
- package/engine/scripts/init-ml.sh +2275 -0
- package/engine/scripts/install-internal-role.sh +190 -0
- package/engine/scripts/install-license.mjs +641 -0
- package/engine/scripts/install-one-shot.mjs +665 -0
- package/engine/scripts/integration_contract.py +220 -0
- package/engine/scripts/integrations/wenyao/adapter.py +98 -0
- package/engine/scripts/integrations/xzh/adapter.py +75 -0
- package/engine/scripts/invoice-mapping.example.json +40 -0
- package/engine/scripts/invoice-table.sh +194 -0
- package/engine/scripts/invoice_carrier_notice.py +279 -0
- package/engine/scripts/invoice_fail_closeout.py +297 -0
- package/engine/scripts/invoice_lip_runner.py +1508 -0
- package/engine/scripts/invoice_lip_runner.py.bak-20260922-1710-freready +1090 -0
- package/engine/scripts/invoice_ready_audit.py +191 -0
- package/engine/scripts/invoice_runner.py +675 -0
- package/engine/scripts/invoice_stageb.py +516 -0
- package/engine/scripts/launchd/com.whyshu.argent-bridge.plist.example +42 -0
- package/engine/scripts/launchd/com.whyshu.fulfillment-poll.plist.example +29 -0
- package/engine/scripts/lease.py +377 -0
- package/engine/scripts/lib/agent-install.mjs +649 -0
- package/engine/scripts/lib/argent-datadir.mjs +16 -0
- package/engine/scripts/lib/argent_datadir.py +262 -0
- package/engine/scripts/lib/argent_filelock.py +507 -0
- package/engine/scripts/lib/bootcheck-wiring.mjs +510 -0
- package/engine/scripts/lib/cdp_ports.py +197 -0
- package/engine/scripts/lib/customer-env.mjs +102 -0
- package/engine/scripts/lib/daily-report-core.mjs +517 -0
- package/engine/scripts/lib/dep-declaration.mjs +81 -0
- package/engine/scripts/lib/deps-migrate.mjs +310 -0
- package/engine/scripts/lib/dsh-host-resolve.mjs +109 -0
- package/engine/scripts/lib/dsh-scope.mjs +500 -0
- package/engine/scripts/lib/dsh-snapshot-path.mjs +35 -0
- package/engine/scripts/lib/dsh-versions.mjs +96 -0
- package/engine/scripts/lib/dsh-web-probe.mjs +214 -0
- package/engine/scripts/lib/is-direct-run.mjs +61 -0
- package/engine/scripts/lib/patch-compose.mjs +241 -0
- package/engine/scripts/lib/patch-target.mjs +35 -0
- package/engine/scripts/lib/plugin-lifecycle.mjs +128 -0
- package/engine/scripts/lib/plugin-packages.mjs +332 -0
- package/engine/scripts/lib/preset-compat.mjs +127 -0
- package/engine/scripts/lib/preset-install.mjs +575 -0
- package/engine/scripts/lib/preset-mechanism.mjs +56 -0
- package/engine/scripts/lib/preset-sync.mjs +59 -0
- package/engine/scripts/lib/profile-retire.mjs +97 -0
- package/engine/scripts/lib/python-runtime.mjs +190 -0
- package/engine/scripts/lib/registry.mjs +72 -0
- package/engine/scripts/lib/repo-root.sh +56 -0
- package/engine/scripts/lib/schedule-mechanism.mjs +659 -0
- package/engine/scripts/lib/schedule-probe.mjs +835 -0
- package/engine/scripts/lib/scope-pointer.mjs +164 -0
- package/engine/scripts/lib/settings-panels.mjs +816 -0
- package/engine/scripts/lib/stdio_utf8.py +86 -0
- package/engine/scripts/lib/wake-auth.mjs +392 -0
- package/engine/scripts/lib/webdriver_ipc.py +264 -0
- package/engine/scripts/lib/zstd-frames.mjs +104 -0
- package/engine/scripts/license-e2e-drill.mjs +426 -0
- package/engine/scripts/license-gate.mjs +245 -0
- package/engine/scripts/lip_backlog.py +171 -0
- package/engine/scripts/lip_table.py +185 -0
- package/engine/scripts/local-usage.mjs +214 -0
- package/engine/scripts/migrate-providers.mjs +127 -0
- package/engine/scripts/migrate-skills.sh +65 -0
- package/engine/scripts/ml-oauth-setup.mjs +550 -0
- package/engine/scripts/ml-store-ids.json +26 -0
- package/engine/scripts/ml_artifact_attribution.py +333 -0
- package/engine/scripts/ml_capacity_probe.py +1158 -0
- package/engine/scripts/ml_hub_status.py +1556 -0
- package/engine/scripts/ml_schema_check.py +115 -0
- package/engine/scripts/ml_store_ids.py +139 -0
- package/engine/scripts/npm-publish-argent.mjs +499 -0
- package/engine/scripts/npm-publish-argent.sh +20 -0
- package/engine/scripts/orchestrator.py +13811 -0
- package/engine/scripts/pack-plugins.mjs +140 -0
- package/engine/scripts/patches/dsh-llm-deepseek--transport-diagnostics.patch +297 -0
- package/engine/scripts/patches/dsh-session--append-message-shape.patch +15 -0
- package/engine/scripts/patches/dsh-session--tool-result-block-017.patch +28 -0
- package/engine/scripts/patches/dsh-session-format-v0-to-v1--permission-preset-origin.patch +11 -0
- package/engine/scripts/patches/dsh-session-format-v3-to-v4--turn-outside-replace.patch +20 -0
- package/engine/scripts/patches/dsh-session-persistence-jsonl--worker-bundled-migrators.patch +39 -0
- package/engine/scripts/patches/dsh-tools--render-return-shape.patch +50 -0
- package/engine/scripts/patches/verify-bundled-migrators.mjs +79 -0
- package/engine/scripts/patches/verify-hardening.mjs +167 -0
- package/engine/scripts/patches/verify-session-migration.mjs +149 -0
- package/engine/scripts/patches/verify-transport-diagnostics.mjs +227 -0
- package/engine/scripts/plan-role-rename.mjs +125 -0
- package/engine/scripts/plugin-bootcheck.mjs +451 -0
- package/engine/scripts/plugin-composition.json +15 -0
- package/engine/scripts/poc-mcp-host.mjs +455 -0
- package/engine/scripts/poll-fulfillment.sh +293 -0
- package/engine/scripts/poll-invoice.sh +74 -0
- package/engine/scripts/profile-doctor.mjs +686 -0
- package/engine/scripts/provider-select.sh +70 -0
- package/engine/scripts/provider-switch.sh +146 -0
- package/engine/scripts/provider-sync-target.check.mjs +64 -0
- package/engine/scripts/python-runtime.sh +78 -0
- package/engine/scripts/query_runner.py +310 -0
- package/engine/scripts/release-argent.sh +574 -0
- package/engine/scripts/repair-unresolved-tools.mjs +178 -0
- package/engine/scripts/run-tests.sh +256 -0
- package/engine/scripts/self-sign-license.mjs +179 -0
- package/engine/scripts/session-health-scan.mjs +63 -0
- package/engine/scripts/session-repair-tool-result-content.mjs +181 -0
- package/engine/scripts/setup.sh +22 -0
- package/engine/scripts/skill-install.mjs +629 -0
- package/engine/scripts/sku_translate.py +148 -0
- package/engine/scripts/sync-plugins.sh +90 -0
- package/engine/scripts/sync-presets.sh +27 -0
- package/engine/scripts/sync-scripts.sh +445 -0
- package/engine/scripts/telemetry.py +873 -0
- package/engine/scripts/ui-copy-count.mjs +220 -0
- package/engine/scripts/usage-anchor.sh +136 -0
- package/engine/scripts/usage_report.py +531 -0
- package/engine/scripts/validate-preset-schema.mjs +208 -0
- package/engine/scripts/vertical-init.mjs +323 -0
- package/engine/scripts/vertical-lint.mjs +482 -0
- package/engine/scripts/wenyao-browser.sh +73 -0
- package/engine/scripts/wenyao-fixture-export.py +116 -0
- package/engine/scripts/wenyao-invoice-writeback.mjs +540 -0
- package/engine/scripts/wenyao-login.sh +34 -0
- package/engine/scripts/wenyao-template-map.json +292 -0
- package/engine/scripts/wenyao_attach.py +131 -0
- package/engine/scripts/wenyao_download_template.py +144 -0
- package/engine/scripts/wenyao_fill_template.py +568 -0
- package/engine/scripts/wenyao_login.py +145 -0
- package/engine/scripts/wenyao_portal.py +633 -0
- package/engine/scripts/wenyao_recon.py +230 -0
- package/engine/scripts/wenyao_run.py +503 -0
- package/engine/scripts/wenyao_shadow_diff.py +160 -0
- package/engine/scripts/wenyao_skill_contract.py +156 -0
- package/engine/scripts/wenyao_template_fetch.py +175 -0
- package/engine/scripts/win/dsh-web-autostart.ps1 +372 -0
- package/engine/scripts/ziniao-auth-probe.sh +268 -0
- package/engine/scripts/ziniao-keepalive.sh +216 -0
- package/engine/scripts/ziniao-post-upgrade-check.sh +120 -0
- package/engine/scripts/ziniao-windows.sh +153 -0
- package/engine/version.mjs +1 -0
- package/engine/verticals/README.md +103 -0
- package/engine/verticals/_engine-words.baseline.txt +237 -0
- package/engine/verticals/_engine-words.json +19 -0
- package/engine/verticals/mercadolibre/README.md +43 -0
- package/engine/verticals/mercadolibre/config.json +709 -0
- package/engine/verticals/mercadolibre/flows.json +706 -0
- package/engine/verticals/mercadolibre/manifest.json +538 -0
- package/engine/verticals/mercadolibre/migrate-machine-state.mjs +138 -0
- package/engine/verticals/mercadolibre/preflight.py +143 -0
- package/engine/verticals/mercadolibre/prompts/daily-report.failure.md +69 -0
- package/engine/verticals/mercadolibre/prompts/daily-report.md +47 -0
- package/engine/verticals/mercadolibre/prompts/daily-report.scheduled.md +79 -0
- package/engine/verticals/mercadolibre/prompts/full.failure.md +125 -0
- package/engine/verticals/mercadolibre/prompts/full.md +91 -0
- package/engine/verticals/mercadolibre/prompts/wenyao-invoice.failure.md +88 -0
- package/engine/verticals/mercadolibre/prompts/wenyao-invoice.md +64 -0
- package/engine/verticals/mercadolibre/prompts/xzh-invoice.failure.md +91 -0
- package/engine/verticals/mercadolibre/prompts/xzh-invoice.md +46 -0
- package/package.json +21 -4
- package/README.md +0 -3
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* 智能体 **bundle** 生成器(0.6.0 W3,2026-10-13):`agents/catalog.json` → `plugins/argent-agent-<id>/`。
|
|
4
|
+
*
|
|
5
|
+
* ## 为什么需要它(与 `gen-preset-rows.mjs` 同因,同一套纪律)
|
|
6
|
+
* W3 的口径是「**agent = 一个 bundle**」:`--agent <id>` 装的不再是"角色/技能/定时器三件散件",
|
|
7
|
+
* 而是**一个包** `@whyshu/argent-agent-<id>`(`dependencies` = 壳 + 该智能体声明的插件;
|
|
8
|
+
* `dsh.bundle` = 该智能体的补丁层;包内**声明字段** = 该智能体要装的能力包与档位)。
|
|
9
|
+
*
|
|
10
|
+
* ⛔ **只有一份真源**:`agents/catalog.json`(L0 货架声明)是**作者格式**,本脚本把它**机械投影**成
|
|
11
|
+
* 6 个包的 `package.json`;安装器读的是**包内声明**(分发形态),⛔ 不在安装器里再写一份映射。
|
|
12
|
+
* 三处判据(同一份真源):
|
|
13
|
+
* ① 本脚本 `--check`:产物与声明**逐字节**一致 + catalog 的每个 agent ⟺ **恰好一个** bundle
|
|
14
|
+
* (缺件 / 多件都判红)+ 目录声明本身过 `validateCatalog()`/`validateHostAssets()`;
|
|
15
|
+
* ② 安装器:把**包内声明**与货架投影**逐字比对**,不一致 ⇒ 零写入判红(`install-argent.mjs`);
|
|
16
|
+
* ③ 门禁:`scripts/tests/agent-bundle-generation.test.mjs`(含"手改产物 / 加删 agent 必须判红"的牙)。
|
|
17
|
+
*
|
|
18
|
+
* ## 产物形态(`plugins/argent-agent-<id>/package.json`,**纯 bundle**:零 JS)
|
|
19
|
+
* ```
|
|
20
|
+
* name @whyshu/argent-agent-<id> ← 与目录名同源(门禁 P6 判据)
|
|
21
|
+
* version 0.1.0
|
|
22
|
+
* license/repository/engines.node/publishConfig npm 发布就绪(⛔ 不设 private)
|
|
23
|
+
* files ['package.json'] ← 闭合(本包真的只有清单)
|
|
24
|
+
* dependencies @whyshu/argent-shell + 该 agent 声明的**非壳**插件(npm 名取自唯一真源)
|
|
25
|
+
* dsh.bundle.patch [] ← 本 bundle 的补丁层(见下)
|
|
26
|
+
* argent.agent { id,title,payload{capabilities,plan},flows,roles,skills,integrations,credentials,scheduler,plugins }
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* ## 为什么今天的 6 个包 `dsh.bundle.patch` 都是**空数组**
|
|
30
|
+
* `dsh.bundle.patch` 是「该 bundle 往组合里 insert 哪些插件行」的声明位。今天**没有一个智能体需要
|
|
31
|
+
* insert 行**:`argent-core`/`argent-skin` 由**壳**(W2)负责 insert,`argent-gateway`/`argent-flow`/
|
|
32
|
+
* `argent-ml` 的挂载面仍是**整装 + 设置页**(W3 ⛔ 不改既有装配语义、⛔ 不改 `--plan-only` 回执口径)。
|
|
33
|
+
* ⇒ 写成 `[]`(**合法的空 bundle 层**:宿主侧 `bundlePatchFiles()` 认数组,空数组 = 零 patch 文件),
|
|
34
|
+
* ⛔ 不是"空 `- insert:`"那种病态形态(那会在启动期报 `patch: id is required`)。
|
|
35
|
+
* 有了它,包在 `dsh plugin add` 之后**就是** profile 的一层(否则宿主会打印
|
|
36
|
+
* `declares no dsh.bundle — installed as a plain dependency`)—— 将来某个智能体真的需要 insert 行时,
|
|
37
|
+
* 只需改本文件的 `insertRowsFor()`(声明驱动,⛔ 不许手改产物)。
|
|
38
|
+
*
|
|
39
|
+
* 用法:
|
|
40
|
+
* node scripts/gen-agent-bundles.mjs # 生成/刷新
|
|
41
|
+
* node scripts/gen-agent-bundles.mjs --check # 只校验(CI/门禁;不一致 exit 1)
|
|
42
|
+
*/
|
|
43
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
|
|
44
|
+
import { dirname, join } from 'node:path'
|
|
45
|
+
import { fileURLToPath } from 'node:url'
|
|
46
|
+
import { npmNameOf } from './lib/plugin-packages.mjs'
|
|
47
|
+
// 判据复用 L1 的**同一份**实现(⛔ 不在这里另写一套目录校验):
|
|
48
|
+
// · `argent-agents.mjs` = 货架声明的解析/校验(安装器与门禁也用它);
|
|
49
|
+
// · `lib/plugin-packages.mjs` = 插件 id ↔ npm 包名的唯一真源。
|
|
50
|
+
import { SHARED_SHELL_PLUGINS, buildContext, findAgent, validateCatalog, validateHostAssets } from './argent-agents.mjs'
|
|
51
|
+
|
|
52
|
+
const HERE = dirname(fileURLToPath(import.meta.url))
|
|
53
|
+
export const REPO = join(HERE, '..')
|
|
54
|
+
|
|
55
|
+
/** 真源(**只此一处**):货架声明。 */
|
|
56
|
+
export const CATALOG_REL = 'agents/catalog.json'
|
|
57
|
+
/** 产物根:`plugins/`。 */
|
|
58
|
+
export const PLUGINS_DIR = join(REPO, 'plugins')
|
|
59
|
+
/** bundle 目录名前缀 —— 安装器与门禁按它认"这是智能体 bundle"。 */
|
|
60
|
+
export const BUNDLE_PREFIX = 'argent-agent-'
|
|
61
|
+
/** bundle 版本(包自身语义化版本;与平台版本、能力包版本是三条轴)。 */
|
|
62
|
+
export const BUNDLE_VERSION = '0.1.1'
|
|
63
|
+
/** `@whyshu/argent-*` 依赖的兼容区间(⛔ 不是宿主 peer —— 那套区间判据只认 `@deepseek-ai/dsh*`)。 */
|
|
64
|
+
export const ARGENT_PLUGIN_RANGE = '>=0.1.0 <0.3'
|
|
65
|
+
/** 宿主 node 门槛(与安装器 `MIN_NODE` 对齐;与既有插件 `engines.node` 的写法逐字同源)。 */
|
|
66
|
+
export const ENGINES_NODE = '>=24.2.0'
|
|
67
|
+
/** npm 元数据(与既有 6 个插件逐字同源)。 */
|
|
68
|
+
export const REPO_URL = 'git+https://whyshu.com/git/argent-dsh.git'
|
|
69
|
+
|
|
70
|
+
/** 读货架声明(读不到 ⇒ null,由调用方响亮报错,⛔ 不静默补一份);`root` 可注入(夹具用)。 */
|
|
71
|
+
export function loadCatalogDoc(root = REPO) {
|
|
72
|
+
try { return JSON.parse(readFileSync(join(root, CATALOG_REL), 'utf8')) } catch { return null }
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** 货架里**在册智能体** id(保序 = 声明顺序)。 */
|
|
76
|
+
export function listCatalogAgentIds(doc = loadCatalogDoc()) {
|
|
77
|
+
return ((doc && doc.agents) || []).map((a) => (a && a.id ? String(a.id) : '')).filter(Boolean)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** 盘上**已存在的** bundle 目录名(`argent-agent-*`)。 */
|
|
81
|
+
export function listBundleDirs(dir = PLUGINS_DIR) {
|
|
82
|
+
if (!existsSync(dir)) return []
|
|
83
|
+
return readdirSync(dir).filter((d) => d.startsWith(BUNDLE_PREFIX)).sort()
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* 目录条目 → **包内声明**(唯一投影;安装器读它、生成器写它、门禁比对它)。
|
|
88
|
+
*
|
|
89
|
+
* ⚠️ 字段名与来源(⛔ 不新增第二份真源):
|
|
90
|
+
* · `payload.capabilities` ← `agent.capability` 或 `agent.capabilities`(二者二选一,⛔ 不在包内再存一份平铺的能力名);
|
|
91
|
+
* · `payload.plan` ← `agent.minPlan`(安装器的 `plan.minPlan` 由它映射,⛔ 不两处各存一份档位);
|
|
92
|
+
* · `flows/roles/skills/integrations/credentials/scheduler/plugins` ← 各自同名声明(逐字)。
|
|
93
|
+
* @param {object} agent `agents/catalog.json#agents[n]`
|
|
94
|
+
* @returns {object}
|
|
95
|
+
*/
|
|
96
|
+
export function declarationFor(agent) {
|
|
97
|
+
const capabilities = Array.isArray(agent.capabilities) ? agent.capabilities.map(String) : [String(agent.capability)]
|
|
98
|
+
const credentials = (agent.credentials || []).map((c) => ({ slot: String(c.slot), target: String(c.target), why: String(c.why) }))
|
|
99
|
+
return {
|
|
100
|
+
id: String(agent.id),
|
|
101
|
+
title: String(agent.title || ''),
|
|
102
|
+
payload: { capabilities, plan: String(agent.minPlan || '') },
|
|
103
|
+
flows: (agent.flows || []).map(String),
|
|
104
|
+
roles: (agent.roles || []).map(String),
|
|
105
|
+
skills: (agent.skills || []).map(String),
|
|
106
|
+
integrations: (agent.integrations || []).map(String),
|
|
107
|
+
credentials,
|
|
108
|
+
scheduler: agent.scheduler === true,
|
|
109
|
+
plugins: (agent.plugins || []).map(String),
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* 该智能体**需要 insert 的插件行**(`dsh.bundle.patch` 的判据)。
|
|
115
|
+
*
|
|
116
|
+
* 今天恒为 `[]`(见文件头「为什么今天 6 个包都是空数组」):壳负责 core/skin,其余插件的挂载面是
|
|
117
|
+
* 整装 + 设置页。函数留着是为了**声明驱动**:将来要挂行时改这里 + 生成 `cordis.patch.yml`,
|
|
118
|
+
* ⛔ 不要手改产物。
|
|
119
|
+
* @returns {string[]} 插件 id(需要 insert 的)
|
|
120
|
+
*/
|
|
121
|
+
export function insertRowsFor(agent) {
|
|
122
|
+
const plugins = (agent.plugins || []).map(String)
|
|
123
|
+
// 「壳负责的插件」不是本 bundle 的行;「声明了但不在共享壳里」的插件今天也**不**由本层挂(见文件头)。
|
|
124
|
+
// ⇒ 判据保留、取值恒空:一旦要改为"由 agent bundle 挂行",只需把下面这行换成
|
|
125
|
+
// `plugins.filter((p) => !SHARED_SHELL_PLUGINS.includes(p))` 并同批生成 cordis.patch.yml。
|
|
126
|
+
void plugins
|
|
127
|
+
return []
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/** 该 bundle 的 `dependencies`(壳 + 该 agent 声明的**非壳**插件;npm 名取自 `plugin-packages.mjs`)。 */
|
|
131
|
+
export function dependenciesFor(agent) {
|
|
132
|
+
const out = {}
|
|
133
|
+
const shell = npmNameOf('argent-shell')
|
|
134
|
+
if (!shell) throw new Error('`scripts/lib/plugin-packages.mjs` 里没有 argent-shell 的 npm 名 —— 无法生成 bundle 依赖')
|
|
135
|
+
out[shell] = ARGENT_PLUGIN_RANGE
|
|
136
|
+
for (const id of (agent.plugins || []).map(String)) {
|
|
137
|
+
if (SHARED_SHELL_PLUGINS.includes(id)) continue // core/skin 由壳带(⛔ 不重复声明)
|
|
138
|
+
if (id === 'argent-shell') continue
|
|
139
|
+
const npm = npmNameOf(id)
|
|
140
|
+
if (!npm) throw new Error(`未知插件 id \`${id}\`(在册:见 scripts/lib/plugin-packages.mjs)—— 无法生成 bundle 依赖`)
|
|
141
|
+
if (out[npm]) continue
|
|
142
|
+
out[npm] = ARGENT_PLUGIN_RANGE
|
|
143
|
+
}
|
|
144
|
+
return out
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/** 渲染 `package.json` 文本(键顺序固定 ⇒ 逐字节稳定)。 */
|
|
148
|
+
export function renderBundlePackageJson(agent) {
|
|
149
|
+
const name = `${BUNDLE_PREFIX}${String(agent.id)}`
|
|
150
|
+
const doc = {
|
|
151
|
+
name: `@whyshu/${name}`,
|
|
152
|
+
version: BUNDLE_VERSION,
|
|
153
|
+
description: `Argent on DSH 智能体 bundle —— ${String(agent.title || agent.id)}(由 agents/catalog.json 生成,⛔ 不要手改)`,
|
|
154
|
+
license: 'MIT',
|
|
155
|
+
repository: { type: 'git', url: REPO_URL, directory: `plugins/${name}` },
|
|
156
|
+
engines: { node: ENGINES_NODE },
|
|
157
|
+
files: ['package.json'],
|
|
158
|
+
publishConfig: { access: 'public' },
|
|
159
|
+
dependencies: dependenciesFor(agent),
|
|
160
|
+
dsh: { bundle: { patch: insertRowsFor(agent).map((id) => `./${id}.patch.yml`) } },
|
|
161
|
+
argent: { agent: declarationFor(agent) },
|
|
162
|
+
}
|
|
163
|
+
return `${JSON.stringify(doc, null, 2)}\n`
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* 生成/校验 6 个 bundle。
|
|
168
|
+
* @param {{check?: boolean}} [o]
|
|
169
|
+
* @returns {{ids: string[], changed: string[], errors: string[]}}
|
|
170
|
+
*/
|
|
171
|
+
export function generate({ check = false, root = REPO } = {}) {
|
|
172
|
+
const doc = loadCatalogDoc(root)
|
|
173
|
+
const pluginsDir = join(root, 'plugins')
|
|
174
|
+
const changed = []
|
|
175
|
+
const errors = []
|
|
176
|
+
if (!doc) return { ids: [], changed, errors: [`读不到货架声明:${CATALOG_REL}`] }
|
|
177
|
+
const agents = (doc.agents || []).filter((a) => a && a.id)
|
|
178
|
+
const ids = agents.map((a) => String(a.id))
|
|
179
|
+
const files = new Map()
|
|
180
|
+
for (const a of agents) {
|
|
181
|
+
const dir = join(pluginsDir, `${BUNDLE_PREFIX}${a.id}`)
|
|
182
|
+
files.set(join(dir, 'package.json'), renderBundlePackageJson(a))
|
|
183
|
+
}
|
|
184
|
+
// 清理已不在货架上的 bundle(多出来的产物 = 陈旧件 ⇒ --check 判红)
|
|
185
|
+
for (const d of listBundleDirs(pluginsDir)) {
|
|
186
|
+
const id = d.slice(BUNDLE_PREFIX.length)
|
|
187
|
+
if (ids.includes(id)) continue
|
|
188
|
+
if (check) changed.push(`(应删除)plugins/${d}`)
|
|
189
|
+
else { rmSync(join(pluginsDir, d), { recursive: true, force: true }); changed.push(`删除 plugins/${d}`) }
|
|
190
|
+
}
|
|
191
|
+
for (const [path, content] of files) {
|
|
192
|
+
const cur = existsSync(path) ? readFileSync(path, 'utf8') : null
|
|
193
|
+
if (cur === content) continue
|
|
194
|
+
if (check) changed.push(path.replace(`${root}/`, ''))
|
|
195
|
+
else {
|
|
196
|
+
mkdirSync(dirname(path), { recursive: true })
|
|
197
|
+
writeFileSync(path, content, 'utf8')
|
|
198
|
+
changed.push(path.replace(`${root}/`, ''))
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
// 双向一致性:货架每个 agent ⟺ **恰好一个** bundle 目录
|
|
202
|
+
const dirs = listBundleDirs(pluginsDir)
|
|
203
|
+
for (const id of ids) if (!dirs.includes(`${BUNDLE_PREFIX}${id}`)) errors.push(`货架有 agent \`${id}\`,但盘上没有 plugins/${BUNDLE_PREFIX}${id}/`)
|
|
204
|
+
for (const d of dirs) {
|
|
205
|
+
const id = d.slice(BUNDLE_PREFIX.length)
|
|
206
|
+
if (!ids.includes(id)) errors.push(`盘上有 plugins/${d}/,但货架里没有 agent \`${id}\``)
|
|
207
|
+
}
|
|
208
|
+
// 目录声明自洽(与门禁 `check-agent-catalog.mjs` 同一条判据;缺注册表时只报告不拦)
|
|
209
|
+
try {
|
|
210
|
+
const ctx = buildContext(root, (m) => errors.push(m))
|
|
211
|
+
const v = validateCatalog(doc, ctx)
|
|
212
|
+
errors.push(...v.errors)
|
|
213
|
+
errors.push(...validateHostAssets(ctx).errors)
|
|
214
|
+
} catch (e) {
|
|
215
|
+
errors.push(`目录声明自检失败:${String(e && e.message).split('\n')[0]}`)
|
|
216
|
+
}
|
|
217
|
+
return { ids, changed, errors }
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* **包内声明 ⟺ 货架投影** 的逐字比对(安装器与门禁用**同一份**判据)。
|
|
222
|
+
* @param {string[]} ids 要比对的 agent id(缺省 = 全部)
|
|
223
|
+
* @returns {string[]} 差异清单(空 = 一致)
|
|
224
|
+
*/
|
|
225
|
+
export function compareBundlesToCatalog(ids = null, { root = REPO } = {}) {
|
|
226
|
+
const doc = loadCatalogDoc(root)
|
|
227
|
+
const out = []
|
|
228
|
+
if (!doc) return [`读不到货架声明:${CATALOG_REL}`]
|
|
229
|
+
const want = ids && ids.length ? ids.map(String) : listCatalogAgentIds(doc)
|
|
230
|
+
for (const id of want) {
|
|
231
|
+
const agent = findAgent(doc, id)
|
|
232
|
+
if (!agent) { out.push(`货架里没有 agent \`${id}\``); continue }
|
|
233
|
+
const p = join(root, 'plugins', `${BUNDLE_PREFIX}${id}`, 'package.json')
|
|
234
|
+
if (!existsSync(p)) { out.push(`缺包内声明:plugins/${BUNDLE_PREFIX}${id}/package.json`); continue }
|
|
235
|
+
let m = null
|
|
236
|
+
try { m = JSON.parse(readFileSync(p, 'utf8')) } catch { out.push(`plugins/${BUNDLE_PREFIX}${id}/package.json 不是合法 JSON`); continue }
|
|
237
|
+
const got = JSON.stringify(m.argent && m.argent.agent)
|
|
238
|
+
const exp = JSON.stringify(declarationFor(agent))
|
|
239
|
+
if (got !== exp) out.push(`plugins/${BUNDLE_PREFIX}${id}/package.json 的包内声明与货架声明**逐字不一致**:`
|
|
240
|
+
+ `\n 包内:${got}\n 货架:${exp}`)
|
|
241
|
+
const wantName = `@whyshu/${BUNDLE_PREFIX}${id}`
|
|
242
|
+
if (String(m.name || '') !== wantName) out.push(`plugins/${BUNDLE_PREFIX}${id}/package.json#name = ${JSON.stringify(m.name)}(应为 ${JSON.stringify(wantName)})`)
|
|
243
|
+
}
|
|
244
|
+
return out
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// ── CLI ───────────────────────────────────────────────────────────────
|
|
248
|
+
if (process.argv[1] && process.argv[1].endsWith('gen-agent-bundles.mjs')) {
|
|
249
|
+
const check = process.argv.includes('--check')
|
|
250
|
+
const { ids, changed, errors } = generate({ check })
|
|
251
|
+
const cross = compareBundlesToCatalog(ids)
|
|
252
|
+
if (!ids.length) {
|
|
253
|
+
console.error('✗ 货架里一个智能体都没有(agents/catalog.json#agents)')
|
|
254
|
+
process.exit(1)
|
|
255
|
+
}
|
|
256
|
+
if (check) {
|
|
257
|
+
const bad = [...new Set([...errors, ...cross])]
|
|
258
|
+
if (changed.length || bad.length) {
|
|
259
|
+
if (changed.length) {
|
|
260
|
+
console.error(`✗ bundle 产物与货架声明不一致(${changed.length} 处)—— 跑 node scripts/gen-agent-bundles.mjs 刷新:`)
|
|
261
|
+
for (const c of changed) console.error(` · ${c}`)
|
|
262
|
+
}
|
|
263
|
+
for (const e of bad) console.error(`✗ ${e}`)
|
|
264
|
+
process.exit(1)
|
|
265
|
+
}
|
|
266
|
+
console.log(`✅ 智能体 bundle 与货架声明一致(${ids.length} 个:${ids.join('、')};每个 agent ⟺ 恰好一个 bundle,包内声明逐字一致)`)
|
|
267
|
+
process.exit(0)
|
|
268
|
+
}
|
|
269
|
+
if (errors.length) {
|
|
270
|
+
for (const e of errors) console.error(`✗ ${e}`)
|
|
271
|
+
console.error('⛔ 货架声明有错 ⇒ 已生成产物但不代表可用(先修声明再重跑)')
|
|
272
|
+
process.exit(1)
|
|
273
|
+
}
|
|
274
|
+
console.log(`✅ 已生成 ${ids.length} 个智能体 bundle → plugins/${BUNDLE_PREFIX}<id>/`)
|
|
275
|
+
for (const c of changed) console.log(` · ${c}`)
|
|
276
|
+
}
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* 角色 preset 生成器:目录式(0.1.5 源) → **行式**(0.1.7 bundle patch)。
|
|
4
|
+
*
|
|
5
|
+
* 为什么需要它:0.1.7 起 preset **不再扫目录**,必须变成 profile 组合里的一行
|
|
6
|
+
* `@deepseek-ai/dsh-agent-preset`(`config.plugins` = 原来的行列表)。我们 13 个角色的
|
|
7
|
+
* 作者格式(`presets/<id>/agent.cordis.yml` + `preset.yml`)保持不变(客户机 0.1.5 还在用),
|
|
8
|
+
* 行式产物由本脚本**从作者格式生成**,保证两边不会各写一份而漂移。
|
|
9
|
+
*
|
|
10
|
+
* 产物(全部落在 `plugins/argent-presets/`,作为一个 bundle 供 0.1.7 机器挂载):
|
|
11
|
+
* presets/<id>.patch.yml —— 一个 insert 行(官方标准:每个 preset 一个 patch 文件)
|
|
12
|
+
* package.json —— dsh.bundle.patch = 上述文件数组
|
|
13
|
+
* presets.json —— id → {name, description, order}(门禁与探针读它取角色清单)
|
|
14
|
+
*
|
|
15
|
+
* 用法:
|
|
16
|
+
* node scripts/gen-preset-rows.mjs # 生成/刷新
|
|
17
|
+
* node scripts/gen-preset-rows.mjs --check # 只校验是否与源一致(CI/门禁;不一致 exit 1)
|
|
18
|
+
*/
|
|
19
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync } from 'node:fs'
|
|
20
|
+
import { dirname, join } from 'node:path'
|
|
21
|
+
import { fileURLToPath } from 'node:url'
|
|
22
|
+
import { applyRowCompat } from './lib/preset-compat.mjs'
|
|
23
|
+
|
|
24
|
+
const HERE = dirname(fileURLToPath(import.meta.url))
|
|
25
|
+
export const REPO = join(HERE, '..')
|
|
26
|
+
|
|
27
|
+
/** 源:作者格式目录(presets/<id>/{agent.cordis.yml,preset.yml})。 */
|
|
28
|
+
export const SRC_DIR = join(REPO, 'presets')
|
|
29
|
+
/** 产物:bundle 插件。 */
|
|
30
|
+
export const OUT_DIR = join(REPO, 'plugins', 'argent-presets')
|
|
31
|
+
/** 子包 indent:`plugins:` 下的行要缩进到 10 空格(与官方 standard.patch.yml 一致)。 */
|
|
32
|
+
const INDENT = ' '.repeat(10)
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* 极简 front-matter 解析(`preset.yml`)。
|
|
36
|
+
*
|
|
37
|
+
* A 批(2026-10-10)起除 `name`/`description` 外还承载**归属与内外划分**:
|
|
38
|
+
* · `capability` —— 该角色属于哪个能力包("装哪个智能体就只落哪些角色"的判据之一);
|
|
39
|
+
* · `visibility` —— `customer`(默认;可落客户机)/ `internal`(我方内部角色,**默认不落**,
|
|
40
|
+
* 需安装器显式 `--internal-roles`);
|
|
41
|
+
* · `always` —— 恒装(`argent-general`);
|
|
42
|
+
* · `rolesFor` —— 显式点名"这个角色归哪些智能体"(列表;无 flow 的能力如 hr 用它)。
|
|
43
|
+
* 生成器把它们写进 `plugins/argent-presets/presets.json`(门禁/安装器读它,⛔ 不再另立名单)。
|
|
44
|
+
* 支持三种写法:标量 `k: v`、内联列表 `k: [a, b]`、块列表(`k:` 后跟 ` - a`)。
|
|
45
|
+
*/
|
|
46
|
+
export function readPresetMeta(dir) {
|
|
47
|
+
const p = join(dir, 'preset.yml')
|
|
48
|
+
const out = {}
|
|
49
|
+
if (!existsSync(p)) return out
|
|
50
|
+
const lines = readFileSync(p, 'utf8').split('\n')
|
|
51
|
+
for (let i = 0; i < lines.length; i++) {
|
|
52
|
+
const m = /^([A-Za-z_][\w-]*):\s*(.*)$/.exec(lines[i])
|
|
53
|
+
if (!m) continue
|
|
54
|
+
const key = m[1]
|
|
55
|
+
const raw = m[2].trim()
|
|
56
|
+
if (raw === '') {
|
|
57
|
+
const items = []
|
|
58
|
+
for (let j = i + 1; j < lines.length; j++) {
|
|
59
|
+
const im = /^\s+-\s*(.+?)\s*$/.exec(lines[j])
|
|
60
|
+
if (!im) break
|
|
61
|
+
items.push(unquote(im[1]))
|
|
62
|
+
i = j
|
|
63
|
+
}
|
|
64
|
+
out[key] = items.length ? items : ''
|
|
65
|
+
continue
|
|
66
|
+
}
|
|
67
|
+
if (/^\[.*\]$/.test(raw)) {
|
|
68
|
+
out[key] = raw.slice(1, -1).split(',').map((x) => unquote(x.trim())).filter(Boolean)
|
|
69
|
+
continue
|
|
70
|
+
}
|
|
71
|
+
out[key] = unquote(raw)
|
|
72
|
+
}
|
|
73
|
+
return out
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function unquote(s) {
|
|
77
|
+
return String(s).replace(/^['"]|['"]$/g, '')
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* `presets.json` 条目的**归一形状**(它是判据面:门禁与安装器都按这些键读 ⇒ 形状必须稳定)。
|
|
82
|
+
* `capability` 与 `rolesFor` 缺省**不写键**(缺席 = 无该归属,避免"空串 ≠ 无"这类第二口径)。
|
|
83
|
+
*/
|
|
84
|
+
export function normalizePresetMeta(meta) {
|
|
85
|
+
const out = { name: meta.name || '', description: meta.description || '' }
|
|
86
|
+
if (meta.capability) out.capability = String(meta.capability)
|
|
87
|
+
out.visibility = meta.visibility === 'internal' ? 'internal' : 'customer'
|
|
88
|
+
out.always = meta.always === true || meta.always === 'true'
|
|
89
|
+
const rf = Array.isArray(meta.rolesFor) ? meta.rolesFor.map(String).filter(Boolean) : []
|
|
90
|
+
if (rf.length) out.rolesFor = rf
|
|
91
|
+
return out
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** 列出作者格式里的所有角色(目录名 + 必需文件齐备)。 */
|
|
95
|
+
export function listSourcePresets(srcDir = SRC_DIR) {
|
|
96
|
+
if (!existsSync(srcDir)) return []
|
|
97
|
+
return readdirSync(srcDir)
|
|
98
|
+
.filter((d) => {
|
|
99
|
+
try { return statSync(join(srcDir, d)).isDirectory() && existsSync(join(srcDir, d, 'agent.cordis.yml')) } catch { return false }
|
|
100
|
+
})
|
|
101
|
+
.sort()
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** 把一份 agent.cordis.yml 嵌进 `plugins:` 之下(**纯缩进**,保留注释与 !!js、不做 YAML 重排)。 */
|
|
105
|
+
export function indentComposition(text) {
|
|
106
|
+
return text.replace(/\n+$/, '\n').split('\n').map((l) => (l.trim() === '' ? '' : INDENT + l)).join('\n')
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** 生成单个角色的 patch 文件内容(含跨版本行改写;改写记录写进文件头便于审计)。 */
|
|
110
|
+
export function renderPatch({ id, meta, composition, order }) {
|
|
111
|
+
const compat = applyRowCompat(composition)
|
|
112
|
+
const name = (meta.name || id).replace(/'/g, "''")
|
|
113
|
+
const desc = (meta.description || '').replace(/'/g, "''")
|
|
114
|
+
const head = [
|
|
115
|
+
`# Agent preset ${id} — 由 scripts/gen-preset-rows.mjs 从 presets/${id}/ 生成,**不要手改**。`,
|
|
116
|
+
`# 改作者格式(presets/${id}/agent.cordis.yml 或 preset.yml)后重跑生成器。`,
|
|
117
|
+
`# 0.1.7 起 preset 是"组合里的一行插件"(不再扫目录):name 固定为 @deepseek-ai/dsh-agent-preset。`,
|
|
118
|
+
...(compat.applied.length
|
|
119
|
+
? [`# 行级兼容改写(lib/preset-compat.mjs):${compat.applied.join(';')}`]
|
|
120
|
+
: []),
|
|
121
|
+
'- insert:',
|
|
122
|
+
` - id: preset-${id}`,
|
|
123
|
+
` name: '@deepseek-ai/dsh-agent-preset'`,
|
|
124
|
+
` config:`,
|
|
125
|
+
` id: ${id}`,
|
|
126
|
+
` name: '${name}'`,
|
|
127
|
+
]
|
|
128
|
+
if (desc) head.push(` description: '${desc}'`)
|
|
129
|
+
head.push(` order: ${order}`)
|
|
130
|
+
head.push(` plugins:`)
|
|
131
|
+
return `${head.join('\n')}\n${indentComposition(compat.text)}`
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* 生成 package.json 内容。
|
|
136
|
+
*
|
|
137
|
+
* ⚠️ 本文件**拥有** `plugins/argent-presets/package.json`(`--check` 逐字节比对 ⇒ 手改产物必红)。
|
|
138
|
+
* 所以 npm 元数据与 `peerDependencies` 必须写在这里 —— 2026-10-12 W1(插件声明补全):
|
|
139
|
+
* · `files`/`repository`/`engines`/`publishConfig` = npm 发布就绪(⛔ 本批不发布;scope 落地属 W9);
|
|
140
|
+
* · `peerDependencies` 的来源与**宿主兼容区间**推导见
|
|
141
|
+
* `docs/Argent-插件化评估与实施计划.md` §4.1.1(下界 = 安装器已验证版本基线 ∪ 已晋级快照的最低版本;
|
|
142
|
+
* 上界必须写 `<0.3` 而不是 `<0.3.0`,否则 `includePrerelease` 下会把 `0.3.0-rc.1` 也算满足)。
|
|
143
|
+
* 防漂移门禁 = `node scripts/tests/plugin-peer-coverage.test.mjs`(范围写窄/写宽/漏件都会当场判红)。
|
|
144
|
+
*/
|
|
145
|
+
export function renderPackageJson(ids) {
|
|
146
|
+
return JSON.stringify({
|
|
147
|
+
name: '@whyshu/argent-presets',
|
|
148
|
+
version: '0.1.0',
|
|
149
|
+
description: 'Argent on DSH — 角色 preset 行式声明(dsh 0.1.7+;bundle patch 形态)',
|
|
150
|
+
type: 'module',
|
|
151
|
+
main: 'src/index.js',
|
|
152
|
+
exports: { '.': './src/index.js', './package.json': './package.json' },
|
|
153
|
+
license: 'MIT',
|
|
154
|
+
repository: {
|
|
155
|
+
type: 'git',
|
|
156
|
+
url: 'git+https://whyshu.com/git/argent-dsh.git',
|
|
157
|
+
directory: 'plugins/argent-presets',
|
|
158
|
+
},
|
|
159
|
+
engines: { node: '>=24.2.0' },
|
|
160
|
+
files: ['src/', 'presets/', 'presets.json'],
|
|
161
|
+
publishConfig: { access: 'public' },
|
|
162
|
+
peerDependencies: {
|
|
163
|
+
'@deepseek-ai/cordis': '~4.0.4',
|
|
164
|
+
'@deepseek-ai/dsh-agent-preset': '>=0.1.0-rc.6 <0.3',
|
|
165
|
+
},
|
|
166
|
+
dsh: {
|
|
167
|
+
plugin: { displayName: 'Argent 角色预设(0.1.7 行式)' },
|
|
168
|
+
bundle: { patch: ids.map((id) => `./presets/${id}.patch.yml`) },
|
|
169
|
+
},
|
|
170
|
+
}, null, 2) + '\n'
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/** 生成插件入口(bundle 的 patch 就是全部内容,入口只做自述,避免"空插件"告警)。 */
|
|
174
|
+
export function renderIndex(ids) {
|
|
175
|
+
return `/**
|
|
176
|
+
* argent-presets —— 角色 preset 的**行式**声明(dsh 0.1.7+)。
|
|
177
|
+
*
|
|
178
|
+
* 本插件的实质内容是 \`presets/*.patch.yml\`(由 package.json 的 \`dsh.bundle.patch\` 数组加载):
|
|
179
|
+
* 每个文件往组合里 insert 一行 \`@deepseek-ai/dsh-agent-preset\`,其 \`config.plugins\` 即该角色的
|
|
180
|
+
* 组合(原 \`presets/<id>/agent.cordis.yml\`)。源码入口本身不注册任何服务/工具。
|
|
181
|
+
*
|
|
182
|
+
* 生成器:scripts/gen-preset-rows.mjs(作者格式 → 本目录,禁止手改产物)。
|
|
183
|
+
*/
|
|
184
|
+
export const name = 'argent-presets'
|
|
185
|
+
export const inject = []
|
|
186
|
+
|
|
187
|
+
/** 角色清单(诊断用;与 presets.json 同源)。 */
|
|
188
|
+
export const presetIds = ${JSON.stringify(ids, null, 2)}
|
|
189
|
+
|
|
190
|
+
export function apply() {
|
|
191
|
+
// patch 由 Loader 在装配期应用;这里无需运行时动作。
|
|
192
|
+
}
|
|
193
|
+
`
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/** 生成/校验。返回 { ids, changed: string[] }。 */
|
|
197
|
+
export function generate({ check = false } = {}) {
|
|
198
|
+
const ids = listSourcePresets()
|
|
199
|
+
const changed = []
|
|
200
|
+
const files = new Map()
|
|
201
|
+
const manifest = {}
|
|
202
|
+
ids.forEach((id, i) => {
|
|
203
|
+
const dir = join(SRC_DIR, id)
|
|
204
|
+
const meta = readPresetMeta(dir)
|
|
205
|
+
const composition = readFileSync(join(dir, 'agent.cordis.yml'), 'utf8')
|
|
206
|
+
files.set(join(OUT_DIR, 'presets', `${id}.patch.yml`), renderPatch({ id, meta, composition, order: i + 1 }))
|
|
207
|
+
manifest[id] = { ...normalizePresetMeta({ ...meta, name: meta.name || id }), order: i + 1 }
|
|
208
|
+
})
|
|
209
|
+
files.set(join(OUT_DIR, 'package.json'), renderPackageJson(ids))
|
|
210
|
+
files.set(join(OUT_DIR, 'src', 'index.js'), renderIndex(ids))
|
|
211
|
+
files.set(join(OUT_DIR, 'presets.json'), JSON.stringify(manifest, null, 2) + '\n')
|
|
212
|
+
|
|
213
|
+
// 清理已不存在的角色的产物
|
|
214
|
+
const staleDir = join(OUT_DIR, 'presets')
|
|
215
|
+
if (existsSync(staleDir)) {
|
|
216
|
+
for (const f of readdirSync(staleDir)) {
|
|
217
|
+
if (!f.endsWith('.patch.yml')) continue
|
|
218
|
+
const id = f.replace(/\.patch\.yml$/, '')
|
|
219
|
+
if (!ids.includes(id)) {
|
|
220
|
+
const p = join(staleDir, f)
|
|
221
|
+
if (check) changed.push(`(应删除)${p.replace(REPO + '/', '')}`)
|
|
222
|
+
else { rmSync(p); changed.push(`删除 ${p.replace(REPO + '/', '')}`) }
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
for (const [path, content] of files) {
|
|
228
|
+
const cur = existsSync(path) ? readFileSync(path, 'utf8') : null
|
|
229
|
+
if (cur === content) continue
|
|
230
|
+
if (check) changed.push(path.replace(REPO + '/', ''))
|
|
231
|
+
else {
|
|
232
|
+
mkdirSync(dirname(path), { recursive: true })
|
|
233
|
+
writeFileSync(path, content, 'utf8')
|
|
234
|
+
changed.push(path.replace(REPO + '/', ''))
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return { ids, changed }
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// ── CLI ───────────────────────────────────────────────────────────────
|
|
241
|
+
if (process.argv[1] && process.argv[1].endsWith('gen-preset-rows.mjs')) {
|
|
242
|
+
const check = process.argv.includes('--check')
|
|
243
|
+
const { ids, changed } = generate({ check })
|
|
244
|
+
if (!ids.length) {
|
|
245
|
+
console.error('✗ 没找到任何作者格式 preset(presets/<id>/agent.cordis.yml)')
|
|
246
|
+
process.exit(1)
|
|
247
|
+
}
|
|
248
|
+
if (check) {
|
|
249
|
+
if (changed.length) {
|
|
250
|
+
console.error(`✗ 行式产物与作者格式不一致(${changed.length} 处)—— 跑 node scripts/gen-preset-rows.mjs 刷新:`)
|
|
251
|
+
for (const c of changed) console.error(` · ${c}`)
|
|
252
|
+
process.exit(1)
|
|
253
|
+
}
|
|
254
|
+
console.log(`✅ 行式产物与作者格式一致(${ids.length} 个角色)`)
|
|
255
|
+
process.exit(0)
|
|
256
|
+
}
|
|
257
|
+
console.log(`✅ 已生成 ${ids.length} 个角色的行式声明 → plugins/argent-presets/`)
|
|
258
|
+
for (const c of changed) console.log(` · ${c}`)
|
|
259
|
+
}
|