@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,34 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ # 上海文鳐门户「人工过验证 + 保存登录态」入口(2026-09-10)
4
+ #
5
+ # 用法(本机或客户机都可用):
6
+ # bash scripts/wenyao-login.sh # 等 30 分钟,你在弹出的 Chrome 里过滑块 + 点登录
7
+ # bash scripts/wenyao-login.sh 600 # 等 10 分钟
8
+ # bash scripts/wenyao-login.sh --check # 只检查登录态是否还有效(不弹验证)
9
+ #
10
+ # 背景:门户登录用阿里云行为验证码(滑块),合成鼠标过不了(实测 2 次失败)且反复试会触发风控 ⇒
11
+ # 采用"人工过一次 → 复用登录态":登录成功后把 storage_state + 持久 profile 存到
12
+ # ~/.dsh/argent/(600 权限),之后的发票流程自动化直接复用,不再需要过验证。
13
+ # 凭据来自 ~/.dsh/argent/wenyao.env(600,不进仓库)。
14
+
15
+ HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
16
+ PY="${WENYAO_PY:-~/.dsh/argent/venv/bin/python3}"
17
+ if [ ! -x "$PY" ]; then
18
+ PY="$(command -v python3 || true)"
19
+ fi
20
+ if [ -z "$PY" ]; then
21
+ echo "[wenyao-login] 找不到 python3" >&2
22
+ exit 1
23
+ fi
24
+ if ! "$PY" -c "import playwright" >/dev/null 2>&1; then
25
+ echo "[wenyao-login] 当前 python 无 playwright:请用 ~/.dsh/argent/venv/bin/python3 或安装 playwright" >&2
26
+ echo " (可用 WENYAO_PY=/path/to/python3 指定)" >&2
27
+ exit 1
28
+ fi
29
+ if [ ! -f "$HOME/.dsh/argent/wenyao.env" ]; then
30
+ echo "[wenyao-login] 缺凭据文件 ~/.dsh/argent/wenyao.env(需含 WENYAO_URL/WENYAO_PHONE/WENYAO_PASSWORD,600 权限)" >&2
31
+ exit 1
32
+ fi
33
+
34
+ exec "$PY" "$HERE/wenyao_login.py" "$@"
@@ -0,0 +1,292 @@
1
+ {
2
+ "_doc": "上海文鳐《发票模版》列映射真源(2026-09-11)。运营版表头在第 7 行、数据填第 8 行(说明行会被覆盖)。source 取值:field=直接取飞书字段;calc=按算式算;const=固定值;llm=需翻译;image=附件转浮动图片;storemap=店铺→卖家ID。 numeric=true 的列按数字写入(否则门户可能不认文本数字);货件号/HS/SKU/卖家ID 一律文本(防科学计数法与丢前导零)。",
3
+ "sheet": "Sheet1",
4
+ "headerRow": 7,
5
+ "dataRow": 8,
6
+ "imageAnchor": "AA8",
7
+ "clearRowsBelow": 9,
8
+ "topBlock": {
9
+ "客户名称": {
10
+ "cell": "A2",
11
+ "source": "const",
12
+ "value": "武汉六禾园"
13
+ },
14
+ "下单时间": {
15
+ "cell": "B2",
16
+ "source": "const",
17
+ "value": "",
18
+ "note": "运营确认:非必须,留空"
19
+ },
20
+ "预计进仓时间": {
21
+ "cell": "C2",
22
+ "source": "const",
23
+ "value": "__TODAY__",
24
+ "format": "date",
25
+ "note": "运营确认:填当前日期值"
26
+ },
27
+ "委托编号": {
28
+ "cell": "D2",
29
+ "source": "const",
30
+ "value": "",
31
+ "note": "免填"
32
+ },
33
+ "起运港": {
34
+ "cell": "E2",
35
+ "source": "const",
36
+ "value": "CNYTN"
37
+ },
38
+ "目的港": {
39
+ "cell": "F2",
40
+ "source": "const",
41
+ "value": "USLGB"
42
+ },
43
+ "港前仓": {
44
+ "cell": "G2",
45
+ "source": "const",
46
+ "value": "华南仓",
47
+ "note": "2026-09-11 用户确认以运营填的华南仓为准"
48
+ },
49
+ "送货国家": {
50
+ "cell": "H2",
51
+ "source": "const",
52
+ "value": "墨西哥"
53
+ }
54
+ },
55
+ "columns": [
56
+ {
57
+ "col": "A",
58
+ "header": "我司关联单号(无需填写)",
59
+ "source": "const",
60
+ "value": ""
61
+ },
62
+ {
63
+ "col": "B",
64
+ "header": "产品中文品名",
65
+ "source": "field",
66
+ "field": "产品名称"
67
+ },
68
+ {
69
+ "col": "C",
70
+ "header": "产品英文品名",
71
+ "source": "llm",
72
+ "field": "产品名称",
73
+ "note": "中文品名 → 英文(LLM),如 42-Piece Professional Makeup Brush and Sponge Cosmetic Bag - Brown"
74
+ },
75
+ {
76
+ "col": "D",
77
+ "header": "货件号/唛头",
78
+ "source": "field",
79
+ "field": "货件号"
80
+ },
81
+ {
82
+ "col": "E",
83
+ "header": "箱序",
84
+ "source": "calc",
85
+ "expr": "1-{箱数}",
86
+ "note": "运营批注:支持正整数/逗号/中横线/波浪线"
87
+ },
88
+ {
89
+ "col": "F",
90
+ "header": "SKU",
91
+ "source": "field",
92
+ "field": "SKU"
93
+ },
94
+ {
95
+ "col": "G",
96
+ "header": "卖家ID",
97
+ "source": "storemap",
98
+ "field": "店铺"
99
+ },
100
+ {
101
+ "col": "H",
102
+ "header": "单箱产品数量",
103
+ "source": "calc",
104
+ "expr": "{数量}/{箱数}"
105
+ },
106
+ {
107
+ "col": "I",
108
+ "header": "总产品数量",
109
+ "source": "field",
110
+ "field": "数量",
111
+ "numeric": true
112
+ },
113
+ {
114
+ "col": "J",
115
+ "header": "总箱数",
116
+ "source": "field",
117
+ "field": "箱数",
118
+ "note": "lip 表箱数是公式列,读值",
119
+ "numeric": true
120
+ },
121
+ {
122
+ "col": "K",
123
+ "header": "单箱总重",
124
+ "source": "field",
125
+ "field": "重量",
126
+ "numeric": true
127
+ },
128
+ {
129
+ "col": "L",
130
+ "header": "单箱产品净重",
131
+ "source": "field",
132
+ "field": "重量",
133
+ "numeric": true
134
+ },
135
+ {
136
+ "col": "M",
137
+ "header": "货箱总重",
138
+ "source": "calc",
139
+ "expr": "{重量}*{箱数}"
140
+ },
141
+ {
142
+ "col": "N",
143
+ "header": "货箱长度",
144
+ "source": "field",
145
+ "field": "长",
146
+ "numeric": true
147
+ },
148
+ {
149
+ "col": "O",
150
+ "header": "货箱宽度",
151
+ "source": "field",
152
+ "field": "宽",
153
+ "numeric": true
154
+ },
155
+ {
156
+ "col": "P",
157
+ "header": "货箱高度",
158
+ "source": "field",
159
+ "field": "高",
160
+ "numeric": true
161
+ },
162
+ {
163
+ "col": "Q",
164
+ "header": "单件方数",
165
+ "source": "calc",
166
+ "expr": "{长}*{宽}*{高}/1000000",
167
+ "numberFormat": "0.000000"
168
+ },
169
+ {
170
+ "col": "R",
171
+ "header": "总方数",
172
+ "source": "calc",
173
+ "expr": "({长}*{宽}*{高}/1000000)*{箱数}",
174
+ "numberFormat": "0.000000"
175
+ },
176
+ {
177
+ "col": "S",
178
+ "header": "产品材质",
179
+ "source": "const",
180
+ "value": "{材质},{材质英文}",
181
+ "note": "运营示例为『塑料,plastics』⇒ 中英双语。材质英文走**三级解析**:① per-SKU 字典(<数据目录>/lip-sku-dict.json,键=SKU,优先 confirmed:true 的「材质英文」)→ ② 本映射的 `materialEn` 小词典 → ③ 会话传入(`--material-en` / 行内 `材质英文`,政策A 允许 LLM 译)。三级都没命中 ⇒ 填报**阻断**(不落盘)并指路「请翻译成英文后用 --material-en 重跑」;③ 命中时真跑会写回字典标 `confirmed:false`。⛔ HS 编码那条人工红线只管 HS。",
182
+ "perRow": true,
183
+ "perRowNote": "本列**随行变化**(每票材质不同,与货件号同级)⇒ 影子对比器按 `perRow` 放行、不再要求与黄金样本逐字相同;该列的判据改由填报器的三级解析 + 阻断兜住(⛔ 不是「英文为空就不管」)。"
184
+ },
185
+ {
186
+ "col": "T",
187
+ "header": "产品用途",
188
+ "source": "const",
189
+ "value": "家用"
190
+ },
191
+ {
192
+ "col": "U",
193
+ "header": "产品品牌",
194
+ "source": "const",
195
+ "value": "无"
196
+ },
197
+ {
198
+ "col": "V",
199
+ "header": "产品型号",
200
+ "source": "const",
201
+ "value": "无"
202
+ },
203
+ {
204
+ "col": "W",
205
+ "header": "产品申报单价",
206
+ "source": "const",
207
+ "value": 7
208
+ },
209
+ {
210
+ "col": "X",
211
+ "header": "产品申报总价",
212
+ "source": "calc",
213
+ "expr": "7*{数量}"
214
+ },
215
+ {
216
+ "col": "Y",
217
+ "header": "申报币种",
218
+ "source": "const",
219
+ "value": "USD"
220
+ },
221
+ {
222
+ "col": "Z",
223
+ "header": "产品海关编码",
224
+ "source": "field",
225
+ "field": "HS编码"
226
+ },
227
+ {
228
+ "col": "AA",
229
+ "header": "产品图片",
230
+ "source": "image",
231
+ "field": "产品图",
232
+ "note": "lip 附件 → 下载 → 以浮动图片插入本格(锚点 AA8 = 数据行「*产品图片」列)。**必须缩放到装得进单元格**:AA 列宽 13 ≈ 96px、行高 40pt ≈ 53px,原先写死 120px 会溢出(用户 2026-09-11 实测反馈)。",
233
+ "anchor": "AA8"
234
+ },
235
+ {
236
+ "col": "AB",
237
+ "header": "是否带电",
238
+ "source": "field",
239
+ "field": "是否带电",
240
+ "default": "否"
241
+ },
242
+ {
243
+ "col": "AC",
244
+ "header": "是否带磁",
245
+ "source": "field",
246
+ "field": "是否带磁",
247
+ "default": "否"
248
+ },
249
+ {
250
+ "col": "AD",
251
+ "header": "危险品",
252
+ "source": "const",
253
+ "value": "否"
254
+ },
255
+ {
256
+ "col": "AE",
257
+ "header": "是否单证报关",
258
+ "source": "const",
259
+ "value": "否"
260
+ },
261
+ {
262
+ "col": "AF",
263
+ "header": "是否投保",
264
+ "source": "const",
265
+ "value": "否",
266
+ "note": "2026-09-11 用户确认填否;门户模板有此列,运营版没有"
267
+ },
268
+ {
269
+ "col": "AG",
270
+ "header": "仓库编码",
271
+ "source": "const",
272
+ "value": "MXRC03",
273
+ "note": "2026-09-11 用户确认 MXRC03(门户显示 + 鑫中航 mapping 一致;运营说明里的 MXCR03 视为笔误)"
274
+ }
275
+ ],
276
+ "materialEn": {
277
+ "塑料": "plastics",
278
+ "牛津布": "oxford fabric",
279
+ "不锈钢": "stainless steel",
280
+ "硅胶": "silicone",
281
+ "玻璃": "glass",
282
+ "纸": "paper",
283
+ "木": "wood",
284
+ "金属": "metal"
285
+ },
286
+ "knownDivergence": {
287
+ "是否投保": "门户自带《跨境电商-下单模板》有『*是否投保』列,运营版表头没有;若导入时门户要求,需确认以哪版为准(用户 2026-09-11 确认:填『否』)",
288
+ "仓库编码列位": "门户模板:是否投保在 AF、仓库编码在 AG(运营版没有是否投保、仓库编码在 AF)⇒ 以门户模板为准"
289
+ },
290
+ "templateSource": "门户下载《跨境电商-下单模板.xlsx》(~/.dsh/argent/wenyao-downloads/);运营版《上海文鳐发票模版.xlsx》仅作填法说明用",
291
+ "_storeIdsNote": "店铺→卖家ID 已**移出本文件**(2026-09-19):真源唯一为 `scripts/ml-store-ids.json`,由 `scripts/ml_store_ids.py` 解析。原先三处各存一份(本文件裸键 '1店' / invoice-mapping.json 短名带后缀 / lip-po-mapping.json 完整店名),鑫中航那条线因匹配不上而静默回退成紫鸟 store_id,6 张发票写错。"
292
+ }
@@ -0,0 +1,131 @@
1
+ #!/usr/bin/env python3
2
+ """wenyao_attach.py — 连到「长驻文鳐浏览器」(CDP) 做预填 / 登录态检查 / 截图(2026-09-10)
3
+
4
+ 配合 wenyao-browser.sh:Chrome 以独立 profile + `--remote-debugging-port=9333` 长驻,
5
+ 本脚本用 Playwright `connect_over_cdp` **接到那个浏览器**(不新开、不关它),因此:
6
+ · 你人工过一次滑块后,登录态在浏览器与 profile 里都留着,可**重复使用**;
7
+ · 后续自动化直接驱动同一个窗口,你能看着它操作;出问题也能人工接手。
8
+
9
+ 只读:不导入订单、不导出文件、不改对方任何业务数据。
10
+ 用法:
11
+ python3 wenyao_attach.py --prefill # 预填手机号/密码(便于人工只滑滑块)
12
+ python3 wenyao_attach.py --status # 打印当前 URL / 是否已登录 / 页面顶部文案
13
+ python3 wenyao_attach.py --shot a.png # 截图(供人工/AI 查看)
14
+ """
15
+ import argparse
16
+ import json
17
+ import os
18
+ import sys
19
+ from pathlib import Path
20
+ from playwright.sync_api import sync_playwright
21
+
22
+ HOME = Path.home()
23
+ # 数据目录:**唯一判据**在 `scripts/lib/argent_datadir.py`(三级链,与 JS 内核同语义)
24
+ sys.path.insert(0, str(Path(__file__).resolve().parent / 'lib'))
25
+ from argent_datadir import resolve_data_dir # noqa: E402 —— 勿在此复制判据
26
+ DATA = Path(resolve_data_dir()['dir'])
27
+ CDP = os.environ.get("WENYAO_CDP", "http://127.0.0.1:9333")
28
+
29
+
30
+ def load_env():
31
+ env = {}
32
+ f = DATA / "wenyao.env"
33
+ if f.exists():
34
+ for line in f.read_text(encoding="utf-8").splitlines():
35
+ line = line.strip()
36
+ if line and not line.startswith("#") and "=" in line:
37
+ k, v = line.split("=", 1)
38
+ env[k.strip()] = v.strip()
39
+ env.setdefault("WENYAO_URL", "https://my.ffl-tech.com")
40
+ return env
41
+
42
+
43
+ def pick_page(browser, url):
44
+ pages = [p for c in browser.contexts for p in c.pages]
45
+ for p in pages:
46
+ if "ffl-tech" in (p.url or ""):
47
+ return p
48
+ return pages[0] if pages else None
49
+
50
+
51
+ def body(page):
52
+ try:
53
+ return page.evaluate("() => (document.body.innerText||'').replace(/\\s+/g,' ')")
54
+ except Exception:
55
+ return ""
56
+
57
+
58
+ def logged_in(page):
59
+ t = body(page)
60
+ if "请按住滑块" in t or "拖动到最右" in t:
61
+ return False
62
+ if "账号密码登录" in t and "短信验证登录" in t:
63
+ return False
64
+ return any(k in t for k in ("退出登录", "个人中心", "导入订单", "订单管理", "我的订单", "头程", "发票"))
65
+
66
+
67
+ def main():
68
+ ap = argparse.ArgumentParser()
69
+ ap.add_argument("--prefill", action="store_true")
70
+ ap.add_argument("--status", action="store_true")
71
+ ap.add_argument("--shot")
72
+ ap.add_argument("--entries", action="store_true", help="打印页面上的入口文本(找模板下载入口)")
73
+ a = ap.parse_args()
74
+ env = load_env()
75
+ out = {"cdp": CDP}
76
+ with sync_playwright() as p:
77
+ try:
78
+ browser = p.chromium.connect_over_cdp(CDP, timeout=8000)
79
+ except Exception as e:
80
+ print(json.dumps({"ok": False, "why": f"连不上 CDP({CDP}):{str(e)[:120]}",
81
+ "hint": "先跑 bash scripts/wenyao-browser.sh start"}, ensure_ascii=False))
82
+ return 1
83
+ page = pick_page(browser, env["WENYAO_URL"])
84
+ if page is None:
85
+ c = browser.contexts[0] if browser.contexts else browser.new_context()
86
+ page = c.new_page()
87
+ page.goto(env["WENYAO_URL"], wait_until="domcontentloaded", timeout=45000)
88
+ page.wait_for_timeout(3000)
89
+ out["url"] = page.url
90
+ if a.prefill:
91
+ # 门户是 Vue SPA:CDP 连上时表单可能还没渲染 ⇒ 先等密码框出现(最多 25s,重试 3 轮)
92
+ for _ in range(3):
93
+ try:
94
+ page.wait_for_selector("input[type=password]", timeout=25000)
95
+ break
96
+ except Exception:
97
+ page.wait_for_timeout(1500)
98
+ filled = {"user": False, "pwd": False}
99
+ for el in page.query_selector_all("input"):
100
+ try:
101
+ if not el.is_visible():
102
+ continue
103
+ t = (el.get_attribute("type") or "text").lower()
104
+ if t == "password" and not filled["pwd"]:
105
+ el.fill(env.get("WENYAO_PASSWORD", "")); filled["pwd"] = True
106
+ elif t in ("text", "tel", "number", "") and not filled["user"]:
107
+ el.fill(env.get("WENYAO_PHONE", "")); filled["user"] = True
108
+ except Exception:
109
+ continue
110
+ out["prefill"] = filled
111
+ if a.shot:
112
+ page.screenshot(path=a.shot, full_page=True)
113
+ out["shot"] = a.shot
114
+ if a.entries:
115
+ try:
116
+ ents = page.evaluate("""() => Array.from(document.querySelectorAll('a,button,li,span,div'))
117
+ .map(e=>(e.innerText||'').trim()).filter(t=>t&&t.length<28)
118
+ .filter((v,i,arr)=>arr.indexOf(v)===i).slice(0,120)""")
119
+ except Exception:
120
+ ents = []
121
+ out["entries"] = ents
122
+ out["interesting"] = [e for e in ents if any(k in e for k in ("模板", "模版", "下载", "导入", "导出", "订单", "发票"))][:20]
123
+ t = body(page)
124
+ out["logged_in"] = logged_in(page)
125
+ out["text_head"] = t[:200]
126
+ print(json.dumps(out, ensure_ascii=False))
127
+ return 0
128
+
129
+
130
+ if __name__ == "__main__":
131
+ raise SystemExit(main())
@@ -0,0 +1,144 @@
1
+ #!/usr/bin/env python3
2
+ """wenyao_download_template.py — 从文鳐门户下载「导入模版」并解析其结构(2026-09-10)
3
+
4
+ 背景:用户提示"登录后进系统找找能否有模板下载入口"。实测**有**:登录 → 跨境电商订单页 →
5
+ 「导入订单」弹窗里有「下载导入模版 / 跨境电商-下单模板.xlsx」。本脚本把它下载到本机固定目录
6
+ 并输出结构(sheet 名 + 表头列),用于确定"按货代路由的模板填写规则"。
7
+
8
+ 安全边界:只**下载模板**;不选任何文件、不点「导入」、不点导出/取消订单;下载后关闭弹窗。
9
+
10
+ 用法:python3 scripts/wenyao_download_template.py [--out-dir ~/.dsh/argent/wenyao-downloads]
11
+ """
12
+ import argparse
13
+ import json
14
+ import os
15
+ import sys
16
+ from pathlib import Path
17
+ from playwright.sync_api import sync_playwright
18
+
19
+ HOME = Path.home()
20
+ # 数据目录:**唯一判据**在 `scripts/lib/argent_datadir.py`(三级链,与 JS 内核同语义)
21
+ sys.path.insert(0, str(Path(__file__).resolve().parent / 'lib'))
22
+ from argent_datadir import resolve_data_dir # noqa: E402 —— 勿在此复制判据
23
+ DATA = Path(resolve_data_dir()['dir'])
24
+ DEFAULT_OUT = DATA / "wenyao-downloads"
25
+ CDP = os.environ.get("WENYAO_CDP", "http://127.0.0.1:9333")
26
+
27
+
28
+ def summarize_xlsx(path):
29
+ try:
30
+ import openpyxl
31
+ except Exception as e:
32
+ return {"err": f"openpyxl 不可用: {e}"}
33
+ try:
34
+ wb = openpyxl.load_workbook(path, data_only=True, read_only=True)
35
+ out = {"sheets": wb.sheetnames, "detail": {}}
36
+ for ws in wb.worksheets:
37
+ rows = []
38
+ for i, r in enumerate(ws.iter_rows(values_only=True)):
39
+ if i > 4:
40
+ break
41
+ rows.append([str(c)[:24] if c is not None else "" for c in r][:18])
42
+ out["detail"][ws.title] = {"dims": f"{ws.max_row}x{ws.max_column}", "head": rows}
43
+ return out
44
+ except Exception as e:
45
+ return {"err": str(e)[:200]}
46
+
47
+
48
+ def main():
49
+ ap = argparse.ArgumentParser()
50
+ ap.add_argument("--out-dir", default=str(DEFAULT_OUT))
51
+ a = ap.parse_args()
52
+ out_dir = Path(a.out_dir)
53
+ out_dir.mkdir(parents=True, exist_ok=True)
54
+ os.chmod(out_dir, 0o700)
55
+ res = {}
56
+ with sync_playwright() as p:
57
+ browser = p.chromium.connect_over_cdp(CDP, timeout=8000)
58
+ pages = [pg for c in browser.contexts for pg in c.pages]
59
+ page = next((pg for pg in pages if "ffl-tech" in (pg.url or "")), pages[0])
60
+ # 关掉可能残留的弹窗,保证从干净状态开始
61
+ try:
62
+ page.keyboard.press("Escape")
63
+ page.wait_for_timeout(600)
64
+ except Exception:
65
+ pass
66
+ opened = False
67
+ for sel in ["button:has-text('导入订单')", "text=导入订单"]:
68
+ try:
69
+ el = page.query_selector(sel)
70
+ if el and el.is_visible():
71
+ el.click(); opened = True; break
72
+ except Exception:
73
+ continue
74
+ page.wait_for_timeout(2500)
75
+ res["dialog_opened"] = opened
76
+ # 找下载入口(文本可能是"下载导入模版"或"跨境电商-下单模板.xlsx")
77
+ target = None
78
+ for sel in ["text=下载导入模版", "text=下载导入模板", "text=跨境电商-下单模板.xlsx",
79
+ "a:has-text('模板')", "button:has-text('模板')"]:
80
+ try:
81
+ el = page.query_selector(sel)
82
+ if el and el.is_visible():
83
+ target = sel
84
+ break
85
+ except Exception:
86
+ continue
87
+ res["download_selector"] = target
88
+ if target:
89
+ # 关键:浏览器是 open -na 启动的(非 Playwright 启动)⇒ 收不到 Playwright 的 download 事件。
90
+ # 直接用 CDP 设置下载行为,把文件落到我们的目录,再轮询目录取新文件。
91
+ before = {f.name for f in out_dir.iterdir()} if out_dir.exists() else set()
92
+ try:
93
+ try:
94
+ sess = page.context.new_cdp_session(page)
95
+ sess.send("Browser.setDownloadBehavior",
96
+ {"behavior": "allow", "downloadPath": str(out_dir), "eventsEnabled": True})
97
+ res["cdp_download_behavior"] = True
98
+ except Exception as e:
99
+ res["cdp_download_behavior"] = f"err: {str(e)[:100]}"
100
+ page.click(target)
101
+ import time as _t
102
+ dest = None
103
+ for _ in range(40):
104
+ page.wait_for_timeout(800)
105
+ now = {f.name for f in out_dir.iterdir()}
106
+ new_files = [f for f in out_dir.iterdir() if f.name not in before and not f.name.endswith('.crdownload')]
107
+ if new_files:
108
+ dest = max(new_files, key=lambda f: f.stat().st_mtime)
109
+ break
110
+ if dest:
111
+ os.chmod(dest, 0o600)
112
+ res["saved"] = {"path": str(dest), "bytes": dest.stat().st_size, "name": dest.name}
113
+ if dest.suffix.lower() in (".xlsx", ".xls", ".xlsm"):
114
+ res["structure"] = summarize_xlsx(dest)
115
+ else:
116
+ res["download_err"] = "点击后 32s 内目录里没有新文件(可能弹了新标签页/需登录态刷新/是邮件发送而非下载)"
117
+ except Exception as e:
118
+ res["download_err"] = str(e)[:200]
119
+ # 关闭弹窗(只关不提交)
120
+ closed = False
121
+ for sel in ["button:has-text('取消')", ".next-dialog-close", "text=取消"]:
122
+ try:
123
+ el = page.query_selector(sel)
124
+ if el and el.is_visible():
125
+ el.click(); closed = True; break
126
+ except Exception:
127
+ continue
128
+ if not closed:
129
+ try:
130
+ page.keyboard.press("Escape")
131
+ except Exception:
132
+ pass
133
+ res["dialog_closed"] = closed
134
+ page.wait_for_timeout(800)
135
+ try:
136
+ page.screenshot(path=str(DATA / "wenyao-probe" / "62-after-template-download.png"), full_page=True)
137
+ except Exception:
138
+ pass
139
+ print(json.dumps(res, ensure_ascii=False, indent=1))
140
+ return 0
141
+
142
+
143
+ if __name__ == "__main__":
144
+ raise SystemExit(main())