@dsh-workbench/shared 0.3.4 → 0.3.5

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.
Files changed (180) hide show
  1. package/dist/api/blocker-table.d.ts +13 -0
  2. package/dist/api/blocker-table.js +13 -0
  3. package/dist/api/blocker.d.ts +6 -0
  4. package/dist/api/context-ref.d.ts +31 -0
  5. package/dist/api/context-ref.js +28 -0
  6. package/dist/api/dsh-client.d.ts +99 -0
  7. package/dist/api/dsh.d.ts +55 -3
  8. package/dist/api/facts.d.ts +42 -0
  9. package/dist/api/facts.js +33 -0
  10. package/dist/api/host-write.d.ts +18 -0
  11. package/dist/api/host-write.js +12 -0
  12. package/dist/api/long-task.d.ts +36 -0
  13. package/dist/api/long-task.js +27 -0
  14. package/dist/api/unit-board.d.ts +25 -0
  15. package/dist/api/unit-board.js +16 -0
  16. package/dist/api/unit-declaration.d.ts +36 -0
  17. package/dist/api/unit-declaration.js +24 -0
  18. package/dist/api/unit.d.ts +32 -0
  19. package/dist/api/unit.js +5 -0
  20. package/dist/api/workbench-client.d.ts +25 -0
  21. package/dist/api/workbench-client.js +13 -0
  22. package/dist/api/workbench-contract.d.ts +12 -0
  23. package/dist/components/Activity.d.ts +33 -0
  24. package/dist/components/Activity.js +24 -0
  25. package/dist/components/ApprovalDetail.d.ts +12 -0
  26. package/dist/components/ApprovalDetail.js +9 -0
  27. package/dist/components/ApprovalPlan.d.ts +14 -0
  28. package/dist/components/ApprovalPlan.js +8 -0
  29. package/dist/components/Card.d.ts +13 -0
  30. package/dist/components/Card.js +10 -0
  31. package/dist/components/CardAnchor.d.ts +14 -0
  32. package/dist/components/CardAnchor.js +11 -0
  33. package/dist/components/CardBoundary.d.ts +20 -0
  34. package/dist/components/CardBoundary.js +14 -0
  35. package/dist/components/CardHead.d.ts +13 -0
  36. package/dist/components/CardHead.js +10 -0
  37. package/dist/components/ChoiceGroup.d.ts +24 -0
  38. package/dist/components/ChoiceGroup.js +12 -0
  39. package/dist/components/Field.d.ts +10 -0
  40. package/dist/components/Field.js +7 -0
  41. package/dist/components/Form.css +6 -0
  42. package/dist/components/Form.d.ts +20 -0
  43. package/dist/components/Form.js +58 -0
  44. package/dist/components/FormActions.d.ts +14 -0
  45. package/dist/components/FormActions.js +5 -0
  46. package/dist/components/FormNodes.d.ts +103 -0
  47. package/dist/components/FormNodes.js +153 -0
  48. package/dist/components/FormRows.d.ts +20 -0
  49. package/dist/components/FormRows.js +14 -0
  50. package/dist/components/FormTypes.d.ts +59 -0
  51. package/dist/components/FormTypes.js +1 -0
  52. package/dist/components/Link.d.ts +12 -0
  53. package/dist/components/Link.js +9 -0
  54. package/dist/components/LongTaskRow.d.ts +19 -0
  55. package/dist/components/LongTaskRow.js +13 -0
  56. package/dist/components/Note.d.ts +11 -0
  57. package/dist/components/Note.js +8 -0
  58. package/dist/components/ResourceStates.d.ts +25 -0
  59. package/dist/components/ResourceStates.js +22 -0
  60. package/dist/components/Rows.d.ts +17 -0
  61. package/dist/components/Rows.js +11 -0
  62. package/dist/components/SaveBar.d.ts +12 -0
  63. package/dist/components/SaveBar.js +9 -0
  64. package/dist/components/SelectField.d.ts +26 -0
  65. package/dist/components/SelectField.js +22 -0
  66. package/dist/components/SelectFieldNodes.d.ts +24 -0
  67. package/dist/components/SelectFieldNodes.js +24 -0
  68. package/dist/components/SettingsSection.d.ts +11 -0
  69. package/dist/components/SettingsSection.js +8 -0
  70. package/dist/components/Spinner.d.ts +9 -0
  71. package/dist/components/Spinner.js +6 -0
  72. package/dist/components/Stack.d.ts +8 -0
  73. package/dist/components/Stack.js +5 -0
  74. package/dist/components/StateBlock.d.ts +13 -0
  75. package/dist/components/StateBlock.js +10 -0
  76. package/dist/components/TextField.d.ts +8 -0
  77. package/dist/components/TextField.js +5 -0
  78. package/dist/components/board-module.d.ts +30 -0
  79. package/dist/components/icons.d.ts +38 -0
  80. package/dist/components/icons.js +35 -0
  81. package/dist/config/constants.d.ts +42 -0
  82. package/dist/config/constants.js +42 -0
  83. package/dist/config/storage.d.ts +4 -0
  84. package/dist/config/storage.js +4 -0
  85. package/dist/host/unit-face.d.ts +5 -1
  86. package/dist/i18n/en.d.ts +1 -0
  87. package/dist/i18n/en.js +8 -8
  88. package/dist/i18n/index.d.ts +11 -9
  89. package/dist/i18n/index.js +1 -0
  90. package/dist/i18n/merge.d.ts +5 -0
  91. package/dist/i18n/merge.js +2 -0
  92. package/dist/i18n/zh.d.ts +9 -8
  93. package/dist/i18n/zh.js +8 -8
  94. package/dist/index.d.ts +6 -2
  95. package/dist/index.js +6 -2
  96. package/dist/lib/blocker-action.d.ts +22 -0
  97. package/dist/lib/blocker-action.js +13 -0
  98. package/dist/lib/board-fact.d.ts +27 -0
  99. package/dist/lib/board-fact.js +18 -0
  100. package/dist/lib/busy.d.ts +10 -0
  101. package/dist/lib/busy.js +7 -0
  102. package/dist/lib/diy-debug.d.ts +42 -2
  103. package/dist/lib/diy-debug.js +19 -1
  104. package/dist/lib/diy-record.d.ts +41 -0
  105. package/dist/lib/diy-record.js +17 -0
  106. package/dist/lib/form-problem.d.ts +10 -0
  107. package/dist/lib/form-problem.js +10 -0
  108. package/dist/lib/panel-state.d.ts +60 -0
  109. package/dist/lib/panel-state.js +30 -0
  110. package/dist/lib/react.d.ts +39 -0
  111. package/dist/lib/react.js +36 -0
  112. package/dist/lib/text.d.ts +22 -0
  113. package/dist/lib/text.js +22 -0
  114. package/dist/lib/ui.d.ts +50 -0
  115. package/dist/lib/ui.js +41 -0
  116. package/package.json +1 -1
  117. package/src/api/blocker-table.ts +13 -0
  118. package/src/api/blocker.ts +6 -0
  119. package/src/api/context-ref.ts +31 -0
  120. package/src/api/dsh-client.ts +99 -0
  121. package/src/api/dsh.ts +56 -1
  122. package/src/api/facts.ts +42 -0
  123. package/src/api/host-write.ts +18 -0
  124. package/src/api/long-task.ts +36 -0
  125. package/src/api/unit-board.ts +25 -0
  126. package/src/api/unit-declaration.ts +36 -0
  127. package/src/api/unit.ts +32 -0
  128. package/src/api/workbench-client.ts +25 -0
  129. package/src/api/workbench-contract.ts +12 -0
  130. package/src/components/Activity.tsx +33 -0
  131. package/src/components/ApprovalDetail.tsx +12 -0
  132. package/src/components/ApprovalPlan.tsx +14 -0
  133. package/src/components/Card.tsx +13 -0
  134. package/src/components/CardAnchor.tsx +14 -0
  135. package/src/components/CardBoundary.tsx +20 -0
  136. package/src/components/CardHead.tsx +13 -0
  137. package/src/components/ChoiceGroup.tsx +24 -0
  138. package/src/components/Field.tsx +10 -0
  139. package/src/components/Form.css +6 -0
  140. package/src/components/Form.test.tsx +475 -0
  141. package/src/components/Form.tsx +78 -0
  142. package/src/components/FormActions.tsx +14 -0
  143. package/src/components/FormNodes.tsx +193 -0
  144. package/src/components/FormRows.tsx +20 -0
  145. package/src/components/FormTypes.ts +65 -0
  146. package/src/components/FormWiring.test.tsx +88 -0
  147. package/src/components/Link.tsx +12 -0
  148. package/src/components/LongTaskRow.tsx +19 -0
  149. package/src/components/Note.tsx +11 -0
  150. package/src/components/ResourceStates.tsx +25 -0
  151. package/src/components/Rows.tsx +17 -0
  152. package/src/components/SaveBar.tsx +12 -0
  153. package/src/components/SelectField.tsx +26 -0
  154. package/src/components/SelectFieldNodes.tsx +24 -0
  155. package/src/components/SettingsSection.tsx +11 -0
  156. package/src/components/Spinner.tsx +9 -0
  157. package/src/components/Stack.tsx +8 -0
  158. package/src/components/StateBlock.tsx +13 -0
  159. package/src/components/TextField.tsx +8 -0
  160. package/src/components/board-module.ts +30 -0
  161. package/src/components/icons.tsx +38 -0
  162. package/src/config/constants.ts +43 -0
  163. package/src/config/storage.ts +4 -0
  164. package/src/host/unit-face.ts +6 -1
  165. package/src/i18n/en.ts +8 -8
  166. package/src/i18n/index.ts +3 -0
  167. package/src/i18n/merge.ts +5 -0
  168. package/src/i18n/zh.ts +9 -8
  169. package/src/index.ts +6 -2
  170. package/src/lib/blocker-action.ts +22 -0
  171. package/src/lib/board-fact.ts +27 -0
  172. package/src/lib/busy.ts +10 -0
  173. package/src/lib/diy-debug.test.ts +2 -1
  174. package/src/lib/diy-debug.ts +44 -3
  175. package/src/lib/diy-record.ts +41 -0
  176. package/src/lib/form-problem.ts +10 -0
  177. package/src/lib/panel-state.ts +60 -0
  178. package/src/lib/react.ts +39 -0
  179. package/src/lib/text.ts +22 -0
  180. package/src/lib/ui.ts +50 -0
@@ -1,6 +1,19 @@
1
+ /**
2
+ * 这颗钮此刻该不该按成等待态:这一轮忙还没收,或有一支正在跑。
3
+ * @param busy - 这一轮忙是不是还在。
4
+ * @param running - 正在跑的那一支的 label;没有就给 `null`。
5
+ * @returns 该等待给 `true`,否则 `false`。
6
+ */
1
7
  export function blockerPending(busy, running) {
2
8
  return busy || running !== null;
3
9
  }
10
+ /**
11
+ * 这颗钮此刻该显示什么字:正在重试说「重试中…」,正在跑的那一支说「修复中…」,刚复制过的说「已复制」,其余原样。
12
+ * @param action - 这颗钮的形状(行为 + 平时文案)。
13
+ * @param state - 此刻的运行态。
14
+ * @param t - i18n 取词函数。
15
+ * @returns 要显示的文案;三种临时态都不成立时就是 `action.label`。
16
+ */
4
17
  export function blockerActionLabel(action, state, t) {
5
18
  if (action.kind === 'retry' && state.retrying)
6
19
  return t('blocker.retry.running');
@@ -1,5 +1,14 @@
1
+ /**
2
+ * 椅面(右栏那块画板)此刻归属哪一类:`workshop` 本工坊、`other` 别家、`hidden` 没画出来、`unknown` 探不到。
3
+ */
1
4
  export type BoardFactState = 'workshop' | 'other' | 'hidden' | 'unknown';
5
+ /**
6
+ * 左栏底部「调试」那条状态要说的档位:`ok` 在板上、`off-workspace` 切去了别的项目、`panel-closed` 面板没开、`other-board` 画的是别家的板、`unknown` 探不到。
7
+ */
2
8
  export type BoardSituation = 'ok' | 'off-workspace' | 'panel-closed' | 'other-board' | 'unknown';
9
+ /**
10
+ * 一次页面探针的读数:外壳在不在、探的是哪个工作区、右栏开没开、板上挂的路径、椅面画出来没有。
11
+ */
3
12
  export interface BoardProbe {
4
13
  readonly workbench: boolean;
5
14
  readonly where: string;
@@ -8,6 +17,24 @@ export interface BoardProbe {
8
17
  readonly open: boolean;
9
18
  readonly drawn: boolean;
10
19
  }
20
+ /**
21
+ * 判一个路径落不落在这个工作区里(按路径前缀比,不是字符串包含)。
22
+ * @param root - 工作区根路径。
23
+ * @param target - 要判的路径。
24
+ * @returns 同一个路径或在其下给 `true`;`root` 末尾带不带斜杠都认(`/a` 不匹配 `/ab`)。
25
+ */
11
26
  export declare function insideWorkshop(root: string, target: string): boolean;
27
+ /**
28
+ * 把一次探针读数归成椅面归属。
29
+ * @param probe - 探针读数。
30
+ * @param workshop - 当前工作区根路径;`null` 表示还不知道当前是哪个工作区。
31
+ * @returns 外壳不在、或板路径与工作区缺一 → `unknown`;右栏没开或没画出来 → `hidden`;板在本工作区 → `workshop`,否则 `other`。
32
+ */
12
33
  export declare function boardFactOf(probe: BoardProbe, workshop: string | null): BoardFactState;
34
+ /**
35
+ * 把探针读数归成左栏那句人话的档位。
36
+ * @param probe - 探针读数。
37
+ * @param workshop - 当前工作区根路径;`null` 一律 `unknown`。
38
+ * @returns 椅面画着 → 本板 `ok` / 别板 `other-board`;没画着 → 页面已走 `off-workspace`,否则 `panel-closed`。
39
+ */
13
40
  export declare function boardSituation(probe: BoardProbe, workshop: string | null): BoardSituation;
@@ -1,9 +1,21 @@
1
+ /**
2
+ * 判一个路径落不落在这个工作区里(按路径前缀比,不是字符串包含)。
3
+ * @param root - 工作区根路径。
4
+ * @param target - 要判的路径。
5
+ * @returns 同一个路径或在其下给 `true`;`root` 末尾带不带斜杠都认(`/a` 不匹配 `/ab`)。
6
+ */
1
7
  export function insideWorkshop(root, target) {
2
8
  if (target === root)
3
9
  return true;
4
10
  const base = root.endsWith('/') ? root : `${root}/`;
5
11
  return target.startsWith(base);
6
12
  }
13
+ /**
14
+ * 把一次探针读数归成椅面归属。
15
+ * @param probe - 探针读数。
16
+ * @param workshop - 当前工作区根路径;`null` 表示还不知道当前是哪个工作区。
17
+ * @returns 外壳不在、或板路径与工作区缺一 → `unknown`;右栏没开或没画出来 → `hidden`;板在本工作区 → `workshop`,否则 `other`。
18
+ */
7
19
  export function boardFactOf(probe, workshop) {
8
20
  if (!probe.workbench)
9
21
  return 'unknown';
@@ -13,6 +25,12 @@ export function boardFactOf(probe, workshop) {
13
25
  return 'unknown';
14
26
  return insideWorkshop(workshop, probe.board) ? 'workshop' : 'other';
15
27
  }
28
+ /**
29
+ * 把探针读数归成左栏那句人话的档位。
30
+ * @param probe - 探针读数。
31
+ * @param workshop - 当前工作区根路径;`null` 一律 `unknown`。
32
+ * @returns 椅面画着 → 本板 `ok` / 别板 `other-board`;没画着 → 页面已走 `off-workspace`,否则 `panel-closed`。
33
+ */
16
34
  export function boardSituation(probe, workshop) {
17
35
  if (!probe.workbench || workshop === null)
18
36
  return 'unknown';
@@ -1,5 +1,15 @@
1
+ /**
2
+ * 忙态按下限收尾的判据结果:还该不该显示(`visible`),以及还要按住多少毫秒(`releaseInMs`,0 = 立刻可收)。
3
+ */
1
4
  export interface BusyHold {
2
5
  readonly visible: boolean;
3
6
  readonly releaseInMs: number;
4
7
  }
8
+ /**
9
+ * 按「至少显示 floorMs」算这一轮忙此刻该不该收:没到下限就继续显示,并给出剩余时长供调用方起定时器。
10
+ * @param since - 这一轮忙开始的时间戳;`null`(没开过这一轮)一律不显示。
11
+ * @param now - 当前时间戳。
12
+ * @param floorMs - 至少显示的时长(毫秒)。
13
+ * @returns 还该不该显示 + 剩余毫秒;到点或已过下限给不显示,时钟倒退按「刚开头」算(剩余 = 下限,不给负数)。
14
+ */
5
15
  export declare function holdBusy(since: number | null, now: number, floorMs: number): BusyHold;
package/dist/lib/busy.js CHANGED
@@ -1,3 +1,10 @@
1
+ /**
2
+ * 按「至少显示 floorMs」算这一轮忙此刻该不该收:没到下限就继续显示,并给出剩余时长供调用方起定时器。
3
+ * @param since - 这一轮忙开始的时间戳;`null`(没开过这一轮)一律不显示。
4
+ * @param now - 当前时间戳。
5
+ * @param floorMs - 至少显示的时长(毫秒)。
6
+ * @returns 还该不该显示 + 剩余毫秒;到点或已过下限给不显示,时钟倒退按「刚开头」算(剩余 = 下限,不给负数)。
7
+ */
1
8
  export function holdBusy(since, now, floorMs) {
2
9
  if (since === null)
3
10
  return { visible: false, releaseInMs: 0 };
@@ -1,26 +1,54 @@
1
+ /**
2
+ * 调试约定的两个相位:`debugging` 正占着用户的屏,`paused` 已暂停但仍持着约定。
3
+ */
1
4
  export type DebugPhase = 'debugging' | 'paused';
5
+ /**
6
+ * 调试约定收得下的三个人话动作:暂停 / 继续 / 结束。
7
+ */
2
8
  export type DebugIntent = 'pause' | 'resume' | 'stop';
9
+ /**
10
+ * 把工具入参收成人话动作。
11
+ * @param value - 任意入参值。
12
+ * @returns `'pause'` / `'resume'` / `'stop'` 原样;别的值(含 `undefined`、多余空白、大小写不同)给 `null`,由调用方拒。
13
+ */
3
14
  export declare function parseDebugIntent(value: unknown): DebugIntent | null;
15
+ /**
16
+ * 调试约定的有效期(4 小时,毫秒):超过它没动静的约定算过期、当场让人。
17
+ */
4
18
  export declare const DEBUG_STALE_MS: number;
19
+ /**
20
+ * 一份活着的调试约定:相位 + 谁的会话 + 哪个工作区 / 板 / 单元 + 起于何时(`at` 是最后一次动作)。
21
+ */
5
22
  export interface DebugState {
6
23
  readonly phase: DebugPhase;
7
24
  readonly sessionId: string;
8
- readonly workspace: string;
25
+ readonly workspacePath: string;
26
+ readonly title: string;
9
27
  readonly board: string;
10
28
  readonly unit: string;
11
29
  readonly name: string;
12
30
  readonly startedAt: number;
13
31
  readonly at: number;
14
32
  }
33
+ /**
34
+ * 建立约定要交的那几件:会话、工作区、板、单元、名字,以及此刻的时间戳。
35
+ */
15
36
  export interface DebugPact {
16
37
  readonly sessionId: string;
17
- readonly workspace: string;
38
+ readonly workspacePath: string;
39
+ readonly title: string;
18
40
  readonly board: string;
19
41
  readonly unit: string;
20
42
  readonly name: string;
21
43
  readonly now: number;
22
44
  }
45
+ /**
46
+ * 约定被拒的原因码:自己已持有 / 别人持着 / 不是持有者 / 没有约定 / 已暂停 / 已在调试。
47
+ */
23
48
  export type DebugRefusal = 'already-held' | 'held-by-other' | 'not-owner' | 'none' | 'already-paused' | 'already-debugging';
49
+ /**
50
+ * 一次约定动作的结果:成功带新状态,失败带拒绝码。
51
+ */
24
52
  export type DebugMove = {
25
53
  readonly ok: true;
26
54
  readonly state: DebugState;
@@ -28,6 +56,9 @@ export type DebugMove = {
28
56
  readonly ok: false;
29
57
  readonly code: DebugRefusal;
30
58
  };
59
+ /**
60
+ * 调试约定的存取口(外壳持有一份):`live` 取当前有效的约定,`begin` / `pause` / `resume` / `stop` 推相位。
61
+ */
31
62
  export interface DebugStore {
32
63
  live(now: number): DebugState | null;
33
64
  begin(pact: DebugPact): DebugMove;
@@ -36,5 +67,14 @@ export interface DebugStore {
36
67
  stop(sessionId: string, now: number): DebugMove;
37
68
  settle?(): Promise<void>;
38
69
  }
70
+ /**
71
+ * 造一份新的调试约定存储(进程内存,同一时刻只可能有一份有效约定)。
72
+ * @returns 存取口;动作成不成都在返回的 `DebugMove` 里,不抛异常。
73
+ */
39
74
  export declare function createDebugStore(): DebugStore;
75
+ /**
76
+ * 「谁还占着」的一句话,用于别人来抢时说清现况。
77
+ * @param state - 当前有效的那份约定。
78
+ * @returns 形如「会话 x(自 HH:mm:ssZ 起在调试 y)」的中文串。
79
+ */
40
80
  export declare function debugOwnerText(state: DebugState): string;
@@ -1,6 +1,14 @@
1
+ /**
2
+ * 把工具入参收成人话动作。
3
+ * @param value - 任意入参值。
4
+ * @returns `'pause'` / `'resume'` / `'stop'` 原样;别的值(含 `undefined`、多余空白、大小写不同)给 `null`,由调用方拒。
5
+ */
1
6
  export function parseDebugIntent(value) {
2
7
  return value === 'pause' || value === 'resume' || value === 'stop' ? value : null;
3
8
  }
9
+ /**
10
+ * 调试约定的有效期(4 小时,毫秒):超过它没动静的约定算过期、当场让人。
11
+ */
4
12
  export const DEBUG_STALE_MS = 4 * 60 * 60 * 1000;
5
13
  function alive(state, now) {
6
14
  if (state === null)
@@ -13,6 +21,10 @@ function ownerOf(state, sessionId, now) {
13
21
  return 'none';
14
22
  return held.sessionId === sessionId ? held : 'not-owner';
15
23
  }
24
+ /**
25
+ * 造一份新的调试约定存储(进程内存,同一时刻只可能有一份有效约定)。
26
+ * @returns 存取口;动作成不成都在返回的 `DebugMove` 里,不抛异常。
27
+ */
16
28
  export function createDebugStore() {
17
29
  let held = null;
18
30
  const live = (now) => alive(held, now);
@@ -26,7 +38,8 @@ export function createDebugStore() {
26
38
  const state = {
27
39
  phase: 'debugging',
28
40
  sessionId: pact.sessionId,
29
- workspace: pact.workspace,
41
+ workspacePath: pact.workspacePath,
42
+ title: pact.title,
30
43
  board: pact.board,
31
44
  unit: pact.unit,
32
45
  name: pact.name,
@@ -65,6 +78,11 @@ export function createDebugStore() {
65
78
  },
66
79
  };
67
80
  }
81
+ /**
82
+ * 「谁还占着」的一句话,用于别人来抢时说清现况。
83
+ * @param state - 当前有效的那份约定。
84
+ * @returns 形如「会话 x(自 HH:mm:ssZ 起在调试 y)」的中文串。
85
+ */
68
86
  export function debugOwnerText(state) {
69
87
  return `会话 ${state.sessionId}(自 ${new Date(state.startedAt).toISOString().slice(11, 19)}Z 起在调试 ${state.unit})`;
70
88
  }
@@ -1,9 +1,21 @@
1
+ /**
2
+ * 录制交接的三个相位:`armed` 等用户在外站页面上动手,`recording` 正在录,`finished` 录完待取。
3
+ */
1
4
  export type RecordPhase = 'armed' | 'recording' | 'finished';
5
+ /**
6
+ * 录制约定的有效期(15 分钟,毫秒):超过它没动静的约定算过期、当场让人。
7
+ */
2
8
  export declare const RECORD_STALE_MS: number;
9
+ /**
10
+ * 这次录制要找的那一次写:HTTP 方法 + URL 里必须含的一段(不填就是只认方法)。
11
+ */
3
12
  export interface RecordExpect {
4
13
  readonly method: string;
5
14
  readonly urlContains: string;
6
15
  }
16
+ /**
17
+ * 一份活着的录制约定:相位 + 谁的会话 + 哪个工作区 / 单元 + 页面 URL 与标题 + 要找的那一次写 + 落盘文件 + 三个时间戳。
18
+ */
7
19
  export interface RecordState {
8
20
  readonly phase: RecordPhase;
9
21
  readonly sessionId: string;
@@ -20,6 +32,9 @@ export interface RecordState {
20
32
  readonly t1: number | null;
21
33
  readonly at: number;
22
34
  }
35
+ /**
36
+ * 开一次录制要交的那几件:会话、工作区、单元、名字、页面 URL 与标题、动作名、期望、落盘文件,以及此刻时间。
37
+ */
23
38
  export interface RecordPact {
24
39
  readonly sessionId: string;
25
40
  readonly workspace: string;
@@ -32,7 +47,13 @@ export interface RecordPact {
32
47
  readonly captureFile: string;
33
48
  readonly now: number;
34
49
  }
50
+ /**
51
+ * 录制被拒的原因码:自己已持有 / 别人持着 / 不是持有者 / 没有约定 / 已在录 / 还没 arm / 不在录 / 还没录完。
52
+ */
35
53
  export type RecordRefusal = 'already-held' | 'held-by-other' | 'not-owner' | 'none' | 'already-recording' | 'not-armed' | 'not-recording' | 'not-finished';
54
+ /**
55
+ * 一次录制动作的结果:成功带新状态,失败带拒绝码。
56
+ */
36
57
  export type RecordMove = {
37
58
  readonly ok: true;
38
59
  readonly state: RecordState;
@@ -40,8 +61,19 @@ export type RecordMove = {
40
61
  readonly ok: false;
41
62
  readonly code: RecordRefusal;
42
63
  };
64
+ /**
65
+ * 录制约定收得下的三个人话动作:看看进度 / 停手 / 结束并取回。
66
+ */
43
67
  export type RecordIntent = 'peek' | 'halt' | 'stop';
68
+ /**
69
+ * 把工具入参收成人话动作。
70
+ * @param raw - 任意入参值。
71
+ * @returns `'peek'` / `'halt'` / `'stop'` 原样;别的值(含 `undefined`、多余空白)给 `null`,由调用方拒。
72
+ */
44
73
  export declare function parseRecordIntent(raw: unknown): RecordIntent | null;
74
+ /**
75
+ * 录制约定的存取口(外壳持有一份):相位随 `begin → started → finished` 推进,`release` 是收尾时放掉浏览器那一跳。
76
+ */
45
77
  export interface RecordStore {
46
78
  readonly release?: ((state: RecordState) => Promise<{
47
79
  readonly tab: boolean;
@@ -53,5 +85,14 @@ export interface RecordStore {
53
85
  finished(sessionId: string, at: number, now: number): RecordMove;
54
86
  stop(sessionId: string, now: number): RecordMove;
55
87
  }
88
+ /**
89
+ * 造一份新的录制约定存储(进程内存,同一时刻只可能有一份有效约定)。
90
+ * @returns 存取口;动作成不成都在返回的 `RecordMove` 里,不抛异常。
91
+ */
56
92
  export declare function createRecordStore(): RecordStore;
93
+ /**
94
+ * 「谁还占着、在录哪个动作」的一句话,用于别人来抢时说清现况。
95
+ * @param state - 当前有效的那份约定。
96
+ * @returns 形如「会话 x(自 HH:mm:ssZ 起在录 y 的「动作」)」的中文串。
97
+ */
57
98
  export declare function recordOwnerText(state: RecordState): string;
@@ -1,4 +1,12 @@
1
+ /**
2
+ * 录制约定的有效期(15 分钟,毫秒):超过它没动静的约定算过期、当场让人。
3
+ */
1
4
  export const RECORD_STALE_MS = 15 * 60 * 1000;
5
+ /**
6
+ * 把工具入参收成人话动作。
7
+ * @param raw - 任意入参值。
8
+ * @returns `'peek'` / `'halt'` / `'stop'` 原样;别的值(含 `undefined`、多余空白)给 `null`,由调用方拒。
9
+ */
2
10
  export function parseRecordIntent(raw) {
3
11
  return raw === 'peek' || raw === 'halt' || raw === 'stop' ? raw : null;
4
12
  }
@@ -13,6 +21,10 @@ function ownerOf(state, sessionId, now) {
13
21
  return 'none';
14
22
  return held.sessionId === sessionId ? held : 'not-owner';
15
23
  }
24
+ /**
25
+ * 造一份新的录制约定存储(进程内存,同一时刻只可能有一份有效约定)。
26
+ * @returns 存取口;动作成不成都在返回的 `RecordMove` 里,不抛异常。
27
+ */
16
28
  export function createRecordStore() {
17
29
  let held = null;
18
30
  const live = (now) => alive(held, now);
@@ -73,6 +85,11 @@ export function createRecordStore() {
73
85
  },
74
86
  };
75
87
  }
88
+ /**
89
+ * 「谁还占着、在录哪个动作」的一句话,用于别人来抢时说清现况。
90
+ * @param state - 当前有效的那份约定。
91
+ * @returns 形如「会话 x(自 HH:mm:ssZ 起在录 y 的「动作」)」的中文串。
92
+ */
76
93
  export function recordOwnerText(state) {
77
94
  const at = new Date(state.startedAt).toISOString().slice(11, 19);
78
95
  return `会话 ${state.sessionId}(自 ${at}Z 起在录 ${state.unit} 的「${state.action}」)`;
@@ -1,2 +1,12 @@
1
+ /**
2
+ * 找 `root` 里第一个带 `[data-wb-problem]` 标记的元素 —— 表单校验失败时,调用方拿它定位「哪一格错了」。
3
+ * @param root - 要搜的范围(表单容器,或 document)。
4
+ * @returns 第一个出问题的元素;一个标记都没有就给 `null`。
5
+ */
1
6
  export declare function firstProblemOf(root: ParentNode): Element | null;
7
+ /**
8
+ * 把第一个出问题的元素滚进视野、并把焦点交给它里面第一个可聚焦控件(输入框 / 按钮 / 链接等)。
9
+ * @param root - 要搜的范围。
10
+ * @returns 找到并滚过给 `true`;没有问题给 `false`(不滚、不抢焦点);元素不可滚或没有可聚焦控件也不报错,只是少做一步。
11
+ */
2
12
  export declare function revealFirstProblem(root: ParentNode): boolean;
@@ -7,9 +7,19 @@ const FOCUSABLE_SELECTOR = [
7
7
  'a[href]',
8
8
  '[tabindex]:not([tabindex="-1"])',
9
9
  ].join(', ');
10
+ /**
11
+ * 找 `root` 里第一个带 `[data-wb-problem]` 标记的元素 —— 表单校验失败时,调用方拿它定位「哪一格错了」。
12
+ * @param root - 要搜的范围(表单容器,或 document)。
13
+ * @returns 第一个出问题的元素;一个标记都没有就给 `null`。
14
+ */
10
15
  export function firstProblemOf(root) {
11
16
  return root.querySelector(PROBLEM_SELECTOR);
12
17
  }
18
+ /**
19
+ * 把第一个出问题的元素滚进视野、并把焦点交给它里面第一个可聚焦控件(输入框 / 按钮 / 链接等)。
20
+ * @param root - 要搜的范围。
21
+ * @returns 找到并滚过给 `true`;没有问题给 `false`(不滚、不抢焦点);元素不可滚或没有可聚焦控件也不报错,只是少做一步。
22
+ */
13
23
  export function revealFirstProblem(root) {
14
24
  const problem = firstProblemOf(root);
15
25
  if (problem === null)
@@ -1,8 +1,17 @@
1
+ /**
2
+ * 一张面板卡片取数走到哪一步:`idle` 还没取、`loading` 取着、`ready` 拿到了、`error` 失败了。
3
+ */
1
4
  export type PanelCardPhase = 'idle' | 'loading' | 'ready' | 'error';
5
+ /**
6
+ * 一次取数失败:机器码 + 给人看的一句话。
7
+ */
2
8
  export interface PanelCardError {
3
9
  readonly code: string;
4
10
  readonly message: string;
5
11
  }
12
+ /**
13
+ * 一张卡片最近一次取数的读数:哪个单元、哪条路由、什么相位、什么时候、失败原因。
14
+ */
6
15
  export interface PanelCardRead {
7
16
  readonly unit: string;
8
17
  readonly route: string;
@@ -10,12 +19,18 @@ export interface PanelCardRead {
10
19
  readonly at: number;
11
20
  readonly error?: PanelCardError;
12
21
  }
22
+ /**
23
+ * 一张卡片崩了的读数:单元、原因、时间,以及同一原因连着崩了几次(窗口见 `PANEL_STATE_CRASH_WINDOW_MS`)。
24
+ */
13
25
  export interface PanelCardCrash {
14
26
  readonly unit: string;
15
27
  readonly reason: string;
16
28
  readonly at: number;
17
29
  readonly count: number;
18
30
  }
31
+ /**
32
+ * 一个单元此刻的读数:它的卡片、最近一次读成的时间(`okAt`,没成过给 `null`),以及崩了的那一条。
33
+ */
19
34
  export interface PanelUnitReport {
20
35
  readonly unit: string;
21
36
  readonly at: number;
@@ -23,31 +38,61 @@ export interface PanelUnitReport {
23
38
  readonly cards: readonly PanelCardRead[];
24
39
  readonly crash?: PanelCardCrash;
25
40
  }
41
+ /**
42
+ * 一个工作区此刻的全量读数(面板按工作区存):所有单元的读数 + 整块最近动过的时间。
43
+ */
26
44
  export interface PanelWorkspaceReport {
27
45
  readonly workspace: string | null;
28
46
  readonly at: number;
29
47
  readonly units: readonly PanelUnitReport[];
30
48
  }
49
+ /**
50
+ * 客户端往上报的一批卡片读数(`POST` 请求体的形状)。
51
+ */
31
52
  export interface PanelCardsReport {
32
53
  readonly workspace: string;
33
54
  readonly cards: readonly PanelCardRead[];
34
55
  }
56
+ /**
57
+ * 客户端往上报的一次卡片崩溃(`POST` 请求体的形状)。
58
+ */
35
59
  export interface PanelCrashReport {
36
60
  readonly workspace: string;
37
61
  readonly unit: string;
38
62
  readonly reason: string;
39
63
  readonly at: number;
40
64
  }
65
+ /**
66
+ * 面板运行态的留存口(宿主持有一份):收卡片读数与崩溃,按工作区取快照。
67
+ */
41
68
  export interface PanelStateStore {
42
69
  cards(report: PanelCardsReport): void;
43
70
  crash(report: PanelCrashReport): void;
44
71
  snapshot(workspace: string | null): PanelWorkspaceReport;
45
72
  }
73
+ /**
74
+ * 留存的工作区上限(LRU,满 64 个丢最旧的)。
75
+ */
46
76
  export declare const PANEL_STATE_MAX_UNITS = 64;
77
+ /**
78
+ * 每个单元留存的卡片上限(按路由 LRU,满 12 张丢最旧的)。
79
+ */
47
80
  export declare const PANEL_STATE_MAX_CARDS = 12;
81
+ /**
82
+ * 一次上报最多读入的卡片条数(32 条之后的丢掉)。
83
+ */
48
84
  export declare const PANEL_STATE_MAX_REPORTS = 32;
85
+ /**
86
+ * 同一原因的连续崩溃算进同一次计数的窗口(10 分钟,毫秒)。
87
+ */
49
88
  export declare const PANEL_STATE_CRASH_WINDOW_MS = 600000;
89
+ /**
90
+ * 上报文本字段的截断长度(2000 字符;workspace / reason / message 共用)。
91
+ */
50
92
  export declare const PANEL_STATE_MAX_TEXT = 2000;
93
+ /**
94
+ * 上报解析的结果:`ok: true` 带收好的值,`ok: false` 带一句中文原因(直接回给上报方)。
95
+ */
51
96
  export type PanelParse<T> = {
52
97
  readonly ok: true;
53
98
  readonly value: T;
@@ -55,6 +100,21 @@ export type PanelParse<T> = {
55
100
  readonly ok: false;
56
101
  readonly message: string;
57
102
  };
103
+ /**
104
+ * 收一批卡片读数上报。
105
+ * @param payload - `POST` 的请求体。
106
+ * @returns 至少收到一条能认的卡片才 `ok: true`;请求体不是对象、`workspace` 为空、`cards` 不是数组,
107
+ * 或一条都认不出(`unit` / `route` / `phase` / `at` 缺一)时 `ok: false` + 中文原因;认不出的单条静默跳过。
108
+ */
58
109
  export declare function parseCardsReport(payload: unknown): PanelParse<PanelCardsReport>;
110
+ /**
111
+ * 收一次卡片崩溃上报。
112
+ * @param payload - `POST` 的请求体。
113
+ * @returns `workspace` / `unit` / `reason` 都不能空,缺一给 `ok: false` + 中文原因;`at` 缺省或不合法时取当前时间。
114
+ */
59
115
  export declare function parseCrashReport(payload: unknown): PanelParse<PanelCrashReport>;
116
+ /**
117
+ * 造一份面板运行态的留存(进程内存、按工作区分桶,带上面那几条上限的 LRU)。
118
+ * @returns 留存口:`cards` / `crash` 收上报,`snapshot(workspace)` 取全量;没存过的工作区(含 `null`)给一份空的。
119
+ */
60
120
  export declare function createPanelStateStore(): PanelStateStore;
@@ -1,7 +1,22 @@
1
+ /**
2
+ * 留存的工作区上限(LRU,满 64 个丢最旧的)。
3
+ */
1
4
  export const PANEL_STATE_MAX_UNITS = 64;
5
+ /**
6
+ * 每个单元留存的卡片上限(按路由 LRU,满 12 张丢最旧的)。
7
+ */
2
8
  export const PANEL_STATE_MAX_CARDS = 12;
9
+ /**
10
+ * 一次上报最多读入的卡片条数(32 条之后的丢掉)。
11
+ */
3
12
  export const PANEL_STATE_MAX_REPORTS = 32;
13
+ /**
14
+ * 同一原因的连续崩溃算进同一次计数的窗口(10 分钟,毫秒)。
15
+ */
4
16
  export const PANEL_STATE_CRASH_WINDOW_MS = 600000;
17
+ /**
18
+ * 上报文本字段的截断长度(2000 字符;workspace / reason / message 共用)。
19
+ */
5
20
  export const PANEL_STATE_MAX_TEXT = 2000;
6
21
  const PHASES = ['idle', 'loading', 'ready', 'error'];
7
22
  function asRecord(value) {
@@ -30,6 +45,12 @@ function errorOf(raw) {
30
45
  return undefined;
31
46
  return { code: code === '' ? 'unknown' : code, message };
32
47
  }
48
+ /**
49
+ * 收一批卡片读数上报。
50
+ * @param payload - `POST` 的请求体。
51
+ * @returns 至少收到一条能认的卡片才 `ok: true`;请求体不是对象、`workspace` 为空、`cards` 不是数组,
52
+ * 或一条都认不出(`unit` / `route` / `phase` / `at` 缺一)时 `ok: false` + 中文原因;认不出的单条静默跳过。
53
+ */
33
54
  export function parseCardsReport(payload) {
34
55
  const record = asRecord(payload);
35
56
  if (record === undefined)
@@ -58,6 +79,11 @@ export function parseCardsReport(payload) {
58
79
  return { ok: false, message: 'cards 里没有一条能认的(unit / route / phase / at 都要有)' };
59
80
  return { ok: true, value: { workspace, cards } };
60
81
  }
82
+ /**
83
+ * 收一次卡片崩溃上报。
84
+ * @param payload - `POST` 的请求体。
85
+ * @returns `workspace` / `unit` / `reason` 都不能空,缺一给 `ok: false` + 中文原因;`at` 缺省或不合法时取当前时间。
86
+ */
61
87
  export function parseCrashReport(payload) {
62
88
  const record = asRecord(payload);
63
89
  if (record === undefined)
@@ -73,6 +99,10 @@ export function parseCrashReport(payload) {
73
99
  return { ok: false, message: 'reason 不能是空的(没有原因的崩溃没法查)' };
74
100
  return { ok: true, value: { workspace, unit, reason, at: atOf(record['at']) ?? Date.now() } };
75
101
  }
102
+ /**
103
+ * 造一份面板运行态的留存(进程内存、按工作区分桶,带上面那几条上限的 LRU)。
104
+ * @returns 留存口:`cards` / `crash` 收上报,`snapshot(workspace)` 取全量;没存过的工作区(含 `null`)给一份空的。
105
+ */
76
106
  export function createPanelStateStore() {
77
107
  const workspaces = new Map();
78
108
  function trim(entry, max) {
@@ -1,14 +1,53 @@
1
1
  import type * as ReactTypes from 'react';
2
+ /**
3
+ * React 的 `createElement` 换个短名字再导出 —— 这套代码用 `h(...)` 写元素。
4
+ */
2
5
  export declare const h: typeof ReactTypes.createElement;
6
+ /**
7
+ * React 的 `Fragment` 原样再导出 —— 模块从这里拿,就不必自己直接依赖 react。
8
+ */
3
9
  export declare const Fragment: ReactTypes.ExoticComponent<ReactTypes.FragmentProps>;
10
+ /**
11
+ * React 的 `Component` 原样再导出 —— 模块从这里拿,就不必自己直接依赖 react。
12
+ */
4
13
  export declare const Component: typeof ReactTypes.Component;
14
+ /**
15
+ * React 的 `createContext` 原样再导出 —— 模块从这里拿,就不必自己直接依赖 react。
16
+ */
5
17
  export declare const createContext: typeof ReactTypes.createContext;
18
+ /**
19
+ * React 的 `useContext` 原样再导出 —— 模块从这里拿,就不必自己直接依赖 react。
20
+ */
6
21
  export declare const useContext: typeof ReactTypes.useContext;
22
+ /**
23
+ * React 的 `useState` 原样再导出 —— 模块从这里拿,就不必自己直接依赖 react。
24
+ */
7
25
  export declare const useState: typeof ReactTypes.useState;
26
+ /**
27
+ * React 的 `useEffect` 原样再导出 —— 模块从这里拿,就不必自己直接依赖 react。
28
+ */
8
29
  export declare const useEffect: typeof ReactTypes.useEffect;
30
+ /**
31
+ * React 的 `useLayoutEffect` 原样再导出 —— 模块从这里拿,就不必自己直接依赖 react。
32
+ */
9
33
  export declare const useLayoutEffect: typeof ReactTypes.useLayoutEffect;
34
+ /**
35
+ * React 的 `useMemo` 原样再导出 —— 模块从这里拿,就不必自己直接依赖 react。
36
+ */
10
37
  export declare const useMemo: typeof ReactTypes.useMemo;
38
+ /**
39
+ * React 的 `useCallback` 原样再导出 —— 模块从这里拿,就不必自己直接依赖 react。
40
+ */
11
41
  export declare const useCallback: typeof ReactTypes.useCallback;
42
+ /**
43
+ * React 的 `useRef` 原样再导出 —— 模块从这里拿,就不必自己直接依赖 react。
44
+ */
12
45
  export declare const useRef: typeof ReactTypes.useRef;
46
+ /**
47
+ * React 的 `useSyncExternalStore` 原样再导出 —— 模块从这里拿,就不必自己直接依赖 react。
48
+ */
13
49
  export declare const useSyncExternalStore: typeof ReactTypes.useSyncExternalStore;
50
+ /**
51
+ * 从 react 借来的三个类型(`ReactNode` / `CSSProperties` / `ChangeEvent`)—— 模块从这里拿,就不必自己直接依赖 react。
52
+ */
14
53
  export type { ReactNode, CSSProperties, ChangeEvent } from 'react';