@dsh-workbench/core 0.1.16 → 0.1.18
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 +665 -127
- package/dist/board.css +31 -0
- package/dist/client/client.body.js +665 -127
- package/dist/client/index.js +665 -127
- package/dist/host/index.js +1510 -263
- package/dist/types/app/client.d.ts +124 -27
- package/dist/types/app/layouts/market/add-module-text.d.ts +2 -0
- package/dist/types/app/layouts/market/use-add-module.d.ts +4 -3
- package/dist/types/app/layouts/market/use-module-versions.d.ts +2 -0
- package/dist/types/app/layouts/rightbar/MarketView.d.ts +3 -1
- package/dist/types/app/layouts/rightbar/__tests__/market-rows-plugins.test.d.ts +1 -0
- package/dist/types/app/layouts/rightbar/market-freshness.d.ts +1 -0
- package/dist/types/app/layouts/rightbar/market-mock.d.ts +9 -0
- package/dist/types/app/layouts/rightbar/market-plugin-rows.d.ts +8 -0
- package/dist/types/app/layouts/rightbar/market-rows.d.ts +14 -3
- package/dist/types/app/layouts/rightbar/registry.d.ts +0 -1
- package/dist/types/app/units/__tests__/manifests.test.d.ts +1 -0
- package/dist/types/app/units/fixture-unit-mock.d.ts +3 -3
- package/dist/types/app/units/host.d.ts +2 -2
- package/dist/types/app/units/manifests.d.ts +5 -0
- package/dist/types/app/units/registry.d.ts +10 -2
- package/dist/types/modules/panels/__tests__/market-env.test.d.ts +1 -0
- package/dist/types/modules/panels/__tests__/market-plugin.test.d.ts +1 -0
- package/dist/types/modules/panels/__tests__/market-route.test.d.ts +1 -0
- package/dist/types/modules/panels/__tests__/plugin-actions.test.d.ts +1 -0
- package/dist/types/modules/panels/__tests__/plugin-ledger.test.d.ts +1 -0
- package/dist/types/modules/panels/__tests__/plugin-section.test.d.ts +1 -0
- package/dist/types/modules/panels/__tests__/scope.test.d.ts +1 -0
- package/dist/types/modules/panels/__tests__/service-release.test.d.ts +1 -0
- package/dist/types/modules/panels/index.d.ts +2 -2
- package/dist/types/modules/panels/model/config.d.ts +27 -9
- package/dist/types/modules/panels/model/market-dispatch.d.ts +9 -0
- package/dist/types/modules/panels/model/market-env.d.ts +20 -0
- package/dist/types/modules/panels/model/market-route.d.ts +26 -0
- package/dist/types/modules/panels/model/market-types.d.ts +71 -0
- package/dist/types/modules/panels/model/market.d.ts +7 -66
- package/dist/types/modules/panels/model/plugin-actions.d.ts +50 -0
- package/dist/types/modules/panels/model/plugin-ledger.d.ts +22 -0
- package/dist/types/modules/panels/model/plugin-name.d.ts +8 -0
- package/dist/types/modules/panels/model/plugin-name.test.d.ts +1 -0
- package/dist/types/modules/panels/model/plugin-section.d.ts +13 -0
- package/dist/types/modules/panels/model/service.d.ts +8 -6
- package/dist/types/shared/api/bundle-install.d.ts +8 -1
- package/dist/types/shared/api/host/__tests__/registry-declaration.test.d.ts +1 -0
- package/dist/types/shared/api/host/__tests__/unit-roster-facts.test.d.ts +1 -0
- package/dist/types/shared/api/host/bundle-routes.d.ts +1 -0
- package/dist/types/shared/api/host/installed-module.d.ts +7 -0
- package/dist/types/shared/api/host/mount-units.d.ts +5 -3
- package/dist/types/shared/api/host/package-content.d.ts +6 -0
- package/dist/types/shared/api/host/package-content.test.d.ts +1 -0
- package/dist/types/shared/api/host/package-kind.d.ts +21 -0
- package/dist/types/shared/api/host/package-kind.test.d.ts +1 -0
- package/dist/types/shared/api/host/package-route.d.ts +23 -0
- package/dist/types/shared/api/host/package-route.test.d.ts +1 -0
- package/dist/types/shared/api/host/registry-declaration.d.ts +23 -0
- package/dist/types/shared/api/host/unit-registry.d.ts +33 -4
- package/dist/types/shared/api/host/unit-roster-facts.d.ts +5 -0
- package/dist/types/shared/api/installed-plugins.d.ts +12 -0
- package/dist/types/shared/api/unit-manifests.d.ts +5 -0
- package/dist/types/shared/api/unit-manifests.test.d.ts +1 -0
- package/dist/types/shared/hooks/bundle-queries.d.ts +2 -0
- package/dist/types/shared/hooks/use-facts.d.ts +1 -0
- package/package.json +2 -2
- package/skills/workbench-module-diy/BUILD.md +5 -5
- package/skills/workbench-module-diy/DESIGN.md +7 -1
- package/skills/workbench-module-diy/REVIEW.md +4 -3
- package/skills/workbench-module-diy/TOOLING.md +2 -2
- package/skills/workbench-module-diy/TOOLS.md +13 -3
|
@@ -1,24 +1,26 @@
|
|
|
1
1
|
import type { WorkspaceStore } from '@dsh-workbench/shared/host';
|
|
2
2
|
import type { UnitManifest } from '@dsh-workbench/shared';
|
|
3
|
-
import { type PanelEntry } from './config';
|
|
3
|
+
import { type BoardTarget, type PanelEntry, type ScopeBoards } from './config';
|
|
4
4
|
export declare const PANELS_MODULE_ID = "panels";
|
|
5
5
|
export declare const PANELS_FILE = "config.json";
|
|
6
6
|
export declare const RELEASED_FILE = "released.json";
|
|
7
7
|
export interface PanelsService {
|
|
8
|
-
list(workspace: string | null): PanelEntry[];
|
|
8
|
+
list(workspace: string | null, target?: BoardTarget): PanelEntry[];
|
|
9
|
+
boards(workspace: string | null): ScopeBoards;
|
|
9
10
|
isReleased(id: string): boolean;
|
|
10
11
|
release(id: string): void;
|
|
11
12
|
accept(id: string): void;
|
|
12
13
|
subscribe(listener: () => void): () => void;
|
|
13
14
|
isEnabled(id: string, workspace: string | null): boolean;
|
|
14
|
-
show(id: string, workspace: string | null): PanelEntry[];
|
|
15
|
-
hide(id: string, workspace: string | null): PanelEntry[];
|
|
16
|
-
move(id: string, index: number, workspace: string | null): PanelEntry[];
|
|
17
|
-
|
|
15
|
+
show(id: string, workspace: string | null, target?: BoardTarget): PanelEntry[];
|
|
16
|
+
hide(id: string, workspace: string | null, target?: BoardTarget): PanelEntry[];
|
|
17
|
+
move(id: string, index: number, workspace: string | null, target?: BoardTarget): PanelEntry[];
|
|
18
|
+
reset(workspace: string | null, target?: BoardTarget): PanelEntry[];
|
|
18
19
|
}
|
|
19
20
|
export declare function createPanelsService(options: {
|
|
20
21
|
manifests: () => readonly UnitManifest[];
|
|
21
22
|
store: WorkspaceStore;
|
|
23
|
+
owned?: (() => readonly string[]) | undefined;
|
|
22
24
|
logger?: {
|
|
23
25
|
warn?(message: string): void;
|
|
24
26
|
} | undefined;
|
|
@@ -8,7 +8,7 @@ export interface BundleRegistries {
|
|
|
8
8
|
readonly fallbackRegistries: readonly BundleRegistry[];
|
|
9
9
|
readonly resolved: string | null;
|
|
10
10
|
}
|
|
11
|
-
export type BundleInspectProblem = 'invalid-spec' | 'already-installed' | 'not-found' | 'not-a-package' | 'not-a-bundle' | 'network' | 'unknown';
|
|
11
|
+
export type BundleInspectProblem = 'invalid-spec' | 'already-installed' | 'not-found' | 'not-a-package' | 'not-a-bundle' | 'not-a-workbench-module' | 'not-a-module-or-plugin' | 'network' | 'unknown';
|
|
12
12
|
export type BundleSpecKind = 'registry' | 'path' | 'git' | 'tarball';
|
|
13
13
|
export interface BundleInspectionAccepted {
|
|
14
14
|
readonly status: 'accepted';
|
|
@@ -74,10 +74,16 @@ export interface BundleSupplyPayload {
|
|
|
74
74
|
readonly state: BundleSupplyState;
|
|
75
75
|
readonly reason?: string;
|
|
76
76
|
}
|
|
77
|
+
export interface BundleInstalledPlugin {
|
|
78
|
+
readonly kind: 'opencli-plugin';
|
|
79
|
+
readonly pkg: string;
|
|
80
|
+
readonly name?: string;
|
|
81
|
+
}
|
|
77
82
|
export interface BundleInstallPayload {
|
|
78
83
|
readonly change: BundleChange;
|
|
79
84
|
readonly module: BundleModulePayload;
|
|
80
85
|
readonly supply: BundleSupplyPayload;
|
|
86
|
+
readonly plugin?: BundleInstalledPlugin;
|
|
81
87
|
}
|
|
82
88
|
export interface BundleRemovePayload {
|
|
83
89
|
readonly change: BundleChange;
|
|
@@ -92,6 +98,7 @@ export interface ModuleVersion {
|
|
|
92
98
|
readonly installed: string;
|
|
93
99
|
readonly latest?: string;
|
|
94
100
|
readonly local?: boolean;
|
|
101
|
+
readonly refused?: readonly string[];
|
|
95
102
|
}
|
|
96
103
|
export interface ModuleVersionsPayload {
|
|
97
104
|
readonly modules: readonly ModuleVersion[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { DshHostContext, DshShell } from '@dsh-workbench/shared';
|
|
2
2
|
import { type RouteHandler } from '@dsh-workbench/shared/host';
|
|
3
3
|
export declare function bundleRegistriesHandler(ctx: DshHostContext): RouteHandler;
|
|
4
|
+
export declare function resetRefusalLog(): void;
|
|
4
5
|
export declare function moduleVersionsHandler(ctx: DshHostContext, shell: DshShell | undefined): RouteHandler;
|
|
5
6
|
export declare function bundleInspectHandler(ctx: DshHostContext): RouteHandler;
|
|
@@ -22,5 +22,12 @@ export interface ProfileModule {
|
|
|
22
22
|
readonly registry?: string;
|
|
23
23
|
readonly local?: boolean;
|
|
24
24
|
}
|
|
25
|
+
export declare function profileManifestOf(profileDir: string | null): Readonly<Record<string, unknown>> | undefined;
|
|
25
26
|
export declare function profileModules(profileDir: string | null): readonly ProfileModule[];
|
|
27
|
+
export declare function moduleDeclarationOf(profileDir: string | null, pkg: string): unknown;
|
|
28
|
+
export interface DeclarationGap {
|
|
29
|
+
readonly pkg: string;
|
|
30
|
+
readonly problems: readonly string[];
|
|
31
|
+
}
|
|
32
|
+
export declare function declarationGaps(profileDir: string | null): readonly DeclarationGap[] | undefined;
|
|
26
33
|
export declare function readInstalledModule(profileDir: string | null, pkg: string): InstalledModule;
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import type { DshHostContext } from '@dsh-workbench/shared';
|
|
2
2
|
import type { UnitManifest } from '@dsh-workbench/shared/host';
|
|
3
3
|
import { type RouteTable } from '@dsh-workbench/shared/host';
|
|
4
|
-
import type { ContextRenderer,
|
|
4
|
+
import type { ContextRenderer, UnitMountDeps, UnitMountResult, UnitCall } from '@dsh-workbench/shared/host';
|
|
5
|
+
import type { HostUnit } from './unit-registry';
|
|
5
6
|
import { type UnitReadiness } from './unit-readiness';
|
|
6
7
|
export interface UnitFailure {
|
|
7
8
|
readonly id: string;
|
|
8
9
|
readonly reason: string;
|
|
9
10
|
}
|
|
10
11
|
export interface MountedUnit {
|
|
11
|
-
readonly
|
|
12
|
+
readonly host: HostUnit;
|
|
12
13
|
readonly result: UnitMountResult;
|
|
13
14
|
readonly readiness: UnitReadiness;
|
|
14
15
|
}
|
|
@@ -40,13 +41,14 @@ interface NamedEntry {
|
|
|
40
41
|
handle(payload: unknown): unknown;
|
|
41
42
|
}
|
|
42
43
|
export declare function failureReasonOf(error: unknown): string;
|
|
43
|
-
export declare function mountUnits(
|
|
44
|
+
export declare function mountUnits(units: readonly HostUnit[], deps: {
|
|
44
45
|
ctx: DshHostContext;
|
|
45
46
|
logger?: {
|
|
46
47
|
info?(m: string): void;
|
|
47
48
|
warn?(m: string): void;
|
|
48
49
|
} | undefined;
|
|
49
50
|
manifests: () => readonly UnitManifest[];
|
|
51
|
+
ownedUnits?: () => readonly string[];
|
|
50
52
|
opencliCommand?: string;
|
|
51
53
|
probe?: UnitMountDeps['probe'];
|
|
52
54
|
store?: UnitMountDeps['store'];
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { DshShell } from '@dsh-workbench/shared';
|
|
2
|
+
export declare function withPackageDir<T>(options: {
|
|
3
|
+
readonly shell?: DshShell | undefined;
|
|
4
|
+
readonly spec: string;
|
|
5
|
+
readonly registry?: string | undefined;
|
|
6
|
+
}, visit: (dir: string) => T): Promise<T | undefined>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export type PackageKind = 'opencli-plugin' | 'dsh-bundle' | 'both' | 'neither';
|
|
2
|
+
export interface PackageVerdict {
|
|
3
|
+
readonly kind: PackageKind;
|
|
4
|
+
readonly pkg?: string;
|
|
5
|
+
readonly pluginName?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface NpmRef {
|
|
8
|
+
readonly name: string;
|
|
9
|
+
readonly version?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare const OPENCLI_MANIFEST_FILE = "opencli-plugin.json";
|
|
12
|
+
export declare function splitNpmSpec(spec: string): NpmRef | undefined;
|
|
13
|
+
export declare function isCommandFile(name: string): boolean;
|
|
14
|
+
export declare function pluginManifestOf(dir: string): Readonly<Record<string, unknown>> | undefined;
|
|
15
|
+
export declare function hasCommandFile(dir: string): boolean;
|
|
16
|
+
export declare function pluginAt(dir: string): {
|
|
17
|
+
readonly name?: string;
|
|
18
|
+
} | undefined;
|
|
19
|
+
export declare function dshMarkersOf(raw: unknown): boolean;
|
|
20
|
+
export declare function verdictOf(dir: string): PackageVerdict | undefined;
|
|
21
|
+
export declare function refusalReason(): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { DshShell } from '@dsh-workbench/shared';
|
|
2
|
+
import { type ResolvedPluginSource } from '@dsh-workbench/shared/host';
|
|
3
|
+
export type PackageRouteKind = 'opencli-plugin' | 'dsh-bundle' | 'neither';
|
|
4
|
+
export interface PackageRoute {
|
|
5
|
+
readonly kind: PackageRouteKind;
|
|
6
|
+
readonly pkg?: string;
|
|
7
|
+
readonly pluginName?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare const LOCAL_PLUGIN_ENV = "DSH_WB_OPENCLI_PLUGIN_PATH";
|
|
10
|
+
export declare const PLUGIN_REGISTRY_ENV = "DSH_WB_OPENCLI_PLUGIN_REGISTRY";
|
|
11
|
+
export declare function packageRouteOf(options: {
|
|
12
|
+
readonly spec: string;
|
|
13
|
+
readonly shell?: DshShell | undefined;
|
|
14
|
+
readonly registry?: string | undefined;
|
|
15
|
+
readonly force?: boolean;
|
|
16
|
+
}): Promise<PackageRoute | undefined>;
|
|
17
|
+
export declare function resetPackageRouteCache(): void;
|
|
18
|
+
export declare function pluginInstallPlan(options: {
|
|
19
|
+
readonly spec: string;
|
|
20
|
+
readonly command: string;
|
|
21
|
+
readonly registry?: string | undefined;
|
|
22
|
+
readonly pluginName?: string | undefined;
|
|
23
|
+
}): ResolvedPluginSource;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { DshShell } from '@dsh-workbench/shared';
|
|
2
|
+
export declare function localDirOf(spec: string): string | undefined;
|
|
3
|
+
export declare function packageManifestOf(dir: string): Readonly<Record<string, unknown>> | undefined;
|
|
4
|
+
export declare function dshRecordOf(dir: string): unknown | undefined;
|
|
5
|
+
export declare function packageNameOf(dir: string): string | undefined;
|
|
6
|
+
export declare function pathDeclarationOf(spec: string): unknown | undefined;
|
|
7
|
+
export interface RegistryDshLookup {
|
|
8
|
+
readonly readable: boolean;
|
|
9
|
+
readonly raw: unknown;
|
|
10
|
+
}
|
|
11
|
+
export declare function registryDshOf(options: {
|
|
12
|
+
shell: DshShell;
|
|
13
|
+
name: string;
|
|
14
|
+
registry?: string | undefined;
|
|
15
|
+
force?: boolean;
|
|
16
|
+
}): Promise<RegistryDshLookup>;
|
|
17
|
+
export declare function registryDeclarationOf(options: {
|
|
18
|
+
shell: DshShell;
|
|
19
|
+
name: string;
|
|
20
|
+
registry: string;
|
|
21
|
+
force?: boolean;
|
|
22
|
+
}): Promise<unknown | undefined>;
|
|
23
|
+
export declare function declarationRefusalOf(name: string, raw: unknown): readonly string[];
|
|
@@ -1,9 +1,38 @@
|
|
|
1
1
|
import type { UnitManifest } from '@dsh-workbench/shared';
|
|
2
|
-
import type {
|
|
2
|
+
import type { UnitModuleFace, UnitOwnedFace } from '@dsh-workbench/shared/host';
|
|
3
|
+
export interface UnitRefusal {
|
|
4
|
+
readonly unit: string;
|
|
5
|
+
readonly pkg?: string;
|
|
6
|
+
readonly reasons: readonly string[];
|
|
7
|
+
}
|
|
8
|
+
export type UnitSource = {
|
|
9
|
+
readonly kind: 'package';
|
|
10
|
+
readonly pkg: string;
|
|
11
|
+
} | {
|
|
12
|
+
readonly kind: 'owned';
|
|
13
|
+
};
|
|
14
|
+
export interface HostUnit {
|
|
15
|
+
readonly unit: string;
|
|
16
|
+
readonly manifest: UnitManifest;
|
|
17
|
+
readonly face: UnitModuleFace;
|
|
18
|
+
readonly source: UnitSource;
|
|
19
|
+
}
|
|
20
|
+
export interface UnitDeclarationSource {
|
|
21
|
+
readonly pkg: string;
|
|
22
|
+
readonly declaration: unknown;
|
|
23
|
+
}
|
|
3
24
|
export interface UnitRegistry {
|
|
4
|
-
register(face:
|
|
5
|
-
|
|
25
|
+
register(face: UnitModuleFace): () => void;
|
|
26
|
+
registerOwned(face: UnitOwnedFace): () => void;
|
|
27
|
+
all(): readonly HostUnit[];
|
|
28
|
+
owned(): readonly string[];
|
|
29
|
+
refusals(): readonly UnitRefusal[];
|
|
6
30
|
manifests(): readonly UnitManifest[];
|
|
7
31
|
subscribe(listener: () => void): () => void;
|
|
8
32
|
}
|
|
9
|
-
export declare function createUnitRegistry(
|
|
33
|
+
export declare function createUnitRegistry(options: {
|
|
34
|
+
declarationOf: (unit: string) => UnitDeclarationSource | undefined;
|
|
35
|
+
logger?: {
|
|
36
|
+
warn?(message: string): void;
|
|
37
|
+
} | undefined;
|
|
38
|
+
}): UnitRegistry;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare const INSTALLED_PLUGINS_ROUTE = "panels/plugins";
|
|
2
|
+
export interface InstalledPlugin {
|
|
3
|
+
readonly pkg: string;
|
|
4
|
+
readonly name?: string;
|
|
5
|
+
readonly installed?: string;
|
|
6
|
+
readonly latest?: string;
|
|
7
|
+
readonly local?: boolean;
|
|
8
|
+
readonly broken?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface InstalledPluginsPayload {
|
|
11
|
+
readonly plugins: readonly InstalledPlugin[];
|
|
12
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { ApiResponse } from '@dsh-workbench/shared';
|
|
2
2
|
import { type BundleInspectionPayload, type BundleRegistriesPayload, type ModuleVersionsPayload } from '../api/bundle-install';
|
|
3
|
+
import { type InstalledPluginsPayload } from '../api/installed-plugins';
|
|
3
4
|
export declare function readBundleRegistries(): Promise<ApiResponse<BundleRegistriesPayload>>;
|
|
4
5
|
export declare function readBundleInspection(spec: string, registry?: string): Promise<ApiResponse<BundleInspectionPayload>>;
|
|
5
6
|
export declare function readModuleVersions(force?: boolean): Promise<ApiResponse<ModuleVersionsPayload>>;
|
|
7
|
+
export declare function readInstalledPlugins(force?: boolean): Promise<ApiResponse<InstalledPluginsPayload>>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dsh-workbench/core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.18",
|
|
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.1.
|
|
90
|
+
"@dsh-workbench/shared": "0.1.18"
|
|
91
91
|
},
|
|
92
92
|
"scripts": {
|
|
93
93
|
"build": "node scripts/build.mjs && node scripts/build-types.mjs",
|
|
@@ -46,7 +46,7 @@ pnpm exec dsh-wb-module init <unit> --dir <工坊>/packages/module-<unit> --temp
|
|
|
46
46
|
`<unit>` 是小写短横线标识(如 `my-thing`),它同时是单元 id、包名后缀、卡片样式前缀。
|
|
47
47
|
**它必须全局唯一** —— 和工作台里其它模块、和外壳里已有的单元都不能撞;撞了装上去当场抛。
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
生成的骨架是**能直接跑的**(十一条判据 + 三个脚本开箱全绿;门禁还在,模板改坏了当场报)。
|
|
50
50
|
|
|
51
51
|
**两个模板,按需要挑**(加 `--template <名字>`):
|
|
52
52
|
|
|
@@ -61,7 +61,7 @@ pnpm exec dsh-wb-module init <unit> --dir <工坊>/packages/module-<unit> --temp
|
|
|
61
61
|
|
|
62
62
|
| 文件 | 职责 |
|
|
63
63
|
|---|---|
|
|
64
|
-
| `package.json` | 自述清单:包名、`dsh.bundle.patch`、`dsh.client`、`dsh.workbench.unit
|
|
64
|
+
| `package.json` | 自述清单:包名、`dsh.bundle.patch`、`dsh.client`、`dsh.workbench.unit`、`dsh.workbenchFaces{host,client}`(工具链字段,**不在协议里**,但门禁必填)、四个脚本、peer 依赖 |
|
|
65
65
|
| `cordis.patch.yml` | 把自己插进 profile 的那一行 |
|
|
66
66
|
| `src/host.ts` | 宿主面:`manifest` + `mount()`(路由 / 工具) |
|
|
67
67
|
| `src/client.tsx` | 浏览器面:`manifest` + `card` |
|
|
@@ -85,7 +85,7 @@ README 里 `<!-- dsh-wb:design:start/end -->` 之间那一段**由它生成**(
|
|
|
85
85
|
|
|
86
86
|
```bash
|
|
87
87
|
dsh-wb-module build # 出 client.js 与 dist/host.js
|
|
88
|
-
dsh-wb-module check #
|
|
88
|
+
dsh-wb-module check # 十一条判据,全跑
|
|
89
89
|
dsh-wb-module check --only cards # 单跑一条(contracts / bundles / source / primitives /
|
|
90
90
|
# kit / cards / standalone / markers / alias / style)
|
|
91
91
|
```
|
|
@@ -104,13 +104,13 @@ pnpm test # vitest
|
|
|
104
104
|
pnpm selfcheck # 构建 + 把 client.js 当加载器跑一遍(`diy` 骨架里还多一条 `design check`)
|
|
105
105
|
```
|
|
106
106
|
|
|
107
|
-
**自己的门禁自己过,红了别抛给用户。**
|
|
107
|
+
**自己的门禁自己过,红了别抛给用户。** 十一条判据在 [REVIEW.md](REVIEW.md) 里逐条翻了人话。
|
|
108
108
|
⚠️ **`check` 不替你跑 `pnpm test`**(它只看形状与产物):状态级的渲染、换算、边界都在你自己的
|
|
109
109
|
`test` 里 —— 骨架开箱就带一份,改了数据源与渲染就顺手把它跑一遍,别让红线留在包里。
|
|
110
110
|
⚠️ **工坊里恒有两条是「不适用」,那不是「通过」**:`独立构建` 扫的是 `packages/*` 里的外壳源码
|
|
111
111
|
(工坊里没有),`公开包无内部标识` 只扫要发出去的包(DIY 模块一律 `private`)。汇总行下面会把
|
|
112
112
|
这次没查的那几条逐条列出来;**要验它们,回工作台仓库根跑一次 `dsh-wb-module check`**。
|
|
113
|
-
所以「8 通过 · 2
|
|
113
|
+
所以「8 通过 · 2 不适用」不等于十一条全绿 —— 别把这句话念给用户听。
|
|
114
114
|
|
|
115
115
|
装上板那一步不是命令,是一把 agent 工具:`workbench_diy`(`action=list` 看工坊里有什么、`action=status, unit=<单元 id>`
|
|
116
116
|
看它现在走到哪一步、`action=install` 装上并上板、`action=open` 只上板)—— 见 §7。
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
- 门禁是绿的 —— 那是 agent 自己的门槛,不用他关心。
|
|
84
84
|
- 下次他再说一句"改一下",不用从头问:设计留下的记录还在。
|
|
85
85
|
|
|
86
|
-
## 5 落点:`design.json
|
|
86
|
+
## 5 落点:`design.json`(设计底稿:人话一处,机器字段在清单)
|
|
87
87
|
|
|
88
88
|
三张表 + 状态矩阵 + 数据源记录 + 验收清单住在模块根目录的 `design.json`,README 里那一段**由它生成**
|
|
89
89
|
(夹在 `<!-- dsh-wb:design:start/end -->` 之间,别手改 —— 下一次 `check` 会判红):
|
|
@@ -100,6 +100,12 @@ key 固定 `idle|loading|ready|empty|unreadable`)+ `config[]` + `capabilities[
|
|
|
100
100
|
`config` / `capabilities` **允许空数组**("这份模块故意没有能力"是一种决定);其余空着就是没定的事。
|
|
101
101
|
`link` 这类**可选格**留空渲染成 `—`,不算空格。
|
|
102
102
|
|
|
103
|
+
`design.json` 是**设计底稿**:只装人话。"这条能力在哪些工作区出现"**哪里都别写** ——
|
|
104
|
+
它既不在底稿、也不在清单:那是**用户**的事(他在 `workbench_panels` 里决定,见 [TOOLS.md](TOOLS.md) §12)。
|
|
105
|
+
协议里那个 `scope`(`tools[].scope` / `card.scope`)**已经删掉**:用户口径是「模块开发者不能定义 scope,
|
|
106
|
+
scope 永远是用户来决定的」(见 [ADR-0038 §2.4 / §6.16](../../../../docs/adr/0038-module-declaration-protocol.md))。
|
|
107
|
+
`contracts` 只拿名字把底稿与清单对起来(键集合对账)。
|
|
108
|
+
|
|
103
109
|
五态那五行是矩阵的行,**不能省**;但某一态对这份模块确实不适用时,写一句为什么就行 ——
|
|
104
110
|
`{ "key": "idle", "na": "读的是账号,不随项目变:没选项目时这张卡压根不渲染" }`,
|
|
105
111
|
那一行不填 `sees` / `canDo` / `agentCan`,表里渲染成「(这份模块不适用)…」。
|
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
#
|
|
1
|
+
# 门禁红了怎么办:十一条判据的人话对照表
|
|
2
2
|
|
|
3
3
|
跑 `dsh-wb-module check`(或单跑一条 `--only <名字>`)。
|
|
4
4
|
**每一条红的都在讲一件真出过事的事**,不是形式主义。红了就照下面修,别抛给用户。
|
|
5
5
|
|
|
6
6
|
| 判据 | 它防的事故 | 红了的典型说法 | 怎么修 |
|
|
7
7
|
|---|---|---|---|
|
|
8
|
-
| `contracts` | dsh 组合阶段**不校验**你 `package.json` 里的声明 —— 错的 `external` 要到浏览器 `require`
|
|
8
|
+
| `contracts` | dsh 组合阶段**不校验**你 `package.json` 里的声明 —— 错的 `external` 要到浏览器 `require` 那一刻才炸;清单与代码、底稿与清单之间漂了也没人拦 | `单元 id "x" 与 … 撞了` / `dsh.workbenchFaces.client 指的文件不存在` / `dsh.workbenchFaces.host 没声明` / `没有对 @dsh-workbench/core 的 peer 依赖` / `没有 typecheck 脚本` / `它不是 private,却既没声明 publishConfig.access=public…` / `src/declared-tools.ts 与清单对不上(生成物过期…)` / `工具名的字面量又写回了源码` / `…没有 key` / `dsh.workbench 声明的能力与代码真正注册的对不上` / `design.json 的能力行里有「x」,清单的 tools[] 里却没有它` | 按报的那一条改 `package.json`(生成物对不上就跑 `dsh-wb-module sync`;工具名的字面量只许留在清单里);`unit` 换个不撞的名字;`dsh.workbenchFaces` 补上两个**源码**入口;四个脚本补全;私有不发就保持 `private: true`。**工具只声明在清单里**(`dsh.workbench.tools`)且必须与 `mount()` 里 `registerTools()` 真正注册的**不重不漏**;写了 `design.json` 的话,它的 `capabilities[].name` 与清单的 `tools[].name` 也要不重不漏(U1c 的**键集合对账**,只对名字 —— 内容各写一处);`gate.deniedTools` 是可选的运行期收窄,门禁不再对它做声明对账(协议里的 `scope` 已删 —— 哪些工作区出现由用户的板决定) |
|
|
9
|
+
| `protocol` | `dsh.workbench` 是外壳读你得懂的那份声明:缺版本、形状不对、**多一个键**、枚举值不认都要在装机前拦下来。多出来的键最阴 —— 外壳会**静默忽略**它(拼错一个键 = 那句话白写) | `没有 apiVersion` / `apiVersion 是 99,这份只认 1` / `声明了 apiVersion 就要把静态半写全 —— 缺 dsh.workbench.tools` / `dsh.workbench 里有协议 v1 不认识的键 "faces"` / `card 里有不认的键 "enabledByDefault"`(这个键连外壳里都没有了 —— A-3 删的,见 [ADR-0038](../../../../docs/adr/0038-module-declaration-protocol.md) §6.7) / `tools[0] 里有协议不认的键 "scopes"` / `tools[0] 里有不认的键 "scope"`(`scope` 自本轮更正起**不在协议里**:能力在哪些工作区出现由用户的板决定,见 [ADR-0038 §2.4 / §6.16](../../../../docs/adr/0038-module-declaration-protocol.md)) | 补 `"apiVersion": 1`;把 `unit` / `card` / `tools` / `host` 四个键写全(没卡片写 `"card": null`、没工具写 `"tools": []`、一个服务都不要写 `"host": { "inject": [] }`);删掉协议外的键(`faces` 自 A-2 起搬到 `dsh.workbenchFaces`,写回 `dsh.workbench` 里就是生字段);`scope` **不要写**(协议不认它,写了就是生字段)。字段清单见 `dsh-wb-module` 的 README「协议」那一节 |
|
|
9
10
|
| `bundles` | 两个运行时互串:浏览器产物里带 node 内置、宿主产物里带 DOM / react | `浏览器产物里出现了 node 内置 …` / `宿主产物里出现了 react` | 宿主面别 import 浏览器侧的东西;浏览器面别 import `node:*`。两侧只通过服务名相接 |
|
|
10
11
|
| `source` | 非种子词的 `@deepseek-ai/*`、宿主侧碰 dsh 的浏览器包、`@/` 指到工作台源码 | `…在宿主侧可达` / `不是平台种子词` | 宿主侧只用 Node 侧的东西;dsh 原语一律走 `kit`;`@/` 只指自己的 `src/` |
|
|
11
12
|
| `primitives` | 声明了 `external` 却没有产物物证 ⇒ dsh 原语被**内联**成第二份实例 | `…用了却没声明 external` / `宿主产物里出现了` | 在 `dsh.client.external` 里显式声明它;确认产物里是 `require(...)` 而不是被打包进来 |
|
|
12
13
|
| `kit` | 用了 peer 下限那份外壳**还没有**的 kit 成员 ⇒ 卡片首帧 `Element type is invalid`,整块面板被 React 卸掉 | `kit.components.X 在这份外壳里没有` / `peer 下限比 devDependency 还旧` | 只用 peer 范围里真有的成员;把 `peerDependencies` 的下限提到你实际用的那档 |
|
|
13
|
-
| `cards` | 卡片拿**空数据**就抛 ⇒ 用户看到"卡片一直不出来 / 点一下白屏" | `空数据下卡片抛了` / `卡片只画出一个节点` / `卡片没套外壳的卡壳` | 让卡片在没数据时也画得出来(已有的加载 / 空 / 阻断态);外面套 `kit.components.Card` |
|
|
14
|
+
| `cards` | 卡片拿**空数据**就抛 ⇒ 用户看到"卡片一直不出来 / 点一下白屏" | `空数据下卡片抛了` / `卡片只画出一个节点` / `卡片没套外壳的卡壳` / `清单的 card.titleKey「x」在模块字典的 en 里没有` / `…没有落点` | 让卡片在没数据时也画得出来(已有的加载 / 空 / 阻断态);外面套 `kit.components.Card`;清单写了 `titleKey`,`registerUnit` 交的 `messages` 里 `zh` / `en` 都得有那一条(漏了面板上显示的是原始键名) |
|
|
14
15
|
| `standalone` | "只有工作台源码在场才编得过" ⇒ 发布出去就散架 | `build 在外壳源码不在场时失败` / `typecheck 在外壳源码不在场时失败` | 别引用工作台源码;`tsconfig` 里 `paths` 的值必须是**相对路径**(`"./src/*"`,不是 `"src/*"`) |
|
|
15
16
|
| `markers` | 内网域名 / 企业内部名泄进要公开发布的包 | `命中内网 npm 源` / `命中内网域名` | 那些值不该写进包里;要配就落到模块自己的配置面,或走用户自己声明的来源 |
|
|
16
17
|
| `alias` | `@/` 伸进工作台源码 ⇒ 装的人手上没有那份源码 | `…指向外壳源码` | `@/` 只许指自己的 `src/`;跨包的东西走包名 |
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
| 纪律(出处) | 固化形态 |
|
|
14
14
|
|---|---|
|
|
15
|
-
|
|
|
15
|
+
| 十一条判据([REVIEW.md](REVIEW.md)) | `dsh-wb-module check`(`--only <判据>` 单跑;`--only kit` 列这份外壳的 kit 成员) |
|
|
16
16
|
| 落点、文件形状、四个脚本([BUILD.md](BUILD.md) §1–§2) | `dsh-wb-module init --template diy`(骨架带一条真读盘的数据源)+ `scripts/smoke.mjs` |
|
|
17
17
|
| 装、上板、不重装([WIRING.md](WIRING.md) §3) | `workbench_diy`(`install` / `open` / `status`)+ `workbench_panels` |
|
|
18
18
|
| 空着的格就是还没定的事([DESIGN.md](DESIGN.md) §5) | `design.json` + `design check`(点名叫出空格)/ `render` / `accept` |
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
| DOM 读怎么读([DATASOURCE.md](DATASOURCE.md) 第 2 步) | `probe`(探)+ `browserFind`(固化)—— 切格 / 按列取值是两个纯函数 |
|
|
28
28
|
| 链接只有一副样子([PANEL.md](PANEL.md) §6) | kit 的 `Link` 是唯一一份(**没有 `icon` 口子**),`check --only style` 拦裸 `<a>` |
|
|
29
29
|
| 输入框不用自己配样式([PANEL.md](PANEL.md) §5.1) | `TextField` 的默认内边距 + kit 的 `Field`(标签 + 提示的排布) |
|
|
30
|
-
|
|
|
30
|
+
| 这个单元在哪些工作区出现([TOOLS.md](TOOLS.md) §12) | **不是模块能声明的事** —— 用户用 `workbench_panels` 的板决定(卡片与全部工具同判);协议里的 `scope` 已删。`gate.deniedTools` 是可选的运行期收窄,门禁不再对它做声明对账 |
|
|
31
31
|
|
|
32
32
|
## 留给 agent 的(判断,不该固化)
|
|
33
33
|
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
### 6.1 写法(清单 + 两个函数;缺一个门禁就红)
|
|
80
80
|
|
|
81
81
|
```ts
|
|
82
|
-
tools: [{ name: 'workbench_demo_rebuild', writes: true }],
|
|
82
|
+
tools: [{ name: 'workbench_demo_rebuild', writes: true, key: 'rebuild' }],
|
|
83
83
|
|
|
84
84
|
needsApproval: (call) => ({
|
|
85
85
|
kind: 'ask',
|
|
@@ -91,6 +91,9 @@ needsApproval: (call) => ({
|
|
|
91
91
|
approvalDetail: async (call) => ({ zh: '会覆盖这 3 个模块的产物,不碰源码', en: '…' }),
|
|
92
92
|
```
|
|
93
93
|
|
|
94
|
+
* `key` 是代码里那个短名(lowerCamelCase)。给了它就 `dsh-wb-module sync` 一次,生成
|
|
95
|
+
`src/declared-tools.ts`,代码写 `DECLARED_TOOLS.rebuild.name` —— 工具名的字面量只剩清单这一处
|
|
96
|
+
(键写错是编译错;生成物过期、半写 key、源码里又写字面量,门禁都红)。一个 key 都不写也行(不适用那一档)。
|
|
94
97
|
* `needsApproval` 回 `{ kind: 'read' }` = 这件不用问;回 `{ kind: 'ask', … }` = 要问;
|
|
95
98
|
**清单写着 `writes: true` 却不认领,外壳当场 deny**("在套件的 needsApproval 里补一条审批")——
|
|
96
99
|
但那条错误只有真跑一次才看得见,所以 `check --only contracts` 会替用户先看一遍:缺 `needsApproval`、
|
|
@@ -250,5 +253,12 @@ return {
|
|
|
250
253
|
`packages/workbench/src/modules/panels/index.ts`):某张卡在这个项目上没开 → 那张卡的工具全不出现;
|
|
251
254
|
工坊那把窄门工具 `workbench_diy` **只在工坊会话里**出现,别处一律不出现。
|
|
252
255
|
|
|
253
|
-
|
|
254
|
-
|
|
256
|
+
**"这条能力在哪些工作区出现"不用你声明 —— 那是用户的事。** 用户口径:「模块开发者不能定义 scope,
|
|
257
|
+
scope 永远是用户来决定的」。他在 `workbench_panels`(agent 工具)里把它们放上/收起;一个单元在不在,
|
|
258
|
+
它的卡片与**全部**工具同判(外壳的 `resolveScope` 只看两份板:本工作区那份,否则机器级那份)。
|
|
259
|
+
协议里那个 `scope`(`dsh.workbench.tools[].scope` / `card.scope`)**已经删掉**,写它就是写了一个
|
|
260
|
+
不认识的键、`check --only protocol` 当场红(见 [ADR-0038 §2.4 / §6.16](../../../../docs/adr/0038-module-declaration-protocol.md))。
|
|
261
|
+
`design.json` 的能力行也没有这一格。
|
|
262
|
+
|
|
263
|
+
`gate.deniedTools` 仍然可以接,但它是**可选**的运行期收窄("这个能力还没配好,先按我自己的开关藏起来"),
|
|
264
|
+
**不是**一条声明出来的承诺:门禁不再拿任何声明去对账它(那条判据已删 —— 没有作者侧声明就没有可比的东西)。
|