@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,99 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# dsh-remote-check.sh —— 远程访问(EasyTier 组网 → 端口转发 → dsh web 围栏)一条命令自检。
|
|
3
|
+
#
|
|
4
|
+
# 为什么有它(2026-09-22 事故):Mac 重启后 PC 打不开 dsh web,排查发现**三处硬编码了同一个
|
|
5
|
+
# 会变的地址**,而失败是"进程还活着、日志写在 /tmp(重启即清)"⇒ 表面看一切正常:
|
|
6
|
+
# ① EasyTier 用 -d(DHCP) ⇒ 重启后地址 .2 → .1;
|
|
7
|
+
# ② dsh-portforward.py --listen-host 10.126.126.2 ⇒ bind 失败(日志 /tmp,无迹可查);
|
|
8
|
+
# ③ dsh-web --trusted-host 10.126.126.2:3080 ⇒ 新地址被围栏 403。
|
|
9
|
+
# 本脚本按层体检,并明确告诉你卡在哪一层、下一步做什么。
|
|
10
|
+
set -uo pipefail
|
|
11
|
+
CIDR="${ARGENT_OVERLAY_CIDR:-10.126.126.}"
|
|
12
|
+
LOGDIR="$HOME/Library/Logs/argent"
|
|
13
|
+
rc=0
|
|
14
|
+
|
|
15
|
+
echo "── ① EasyTier 进程与覆盖网地址"
|
|
16
|
+
if pgrep -x easytier-core >/dev/null; then
|
|
17
|
+
echo " ✅ easytier-core 在跑(PID $(pgrep -x easytier-core | head -1))"
|
|
18
|
+
else
|
|
19
|
+
echo " ❌ easytier-core 没在跑 ⇒ PC 根本到不了这台机器"
|
|
20
|
+
echo " ↳ 修:/Users/$USER/.local/bin/start-easytier.sh(或在 launchd 里 kickstart com.easytier.whyshu)"
|
|
21
|
+
rc=1
|
|
22
|
+
fi
|
|
23
|
+
mapfile -t OVERLAY < <(ifconfig 2>/dev/null | awk '/inet /{print $2}' | grep "^${CIDR}" || true)
|
|
24
|
+
if [ "${#OVERLAY[@]}" -eq 0 ]; then
|
|
25
|
+
echo " ❌ 找不到 ${CIDR}x 的地址(覆盖网没起来 / 地址变了)"
|
|
26
|
+
rc=1
|
|
27
|
+
else
|
|
28
|
+
echo " ✅ 覆盖网地址:${OVERLAY[*]}"
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
echo "── ② 端口转发(本机覆盖网 IP:3080 → 127.0.0.1:3080)"
|
|
32
|
+
if launchctl list com.whyshu.dsh-portforward >/dev/null 2>&1; then
|
|
33
|
+
echo " ✅ LaunchAgent 已加载(pid=$(launchctl list | awk '/dsh-portforward/{print $1}'))"
|
|
34
|
+
else
|
|
35
|
+
echo " ❌ LaunchAgent 未加载 ⇒ 外部无法从覆盖网访问"
|
|
36
|
+
echo " ↳ 修:bash ~/Code/argent-dsh/scripts/dsh-remote-access.sh install(若提供)或 launchctl bootstrap gui/\$(id -u) ~/Library/LaunchAgents/com.whyshu.dsh-portforward.plist"
|
|
37
|
+
rc=1
|
|
38
|
+
fi
|
|
39
|
+
BOUND=$(lsof -nP -iTCP:3080 -sTCP:LISTEN 2>/dev/null | awk -v p="$CIDR" '$9 ~ p {print $9}')
|
|
40
|
+
if [ -n "$BOUND" ]; then
|
|
41
|
+
echo " ✅ 已监听:$BOUND"
|
|
42
|
+
else
|
|
43
|
+
echo " ❌ 覆盖网上没有监听 3080(转发器多半 bind 失败——典型原因:它被写死到某个已不存在的地址)"
|
|
44
|
+
echo " ↳ 看日志:tail -20 $LOGDIR/dsh-portforward.log(历史事故里这条日志曾写在 /tmp,重启即清)"
|
|
45
|
+
rc=1
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
echo "── ③ dsh web 围栏(trusted-host)与可达性"
|
|
49
|
+
TRUST=$(plutil -p ~/Library/LaunchAgents/com.whyshu.dsh-web.plist 2>/dev/null \
|
|
50
|
+
| grep -oE '[0-9]{1,3}(\.[0-9]{1,3}){3}:[0-9]+' | sort -u | tr '\n' ' ')
|
|
51
|
+
echo " plist 里的 trusted-host:${TRUST:-(无)}"
|
|
52
|
+
# ⚠️ plist 改了 ≠ 生效:launchd 的 `kickstart -k` 用的是**缓存的旧定义**(2026-09-22 实测:
|
|
53
|
+
# 改完 plist 再 kickstart,运行中的进程仍只有旧地址 ⇒ 新地址继续 403)。必须比对运行参数。
|
|
54
|
+
#
|
|
55
|
+
# 2026-10-01 修**假警报**(与 dsh-restart.sh 同一处判据,用户实测):dsh web 是**父子两段**
|
|
56
|
+
# 进程(启动器 `dsh-web-launch.mjs web …` + 真正采用参数的 `…/dsh/lib/bin.js web …`),
|
|
57
|
+
# launchd 起的 argv[0] 又是绝对路径。旧的 `grep "[d]sh web" | head -1` 只取一个进程 ⇒
|
|
58
|
+
# 随手就会误报"未采用"。现判据 = **全部相关进程的 trusted-host 并集**,唯一实现
|
|
59
|
+
# 在 `scripts/lib/dsh-web-probe.mjs`(与 dsh-restart.sh 共用,收集/比对/文案都只有一份)。
|
|
60
|
+
# 退出码:0 通过 | 1 **真的缺失** | 2 没找到进程(未运行/进程名不符)| 3 探测失败。
|
|
61
|
+
PROBE="$(dirname "${BASH_SOURCE[0]}")/lib/dsh-web-probe.mjs"
|
|
62
|
+
if [ ! -f "$PROBE" ]; then
|
|
63
|
+
echo " ⚠️ 探测模块缺失(${PROBE})⇒ 跳过运行参数核对(不退回旧的单进程判据:它会把父子两段误报成「未采用」)"
|
|
64
|
+
else
|
|
65
|
+
node "$PROBE" --want "$TRUST" | sed 's/^/ /'
|
|
66
|
+
PROBE_RC=${PIPESTATUS[0]}
|
|
67
|
+
case "$PROBE_RC" in
|
|
68
|
+
0) : ;;
|
|
69
|
+
1) rc=1 ;;
|
|
70
|
+
*) echo " ↳ 这只是**没能核对**(不是「未采用」);服务是否被信任仍看下面的逐地址探测结果" ;;
|
|
71
|
+
esac
|
|
72
|
+
fi
|
|
73
|
+
for ip in "${OVERLAY[@]}"; do
|
|
74
|
+
code=$(curl -s -o /dev/null -m 5 -w "%{http_code}" "http://$ip:3080/api" -H "Host: $ip:3080" || echo 000)
|
|
75
|
+
case "$code" in
|
|
76
|
+
401) echo " ✅ $ip:3080 可达且被信任(HTTP 401 = 需要登录,属正常)" ;;
|
|
77
|
+
403) echo " ⚠️ $ip:3080 被 dsh web 围栏拒绝(HTTP 403)⇒ 该地址不在 trusted-host 里"
|
|
78
|
+
echo " ↳ plist 已补地址,但要**重启 dsh web** 才生效:bash ~/Code/argent-dsh/scripts/dsh-restart.sh"; rc=1 ;;
|
|
79
|
+
000) echo " ❌ $ip:3080 连不上(转发或覆盖网问题,看上两层)"; rc=1 ;;
|
|
80
|
+
*) echo " ⚠️ $ip:3080 返回 HTTP $code" ;;
|
|
81
|
+
esac
|
|
82
|
+
done
|
|
83
|
+
# 白名单是否覆盖当前地址(未覆盖 ⇒ 重启 dsh web 才生效;没重启就会 403)
|
|
84
|
+
if [ "${#OVERLAY[@]}" -gt 0 ]; then
|
|
85
|
+
cur="${OVERLAY[0]}:3080"
|
|
86
|
+
if ! grep -q "$cur" <<<"$TRUST"; then
|
|
87
|
+
echo " ⚠️ 当前地址 $cur 不在 trusted-host 里 ⇒ PC 会收到 403"
|
|
88
|
+
echo " ↳ 修:plist 已补该地址,需**重启 dsh web** 生效:bash ~/Code/argent-dsh/scripts/dsh-restart.sh"
|
|
89
|
+
rc=1
|
|
90
|
+
fi
|
|
91
|
+
fi
|
|
92
|
+
|
|
93
|
+
echo "── ④ PC 侧应使用的地址"
|
|
94
|
+
if [ "${#OVERLAY[@]}" -gt 0 ]; then
|
|
95
|
+
echo " http://${OVERLAY[0]}:3080/ (若 EasyTier 已按 -i 固定地址,则用固定那个)"
|
|
96
|
+
fi
|
|
97
|
+
echo
|
|
98
|
+
[ "$rc" -eq 0 ] && echo " ✅ 远程访问链路正常" || echo " ❌ 上面标 ❌/⚠️ 的层需要处理"
|
|
99
|
+
exit $rc
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# dsh-restart.sh — 可靠重启 dsh web 服务(处理 launchd 各种状态)
|
|
3
|
+
#
|
|
4
|
+
# 背景:bootout 后立即 bootstrap 偶发 'Bootstrap failed: 5: Input/output error'
|
|
5
|
+
# (macOS launchd 状态刷新问题)——本脚本自动处理:已加载→kickstart;未加载→
|
|
6
|
+
# enable + bootstrap(带重试);最后验证 3080 监听。
|
|
7
|
+
#
|
|
8
|
+
# 用法:bash ~/Code/argent-dsh/scripts/dsh-restart.sh
|
|
9
|
+
# bash ~/Code/argent-dsh/scripts/dsh-restart.sh --check # **只读**:只报日志落点+启动行(token 脱敏),不重启
|
|
10
|
+
set -u
|
|
11
|
+
|
|
12
|
+
LABEL="com.whyshu.dsh-web"
|
|
13
|
+
PLIST="$HOME/Library/LaunchAgents/$LABEL.plist"
|
|
14
|
+
UID_NUM=$(id -u)
|
|
15
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
16
|
+
|
|
17
|
+
# ── dsh-web 启动日志的落点:**跟随"日志被挪到哪儿了"**,不再硬编码 /tmp ──────────────
|
|
18
|
+
# 事故(2026-10-08):这里曾写死 `/tmp/dsh-web.log` ⇒ 运维按 wake-auth 的建议把日志挪到
|
|
19
|
+
# `~/.dsh/logs/`(客户机)后,本脚本仍去读旧路径 ⇒ **打印上一次启动的陈旧 token**(看着成功、其实误导),
|
|
20
|
+
# 且"3080 未监听"分支把人指向一个已经不存在的文件。
|
|
21
|
+
# 顺序与 `scripts/lib/wake-auth.mjs#logPaths()` 的**路径**部分保持一致(那边是唤醒端的鉴权来源链):
|
|
22
|
+
# $DSH_WEB_LOG → plist 的 StandardOutPath/StandardErrorPath → $DSH_HOME/dsh-web.log
|
|
23
|
+
# → ~/Library/Logs/dsh-web.log → /tmp/dsh-web.log(历史兜底,最后)
|
|
24
|
+
# 为什么本脚本**不**直接 import `wake-auth.mjs`(取"最小且无循环依赖"):
|
|
25
|
+
# ① 本脚本的价值恰恰在"服务/环境已经坏了"时仍能跑 ⇒ 不引入 node 运行时依赖;
|
|
26
|
+
# ② `wake-auth.mjs` 的失败文案会指引读者来跑**本脚本**(authFailureText 里点名 dsh-restart.sh)
|
|
27
|
+
# ⇒ 本脚本反过来 import 它即成循环;
|
|
28
|
+
# ③ wake-auth 的**主源**是 credentials 里的签名 cookie(唤醒端的凭据面)——重启脚本不需要、
|
|
29
|
+
# 也不该读凭据,更不该对刚起来的服务做网络探测;
|
|
30
|
+
# ④ 本脚本只需要"日志落点"这一件事,读 plist 就够(`plutil` 本就是本脚本已有的依赖,见下 WANT_TRUST)。
|
|
31
|
+
dsh_web_log_path() {
|
|
32
|
+
if [ -n "${DSH_WEB_LOG:-}" ]; then printf '%s' "$DSH_WEB_LOG"; return; fi
|
|
33
|
+
local p=""
|
|
34
|
+
p=$(plutil -p "$PLIST" 2>/dev/null | sed -n 's/^[[:space:]]*"StandardOutPath"[[:space:]]*=>[[:space:]]*"\(.*\)"$/\1/p' | head -1)
|
|
35
|
+
case "$p" in /*) printf '%s' "$p"; return;; esac
|
|
36
|
+
p=$(plutil -p "$PLIST" 2>/dev/null | sed -n 's/^[[:space:]]*"StandardErrorPath"[[:space:]]*=>[[:space:]]*"\(.*\)"$/\1/p' | head -1)
|
|
37
|
+
case "$p" in /*) printf '%s' "$p"; return;; esac
|
|
38
|
+
p="${DSH_HOME:-$HOME/.dsh}/dsh-web.log"
|
|
39
|
+
if [ -f "$p" ]; then printf '%s' "$p"; return; fi
|
|
40
|
+
p="$HOME/Library/Logs/dsh-web.log"
|
|
41
|
+
if [ -f "$p" ]; then printf '%s' "$p"; return; fi
|
|
42
|
+
printf '%s' "/tmp/dsh-web.log"
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
# token 脱敏:**沿用既有约定**(`scripts/lib/settings-panels.mjs:104`:留首尾各 3 位,中间 ****)。
|
|
46
|
+
mask_token() {
|
|
47
|
+
local s="$1"
|
|
48
|
+
if [ "${#s}" -le 8 ]; then printf '%s' '******'; else printf '%s' "${s:0:3}****${s: -3}"; fi
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
# 只读报告:日志落点 + 启动行(token **脱敏**);`--check` 与"重启成功后"共用这一份实现(避免两处口径漂移)。
|
|
52
|
+
report_dsh_web_log() {
|
|
53
|
+
local LOG TOK URL_LINE
|
|
54
|
+
LOG="$(dsh_web_log_path)"
|
|
55
|
+
echo " 启动日志: $LOG"
|
|
56
|
+
# ⛔ **绝不打印 token 明文**(2026-10-08):token 是每进程随机的,且这行取自日志的**最后一次**启动记录
|
|
57
|
+
# —— 打印它既无必要(有 cookie 就不需要 token),又会因读到旧记录而**误导**(本脚本的前身就这么错过)。
|
|
58
|
+
# 这里只确认"日志里有启动行"并按既有约定**脱敏**展示;完整 URL 由操作者按提示自己取。
|
|
59
|
+
if [ -f "$LOG" ]; then
|
|
60
|
+
URL_LINE=$(grep "dsh web: http" "$LOG" 2>/dev/null | tail -1 | sed 's/^.*dsh web: //')
|
|
61
|
+
if [ -n "$URL_LINE" ]; then
|
|
62
|
+
TOK="${URL_LINE##*token=}"
|
|
63
|
+
if [ "$TOK" != "$URL_LINE" ]; then
|
|
64
|
+
echo " 带 token 的 URL(**已脱敏**,仅供确认启动行存在): ${URL_LINE%token=*}token=$(mask_token "$TOK")"
|
|
65
|
+
else
|
|
66
|
+
echo " 启动 URL(该行不含 token=): $URL_LINE"
|
|
67
|
+
fi
|
|
68
|
+
echo " 完整 URL 请自行取(本脚本不打印明文):grep 'dsh web: http' \"$LOG\" | tail -1"
|
|
69
|
+
else
|
|
70
|
+
echo " ⚠️ 取不到启动 URL:日志 $LOG 里没有 'dsh web: http' 行(刚起来还没写?稍等再看一次)"
|
|
71
|
+
echo " grep 'dsh web: http' \"$LOG\" | tail -1"
|
|
72
|
+
fi
|
|
73
|
+
else
|
|
74
|
+
echo " ⚠️ 取不到启动 URL:日志文件不存在(${LOG})"
|
|
75
|
+
echo " ⇒ 若日志已被挪走,核 plist 的落点声明(本脚本就是按它找的):"
|
|
76
|
+
echo " plutil -p \"$PLIST\" | grep -i StandardOutPath"
|
|
77
|
+
echo " ⇒ token 的其它来源(不依赖日志)见 scripts/lib/wake-auth.mjs 的来源优先级表"
|
|
78
|
+
fi
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if [ ! -f "$PLIST" ]; then
|
|
82
|
+
echo "❌ plist 不存在: $PLIST"
|
|
83
|
+
exit 1
|
|
84
|
+
fi
|
|
85
|
+
|
|
86
|
+
# ── 只读模式(`--check`):只报告日志落点与启动行(token 脱敏),**不碰 launchd、不重启** ──
|
|
87
|
+
# 用途:① 运维确认"日志被挪到哪儿了"(本脚本按 plist 解析,不再硬编码 /tmp);
|
|
88
|
+
# ② 双端核对 / 回归测试 —— 让"验证这条路径"不必以重启生产服务为代价。
|
|
89
|
+
if [ "${1:-}" = "--check" ] || [ "${1:-}" = "--print-log-path" ]; then
|
|
90
|
+
if lsof -nP -iTCP:3080 -sTCP:LISTEN 2>/dev/null | grep -q node; then
|
|
91
|
+
echo "✅ dsh web 正在监听 3080(只读检查,未做任何改动)"
|
|
92
|
+
else
|
|
93
|
+
echo "⚠️ 3080 当前没有 node 监听(只读检查,未做任何改动)"
|
|
94
|
+
fi
|
|
95
|
+
report_dsh_web_log
|
|
96
|
+
exit 0
|
|
97
|
+
fi
|
|
98
|
+
|
|
99
|
+
# 先记下 plist 里的权威参数(重启后要核对进程是否真的采用了)
|
|
100
|
+
WANT_TRUST=$(plutil -p "$PLIST" 2>/dev/null | grep -oE '[0-9]{1,3}(\.[0-9]{1,3}){3}:[0-9]+' | sort -u | tr '\n' ' ')
|
|
101
|
+
|
|
102
|
+
if launchctl list | grep -q "$LABEL"; then
|
|
103
|
+
echo "→ 完整重载(bootout → bootstrap):只有这样才能让**磁盘上改过的 plist 生效**"
|
|
104
|
+
launchctl bootout "gui/$UID_NUM/$LABEL" 2>/dev/null || true
|
|
105
|
+
sleep 3
|
|
106
|
+
fi
|
|
107
|
+
launchctl enable "gui/$UID_NUM/$LABEL" 2>/dev/null || true
|
|
108
|
+
if ! launchctl bootstrap "gui/$UID_NUM" "$PLIST"; then
|
|
109
|
+
echo "⚠️ bootstrap 失败(launchd 偶发 IO error),5s 后重试…"
|
|
110
|
+
sleep 5
|
|
111
|
+
launchctl bootstrap "gui/$UID_NUM" "$PLIST" || {
|
|
112
|
+
echo "❌ 两次 bootstrap 都失败——plist 语法?plutil -lint \"$PLIST\""
|
|
113
|
+
exit 1
|
|
114
|
+
}
|
|
115
|
+
fi
|
|
116
|
+
|
|
117
|
+
echo "→ 等待服务就绪(10s)…"
|
|
118
|
+
sleep 10
|
|
119
|
+
if lsof -nP -iTCP:3080 -sTCP:LISTEN 2>/dev/null | grep -q node; then
|
|
120
|
+
echo "✅ dsh web 已就绪"
|
|
121
|
+
echo " 访问: http://127.0.0.1:3080/(已有 cookie 的浏览器直接用,无需 token)"
|
|
122
|
+
report_dsh_web_log
|
|
123
|
+
# 运行参数核对:进程实际带的 --trusted-host 必须覆盖 plist 里声明的全部地址,
|
|
124
|
+
# 否则"重启了但没生效"(2026-09-22 实测:kickstart 沿用缓存旧定义 ⇒ 新地址仍 403)
|
|
125
|
+
#
|
|
126
|
+
# 2026-10-01 修**假警报**(用户实测:明明 3 个进程都带参数,却报"未采用"且 `进程=` 是空的):
|
|
127
|
+
# dsh web 是**父子两段**进程 —— 启动器 `dsh-web-launch.mjs web …` + 真正采用参数的
|
|
128
|
+
# `…/@deepseek-ai/dsh/lib/bin.js web …`;而 launchd 起的 argv[0] 是**绝对路径**
|
|
129
|
+
# (`/opt/homebrew/bin/node`)。旧写法 `grep -E "^node .*/dsh web" | head -1` 两处都不占:
|
|
130
|
+
# ① `^node ` 匹配不到绝对路径;② 只看第一个匹配 ⇒ RUN_ARGS 恒空 ⇒ **每个地址都被误报**。
|
|
131
|
+
# 现判据 = **全部相关进程的 trusted-host 并集**(唯一实现在 scripts/lib/dsh-web-probe.mjs,
|
|
132
|
+
# dsh-remote-check.sh 复用同一模块;收集/比对/文案都只有一份)。
|
|
133
|
+
# 退出码语义:0 通过 | 1 **真的缺失**(唯一该失败的情形)| 2 没找到进程 | 3 探测失败。
|
|
134
|
+
# 2/3 明确报"没核对上",绝不打印空白的"进程="让人误解成"没采用"。
|
|
135
|
+
PROBE="$SCRIPT_DIR/lib/dsh-web-probe.mjs"
|
|
136
|
+
if [ -f "$PROBE" ]; then
|
|
137
|
+
node "$PROBE" --want "$WANT_TRUST"
|
|
138
|
+
PROBE_RC=$?
|
|
139
|
+
case "$PROBE_RC" in
|
|
140
|
+
0) : ;;
|
|
141
|
+
1) exit 1 ;;
|
|
142
|
+
*) echo " ↳ 服务本身已就绪(3080 在监听),但**没能核对**运行参数;如需人工复核:bash $SCRIPT_DIR/dsh-remote-check.sh" ;;
|
|
143
|
+
esac
|
|
144
|
+
else
|
|
145
|
+
echo " ⚠️ 探测模块缺失(${PROBE})⇒ 跳过 trusted-host 核对"
|
|
146
|
+
echo " (刻意不退回旧的单进程判据:它会把父子两段进程误报成「未采用」)"
|
|
147
|
+
fi
|
|
148
|
+
|
|
149
|
+
# ── 计费/provider 诊断摘要(**只读**;重启成功后打印一次)─────────────────────────
|
|
150
|
+
# 2026-10-01 处置(任务「计费模式自愈死代码」):
|
|
151
|
+
# · 旧块(`check-billing-mode.sh --fix`)挂在两个 `exit` **之后** ⇒ 永不可达(死代码);
|
|
152
|
+
# · 更要紧的是它的**意图**:`--fix` 历史上会改写 `llm-deepseek.baseURL` / 重写
|
|
153
|
+
# `~/.dsh/settings.yaml` —— 前者 = 劫持官方直连 provider(provider id 仍叫 deepseek-official,
|
|
154
|
+
# 实际指向问述),后者是官方 schema 的自有文件(被"自身 schema 重写"会丢掉未知的 `llm-*` 段,
|
|
155
|
+
# 实测文件只剩 1 字节 ⇒ 模式静默退回直连、积分不再扣)。**用户明确禁止**这两件事
|
|
156
|
+
# (见 ~/.dsh/AGENTS.md「LLM provider 设计」)。所以这里**只报告、绝不写文件**:
|
|
157
|
+
# 跑一次只读报告;异常时**打印建议命令**,由用户自己决定要不要执行。
|
|
158
|
+
BILLING="$SCRIPT_DIR/check-billing-mode.sh"
|
|
159
|
+
if [ -x "$BILLING" ]; then
|
|
160
|
+
echo
|
|
161
|
+
echo "── 计费/provider 诊断(只读;本脚本不会替你做任何修改)──"
|
|
162
|
+
if ! bash "$BILLING"; then
|
|
163
|
+
echo " ↳ provider 装配异常(组合**声明了**的 provider 没装上 exit=1 / 无法判定 exit=2)。建议命令(**需你手动执行**):"
|
|
164
|
+
echo " bash $SCRIPT_DIR/provider-select.sh status # 看当前默认 provider"
|
|
165
|
+
echo " bash $SCRIPT_DIR/provider-select.sh whyshu # 或 deepseek;改完需重启 dsh"
|
|
166
|
+
echo " ⛔ 不要用 check-billing-mode.sh --fix(已熔断,exit 3):改 provider 请走模型选择器"
|
|
167
|
+
fi
|
|
168
|
+
fi
|
|
169
|
+
exit 0
|
|
170
|
+
else
|
|
171
|
+
LOG="$(dsh_web_log_path)"
|
|
172
|
+
echo "❌ 3080 未监听——检查日志:tail -40 $LOG"
|
|
173
|
+
echo " (日志落点按 plist 的 StandardOutPath 解析;若与预期不符:plutil -p \"$PLIST\" | grep -i StandardOutPath)"
|
|
174
|
+
exit 1
|
|
175
|
+
fi
|
|
176
|
+
|
|
177
|
+
# ⚠️ 本行之后**不要**再放任何代码:上面两个分支都以 exit 结尾 ⇒ 写在这里的代码**永不可达**。
|
|
178
|
+
# (2026-09-29 的「计费模式自愈」块就是这么变成死代码的:它挂在 exit 之后,从未执行过一次;
|
|
179
|
+
# 而死代码比"没有这段代码"更危险 —— 读代码的人以为它在生效,出问题时排错方向全错。)
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# dsh-restore —— 默认入口的**人工还原**(P5,2026-09-29):不依赖 dsh,纯 shell + node。
|
|
3
|
+
#
|
|
4
|
+
# 用途(救援面也挂了时的最后一道保险):
|
|
5
|
+
# bash scripts/dsh-restore.sh --list # 看当前指针、审计、可用树
|
|
6
|
+
# bash scripts/dsh-restore.sh --to <树目录> # 把默认入口指到某棵树(并重载服务)
|
|
7
|
+
# bash scripts/dsh-restore.sh --to <树目录> --no-reload
|
|
8
|
+
# bash scripts/dsh-restore.sh --rollback # 回退到审计里的上一棵 known-good 树
|
|
9
|
+
#
|
|
10
|
+
# 为什么单独有它:`dsh-web-launch.mjs` 的熔断也走同一套指针与审计 —— 两边共用
|
|
11
|
+
# `scripts/lib/scope-pointer.mjs`(唯一真源),所以人工还原和自动熔断不会各写一套。
|
|
12
|
+
#
|
|
13
|
+
# ⛔ 重载服务 = 重启 dsh web(会中断当前会话)。除本脚本的人工调用与熔断那一次自动重启外,
|
|
14
|
+
# 任何自动化都不得重启服务(AGENTS.md「严禁自杀式重启」)。
|
|
15
|
+
set -uo pipefail
|
|
16
|
+
REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
17
|
+
DSH_HOME="${DSH_HOME:-$HOME/.dsh}"
|
|
18
|
+
LABEL="${DSH_RESTORE_LABEL:-com.whyshu.dsh-web}"
|
|
19
|
+
POINTER="$DSH_HOME/argent/base/current-scope"
|
|
20
|
+
NODE="${ARGENT_NODE:-$(command -v node || true)}"
|
|
21
|
+
|
|
22
|
+
[ -n "$NODE" ] || { echo "✗ 找不到 node(可用 ARGENT_NODE 指定)" >&2; exit 2; }
|
|
23
|
+
|
|
24
|
+
MODE=""; TARGET=""; RELOAD=1
|
|
25
|
+
while [ $# -gt 0 ]; do
|
|
26
|
+
case "$1" in
|
|
27
|
+
--list) MODE=list; shift;;
|
|
28
|
+
--rollback) MODE=rollback; shift;;
|
|
29
|
+
--to) MODE=to; TARGET="${2:-}"; shift 2;;
|
|
30
|
+
--no-reload) RELOAD=0; shift;;
|
|
31
|
+
-h|--help) sed -n '2,16p' "$0" | sed 's/^# \{0,1\}//'; exit 0;;
|
|
32
|
+
*) echo "未知参数:$1(--help)" >&2; exit 2;;
|
|
33
|
+
esac
|
|
34
|
+
done
|
|
35
|
+
|
|
36
|
+
pointer_of() { "$NODE" -e '
|
|
37
|
+
import { readPointer } from "./scripts/lib/scope-pointer.mjs"
|
|
38
|
+
process.stdout.write(readPointer() || "")
|
|
39
|
+
' ; }
|
|
40
|
+
|
|
41
|
+
if [ "$MODE" = list ] || [ -z "$MODE" ]; then
|
|
42
|
+
echo "指针文件:$POINTER"
|
|
43
|
+
echo "当前指向:$("$NODE" -e '
|
|
44
|
+
import { readPointer } from "./scripts/lib/scope-pointer.mjs"
|
|
45
|
+
console.log(readPointer() || "(未设置)")
|
|
46
|
+
' 2>/dev/null)"
|
|
47
|
+
echo
|
|
48
|
+
echo "审计(最近 10 条切换):"
|
|
49
|
+
"$NODE" -e '
|
|
50
|
+
import { readHistory } from "./scripts/lib/scope-pointer.mjs"
|
|
51
|
+
const h = readHistory(process.env, 10)
|
|
52
|
+
if (!h.length) console.log(" (无)")
|
|
53
|
+
for (const e of h) console.log(` ${e.at || "?"} → ${e.scopeDir}${e.reason ? "(" + e.reason + ")" : ""}`)
|
|
54
|
+
' 2>/dev/null | sed 's/^/ /'
|
|
55
|
+
echo
|
|
56
|
+
echo "候选树(存在且像 dsh 安装):"
|
|
57
|
+
for c in /opt/homebrew/lib/node_modules/@deepseek-ai "$HOME/node/lib/node_modules/@deepseek-ai" \
|
|
58
|
+
"$HOME"/dsh-*/lib/node_modules/@deepseek-ai; do
|
|
59
|
+
[ -d "$c" ] || continue
|
|
60
|
+
if [ -f "$c/dsh/lib/bin.js" ]; then echo " ✅ $c"; else echo " ⚠️ ${c}(缺 dsh/lib/bin.js)"; fi
|
|
61
|
+
done
|
|
62
|
+
echo
|
|
63
|
+
echo "整树备份(⚠️ 需先搬到 node_modules/ 下才能当默认入口):"
|
|
64
|
+
for b in "$HOME"/.dsh/argent/backup/*/scope; do
|
|
65
|
+
[ -d "$b" ] || continue
|
|
66
|
+
if "$NODE" -e 'import("./scripts/lib/scope-pointer.mjs").then(m => process.exit(m.looksLikeScope(process.argv[1]) ? 0 : 1))' "$b" 2>/dev/null; then
|
|
67
|
+
echo " ✅ ${b}(布局可用)"
|
|
68
|
+
else
|
|
69
|
+
echo " ⚠️ ${b}(有 dsh 入口但布局不可直接运行 ⇒ 搬到 <root>/lib/node_modules/@deepseek-ai)"
|
|
70
|
+
fi
|
|
71
|
+
done
|
|
72
|
+
[ -n "$MODE" ] && exit 0
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
if [ "$MODE" = rollback ]; then
|
|
76
|
+
TARGET="$("$NODE" -e '
|
|
77
|
+
import { previousScope } from "./scripts/lib/scope-pointer.mjs"
|
|
78
|
+
console.log(previousScope(process.env) || "")
|
|
79
|
+
')"
|
|
80
|
+
[ -n "$TARGET" ] || { echo "✗ 审计里找不到可回退的树(用 --to 显式指定)" >&2; exit 2; }
|
|
81
|
+
echo "回退目标(来自审计):$TARGET"
|
|
82
|
+
fi
|
|
83
|
+
|
|
84
|
+
if [ "$MODE" = to ] || [ "$MODE" = rollback ]; then
|
|
85
|
+
[ -n "$TARGET" ] || { echo "✗ --to 需要一个树目录" >&2; exit 2; }
|
|
86
|
+
[ -f "$TARGET/dsh/lib/bin.js" ] || { echo "✗ 目标不是 dsh 安装树(缺 dsh/lib/bin.js):$TARGET" >&2; exit 2; }
|
|
87
|
+
"$NODE" -e '
|
|
88
|
+
import { writePointer, readPointer } from "./scripts/lib/scope-pointer.mjs"
|
|
89
|
+
const target = process.argv[1]
|
|
90
|
+
const before = readPointer()
|
|
91
|
+
writePointer(target, { reason: "manual restore (dsh-restore.sh)", previous: before })
|
|
92
|
+
console.log(`✅ 指针:${before || "(未设置)"} → ${target}`)
|
|
93
|
+
' "$TARGET" || exit 1
|
|
94
|
+
|
|
95
|
+
# 人工还原 = "人已介入" ⇒ 顺手解除熔断标记(否则下次启动会被启动器拒绝)
|
|
96
|
+
if "$NODE" --input-type=module -e 'import { clearFused } from "./scripts/lib/scope-pointer.mjs"; process.exit(clearFused() ? 0 : 1)' 2>/dev/null; then
|
|
97
|
+
echo " ✅ 已解除熔断标记(如曾有)"
|
|
98
|
+
fi
|
|
99
|
+
|
|
100
|
+
if [ "$RELOAD" = 1 ]; then
|
|
101
|
+
echo "重载 LaunchAgent:${LABEL}(这会重启 dsh web 服务)"
|
|
102
|
+
launchctl kickstart -k "gui/$(id -u)/$LABEL" 2>/dev/null \
|
|
103
|
+
|| { echo " ⚠️ kickstart 失败,尝试 bootout+bootstrap"; \
|
|
104
|
+
launchctl bootout "gui/$(id -u)/$LABEL" 2>/dev/null; \
|
|
105
|
+
launchctl bootstrap "gui/$(id -u)" "$HOME/Library/LaunchAgents/$LABEL.plist"; }
|
|
106
|
+
sleep 3
|
|
107
|
+
if pgrep -f "dsh web" >/dev/null; then echo " ✅ 服务进程在跑"; else echo " ✗ 服务未起来 —— 看 /tmp/dsh-web.log 与 --list 的候选树"; fi
|
|
108
|
+
else
|
|
109
|
+
echo "(--no-reload:未重启服务;下次服务重启时生效)"
|
|
110
|
+
fi
|
|
111
|
+
fi
|