@dimina-kit/devtools 0.4.0-dev.20260616102751 → 0.4.0-dev.20260624040247

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 (78) hide show
  1. package/README.md +30 -25
  2. package/dist/main/app/app.js +14 -2
  3. package/dist/main/index.bundle.js +559 -111
  4. package/dist/main/ipc/bridge-router.js +57 -9
  5. package/dist/main/ipc/projects.js +1 -1
  6. package/dist/main/ipc/simulator.js +1 -1
  7. package/dist/main/runtime/devtools-backend.d.ts +1 -1
  8. package/dist/main/runtime/devtools-backend.js +1 -1
  9. package/dist/main/runtime/miniapp-runtime.d.ts +5 -5
  10. package/dist/main/services/console-forward/index.js +8 -1
  11. package/dist/main/services/elements-forward/index.js +36 -12
  12. package/dist/main/services/layout/index.d.ts +12 -0
  13. package/dist/main/services/layout/index.js +14 -2
  14. package/dist/main/services/network-forward/index.d.ts +5 -6
  15. package/dist/main/services/network-forward/index.js +9 -10
  16. package/dist/main/services/notifications/renderer-notifier.d.ts +3 -4
  17. package/dist/main/services/projects/index.js +1 -1
  18. package/dist/main/services/projects/types.d.ts +1 -1
  19. package/dist/main/services/projects/types.js +1 -1
  20. package/dist/main/services/service-console/console-api.d.ts +77 -0
  21. package/dist/main/services/service-console/console-api.js +103 -0
  22. package/dist/main/services/service-console/index.d.ts +47 -0
  23. package/dist/main/services/service-console/index.js +139 -0
  24. package/dist/main/services/service-host-pool/pool.d.ts +2 -3
  25. package/dist/main/services/simulator-storage/index.d.ts +2 -4
  26. package/dist/main/services/simulator-storage/index.js +2 -4
  27. package/dist/main/services/simulator-temp-files/index.js +2 -2
  28. package/dist/main/services/update/update-manager.d.ts +1 -1
  29. package/dist/main/services/update/update-manager.js +1 -1
  30. package/dist/main/services/views/host-toolbar-session-runtime.d.ts +4 -4
  31. package/dist/main/services/views/host-toolbar-session-runtime.js +4 -4
  32. package/dist/main/services/views/view-manager.d.ts +24 -1
  33. package/dist/main/services/views/view-manager.js +120 -41
  34. package/dist/main/services/workbench-context.d.ts +7 -6
  35. package/dist/main/services/workspace/workspace-service.js +11 -0
  36. package/dist/main/windows/service-host-window/create.d.ts +1 -0
  37. package/dist/main/windows/service-host-window/create.js +1 -0
  38. package/dist/preload/runtime/host-toolbar-port.d.ts +1 -1
  39. package/dist/preload/runtime/host-toolbar-port.js +1 -1
  40. package/dist/preload/runtime/host-toolbar-runtime.d.ts +8 -7
  41. package/dist/preload/runtime/host-toolbar-runtime.js +8 -7
  42. package/dist/preload/windows/host-toolbar-runtime.cjs.map +2 -2
  43. package/dist/preload/windows/main.cjs.map +2 -2
  44. package/dist/preload/windows/simulator.cjs +1 -1
  45. package/dist/preload/windows/simulator.cjs.map +1 -1
  46. package/dist/preload/windows/simulator.js +1 -1
  47. package/dist/renderer/assets/index-PtsdWlGu.js +50 -0
  48. package/dist/renderer/assets/{input-B8NDCYv3.js → input-DiCxYlqY.js} +2 -2
  49. package/dist/renderer/assets/{ipc-transport-DhrajiC5.js → ipc-transport-DSBmaWpJ.js} +1 -1
  50. package/dist/renderer/assets/ipc-transport-DZxf2YoM.css +1 -0
  51. package/dist/renderer/assets/{popover-DbZOg03s.js → popover-CyL_uffj.js} +2 -2
  52. package/dist/renderer/assets/{select-pW3Ysc9T.js → select-BSwvDMtA.js} +2 -2
  53. package/dist/renderer/assets/settings-Ch8XbFxf.js +2 -0
  54. package/dist/renderer/assets/{settings-api-BSKzKiWd.js → settings-api-e9ILe2JO.js} +2 -2
  55. package/dist/renderer/assets/{workbenchSettings-BGxjl25x.js → workbenchSettings-DZsHf1g_.js} +2 -2
  56. package/dist/renderer/entries/main/index.html +6 -6
  57. package/dist/renderer/entries/popover/index.html +5 -5
  58. package/dist/renderer/entries/settings/index.html +11 -5
  59. package/dist/renderer/entries/workbench-settings/index.html +4 -4
  60. package/dist/service-host/preload.cjs +13 -15
  61. package/dist/service-host/sourcemap-rewrite.cjs +21 -12
  62. package/dist/shared/appdata-accumulator.d.ts +2 -2
  63. package/dist/shared/appdata-accumulator.js +3 -3
  64. package/dist/shared/constants.d.ts +1 -1
  65. package/dist/shared/constants.js +1 -1
  66. package/dist/shared/ipc-channels.d.ts +3 -3
  67. package/dist/shared/ipc-channels.js +3 -3
  68. package/dist/shared/open-in-editor.d.ts +20 -1
  69. package/dist/shared/open-in-editor.js +246 -3
  70. package/dist/shared/vpath.d.ts +2 -2
  71. package/dist/shared/vpath.js +2 -2
  72. package/dist/simulator/assets/{device-shell-BWX7Yopg.js → device-shell-TtcSXwhb.js} +2 -2
  73. package/dist/simulator/assets/{simulator-sf-D0mhw.js → simulator-CtyXt_4V.js} +3 -3
  74. package/dist/simulator/simulator.html +1 -1
  75. package/package.json +8 -6
  76. package/dist/renderer/assets/index-Z4Rh52G8.js +0 -50
  77. package/dist/renderer/assets/ipc-transport-9agi76dX.css +0 -1
  78. package/dist/renderer/assets/settings-CZJOHt8b.js +0 -2
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Pure helpers for the native-host service-console forwarder.
3
+ *
4
+ * The service-host's console is captured via CDP `Runtime.consoleAPICalled`,
5
+ * which preserves native source attribution. A `console.*` monkeypatch in
6
+ * `service-host/preload.cjs` would add a stack frame, so Chrome DevTools (attached
7
+ * natively to the service host) would attribute EVERY service-layer log to the
8
+ * wrapper line instead of the developer's source.
9
+ *
10
+ * These functions turn the CDP event shape into the `GuestConsoleEntry` shape
11
+ * the existing console fan-out (automation `App.logAdded`) expects, WITHOUT any
12
+ * electron / IO dependency so they are unit-testable in isolation. The async
13
+ * deep-fetch (`Runtime.callFunctionOn`) for object args lives in `index.ts`.
14
+ */
15
+ /**
16
+ * sourceURL stamped on the render→service `[视图]` re-injection script
17
+ * (`console-forward.buildForwardScript`). The CDP capture skips any
18
+ * `consoleAPICalled` whose top frame carries this URL so a forwarded render line
19
+ * is not re-captured and re-broadcast as a service entry (duplicate / loop).
20
+ */
21
+ export const RENDER_FORWARD_SOURCE_URL = 'dimina://render-console-forward';
22
+ const KNOWN_LEVELS = new Set(['log', 'warn', 'error', 'info', 'debug']);
23
+ /**
24
+ * CDP `consoleAPICalled.type` → our console level. CDP emits `'warning'` where
25
+ * we use `'warn'`; every other known level passes through; anything else (e.g.
26
+ * `'dir'`, `'table'`, `'trace'`, `undefined`) maps to `'log'`.
27
+ */
28
+ export function mapConsoleApiType(type) {
29
+ if (type === 'warning')
30
+ return 'warn';
31
+ if (type && KNOWN_LEVELS.has(type))
32
+ return type;
33
+ return 'log';
34
+ }
35
+ const BIGINT_LITERAL = /^-?\d+n$/;
36
+ /**
37
+ * A single RemoteObject → a JSON-serializable value WITHOUT a CDP round-trip
38
+ * (shallow). Objects that need their full contents are flagged by
39
+ * {@link needsDeepFetch} and deep-serialized by the caller; this is the
40
+ * inline/best-effort fallback.
41
+ */
42
+ export function remoteObjectToValue(ro) {
43
+ if (!ro)
44
+ return ro;
45
+ // 1. An inlined value (CDP includes `value` for JSON-serializable primitives
46
+ // and small arrays). Use `in` so falsy values (0, '', false) and an
47
+ // explicit `null` are honoured rather than falling through.
48
+ if ('value' in ro)
49
+ return ro.value;
50
+ // 2. Specials that can't ride in `value`.
51
+ if (typeof ro.unserializableValue === 'string') {
52
+ const u = ro.unserializableValue;
53
+ if (u === 'Infinity')
54
+ return Infinity;
55
+ if (u === '-Infinity')
56
+ return -Infinity;
57
+ if (u === 'NaN')
58
+ return NaN;
59
+ if (u === '-0')
60
+ return -0;
61
+ if (BIGINT_LITERAL.test(u))
62
+ return u;
63
+ return u;
64
+ }
65
+ // 3. Fall back by type.
66
+ switch (ro.type) {
67
+ case 'undefined':
68
+ return undefined;
69
+ case 'function':
70
+ return ro.description ?? '[Function]';
71
+ case 'symbol':
72
+ return ro.description ?? '[Symbol]';
73
+ case 'object':
74
+ if (ro.subtype === 'null')
75
+ return null;
76
+ return ro.description ?? '[Object]';
77
+ default:
78
+ return ro.description ?? '[Unknown]';
79
+ }
80
+ }
81
+ /**
82
+ * Whether this RemoteObject must be deep-fetched via `Runtime.callFunctionOn`
83
+ * (returnByValue) to be fully serialized — i.e. a real object/array referenced
84
+ * by `objectId` with no inline `value`. Functions, primitives, `null`, and
85
+ * already-inlined values do not.
86
+ */
87
+ export function needsDeepFetch(ro) {
88
+ if (!ro)
89
+ return false;
90
+ if ('value' in ro)
91
+ return false;
92
+ return ro.type === 'object' && ro.subtype !== 'null' && typeof ro.objectId === 'string';
93
+ }
94
+ /**
95
+ * True when a `consoleAPICalled` event is the render→service `[视图]`
96
+ * re-injection (its top call frame URL === the sentinel) and must NOT be
97
+ * re-forwarded — the original render entry already reached every consumer.
98
+ */
99
+ export function isRenderForwardEvent(params, sentinelUrl) {
100
+ const top = params?.stackTrace?.callFrames?.[0]?.url;
101
+ return typeof top === 'string' && top === sentinelUrl;
102
+ }
103
+ //# sourceMappingURL=console-api.js.map
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Native-host SERVICE-layer console capture via CDP.
3
+ *
4
+ * The embedded Chrome DevTools front-end is attached natively to the service
5
+ * host, so the service layer's `console.*` already displays there with correct
6
+ * source attribution + sourcemaps — UNLESS something rewrites `console.*`. The
7
+ * old `service-host/preload.cjs` monkeypatch did exactly that (wrapping each
8
+ * level to also post the entry to main), which made DevTools attribute every
9
+ * service log to the wrapper line (`preload.cjs:237`) instead of the developer's
10
+ * source. That monkeypatch is removed; this service replaces its ONE remaining
11
+ * job — feeding service-layer entries to the console fan-out (automation
12
+ * `App.logAdded`) — by capturing `Runtime.consoleAPICalled` over an in-process
13
+ * CDP session instead. Capturing at the CDP layer adds no stack frame, so native
14
+ * attribution in the DevTools console is preserved (verified: an in-process
15
+ * `debugger.attach('1.3')` coexists with the custom-host DevTools front-end on
16
+ * the same wc — Electron multi-client CDP).
17
+ *
18
+ * Lifecycle: installed when the right-panel DevTools is pointed at a service host
19
+ * wc (`view-manager.pointNativeDevtoolsAtServiceWc`) and stopped when that source
20
+ * is closed / swapped (pre-warm pool recycles the service window). `stop()` is
21
+ * idempotent.
22
+ */
23
+ import type { WebContents } from 'electron';
24
+ import type { ConnectionRegistry } from '@dimina-kit/electron-deck/main';
25
+ import type { GuestConsoleEntry } from '../console-forward/index.js';
26
+ export interface ServiceConsoleForwardDeps {
27
+ /** The service host wc whose `console.*` we capture (top-level BrowserWindow wc). */
28
+ serviceWc: WebContents;
29
+ /** Sink for each captured service entry (wired to `consoleForwarder.emit`). */
30
+ emit: (entry: GuestConsoleEntry) => void;
31
+ /** Connection registry — binds teardown to the service wc's destroy ('closed'). */
32
+ connections?: ConnectionRegistry;
33
+ }
34
+ export interface ServiceConsoleForwardHandle {
35
+ /** Detach the CDP session (if we attached it) and stop capturing. Idempotent. */
36
+ stop(): void;
37
+ }
38
+ /**
39
+ * Attach an in-process CDP session to `serviceWc`, enable Runtime, and forward
40
+ * every `Runtime.consoleAPICalled` to `emit` as a `source:'service'` entry —
41
+ * EXCEPT the render→service `[视图]` re-injection (skipped via sentinel so it is
42
+ * not double-broadcast). Object args are deep-serialized via
43
+ * `Runtime.callFunctionOn` on our OWN session (the objectId can't be released by
44
+ * the front-end), falling back to the shallow inline value on failure.
45
+ */
46
+ export declare function installServiceConsoleForward(deps: ServiceConsoleForwardDeps): ServiceConsoleForwardHandle;
47
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,139 @@
1
+ import { RENDER_FORWARD_SOURCE_URL, mapConsoleApiType, needsDeepFetch, remoteObjectToValue, isRenderForwardEvent, } from './console-api.js';
2
+ /**
3
+ * Attach an in-process CDP session to `serviceWc`, enable Runtime, and forward
4
+ * every `Runtime.consoleAPICalled` to `emit` as a `source:'service'` entry —
5
+ * EXCEPT the render→service `[视图]` re-injection (skipped via sentinel so it is
6
+ * not double-broadcast). Object args are deep-serialized via
7
+ * `Runtime.callFunctionOn` on our OWN session (the objectId can't be released by
8
+ * the front-end), falling back to the shallow inline value on failure.
9
+ */
10
+ export function installServiceConsoleForward(deps) {
11
+ const { serviceWc, emit, connections } = deps;
12
+ let disposed = false;
13
+ // Did WE attach the session (vs. it already being attached by someone else)?
14
+ // Only detach what we own.
15
+ let selfAttached = false;
16
+ // Process events in arrival order even though arg resolution is async, so the
17
+ // forwarded sequence matches the order the developer logged.
18
+ let tail = Promise.resolve();
19
+ let closedSub;
20
+ function usableDebugger() {
21
+ try {
22
+ if (serviceWc.isDestroyed())
23
+ return false;
24
+ if (serviceWc.debugger.isAttached())
25
+ return true;
26
+ }
27
+ catch {
28
+ return false;
29
+ }
30
+ try {
31
+ serviceWc.debugger.attach('1.3');
32
+ selfAttached = true;
33
+ return true;
34
+ }
35
+ catch {
36
+ // Race: someone attached between the check and here → still usable.
37
+ try {
38
+ return serviceWc.debugger.isAttached();
39
+ }
40
+ catch {
41
+ return false;
42
+ }
43
+ }
44
+ }
45
+ /** Deep-serialize one arg; best-effort, never throws. */
46
+ async function resolveArg(ro) {
47
+ if (!needsDeepFetch(ro))
48
+ return remoteObjectToValue(ro);
49
+ try {
50
+ const res = (await serviceWc.debugger.sendCommand('Runtime.callFunctionOn', {
51
+ objectId: ro.objectId,
52
+ functionDeclaration: 'function () { return this }',
53
+ returnByValue: true,
54
+ }));
55
+ if (res && res.result && 'value' in res.result)
56
+ return res.result.value;
57
+ }
58
+ catch {
59
+ // Object released / host navigating — fall back to the shallow value.
60
+ }
61
+ return remoteObjectToValue(ro);
62
+ }
63
+ async function handleConsoleApi(params) {
64
+ if (disposed)
65
+ return;
66
+ // Skip the render→service `[视图]` re-injection — the original render entry
67
+ // already reached every consumer; re-forwarding would duplicate it.
68
+ if (isRenderForwardEvent(params, RENDER_FORWARD_SOURCE_URL))
69
+ return;
70
+ const level = mapConsoleApiType(params.type);
71
+ const rawArgs = Array.isArray(params.args) ? params.args : [];
72
+ let args;
73
+ try {
74
+ args = await Promise.all(rawArgs.map((a) => resolveArg(a)));
75
+ }
76
+ catch {
77
+ args = rawArgs.map((a) => remoteObjectToValue(a));
78
+ }
79
+ if (disposed)
80
+ return;
81
+ emit({ source: 'service', level, args, ts: Date.now() });
82
+ }
83
+ const onMessage = (_event, method, params) => {
84
+ if (disposed)
85
+ return;
86
+ if (method !== 'Runtime.consoleAPICalled')
87
+ return;
88
+ const p = params;
89
+ tail = tail.then(() => handleConsoleApi(p)).catch(() => { });
90
+ };
91
+ function stop() {
92
+ if (disposed)
93
+ return;
94
+ disposed = true;
95
+ try {
96
+ closedSub?.dispose();
97
+ }
98
+ catch { /* gone */ }
99
+ try {
100
+ serviceWc.debugger.removeListener('message', onMessage);
101
+ }
102
+ catch { /* gone */ }
103
+ if (selfAttached) {
104
+ try {
105
+ if (!serviceWc.isDestroyed() && serviceWc.debugger.isAttached())
106
+ serviceWc.debugger.detach();
107
+ }
108
+ catch { /* already detached / destroyed */ }
109
+ selfAttached = false;
110
+ }
111
+ }
112
+ if (!usableDebugger()) {
113
+ disposed = true;
114
+ return { stop() { } };
115
+ }
116
+ try {
117
+ serviceWc.debugger.on('message', onMessage);
118
+ }
119
+ catch {
120
+ stop();
121
+ return { stop() { } };
122
+ }
123
+ // Enable Runtime so consoleAPICalled flows. Best-effort — a mid-destroy host
124
+ // rejects, in which case there's simply nothing to capture.
125
+ serviceWc.debugger.sendCommand('Runtime.enable').catch(() => { });
126
+ // Bind teardown to the service wc's real destroy. The service window is
127
+ // pool-recycled, but 'closed' fires only on hard destroy — the right lifetime
128
+ // for a session we attached to THIS wc. `on('closed')` returns a handle whose
129
+ // dispose() removes the listener WITHOUT firing it.
130
+ try {
131
+ if (connections)
132
+ closedSub = connections.acquire(serviceWc).on('closed', stop);
133
+ else
134
+ serviceWc.once('destroyed', stop);
135
+ }
136
+ catch { /* fake/minimal wc in tests */ }
137
+ return { stop };
138
+ }
139
+ //# sourceMappingURL=index.js.map
@@ -7,9 +7,8 @@ import { BrowserWindow } from 'electron';
7
7
  * (release / releaseDestroyed), opt-in behind `DIMINA_PREWARM_POOL_SIZE`
8
8
  * (default OFF). Only the SERVICE-HOST window is pooled; the simulator content
9
9
  * WebContentsView (`view-manager.attachNativeSimulator`) is created fresh per
10
- * attach. (The historical `<webview>`-tag default arch was never poolable —
11
- * Electron can't reparent a pre-warmed WebContents into a `<webview>`; doc §5
12
- * Phase 4 — and that route has since been deleted outright.)
10
+ * attach. (A `<webview>`-tag arch is not poolable — Electron can't reparent a
11
+ * pre-warmed WebContents into a `<webview>`.)
13
12
  *
14
13
  * Lifecycle of a pool entry:
15
14
  * warming — BrowserWindow constructed, page loading
@@ -2,11 +2,9 @@
2
2
  * SimulatorStorageWatcher
3
3
  *
4
4
  * Attaches the Chrome DevTools Protocol debugger to the simulator <webview>
5
- * and forwards `DOMStorage.*` events to the renderer host. Replaces the
6
- * preload-side localStorage.setItem hook that used to push storage changes
7
- * via SimulatorChannel.Storage / StorageAll.
5
+ * and forwards `DOMStorage.*` events to the renderer host.
8
6
  *
9
- * Trade-offs vs the preload approach:
7
+ * Trade-offs vs a preload-side localStorage.setItem hook:
10
8
  * + Uses standard browser protocol; no preload injection
11
9
  * + Captures every change including ones bypassing wx (api-compat fallback,
12
10
  * direct localStorage.setItem from devtools, etc.)
@@ -2,11 +2,9 @@
2
2
  * SimulatorStorageWatcher
3
3
  *
4
4
  * Attaches the Chrome DevTools Protocol debugger to the simulator <webview>
5
- * and forwards `DOMStorage.*` events to the renderer host. Replaces the
6
- * preload-side localStorage.setItem hook that used to push storage changes
7
- * via SimulatorChannel.Storage / StorageAll.
5
+ * and forwards `DOMStorage.*` events to the renderer host.
8
6
  *
9
- * Trade-offs vs the preload approach:
7
+ * Trade-offs vs a preload-side localStorage.setItem hook:
10
8
  * + Uses standard browser protocol; no preload injection
11
9
  * + Captures every change including ones bypassing wx (api-compat fallback,
12
10
  * direct localStorage.setItem from devtools, etc.)
@@ -155,8 +155,8 @@ export function setupSimulatorTempFiles(simSession) {
155
155
  installOnSession(simSession);
156
156
  // Apply to every per-project miniapp partition session (current + future).
157
157
  const unregisterConfigurator = registerMiniappSessionConfigurator((sess) => installOnSession(sess));
158
- // Phase 1 (P1-7): renderer FSM → main fs operations bridge. The same
159
- // simulator-only sender policy applies — registry instance is shared.
158
+ // Renderer FSM → main fs operations bridge. The same simulator-only sender
159
+ // policy applies — registry instance is shared.
160
160
  registry.handle('simulator:fs:read', (_event, payload) => handleFsRead(payload));
161
161
  registry.handle('simulator:fs:write', (_event, payload) => handleFsWrite(payload));
162
162
  registry.handle('simulator:fs:stat', (_event, payload) => handleFsStat(payload));
@@ -26,7 +26,7 @@ export declare class UpdateManager {
26
26
  private downloadedPath;
27
27
  /**
28
28
  * Whether this instance has already emitted `Available` once. The periodic
29
- * check fires forever (interval default 1h), and downstream UI (qdmp shell
29
+ * check fires forever (interval default 1h), and downstream UI (a downstream host shell
30
30
  * renders a native toast / Notification) is not idempotent — every event
31
31
  * stacks. We dedupe at the source: at most one Available per instance
32
32
  * lifetime, regardless of how the upstream `info.version` shifts. The user
@@ -9,7 +9,7 @@ export class UpdateManager {
9
9
  downloadedPath = null;
10
10
  /**
11
11
  * Whether this instance has already emitted `Available` once. The periodic
12
- * check fires forever (interval default 1h), and downstream UI (qdmp shell
12
+ * check fires forever (interval default 1h), and downstream UI (a downstream host shell
13
13
  * renders a native toast / Notification) is not idempotent — every event
14
14
  * stacks. We dedupe at the source: at most one Available per instance
15
15
  * lifetime, regardless of how the upstream `info.version` shifts. The user
@@ -2,15 +2,15 @@
2
2
  * Ref-counted registration of the host-toolbar framework runtime on
3
3
  * `session.defaultSession`.
4
4
  *
5
- * The toolbar's height advertiser no longer rides the toolbar WCV's
6
- * `webPreferences.preload` (a host's `setPreloadPath` used to replace it and
7
- * the strip height collapsed to 0). Instead the runtime bundle
5
+ * The toolbar's height advertiser does not ride the toolbar WCV's
6
+ * `webPreferences.preload`: a host's `setPreloadPath` would replace it and the
7
+ * strip height would collapse to 0. Instead the runtime bundle
8
8
  * (`hostToolbarRuntimePreloadPath`) is registered once per process as a
9
9
  * session frame preload; its own guard (`--dimina-host-toolbar` marker +
10
10
  * `isMainFrame`) keeps it a zero-footprint no-op in every other defaultSession
11
11
  * renderer.
12
12
  *
13
- * Ref-counting (codex condition 3): multiple ViewManagers can coexist in one
13
+ * Ref-counting: multiple ViewManagers can coexist in one
14
14
  * process and share the ONE defaultSession. Each manager acquires at most one
15
15
  * reference (on first toolbar need) and releases it in `disposeAll`. Only the
16
16
  * first acquire registers; only the last release unregisters (with the id
@@ -2,15 +2,15 @@
2
2
  * Ref-counted registration of the host-toolbar framework runtime on
3
3
  * `session.defaultSession`.
4
4
  *
5
- * The toolbar's height advertiser no longer rides the toolbar WCV's
6
- * `webPreferences.preload` (a host's `setPreloadPath` used to replace it and
7
- * the strip height collapsed to 0). Instead the runtime bundle
5
+ * The toolbar's height advertiser does not ride the toolbar WCV's
6
+ * `webPreferences.preload`: a host's `setPreloadPath` would replace it and the
7
+ * strip height would collapse to 0. Instead the runtime bundle
8
8
  * (`hostToolbarRuntimePreloadPath`) is registered once per process as a
9
9
  * session frame preload; its own guard (`--dimina-host-toolbar` marker +
10
10
  * `isMainFrame`) keeps it a zero-footprint no-op in every other defaultSession
11
11
  * renderer.
12
12
  *
13
- * Ref-counting (codex condition 3): multiple ViewManagers can coexist in one
13
+ * Ref-counting: multiple ViewManagers can coexist in one
14
14
  * process and share the ONE defaultSession. Each manager acquires at most one
15
15
  * reference (on first toolbar need) and releases it in `disposeAll`. Only the
16
16
  * first acquire registers; only the last release unregisters (with the id
@@ -1,5 +1,6 @@
1
1
  import type { WebContents } from 'electron';
2
2
  import type { NativeDeviceInfo } from '../../../shared/ipc-channels.js';
3
+ import { type OpenInEditorRequest } from '../../../shared/open-in-editor.js';
3
4
  import { type WorkbenchContext } from '../workbench-context.js';
4
5
  import { type HostToolbarMessageSubscription } from './host-toolbar-port-channel.js';
5
6
  /**
@@ -17,6 +18,8 @@ export interface ViewManagerContext {
17
18
  * `createWorkbenchContext` always supplies it.
18
19
  */
19
20
  connections: WorkbenchContext['connections'];
21
+ /** Active project root used to validate/open console source locations. */
22
+ workspace?: WorkbenchContext['workspace'];
20
23
  /**
21
24
  * Absolute path to the simulator preload bundle. Only consumed by the
22
25
  * native-host simulator WebContentsView (`attachNativeSimulator`); the
@@ -34,6 +37,13 @@ export interface ViewManagerContext {
34
37
  * console line is the fallback). Optional so partial test contexts compile.
35
38
  */
36
39
  networkForward?: WorkbenchContext['networkForward'];
40
+ /**
41
+ * Always-on console fan-out (set by `installBridgeRouter`). The service-console
42
+ * capture feeds service-layer `consoleAPICalled` entries here so they reach
43
+ * automation; mirrors how render entries arrive via the bridge. Optional so
44
+ * partial test contexts compile.
45
+ */
46
+ consoleForwarder?: WorkbenchContext['consoleForwarder'];
37
47
  /**
38
48
  * Per-context registry of host-registered simulator custom APIs. The
39
49
  * native-host simulator is a top-level WebContentsView with no embedder
@@ -75,7 +85,7 @@ export interface ViewManager {
75
85
  * `simWidth` rides the wire for schema compatibility but is unused: all
76
86
  * geometry is anchor-published.
77
87
  */
78
- attachNativeSimulator(simulatorUrl: string, simWidth: number): void;
88
+ attachNativeSimulator(simulatorUrl: string, simWidth: number): Promise<void>;
79
89
  /**
80
90
  * Destroy and null out the simulator view (e.g. on simulator detach).
81
91
  * Also destroys the cached settings view and hides the popover —
@@ -99,6 +109,8 @@ export interface ViewManager {
99
109
  getSimulatorWebContentsId(): number | null;
100
110
  /** Return the live webContents of the currently attached simulator, or null. */
101
111
  getSimulatorWebContents(): WebContents | null;
112
+ /** Return the active project path bound to the current native simulator. */
113
+ getSimulatorProjectPath(): string | null;
102
114
  /** Return the settings overlay's WebContents (for renderer-notifier). */
103
115
  getSettingsWebContents(): WebContents | null;
104
116
  /** Return the webContents ID of the settings overlay if alive, else null. */
@@ -270,6 +282,17 @@ export interface HostToolbarControl {
270
282
  */
271
283
  setHeightMode(mode: HostToolbarHeightMode): void;
272
284
  }
285
+ export interface ProjectEditorTarget {
286
+ path: string;
287
+ line?: number;
288
+ column?: number;
289
+ }
290
+ /**
291
+ * Resolve a DevTools source request against the service-host URL that created
292
+ * the inspected app. Its pkgRoot is authoritative; the workspace is only a
293
+ * stale-session consistency guard.
294
+ */
295
+ export declare function resolveProjectEditorTarget(serviceHostUrl: string, activeProjectRoot: string | undefined, req: OpenInEditorRequest, isFile?: (absolutePath: string) => boolean): ProjectEditorTarget | null;
273
296
  /**
274
297
  * Build a ViewManager bound to the given context. The returned object is the
275
298
  * only component allowed to instantiate or add/remove overlay WebContentsViews.