@dsh-workbench/core 0.3.6 → 0.3.7
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/client.js +1260 -1928
- package/dist/client/client.body.js +1260 -1928
- package/dist/client/index.js +1260 -1928
- package/dist/host/index.js +1240 -790
- package/dist/types/app/client.d.ts +76 -3388
- package/dist/types/app/layouts/env-gate/boot-gate.d.ts +8 -1
- package/dist/types/app/layouts/rightbar/market-busy.d.ts +28 -0
- package/dist/types/app/layouts/rightbar/market-hint.d.ts +7 -0
- package/dist/types/app/layouts/sidebar/DebugFooterAction.d.ts +2 -1
- package/dist/types/app/layouts/sidebar/RecordFooterAction.d.ts +2 -1
- package/dist/types/app/layouts/sidebar/SessionList.d.ts +3 -1
- package/dist/types/app/layouts/sidebar/session-pick.d.ts +2 -0
- package/dist/types/app/layouts/sidebar/use-attention.d.ts +7 -1
- package/dist/types/modules/panels/model/diy-context.d.ts +9 -0
- package/dist/types/modules/panels/model/diy-record-beat.test.d.ts +1 -0
- package/dist/types/modules/panels/model/diy-record-close.test.d.ts +1 -0
- package/dist/types/modules/panels/model/diy-record-hook.test.d.ts +1 -0
- package/dist/types/modules/panels/model/diy-record-open.d.ts +28 -0
- package/dist/types/modules/panels/model/diy-record-open.test.d.ts +1 -0
- package/dist/types/modules/panels/model/diy-record-shot.test.d.ts +1 -0
- package/dist/types/modules/panels/model/diy-record-text.d.ts +16 -1
- package/dist/types/modules/panels/model/diy-record-tools.d.ts +2 -1
- package/dist/types/modules/panels/model/diy-record.d.ts +40 -1
- package/dist/types/modules/panels/model/diy-report.d.ts +1 -1
- package/dist/types/modules/sessions/index.d.ts +1 -1
- package/dist/types/modules/sessions/model/attention-long-task.test.d.ts +1 -0
- package/dist/types/modules/sessions/model/attention.d.ts +23 -1
- package/dist/types/modules/sessions/model/session-node.d.ts +12 -1
- package/dist/types/shared/api/host/long-tasks.d.ts +10 -0
- package/dist/types/shared/api/host/preflight.d.ts +7 -1
- package/dist/types/shared/api/host/workshop-root.d.ts +9 -0
- package/dist/types/shared/api/long-tasks.d.ts +19 -0
- package/dist/types/shared/hooks/panel-state-report.d.ts +1 -1
- package/dist/types/shared/hooks/use-diy-debug.d.ts +1 -1
- package/dist/types/shared/hooks/use-diy-record.d.ts +1 -1
- package/dist/types/shared/hooks/use-shell-long-tasks.d.ts +8 -0
- package/package.json +2 -2
- package/skills/workbench-module-diy/BUILD.md +1 -1
- package/skills/workbench-module-diy/FAMILY.md +1 -1
- package/skills/workbench-module-diy/KIT.md +23 -23
- package/skills/workbench-module-diy/PANEL.md +1 -1
- package/skills/workbench-module-diy/TOOLS.md +3 -1
- package/skills/workbench-module-diy/WRITES.md +20 -3
|
@@ -37,7 +37,7 @@ h(Card, { t: props.t, title: t('myunit.cardTitle'),
|
|
|
37
37
|
| 在读、且你已经有大概形状 | `SkeletonRows`(骨架) |
|
|
38
38
|
| 一句说明 / 一句报错 | `Note`(`tone: 'problem'` 是报错) |
|
|
39
39
|
|
|
40
|
-
prop 与默认值看 `.d.ts
|
|
40
|
+
prop 与默认值看 `.d.ts`。
|
|
41
41
|
|
|
42
42
|
```tsx
|
|
43
43
|
h(CenteredState, { icon: null, title: t('myunit.loading'), hint: t('myunit.loadingHint'), compact: true })
|
|
@@ -71,22 +71,23 @@ h(Rows, null,
|
|
|
71
71
|
第一处错误怎么带进视口、操作区怎么排全归它。**一张完整的表单就用它**(口径见 §5,逐件看 `.d.ts`)。
|
|
72
72
|
|
|
73
73
|
```tsx
|
|
74
|
-
h(Form
|
|
74
|
+
h(Form<{ branch: string }>, {
|
|
75
75
|
fields: [
|
|
76
|
-
{ key: 'branch', label: t('myunit.branch'), value: branch,
|
|
76
|
+
{ key: 'branch', label: t('myunit.branch'), value: draft.branch, onChange: onBranch, // 值与改写同一处
|
|
77
77
|
validate: (v) => (v === '' ? t('myunit.branchRequired') : undefined),
|
|
78
78
|
control: (b) => h(TextField, { id: b.id, name: b.name, invalid: b.invalid,
|
|
79
|
-
disabled: b.disabled, value:
|
|
79
|
+
disabled: b.disabled, value: b.value, onChange: (e) => b.onChange(e.currentTarget.value) }) },
|
|
80
80
|
],
|
|
81
|
-
submit: { label: t('myunit.save'), busyLabel: t('myunit.saving') },
|
|
82
|
-
|
|
83
|
-
extra: [{ key: 'retry', label: t('myunit.retry'), onClick: onRetry }], // 其余动作排最左
|
|
84
|
-
onSubmit: save, // 有错就不调它
|
|
81
|
+
submit: { label: t('myunit.save'), busyLabel: t('myunit.saving') }, // cancel / extra 见 `.d.ts`
|
|
82
|
+
onSubmit: save, // 有错就不调它;values 就是这个类型
|
|
85
83
|
})
|
|
86
84
|
```
|
|
87
85
|
|
|
88
|
-
|
|
89
|
-
|
|
86
|
+
**`Form<Values>` 把每一格的键与值类型钉住**(不写类型参数 = 默认档、不钉,每格要自己收窄);
|
|
87
|
+
**值与它的改写写在同一格**(`value` + `onChange`,`control` 从绑定取 `binding.value` / `binding.onChange`
|
|
88
|
+
—— `Form` 不持有值);**会 `visible: false` 的键在 `Values` 里写可选**(`branch?: string` ⇒ 值是
|
|
89
|
+
`string | undefined`)。`validate` 是同步纯函数、第二参是整张值表(跨字段读得到别的格);**控件永远由
|
|
90
|
+
`control` 给**(没有"给个 `options` 自己选控件"的 DSL)。
|
|
90
91
|
|
|
91
92
|
**控件那几件** —— `Field`(没进 `FormRow` 时兜住标签 + 说明)· `TextField`(`invalid` 标红)·
|
|
92
93
|
`ChoiceGroup`(`multi` 区分多选)· `SelectField`(默认常规下拉框,`variant: 'ghost'` 是无边框那档,
|
|
@@ -102,7 +103,11 @@ h(Form, {
|
|
|
102
103
|
**别手写 `<button>` / `<input>` / `<select>`**(dsh 有 `Button`,kit 有上面这几件;手写的判据会红)。
|
|
103
104
|
`<textarea>` 例外(dsh 与 kit 都没有多行输入)。
|
|
104
105
|
|
|
105
|
-
|
|
106
|
+
**`ConfirmBar`** —— 「先问一句再动手」那一条(标题 / 说明 / 键值 / 失败那句 / 动作区一次收口):
|
|
107
|
+
键值走 `Rows` / `Row`、错走 `Note tone="problem"`、动作走 `FormActions` —— **别自己拼这四个槽**。
|
|
108
|
+
**要不要问归调用点**(同 `FormActions`:`danger` 只标"破坏性")。口径见 ADR-0073。
|
|
109
|
+
|
|
110
|
+
怎么排(标签位置、错误态、尺寸)见 §5。
|
|
106
111
|
|
|
107
112
|
## 4′ hook 怎么搭(逐件看 `.d.ts`)
|
|
108
113
|
|
|
@@ -115,21 +120,16 @@ kit 的 hook 也分四个场合,**别自己 `useState` + `setTimeout` 造一
|
|
|
115
120
|
| "至少转一会儿"的忙态 | `useVisibleBusy`(投影那两件 `busyView` / `heldPhase`) |
|
|
116
121
|
| 一格**卡片**起步(gate + 忙 + 探针 + 上报 + blocker 一次叠好) | `useUnitBoard`(`read(gated)` 里自己调 `useApiResource`) |
|
|
117
122
|
| 只要一格的能力门 / 整张能力表 | `useCapabilityGate` / `useCapabilityMap` |
|
|
118
|
-
| 写(**别在组件里 `fetch`**) / 轮询长任务 | `useHostWrite` / `useLongTask`(画用 `LongTaskRow
|
|
123
|
+
| 写(**别在组件里 `fetch`**) / 轮询长任务 | `useHostWrite` / `useLongTask`(画用 `LongTaskRow` —— 圆点与阶段它自己带) |
|
|
119
124
|
|
|
120
125
|
取数那条链的图见 [LINKAGE.md](LINKAGE.md) §8,写通道与配置见 [PANEL.md](PANEL.md) §5。
|
|
121
126
|
|
|
122
127
|
## 5 表单这一层:`Form`(面)→ 行 → 控件
|
|
123
128
|
|
|
124
|
-
表单三层:**面**(`Form
|
|
125
|
-
`ChoiceGroup
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
里自己接,`binding` 只递 `id` / `name` / `invalid` / `disabled`);**控件永远由 `control` 给**(没有"给个
|
|
129
|
-
`options` 自己选控件"的 DSL);`validate` 是同步纯函数;`visible: false` 的那格当它不存在(不渲染 /
|
|
130
|
-
不校验 / 不进 `values`)。**别再自己摆操作区** —— 它自己组 `[...extra, ...cancel, submit(primary)]`
|
|
131
|
-
(提交钮永远在右;「一会在左一会在右」就是自己摆的结果)。其余口径(时机 / 第一处错误 / `busy` /
|
|
132
|
-
`disabled` / `key`)看它的 JSDoc 与 ADR-0068。
|
|
129
|
+
表单三层:**面**(`Form`,写法见 §4:值 / 校验 / 操作区全归它)→ **行**(`FormRows` + `FormRow`)→
|
|
130
|
+
**控件**(`TextField` / `SelectField` / `ChoiceGroup`)。**一张表单一个面**。**别再自己摆操作区** ——
|
|
131
|
+
它自己组 `[...extra, ...cancel, submit(primary)]`(提交钮永远在右;「一会在左一会在右」就是自己摆的结果);
|
|
132
|
+
其余口径(时机 / 第一处错误 / `busy` / `disabled`)看它的 JSDoc 与 ADR-0068 / ADR-0074。
|
|
133
133
|
|
|
134
134
|
`FormRows` + `FormRow` + `FormActions` 留给**不是整张表单**的地方:单行(一格字段嵌在别处,比如卡片里
|
|
135
135
|
那一条设定)、非表单的一组动作(工具栏、卡头那几颗钮)。那里才自己拼这三件:
|
|
@@ -164,8 +164,8 @@ h('form', …) // ← 裸 <form> / 手写行槽
|
|
|
164
164
|
```
|
|
165
165
|
|
|
166
166
|
**时点**:这一层随外壳发版后模块才能用(`check --only kit` 拿 peer 下限那份外壳比,不抬必红)。
|
|
167
|
-
**`Form`
|
|
168
|
-
|
|
167
|
+
**`Form` / `ConfirmBar` 是新成员**:要用得等外壳**发一版含它的版本**,再把 peer 下限抬到**那一版**
|
|
168
|
+
(版本随发版填,别照抄别的件);`FormRow(s)` / `FormActions` 的下限是另一件事。
|
|
169
169
|
|
|
170
170
|
## 6 别的
|
|
171
171
|
|
|
@@ -119,7 +119,7 @@ agent 那一侧也要能通过模块自己的能力读到同一份偏好。
|
|
|
119
119
|
- **默认收起**:历史、明细折叠,露出最近一条;只有一条时不给折叠三角(没有可展开的东西)。
|
|
120
120
|
- **屏幕上的字越少越好**:他能看懂的(红点绿点、数字)就不用再写一段规则解释;删掉的东西不要留一行说明。
|
|
121
121
|
- **默认状态点**只有四种意思:在做 / 做完了 / 出错 / 没在跑。
|
|
122
|
-
- **外链一律用 kit 的 `Link`**(`h(Link, { href: … }, 文案)
|
|
122
|
+
- **外链一律用 kit 的 `Link`**(`h(Link, { href: … }, 文案)` —— `h` 从 `react` 引,**不在 kit 面里**):新窗口 + `rel` + 自带外链箭头,
|
|
123
123
|
**它自带的样子就是唯一一份,别去掉箭头、别换箭头、别自己调**(没有 `icon` 这个口子)——
|
|
124
124
|
全仓的链接必须长得一样。
|
|
125
125
|
模块源码里手写 `<a>` / `h('a', …)` 会被「样式归属」判据**直接判红**。
|
|
@@ -105,7 +105,9 @@
|
|
|
105
105
|
|
|
106
106
|
**为什么不走 `ctx.jobs`**:dsh 的 job 归**一次 agent 会话**(teardown 主动取消、读口按会话围栏),我们的长跑归**工作区的一个目标**(`dispose` 刻意不取消)—— 归属轴不同;换过去要改归属口径,而它的 `JobStatus` 里没有 `needs-login`、`JobView` 里也没有工作区字段。理由、代价与"只借形状"那四件见仓内 ADR-0069(这里不链仓内路径)。
|
|
107
107
|
|
|
108
|
-
判据(`check --only contracts
|
|
108
|
+
判据(`check --only contracts`):注册表**七个**方法要全(含 `stop` / `live`)、`create` 的 `key`/`run`/`view` 不能缺、产物里必须有 `useLongTask`/`LongTaskRow`/`longTaskDot` 之一。**它只查形状与"画得出来"** —— "你真认了 signal 吗、真收得住手吗"不在它的射程里(那只有你自己知道,见上面第一条)。
|
|
109
|
+
|
|
110
|
+
**左栏那颗 loading 点不用你做**:有长任务在跑时,起它的那条会话行、以及项目下拉里有它的那个工作区那一行,各自那颗状态点会自己转(外壳按 `live()` 读,不看是谁起的;用户在面板上按的那趟也会点亮它所在工作区那一行)。
|
|
109
111
|
|
|
110
112
|
**要用 `stop` 这个新 prop / 新返回字段,就得装带这次改动的那份外壳**:把自己 `peerDependencies['@dsh-workbench/core']` 的下限抬到那一版 —— `check --only kit` 盯着这条(产物实际取的 kit 成员 ⊆ 你 peer 下限那份外壳的 kit)。**同理**:`start` 收 `session`、外壳那两把 `workbench_long_tasks_*` 工具,也都是这一版才有的。
|
|
111
113
|
|
|
@@ -43,10 +43,18 @@
|
|
|
43
43
|
站点、录哪一下、落在哪、录完不替他切回来),窗里有一根浮条。请他 ① 按「开始录制」 ② 做**一次**那动作 ③ 按「结束录制」;
|
|
44
44
|
**别让他点第二次**。`url` 必须是**这个模块读源同域**的页面 —— 模块的 `design.json` 说过读源时,跨域会**当场拒**
|
|
45
45
|
(没说过就不拦;那一条比的是"别把别处的请求原文带进这个模块")。
|
|
46
|
+
- **再让他按一下浮条上的「截图」**:时机是**把表填对之后、点提交之前**(提交完表单就没了)——
|
|
47
|
+
这一下**不另外审批**(屏幕在 prepare 那一拍已经借过)。它同时落下两样东西:一张整页图(落 `shots/rec-shot-<unit>-<n>.png`)
|
|
48
|
+
与一份**页面快照**(每个控件的 `name`/`id`、标签、`required`/`aria-required`/容器 class/`*` 这类必填痕迹、当时的填值、是否空、
|
|
49
|
+
有没有被改过)。**提交那一刻我们会自动再抓一份**,所以他忘了按也不至于空手。
|
|
50
|
+
他按了截图之后,浮条上会多一个「已拍 N 张」,左栏底部那句也跟着带张数。
|
|
46
51
|
- `workbench_diy_record_read` 取那一段(他按完结束再取):回的是**清单** `rows`(每条 `index` / `key` / `method` /
|
|
47
52
|
`url` / `status` / `ct` / `size` / `source` / `hasRequest` / `hasResponse` / `likelyWrite` / `marked`),
|
|
48
|
-
**一条都不删、也不回体**;`expect` 只用来标 ⭐ 并把 ⭐
|
|
49
|
-
|
|
53
|
+
**一条都不删、也不回体**;`expect` 只用来标 ⭐ 并把 ⭐ 排到前面。**正文每一行就把它要的两样摆出来了**:
|
|
54
|
+
`· [0] ⭐ POST 站点/路径(捕获 · 入参 有 · 出参 40 B · at 1792583917392)` —— 开头那串就是 `key` 原文(opencli 给的,
|
|
55
|
+
可能带 `#2` 这种后缀),`at` 是毫秒时间戳;**没有 `key` 的钩子行**(页面钩子只记 `method`/`url`,没给 key)会写成
|
|
56
|
+
`method url(钩子 · … · 无 key)`,那种行只有还开着时按 `index` 才取得到。要哪一条的原文再调
|
|
57
|
+
**`workbench_diy_record_detail`**(给那一行的 `key`,或序号 `index`;**同一个 key 跨轮会重名**,
|
|
50
58
|
再带上那一行的 `at` 才钉得住是哪一次)——它回**入参(`request.body`)与
|
|
51
59
|
出参(`response body`)原文**,外加请求头(可能含凭据,别落进 `design.json`)。他还没按结束时 read 会说清"还在录"
|
|
52
60
|
(要等就带 `waitMs`,帽 15 分钟;等不到会挂一条 notice 叫你);浮条被导航干掉过会顺手重新装上。
|
|
@@ -115,7 +123,7 @@
|
|
|
115
123
|
| 字段 | 渲染出来的行 |
|
|
116
124
|
|---|---|
|
|
117
125
|
| `command` | 哪条写(命令 / URL + 方法) |
|
|
118
|
-
| `params` | 参数(必填 / 取值枚举 /
|
|
126
|
+
| `params` | 参数(必填 / 取值枚举 / 上限)—— 写"必填"就得带来源括号,见下 |
|
|
119
127
|
| `credentials` | 凭据从哪来 |
|
|
120
128
|
| `preview` | 有没有预览档(没有就写"没有,一次就是真的") |
|
|
121
129
|
| `readback` | 写完之后怎么回读确认(哪条读 / 出参哪个字段) |
|
|
@@ -129,3 +137,12 @@
|
|
|
129
137
|
|
|
130
138
|
`undo` 是 2026-10-19 加的(照 opencli 的 `write-without-delete-pair`):**旧模块**跑 `design check`
|
|
131
139
|
会多出一格 `write.undo` 的空格 —— 补一句"没有配对,一次就是真的"(或真配对那条命令)就过,别的不用动。
|
|
140
|
+
|
|
141
|
+
`params` **带证据**是 2026-10-21 加的(照 `undo` 那一格同一套做法):录完一次之后,
|
|
142
|
+
`workbench_diy_record_read` 会给到这一场落下的**图**(他按「截图」那几张)与 `workbench_diy_record_detail` 里的**捕获原文** ——
|
|
143
|
+
照它们写:哪一格必填,就看**图上有没有那个红 `*`**,或者看**契约**(`opencli <命令> --help -f json` 里的 `required`)。
|
|
144
|
+
那一格**没有 DOM 快照这条路**(2026-10-21 撤了:页面的弹层/抽屉在真机上是哈希类名,通用规则圈不住他正在填的那一层)。
|
|
145
|
+
判据只咬**来源有没有写出来**:`params` 里出现"必填"时,同一格必须带来源关键词之一
|
|
146
|
+
(`已证` / `声明` / `人证` / `契约` / `未定`),否则 `design check` 点名 `write.params.source`。
|
|
147
|
+
**旧模块**补一个括号就过 —— `(前端已证)` / `(服务端已证)` / `(人证)` / `(契约)` / `(未定)`;别的不用动。
|
|
148
|
+
写成 `非必填` / `不必填` 的不需要来源(那一格是"可选")。这一条**不校验来源是不是真的** —— 它逼你想过,不逼你造假。
|