@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.
- package/MANIFEST.json +341 -0
- package/engine/VERSION +1 -0
- package/engine/agents/catalog.json +454 -0
- package/engine/configs/_aliases.proposed.json +651 -0
- package/engine/configs/_migration-plan.proposed.json +899 -0
- package/engine/configs/account.json +272 -0
- package/engine/configs/advanced.json +205 -0
- package/engine/configs/host.json +149 -0
- package/engine/configs/hr.json +27 -0
- package/engine/configs/notify.json +264 -0
- package/engine/core/cli/argent.mjs +277 -0
- package/engine/core/contracts/argent.contracts.json +1065 -0
- package/engine/core/contracts/verbs.schema.json +2539 -0
- package/engine/core/lib/argent-datadir.mjs +223 -0
- package/engine/core/lib/audit.mjs +187 -0
- package/engine/core/lib/claim.mjs +258 -0
- package/engine/core/lib/config-catalog.mjs +1172 -0
- package/engine/core/lib/doctor-customer.mjs +577 -0
- package/engine/core/lib/flow-list.mjs +138 -0
- package/engine/core/lib/flow-registry.mjs +48 -0
- package/engine/core/lib/init.mjs +247 -0
- package/engine/core/lib/ledger.mjs +124 -0
- package/engine/core/lib/license-activate.mjs +813 -0
- package/engine/core/lib/license-device.mjs +314 -0
- package/engine/core/lib/license-file.mjs +349 -0
- package/engine/core/lib/license-guard.mjs +123 -0
- package/engine/core/lib/license-ops.mjs +1645 -0
- package/engine/core/lib/license-verdict.mjs +133 -0
- package/engine/core/lib/license.mjs +577 -0
- package/engine/core/lib/notify/dedup.mjs +101 -0
- package/engine/core/lib/notify/feishu.mjs +38 -0
- package/engine/core/lib/notify/index.mjs +95 -0
- package/engine/core/lib/notify/verb.mjs +327 -0
- package/engine/core/lib/notify/webhook.mjs +135 -0
- package/engine/core/lib/notify/wecom.mjs +36 -0
- package/engine/core/lib/python.mjs +145 -0
- package/engine/core/lib/sop.mjs +116 -0
- package/engine/core/lib/versions.mjs +205 -0
- package/engine/core/mcp/client.mjs +67 -0
- package/engine/core/mcp/http.mjs +138 -0
- package/engine/core/mcp/server.mjs +702 -0
- package/engine/scripts/_engine_rules_probe.py +15 -0
- package/engine/scripts/analyze-full-day.py +568 -0
- package/engine/scripts/archive/feishu-bridge.js +246 -0
- package/engine/scripts/argent-agents.mjs +527 -0
- package/engine/scripts/argent-capabilities.mjs +776 -0
- package/engine/scripts/argent-catalog.mjs +186 -0
- package/engine/scripts/argent-datadir.py +62 -0
- package/engine/scripts/argent-doctor.mjs +624 -0
- package/engine/scripts/argent-env-write.mjs +302 -0
- package/engine/scripts/argent-schedule.mjs +620 -0
- package/engine/scripts/argent-setup-check.mjs +369 -0
- package/engine/scripts/argent-upgrade.mjs +1046 -0
- package/engine/scripts/base-bootstrap.sh +576 -0
- package/engine/scripts/billing-mode-daily.sh +13 -0
- package/engine/scripts/build-engine-package.mjs +126 -0
- package/engine/scripts/capability-packs.lock.json +484 -0
- package/engine/scripts/capability_pack.py +1242 -0
- package/engine/scripts/check-1.0-criteria.mjs +355 -0
- package/engine/scripts/check-agent-catalog.mjs +141 -0
- package/engine/scripts/check-billing-mode.sh +378 -0
- package/engine/scripts/check-child-sessions.mjs +83 -0
- package/engine/scripts/check-config-catalog.mjs +677 -0
- package/engine/scripts/check-docs-drift.mjs +522 -0
- package/engine/scripts/check-dsh-web-expose.sh +98 -0
- package/engine/scripts/check-judgment-drift.mjs +403 -0
- package/engine/scripts/check-license.mjs +199 -0
- package/engine/scripts/check-model-auth.py +443 -0
- package/engine/scripts/check-pack-closure.mjs +661 -0
- package/engine/scripts/check-portable-symbols.mjs +116 -0
- package/engine/scripts/check-preset-landing.mjs +124 -0
- package/engine/scripts/check-production-home.mjs +602 -0
- package/engine/scripts/check-role-mapping.mjs +461 -0
- package/engine/scripts/check-sample-redaction.mjs +320 -0
- package/engine/scripts/check-skill-classification.mjs +188 -0
- package/engine/scripts/check-sop-consistency.mjs +431 -0
- package/engine/scripts/check-test-env-safety.mjs +627 -0
- package/engine/scripts/check-version-consistency.mjs +452 -0
- package/engine/scripts/ci-run.sh +558 -0
- package/engine/scripts/collect-evidence.mjs +42 -0
- package/engine/scripts/config-explain.mjs +278 -0
- package/engine/scripts/configure-provider.rb +29 -0
- package/engine/scripts/customer-config-migrate.mjs +179 -0
- package/engine/scripts/customer-preflight.py +892 -0
- package/engine/scripts/customer-readiness.sh +135 -0
- package/engine/scripts/daily-report-inbox.py +242 -0
- package/engine/scripts/daily-report-reconcile.mjs +312 -0
- package/engine/scripts/daily-report.mjs +1310 -0
- package/engine/scripts/daily-report.sh +47 -0
- package/engine/scripts/data/lip-product-dict.json +306 -0
- package/engine/scripts/deliver-customer.mjs +932 -0
- package/engine/scripts/delivery-faces.txt +31 -0
- package/engine/scripts/desktop-trial.sh +146 -0
- package/engine/scripts/dev-window.sh +261 -0
- package/engine/scripts/drill-clean-machine.sh +315 -0
- package/engine/scripts/dsh-api-client.mjs +215 -0
- package/engine/scripts/dsh-backup-scope.sh +83 -0
- package/engine/scripts/dsh-offline-pack.mjs +77 -0
- package/engine/scripts/dsh-overlay-pin.sh +87 -0
- package/engine/scripts/dsh-plane.mjs +153 -0
- package/engine/scripts/dsh-portforward.py +223 -0
- package/engine/scripts/dsh-preflight.mjs +179 -0
- package/engine/scripts/dsh-release-watch-daily.sh +19 -0
- package/engine/scripts/dsh-release-watch.mjs +458 -0
- package/engine/scripts/dsh-remote-check.sh +99 -0
- package/engine/scripts/dsh-restart.sh +179 -0
- package/engine/scripts/dsh-restore.sh +111 -0
- package/engine/scripts/dsh-scope-rewire.mjs +803 -0
- package/engine/scripts/dsh-snapshot.mjs +116 -0
- package/engine/scripts/dsh-upgrade-readiness.mjs +165 -0
- package/engine/scripts/dsh-upgrade.mjs +612 -0
- package/engine/scripts/dsh-url.sh +86 -0
- package/engine/scripts/dsh-web-launch.mjs +155 -0
- package/engine/scripts/ensure-store-windows.py +509 -0
- package/engine/scripts/entitlements.py +458 -0
- package/engine/scripts/env_probe.py +411 -0
- package/engine/scripts/feishu-card.mjs +252 -0
- package/engine/scripts/final-check.mjs +43 -0
- package/engine/scripts/fix-skill-frontmatter.py +209 -0
- package/engine/scripts/flow-auto-retry.py +454 -0
- package/engine/scripts/flow-requirements.json +735 -0
- package/engine/scripts/flow-scaffold.py +275 -0
- package/engine/scripts/flow-timers-plist.sh +87 -0
- package/engine/scripts/flow-timers.sh +184 -0
- package/engine/scripts/flow-trigger-wake.mjs +284 -0
- package/engine/scripts/flow-trigger.sh +571 -0
- package/engine/scripts/flow_billing.py +354 -0
- package/engine/scripts/flow_capability_stats.py +314 -0
- package/engine/scripts/flow_case.py +194 -0
- package/engine/scripts/flow_claim.py +497 -0
- package/engine/scripts/flow_config.py +1025 -0
- package/engine/scripts/flow_failure.py +588 -0
- package/engine/scripts/flow_learn.py +105 -0
- package/engine/scripts/flow_ledger.py +235 -0
- package/engine/scripts/flow_policy.py +238 -0
- package/engine/scripts/flow_preflight.py +339 -0
- package/engine/scripts/flow_registry.py +341 -0
- package/engine/scripts/flow_retry.py +304 -0
- package/engine/scripts/flow_return_to_ops.py +191 -0
- package/engine/scripts/flow_source.py +315 -0
- package/engine/scripts/flow_sources/__init__.py +53 -0
- package/engine/scripts/flow_sources/cases_json.py +106 -0
- package/engine/scripts/flow_sources/common.py +428 -0
- package/engine/scripts/flow_sources/feishu_base.py +273 -0
- package/engine/scripts/flow_stale.py +185 -0
- package/engine/scripts/flow_status_reconcile.py +344 -0
- package/engine/scripts/flow_triage.py +849 -0
- package/engine/scripts/flow_write_verify.py +496 -0
- package/engine/scripts/fulfillment.js +586 -0
- package/engine/scripts/gen-agent-bundles.mjs +276 -0
- package/engine/scripts/gen-preset-rows.mjs +259 -0
- package/engine/scripts/init-ml.sh +2278 -0
- package/engine/scripts/install-internal-role.sh +190 -0
- package/engine/scripts/install-license.mjs +641 -0
- package/engine/scripts/install-one-shot.mjs +665 -0
- package/engine/scripts/integration_contract.py +220 -0
- package/engine/scripts/integrations/wenyao/adapter.py +98 -0
- package/engine/scripts/integrations/xzh/adapter.py +75 -0
- package/engine/scripts/invoice-mapping.example.json +40 -0
- package/engine/scripts/invoice-table.sh +195 -0
- package/engine/scripts/invoice_carrier_notice.py +279 -0
- package/engine/scripts/invoice_fail_closeout.py +297 -0
- package/engine/scripts/invoice_lip_runner.py +1508 -0
- package/engine/scripts/invoice_lip_runner.py.bak-20260922-1710-freready +1090 -0
- package/engine/scripts/invoice_ready_audit.py +191 -0
- package/engine/scripts/invoice_runner.py +675 -0
- package/engine/scripts/invoice_stageb.py +516 -0
- package/engine/scripts/launchd/com.whyshu.argent-bridge.plist.example +42 -0
- package/engine/scripts/launchd/com.whyshu.fulfillment-poll.plist.example +29 -0
- package/engine/scripts/lease.py +377 -0
- package/engine/scripts/lib/agent-install.mjs +649 -0
- package/engine/scripts/lib/argent-datadir.mjs +16 -0
- package/engine/scripts/lib/argent-datadir.sh +18 -0
- package/engine/scripts/lib/argent_datadir.py +285 -0
- package/engine/scripts/lib/argent_filelock.py +507 -0
- package/engine/scripts/lib/bootcheck-wiring.mjs +510 -0
- package/engine/scripts/lib/cdp_ports.py +197 -0
- package/engine/scripts/lib/customer-env.mjs +102 -0
- package/engine/scripts/lib/daily-report-core.mjs +517 -0
- package/engine/scripts/lib/dep-declaration.mjs +81 -0
- package/engine/scripts/lib/deps-migrate.mjs +310 -0
- package/engine/scripts/lib/dsh-host-resolve.mjs +109 -0
- package/engine/scripts/lib/dsh-scope.mjs +500 -0
- package/engine/scripts/lib/dsh-snapshot-path.mjs +35 -0
- package/engine/scripts/lib/dsh-versions.mjs +96 -0
- package/engine/scripts/lib/dsh-web-probe.mjs +214 -0
- package/engine/scripts/lib/is-direct-run.mjs +61 -0
- package/engine/scripts/lib/patch-compose.mjs +241 -0
- package/engine/scripts/lib/patch-target.mjs +35 -0
- package/engine/scripts/lib/plugin-lifecycle.mjs +128 -0
- package/engine/scripts/lib/plugin-packages.mjs +332 -0
- package/engine/scripts/lib/preset-compat.mjs +127 -0
- package/engine/scripts/lib/preset-install.mjs +575 -0
- package/engine/scripts/lib/preset-mechanism.mjs +56 -0
- package/engine/scripts/lib/preset-sync.mjs +59 -0
- package/engine/scripts/lib/profile-retire.mjs +97 -0
- package/engine/scripts/lib/python-runtime.mjs +190 -0
- package/engine/scripts/lib/registry.mjs +72 -0
- package/engine/scripts/lib/repo-root.sh +56 -0
- package/engine/scripts/lib/schedule-mechanism.mjs +659 -0
- package/engine/scripts/lib/schedule-probe.mjs +835 -0
- package/engine/scripts/lib/scope-pointer.mjs +164 -0
- package/engine/scripts/lib/settings-panels.mjs +816 -0
- package/engine/scripts/lib/stdio_utf8.py +86 -0
- package/engine/scripts/lib/wake-auth.mjs +392 -0
- package/engine/scripts/lib/webdriver_ipc.py +264 -0
- package/engine/scripts/lib/zstd-frames.mjs +104 -0
- package/engine/scripts/license-e2e-drill.mjs +426 -0
- package/engine/scripts/license-gate.mjs +245 -0
- package/engine/scripts/lip_backlog.py +171 -0
- package/engine/scripts/lip_table.py +185 -0
- package/engine/scripts/local-usage.mjs +214 -0
- package/engine/scripts/migrate-providers.mjs +127 -0
- package/engine/scripts/migrate-skills.sh +65 -0
- package/engine/scripts/ml-oauth-setup.mjs +550 -0
- package/engine/scripts/ml-store-ids.json +26 -0
- package/engine/scripts/ml_artifact_attribution.py +333 -0
- package/engine/scripts/ml_capacity_probe.py +1158 -0
- package/engine/scripts/ml_hub_status.py +1556 -0
- package/engine/scripts/ml_schema_check.py +115 -0
- package/engine/scripts/ml_store_ids.py +139 -0
- package/engine/scripts/npm-publish-argent.mjs +499 -0
- package/engine/scripts/npm-publish-argent.sh +20 -0
- package/engine/scripts/orchestrator.py +13811 -0
- package/engine/scripts/pack-plugins.mjs +140 -0
- package/engine/scripts/patches/dsh-llm-deepseek--transport-diagnostics.patch +297 -0
- package/engine/scripts/patches/dsh-session--append-message-shape.patch +15 -0
- package/engine/scripts/patches/dsh-session--tool-result-block-017.patch +28 -0
- package/engine/scripts/patches/dsh-session-format-v0-to-v1--permission-preset-origin.patch +11 -0
- package/engine/scripts/patches/dsh-session-format-v3-to-v4--turn-outside-replace.patch +20 -0
- package/engine/scripts/patches/dsh-session-persistence-jsonl--worker-bundled-migrators.patch +39 -0
- package/engine/scripts/patches/dsh-tools--render-return-shape.patch +50 -0
- package/engine/scripts/patches/verify-bundled-migrators.mjs +79 -0
- package/engine/scripts/patches/verify-hardening.mjs +167 -0
- package/engine/scripts/patches/verify-session-migration.mjs +149 -0
- package/engine/scripts/patches/verify-transport-diagnostics.mjs +227 -0
- package/engine/scripts/plan-role-rename.mjs +125 -0
- package/engine/scripts/plugin-bootcheck.mjs +451 -0
- package/engine/scripts/plugin-composition.json +15 -0
- package/engine/scripts/poc-mcp-host.mjs +455 -0
- package/engine/scripts/poll-fulfillment.sh +295 -0
- package/engine/scripts/poll-invoice.sh +76 -0
- package/engine/scripts/profile-doctor.mjs +686 -0
- package/engine/scripts/provider-select.sh +71 -0
- package/engine/scripts/provider-switch.sh +146 -0
- package/engine/scripts/provider-sync-target.check.mjs +64 -0
- package/engine/scripts/python-runtime.sh +78 -0
- package/engine/scripts/query_runner.py +310 -0
- package/engine/scripts/release-argent.sh +574 -0
- package/engine/scripts/repair-unresolved-tools.mjs +178 -0
- package/engine/scripts/retire-inventory.mjs +40 -0
- package/engine/scripts/run-tests.sh +257 -0
- package/engine/scripts/s1-audit.mjs +85 -0
- package/engine/scripts/self-sign-license.mjs +179 -0
- package/engine/scripts/session-health-scan.mjs +63 -0
- package/engine/scripts/session-repair-tool-result-content.mjs +181 -0
- package/engine/scripts/setup.sh +22 -0
- package/engine/scripts/skill-install.mjs +629 -0
- package/engine/scripts/sku_translate.py +148 -0
- package/engine/scripts/sync-plugins.sh +90 -0
- package/engine/scripts/sync-presets.sh +27 -0
- package/engine/scripts/sync-scripts.sh +445 -0
- package/engine/scripts/telemetry.py +873 -0
- package/engine/scripts/ui-copy-count.mjs +220 -0
- package/engine/scripts/usage-anchor.sh +137 -0
- package/engine/scripts/usage_report.py +531 -0
- package/engine/scripts/validate-preset-schema.mjs +208 -0
- package/engine/scripts/vertical-init.mjs +323 -0
- package/engine/scripts/vertical-lint.mjs +482 -0
- package/engine/scripts/wenyao-browser.sh +74 -0
- package/engine/scripts/wenyao-fixture-export.py +116 -0
- package/engine/scripts/wenyao-invoice-writeback.mjs +540 -0
- package/engine/scripts/wenyao-login.sh +35 -0
- package/engine/scripts/wenyao-template-map.json +292 -0
- package/engine/scripts/wenyao_attach.py +131 -0
- package/engine/scripts/wenyao_download_template.py +144 -0
- package/engine/scripts/wenyao_fill_template.py +568 -0
- package/engine/scripts/wenyao_login.py +145 -0
- package/engine/scripts/wenyao_portal.py +633 -0
- package/engine/scripts/wenyao_recon.py +230 -0
- package/engine/scripts/wenyao_run.py +503 -0
- package/engine/scripts/wenyao_shadow_diff.py +160 -0
- package/engine/scripts/wenyao_skill_contract.py +156 -0
- package/engine/scripts/wenyao_template_fetch.py +175 -0
- package/engine/scripts/win/dsh-web-autostart.ps1 +372 -0
- package/engine/scripts/ziniao-auth-probe.sh +268 -0
- package/engine/scripts/ziniao-keepalive.sh +217 -0
- package/engine/scripts/ziniao-post-upgrade-check.sh +121 -0
- package/engine/scripts/ziniao-windows.sh +154 -0
- package/engine/skills/README.md +86 -0
- package/engine/skills/argent-dev/SKILL.md +41 -0
- package/engine/skills/internal.json +37 -0
- package/engine/skills/lktop-pm/SKILL.md +35 -0
- package/engine/skills/lktopapp-dev/SKILL.md +34 -0
- package/engine/skills/ml-config-guide/SKILL.md +50 -0
- package/engine/skills/ml-fulfillment-sop/SKILL.md +178 -0
- package/engine/skills/ml-fulfillment-sop/references/andes-components.md +69 -0
- package/engine/skills/ml-fulfillment-sop/references/cdp-port-mapping.md +35 -0
- package/engine/skills/ml-fulfillment-sop/references/feishu-base-fulfillment-schema.md +136 -0
- package/engine/skills/ml-fulfillment-sop/references/multi-window-concurrency.md +69 -0
- package/engine/skills/ml-fulfillment-sop/references/pitfalls.md +77 -0
- package/engine/skills/ml-fulfillment-sop/references/selectors.md +243 -0
- package/engine/skills/ml-fulfillment-sop/scripts/fulfillment.js +586 -0
- package/engine/skills/ml-fulfillment-sop/scripts/poll-and-execute.sh +271 -0
- package/engine/skills/ml-fulfillment-sop/templates/report.md +55 -0
- package/engine/skills/ml-invoice/SKILL.md +506 -0
- package/engine/skills/ml-invoice/references/pitfalls.md +268 -0
- package/engine/skills/ml-invoice/references/portal-flow.md +360 -0
- package/engine/skills/ml-invoice/references/template-fill-contract.md +133 -0
- package/engine/skills/ml-invoice-xzh/SKILL.md +133 -0
- package/engine/skills/ml-invoice-xzh/references/pitfalls.md +230 -0
- package/engine/skills/ml-store-daily-report/SKILL.md +224 -0
- package/engine/skills/ml-store-daily-report/scripts/README.md +25 -0
- package/engine/skills/ml-store-daily-report/scripts/extract.js +691 -0
- package/engine/skills/ml-store-daily-report/scripts/generate.js +299 -0
- package/engine/skills/pet-dev/SKILL.md +42 -0
- package/engine/skills/whyshu-pm/SKILL.md +35 -0
- package/engine/skills/whyshu-web-dev/SKILL.md +50 -0
- package/engine/version.mjs +1 -0
- package/engine/verticals/README.md +103 -0
- package/engine/verticals/_engine-words.baseline.txt +237 -0
- package/engine/verticals/_engine-words.json +19 -0
- package/engine/verticals/mercadolibre/README.md +43 -0
- package/engine/verticals/mercadolibre/config.json +709 -0
- package/engine/verticals/mercadolibre/flows.json +738 -0
- package/engine/verticals/mercadolibre/manifest.json +538 -0
- package/engine/verticals/mercadolibre/migrate-machine-state.mjs +138 -0
- package/engine/verticals/mercadolibre/preflight.py +143 -0
- package/engine/verticals/mercadolibre/prompts/daily-report.failure.md +69 -0
- package/engine/verticals/mercadolibre/prompts/daily-report.md +47 -0
- package/engine/verticals/mercadolibre/prompts/daily-report.scheduled.md +79 -0
- package/engine/verticals/mercadolibre/prompts/full.failure.md +125 -0
- package/engine/verticals/mercadolibre/prompts/full.md +91 -0
- package/engine/verticals/mercadolibre/prompts/wenyao-invoice.failure.md +88 -0
- package/engine/verticals/mercadolibre/prompts/wenyao-invoice.md +64 -0
- package/engine/verticals/mercadolibre/prompts/xzh-invoice.failure.md +91 -0
- package/engine/verticals/mercadolibre/prompts/xzh-invoice.md +46 -0
- package/package.json +22 -4
- package/requirements.txt +5 -0
- package/README.md +0 -3
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
. "$(dirname "$0")/lib/argent-datadir.sh" # 0.7.0 W8/S1:数据根唯一判据
|
|
3
|
+
# customer-readiness —— **只读**客户机就绪体检(给"客户机安装"做准备/开窗前复核用)。
|
|
4
|
+
#
|
|
5
|
+
# 为什么要有它:客户机与开发机的差异都在"运行时/插件集/配置形状/定时器"这些**不能靠代码门禁
|
|
6
|
+
# 覆盖**的面上(2026-09-18 实测差异:dsh 0.1.1 vs 0.1.5、插件集多了 kanban/notify/packs/
|
|
7
|
+
# instances/drive、缺 roles.json、gateway.json 只有 2 个角色、~/.dsh/argent/venv 易失、5 个 PAUSE 开关)。
|
|
8
|
+
# 逐条人工核对既慢又容易漏 ⇒ 固化成脚本,开窗前一条命令出体检表。
|
|
9
|
+
#
|
|
10
|
+
# 红线:**只读**。不写任何配置/表、不动 PAUSE 开关、不建会话、不认领票据。
|
|
11
|
+
#
|
|
12
|
+
# 用法:
|
|
13
|
+
# bash scripts/customer-readiness.sh # 体检本机
|
|
14
|
+
# bash scripts/customer-readiness.sh --ssh huangwei@10.126.126.1 # 体检客户机(走 SSH,只读)
|
|
15
|
+
# ⚠️ 客户机地址 2026-10-03 实测更正:`10.126.126.3` 已失效(ping 100% 丢包 + ssh 超时),
|
|
16
|
+
# 可达的是 `.1`(hostname `huangweideMac-mini.local`)。
|
|
17
|
+
# bash scripts/customer-readiness.sh --json # 机器可读
|
|
18
|
+
# 退出码:0 = 无 FAIL;1 = 有 FAIL(缺关键件);2 = 参数/连接错误。
|
|
19
|
+
set -uo pipefail
|
|
20
|
+
|
|
21
|
+
SSH_TARGET=""
|
|
22
|
+
JSON=0
|
|
23
|
+
while [ $# -gt 0 ]; do
|
|
24
|
+
case "$1" in
|
|
25
|
+
--ssh) SSH_TARGET="$2"; shift 2;;
|
|
26
|
+
--json) JSON=1; shift;;
|
|
27
|
+
-h|--help) sed -n '2,20p' "${BASH_SOURCE[0]}" | sed 's/^# \{0,1\}//'; exit 0;;
|
|
28
|
+
*) shift;;
|
|
29
|
+
esac
|
|
30
|
+
done
|
|
31
|
+
|
|
32
|
+
PROBE=$(cat <<'EOS'
|
|
33
|
+
export PATH="$HOME/.local/bin:$HOME/node/bin:/usr/local/bin:/opt/homebrew/bin:$PATH"
|
|
34
|
+
pass=0; warn=0; fail=0
|
|
35
|
+
line() { printf '%s\t%s\t%s\n' "$1" "$2" "$3"; } # 状态 项目 说明
|
|
36
|
+
# ── 运行时 ──
|
|
37
|
+
if command -v node >/dev/null 2>&1; then line PASS "node" "$(node -v)"; else line FAIL "node" "未找到(定时器/脚本需要)"; fi
|
|
38
|
+
if [ -x ~/.dsh/argent/venv/bin/python3 ]; then line PASS "python venv" "$(~/.dsh/argent/venv/bin/python3 -V 2>&1)"; else line FAIL "python venv" "缺 ~/.dsh/argent/venv(流程引擎解释器;客户端重启后会静默空转)"; fi
|
|
39
|
+
if command -v lark-cli >/dev/null 2>&1; then line PASS "lark-cli" "$(lark-cli --version 2>/dev/null | head -1)"; else line FAIL "lark-cli" "未找到"; fi
|
|
40
|
+
if command -v dsh >/dev/null 2>&1; then
|
|
41
|
+
V=$(dsh --version 2>/dev/null | head -1)
|
|
42
|
+
case "$V" in 0.1.5*) line PASS "dsh" "$V";; *) line WARN "dsh" "${V}(本机开发机为 0.1.5-rc.1;新插件按 0.1.5 契约)";; esac
|
|
43
|
+
else line FAIL "dsh" "未找到"; fi
|
|
44
|
+
# ── 安装克隆 ──
|
|
45
|
+
if [ -d "$HOME/.argent-dsh/.git" ]; then
|
|
46
|
+
cd "$HOME/.argent-dsh"
|
|
47
|
+
DIRTY=$(git status --porcelain 2>/dev/null | wc -l | tr -d ' ')
|
|
48
|
+
COMMIT=$(git rev-parse --short HEAD 2>/dev/null); WHEN=$(git log -1 --format=%cd --date=format:'%m-%d %H:%M' 2>/dev/null)
|
|
49
|
+
if [ "$DIRTY" = "0" ]; then line PASS "安装克隆" "${COMMIT}(${WHEN})"; else line WARN "安装克隆" "$COMMIT 但有 $DIRTY 处未提交改动(会阻塞 git pull)"; fi
|
|
50
|
+
else line FAIL "安装克隆" "缺 ~/.argent-dsh"; fi
|
|
51
|
+
# ── 插件集 ──
|
|
52
|
+
PLUG=$(ls "$HOME/.dsh/profiles"/*/node_modules 2>/dev/null | grep -E "^argent-" | sort -u | tr '\n' ' ')
|
|
53
|
+
for need in argent-core argent-gateway argent-skin argent-ml; do
|
|
54
|
+
case " $PLUG " in *" $need "*) :;; *) line FAIL "插件:$need" "未安装";; esac
|
|
55
|
+
done
|
|
56
|
+
case " $PLUG " in *" argent-flow "*) line PASS "插件:argent-flow" "已装(新流程引擎)";; *) line WARN "插件:argent-flow" "未装 —— 安装阶段需补装";; esac
|
|
57
|
+
for old in argent-kanban argent-notify argent-packs argent-instances argent-instances-local argent-drive; do
|
|
58
|
+
case " $PLUG " in *" $old "*) line WARN "旧插件:$old" "仍在(新架构已不需要,安装阶段决定去留)";; esac
|
|
59
|
+
done
|
|
60
|
+
# ── 配置形状 ──
|
|
61
|
+
A="$ARGENT_DATA_DIR_RESOLVED"
|
|
62
|
+
[ -f "$A/roles.json" ] && line PASS "roles.json" "有" || line WARN "roles.json" "缺(新网关用角色→preset 映射)"
|
|
63
|
+
if [ -f "$A/gateway.json" ]; then
|
|
64
|
+
N=$(python3 -c "import json;print(len(json.load(open('$A/gateway.json')).get('roles') or []))" 2>/dev/null || echo "?")
|
|
65
|
+
line PASS "gateway.json" "角色 $N 个(开发机 13 个 = 12 角色 + main;2026-10-04 补 ml-invoice-xzh)"
|
|
66
|
+
else line FAIL "gateway.json" "缺"; fi
|
|
67
|
+
for f in fulfillment.env daily-report.env config.json ml-api-stores.json; do
|
|
68
|
+
[ -f "$A/$f" ] && line PASS "配置:$f" "有" || line WARN "配置:$f" "缺"
|
|
69
|
+
done
|
|
70
|
+
# 新键(FULL 完成卡落点 + 通知模式)
|
|
71
|
+
if [ -f "$A/fulfillment.env" ]; then
|
|
72
|
+
for k in FULL_NOTIFY_MODE FULL_INTERNAL_CHAT_ID FULL_DONE_CHAT_ID FULL_DONE_PROFILE; do
|
|
73
|
+
grep -q "^$k=" "$A/fulfillment.env" 2>/dev/null && line PASS "env:$k" "已设" || line WARN "env:$k" "未设(安装阶段补)"
|
|
74
|
+
done
|
|
75
|
+
fi
|
|
76
|
+
# ── 触发面 ──
|
|
77
|
+
P=$(ls "$A"/PAUSE_* 2>/dev/null | wc -l | tr -d ' ')
|
|
78
|
+
line PASS "PAUSE 开关" "$P 个(安装期间保持,逐流程验证后再摘)"
|
|
79
|
+
C=$(crontab -l 2>/dev/null | grep -vcE "^#|^$|^PATH")
|
|
80
|
+
[ "$C" = "0" ] && line PASS "crontab" "仅 PATH(无旧任务)" || line WARN "crontab" "有 $C 条任务(可能与新触发器双跑)"
|
|
81
|
+
T=$(launchctl list 2>/dev/null | grep -c "com.whyshu.flow-trigger")
|
|
82
|
+
[ "$T" = "0" ] && line WARN "flow 定时器" "未安装(安装阶段用 flow-timers.sh install --all)" || line PASS "flow 定时器" "$T 个已装"
|
|
83
|
+
# ── 数据面(只读统计,不读业务表内容)──
|
|
84
|
+
[ -f "$A/ml-api-stores.json" ] && line PASS "ML 授权店铺" "$(python3 -c "import json;d=json.load(open('$A/ml-api-stores.json'));print(len(d.get('stores') or d))" 2>/dev/null) 家"
|
|
85
|
+
if [ -f "$A/daily-report-cache/.pushed-placeholder" ]; then :; fi
|
|
86
|
+
LAST=$(ls -t "$A"/daily-report-cache/.pushed-* 2>/dev/null | head -1 | sed 's/.*\.pushed-//')
|
|
87
|
+
[ -n "$LAST" ] && line PASS "日报最近推送" "$LAST" || line WARN "日报最近推送" "无标记(从未推送过?)"
|
|
88
|
+
# ── 模型凭证(2026-09-29 日报事故固化):缺/死 ⇒ 跑起来也只会 401 空转,必须开窗前就看见 ──
|
|
89
|
+
MA=$(mktemp); if python3 "$HOME/.argent-dsh/scripts/check-model-auth.py" --json > "$MA" 2>/dev/null; then
|
|
90
|
+
line PASS "模型凭证" "$(python3 -c "import json;print(json.load(open('$MA'))['mode'])" 2>/dev/null)(在位)"
|
|
91
|
+
else
|
|
92
|
+
if [ -s "$MA" ]; then
|
|
93
|
+
line FAIL "模型凭证" "$(python3 -c "import json;d=json.load(open('$MA'));print(';'.join(i['title'] for i in d['checks'] if i['level']=='fail')[:120])" 2>/dev/null)"
|
|
94
|
+
else
|
|
95
|
+
line WARN "模型凭证" "缺 check-model-auth.py(老克隆)或 python3 不可用"
|
|
96
|
+
fi
|
|
97
|
+
fi; rm -f "$MA"
|
|
98
|
+
EOS
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
if [ -n "$SSH_TARGET" ]; then
|
|
102
|
+
command -v ssh >/dev/null 2>&1 || { echo "缺 ssh" >&2; exit 2; }
|
|
103
|
+
OUT=$(ssh -o ConnectTimeout=10 -o BatchMode=yes "$SSH_TARGET" 'bash -s' <<<"$PROBE" 2>&1) || { echo "SSH 失败:$OUT" >&2; exit 2; }
|
|
104
|
+
TITLE="客户机 $SSH_TARGET"
|
|
105
|
+
else
|
|
106
|
+
OUT=$(bash -s <<<"$PROBE" 2>&1)
|
|
107
|
+
TITLE="本机 $(hostname -s)"
|
|
108
|
+
fi
|
|
109
|
+
|
|
110
|
+
if [ "$JSON" = "1" ]; then
|
|
111
|
+
printf '%s\n' "$OUT" | python3 -c "
|
|
112
|
+
import sys, json
|
|
113
|
+
rows = [l.rstrip('\n').split('\t') for l in sys.stdin if l.strip()]
|
|
114
|
+
items = [{'status': r[0], 'item': r[1], 'detail': r[2] if len(r) > 2 else ''} for r in rows if len(r) >= 2]
|
|
115
|
+
print(json.dumps({'title': '$TITLE', 'items': items,
|
|
116
|
+
'summary': {s: sum(1 for i in items if i['status'] == s) for s in ('PASS', 'WARN', 'FAIL')}},
|
|
117
|
+
ensure_ascii=False, indent=2))
|
|
118
|
+
"
|
|
119
|
+
else
|
|
120
|
+
echo "═══ 客户机就绪体检:${TITLE}(只读)═══"
|
|
121
|
+
printf '%s\n' "$OUT" | awk -F'\t' '{ icon = ($1=="PASS" ? "✅" : ($1=="WARN" ? "⚠️ " : "❌")); printf " %s %-22s %s\n", icon, $2, $3 }'
|
|
122
|
+
echo
|
|
123
|
+
printf '%s\n' "$OUT" | awk -F'\t' '{c[$1]++} END { printf " ── 合计:PASS %d / WARN %d / FAIL %d\n", c["PASS"], c["WARN"], c["FAIL"] }'
|
|
124
|
+
fi
|
|
125
|
+
|
|
126
|
+
printf '%s\n' "$OUT" | grep -q "^FAIL" && exit 1 || exit 0
|
|
127
|
+
|
|
128
|
+
# Python 运行时(持久 venv)——单一事实源:scripts/python-runtime.sh check
|
|
129
|
+
echo
|
|
130
|
+
echo "── Python 运行时(流程引擎)"
|
|
131
|
+
if bash "$(dirname "${BASH_SOURCE[0]}")/python-runtime.sh" check; then
|
|
132
|
+
echo " ✅ 运行时可用(重启后流程不会静默停摆)"
|
|
133
|
+
else
|
|
134
|
+
echo " ❌ 运行时不可用 ⇒ 客户机重启后定时器会静默空转;修:bash scripts/python-runtime.sh ensure"
|
|
135
|
+
fi
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""daily-report-inbox —— 生成日报流程的**待处理清单**(P2)。
|
|
3
|
+
|
|
4
|
+
为什么需要:日报的"待处理单元"不在表里,而是
|
|
5
|
+
**(店铺清单 × 站点本地日期 × 幂等标记)** 三个东西的差集。
|
|
6
|
+
本脚本把它算成一份批量清单(cases-json),供 `flow_source` / `flow_triage` / `flow_claim` 消费:
|
|
7
|
+
|
|
8
|
+
~/.dsh/argent/ml-api-stores.json
|
|
9
|
+
+ ~/.dsh/argent/daily-report-cache/.pushed-<date>-<storeKey>
|
|
10
|
+
⇒ ~/.dsh/argent/flow-inbox/daily-report.json
|
|
11
|
+
|
|
12
|
+
**零 API 调用、只读**:不碰美客多接口、不推送、不写缓存与标记 —— 这就是"廉价轮询"的输入
|
|
13
|
+
(真正的抓取/推送由角色派出的 subagent 跑 `daily-report.mjs` 完成)。
|
|
14
|
+
|
|
15
|
+
单元口径:站点**本地**"昨天"(可用 `--date` 覆盖);已有幂等标记的(已推送)默认不产出,
|
|
16
|
+
因此清单天然幂等、跑完即清空。
|
|
17
|
+
|
|
18
|
+
**到点门控(2026-09-18 加)**:只有站点本地时间**已到推送点**(`mlDailyTime`,缺省 08:00)
|
|
19
|
+
且在 `daily-report.mjs` 的补推窗口(+5h)内才产出单元。理由:单元一旦产出,定时器就会
|
|
20
|
+
唤醒角色(每轮烧模型回合);未到点就产出=白唤醒一堆轮次。把门控放在这里(确定性、零成本),
|
|
21
|
+
角色只在"真该推了"的那一刻被叫醒。
|
|
22
|
+
|
|
23
|
+
**为什么必须有人调它**:本脚本曾**没有任何调用方**(不在触发器、不在插件、cron 已清空)
|
|
24
|
+
⇒ 清单冻结、其单元被影子轮消费后每轮"无票可认领"⇒ 当天永不推送(用户实测静默停摆一整天)。
|
|
25
|
+
现在由源适配器按注册表 `source.regenerate` 在每轮读清单前调用。
|
|
26
|
+
|
|
27
|
+
用法:
|
|
28
|
+
python3 scripts/daily-report-inbox.py # 按各店站点本地昨天生成
|
|
29
|
+
python3 scripts/daily-report-inbox.py --date 2026-08-30
|
|
30
|
+
python3 scripts/daily-report-inbox.py --dry-run # 只打印不写文件
|
|
31
|
+
python3 scripts/daily-report-inbox.py --include-pushed # 连已推送的也列出来(排查用)
|
|
32
|
+
退出码:0 成功(含 0 个单元);2 配置缺失/读取失败。
|
|
33
|
+
"""
|
|
34
|
+
from __future__ import annotations
|
|
35
|
+
|
|
36
|
+
import argparse
|
|
37
|
+
import datetime as dt
|
|
38
|
+
import json
|
|
39
|
+
import os
|
|
40
|
+
import pathlib
|
|
41
|
+
import sys
|
|
42
|
+
|
|
43
|
+
# 数据目录:`ARGENT_DATA_HOME` 是**历史别名**(core/mcp 影子跑两者都设)⇒ 保留优先,
|
|
44
|
+
# 与 `scripts/daily-report.mjs` 同一口径;其余走**唯一判据** scripts/lib/argent_datadir.py
|
|
45
|
+
# (三级链 `ARGENT_DATA_DIR` → `$DSH_HOME/argent` → `~/.dsh/argent`)。勿在此复制链。
|
|
46
|
+
sys.path.insert(0, str(pathlib.Path(__file__).resolve().parent / 'lib'))
|
|
47
|
+
from argent_datadir import resolve_data_dir # noqa: E402
|
|
48
|
+
_ALIAS = os.environ.get("ARGENT_DATA_HOME") or ""
|
|
49
|
+
DATA_HOME = pathlib.Path(_ALIAS) if _ALIAS else pathlib.Path(resolve_data_dir()["dir"])
|
|
50
|
+
STORES_FILE = pathlib.Path(os.environ.get("ML_API_STORES_JSON") or (DATA_HOME / "ml-api-stores.json"))
|
|
51
|
+
CACHE_DIR = DATA_HOME / "daily-report-cache"
|
|
52
|
+
OUT_FILE = DATA_HOME / "flow-inbox" / "daily-report.json"
|
|
53
|
+
|
|
54
|
+
# 站点 → 时区(与 scripts/daily-report.mjs 的 SITE_TZ 保持一致;改动请两边同步)
|
|
55
|
+
SITE_TZ = {
|
|
56
|
+
"MLM": "America/Mexico_City", "MLB": "America/Sao_Paulo", "MLA": "America/Argentina/Buenos_Aires",
|
|
57
|
+
"MLC": "America/Santiago", "MCO": "America/Bogota", "MPE": "America/Lima",
|
|
58
|
+
"MLU": "America/Montevideo", "MEC": "America/Guayaquil", "MLV": "America/Caracas",
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def store_key(store: dict) -> str:
|
|
63
|
+
"""与 daily-report.mjs 的 storeKey() 同构:store-<user_id|name>。"""
|
|
64
|
+
return f"store-{store.get('user_id') if store.get('user_id') is not None else store.get('name')}"
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def report_date_for(site: str, override: str | None, now_utc: dt.datetime | None = None) -> str:
|
|
68
|
+
"""站点本地"昨天"(无时区信息则退回本机时区)。"""
|
|
69
|
+
if override:
|
|
70
|
+
return override
|
|
71
|
+
now = now_utc or dt.datetime.now(dt.timezone.utc)
|
|
72
|
+
tzname = SITE_TZ.get((site or "").upper())
|
|
73
|
+
if tzname:
|
|
74
|
+
try:
|
|
75
|
+
from zoneinfo import ZoneInfo
|
|
76
|
+
local = now.astimezone(ZoneInfo(tzname))
|
|
77
|
+
except Exception:
|
|
78
|
+
local = now.astimezone()
|
|
79
|
+
else:
|
|
80
|
+
local = now.astimezone()
|
|
81
|
+
return (local.date() - dt.timedelta(days=1)).isoformat()
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
CATCHUP_HOURS = 5 # 与 scripts/daily-report.mjs 的 gateCatchUp 对齐(+5h 补推窗口)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def load_report_time() -> str:
|
|
88
|
+
"""推送时刻(站点本地 HH:MM):config.json 的 mlDailyTime → env REPORT_TIME → 08:00。
|
|
89
|
+
|
|
90
|
+
与 scripts/daily-report.mjs 同一条读取链(`pick(cfg, env, 'mlDailyTime','REPORT_TIME','08:00')`),
|
|
91
|
+
避免"配了等于没配"(两边不一致时,本脚本会一直不产出、或产出后脚本自己跳过)。
|
|
92
|
+
"""
|
|
93
|
+
# `DATA_HOME` 已是「ARGENT_DATA_HOME → ARGENT_DATA_DIR → ~/.dsh/argent」(上方定义)⇒
|
|
94
|
+
# 不再并列一条硬编码 `~/.dsh/argent/config.json`(隔离跑时会先读生产配置,2026-10-02 修)。
|
|
95
|
+
for p in (DATA_HOME / "config.json",
|
|
96
|
+
DATA_HOME / "daily-report.env"):
|
|
97
|
+
try:
|
|
98
|
+
if p.suffix == ".env":
|
|
99
|
+
for ln in p.read_text(encoding="utf-8").splitlines():
|
|
100
|
+
if ln.strip().startswith("REPORT_TIME="):
|
|
101
|
+
return ln.split("=", 1)[1].strip()
|
|
102
|
+
else:
|
|
103
|
+
v = (json.loads(p.read_text(encoding="utf-8")) or {}).get("mlDailyTime")
|
|
104
|
+
if v:
|
|
105
|
+
return str(v).strip()
|
|
106
|
+
except Exception:
|
|
107
|
+
continue
|
|
108
|
+
return os.environ.get("REPORT_TIME") or "08:00"
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def gate_state(site: str, report_time: str, now_utc: dt.datetime | None = None) -> str:
|
|
112
|
+
"""返回 'due' | 'not_due' | 'window_missed'(站点本地口径,与 daily-report.mjs 一致)。"""
|
|
113
|
+
try:
|
|
114
|
+
hour = int(str(report_time).split(":")[0])
|
|
115
|
+
except Exception:
|
|
116
|
+
hour = 8
|
|
117
|
+
now = now_utc or dt.datetime.now(dt.timezone.utc)
|
|
118
|
+
tzname = SITE_TZ.get((site or "").upper())
|
|
119
|
+
try:
|
|
120
|
+
from zoneinfo import ZoneInfo
|
|
121
|
+
local = now.astimezone(ZoneInfo(tzname)) if tzname else now.astimezone()
|
|
122
|
+
except Exception:
|
|
123
|
+
local = now.astimezone()
|
|
124
|
+
h = local.hour
|
|
125
|
+
if h == hour:
|
|
126
|
+
return "due"
|
|
127
|
+
if hour < h <= hour + CATCHUP_HOURS:
|
|
128
|
+
return "due" # 补推窗口内(错过整点仍要补)
|
|
129
|
+
if h < hour:
|
|
130
|
+
return "not_due"
|
|
131
|
+
return "window_missed"
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def build(include_pushed: bool = False, date_override: str | None = None,
|
|
135
|
+
only: str | None = None, force_due: bool = False) -> dict:
|
|
136
|
+
if not STORES_FILE.exists():
|
|
137
|
+
print(f"❌ 找不到店铺清单:{STORES_FILE}(先跑 init-ml.sh / ml-oauth-setup)", file=sys.stderr)
|
|
138
|
+
raise SystemExit(2)
|
|
139
|
+
try:
|
|
140
|
+
doc = json.loads(STORES_FILE.read_text(encoding="utf-8"))
|
|
141
|
+
except Exception as exc:
|
|
142
|
+
print(f"❌ 店铺清单解析失败:{exc}", file=sys.stderr)
|
|
143
|
+
raise SystemExit(2)
|
|
144
|
+
stores = doc.get("stores") if isinstance(doc, dict) else doc
|
|
145
|
+
if not isinstance(stores, list):
|
|
146
|
+
print("❌ 店铺清单格式异常(应为 {stores:[…]} 或数组)", file=sys.stderr)
|
|
147
|
+
raise SystemExit(2)
|
|
148
|
+
|
|
149
|
+
report_time = load_report_time()
|
|
150
|
+
cases, skipped = [], []
|
|
151
|
+
for st in stores:
|
|
152
|
+
if not isinstance(st, dict):
|
|
153
|
+
continue
|
|
154
|
+
name = str(st.get("name") or "")
|
|
155
|
+
if only and only not in name:
|
|
156
|
+
continue
|
|
157
|
+
site = str(st.get("site") or "").upper()
|
|
158
|
+
key = store_key(st)
|
|
159
|
+
date = report_date_for(site, date_override)
|
|
160
|
+
marker = CACHE_DIR / f".pushed-{date}-{key}"
|
|
161
|
+
snapshot = CACHE_DIR / f"{date}-{key}.json"
|
|
162
|
+
pushed = marker.exists()
|
|
163
|
+
if pushed and not include_pushed:
|
|
164
|
+
skipped.append({"store": name, "site": site, "date": date, "why": "已推送(有幂等标记)"})
|
|
165
|
+
continue
|
|
166
|
+
gs = "due" if (force_due or include_pushed) else gate_state(site, report_time)
|
|
167
|
+
if gs != "due":
|
|
168
|
+
why = (f"未到推送点(站点本地 {report_time})" if gs == "not_due"
|
|
169
|
+
else f"已过补推窗口(推送点 站点本地 {report_time},仅 +{CATCHUP_HOURS}h 内可补)")
|
|
170
|
+
skipped.append({"store": name, "site": site, "date": date, "why": why})
|
|
171
|
+
continue
|
|
172
|
+
ticket = f"{site}-{date}-{st.get('user_id') if st.get('user_id') is not None else name}"
|
|
173
|
+
cases.append({
|
|
174
|
+
"ticketKey": ticket,
|
|
175
|
+
"fields": {
|
|
176
|
+
"store": name,
|
|
177
|
+
"site": site,
|
|
178
|
+
"date": date,
|
|
179
|
+
"store_key": key,
|
|
180
|
+
"tz": SITE_TZ.get(site, "本机时区"),
|
|
181
|
+
"pushed": pushed,
|
|
182
|
+
"snapshot": snapshot.exists(),
|
|
183
|
+
},
|
|
184
|
+
})
|
|
185
|
+
notes = []
|
|
186
|
+
if not cases:
|
|
187
|
+
if skipped:
|
|
188
|
+
notes = [f"{s0['store']} {s0['why']}" for s0 in skipped[:4]]
|
|
189
|
+
else:
|
|
190
|
+
notes = ["店铺清单为空(先跑 ml-oauth-setup 授权店铺)"]
|
|
191
|
+
return {
|
|
192
|
+
"flow": "daily-report",
|
|
193
|
+
"generatedAt": dt.datetime.now(dt.timezone.utc).isoformat(),
|
|
194
|
+
"reportTime": report_time,
|
|
195
|
+
"cases": cases,
|
|
196
|
+
"skipped": skipped,
|
|
197
|
+
"notes": notes,
|
|
198
|
+
"stores": len(stores),
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def main(argv=None) -> int:
|
|
203
|
+
ap = argparse.ArgumentParser(description="生成日报待处理清单(零 API 调用、只读)")
|
|
204
|
+
ap.add_argument("--date", help="指定日报日期(YYYY-MM-DD;默认各店站点本地昨天)")
|
|
205
|
+
ap.add_argument("--out", default=str(OUT_FILE), help=f"输出路径(默认 {OUT_FILE})")
|
|
206
|
+
ap.add_argument("--store", help="只处理名字包含该子串的店铺")
|
|
207
|
+
ap.add_argument("--include-pushed", action="store_true", help="已推送的也列出(排查用)")
|
|
208
|
+
ap.add_argument("--force-due", action="store_true",
|
|
209
|
+
help="忽略到点门控(人工排查/补历史用;正常轮询**不要**加)")
|
|
210
|
+
ap.add_argument("--dry-run", action="store_true", help="只打印,不写文件")
|
|
211
|
+
ap.add_argument("--json", action="store_true", help="把清单打到 stdout")
|
|
212
|
+
a = ap.parse_args(argv)
|
|
213
|
+
|
|
214
|
+
plan = build(include_pushed=a.include_pushed, date_override=a.date, only=a.store,
|
|
215
|
+
force_due=a.force_due)
|
|
216
|
+
n = len(plan["cases"])
|
|
217
|
+
# --json 时必须**纯 JSON 到 stdout**(否则调用方无法直接 parse);人读的提示一律走 stderr
|
|
218
|
+
note = sys.stderr if a.json else sys.stdout
|
|
219
|
+
if a.json:
|
|
220
|
+
print(json.dumps(plan, ensure_ascii=False, indent=2))
|
|
221
|
+
else:
|
|
222
|
+
print(f" 店铺 {plan['stores']} 家 ⇒ 待处理单元 {n} 个"
|
|
223
|
+
+ (f",跳过 {len(plan['skipped'])} 个" if plan["skipped"] else "")
|
|
224
|
+
+ f"(推送点 站点本地 {plan.get('reportTime')})")
|
|
225
|
+
for s0 in plan.get("skipped") or []:
|
|
226
|
+
print(f" · 跳过 {s0['store']}:{s0['why']}")
|
|
227
|
+
for c in plan["cases"]:
|
|
228
|
+
f = c["fields"]
|
|
229
|
+
print(f" · {c['ticketKey']} {f['store']}({f['site']}){f['date']}"
|
|
230
|
+
+ (" [已推送]" if f["pushed"] else ""))
|
|
231
|
+
if a.dry_run:
|
|
232
|
+
print(" [dry-run] 未写文件", file=note)
|
|
233
|
+
return 0
|
|
234
|
+
out = pathlib.Path(a.out)
|
|
235
|
+
out.parent.mkdir(parents=True, exist_ok=True)
|
|
236
|
+
out.write_text(json.dumps(plan, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
|
|
237
|
+
print(f" ✅ 已写 {out}({n} 个单元)", file=note)
|
|
238
|
+
return 0
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
if __name__ == "__main__":
|
|
242
|
+
raise SystemExit(main())
|