@dsh-workbench/shared 0.3.3 → 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.
- package/dist/api/blocker-table.d.ts +13 -0
- package/dist/api/blocker-table.js +13 -0
- package/dist/api/blocker.d.ts +6 -0
- package/dist/api/context-ref.d.ts +31 -0
- package/dist/api/context-ref.js +28 -0
- package/dist/api/dsh-client.d.ts +99 -0
- package/dist/api/dsh.d.ts +55 -3
- package/dist/api/facts.d.ts +42 -0
- package/dist/api/facts.js +33 -0
- package/dist/api/host-write.d.ts +19 -1
- package/dist/api/host-write.js +12 -0
- package/dist/api/long-task.d.ts +36 -0
- package/dist/api/long-task.js +27 -0
- package/dist/api/unit-board.d.ts +25 -0
- package/dist/api/unit-board.js +16 -0
- package/dist/api/unit-declaration.d.ts +36 -0
- package/dist/api/unit-declaration.js +24 -0
- package/dist/api/unit.d.ts +32 -0
- package/dist/api/unit.js +5 -0
- package/dist/api/workbench-client.d.ts +25 -0
- package/dist/api/workbench-client.js +13 -0
- package/dist/api/workbench-contract.d.ts +12 -0
- package/dist/components/Activity.d.ts +33 -0
- package/dist/components/Activity.js +24 -0
- package/dist/components/ApprovalDetail.d.ts +15 -1
- package/dist/components/ApprovalDetail.js +13 -1
- package/dist/components/ApprovalPlan.d.ts +14 -0
- package/dist/components/ApprovalPlan.js +8 -0
- package/dist/components/Card.d.ts +13 -0
- package/dist/components/Card.js +10 -0
- package/dist/components/CardAnchor.d.ts +14 -0
- package/dist/components/CardAnchor.js +11 -0
- package/dist/components/CardBoundary.d.ts +20 -0
- package/dist/components/CardBoundary.js +14 -0
- package/dist/components/CardHead.d.ts +13 -0
- package/dist/components/CardHead.js +10 -0
- package/dist/components/ChoiceGroup.d.ts +24 -0
- package/dist/components/ChoiceGroup.js +12 -0
- package/dist/components/Field.d.ts +10 -0
- package/dist/components/Field.js +7 -0
- package/dist/components/Form.css +6 -0
- package/dist/components/Form.d.ts +20 -0
- package/dist/components/Form.js +58 -0
- package/dist/components/FormActions.d.ts +14 -0
- package/dist/components/FormActions.js +5 -0
- package/dist/components/FormNodes.d.ts +103 -0
- package/dist/components/FormNodes.js +153 -0
- package/dist/components/FormRows.d.ts +20 -0
- package/dist/components/FormRows.js +14 -0
- package/dist/components/FormTypes.d.ts +59 -0
- package/dist/components/FormTypes.js +1 -0
- package/dist/components/Link.d.ts +12 -0
- package/dist/components/Link.js +9 -0
- package/dist/components/LongTaskRow.d.ts +19 -0
- package/dist/components/LongTaskRow.js +13 -0
- package/dist/components/Note.d.ts +11 -0
- package/dist/components/Note.js +8 -0
- package/dist/components/ResourceStates.d.ts +25 -0
- package/dist/components/ResourceStates.js +22 -0
- package/dist/components/Rows.d.ts +17 -0
- package/dist/components/Rows.js +11 -0
- package/dist/components/SaveBar.d.ts +12 -0
- package/dist/components/SaveBar.js +9 -0
- package/dist/components/SelectField.d.ts +26 -0
- package/dist/components/SelectField.js +22 -0
- package/dist/components/SelectFieldNodes.d.ts +24 -0
- package/dist/components/SelectFieldNodes.js +24 -0
- package/dist/components/SettingsSection.d.ts +11 -0
- package/dist/components/SettingsSection.js +8 -0
- package/dist/components/Spinner.d.ts +9 -0
- package/dist/components/Spinner.js +6 -0
- package/dist/components/Stack.d.ts +8 -0
- package/dist/components/Stack.js +5 -0
- package/dist/components/StateBlock.d.ts +13 -0
- package/dist/components/StateBlock.js +10 -0
- package/dist/components/TextField.d.ts +8 -0
- package/dist/components/TextField.js +5 -0
- package/dist/components/board-module.d.ts +30 -0
- package/dist/components/icons.d.ts +38 -0
- package/dist/components/icons.js +35 -0
- package/dist/config/constants.d.ts +45 -0
- package/dist/config/constants.js +45 -0
- package/dist/config/storage.d.ts +4 -0
- package/dist/config/storage.js +4 -0
- package/dist/host/browser-read.d.ts +1 -0
- package/dist/host/browser-read.js +1 -0
- package/dist/host/http.d.ts +3 -0
- package/dist/host/http.js +10 -1
- package/dist/host/tool-approval.d.ts +5 -0
- package/dist/host/tool-approval.js +11 -5
- package/dist/host/unit-face.d.ts +5 -1
- package/dist/host.d.ts +1 -0
- package/dist/host.js +1 -0
- package/dist/i18n/en.d.ts +1 -0
- package/dist/i18n/en.js +22 -8
- package/dist/i18n/index.d.ts +25 -9
- package/dist/i18n/index.js +1 -0
- package/dist/i18n/merge.d.ts +5 -0
- package/dist/i18n/merge.js +2 -0
- package/dist/i18n/zh.d.ts +23 -8
- package/dist/i18n/zh.js +22 -8
- package/dist/index.d.ts +7 -2
- package/dist/index.js +7 -2
- package/dist/lib/blocker-action.d.ts +22 -0
- package/dist/lib/blocker-action.js +13 -0
- package/dist/lib/board-fact.d.ts +27 -0
- package/dist/lib/board-fact.js +18 -0
- package/dist/lib/busy.d.ts +10 -0
- package/dist/lib/busy.js +7 -0
- package/dist/lib/diy-debug.d.ts +42 -2
- package/dist/lib/diy-debug.js +19 -1
- package/dist/lib/diy-record.d.ts +98 -0
- package/dist/lib/diy-record.js +96 -0
- package/dist/lib/form-problem.d.ts +10 -0
- package/dist/lib/form-problem.js +10 -0
- package/dist/lib/panel-state.d.ts +60 -0
- package/dist/lib/panel-state.js +30 -0
- package/dist/lib/react.d.ts +39 -0
- package/dist/lib/react.js +36 -0
- package/dist/lib/text.d.ts +22 -0
- package/dist/lib/text.js +22 -0
- package/dist/lib/ui.d.ts +50 -0
- package/dist/lib/ui.js +41 -0
- package/package.json +1 -1
- package/src/api/blocker-table.ts +13 -0
- package/src/api/blocker.ts +6 -0
- package/src/api/context-ref.ts +31 -0
- package/src/api/dsh-client.ts +99 -0
- package/src/api/dsh.ts +56 -1
- package/src/api/facts.ts +42 -0
- package/src/api/host-write.ts +20 -1
- package/src/api/long-task.ts +36 -0
- package/src/api/unit-board.ts +25 -0
- package/src/api/unit-declaration.ts +36 -0
- package/src/api/unit.ts +32 -0
- package/src/api/workbench-client.ts +25 -0
- package/src/api/workbench-contract.ts +12 -0
- package/src/components/Activity.tsx +33 -0
- package/src/components/ApprovalDetail.tsx +17 -1
- package/src/components/ApprovalPlan.tsx +14 -0
- package/src/components/Card.tsx +13 -0
- package/src/components/CardAnchor.tsx +14 -0
- package/src/components/CardBoundary.tsx +20 -0
- package/src/components/CardHead.tsx +13 -0
- package/src/components/ChoiceGroup.tsx +24 -0
- package/src/components/Field.tsx +10 -0
- package/src/components/Form.css +6 -0
- package/src/components/Form.test.tsx +475 -0
- package/src/components/Form.tsx +78 -0
- package/src/components/FormActions.tsx +14 -0
- package/src/components/FormNodes.tsx +193 -0
- package/src/components/FormRows.tsx +20 -0
- package/src/components/FormTypes.ts +65 -0
- package/src/components/FormWiring.test.tsx +88 -0
- package/src/components/Link.tsx +12 -0
- package/src/components/LongTaskRow.tsx +19 -0
- package/src/components/Note.tsx +11 -0
- package/src/components/ResourceStates.tsx +25 -0
- package/src/components/Rows.tsx +17 -0
- package/src/components/SaveBar.tsx +12 -0
- package/src/components/SelectField.tsx +26 -0
- package/src/components/SelectFieldNodes.tsx +24 -0
- package/src/components/SettingsSection.tsx +11 -0
- package/src/components/Spinner.tsx +9 -0
- package/src/components/Stack.tsx +8 -0
- package/src/components/StateBlock.tsx +13 -0
- package/src/components/TextField.tsx +8 -0
- package/src/components/board-module.ts +30 -0
- package/src/components/icons.tsx +38 -0
- package/src/config/constants.ts +48 -0
- package/src/config/storage.ts +4 -0
- package/src/host/browser-read.ts +1 -0
- package/src/host/http.ts +15 -1
- package/src/host/tool-approval.ts +18 -4
- package/src/host/unit-face.ts +6 -1
- package/src/host.ts +1 -0
- package/src/i18n/en.ts +22 -8
- package/src/i18n/index.ts +3 -0
- package/src/i18n/merge.ts +5 -0
- package/src/i18n/zh.ts +23 -8
- package/src/index.ts +7 -2
- package/src/lib/blocker-action.ts +22 -0
- package/src/lib/board-fact.ts +27 -0
- package/src/lib/busy.ts +10 -0
- package/src/lib/diy-debug.test.ts +2 -1
- package/src/lib/diy-debug.ts +44 -3
- package/src/lib/diy-record.test.ts +171 -0
- package/src/lib/diy-record.ts +185 -0
- package/src/lib/form-problem.ts +10 -0
- package/src/lib/panel-state.ts +60 -0
- package/src/lib/react.ts +39 -0
- package/src/lib/text.ts +22 -0
- package/src/lib/ui.ts +50 -0
|
@@ -1,20 +1,35 @@
|
|
|
1
1
|
import type { UnitEnvNeeds, UnitHostNeeds, UnitManifest } from './unit.js';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* 声明协议当前版本;模块清单的 dsh.workbench.apiVersion 要写这个整数。
|
|
5
|
+
*/
|
|
3
6
|
export const WORKBENCH_API_VERSION = 1;
|
|
4
7
|
|
|
8
|
+
/**
|
|
9
|
+
* 外壳愿意认的协议版本;不在表里的模块当场被拒,不猜语义。
|
|
10
|
+
*/
|
|
5
11
|
export const SUPPORTED_API_VERSIONS: readonly number[] = [WORKBENCH_API_VERSION];
|
|
6
12
|
|
|
13
|
+
/**
|
|
14
|
+
* 清单里那半张卡片声明:文案键加排序位;卡片默认显不显示不在这里(那是运行期面板配置的事)。
|
|
15
|
+
*/
|
|
7
16
|
export interface UnitCardDeclaration {
|
|
8
17
|
readonly titleKey: string;
|
|
9
18
|
readonly order: number;
|
|
10
19
|
}
|
|
11
20
|
|
|
21
|
+
/**
|
|
22
|
+
* 清单里的一条工具声明:进 dsh 工具表的全名、会不会写,以及生成物里的键名。
|
|
23
|
+
*/
|
|
12
24
|
export interface UnitToolDeclaration {
|
|
13
25
|
readonly name: string;
|
|
14
26
|
readonly writes: boolean;
|
|
15
27
|
readonly key?: string;
|
|
16
28
|
}
|
|
17
29
|
|
|
30
|
+
/**
|
|
31
|
+
* 模块清单里 dsh.workbench 那一段的完整形状(协议版本、单元 id、卡片、工具、宿主与环境需要)。
|
|
32
|
+
*/
|
|
18
33
|
export interface UnitDeclaration {
|
|
19
34
|
readonly apiVersion: number;
|
|
20
35
|
readonly unit: string;
|
|
@@ -24,6 +39,9 @@ export interface UnitDeclaration {
|
|
|
24
39
|
readonly env?: UnitEnvNeeds;
|
|
25
40
|
}
|
|
26
41
|
|
|
42
|
+
/**
|
|
43
|
+
* 协议认得的全部键;写了别的键不会被采纳(外壳静默忽略),所以字段名拼错不会有提示。
|
|
44
|
+
*/
|
|
27
45
|
export const DECLARATION_KEYS: readonly string[] = [
|
|
28
46
|
'apiVersion',
|
|
29
47
|
'unit',
|
|
@@ -33,6 +51,9 @@ export const DECLARATION_KEYS: readonly string[] = [
|
|
|
33
51
|
'env',
|
|
34
52
|
];
|
|
35
53
|
|
|
54
|
+
/**
|
|
55
|
+
* 协议要求必写的键;env 不在其中(没有环境需要就不写)。
|
|
56
|
+
*/
|
|
36
57
|
export const DECLARATION_REQUIRED_KEYS: readonly string[] = [
|
|
37
58
|
'apiVersion',
|
|
38
59
|
'unit',
|
|
@@ -70,6 +91,12 @@ function stringArrayProblems(at: string, value: unknown): string[] {
|
|
|
70
91
|
);
|
|
71
92
|
}
|
|
72
93
|
|
|
94
|
+
/**
|
|
95
|
+
* 查清单里 dsh.workbench 那一段的形状,回一串给人看的问题(中文,带字段路径)。
|
|
96
|
+
* @param subject 报错时用的主语,一般是包名。
|
|
97
|
+
* @param raw 清单里那段原始值,可能什么都不是。
|
|
98
|
+
* @returns 空数组表示形状过得去;版本不对就当场返回(后面的字段无从判起)。
|
|
99
|
+
*/
|
|
73
100
|
export function declarationProblemsOf(subject: string, raw: unknown): readonly string[] {
|
|
74
101
|
if (!isRecord(raw)) return [`${subject}: dsh.workbench 不是一个对象 —— ${JSON.stringify(raw)}`];
|
|
75
102
|
|
|
@@ -207,12 +234,21 @@ export function declarationProblemsOf(subject: string, raw: unknown): readonly s
|
|
|
207
234
|
return problems;
|
|
208
235
|
}
|
|
209
236
|
|
|
237
|
+
/**
|
|
238
|
+
* 读一份清单的结果:要么带着规整过的声明与 manifest,要么只带一串问题。
|
|
239
|
+
*/
|
|
210
240
|
export interface DeclarationRead {
|
|
211
241
|
readonly declaration?: UnitDeclaration;
|
|
212
242
|
readonly manifest?: UnitManifest;
|
|
213
243
|
readonly problems: readonly string[];
|
|
214
244
|
}
|
|
215
245
|
|
|
246
|
+
/**
|
|
247
|
+
* 读一份清单:先查形状,过了再把声明规整成 manifest。
|
|
248
|
+
* @param subject 报错时用的主语。
|
|
249
|
+
* @param raw 清单里 dsh.workbench 那段原始值。
|
|
250
|
+
* @returns 有问题时只有 problems;没问题时 declaration 与 manifest 都给,manifest 里的字符串已 trim。
|
|
251
|
+
*/
|
|
216
252
|
export function readDeclaration(subject: string, raw: unknown): DeclarationRead {
|
|
217
253
|
const problems = declarationProblemsOf(subject, raw);
|
|
218
254
|
if (problems.length > 0) return { problems };
|
package/src/api/unit.ts
CHANGED
|
@@ -1,18 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 一张卡片在清单里的静态声明(文案键加排序位);默认显不显示由运行期面板配置定。
|
|
3
|
+
*/
|
|
1
4
|
export interface UnitCard {
|
|
2
5
|
readonly titleKey: string;
|
|
3
6
|
readonly order: number;
|
|
4
7
|
}
|
|
5
8
|
|
|
9
|
+
/**
|
|
10
|
+
* 一条工具在清单里的样子:全名加会不会写;审批按 writes 认领。
|
|
11
|
+
*/
|
|
6
12
|
export interface UnitTool {
|
|
7
13
|
readonly name: string;
|
|
8
14
|
readonly writes: boolean;
|
|
9
15
|
}
|
|
10
16
|
|
|
17
|
+
/**
|
|
18
|
+
* 模块要外壳的哪些服务:inject 缺一个就挂不上,optional 缺了照挂。
|
|
19
|
+
*/
|
|
11
20
|
export interface UnitHostNeeds {
|
|
12
21
|
readonly inject: readonly string[];
|
|
13
22
|
readonly optional?: readonly string[];
|
|
14
23
|
}
|
|
15
24
|
|
|
25
|
+
/**
|
|
26
|
+
* 一个 opencli 插件的来源三选一(git / 本地 / npm);npm 那支的安装源先看 registryEnv 那个环境变量,没设才用 registryDefault。
|
|
27
|
+
*/
|
|
16
28
|
export type PluginSource =
|
|
17
29
|
| { readonly kind: 'git'; readonly url: string }
|
|
18
30
|
| { readonly kind: 'local'; readonly env: string }
|
|
@@ -23,12 +35,18 @@ export type PluginSource =
|
|
|
23
35
|
readonly registryDefault?: string;
|
|
24
36
|
};
|
|
25
37
|
|
|
38
|
+
/**
|
|
39
|
+
* 模块要的一个 opencli 插件:名字、它得提供的命令,以及装它的来源(没写就是不代装)。
|
|
40
|
+
*/
|
|
26
41
|
export interface UnitPluginNeed {
|
|
27
42
|
readonly name: string;
|
|
28
43
|
readonly commands?: readonly string[];
|
|
29
44
|
readonly installSource?: PluginSource;
|
|
30
45
|
}
|
|
31
46
|
|
|
47
|
+
/**
|
|
48
|
+
* 模块要的一个共用库:名字、期望范围与它为什么要这个版本(purpose 会进申报文案)。
|
|
49
|
+
*/
|
|
32
50
|
export interface UnitLibNeed {
|
|
33
51
|
readonly name: string;
|
|
34
52
|
readonly version?: string | undefined;
|
|
@@ -37,17 +55,26 @@ export interface UnitLibNeed {
|
|
|
37
55
|
readonly purpose: string;
|
|
38
56
|
}
|
|
39
57
|
|
|
58
|
+
/**
|
|
59
|
+
* 模块的整份环境需要:一条自检命令,加上插件与共用库两张表。
|
|
60
|
+
*/
|
|
40
61
|
export interface UnitEnvNeeds {
|
|
41
62
|
readonly command?: string;
|
|
42
63
|
readonly plugins?: readonly UnitPluginNeed[];
|
|
43
64
|
readonly libs?: readonly UnitLibNeed[];
|
|
44
65
|
}
|
|
45
66
|
|
|
67
|
+
/**
|
|
68
|
+
* 已装插件与源上最新版那一对,用来判该不该提示升级;latest 缺省表示还没查到。
|
|
69
|
+
*/
|
|
46
70
|
export interface PluginRelease {
|
|
47
71
|
readonly installed: string;
|
|
48
72
|
readonly latest?: string;
|
|
49
73
|
}
|
|
50
74
|
|
|
75
|
+
/**
|
|
76
|
+
* 装配期用的模块清单:单元 id、卡片、工具与宿主 / 环境需要,比声明少一层协议包装。
|
|
77
|
+
*/
|
|
51
78
|
export interface UnitManifest {
|
|
52
79
|
readonly id: string;
|
|
53
80
|
readonly card: UnitCard | null;
|
|
@@ -56,6 +83,11 @@ export interface UnitManifest {
|
|
|
56
83
|
readonly env?: UnitEnvNeeds;
|
|
57
84
|
}
|
|
58
85
|
|
|
86
|
+
/**
|
|
87
|
+
* 判这个模块要不要往外装东西。
|
|
88
|
+
* @param manifest 模块清单。
|
|
89
|
+
* @returns 插件与共用库两张表都空时给 false。
|
|
90
|
+
*/
|
|
59
91
|
export function hasEnvSupply(manifest: UnitManifest): boolean {
|
|
60
92
|
return (manifest.env?.plugins ?? []).length > 0 || (manifest.env?.libs ?? []).length > 0;
|
|
61
93
|
}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { API_PREFIX } from '../config/constants.js';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* 宿主读口 / 写口回的错误:code 给判据分档,message 给人看,helpUrl 有就去点。
|
|
5
|
+
*/
|
|
3
6
|
export interface ApiError {
|
|
4
7
|
readonly code: string;
|
|
5
8
|
readonly message: string;
|
|
@@ -8,14 +11,30 @@ export interface ApiError {
|
|
|
8
11
|
readonly helpUrl?: string;
|
|
9
12
|
}
|
|
10
13
|
|
|
14
|
+
/**
|
|
15
|
+
* 读口的统一响应:成了把载荷摊平在顶层,没成只有一条 ApiError。
|
|
16
|
+
*/
|
|
11
17
|
export type ApiResponse<T> = ({ readonly ok: true } & T) | { readonly ok: false; readonly error: ApiError };
|
|
12
18
|
|
|
19
|
+
/**
|
|
20
|
+
* GET 的查询参数:值为 undefined 的键直接丢掉,不进 URL。
|
|
21
|
+
*/
|
|
13
22
|
export type Query = Record<string, string | number | boolean | undefined>;
|
|
14
23
|
|
|
24
|
+
/**
|
|
25
|
+
* GET 的可选项;目前只有中止信号。
|
|
26
|
+
*/
|
|
15
27
|
export interface ApiGetOptions {
|
|
16
28
|
readonly signal?: AbortSignal | undefined;
|
|
17
29
|
}
|
|
18
30
|
|
|
31
|
+
/**
|
|
32
|
+
* 打一条宿主读口。
|
|
33
|
+
* @param route 路由,相对 API_PREFIX,不带前导斜杠。
|
|
34
|
+
* @param query 查询参数,undefined 的值不序列化。
|
|
35
|
+
* @param options 中止信号等。
|
|
36
|
+
* @returns HTTP 不是 2xx 时给 ok: false(code 为 http);响应体不是 JSON 会当场抛,调用点要接住。
|
|
37
|
+
*/
|
|
19
38
|
export async function apiGet<T>(
|
|
20
39
|
route: string,
|
|
21
40
|
query: Query = {},
|
|
@@ -44,6 +63,12 @@ export async function apiGet<T>(
|
|
|
44
63
|
return (await response.json()) as ApiResponse<T>;
|
|
45
64
|
}
|
|
46
65
|
|
|
66
|
+
/**
|
|
67
|
+
* 打一条宿主写口。
|
|
68
|
+
* @param route 路由,相对 API_PREFIX,不带前导斜杠。
|
|
69
|
+
* @param body 请求体,按 JSON 序列化。
|
|
70
|
+
* @returns HTTP 不是 2xx 时给 ok: false(code 为 http);响应体不是 JSON 会当场抛。
|
|
71
|
+
*/
|
|
47
72
|
export async function apiPost<T>(route: string, body: Record<string, unknown>): Promise<ApiResponse<T>> {
|
|
48
73
|
const response = await fetch(`${API_PREFIX}/${route}`, {
|
|
49
74
|
method: 'POST',
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import type { PluginRelease } from '../api/unit.js';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* 供给动作的那几档(装 / 升 / 卸,模块、共用依赖与插件各一套);写口按它分派。
|
|
5
|
+
*/
|
|
3
6
|
export type ProvisionAction =
|
|
4
7
|
| 'install'
|
|
5
8
|
| 'update'
|
|
@@ -13,6 +16,9 @@ export type ProvisionAction =
|
|
|
13
16
|
| 'uninstall-plugin'
|
|
14
17
|
| 'update-workbench';
|
|
15
18
|
|
|
19
|
+
/**
|
|
20
|
+
* 宿主报的一个 opencli 插件此刻的状态:装没装、缺哪些命令、该不该升,以及怎么升。
|
|
21
|
+
*/
|
|
16
22
|
export interface PluginStatePayload {
|
|
17
23
|
readonly name: string;
|
|
18
24
|
readonly status: 'ok' | 'outdated' | 'missing';
|
|
@@ -22,6 +28,9 @@ export interface PluginStatePayload {
|
|
|
22
28
|
readonly release?: PluginRelease;
|
|
23
29
|
}
|
|
24
30
|
|
|
31
|
+
/**
|
|
32
|
+
* 宿主对「这个单元现在能不能用」的那份读数:状态、缺的命令与插件、修复动作和供给细节。
|
|
33
|
+
*/
|
|
25
34
|
export interface CapabilityPayload {
|
|
26
35
|
readonly unit: string;
|
|
27
36
|
readonly status: 'ok' | 'failed' | 'missing-commands' | 'missing-plugin' | 'unchecked';
|
|
@@ -37,6 +46,9 @@ export interface CapabilityPayload {
|
|
|
37
46
|
readonly libs?: readonly LibStatePayload[];
|
|
38
47
|
}
|
|
39
48
|
|
|
49
|
+
/**
|
|
50
|
+
* 宿主报的一个共用库此刻的状态(装没装、版本对不对)与它为什么要这个版本。
|
|
51
|
+
*/
|
|
40
52
|
export interface LibStatePayload {
|
|
41
53
|
readonly name: string;
|
|
42
54
|
readonly purpose: string;
|
|
@@ -3,11 +3,20 @@ import { Button, Tooltip } from '@deepseek-ai/dsh-client-ui-primitives';
|
|
|
3
3
|
import { h } from '../lib/react.js';
|
|
4
4
|
import './Activity.css';
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* `ActivityBlock` 的契约:块头与块内容。
|
|
8
|
+
*/
|
|
6
9
|
export interface ActivityBlockProps {
|
|
7
10
|
readonly head?: ReactNode | undefined;
|
|
8
11
|
readonly children?: ReactNode | undefined;
|
|
9
12
|
}
|
|
10
13
|
|
|
14
|
+
/**
|
|
15
|
+
* "它做过什么"那一块:上面一行块头、下面一列活动行,卡里放时间线就用它。
|
|
16
|
+
* @param props.head - 块头(如"最近 10 次");不给不画那一行。
|
|
17
|
+
* @param props.children - 块内容,通常是一串 `ActivityLine`。
|
|
18
|
+
* @returns 一个 div。
|
|
19
|
+
*/
|
|
11
20
|
export function ActivityBlock({ head, children }: ActivityBlockProps) {
|
|
12
21
|
return (
|
|
13
22
|
<div className="wb-activityBlock">
|
|
@@ -17,6 +26,9 @@ export function ActivityBlock({ head, children }: ActivityBlockProps) {
|
|
|
17
26
|
);
|
|
18
27
|
}
|
|
19
28
|
|
|
29
|
+
/**
|
|
30
|
+
* `ActivityLine` 的契约:状态点、正文、时间与行尾动作。
|
|
31
|
+
*/
|
|
20
32
|
export interface ActivityLineProps {
|
|
21
33
|
readonly dot?: ReactNode | undefined;
|
|
22
34
|
readonly text: ReactNode;
|
|
@@ -24,6 +36,14 @@ export interface ActivityLineProps {
|
|
|
24
36
|
readonly actions?: ReactNode | undefined;
|
|
25
37
|
}
|
|
26
38
|
|
|
39
|
+
/**
|
|
40
|
+
* 一条活动:状态点 + 正文 + 时间,行尾可挂动作;时间一律用它,别自己拼。
|
|
41
|
+
* @param props.dot - 行首那枚状态点;不给就只留正文。
|
|
42
|
+
* @param props.text - 这一条干了什么。
|
|
43
|
+
* @param props.at - 时间那一格(相对时间文本);不给不画。
|
|
44
|
+
* @param props.actions - 行尾动作,通常是一两颗 `ActivityAction`;不给不画。
|
|
45
|
+
* @returns 一行。
|
|
46
|
+
*/
|
|
27
47
|
export function ActivityLine({ dot, text, at, actions }: ActivityLineProps) {
|
|
28
48
|
return (
|
|
29
49
|
<div className="wb-activityLine">
|
|
@@ -35,6 +55,9 @@ export function ActivityLine({ dot, text, at, actions }: ActivityLineProps) {
|
|
|
35
55
|
);
|
|
36
56
|
}
|
|
37
57
|
|
|
58
|
+
/**
|
|
59
|
+
* `ActivityAction` 的契约:一颗图标钮、一个外链,或一个失败态。
|
|
60
|
+
*/
|
|
38
61
|
export interface ActivityActionProps {
|
|
39
62
|
readonly label: string;
|
|
40
63
|
readonly hint?: string | undefined;
|
|
@@ -44,6 +67,16 @@ export interface ActivityActionProps {
|
|
|
44
67
|
readonly failed?: boolean | undefined;
|
|
45
68
|
}
|
|
46
69
|
|
|
70
|
+
/**
|
|
71
|
+
* 活动行尾那颗动作:给 `href` 就是外链,否则是图标钮并带上 tooltip。
|
|
72
|
+
* @param props.label - 读屏名,也是 `hint` 不给时的 tooltip 文案。
|
|
73
|
+
* @param props.hint - tooltip 上那句更细的说明;不给退化成 `label`。
|
|
74
|
+
* @param props.icon - 那颗图标。
|
|
75
|
+
* @param props.href - 给了就渲染成新窗口外链;与 `onClick` 同时给时以它为准。
|
|
76
|
+
* @param props.onClick - 图标钮的点击回调。
|
|
77
|
+
* @param props.failed - 上一次动作失败了:钮换成危险色(默认 false)。
|
|
78
|
+
* @returns 一个 `<a>` 或一颗 `Button`。
|
|
79
|
+
*/
|
|
47
80
|
export function ActivityAction({ label, hint, icon, href, onClick, failed }: ActivityActionProps) {
|
|
48
81
|
const tip = hint ?? label;
|
|
49
82
|
if (href !== undefined) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Translate } from '../api/dsh-client.js';
|
|
2
2
|
import type { ApprovalInput, UnitClientFace } from '../components/board-module.js';
|
|
3
|
-
import { h } from '../lib/react.js';
|
|
3
|
+
import { Fragment, h, type ReactNode } from '../lib/react.js';
|
|
4
4
|
import { CodeBlock } from '@deepseek-ai/dsh-client-ui-primitives';
|
|
5
5
|
import { CardBoundary } from './CardBoundary.js';
|
|
6
6
|
import './ApprovalDetail.css';
|
|
@@ -18,11 +18,15 @@ interface ChatSnapshot {
|
|
|
18
18
|
|
|
19
19
|
type UseChat = <T>(selector: (snapshot: ChatSnapshot) => T) => T | undefined;
|
|
20
20
|
|
|
21
|
+
/**
|
|
22
|
+
* `ApprovalDetail` 的契约:调用 id、读会话快照的钩子、已装模块与兜底渲染。
|
|
23
|
+
*/
|
|
21
24
|
export interface ApprovalDetailProps {
|
|
22
25
|
readonly callId?: string;
|
|
23
26
|
readonly useChat?: UseChat;
|
|
24
27
|
readonly units?: readonly UnitClientFace[];
|
|
25
28
|
readonly t?: Translate;
|
|
29
|
+
readonly renderShell?: ((input: ApprovalInput, t: Translate) => ReactNode) | undefined;
|
|
26
30
|
}
|
|
27
31
|
|
|
28
32
|
function callOf(snapshot: ChatSnapshot, callId: string | undefined): { name?: string; argsRaw: string } | undefined {
|
|
@@ -44,6 +48,15 @@ function parseArgs(raw: string): Readonly<Record<string, unknown>> {
|
|
|
44
48
|
}
|
|
45
49
|
}
|
|
46
50
|
|
|
51
|
+
/**
|
|
52
|
+
* 审批屏的详情格:按工具名找到认领它的模块交给它渲染,没有模块认领就退回外壳那张表或一段原始命令。
|
|
53
|
+
* @param props.callId - 这次工具调用的 id;不给就直接走兜底(连调用都找不到)。
|
|
54
|
+
* @param props.useChat - 读会话快照的钩子(dsh 注入);不给就当作读不到调用。
|
|
55
|
+
* @param props.units - 已装模块的面,按各自的 `approval.tools` 认领这次调用。
|
|
56
|
+
* @param props.t - 翻译函数;不给就用返回 key 的直通实现。
|
|
57
|
+
* @param props.renderShell - 没有模块认领时外壳自己的渲染(那张表);不给且这次调用没带 `command` 时整格返回 `null`。
|
|
58
|
+
* @returns 认领方的渲染、外壳那张表,或一段可复制的命令。
|
|
59
|
+
*/
|
|
47
60
|
export function ApprovalDetail(props: ApprovalDetailProps) {
|
|
48
61
|
const useChat = props.useChat ?? ((): undefined => undefined);
|
|
49
62
|
const call = useChat((snapshot) => callOf(snapshot, props.callId));
|
|
@@ -63,6 +76,9 @@ export function ApprovalDetail(props: ApprovalDetailProps) {
|
|
|
63
76
|
);
|
|
64
77
|
}
|
|
65
78
|
|
|
79
|
+
const shell = props.renderShell?.(input, t);
|
|
80
|
+
if (shell !== undefined && shell !== null) return <Fragment>{shell}</Fragment>;
|
|
81
|
+
|
|
66
82
|
if (command === '') return null;
|
|
67
83
|
return (
|
|
68
84
|
<CodeBlock
|
|
@@ -2,11 +2,17 @@ import type { ReactNode } from '../lib/react.js';
|
|
|
2
2
|
import { h } from '../lib/react.js';
|
|
3
3
|
import './ApprovalPlan.css';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* 审批详情里的一行:左边标签、右边值。
|
|
7
|
+
*/
|
|
5
8
|
export interface ApprovalPlanRow {
|
|
6
9
|
readonly label: ReactNode;
|
|
7
10
|
readonly value: ReactNode;
|
|
8
11
|
}
|
|
9
12
|
|
|
13
|
+
/**
|
|
14
|
+
* `ApprovalPlan` 的契约:详情行,外加附注与警告两格。
|
|
15
|
+
*/
|
|
10
16
|
export interface ApprovalPlanProps {
|
|
11
17
|
readonly rows: readonly ApprovalPlanRow[];
|
|
12
18
|
readonly hint?: ReactNode | undefined;
|
|
@@ -14,6 +20,14 @@ export interface ApprovalPlanProps {
|
|
|
14
20
|
readonly children?: ReactNode | undefined;
|
|
15
21
|
}
|
|
16
22
|
|
|
23
|
+
/**
|
|
24
|
+
* 审批屏那张"这次要做什么"的表:一行一项,上面可给一句附注、下面可给一句警告。
|
|
25
|
+
* @param props.rows - 详情行,按给的顺序渲染;空数组时只剩附注与警告。
|
|
26
|
+
* @param props.hint - 表上面那句说明;不给不画。
|
|
27
|
+
* @param props.warn - 表下面那句警告;不给不画。
|
|
28
|
+
* @param props.children - 插在表与 `warn` 之间的补充内容。
|
|
29
|
+
* @returns 一个 div。
|
|
30
|
+
*/
|
|
17
31
|
export function ApprovalPlan({ rows, hint, warn, children }: ApprovalPlanProps) {
|
|
18
32
|
return (
|
|
19
33
|
<div className="wb-approvalPlan">
|
package/src/components/Card.tsx
CHANGED
|
@@ -4,6 +4,9 @@ import { h } from '../lib/react.js';
|
|
|
4
4
|
import { CardHead } from './CardHead.js';
|
|
5
5
|
import './Card.css';
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* `Card` 的契约:标题、刷新、卡片体,以及可整块替换的卡头。
|
|
9
|
+
*/
|
|
7
10
|
export interface CardProps {
|
|
8
11
|
readonly t: Translate;
|
|
9
12
|
readonly title: string;
|
|
@@ -14,6 +17,16 @@ export interface CardProps {
|
|
|
14
17
|
readonly children?: ReactNode | undefined;
|
|
15
18
|
}
|
|
16
19
|
|
|
20
|
+
/**
|
|
21
|
+
* 一张卡的壳:卡头(标题 + 刷新钮)+ 卡片体,面板上每一格都是它。
|
|
22
|
+
* @param props.t - 卡头那两句文案(刷新 / 刷新中)的翻译函数。
|
|
23
|
+
* @param props.refreshing - 正在刷新:刷新钮随之禁用并转圈;接 `resource.phase === 'loading'`。
|
|
24
|
+
* @param props.onRefresh - 点刷新钮做什么,异步由调用点自己管。
|
|
25
|
+
* @param props.meta - 标题右侧那一小段补充(条数、时间);不给不占位。
|
|
26
|
+
* @param props.head - 整块替换卡头时给(如自带齿轮的 `CardHead`);不给用默认卡头。
|
|
27
|
+
* @param props.children - 卡片体。
|
|
28
|
+
* @returns 一个 `<section>`。
|
|
29
|
+
*/
|
|
17
30
|
export function Card({ t, title, refreshing, onRefresh, meta, head, children }: CardProps) {
|
|
18
31
|
return (
|
|
19
32
|
<section className="wb-card">
|
|
@@ -2,15 +2,29 @@ import type { ReactNode } from '../lib/react.js';
|
|
|
2
2
|
import { h } from '../lib/react.js';
|
|
3
3
|
import styles from './CardAnchor.module.css';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* 由 unit id 拼出卡片锚点 id,外壳的截图、滚动与页面探针都按它找卡。
|
|
7
|
+
* @param unit - unit id;`null` 或空串(没有 unit 的卡)时返回 undefined,不生成锚点。
|
|
8
|
+
* @returns `wb-card-<unit>`,或 undefined。
|
|
9
|
+
*/
|
|
5
10
|
export function cardIdOf(unit: string | null): string | undefined {
|
|
6
11
|
return unit === null || unit === '' ? undefined : `wb-card-${unit}`;
|
|
7
12
|
}
|
|
8
13
|
|
|
14
|
+
/**
|
|
15
|
+
* `CardAnchor` 的契约:unit id 与它锚住的内容。
|
|
16
|
+
*/
|
|
9
17
|
export interface CardAnchorProps {
|
|
10
18
|
readonly unit: string;
|
|
11
19
|
readonly children?: ReactNode | undefined;
|
|
12
20
|
}
|
|
13
21
|
|
|
22
|
+
/**
|
|
23
|
+
* 外壳自己盖的卡片锚点:套在卡外面给出 `id="wb-card-<unit>"`;模块别自己写,也别删。
|
|
24
|
+
* @param props.unit - 卡的 unit id,用来算锚点 id。
|
|
25
|
+
* @param props.children - 被锚住的卡片本体;锚点自己 `display: contents`,不占布局。
|
|
26
|
+
* @returns 带 id 的占位 div。
|
|
27
|
+
*/
|
|
14
28
|
export function CardAnchor({ unit, children }: CardAnchorProps) {
|
|
15
29
|
return (
|
|
16
30
|
<div id={cardIdOf(unit)} className={styles.anchor}>
|
|
@@ -4,6 +4,9 @@ import type { ReactNode } from '../lib/react.js';
|
|
|
4
4
|
import { Component, h } from '../lib/react.js';
|
|
5
5
|
import { Note } from './Note.js';
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* `CardBoundary` 的契约:被守的 unit、重来键与失败回调。
|
|
9
|
+
*/
|
|
7
10
|
export interface CardBoundaryProps {
|
|
8
11
|
readonly unit: string;
|
|
9
12
|
readonly resetKey: string;
|
|
@@ -12,15 +15,32 @@ export interface CardBoundaryProps {
|
|
|
12
15
|
readonly children?: ReactNode | undefined;
|
|
13
16
|
}
|
|
14
17
|
|
|
18
|
+
/**
|
|
19
|
+
* `CardBoundary` 的状态:这次渲染炸出来的那句话,没炸是 `null`。
|
|
20
|
+
*/
|
|
15
21
|
export interface CardBoundaryState {
|
|
16
22
|
readonly reason: string | null;
|
|
17
23
|
}
|
|
18
24
|
|
|
25
|
+
/**
|
|
26
|
+
* 把抛出来的任何东西收成一句人能看的失败原因,上报与展示都用它。
|
|
27
|
+
* @param error - 抛出来的值:`Error` 取 `message`,字符串原样,其余走 JSON。
|
|
28
|
+
* @returns 一句原因文本;`Error('')` 这种没带 message 的会回空串(调用点别把它当"一定有话")。
|
|
29
|
+
*/
|
|
19
30
|
export function errorReasonOf(error: unknown): string {
|
|
20
31
|
if (error instanceof Error) return error.message;
|
|
21
32
|
return typeof error === 'string' ? error : JSON.stringify(error) ?? String(error);
|
|
22
33
|
}
|
|
23
34
|
|
|
35
|
+
/**
|
|
36
|
+
* 卡片级错误边界:一张卡渲染炸了只画一条报错 + 重试,不让整块面板跟着塌。
|
|
37
|
+
* @param props.unit - 出事的 unit id,写进报错文案并作为上报标识。
|
|
38
|
+
* @param props.resetKey - 重来键:它一变(如切了工作区)就自动清掉报错,把卡片重新渲染一遍。
|
|
39
|
+
* @param props.t - 报错那句与重试钮文案的翻译函数。
|
|
40
|
+
* @param props.onFailure - 失败时把原因报给宿主(面板状态要用);不给就只打一条 console。
|
|
41
|
+
* @param props.children - 正常时要渲染的卡片内容。
|
|
42
|
+
* @returns 正常时是 `children`,炸过且还没重来之前是一条报错。
|
|
43
|
+
*/
|
|
24
44
|
export class CardBoundary extends Component<CardBoundaryProps, CardBoundaryState> {
|
|
25
45
|
override state: CardBoundaryState = { reason: null };
|
|
26
46
|
|
|
@@ -10,6 +10,9 @@ import {
|
|
|
10
10
|
import { h } from '../lib/react.js';
|
|
11
11
|
import './CardHead.css';
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* `CardHead` 的契约:标题、补充、刷新,外加齿轮与平台跳转两格。
|
|
15
|
+
*/
|
|
13
16
|
export interface CardHeadProps {
|
|
14
17
|
readonly t: Translate;
|
|
15
18
|
readonly title: string;
|
|
@@ -24,6 +27,16 @@ export interface CardHeadProps {
|
|
|
24
27
|
readonly platformTitle?: string | undefined;
|
|
25
28
|
}
|
|
26
29
|
|
|
30
|
+
/**
|
|
31
|
+
* 卡头:标题 + 补充 + 刷新钮(`Card` 内部就是它),要自己拼卡头或加齿轮 / 平台跳转时直接用。
|
|
32
|
+
* @param props.t - 刷新那两句文案(刷新 / 刷新中)的翻译函数。
|
|
33
|
+
* @param props.title - 卡标题;`props.meta` 是它右侧那一小段补充,不给不占位。
|
|
34
|
+
* @param props.refreshing - 正在刷新:刷新钮禁用并转圈。
|
|
35
|
+
* @param props.onRefresh - 点刷新钮做什么。
|
|
36
|
+
* @param props.gear - 齿轮钮的读屏名;`gearOpen` 控制它高亮、`onToggleGear` 是点击回调,三者一起给才画。
|
|
37
|
+
* @param props.platformHref - 整张卡对应系统的地址:给了就画那颗 ↗(新窗口),tooltip 用 `platformTitle`,缺了退化用 `platform`。
|
|
38
|
+
* @returns 一个 `<header>`。
|
|
39
|
+
*/
|
|
27
40
|
export function CardHead({
|
|
28
41
|
t,
|
|
29
42
|
title,
|
|
@@ -4,6 +4,9 @@ import { IconCheckOutlineRegular } from '@deepseek-ai/dsh-client-ui-primitives';
|
|
|
4
4
|
import { Spinner } from './Spinner.js';
|
|
5
5
|
import './ChoiceGroup.css';
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* 一个候选项:值、人看的标签,可带一行说明。
|
|
9
|
+
*/
|
|
7
10
|
export interface ChoiceGroupOption {
|
|
8
11
|
readonly value: string;
|
|
9
12
|
readonly label: ReactNode;
|
|
@@ -21,18 +24,27 @@ interface ChoiceGroupCommon {
|
|
|
21
24
|
readonly emptyText?: ReactNode | undefined;
|
|
22
25
|
}
|
|
23
26
|
|
|
27
|
+
/**
|
|
28
|
+
* 单选那一支的契约:`value` + `onChange(next)`;`multi` 不给或给 false。
|
|
29
|
+
*/
|
|
24
30
|
export interface ChoiceGroupSingleProps extends ChoiceGroupCommon {
|
|
25
31
|
readonly multi?: false | undefined;
|
|
26
32
|
readonly value: string;
|
|
27
33
|
readonly onChange: (next: string) => void;
|
|
28
34
|
}
|
|
29
35
|
|
|
36
|
+
/**
|
|
37
|
+
* 多选那一支的契约:`multi: true` + `values` + `onChange(next[])`。
|
|
38
|
+
*/
|
|
30
39
|
export interface ChoiceGroupMultiProps extends ChoiceGroupCommon {
|
|
31
40
|
readonly multi: true;
|
|
32
41
|
readonly values: readonly string[];
|
|
33
42
|
readonly onChange: (next: readonly string[]) => void;
|
|
34
43
|
}
|
|
35
44
|
|
|
45
|
+
/**
|
|
46
|
+
* `ChoiceGroup` 的契约:单选与多选两支的联合。
|
|
47
|
+
*/
|
|
36
48
|
export type ChoiceGroupProps = ChoiceGroupSingleProps | ChoiceGroupMultiProps;
|
|
37
49
|
|
|
38
50
|
interface ChoiceRowState {
|
|
@@ -110,6 +122,18 @@ function ChoiceMenu(input: {
|
|
|
110
122
|
);
|
|
111
123
|
}
|
|
112
124
|
|
|
125
|
+
/**
|
|
126
|
+
* 一组单选或多选:候选少、要一眼看全时用它;候选多或要搜索就用 `SelectField`。
|
|
127
|
+
* @param props.multi - true 走多选那支(`values` / `onChange(string[])`);默认单选(`value` / `onChange(string)`)。
|
|
128
|
+
* @param props.label - 只给读屏的组名(`aria-label`)。
|
|
129
|
+
* @param props.name - 这一组 `input` 的共用 name。
|
|
130
|
+
* @param props.options - 候选项,按给的顺序排;空数组时画 `emptyText`(没给就什么都不画)。
|
|
131
|
+
* @param props.disabled - 禁掉整组(默认 false),不是单颗。
|
|
132
|
+
* @param props.variant - `boxed`(默认,带边框的选项格)或 `ghost`(无边框,跟着父容器走)。
|
|
133
|
+
* @param props.loading - 正在读候选:整组换成转圈,文案取 `loadingText`(不给是 `…`);默认 false。
|
|
134
|
+
* @param props.emptyText - 读到了但一个候选都没有时那句话;不给不画。
|
|
135
|
+
* @returns 一组 `radio` / `checkbox` 选项。
|
|
136
|
+
*/
|
|
113
137
|
export function ChoiceGroup(props: ChoiceGroupProps) {
|
|
114
138
|
const common = {
|
|
115
139
|
label: props.label,
|
package/src/components/Field.tsx
CHANGED
|
@@ -2,12 +2,22 @@ import type { ReactNode } from '../lib/react.js';
|
|
|
2
2
|
import { h } from '../lib/react.js';
|
|
3
3
|
import './Field.css';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* `Field` 的契约:一行"标签 + 控件 + 说明"的排布。
|
|
7
|
+
*/
|
|
5
8
|
export interface FieldProps {
|
|
6
9
|
readonly label: ReactNode;
|
|
7
10
|
readonly hint?: ReactNode | undefined;
|
|
8
11
|
readonly children?: ReactNode | undefined;
|
|
9
12
|
}
|
|
10
13
|
|
|
14
|
+
/**
|
|
15
|
+
* 标签 + 控件的排布:没进 `FormRow` 时用它兜住一个字段的标签与说明。
|
|
16
|
+
* @param props.label - 左侧标签,必给。
|
|
17
|
+
* @param props.hint - 控件下面那行说明;不给不画。
|
|
18
|
+
* @param props.children - 控件本体,落在标签与说明之间。
|
|
19
|
+
* @returns 一个 `<label>`,点标签会聚焦里面的控件。
|
|
20
|
+
*/
|
|
11
21
|
export function Field({ label, hint, children }: FieldProps) {
|
|
12
22
|
return (
|
|
13
23
|
<label className="wb-field">
|