@konitif/workbench-runtime 0.284.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/LICENSE.md +22 -0
  2. package/README.md +60 -0
  3. package/dist/boot/createDemoWorkbenchBootGraph.d.ts +9 -0
  4. package/dist/boot/createDemoWorkbenchBootGraph.js +180 -0
  5. package/dist/boot/createLegacyWorkbenchBootGraph.d.ts +34 -0
  6. package/dist/boot/createLegacyWorkbenchBootGraph.js +321 -0
  7. package/dist/boot/createWorkbenchBootSession.d.ts +23 -0
  8. package/dist/boot/createWorkbenchBootSession.js +90 -0
  9. package/dist/boot/index.d.ts +3 -0
  10. package/dist/boot/index.js +3 -0
  11. package/dist/index.d.ts +10 -0
  12. package/dist/index.js +9 -0
  13. package/dist/runtime.d.ts +7 -0
  14. package/dist/runtime.js +2 -0
  15. package/dist/workbench/browserDetachedWindowHost.d.ts +3 -0
  16. package/dist/workbench/browserDetachedWindowHost.js +69 -0
  17. package/dist/workbench/browserWorkbenchHostEvents.d.ts +3 -0
  18. package/dist/workbench/browserWorkbenchHostEvents.js +35 -0
  19. package/dist/workbench/createWorkbenchStore.d.ts +129 -0
  20. package/dist/workbench/createWorkbenchStore.js +50 -0
  21. package/dist/workbench/createWorkbenchStoreRuntime.d.ts +154 -0
  22. package/dist/workbench/createWorkbenchStoreRuntime.js +242 -0
  23. package/dist/workbench/createWorkspaceModeController.d.ts +36 -0
  24. package/dist/workbench/createWorkspaceModeController.js +168 -0
  25. package/dist/workbench/workbenchDetachedWindowHost.d.ts +16 -0
  26. package/dist/workbench/workbenchDetachedWindowHost.js +1 -0
  27. package/dist/workbench/workbenchFocusPersistence.d.ts +15 -0
  28. package/dist/workbench/workbenchFocusPersistence.js +44 -0
  29. package/dist/workbench/workbenchHistoryActions.d.ts +21 -0
  30. package/dist/workbench/workbenchHistoryActions.js +45 -0
  31. package/dist/workbench/workbenchHistoryRuntime.d.ts +16 -0
  32. package/dist/workbench/workbenchHistoryRuntime.js +42 -0
  33. package/dist/workbench/workbenchHostEvents.d.ts +13 -0
  34. package/dist/workbench/workbenchHostEvents.js +1 -0
  35. package/dist/workbench/workbenchLayoutActions.d.ts +84 -0
  36. package/dist/workbench/workbenchLayoutActions.js +191 -0
  37. package/dist/workbench/workbenchPersistenceRuntime.d.ts +39 -0
  38. package/dist/workbench/workbenchPersistenceRuntime.js +168 -0
  39. package/dist/workbench/workbenchShellActions.d.ts +24 -0
  40. package/dist/workbench/workbenchShellActions.js +63 -0
  41. package/dist/workbench/workbenchShellPersistence.d.ts +18 -0
  42. package/dist/workbench/workbenchShellPersistence.js +124 -0
  43. package/dist/workbench/workbenchStateFactory.d.ts +22 -0
  44. package/dist/workbench/workbenchStateFactory.js +47 -0
  45. package/dist/workbench/workbenchToolRuntimeActions.d.ts +23 -0
  46. package/dist/workbench/workbenchToolRuntimeActions.js +98 -0
  47. package/dist/workbench/workbenchToolRuntimeUiStore.d.ts +17 -0
  48. package/dist/workbench/workbenchToolRuntimeUiStore.js +85 -0
  49. package/dist/workbench/workbenchWindowRuntime.d.ts +19 -0
  50. package/dist/workbench/workbenchWindowRuntime.js +85 -0
  51. package/dist/workbench/workbenchWorkspaceActions.d.ts +30 -0
  52. package/dist/workbench/workbenchWorkspaceActions.js +55 -0
  53. package/dist/workbench/workspaceHistoryController.d.ts +28 -0
  54. package/dist/workbench/workspaceHistoryController.js +126 -0
  55. package/dist/workbench/workspaceSyncController.d.ts +20 -0
  56. package/dist/workbench/workspaceSyncController.js +105 -0
  57. package/package.json +49 -0
package/LICENSE.md ADDED
@@ -0,0 +1,22 @@
1
+ # Licence — @konitif/workbench-runtime
2
+
3
+ SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
4
+
5
+ The original KONITIF / Workbench code in this v0.x package is made available
6
+ under the PolyForm Noncommercial License 1.0.0:
7
+ https://polyformproject.org/licenses/noncommercial/1.0.0
8
+
9
+ This notice incorporates the standard terms by reference; it is not a modified
10
+ version of the licence. This is source-available software, not OSI open source.
11
+ Third-party components retain their own licences and notices.
12
+
13
+ Uses outside the standard licence's permitted purposes require a separate
14
+ written licence. A public repository or npm download grants no additional
15
+ commercial rights. Any free professional authorization must be explicit,
16
+ nominative and limited to the agreed products; none is granted by this notice.
17
+
18
+ The KONITIF name, logo and official identity belong to Maxime Mouflard.
19
+ Descriptive reference is permitted. No third-party version may claim to be
20
+ official, certified or approved without authorization. This trademark notice
21
+ is separate from the software licence and does not amend its terms.
22
+
package/README.md ADDED
@@ -0,0 +1,60 @@
1
+ # @konitif/workbench-runtime
2
+
3
+ Public runtime orchestration for a KONITIF Workbench. It connects Workbench contracts to reactive application state without owning product semantics.
4
+
5
+ Products compose this runtime and provide their own tools, widgets, persistence adapters and policies.
6
+
7
+ ## Autonomous distribution
8
+
9
+ Run `npm run build`, `npm test` and `npm run verify:package` from this
10
+ repository. The build emits ESM and declarations into `dist`; the verifier
11
+ packs that compiled allowlist, checks its exact contents and consumes both
12
+ public entries outside the source tree. No lifecycle script performs an
13
+ installation or publication.
14
+
15
+ The package depends on the published Workbench authority rather than a workspace
16
+ locator. Only the archive retained by the release verifier may be published.
17
+
18
+ ## Explicit runtime entry
19
+
20
+ ```ts
21
+ import {
22
+ createWorkbenchStoreRuntime,
23
+ type CreateWorkbenchStoreRuntimeOptions,
24
+ } from '@konitif/workbench-runtime/runtime';
25
+ ```
26
+
27
+ This entry requires all six host ports: `workspacePersistence`,
28
+ `shellPersistence`, `focusPersistence`, `workspaceSync`, `hostEvents` and
29
+ `detachedWindows`. Only the last two accept `null`, explicitly disabling those
30
+ capabilities. Missing ports are rejected before providers are read.
31
+
32
+ Port types are exported from the same entry. Workspace contracts remain owned
33
+ by `@konitif/workbench/workspace-contracts`. The runtime owns its subscriptions,
34
+ not the supplied shared providers; call `flushPersistence()` before `dispose()`
35
+ if pending state must be saved. Disposal does not close native windows.
36
+
37
+ The root entry retains `createWorkbenchStore` and its browser defaults for
38
+ compatibility. The explicit entry selects no browser defaults, but still uses
39
+ Svelte stores, global debounce timers and the existing identity generator.
40
+
41
+ The npm distribution exposes compiled Node-compatible ESM and NodeNext
42
+ declarations. Repository sources remain TypeScript and are not included in the
43
+ archive.
44
+
45
+ ## Host notifications
46
+
47
+ `createWorkbenchStore` accepts an optional `hostEvents` provider:
48
+
49
+ - Omitted: browser `pagehide`, `beforeunload`, hidden visibility and `storage` notifications.
50
+ - `null`: no subscriptions to those host events, even in a browser.
51
+ - `WorkbenchHostEvents`: explicit provider returning an unsubscribe function for each subscription.
52
+
53
+ The provider calls `onPersistenceBoundary()` or `onStorageChange({ key, newValue })`.
54
+ It does not own workspace state or perform persistence. The coordinator filters
55
+ storage notifications, reloads through its persistence ports and validates the
56
+ workspace. Disposal unsubscribes without destroying a shared provider; it does
57
+ not implicitly flush pending saves. Call `flushPersistence()` first when needed.
58
+
59
+ This option does not disable `workspaceSync`, detached-window controls or default
60
+ storage adapters. Supply those ports separately for a non-browser host.
@@ -0,0 +1,9 @@
1
+ import type { BootGraph } from '@konitif/workbench';
2
+ export interface DemoWorkbenchBootGraphOptions {
3
+ stepDelayMs?: number;
4
+ delayMs?: number;
5
+ failStepId?: string;
6
+ failCritical?: boolean;
7
+ }
8
+ export type CreateDemoWorkbenchBootGraphOptions = DemoWorkbenchBootGraphOptions;
9
+ export declare function createDemoWorkbenchBootGraph(options?: DemoWorkbenchBootGraphOptions): BootGraph;
@@ -0,0 +1,180 @@
1
+ const DEMO_BOOT_STEPS = [
2
+ {
3
+ id: 'plan.validate-runtime-plan',
4
+ label: 'Validate runtime plan',
5
+ phase: 'plan',
6
+ },
7
+ {
8
+ id: 'plan.validate-boot-graph',
9
+ label: 'Validate boot graph',
10
+ phase: 'plan',
11
+ dependsOn: ['plan.validate-runtime-plan'],
12
+ },
13
+ {
14
+ id: 'initialize.persistence',
15
+ label: 'Initialize persistence',
16
+ phase: 'initialize',
17
+ dependsOn: ['plan.validate-boot-graph'],
18
+ },
19
+ {
20
+ id: 'initialize.workspace',
21
+ label: 'Initialize workspace',
22
+ phase: 'initialize',
23
+ dependsOn: ['initialize.persistence'],
24
+ },
25
+ {
26
+ id: 'initialize.shell',
27
+ label: 'Initialize shell',
28
+ phase: 'initialize',
29
+ dependsOn: ['initialize.workspace'],
30
+ },
31
+ {
32
+ id: 'initialize.layout-interactions',
33
+ label: 'Initialize layout interactions',
34
+ phase: 'initialize',
35
+ dependsOn: ['initialize.shell'],
36
+ },
37
+ {
38
+ id: 'initialize.observability',
39
+ label: 'Initialize observability',
40
+ phase: 'initialize',
41
+ dependsOn: ['initialize.layout-interactions'],
42
+ },
43
+ {
44
+ id: 'hydrate.workspace',
45
+ label: 'Hydrate workspace',
46
+ phase: 'hydrate',
47
+ dependsOn: ['initialize.workspace', 'initialize.observability'],
48
+ },
49
+ {
50
+ id: 'hydrate.shell',
51
+ label: 'Hydrate shell',
52
+ phase: 'hydrate',
53
+ dependsOn: ['hydrate.workspace', 'initialize.shell'],
54
+ },
55
+ {
56
+ id: 'hydrate.layout',
57
+ label: 'Hydrate layout',
58
+ phase: 'hydrate',
59
+ dependsOn: ['hydrate.shell', 'initialize.layout-interactions'],
60
+ },
61
+ {
62
+ id: 'hydrate.sessions',
63
+ label: 'Hydrate sessions',
64
+ phase: 'hydrate',
65
+ dependsOn: ['hydrate.layout'],
66
+ },
67
+ {
68
+ id: 'hydrate.projections',
69
+ label: 'Hydrate projections',
70
+ phase: 'hydrate',
71
+ dependsOn: ['hydrate.sessions', 'initialize.observability'],
72
+ },
73
+ {
74
+ id: 'run.history',
75
+ label: 'Attach history',
76
+ phase: 'run',
77
+ dependsOn: ['hydrate.shell'],
78
+ },
79
+ {
80
+ id: 'run.sync',
81
+ label: 'Attach sync',
82
+ phase: 'run',
83
+ dependsOn: ['hydrate.projections'],
84
+ },
85
+ {
86
+ id: 'run.persistence-subscriptions',
87
+ label: 'Attach persistence subscriptions',
88
+ phase: 'run',
89
+ dependsOn: ['run.history', 'initialize.persistence'],
90
+ },
91
+ {
92
+ id: 'run.runtime-inspector',
93
+ label: 'Register runtime inspector',
94
+ phase: 'run',
95
+ dependsOn: ['run.sync', 'initialize.observability'],
96
+ },
97
+ {
98
+ id: 'run.expose-store',
99
+ label: 'Expose workbench store',
100
+ phase: 'run',
101
+ dependsOn: ['run.persistence-subscriptions', 'run.runtime-inspector'],
102
+ },
103
+ ];
104
+ export function createDemoWorkbenchBootGraph(options = {}) {
105
+ const delayMs = options.stepDelayMs ?? options.delayMs ?? 120;
106
+ const optionalFailureDependents = options.failStepId && options.failCritical === false
107
+ ? collectTransitiveDependents(options.failStepId)
108
+ : new Set();
109
+ return {
110
+ steps: DEMO_BOOT_STEPS.map((definition) => createDemoBootStep(definition, {
111
+ delayMs,
112
+ failStepId: options.failStepId,
113
+ failCritical: options.failCritical ?? true,
114
+ optionalFailureDependents,
115
+ })),
116
+ };
117
+ }
118
+ function createDemoBootStep(definition, options) {
119
+ const shouldFail = definition.id === options.failStepId;
120
+ const criticality = shouldFail && !options.failCritical
121
+ ? 'optional'
122
+ : options.optionalFailureDependents.has(definition.id)
123
+ ? 'optional'
124
+ : 'critical';
125
+ return {
126
+ id: definition.id,
127
+ label: definition.label,
128
+ phase: definition.phase,
129
+ criticality,
130
+ dependsOn: definition.dependsOn?.map((stepId) => ({ stepId })),
131
+ async run() {
132
+ await delay(options.delayMs);
133
+ if (shouldFail) {
134
+ throw new Error(`Simulated boot failure at ${definition.id}.`);
135
+ }
136
+ return {
137
+ metadata: {
138
+ simulated: true,
139
+ phase: definition.phase,
140
+ ...(definition.metadata ?? {}),
141
+ },
142
+ };
143
+ },
144
+ async rollback() {
145
+ await delay(Math.max(0, Math.min(options.delayMs, 40)));
146
+ return {
147
+ metadata: {
148
+ rollback: true,
149
+ simulated: true,
150
+ phase: definition.phase,
151
+ },
152
+ };
153
+ },
154
+ };
155
+ }
156
+ function collectTransitiveDependents(rootStepId) {
157
+ const dependents = new Set();
158
+ let changed = true;
159
+ while (changed) {
160
+ changed = false;
161
+ for (const definition of DEMO_BOOT_STEPS) {
162
+ if (definition.id === rootStepId || dependents.has(definition.id)) {
163
+ continue;
164
+ }
165
+ const dependencies = definition.dependsOn ?? [];
166
+ const dependsOnFailedRoot = dependencies.includes(rootStepId);
167
+ const dependsOnFailedDependent = dependencies.some((stepId) => dependents.has(stepId));
168
+ if (dependsOnFailedRoot || dependsOnFailedDependent) {
169
+ dependents.add(definition.id);
170
+ changed = true;
171
+ }
172
+ }
173
+ }
174
+ return dependents;
175
+ }
176
+ function delay(ms) {
177
+ return new Promise((resolve) => {
178
+ setTimeout(resolve, ms);
179
+ });
180
+ }
@@ -0,0 +1,34 @@
1
+ import { type BootContext, type BootGraph, type BootMode, type BootStepResult, type RuntimePlan, type RuntimePlanStep } from '@konitif/workbench';
2
+ export declare const LEGACY_WORKBENCH_BOOT_SNAPSHOT_OPTION = "legacyWorkbench.snapshot";
3
+ export interface LegacyWorkbenchBootSnapshot {
4
+ targetKind: string;
5
+ targetLabel: string;
6
+ profile: string;
7
+ projectRoot?: string | null;
8
+ projectKind?: string | null;
9
+ shellRoute?: string | null;
10
+ workspaceMode?: string | null;
11
+ source?: string | null;
12
+ }
13
+ export interface LegacyWorkbenchBootGraphOptions {
14
+ stepDelayMs?: number;
15
+ delayMs?: number;
16
+ snapshot?: LegacyWorkbenchBootSnapshot;
17
+ runtimeStepHandlers?: LegacyRuntimePlanStepHandlers;
18
+ }
19
+ export interface LegacyRuntimePlanStepHandlerInput {
20
+ snapshot: LegacyWorkbenchBootSnapshot;
21
+ plan: RuntimePlan;
22
+ step: RuntimePlanStep;
23
+ }
24
+ export type LegacyRuntimePlanStepHandler = (ctx: BootContext, input: LegacyRuntimePlanStepHandlerInput) => BootStepResult | void | Promise<BootStepResult | void>;
25
+ export interface LegacyRuntimePlanStepLifecycleHandler {
26
+ run?: LegacyRuntimePlanStepHandler;
27
+ rollback?: LegacyRuntimePlanStepHandler;
28
+ teardown?: LegacyRuntimePlanStepHandler;
29
+ }
30
+ export type LegacyRuntimePlanStepHandlerDefinition = LegacyRuntimePlanStepHandler | LegacyRuntimePlanStepLifecycleHandler;
31
+ export type LegacyRuntimePlanStepHandlers = Partial<Record<string, LegacyRuntimePlanStepHandlerDefinition>>;
32
+ export declare function createLegacyWorkbenchBootGraph(options?: LegacyWorkbenchBootGraphOptions): BootGraph;
33
+ export declare function createLegacyWorkbenchBootContextOptions(snapshot: LegacyWorkbenchBootSnapshot): Iterable<readonly [string, unknown]>;
34
+ export declare function resolveLegacyWorkbenchBootMode(snapshot: LegacyWorkbenchBootSnapshot): BootMode;
@@ -0,0 +1,321 @@
1
+ import { RuntimePlanEngine, createLaunchPreflightSummary, createProjectLaunchTarget, createSelfLaunchTarget, getBootOption, getRuntimeValue, setCapability, setRuntimeValue, } from '@konitif/workbench';
2
+ export const LEGACY_WORKBENCH_BOOT_SNAPSHOT_OPTION = 'legacyWorkbench.snapshot';
3
+ const LEGACY_BOOT_PLAN_STEPS = [
4
+ {
5
+ id: 'plan.resolve-launch-target',
6
+ label: 'Resolve launch target',
7
+ phase: 'plan',
8
+ run(ctx) {
9
+ const snapshot = readLegacyWorkbenchBootSnapshot(ctx);
10
+ setRuntimeValue(ctx, 'launch.target', snapshot);
11
+ return {
12
+ metadata: {
13
+ observed: true,
14
+ targetKind: snapshot.targetKind,
15
+ targetLabel: snapshot.targetLabel,
16
+ profile: snapshot.profile,
17
+ projectRoot: snapshot.projectRoot ?? null,
18
+ source: snapshot.source ?? 'legacy-workbench',
19
+ },
20
+ };
21
+ },
22
+ },
23
+ {
24
+ id: 'plan.create-runtime-plan',
25
+ label: 'Create runtime plan',
26
+ phase: 'plan',
27
+ dependsOn: ['plan.resolve-launch-target'],
28
+ run(ctx) {
29
+ const snapshot = readLegacyWorkbenchBootSnapshot(ctx);
30
+ const plan = createLegacyRuntimePlan(snapshot);
31
+ setRuntimeValue(ctx, 'runtime.plan', plan);
32
+ return {
33
+ metadata: {
34
+ runtimePlanId: plan.id,
35
+ profile: plan.profile,
36
+ canExecute: plan.canExecute,
37
+ stepCount: plan.steps.length,
38
+ warningCount: plan.warnings.length,
39
+ targetKind: plan.target.kind,
40
+ },
41
+ warnings: plan.canExecute ? [] : ['Runtime plan is blocked by preflight.'],
42
+ };
43
+ },
44
+ },
45
+ ];
46
+ const LEGACY_BOOT_HYDRATE_SHELL_STEP = {
47
+ id: 'hydrate.capture-workspace-shell',
48
+ label: 'Capture workspace shell context',
49
+ phase: 'hydrate',
50
+ run(ctx) {
51
+ const snapshot = readLegacyWorkbenchBootSnapshot(ctx);
52
+ setRuntimeValue(ctx, 'workspace.shell', {
53
+ shellRoute: snapshot.shellRoute ?? 'workspace',
54
+ workspaceMode: snapshot.workspaceMode ?? 'studio',
55
+ });
56
+ return {
57
+ metadata: {
58
+ shellRoute: snapshot.shellRoute ?? 'workspace',
59
+ workspaceMode: snapshot.workspaceMode ?? 'studio',
60
+ persistence: 'external',
61
+ },
62
+ };
63
+ },
64
+ };
65
+ const LEGACY_BOOT_RUN_STEPS = [
66
+ {
67
+ id: 'run.expose-legacy-runtime',
68
+ label: 'Expose legacy runtime projection',
69
+ phase: 'run',
70
+ run(ctx) {
71
+ const plan = getRuntimeValue(ctx, 'runtime.plan');
72
+ setRuntimeValue(ctx, 'legacy.runtime.ready', true);
73
+ setCapability(ctx, 'legacy.workbench-store.delegated', true);
74
+ return {
75
+ metadata: {
76
+ observable: true,
77
+ delegatedTo: 'createWorkbenchStore',
78
+ nextMigrationTarget: 'store factory ownership',
79
+ runtimePlanId: plan.id,
80
+ runtimeStepCount: plan.steps.length,
81
+ },
82
+ };
83
+ },
84
+ },
85
+ ];
86
+ export function createLegacyWorkbenchBootGraph(options = {}) {
87
+ const delayMs = options.stepDelayMs ?? options.delayMs ?? 70;
88
+ const graphPlan = createLegacyRuntimePlan(sanitizeLegacyWorkbenchBootSnapshot(options.snapshot ?? createFallbackLegacyWorkbenchBootSnapshot()), 'legacy-boot-graph');
89
+ const runtimePlanSteps = createRuntimePlanBootStepDefinitions(graphPlan.steps, sanitizeLegacyWorkbenchBootSnapshot(options.snapshot ?? createFallbackLegacyWorkbenchBootSnapshot()), options.runtimeStepHandlers ?? {});
90
+ const hydrateShellStep = {
91
+ ...LEGACY_BOOT_HYDRATE_SHELL_STEP,
92
+ dependsOn: [resolveLastStepId(runtimePlanSteps.initialize, 'plan.create-runtime-plan')],
93
+ };
94
+ const firstRunStep = runtimePlanSteps.run[0];
95
+ if (firstRunStep && !firstRunStep.dependsOn?.length) {
96
+ firstRunStep.dependsOn = [resolveLastStepId(runtimePlanSteps.hydrate, hydrateShellStep.id)];
97
+ }
98
+ const runSteps = LEGACY_BOOT_RUN_STEPS.map((step) => ({
99
+ ...step,
100
+ dependsOn: [resolveLastStepId([...runtimePlanSteps.hydrate, ...runtimePlanSteps.run], hydrateShellStep.id)],
101
+ }));
102
+ const definitions = [
103
+ ...LEGACY_BOOT_PLAN_STEPS,
104
+ ...runtimePlanSteps.initialize,
105
+ hydrateShellStep,
106
+ ...runtimePlanSteps.hydrate,
107
+ ...runtimePlanSteps.run,
108
+ ...runSteps,
109
+ ];
110
+ return {
111
+ steps: definitions.map((definition) => createLegacyBootStep(definition, delayMs)),
112
+ };
113
+ }
114
+ export function createLegacyWorkbenchBootContextOptions(snapshot) {
115
+ return [[LEGACY_WORKBENCH_BOOT_SNAPSHOT_OPTION, sanitizeLegacyWorkbenchBootSnapshot(snapshot)]];
116
+ }
117
+ export function resolveLegacyWorkbenchBootMode(snapshot) {
118
+ return snapshot.targetKind === 'self' ? 'readonly' : 'normal';
119
+ }
120
+ function createLegacyBootStep(definition, delayMs) {
121
+ return {
122
+ id: definition.id,
123
+ label: definition.label,
124
+ phase: definition.phase,
125
+ criticality: 'critical',
126
+ dependsOn: definition.dependsOn?.map((stepId) => ({ stepId })),
127
+ async run(ctx) {
128
+ await delay(delayMs);
129
+ return definition.run(ctx);
130
+ },
131
+ async rollback(ctx) {
132
+ if (!definition.rollback) {
133
+ return undefined;
134
+ }
135
+ await delay(Math.max(0, Math.min(delayMs, 40)));
136
+ return definition.rollback(ctx);
137
+ },
138
+ async teardown(ctx) {
139
+ if (!definition.teardown) {
140
+ return undefined;
141
+ }
142
+ await delay(Math.max(0, Math.min(delayMs, 40)));
143
+ return definition.teardown(ctx);
144
+ },
145
+ };
146
+ }
147
+ function readLegacyWorkbenchBootSnapshot(ctx) {
148
+ return sanitizeLegacyWorkbenchBootSnapshot(getBootOption(ctx, LEGACY_WORKBENCH_BOOT_SNAPSHOT_OPTION));
149
+ }
150
+ function sanitizeLegacyWorkbenchBootSnapshot(snapshot) {
151
+ return {
152
+ targetKind: snapshot.targetKind || 'unknown',
153
+ targetLabel: snapshot.targetLabel || 'Unknown target',
154
+ profile: snapshot.profile || 'unknown',
155
+ projectRoot: snapshot.projectRoot || null,
156
+ projectKind: snapshot.projectKind || null,
157
+ shellRoute: snapshot.shellRoute || null,
158
+ workspaceMode: snapshot.workspaceMode || null,
159
+ source: snapshot.source || null,
160
+ };
161
+ }
162
+ function createFallbackLegacyWorkbenchBootSnapshot() {
163
+ return {
164
+ targetKind: 'unknown',
165
+ targetLabel: 'Unknown target',
166
+ profile: 'project-workbench',
167
+ projectRoot: 'legacy-workbench',
168
+ projectKind: 'repository',
169
+ source: 'legacy-workbench',
170
+ };
171
+ }
172
+ function createLegacyRuntimePlan(snapshot, now = new Date().toISOString()) {
173
+ const target = createLaunchTargetFromLegacySnapshot(snapshot);
174
+ return new RuntimePlanEngine().createPlan({
175
+ target,
176
+ preflight: createLaunchPreflightSummary(target),
177
+ now,
178
+ });
179
+ }
180
+ function createLaunchTargetFromLegacySnapshot(snapshot) {
181
+ if (snapshot.targetKind === 'self') {
182
+ return createSelfLaunchTarget();
183
+ }
184
+ const projectRoot = snapshot.projectRoot || snapshot.targetLabel || 'legacy-workbench';
185
+ const project = {
186
+ id: createLegacyProjectId(projectRoot),
187
+ kind: resolveLegacyProjectKind(snapshot.projectKind),
188
+ label: snapshot.targetLabel || createProjectLabel(projectRoot),
189
+ root: projectRoot,
190
+ description: snapshot.source ? `Legacy boot source: ${snapshot.source}` : null,
191
+ };
192
+ return createProjectLaunchTarget(project, resolveLegacyLaunchProfile(snapshot.profile));
193
+ }
194
+ function createRuntimePlanBootStepDefinitions(steps, snapshot, handlers) {
195
+ const grouped = {
196
+ initialize: [],
197
+ hydrate: [],
198
+ run: [],
199
+ };
200
+ const dependenciesByPhase = {
201
+ initialize: 'plan.create-runtime-plan',
202
+ hydrate: 'hydrate.capture-workspace-shell',
203
+ run: '',
204
+ };
205
+ for (const step of steps) {
206
+ const phase = resolveRuntimePlanBootPhase(step.kind);
207
+ const definition = createRuntimePlanBootStepDefinition(step, phase, dependenciesByPhase[phase], snapshot, handlers);
208
+ grouped[phase].push(definition);
209
+ dependenciesByPhase[phase] = definition.id;
210
+ }
211
+ return grouped;
212
+ }
213
+ function createRuntimePlanBootStepDefinition(step, phase, dependencyId, snapshot, handlers) {
214
+ return {
215
+ id: `runtime-plan.${step.id}`,
216
+ label: step.label,
217
+ phase,
218
+ dependsOn: dependencyId ? [dependencyId] : undefined,
219
+ async run(ctx) {
220
+ const plan = getRuntimeValue(ctx, 'runtime.plan');
221
+ const runtimeStep = plan.steps.find((entry) => entry.id === step.id) ?? step;
222
+ const handler = resolveLegacyRuntimePlanStepHandler(handlers[runtimeStep.id], 'run');
223
+ if (runtimeStep.status === 'blocked') {
224
+ throw new Error(runtimeStep.reason ?? `Runtime plan step "${runtimeStep.id}" is blocked.`);
225
+ }
226
+ const handlerResult = await handler?.(ctx, { snapshot, plan, step: runtimeStep });
227
+ setRuntimeValue(ctx, `runtime.plan.step.${runtimeStep.id}`, 'success');
228
+ return {
229
+ metadata: {
230
+ runtimePlanId: plan.id,
231
+ planStepId: runtimeStep.id,
232
+ kind: runtimeStep.kind,
233
+ critical: runtimeStep.critical,
234
+ profile: plan.profile,
235
+ status: runtimeStep.status,
236
+ ...(handlerResult?.metadata ?? {}),
237
+ },
238
+ warnings: [
239
+ ...(runtimeStep.status === 'skipped' && runtimeStep.reason ? [runtimeStep.reason] : []),
240
+ ...(handlerResult?.warnings ?? []),
241
+ ],
242
+ };
243
+ },
244
+ async rollback(ctx) {
245
+ const plan = getRuntimeValue(ctx, 'runtime.plan');
246
+ const runtimeStep = plan.steps.find((entry) => entry.id === step.id) ?? step;
247
+ const handler = resolveLegacyRuntimePlanStepHandler(handlers[runtimeStep.id], 'rollback');
248
+ const handlerResult = await handler?.(ctx, { snapshot, plan, step: runtimeStep });
249
+ return {
250
+ metadata: {
251
+ rollback: true,
252
+ runtimePlanId: plan.id,
253
+ planStepId: runtimeStep.id,
254
+ ...(handlerResult?.metadata ?? {}),
255
+ },
256
+ warnings: handlerResult?.warnings ?? [],
257
+ };
258
+ },
259
+ async teardown(ctx) {
260
+ const plan = getRuntimeValue(ctx, 'runtime.plan');
261
+ const runtimeStep = plan.steps.find((entry) => entry.id === step.id) ?? step;
262
+ const handler = resolveLegacyRuntimePlanStepHandler(handlers[runtimeStep.id], 'teardown');
263
+ const handlerResult = await handler?.(ctx, { snapshot, plan, step: runtimeStep });
264
+ return {
265
+ metadata: {
266
+ teardown: true,
267
+ runtimePlanId: plan.id,
268
+ planStepId: runtimeStep.id,
269
+ ...(handlerResult?.metadata ?? {}),
270
+ },
271
+ warnings: handlerResult?.warnings ?? [],
272
+ };
273
+ },
274
+ };
275
+ }
276
+ function resolveLegacyRuntimePlanStepHandler(handler, lifecycle) {
277
+ if (typeof handler === 'function') {
278
+ return lifecycle === 'run' ? handler : undefined;
279
+ }
280
+ return handler?.[lifecycle];
281
+ }
282
+ function resolveRuntimePlanBootPhase(kind) {
283
+ if (kind === 'activate-watcher' || kind === 'launch-worker') {
284
+ return 'run';
285
+ }
286
+ if (kind === 'start-service' || kind === 'initialize-manager' || kind === 'register-tool') {
287
+ return 'hydrate';
288
+ }
289
+ return 'initialize';
290
+ }
291
+ function resolveLastStepId(steps, fallback) {
292
+ return steps[steps.length - 1]?.id ?? fallback;
293
+ }
294
+ function resolveLegacyLaunchProfile(profile) {
295
+ if (profile === 'core-only' ||
296
+ profile === 'project-workbench' ||
297
+ profile === 'repo-inspect-only' ||
298
+ profile === 'app-safe-mode' ||
299
+ profile === 'app-full-runtime' ||
300
+ profile === 'sandbox-runtime' ||
301
+ profile === 'recovery-mode') {
302
+ return profile;
303
+ }
304
+ return 'project-workbench';
305
+ }
306
+ function resolveLegacyProjectKind(kind) {
307
+ return kind === 'app' ? 'app' : 'repository';
308
+ }
309
+ function createLegacyProjectId(root) {
310
+ const normalizedRoot = root.replace(/[^a-z0-9]+/gi, '.').replace(/^\.+|\.+$/g, '').toLowerCase();
311
+ return `legacy.${normalizedRoot || 'workbench'}`;
312
+ }
313
+ function createProjectLabel(root) {
314
+ const normalizedRoot = root.replace(/\\/g, '/').replace(/\/+$/, '');
315
+ return normalizedRoot.split('/').filter(Boolean).pop() ?? 'Legacy project';
316
+ }
317
+ function delay(ms) {
318
+ return new Promise((resolve) => {
319
+ setTimeout(resolve, ms);
320
+ });
321
+ }
@@ -0,0 +1,23 @@
1
+ import { type BootContext, type BootEvent, type BootEventBus, type BootExecutionState, type BootExecutor, type BootGraph, type BootMode, type BootProjection } from '@konitif/workbench';
2
+ import { type DemoWorkbenchBootGraphOptions } from "./createDemoWorkbenchBootGraph.js";
3
+ export interface CreateWorkbenchBootSessionOptions {
4
+ mode?: BootMode;
5
+ graph?: BootGraph;
6
+ demoGraph?: DemoWorkbenchBootGraphOptions;
7
+ context?: BootContext;
8
+ eventBus?: BootEventBus;
9
+ createExecutionId?: () => string;
10
+ now?: () => number;
11
+ eventHistoryLimit?: number;
12
+ }
13
+ export interface WorkbenchBootSession {
14
+ graph: BootGraph;
15
+ context: BootContext;
16
+ executor: BootExecutor;
17
+ getProjection(): BootProjection;
18
+ getEventHistory(): BootEvent[];
19
+ subscribe(listener: (projection: BootProjection) => void): () => void;
20
+ start(): Promise<BootExecutionState>;
21
+ teardown(): Promise<BootExecutionState>;
22
+ }
23
+ export declare function createWorkbenchBootSession(options?: CreateWorkbenchBootSessionOptions): WorkbenchBootSession;