@dsh-workbench/core 1.1.8 → 1.1.9

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 (116) hide show
  1. package/bin/dsh-workbench +11 -45
  2. package/client.js +360 -303
  3. package/dist/client/client.body.js +360 -303
  4. package/dist/client/index.js +233 -176
  5. package/dist/host/index.js +4429 -3806
  6. package/dist/types/app/layouts/approval-detail.d.ts +5 -5
  7. package/dist/types/app/layouts/env-gate/gate-text.d.ts +5 -4
  8. package/dist/types/app/layouts/rightbar/MarketView.d.ts +25 -3
  9. package/dist/types/app/layouts/rightbar/market-rows.d.ts +0 -1
  10. package/dist/types/app/layouts/rightbar/market-view-text.d.ts +1 -2
  11. package/dist/types/app/layouts/sidebar/ProjectSwitcher.d.ts +1 -1
  12. package/dist/types/app/layouts/sidebar/workspace-groups.d.ts +4 -1
  13. package/dist/types/kernel/contract/index.d.ts +1 -0
  14. package/dist/types/modules/panels/model/diy-browser-act.d.ts +2 -2
  15. package/dist/types/modules/panels/model/diy-browser.d.ts +4 -2
  16. package/dist/types/modules/panels/model/diy-page.d.ts +2 -1
  17. package/dist/types/modules/panels/model/diy-record.d.ts +2 -1
  18. package/dist/types/modules/panels/model/diy-tools.d.ts +1 -0
  19. package/dist/types/modules/panels/model/market-dependency.d.ts +1 -1
  20. package/dist/types/modules/panels/model/market-env.d.ts +2 -0
  21. package/dist/types/modules/panels/model/market.d.ts +1 -1
  22. package/dist/types/modules/panels/model/plugin-ledger.d.ts +3 -0
  23. package/dist/types/modules/panels/model/plugin-name.d.ts +7 -3
  24. package/dist/types/modules/sessions/index.d.ts +1 -1
  25. package/dist/types/modules/sessions/model/attention.d.ts +1 -0
  26. package/dist/types/shared/api/host/diy-recon-fs.d.ts +1 -1
  27. package/dist/types/shared/api/host/diy-recon.d.ts +12 -5
  28. package/dist/types/shared/api/host/flow/task.d.ts +10 -0
  29. package/dist/types/shared/api/host/flow/tool.d.ts +12 -0
  30. package/dist/types/shared/api/host/host-routes.d.ts +2 -2
  31. package/dist/types/shared/api/host/plugin-term.d.ts +2 -0
  32. package/dist/types/shared/api/host/runtime-surface.d.ts +3 -0
  33. package/dist/types/shared/hooks/locale-text.d.ts +3 -0
  34. package/dist/types/shared/hooks/runtime-queries.d.ts +6 -0
  35. package/dist/types/shared/hooks/runtime-terms.d.ts +2 -0
  36. package/dist/types/shared/hooks/use-runtime-capabilities.d.ts +6 -0
  37. package/package.json +6 -3
  38. package/scripts/seed-workshop.sh +1 -1
  39. package/skills/workbench-module-diy/DESIGN.md +3 -1
  40. package/skills/workbench-module-diy/FLOW.md +117 -0
  41. package/skills/workbench-module-diy/PANEL.md +9 -7
  42. package/skills/workbench-module-diy/SKILL.md +7 -1
  43. package/skills/workbench-module-diy/STEPS.md +12 -1
  44. package/skills/workbench-module-diy/TOOLS.md +16 -4
  45. package/skills/workbench-module-diy/WIRING.md +2 -2
  46. package/skills/workbench-module-diy/WRITES.md +2 -2
  47. package/bin/opencli-isolated +0 -62
  48. package/bin/opencli-isolated.mjs +0 -44
  49. package/bin/opencli-node-mode.cjs +0 -1
  50. package/dist/types/app/layouts/rightbar/AskAgentButton.d.ts +0 -6
  51. package/dist/types/app/layouts/rightbar/board-columns.test.d.ts +0 -1
  52. package/dist/types/app/layouts/rightbar/dsh-borrow.test.d.ts +0 -1
  53. package/dist/types/app/layouts/rightbar/dsh-column-source.test.d.ts +0 -1
  54. package/dist/types/app/layouts/rightbar/dsh-surface.test.d.ts +0 -1
  55. package/dist/types/app/layouts/rightbar/presentation.test.d.ts +0 -1
  56. package/dist/types/app/layouts/rightbar/rightbar-width.test.d.ts +0 -1
  57. package/dist/types/app/layouts/rightbar/store.test.d.ts +0 -1
  58. package/dist/types/kernel/contract/contracts.test.d.ts +0 -1
  59. package/dist/types/kernel/contract/index.test.d.ts +0 -1
  60. package/dist/types/modules/panels/model/diy-browser-act.test.d.ts +0 -1
  61. package/dist/types/modules/panels/model/diy-browser-tools-shot.test.d.ts +0 -1
  62. package/dist/types/modules/panels/model/diy-browser-tools.test.d.ts +0 -1
  63. package/dist/types/modules/panels/model/diy-browser.test.d.ts +0 -1
  64. package/dist/types/modules/panels/model/diy-components.test.d.ts +0 -1
  65. package/dist/types/modules/panels/model/diy-context.test.d.ts +0 -1
  66. package/dist/types/modules/panels/model/diy-debug-routes.test.d.ts +0 -1
  67. package/dist/types/modules/panels/model/diy-debug-tools.test.d.ts +0 -1
  68. package/dist/types/modules/panels/model/diy-logs.test.d.ts +0 -1
  69. package/dist/types/modules/panels/model/diy-observers.test.d.ts +0 -1
  70. package/dist/types/modules/panels/model/diy-page.test.d.ts +0 -1
  71. package/dist/types/modules/panels/model/diy-record-bar.test.d.ts +0 -1
  72. package/dist/types/modules/panels/model/diy-record-beat.test.d.ts +0 -1
  73. package/dist/types/modules/panels/model/diy-record-capture.test.d.ts +0 -1
  74. package/dist/types/modules/panels/model/diy-record-close.test.d.ts +0 -1
  75. package/dist/types/modules/panels/model/diy-record-failure.test.d.ts +0 -1
  76. package/dist/types/modules/panels/model/diy-record-hook.test.d.ts +0 -1
  77. package/dist/types/modules/panels/model/diy-record-open.test.d.ts +0 -1
  78. package/dist/types/modules/panels/model/diy-record-routes.test.d.ts +0 -1
  79. package/dist/types/modules/panels/model/diy-record-shot.test.d.ts +0 -1
  80. package/dist/types/modules/panels/model/diy-record-text.test.d.ts +0 -1
  81. package/dist/types/modules/panels/model/diy-record.test.d.ts +0 -1
  82. package/dist/types/modules/panels/model/diy-schema.test.d.ts +0 -1
  83. package/dist/types/modules/panels/model/diy-spec.test.d.ts +0 -1
  84. package/dist/types/modules/panels/model/handoff.test.d.ts +0 -1
  85. package/dist/types/modules/panels/model/long-task-tools.test.d.ts +0 -1
  86. package/dist/types/modules/panels/model/market-install-error.test.d.ts +0 -1
  87. package/dist/types/modules/panels/model/market-installed.test.d.ts +0 -1
  88. package/dist/types/modules/panels/model/market-registry.test.d.ts +0 -1
  89. package/dist/types/modules/panels/model/market-remove.test.d.ts +0 -1
  90. package/dist/types/modules/panels/model/market-restart.test.d.ts +0 -1
  91. package/dist/types/modules/panels/model/market-sources-tool.test.d.ts +0 -1
  92. package/dist/types/modules/panels/model/market-swap-stuck.test.d.ts +0 -1
  93. package/dist/types/modules/panels/model/plugin-name.test.d.ts +0 -1
  94. package/dist/types/modules/panels/model/routes.test.d.ts +0 -1
  95. package/dist/types/modules/sessions/model/attention-long-task.test.d.ts +0 -1
  96. package/dist/types/modules/sessions/model/attention.test.d.ts +0 -1
  97. package/dist/types/modules/sessions/model/scroll-edges.test.d.ts +0 -1
  98. package/dist/types/modules/sessions/model/session-node.test.d.ts +0 -1
  99. package/dist/types/shared/api/config-sync.test.d.ts +0 -1
  100. package/dist/types/shared/api/diy.test.d.ts +0 -1
  101. package/dist/types/shared/api/dsh-plugins.test.d.ts +0 -1
  102. package/dist/types/shared/api/host/bundle-inspect-kind.test.d.ts +0 -1
  103. package/dist/types/shared/api/host/bundle-routes-self.test.d.ts +0 -1
  104. package/dist/types/shared/api/host/bundle-routes.test.d.ts +0 -1
  105. package/dist/types/shared/api/host/diy-facts.test.d.ts +0 -1
  106. package/dist/types/shared/api/host/diy-recon-fs.test.d.ts +0 -1
  107. package/dist/types/shared/api/host/diy-recon.test.d.ts +0 -1
  108. package/dist/types/shared/api/host/diy.test.d.ts +0 -1
  109. package/dist/types/shared/api/host/http.test.d.ts +0 -1
  110. package/dist/types/shared/api/host/png-crop.test.d.ts +0 -1
  111. package/dist/types/shared/api/host/runtime-seed.test.d.ts +0 -1
  112. package/dist/types/shared/api/host/self-update-marker.test.d.ts +0 -1
  113. package/dist/types/shared/api/host/shell.test.d.ts +0 -1
  114. package/dist/types/shared/api/unit-manifests.test.d.ts +0 -1
  115. package/dist/types/shared/components/blocker-action.test.d.ts +0 -1
  116. package/dist/types/shared/hooks/panel-state-report.test.d.ts +0 -1
@@ -1,4 +1,4 @@
1
- import type { ApprovalInput, ReactNode, Translate, UnitManifest, UnitToolOpencli } from '@dsh-workbench/shared';
1
+ import type { ApprovalInput, ReactNode, Translate, UnitManifest, UnitToolRuntime } from '@dsh-workbench/shared';
2
2
  import type { MarketSourcesPayload, PublishPreview } from '../../kernel/contract/market-index';
3
3
  export interface ApprovalRow {
4
4
  readonly label: string;
@@ -12,9 +12,9 @@ export interface ApprovalPlanView {
12
12
  readonly warn?: string | undefined;
13
13
  }
14
14
  export declare function marketSourceRows(tool: string, args: Readonly<Record<string, unknown>>, payload: MarketSourcesPayload | null | undefined, t: Translate): readonly ApprovalRow[];
15
- export declare function pluginToolIndexOf(manifests: readonly UnitManifest[]): ReadonlyMap<string, UnitToolOpencli>;
16
- export declare function pluginApprovalRows(origin: UnitToolOpencli, args: Readonly<Record<string, unknown>>, t: Translate): readonly ApprovalRow[];
15
+ export declare function pluginToolIndexOf(manifests: readonly UnitManifest[]): ReadonlyMap<string, UnitToolRuntime>;
16
+ export declare function pluginApprovalRows(origin: UnitToolRuntime, args: Readonly<Record<string, unknown>>, t: Translate): readonly ApprovalRow[];
17
17
  export declare function shellApprovalRenderer(manifests: () => readonly UnitManifest[]): (input: ApprovalInput, t: Translate) => ReactNode;
18
18
  export declare function shellClaimsApprovalDetail(tool: string): boolean;
19
- export declare function shellApprovalPlan(input: ApprovalInput, t: Translate, pluginTools?: ReadonlyMap<string, UnitToolOpencli> | undefined): ApprovalPlanView | undefined;
20
- export declare function shellApprovalDetail(input: ApprovalInput, t: Translate, pluginTools?: ReadonlyMap<string, UnitToolOpencli> | undefined): ReactNode;
19
+ export declare function shellApprovalPlan(input: ApprovalInput, t: Translate, pluginTools?: ReadonlyMap<string, UnitToolRuntime> | undefined): ApprovalPlanView | undefined;
20
+ export declare function shellApprovalDetail(input: ApprovalInput, t: Translate, pluginTools?: ReadonlyMap<string, UnitToolRuntime> | undefined): ReactNode;
@@ -1,14 +1,15 @@
1
1
  import type { Translate } from '@dsh-workbench/shared';
2
2
  import type { PreflightBridgeIssue, PreflightGuidance, PreflightSnapshot, PreflightStep } from '@dsh-workbench/shared/host';
3
+ import type { RuntimeProfile } from '@dsh-workbench/shared';
3
4
  export declare function failedStepText(guidance: PreflightGuidance | undefined, t: Translate): string;
4
5
  export declare function stepDetailText(step: PreflightStep, snapshot: PreflightSnapshot, t: Translate): string;
5
6
  export declare function showsRawDetails(snapshot: PreflightSnapshot): boolean;
6
- export declare const OPENCLI_EXTENSION_URL = "https://chromewebstore.google.com/detail/opencli/ildkmabpimmkaediidaifkhjpohdnifk";
7
+ export declare function showsRawAll(snapshot: PreflightSnapshot, panelShown: boolean): boolean;
7
8
  export interface BridgeAdvice {
8
- readonly textKey: string;
9
+ readonly text: string;
9
10
  readonly link?: {
10
- readonly labelKey: string;
11
+ readonly label: string;
11
12
  readonly href: string;
12
13
  };
13
14
  }
14
- export declare function bridgeAdvice(issue: PreflightBridgeIssue): BridgeAdvice;
15
+ export declare function bridgeAdvice(issue: PreflightBridgeIssue, t: Translate, fixes?: RuntimeProfile['bridge']): BridgeAdvice;
@@ -1,13 +1,15 @@
1
- import type { Translate } from '@dsh-workbench/shared';
1
+ import type { ReactNode, Translate } from '@dsh-workbench/shared';
2
2
  import type { UnitManifest } from '@dsh-workbench/shared';
3
3
  import type { CapabilityMap } from '../../../shared/hooks/use-capabilities';
4
4
  import type { MarketFreshness } from './market-freshness';
5
5
  import type { InstalledPlugin } from '../../../shared/api/installed-plugins';
6
- import { type InstalledWorkbenchModule } from './market-rows';
6
+ import { type InstalledWorkbenchModule, type MarketRow, type MarketRowAction, type SharedRow } from './market-rows';
7
7
  import type { TitleResolve } from './market-names';
8
8
  import type { MarketMock } from './market-mock';
9
+ import type { MarketFailure } from './market-row-types';
9
10
  import type { ModuleUpdateMap } from './market-rows';
10
11
  import type { WorkbenchSelfUpdate, WorkbenchVersion } from '../../../kernel/contract/bundle-install';
12
+ import { type Pending } from './market-view-text';
11
13
  import type { VersionsCheck, VersionsPart } from '../market/use-module-versions';
12
14
  export interface MarketViewProps {
13
15
  readonly t: Translate;
@@ -15,6 +17,7 @@ export interface MarketViewProps {
15
17
  readonly manifests: readonly UnitManifest[];
16
18
  readonly installable?: ReadonlySet<string> | null | undefined;
17
19
  readonly capabilities: CapabilityMap | null;
20
+ readonly runtimePluginMarket?: boolean | undefined;
18
21
  readonly freshness: MarketFreshness;
19
22
  readonly onChanged: (options?: {
20
23
  readonly force?: boolean;
@@ -35,4 +38,23 @@ export interface MarketViewProps {
35
38
  readonly defaults?: readonly string[] | undefined;
36
39
  readonly changed?: Readonly<Record<string, number>> | undefined;
37
40
  }
38
- export declare function MarketView({ t, titleOf, manifests, installable, capabilities, freshness, onChanged, onPending, updates, modulesCheck, pluginsCheck, onCheck, installed, installedRead, workbench, selfUpdate, plugins, settling, installing, mock, defaults, changed, }: MarketViewProps): JSX.Element;
41
+ export declare function MarketBody({ t, self, shown, pluginList, installedList, shared, pending, failed, notice, act, onConfirming, setDefault, boardBusy, checks, onRecheck, rechecking, runtimePluginMarket, }: {
42
+ readonly t: Translate;
43
+ readonly runtimePluginMarket?: boolean | undefined;
44
+ readonly self: MarketRow | undefined;
45
+ readonly shown: readonly MarketRow[];
46
+ readonly pluginList: readonly MarketRow[];
47
+ readonly installedList: readonly MarketRow[];
48
+ readonly shared: readonly SharedRow[];
49
+ readonly pending: Pending | null;
50
+ readonly failed: MarketFailure | null;
51
+ readonly notice: string | null;
52
+ readonly act: (id: string, action: MarketRowAction) => Promise<void>;
53
+ readonly onConfirming: (id: string | null) => void;
54
+ readonly setDefault: (id: string, next: boolean) => Promise<void>;
55
+ readonly boardBusy: boolean;
56
+ readonly checks: Readonly<Record<VersionsPart, ReactNode>>;
57
+ readonly onRecheck: () => void;
58
+ readonly rechecking: boolean;
59
+ }): JSX.Element;
60
+ export declare function MarketView({ t, titleOf, manifests, installable, capabilities, runtimePluginMarket, freshness, onChanged, onPending, updates, modulesCheck, pluginsCheck, onCheck, installed, installedRead, workbench, selfUpdate, plugins, settling, installing, mock, defaults, changed, }: MarketViewProps): JSX.Element;
@@ -41,7 +41,6 @@ export declare function latestCheckSummary(modules: readonly InstalledWorkbenchM
41
41
  export declare function checkedPluginCount(plugins: readonly InstalledPlugin[] | null | undefined): number;
42
42
  export declare function installedRows(modules: readonly InstalledWorkbenchModule[], manifests: readonly UnitManifest[], listed: ReadonlySet<string>, names?: MarketNameMap | undefined, defaults?: ReadonlySet<string>, changed?: Readonly<Record<string, number>>): MarketRow[];
43
43
  export declare function marketSwitchLocked(row: MarketRow): boolean;
44
- export declare function marketAsksAgent(row: MarketRow): boolean;
45
44
  export declare function marketActions(row: MarketRow): MarketRowAction[];
46
45
  export declare function capabilityOutdated(capabilities: CapabilityMap | null, unit: string): boolean;
47
46
  export declare function marketCatalog(manifests: readonly UnitManifest[], installable: ReadonlySet<string> | null | undefined): readonly UnitManifest[];
@@ -5,6 +5,7 @@ import type { MarketRow, MarketRowAction, ModuleUpdateMap } from './market-rows'
5
5
  import type { SharedRow } from './market-shared-rows';
6
6
  export declare const PROGRESS_KEY: Readonly<Record<MarketRowAction, string>>;
7
7
  export declare const ACTION_LABEL_KEY: Readonly<Record<MarketRowAction, string>>;
8
+ export declare const UPDATE_ACTIONS: readonly MarketRowAction[];
8
9
  export interface HeldRow {
9
10
  readonly id: string;
10
11
  readonly row: MarketRow;
@@ -48,5 +49,3 @@ export declare function pendingRowOf(input: {
48
49
  readonly rows: readonly MarketRow[];
49
50
  readonly names: MarketNameMap;
50
51
  }): MarketRow | undefined;
51
- export declare function askAgentReason(row: MarketRow, t: Translate): string;
52
- export declare function askAgentText(row: MarketRow, t: Translate): string;
@@ -1,5 +1,5 @@
1
1
  import type { Translate, WorkspaceView } from '@dsh-workbench/shared';
2
- import type { Attention } from '../../../modules/sessions';
2
+ import { type Attention } from '../../../modules/sessions';
3
3
  export interface ProjectSwitcherProps {
4
4
  items: readonly WorkspaceView[];
5
5
  current: WorkspaceView | null;
@@ -9,7 +9,10 @@ export interface WorkspaceSectionPlan<T> {
9
9
  readonly heading: string | null;
10
10
  readonly items: readonly T[];
11
11
  }
12
+ export interface WorkspaceSectionOptions<T> {
13
+ readonly rankOf?: ((item: T) => number) | undefined;
14
+ }
12
15
  export declare function workspaceSections<T extends {
13
16
  readonly path: string;
14
17
  readonly title: string;
15
- }>(items: readonly T[], headings: WorkspaceHeadings): readonly WorkspaceSectionPlan<T>[];
18
+ }>(items: readonly T[], headings: WorkspaceHeadings, options?: WorkspaceSectionOptions<T>): readonly WorkspaceSectionPlan<T>[];
@@ -1,4 +1,5 @@
1
1
  export type { UnitModuleFace, UnitMountDeps, UnitMountResult } from '@dsh-workbench/shared/host';
2
+ export type { FlowAction, FlowActionContext, FlowActionRegistry, FlowActionStep, FlowCheck, FlowDefinition, FlowForEach, FlowHost, FlowPoll, FlowPredicate, FlowProblem, FlowResult, FlowRetry, FlowRunOptions, FlowScope, FlowStep, FlowStepEvent, FlowSubFlowStep, FlowValue, HostKit, } from '@dsh-workbench/shared/host';
2
3
  export type { ExtensionCaller, ExtensionCallOptions, ExtensionNeed, ExtensionSession, CommandReader, ExtensionValue, GitReader, LibReader } from '@dsh-workbench/shared';
3
4
  export type { BoardModuleProps as BoardProps, CallOverrides, DataError, DataReader, DataRequest, DataResult, RequestRecipe, UnitClientApi, UnitClientFace, } from '@dsh-workbench/shared';
4
5
  export type { DshClientContext as ClientContext, DshHostContext as HostContext } from '@dsh-workbench/shared';
@@ -1,10 +1,10 @@
1
1
  import type { DshShell } from '@dsh-workbench/shared';
2
- import { type BrowserStep } from './diy-browser';
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): Promise<ActStep>;
7
+ export declare function actBrowser(shell: DshShell, 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
10
  export declare function stopNetworkExact(shell: DshShell, file: string, timeoutMs?: number): Promise<boolean>;
@@ -8,7 +8,9 @@ export interface BrowserStep {
8
8
  readonly timedOut: boolean;
9
9
  readonly truncated: boolean;
10
10
  }
11
- export declare function runBrowserStep(shell: DshShell, command: string, argv: readonly string[], timeoutMs?: number): Promise<BrowserStep>;
11
+ export type LineMaker = (command: string, argv: readonly string[]) => string;
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>;
12
14
  export declare function jsonOf(raw: string): Record<string, unknown> | undefined;
13
15
  export declare function textOf(value: unknown): string;
14
16
  export interface BoundTab {
@@ -17,7 +19,7 @@ export interface BoundTab {
17
19
  readonly title: string;
18
20
  readonly reason: string;
19
21
  }
20
- export declare function bindCurrentTab(shell: DshShell, command: string, session: string): Promise<BoundTab>;
22
+ export declare function bindCurrentTab(shell: DshShell, command: string, session: string, timeoutMs?: number, line?: LineMaker): Promise<BoundTab>;
21
23
  export interface WorkbenchPage {
22
24
  readonly ok: boolean;
23
25
  readonly url: string;
@@ -1,7 +1,7 @@
1
1
  import type { DshHostContext, DshShell, DshToolRunContext } from '@dsh-workbench/shared';
2
2
  import type { DebugState } from '@dsh-workbench/shared/host';
3
3
  import { type BoardFactState, type BoardProbe, type BoardSituation } from '@dsh-workbench/shared/host';
4
- import { type WorkbenchPage } from './diy-browser';
4
+ import { type LineMaker, type WorkbenchPage } from './diy-browser';
5
5
  export type BoardState = BoardFactState;
6
6
  export interface PageHandle {
7
7
  readonly root: string;
@@ -11,6 +11,7 @@ export interface PageHandle {
11
11
  readonly shell: DshShell;
12
12
  readonly command: string;
13
13
  readonly session: string;
14
+ readonly line?: LineMaker;
14
15
  readonly bound: boolean;
15
16
  readonly board: BoardState;
16
17
  readonly boardPath: string;
@@ -1,5 +1,6 @@
1
1
  import type { DshHostContext, DshShell } from '@dsh-workbench/shared';
2
2
  import type { RecordState, RecordStore } from '@dsh-workbench/shared/host';
3
+ import { type LineMaker } from './diy-browser';
3
4
  import type { CaptureEntry } from './diy-record-capture';
4
5
  import type { RecordCall, RecordListRow, RecordPageRead } from './diy-record-text';
5
6
  export declare const OPEN_TIMEOUT_MS = 30000;
@@ -15,7 +16,7 @@ export declare function captureFileOf(artifactsDir: string, unit: string): strin
15
16
  export declare function lastCaptureFileOf(file: string): string;
16
17
  export declare function shotFileOf(captureFile: string, unit: string, n: number): string;
17
18
  export declare function takeShotOf(input: WatchFinishDeps, held: RecordState, n: number): Promise<void>;
18
- export declare function startRecordCapture(shell: DshShell, command: string, session: string, file: string): Promise<boolean>;
19
+ export declare function startRecordCapture(shell: DshShell, command: string, session: string, file: string, makeLine?: LineMaker): Promise<boolean>;
19
20
  export interface WatchFinishDeps {
20
21
  readonly ctx: DshHostContext;
21
22
  readonly shell: DshShell;
@@ -1,5 +1,6 @@
1
1
  import type { DshHostContext } from '@dsh-workbench/shared';
2
2
  import type { DebugStore } from '@dsh-workbench/shared/host';
3
+ export declare function browserBridgeOn(ctx: DshHostContext): boolean;
3
4
  import type { PublishPreview } from '@dsh-workbench/shared/contract/protocol/market-index';
4
5
  import type { MarketService } from './market';
5
6
  import type { PanelsService } from './service';
@@ -25,7 +25,7 @@ export declare function parseDependencyId(id: string): {
25
25
  readonly kind: DependencyKind;
26
26
  readonly name: string;
27
27
  } | undefined;
28
- export declare function findDependency(manifests: readonly UnitManifest[], id: string, isReleased?: ((unit: string) => boolean) | undefined): DependencyTarget | undefined;
28
+ export declare function findDependency(manifests: readonly UnitManifest[], id: string, isReleased?: ((unit: string) => boolean) | undefined, packagePrefix?: string | undefined): DependencyTarget | undefined;
29
29
  export declare function affectedUnitsOf(manifests: readonly UnitManifest[], request: {
30
30
  readonly id?: string | undefined;
31
31
  readonly unit?: string | undefined;
@@ -12,6 +12,8 @@ export declare function createEnvDropper(options: {
12
12
  readonly references?: (() => PluginReferences) | undefined;
13
13
  readonly command: string;
14
14
  readonly run: (line: string, optional?: boolean) => Promise<void>;
15
+ readonly libUninstallCommand: (need: Need) => string;
16
+ readonly pluginPackagePrefix?: string | undefined;
15
17
  readonly logger?: {
16
18
  info?(message: string): void;
17
19
  warn?(message: string): void;
@@ -16,7 +16,7 @@ export declare function createMarketService(options: {
16
16
  manifestsNow?: (() => readonly UnitManifest[]) | undefined;
17
17
  probe?: UnitMountDeps['probe'];
18
18
  shell?: DshShell | undefined;
19
- command?: string | undefined;
19
+ command: string;
20
20
  onInstalled?: (unit: string) => void;
21
21
  onUninstalled?: (unit: string) => void;
22
22
  isReleased?: (unit: string) => boolean;
@@ -1,4 +1,5 @@
1
1
  import type { PluginLedgerEntry, WorkspaceStore } from '@dsh-workbench/shared/host';
2
+ import { type PluginFiles } from './plugin-name';
2
3
  export interface PluginLedgerIntent {
3
4
  readonly package: string;
4
5
  readonly registry?: string | undefined;
@@ -6,6 +7,7 @@ export interface PluginLedgerIntent {
6
7
  }
7
8
  export interface PluginLedger {
8
9
  readonly home: string;
10
+ readonly pluginFiles?: PluginFiles | undefined;
9
11
  list(): readonly PluginLedgerEntry[];
10
12
  all(): readonly PluginLedgerEntry[];
11
13
  read(pkg: string): PluginLedgerEntry | undefined;
@@ -19,4 +21,5 @@ export interface PluginLedger {
19
21
  export declare function createPluginLedger(options: {
20
22
  readonly store: WorkspaceStore;
21
23
  readonly home: string;
24
+ readonly pluginFiles?: PluginFiles | undefined;
22
25
  }): PluginLedger;
@@ -3,6 +3,10 @@ export interface PluginEntryRef {
3
3
  readonly local?: boolean | undefined;
4
4
  readonly name?: string | undefined;
5
5
  }
6
- export declare function pluginDirOf(entry: PluginEntryRef): string;
7
- export declare function pluginOnDisk(entry: PluginEntryRef): boolean;
8
- export declare function pluginNameOf(entry: PluginEntryRef): string | undefined;
6
+ export interface PluginFiles {
7
+ readonly dir?: string | undefined;
8
+ readonly manifest?: string | undefined;
9
+ }
10
+ export declare function pluginDirOf(entry: PluginEntryRef, files: PluginFiles | undefined): string;
11
+ export declare function pluginOnDisk(entry: PluginEntryRef, files: PluginFiles | undefined): boolean;
12
+ export declare function pluginNameOf(entry: PluginEntryRef, files: PluginFiles | undefined): string | undefined;
@@ -1,3 +1,3 @@
1
1
  export { currentSessionId, orderByRecency, sessionNode, orderSessionRows, sessionRows, workspaceOfSession, sessionStatuses, visiblePendingKind, type SessionNode, type SessionStatusDot, } from './model/session-node';
2
2
  export { scrollEdgesOf, type ScrollEdges } from './model/scroll-edges';
3
- export { attentionLabel, attentionOf, attentionOfSession, attentionSessionIdOf, attentionWordLabel, longTaskPresenceOf, type Attention, type AttentionInput, type AttentionSeverity, type LongTaskPresence, type WorkspaceAttention, } from './model/attention';
3
+ export { attentionLabel, attentionListRank, attentionOf, attentionOfSession, attentionSessionIdOf, attentionWordLabel, longTaskPresenceOf, type Attention, type AttentionInput, type AttentionSeverity, type LongTaskPresence, type WorkspaceAttention, } from './model/attention';
@@ -26,6 +26,7 @@ export interface AttentionInput {
26
26
  readonly currentWorkspaceId: string | null;
27
27
  readonly longTasks?: LongTaskPresence | undefined;
28
28
  }
29
+ export declare function attentionListRank(attention: WorkspaceAttention | null | undefined): number;
29
30
  export declare function attentionOfSession(summary: SessionSummary, statusById: SessionStatusSnapshot, sessions: SessionsSnapshot, longTaskIds?: ReadonlySet<string>): AttentionSeverity | undefined;
30
31
  export interface AttentionPickInput {
31
32
  readonly workspace: WorkspaceView | null;
@@ -1,3 +1,3 @@
1
1
  import { type ReconCommand, type ReconPlugin } from './diy-recon';
2
2
  export declare function reconCatalogOf(path: string): readonly ReconCommand[] | undefined;
3
- export declare function installedPluginsOf(dir: string): readonly ReconPlugin[];
3
+ export declare function installedPluginsOf(dir: string, prefix: string): readonly ReconPlugin[];
@@ -26,6 +26,13 @@ export interface ReconSite {
26
26
  readonly browser: boolean;
27
27
  readonly commands: readonly ReconCommand[];
28
28
  }
29
+ export interface ReconSurface {
30
+ readonly name: string;
31
+ readonly pluginPrefix: string;
32
+ invoke(site: string, command?: string): string;
33
+ help(site: string): string;
34
+ readonly authorHint?: string;
35
+ }
29
36
  export interface ReconPlugin {
30
37
  readonly name: string;
31
38
  readonly commands: readonly string[];
@@ -37,13 +44,13 @@ export interface ReconAnswer {
37
44
  readonly next: string;
38
45
  readonly text: string;
39
46
  }
40
- export declare function invocableOf(command: ReconCommand): string;
47
+ export declare function invocableOf(command: ReconCommand, surface: ReconSurface): string;
41
48
  export declare function manifestCommandsOf(raw: string): readonly ReconCommand[];
42
- export declare function pluginNamesOf(entries: readonly string[]): readonly string[];
49
+ export declare function pluginNamesOf(entries: readonly string[], prefix: string): readonly string[];
43
50
  export declare function pluginCommandsOf(files: readonly string[]): readonly string[];
44
51
  export declare function hostOf(url: string): string;
45
52
  export declare function keywordsOf(keyword: string, url: string): readonly string[];
46
53
  export declare function scoreOf(command: ReconCommand, word: string): number;
47
- export declare function reconOf(commands: readonly ReconCommand[], plugins: readonly ReconPlugin[], keywords: readonly string[]): ReconAnswer;
48
- export declare function nextOf(answer: ReconAnswer): string;
49
- export declare function textOf(answer: ReconAnswer): string;
54
+ export declare function reconOf(commands: readonly ReconCommand[], plugins: readonly ReconPlugin[], keywords: readonly string[], surface: ReconSurface): ReconAnswer;
55
+ export declare function nextOf(answer: ReconAnswer, surface: ReconSurface): string;
56
+ export declare function textOf(answer: ReconAnswer, surface: ReconSurface): string;
@@ -0,0 +1,10 @@
1
+ import { type FlowActionRegistry, type FlowDefinition, type LongTaskBase, type LongTaskDeps, type LongTaskRegistry } from '@dsh-workbench/shared/host';
2
+ export declare function flowTaskDeps(actions: FlowActionRegistry): Pick<LongTaskDeps<LongTaskBase>, 'run' | 'outcome' | 'view' | 'stopped'>;
3
+ export interface StartFlowOptions {
4
+ readonly runs: LongTaskRegistry<LongTaskBase>;
5
+ readonly flow: FlowDefinition;
6
+ readonly input: unknown;
7
+ readonly workspace: string;
8
+ readonly session?: string | undefined;
9
+ }
10
+ export declare function startFlow(options: StartFlowOptions): LongTaskBase;
@@ -0,0 +1,12 @@
1
+ import type { DshToolDefinition, DshToolRunContext } from '@dsh-workbench/shared';
2
+ import { type FlowActionRegistry, type FlowDefinition, type LongTaskBase, type LongTaskRegistry } from '@dsh-workbench/shared/host';
3
+ export interface FlowToolOptions {
4
+ readonly name: string;
5
+ readonly description: string;
6
+ readonly flow: FlowDefinition;
7
+ readonly actions: FlowActionRegistry;
8
+ readonly runs: LongTaskRegistry<LongTaskBase>;
9
+ readonly workspaceOf?: ((exec: DshToolRunContext | undefined) => string | null) | undefined;
10
+ readonly sessionOf?: ((exec: DshToolRunContext | undefined) => string | null) | undefined;
11
+ }
12
+ export declare function flowTool(options: FlowToolOptions): DshToolDefinition;
@@ -1,10 +1,10 @@
1
1
  import type { DshHostContext } from '@dsh-workbench/shared';
2
2
  import type { FactLog, ProfilePort, RouteTable } from '@dsh-workbench/shared/host';
3
- import type { OpencliResolution } from '@dsh-workbench/shared/host';
3
+ import type { RuntimeStatus } from '@dsh-workbench/shared/host';
4
4
  export declare function createHostRoutes(input: {
5
5
  readonly ctx: DshHostContext;
6
6
  readonly facts: FactLog;
7
- readonly opencli: OpencliResolution;
7
+ readonly runtimes: Readonly<Record<string, RuntimeStatus>>;
8
8
  readonly running: string | undefined;
9
9
  readonly profile: ProfilePort;
10
10
  }): RouteTable;
@@ -0,0 +1,2 @@
1
+ import type { DshHostContext } from '@dsh-workbench/shared';
2
+ export declare function pluginTermOf(ctx: DshHostContext): string;
@@ -0,0 +1,3 @@
1
+ import type { DshHostContext } from '@dsh-workbench/shared';
2
+ import type { RuntimeCommandSurface } from '@dsh-workbench/shared/host';
3
+ export declare function surfaceOf(ctx: DshHostContext): RuntimeCommandSurface | undefined;
@@ -0,0 +1,3 @@
1
+ import type { RuntimeText } from '@dsh-workbench/shared';
2
+ export declare function setRuntimeTextResolver(next?: (text: RuntimeText) => string): void;
3
+ export declare function runtimeText(text: RuntimeText): string;
@@ -0,0 +1,6 @@
1
+ import type { ApiResponse, RuntimeCapabilities, RuntimeProfile } from '@dsh-workbench/shared';
2
+ export type RuntimeCapabilitiesPayload = {
3
+ readonly capabilities: RuntimeCapabilities;
4
+ readonly runtimeProfile?: RuntimeProfile | null;
5
+ };
6
+ export declare function readRuntimeCapabilities(): Promise<ApiResponse<RuntimeCapabilitiesPayload>>;
@@ -0,0 +1,2 @@
1
+ import type { Translate } from '@dsh-workbench/shared';
2
+ export declare function runtimeTermsOf(t: Translate): Readonly<Record<string, string>>;
@@ -0,0 +1,6 @@
1
+ import type { RuntimeCapabilities, RuntimeProfile } from '@dsh-workbench/shared';
2
+ export declare function pluginMarketOf(capabilities: RuntimeCapabilities | undefined): boolean;
3
+ export declare function runtimeCapabilitiesValue(): RuntimeCapabilities | undefined;
4
+ export declare function runtimeProfileValue(): RuntimeProfile | undefined;
5
+ export declare function resetRuntimeCapabilities(): void;
6
+ export declare function useRuntimeCapabilities(): RuntimeCapabilities | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dsh-workbench/core",
3
- "version": "1.1.8",
3
+ "version": "1.1.9",
4
4
  "description": "个人工作台:Agent 工作台(左栏 + 常驻对话 + 自研右侧数据面板)。",
5
5
  "type": "module",
6
6
  "icon": "./icon.svg",
@@ -100,8 +100,8 @@
100
100
  "proper-lockfile": "^4.1.2",
101
101
  "which": "^7.0.0",
102
102
  "write-file-atomic": "^8.0.0",
103
- "@dsh-workbench/shared": "1.1.8",
104
- "@dsh-workbench/adapters-default": "1.1.8"
103
+ "@dsh-workbench/adapters-default": "1.1.9",
104
+ "@dsh-workbench/shared": "1.1.9"
105
105
  },
106
106
  "license": "MIT",
107
107
  "repository": {
@@ -113,6 +113,9 @@
113
113
  "bugs": {
114
114
  "url": "https://github.com/novaeth/dsh-workbench/issues"
115
115
  },
116
+ "workbench": {
117
+ "adapterSet": "@dsh-workbench/adapters-default"
118
+ },
116
119
  "scripts": {
117
120
  "build": "node scripts/build.mjs && node scripts/build-types.mjs",
118
121
  "build:host": "node scripts/build.mjs host",
@@ -524,7 +524,7 @@ fi
524
524
  # 且那句 pnpm 前缀每次都要写对)。这里给一个**与 cwd 无关**的同名入口,启动器把它
525
525
  # 挂进 PATH —— 于是"在工坊里"和"在别的目录里"都叫得动同一个工具链。
526
526
  #
527
- # 转发脚本而不是软链:同 `bin/opencli-isolated` 那条坑 —— pnpm publish 之后包里的脚本没有 x 位,
527
+ # 转发脚本而不是软链:同运行时包装那条坑 —— pnpm publish 之后包里的脚本没有 x 位,
528
528
  # 软链过去一执行就是 Permission denied。x 位由 chmod 当场给。
529
529
  # ⚠️ 先 rm -f:旧版本留下的软链还在时,`>` 会顺着软链把真脚本覆盖掉。
530
530
  ENTRY_DIR="$WORKBENCH_HOME/bin"
@@ -14,10 +14,12 @@
14
14
  | agent 写平台(提交、发布、改配置) | DIY | 预览 + 确认两拍([TOOLS.md](TOOLS.md) §5–§7) |
15
15
  | 用户已在浏览器登录过该系统,只是不知道数据在哪 | DIY | 复用登录探([DATASOURCE.md](DATASOURCE.md)) |
16
16
  | 要**新凭据**(账号 / 密钥 / token) | 工程 | 停;说清谁配什么 |
17
- | 多步长流程(要等、中途要人、失败要续) | 工程 | 同上 |
17
+ | 多步、要等、要重试、以后还要跑 | 先问 | 一次性 → 直接用工具跑;固化 → DIY 的 workflow([FLOW.md](FLOW.md));要新凭据 / 新服务 → 工程 |
18
18
  | 新服务 / 新进程 / 新依赖 | 工程 | 同上 |
19
19
  | 改工作台外壳,或改已发布模块 | 工程 | 同上 |
20
20
 
21
+ 多步长流程不是一律工程:复用现有登录、没有新凭据、要固化 → DIY 的 workflow;只有新凭据 / 新服务 / 新依赖才停。
22
+
21
23
  输出:一句结论 + 下一步 + 预计发生什么。
22
24
 
23
25
  ## 1 分工
@@ -0,0 +1,117 @@
1
+ # Workflow:先问一次性还是固化
2
+
3
+ 多步、要等、要重试、要写平台的活,**不要默认造模块**。先问一句,再决定。
4
+
5
+ ## 1 先问
6
+
7
+ 问用户(给推荐,允许一字通过):
8
+
9
+ > 这件事是一次性的,还是以后还要按同样步骤跑?我建议 **<一次性 / 固化>**,因为 **<重复信号 / 只此一次>**。
10
+
11
+ 只问一次;用户已经说过「就这一次 / 以后都要 / 固化」,照办,不追问。
12
+
13
+ | 信号 | 建议 |
14
+ |---|---|
15
+ | 用户说「以后 / 每次 / 每周 / 按这个流程 / 固化 / 做成按钮」 | 固化 |
16
+ | 三步以上、有先后依赖 | 固化 |
17
+ | 要等、轮询、重试、取消、中途登录 | 固化 |
18
+ | 要写平台、要审批、要留痕 | 固化 |
19
+ | 只这一次、还在探、单步读 / 写 | 一次性 |
20
+ | 拿不准 | 先一次性,跑通后用户再要固化 |
21
+
22
+ - **一次性**:不建模块、不写 flow;直接用现有工具 / 命令跑完,告诉用户「这次直接跑,没固化」。
23
+ - **固化**:进入第 2 节;先给流程形状,再问一次「按这个固化吗?」。
24
+
25
+ 不要问「要不要用 FlowDefinition / 怎么写代码 / 选哪个引擎」——这些是实现,用户不决定。
26
+
27
+ ## 2 固化后长什么样
28
+
29
+ 一条 workflow = 模块宿主半侧的一份 `FlowDefinition` + 动作表 + 长任务 + 工具(可选卡片)。
30
+ **v0 没有 flow 仓库,固化就是写进模块**,不是存一份 JSON。
31
+
32
+ 跑起来用户看到:
33
+
34
+ - 一条长任务行:到哪步、重试第几次、要登录、可停止、失败原因。
35
+ - 写平台前有一次审批(模块清单 `writes: true` + `needsApproval`)。
36
+ - 工具返回 `runId`;再调可看同一条。
37
+
38
+ 固化前给用户看这个形状(一句话 + 步骤表),问一次:
39
+
40
+ > 我建议固化成 N 步:A → B(每 5s 查,最多 5 次,找不到就触发)→ C;输入:…;写到:…;失败停在:…。按这个固化吗?
41
+
42
+ ## 3 怎么写
43
+
44
+ 只走宿主 kit(`mount(deps)` 的 `deps.flow`)与 `@dsh-workbench/core/contract` 的类型:
45
+
46
+ - `FlowDefinition` / `FlowStep` / `FlowValue` / `FlowPredicate` 从 `@dsh-workbench/core/contract` 取。
47
+ - `deps.flow.createActions()` / `deps.flow.check()` / `deps.flow.run()`。
48
+
49
+ 最小宿主半侧(长任务与工具的完整签名见 [TOOLS.md](TOOLS.md) §9):
50
+
51
+ ```ts
52
+ import type { FlowDefinition, UnitModuleFace } from '@dsh-workbench/core/contract';
53
+
54
+ const flow: FlowDefinition = {
55
+ id: 'release',
56
+ title: '发布',
57
+ target: { $ref: 'in.env' },
58
+ steps: [
59
+ { id: 'read', action: 'read' },
60
+ {
61
+ id: 'wait',
62
+ action: 'wait',
63
+ poll: {
64
+ everyMs: 5000,
65
+ maxMs: 300000,
66
+ until: { $eq: [{ $ref: 'value.state' }, { $lit: 'done' }] },
67
+ },
68
+ },
69
+ ],
70
+ };
71
+
72
+ export const face: UnitModuleFace = {
73
+ unit: 'release',
74
+ mount(deps) {
75
+ const actions = deps.flow.createActions();
76
+ actions.register('read', async () => ({ ok: true }));
77
+ actions.register('wait', async () => ({ state: 'done' }));
78
+ return { routes: {}, registerTools: () => [] };
79
+ },
80
+ };
81
+ ```
82
+
83
+ 在模块 `mount` 里:
84
+
85
+ - `const runs = deps.longTasks.create({ key, run, view, outcome, stopped })`;`run` 调 `deps.flow.run`,把 `onStep` 映射到长任务的 `onStep`;返回 `status === 'failed'` 时 throw,让注册表标 failed。
86
+ - `registerTools` 返回一把工具:`execute` 里 `runs.start`,返回 `{ ok, runId, status, text }`;再按 `runId` 查。
87
+ - 写平台的工具:清单 `writes: true` + `needsApproval` / `approvalDetail`;动作里不要自己再问一遍。
88
+ - 校验:`deps.flow.check(flow, actions)`;有问题先修,不装。
89
+
90
+ ### v0.1 能用的形状
91
+
92
+ | 需要 | 写法 |
93
+ |---|---|
94
+ | 等 / 轮询 | `poll: { everyMs, maxMs, until }` |
95
+ | 超时继续 | `poll.onTimeout: 'continue'`,后面用 `when: { $not: { $exists: ... } }` |
96
+ | 不限时(审核) | `poll.maxMs: 0` |
97
+ | 逐项 + 轮询 | `forEach` 与 `poll` 同一步;每项单独轮询 |
98
+ | 子流程 | `{ id, flow: subFlow, with: { ... } }`;结果在 `steps.<id>` |
99
+ | 提前结束 | `flow.stopWhen` |
100
+ | 登录 | 动作里 `ctx.login(url)`;长任务进 `needs-login`,动作自己等 / 重试 |
101
+
102
+ 分支(`already_merged` / `can_merge` / `REVIEW_WAITING`)继续写在动作里;flow 只保留稳定的外层顺序。
103
+
104
+ ## 4 不要做
105
+
106
+ - 为一次性任务建模块 / 写 flow;先跑。
107
+ - 不问用户就固化;也不要把「要不要固化」问成技术选型。
108
+ - 把分支、重试、登录循环全塞进 flow 配置;flow 表达不了的就放动作。
109
+ - 在 flow 里存密钥 / token;凭据走已有登录或 `needs`。
110
+ - 让 flow 绕过审批;写工具的审批在清单,不在动作里。
111
+
112
+ ## 5 验收
113
+
114
+ - `deps.flow.check` 无问题;`dsh-wb-module build` / `check` 绿。
115
+ - 真跑一遍:长任务行出现、进度对、能停止、失败给原因;要登录时给链接。
116
+ - 写平台前审批屏能看到对象 / 环境 / 影响;拒绝后不跑。
117
+ - 用户只说过需求;没被问实现。