@dsh-workbench/core 0.3.11 → 1.0.0-beta.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/LICENSE +21 -0
- package/README.md +148 -117
- package/bin/dsh-workbench +130 -29
- package/bin/dsh-workbench.cmd +5 -0
- package/bin/opencli-isolated +3 -2
- package/bin/opencli-isolated.mjs +44 -0
- package/bin/opencli-node-mode.cjs +1 -0
- package/bin/seed-workshop-windows.mjs +307 -0
- package/client.js +6572 -3959
- package/cordis.patch.yml +3 -3
- package/dist/client/client.body.js +6572 -3959
- package/dist/client/index.js +6417 -3804
- package/dist/host/index.js +5704 -5945
- package/dist/types/app/client.d.ts +1 -0
- package/dist/types/app/host.d.ts +2 -1
- package/dist/types/app/layouts/approval-detail.d.ts +3 -0
- package/dist/types/app/layouts/env-gate/boot-gate.d.ts +1 -12
- package/dist/types/app/layouts/env-gate/gate-text.d.ts +2 -1
- package/dist/types/app/layouts/market/DiscoverPanel.d.ts +8 -0
- package/dist/types/app/layouts/market/add-module-text.d.ts +1 -1
- package/dist/types/app/layouts/market/discover-categories.d.ts +8 -0
- package/dist/types/app/layouts/market/discover-confirm.d.ts +14 -0
- package/dist/types/app/layouts/market/discover-detail.d.ts +12 -0
- package/dist/types/app/layouts/market/discover-dialogs.d.ts +7 -0
- package/dist/types/app/layouts/market/discover-doc.d.ts +18 -0
- package/dist/types/app/layouts/market/discover-init-dialog.d.ts +10 -0
- package/dist/types/app/layouts/market/discover-rows.d.ts +24 -0
- package/dist/types/app/layouts/market/discover-sources-dialog.d.ts +16 -0
- package/dist/types/app/layouts/market/discover-states.d.ts +22 -0
- package/dist/types/app/layouts/market/discover-toolbar.d.ts +23 -0
- package/dist/types/app/layouts/market/discover-versions.d.ts +9 -0
- package/dist/types/app/layouts/market/discover-view.d.ts +38 -0
- package/dist/types/app/layouts/market/market-header.d.ts +13 -0
- package/dist/types/app/layouts/market/panel.d.ts +1 -1
- package/dist/types/app/layouts/market/use-add-module.d.ts +1 -1
- package/dist/types/app/layouts/market/use-discover.d.ts +72 -0
- package/dist/types/app/layouts/market/use-module-versions.d.ts +1 -8
- package/dist/types/app/layouts/rightbar/MarketView.d.ts +1 -1
- package/dist/types/app/layouts/rightbar/Rightbar.d.ts +1 -1
- package/dist/types/app/layouts/rightbar/board-shape.d.ts +1 -14
- package/dist/types/app/layouts/rightbar/market-busy.d.ts +0 -22
- package/dist/types/app/layouts/rightbar/market-change.d.ts +1 -1
- package/dist/types/app/layouts/rightbar/market-hint.d.ts +1 -7
- package/dist/types/app/layouts/rightbar/market-plugin-rows.d.ts +0 -7
- package/dist/types/app/layouts/rightbar/market-row-icon.d.ts +1 -1
- package/dist/types/app/layouts/rightbar/market-row-types.d.ts +2 -2
- package/dist/types/app/layouts/rightbar/market-rows.d.ts +1 -1
- package/dist/types/app/layouts/rightbar/market-section-icon.d.ts +1 -1
- package/dist/types/app/layouts/rightbar/market-settle-hold.d.ts +1 -1
- package/dist/types/app/layouts/rightbar/market-settle.d.ts +4 -7
- package/dist/types/app/layouts/rightbar/market-shared-rows.d.ts +1 -1
- package/dist/types/app/layouts/rightbar/market-update-verdict.d.ts +1 -11
- package/dist/types/app/layouts/rightbar/market-view-text.d.ts +5 -1
- package/dist/types/app/layouts/rightbar/market-workbench-row.d.ts +1 -1
- package/dist/types/app/layouts/rightbar/store.d.ts +0 -12
- package/dist/types/app/layouts/sidebar/LongTaskDot.d.ts +0 -6
- package/dist/types/app/layouts/sidebar/LongTaskHover.d.ts +0 -6
- package/dist/types/app/layouts/sidebar/edition-boot.d.ts +1 -19
- package/dist/types/app/layouts/sidebar/edition.d.ts +1 -18
- package/dist/types/app/layouts/sidebar/use-attention.d.ts +0 -4
- package/dist/types/app/layouts/sidebar/workshop-preset.d.ts +2 -0
- package/dist/types/app/layouts/workbench-settings/AdapterSetItem.d.ts +5 -0
- package/dist/types/app/layouts/workbench-settings/ConfigSyncRows.d.ts +11 -0
- package/dist/types/app/layouts/workbench-settings/NewWorkbenchItem.d.ts +5 -0
- package/dist/types/app/layouts/workbench-settings/SettingsItem.d.ts +0 -9
- package/dist/types/app/layouts/workbench-settings/SidebarEditionItem.d.ts +0 -6
- package/dist/types/app/layouts/workbench-settings/WorkbenchSettingsSection.d.ts +0 -6
- package/dist/types/app/units/manifests.d.ts +1 -1
- package/dist/types/{app/units → kernel/client}/registry.d.ts +1 -1
- package/dist/types/kernel/contract/bundle-install.d.ts +2 -0
- package/dist/types/kernel/contract/config-sync.d.ts +2 -0
- package/dist/types/kernel/contract/diy.d.ts +1 -0
- package/dist/types/kernel/contract/dsh-plugins.d.ts +2 -0
- package/dist/types/kernel/contract/index.d.ts +4 -0
- package/dist/types/kernel/contract/long-tasks.d.ts +2 -0
- package/dist/types/kernel/contract/market-index.d.ts +2 -0
- package/dist/types/kernel/contract/platform.d.ts +1 -0
- package/dist/types/kernel/contract/preflight-wake.d.ts +2 -0
- package/dist/types/kernel/contract/profile-create.d.ts +2 -0
- package/dist/types/kernel/contract/sidebar-edition.d.ts +2 -0
- package/dist/types/kernel/contract/unit-manifests.d.ts +2 -0
- package/dist/types/{shared/api → kernel}/host/mount-units.d.ts +2 -1
- package/dist/types/modules/panels/client.d.ts +1 -1
- package/dist/types/modules/panels/model/approval.d.ts +3 -15
- package/dist/types/modules/panels/model/diy-changelog.d.ts +2 -0
- package/dist/types/modules/panels/model/diy-context.d.ts +1 -16
- package/dist/types/modules/panels/model/diy-page.d.ts +1 -0
- package/dist/types/modules/panels/model/diy-record-open.d.ts +0 -15
- package/dist/types/modules/panels/model/diy-record-text.d.ts +0 -2
- package/dist/types/modules/panels/model/diy-record.d.ts +0 -30
- package/dist/types/modules/panels/model/diy-tools.d.ts +1 -0
- package/dist/types/modules/panels/model/long-task-tools.d.ts +0 -11
- package/dist/types/modules/panels/model/market-dependency-update.d.ts +1 -7
- package/dist/types/modules/panels/model/market-dependency.d.ts +15 -10
- package/dist/types/modules/panels/model/market-discover-routes.d.ts +3 -0
- package/dist/types/modules/panels/model/market-discover.d.ts +33 -0
- package/dist/types/modules/panels/model/market-dispatch.d.ts +3 -3
- package/dist/types/modules/panels/model/market-env.d.ts +2 -3
- package/dist/types/modules/panels/model/market-registry.d.ts +3 -3
- package/dist/types/modules/panels/model/market-restart.d.ts +1 -1
- package/dist/types/modules/panels/model/market-route.d.ts +5 -3
- package/dist/types/modules/panels/model/market-sources-act.d.ts +9 -0
- package/dist/types/modules/panels/model/market-types.d.ts +6 -13
- package/dist/types/modules/panels/model/market-update-bundle.d.ts +3 -9
- package/dist/types/modules/panels/model/market-verify.d.ts +3 -19
- package/dist/types/modules/panels/model/market-workbench-update.d.ts +3 -2
- package/dist/types/modules/panels/model/market.d.ts +6 -5
- package/dist/types/modules/panels/model/plugin-actions.d.ts +2 -1
- package/dist/types/modules/panels/model/plugin-section.d.ts +3 -1
- package/dist/types/modules/panels/model/publish-preview-routes.d.ts +2 -0
- package/dist/types/modules/panels/unit.d.ts +7 -3
- package/dist/types/modules/sessions/model/attention.d.ts +0 -11
- package/dist/types/modules/sessions/model/session-node.d.ts +0 -10
- package/dist/types/shared/api/diy.d.ts +6 -4
- package/dist/types/shared/api/host/approval-call.d.ts +0 -9
- package/dist/types/shared/api/host/approval-gate.d.ts +0 -13
- package/dist/types/shared/api/host/bundle-routes.d.ts +1 -1
- package/dist/types/shared/api/host/diy-artifacts.d.ts +0 -11
- package/dist/types/shared/api/host/diy-changelog.d.ts +13 -0
- package/dist/types/shared/api/host/diy-components.d.ts +2 -3
- package/dist/types/shared/api/host/diy-modules.d.ts +0 -16
- package/dist/types/shared/api/host/diy-publish-preview.d.ts +4 -0
- package/dist/types/shared/api/host/diy-recon-fs.d.ts +2 -2
- package/dist/types/shared/api/host/diy-tokens.d.ts +8 -0
- package/dist/types/shared/api/host/host-routes.d.ts +3 -6
- package/dist/types/shared/api/host/long-task-notice.d.ts +0 -20
- package/dist/types/shared/api/host/long-tasks.d.ts +1 -8
- package/dist/types/shared/api/host/market-doc.d.ts +21 -0
- package/dist/types/shared/api/host/market-index-fetch.d.ts +37 -0
- package/dist/types/shared/api/host/market-source-init.d.ts +22 -0
- package/dist/types/shared/api/host/market-sources-store.d.ts +15 -0
- package/dist/types/shared/api/host/permission-mode.d.ts +0 -5
- package/dist/types/shared/api/host/post-channels.d.ts +1 -1
- package/dist/types/shared/api/host/sidebar-edition.d.ts +1 -33
- package/dist/types/shared/api/host/unit-roster-facts.d.ts +1 -1
- package/dist/types/shared/api/host/workspace-root.d.ts +0 -7
- package/dist/types/shared/api/platform/client.d.ts +10 -0
- package/dist/types/shared/api/unit-board.d.ts +0 -16
- package/dist/types/shared/api/write-outcome.d.ts +0 -12
- package/dist/types/shared/components/IconModules.d.ts +0 -6
- package/dist/types/shared/components/PanelFoot.d.ts +0 -9
- package/dist/types/shared/components/blocker-action.d.ts +0 -13
- package/dist/types/shared/dev-surface/index.d.ts +5 -0
- package/dist/types/shared/dev-surface/types.d.ts +79 -0
- package/dist/types/shared/hooks/bundle-queries.d.ts +1 -13
- package/dist/types/shared/hooks/fact-transport.d.ts +4 -0
- package/dist/types/shared/hooks/fact-transports.d.ts +0 -4
- package/dist/types/shared/hooks/market-queries.d.ts +11 -0
- package/dist/types/shared/hooks/panel-state-report.d.ts +0 -12
- package/dist/types/shared/hooks/sidebar-edition.d.ts +1 -6
- package/dist/types/shared/hooks/use-blocker-actions.d.ts +0 -8
- package/dist/types/shared/hooks/use-capabilities.d.ts +0 -59
- package/dist/types/shared/hooks/use-diy-debug.d.ts +0 -13
- package/dist/types/shared/hooks/use-diy-record.d.ts +0 -13
- package/dist/types/shared/hooks/use-shell-long-tasks.d.ts +1 -7
- package/icon.svg +17 -28
- package/package.json +33 -13
- package/preset/diy.patch.yml +1 -1
- package/profile/isolation.patch.yml +8 -8
- package/profile/sandbox.patch.yml +2 -2
- package/scripts/clone-profile.mjs +268 -0
- package/scripts/create-workbench.mjs +166 -0
- package/scripts/seed-profile.sh +22 -10
- package/scripts/seed-workshop.sh +17 -19
- package/skills/workbench-module-diy/BUILD.md +4 -11
- package/skills/workbench-module-diy/COPY.md +1 -1
- package/skills/workbench-module-diy/DATASOURCE.md +107 -22
- package/skills/workbench-module-diy/DESIGN.md +2 -1
- package/skills/workbench-module-diy/FAMILY.md +48 -68
- package/skills/workbench-module-diy/KIT.md +2 -1
- package/skills/workbench-module-diy/LINKAGE.md +1 -1
- package/skills/workbench-module-diy/PANEL.md +5 -3
- package/skills/workbench-module-diy/REVIEW.md +7 -7
- package/skills/workbench-module-diy/SKILL.md +20 -11
- package/skills/workbench-module-diy/STEPS.md +1 -1
- package/skills/workbench-module-diy/TOOLS.md +33 -9
- package/skills/workbench-module-diy/WIRING.md +18 -6
- package/skills/workbench-module-diy/WRITES.md +30 -4
- package/dist/types/shared/api/bundle-install.d.ts +0 -136
- package/dist/types/shared/api/config-sync.d.ts +0 -35
- package/dist/types/shared/api/dsh-plugins.d.ts +0 -11
- package/dist/types/shared/api/host/bundle-manager.d.ts +0 -11
- package/dist/types/shared/api/host/config-sync.d.ts +0 -46
- package/dist/types/shared/api/host/diy-preset-health.d.ts +0 -35
- package/dist/types/shared/api/host/dsh-plugins.d.ts +0 -5
- package/dist/types/shared/api/host/installed-module.d.ts +0 -54
- package/dist/types/shared/api/host/installed-module.test.d.ts +0 -1
- package/dist/types/shared/api/host/opencli-command.d.ts +0 -10
- package/dist/types/shared/api/host/opencli-command.test.d.ts +0 -1
- package/dist/types/shared/api/host/opencli.test.d.ts +0 -1
- package/dist/types/shared/api/host/package-content.d.ts +0 -6
- package/dist/types/shared/api/host/package-content.test.d.ts +0 -1
- package/dist/types/shared/api/host/package-kind.d.ts +0 -21
- package/dist/types/shared/api/host/package-kind.test.d.ts +0 -1
- package/dist/types/shared/api/host/package-route.d.ts +0 -23
- package/dist/types/shared/api/host/package-route.test.d.ts +0 -1
- package/dist/types/shared/api/host/plugin-catalog.d.ts +0 -65
- package/dist/types/shared/api/host/plugin-login-hint.d.ts +0 -2
- package/dist/types/shared/api/host/plugin-tools.d.ts +0 -14
- package/dist/types/shared/api/host/plugin-units.d.ts +0 -48
- package/dist/types/shared/api/host/preflight-route.d.ts +0 -15
- package/dist/types/shared/api/host/preflight.d.ts +0 -75
- package/dist/types/shared/api/host/probe-cache.d.ts +0 -6
- package/dist/types/shared/api/host/probe-libs.d.ts +0 -11
- package/dist/types/shared/api/host/probe-units.d.ts +0 -17
- package/dist/types/shared/api/host/probe-verdict.d.ts +0 -7
- package/dist/types/shared/api/host/profile-registries.d.ts +0 -21
- package/dist/types/shared/api/host/registry-declaration.d.ts +0 -23
- package/dist/types/shared/api/host/release.d.ts +0 -24
- package/dist/types/shared/api/host/runtime-seed.d.ts +0 -40
- package/dist/types/shared/api/host/self-update.d.ts +0 -52
- package/dist/types/shared/api/host/version-range.d.ts +0 -2
- package/dist/types/shared/api/long-tasks.d.ts +0 -19
- package/dist/types/shared/api/sidebar-edition.d.ts +0 -14
- package/dist/types/shared/api/unit-manifests.d.ts +0 -6
- package/docs/HANDOFF.md +0 -333
- package/docs/OPERATIONS.md +0 -240
- package/skills/workbench-module-diy/TOOLING.md +0 -38
- /package/dist/types/{app/layouts/rightbar/registry.d.ts → kernel/client/board-registry.d.ts} +0 -0
- /package/dist/types/{app/layouts/rightbar/registry.test.d.ts → kernel/contract/contracts.test.d.ts} +0 -0
- /package/dist/types/{shared/api/host/bundle-manager.test.d.ts → kernel/contract/index.test.d.ts} +0 -0
- /package/dist/types/{shared/api → kernel}/host/unit-readiness.d.ts +0 -0
- /package/dist/types/{shared/api → kernel}/host/unit-registry.d.ts +0 -0
- /package/dist/types/shared/{api/host/dsh-plugins.test.d.ts → dev-surface/install.d.ts} +0 -0
package/scripts/seed-profile.sh
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
#
|
|
7
7
|
# **设置不在这里继承**(这里曾经把 web 的 cordis.patch.yml 快照一份过来):
|
|
8
8
|
# 工作台自己的 patch 是唯一真相,想搬 web 的哪几行由用户走「设置 → 配置同步」。
|
|
9
|
-
# 为什么这么分(安装 vs
|
|
9
|
+
# 为什么这么分(安装 vs 设置)、为什么不再是自动的:内部设计记录
|
|
10
10
|
#
|
|
11
11
|
# 幂等 / 可续跑:profile 已存在就跳过创建,隔离层已存在就跳过追加
|
|
12
12
|
# —— 重复运行不会覆盖任何东西。
|
|
@@ -23,8 +23,11 @@ set -euo pipefail
|
|
|
23
23
|
|
|
24
24
|
DSH_HOME="${DSH_HOME:-$HOME/.dsh}"
|
|
25
25
|
PROFILE="${WORKBENCH_PROFILE:-workbench}"
|
|
26
|
-
|
|
26
|
+
SRC_PROFILE_NAME="${WORKBENCH_SOURCE_PROFILE:-web}"
|
|
27
|
+
SRC_PROFILE="$DSH_HOME/profiles/$SRC_PROFILE_NAME"
|
|
27
28
|
DST_PROFILE="$DSH_HOME/profiles/$PROFILE"
|
|
29
|
+
WORKBENCH_HOME="${DSH_WORKBENCH_HOME:-$DSH_HOME/$PROFILE}"
|
|
30
|
+
export DSH_WORKBENCH_HOME="$WORKBENCH_HOME"
|
|
28
31
|
PKG='@dsh-workbench/core'
|
|
29
32
|
REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
30
33
|
GIT_TOP="$(git -C "$REPO_DIR" rev-parse --show-toplevel 2>/dev/null || true)"
|
|
@@ -93,8 +96,10 @@ if [ "${1:-}" = "ensure-selected" ]; then
|
|
|
93
96
|
exit 0
|
|
94
97
|
fi
|
|
95
98
|
|
|
96
|
-
|
|
97
|
-
|
|
99
|
+
HAS_SOURCE=0
|
|
100
|
+
if [ -f "$SRC_PROFILE/package.json" ]; then
|
|
101
|
+
HAS_SOURCE=1
|
|
102
|
+
fi
|
|
98
103
|
[ -f "$ISOLATION" ] || die "找不到 $ISOLATION"
|
|
99
104
|
|
|
100
105
|
DST_PATCH="$DST_PROFILE/cordis.patch.yml"
|
|
@@ -107,8 +112,8 @@ DST_PATCH="$DST_PROFILE/cordis.patch.yml"
|
|
|
107
112
|
if [ -f "$DST_PROFILE/package.json" ]; then
|
|
108
113
|
echo "→ profile '$PROFILE' 已存在,跳过创建"
|
|
109
114
|
else
|
|
110
|
-
echo "→ 创建 profile '$PROFILE'(模板:
|
|
111
|
-
dsh "$PROFILE" --from-default-profile
|
|
115
|
+
echo "→ 创建 profile '$PROFILE'(模板: ${SRC_PROFILE_NAME})"
|
|
116
|
+
dsh "$PROFILE" --from-default-profile "$SRC_PROFILE_NAME" --dump-config >/dev/null
|
|
112
117
|
fi
|
|
113
118
|
|
|
114
119
|
[ -f "$DST_PATCH" ] || die "profile 缺少 $DST_PATCH"
|
|
@@ -119,8 +124,10 @@ fi
|
|
|
119
124
|
# 改过(例如启用了某个可选 bundle)。所以这里把 web 清单里的 bundles
|
|
120
125
|
# 并进来,同时保留 workbench 自己已有的额外项(例如 @dsh-workbench/core),
|
|
121
126
|
# 使脚本可重复运行。
|
|
127
|
+
if [ "$HAS_SOURCE" = "1" ]; then
|
|
122
128
|
WB_MANIFEST="$DST_PROFILE/package.json" \
|
|
123
129
|
WEB_MANIFEST="$SRC_PROFILE/package.json" \
|
|
130
|
+
WB_SOURCE_NAME="$SRC_PROFILE_NAME" \
|
|
124
131
|
node -e '
|
|
125
132
|
const fs = require("node:fs");
|
|
126
133
|
const read = (p) => JSON.parse(fs.readFileSync(p, "utf8"));
|
|
@@ -137,15 +144,18 @@ wb.dsh = Object.assign({}, wb.dsh, {
|
|
|
137
144
|
profile: Object.assign({}, webProfile, wbProfile, { bundles: merged }),
|
|
138
145
|
});
|
|
139
146
|
fs.writeFileSync(process.env.WB_MANIFEST, JSON.stringify(wb, null, 2) + "\n");
|
|
140
|
-
console.log("→ 已继承
|
|
147
|
+
console.log("→ 已继承 " + process.env.WB_SOURCE_NAME + " 的 bundle 列表: " + merged.join(", "));
|
|
141
148
|
'
|
|
149
|
+
else
|
|
150
|
+
echo "→ 本机还没有来源 profile '$SRC_PROFILE_NAME';用 dsh 出厂模板的 bundle 列表(如需继承它的设置/插件,先跑一次来源 profile)"
|
|
151
|
+
fi
|
|
142
152
|
|
|
143
153
|
# ── 第 2.5 步:修掉旧版启动器留下的"装出来的那份被当成仓库副本" ──────────
|
|
144
154
|
#
|
|
145
155
|
# 旧判据只问 `git rev-parse --show-toplevel`("**某个祖先**是不是仓库"),于是包目录落在任何
|
|
146
156
|
# 仓库里的机器(最常见:`$HOME` 是 dotfiles 仓库,而 npm/nvm 的前缀就在 `$HOME` 下)在 setup
|
|
147
|
-
# 时会把**全局安装目录**以 `link:` 装进 profile ——
|
|
148
|
-
#
|
|
157
|
+
# 时会把**全局安装目录**以 `link:` 装进 profile —— 市场里工作台那一行因此打上「本地」标
|
|
158
|
+
# (不比对源、不提示更新),而 `npm i -g …@latest` 还会悄悄换掉
|
|
149
159
|
# profile 跑的东西。判据窄到只认那一个坏形状:**我自己是装出来的那份**(GIT_TOP 为空)
|
|
150
160
|
# **且 profile 里那条 `link:` 指着的正是我自己这份目录** —— 指别处的 link:(用户自己链的)不动。
|
|
151
161
|
if [ -z "$GIT_TOP" ] && [ -f "$DST_PROFILE/package.json" ]; then
|
|
@@ -184,6 +194,7 @@ else
|
|
|
184
194
|
printf '\n' >>"$DST_PATCH"
|
|
185
195
|
cat "$ISOLATION" >>"$DST_PATCH"
|
|
186
196
|
echo "→ 已追加隔离层(sessions / storages / attachments 分家)"
|
|
197
|
+
rm -f "$DST_PATCH.tmp"
|
|
187
198
|
fi
|
|
188
199
|
|
|
189
200
|
# ── 第 4 步:建 DIY 工坊 ────────────────────────────────────────────────
|
|
@@ -206,7 +217,8 @@ cat <<EOF
|
|
|
206
217
|
|
|
207
218
|
profile '$DST_PROFILE' 的骨架好了(bundle 清单 + 会话/存储/附件隔离层)。
|
|
208
219
|
|
|
209
|
-
|
|
220
|
+
设置与本地插件按创建时的勾选从 $SRC_PROFILE_NAME 继承;直接跑 setup 时只继承
|
|
221
|
+
bundle 清单,想要 web 那边的模型供应商 / 搜索源 / MCP,起工作台后去
|
|
210
222
|
「设置 → 配置同步」按行勾(读的是那个 profile 的 cordis.patch.yml;搬完重启生效)。
|
|
211
223
|
|
|
212
224
|
装 bundle —— 两条**等价**的路,任选一条(都走 dsh 的 runPluginCommand,装完会
|
package/scripts/seed-workshop.sh
CHANGED
|
@@ -20,6 +20,8 @@
|
|
|
20
20
|
set -euo pipefail
|
|
21
21
|
|
|
22
22
|
DSH_HOME="${DSH_HOME:-$HOME/.dsh}"
|
|
23
|
+
WORKBENCH_HOME="${DSH_WORKBENCH_HOME:-$DSH_HOME/workbench}"
|
|
24
|
+
export DSH_WORKBENCH_HOME="$WORKBENCH_HOME"
|
|
23
25
|
SELF="${BASH_SOURCE[0]}"
|
|
24
26
|
while [ -L "$SELF" ]; do
|
|
25
27
|
SELF="$(cd "$(dirname "$SELF")" && pwd -P)/$(readlink "$SELF")"
|
|
@@ -36,8 +38,8 @@ MODE="${1:-skeleton}"
|
|
|
36
38
|
# 仓库副本,去 link 一个不存在的 `../module-tools`,脚本当场死在 `cd` 上 —— 而它是**后台**
|
|
37
39
|
# 被拉起来的(宿主自举 / 启动器),症状就是"工坊怎么都没建起来,一声不响"。
|
|
38
40
|
#
|
|
39
|
-
# 所以认仓库要认**本仓的形状**:根上同时有 packages/
|
|
40
|
-
if [ -n "$GIT_TOP" ] && [ -f "$GIT_TOP/packages/
|
|
41
|
+
# 所以认仓库要认**本仓的形状**:根上同时有 packages/core 与 packages/module-tools。
|
|
42
|
+
if [ -n "$GIT_TOP" ] && [ -f "$GIT_TOP/packages/core/package.json" ] &&
|
|
41
43
|
[ -f "$GIT_TOP/packages/module-tools/package.json" ]; then
|
|
42
44
|
IN_REPO=1
|
|
43
45
|
else
|
|
@@ -71,8 +73,8 @@ fi
|
|
|
71
73
|
# 冻结接口:状态文件 $DSH_HOME/workbench/diy/.sync.json =
|
|
72
74
|
# { state: "ok"|"syncing"|"failed", version: <基准版本>, at: <ISO>, reason?: <一句话> }
|
|
73
75
|
SHELL_ROOT="${DSH_WB_SHELL_ROOT:-}"
|
|
74
|
-
DIY_DIR="$
|
|
75
|
-
SEED_LOG="$
|
|
76
|
+
DIY_DIR="$WORKBENCH_HOME/diy"
|
|
77
|
+
SEED_LOG="$WORKBENCH_HOME/seed.log"
|
|
76
78
|
SYNC_STATE="$DIY_DIR/.sync.json"
|
|
77
79
|
SYNC_LOCK="$DIY_DIR/.sync.lock"
|
|
78
80
|
SYNC_BACKOFF_SECONDS=3600
|
|
@@ -103,7 +105,7 @@ target_version() {
|
|
|
103
105
|
}
|
|
104
106
|
|
|
105
107
|
# 外壳 manifest 里钉的那份 dsh UI 版本(模块模板默认带的那个 devDependency,见
|
|
106
|
-
#
|
|
108
|
+
# `内部设计记录` §3.1)。源优先**基准**(正在跑的那份外壳),
|
|
107
109
|
# 没有才退回跑脚本这份副本 —— 与 link_workshop_skills 同一条口径。
|
|
108
110
|
# 读不到就留空:调用方按"不写这一项"处理(模块 `init` 那边有自己的兜底常量与一句人话)。
|
|
109
111
|
shell_primitives_version() {
|
|
@@ -143,7 +145,7 @@ compute_specs() {
|
|
|
143
145
|
SHARED_SPEC="^$version"
|
|
144
146
|
fi
|
|
145
147
|
# dsh 原语(模块模板默认带的那个):**精确版**,与模块自己那份 devDependency 对齐 ——
|
|
146
|
-
#
|
|
148
|
+
# 类型面要对齐对账过的那一版(`内部设计记录` §3.1)。
|
|
147
149
|
# 空 = 读不到外壳 manifest,就**不写这一项**(模块 `init` 有自己的兜底常量)。
|
|
148
150
|
local primitives_version
|
|
149
151
|
primitives_version="$(shell_primitives_version)"
|
|
@@ -286,9 +288,7 @@ sync_lock_stale() {
|
|
|
286
288
|
|
|
287
289
|
# 强行清锁:只给"判定持锁者已崩"那条路用(那时锁已经不是原主的了)。
|
|
288
290
|
drop_sync_lock() {
|
|
289
|
-
|
|
290
|
-
*/workbench/diy/.sync.lock) rm -rf "$SYNC_LOCK" ;;
|
|
291
|
-
esac
|
|
291
|
+
if [ "${SYNC_LOCK:-}" = "$WORKBENCH_HOME/diy/.sync.lock" ]; then rm -rf "$SYNC_LOCK"; fi
|
|
292
292
|
}
|
|
293
293
|
|
|
294
294
|
# 抢锁的返回值:0 = 抢到;1 = 同一代的人正装着(跳过);2 = 这地方建不出锁;3 = 另一代正装着、等过一轮没抢到。
|
|
@@ -346,13 +346,11 @@ stop_sync_heartbeat() {
|
|
|
346
346
|
|
|
347
347
|
# 只删**自己的**锁:锁被清过 / 换了主人时,这里必须放手(否则新持锁者的 install 被砍在半路)。
|
|
348
348
|
release_sync_lock() {
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
;;
|
|
355
|
-
esac
|
|
349
|
+
if [ "${SYNC_LOCK:-}" = "$WORKBENCH_HOME/diy/.sync.lock" ]; then
|
|
350
|
+
if [ -n "${SYNC_LOCK_TOKEN:-}" ] && [ "$(lock_field owner)" = "$SYNC_LOCK_TOKEN" ]; then
|
|
351
|
+
rm -rf "$SYNC_LOCK"
|
|
352
|
+
fi
|
|
353
|
+
fi
|
|
356
354
|
}
|
|
357
355
|
|
|
358
356
|
# sync:幂等、可重跑、可续。**复核过才写 ok**。
|
|
@@ -529,15 +527,15 @@ fi
|
|
|
529
527
|
# 转发脚本而不是软链:同 `bin/opencli-isolated` 那条坑 —— pnpm publish 之后包里的脚本没有 x 位,
|
|
530
528
|
# 软链过去一执行就是 Permission denied。x 位由 chmod 当场给。
|
|
531
529
|
# ⚠️ 先 rm -f:旧版本留下的软链还在时,`>` 会顺着软链把真脚本覆盖掉。
|
|
532
|
-
ENTRY_DIR="$
|
|
530
|
+
ENTRY_DIR="$WORKBENCH_HOME/bin"
|
|
533
531
|
mkdir -p "$ENTRY_DIR"
|
|
534
532
|
rm -f "$ENTRY_DIR/dsh-wb-module"
|
|
535
533
|
cat >"$ENTRY_DIR/dsh-wb-module" <<EOF
|
|
536
534
|
#!/bin/sh
|
|
537
|
-
BIN="$
|
|
535
|
+
BIN="$WORKBENCH_HOME/diy/node_modules/.bin/dsh-wb-module"
|
|
538
536
|
if [ -x "\$BIN" ]; then exec "\$BIN" "\$@"; fi
|
|
539
537
|
if command -v pnpm >/dev/null 2>&1; then
|
|
540
|
-
exec pnpm --dir "$
|
|
538
|
+
exec pnpm --dir "$WORKBENCH_HOME/diy" exec dsh-wb-module "\$@"
|
|
541
539
|
fi
|
|
542
540
|
echo "dsh-wb-module: 工坊的依赖还没装 —— 先跑 dsh-workbench setup" >&2
|
|
543
541
|
exit 127
|
|
@@ -60,17 +60,9 @@ pnpm exec dsh-wb-module init <unit> --dir <工作区>/packages/module-<unit> --t
|
|
|
60
60
|
|
|
61
61
|
## 3 命令
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
dsh-wb-module check --only cards # 单条(contracts / protocol / bundles / source / arch / lint /
|
|
67
|
-
# primitives / kit / cards / standalone / markers / style / alias)
|
|
68
|
-
dsh-wb-module check --only primitives [--all|--json] # 查询 dsh 原语
|
|
69
|
-
dsh-wb-module lint [--fix] # 模块 eslint;--fix 写回
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
用 `pnpm exec dsh-wb-module …`。`package.json` 六个脚本(`build` / `typecheck` / `test` / `selfcheck` /
|
|
73
|
-
`check` / `lint`)必须保留,`contracts` 点名缺失。
|
|
63
|
+
用 `pnpm exec dsh-wb-module …`;命令、`--only` 判据名与模板参数看 `--help` / `check --list`,不在指引里抄。
|
|
64
|
+
`package.json` 六个脚本(`build` / `typecheck` / `test` / `selfcheck` / `check` / `lint`)必须保留,
|
|
65
|
+
`contracts` 点名缺失。
|
|
74
66
|
|
|
75
67
|
- `check` 不跑 `pnpm test`;状态、换算、边界测试自己跑。
|
|
76
68
|
- "不适用"不是"通过":`standalone` 需外壳源码在场,`markers` 只扫公开包(DIY 模块 `private`)。
|
|
@@ -94,6 +86,7 @@ export function apply(ctx) {
|
|
|
94
86
|
}
|
|
95
87
|
```
|
|
96
88
|
|
|
89
|
+
`mount({ data })` 的 `data` 是统一数据端口(`DataReader`);读数据用 `data.read(...)`,不要自己 import adapter。
|
|
97
90
|
`mount()` 返回 `{ routes, registerTools, prefs? }`。`routes` 挂 `/workbench/api/<路由>`,只许 GET,
|
|
98
91
|
键必须在 `<unit>` 或 `<unit>/…` 之下(否则装配抛错)。错误返回
|
|
99
92
|
`{ ok: false, error: { code, message, hint? } }`(HTTP 200,外壳转发)。`registerTools` 提供模块工具。
|
|
@@ -86,4 +86,4 @@
|
|
|
86
86
|
| 描述 | 用于查看构建状态的工具 | 看某个环境最近一次构建:状态、耗时、提交;用户说“发布没成功”就先调它。 |
|
|
87
87
|
| 返回 | 操作成功 | 已发布 v1.2.3 到生产;下一步 `_build` 看结果。 |
|
|
88
88
|
| 拒绝 | 不允许 | 这个环境是生产;先在确认条上点「发布到生产」。 |
|
|
89
|
-
| 日志 | 出错了 | `[
|
|
89
|
+
| 日志 | 出错了 | `[inventory] release v1.2.3 failed: HTTP 502 (retryable)` |
|
|
@@ -6,14 +6,14 @@
|
|
|
6
6
|
|
|
7
7
|
| 情况 | 域 |
|
|
8
8
|
|---|---|
|
|
9
|
-
| 用户已在浏览器登录过该系统 | DIY:用 opencli
|
|
9
|
+
| 用户已在浏览器登录过该系统 | DIY:用 opencli 复用登录探(下文五步) |
|
|
10
10
|
| 要新凭据(账号 / 密钥 / token) | 工程:停,说清谁配什么 |
|
|
11
11
|
|
|
12
12
|
判据是"要不要新凭据",不是"要不要接新平台"。其余类型见 [DESIGN.md](DESIGN.md) §0。
|
|
13
13
|
|
|
14
|
-
##
|
|
14
|
+
## 五步
|
|
15
15
|
|
|
16
|
-
1. **问入口** —— "你平时在哪个网页 / 软件里看这个?"记下入口。不问"用
|
|
16
|
+
1. **问入口** —— "你平时在哪个网页 / 软件里看这个?"记下入口。不问"用 deploy 还是 jenkins"。
|
|
17
17
|
把用户的需求翻成站点 / 系统关键词是你的工作。
|
|
18
18
|
|
|
19
19
|
2. **按四层找数据**:
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
`workbench_diy_spec`(`command='<site> <name>'`)取 `--help -f json` 原文(插件与内置均可)。
|
|
30
30
|
|
|
31
31
|
③ **官方有、这台机器没有** → 安装:`opencli plugin install github:user/repo`、`opencli external install <名>`,
|
|
32
|
-
或模块清单 `
|
|
32
|
+
或模块清单 `needs` 里 `kind: "extension"` 的那些。安装改这台机器且执行第三方代码 → 需用户审批;优先内网或官方源。
|
|
33
33
|
|
|
34
34
|
④ **都没有** → 开发:一次性探用下文的 eval;长期用写 adapter(`opencli skills read opencli-adapter-author`,
|
|
35
35
|
失效用 `opencli-autofix`)。
|
|
@@ -39,6 +39,9 @@
|
|
|
39
39
|
两拍、重启重试、平台码映射都在工具内。目标:找到承载数据的位置(列表页或其后的 XHR),
|
|
40
40
|
记 URL、参数、凭据来源。
|
|
41
41
|
|
|
42
|
+
**Desktop**:这条 `read=` 探索线照旧;Desktop 只是不能对 Electron 里的工作台页做屏调试,
|
|
43
|
+
不影响站点探索。录制(`_record_*`)也照旧。
|
|
44
|
+
|
|
42
45
|
- 不知道数据在哪:先跑 `performance.getEntriesByType('resource')`,筛 `/api/`、`.json`。
|
|
43
46
|
有 → 接口读;无但页面有整块表格 → DOM 读。判断一次即可。
|
|
44
47
|
- `opencli` 随工作台预装(隔离运行时 `$DSH_HOME/workbench/opencli/`,启动体检安装,不碰 `~/.opencli`)。
|
|
@@ -48,25 +51,107 @@
|
|
|
48
51
|
- 新 session 的 `eval` 会静默开 `about:blank`(后台容器窗,不抢焦点)。脚本第一行判断
|
|
49
52
|
`location.origin`;不在站点则 `open` 该页,等约 1 秒再 eval。两拍都用 shared 的 `backgroundLine`
|
|
50
53
|
拼(前缀 `env OPENCLI_WINDOW=background`),不要直接拼 `opencli browser …`。
|
|
51
|
-
- 读与屏用不同会话:`
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
`
|
|
55
|
-
(`find --css … --limit N --text-max M`,返回 `{ entries: [{ text, tag, nth }] }`;
|
|
56
|
-
一行单元格按换行拼在 `text` 内,"切格 + 按列取值"做成两个纯函数)。
|
|
54
|
+
- 读与屏用不同会话:`data.read({ kind: 'browser' })` 默认读会话 `workbench-read`;`workbench` 是看 / 动族的屏会话。同名会把用户的页导航走。需要独立标签就传 `session: "<unit>"`。
|
|
55
|
+
- DOM 读不要在宿主脚本里 `querySelectorAll`:宿主产物禁止 `document.`,且无法单测。探时用
|
|
56
|
+
`workbench_diy_find`(`read=…, args=["--css", "<选择器>"]`);固化用
|
|
57
|
+
`data.read({ kind: 'browser', url, script })` 返回 JSON,把"切格 + 按列取值"做成两个纯函数。
|
|
57
58
|
- 工作台刚重启时桥未就绪:首次读报"命令跑不起来",等一秒重读;超时不重试。
|
|
58
59
|
|
|
59
60
|
3. **试一条最小读** —— 先证明能拿到,再写模块。记录:结构化字段形状;未登录长什么样;超时 / 被墙的形状。
|
|
60
61
|
产出必须是一条可重复的命令或请求。
|
|
61
62
|
|
|
62
|
-
4.
|
|
63
|
-
|
|
64
|
-
`
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
`
|
|
63
|
+
4. **落配方** —— 把探明结果填成 `design.json` 里这条读的 `recipe`:`origin`、`request`(method / path /
|
|
64
|
+
query / body / contentType)、`auth`(凭据从哪来、放到哪)、`response`(json / text、取哪一格)。
|
|
65
|
+
同时把 `key` 写成 lowerCamelCase。配方与"哪条读 / 参数 / 凭据 / 没登录 / 超时 / 当时调用原文"
|
|
66
|
+
并存:前两格给人看,后一格给壳用。形状见下面「配方」。
|
|
67
|
+
5. **固化进模块** —— 跑 `dsh-wb-module sync`,它把 `key + recipe` 生成到 `src/datasource.ts`;
|
|
68
|
+
宿主半侧 `mount({ data })` 只写一行 `data.request(DATASOURCE.<key>, overrides?)`(读)或
|
|
69
|
+
`data.submit(...)`(写,在工具里)。路由把 `DataResult` 摊平成 `{ ok: true, ...data }` /
|
|
70
|
+
`{ ok: false, error }`,卡片只依赖这条路由。写操作走 [WRITES.md](WRITES.md)。
|
|
71
|
+
|
|
72
|
+
## 配方
|
|
73
|
+
|
|
74
|
+
```json
|
|
75
|
+
{
|
|
76
|
+
"key": "balance",
|
|
77
|
+
"recipe": {
|
|
78
|
+
"origin": "https://x.example.com",
|
|
79
|
+
"loginUrl": "https://x.example.com/login",
|
|
80
|
+
"request": { "method": "GET", "path": "/api/balance", "query": { "scope": "self" } },
|
|
81
|
+
"response": { "kind": "json", "path": "data" }
|
|
82
|
+
},
|
|
83
|
+
"read": "GET /api/balance(登录态 cookie)",
|
|
84
|
+
"params": "scope 固定 self",
|
|
85
|
+
"credentials": "复用浏览器登录:同源 cookie",
|
|
86
|
+
"notLoggedIn": "401 → 阻断屏,code auth,helpUrl 指 /login",
|
|
87
|
+
"timeout": "25 秒;超时归 timeout,不整卡换文案"
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
宿主侧:
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
routes: {
|
|
95
|
+
'x/balance': async () => {
|
|
96
|
+
const result = await data.request<Balance>(DATASOURCE.balance);
|
|
97
|
+
return result.ok ? { ok: true, ...result.data } : result;
|
|
98
|
+
},
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
六种配方:
|
|
103
|
+
|
|
104
|
+
| 配方 | 什么时候用 | `auth` |
|
|
105
|
+
|---|---|---|
|
|
106
|
+
| 公开 | 不要登录 | `{ kind: 'none' }` |
|
|
107
|
+
| cookie | 同源接口,cookie 就够 | 省略(默认) |
|
|
108
|
+
| cookie + CSRF | 表单类后台 | `source: meta / cookieValue`,`place: header` |
|
|
109
|
+
| bearer-refresh | 页面先换 token(如 `/api/auth/refresh`) | `source: endpoint`,`place: header` |
|
|
110
|
+
| bearer-page | token 在页面初始 state / storage | `source: global / storage`,`place: header` |
|
|
111
|
+
| custom | 签名 / WS / 多步 / 一次性 token | 不写 recipe,写 `custom: { why }`,代码里用旧的 `data.read({ kind: 'browser', script })` |
|
|
112
|
+
|
|
113
|
+
同一次读要打多条接口时(一个 refresh 换 token,再并发取余额、用量、订阅……),不要拆成 N 条配方
|
|
114
|
+
各调一次:一条配方 + 一格 `calls`,一次换 token、并发打,结果按键回、每格各自成败:
|
|
115
|
+
|
|
116
|
+
```json
|
|
117
|
+
{
|
|
118
|
+
"key": "wallet",
|
|
119
|
+
"recipe": { "origin": "https://x.example.com",
|
|
120
|
+
"auth": { "source": { "kind": "endpoint", "url": "/api/user/auth/refresh",
|
|
121
|
+
"method": "POST", "body": {}, "path": "data.access_token" },
|
|
122
|
+
"place": { "in": "header", "name": "authorization", "prefix": "Bearer " } },
|
|
123
|
+
"request": { "method": "GET", "path": "/api/subscription/self" } },
|
|
124
|
+
"calls": {
|
|
125
|
+
"balance": { "path": "/api/wallet/balance", "response": { "path": "data.balance" } },
|
|
126
|
+
"usage": { "query": { "days": 7 } }
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
`sync` 会多生成一个 `DATASOURCE_CALLS.wallet`;代码里一次调用:
|
|
132
|
+
|
|
133
|
+
```ts
|
|
134
|
+
const results = await data.requestMany(DATASOURCE.wallet, DATASOURCE_CALLS.wallet);
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
`calls` 的键就是结果名;配方里的 `path` / `query` / `headers` / `response` 是每条的默认值,
|
|
138
|
+
`calls` 里的同名格覆盖它;一次最多 8 条。`calls` 必须配 `recipe`,`design check` 逐格校验。
|
|
139
|
+
`requestMany` 也只读 GET —— 写仍是一条一条走 `submit`。
|
|
140
|
+
|
|
141
|
+
配方还有两个可选机器字段:`session`(这条读用哪条 opencli 会话,默认 `workbench-read`;要和屏会话分开时写)
|
|
142
|
+
与 `timeoutMs`(默认 25 秒)。
|
|
143
|
+
|
|
144
|
+
`custom` 只记"为什么配方盖不住",脚本仍在代码里;`design check` 会给 warn。
|
|
145
|
+
|
|
146
|
+
探 DOM(服务端渲染的表格)不在配方里:用 `_find` 探,固化仍走老的 `data.read({ kind: 'browser', script })`
|
|
147
|
+
或 `browserFind`(DOM 读走 `find`,不写 eval 脚本)。
|
|
148
|
+
|
|
149
|
+
`opencli` 是**侦察兵,不是日常通道**:探明后,日常读必须是一条固定、便宜、可解释的调用
|
|
150
|
+
(配方就是那条调用;`eval` 只在探测和 `custom` 里出现)。
|
|
151
|
+
|
|
152
|
+
配方的**执行体由壳决定,不写在模块里**:凭据来源是 `cookie` / `cookieValue` 时,壳可能用宿主侧的
|
|
153
|
+
公共通道(Node fetch + 浏览器 cookie jar)而不是页面脚本;两者结果形状、错误码、三态都一样。
|
|
154
|
+
模块不需要知道走的是哪条 —— 照 `data.request(DATASOURCE.<key>)` 写就对了。
|
|
70
155
|
|
|
71
156
|
## 三态
|
|
72
157
|
|
|
@@ -87,10 +172,10 @@
|
|
|
87
172
|
|
|
88
173
|
| code | 用户看到 |
|
|
89
174
|
|---|---|
|
|
90
|
-
| `auth
|
|
91
|
-
| `
|
|
92
|
-
| `
|
|
93
|
-
| `
|
|
175
|
+
| `auth` + `helpUrl` | "需要登录 XX" + 去登录 + 重试(无 `helpUrl` 只剩重试) |
|
|
176
|
+
| `timeout` | 细提示(不换整卡)+ 重试 |
|
|
177
|
+
| `command` / `http` / `parse` | 整卡"读不到" + 重试;`hint` 写清确认什么 |
|
|
178
|
+
| `browser` + `helpUrl` | "没有权限" / 页面读失败 + 权限页 + 重试 |
|
|
94
179
|
| 其他 | 整卡显示 `message` + 重试 |
|
|
95
180
|
|
|
96
181
|
字段位置:`message` 标题、`hint` 可照做的一句、`detail` 折叠的原始输出。
|
|
@@ -100,7 +100,8 @@ pnpm exec dsh-wb-module design accept # 逐条走通后打勾
|
|
|
100
100
|
|
|
101
101
|
字段:`unit` / `name` / `oneLine` + `panel[]`(这一格 / 结论 / 去哪)+ `states[]`(五态必填,key 固定
|
|
102
102
|
`idle|loading|ready|empty|unreadable`)+ `config[]` + `capabilities[]` + `linkage[]` +
|
|
103
|
-
`datasource{}`(一条读)或 `reads[]
|
|
103
|
+
`datasource{}`(一条读)或 `reads[]`(多条,一条一行;每条可带 `key` + `recipe`,见
|
|
104
|
+
[DATASOURCE.md](DATASOURCE.md)「配方」)+ `writes[]`(写通道;单条可写 `write{}`;没有就不写)+
|
|
104
105
|
`acceptance[]`。`config` / `capabilities` 可为空数组;其余空 = 未定。写通道字段见 [WRITES.md](WRITES.md)。
|
|
105
106
|
|
|
106
107
|
单态不适用时写 `na`:`{ "key": "idle", "na": "读的是账号,不随项目变" }`,不填 `sees` / `canDo` / `agentCan`。
|
|
@@ -1,72 +1,52 @@
|
|
|
1
|
-
# DIY
|
|
1
|
+
# DIY 工具族:怎么选、怎么串
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
只写工具定义里没有的东西:什么时候用哪把、先后顺序、参数说明之外的坑。
|
|
4
|
+
逐把的参数与返回以调用时拿到的工具定义为准;模块自身的能力见 [TOOLS.md](TOOLS.md)。
|
|
4
5
|
|
|
5
|
-
## 1
|
|
6
|
+
## 1 选哪把
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
- 看 / 动 / 网络 / 日志族需先 `workbench_diy_debug_start`(审批一次);无约定一律拒,零命令。
|
|
9
|
-
不看屏 `_debug_pause`;收工 `_debug_stop`(一并收网络与日志钩子)。
|
|
10
|
-
- 固定会话 `workbench`,每条带 `--window background`。`_status` / `_panel` / `_components` / `_recon` / `_spec` /
|
|
11
|
-
`_install` / `_show` 不碰屏,无需约定;`_find` / `_eval` 带 `read=` 走只读线,也不碰。
|
|
12
|
-
- 录制交接(§4)独立:会话 `workbench-rec`;`_record_prepare` 审批一次,其余不问。
|
|
13
|
-
|
|
14
|
-
## 2 浏览器 14 把
|
|
15
|
-
|
|
16
|
-
工具名 → opencli 子命令(前缀 `workbench_diy_`):
|
|
17
|
-
|
|
18
|
-
`_state`→`state` · `_html`→`get html` · `_find`→`find` · `_click`→`click` · `_hover`→`hover` · `_type`→`type` ·
|
|
19
|
-
`_fill`→`fill` · `_keys`→`keys` · `_scroll`→`scroll` · `_wait`→`wait` · `_eval`→`eval` · `_screenshot`→`screenshot` ·
|
|
20
|
-
`_network`→`network` · `_dialog`→`dialog`
|
|
21
|
-
|
|
22
|
-
返回要点:`_state` = URL + 标题 + 可点元素(ref 来源);`_html` = HTML(`--as json` 树);`_find` =
|
|
23
|
-
`{matches_n, entries[]}`;`_network` = 收发包(`--follow`;body 不可取);`_screenshot` 写文件(`clip` 裁剪)。
|
|
24
|
-
|
|
25
|
-
参数(`scope` / `in` 默认 `page`):
|
|
26
|
-
|
|
27
|
-
- 公共:`unit?`(卡片;可省。使用 `scope: 'card'` / `in: 'card'` / `$card` 时必给,否则拒)·
|
|
28
|
-
`args?: string[]`(原样接在 `opencli browser workbench <verb…>` 后)· `timeoutMs?`(默认 30000)·
|
|
29
|
-
`read?: string`(只读线)。
|
|
30
|
-
- `scope: 'card'` 仅七把:`_find`(`--css`)、`_html`(`--selector`)、`_click` / `_hover` / `_type` / `_fill`
|
|
31
|
-
(位置参数 0)、`_wait`(仅 `wait selector`,位置参数 1)。`card` = 目标挂 `#wb-card-<unit> .wb-card `。
|
|
32
|
-
- 只读线:带 `read: <地址>` 时跑在 `workbench-read` 会话,不要约定、不需板在屏、不认卡作用域
|
|
33
|
-
(`unit` / `scope: 'card'` / `in: 'card'` / `$card` 均拒),也不要求工作区有模块。
|
|
34
|
-
返回字段与屏线相同,另带 `session` / `opened`(`opened` = 曾代开站点:先比 `get url`,不在则 `open <read>` 再跑)。
|
|
35
|
-
`_eval` 脚本返回 `{ ok: false, code: "not-logged-in" }` 时追加一句"去 <read> 登录"。
|
|
36
|
-
- `in: 'card'` 仅 `_eval`(注入卡根 `root`,脚本自行 `return`);`clip`(CSS px)仅 `_screenshot`;
|
|
37
|
-
`$card` 在任意 `args` 中替换为 `#wb-card-<unit> .wb-card`。
|
|
38
|
-
|
|
39
|
-
返回:`{ ok, exitCode, timedOut, truncated, stdout, stderr }` + `workshop` / `unit` / `verb` / `argv`
|
|
40
|
-
(只读线为 `session` / `opened`);`_screenshot` 另带 `file` / `cropped` / `cropReason`。
|
|
41
|
-
`ok` 仅表示进程退出;事实在 `stdout`(错误体为 `{"error":{…}}`,`ok` 可能为 true)。不做 JSON 解析、
|
|
42
|
-
不翻译、不归一。参数不明先 `args: ['<verb>', '--help']`。
|
|
43
|
-
"原样"有折损:空串 / 纯空白 / 非字符串参数被丢弃,词前后 trim,stdout / stderr trim ⇒ `_fill` 无法清空、
|
|
44
|
-
`_type` 无法输入空格。
|
|
45
|
-
|
|
46
|
-
补充用法:`_select` 不存在,下拉两拍(点触发器 → `scope: 'page'` + `--role menuitem` 按名点);
|
|
47
|
-
刷新用 `eval 'location.reload()'`;视口用 `screenshot --width/--height`。
|
|
48
|
-
|
|
49
|
-
## 3 边界
|
|
50
|
-
|
|
51
|
-
- `screenshot` 无 selector:卡图先 `eval` 量盒再 `clip`;不给路径写
|
|
52
|
-
`~/.dsh/workbench/artifacts/<工作区>/<unit|page>-<时间戳>.png`,否则回 base64;裁剪块不在视口时退回整屏,
|
|
53
|
-
原因在 `cropReason`。
|
|
54
|
-
- `state` 无 `scope`(卡内用 `find --css '$card …'`);无右键;ref 仅一次快照内有效;`_dialog` 不校验
|
|
55
|
-
`accept|dismiss`;`_network --detail` 无 body → 用 `_eval` 的 `fetch`。
|
|
56
|
-
- 录制会话捕获带 body:跟随 `network --follow` 只用于臂上;每 3 秒一次非跟随 `network --all --raw` 排空缓冲,
|
|
57
|
-
取请求体与响应体。按 URL 去静态资源与 `data:` 后落盘。它覆盖整场,比页面钩子全(钩子只认该页 `fetch` / XHR)。
|
|
58
|
-
不要换成 opencli 默认过滤(按响应 ct 白名单,会丢"按结束即回包未到"的写)。
|
|
59
|
-
- 其他:`_status` / `_install` / `_show`、`_components`(清单 / 类型面;`name=Button` 取声明)、
|
|
60
|
-
`_panel`、`_recon`、`_spec`(opencli 命令形状,插件适用)、`_logs_*`、`_debug_*`、`_record_*`(§4)。
|
|
61
|
-
|
|
62
|
-
## 4 录制交接
|
|
63
|
-
|
|
64
|
-
| 工具 | 契约 |
|
|
8
|
+
| 要做什么 | 用 |
|
|
65
9
|
|---|---|
|
|
66
|
-
|
|
|
67
|
-
|
|
|
68
|
-
|
|
|
69
|
-
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
10
|
+
| 认路、装没装、起不起得来 | `_status`(`unit` 可省);它的「下一步」就是下一件事 |
|
|
11
|
+
| 卡片空白 / 崩了 / 读不到 | `_panel` |
|
|
12
|
+
| 找 opencli 命令、看命令形状 | `_recon` → `_spec`(`--help -f json` 原样) |
|
|
13
|
+
| kit 有什么 / 令牌叫什么 | `_components`(`bucket` / `name` 取声明;`scope: tokens` 现读 `--dsw-*` / `--wb-*`) |
|
|
14
|
+
| 装一次 / 只上板 | `_install` / `_show` |
|
|
15
|
+
| 发布前记这一版改了什么 | `_changelog`(`note` 必填;文件不在就先建) |
|
|
16
|
+
| 发布 | `_publish`,只在用户说「帮我发布」之后 |
|
|
17
|
+
| 看 / 动当前页 | `_state` · `_html` · `_find` · `_screenshot` · `_click` · `_hover` · `_type` · `_fill` · `_keys` · `_scroll` · `_wait` · `_network` · `_dialog` |
|
|
18
|
+
| 控制台 | `_logs_watch` → 操作 → `_logs_read` → `_logs_stop` |
|
|
19
|
+
| 抓「用户点了之后发了什么」 | `_record_prepare` → 用户操作 → `_record_read` → `_record_detail` → `_record_stop` |
|
|
20
|
+
|
|
21
|
+
## 2 前置
|
|
22
|
+
|
|
23
|
+
- 只在 DIY 模式的会话出现;面板得画在屏上。
|
|
24
|
+
- 看 / 动 / 网络 / 日志族先 `_debug_start`(审批一次),否则整族拒、零命令;收工 `_debug_stop`。
|
|
25
|
+
`_pause` 只暂停看屏。不碰屏的:`_status` / `_panel` / `_components` / `_recon` / `_spec` /
|
|
26
|
+
`_install` / `_show` / `_changelog` / `_publish`;`_find` / `_eval` 带 `read=` 时也不碰。
|
|
27
|
+
- 录制独立:`_record_prepare` 审批一次,其余不问;同时只有一场,要重来先 `_record_stop`。
|
|
28
|
+
|
|
29
|
+
## 3 参数之外的坑
|
|
30
|
+
|
|
31
|
+
- 浏览器工具都能带 `args` 原样转发;空串 / 纯空白 / 非字符串会被丢弃,词前后 trim ——
|
|
32
|
+
`_fill` 清不空、`_type` 打不了纯空格。
|
|
33
|
+
- `ok` 只表示进程退出。事实在 `stdout`;错误体是 `{"error":{…}}`,`ok` 仍可能是 true。
|
|
34
|
+
不解析、不翻译;参数不明先 `args: ['<verb>', '--help']`。
|
|
35
|
+
- 卡作用域:`unit` 指卡;`scope: 'card'` / `in: 'card'` / `$card` 需要它,
|
|
36
|
+
`$card` 在 args 里换成 `#wb-card-<unit> .wb-card`。
|
|
37
|
+
- 只读线:带 `read: <地址>` 时跑在 `workbench-read` 会话,不碰屏、不认卡作用域、能代开站点;
|
|
38
|
+
`_eval` 返回 `not-logged-in` 时让用户去登录。
|
|
39
|
+
- `_screenshot` 不给路径时写 artifacts 目录;拿不到选择器就先 `_eval` 量盒再 `clip`。
|
|
40
|
+
- `state` 没有 `scope`;`_select` 不存在(下拉两拍);ref 只在一次快照内有效;
|
|
41
|
+
`_dialog` 不校验 `accept|dismiss`;`_network --detail` 没有 body,要 body 用 `_eval` 的 fetch。
|
|
42
|
+
- 录制按 URL 去静态资源后落盘;`_record_read` 不回体,取体用 `_record_detail`;
|
|
43
|
+
`_record_stop` 先读文件再另存 `.last`,所以先 read / detail 再 stop。取不到时给 DevTools 复制 curl。
|
|
44
|
+
场次 15 分钟过期;过期或台账变更会停捕获、收标签。
|
|
45
|
+
|
|
46
|
+
## 4 发布
|
|
47
|
+
|
|
48
|
+
只在用户明确说「帮我发布」后调。它一次做完预检 → 全门禁 → 按出口发布 → 发后核包,审批一次。
|
|
49
|
+
发布前先 `_changelog` 把这一版写进 `CHANGELOG.md`:没有这一版的记录,`_publish` 会拦下。
|
|
50
|
+
审批屏会把这一版的更新日志按 markdown 展示给用户。
|
|
51
|
+
需要用户接管时返回 `needsUser: { step, text, command? }` 而不抛异常:把 `text` 说给用户、给命令,
|
|
52
|
+
等「好了」再跑;不向用户要 token,不展示 `package.json`。
|
|
@@ -130,7 +130,8 @@ h(FormRows, null,
|
|
|
130
130
|
## 7 规则
|
|
131
131
|
|
|
132
132
|
1. 调用点只给数据与语义;外观类名只允许布局槽(通栏、外边距、网格位置)。
|
|
133
|
-
2. 字号与颜色走 kit
|
|
133
|
+
2. 字号与颜色走 kit 与令牌。重点数字用 `--dsw-font-xl-24` + `tabular-nums`;
|
|
134
|
+
令牌名现查不猜:`workbench_diy_components` 给 `scope: 'tokens'`(现读装着的 dsh 与外壳;`name=--dsw-…` 连浅/深值)。
|
|
134
135
|
刻度外字面值在模块 `README.md` 说明([PANEL.md](PANEL.md) §6)。
|
|
135
136
|
3. 自写 CSS 只写布局(flex / grid / gap / 对齐)。
|
|
136
137
|
|
|
@@ -86,10 +86,12 @@ write.send({ ignored, timeoutSeconds, workspace }); // 控件:Field + TextFi
|
|
|
86
86
|
- 跳整张卡对应的系统 → 卡头 `CardHead.platformHref`;跳具体页面 / 记录 → `Link`;触发动作 → dsh `Button` 或阻断屏 `action`。
|
|
87
87
|
- 标签 + 输入框用 `Field` + `TextField`,不自写 CSS。
|
|
88
88
|
- 组件选型照 [KIT.md](KIT.md)。
|
|
89
|
-
-
|
|
90
|
-
|
|
89
|
+
- **字号与重点**:走刻度,不整卡同字号 —— 刻度以 `--dsw-font-*` 的定义为准,别背数字
|
|
90
|
+
(`workbench_diy_components` `scope: 'tokens'`、`bucket=font` 现查)。
|
|
91
|
+
最重点的数字用最大一档(`--dsw-font-xl-24`),旁注用最小一档;刻度外字面值需在模块 `README.md` 说明。
|
|
91
92
|
成列数字加 `font-variant-numeric: tabular-nums`。
|
|
92
|
-
-
|
|
93
|
+
- 颜色与间距走令牌;名字现查不猜:`workbench_diy_components` 给 `scope: 'tokens'`(`bucket` 按族、`name` 连浅/深值)。
|
|
94
|
+
写进 CSS 的令牌名由 `check --only style` 对着现读的清单验,拼错判红。自写 CSS 只写布局(flex / grid / gap / 对齐)。
|
|
93
95
|
|
|
94
96
|
## 7 状态矩阵
|
|
95
97
|
|
|
@@ -5,18 +5,18 @@
|
|
|
5
5
|
| 判据 | 检查 | 修法 |
|
|
6
6
|
|---|---|---|
|
|
7
7
|
| `contracts` | 清单 ↔ 代码 ↔ `design.json` 漂移;dsh 组合期不校验清单 | 按报错改:`unit` 重名换名;`dsh.workbenchFaces` 两个源码入口;六个脚本;`private: true`。`dsh.workbench.tools` 与 `registerTools()` 一致;`design.json` 对键名;生成物过期跑 `sync` |
|
|
8
|
-
| `protocol` | `dsh.workbench` 版本 / 形状 / 多余键(外壳静默忽略生字段) | 补 `"apiVersion":
|
|
8
|
+
| `protocol` | `dsh.workbench` 版本 / 形状 / 多余键(外壳静默忽略生字段) | 补 `"apiVersion": 2`;`unit` / `card` / `tools` / `host` 写全(无卡片 `null`、无工具 `[]`);删协议外键(`faces` 在 `dsh.workbenchFaces`;不写 `scope`) |
|
|
9
9
|
| `bundles` | 运行时互串:浏览器产物含 node 内置 / 宿主产物含 DOM、react | 不 import 对方那侧 |
|
|
10
|
-
| `source` | 非种子 `@deepseek-ai/*`;宿主碰 dsh 浏览器包;`@/` 指外壳;根入口取运行值;客户端引 `/host
|
|
10
|
+
| `source` | 非种子 `@deepseek-ai/*`;宿主碰 dsh 浏览器包;`@/` 指外壳;根入口取运行值;客户端引 `/host`;**手写进程 / PATH / 文件锁 / 状态原子写**(import 首选库放行) | 宿主只用 Node 侧;种子词仅在 client 可达文件;`@/` 只指自己 `src/`;运行值:浏览器 `kit`、宿主 `shared/host`;进程/锁/状态写交给外壳 |
|
|
11
11
|
| `primitives` | 声明 `external` 但产物无物证(原语被内联) | `dsh.client.external` 声明;devDependency 精确版对齐;产物中为 `require(...)` |
|
|
12
12
|
| `kit` | 用了 peer 下限外壳没有的成员(首帧 `Element type is invalid`) | 只用 peer 范围内成员;下限抬到实际使用版 |
|
|
13
13
|
| `cards` | 七种外壳侧输入 × `zh` / `en` 下崩溃 / 空白 / 脏值 | 五态可画;外层 `Card`;`titleKey` 与卡片用到的键双语齐。不断言具体态(归 `plugin.test.ts`) |
|
|
14
14
|
| `standalone` | 依赖工作台源码才能构建 | 不引用工作台源码;`tsconfig.paths` 用相对路径 |
|
|
15
|
-
| `markers` |
|
|
15
|
+
| `markers` | 私有源 / 私网地址 / 内网域名进入公开包 | 不进包;配置落到模块配置面;组织特有的词表由 `DSH_WB_INTERNAL_MARKERS` 提供 |
|
|
16
16
|
| `alias` | `@/` 指向工作台源码 | `@/` 只指自己 `src/` |
|
|
17
|
-
| `style` | 模块定义 `.wb-*`;手写行 / 操作区 / 表单(F1–F4
|
|
18
|
-
| `arch` | 结构:巨文件 / 反向依赖 / 跨运行时 / 表外目录 /
|
|
19
|
-
| `lint` | 语法:`as any` / `console` / `debugger` / 颜色字面量 / `!important` / react-hooks | 见「第十三条」 |
|
|
17
|
+
| `style` | 模块定义 `.wb-*`;手写行 / 操作区 / 表单(F1–F4);`--dsw-*` / `--wb-*` 不在现读的令牌清单 | 样式走 `*.module.css`(无 `wb-` 前缀);借外壳类用 `:global(.wb-…)`;行 / 操作区用 `FormRow(s)` / `FormActions`,表单用 `Form`([KIT.md](KIT.md) §5)。F4:裸 `<form` 或手写 `wb-formRow` / `wb-formRows` / `wb-field`。令牌名现查:`workbench_diy_components` `scope: 'tokens'` |
|
|
18
|
+
| `arch` | 结构:巨文件 / 反向依赖 / 跨运行时 / 表外目录 / 模型无测试;依赖白名单(含 execa / which / proper-lockfile / write-file-atomic / dayjs / zod)+ `shell-quote` / `shelljs` / `zx` deny;能力首选 dayjs / structuredClone / URLSearchParams / zod(日期已是硬门禁) | 见「第十二条」 |
|
|
19
|
+
| `lint` | 语法:`as any` / `console` / `debugger` / 颜色字面量 / `!important` / **直接读 `process.platform` / `versions.electron` / `dshDesktop` / `hostOs` / `navigator.userAgent`** / react-hooks | 见「第十三条」 |
|
|
20
20
|
|
|
21
21
|
## 第十二条 `arch`
|
|
22
22
|
|
|
@@ -71,7 +71,7 @@ export default moduleLint({ rootDir: import.meta.dirname });
|
|
|
71
71
|
| `no-explicit-any` | `as any` / `: any` | 写真实类型;或在 `moduleLint({ rules })` 放行 |
|
|
72
72
|
| `no-console` | `src/**` 的 `console.log` / `info` / `debug`(`warn` / `error` 放行) | 删除;`scripts/**` 不判 |
|
|
73
73
|
| `no-debugger` | 残留 `debugger` | 删除 |
|
|
74
|
-
| `no-restricted-syntax` | 颜色字面量(`#ff0000` / `rgb(` / `hsl(`)、字符串 `!important` | 用令牌与 `*.module.css` |
|
|
74
|
+
| `no-restricted-syntax` | 颜色字面量(`#ff0000` / `rgb(` / `hsl(`)、字符串 `!important`、平台原始事实(`process.platform` / `versions.electron` / `dshDesktop` / `hostOs` / `navigator.userAgent`) | 用令牌与 `*.module.css`;平台差异走能力面(`HostSurface` / `ClientSurface`),宿主/浏览器面分开写 |
|
|
75
75
|
| `react-hooks/*` | 条件 hook / 渲染期写 ref / 漏依赖 | 提到顶层;副作用进 `useEffect`;补依赖 |
|
|
76
76
|
| `no-unused-vars` | 死代码(`^_` 放行) | 删除或改 `_x` |
|
|
77
77
|
| 其他 `recommended` / `react/*` | 语法规则 | 按 eslint 原文 |
|