@dsh-workbench/core 0.3.0 → 0.3.1
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/README.md +6 -2
- package/bin/dsh-workbench +17 -15
- package/client.js +359 -64
- package/dist/client/client.body.js +359 -64
- package/dist/client/index.js +359 -64
- package/dist/host/index.js +443 -385
- package/dist/types/app/client.d.ts +3 -0
- package/dist/types/app/layouts/rightbar/BoardGrid.d.ts +23 -0
- package/dist/types/app/layouts/rightbar/board-columns.d.ts +17 -4
- package/dist/types/app/layouts/rightbar/rightbar-width.d.ts +16 -0
- package/dist/types/app/layouts/rightbar/rightbar-width.test.d.ts +1 -0
- package/dist/types/app/layouts/rightbar/use-board-split.d.ts +8 -0
- package/dist/types/modules/panels/model/diy-report.d.ts +13 -2
- package/dist/types/shared/api/host/diy-workshop.d.ts +13 -0
- package/dist/types/shared/api/host/runtime-seed.d.ts +0 -2
- package/docs/HANDOFF.md +11 -1
- package/docs/OPERATIONS.md +43 -0
- package/package.json +2 -2
- package/scripts/seed-workshop.sh +461 -13
- package/skills/workbench-module-diy/BUILD.md +6 -1
|
@@ -181,6 +181,7 @@ export declare const kit: {
|
|
|
181
181
|
STORAGE_KEY_PROJECT: "dsh-workbench.project";
|
|
182
182
|
STORAGE_KEY_RIGHTBAR: "dsh-workbench.rightbar.expanded";
|
|
183
183
|
STORAGE_KEY_RIGHTBAR_COLUMN: "dsh-workbench.rightbar.column";
|
|
184
|
+
STORAGE_KEY_RIGHTBAR_WIDTH: "dsh-workbench.rightbar.width";
|
|
184
185
|
RIGHTBAR_FULLSCREEN_WIDTH: 768;
|
|
185
186
|
LOCALE_NS: "workbench";
|
|
186
187
|
LOCALES: readonly ["zh", "en"];
|
|
@@ -1216,6 +1217,7 @@ export declare const kit: {
|
|
|
1216
1217
|
STORAGE_KEY_PROJECT: "dsh-workbench.project";
|
|
1217
1218
|
STORAGE_KEY_RIGHTBAR: "dsh-workbench.rightbar.expanded";
|
|
1218
1219
|
STORAGE_KEY_RIGHTBAR_COLUMN: "dsh-workbench.rightbar.column";
|
|
1220
|
+
STORAGE_KEY_RIGHTBAR_WIDTH: "dsh-workbench.rightbar.width";
|
|
1219
1221
|
RIGHTBAR_FULLSCREEN_WIDTH: 768;
|
|
1220
1222
|
LOCALE_NS: "workbench";
|
|
1221
1223
|
LOCALES: readonly ["zh", "en"];
|
|
@@ -2246,6 +2248,7 @@ export declare const kit: {
|
|
|
2246
2248
|
STORAGE_KEY_PROJECT: "dsh-workbench.project";
|
|
2247
2249
|
STORAGE_KEY_RIGHTBAR: "dsh-workbench.rightbar.expanded";
|
|
2248
2250
|
STORAGE_KEY_RIGHTBAR_COLUMN: "dsh-workbench.rightbar.column";
|
|
2251
|
+
STORAGE_KEY_RIGHTBAR_WIDTH: "dsh-workbench.rightbar.width";
|
|
2249
2252
|
RIGHTBAR_FULLSCREEN_WIDTH: 768;
|
|
2250
2253
|
LOCALE_NS: "workbench";
|
|
2251
2254
|
LOCALES: readonly ["zh", "en"];
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { BoardModule, BoardModuleProps, ModuleSummary, PanelStep, SuiteWorld, Translate } from '@dsh-workbench/shared';
|
|
2
|
+
import type { BoardPlan } from './board-plan';
|
|
3
|
+
export declare function workspacePathOf(world: SuiteWorld): string;
|
|
4
|
+
export declare function ModuleHost({ module, step, panelToken, onPanelRefresh, onSummary, ...rest }: {
|
|
5
|
+
module: BoardModule;
|
|
6
|
+
step?: string;
|
|
7
|
+
panelToken: number;
|
|
8
|
+
onPanelRefresh: () => void;
|
|
9
|
+
} & Omit<BoardModuleProps, 'refreshToken' | 'onRefresh' | 'onSummary'> & {
|
|
10
|
+
onSummary: (id: string, summary: ModuleSummary) => void;
|
|
11
|
+
}): JSX.Element;
|
|
12
|
+
export declare function BoardGrid({ entries, panelWidth, world, panelToken, onPanelRefresh, onNavigate, onOpenMarket, onSummary, onCardFailure, t, }: {
|
|
13
|
+
entries: BoardPlan['modules'];
|
|
14
|
+
panelWidth: number;
|
|
15
|
+
world: SuiteWorld;
|
|
16
|
+
panelToken: number;
|
|
17
|
+
onPanelRefresh: () => void;
|
|
18
|
+
onNavigate: (step: PanelStep) => void;
|
|
19
|
+
onOpenMarket: () => void;
|
|
20
|
+
onSummary: (id: string, summary: ModuleSummary) => void;
|
|
21
|
+
onCardFailure: (unit: string, reason: string) => void;
|
|
22
|
+
t: Translate;
|
|
23
|
+
}): JSX.Element | null;
|
|
@@ -2,7 +2,20 @@ export declare const BOARD_COLUMN_MIN_WIDTH = 332;
|
|
|
2
2
|
export declare const BOARD_COLUMN_GAP = 12;
|
|
3
3
|
export declare const BOARD_PANEL_PADDING = 12;
|
|
4
4
|
export declare const BOARD_COLUMNS_AT: number;
|
|
5
|
-
export declare
|
|
6
|
-
export
|
|
7
|
-
export declare
|
|
8
|
-
export declare
|
|
5
|
+
export declare const BOARD_SPLIT_SEARCH_LIMIT = 100000;
|
|
6
|
+
export declare const BOARD_SPLIT_MIN_GAIN = 32;
|
|
7
|
+
export declare const BOARD_SPLIT_QUIET_MS = 600;
|
|
8
|
+
export declare const BOARD_SPLIT_DEADLINE_MS = 3000;
|
|
9
|
+
export declare function boardColumnCount(panelWidth: number, itemCount: number): number;
|
|
10
|
+
export declare function roundRobinIndexes(count: number, columns: number): readonly number[];
|
|
11
|
+
export declare function roundRobinColumns<T>(items: readonly T[], columns: number): readonly (readonly T[])[];
|
|
12
|
+
export declare function boardImproves(current: readonly number[], candidate: readonly number[], heights: readonly number[], columns: number): boolean;
|
|
13
|
+
export declare function boardColumnIndexes(heights: readonly number[], columns: number): readonly number[];
|
|
14
|
+
export declare function boardAssignment(heights: readonly number[], columns: number): readonly number[];
|
|
15
|
+
export declare function boardColumnsByHeight<T>(items: readonly T[], heights: readonly number[], columns: number): readonly (readonly T[])[];
|
|
16
|
+
export interface BoardSlot {
|
|
17
|
+
readonly index: number;
|
|
18
|
+
readonly breakBefore: boolean;
|
|
19
|
+
readonly trailing: boolean;
|
|
20
|
+
}
|
|
21
|
+
export declare function boardLayout(assignment: readonly number[], columns: number): readonly BoardSlot[];
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { DshLayoutPanels } from '@dsh-workbench/shared';
|
|
2
|
+
import { writeText } from '@dsh-workbench/shared';
|
|
3
|
+
export declare const RIGHTBAR_DEFAULT_WIDTH = 420;
|
|
4
|
+
export declare const RIGHTBAR_WIDTH_MAX = 4000;
|
|
5
|
+
export declare function parseRightbarWidth(raw: string | null): number | null;
|
|
6
|
+
export declare function readRightbarWidth(): number | null;
|
|
7
|
+
export declare function writeRightbarWidth(px: number, write?: typeof writeText): void;
|
|
8
|
+
export interface RightbarWidthMemory {
|
|
9
|
+
seed(px: number): void;
|
|
10
|
+
dispose(): void;
|
|
11
|
+
}
|
|
12
|
+
export declare function createRightbarWidthMemory(panels: DshLayoutPanels | undefined, write?: (px: number) => void): RightbarWidthMemory;
|
|
13
|
+
export declare function ensureRightbarWidthMemory(panels: DshLayoutPanels | undefined, write?: (px: number) => void): RightbarWidthMemory;
|
|
14
|
+
export declare function releaseRightbarWidthMemory(panels: DshLayoutPanels | undefined): void;
|
|
15
|
+
export declare function restoreRightbarWidth(panels: DshLayoutPanels | undefined, remembered?: number | null): void;
|
|
16
|
+
export declare function seedRightbarWidth(panels: DshLayoutPanels | undefined, remembered?: number | null): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type BoardSlot } from './board-columns';
|
|
2
|
+
export interface BoardSplit {
|
|
3
|
+
readonly root: {
|
|
4
|
+
current: HTMLDivElement | null;
|
|
5
|
+
};
|
|
6
|
+
readonly slots: readonly BoardSlot[] | null;
|
|
7
|
+
}
|
|
8
|
+
export declare function useBoardSplit(keys: readonly string[], columns: number): BoardSplit;
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import type { PanelUnitReport } from '@dsh-workbench/shared';
|
|
2
|
-
import type
|
|
2
|
+
import { type WorkshopModule, type WorkshopSync, type WorkshopToolchain } from '../../../shared/api/host/diy-workshop';
|
|
3
|
+
export declare const SYNC_STALE_MINUTES = 15;
|
|
4
|
+
export declare const SYNC_STALE_MS: number;
|
|
5
|
+
export declare function syncNotice(input: {
|
|
6
|
+
readonly sync: WorkshopSync | undefined;
|
|
7
|
+
readonly shellVersion: string | undefined;
|
|
8
|
+
readonly toolchain: WorkshopToolchain | undefined;
|
|
9
|
+
readonly now?: number;
|
|
10
|
+
readonly windowMs?: number;
|
|
11
|
+
}): string | undefined;
|
|
3
12
|
export interface SuiteHealth {
|
|
4
13
|
readonly state: 'ok' | 'failed' | 'absent';
|
|
5
14
|
readonly reason?: string;
|
|
@@ -59,5 +68,7 @@ export declare function statusOf(options: {
|
|
|
59
68
|
readonly open: boolean;
|
|
60
69
|
readonly health: SuiteHealth;
|
|
61
70
|
}): ModuleStatus;
|
|
62
|
-
export declare function renderStatus(packagesDir: string, lines: readonly ModuleStatus[]
|
|
71
|
+
export declare function renderStatus(packagesDir: string, lines: readonly ModuleStatus[], options?: {
|
|
72
|
+
readonly shellVersion?: string;
|
|
73
|
+
}): string;
|
|
63
74
|
export declare function renderList(packagesDir: string, modules: readonly WorkshopModule[]): string;
|
|
@@ -10,3 +10,16 @@ export declare function workshopPackagesDir(ctx: DshHostContext): string | null;
|
|
|
10
10
|
export declare function insideWorkshop(root: string, target: string): boolean;
|
|
11
11
|
export declare function workshopModules(packagesDir: string, installed?: readonly string[]): readonly WorkshopModule[];
|
|
12
12
|
export declare function inWorkshopSession(ctx: DshHostContext, workspace: string | null): boolean;
|
|
13
|
+
export interface WorkshopSync {
|
|
14
|
+
readonly state: 'ok' | 'syncing' | 'failed';
|
|
15
|
+
readonly version: string;
|
|
16
|
+
readonly at: string;
|
|
17
|
+
readonly reason?: string;
|
|
18
|
+
}
|
|
19
|
+
export declare function workshopSyncOf(workshopRoot: string): WorkshopSync | undefined;
|
|
20
|
+
export interface WorkshopToolchain {
|
|
21
|
+
readonly core: string;
|
|
22
|
+
readonly moduleTools: string;
|
|
23
|
+
readonly shared: string;
|
|
24
|
+
}
|
|
25
|
+
export declare function workshopToolchainOf(workshopRoot: string): WorkshopToolchain | undefined;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { spawn } from 'node:child_process';
|
|
2
2
|
import type { DshHostContext } from '@dsh-workbench/shared';
|
|
3
|
-
export declare const WORKSHOP_SKILLS_DIR = "workbench-module-diy";
|
|
4
3
|
export type SeedLog = (message: string) => void;
|
|
5
4
|
export interface RuntimeSeedPaths {
|
|
6
5
|
readonly root: string;
|
|
@@ -12,7 +11,6 @@ export interface RuntimeSeedPaths {
|
|
|
12
11
|
readonly workshop: string;
|
|
13
12
|
readonly workshopPackages: string;
|
|
14
13
|
readonly workshopManifest: string;
|
|
15
|
-
readonly skillsLink: string;
|
|
16
14
|
}
|
|
17
15
|
export interface RuntimeSeedOptions {
|
|
18
16
|
readonly root: string;
|
package/docs/HANDOFF.md
CHANGED
|
@@ -37,7 +37,11 @@
|
|
|
37
37
|
DIY 工坊骨架、可写根)由**外壳自己**补齐 —— 不用跑 `setup`,也不用起第二个实例。
|
|
38
38
|
|
|
39
39
|
差别(先跟对方说清):**会话 / 存储不分家**(接着用他原来那份)、**没有独立端口与进程**、
|
|
40
|
-
**改外壳源码不热重载**、DIY
|
|
40
|
+
**改外壳源码不热重载**、DIY 工坊依赖是首次启动在后台装的。工坊的工具链(那三个
|
|
41
|
+
`@dsh-workbench/*`)此后**每次启动**都会与**正在跑的那份外壳**比一次(基准经 `DSH_WB_SHELL_ROOT`
|
|
42
|
+
显式传入 —— 宿主给加载中那份、启动器给 profile 里那份),不同代就在后台增量同步到同代 ——
|
|
43
|
+
升级外壳不用手动删工坊,**下一次启动**就对上了;同步不上时 `workbench_diy_status` 会说清
|
|
44
|
+
(差在哪、为什么、怎么修),日志在 `$DSH_HOME/workbench/seed.log`。
|
|
41
45
|
|
|
42
46
|
## 三、B:两步装(独立 profile,占 :3081)
|
|
43
47
|
|
|
@@ -99,6 +103,12 @@ Settings → 插件里把 `@dsh-workbench/core` 关掉后,工作台会**退化
|
|
|
99
103
|
就一个字节不写)。为什么单列这一步:`dsh plugin add` 装完的登记**跳过已存在的依赖**,
|
|
100
104
|
所以重跑 setup(包已在清单里)时它不会补 bundle —— 那一档是静默的(起得来、侧边栏
|
|
101
105
|
没入口),现在启动器拿"选中"当硬门禁,这一步就是它给的修复命令。
|
|
106
|
+
6. `scripts/seed-workshop.sh`(`seed-profile.sh:155-160` 调它)—— 建 / 补齐 **DIY 工坊**:
|
|
107
|
+
骨架缺才建、依赖缺才装、写 `dsh-wb-module` 入口。**这一步不做代际对齐**:代际比对的基准是
|
|
108
|
+
"正在跑的那份外壳"(`DSH_WB_SHELL_ROOT`),而 `setup` 这趟 profile 里那份还没装 / 还是旧的,
|
|
109
|
+
所以它**不设基准、这一轮不比对**。**重跑 `setup` 只建骨架 / 装依赖;工坊工具链对上正在跑的那一代
|
|
110
|
+
发生在下一次启动**(启动器按 profile 里那份、宿主按加载中那份,同一个基准)—— 与 README 的
|
|
111
|
+
"升级要重启一次"一致,不必手动删工坊。
|
|
102
112
|
|
|
103
113
|
**设置不在这一步继承**(这里以前快照 web 的 patch、并继承被它点名的依赖):新机器上
|
|
104
114
|
`setup` 完的工作台**没有模型供应商**,第一次打开去 设置 → 「配置同步」拉一次即可 ——
|
package/docs/OPERATIONS.md
CHANGED
|
@@ -49,6 +49,8 @@
|
|
|
49
49
|
|
|
50
50
|
差别:**会话 / 存储不隔离**(接着用你原来那份)、**没有独立端口与进程**、
|
|
51
51
|
**改外壳源码不热重载**、DIY 工坊依赖是首次启动在后台装的(几百 MB,失败只落日志)。
|
|
52
|
+
此后**每次启动**都会比对工坊里那三个 `@dsh-workbench/*` 与**正在跑的那份外壳**的版本,不同代就在后台**增量同步**
|
|
53
|
+
(见下面「工坊工具链怎么跟着外壳走」)。
|
|
52
54
|
|
|
53
55
|
撤销:Plugins 页卸载 `@dsh-workbench/core`(配置与数据不清);`~/.dsh/workbench/**` 想清就手删。
|
|
54
56
|
|
|
@@ -158,6 +160,47 @@ WORKBENCH_PORT=3091 pnpm run dev # 换端口(监听与实例同一个端口
|
|
|
158
160
|
现在的脚本追加前会先把那行单独的 `[]` 让位(`selfcheck` 有判据钉着)。如果你手上那份 profile 是旧脚本建出来的,
|
|
159
161
|
手工把 `cordis.patch.yml` 里**单独一行**的 `[]` 删掉再起即可(其余内容不用动)。
|
|
160
162
|
|
|
163
|
+
### 工坊工具链怎么跟着外壳走
|
|
164
|
+
|
|
165
|
+
工坊(`$DSH_HOME/workbench/diy`)里那三个 `@dsh-workbench/*` 必须与**当前跑着的外壳**同代 ——
|
|
166
|
+
不同代就是"指引是新的、判据与模板是旧的",报错会指着你的声明而不是指着版本。
|
|
167
|
+
|
|
168
|
+
- **判据**:工坊 `node_modules/@dsh-workbench/{core,module-tools,shared}/package.json` 里**实装**的
|
|
169
|
+
`version`,与**基准版本**(见下条)**全等**。不看 `package.json` 里写的范围,也不信 `pnpm` 的退出码 ——
|
|
170
|
+
装完会按盘上那份复核实装版本,只有真的同代才写 `ok`。
|
|
171
|
+
- **基准 = 正在跑的那份外壳**,由调用者经 `DSH_WB_SHELL_ROOT` 显式传进来:
|
|
172
|
+
宿主自举给**加载中的那份**(`packageRootOf(import.meta.url)`),启动器给 **profile 里那份**
|
|
173
|
+
`node_modules/@dsh-workbench/core`(只在它真能读出 `package.json` 时才给)。**谁都没传 → 这一轮不比对**
|
|
174
|
+
(不读工坊实装版本、不起同步、不写 `.sync.json`、不动工坊一个字节)。
|
|
175
|
+
⚠️ **跑脚本的那份副本不算基准**:安装态下启动器与宿主是**两份物理副本**,谁后跑谁说了算会来回漂
|
|
176
|
+
—— 现在启动器那份落后**不会再**把工坊往回拽(实测那一次:启动器 0.3.0 / profile 0.3.1 / 工坊已跟到
|
|
177
|
+
0.3.1,旧口径把工坊降级成 0.3.0,见 [ADR-0056](../../../docs/adr/0056-workshop-toolchain-follows-the-shell.md) 补记)。
|
|
178
|
+
- **触发**:每次启动都会比一次(`bin/dsh-workbench` 与宿主自举走的那条 `entry`)。
|
|
179
|
+
无参那一趟(建骨架 / 重跑 `setup`)**只有带基准时才比** —— 启动器兜底建骨架时带,`setup` 那趟
|
|
180
|
+
**不设基准 → 空转**。所以**重跑 `setup` 不做代际对齐**,对齐发生在**下一次启动**工作台时
|
|
181
|
+
(与 README 的"升级要重启一次"一致)。比对是**便宜**的:只读四份 `package.json` 的版本。
|
|
182
|
+
- **不一致 → 后台自愈**:起一个 `nohup` 的 `seed-workshop.sh sync`,把工坊根的 `devDependency`
|
|
183
|
+
范围与 `pnpm.overrides` 都对齐到基准那一代,再增量 `pnpm install`,跑完复核实装版本。
|
|
184
|
+
启动路径不等它。
|
|
185
|
+
- **状态文件**:`$DSH_HOME/workbench/diy/.sync.json`(`state` / `version` / `at` / `reason`),四种态:
|
|
186
|
+
- `ok`:复核过、同代。⚠️ **`ok` 可能是旧版本的记录** —— 判据**永远是实装版本**,
|
|
187
|
+
`.sync.json` 只用于退避与说人话,别拿它当"装好了"的证据;
|
|
188
|
+
- `syncing`:正在后台同步;超过 15 分钟还停在这,`workbench_diy_status` 会说
|
|
189
|
+
「⚠️ 工坊工具链上一次同步没走完(这条停在 <at>,超过 15 分钟了)」;
|
|
190
|
+
- `failed`:**这一轮没修好**(原因在 `reason` 里),`workbench_diy_status` 会直说
|
|
191
|
+
「⚠️ 工坊工具链还是上一代(…;外壳已经是 <版本>):<原因>」并把修法一起给出来;
|
|
192
|
+
- 文件不在:还没有同步记录(首次 / 天然同代);**实装版本与外壳同代时不出声**,不同代时显示
|
|
193
|
+
「⏳ 工坊工具链还是上一代(工坊里 <包> <版本>,外壳 <版本>)—— 下一轮工作台启动时会对齐到 <版本>;一直这样就看 `$DSH_HOME/workbench/seed.log`」。
|
|
194
|
+
- **去哪看**:日志在 `$DSH_HOME/workbench/seed.log`(每次同步都写:比对的实装版本、开始自愈、
|
|
195
|
+
`pnpm install` 的原话、复核结果);状态也可以直接问 agent:`workbench_diy_status`。
|
|
196
|
+
- **失败了怎么修**:先照状态里那条命令来 —— `cd "$DSH_HOME/workbench/diy" && pnpm install`;
|
|
197
|
+
还是不行就把工坊目录删掉再重启一次工作台(骨架会自己重建;`packages/` 下你造的模块先留着或另存)。
|
|
198
|
+
两句常见原因:PATH 上没有 `pnpm`(装好后 `cd <工坊> && pnpm install`)、
|
|
199
|
+
工坊根 `package.json` 被手改坏了(修回一份合法 JSON)。
|
|
200
|
+
- **离线 / 装不动**:就停在旧一代,但**看得见**(`failed` + `reason` + 修法)。同一个外壳版本上失败过,
|
|
201
|
+
一小时内不再重试(`SYNC_BACKOFF_SECONDS=3600`);外壳换了一代就是新问题,会重新试。
|
|
202
|
+
自愈锁的过期判据是 15 分钟(`SYNC_LOCK_STALE_MINUTES=15`,持锁者崩了不会被永久锁死)。
|
|
203
|
+
|
|
161
204
|
## 排障
|
|
162
205
|
|
|
163
206
|
| 症状 | 原因 |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dsh-workbench/core",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "个人工作台:Agent 工作台外壳(左栏 + 常驻对话 + 自研右侧数据面板)。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"icon": "./icon.svg",
|
|
@@ -87,7 +87,7 @@
|
|
|
87
87
|
"access": "public"
|
|
88
88
|
},
|
|
89
89
|
"dependencies": {
|
|
90
|
-
"@dsh-workbench/shared": "0.3.
|
|
90
|
+
"@dsh-workbench/shared": "0.3.1"
|
|
91
91
|
},
|
|
92
92
|
"scripts": {
|
|
93
93
|
"build": "node scripts/build.mjs && node scripts/build-types.mjs",
|