@dsh-workbench/core 1.1.14-beta.2 → 1.1.15

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 (41) hide show
  1. package/README.md +1 -1
  2. package/bin/dsh-workbench +6 -52
  3. package/client.js +59 -16
  4. package/cordis.patch.yml +5 -6
  5. package/dist/client/client.body.js +59 -16
  6. package/dist/client/index.js +59 -16
  7. package/dist/host/index.js +1873 -680
  8. package/dist/types/app/layouts/env-gate/gate-text.d.ts +2 -3
  9. package/dist/types/app/units/manifests.d.ts +2 -0
  10. package/dist/types/kernel/host/mount-units.d.ts +2 -1
  11. package/dist/types/modules/panels/model/diy-browser-act.d.ts +2 -3
  12. package/dist/types/modules/panels/model/diy-browser-clip.d.ts +14 -0
  13. package/dist/types/modules/panels/model/diy-browser-tools.d.ts +1 -14
  14. package/dist/types/modules/panels/model/diy-browser.d.ts +6 -6
  15. package/dist/types/modules/panels/model/diy-page.d.ts +3 -2
  16. package/dist/types/modules/panels/model/diy-record-open.d.ts +2 -2
  17. package/dist/types/modules/panels/model/diy-record.d.ts +14 -14
  18. package/dist/types/modules/panels/model/market-discover.d.ts +2 -2
  19. package/dist/types/modules/panels/model/market-follow-up.d.ts +2 -1
  20. package/dist/types/modules/panels/model/market-route.d.ts +2 -3
  21. package/dist/types/modules/panels/model/market-update-bundle.d.ts +2 -3
  22. package/dist/types/modules/panels/model/market-workbench-update.d.ts +2 -2
  23. package/dist/types/modules/panels/model/market.d.ts +2 -2
  24. package/dist/types/modules/panels/model/plugin-actions.d.ts +2 -3
  25. package/dist/types/modules/panels/model/plugin-section.d.ts +3 -4
  26. package/dist/types/shared/api/host/bundle-routes.d.ts +3 -3
  27. package/dist/types/shared/api/host/diy-artifacts.d.ts +1 -2
  28. package/dist/types/shared/api/host/diy-capture-live.d.ts +25 -0
  29. package/dist/types/shared/api/host/diy-components.d.ts +2 -2
  30. package/dist/types/shared/api/host/diy-release-staging.d.ts +6 -0
  31. package/dist/types/shared/api/host/diy.d.ts +1 -1
  32. package/dist/types/shared/api/host/git-exec.d.ts +1 -1
  33. package/dist/types/shared/api/host/git-process.d.ts +3 -0
  34. package/dist/types/shared/api/host/shipped-adapter-set.d.ts +4 -0
  35. package/dist/types/shared/api/host/workbench-seam.d.ts +3 -0
  36. package/package.json +3 -6
  37. package/scripts/seed-profile.sh +3 -3
  38. package/scripts/share-data-root.mjs +10 -13
  39. package/skills/workbench-module-diy/BUILD.md +38 -0
  40. package/skills/workbench-module-diy/SKILL.md +1 -0
  41. package/profile/sandbox.patch.yml +0 -28
@@ -6,11 +6,9 @@ export interface GuidanceText {
6
6
  readonly why: string;
7
7
  readonly step: string;
8
8
  }
9
- export declare function guidanceTextOf(guidance: PreflightGuidance | undefined, t: Translate): GuidanceText;
9
+ export declare function guidanceTextOf(guidance: PreflightGuidance | undefined, t: Translate, hasCommand?: boolean): GuidanceText;
10
10
  export declare function stepDetailText(step: PreflightStep, snapshot: PreflightSnapshot, t: Translate): string;
11
11
  export declare function gateHintOf(snapshot: PreflightSnapshot, t: Translate): string;
12
- export declare function showsRawDetails(snapshot: PreflightSnapshot): boolean;
13
- export declare function showsRawAll(snapshot: PreflightSnapshot, panelShown: boolean): boolean;
14
12
  export interface BridgeAdvice {
15
13
  readonly text: string;
16
14
  readonly link?: {
@@ -19,3 +17,4 @@ export interface BridgeAdvice {
19
17
  };
20
18
  }
21
19
  export declare function bridgeAdvice(issue: PreflightBridgeIssue, t: Translate, fixes?: RuntimeProfile['bridge']): BridgeAdvice;
20
+ export declare function bridgeAdviceLines(issues: readonly PreflightBridgeIssue[], t: Translate, fixes?: RuntimeProfile['bridge']): readonly BridgeAdvice[];
@@ -1,5 +1,7 @@
1
1
  import type { ClientUnitRegistry } from '../../kernel/client/registry';
2
2
  export interface UnitManifestLoaderOptions {
3
3
  readonly subscribeFacts?: (fact: string, listener: () => void) => () => void;
4
+ readonly retryDelayMs?: number;
5
+ readonly maxRetries?: number;
4
6
  }
5
7
  export declare function createUnitManifestLoader(options?: UnitManifestLoaderOptions): (registry: ClientUnitRegistry) => void;
@@ -1,7 +1,7 @@
1
1
  import type { DshHostContext, HostSurface } 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, LongTaskBase, LongTaskChange, LongTaskRegistry, UnitMountDeps, UnitMountResult, UnitCall } from '@dsh-workbench/shared/host';
4
+ import type { ContextRenderer, LongTaskBase, LongTaskChange, LongTaskRegistry, Seam, UnitMountDeps, UnitMountResult, UnitCall } from '@dsh-workbench/shared/host';
5
5
  import type { DataReader } from '@dsh-workbench/shared/host';
6
6
  import type { HostUnit } from './unit-registry';
7
7
  import { type UnitReadiness } from './unit-readiness';
@@ -69,6 +69,7 @@ export declare function mountUnits(units: readonly HostUnit[], deps: {
69
69
  store?: UnitMountDeps['store'];
70
70
  values?: UnitMountDeps['values'];
71
71
  surface?: HostSurface | undefined;
72
+ seam?: Seam | undefined;
72
73
  longTasks?: {
73
74
  readonly scope: string;
74
75
  readonly bump: (facts: readonly string[]) => void;
@@ -1,10 +1,9 @@
1
- import type { DshShell } from '@dsh-workbench/shared';
1
+ import { type Seam } from '@dsh-workbench/shared/host';
2
2
  import { type LineMaker, type BrowserStep } from './diy-browser';
3
3
  export declare const ACT_TIMEOUT_MS = 15000;
4
4
  export interface ActStep extends BrowserStep {
5
5
  readonly payload: Record<string, unknown> | undefined;
6
6
  }
7
- export declare function actBrowser(shell: DshShell, command: string, session: string, argv: readonly string[], timeoutMs?: number, line?: LineMaker): Promise<ActStep>;
7
+ export declare function actBrowser(seam: Seam, command: string, session: string, argv: readonly string[], timeoutMs?: number, line?: LineMaker): Promise<ActStep>;
8
8
  export declare function actErrorOf(step: ActStep): string;
9
9
  export declare const SWEEP_TIMEOUT_MS = 4000;
10
- export declare function stopNetworkExact(shell: DshShell, file: string, timeoutMs?: number): Promise<boolean>;
@@ -0,0 +1,14 @@
1
+ import type { PngRect } from '../../../shared/api/host/png-crop';
2
+ export interface PngClip {
3
+ readonly x: number;
4
+ readonly y: number;
5
+ readonly width: number;
6
+ readonly height: number;
7
+ }
8
+ export declare function clipOf(value: unknown): PngClip | undefined;
9
+ export declare function deviceClipRect(clip: PngClip, dpr: number): PngRect;
10
+ export declare function clipNote(clip: PngClip, viewport: {
11
+ readonly width: number;
12
+ readonly height: number;
13
+ }): string;
14
+ export declare function defaultShotPath(dir: string, unit: string, stamp: number): string;
@@ -1,13 +1,6 @@
1
1
  import type { DshHostContext, DshToolRegistry } from '@dsh-workbench/shared';
2
- import { type PngRect } from '../../../shared/api/host/png-crop';
3
2
  import { type PanelsToolName } from '../unit';
4
3
  export declare const CARD_TOKEN = "$card";
5
- export interface PngClip {
6
- readonly x: number;
7
- readonly y: number;
8
- readonly width: number;
9
- readonly height: number;
10
- }
11
4
  export type CssTarget = {
12
5
  readonly kind: 'positional';
13
6
  readonly at: number;
@@ -28,12 +21,6 @@ export interface BrowserToolRow {
28
21
  export declare function cardSelectorIn(unit: string): string;
29
22
  export declare function evalWrapped(script: string, card: string): string;
30
23
  export declare function argvOf(row: BrowserToolRow, raw: Record<string, unknown>, unit: string): string[];
31
- export declare function clipOf(value: unknown): PngClip | undefined;
32
- export declare function deviceClipRect(clip: PngClip, dpr: number): PngRect;
33
- export declare function clipNote(clip: PngClip, viewport: {
34
- readonly width: number;
35
- readonly height: number;
36
- }): string;
37
- export declare function defaultShotPath(dir: string, unit: string, stamp: number): string;
38
24
  export declare const BROWSER_TOOLS: readonly BrowserToolRow[];
39
25
  export declare function registerBrowserTools(ctx: DshHostContext, tools: DshToolRegistry): readonly (() => void)[];
26
+ export { clipNote, clipOf, defaultShotPath, deviceClipRect, type PngClip } from './diy-browser-clip';
@@ -1,4 +1,4 @@
1
- import type { DshShell } from '@dsh-workbench/shared';
1
+ import { type Seam, type WriteIntent } from '@dsh-workbench/shared/host';
2
2
  export declare const LOOK_TIMEOUT_MS = 30000;
3
3
  export interface BrowserStep {
4
4
  readonly ok: boolean;
@@ -10,7 +10,7 @@ export interface BrowserStep {
10
10
  }
11
11
  export type LineMaker = (command: string, argv: readonly string[]) => string;
12
12
  export declare function plainLine(command: string, argv: readonly string[]): string;
13
- export declare function runBrowserStep(shell: DshShell, command: string, argv: readonly string[], timeoutMs?: number, line?: LineMaker): Promise<BrowserStep>;
13
+ export declare function runBrowserStep(seam: Seam, command: string, argv: readonly string[], timeoutMs?: number, line?: LineMaker, intent?: WriteIntent): Promise<BrowserStep>;
14
14
  export declare function jsonOf(raw: string): Record<string, unknown> | undefined;
15
15
  export declare function textOf(value: unknown): string;
16
16
  export interface BoundTab {
@@ -19,7 +19,7 @@ export interface BoundTab {
19
19
  readonly title: string;
20
20
  readonly reason: string;
21
21
  }
22
- export declare function bindCurrentTab(shell: DshShell, command: string, session: string, timeoutMs?: number, line?: LineMaker): Promise<BoundTab>;
22
+ export declare function bindCurrentTab(seam: Seam, command: string, session: string, timeoutMs?: number, line?: LineMaker): Promise<BoundTab>;
23
23
  export interface WorkbenchPage {
24
24
  readonly ok: boolean;
25
25
  readonly url: string;
@@ -29,12 +29,12 @@ export interface WorkbenchPage {
29
29
  readonly open: boolean | null;
30
30
  readonly shown: boolean;
31
31
  }
32
- export declare function workbenchPageOf(shell: DshShell, command: string, session: string): Promise<WorkbenchPage>;
33
- export declare function writeShotsDir(shell: DshShell, dir: string): Promise<boolean>;
32
+ export declare function workbenchPageOf(seam: Seam, command: string, session: string): Promise<WorkbenchPage>;
33
+ export declare function writeShotsDir(seam: Seam, dir: string): Promise<boolean>;
34
34
  export interface PageHandshake {
35
35
  readonly ok: boolean;
36
36
  readonly bound: boolean;
37
37
  readonly page: WorkbenchPage;
38
38
  readonly reason: string;
39
39
  }
40
- export declare function readyPageOf(shell: DshShell, command: string, session: string): Promise<PageHandshake>;
40
+ export declare function readyPageOf(seam: Seam, command: string, session: string): Promise<PageHandshake>;
@@ -1,4 +1,5 @@
1
- import type { DshHostContext, DshShell, DshToolRunContext } from '@dsh-workbench/shared';
1
+ import type { DshHostContext, DshToolRunContext } from '@dsh-workbench/shared';
2
+ import { type Seam } from '@dsh-workbench/shared/host';
2
3
  import type { DebugState } from '@dsh-workbench/shared/host';
3
4
  import { type BoardFactState, type BoardProbe, type BoardSituation } from '@dsh-workbench/shared/host';
4
5
  import { type LineMaker, type WorkbenchPage } from './diy-browser';
@@ -8,7 +9,7 @@ export interface PageHandle {
8
9
  readonly artifactsDir: string;
9
10
  readonly unit: string;
10
11
  readonly args: Record<string, unknown>;
11
- readonly shell: DshShell;
12
+ readonly seam: Seam;
12
13
  readonly command: string;
13
14
  readonly session: string;
14
15
  readonly line?: LineMaker;
@@ -1,7 +1,7 @@
1
- import type { DshShell } from '@dsh-workbench/shared';
1
+ import type { Seam } from '@dsh-workbench/shared/host';
2
2
  export declare function samePageOf(here: string, want: string): boolean;
3
3
  export declare function openRecordPage(input: {
4
- readonly shell: DshShell;
4
+ readonly seam: Seam;
5
5
  readonly command: string;
6
6
  readonly session: string;
7
7
  readonly url: string;
@@ -1,13 +1,13 @@
1
- import type { DshHostContext, DshShell } from '@dsh-workbench/shared';
1
+ import type { DshHostContext } from '@dsh-workbench/shared';
2
2
  import type { RecordState, RecordStore } from '@dsh-workbench/shared/host';
3
- import { type LineMaker } from './diy-browser';
3
+ import { type Seam } from '@dsh-workbench/shared/host';
4
4
  import type { CaptureEntry } from './diy-record-capture';
5
5
  import type { RecordCall, RecordListRow, RecordPageRead } from './diy-record-text';
6
6
  export declare const OPEN_TIMEOUT_MS = 30000;
7
7
  export declare const SETTLE_MS = 2000;
8
8
  export declare const WAIT_CAP_MS: number;
9
9
  export declare const POLL_MS = 1000;
10
- export declare const STATIC_URL_PATTERN = "^(data:)|(\\.(js|css|png|jpe?g|gif|svg|woff2?|ico|map|webp|mp4)(\\?|$))";
10
+ export { STATIC_URL_PATTERN } from '../../../shared/api/host/diy-capture-live';
11
11
  export declare const DETAIL_MAX_BYTES = 60000;
12
12
  export declare const pauseFor: (ms: number) => Promise<void>;
13
13
  export declare function waitOf(value: unknown): number;
@@ -16,10 +16,10 @@ export declare function captureFileOf(artifactsDir: string, unit: string): strin
16
16
  export declare function lastCaptureFileOf(file: string): string;
17
17
  export declare function shotFileOf(captureFile: string, unit: string, n: number): string;
18
18
  export declare function takeShotOf(input: WatchFinishDeps, held: RecordState, n: number): Promise<void>;
19
- export declare function startRecordCapture(shell: DshShell, command: string, session: string, file: string, makeLine?: LineMaker): Promise<boolean>;
19
+ export declare function startRecordCapture(seam: Seam, command: string, session: string, file: string): Promise<boolean>;
20
20
  export interface WatchFinishDeps {
21
21
  readonly ctx: DshHostContext;
22
- readonly shell: DshShell;
22
+ readonly seam: Seam;
23
23
  readonly command: string;
24
24
  readonly sessionId: string;
25
25
  readonly store: RecordStore;
@@ -43,15 +43,15 @@ export interface CaptureRead {
43
43
  readonly truncated: boolean;
44
44
  readonly round: string;
45
45
  }
46
- export declare function captureLinesOf(shell: DshShell, file: string, timeoutMs?: number): Promise<number>;
47
- export declare function captureRoundOf(shell: DshShell, file: string, timeoutMs?: number): Promise<string>;
48
- export declare function captureTextOf(shell: DshShell, file: string, timeoutMs?: number): Promise<{
46
+ export declare function captureLinesOf(file: string): number;
47
+ export declare function captureRoundOf(file: string): string;
48
+ export declare function captureTextOf(file: string): {
49
49
  readonly text: string;
50
50
  readonly truncated: boolean;
51
- }>;
52
- export declare function captureReadOf(shell: DshShell, file: string, timeoutMs?: number): Promise<CaptureRead>;
53
- export declare function keepCaptureOf(shell: DshShell, file: string, timeoutMs?: number): Promise<boolean>;
54
- export declare function captureLinesWithKeyOf(shell: DshShell, file: string, key: string, timeoutMs?: number): Promise<string>;
51
+ };
52
+ export declare function captureReadOf(file: string): CaptureRead;
53
+ export declare function keepCaptureOf(file: string): boolean;
54
+ export declare function captureLinesWithKeyOf(file: string, key: string): string;
55
55
  export interface SegmentBundle {
56
56
  readonly capture: CaptureRead;
57
57
  readonly entries: readonly CaptureEntry[];
@@ -65,7 +65,7 @@ export declare function hookCallOf(page: RecordPageRead, key: string): RecordCal
65
65
  export declare function detailOfEntry(entry: CaptureEntry, maxBytes: number, ambiguous?: number): Record<string, unknown>;
66
66
  export declare function detailOfCall(call: RecordCall, maxBytes: number): Record<string, unknown>;
67
67
  export declare function releaseRecord(input: {
68
- readonly shell: DshShell;
68
+ readonly seam: Seam;
69
69
  readonly command: string;
70
70
  readonly session: string;
71
71
  readonly url: string;
@@ -75,7 +75,7 @@ export declare function releaseRecord(input: {
75
75
  readonly capture: boolean;
76
76
  }>;
77
77
  export declare function releaseQuietly(input: {
78
- readonly shell: DshShell;
78
+ readonly seam: Seam;
79
79
  readonly command: string;
80
80
  readonly session: string;
81
81
  readonly url: string;
@@ -1,6 +1,6 @@
1
- import type { DshShell } from '@dsh-workbench/shared';
2
1
  import type { ProfileModule } from '@dsh-workbench/shared/host';
3
2
  import type { DiscoverDoc, DiscoverDocKind, DiscoverEntry, DiscoverFilter, DiscoverPayload } from '@dsh-workbench/shared/contract/protocol/market-index';
3
+ import { type Seam } from '@dsh-workbench/shared/host';
4
4
  import type { MarketIndexReader } from '../../../shared/api/host/market-index-fetch';
5
5
  import type { MarketDocReader } from '../../../shared/api/host/market-doc';
6
6
  import type { MarketSourcesStore } from '../../../shared/api/host/market-sources-store';
@@ -17,7 +17,7 @@ export interface MarketDiscoverOptions {
17
17
  readonly modules: () => readonly ProfileModule[];
18
18
  readonly defaultRegistry: () => Promise<string | undefined>;
19
19
  readonly profilePath?: string | undefined;
20
- readonly shell?: DshShell | undefined;
20
+ readonly seam?: Seam | undefined;
21
21
  readonly shellVersion?: string | undefined;
22
22
  readonly fetchImpl?: ((url: string, init: RequestInit) => Promise<Response>) | undefined;
23
23
  readonly now?: (() => number) | undefined;
@@ -1,9 +1,10 @@
1
- import type { ProfilePackage } from '@dsh-workbench/shared/host';
1
+ import type { ProfilePackage, Seam } from '@dsh-workbench/shared/host';
2
2
  import { type MigrationRunInput, type MigrationRunResult } from '../../../shared/api/host/migrate-workbench';
3
3
  export interface WorkbenchFollowUpDeps {
4
4
  readonly dshHome: (() => string) | undefined;
5
5
  readonly profileName: (() => string | null) | undefined;
6
6
  readonly workbench: ((pkg: string) => ProfilePackage | undefined) | undefined;
7
+ readonly seam?: Seam | undefined;
7
8
  readonly runMigration?: ((input: MigrationRunInput) => Promise<MigrationRunResult>) | undefined;
8
9
  }
9
10
  export interface WorkbenchFollowUpActions {
@@ -1,5 +1,4 @@
1
- import type { DshShell } from '@dsh-workbench/shared';
2
- import type { PluginSourceCommand } from '@dsh-workbench/shared/host';
1
+ import type { PluginSourceCommand, Seam } from '@dsh-workbench/shared/host';
3
2
  import type { BundleChange } from '../../../kernel/contract/bundle-install';
4
3
  import type { BundleManager } from '@dsh-workbench/shared/host';
5
4
  import type { InstalledModule } from '@dsh-workbench/shared/host';
@@ -11,7 +10,7 @@ export interface BundleInstallDeps {
11
10
  readonly options?: BundleInstallOptions | undefined;
12
11
  readonly registry?: string | undefined;
13
12
  readonly command: string;
14
- readonly shell?: DshShell | undefined;
13
+ readonly seam?: Seam | undefined;
15
14
  readonly supply?: SupplyPort | undefined;
16
15
  readonly manager: BundleManager;
17
16
  readonly installed?: ((pkg: string) => InstalledModule) | undefined;
@@ -1,12 +1,11 @@
1
- import type { DshShell } from '@dsh-workbench/shared';
2
- import type { BundleManager, SupplyPort } from '@dsh-workbench/shared/host';
1
+ import type { BundleManager, Seam, SupplyPort } from '@dsh-workbench/shared/host';
3
2
  import type { InstalledModule, ProfileModule } from '@dsh-workbench/shared/host';
4
3
  import { type ReplaceBundleDeps } from './market-route';
5
4
  import type { BundleInstallOutcome } from './market-types';
6
5
  export interface BundleUpdateDeps {
7
6
  readonly modules: (() => readonly ProfileModule[]) | undefined;
8
7
  readonly installed: ((pkg: string) => InstalledModule) | undefined;
9
- readonly shell: DshShell | undefined;
8
+ readonly seam: Seam | undefined;
10
9
  readonly manager: BundleManager;
11
10
  readonly routeDeps: ReplaceBundleDeps;
12
11
  readonly sweep: () => Promise<void>;
@@ -1,11 +1,11 @@
1
- import type { DshShell } from '@dsh-workbench/shared';
1
+ import { type Seam } from '@dsh-workbench/shared/host';
2
2
  import type { InstalledModule, ProfilePackage, SupplyPort } from '@dsh-workbench/shared/host';
3
3
  import type { SelfUpdateRequest, SelfUpdateStart } from '@dsh-workbench/shared/host';
4
4
  import type { BundleInstallOutcome } from './market-types';
5
5
  export interface WorkbenchUpdateDeps {
6
6
  readonly asked: string;
7
7
  readonly workbench?: ((pkg: string) => ProfilePackage | undefined) | undefined;
8
- readonly shell?: DshShell | undefined;
8
+ readonly seam?: Seam | undefined;
9
9
  readonly installed?: ((pkg: string) => InstalledModule) | undefined;
10
10
  readonly dshHome?: (() => string) | undefined;
11
11
  readonly profileRegistry?: (() => Promise<string | undefined>) | undefined;
@@ -1,9 +1,9 @@
1
- import type { DshShell } from '@dsh-workbench/shared';
2
1
  import type { UnitManifest } from '@dsh-workbench/shared';
3
2
  import type { BundleManager } from '@dsh-workbench/shared/host';
4
3
  import type { InstalledModule, ProfileModule, ProfilePackage } from '@dsh-workbench/shared/host';
5
4
  import type { RegistryNotebook } from '@dsh-workbench/shared/host';
6
5
  import { type SupplyPort, type UnitMountDeps } from '@dsh-workbench/shared/host';
6
+ import { type Seam } from '@dsh-workbench/shared/host';
7
7
  import type { SelfUpdateRequest, SelfUpdateStart } from '@dsh-workbench/shared/host';
8
8
  import { type WorkbenchFollowUpDeps } from './market-follow-up';
9
9
  import { type PluginReferences } from './plugin-actions';
@@ -15,7 +15,7 @@ export declare function createMarketService(options: {
15
15
  manifests: readonly UnitManifest[];
16
16
  manifestsNow?: (() => readonly UnitManifest[]) | undefined;
17
17
  probe?: UnitMountDeps['probe'];
18
- shell?: DshShell | undefined;
18
+ seam?: Seam | undefined;
19
19
  command: string;
20
20
  onInstalled?: (unit: string) => void;
21
21
  onUninstalled?: (unit: string) => void;
@@ -1,5 +1,4 @@
1
- import type { DshShell } from '@dsh-workbench/shared';
2
- import { type PluginSourceCommand, type SupplyPort } from '@dsh-workbench/shared/host';
1
+ import { type PluginSourceCommand, type Seam, type SupplyPort } from '@dsh-workbench/shared/host';
3
2
  import type { PluginLedger } from './plugin-ledger';
4
3
  export type PluginKept = {
5
4
  readonly kind: 'held';
@@ -38,7 +37,7 @@ export interface PluginActions {
38
37
  }
39
38
  export declare function createPluginActions(options: {
40
39
  readonly ledger?: PluginLedger | undefined;
41
- readonly shell?: DshShell | undefined;
40
+ readonly seam?: Seam | undefined;
42
41
  readonly command: string;
43
42
  readonly runAll: (commands: readonly PluginSourceCommand[]) => Promise<void>;
44
43
  readonly claimedBy?: ((plugin: string) => readonly string[]) | undefined;
@@ -1,16 +1,15 @@
1
- import type { DshShell } from '@dsh-workbench/shared';
2
- import { type RouteTable, type SupplyPort } from '@dsh-workbench/shared/host';
1
+ import { type RouteTable, type Seam, type SupplyPort } from '@dsh-workbench/shared/host';
3
2
  import type { InstalledPlugin } from '../../../shared/api/installed-plugins';
4
3
  import type { PluginLedger } from './plugin-ledger';
5
4
  export declare function installedPlugins(options: {
6
5
  readonly ledger: PluginLedger;
7
- readonly shell?: DshShell | undefined;
6
+ readonly seam?: Seam | undefined;
8
7
  readonly force?: boolean;
9
8
  readonly check?: boolean;
10
9
  readonly supply?: SupplyPort | undefined;
11
10
  }): Promise<readonly InstalledPlugin[]>;
12
11
  export declare function pluginRoutes(options: {
13
12
  readonly ledger: PluginLedger;
14
- readonly shell?: DshShell | undefined;
13
+ readonly seam?: Seam | undefined;
15
14
  readonly supply?: SupplyPort | undefined;
16
15
  }): RouteTable;
@@ -1,8 +1,8 @@
1
- import type { DshHostContext, DshShell } from '@dsh-workbench/shared';
2
- import { type RouteHandler } from '@dsh-workbench/shared/host';
1
+ import type { DshHostContext } from '@dsh-workbench/shared';
2
+ import { type RouteHandler, type Seam } from '@dsh-workbench/shared/host';
3
3
  import { type WorkbenchSelfUpdate } from '../../../kernel/contract/bundle-install';
4
4
  export declare function bundleRegistriesHandler(ctx: DshHostContext): RouteHandler;
5
5
  export declare function resetRefusalLog(): void;
6
6
  export declare function resetHoldLog(): void;
7
- export declare function moduleVersionsHandler(ctx: DshHostContext, shell: DshShell | undefined, running?: string | undefined, selfUpdate?: (() => WorkbenchSelfUpdate | undefined) | undefined): RouteHandler;
7
+ export declare function moduleVersionsHandler(ctx: DshHostContext, seam: Seam | undefined, running?: string | undefined, selfUpdate?: (() => WorkbenchSelfUpdate | undefined) | undefined): RouteHandler;
8
8
  export declare function bundleInspectHandler(ctx: DshHostContext): RouteHandler;
@@ -1,3 +1,2 @@
1
- import type { DshHostContext } from '@dsh-workbench/shared';
2
- export declare function artifactsDirOf(ctx: DshHostContext, root: string): string;
1
+ export declare function artifactsDirOf(root: string): string;
3
2
  export declare function ensureDirOf(dir: string): void;
@@ -0,0 +1,25 @@
1
+ import { type Seam } from '@dsh-workbench/shared/host';
2
+ export declare const LIVE_POLL_MS = 3000;
3
+ export declare const LIVE_ARM_MS = 2000;
4
+ export declare const LIVE_SNAP_TIMEOUT_MS = 15000;
5
+ export declare const LIVE_TAIL_LINES = 20000;
6
+ export declare const LIVE_KEY_LINES = 20;
7
+ export declare const STATIC_URL_PATTERN = "^(data:)|(\\.(js|css|png|jpe?g|gif|svg|woff2?|ico|map|webp|mp4)(\\?|$))";
8
+ export declare function filterStaticLines(raw: string): string;
9
+ export declare function captureTickOnce(seam: Seam, command: string, session: string, file: string, timeoutMs?: number): Promise<string>;
10
+ export declare function startLiveCapture(input: {
11
+ readonly seam: Seam;
12
+ readonly command: string;
13
+ readonly session: string;
14
+ readonly file: string;
15
+ }): Promise<boolean>;
16
+ export declare function stopLiveCapture(file: string): boolean;
17
+ export declare function liveCaptureOf(file: string): boolean;
18
+ export declare function readCaptureLines(file: string): number;
19
+ export declare function readCaptureRound(file: string): string;
20
+ export declare function readCaptureText(file: string): {
21
+ readonly text: string;
22
+ readonly truncated: boolean;
23
+ };
24
+ export declare function readCaptureLinesWithKey(file: string, key: string): string;
25
+ export declare function keepCaptureFile(file: string): boolean;
@@ -1,4 +1,4 @@
1
- import type { DshShell } from '@dsh-workbench/shared';
1
+ import { type Seam } from '@dsh-workbench/shared/host';
2
2
  export declare const SURFACE_TIMEOUT_MS = 30000;
3
3
  export declare const EXCERPT_LINES = 60;
4
4
  export declare const SUMMARY_PER_BUCKET = 12;
@@ -20,7 +20,7 @@ export declare function wantsKit(scope: SurfaceScope): boolean;
20
20
  export declare function toolchainBinOf(root: string): string | null;
21
21
  export declare function toolchainBinAmong(root: string, dirs: readonly string[]): string | null;
22
22
  export declare function queryCommandOf(bin: string, only: 'kit' | 'primitives'): string;
23
- export declare function runSurfaceQuery(shell: DshShell, bin: string, only: 'kit' | 'primitives', root: string, fallbackBin?: string): Promise<SurfacePayload>;
23
+ export declare function runSurfaceQuery(seam: Seam, bin: string, only: 'kit' | 'primitives', root: string, fallbackBin?: string): Promise<SurfacePayload>;
24
24
  export declare function filesOf(payload: SurfacePayload | undefined): Record<string, string>;
25
25
  export declare function rootsOf(payload: SurfacePayload | undefined): Record<string, string>;
26
26
  export declare function countsOf(payload: SurfacePayload | undefined): Record<string, number>;
@@ -0,0 +1,6 @@
1
+ export declare function stagingDirOf(unit: string): string;
2
+ export declare function journalFileOf(staging: string, unit: string): string;
3
+ export declare function prepareStaging(unit: string, resume: boolean): string;
4
+ export declare function cleanupStaging(unit: string): void;
5
+ export declare function adoptTarballFile(file: string, unit: string): string | undefined;
6
+ export declare function mirrorJournal(staging: string, unit: string): void;
@@ -1,2 +1,2 @@
1
1
  import type { DshHostContext } from '@dsh-workbench/shared';
2
- export declare function workshopPathOf(ctx: DshHostContext): string | null;
2
+ export declare function workshopPathOf(_ctx: DshHostContext): string | null;
@@ -1,3 +1,3 @@
1
1
  export declare function gitNoPromptEnv(platform?: NodeJS.Platform): Readonly<Record<string, string>>;
2
- export declare function gitNoPromptProcessEnv(parent?: NodeJS.ProcessEnv, platform?: NodeJS.Platform): NodeJS.ProcessEnv;
2
+ export declare function gitNoPromptProcessEnv(parent?: NodeJS.ProcessEnv, platform?: NodeJS.Platform): Record<string, string>;
3
3
  export declare function withoutAskpassNoise(text: string): string;
@@ -1,3 +1,4 @@
1
+ import type { Seam } from '@dsh-workbench/shared/host';
1
2
  export interface GitRunResult {
2
3
  readonly exitCode: number | null;
3
4
  readonly stdout: string;
@@ -10,4 +11,6 @@ export interface GitRunOptions {
10
11
  readonly maxBytes?: number;
11
12
  }
12
13
  export type GitRunner = (args: readonly string[], options?: GitRunOptions) => Promise<GitRunResult>;
14
+ export declare function provideGitProcessSeam(seam: Seam | undefined): void;
15
+ export declare function createGitRunner(seam: Seam): GitRunner;
13
16
  export declare const runGitProcess: GitRunner;
@@ -0,0 +1,4 @@
1
+ import type { DshHostContext } from '@dsh-workbench/shared';
2
+ import type { AdapterSet } from '@dsh-workbench/shared/host';
3
+ export declare function shippedAdapterSetSpec(moduleUrl: string): string;
4
+ export declare function shippedAdapterSet(ctx: DshHostContext): Promise<AdapterSet>;
@@ -0,0 +1,3 @@
1
+ import type { DshHostContext } from '@dsh-workbench/shared';
2
+ import { type Seam } from '@dsh-workbench/shared/host';
3
+ export declare function provideWorkbenchSeam(ctx: DshHostContext): Seam | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dsh-workbench/core",
3
- "version": "1.1.14-beta.2",
3
+ "version": "1.1.15",
4
4
  "description": "个人工作台:Agent 工作台(左栏 + 常驻对话 + 自研右侧数据面板)。",
5
5
  "type": "module",
6
6
  "icon": "./icon.svg",
@@ -31,7 +31,6 @@
31
31
  "cordis.patch.yml",
32
32
  "icon.svg",
33
33
  "bin",
34
- "profile",
35
34
  "skills",
36
35
  "preset",
37
36
  "scripts/create-workbench.mjs",
@@ -82,7 +81,6 @@
82
81
  "@types/proper-lockfile": "^4.1.4",
83
82
  "@types/react": "^19.3.0",
84
83
  "@types/which": "^3.0.4",
85
- "@types/write-file-atomic": "^4.0.3",
86
84
  "@vitest/coverage-v8": "^5.0.2",
87
85
  "esbuild": "^0.28.2",
88
86
  "react": "^19.3.0",
@@ -95,13 +93,12 @@
95
93
  },
96
94
  "dependencies": {
97
95
  "dayjs": "^1.11.23",
98
- "execa": "^10.2.0",
99
96
  "prompts": "^2.4.2",
100
97
  "proper-lockfile": "^4.1.2",
101
98
  "which": "^7.0.0",
102
99
  "write-file-atomic": "^8.0.0",
103
- "@dsh-workbench/adapters-default": "1.1.14-beta.2",
104
- "@dsh-workbench/shared": "1.1.14-beta.2"
100
+ "@dsh-workbench/adapters-default": "1.1.15",
101
+ "@dsh-workbench/shared": "1.1.15"
105
102
  },
106
103
  "license": "MIT",
107
104
  "repository": {
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # 一次性引导:从 shipped 的 web 模板创建 workbench profile,
4
4
  # 继承 web 的 **bundle 清单**(这台机器上装了哪些 bundle),
5
- # 补上可写根那一行;新 profile 直接跟 web 共用数据根,旧 profile 保持原状,等用户跑 migrate。
5
+ # 清掉旧版留下的可写根那一行(现在由产品代码声明);新 profile 直接跟 web 共用数据根,旧 profile 保持原状,等用户跑 migrate。
6
6
  #
7
7
  # **设置不在这里继承**(这里曾经把 web 的 cordis.patch.yml 快照一份过来):
8
8
  # 工作台自己的 patch 是唯一真相,想同步 web 的哪几行由用户走「设置 → 配置同步」。
@@ -176,7 +176,7 @@ console.log("→ profile 里那条 link: 指的是我这份装出来的副本(
176
176
  '
177
177
  fi
178
178
 
179
- # ── 第 3 步:数据根配置 + 可写根那一行 ─────────────────────────────────
179
+ # ── 第 3 步:数据根配置(顺手清掉旧版塞进来的可写根那一行)─────────────
180
180
  #
181
181
  # 新 profile 跟 `dsh web` / Desktop 一样只分 profile,数据落在 `$DSH_HOME`。
182
182
  # 旧 profile 如果还有没迁的数据,这里只打印 migrate 提示,保持隔离、不动数据;
@@ -203,7 +203,7 @@ fi
203
203
 
204
204
  cat <<EOF
205
205
 
206
- profile '$DST_PROFILE' 的骨架好了(bundle 清单 + 可写根)。
206
+ profile '$DST_PROFILE' 的骨架好了(bundle 清单)。
207
207
  旧实例如果还有数据没迁,启动时会提示;要切共用根并并旧数据,跑 dsh-workbench migrate。
208
208
 
209
209
  设置按创建时的勾选从 $SRC_PROFILE_NAME 继承(只同步改已有插件的行;挂新插件的行不同步);
@@ -13,17 +13,13 @@ import {
13
13
  import { randomUUID } from 'node:crypto';
14
14
  import { homedir } from 'node:os';
15
15
  import { dirname, join, resolve } from 'node:path';
16
- import { fileURLToPath } from 'node:url';
17
- import { appendBlocks, parseBlocks, removeBlocks } from './patch-blocks.mjs';
16
+ import { parseBlocks, removeBlocks } from './patch-blocks.mjs';
18
17
 
19
- const SCRIPT_DIR = dirname(fileURLToPath(import.meta.url));
20
- const PKG_ROOT = dirname(SCRIPT_DIR);
21
18
  const HOME = process.env.DSH_HOME?.trim() || join(homedir(), '.dsh');
22
19
  const PROFILE = process.env.WORKBENCH_PROFILE?.trim() || 'workbench';
23
20
  const PROFILE_DIR = join(HOME, 'profiles', PROFILE);
24
21
  const RUNTIME_ROOT = process.env.DSH_WORKBENCH_HOME?.trim() || join(HOME, PROFILE);
25
22
  const PATCH_PATH = join(PROFILE_DIR, 'cordis.patch.yml');
26
- const SANDBOX_PATCH = join(PKG_ROOT, 'profile', 'sandbox.patch.yml');
27
23
  const MARKER = join(RUNTIME_ROOT, '.data-root-shared');
28
24
 
29
25
  const DATA_ROOT_IDS = new Set(['session-persistence-jsonl', 'storage-json', 'attachment-local']);
@@ -300,14 +296,19 @@ function writeMarker() {
300
296
  );
301
297
  }
302
298
 
299
+ const STALE_SANDBOX =
300
+ /workspaceRoot: !!js (?:process\.env\.DSH_WORKBENCH_HOME \?\? )?dshHomePath\(\s*['"]workbench['"]\)/;
301
+
303
302
  function inspectProfile() {
304
303
  const patch = readText(PATCH_PATH);
305
304
  if (patch === null) return null;
306
305
  const legacy = parseBlocks(patch).filter((block) => DATA_ROOT_IDS.has(block.id));
306
+ const sandbox = parseBlocks(patch).filter((block) => block.id === 'sandbox-policy' && STALE_SANDBOX.test(block.body));
307
307
  return {
308
308
  patch,
309
309
  ours: legacy.filter((block) => OWN_ROOT.test(block.body)),
310
310
  custom: legacy.filter((block) => !OWN_ROOT.test(block.body)),
311
+ sandbox,
311
312
  };
312
313
  }
313
314
 
@@ -328,14 +329,10 @@ function applySharedConfig(state) {
328
329
  writeAtomic(PATCH_PATH, patch);
329
330
  say(`数据根改回共用:从 ${PROFILE} 的 profile 里去掉 ${state.ours.map((block) => block.id).join(' / ')}。`);
330
331
  }
331
- const hasSandbox = parseBlocks(patch).some((block) => block.id === 'sandbox-policy');
332
- if (!hasSandbox) {
333
- const sandbox = readText(SANDBOX_PATCH);
334
- const row = sandbox === null ? undefined : parseBlocks(sandbox).find((block) => block.id === 'sandbox-policy');
335
- if (row !== undefined) {
336
- patch = appendBlocks(patch, row.body);
337
- writeAtomic(PATCH_PATH, patch);
338
- }
332
+ if (state.sandbox.length > 0) {
333
+ patch = removeBlocks(patch, (block) => block.id === 'sandbox-policy' && STALE_SANDBOX.test(block.body));
334
+ writeAtomic(PATCH_PATH, patch);
335
+ say(`可写根改由工作台自己声明:从 ${PROFILE} 的 profile 里去掉 sandbox-policy 那一行。`);
339
336
  }
340
337
  repairTarget(join(HOME, 'storages', 'workspace.json'));
341
338
  return true;