@whyshu/argent-engine 0.0.0-stage → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/MANIFEST.json +307 -0
- package/engine/VERSION +1 -0
- package/engine/agents/catalog.json +454 -0
- package/engine/configs/_aliases.proposed.json +651 -0
- package/engine/configs/_migration-plan.proposed.json +899 -0
- package/engine/configs/account.json +272 -0
- package/engine/configs/advanced.json +205 -0
- package/engine/configs/host.json +149 -0
- package/engine/configs/hr.json +27 -0
- package/engine/configs/notify.json +264 -0
- package/engine/core/cli/argent.mjs +277 -0
- package/engine/core/contracts/argent.contracts.json +1065 -0
- package/engine/core/contracts/verbs.schema.json +2539 -0
- package/engine/core/lib/argent-datadir.mjs +223 -0
- package/engine/core/lib/audit.mjs +187 -0
- package/engine/core/lib/claim.mjs +258 -0
- package/engine/core/lib/config-catalog.mjs +1172 -0
- package/engine/core/lib/doctor-customer.mjs +577 -0
- package/engine/core/lib/flow-list.mjs +138 -0
- package/engine/core/lib/flow-registry.mjs +48 -0
- package/engine/core/lib/init.mjs +247 -0
- package/engine/core/lib/ledger.mjs +124 -0
- package/engine/core/lib/license-activate.mjs +813 -0
- package/engine/core/lib/license-device.mjs +314 -0
- package/engine/core/lib/license-file.mjs +349 -0
- package/engine/core/lib/license-guard.mjs +123 -0
- package/engine/core/lib/license-ops.mjs +1645 -0
- package/engine/core/lib/license-verdict.mjs +133 -0
- package/engine/core/lib/license.mjs +577 -0
- package/engine/core/lib/notify/dedup.mjs +101 -0
- package/engine/core/lib/notify/feishu.mjs +38 -0
- package/engine/core/lib/notify/index.mjs +95 -0
- package/engine/core/lib/notify/verb.mjs +327 -0
- package/engine/core/lib/notify/webhook.mjs +135 -0
- package/engine/core/lib/notify/wecom.mjs +36 -0
- package/engine/core/lib/python.mjs +145 -0
- package/engine/core/lib/sop.mjs +116 -0
- package/engine/core/lib/versions.mjs +205 -0
- package/engine/core/mcp/client.mjs +67 -0
- package/engine/core/mcp/http.mjs +138 -0
- package/engine/core/mcp/server.mjs +702 -0
- package/engine/scripts/_engine_rules_probe.py +15 -0
- package/engine/scripts/analyze-full-day.py +568 -0
- package/engine/scripts/archive/feishu-bridge.js +246 -0
- package/engine/scripts/argent-agents.mjs +527 -0
- package/engine/scripts/argent-capabilities.mjs +776 -0
- package/engine/scripts/argent-catalog.mjs +186 -0
- package/engine/scripts/argent-datadir.py +62 -0
- package/engine/scripts/argent-doctor.mjs +624 -0
- package/engine/scripts/argent-env-write.mjs +302 -0
- package/engine/scripts/argent-schedule.mjs +620 -0
- package/engine/scripts/argent-setup-check.mjs +369 -0
- package/engine/scripts/argent-upgrade.mjs +1046 -0
- package/engine/scripts/base-bootstrap.sh +575 -0
- package/engine/scripts/billing-mode-daily.sh +12 -0
- package/engine/scripts/build-engine-package.mjs +123 -0
- package/engine/scripts/capability-packs.lock.json +484 -0
- package/engine/scripts/capability_pack.py +1242 -0
- package/engine/scripts/check-1.0-criteria.mjs +355 -0
- package/engine/scripts/check-agent-catalog.mjs +141 -0
- package/engine/scripts/check-billing-mode.sh +377 -0
- package/engine/scripts/check-child-sessions.mjs +83 -0
- package/engine/scripts/check-config-catalog.mjs +677 -0
- package/engine/scripts/check-docs-drift.mjs +522 -0
- package/engine/scripts/check-dsh-web-expose.sh +98 -0
- package/engine/scripts/check-judgment-drift.mjs +403 -0
- package/engine/scripts/check-license.mjs +199 -0
- package/engine/scripts/check-model-auth.py +443 -0
- package/engine/scripts/check-pack-closure.mjs +661 -0
- package/engine/scripts/check-portable-symbols.mjs +116 -0
- package/engine/scripts/check-preset-landing.mjs +124 -0
- package/engine/scripts/check-production-home.mjs +602 -0
- package/engine/scripts/check-role-mapping.mjs +461 -0
- package/engine/scripts/check-sample-redaction.mjs +320 -0
- package/engine/scripts/check-skill-classification.mjs +188 -0
- package/engine/scripts/check-sop-consistency.mjs +431 -0
- package/engine/scripts/check-test-env-safety.mjs +627 -0
- package/engine/scripts/check-version-consistency.mjs +452 -0
- package/engine/scripts/ci-run.sh +558 -0
- package/engine/scripts/config-explain.mjs +278 -0
- package/engine/scripts/configure-provider.rb +29 -0
- package/engine/scripts/customer-config-migrate.mjs +179 -0
- package/engine/scripts/customer-preflight.py +892 -0
- package/engine/scripts/customer-readiness.sh +134 -0
- package/engine/scripts/daily-report-inbox.py +242 -0
- package/engine/scripts/daily-report-reconcile.mjs +312 -0
- package/engine/scripts/daily-report.mjs +1310 -0
- package/engine/scripts/daily-report.sh +46 -0
- package/engine/scripts/data/lip-product-dict.json +306 -0
- package/engine/scripts/deliver-customer.mjs +932 -0
- package/engine/scripts/delivery-faces.txt +31 -0
- package/engine/scripts/desktop-trial.sh +146 -0
- package/engine/scripts/dev-window.sh +260 -0
- package/engine/scripts/drill-clean-machine.sh +315 -0
- package/engine/scripts/dsh-api-client.mjs +215 -0
- package/engine/scripts/dsh-backup-scope.sh +83 -0
- package/engine/scripts/dsh-offline-pack.mjs +77 -0
- package/engine/scripts/dsh-overlay-pin.sh +87 -0
- package/engine/scripts/dsh-plane.mjs +153 -0
- package/engine/scripts/dsh-portforward.py +223 -0
- package/engine/scripts/dsh-preflight.mjs +179 -0
- package/engine/scripts/dsh-release-watch-daily.sh +19 -0
- package/engine/scripts/dsh-release-watch.mjs +458 -0
- package/engine/scripts/dsh-remote-check.sh +99 -0
- package/engine/scripts/dsh-restart.sh +179 -0
- package/engine/scripts/dsh-restore.sh +111 -0
- package/engine/scripts/dsh-scope-rewire.mjs +803 -0
- package/engine/scripts/dsh-snapshot.mjs +116 -0
- package/engine/scripts/dsh-upgrade-readiness.mjs +165 -0
- package/engine/scripts/dsh-upgrade.mjs +612 -0
- package/engine/scripts/dsh-url.sh +86 -0
- package/engine/scripts/dsh-web-launch.mjs +155 -0
- package/engine/scripts/ensure-store-windows.py +509 -0
- package/engine/scripts/entitlements.py +458 -0
- package/engine/scripts/env_probe.py +411 -0
- package/engine/scripts/feishu-card.mjs +252 -0
- package/engine/scripts/fix-skill-frontmatter.py +209 -0
- package/engine/scripts/flow-auto-retry.py +454 -0
- package/engine/scripts/flow-requirements.json +720 -0
- package/engine/scripts/flow-scaffold.py +275 -0
- package/engine/scripts/flow-timers-plist.sh +86 -0
- package/engine/scripts/flow-timers.sh +182 -0
- package/engine/scripts/flow-trigger-wake.mjs +284 -0
- package/engine/scripts/flow-trigger.sh +571 -0
- package/engine/scripts/flow_billing.py +354 -0
- package/engine/scripts/flow_capability_stats.py +314 -0
- package/engine/scripts/flow_case.py +194 -0
- package/engine/scripts/flow_claim.py +497 -0
- package/engine/scripts/flow_config.py +1024 -0
- package/engine/scripts/flow_failure.py +588 -0
- package/engine/scripts/flow_learn.py +105 -0
- package/engine/scripts/flow_ledger.py +235 -0
- package/engine/scripts/flow_policy.py +238 -0
- package/engine/scripts/flow_preflight.py +339 -0
- package/engine/scripts/flow_registry.py +341 -0
- package/engine/scripts/flow_retry.py +304 -0
- package/engine/scripts/flow_return_to_ops.py +191 -0
- package/engine/scripts/flow_source.py +315 -0
- package/engine/scripts/flow_sources/__init__.py +53 -0
- package/engine/scripts/flow_sources/cases_json.py +106 -0
- package/engine/scripts/flow_sources/common.py +428 -0
- package/engine/scripts/flow_sources/feishu_base.py +273 -0
- package/engine/scripts/flow_stale.py +185 -0
- package/engine/scripts/flow_status_reconcile.py +344 -0
- package/engine/scripts/flow_triage.py +849 -0
- package/engine/scripts/flow_write_verify.py +496 -0
- package/engine/scripts/fulfillment.js +586 -0
- package/engine/scripts/gen-agent-bundles.mjs +276 -0
- package/engine/scripts/gen-preset-rows.mjs +259 -0
- package/engine/scripts/init-ml.sh +2275 -0
- package/engine/scripts/install-internal-role.sh +190 -0
- package/engine/scripts/install-license.mjs +641 -0
- package/engine/scripts/install-one-shot.mjs +665 -0
- package/engine/scripts/integration_contract.py +220 -0
- package/engine/scripts/integrations/wenyao/adapter.py +98 -0
- package/engine/scripts/integrations/xzh/adapter.py +75 -0
- package/engine/scripts/invoice-mapping.example.json +40 -0
- package/engine/scripts/invoice-table.sh +194 -0
- package/engine/scripts/invoice_carrier_notice.py +279 -0
- package/engine/scripts/invoice_fail_closeout.py +297 -0
- package/engine/scripts/invoice_lip_runner.py +1508 -0
- package/engine/scripts/invoice_lip_runner.py.bak-20260922-1710-freready +1090 -0
- package/engine/scripts/invoice_ready_audit.py +191 -0
- package/engine/scripts/invoice_runner.py +675 -0
- package/engine/scripts/invoice_stageb.py +516 -0
- package/engine/scripts/launchd/com.whyshu.argent-bridge.plist.example +42 -0
- package/engine/scripts/launchd/com.whyshu.fulfillment-poll.plist.example +29 -0
- package/engine/scripts/lease.py +377 -0
- package/engine/scripts/lib/agent-install.mjs +649 -0
- package/engine/scripts/lib/argent-datadir.mjs +16 -0
- package/engine/scripts/lib/argent_datadir.py +262 -0
- package/engine/scripts/lib/argent_filelock.py +507 -0
- package/engine/scripts/lib/bootcheck-wiring.mjs +510 -0
- package/engine/scripts/lib/cdp_ports.py +197 -0
- package/engine/scripts/lib/customer-env.mjs +102 -0
- package/engine/scripts/lib/daily-report-core.mjs +517 -0
- package/engine/scripts/lib/dep-declaration.mjs +81 -0
- package/engine/scripts/lib/deps-migrate.mjs +310 -0
- package/engine/scripts/lib/dsh-host-resolve.mjs +109 -0
- package/engine/scripts/lib/dsh-scope.mjs +500 -0
- package/engine/scripts/lib/dsh-snapshot-path.mjs +35 -0
- package/engine/scripts/lib/dsh-versions.mjs +96 -0
- package/engine/scripts/lib/dsh-web-probe.mjs +214 -0
- package/engine/scripts/lib/is-direct-run.mjs +61 -0
- package/engine/scripts/lib/patch-compose.mjs +241 -0
- package/engine/scripts/lib/patch-target.mjs +35 -0
- package/engine/scripts/lib/plugin-lifecycle.mjs +128 -0
- package/engine/scripts/lib/plugin-packages.mjs +332 -0
- package/engine/scripts/lib/preset-compat.mjs +127 -0
- package/engine/scripts/lib/preset-install.mjs +575 -0
- package/engine/scripts/lib/preset-mechanism.mjs +56 -0
- package/engine/scripts/lib/preset-sync.mjs +59 -0
- package/engine/scripts/lib/profile-retire.mjs +97 -0
- package/engine/scripts/lib/python-runtime.mjs +190 -0
- package/engine/scripts/lib/registry.mjs +72 -0
- package/engine/scripts/lib/repo-root.sh +56 -0
- package/engine/scripts/lib/schedule-mechanism.mjs +659 -0
- package/engine/scripts/lib/schedule-probe.mjs +835 -0
- package/engine/scripts/lib/scope-pointer.mjs +164 -0
- package/engine/scripts/lib/settings-panels.mjs +816 -0
- package/engine/scripts/lib/stdio_utf8.py +86 -0
- package/engine/scripts/lib/wake-auth.mjs +392 -0
- package/engine/scripts/lib/webdriver_ipc.py +264 -0
- package/engine/scripts/lib/zstd-frames.mjs +104 -0
- package/engine/scripts/license-e2e-drill.mjs +426 -0
- package/engine/scripts/license-gate.mjs +245 -0
- package/engine/scripts/lip_backlog.py +171 -0
- package/engine/scripts/lip_table.py +185 -0
- package/engine/scripts/local-usage.mjs +214 -0
- package/engine/scripts/migrate-providers.mjs +127 -0
- package/engine/scripts/migrate-skills.sh +65 -0
- package/engine/scripts/ml-oauth-setup.mjs +550 -0
- package/engine/scripts/ml-store-ids.json +26 -0
- package/engine/scripts/ml_artifact_attribution.py +333 -0
- package/engine/scripts/ml_capacity_probe.py +1158 -0
- package/engine/scripts/ml_hub_status.py +1556 -0
- package/engine/scripts/ml_schema_check.py +115 -0
- package/engine/scripts/ml_store_ids.py +139 -0
- package/engine/scripts/npm-publish-argent.mjs +499 -0
- package/engine/scripts/npm-publish-argent.sh +20 -0
- package/engine/scripts/orchestrator.py +13811 -0
- package/engine/scripts/pack-plugins.mjs +140 -0
- package/engine/scripts/patches/dsh-llm-deepseek--transport-diagnostics.patch +297 -0
- package/engine/scripts/patches/dsh-session--append-message-shape.patch +15 -0
- package/engine/scripts/patches/dsh-session--tool-result-block-017.patch +28 -0
- package/engine/scripts/patches/dsh-session-format-v0-to-v1--permission-preset-origin.patch +11 -0
- package/engine/scripts/patches/dsh-session-format-v3-to-v4--turn-outside-replace.patch +20 -0
- package/engine/scripts/patches/dsh-session-persistence-jsonl--worker-bundled-migrators.patch +39 -0
- package/engine/scripts/patches/dsh-tools--render-return-shape.patch +50 -0
- package/engine/scripts/patches/verify-bundled-migrators.mjs +79 -0
- package/engine/scripts/patches/verify-hardening.mjs +167 -0
- package/engine/scripts/patches/verify-session-migration.mjs +149 -0
- package/engine/scripts/patches/verify-transport-diagnostics.mjs +227 -0
- package/engine/scripts/plan-role-rename.mjs +125 -0
- package/engine/scripts/plugin-bootcheck.mjs +451 -0
- package/engine/scripts/plugin-composition.json +15 -0
- package/engine/scripts/poc-mcp-host.mjs +455 -0
- package/engine/scripts/poll-fulfillment.sh +293 -0
- package/engine/scripts/poll-invoice.sh +74 -0
- package/engine/scripts/profile-doctor.mjs +686 -0
- package/engine/scripts/provider-select.sh +70 -0
- package/engine/scripts/provider-switch.sh +146 -0
- package/engine/scripts/provider-sync-target.check.mjs +64 -0
- package/engine/scripts/python-runtime.sh +78 -0
- package/engine/scripts/query_runner.py +310 -0
- package/engine/scripts/release-argent.sh +574 -0
- package/engine/scripts/repair-unresolved-tools.mjs +178 -0
- package/engine/scripts/run-tests.sh +256 -0
- package/engine/scripts/self-sign-license.mjs +179 -0
- package/engine/scripts/session-health-scan.mjs +63 -0
- package/engine/scripts/session-repair-tool-result-content.mjs +181 -0
- package/engine/scripts/setup.sh +22 -0
- package/engine/scripts/skill-install.mjs +629 -0
- package/engine/scripts/sku_translate.py +148 -0
- package/engine/scripts/sync-plugins.sh +90 -0
- package/engine/scripts/sync-presets.sh +27 -0
- package/engine/scripts/sync-scripts.sh +445 -0
- package/engine/scripts/telemetry.py +873 -0
- package/engine/scripts/ui-copy-count.mjs +220 -0
- package/engine/scripts/usage-anchor.sh +136 -0
- package/engine/scripts/usage_report.py +531 -0
- package/engine/scripts/validate-preset-schema.mjs +208 -0
- package/engine/scripts/vertical-init.mjs +323 -0
- package/engine/scripts/vertical-lint.mjs +482 -0
- package/engine/scripts/wenyao-browser.sh +73 -0
- package/engine/scripts/wenyao-fixture-export.py +116 -0
- package/engine/scripts/wenyao-invoice-writeback.mjs +540 -0
- package/engine/scripts/wenyao-login.sh +34 -0
- package/engine/scripts/wenyao-template-map.json +292 -0
- package/engine/scripts/wenyao_attach.py +131 -0
- package/engine/scripts/wenyao_download_template.py +144 -0
- package/engine/scripts/wenyao_fill_template.py +568 -0
- package/engine/scripts/wenyao_login.py +145 -0
- package/engine/scripts/wenyao_portal.py +633 -0
- package/engine/scripts/wenyao_recon.py +230 -0
- package/engine/scripts/wenyao_run.py +503 -0
- package/engine/scripts/wenyao_shadow_diff.py +160 -0
- package/engine/scripts/wenyao_skill_contract.py +156 -0
- package/engine/scripts/wenyao_template_fetch.py +175 -0
- package/engine/scripts/win/dsh-web-autostart.ps1 +372 -0
- package/engine/scripts/ziniao-auth-probe.sh +268 -0
- package/engine/scripts/ziniao-keepalive.sh +216 -0
- package/engine/scripts/ziniao-post-upgrade-check.sh +120 -0
- package/engine/scripts/ziniao-windows.sh +153 -0
- package/engine/version.mjs +1 -0
- package/engine/verticals/README.md +103 -0
- package/engine/verticals/_engine-words.baseline.txt +237 -0
- package/engine/verticals/_engine-words.json +19 -0
- package/engine/verticals/mercadolibre/README.md +43 -0
- package/engine/verticals/mercadolibre/config.json +709 -0
- package/engine/verticals/mercadolibre/flows.json +706 -0
- package/engine/verticals/mercadolibre/manifest.json +538 -0
- package/engine/verticals/mercadolibre/migrate-machine-state.mjs +138 -0
- package/engine/verticals/mercadolibre/preflight.py +143 -0
- package/engine/verticals/mercadolibre/prompts/daily-report.failure.md +69 -0
- package/engine/verticals/mercadolibre/prompts/daily-report.md +47 -0
- package/engine/verticals/mercadolibre/prompts/daily-report.scheduled.md +79 -0
- package/engine/verticals/mercadolibre/prompts/full.failure.md +125 -0
- package/engine/verticals/mercadolibre/prompts/full.md +91 -0
- package/engine/verticals/mercadolibre/prompts/wenyao-invoice.failure.md +88 -0
- package/engine/verticals/mercadolibre/prompts/wenyao-invoice.md +64 -0
- package/engine/verticals/mercadolibre/prompts/xzh-invoice.failure.md +91 -0
- package/engine/verticals/mercadolibre/prompts/xzh-invoice.md +46 -0
- package/package.json +21 -4
- package/README.md +0 -3
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# ziniao-keepalive.sh —— 紫鸟**常驻 WebDriver 模式**的守护(W2 部署件)
|
|
3
|
+
#
|
|
4
|
+
# ## 为什么需要
|
|
5
|
+
# 2026-09-24 用户选定「生产机常驻 WebDriver 模式」。常驻要成立,三件事必须自动:
|
|
6
|
+
# ① 开机/登录后**自己起来**(RunAtLoad);
|
|
7
|
+
# ② 掉线(客户端退出/内核崩/IPC 端口不再监听)**自己拉回来**;
|
|
8
|
+
# ③ 授权链路(applyAuth 设备授权)**每天自愈一次**(`ziniao-auth-probe.sh` 已实现,这里复用)。
|
|
9
|
+
#
|
|
10
|
+
# ## 安全口径(这条比功能重要)
|
|
11
|
+
# **默认不 kill 一个正在跑的 GUI 客户端**(那会关掉用户手开的所有店铺窗口 —— W2 已定的口径)。
|
|
12
|
+
# 只有两种情况会启动客户端:① 完全没有紫鸟进程;② 显式 `ZINIAO_KEEPALIVE_RESTART=1`(生产机专用,
|
|
13
|
+
# 表示"这台机器的客户端就该常驻 WebDriver 模式")。
|
|
14
|
+
# 应急开关:`touch ~/.dsh/argent/PAUSE_ZINIAO_KEEPALIVE` ⇒ 巡检直接跳过(运维在人工操作时用)。
|
|
15
|
+
#
|
|
16
|
+
# 用法:
|
|
17
|
+
# bash scripts/ziniao-keepalive.sh run # 单次巡检(LaunchAgent 调的就是它)
|
|
18
|
+
# bash scripts/ziniao-keepalive.sh run --dry-run # 只判断不动作(测试/排障)
|
|
19
|
+
# bash scripts/ziniao-keepalive.sh status # 看 agent + 当前 IPC/客户端状态
|
|
20
|
+
# bash scripts/ziniao-keepalive.sh print-plist # 只打印 plist(不装;测试用)
|
|
21
|
+
# bash scripts/ziniao-keepalive.sh install # 写 plist + bootstrap(**改本机系统**)
|
|
22
|
+
# bash scripts/ziniao-keepalive.sh uninstall # bootout + 删 plist
|
|
23
|
+
set -uo pipefail
|
|
24
|
+
|
|
25
|
+
# 仓库根与 agent PATH 都用共享实现(写死会让客户机的 plist 指向不存在的脚本)
|
|
26
|
+
. "$(dirname "${BASH_SOURCE[0]}")/lib/repo-root.sh"
|
|
27
|
+
REPO="$(argent_repo_root "${BASH_SOURCE[0]}")"
|
|
28
|
+
AGENT_PATH="$(argent_agent_path)"
|
|
29
|
+
export PATH="$(printf '%s' "$AGENT_PATH" | tr ':' '\n' | head -3 | paste -sd: -):$PATH"
|
|
30
|
+
LABEL="com.whyshu.ziniao-keepalive"
|
|
31
|
+
AGENTS="$HOME/Library/LaunchAgents"
|
|
32
|
+
PLIST="$AGENTS/$LABEL.plist"
|
|
33
|
+
LOGDIR="${ARGENT_LOG_DIR:-$HOME/Library/Logs/argent}"
|
|
34
|
+
UID_N="$(id -u)"
|
|
35
|
+
WD_PORT="${ZINIAO_WD_PORT:-19515}"
|
|
36
|
+
INTERVAL_SEC="${ZINIAO_KEEPALIVE_INTERVAL_SEC:-180}"
|
|
37
|
+
|
|
38
|
+
log() { echo "[$(date '+%F %T')] $*"; }
|
|
39
|
+
pick_py() {
|
|
40
|
+
local c
|
|
41
|
+
for c in "${ARGENT_PY:-}" "$HOME/.dsh/argent/venv/bin/python3" "$REPO/.venv/bin/python3" \
|
|
42
|
+
"$(command -v python3 2>/dev/null || true)"; do
|
|
43
|
+
[ -n "$c" ] && [ -x "$c" ] && { printf '%s' "$c"; return 0; }
|
|
44
|
+
done
|
|
45
|
+
return 1
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
port_listening() {
|
|
49
|
+
"$PY" - "$WD_PORT" <<'PY' 2>/dev/null
|
|
50
|
+
import socket, sys
|
|
51
|
+
s = socket.socket(); s.settimeout(1.0)
|
|
52
|
+
try:
|
|
53
|
+
s.connect(("127.0.0.1", int(sys.argv[1]))); print("yes")
|
|
54
|
+
except Exception:
|
|
55
|
+
print("no")
|
|
56
|
+
finally:
|
|
57
|
+
s.close()
|
|
58
|
+
PY
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
client_running() { pgrep -f "[A]pplications/ziniao.app" >/dev/null 2>&1; }
|
|
62
|
+
|
|
63
|
+
ipc_healthy() {
|
|
64
|
+
# 端口在听 ≠ 服务正常:真发一次 getRunningInfo(免凭据)
|
|
65
|
+
[ "$(port_listening)" = "yes" ] || return 1
|
|
66
|
+
"$PY" - "$REPO" "$WD_PORT" <<'PY' >/dev/null 2>&1
|
|
67
|
+
import importlib.util, pathlib, sys
|
|
68
|
+
repo, port = sys.argv[1], int(sys.argv[2])
|
|
69
|
+
spec = importlib.util.spec_from_file_location("orch", pathlib.Path(repo) / "scripts" / "orchestrator.py")
|
|
70
|
+
m = importlib.util.module_from_spec(spec); sys.modules["orch"] = m; spec.loader.exec_module(m)
|
|
71
|
+
cfg = m.load_config()
|
|
72
|
+
m.wd_running_info(cfg) # 免凭据;失败会抛
|
|
73
|
+
PY
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
cmd_run() {
|
|
77
|
+
local dry=0
|
|
78
|
+
for a in "$@"; do [ "$a" = "--dry-run" ] && dry=1; done
|
|
79
|
+
if [ -f "$PAUSE" ]; then
|
|
80
|
+
log "PAUSE_ZINIAO_KEEPALIVE 存在 ⇒ 跳过本次巡检(运维人工操作中)"; return 0
|
|
81
|
+
fi
|
|
82
|
+
if ipc_healthy; then
|
|
83
|
+
log "✅ WebDriver IPC 正常(端口 ${WD_PORT})"
|
|
84
|
+
# ③ 授权链路每天自愈一次(探针自带 12h 去重;失败不阻塞,只叫人)
|
|
85
|
+
if [ -f "$REPO/scripts/ziniao-auth-probe.sh" ]; then
|
|
86
|
+
bash "$REPO/scripts/ziniao-auth-probe.sh" --quiet || {
|
|
87
|
+
local rc=$?
|
|
88
|
+
[ "$rc" = "2" ] && log "⚠️ 授权链路需要人工(ziniao-auth-probe --force 看详情)"
|
|
89
|
+
}
|
|
90
|
+
fi
|
|
91
|
+
return 0
|
|
92
|
+
fi
|
|
93
|
+
|
|
94
|
+
# IPC 不健康
|
|
95
|
+
if client_running; then
|
|
96
|
+
if [ "${ZINIAO_KEEPALIVE_RESTART:-0}" != "1" ]; then
|
|
97
|
+
log "⚠️ WebDriver IPC 不可用(端口 ${WD_PORT} 未响应)且客户端在跑 ⇒ **不 kill**(会关掉用户手开的窗口)"
|
|
98
|
+
log " 首因通常是**模式不对**:人工打开客户端 = GUI 模式,与 WebDriver 模式不能并存(**不是登录过期**)"
|
|
99
|
+
log " 处置:① 人工按部署约定以 --run_type=web_driver 重启;② 或设 ZINIAO_KEEPALIVE_RESTART=1 让本脚本接管重启"
|
|
100
|
+
return 3
|
|
101
|
+
fi
|
|
102
|
+
log "♻️ ZINIAO_KEEPALIVE_RESTART=1 ⇒ 关闭客户端后以 WebDriver 模式拉起(会关闭已开窗口)"
|
|
103
|
+
[ "$dry" = "1" ] && { log "[dry-run] 将 kill 紫鸟并重启"; return 0; }
|
|
104
|
+
pkill -f "[A]pplications/ziniao.app" 2>/dev/null || true
|
|
105
|
+
sleep 5
|
|
106
|
+
else
|
|
107
|
+
log "ℹ️ 没有紫鸟进程 ⇒ 以 WebDriver 模式启动"
|
|
108
|
+
[ "$dry" = "1" ] && { log "[dry-run] 将启动:open -a /Applications/ziniao.app --args --run_type=web_driver --ipc_type=http --port=${WD_PORT}"; return 0; }
|
|
109
|
+
fi
|
|
110
|
+
|
|
111
|
+
# 启动(官方前的提是主进程已完全退出;上面已确保)
|
|
112
|
+
open -a /Applications/ziniao.app --args --run_type=web_driver --ipc_type=http --port="${WD_PORT}" \
|
|
113
|
+
>/dev/null 2>&1 || { log "❌ open -a 启动失败(紫鸟是否已安装?)"; return 1; }
|
|
114
|
+
local deadline=$(( $(date +%s) + 120 ))
|
|
115
|
+
while [ "$(date +%s)" -lt "$deadline" ]; do
|
|
116
|
+
if ipc_healthy; then
|
|
117
|
+
log "✅ 已拉起并确认 IPC 正常(端口 ${WD_PORT})"
|
|
118
|
+
[ -f "$REPO/scripts/ziniao-auth-probe.sh" ] && bash "$REPO/scripts/ziniao-auth-probe.sh" --quiet || true
|
|
119
|
+
return 0
|
|
120
|
+
fi
|
|
121
|
+
sleep 3
|
|
122
|
+
done
|
|
123
|
+
log "❌ 拉起后 120s 内 IPC 仍不可用 ⇒ 需人工(ziniao-auth-probe --force / 看客户端界面)"
|
|
124
|
+
"$PY" "$REPO/scripts/telemetry.py" --emit --kind engine --flow full --error-class needs_human \
|
|
125
|
+
--detail "紫鸟 keepalive:拉起后 IPC 仍不可用" >/dev/null 2>&1 || true
|
|
126
|
+
"$PY" "$REPO/scripts/telemetry.py" --flush >/dev/null 2>&1 || true
|
|
127
|
+
return 2
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
gen_plist() {
|
|
131
|
+
cat <<PLIST
|
|
132
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
133
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
134
|
+
<!-- 由 scripts/ziniao-keepalive.sh 生成(勿手改) -->
|
|
135
|
+
<plist version="1.0">
|
|
136
|
+
<dict>
|
|
137
|
+
<key>Label</key>
|
|
138
|
+
<string>$LABEL</string>
|
|
139
|
+
<key>ProgramArguments</key>
|
|
140
|
+
<array>
|
|
141
|
+
<string>/bin/bash</string>
|
|
142
|
+
<string>$REPO/scripts/ziniao-keepalive.sh</string>
|
|
143
|
+
<string>run</string>
|
|
144
|
+
</array>
|
|
145
|
+
<key>RunAtLoad</key>
|
|
146
|
+
<true/>
|
|
147
|
+
<key>StartInterval</key>
|
|
148
|
+
<integer>$INTERVAL_SEC</integer>
|
|
149
|
+
<key>AbandonProcessGroup</key>
|
|
150
|
+
<true/>
|
|
151
|
+
<key>EnvironmentVariables</key>
|
|
152
|
+
<dict>
|
|
153
|
+
<key>ARGENT_PY</key><string>$PY</string>
|
|
154
|
+
<key>ZINIAO_WD_PORT</key><string>$WD_PORT</string>
|
|
155
|
+
<key>ZINIAO_KEEPALIVE_RESTART</key><string>${ZINIAO_KEEPALIVE_RESTART:-0}</string>
|
|
156
|
+
<key>PATH</key><string>$AGENT_PATH</string>
|
|
157
|
+
</dict>
|
|
158
|
+
<key>StandardOutPath</key><string>$LOGDIR/ziniao-keepalive.out.log</string>
|
|
159
|
+
<key>StandardErrorPath</key><string>$LOGDIR/ziniao-keepalive.err.log</string>
|
|
160
|
+
</dict>
|
|
161
|
+
</plist>
|
|
162
|
+
PLIST
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
cmd_status() {
|
|
166
|
+
echo "── agent ──"
|
|
167
|
+
launchctl list 2>/dev/null | grep -i "$LABEL" || echo " (未安装:bash scripts/ziniao-keepalive.sh install)"
|
|
168
|
+
echo "── 客户端 ──"
|
|
169
|
+
client_running && echo " ✓ 紫鸟客户端进程在" || echo " ✗ 无紫鸟客户端进程"
|
|
170
|
+
echo " IPC ${WD_PORT}: $(port_listening)"
|
|
171
|
+
ipc_healthy && echo " ✓ getRunningInfo 正常" || echo " ✗ getRunningInfo 异常"
|
|
172
|
+
echo " ${LOGDIR}/ziniao-keepalive.out.log(最近 5 行):"
|
|
173
|
+
tail -5 "$LOGDIR/ziniao-keepalive.out.log" 2>/dev/null | sed 's/^/ /' || echo " (无日志)"
|
|
174
|
+
[ -f "$PAUSE" ] && echo " ⏸ PAUSE_ZINIAO_KEEPALIVE 存在 ⇒ 巡检被跳过"
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
cmd_install() {
|
|
178
|
+
PY="$(pick_py)" || { echo "❌ 找不到 python3" >&2; exit 2; }
|
|
179
|
+
mkdir -p "$AGENTS" "$LOGDIR"
|
|
180
|
+
gen_plist > "$PLIST"
|
|
181
|
+
launchctl bootout "gui/$UID_N/$LABEL" 2>/dev/null || true
|
|
182
|
+
launchctl bootstrap "gui/$UID_N" "$PLIST" 2>/dev/null || launchctl load -w "$PLIST" 2>/dev/null || true
|
|
183
|
+
echo "✅ 已安装 ${PLIST}(RunAtLoad + 每 ${INTERVAL_SEC}s 巡检;日志 $LOGDIR/ziniao-keepalive.*.log)"
|
|
184
|
+
echo " 立刻生效判定:bash scripts/ziniao-keepalive.sh status"
|
|
185
|
+
echo " 卸载:bash scripts/ziniao-keepalive.sh uninstall"
|
|
186
|
+
[ "${ZINIAO_KEEPALIVE_RESTART:-0}" = "1" ] \
|
|
187
|
+
&& echo " ⚠️ ZINIAO_KEEPALIVE_RESTART=1:客户端不在 WebDriver 模式时脚本会**关闭并重启**它(会关掉已开窗口)" \
|
|
188
|
+
|| echo " ℹ️ 默认不 kill 正在跑的 GUI 客户端(生产机若要「永远 WebDriver 模式」,安装前设 ZINIAO_KEEPALIVE_RESTART=1)"
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
cmd_uninstall() {
|
|
192
|
+
launchctl bootout "gui/$UID_N/$LABEL" 2>/dev/null || true
|
|
193
|
+
rm -f "$PLIST"
|
|
194
|
+
echo "🗑 已卸载 ${LABEL}(客户端与店铺窗口**未**被触碰)"
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
PY="$(pick_py)" || { echo "❌ 找不到 python3" >&2; exit 2; }
|
|
198
|
+
|
|
199
|
+
# 数据目录:**唯一判据**在 Python 单一实现(scripts/lib/argent_datadir.py,经 CLI 包装
|
|
200
|
+
# scripts/argent-datadir.py)——⛔ 不在 bash 里重写三级链。取不到 ⇒ 响亮停住(fail-closed)。
|
|
201
|
+
# 放在 `$PY` 之后:客户机 launchd 的 PATH 极简,用**已验过可执行**的解释器最稳。
|
|
202
|
+
DATA="$("$PY" "$REPO/scripts/argent-datadir.py" 2>/dev/null || true)"
|
|
203
|
+
if [ -z "$DATA" ]; then
|
|
204
|
+
echo "❌ $(basename "${BASH_SOURCE[0]}"): 数据目录判据不可用($REPO/scripts/argent-datadir.py 取不到)⇒ 停住,不猜目录" >&2
|
|
205
|
+
exit 2
|
|
206
|
+
fi
|
|
207
|
+
PAUSE="$DATA/PAUSE_ZINIAO_KEEPALIVE"
|
|
208
|
+
|
|
209
|
+
case "${1:-status}" in
|
|
210
|
+
run) shift; cmd_run "$@" ;;
|
|
211
|
+
status) cmd_status ;;
|
|
212
|
+
print-plist) gen_plist ;;
|
|
213
|
+
install) cmd_install ;;
|
|
214
|
+
uninstall) cmd_uninstall ;;
|
|
215
|
+
*) echo "用法:bash scripts/ziniao-keepalive.sh run [--dry-run] | status | print-plist | install | uninstall" >&2; exit 2 ;;
|
|
216
|
+
esac
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# ziniao-post-upgrade-check.sh —— 紫鸟客户端**升级后**的一键复核(只读 + 幂等;不改业务数据)
|
|
3
|
+
#
|
|
4
|
+
# 背景:2026-09-24 排查"30 天人工登录",定位到根因 = 客户端 6.26.6.6 太旧(Bridge 没有 /login 路由
|
|
5
|
+
# ⇒ `zclaw login` 报 `parse login response: invalid character '<'`)。升级客户端后要确认:
|
|
6
|
+
# ① 版本变了;② doctor 的"终端绑定检查"不再报版本不支持;③ `zclaw login` 能成功(这是"免人工"关键);
|
|
7
|
+
# ④ WebDriver 授权链路(IPC + applyAuth/getBrowserList)仍正常;⑤ 客户端回到常驻 WebDriver 模式。
|
|
8
|
+
#
|
|
9
|
+
# 用法:bash scripts/ziniao-post-upgrade-check.sh
|
|
10
|
+
# 退出码:0=全部通过 / 2=有需要人工的项(逐条打印)
|
|
11
|
+
set -uo pipefail
|
|
12
|
+
# 仓库根:共享解析(脚本自身位置优先)—— 写死 ~/Code/argent-dsh 会让客户机
|
|
13
|
+
# (克隆在 ~/.argent-dsh)上找不到本仓文件(2026-09-28 实测)
|
|
14
|
+
. "$(dirname "${BASH_SOURCE[0]}")/lib/repo-root.sh"
|
|
15
|
+
REPO="$(argent_repo_root "${BASH_SOURCE[0]}")"
|
|
16
|
+
# 数据目录:**唯一判据**在 Python 单一实现(scripts/lib/argent_datadir.py,经 CLI 包装
|
|
17
|
+
# scripts/argent-datadir.py)——⛔ 不在 bash 里重写三级链。取不到 ⇒ 响亮停住(fail-closed)。
|
|
18
|
+
# 本脚本自身不依赖 python(纯 shell 诊断)⇒ 这里显式给候选解释器(与各脚本 pick_py 的候选表同源):
|
|
19
|
+
# ARGENT_PY → PATH 的 python3 → 默认位置的 venv。
|
|
20
|
+
_DATA_PY="${ARGENT_PY:-$(command -v python3 2>/dev/null || true)}"
|
|
21
|
+
if [ -z "$_DATA_PY" ] || [ ! -x "$_DATA_PY" ]; then
|
|
22
|
+
_DATA_PY="$HOME/.dsh/argent/venv/bin/python3"
|
|
23
|
+
fi
|
|
24
|
+
DATA="$("$_DATA_PY" "$REPO/scripts/argent-datadir.py" 2>/dev/null || true)"
|
|
25
|
+
if [ -z "$DATA" ]; then
|
|
26
|
+
echo "❌ $(basename "${BASH_SOURCE[0]}"): 数据目录判据不可用($REPO/scripts/argent-datadir.py 取不到)⇒ 停住,不猜目录" >&2
|
|
27
|
+
exit 2
|
|
28
|
+
fi
|
|
29
|
+
PRE="$DATA/.ziniao-pre-upgrade.txt"
|
|
30
|
+
fails=0
|
|
31
|
+
say() { echo "$*"; }
|
|
32
|
+
ok() { echo " ✅ $*"; }
|
|
33
|
+
bad() { echo " ❌ $*"; fails=$((fails+1)); }
|
|
34
|
+
warn(){ echo " ⚠️ $*"; }
|
|
35
|
+
|
|
36
|
+
say "═══ 紫鸟客户端升级后复核 $(date '+%F %T') ═══"
|
|
37
|
+
|
|
38
|
+
say
|
|
39
|
+
say "【0】版本:升级前 → 现在"
|
|
40
|
+
[ -f "$PRE" ] && say " 升级前(快照):$(grep -m1 '^version=' "$PRE" 2>/dev/null | cut -d= -f2-)"
|
|
41
|
+
now="$(defaults read /Applications/ziniao.app/Contents/Info.plist CFBundleShortVersionString 2>/dev/null || echo '?')"
|
|
42
|
+
say " 现在:${now}"
|
|
43
|
+
if [ -d "$DATA/backup" ]; then
|
|
44
|
+
say " 回滚备份:$(ls -d "$DATA"/backup/ziniao-app-*.app 2>/dev/null | tail -1 || echo '(无)')"
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
say
|
|
48
|
+
say "【1】doctor(期望:终端绑定检查不再报「版本不支持」)"
|
|
49
|
+
doc="$(ziniao-cli doctor 2>&1 || true)"
|
|
50
|
+
if echo "$doc" | grep -q "不支持终端绑定检查"; then
|
|
51
|
+
bad "仍报「当前客户端版本不支持终端绑定检查」⇒ 客户端可能没升级成功"
|
|
52
|
+
else
|
|
53
|
+
ok "终端绑定检查不再报版本不支持"
|
|
54
|
+
fi
|
|
55
|
+
echo "$doc" | grep -E "客户端登录用户|API Key 有效|Bridge" | sed 's/^/ /'
|
|
56
|
+
echo "$doc" | grep -q "客户端登录用户" && ok "客户端已登录" || warn "客户端未登录(若被登出,需人工登录一次)"
|
|
57
|
+
|
|
58
|
+
say
|
|
59
|
+
say "【2】zclaw login(「免人工登录」的关键一环)"
|
|
60
|
+
out="$(ziniao-cli zclaw login 2>&1)"; rc=$?
|
|
61
|
+
case "$out" in
|
|
62
|
+
*次数过多*|*请1分钟后再试*)
|
|
63
|
+
warn "zclaw login 被**限流**(供应商:apiKey 登录验证次数过多,请1分钟后再试)⇒ 本次未判定,不是 Key 失效"
|
|
64
|
+
say " (本脚本反复跑会撞限流;等 1 分钟后单独复跑:ziniao-cli zclaw login)" ;;
|
|
65
|
+
*)
|
|
66
|
+
if [ "$rc" = "0" ] && ! echo "$out" | grep -q "invalid character"; then
|
|
67
|
+
ok "zclaw login 成功 ⇒ 以后客户端会话到期可**程序化**恢复,不再需要人工点登录"
|
|
68
|
+
else
|
|
69
|
+
bad "zclaw login 仍失败:$(echo "$out" | head -2 | tr '\n' ' ')"
|
|
70
|
+
say " ⇒ 把这条证据发给紫鸟支持:新 CLI 需要 Bridge 的 /login 路由;并问 WebDriver 模式下该端点是否可用"
|
|
71
|
+
fi ;;
|
|
72
|
+
esac
|
|
73
|
+
|
|
74
|
+
say
|
|
75
|
+
say "【3】WebDriver 授权链路(跑票用;与上面那层无关)"
|
|
76
|
+
if [ -f "$REPO/scripts/ziniao-auth-probe.sh" ]; then
|
|
77
|
+
ZINIAO_AUTH_PROBE_TTL_H=0 bash "$REPO/scripts/ziniao-auth-probe.sh" --force 2>&1 | sed 's/^/ /'
|
|
78
|
+
probe_rc=${PIPESTATUS[0]}
|
|
79
|
+
[ "$probe_rc" = "0" ] && ok "授权链路正常(⓪①② 全绿)" || bad "授权探针退出码 ${probe_rc}(看上面 ⓪①② 分层结论)"
|
|
80
|
+
else
|
|
81
|
+
warn "找不到 ziniao-auth-probe.sh(跳过)"
|
|
82
|
+
fi
|
|
83
|
+
|
|
84
|
+
say
|
|
85
|
+
say "【4】常驻形态:客户端是否在 WebDriver 模式"
|
|
86
|
+
if [ -f "$REPO/scripts/ziniao-keepalive.sh" ]; then
|
|
87
|
+
bash "$REPO/scripts/ziniao-keepalive.sh" status 2>&1 | sed 's/^/ /' | head -8
|
|
88
|
+
say " (若 IPC 不在听:升级期间守护被 PAUSE_ZINIAO_KEEPALIVE 挡住了,"
|
|
89
|
+
say " 确认无票在跑后执行:rm -f $DATA/PAUSE_ZINIAO_KEEPALIVE && bash scripts/*-keepalive.sh run)"
|
|
90
|
+
else
|
|
91
|
+
warn "找不到 *-keepalive.sh(跳过)"
|
|
92
|
+
fi
|
|
93
|
+
|
|
94
|
+
say
|
|
95
|
+
say "【5】ChromeDriver 缓存面 ↔ 内核大版本(只读;P1-g)"
|
|
96
|
+
WINDOWS="$REPO/scripts/ziniao-windows.sh"
|
|
97
|
+
if [ -f "$WINDOWS" ]; then
|
|
98
|
+
# 只读:缓存里有哪些大版本的驱动 ↔ 在跑窗口的内核大版本(免凭据:getRunningInfo + 窗口 CDP)。
|
|
99
|
+
# ⛔ 不下载、不删除、不调需凭据接口;结果只打印,不参与 fails 判据(缓存缺失不是"升级失败")。
|
|
100
|
+
bash "$WINDOWS" cache 2>&1 | sed 's/^/ /' || warn "缓存面巡检未跑成(看上面输出;只读项,不影响升级判定)"
|
|
101
|
+
else
|
|
102
|
+
warn "找不到 *-windows.sh(跳过缓存面巡检)"
|
|
103
|
+
fi
|
|
104
|
+
|
|
105
|
+
say
|
|
106
|
+
say "【6】插件安装状态(只读探测;P1-f)"
|
|
107
|
+
if [ -f "$WINDOWS" ]; then
|
|
108
|
+
# 官方 getPluginInstalled 免凭据,但需要 pluginIds 来源;没有来源时只报「能力未接」(⛔ 不猜)。
|
|
109
|
+
bash "$WINDOWS" plugins 2>&1 | sed 's/^/ /' || warn "插件探测未跑成(只读项,不影响升级判定)"
|
|
110
|
+
else
|
|
111
|
+
warn "找不到 *-windows.sh(跳过插件探测)"
|
|
112
|
+
fi
|
|
113
|
+
|
|
114
|
+
say
|
|
115
|
+
if [ "$fails" = "0" ]; then
|
|
116
|
+
say "✅ 全部通过。下一步(确认无票在跑后):bash scripts/dev-window.sh off(恢复被本窗口暂停的轮询)"
|
|
117
|
+
exit 0
|
|
118
|
+
fi
|
|
119
|
+
say "❌ 有 ${fails} 项需要处理(见上)"
|
|
120
|
+
exit 2
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# ziniao-windows.sh —— 紫鸟**窗口**运维小工具(W5:窗口回收由人显式决定,不自动关)
|
|
3
|
+
#
|
|
4
|
+
# 为什么不做"跑完自动关店"(W5 的原始设想被否):我们刚修好"每轮 startBrowser = 重启窗口"
|
|
5
|
+
# (官方 api-core.md 原文),而**跑完就关店**会让下一轮又得 startBrowser 重启一遍——
|
|
6
|
+
# 等于把刚修掉的病再种回去(端口又会漂、旧标签页又会失效)。
|
|
7
|
+
# 所以:**默认什么都不关**;要回收窗口时由人显式执行本脚本。
|
|
8
|
+
#
|
|
9
|
+
# 用法:
|
|
10
|
+
# bash scripts/*-windows.sh list # 只读:列出当前已开店铺窗口(端口/内核/句柄)
|
|
11
|
+
# bash scripts/*-windows.sh close <店铺名> # 关闭指定店铺窗口(stopBrowser,异步,有界等待)
|
|
12
|
+
# bash scripts/*-windows.sh close --store-id <id>
|
|
13
|
+
# bash scripts/*-windows.sh cache # 只读(P1-g):ChromeDriver 缓存面 ↔ 在跑窗口内核大版本
|
|
14
|
+
# bash scripts/*-windows.sh plugins # 只读(P1-f):插件安装状态(无 pluginIds 来源 ⇒ 只报「能力未接」)
|
|
15
|
+
# bash scripts/*-windows.sh clear-cache [--oauth <店铺标识>]… [--yes]
|
|
16
|
+
# # **写**:清理本地缓存(免凭据;⛔ 默认 dry-run)
|
|
17
|
+
# bash scripts/*-windows.sh clear-online --store <店铺名> [--type 1|2|3] [--yes]
|
|
18
|
+
# # **写 + 需凭据**:清理在线缓存(⛔ 默认 dry-run;
|
|
19
|
+
# # type=3 = 仅保留二步认证 cookie = 登录态在、页面脏时用)
|
|
20
|
+
# ⛔ 后两条**只供人工**:编排路径不会调用它们(默认 dry-run,`--yes` 才真跑)。
|
|
21
|
+
set -uo pipefail
|
|
22
|
+
|
|
23
|
+
# 仓库根:共享解析(脚本自身位置优先)—— 写死 ~/Code/argent-dsh 会让客户机
|
|
24
|
+
# (克隆在 ~/.argent-dsh)上找不到本仓文件(2026-09-28 实测)
|
|
25
|
+
. "$(dirname "${BASH_SOURCE[0]}")/lib/repo-root.sh"
|
|
26
|
+
REPO="$(argent_repo_root "${BASH_SOURCE[0]}")"
|
|
27
|
+
PY="${ARGENT_PY:-$HOME/.dsh/argent/venv/bin/python3}"
|
|
28
|
+
[ -x "$PY" ] || PY="$(command -v python3)"
|
|
29
|
+
|
|
30
|
+
cmd="${1:-list}"; shift || true
|
|
31
|
+
exec "$PY" - "$cmd" "$@" <<'PY'
|
|
32
|
+
import json, os, sys, time
|
|
33
|
+
sys.path.insert(0, os.path.join(os.environ.get("ARGENT_DSH_REPO", os.path.expanduser("~/Code/argent-dsh")), "scripts"))
|
|
34
|
+
import importlib.util, pathlib
|
|
35
|
+
repo = os.environ.get("ARGENT_DSH_REPO", os.path.expanduser("~/Code/argent-dsh"))
|
|
36
|
+
spec = importlib.util.spec_from_file_location("orch", pathlib.Path(repo) / "scripts" / "orchestrator.py")
|
|
37
|
+
m = importlib.util.module_from_spec(spec); sys.modules["orch"] = m; spec.loader.exec_module(m)
|
|
38
|
+
cfg = m.load_config()
|
|
39
|
+
cmd = sys.argv[1] if len(sys.argv) > 1 else "list"
|
|
40
|
+
if cmd == "list":
|
|
41
|
+
inv = m.window_inventory(cfg)
|
|
42
|
+
print("已开店铺窗口:", inv or "(无)")
|
|
43
|
+
print("(口径:官方 getRunningInfo;端口/内核/句柄可用于判断窗口是否被重启过)")
|
|
44
|
+
raise SystemExit(0)
|
|
45
|
+
if cmd == "close":
|
|
46
|
+
target = " ".join(sys.argv[2:]).strip()
|
|
47
|
+
if not target:
|
|
48
|
+
print("用法:ziniao-windows.sh close <店铺名|--store-id <id>>", file=sys.stderr); raise SystemExit(2)
|
|
49
|
+
creds = m._load_wd_creds()
|
|
50
|
+
if creds is None:
|
|
51
|
+
print("✗ 缺少 WebDriver 凭据(~/.dsh/argent/ziniao-webdriver.env)", file=sys.stderr); raise SystemExit(2)
|
|
52
|
+
try:
|
|
53
|
+
stores = m.wd_list_stores(cfg, creds)
|
|
54
|
+
except Exception as exc:
|
|
55
|
+
print(f"✗ 取店铺清单失败:{exc}", file=sys.stderr); raise SystemExit(2)
|
|
56
|
+
if target.startswith("--store-id"):
|
|
57
|
+
sid = target.split()[-1]
|
|
58
|
+
hit = next((s for s in stores if str(s.get("browserId")) == sid), None)
|
|
59
|
+
else:
|
|
60
|
+
hit = next((s for s in stores if str(s.get("browserName")) == target), None)
|
|
61
|
+
if hit is None:
|
|
62
|
+
print(f"✗ 店铺清单里没有 {target!r};先 `ziniao-windows.sh list` 看名字", file=sys.stderr)
|
|
63
|
+
raise SystemExit(2)
|
|
64
|
+
print(f"▸ 关闭店铺窗口:{hit.get('browserName')}(stopBrowser,异步有界等待)")
|
|
65
|
+
m.wd_stop_browser(cfg, creds, hit)
|
|
66
|
+
print("✅ 已请求关闭;用 list 复核(异步关闭通常数秒完成)")
|
|
67
|
+
raise SystemExit(0)
|
|
68
|
+
if cmd == "cache":
|
|
69
|
+
# P1-g(只读):ChromeDriver 缓存面 ↔ 在跑窗口的内核大版本(免凭据:getRunningInfo + 窗口 CDP)
|
|
70
|
+
ver, src = m.detect_running_core_version_free(cfg)
|
|
71
|
+
info = m.chromedriver_cache_inventory(ver)
|
|
72
|
+
print(m.chromedriver_cache_line(info))
|
|
73
|
+
print(f"(内核大版本判据:{ver or '取不到'};来源:{src})")
|
|
74
|
+
print("(口径:官方 prerequisites 的缓存目录 {大版本}/chromedriver;⛔ 只读——不下载、不删除、不连需凭据接口)")
|
|
75
|
+
raise SystemExit(0)
|
|
76
|
+
if cmd == "plugins":
|
|
77
|
+
# P1-f(只读):插件安装状态。没有 pluginIds 来源 ⇒ 如实报「能力未接」,⛔ 不猜、不硬凑
|
|
78
|
+
probe = m.probe_plugin_installed(cfg)
|
|
79
|
+
print(m.format_plugin_probe(probe))
|
|
80
|
+
print(f"(调用计划:callable={probe.get('callable')} reason={probe.get('reason')} "
|
|
81
|
+
f"needs_creds={probe.get('needs_creds')} browserId={probe.get('browser_id') or '(无)'})")
|
|
82
|
+
raise SystemExit(0)
|
|
83
|
+
if cmd in ("clear-cache", "clear-online"):
|
|
84
|
+
# P1-h(**写**操作;⛔ 默认 dry-run,`--yes` 才真跑;编排路径不调用本命令)
|
|
85
|
+
rest = sys.argv[2:]
|
|
86
|
+
yes = "--yes" in rest
|
|
87
|
+
where = lambda flag: [rest[i + 1] for i, a in enumerate(rest)
|
|
88
|
+
if a == flag and i + 1 < len(rest)]
|
|
89
|
+
if cmd == "clear-cache":
|
|
90
|
+
oauths = where("--oauth")
|
|
91
|
+
payload = m.clear_cache_payload(oauths)
|
|
92
|
+
print(m.format_clear_preview(m.clear_request_preview(
|
|
93
|
+
"clear-cache", payload, store_name="、".join(oauths) or "(全部店铺)",
|
|
94
|
+
notes=["免凭据接口;要指定店铺用 --oauth <店铺标识>(可重复),不给 = 全部"])))
|
|
95
|
+
if not yes:
|
|
96
|
+
raise SystemExit(0)
|
|
97
|
+
try:
|
|
98
|
+
resp = m.wd_clear_cache(m._wd_ipc_port(cfg), oauths)
|
|
99
|
+
except Exception as exc: # noqa: BLE001
|
|
100
|
+
print(f"✗ ClearCache 调用失败:{exc}", file=sys.stderr); raise SystemExit(2)
|
|
101
|
+
print(f"✅ ClearCache 已调用:statusCode={resp.get('statusCode')}"
|
|
102
|
+
f"{(' LastError=' + str(resp.get('LastError'))) if resp.get('LastError') else ''}")
|
|
103
|
+
raise SystemExit(0)
|
|
104
|
+
# clear-online:需凭据 + 目标店铺
|
|
105
|
+
typ = 3
|
|
106
|
+
for v in where("--type"):
|
|
107
|
+
try:
|
|
108
|
+
typ = int(v)
|
|
109
|
+
except ValueError:
|
|
110
|
+
print("✗ --type 只能是 1/2/3", file=sys.stderr); raise SystemExit(2)
|
|
111
|
+
creds = m._load_wd_creds()
|
|
112
|
+
if creds is None:
|
|
113
|
+
print("✗ ClearOnline 需要凭据(~/.dsh/argent/ziniao-webdriver.env)", file=sys.stderr)
|
|
114
|
+
raise SystemExit(2)
|
|
115
|
+
target = (where("--store-id") or where("--store") or [""])[0]
|
|
116
|
+
oauth = (where("--oauth") or [""])[0]
|
|
117
|
+
if target and not oauth:
|
|
118
|
+
try:
|
|
119
|
+
stores = m.wd_list_stores(cfg, creds)
|
|
120
|
+
except Exception as exc: # noqa: BLE001
|
|
121
|
+
print(f"✗ 取店铺清单失败:{exc}", file=sys.stderr); raise SystemExit(2)
|
|
122
|
+
key = "--store-id" if where("--store-id") else "--store"
|
|
123
|
+
hit = next((s for s in stores if str(s.get("browserId" if key == "--store-id" else "browserName")) == target), None)
|
|
124
|
+
if hit is None:
|
|
125
|
+
print(f"✗ 店铺清单里没有 {target!r};先 `scripts/*-windows.sh list` 看名字", file=sys.stderr)
|
|
126
|
+
raise SystemExit(2)
|
|
127
|
+
oauth = str(hit.get("browserOauth") or hit.get("browserId") or "")
|
|
128
|
+
if not oauth:
|
|
129
|
+
print("✗ ClearOnline 需要 --store <店铺名> / --store-id <id> / --oauth <店铺标识> 之一", file=sys.stderr)
|
|
130
|
+
raise SystemExit(2)
|
|
131
|
+
try:
|
|
132
|
+
payload = m.clear_online_payload(creds, oauth, typ)
|
|
133
|
+
except ValueError as exc:
|
|
134
|
+
print(f"✗ {exc}", file=sys.stderr); raise SystemExit(2)
|
|
135
|
+
print(m.format_clear_preview(m.clear_request_preview(
|
|
136
|
+
"clear-online", payload, store_name=target or oauth,
|
|
137
|
+
notes=[f"type={typ} 的适用场景见上一行;写操作会改本机店铺缓存的在线状态",
|
|
138
|
+
"真要跑请确认该店铺**没有**在跑票(编排路径不会自动调用本命令)"])))
|
|
139
|
+
if not yes:
|
|
140
|
+
raise SystemExit(0)
|
|
141
|
+
try:
|
|
142
|
+
resp = m.wd_clear_online(m._wd_ipc_port(cfg), creds, oauth, typ)
|
|
143
|
+
except Exception as exc: # noqa: BLE001
|
|
144
|
+
print(f"✗ ClearOnline 调用失败:{exc}", file=sys.stderr); raise SystemExit(2)
|
|
145
|
+
print(f"✅ ClearOnline 已调用(type={typ}):statusCode={resp.get('statusCode')}"
|
|
146
|
+
f" {resp.get('statusMsg') or ''}"
|
|
147
|
+
f"{(' LastError=' + str(resp.get('LastError'))) if resp.get('LastError') else ''}")
|
|
148
|
+
raise SystemExit(0)
|
|
149
|
+
print("用法:list | close <店铺名|--store-id <id>> | cache | plugins | "
|
|
150
|
+
"clear-cache [--oauth <店铺标识>]… [--yes] | "
|
|
151
|
+
"clear-online (--store <店铺名>|--oauth <店铺标识>) [--type 1|2|3] [--yes]",
|
|
152
|
+
file=sys.stderr); raise SystemExit(2)
|
|
153
|
+
PY
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const VERSION = "0.6.0"
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# 业务线(vertical)契约
|
|
2
|
+
|
|
3
|
+
> Argent 0.2 起,**底座与业务线分离**:底座(引擎/角色运行时/装机器/门禁/商业机制)业务中立,
|
|
4
|
+
> 一条业务线 = 一个可独立开发、安装、授权、迭代、回滚的单元。
|
|
5
|
+
> 本文件是**业务线作者**(含将来的第三方)的唯一入口;引擎侧规则见
|
|
6
|
+
> `docs/Argent-0.2-平台与业务线架构-评审稿-2026-09-29.md`。
|
|
7
|
+
|
|
8
|
+
## 一条业务线长什么样
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
verticals/<id>/
|
|
12
|
+
manifest.json 元数据:版本、依赖区间、端口、能力、角色、技能、流程清单
|
|
13
|
+
flows.json 流程声明(局部 id;合并后规范 id = <id>.<local>)
|
|
14
|
+
prompts/<flow>.md 派发提示词(引擎按轮次投给角色)
|
|
15
|
+
roles/ 角色 preset 源 → 安装到 `presets/argent-<id>-<role>/`
|
|
16
|
+
skills/ 技能源 → 安装到 `skills/<id>-<skill>/`
|
|
17
|
+
adapters/<system>/ 外部系统适配器(人工门、错误词表、可执行计划)
|
|
18
|
+
billing.json 计费单位(只算成功 / 一票一结 / 证据可核)
|
|
19
|
+
preflight.py 本线验收检查段(由 customer-preflight 汇总)
|
|
20
|
+
tests/ 本线测试与夹具(run-all-tests.sh 自动收集)
|
|
21
|
+
env/ 本线环境变量(600;**只在本线可见**)
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## 三条硬规矩(`vertical-lint.mjs` 会拦)
|
|
25
|
+
|
|
26
|
+
1. **命名空间**:所有对外可见的名字都带业务线前缀 —— 两条线装在同一台机器上不允许撞名。
|
|
27
|
+
|
|
28
|
+
| 对象 | 规则 | 例(`id=customer-order`) |
|
|
29
|
+
|---|---|---|
|
|
30
|
+
| flow id | `<id>.<local>` | `customer-order.intake` |
|
|
31
|
+
| 角色(preset) | `argent-<id>-<role>` | `argent-customer-order-clerk` |
|
|
32
|
+
| 技能 | `<id>-<skill>` | `customer-order-intake` |
|
|
33
|
+
| 暂停开关 | `verticals/<id>/PAUSE.<flow>` | `verticals/customer-order/PAUSE.intake` |
|
|
34
|
+
| 定时器 label | `com.whyshu.flow-trigger.<id>.<flow>` | 自动派生 |
|
|
35
|
+
| env 文件 | `verticals/<id>/env/*.env` | `verticals/customer-order/env/prod.env` |
|
|
36
|
+
| 提示词 | `verticals/<id>/prompts/*.md` | — |
|
|
37
|
+
| 能力包 id | `<id>.<unit>` | `customer-order.intake` |
|
|
38
|
+
|
|
39
|
+
2. **跨线引用为零**:`verticals/A` 不得引用 `verticals/B` 的路径、flow、角色、技能。
|
|
40
|
+
两条线需要共享的东西,**上提到引擎或端口**,不要在业务线之间拉手。
|
|
41
|
+
|
|
42
|
+
3. **引擎不掺业务**:`scripts/` 与 `plugins/<plugin>/src/` 不得出现业务词(美客多/文鳐/紫鸟/…)。
|
|
43
|
+
历史存量记在 `_engine-words.baseline.txt`,门禁只拦**新增**;搬迁完成后基线应清零。
|
|
44
|
+
|
|
45
|
+
## 冲突判据在加载器,不在 lint
|
|
46
|
+
|
|
47
|
+
`scripts/flow_registry.py` 负责合并 **base(`scripts/flow-requirements.json`)+ 各业务线**,并保证:
|
|
48
|
+
同名 flow / 能力 / 计费单位 / 失败类 / 别名 **一律 fail(不静默覆盖)**;`manifest.id`、
|
|
49
|
+
`flows.json#vertical` 与目录名不一致也 fail(防复制粘贴串线)。
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
python3 scripts/flow_registry.py --check # 合并与冲突
|
|
53
|
+
python3 scripts/flow_registry.py --list # 规范 flow id
|
|
54
|
+
python3 scripts/flow_registry.py --flow intake # 别名 → 规范 id
|
|
55
|
+
node scripts/vertical-lint.mjs # 业务线门禁
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
回退开关:`ARGENT_REGISTRY_MODE=legacy`(只读 base,不扫业务线);显式 `--registry <file>` 亦为 legacy 单文件行为。
|
|
59
|
+
|
|
60
|
+
## 端口(该线用到哪些底座能力)
|
|
61
|
+
|
|
62
|
+
在 `manifest.json#ports` 声明;新增实现时同步更新 `vertical-lint.mjs` 的 `KNOWN_PORTS`。
|
|
63
|
+
|
|
64
|
+
| 端口 | 职责 | 现有实现 |
|
|
65
|
+
|---|---|---|
|
|
66
|
+
| `source` | 任务队列/数据源 | `feishu-base`(唯一实现;`http-json`/`sql`/`file`/`manual` 待做,见 P4) |
|
|
67
|
+
| `transport` | 人机通道(收指令、唤醒) | `feishu`(`gateway-core` 拆分后可有 `web`/`wecom`) |
|
|
68
|
+
| `notify` | 出站通知/卡片 | `feishu-card`、`log` |
|
|
69
|
+
| `actor` | 外部系统动作 | `none`、`internal-http`;货代类见 `scripts/integrations/`(待泛化) |
|
|
70
|
+
| `identity` | 凭据/身份 | `env`(`verticals/<id>/env/*.env`) |
|
|
71
|
+
|
|
72
|
+
## 开一条新线
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
node scripts/vertical-init.mjs --id customer-order --title "客单系统" \
|
|
76
|
+
--flow intake --role clerk --skill intake
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
生成物是**安全态**(`wake=off`、`mode=shadow`),按 `verticals/<id>/README.md` 的待办清单逐项填。
|
|
80
|
+
上线顺序固定:**只读跑通 → `mode=real` → `wake=session`**。
|
|
81
|
+
|
|
82
|
+
## 门禁(每条线都要过)
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
node scripts/vertical-lint.mjs # 本文件的三条硬规矩 + manifest 自洽
|
|
86
|
+
python3 scripts/flow_registry.py --check
|
|
87
|
+
node scripts/tests/run-all-tests.sh # 平台回归 + 本线测试(tests/ 自动收集)
|
|
88
|
+
node scripts/gen-preset-rows.mjs # 改了角色后必跑(0.1.7 行式 preset)
|
|
89
|
+
node scripts/validate-preset-schema.mjs --runtime && node scripts/plugin-bootcheck.mjs
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## 安装与授权
|
|
93
|
+
|
|
94
|
+
- 业务线是**安装边界**:`install-argent.mjs --add-capability <id>` 只落本线声明的文件,
|
|
95
|
+
别的线的文件不会上机器;`--rollback` 按线回退上一版。
|
|
96
|
+
- 授权:`manifest.capabilities[].minPlan` + 注册表 `entitlements`(档位矩阵是唯一出处)。
|
|
97
|
+
- 装机前校验 `manifest.requires.{argent,dsh}` 与 `verifiedOn`("已在哪些版本实测过")——
|
|
98
|
+
不允许把没验过的线装到目标机器上。
|
|
99
|
+
|
|
100
|
+
## 与 profile 的关系
|
|
101
|
+
|
|
102
|
+
**能力包能分开的,用包分;包分不开的(专属插件/专属通道/不同 dsh 版本/独立 UI),
|
|
103
|
+
才用 dsh profile 分**(`dsh web --profile <v> --port <n>`)。默认形态是"业务线包 + 共用 base profile"。
|