@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.
Files changed (305) hide show
  1. package/MANIFEST.json +307 -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 +575 -0
  55. package/engine/scripts/billing-mode-daily.sh +12 -0
  56. package/engine/scripts/build-engine-package.mjs +123 -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 +377 -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/config-explain.mjs +278 -0
  81. package/engine/scripts/configure-provider.rb +29 -0
  82. package/engine/scripts/customer-config-migrate.mjs +179 -0
  83. package/engine/scripts/customer-preflight.py +892 -0
  84. package/engine/scripts/customer-readiness.sh +134 -0
  85. package/engine/scripts/daily-report-inbox.py +242 -0
  86. package/engine/scripts/daily-report-reconcile.mjs +312 -0
  87. package/engine/scripts/daily-report.mjs +1310 -0
  88. package/engine/scripts/daily-report.sh +46 -0
  89. package/engine/scripts/data/lip-product-dict.json +306 -0
  90. package/engine/scripts/deliver-customer.mjs +932 -0
  91. package/engine/scripts/delivery-faces.txt +31 -0
  92. package/engine/scripts/desktop-trial.sh +146 -0
  93. package/engine/scripts/dev-window.sh +260 -0
  94. package/engine/scripts/drill-clean-machine.sh +315 -0
  95. package/engine/scripts/dsh-api-client.mjs +215 -0
  96. package/engine/scripts/dsh-backup-scope.sh +83 -0
  97. package/engine/scripts/dsh-offline-pack.mjs +77 -0
  98. package/engine/scripts/dsh-overlay-pin.sh +87 -0
  99. package/engine/scripts/dsh-plane.mjs +153 -0
  100. package/engine/scripts/dsh-portforward.py +223 -0
  101. package/engine/scripts/dsh-preflight.mjs +179 -0
  102. package/engine/scripts/dsh-release-watch-daily.sh +19 -0
  103. package/engine/scripts/dsh-release-watch.mjs +458 -0
  104. package/engine/scripts/dsh-remote-check.sh +99 -0
  105. package/engine/scripts/dsh-restart.sh +179 -0
  106. package/engine/scripts/dsh-restore.sh +111 -0
  107. package/engine/scripts/dsh-scope-rewire.mjs +803 -0
  108. package/engine/scripts/dsh-snapshot.mjs +116 -0
  109. package/engine/scripts/dsh-upgrade-readiness.mjs +165 -0
  110. package/engine/scripts/dsh-upgrade.mjs +612 -0
  111. package/engine/scripts/dsh-url.sh +86 -0
  112. package/engine/scripts/dsh-web-launch.mjs +155 -0
  113. package/engine/scripts/ensure-store-windows.py +509 -0
  114. package/engine/scripts/entitlements.py +458 -0
  115. package/engine/scripts/env_probe.py +411 -0
  116. package/engine/scripts/feishu-card.mjs +252 -0
  117. package/engine/scripts/fix-skill-frontmatter.py +209 -0
  118. package/engine/scripts/flow-auto-retry.py +454 -0
  119. package/engine/scripts/flow-requirements.json +720 -0
  120. package/engine/scripts/flow-scaffold.py +275 -0
  121. package/engine/scripts/flow-timers-plist.sh +86 -0
  122. package/engine/scripts/flow-timers.sh +182 -0
  123. package/engine/scripts/flow-trigger-wake.mjs +284 -0
  124. package/engine/scripts/flow-trigger.sh +571 -0
  125. package/engine/scripts/flow_billing.py +354 -0
  126. package/engine/scripts/flow_capability_stats.py +314 -0
  127. package/engine/scripts/flow_case.py +194 -0
  128. package/engine/scripts/flow_claim.py +497 -0
  129. package/engine/scripts/flow_config.py +1024 -0
  130. package/engine/scripts/flow_failure.py +588 -0
  131. package/engine/scripts/flow_learn.py +105 -0
  132. package/engine/scripts/flow_ledger.py +235 -0
  133. package/engine/scripts/flow_policy.py +238 -0
  134. package/engine/scripts/flow_preflight.py +339 -0
  135. package/engine/scripts/flow_registry.py +341 -0
  136. package/engine/scripts/flow_retry.py +304 -0
  137. package/engine/scripts/flow_return_to_ops.py +191 -0
  138. package/engine/scripts/flow_source.py +315 -0
  139. package/engine/scripts/flow_sources/__init__.py +53 -0
  140. package/engine/scripts/flow_sources/cases_json.py +106 -0
  141. package/engine/scripts/flow_sources/common.py +428 -0
  142. package/engine/scripts/flow_sources/feishu_base.py +273 -0
  143. package/engine/scripts/flow_stale.py +185 -0
  144. package/engine/scripts/flow_status_reconcile.py +344 -0
  145. package/engine/scripts/flow_triage.py +849 -0
  146. package/engine/scripts/flow_write_verify.py +496 -0
  147. package/engine/scripts/fulfillment.js +586 -0
  148. package/engine/scripts/gen-agent-bundles.mjs +276 -0
  149. package/engine/scripts/gen-preset-rows.mjs +259 -0
  150. package/engine/scripts/init-ml.sh +2275 -0
  151. package/engine/scripts/install-internal-role.sh +190 -0
  152. package/engine/scripts/install-license.mjs +641 -0
  153. package/engine/scripts/install-one-shot.mjs +665 -0
  154. package/engine/scripts/integration_contract.py +220 -0
  155. package/engine/scripts/integrations/wenyao/adapter.py +98 -0
  156. package/engine/scripts/integrations/xzh/adapter.py +75 -0
  157. package/engine/scripts/invoice-mapping.example.json +40 -0
  158. package/engine/scripts/invoice-table.sh +194 -0
  159. package/engine/scripts/invoice_carrier_notice.py +279 -0
  160. package/engine/scripts/invoice_fail_closeout.py +297 -0
  161. package/engine/scripts/invoice_lip_runner.py +1508 -0
  162. package/engine/scripts/invoice_lip_runner.py.bak-20260922-1710-freready +1090 -0
  163. package/engine/scripts/invoice_ready_audit.py +191 -0
  164. package/engine/scripts/invoice_runner.py +675 -0
  165. package/engine/scripts/invoice_stageb.py +516 -0
  166. package/engine/scripts/launchd/com.whyshu.argent-bridge.plist.example +42 -0
  167. package/engine/scripts/launchd/com.whyshu.fulfillment-poll.plist.example +29 -0
  168. package/engine/scripts/lease.py +377 -0
  169. package/engine/scripts/lib/agent-install.mjs +649 -0
  170. package/engine/scripts/lib/argent-datadir.mjs +16 -0
  171. package/engine/scripts/lib/argent_datadir.py +262 -0
  172. package/engine/scripts/lib/argent_filelock.py +507 -0
  173. package/engine/scripts/lib/bootcheck-wiring.mjs +510 -0
  174. package/engine/scripts/lib/cdp_ports.py +197 -0
  175. package/engine/scripts/lib/customer-env.mjs +102 -0
  176. package/engine/scripts/lib/daily-report-core.mjs +517 -0
  177. package/engine/scripts/lib/dep-declaration.mjs +81 -0
  178. package/engine/scripts/lib/deps-migrate.mjs +310 -0
  179. package/engine/scripts/lib/dsh-host-resolve.mjs +109 -0
  180. package/engine/scripts/lib/dsh-scope.mjs +500 -0
  181. package/engine/scripts/lib/dsh-snapshot-path.mjs +35 -0
  182. package/engine/scripts/lib/dsh-versions.mjs +96 -0
  183. package/engine/scripts/lib/dsh-web-probe.mjs +214 -0
  184. package/engine/scripts/lib/is-direct-run.mjs +61 -0
  185. package/engine/scripts/lib/patch-compose.mjs +241 -0
  186. package/engine/scripts/lib/patch-target.mjs +35 -0
  187. package/engine/scripts/lib/plugin-lifecycle.mjs +128 -0
  188. package/engine/scripts/lib/plugin-packages.mjs +332 -0
  189. package/engine/scripts/lib/preset-compat.mjs +127 -0
  190. package/engine/scripts/lib/preset-install.mjs +575 -0
  191. package/engine/scripts/lib/preset-mechanism.mjs +56 -0
  192. package/engine/scripts/lib/preset-sync.mjs +59 -0
  193. package/engine/scripts/lib/profile-retire.mjs +97 -0
  194. package/engine/scripts/lib/python-runtime.mjs +190 -0
  195. package/engine/scripts/lib/registry.mjs +72 -0
  196. package/engine/scripts/lib/repo-root.sh +56 -0
  197. package/engine/scripts/lib/schedule-mechanism.mjs +659 -0
  198. package/engine/scripts/lib/schedule-probe.mjs +835 -0
  199. package/engine/scripts/lib/scope-pointer.mjs +164 -0
  200. package/engine/scripts/lib/settings-panels.mjs +816 -0
  201. package/engine/scripts/lib/stdio_utf8.py +86 -0
  202. package/engine/scripts/lib/wake-auth.mjs +392 -0
  203. package/engine/scripts/lib/webdriver_ipc.py +264 -0
  204. package/engine/scripts/lib/zstd-frames.mjs +104 -0
  205. package/engine/scripts/license-e2e-drill.mjs +426 -0
  206. package/engine/scripts/license-gate.mjs +245 -0
  207. package/engine/scripts/lip_backlog.py +171 -0
  208. package/engine/scripts/lip_table.py +185 -0
  209. package/engine/scripts/local-usage.mjs +214 -0
  210. package/engine/scripts/migrate-providers.mjs +127 -0
  211. package/engine/scripts/migrate-skills.sh +65 -0
  212. package/engine/scripts/ml-oauth-setup.mjs +550 -0
  213. package/engine/scripts/ml-store-ids.json +26 -0
  214. package/engine/scripts/ml_artifact_attribution.py +333 -0
  215. package/engine/scripts/ml_capacity_probe.py +1158 -0
  216. package/engine/scripts/ml_hub_status.py +1556 -0
  217. package/engine/scripts/ml_schema_check.py +115 -0
  218. package/engine/scripts/ml_store_ids.py +139 -0
  219. package/engine/scripts/npm-publish-argent.mjs +499 -0
  220. package/engine/scripts/npm-publish-argent.sh +20 -0
  221. package/engine/scripts/orchestrator.py +13811 -0
  222. package/engine/scripts/pack-plugins.mjs +140 -0
  223. package/engine/scripts/patches/dsh-llm-deepseek--transport-diagnostics.patch +297 -0
  224. package/engine/scripts/patches/dsh-session--append-message-shape.patch +15 -0
  225. package/engine/scripts/patches/dsh-session--tool-result-block-017.patch +28 -0
  226. package/engine/scripts/patches/dsh-session-format-v0-to-v1--permission-preset-origin.patch +11 -0
  227. package/engine/scripts/patches/dsh-session-format-v3-to-v4--turn-outside-replace.patch +20 -0
  228. package/engine/scripts/patches/dsh-session-persistence-jsonl--worker-bundled-migrators.patch +39 -0
  229. package/engine/scripts/patches/dsh-tools--render-return-shape.patch +50 -0
  230. package/engine/scripts/patches/verify-bundled-migrators.mjs +79 -0
  231. package/engine/scripts/patches/verify-hardening.mjs +167 -0
  232. package/engine/scripts/patches/verify-session-migration.mjs +149 -0
  233. package/engine/scripts/patches/verify-transport-diagnostics.mjs +227 -0
  234. package/engine/scripts/plan-role-rename.mjs +125 -0
  235. package/engine/scripts/plugin-bootcheck.mjs +451 -0
  236. package/engine/scripts/plugin-composition.json +15 -0
  237. package/engine/scripts/poc-mcp-host.mjs +455 -0
  238. package/engine/scripts/poll-fulfillment.sh +293 -0
  239. package/engine/scripts/poll-invoice.sh +74 -0
  240. package/engine/scripts/profile-doctor.mjs +686 -0
  241. package/engine/scripts/provider-select.sh +70 -0
  242. package/engine/scripts/provider-switch.sh +146 -0
  243. package/engine/scripts/provider-sync-target.check.mjs +64 -0
  244. package/engine/scripts/python-runtime.sh +78 -0
  245. package/engine/scripts/query_runner.py +310 -0
  246. package/engine/scripts/release-argent.sh +574 -0
  247. package/engine/scripts/repair-unresolved-tools.mjs +178 -0
  248. package/engine/scripts/run-tests.sh +256 -0
  249. package/engine/scripts/self-sign-license.mjs +179 -0
  250. package/engine/scripts/session-health-scan.mjs +63 -0
  251. package/engine/scripts/session-repair-tool-result-content.mjs +181 -0
  252. package/engine/scripts/setup.sh +22 -0
  253. package/engine/scripts/skill-install.mjs +629 -0
  254. package/engine/scripts/sku_translate.py +148 -0
  255. package/engine/scripts/sync-plugins.sh +90 -0
  256. package/engine/scripts/sync-presets.sh +27 -0
  257. package/engine/scripts/sync-scripts.sh +445 -0
  258. package/engine/scripts/telemetry.py +873 -0
  259. package/engine/scripts/ui-copy-count.mjs +220 -0
  260. package/engine/scripts/usage-anchor.sh +136 -0
  261. package/engine/scripts/usage_report.py +531 -0
  262. package/engine/scripts/validate-preset-schema.mjs +208 -0
  263. package/engine/scripts/vertical-init.mjs +323 -0
  264. package/engine/scripts/vertical-lint.mjs +482 -0
  265. package/engine/scripts/wenyao-browser.sh +73 -0
  266. package/engine/scripts/wenyao-fixture-export.py +116 -0
  267. package/engine/scripts/wenyao-invoice-writeback.mjs +540 -0
  268. package/engine/scripts/wenyao-login.sh +34 -0
  269. package/engine/scripts/wenyao-template-map.json +292 -0
  270. package/engine/scripts/wenyao_attach.py +131 -0
  271. package/engine/scripts/wenyao_download_template.py +144 -0
  272. package/engine/scripts/wenyao_fill_template.py +568 -0
  273. package/engine/scripts/wenyao_login.py +145 -0
  274. package/engine/scripts/wenyao_portal.py +633 -0
  275. package/engine/scripts/wenyao_recon.py +230 -0
  276. package/engine/scripts/wenyao_run.py +503 -0
  277. package/engine/scripts/wenyao_shadow_diff.py +160 -0
  278. package/engine/scripts/wenyao_skill_contract.py +156 -0
  279. package/engine/scripts/wenyao_template_fetch.py +175 -0
  280. package/engine/scripts/win/dsh-web-autostart.ps1 +372 -0
  281. package/engine/scripts/ziniao-auth-probe.sh +268 -0
  282. package/engine/scripts/ziniao-keepalive.sh +216 -0
  283. package/engine/scripts/ziniao-post-upgrade-check.sh +120 -0
  284. package/engine/scripts/ziniao-windows.sh +153 -0
  285. package/engine/version.mjs +1 -0
  286. package/engine/verticals/README.md +103 -0
  287. package/engine/verticals/_engine-words.baseline.txt +237 -0
  288. package/engine/verticals/_engine-words.json +19 -0
  289. package/engine/verticals/mercadolibre/README.md +43 -0
  290. package/engine/verticals/mercadolibre/config.json +709 -0
  291. package/engine/verticals/mercadolibre/flows.json +706 -0
  292. package/engine/verticals/mercadolibre/manifest.json +538 -0
  293. package/engine/verticals/mercadolibre/migrate-machine-state.mjs +138 -0
  294. package/engine/verticals/mercadolibre/preflight.py +143 -0
  295. package/engine/verticals/mercadolibre/prompts/daily-report.failure.md +69 -0
  296. package/engine/verticals/mercadolibre/prompts/daily-report.md +47 -0
  297. package/engine/verticals/mercadolibre/prompts/daily-report.scheduled.md +79 -0
  298. package/engine/verticals/mercadolibre/prompts/full.failure.md +125 -0
  299. package/engine/verticals/mercadolibre/prompts/full.md +91 -0
  300. package/engine/verticals/mercadolibre/prompts/wenyao-invoice.failure.md +88 -0
  301. package/engine/verticals/mercadolibre/prompts/wenyao-invoice.md +64 -0
  302. package/engine/verticals/mercadolibre/prompts/xzh-invoice.failure.md +91 -0
  303. package/engine/verticals/mercadolibre/prompts/xzh-invoice.md +46 -0
  304. package/package.json +21 -4
  305. package/README.md +0 -3
@@ -0,0 +1,86 @@
1
+ #!/bin/bash
2
+ # dsh-url.sh — 查看当前 dsh web 的访问地址(带 token;只读,不重启服务)
3
+ #
4
+ # 用途:dsh 是开机自启动的,想知道"现在的带 token URL"跑这个脚本即可。
5
+ # 原理:dsh 每次启动会把带 token 的 URL 打印到日志(取最后一条 = 当前进程的)。
6
+ # 注意:token 每次重启变化;已用 URL 换过 cookie 的设备(30 天有效)无需再带 token。
7
+ #
8
+ # ⑩c(2026-10-08):日志落点**不再写死 `/tmp/dsh-web.log`** —— 候选顺序的唯一真源是
9
+ # `scripts/lib/wake-auth.mjs#logPaths()`(`node scripts/lib/wake-auth.mjs --log-paths` 可取到):
10
+ # DSH_WEB_LOG → plist 的 StandardOutPath → $DSH_HOME/dsh-web.log → ~/Library/Logs/dsh-web.log
11
+ # → /tmp/dsh-web.log(历史兜底,排最后)
12
+ # 逐项试、**命中即停** ⇒ "设了 DSH_WEB_LOG 就绝不碰 /tmp"是同一个循环的自然结果,不是第二份判据。
13
+ # 全部落空 ⇒ **响亮失败**(非零退出 + 点名每个落点 + 修法),⛔ 不再打印占位提示(半静默)。
14
+ set -u
15
+
16
+ SELF="${BASH_SOURCE[0]}"
17
+ . "$(dirname "${SELF}")/lib/repo-root.sh"
18
+ REPO="$(argent_repo_root "${SELF}")"
19
+ WAKE_AUTH="${REPO}/scripts/lib/wake-auth.mjs"
20
+
21
+ if ! lsof -nP -iTCP:3080 -sTCP:LISTEN 2>/dev/null | grep -q node; then
22
+ echo "❌ dsh web 未在运行(3080 无 node 监听)"
23
+ echo " 拉起服务:bash ~/Code/argent-dsh/scripts/dsh-restart.sh"
24
+ exit 1
25
+ fi
26
+
27
+ # ── 候选落点:唯一真源(wake-auth#logPaths),逐项试、命中即停 ────────────────────
28
+ CANDS="$(node "${WAKE_AUTH}" --log-paths 2>&1)"
29
+ NODE_RC=$?
30
+ if [ "${NODE_RC}" -ne 0 ] || [ -z "${CANDS}" ]; then
31
+ {
32
+ echo "❌ 取不到日志候选落点(node ${WAKE_AUTH} --log-paths 失败,exit=${NODE_RC}):"
33
+ printf '%s\n' "${CANDS}" | sed 's/^/ /'
34
+ echo " 修法:确认 node 可用,且 ${REPO} 是完整的 argent-dsh 树(scripts/lib/wake-auth.mjs 在位)"
35
+ } >&2
36
+ exit 1
37
+ fi
38
+
39
+ LOG=""
40
+ TRIED=""
41
+ while IFS= read -r p; do
42
+ [ -n "${p}" ] || continue
43
+ if [ ! -f "${p}" ]; then
44
+ TRIED="${TRIED} ❌ ${p}:文件不存在(日志被系统清理或被运维挪走)"$'\n'
45
+ continue
46
+ fi
47
+ if grep -q "dsh web: http" "${p}" 2>/dev/null; then LOG="${p}"; break; fi
48
+ TRIED="${TRIED} ❌ ${p}:有文件,但没有「dsh web: http」那一行(多半是别的进程/旧日志)"$'\n'
49
+ done <<< "${CANDS}"
50
+
51
+ if [ -z "${LOG}" ]; then
52
+ {
53
+ echo "❌ 取不到 dsh web 的启动地址:候选日志**全部不可用**(token 只在启动那一行里,日志没了就取不到)"
54
+ printf '%s' "${TRIED}"
55
+ echo " 修法(按代价从低到高):"
56
+ echo " · 日志若被挪走,本链会自动跟随 plist 的声明:plutil -p ~/Library/LaunchAgents/com.whyshu.dsh-web.plist | grep -i path"
57
+ echo " · 重启并打印落点:bash ~/Code/argent-dsh/scripts/dsh-restart.sh"
58
+ echo " · 或显式指定落点(\":\" 分隔可给多个):export DSH_WEB_LOG=<日志路径> / export ARGENT_WAKE_LOG_PATHS=<路径1>:<路径2>"
59
+ echo " · 候选表由 scripts/lib/wake-auth.mjs#logPaths() 给出:node scripts/lib/wake-auth.mjs --log-paths"
60
+ } >&2
61
+ exit 1
62
+ fi
63
+
64
+ URL=$(grep "dsh web: http" "${LOG}" | tail -1 | sed 's/^.*dsh web: //')
65
+ if [ -z "${URL}" ]; then
66
+ echo "❌ 从日志里取不到 URL(文件 ${LOG} 命中了关键字、但解析为空)" >&2
67
+ exit 1
68
+ fi
69
+
70
+ echo "✅ dsh web 运行中"
71
+ echo " 日志落点:${LOG}"
72
+ echo
73
+ echo "本机访问:"
74
+ echo " ${URL}"
75
+ echo
76
+ # 组网(手机/其他设备)访问:同一 token 配 EasyTier IP
77
+ TOKEN=$(echo "${URL}" | sed 's/.*?token=//')
78
+ IP=$(ifconfig 2>/dev/null | grep -oE '10\.126\.126\.[0-9]+' | head -1)
79
+ if [ -n "${IP}" ] && [ -n "${TOKEN}" ]; then
80
+ echo "组网访问(手机等,需已连 EasyTier):"
81
+ echo " http://${IP}:3080/?token=${TOKEN}"
82
+ echo
83
+ fi
84
+ echo "提示:token 每次服务重启会变;已用上述 URL 换过 cookie 的设备(30 天有效)"
85
+ echo " 之后直接访问 http://127.0.0.1:3080/(或组网 IP)即可,无需再带 token。"
86
+ echo " 当前有 cookie 的老设备不受重启影响(browser-session 授权已持久化)。"
@@ -0,0 +1,155 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * dsh-web-launch —— 服务默认入口的**稳定包装脚本**(P5,2026-09-29,B 方案)
4
+ *
5
+ * LaunchAgent 不再直接调 `dsh`(那个链接会被升级重建、跟着坏版本走),而是调本脚本:
6
+ * ① 读指针 `<DSH_HOME>/argent/base/current-scope` → 拿到当前该跑哪棵树;
7
+ * ② exec `<tree>/dsh/lib/bin.js web …`(参数原样透传);
8
+ * ③ 启动失败(或起后 `--min-uptime` 秒内退出)⇒ 记事件;
9
+ * **连续 3 次**失败 ⇒ 把指针切回上一棵 known-good 树并**重启一次**;
10
+ * 回退目标也失败 ⇒ 停下并打印人工指引(不无限重启 —— 这正是历史上踩过的循环)。
11
+ *
12
+ * 为什么熔断放在这里而不是 launchd:KeepAlive 只知道"进程退了就再起",它不会判断
13
+ * "连起三次都秒退"这件事;熔断必须在**入口**这一层。
14
+ *
15
+ * 用法(LaunchAgent 用;人工排障也可直接跑):
16
+ * node scripts/dsh-web-launch.mjs [--dry-run] [--min-uptime 30] [--max-failures 3] [--] <dsh web 的参数…>
17
+ * 退出码:透传 dsh 的退出码;熔断放弃时 78(配置错误,规范用法)。
18
+ */
19
+ import { spawn } from 'node:child_process'
20
+ import { existsSync } from 'node:fs'
21
+ import { join } from 'node:path'
22
+ import {
23
+ clearFused, consecutiveFailures, looksLikeScope, previousScope, readFused, readPointer,
24
+ recordFailure, writePointer, writeFused,
25
+ } from './lib/scope-pointer.mjs'
26
+
27
+ const argv = process.argv.slice(2)
28
+ const flag = (name, dflt) => {
29
+ const i = argv.indexOf(name)
30
+ return i > -1 ? argv[i + 1] ?? dflt : dflt
31
+ }
32
+ const DRY = argv.includes('--dry-run')
33
+ const MIN_UPTIME_MS = Number(flag('--min-uptime', 30)) * 1000
34
+ const MAX_FAILURES = Number(flag('--max-failures', 3))
35
+ const NO_BOOTOUT = argv.includes('--no-bootout') // 保险丝:不动 launchd(测试/人工排障用)
36
+ const RESET_FUSE = argv.includes('--reset-fuse') // 人工确认修好后解除熔断
37
+ const LABEL = flag('--label', process.env.DSH_WEB_LABEL || 'com.whyshu.dsh-web')
38
+ const sepIdx = argv.indexOf('--')
39
+ // 只剥离 launcher 自身的参数(--dry-run / --min-uptime N / --max-failures N);
40
+ // 其余参数(含 --no-open、--trusted-host X 等 dsh 自身选项)**原样透传**。
41
+ // 2026-09-29 修复(真实事故):旧实现把全部 `--` 开头项删掉、只留下它们的值
42
+ // ⇒ dsh 收到裸的 `10.126.126.2:3080 10.126.126.1:3080` 报
43
+ // "too many arguments. Expected 0 arguments but got 2" ⇒ 服务秒退 ⇒ KeepAlive 无限重启循环。
44
+ const passthrough = (sepIdx > -1 ? argv.slice(sepIdx + 1) : (() => {
45
+ const out = []
46
+ for (let i = 0; i < argv.length; i += 1) {
47
+ const a = argv[i]
48
+ if (a === '--dry-run') continue
49
+ if (a === '--min-uptime' || a === '--max-failures' || a === '--label') { i += 1; continue }
50
+ out.push(a)
51
+ }
52
+ return out
53
+ })())
54
+
55
+ const log = (msg) => console.log(`[dsh-web-launch] ${msg}`)
56
+ const recoveryHint = () => ` 修好后解除熔断:node scripts/dsh-web-launch.mjs --reset-fuse\n` +
57
+ ` 再重载服务:bash scripts/dsh-restart.sh(或 launchctl bootstrap gui/$(id -u)/${LABEL} ~/Library/LaunchAgents/${LABEL}.plist)`
58
+
59
+ if (RESET_FUSE) {
60
+ const had = clearFused()
61
+ log(had ? '✅ 已解除熔断标记(下次启动会正常执行)' : '(本来就没有熔断标记)')
62
+ console.log(recoveryHint())
63
+ process.exit(0)
64
+ }
65
+ // 已熔断:拒绝启动,避免"回退目标也起不来"的坏状态被 launchd 无限重演
66
+ {
67
+ const fused = readFused()
68
+ if (fused) {
69
+ console.error(`[dsh-web-launch] ⛔ 处于熔断状态(${fused.at || '?'}):${fused.why || '回退目标也启动失败'}\n` +
70
+ ` 当时失败的树:${fused.scope || '?'}\n` + recoveryHint())
71
+ process.exit(78)
72
+ }
73
+ }
74
+
75
+ function binOf(scope) {
76
+ return join(scope, 'dsh', 'lib', 'bin.js')
77
+ }
78
+
79
+ /** 跑一次 dsh,返回 {code, uptimeMs};用 spawn(不 shell)以免参数被二次解释。 */
80
+ function runOnce(scope, args) {
81
+ return new Promise((resolve) => {
82
+ const started = Date.now()
83
+ const child = spawn(process.execPath, [binOf(scope), ...args], { stdio: 'inherit' })
84
+ const done = (code, signal) => resolve({ code: code ?? (signal ? 1 : 0), uptimeMs: Date.now() - started })
85
+ child.on('error', (e) => { log(`启动失败:${e.message}`); done(127) })
86
+ child.on('exit', (code, signal) => {
87
+ const up = Date.now() - started
88
+ log(`dsh 退出:code=${code} signal=${signal || '-'} 存活 ${Math.round(up / 1000)}s`)
89
+ done(code, signal)
90
+ })
91
+ if (DRY) { child.kill('SIGTERM') }
92
+ })
93
+ }
94
+
95
+ const pointer = readPointer()
96
+ log(`指针:${pointer || '(未设置)'}${DRY ? '(dry-run)' : ''}`)
97
+ if (!pointer || !looksLikeScope(pointer)) {
98
+ console.error(`[dsh-web-launch] ✗ 指针缺失或指向的不是 dsh 安装树:${pointer}\n` +
99
+ ' 修:bash scripts/dsh-restore.sh --list # 看历史与可用树\n' +
100
+ ' bash scripts/dsh-restore.sh --to <树目录>')
101
+ process.exit(78)
102
+ }
103
+
104
+ const first = await runOnce(pointer, passthrough)
105
+ const failedFast = first.code !== 0 || first.uptimeMs < MIN_UPTIME_MS
106
+ if (!failedFast) process.exit(first.code)
107
+
108
+ if (!DRY) recordFailure(process.env, { ok: false, scope: pointer, code: first.code, uptimeMs: first.uptimeMs })
109
+ const { count } = consecutiveFailures(process.env)
110
+ log(`连续失败 ${count}/${MAX_FAILURES} 次`)
111
+
112
+ if (count < MAX_FAILURES) {
113
+ process.exit(first.code) // 还没到阈值:交给 KeepAlive 再试,别急着回退
114
+ }
115
+
116
+ // ── 熔断:切回上一棵 known-good 树并重启一次 ──────────────────────
117
+ const prev = previousScope(process.env, pointer)
118
+ if (!prev) {
119
+ console.error(`[dsh-web-launch] ✗ 连续 ${count} 次失败,但审计里找不到可回退的树。\n` +
120
+ ' 人工:bash scripts/dsh-restore.sh --to <树目录>(或从整树备份恢复)')
121
+ process.exit(78)
122
+ }
123
+ log(`⛔ 熔断:连续 ${count} 次失败 ⇒ 回退到上一棵 known-good 树:${prev}`)
124
+ if (DRY) { log('(dry-run:不实际切换、不重启)'); process.exit(first.code) }
125
+ writePointer(prev, { reason: `fuse: ${count} consecutive failures on ${pointer}`, previous: pointer })
126
+
127
+ const second = await runOnce(prev, passthrough)
128
+ if (second.code === 0 || second.uptimeMs >= MIN_UPTIME_MS) {
129
+ recordFailure(process.env, { ok: true, scope: prev, note: 'fuse rollback succeeded', uptimeMs: second.uptimeMs })
130
+ process.exit(second.code)
131
+ }
132
+ recordFailure(process.env, { ok: false, scope: prev, code: second.code, note: 'rollback target also failed' })
133
+ // 真正"停下来":写熔断标记(防再次被拉起)+ bootout 掉 job(让 KeepAlive 不再拉起)
134
+ const marker = DRY ? null : writeFused(process.env, {
135
+ why: `连续 ${count} 次失败,且回退目标 ${prev} 也起不来`, scope: pointer, rollbackTarget: prev, label: LABEL,
136
+ })
137
+ if (marker) log(`已落熔断标记:${marker}`)
138
+ let booted = false
139
+ if (DRY || NO_BOOTOUT) {
140
+ log(DRY ? '(dry-run:不 bootout)' : '(--no-bootout:不动 launchd)')
141
+ } else {
142
+ try {
143
+ const { execFileSync } = await import('node:child_process')
144
+ execFileSync('launchctl', ['bootout', `gui/${process.getuid()}/${LABEL}`], { stdio: 'inherit' })
145
+ booted = true
146
+ log(`已 bootout ${LABEL} —— launchd 不会再拉起(避免无限重启循环)`)
147
+ } catch (e) {
148
+ // bootout 失败不算致命:标记仍在,下次被拉起时会拒绝启动
149
+ log(`bootout 未成功(${String(e.message || e).slice(0, 80)})—— 标记仍在,下次启动会拒绝执行`)
150
+ }
151
+ }
152
+ console.error(`[dsh-web-launch] ✗ 回退目标也起不来 ⇒ 已停止自动重试${booted ? '(job 已卸载)' : ''}。\n` +
153
+ ' 人工:bash scripts/dsh-restore.sh --list ;必要时用整树备份恢复后 --to <树>\n' +
154
+ ` 然后解除熔断:node scripts/dsh-web-launch.mjs --reset-fuse`)
155
+ process.exit(78)