@whyshu/argent-engine 0.0.0-stage → 0.6.1

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.
Files changed (340) hide show
  1. package/MANIFEST.json +341 -0
  2. package/engine/VERSION +1 -0
  3. package/engine/agents/catalog.json +454 -0
  4. package/engine/configs/_aliases.proposed.json +651 -0
  5. package/engine/configs/_migration-plan.proposed.json +899 -0
  6. package/engine/configs/account.json +272 -0
  7. package/engine/configs/advanced.json +205 -0
  8. package/engine/configs/host.json +149 -0
  9. package/engine/configs/hr.json +27 -0
  10. package/engine/configs/notify.json +264 -0
  11. package/engine/core/cli/argent.mjs +277 -0
  12. package/engine/core/contracts/argent.contracts.json +1065 -0
  13. package/engine/core/contracts/verbs.schema.json +2539 -0
  14. package/engine/core/lib/argent-datadir.mjs +223 -0
  15. package/engine/core/lib/audit.mjs +187 -0
  16. package/engine/core/lib/claim.mjs +258 -0
  17. package/engine/core/lib/config-catalog.mjs +1172 -0
  18. package/engine/core/lib/doctor-customer.mjs +577 -0
  19. package/engine/core/lib/flow-list.mjs +138 -0
  20. package/engine/core/lib/flow-registry.mjs +48 -0
  21. package/engine/core/lib/init.mjs +247 -0
  22. package/engine/core/lib/ledger.mjs +124 -0
  23. package/engine/core/lib/license-activate.mjs +813 -0
  24. package/engine/core/lib/license-device.mjs +314 -0
  25. package/engine/core/lib/license-file.mjs +349 -0
  26. package/engine/core/lib/license-guard.mjs +123 -0
  27. package/engine/core/lib/license-ops.mjs +1645 -0
  28. package/engine/core/lib/license-verdict.mjs +133 -0
  29. package/engine/core/lib/license.mjs +577 -0
  30. package/engine/core/lib/notify/dedup.mjs +101 -0
  31. package/engine/core/lib/notify/feishu.mjs +38 -0
  32. package/engine/core/lib/notify/index.mjs +95 -0
  33. package/engine/core/lib/notify/verb.mjs +327 -0
  34. package/engine/core/lib/notify/webhook.mjs +135 -0
  35. package/engine/core/lib/notify/wecom.mjs +36 -0
  36. package/engine/core/lib/python.mjs +145 -0
  37. package/engine/core/lib/sop.mjs +116 -0
  38. package/engine/core/lib/versions.mjs +205 -0
  39. package/engine/core/mcp/client.mjs +67 -0
  40. package/engine/core/mcp/http.mjs +138 -0
  41. package/engine/core/mcp/server.mjs +702 -0
  42. package/engine/scripts/_engine_rules_probe.py +15 -0
  43. package/engine/scripts/analyze-full-day.py +568 -0
  44. package/engine/scripts/archive/feishu-bridge.js +246 -0
  45. package/engine/scripts/argent-agents.mjs +527 -0
  46. package/engine/scripts/argent-capabilities.mjs +776 -0
  47. package/engine/scripts/argent-catalog.mjs +186 -0
  48. package/engine/scripts/argent-datadir.py +62 -0
  49. package/engine/scripts/argent-doctor.mjs +624 -0
  50. package/engine/scripts/argent-env-write.mjs +302 -0
  51. package/engine/scripts/argent-schedule.mjs +620 -0
  52. package/engine/scripts/argent-setup-check.mjs +369 -0
  53. package/engine/scripts/argent-upgrade.mjs +1046 -0
  54. package/engine/scripts/base-bootstrap.sh +576 -0
  55. package/engine/scripts/billing-mode-daily.sh +13 -0
  56. package/engine/scripts/build-engine-package.mjs +126 -0
  57. package/engine/scripts/capability-packs.lock.json +484 -0
  58. package/engine/scripts/capability_pack.py +1242 -0
  59. package/engine/scripts/check-1.0-criteria.mjs +355 -0
  60. package/engine/scripts/check-agent-catalog.mjs +141 -0
  61. package/engine/scripts/check-billing-mode.sh +378 -0
  62. package/engine/scripts/check-child-sessions.mjs +83 -0
  63. package/engine/scripts/check-config-catalog.mjs +677 -0
  64. package/engine/scripts/check-docs-drift.mjs +522 -0
  65. package/engine/scripts/check-dsh-web-expose.sh +98 -0
  66. package/engine/scripts/check-judgment-drift.mjs +403 -0
  67. package/engine/scripts/check-license.mjs +199 -0
  68. package/engine/scripts/check-model-auth.py +443 -0
  69. package/engine/scripts/check-pack-closure.mjs +661 -0
  70. package/engine/scripts/check-portable-symbols.mjs +116 -0
  71. package/engine/scripts/check-preset-landing.mjs +124 -0
  72. package/engine/scripts/check-production-home.mjs +602 -0
  73. package/engine/scripts/check-role-mapping.mjs +461 -0
  74. package/engine/scripts/check-sample-redaction.mjs +320 -0
  75. package/engine/scripts/check-skill-classification.mjs +188 -0
  76. package/engine/scripts/check-sop-consistency.mjs +431 -0
  77. package/engine/scripts/check-test-env-safety.mjs +627 -0
  78. package/engine/scripts/check-version-consistency.mjs +452 -0
  79. package/engine/scripts/ci-run.sh +558 -0
  80. package/engine/scripts/collect-evidence.mjs +42 -0
  81. package/engine/scripts/config-explain.mjs +278 -0
  82. package/engine/scripts/configure-provider.rb +29 -0
  83. package/engine/scripts/customer-config-migrate.mjs +179 -0
  84. package/engine/scripts/customer-preflight.py +892 -0
  85. package/engine/scripts/customer-readiness.sh +135 -0
  86. package/engine/scripts/daily-report-inbox.py +242 -0
  87. package/engine/scripts/daily-report-reconcile.mjs +312 -0
  88. package/engine/scripts/daily-report.mjs +1310 -0
  89. package/engine/scripts/daily-report.sh +47 -0
  90. package/engine/scripts/data/lip-product-dict.json +306 -0
  91. package/engine/scripts/deliver-customer.mjs +932 -0
  92. package/engine/scripts/delivery-faces.txt +31 -0
  93. package/engine/scripts/desktop-trial.sh +146 -0
  94. package/engine/scripts/dev-window.sh +261 -0
  95. package/engine/scripts/drill-clean-machine.sh +315 -0
  96. package/engine/scripts/dsh-api-client.mjs +215 -0
  97. package/engine/scripts/dsh-backup-scope.sh +83 -0
  98. package/engine/scripts/dsh-offline-pack.mjs +77 -0
  99. package/engine/scripts/dsh-overlay-pin.sh +87 -0
  100. package/engine/scripts/dsh-plane.mjs +153 -0
  101. package/engine/scripts/dsh-portforward.py +223 -0
  102. package/engine/scripts/dsh-preflight.mjs +179 -0
  103. package/engine/scripts/dsh-release-watch-daily.sh +19 -0
  104. package/engine/scripts/dsh-release-watch.mjs +458 -0
  105. package/engine/scripts/dsh-remote-check.sh +99 -0
  106. package/engine/scripts/dsh-restart.sh +179 -0
  107. package/engine/scripts/dsh-restore.sh +111 -0
  108. package/engine/scripts/dsh-scope-rewire.mjs +803 -0
  109. package/engine/scripts/dsh-snapshot.mjs +116 -0
  110. package/engine/scripts/dsh-upgrade-readiness.mjs +165 -0
  111. package/engine/scripts/dsh-upgrade.mjs +612 -0
  112. package/engine/scripts/dsh-url.sh +86 -0
  113. package/engine/scripts/dsh-web-launch.mjs +155 -0
  114. package/engine/scripts/ensure-store-windows.py +509 -0
  115. package/engine/scripts/entitlements.py +458 -0
  116. package/engine/scripts/env_probe.py +411 -0
  117. package/engine/scripts/feishu-card.mjs +252 -0
  118. package/engine/scripts/final-check.mjs +43 -0
  119. package/engine/scripts/fix-skill-frontmatter.py +209 -0
  120. package/engine/scripts/flow-auto-retry.py +454 -0
  121. package/engine/scripts/flow-requirements.json +735 -0
  122. package/engine/scripts/flow-scaffold.py +275 -0
  123. package/engine/scripts/flow-timers-plist.sh +87 -0
  124. package/engine/scripts/flow-timers.sh +184 -0
  125. package/engine/scripts/flow-trigger-wake.mjs +284 -0
  126. package/engine/scripts/flow-trigger.sh +571 -0
  127. package/engine/scripts/flow_billing.py +354 -0
  128. package/engine/scripts/flow_capability_stats.py +314 -0
  129. package/engine/scripts/flow_case.py +194 -0
  130. package/engine/scripts/flow_claim.py +497 -0
  131. package/engine/scripts/flow_config.py +1025 -0
  132. package/engine/scripts/flow_failure.py +588 -0
  133. package/engine/scripts/flow_learn.py +105 -0
  134. package/engine/scripts/flow_ledger.py +235 -0
  135. package/engine/scripts/flow_policy.py +238 -0
  136. package/engine/scripts/flow_preflight.py +339 -0
  137. package/engine/scripts/flow_registry.py +341 -0
  138. package/engine/scripts/flow_retry.py +304 -0
  139. package/engine/scripts/flow_return_to_ops.py +191 -0
  140. package/engine/scripts/flow_source.py +315 -0
  141. package/engine/scripts/flow_sources/__init__.py +53 -0
  142. package/engine/scripts/flow_sources/cases_json.py +106 -0
  143. package/engine/scripts/flow_sources/common.py +428 -0
  144. package/engine/scripts/flow_sources/feishu_base.py +273 -0
  145. package/engine/scripts/flow_stale.py +185 -0
  146. package/engine/scripts/flow_status_reconcile.py +344 -0
  147. package/engine/scripts/flow_triage.py +849 -0
  148. package/engine/scripts/flow_write_verify.py +496 -0
  149. package/engine/scripts/fulfillment.js +586 -0
  150. package/engine/scripts/gen-agent-bundles.mjs +276 -0
  151. package/engine/scripts/gen-preset-rows.mjs +259 -0
  152. package/engine/scripts/init-ml.sh +2278 -0
  153. package/engine/scripts/install-internal-role.sh +190 -0
  154. package/engine/scripts/install-license.mjs +641 -0
  155. package/engine/scripts/install-one-shot.mjs +665 -0
  156. package/engine/scripts/integration_contract.py +220 -0
  157. package/engine/scripts/integrations/wenyao/adapter.py +98 -0
  158. package/engine/scripts/integrations/xzh/adapter.py +75 -0
  159. package/engine/scripts/invoice-mapping.example.json +40 -0
  160. package/engine/scripts/invoice-table.sh +195 -0
  161. package/engine/scripts/invoice_carrier_notice.py +279 -0
  162. package/engine/scripts/invoice_fail_closeout.py +297 -0
  163. package/engine/scripts/invoice_lip_runner.py +1508 -0
  164. package/engine/scripts/invoice_lip_runner.py.bak-20260922-1710-freready +1090 -0
  165. package/engine/scripts/invoice_ready_audit.py +191 -0
  166. package/engine/scripts/invoice_runner.py +675 -0
  167. package/engine/scripts/invoice_stageb.py +516 -0
  168. package/engine/scripts/launchd/com.whyshu.argent-bridge.plist.example +42 -0
  169. package/engine/scripts/launchd/com.whyshu.fulfillment-poll.plist.example +29 -0
  170. package/engine/scripts/lease.py +377 -0
  171. package/engine/scripts/lib/agent-install.mjs +649 -0
  172. package/engine/scripts/lib/argent-datadir.mjs +16 -0
  173. package/engine/scripts/lib/argent-datadir.sh +18 -0
  174. package/engine/scripts/lib/argent_datadir.py +285 -0
  175. package/engine/scripts/lib/argent_filelock.py +507 -0
  176. package/engine/scripts/lib/bootcheck-wiring.mjs +510 -0
  177. package/engine/scripts/lib/cdp_ports.py +197 -0
  178. package/engine/scripts/lib/customer-env.mjs +102 -0
  179. package/engine/scripts/lib/daily-report-core.mjs +517 -0
  180. package/engine/scripts/lib/dep-declaration.mjs +81 -0
  181. package/engine/scripts/lib/deps-migrate.mjs +310 -0
  182. package/engine/scripts/lib/dsh-host-resolve.mjs +109 -0
  183. package/engine/scripts/lib/dsh-scope.mjs +500 -0
  184. package/engine/scripts/lib/dsh-snapshot-path.mjs +35 -0
  185. package/engine/scripts/lib/dsh-versions.mjs +96 -0
  186. package/engine/scripts/lib/dsh-web-probe.mjs +214 -0
  187. package/engine/scripts/lib/is-direct-run.mjs +61 -0
  188. package/engine/scripts/lib/patch-compose.mjs +241 -0
  189. package/engine/scripts/lib/patch-target.mjs +35 -0
  190. package/engine/scripts/lib/plugin-lifecycle.mjs +128 -0
  191. package/engine/scripts/lib/plugin-packages.mjs +332 -0
  192. package/engine/scripts/lib/preset-compat.mjs +127 -0
  193. package/engine/scripts/lib/preset-install.mjs +575 -0
  194. package/engine/scripts/lib/preset-mechanism.mjs +56 -0
  195. package/engine/scripts/lib/preset-sync.mjs +59 -0
  196. package/engine/scripts/lib/profile-retire.mjs +97 -0
  197. package/engine/scripts/lib/python-runtime.mjs +190 -0
  198. package/engine/scripts/lib/registry.mjs +72 -0
  199. package/engine/scripts/lib/repo-root.sh +56 -0
  200. package/engine/scripts/lib/schedule-mechanism.mjs +659 -0
  201. package/engine/scripts/lib/schedule-probe.mjs +835 -0
  202. package/engine/scripts/lib/scope-pointer.mjs +164 -0
  203. package/engine/scripts/lib/settings-panels.mjs +816 -0
  204. package/engine/scripts/lib/stdio_utf8.py +86 -0
  205. package/engine/scripts/lib/wake-auth.mjs +392 -0
  206. package/engine/scripts/lib/webdriver_ipc.py +264 -0
  207. package/engine/scripts/lib/zstd-frames.mjs +104 -0
  208. package/engine/scripts/license-e2e-drill.mjs +426 -0
  209. package/engine/scripts/license-gate.mjs +245 -0
  210. package/engine/scripts/lip_backlog.py +171 -0
  211. package/engine/scripts/lip_table.py +185 -0
  212. package/engine/scripts/local-usage.mjs +214 -0
  213. package/engine/scripts/migrate-providers.mjs +127 -0
  214. package/engine/scripts/migrate-skills.sh +65 -0
  215. package/engine/scripts/ml-oauth-setup.mjs +550 -0
  216. package/engine/scripts/ml-store-ids.json +26 -0
  217. package/engine/scripts/ml_artifact_attribution.py +333 -0
  218. package/engine/scripts/ml_capacity_probe.py +1158 -0
  219. package/engine/scripts/ml_hub_status.py +1556 -0
  220. package/engine/scripts/ml_schema_check.py +115 -0
  221. package/engine/scripts/ml_store_ids.py +139 -0
  222. package/engine/scripts/npm-publish-argent.mjs +499 -0
  223. package/engine/scripts/npm-publish-argent.sh +20 -0
  224. package/engine/scripts/orchestrator.py +13811 -0
  225. package/engine/scripts/pack-plugins.mjs +140 -0
  226. package/engine/scripts/patches/dsh-llm-deepseek--transport-diagnostics.patch +297 -0
  227. package/engine/scripts/patches/dsh-session--append-message-shape.patch +15 -0
  228. package/engine/scripts/patches/dsh-session--tool-result-block-017.patch +28 -0
  229. package/engine/scripts/patches/dsh-session-format-v0-to-v1--permission-preset-origin.patch +11 -0
  230. package/engine/scripts/patches/dsh-session-format-v3-to-v4--turn-outside-replace.patch +20 -0
  231. package/engine/scripts/patches/dsh-session-persistence-jsonl--worker-bundled-migrators.patch +39 -0
  232. package/engine/scripts/patches/dsh-tools--render-return-shape.patch +50 -0
  233. package/engine/scripts/patches/verify-bundled-migrators.mjs +79 -0
  234. package/engine/scripts/patches/verify-hardening.mjs +167 -0
  235. package/engine/scripts/patches/verify-session-migration.mjs +149 -0
  236. package/engine/scripts/patches/verify-transport-diagnostics.mjs +227 -0
  237. package/engine/scripts/plan-role-rename.mjs +125 -0
  238. package/engine/scripts/plugin-bootcheck.mjs +451 -0
  239. package/engine/scripts/plugin-composition.json +15 -0
  240. package/engine/scripts/poc-mcp-host.mjs +455 -0
  241. package/engine/scripts/poll-fulfillment.sh +295 -0
  242. package/engine/scripts/poll-invoice.sh +76 -0
  243. package/engine/scripts/profile-doctor.mjs +686 -0
  244. package/engine/scripts/provider-select.sh +71 -0
  245. package/engine/scripts/provider-switch.sh +146 -0
  246. package/engine/scripts/provider-sync-target.check.mjs +64 -0
  247. package/engine/scripts/python-runtime.sh +78 -0
  248. package/engine/scripts/query_runner.py +310 -0
  249. package/engine/scripts/release-argent.sh +574 -0
  250. package/engine/scripts/repair-unresolved-tools.mjs +178 -0
  251. package/engine/scripts/retire-inventory.mjs +40 -0
  252. package/engine/scripts/run-tests.sh +257 -0
  253. package/engine/scripts/s1-audit.mjs +85 -0
  254. package/engine/scripts/self-sign-license.mjs +179 -0
  255. package/engine/scripts/session-health-scan.mjs +63 -0
  256. package/engine/scripts/session-repair-tool-result-content.mjs +181 -0
  257. package/engine/scripts/setup.sh +22 -0
  258. package/engine/scripts/skill-install.mjs +629 -0
  259. package/engine/scripts/sku_translate.py +148 -0
  260. package/engine/scripts/sync-plugins.sh +90 -0
  261. package/engine/scripts/sync-presets.sh +27 -0
  262. package/engine/scripts/sync-scripts.sh +445 -0
  263. package/engine/scripts/telemetry.py +873 -0
  264. package/engine/scripts/ui-copy-count.mjs +220 -0
  265. package/engine/scripts/usage-anchor.sh +137 -0
  266. package/engine/scripts/usage_report.py +531 -0
  267. package/engine/scripts/validate-preset-schema.mjs +208 -0
  268. package/engine/scripts/vertical-init.mjs +323 -0
  269. package/engine/scripts/vertical-lint.mjs +482 -0
  270. package/engine/scripts/wenyao-browser.sh +74 -0
  271. package/engine/scripts/wenyao-fixture-export.py +116 -0
  272. package/engine/scripts/wenyao-invoice-writeback.mjs +540 -0
  273. package/engine/scripts/wenyao-login.sh +35 -0
  274. package/engine/scripts/wenyao-template-map.json +292 -0
  275. package/engine/scripts/wenyao_attach.py +131 -0
  276. package/engine/scripts/wenyao_download_template.py +144 -0
  277. package/engine/scripts/wenyao_fill_template.py +568 -0
  278. package/engine/scripts/wenyao_login.py +145 -0
  279. package/engine/scripts/wenyao_portal.py +633 -0
  280. package/engine/scripts/wenyao_recon.py +230 -0
  281. package/engine/scripts/wenyao_run.py +503 -0
  282. package/engine/scripts/wenyao_shadow_diff.py +160 -0
  283. package/engine/scripts/wenyao_skill_contract.py +156 -0
  284. package/engine/scripts/wenyao_template_fetch.py +175 -0
  285. package/engine/scripts/win/dsh-web-autostart.ps1 +372 -0
  286. package/engine/scripts/ziniao-auth-probe.sh +268 -0
  287. package/engine/scripts/ziniao-keepalive.sh +217 -0
  288. package/engine/scripts/ziniao-post-upgrade-check.sh +121 -0
  289. package/engine/scripts/ziniao-windows.sh +154 -0
  290. package/engine/skills/README.md +86 -0
  291. package/engine/skills/argent-dev/SKILL.md +41 -0
  292. package/engine/skills/internal.json +37 -0
  293. package/engine/skills/lktop-pm/SKILL.md +35 -0
  294. package/engine/skills/lktopapp-dev/SKILL.md +34 -0
  295. package/engine/skills/ml-config-guide/SKILL.md +50 -0
  296. package/engine/skills/ml-fulfillment-sop/SKILL.md +178 -0
  297. package/engine/skills/ml-fulfillment-sop/references/andes-components.md +69 -0
  298. package/engine/skills/ml-fulfillment-sop/references/cdp-port-mapping.md +35 -0
  299. package/engine/skills/ml-fulfillment-sop/references/feishu-base-fulfillment-schema.md +136 -0
  300. package/engine/skills/ml-fulfillment-sop/references/multi-window-concurrency.md +69 -0
  301. package/engine/skills/ml-fulfillment-sop/references/pitfalls.md +77 -0
  302. package/engine/skills/ml-fulfillment-sop/references/selectors.md +243 -0
  303. package/engine/skills/ml-fulfillment-sop/scripts/fulfillment.js +586 -0
  304. package/engine/skills/ml-fulfillment-sop/scripts/poll-and-execute.sh +271 -0
  305. package/engine/skills/ml-fulfillment-sop/templates/report.md +55 -0
  306. package/engine/skills/ml-invoice/SKILL.md +506 -0
  307. package/engine/skills/ml-invoice/references/pitfalls.md +268 -0
  308. package/engine/skills/ml-invoice/references/portal-flow.md +360 -0
  309. package/engine/skills/ml-invoice/references/template-fill-contract.md +133 -0
  310. package/engine/skills/ml-invoice-xzh/SKILL.md +133 -0
  311. package/engine/skills/ml-invoice-xzh/references/pitfalls.md +230 -0
  312. package/engine/skills/ml-store-daily-report/SKILL.md +224 -0
  313. package/engine/skills/ml-store-daily-report/scripts/README.md +25 -0
  314. package/engine/skills/ml-store-daily-report/scripts/extract.js +691 -0
  315. package/engine/skills/ml-store-daily-report/scripts/generate.js +299 -0
  316. package/engine/skills/pet-dev/SKILL.md +42 -0
  317. package/engine/skills/whyshu-pm/SKILL.md +35 -0
  318. package/engine/skills/whyshu-web-dev/SKILL.md +50 -0
  319. package/engine/version.mjs +1 -0
  320. package/engine/verticals/README.md +103 -0
  321. package/engine/verticals/_engine-words.baseline.txt +237 -0
  322. package/engine/verticals/_engine-words.json +19 -0
  323. package/engine/verticals/mercadolibre/README.md +43 -0
  324. package/engine/verticals/mercadolibre/config.json +709 -0
  325. package/engine/verticals/mercadolibre/flows.json +738 -0
  326. package/engine/verticals/mercadolibre/manifest.json +538 -0
  327. package/engine/verticals/mercadolibre/migrate-machine-state.mjs +138 -0
  328. package/engine/verticals/mercadolibre/preflight.py +143 -0
  329. package/engine/verticals/mercadolibre/prompts/daily-report.failure.md +69 -0
  330. package/engine/verticals/mercadolibre/prompts/daily-report.md +47 -0
  331. package/engine/verticals/mercadolibre/prompts/daily-report.scheduled.md +79 -0
  332. package/engine/verticals/mercadolibre/prompts/full.failure.md +125 -0
  333. package/engine/verticals/mercadolibre/prompts/full.md +91 -0
  334. package/engine/verticals/mercadolibre/prompts/wenyao-invoice.failure.md +88 -0
  335. package/engine/verticals/mercadolibre/prompts/wenyao-invoice.md +64 -0
  336. package/engine/verticals/mercadolibre/prompts/xzh-invoice.failure.md +91 -0
  337. package/engine/verticals/mercadolibre/prompts/xzh-invoice.md +46 -0
  338. package/package.json +22 -4
  339. package/requirements.txt +5 -0
  340. package/README.md +0 -3
@@ -0,0 +1,140 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * pack-plugins.mjs — 付费插件包打包上传(决策㉓:鉴权下载通道)
4
+ *
5
+ * 打包付费插件(plugins/argent-* 与 presets/argent-*)→ tarball + 版本/哈希清单
6
+ * → 上传到 whyshu 服务器 /home/whyshu/server/packs-store/(非 public,经 API 鉴权下载)。
7
+ *
8
+ * 用法:
9
+ * node pack-plugins.mjs # 打包并上传全部付费包
10
+ * node pack-plugins.mjs kanban # 仅打包指定包
11
+ * SKIP_UPLOAD=1 node pack-plugins.mjs # 只打包不上传(产物在 dist/packs/)
12
+ */
13
+
14
+ import { homedir, tmpdir } from 'node:os'
15
+ import { join } from 'node:path'
16
+ import { mkdirSync, mkdtempSync, readFileSync, writeFileSync, copyFileSync, existsSync, rmSync, readdirSync, statSync } from 'node:fs'
17
+ import { execFileSync } from 'node:child_process'
18
+ import { createHash } from 'node:crypto'
19
+
20
+ const REPO = process.env.ARGENT_DISH_HOME || join(homedir(), '.argent-dsh')
21
+ // 产物目录可覆盖(`PACKS_OUT`,与 release-argent.sh --publish-packs 同一变量名)——
22
+ // 默认 dist/packs 在仓库工作树里,未跟踪但**未被 .gitignore 挡**,用 /tmp 可彻底避免误提交。
23
+ const OUT = process.env.PACKS_OUT || join(REPO, 'dist', 'packs')
24
+ const SERVER = 'ubuntu@81.69.222.211'
25
+ const SERVER_DIR = '/home/whyshu/server/packs-store'
26
+ const SSH = ['-i', join(homedir(), '.ssh', 'whyshu.pem')]
27
+
28
+ // 付费包定义(id → 组件清单;与 whyshu-svr PLUGIN_PACKS 对齐)
29
+ // 两种形态:
30
+ // · `plugins`/`presets` = 插件包:逐组件 tar(版本取仓库 VERSION)
31
+ // · `capability` = **能力包**:产物交给既有构建器 `capability_pack.py --build <id> --tar`
32
+ // (含 PACK.json,`install-argent.mjs --from-packs` 可直装),版本/摘要取自同一构建器的
33
+ // `--emit-server-manifest`(**不**用仓库 VERSION —— 能力包有自己的语义化版本)
34
+ const PACKS = {
35
+ // P3.5(2026-09-17):kanban 包删除(argent-kanban 已退役);gateway 包去掉 argent-notify(已退役)
36
+ gateway: { plugins: ['argent-gateway'], presets: [] },
37
+ // P0(2026-10-06,id 对齐):旧 id `hr-office` 是**已退役的角色名**(2026-10-04 退役,preset 只作墓碑),
38
+ // 而服务端 `PLUGIN_PACKS` 与注册表 `capabilities.hr` 的口径是**能力包 id `hr`**(minPlan=pro)。
39
+ // 本表若仍写旧 id ⇒ packs-store/manifest.json 里只有 `hr-office`、服务端按 `hr` 查不到版本
40
+ // (`packs[].version = null`:unlocked=true 却拿不到产物)⇒ id 必须与**能力 id**同名。
41
+ hr: { capability: 'hr' },
42
+ 'ml-daily': { plugins: ['argent-ml'], presets: ['argent-ml-daily'] },
43
+ 'ml-fulfillment': { plugins: ['argent-ml'], presets: ['argent-ml-fulfillment'] },
44
+ }
45
+
46
+ const targets = process.argv.slice(2)
47
+ const upload = process.env.SKIP_UPLOAD !== '1'
48
+
49
+ function packDir(dir, name) {
50
+ // tar czf 相对路径打包(包内以 <name>/ 为顶层,便于解压到对应位置)
51
+ const tar = execFileSync('tar', ['czf', '-', '-C', join(dir, '..'), name], { maxBuffer: 64 * 1024 * 1024 })
52
+ return tar
53
+ }
54
+
55
+ function sha256(buf) {
56
+ return createHash('sha256').update(buf).digest('hex')
57
+ }
58
+
59
+ const PY = process.env.ARGENT_PY || 'python3'
60
+
61
+ /** 能力包发布口径索引(`capability_pack.py --emit-server-manifest`):能力 → 版本 + **整包内容摘要**。 */
62
+ function capabilityIndex() {
63
+ const tmp = join(mkdtempSync(join(tmpdir(), 'pack-plugins-manifest-')), 'server-manifest.json')
64
+ execFileSync(PY, [join(REPO, 'scripts', 'capability_pack.py'), '--emit-server-manifest', '--out', tmp],
65
+ { cwd: REPO, stdio: ['ignore', 'pipe', 'pipe'] })
66
+ const doc = JSON.parse(readFileSync(tmp, 'utf-8'))
67
+ rmSync(tmp, { force: true })
68
+ return doc.capabilities || {}
69
+ }
70
+
71
+ mkdirSync(OUT, { recursive: true })
72
+ const manifest = {}
73
+ let capIndex = null
74
+
75
+ for (const [id, def] of Object.entries(PACKS)) {
76
+ if (targets.length && !targets.includes(id)) continue
77
+ if (def.capability) {
78
+ // 能力包:现场构建。构建器**拒绝**把包装配进仓库(`REPO in out_dir.parents` ⇒ 抛错)
79
+ // ⇒ 先落到临时目录,再把 tgz 取进 OUT。
80
+ capIndex = capIndex || capabilityIndex()
81
+ const info = capIndex[def.capability]
82
+ if (!info) { console.error(`✗ ${id}: 能力清单里没有 ${def.capability}`); process.exit(1) }
83
+ const tmpRoot = mkdtempSync(join(tmpdir(), `pack-plugins-${def.capability}-`))
84
+ execFileSync(PY, [join(REPO, 'scripts', 'capability_pack.py'), '--build', def.capability,
85
+ '--out-dir', join(tmpRoot, def.capability), '--tar', '--force'],
86
+ { cwd: REPO, stdio: ['ignore', 'pipe', 'inherit'] })
87
+ const fname = `${def.capability}-${info.version}.tgz`
88
+ const built = join(tmpRoot, fname)
89
+ if (!existsSync(built)) { console.error(`✗ ${id}: 构建器未产出 ${fname}`); process.exit(1) }
90
+ const buf = readFileSync(built)
91
+ copyFileSync(built, join(OUT, fname))
92
+ rmSync(tmpRoot, { recursive: true, force: true })
93
+ // 两个 sha 别混(用途不同;口径与 id⇄能力⇄档位对应表见
94
+ // whyshu-svr `docs/ops/deploy-5cebae1-hr-pack.md`):
95
+ // · contentDigest = **整包内容摘要**(PACK.json 里 `文件:sha16` 排序求摘要 = `--expect-sha256` 口径,
96
+ // 也是服务端能力清单 `capability-packs.json` 的 sha256)
97
+ // · sha256 = tgz **字节**摘要(传输完整性;store 清单既有口径)
98
+ manifest[id] = { version: info.version, files: { [def.capability]: {
99
+ file: fname, sha256: sha256(buf), contentDigest: info.sha256, size: buf.length } } }
100
+ console.log(`✓ ${id}@${info.version}:${fname}(${(buf.length / 1024).toFixed(1)} KB,内容摘要 ${info.sha256.slice(0, 16)}…)`)
101
+ continue
102
+ }
103
+ const parts = []
104
+ for (const p of def.plugins) {
105
+ const src = join(REPO, 'plugins', p)
106
+ if (!existsSync(src)) { console.error(`✗ ${id}: 插件缺失 ${p}`); process.exit(1) }
107
+ parts.push(packDir(src, p))
108
+ }
109
+ for (const pr of def.presets) {
110
+ const src = join(REPO, 'presets', pr)
111
+ if (!existsSync(src)) { console.error(`✗ ${id}: preset 缺失 ${pr}`); process.exit(1) }
112
+ parts.push(packDir(src, pr))
113
+ }
114
+ // 合并所有 part 为一个 tgz(tar 拼接:多段 tar 流合并不规范——改为逐组件独立 tgz,清单记录)
115
+ const version = (readFileSync(join(REPO, 'VERSION'), 'utf-8') || '0.0.0').trim()
116
+ const files = {}
117
+ for (let i = 0; i < parts.length; i++) {
118
+ const component = [...def.plugins, ...def.presets][i]
119
+ const fname = `${component}.tgz`
120
+ writeFileSync(join(OUT, fname), parts[i])
121
+ files[component] = { file: fname, sha256: sha256(parts[i]), size: parts[i].length }
122
+ }
123
+ manifest[id] = { version, files }
124
+ console.log(`✓ ${id}@${version}:${Object.keys(files).join(', ')}`)
125
+ }
126
+
127
+ writeFileSync(join(OUT, 'manifest.json'), JSON.stringify(manifest, null, 2))
128
+ console.log(`\n清单: ${join(OUT, 'manifest.json')}`)
129
+
130
+ if (upload) {
131
+ console.log(`\n上传到 ${SERVER}:${SERVER_DIR} ...`)
132
+ execFileSync('ssh', [...SSH, SERVER, `mkdir -p ${SERVER_DIR}`])
133
+ execFileSync('scp', [...SSH, join(OUT, 'manifest.json'), `${SERVER}:${SERVER_DIR}/`])
134
+ for (const id of Object.keys(manifest)) {
135
+ for (const f of Object.values(manifest[id].files)) {
136
+ execFileSync('scp', [...SSH, join(OUT, f.file), `${SERVER}:${SERVER_DIR}/`])
137
+ }
138
+ }
139
+ console.log('上传完成(经 /api/argent/packs/<id>/download 鉴权下载)')
140
+ }
@@ -0,0 +1,297 @@
1
+ # requires-dsh: >=0.1.7 (TRANSPORT 可诊断性;判定语义不变,只加可观测字段)
2
+ #
3
+ # 目标:@deepseek-ai/dsh-llm-deepseek/lib/index.js(官方 Messages 适配器;**问述代理复用同一份**,
4
+ # 见 plugins/argent-core/src/llm-whyshu.js —— 它只把 provider 注册成 `whyshu`)。
5
+ #
6
+ # 为什么(2026-10-02):`generate()` 的 catch 把"非空闲超时、非用户中断"的**一切**错误折叠成
7
+ # `DeepSeek Messages transport failed` / TRANSPORT,`failure` 只剩 message+code
8
+ # ⇒ 落到会话日志的 `llm/retry` 事件也只有这两项(实测 session-878f3e3b:6 次连败,事后完全
9
+ # 分不清 ECONNRESET / 提前关闭 / 5xx 断流),且无法回答"这次到底产出了没有"。
10
+ #
11
+ # 本补丁做三件事(**都不改 TIMEOUT/ABORTED/TRANSPORT 三分支判定**):
12
+ # ① 捕获 provider 侧请求标识(request-id / x-request-id / x-deepseek-request-id)与 HTTP 状态,
13
+ # 并作为 `requestId` 塞进 LlmError.failure ⇒ 随 `llm/retry` 事件**落进会话日志**;
14
+ # ② 统计已产出内容(chunks / text / reasoning / toolArgs / blockStarts / settled / anyOutput);
15
+ # ③ 打两行 warn:`[argent-transport] ...` 单行摘要(可 grep)+ 结构化 `TRANSPORT detail %o`。
16
+ #
17
+ # 回滚:git checkout 该文件(或用 patch -R)。重启不必要(模块在下次进程启动时加载)。
18
+ --- /opt/homebrew/lib/node_modules/@deepseek-ai/dsh-llm-deepseek/lib/index.js.orig
19
+ +++ /opt/homebrew/lib/node_modules/@deepseek-ai/dsh-llm-deepseek/lib/index.js
20
+ @@ -2061,6 +2061,191 @@
21
+ var e = new Error(message);
22
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
23
+ });
24
+ +/**
25
+ + * Argent hotfix (2026-10-02) — TRANSPORT 可诊断性(**只加可观测字段,不改判定语义**)。
26
+ + *
27
+ + * 事故:`generate()` 的 catch 把"非空闲超时、非用户中断"的**一切**错误折叠成
28
+ + * `DeepSeek Messages transport failed` / TRANSPORT,`failure` 里只剩 message+code
29
+ + * ⇒ 落到会话日志的 `llm/retry` 事件也只有这两项,事后完全分不清是
30
+ + * 连接被对端重置(ECONNRESET)、提前关闭(socket hang up)、读超时(ETIMEDOUT)、
31
+ + * 还是 5xx 断流;也无法回答"这次到底产出了没有"(决定能不能安全重试)。
32
+ + * 下面这些纯函数只负责收集与格式化,**不参与** TIMEOUT/ABORTED/TRANSPORT 的分支判定。
33
+ + */
34
+ +let argentTransportCallSeq = 0;
35
+ +/** 建一次请求的诊断累加器(每回合一个)。 */
36
+ +function argentTransportDiagnostics(options, connection) {
37
+ + return {
38
+ + provider: options.provider,
39
+ + model: options.model,
40
+ + sessionId: options.sessionId === void 0 ? void 0 : String(options.sessionId),
41
+ + purpose: options.purpose,
42
+ + callId: `${Date.now().toString(36)}-${++argentTransportCallSeq}`,
43
+ + startedAt: Date.now(),
44
+ + signalAbortedAtStart: options.signal?.aborted === true,
45
+ + idleTimeoutMs: connection.streamIdleTimeoutMs,
46
+ + requestId: void 0,
47
+ + httpStatus: void 0,
48
+ + responseAt: void 0,
49
+ + bodySnippet: void 0,
50
+ + produced: {
51
+ + chunks: 0,
52
+ + blockStarts: 0,
53
+ + blocksEnded: 0,
54
+ + textChars: 0,
55
+ + reasoningChars: 0,
56
+ + toolCallChars: 0,
57
+ + toolCallNames: [],
58
+ + settled: false
59
+ + },
60
+ + lastChunkAt: void 0
61
+ + };
62
+ +}
63
+ +/** 记一条已产出的流分片 —— "有没有输出" = `chunks>0` 且任一类计数非零。 */
64
+ +function argentRecordProducedChunk(diagnostics, chunk) {
65
+ + if (diagnostics === void 0 || chunk === null || typeof chunk !== "object") return;
66
+ + const produced = diagnostics.produced;
67
+ + produced.chunks += 1;
68
+ + diagnostics.lastChunkAt = Date.now();
69
+ + if (chunk.type === "text-delta") produced.textChars += typeof chunk.text === "string" ? chunk.text.length : 0;
70
+ + else if (chunk.type === "reasoning-delta") produced.reasoningChars += typeof chunk.text === "string" ? chunk.text.length : 0;
71
+ + else if (chunk.type === "tool-call-delta") {
72
+ + produced.toolCallChars += typeof chunk.argumentsDelta === "string" ? chunk.argumentsDelta.length : 0;
73
+ + if (typeof chunk.name === "string" && chunk.name.length > 0 && !produced.toolCallNames.includes(chunk.name)) produced.toolCallNames.push(chunk.name);
74
+ + } else if (chunk.type === "block-start") produced.blockStarts += 1;
75
+ + else if (chunk.type === "block-end") produced.blocksEnded += 1;
76
+ + else if (chunk.type === "finish" || chunk.type === "usage") produced.settled = true;
77
+ +}
78
+ +/** `produced` 的摘要字段(写进日志,也用于"是否可安全重试"的判断依据)。 */
79
+ +function argentProducedSummary(diagnostics) {
80
+ + const produced = diagnostics?.produced;
81
+ + if (produced === void 0) return { chunks: 0, textChars: 0, reasoningChars: 0, toolCallChars: 0, blockStarts: 0, blocksEnded: 0, toolCallNames: [], settled: false, anyOutput: false };
82
+ + return {
83
+ + chunks: produced.chunks,
84
+ + textChars: produced.textChars,
85
+ + reasoningChars: produced.reasoningChars,
86
+ + toolCallChars: produced.toolCallChars,
87
+ + blockStarts: produced.blockStarts,
88
+ + blocksEnded: produced.blocksEnded,
89
+ + toolCallNames: [...produced.toolCallNames],
90
+ + settled: produced.settled,
91
+ + anyOutput: produced.textChars + produced.reasoningChars + produced.toolCallChars + produced.blockStarts > 0
92
+ + };
93
+ +}
94
+ +/** 从响应头取 provider 侧请求标识(与 `providerError()` 同一组头、同一优先级)。 */
95
+ +function argentRequestIdOf(headers) {
96
+ + if (headers === void 0 || headers === null || typeof headers.get !== "function") return void 0;
97
+ + const id = headers.get("request-id") ?? headers.get("x-request-id") ?? headers.get("x-deepseek-request-id");
98
+ + return id === null || id === void 0 || id.length === 0 ? void 0 : ProviderRequestId(id);
99
+ +}
100
+ +/** 响应一到就记下状态码与请求标识(**即便后面流断掉**,这些也已经拿到了)。 */
101
+ +function argentNoteResponse(diagnostics, response) {
102
+ + if (diagnostics === void 0) return;
103
+ + diagnostics.responseAt = Date.now();
104
+ + diagnostics.httpStatus = response.status;
105
+ + const id = argentRequestIdOf(response.headers);
106
+ + if (id !== void 0) diagnostics.requestId = id;
107
+ +}
108
+ +/** 记非 2xx 的响应体片段(判 5xx 断流 vs 网关错误页用;截断,避免日志被 HTML 淹没)。 */
109
+ +function argentNoteHttpFailure(diagnostics, response, text) {
110
+ + if (diagnostics === void 0) return;
111
+ + diagnostics.httpStatus = response.status;
112
+ + const id = argentRequestIdOf(response.headers);
113
+ + if (id !== void 0) diagnostics.requestId = id;
114
+ + diagnostics.bodySnippet = typeof text === "string" ? text.slice(0, 400) : void 0;
115
+ +}
116
+ +/**
117
+ + * 把任意 error 折成**可读的 cause 形态**。覆盖:
118
+ + * · `ECONNRESET` / `socket hang up` / `ETIMEDOUT` / `UND_ERR_*` —— Node fetch(undici) 的
119
+ + * 连接层错误,**通常在 `error.cause` 上**(undici 会包一层 `TypeError: fetch failed` 或
120
+ + * `TypeError: terminated`);
121
+ + * · 非 2xx 状态码 + 响应体片段 —— provider 侧网关/上游错误;
122
+ + * · `AbortError` —— 区分"空闲 watchdog 触发"(已归 TIMEOUT)与"其它中断"。
123
+ + * @param error - catch 到的原始错误。
124
+ + * @param depth - 递归深度(只跟 cause 链,最多 4 层)。
125
+ + * @returns 平铺的 cause 事实(可直接 JSON 化)。
126
+ + */
127
+ +function argentDescribeTransportCause(error, depth = 0) {
128
+ + const out = {
129
+ + depth,
130
+ + name: void 0,
131
+ + message: void 0,
132
+ + code: void 0,
133
+ + errno: void 0,
134
+ + syscall: void 0,
135
+ + abort: false,
136
+ + kind: "unknown"
137
+ + };
138
+ + if (error === null || error === void 0 || typeof error !== "object") {
139
+ + out.message = String(error);
140
+ + return out;
141
+ + }
142
+ + out.name = typeof error.name === "string" ? error.name : void 0;
143
+ + out.message = typeof error.message === "string" ? error.message : String(error);
144
+ + out.code = typeof error.code === "string" ? error.code : void 0;
145
+ + out.errno = error.errno === void 0 ? void 0 : String(error.errno);
146
+ + out.syscall = typeof error.syscall === "string" ? error.syscall : void 0;
147
+ + out.abort = out.name === "AbortError" || out.code === "ABORT_ERR";
148
+ + const text = `${out.name ?? ""} ${out.code ?? ""} ${out.message ?? ""}`;
149
+ + if (out.abort) out.kind = "AbortError";
150
+ + else if (out.code === "ECONNRESET" || /socket hang up|ECONNRESET/i.test(text)) out.kind = "ECONNRESET";
151
+ + else if (out.code === "ETIMEDOUT" || /ETIMEDOUT|timed? ?out/i.test(text)) out.kind = "ETIMEDOUT";
152
+ + else if (out.code === "ECONNREFUSED" || /ECONNREFUSED/i.test(text)) out.kind = "ECONNREFUSED";
153
+ + else if (out.code === "EPIPE") out.kind = "EPIPE";
154
+ + else if (out.code === "UND_ERR_SOCKET" || out.code === "ERR_STREAM_PREMATURE_CLOSE") out.kind = "EARLY_CLOSE";
155
+ + else if (out.code === "UND_ERR_ABORTED") out.kind = "AbortError";
156
+ + else if (out.code === "UND_ERR_CONNECT_TIMEOUT" || out.code === "UND_ERR_HEADERS_TIMEOUT" || out.code === "UND_ERR_BODY_TIMEOUT") out.kind = "ETIMEDOUT";
157
+ + else if (typeof out.code === "string" && out.code.startsWith("UND_ERR")) out.kind = out.code;
158
+ + else if (/terminated|premature close|other side closed/i.test(text)) out.kind = "EARLY_CLOSE";
159
+ + else if (/fetch failed/i.test(text)) out.kind = "FETCH_FAILED";
160
+ + return out;
161
+ +}
162
+ +/** 汇总本回合的全部诊断事实(一次调用产出日志行 + 结构化字段)。 */
163
+ +function argentTransportReport(diagnostics, error, connection) {
164
+ + const now = Date.now();
165
+ + const cause = argentDescribeTransportCause(error?.cause ?? error);
166
+ + const produced = argentProducedSummary(diagnostics);
167
+ + const requestId = diagnostics?.requestId ?? (typeof error?.failure?.requestId === "string" ? error.failure.requestId : void 0);
168
+ + const status = diagnostics?.httpStatus;
169
+ + return {
170
+ + provider: diagnostics?.provider,
171
+ + model: diagnostics?.model,
172
+ + sessionId: diagnostics?.sessionId,
173
+ + purpose: diagnostics?.purpose,
174
+ + callId: diagnostics?.callId,
175
+ + requestId,
176
+ + httpStatus: status,
177
+ + produced,
178
+ + elapsedMs: diagnostics === void 0 ? void 0 : now - diagnostics.startedAt,
179
+ + msSinceLastChunk: diagnostics?.lastChunkAt === void 0 ? void 0 : now - diagnostics.lastChunkAt,
180
+ + idleTimeoutMs: connection.streamIdleTimeoutMs,
181
+ + cause,
182
+ + causeChain: (() => {
183
+ + const chain = [];
184
+ + let node = error;
185
+ + for (let i = 0; i < 4 && node !== null && node !== void 0 && typeof node === "object"; i += 1) {
186
+ + chain.push(argentDescribeTransportCause(node, i));
187
+ + node = node.cause;
188
+ + }
189
+ + return chain;
190
+ + })(),
191
+ + bodySnippet: diagnostics?.bodySnippet,
192
+ + aborted: false
193
+ + };
194
+ +}
195
+ +/** 单行、可 grep 的日志文本(`[argent-transport]` 前缀固定,便于 tail/grep 定位)。 */
196
+ +function argentTransportLogLine(report) {
197
+ + const p = report.produced;
198
+ + return `[argent-transport] route=${report.provider ?? "?"}/${report.model ?? "?"}`
199
+ + + ` callId=${report.callId ?? "?"} providerRequestId=${report.requestId ?? "(none)"}`
200
+ + + ` httpStatus=${report.httpStatus ?? "(no response)"} cause=${report.cause.kind}`
201
+ + + ` causeName=${report.cause.name ?? "?"} causeCode=${report.cause.code ?? "?"} causeErrno=${report.cause.errno ?? "?"}`
202
+ + + ` causeMessage=${JSON.stringify(String(report.cause.message ?? "").slice(0, 200))}`
203
+ + + ` produced={chunks:${p.chunks},text:${p.textChars},reasoning:${p.reasoningChars},toolArgs:${p.toolCallChars},blockStarts:${p.blockStarts},settled:${p.settled},anyOutput:${p.anyOutput}}`
204
+ + + ` toolCalls=${JSON.stringify(report.produced.toolCallNames ?? [])}`
205
+ + + ` elapsedMs=${report.elapsedMs ?? "?"} msSinceLastChunk=${report.msSinceLastChunk ?? "?"}`
206
+ + + ` idleTimeoutMs=${report.idleTimeoutMs ?? "?"} sessionId=${report.sessionId ?? "(none)"}`
207
+ + + (report.bodySnippet === void 0 ? "" : ` bodySnippet=${JSON.stringify(report.bodySnippet.slice(0, 200))}`);
208
+ +}
209
+ /** DeepSeek provider using Messages content and native thinking replay. */
210
+ var DeepSeekAdapter = class extends LlmAdapter {
211
+ dependencies;
212
+ @@ -2111,20 +2296,32 @@
213
+ try {
214
+ const consumer = new AbortController();
215
+ const watchdog = __addDisposableResource(env_1, idleWatchdog(options.signal === void 0 ? consumer.signal : AbortSignal.any([consumer.signal, options.signal]), connection.streamIdleTimeoutMs, "MESSAGES_IDLE"), false);
216
+ + /* Argent hotfix (2026-10-02):TRANSPORT 诊断累加器(只观测,不参与判定)。 */
217
+ + const transportDiagnostics = argentTransportDiagnostics(options, connection);
218
+ const iterator = this.request(options, connection, watchdog.signal, () => {
219
+ watchdog.pulse();
220
+ - });
221
+ + }, transportDiagnostics);
222
+ try {
223
+ while (true) {
224
+ const next = await watchdog.next(iterator);
225
+ if (next.done) return;
226
+ + argentRecordProducedChunk(transportDiagnostics, next.value);
227
+ yield next.value;
228
+ }
229
+ } catch (error) {
230
+ if (timeoutOf(watchdog.signal, "MESSAGES_IDLE") !== void 0) throw new LlmError("DeepSeek Messages stream idle timeout", "TIMEOUT", { cause: error });
231
+ if (options.signal?.aborted) throw new LlmError("DeepSeek Messages request aborted", "ABORTED", { cause: error });
232
+ if (error instanceof LlmError) throw error;
233
+ - throw new LlmError("DeepSeek Messages transport failed", "TRANSPORT", { cause: error });
234
+ + /* Argent hotfix (2026-10-02):**判定不变**(仍是 TRANSPORT),只补可观测字段:
235
+ + * ① 通过 onTransportFailure 打一行可 grep 的 cause/streamId/已产出长度;
236
+ + * ② 把 provider 侧请求标识塞进 LlmError.failure ⇒ 随 llm/retry 事件**落进会话日志**
237
+ + * (此前 failure 只有 message+code,事后无法复盘)。 */
238
+ + const transportReport = argentTransportReport(transportDiagnostics, error, connection);
239
+ + this.dependencies.onTransportFailure?.(transportReport);
240
+ + throw new LlmError("DeepSeek Messages transport failed", "TRANSPORT", {
241
+ + cause: error,
242
+ + ...transportReport.requestId === void 0 ? {} : { requestId: transportReport.requestId }
243
+ + });
244
+ } finally {
245
+ consumer.abort();
246
+ try {
247
+ @@ -2138,7 +2335,7 @@
248
+ __disposeResources(env_1);
249
+ }
250
+ }
251
+ - async *request(options, connection, signal, activity) {
252
+ + async *request(options, connection, signal, activity, transportDiagnostics) {
253
+ signal.throwIfAborted();
254
+ const { messages, versions } = await prepareImages(options.messages, connection, options.model, this.dependencies.resolveAttachments?.(), this.imageAccess, signal);
255
+ const auth = await this.dependencies.resolveAuth(connection);
256
+ @@ -2197,8 +2394,12 @@
257
+ ...options.purpose === "compaction" ? { "x-deepseek-harness-compact": "1" } : {}
258
+ }
259
+ });
260
+ + /* Argent hotfix (2026-10-02):响应一到就记下状态码 + provider 请求标识
261
+ + * ——**即便随后流被对端切断**,这两个也已拿到,是事后定位的唯一线索。 */
262
+ + argentNoteResponse(transportDiagnostics, response);
263
+ if (!response.ok) {
264
+ const text = await response.text();
265
+ + argentNoteHttpFailure(transportDiagnostics, response, text);
266
+ let raw;
267
+ try {
268
+ raw = JSON.parse(text);
269
+ @@ -2252,6 +2453,27 @@
270
+ onExtensionsOmitted: ({ provider, model, fields, error }) => {
271
+ ctx.logger.warn(`llm-deepseek: sending route "${provider}/${model}" without request extension fields ${fields.join(", ")} because they failed to serialize: %o`, error);
272
+ },
273
+ + /* Argent hotfix (2026-10-02):TRANSPORT 的可诊断性。
274
+ + * 一次失败打两行:① 单行、可 grep 的摘要(cause/streamId/已产出长度);
275
+ + * ② 结构化对象(`%o`)供 `dsh` 日志详情/后续工具解析。判定语义不变。 */
276
+ + onTransportFailure: (report) => {
277
+ + ctx.logger.warn(argentTransportLogLine(report));
278
+ + ctx.logger.warn("llm-deepseek: TRANSPORT detail %o", {
279
+ + route: `${report.provider ?? "?"}/${report.model ?? "?"}`,
280
+ + callId: report.callId,
281
+ + providerRequestId: report.requestId,
282
+ + httpStatus: report.httpStatus,
283
+ + produced: report.produced,
284
+ + elapsedMs: report.elapsedMs,
285
+ + msSinceLastChunk: report.msSinceLastChunk,
286
+ + idleTimeoutMs: report.idleTimeoutMs,
287
+ + cause: report.cause,
288
+ + causeChain: report.causeChain,
289
+ + bodySnippet: report.bodySnippet,
290
+ + sessionId: report.sessionId,
291
+ + purpose: report.purpose
292
+ + });
293
+ + },
294
+ resolveAttachments: () => ctx.get("attachments"),
295
+ resolveImageAccess: (attachments, ref) => resolveImageAttachmentAccess(attachments, (hostPath) => ctx.get("fs")?.processPathFromHostPath(hostPath), ref),
296
+ prepareExtensions: (request) => ctx.get("deepseekLlmApiExtensions")?.prepare(request) ?? Promise.resolve({
297
+
@@ -0,0 +1,15 @@
1
+ --- /opt/homebrew/lib/node_modules/@deepseek-ai/dsh-session/lib/index.js.orig
2
+ +++ /opt/homebrew/lib/node_modules/@deepseek-ai/dsh-session/lib/index.js
3
+ @@ -1187,6 +1187,12 @@
4
+ ...surfaceMetadataSnapshot
5
+ });
6
+ validateSessionEventData(event, `session event "${type}" at seq ${event.seq}`);
7
+ + /* Hardening (2026-09-18, argent-dsh hotfix): the append boundary must reject a
8
+ + message event that could never be replayed. Otherwise a malformed tool/result
9
+ + (e.g. a render that returned a bare string) lands in the log and only fails
10
+ + when the session is next LOADED from disk — by then the session cannot even be
11
+ + opened, and a surface replace cannot repair it. Fail at the writer instead. */
12
+ + assertMessageEventShape(event, `session event "${type}" at seq ${event.seq}`);
13
+ this.surfaceManager.validateNext(event);
14
+ if (entry !== void 0) entry.appending = true;
15
+ try {
@@ -0,0 +1,28 @@
1
+ # requires-dsh: >=0.1.7 (0.1.7 重写校验器时丢了 0.1.5 的 tool-result 形状规则;本补丁恢复防毒化检查。
2
+ # 2026-09-29 修正:初版恢复的"必须是 tool-result block"与 v4 形态矛盾(v4 里 tool-result wrapper 是
3
+ # retired syntax,v3→v4 迁移器展开为 text blocks),会误杀全部含 tool/result 的 v4 session 加载;
4
+ # 现改为"content 为非空 ContentBlock 数组"——保留防裸字符串毒化的核心,兼容 v4。)
5
+ --- /opt/homebrew/lib/node_modules/@deepseek-ai/dsh-session/lib/index.js.orig
6
+ +++ /opt/homebrew/lib/node_modules/@deepseek-ai/dsh-session/lib/index.js
7
+ @@ -1172,6 +1172,21 @@
8
+ }
9
+ if (type !== "tool/result") return;
10
+ if (sourceRecord["kind"] !== "tool" || typeof sourceRecord["callId"] !== "string" || sourceRecord["callId"] === "") throw new Error(`${subject} message must have tool source`);
11
+ + /* Hardening (2026-09-29, argent-dsh hotfix for 0.1.7): upstream rewrote this validator and
12
+ + dropped the "exactly one tool-result block with array content" rule that 0.1.5 had. Without
13
+ + it a malformed tool/result (e.g. a render that returned a bare string) is accepted at the
14
+ + append boundary and only blows up when the session is next LOADED from disk — by then the
15
+ + session cannot even be opened (see AGENTS.md 会话毒化事故). Restore the rule. */
16
+ + {
17
+ + const content = messageRecord["content"];
18
+ + const block = content[0];
19
+ + /* 2026-09-29 修正:原规则"必须是 tool-result block"与 v4 形态矛盾——v4 里 tool-result
20
+ + wrapper 是 retired syntax(由 v3→v4 迁移器展开为 text blocks + message.toolCallId,
21
+ + 见 v3-to-v4 的 assertV4RetiredSyntax)。恢复旧规则会误杀**全部含 tool/result 的 v4
22
+ + session 加载**(实测 06732069 报 "must contain one tool-result block")。
23
+ + 防"毒化"(裸字符串 content)的核心 = content 为非空 ContentBlock 数组。 */
24
+ + if (content.length === 0 || typeof block !== "object" || block === null || typeof block["type"] !== "string") throw new Error(`${subject} message must contain a non-empty content block array`);
25
+ + }
26
+ if (messageRecord["toolCallId"] !== sourceRecord["callId"]) throw new Error(`${subject} message has mismatched tool call ids`);
27
+ }
28
+ /** Whether an unknown value carries the current provider/model pair. */
@@ -0,0 +1,11 @@
1
+ --- /tmp/dsh-fix-test/index.js.orig 2026-09-10 16:21:27
2
+ +++ /opt/homebrew/lib/node_modules/@deepseek-ai/dsh-session-format-v0-to-v1/lib/index.js 2026-09-10 16:21:27
3
+ @@ -116,7 +116,7 @@
4
+ "retry"
5
+ ]),
6
+ "model/selection": disposition(["provider", "model"], ["reasoningEffort"]),
7
+ - "permission/preset": disposition(["preset"]),
8
+ + "permission/preset": disposition(["preset"], ["origin"]),
9
+ "plan/mode": disposition(["active"]),
10
+ "request/context": disposition(["provider", "model"], ["contextWindow"]),
11
+ "request/header": disposition(["header", "reason"], ["startsSeries"]),
@@ -0,0 +1,20 @@
1
+ # requires-dsh: >=0.1.7 (v3→v4 迁移器 0.1.7 新增;修复"turn 外替换型 tool/result"过严拒绝)
2
+ --- /opt/homebrew/lib/node_modules/@deepseek-ai/dsh-session-format-v3-to-v4/lib/index.js.orig
3
+ +++ /opt/homebrew/lib/node_modules/@deepseek-ai/dsh-session-format-v3-to-v4/lib/index.js
4
+ @@ -617,7 +617,15 @@
5
+ }
6
+ tool(event, data) {
7
+ if (event.type === "tool/result" && event["surfaceOp"] !== "append") {
8
+ - this.requireTurn(event.type);
9
+ + /* Hardening (2026-09-29, argent-dsh hotfix for 0.1.7): v3 允许"turn 结束后的替换型
10
+ + tool/result"(编辑/重放场景:重写早先 turn 的工具结果,如 surface 自替换)。
11
+ + 原 requireTurn 过严 → 整个 session 迁移失败('tool/result is outside an
12
+ + open turn',实测 06732069/34c3e088 等)。现在:turn 外时校验 data.turn 指向
13
+ + 已关闭的历史 turn(防真损坏,放行合法历史)。 */
14
+ + if (this.turn === null) {
15
+ + const t = data["turn"];
16
+ + if (!Number.isSafeInteger(t) || t >= this.nextTurn) throw new SessionFormatError(`${event.type} is outside an open turn`);
17
+ + }
18
+ return;
19
+ }
20
+ this.requireStep(event, data);
@@ -0,0 +1,39 @@
1
+ # requires-dsh: >=0.1.7 (迁移校验 worker 的**打包副本**——模块版 hotfix 打不到它,必须单独打)
2
+ #
3
+ # 背景(2026-09-29 事故,实例 session-06732069「Argent项目」):
4
+ # v3→v4 迁移由 @deepseek-ai/dsh-session-persistence-jsonl 起 worker 线程做最终校验
5
+ # (lib/worker.cjs,539KB 打包件,内联了一整份 v0→v1 与 v3→v4 的迁移器/校验器)。
6
+ # 此前所有 hotfix 只打在 lib/index.js 这些**模块**上 ⇒
7
+ # · 离线校验器(verify-session-migration.mjs)import 模块 → 一直假绿;
8
+ # · 真实 resume 走 worker 的**旧副本** → 抛
9
+ # SessionPersistenceCorruptionError: stored log is corrupt:
10
+ # Error: tool/result is outside an open turn
11
+ # ⇒ 前端发送消息弹白 toast、会话打不开。
12
+ # 本补丁把两处 hotfix 同步进 worker 打包副本:
13
+ # ① v3→v4 `tool()`:turn 结束后的**替换型** tool/result 在 v3 里合法(编辑/重放),
14
+ # 原 requireTurn 过严 → 整个迁移失败;
15
+ # ② v0 `permission/preset`:容忍旧数据里的 `origin` 字段(= 2026-09-10 hotfix 的镜像,
16
+ # 此前同样只打在模块上)。
17
+ --- /opt/homebrew/lib/node_modules/@deepseek-ai/dsh-session-persistence-jsonl/lib/worker.cjs.orig
18
+ +++ /opt/homebrew/lib/node_modules/@deepseek-ai/dsh-session-persistence-jsonl/lib/worker.cjs
19
+ @@ -6749,4 +6749,4 @@
20
+ ]),
21
+ "model/selection": disposition(["provider", "model"], ["reasoningEffort"]),
22
+ - "permission/preset": disposition(["preset"]),
23
+ + "permission/preset": disposition(["preset"], ["origin"]),
24
+ "plan/mode": disposition(["active"]),
25
+ @@ -11331,7 +11331,13 @@
26
+ }
27
+ tool(event, data) {
28
+ if (event.type === "tool/result" && event["surfaceOp"] !== "append") {
29
+ - this.requireTurn(event.type);
30
+ + /* Hardening (2026-09-29, argent-dsh hotfix, mirrored into the bundled worker):
31
+ + v3 allows a REPLACEMENT tool/result after its turn closed (edit/replay); the strict
32
+ + requireTurn killed the entire migration. Same rule as the module patch. */
33
+ + if (this.turn === null) {
34
+ + const t = data["turn"];
35
+ + if (!Number.isSafeInteger(t) || t >= this.nextTurn) throw new SessionFormatError(`${event.type} is outside an open turn`);
36
+ + }
37
+ return;
38
+ }
39
+ this.requireStep(event, data);
@@ -0,0 +1,50 @@
1
+ --- /opt/homebrew/lib/node_modules/@deepseek-ai/dsh-tools/lib/index.js.orig
2
+ +++ /opt/homebrew/lib/node_modules/@deepseek-ai/dsh-tools/lib/index.js
3
+ @@ -834,6 +834,38 @@
4
+ * @param options - typed definition and optional finalizer and presenters.
5
+ * @returns A registry-ready definition.
6
+ */
7
+ +/**
8
+ + * Normalize a tool's `output.render` return value into ContentBlock[].
9
+ + *
10
+ + * Hardening (2026-09-18, argent-dsh hotfix): dsh-tools used to publish the render
11
+ + * return value as the tool-result content VERBATIM. A render that returned a bare
12
+ + * string therefore wrote `content:"…"` into the session log, and every later request
13
+ + * then threw `content.some is not a function` inside dsh-llm's contentHasImage() —
14
+ + * permanently poisoning that session (it could not even be reopened: the loader
15
+ + * rejects the event with "message must contain one tool-result block"). Wrap a
16
+ + * non-array return instead of letting it reach the log, and name the tool.
17
+ + * @param toolName - registered tool name, for the diagnostic.
18
+ + * @param rendered - the value `output.render` returned.
19
+ + * @returns the value unchanged when it already is a ContentBlock array.
20
+ + */
21
+ +function normalizeRenderOutput(toolName, rendered) {
22
+ + if (Array.isArray(rendered)) return rendered;
23
+ + let text;
24
+ + if (typeof rendered === "string") text = rendered;
25
+ + else if (rendered === void 0) text = "undefined";
26
+ + else {
27
+ + try {
28
+ + text = JSON.stringify(rendered) ?? String(rendered);
29
+ + } catch {
30
+ + text = String(rendered);
31
+ + }
32
+ + }
33
+ + console.warn(`[dsh-tools] tool "${toolName}": output.render must return a ContentBlock array but returned ${rendered === null ? "null" : typeof rendered}; wrapping it as one text block (contract: [{type:"text",text}]).`);
34
+ + return [{
35
+ + type: "text",
36
+ + text
37
+ + }];
38
+ +}
39
+ function defineTool(options) {
40
+ const userExecute = options.execute;
41
+ const userFinalizeContent = options.finalizeContent;
42
+ @@ -3423,7 +3455,7 @@
43
+ } catch (error) {
44
+ throw projectionError(tool.name, "render", error);
45
+ }
46
+ - const content = snapshotProjection(tool.name, "render", rendered);
47
+ + const content = snapshotProjection(tool.name, "render", normalizeRenderOutput(tool.name, rendered));
48
+ let meta;
49
+ if (exec.parent === void 0 && tool.output.presentationMeta !== void 0) {
50
+ let projected;