@dimina-kit/devtools 0.4.0-dev.20260828161241 → 0.4.0-dev.20260907055341
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -729
- package/dist/main/app/app.d.ts +27 -7
- package/dist/main/app/app.js +285 -681
- package/dist/main/app/editor-view.d.ts +21 -0
- package/dist/main/app/editor-view.js +71 -0
- package/dist/main/app/global-mirrors.d.ts +23 -0
- package/dist/main/app/global-mirrors.js +37 -0
- package/dist/main/app/host-sidebar-default.d.ts +19 -0
- package/dist/main/app/host-sidebar-default.js +44 -0
- package/dist/main/app/menu-setup.d.ts +13 -0
- package/dist/main/app/menu-setup.js +49 -0
- package/dist/main/app/open-project-ipc.d.ts +13 -0
- package/dist/main/app/open-project-ipc.js +21 -0
- package/dist/main/app/project-list-surface.d.ts +31 -0
- package/dist/main/app/project-list-surface.js +20 -0
- package/dist/main/app/project-window.d.ts +36 -0
- package/dist/main/app/project-window.js +93 -0
- package/dist/main/app/servers.d.ts +17 -0
- package/dist/main/app/servers.js +60 -0
- package/dist/main/app/ui-extension-targets.d.ts +42 -0
- package/dist/main/app/ui-extension-targets.js +101 -0
- package/dist/main/app/window-close-reveal.harness.d.ts +34 -0
- package/dist/main/app/window-close-reveal.harness.js +65 -0
- package/dist/main/app/window-events.d.ts +15 -0
- package/dist/main/app/window-events.js +45 -0
- package/dist/main/app/window-runtime-services.d.ts +41 -0
- package/dist/main/app/window-runtime-services.js +178 -0
- package/dist/main/app/workbench-modules.d.ts +24 -0
- package/dist/main/app/workbench-modules.js +51 -0
- package/dist/main/app/workbench-window.d.ts +85 -0
- package/dist/main/app/workbench-window.js +310 -0
- package/dist/main/index.bundle.js +10669 -9096
- package/dist/main/ipc/app.d.ts +4 -1
- package/dist/main/ipc/app.js +4 -3
- package/dist/main/ipc/device-picker.d.ts +16 -0
- package/dist/main/ipc/device-picker.js +27 -0
- package/dist/main/ipc/index.d.ts +1 -0
- package/dist/main/ipc/index.js +1 -0
- package/dist/main/ipc/internal-devtools.d.ts +2 -1
- package/dist/main/ipc/internal-devtools.js +4 -3
- package/dist/main/ipc/popover.d.ts +4 -1
- package/dist/main/ipc/popover.js +25 -9
- package/dist/main/ipc/project-create.d.ts +2 -1
- package/dist/main/ipc/project-create.js +6 -5
- package/dist/main/ipc/project-fs.d.ts +3 -1
- package/dist/main/ipc/project-fs.js +17 -17
- package/dist/main/ipc/projects.d.ts +3 -3
- package/dist/main/ipc/projects.js +13 -12
- package/dist/main/ipc/session.d.ts +4 -1
- package/dist/main/ipc/session.js +16 -11
- package/dist/main/ipc/settings.d.ts +4 -1
- package/dist/main/ipc/settings.js +12 -19
- package/dist/main/ipc/simulator-module.d.ts +5 -0
- package/dist/main/ipc/simulator-module.js +9 -5
- package/dist/main/ipc/simulator.d.ts +4 -1
- package/dist/main/ipc/simulator.js +12 -18
- package/dist/main/ipc/tooltip.d.ts +2 -1
- package/dist/main/ipc/tooltip.js +8 -7
- package/dist/main/ipc/views.d.ts +4 -1
- package/dist/main/ipc/views.js +20 -9
- package/dist/main/runtime/devtools-backend-before-quit.harness.d.ts +2 -20
- package/dist/main/runtime/devtools-backend-before-quit.harness.js +14 -283
- package/dist/main/runtime/devtools-backend.js +14 -3
- package/dist/main/runtime/devtools-runtime-mock.harness.d.ts +21 -0
- package/dist/main/runtime/devtools-runtime-mock.harness.js +313 -0
- package/dist/main/services/app-services.d.ts +62 -0
- package/dist/main/services/app-services.js +64 -0
- package/dist/main/services/automation/connection-target.d.ts +36 -0
- package/dist/main/services/automation/connection-target.js +29 -0
- package/dist/main/services/automation/console-bridge.d.ts +28 -0
- package/dist/main/services/automation/console-bridge.js +91 -0
- package/dist/main/services/automation/handlers/app.js +4 -4
- package/dist/main/services/automation/handlers/element.js +55 -21
- package/dist/main/services/automation/index.d.ts +12 -1
- package/dist/main/services/automation/index.js +54 -133
- package/dist/main/services/default-adapter.js +1 -1
- package/dist/main/services/fs-bridge-protocol.d.ts +61 -0
- package/dist/main/services/fs-bridge-protocol.js +34 -0
- package/dist/main/services/fs-watch-sse.d.ts +8 -1
- package/dist/main/services/fs-watch-sse.js +19 -5
- package/dist/main/services/mcp/connection-owner.d.ts +38 -0
- package/dist/main/services/mcp/connection-owner.js +79 -0
- package/dist/main/services/mcp/index.d.ts +3 -1
- package/dist/main/services/mcp/index.js +4 -3
- package/dist/main/services/mcp/opened-project.d.ts +88 -0
- package/dist/main/services/mcp/opened-project.js +60 -0
- package/dist/main/services/mcp/target-manager.d.ts +71 -23
- package/dist/main/services/mcp/target-manager.js +269 -142
- package/dist/main/services/mcp/target-selection.d.ts +47 -0
- package/dist/main/services/mcp/target-selection.js +71 -0
- package/dist/main/services/mcp/tools/context-tools.js +20 -5
- package/dist/main/services/mcp/tools/project-tools.d.ts +29 -6
- package/dist/main/services/mcp/tools/project-tools.js +37 -25
- package/dist/main/services/module.d.ts +13 -5
- package/dist/main/services/notifications/renderer-notifier.d.ts +28 -4
- package/dist/main/services/notifications/renderer-notifier.js +15 -3
- package/dist/main/services/projects/local-provider.js +2 -0
- package/dist/main/services/projects/project-repository.d.ts +31 -1
- package/dist/main/services/projects/project-repository.js +144 -20
- package/dist/main/services/projects/types.d.ts +31 -8
- package/dist/main/services/safe-area/index.d.ts +19 -5
- package/dist/main/services/safe-area/index.js +38 -13
- package/dist/main/services/simulator/ui-extensions.d.ts +8 -0
- package/dist/main/services/simulator/ui-extensions.js +16 -6
- package/dist/main/services/simulator-storage/index.d.ts +12 -1
- package/dist/main/services/simulator-storage/index.js +22 -7
- package/dist/main/services/simulator-storage/window-scope.d.ts +20 -0
- package/dist/main/services/simulator-storage/window-scope.js +20 -0
- package/dist/main/services/views/host-slot-port-channel.d.ts +20 -3
- package/dist/main/services/views/host-slot-port-channel.js +33 -5
- package/dist/main/services/views/managed-web-contents-view.js +21 -1
- package/dist/main/services/views/native-simulator-view.js +13 -16
- package/dist/main/services/views/overlay-panels-view.d.ts +13 -0
- package/dist/main/services/views/overlay-panels-view.js +31 -0
- package/dist/main/services/views/view-manager.d.ts +1 -1
- package/dist/main/services/views/view-manager.js +3 -0
- package/dist/main/services/window-contexts/context-router.d.ts +36 -0
- package/dist/main/services/window-contexts/context-router.js +55 -0
- package/dist/main/services/workbench-coi-host.d.ts +52 -0
- package/dist/main/services/workbench-coi-host.js +227 -0
- package/dist/main/services/workbench-coi-server.js +75 -133
- package/dist/main/services/workbench-coi-shutdown.d.ts +40 -0
- package/dist/main/services/workbench-coi-shutdown.js +69 -0
- package/dist/main/services/workbench-coi-static.d.ts +23 -0
- package/dist/main/services/workbench-coi-static.js +87 -0
- package/dist/main/services/workbench-context.d.ts +27 -3
- package/dist/main/services/workbench-context.js +10 -5
- package/dist/main/services/workspace/compile-mode-adapter.d.ts +18 -0
- package/dist/main/services/workspace/compile-mode-adapter.js +57 -0
- package/dist/main/services/workspace/compile-mode-store.d.ts +25 -0
- package/dist/main/services/workspace/compile-mode-store.js +71 -0
- package/dist/main/services/workspace/workspace-compile-modes.d.ts +59 -0
- package/dist/main/services/workspace/workspace-compile-modes.js +93 -0
- package/dist/main/services/workspace/workspace-referer.d.ts +17 -0
- package/dist/main/services/workspace/workspace-referer.js +26 -0
- package/dist/main/services/workspace/workspace-service.d.ts +4 -0
- package/dist/main/services/workspace/workspace-service.js +51 -84
- package/dist/main/services/workspace/workspace-thumbnails.d.ts +22 -0
- package/dist/main/services/workspace/workspace-thumbnails.js +67 -0
- package/dist/main/utils/ipc-context-source.d.ts +40 -0
- package/dist/main/utils/ipc-context-source.js +23 -0
- package/dist/main/utils/ipc-registry.d.ts +42 -36
- package/dist/main/utils/ipc-registry.js +117 -50
- package/dist/main/utils/sender-policy.d.ts +9 -0
- package/dist/main/utils/sender-policy.js +26 -3
- package/dist/main/utils/theme.d.ts +3 -2
- package/dist/main/utils/theme.js +3 -2
- package/dist/main/windows/main-window/create.d.ts +16 -0
- package/dist/main/windows/main-window/create.js +19 -11
- package/dist/main/windows/main-window/events.d.ts +1 -1
- package/dist/main/windows/main-window/events.js +26 -13
- package/dist/main/windows/main-window/index.d.ts +1 -1
- package/dist/main/windows/main-window/index.js +1 -1
- package/dist/native-host/common/common.js +94 -73
- package/dist/native-host/render/render.js +4079 -3171
- package/dist/native-host/service/service.js +2 -2
- package/dist/preload/runtime/native-host.d.ts +4 -0
- package/dist/preload/runtime/temp-files.js +9 -2
- package/dist/preload/runtime/wait-for-slot-root.d.ts +7 -4
- package/dist/preload/runtime/wait-for-slot-root.js +36 -8
- package/dist/preload/windows/host-dialog-runtime.cjs +10 -3
- package/dist/preload/windows/host-dialog-runtime.cjs.map +2 -2
- package/dist/preload/windows/host-sidebar-runtime.cjs +10 -3
- package/dist/preload/windows/host-sidebar-runtime.cjs.map +2 -2
- package/dist/preload/windows/host-toolbar-runtime.cjs +10 -3
- package/dist/preload/windows/host-toolbar-runtime.cjs.map +2 -2
- package/dist/preload/windows/main.cjs +181 -4
- package/dist/preload/windows/main.cjs.map +4 -4
- package/dist/preload/windows/simulator.cjs +10 -0
- package/dist/preload/windows/simulator.cjs.map +2 -2
- package/dist/preload/windows/simulator.js +10 -0
- package/dist/render-host/pageFrame.html +1 -1
- package/dist/render-host/preload.cjs +16 -4
- package/dist/renderer/assets/button-CB2MWjHY.js +2 -0
- package/dist/renderer/assets/constants-CkoGPQTS.js +2 -0
- package/dist/renderer/assets/constants-zQZ2-y21.js +2 -0
- package/dist/renderer/assets/{createLucideIcon-Bqi8hpdi.js → createLucideIcon-cZ9FlZZw.js} +2 -2
- package/dist/renderer/assets/devicePicker-H2eIO4e1.js +2 -0
- package/dist/renderer/assets/dialog-pHzEA8Vx.js +46 -0
- package/dist/renderer/assets/dist-B5HADirS.js +2 -0
- package/dist/renderer/assets/{dist-DKWdE1TK.js → dist-DIFlRMKe.js} +2 -2
- package/dist/renderer/assets/hostSidebarDefault-DRWh6OCt.js +2 -0
- package/dist/renderer/assets/index-CEL_XFge.js +2 -0
- package/dist/renderer/assets/{input-Ct3alvkq.js → input-CAObw95L.js} +2 -2
- package/dist/renderer/assets/ipc-channels-overlays-gIPUFnqc.js +2 -0
- package/dist/renderer/assets/jsx-runtime-DICEQH_0.css +1 -0
- package/dist/renderer/assets/{jsx-runtime-DGLHmmOq.js → jsx-runtime-DIw5wnYl.js} +1 -1
- package/dist/renderer/assets/plus-BQ9u5EbL.js +2 -0
- package/dist/renderer/assets/popover-Cw7G2Ctp.js +2 -0
- package/dist/renderer/assets/presets-DMZOb9ay.js +2 -0
- package/dist/renderer/assets/project-api-YTOr_Yvo.js +2 -0
- package/dist/renderer/assets/{projectCreateDialog-Bbjz75bP.js → projectCreateDialog-BmLqiYxn.js} +2 -2
- package/dist/renderer/assets/search-BMvuYF48.js +2 -0
- package/dist/renderer/assets/select-nFP95TxM.js +2 -0
- package/dist/renderer/assets/settings-CnpVfSWt.js +2 -0
- package/dist/renderer/assets/settings-api-Ccsf-Nsj.js +2 -0
- package/dist/renderer/assets/settings-tab-bar-CAzrv32m.js +2 -0
- package/dist/renderer/assets/smartphone-Bb2GdIKy.js +2 -0
- package/dist/renderer/assets/tabs-CPKN3Mmq.js +2 -0
- package/dist/renderer/assets/{tooltip-B_-_YVbw.js → tooltip-D6AxXRk5.js} +2 -2
- package/dist/renderer/assets/types-Bh0hA7El.js +2 -0
- package/dist/renderer/assets/updateDialog-CwndJ0Bl.js +2 -0
- package/dist/renderer/assets/{utils-kfQov6Pa.js → utils-sEB5OZEQ.js} +2 -2
- package/dist/renderer/assets/view-api-B-2zPBR5.js +2 -0
- package/dist/renderer/assets/view-ids-BfaDVV5P.js +2 -0
- package/dist/renderer/assets/workbench-BLJ0wKsg.js +5 -0
- package/dist/renderer/assets/{workbenchSettings-CV4LVA9b.js → workbenchSettings-YD0Ctbm_.js} +3 -3
- package/dist/renderer/entries/device-picker/index.html +28 -0
- package/dist/renderer/entries/host-sidebar-default/index.html +6 -5
- package/dist/renderer/entries/main/index.html +16 -17
- package/dist/renderer/entries/popover/index.html +16 -10
- package/dist/renderer/entries/project-create-dialog/index.html +12 -12
- package/dist/renderer/entries/settings/index.html +10 -10
- package/dist/renderer/entries/tooltip/index.html +5 -5
- package/dist/renderer/entries/update-dialog/index.html +10 -10
- package/dist/renderer/entries/workbench/index.html +49 -0
- package/dist/renderer/entries/workbench-settings/index.html +12 -11
- package/dist/service-host/host-env-update.cjs +23 -0
- package/dist/service-host/preload.cjs +24 -49
- package/dist/service-host/service-message-queue.cjs +71 -0
- package/dist/service-host/sync-impls/system-info.js +31 -9
- package/dist/shared/compile-mode-state.d.ts +73 -0
- package/dist/shared/compile-mode-state.js +100 -0
- package/dist/shared/compile-modes.d.ts +152 -0
- package/dist/shared/compile-modes.js +237 -0
- package/dist/shared/ipc-channels-overlays.d.ts +8 -2
- package/dist/shared/ipc-channels-overlays.js +19 -2
- package/dist/shared/ipc-channels.d.ts +5 -10
- package/dist/shared/ipc-channels.js +17 -14
- package/dist/shared/ipc-schemas.d.ts +76 -24
- package/dist/shared/ipc-schemas.js +55 -10
- package/dist/shared/project-window-types.d.ts +42 -0
- package/dist/shared/project-window-types.js +2 -0
- package/dist/shared/types.d.ts +43 -17
- package/dist/shared/view-ids.d.ts +1 -0
- package/dist/shared/view-ids.js +3 -1
- package/dist/simulator/assets/bridge-channels-B3JAmRfl.js +2 -0
- package/dist/simulator/assets/device-shell-ATEhHV2_.css +1 -0
- package/dist/simulator/assets/device-shell-pxnZZp10.js +431 -0
- package/dist/simulator/assets/simulator-Dwp7lnvu.js +10 -0
- package/dist/simulator/assets/simulator-mini-app-DFo7fhi5.js +2 -0
- package/dist/simulator/assets/simulator-ui-B2ddJB1R.js +2 -0
- package/dist/simulator/simulator.html +3 -3
- package/dist/simulator/temp-files.d.ts +6 -0
- package/dist/simulator/temp-files.js +46 -4
- package/dist/simulator/types.d.ts +7 -0
- package/dist/vscode-workbench/assets/__vite-browser-external-JIkWewFf.js +1 -0
- package/dist/vscode-workbench/assets/{dist-CMfmHflW.js → dist-CXG-u1VB.js} +3 -3
- package/dist/vscode-workbench/assets/{iconv-lite-umd-Bx8CgaZq.js → iconv-lite-umd-Dxx9Qyb4.js} +1 -1
- package/dist/vscode-workbench/assets/{index-CdG6YWhW.js → index-6VJMsaWj.js} +460 -460
- package/dist/vscode-workbench/assets/{jschardet-M0qgd2lN.js → jschardet-Ba3D16vt.js} +1 -1
- package/dist/vscode-workbench/index.html +1 -1
- package/package.json +11 -8
- package/dist/renderer/assets/button-D5Q2wkXq.js +0 -2
- package/dist/renderer/assets/constants-D7DfVqMp.js +0 -2
- package/dist/renderer/assets/constants-D8zsejFq.js +0 -2
- package/dist/renderer/assets/dialog-e1TecTOY.js +0 -46
- package/dist/renderer/assets/hostSidebarDefault-B3yLfy8j.js +0 -2
- package/dist/renderer/assets/index-CsPD68N_.js +0 -5
- package/dist/renderer/assets/ipc-channels-overlays-LsDzGAtV.js +0 -2
- package/dist/renderer/assets/jsx-runtime-2vXHouwr.css +0 -1
- package/dist/renderer/assets/popover-Dix5cm_b.js +0 -2
- package/dist/renderer/assets/project-api-k7Oq9iaq.js +0 -2
- package/dist/renderer/assets/select-acGb0AmJ.js +0 -2
- package/dist/renderer/assets/settings-CQrTMr43.js +0 -2
- package/dist/renderer/assets/settings-api-CrUQ9rYV.js +0 -2
- package/dist/renderer/assets/settings-tab-bar-Cw1kVIf2.js +0 -2
- package/dist/renderer/assets/types-CsEKtFyr.js +0 -2
- package/dist/renderer/assets/updateDialog-NsF8223A.js +0 -2
- package/dist/renderer/assets/view-api-CLn3rcQE.js +0 -2
- package/dist/simulator/assets/bridge-channels-zhsumfky.js +0 -2
- package/dist/simulator/assets/device-shell-CmtM1QxP.js +0 -2
- package/dist/simulator/assets/device-shell-iFZo1igL.css +0 -1
- package/dist/simulator/assets/simulator-CIobn3Mh.js +0 -10
- package/dist/simulator/assets/simulator-mini-app-CRe6n9br.js +0 -2
- package/dist/simulator/assets/simulator-ui-C_cP602X.js +0 -2
- package/dist/vscode-workbench/assets/__vite-browser-external-Bc1vizTf.js +0 -1
|
@@ -11,82 +11,108 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import CDP from 'chrome-remote-interface';
|
|
13
13
|
import { DEFAULT_CDP_PORT } from '../../../shared/constants.js';
|
|
14
|
-
import {
|
|
15
|
-
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
|
|
20
|
-
// sync with the actual document URL shape (dmb-resource-url.ts).
|
|
21
|
-
const RENDER_GUEST_PATTERN = DMB_PAGEFRAME_DOC_NAME;
|
|
14
|
+
import { connectionOwner } from './connection-owner.js';
|
|
15
|
+
import { selectSimulatorTarget, selectWorkbenchTarget } from './target-selection.js';
|
|
16
|
+
// Re-exported so existing `./target-manager.js` imports keep working — the
|
|
17
|
+
// candidate-ranking rules live in target-selection.ts, but callers reach them
|
|
18
|
+
// through the connection manager that uses them.
|
|
19
|
+
export { selectSimulatorTarget, selectWorkbenchTarget } from './target-selection.js';
|
|
22
20
|
const MAX_BUFFER = 500;
|
|
23
21
|
const RECONNECT_INTERVAL_MS = 3000;
|
|
22
|
+
// How long a burst of focus changes is allowed to settle before the live
|
|
23
|
+
// connections are re-aimed.
|
|
24
|
+
const ACTIVE_WINDOW_SETTLE_MS = 150;
|
|
24
25
|
let cdpPort = DEFAULT_CDP_PORT;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
workbench: { client: null, connected: false, timer: null, consoleLogs: [], networkRequests: [] },
|
|
36
|
-
};
|
|
37
|
-
export function setCdpPort(port) {
|
|
38
|
-
cdpPort = port;
|
|
26
|
+
const windowFacts = new Map();
|
|
27
|
+
let resolveActiveOwner = () => null;
|
|
28
|
+
/**
|
|
29
|
+
* Point MCP at the window the user is working in. Assembled once by the app;
|
|
30
|
+
* `owner` is the opaque token a window registered itself under. Resolving to
|
|
31
|
+
* null means no project window is open, which is the answer MCP reports before
|
|
32
|
+
* the first project is opened.
|
|
33
|
+
*/
|
|
34
|
+
export function setActiveMcpWindowResolver(resolve) {
|
|
35
|
+
resolveActiveOwner = resolve;
|
|
39
36
|
}
|
|
40
|
-
export function
|
|
41
|
-
|
|
37
|
+
export function registerMcpWindow(owner, facts) {
|
|
38
|
+
windowFacts.set(owner, facts);
|
|
39
|
+
return {
|
|
40
|
+
facts,
|
|
41
|
+
dispose: () => {
|
|
42
|
+
// Only this window's record: other project windows may still be open and
|
|
43
|
+
// their native-host state has to survive this teardown.
|
|
44
|
+
if (windowFacts.get(owner) === facts)
|
|
45
|
+
windowFacts.delete(owner);
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/** The facts of the project window MCP currently drives, or null when none is open. */
|
|
50
|
+
export function activeMcpWindow() {
|
|
51
|
+
const owner = resolveActiveOwner();
|
|
52
|
+
return (owner !== null && windowFacts.get(owner)) || null;
|
|
42
53
|
}
|
|
43
54
|
/**
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
* reconnect so MCP re-points at the new active page.
|
|
55
|
+
* Record the render guest now visible in `owner`'s window. Re-points the live
|
|
56
|
+
* simulator connection only when that window is the one MCP drives — a
|
|
57
|
+
* navigation in a background project window must not steal the target.
|
|
48
58
|
*/
|
|
49
|
-
export function
|
|
50
|
-
|
|
59
|
+
export function noteActiveBridgeId(owner, id) {
|
|
60
|
+
const facts = windowFacts.get(owner);
|
|
61
|
+
if (!facts || facts.activeBridgeId === id)
|
|
51
62
|
return;
|
|
52
|
-
activeBridgeId = id;
|
|
53
|
-
if (
|
|
63
|
+
facts.activeBridgeId = id;
|
|
64
|
+
if (facts.nativeHost && resolveActiveOwner() === owner && targets.simulator.connected) {
|
|
54
65
|
void connectTarget('simulator');
|
|
55
66
|
}
|
|
56
67
|
}
|
|
57
|
-
export function setNativeOverviewProvider(provider) {
|
|
58
|
-
nativeOverviewProvider = provider;
|
|
59
|
-
}
|
|
60
|
-
export function getNativeOverviewProvider() {
|
|
61
|
-
return nativeOverviewProvider;
|
|
62
|
-
}
|
|
63
68
|
/**
|
|
64
|
-
*
|
|
69
|
+
* The active project window changed. A connection that is already established
|
|
70
|
+
* was aimed at whichever window was active when it was made, and nothing
|
|
71
|
+
* re-read that afterwards — so without this the MCP tools keep reporting and
|
|
72
|
+
* driving the project the user has left. Only connections bound to a different
|
|
73
|
+
* window are re-aimed; the rest are left alone.
|
|
65
74
|
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
* Native-host path: the active render-host <webview> guest
|
|
70
|
-
* (pageFrame.html?...bridgeId=<id>), preferring the guest matching
|
|
71
|
-
* `activeBridgeId`, then any pageFrame guest, then degrading to the shell.
|
|
75
|
+
* Coalesced on purpose: clicking across windows produces a burst of these, and
|
|
76
|
+
* re-resolving once the burst settles means focus that returns to the window a
|
|
77
|
+
* connection already holds costs nothing.
|
|
72
78
|
*/
|
|
73
|
-
export function
|
|
74
|
-
if (
|
|
75
|
-
return
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
79
|
+
export function noteActiveMcpWindowChanged() {
|
|
80
|
+
if (repointTimer)
|
|
81
|
+
return;
|
|
82
|
+
repointTimer = setTimeout(() => {
|
|
83
|
+
repointTimer = null;
|
|
84
|
+
const owner = resolveActiveOwner();
|
|
85
|
+
// A window whose facts are already gone is on its way out: its pages are
|
|
86
|
+
// about to be destroyed, so connecting into them would only produce a
|
|
87
|
+
// client that immediately disconnects. The reconnect timer picks up
|
|
88
|
+
// whichever window replaces it.
|
|
89
|
+
if (owner !== null && !windowFacts.has(owner))
|
|
90
|
+
return;
|
|
91
|
+
for (const kind of Object.keys(targets)) {
|
|
92
|
+
if (!targets[kind].connected || targets[kind].owner === owner)
|
|
93
|
+
continue;
|
|
94
|
+
void connectTarget(kind);
|
|
95
|
+
}
|
|
96
|
+
}, ACTIVE_WINDOW_SETTLE_MS);
|
|
97
|
+
}
|
|
98
|
+
// The two CDP connections are process-wide on purpose: MCP exposes one
|
|
99
|
+
// `simulator` and one `workbench` target with no window argument, so both
|
|
100
|
+
// always mean "the project the user is working in". Which window that is comes
|
|
101
|
+
// from `activeMcpWindow()` on every (re)connect, so the pair follows the
|
|
102
|
+
// active window rather than belonging to any one of them.
|
|
103
|
+
const targets = {
|
|
104
|
+
simulator: { client: null, connected: false, owner: null, timer: null, consoleLogs: [], networkRequests: [], bufferOwner: null },
|
|
105
|
+
workbench: { client: null, connected: false, owner: null, timer: null, consoleLogs: [], networkRequests: [], bufferOwner: null },
|
|
106
|
+
};
|
|
107
|
+
/** Monotonic per target: only the newest connect attempt may publish itself. */
|
|
108
|
+
const connectGeneration = { simulator: 0, workbench: 0 };
|
|
109
|
+
let repointTimer = null;
|
|
110
|
+
export function setCdpPort(port) {
|
|
111
|
+
cdpPort = port;
|
|
112
|
+
}
|
|
113
|
+
/** The cross-process overview reader of the window MCP drives, if it has one. */
|
|
114
|
+
export function getNativeOverviewProvider() {
|
|
115
|
+
return activeMcpWindow()?.nativeOverviewProvider ?? null;
|
|
90
116
|
}
|
|
91
117
|
export function getTargetState(kind) {
|
|
92
118
|
return targets[kind];
|
|
@@ -100,27 +126,150 @@ async function listCdpTargets() {
|
|
|
100
126
|
}
|
|
101
127
|
}
|
|
102
128
|
export { listCdpTargets as listTargets };
|
|
129
|
+
/**
|
|
130
|
+
* `selectWorkbenchTarget` already matches on the active window's exact
|
|
131
|
+
* `projectPath`, so no candidate ranking is blind to ownership there — the
|
|
132
|
+
* match is exact or nothing, with nothing left for a pre-filter to change.
|
|
133
|
+
*/
|
|
134
|
+
function findWorkbenchTarget(allTargets) {
|
|
135
|
+
const active = activeMcpWindow();
|
|
136
|
+
return selectWorkbenchTarget(allTargets, { projectPath: active ? active.projectPath : null });
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* `selectSimulatorTarget` ranks candidates by a fixed priority order with no
|
|
140
|
+
* idea which window each one belongs to, and its "any guest" tier in
|
|
141
|
+
* particular has no way to tell a stray guest left over from another window
|
|
142
|
+
* apart from a legitimate one.
|
|
143
|
+
*
|
|
144
|
+
* Once the active window has an `activeBridgeId` of its own, it is known to
|
|
145
|
+
* be genuinely on a native page and merely waiting for that specific guest
|
|
146
|
+
* target to show up in the CDP list — connecting to whatever guest IS present
|
|
147
|
+
* and letting the post-connect ownership check below reject a wrong one is a
|
|
148
|
+
* reasonable, existing way to close that timing gap, so ranking stays
|
|
149
|
+
* unfiltered in that case.
|
|
150
|
+
*
|
|
151
|
+
* Before any page is known for this window (`activeBridgeId === null`, which
|
|
152
|
+
* is also always true for non-native windows), though, "any guest present"
|
|
153
|
+
* carries no signal it belongs to THIS window at all — so ranking is
|
|
154
|
+
* restricted to targets `connectionOwner` attributes to the active window,
|
|
155
|
+
* falling back to the raw list only when none of them qualify (the same
|
|
156
|
+
* retry-and-reject cadence as the unfiltered path, for a candidate list that
|
|
157
|
+
* belongs to no window MCP can currently claim).
|
|
158
|
+
*/
|
|
159
|
+
function findSimulatorTarget(allTargets) {
|
|
160
|
+
const active = activeMcpWindow();
|
|
161
|
+
const opts = { nativeHost: active?.nativeHost ?? false, activeBridgeId: active?.activeBridgeId ?? null };
|
|
162
|
+
if (opts.activeBridgeId !== null)
|
|
163
|
+
return selectSimulatorTarget(allTargets, opts);
|
|
164
|
+
const intended = resolveActiveOwner();
|
|
165
|
+
const owned = allTargets.filter((t) => connectionOwner('simulator', t.url, intended, windowFacts).onTarget);
|
|
166
|
+
return selectSimulatorTarget(owned, opts) ?? selectSimulatorTarget(allTargets, opts);
|
|
167
|
+
}
|
|
103
168
|
function findTarget(allTargets, kind) {
|
|
104
|
-
|
|
105
|
-
|
|
169
|
+
return kind === 'simulator' ? findSimulatorTarget(allTargets) : findWorkbenchTarget(allTargets);
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Console and network events into this target's ring buffers, which is all
|
|
173
|
+
* these subscriptions do — they hold no view of which window is connected, so
|
|
174
|
+
* they outlive nothing and need no generation check of their own.
|
|
175
|
+
*/
|
|
176
|
+
function subscribeBuffers(client, state) {
|
|
177
|
+
const pending = new Map();
|
|
178
|
+
const pushNetworkRequest = (entry) => {
|
|
179
|
+
state.networkRequests.push(entry);
|
|
180
|
+
if (state.networkRequests.length > MAX_BUFFER)
|
|
181
|
+
state.networkRequests = state.networkRequests.slice(-MAX_BUFFER);
|
|
182
|
+
};
|
|
183
|
+
const pushConsoleLog = (entry) => {
|
|
184
|
+
state.consoleLogs.push(entry);
|
|
185
|
+
if (state.consoleLogs.length > MAX_BUFFER)
|
|
186
|
+
state.consoleLogs = state.consoleLogs.slice(-MAX_BUFFER);
|
|
187
|
+
};
|
|
188
|
+
client.Runtime.on('consoleAPICalled', (params) => {
|
|
189
|
+
pushConsoleLog({
|
|
190
|
+
level: params.type,
|
|
191
|
+
text: params.args.map((a) => String(a.value ?? a.description ?? JSON.stringify(a))).join(' '),
|
|
192
|
+
timestamp: new Date(params.timestamp).toISOString(),
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
client.Console.on('messageAdded', (params) => {
|
|
196
|
+
const msg = params.message;
|
|
197
|
+
pushConsoleLog({ level: msg.level, text: msg.text, timestamp: new Date().toISOString() });
|
|
198
|
+
});
|
|
199
|
+
client.Network.on('requestWillBeSent', (params) => {
|
|
200
|
+
pending.set(params.requestId, { url: params.request.url, method: params.request.method, timestamp: params.timestamp });
|
|
201
|
+
});
|
|
202
|
+
client.Network.on('responseReceived', (params) => {
|
|
203
|
+
const req = pending.get(params.requestId);
|
|
204
|
+
if (!req)
|
|
205
|
+
return;
|
|
206
|
+
pending.delete(params.requestId);
|
|
207
|
+
pushNetworkRequest({
|
|
208
|
+
url: req.url, method: req.method,
|
|
209
|
+
status: params.response.status, mimeType: params.response.mimeType,
|
|
210
|
+
responseSize: params.response.encodedDataLength || 0,
|
|
211
|
+
timing: params.response.timing
|
|
212
|
+
? { requestTime: params.response.timing.requestTime, receiveHeadersEnd: params.response.timing.receiveHeadersEnd }
|
|
213
|
+
: null,
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
client.Network.on('loadingFailed', (params) => {
|
|
217
|
+
const req = pending.get(params.requestId);
|
|
218
|
+
if (!req)
|
|
219
|
+
return;
|
|
220
|
+
pending.delete(params.requestId);
|
|
221
|
+
pushNetworkRequest({ url: req.url, method: req.method, status: 0, mimeType: '', responseSize: 0, timing: null });
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
/** Closing a client is never the reason an attempt fails. */
|
|
225
|
+
async function closeQuietly(client) {
|
|
226
|
+
if (!client)
|
|
227
|
+
return;
|
|
228
|
+
try {
|
|
229
|
+
await client.close();
|
|
230
|
+
}
|
|
231
|
+
catch { }
|
|
232
|
+
}
|
|
233
|
+
/** No usable target right now: publish nothing and keep retrying. */
|
|
234
|
+
function loseTarget(kind) {
|
|
235
|
+
const state = targets[kind];
|
|
236
|
+
state.client = null;
|
|
237
|
+
state.connected = false;
|
|
238
|
+
state.owner = null;
|
|
239
|
+
scheduleReconnect(kind);
|
|
240
|
+
}
|
|
241
|
+
/** Publish a connection that survived the race, on the window it reached. */
|
|
242
|
+
function publishConnection(kind, client, owner) {
|
|
243
|
+
const state = targets[kind];
|
|
244
|
+
state.client = client;
|
|
245
|
+
state.connected = true;
|
|
246
|
+
state.owner = owner;
|
|
247
|
+
if (state.timer) {
|
|
248
|
+
clearTimeout(state.timer);
|
|
249
|
+
state.timer = null;
|
|
106
250
|
}
|
|
107
|
-
// workbench main window: page target whose URL contains index.html (renderer)
|
|
108
|
-
return allTargets.find((t) => t.type === 'page' && t.url?.includes('entries/main/index.html') && !t.url?.includes(SIMULATOR_URL_PATTERN));
|
|
109
251
|
}
|
|
110
252
|
export async function connectTarget(kind) {
|
|
111
253
|
const state = targets[kind];
|
|
254
|
+
// Establishing a connection is a long chain of awaits, and the reason to
|
|
255
|
+
// establish it — which window is active, which page it shows — can change
|
|
256
|
+
// while that chain runs. An attempt overtaken by a newer one must publish
|
|
257
|
+
// nothing, close the client it opened, and schedule no work.
|
|
258
|
+
const generation = (connectGeneration[kind] += 1);
|
|
259
|
+
const superseded = () => connectGeneration[kind] !== generation;
|
|
112
260
|
if (state.client) {
|
|
113
|
-
|
|
114
|
-
await state.client.close();
|
|
115
|
-
}
|
|
116
|
-
catch { }
|
|
261
|
+
const previous = state.client;
|
|
117
262
|
state.client = null;
|
|
263
|
+
await closeQuietly(previous);
|
|
264
|
+
if (superseded())
|
|
265
|
+
return;
|
|
118
266
|
}
|
|
119
267
|
const allTargets = await listCdpTargets();
|
|
120
268
|
const target = findTarget(allTargets, kind);
|
|
269
|
+
if (superseded())
|
|
270
|
+
return;
|
|
121
271
|
if (!target) {
|
|
122
|
-
|
|
123
|
-
scheduleReconnect(kind);
|
|
272
|
+
loseTarget(kind);
|
|
124
273
|
return;
|
|
125
274
|
}
|
|
126
275
|
let client = null;
|
|
@@ -133,83 +282,54 @@ export async function connectTarget(kind) {
|
|
|
133
282
|
client.Network.enable(),
|
|
134
283
|
client.Console.enable(),
|
|
135
284
|
]);
|
|
136
|
-
//
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
//
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
client.Console.on('messageAdded', (params) => {
|
|
155
|
-
const msg = params.message;
|
|
156
|
-
state.consoleLogs.push({ level: msg.level, text: msg.text, timestamp: new Date().toISOString() });
|
|
157
|
-
if (state.consoleLogs.length > MAX_BUFFER)
|
|
158
|
-
state.consoleLogs = state.consoleLogs.slice(-MAX_BUFFER);
|
|
159
|
-
});
|
|
160
|
-
client.Network.on('requestWillBeSent', (params) => {
|
|
161
|
-
pending.set(params.requestId, { url: params.request.url, method: params.request.method, timestamp: params.timestamp });
|
|
162
|
-
});
|
|
163
|
-
client.Network.on('responseReceived', (params) => {
|
|
164
|
-
const req = pending.get(params.requestId);
|
|
165
|
-
if (!req)
|
|
166
|
-
return;
|
|
167
|
-
pending.delete(params.requestId);
|
|
168
|
-
pushNetworkRequest({
|
|
169
|
-
url: req.url, method: req.method,
|
|
170
|
-
status: params.response.status, mimeType: params.response.mimeType,
|
|
171
|
-
responseSize: params.response.encodedDataLength || 0,
|
|
172
|
-
timing: params.response.timing
|
|
173
|
-
? { requestTime: params.response.timing.requestTime, receiveHeadersEnd: params.response.timing.receiveHeadersEnd }
|
|
174
|
-
: null,
|
|
175
|
-
});
|
|
176
|
-
});
|
|
177
|
-
client.Network.on('loadingFailed', (params) => {
|
|
178
|
-
const req = pending.get(params.requestId);
|
|
179
|
-
if (!req)
|
|
285
|
+
// Everything below subscribes or publishes, so an attempt that lost the
|
|
286
|
+
// race stops here and leaves nothing behind but its own closed client.
|
|
287
|
+
if (superseded()) {
|
|
288
|
+
await closeQuietly(client);
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
// Which window this target belongs to is resolved here, not when the
|
|
292
|
+
// attempt started: an attempt that outlived a window switch has to be
|
|
293
|
+
// judged against the window the user is in now. MCP exposes ONE client per
|
|
294
|
+
// kind, so a target belonging to another window leaves nothing behind at
|
|
295
|
+
// all — buffers wired to it would mix that window's console and network
|
|
296
|
+
// events into the ones the eventual right connection appends to, and
|
|
297
|
+
// `connected` would hand it out meanwhile. The retry cadence is the only
|
|
298
|
+
// thing that carries over: the exact target may still be loading.
|
|
299
|
+
const binding = connectionOwner(kind, target.url, resolveActiveOwner(), windowFacts);
|
|
300
|
+
if (!binding.onTarget) {
|
|
301
|
+
await closeQuietly(client);
|
|
302
|
+
if (superseded())
|
|
180
303
|
return;
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
304
|
+
loseTarget(kind);
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
// Buffers are keyed to the owner they were collected for, not to the
|
|
308
|
+
// kind slot: a reconnect landing on the SAME owner (a transient CDP drop)
|
|
309
|
+
// must keep what was already buffered, but re-aiming at a different
|
|
310
|
+
// window must not let that window inherit the previous owner's entries.
|
|
311
|
+
if (state.bufferOwner !== binding.owner) {
|
|
312
|
+
state.consoleLogs = [];
|
|
313
|
+
state.networkRequests = [];
|
|
314
|
+
state.bufferOwner = binding.owner;
|
|
315
|
+
}
|
|
316
|
+
subscribeBuffers(client, state);
|
|
191
317
|
client.on('disconnect', () => {
|
|
318
|
+
// A superseded client is closed on purpose; only the live connection
|
|
319
|
+
// going away means MCP has lost its target.
|
|
320
|
+
if (superseded())
|
|
321
|
+
return;
|
|
192
322
|
state.connected = false;
|
|
193
323
|
state.client = null;
|
|
194
324
|
scheduleReconnect(kind);
|
|
195
325
|
});
|
|
196
|
-
|
|
197
|
-
state.connected = true;
|
|
198
|
-
if (state.timer) {
|
|
199
|
-
clearTimeout(state.timer);
|
|
200
|
-
state.timer = null;
|
|
201
|
-
}
|
|
326
|
+
publishConnection(kind, client, binding.owner);
|
|
202
327
|
}
|
|
203
328
|
catch {
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
catch { }
|
|
209
|
-
}
|
|
210
|
-
state.client = null;
|
|
211
|
-
state.connected = false;
|
|
212
|
-
scheduleReconnect(kind);
|
|
329
|
+
await closeQuietly(client);
|
|
330
|
+
if (superseded())
|
|
331
|
+
return;
|
|
332
|
+
loseTarget(kind);
|
|
213
333
|
}
|
|
214
334
|
}
|
|
215
335
|
function scheduleReconnect(kind) {
|
|
@@ -223,10 +343,17 @@ function scheduleReconnect(kind) {
|
|
|
223
343
|
}
|
|
224
344
|
export function getClient(kind) {
|
|
225
345
|
const state = targets[kind];
|
|
346
|
+
const label = kind === 'simulator' ? '模拟器' : '主窗口';
|
|
226
347
|
if (!state.connected || !state.client) {
|
|
227
|
-
const label = kind === 'simulator' ? '模拟器' : '主窗口';
|
|
228
348
|
throw new Error(`未连接到${label}。请确保 dimina-devtools 正在以开发模式运行。`);
|
|
229
349
|
}
|
|
350
|
+
// A focus change re-aims the live connections only once the burst settles,
|
|
351
|
+
// and during that gap the client still belongs to the window the user left.
|
|
352
|
+
// Answering from it would report and drive the wrong project, so the caller
|
|
353
|
+
// waits for the re-aim instead.
|
|
354
|
+
if (state.owner !== resolveActiveOwner()) {
|
|
355
|
+
throw new Error(`${label}连接属于已切换的项目窗口,正在重新连接,请稍后重试。`);
|
|
356
|
+
}
|
|
230
357
|
return state.client;
|
|
231
358
|
}
|
|
232
359
|
//# sourceMappingURL=target-manager.js.map
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure candidate-ranking rules for the two MCP CDP targets.
|
|
3
|
+
*
|
|
4
|
+
* Split out of target-manager.ts: these functions only rank a raw CDP.List
|
|
5
|
+
* result by URL shape and carry no connection state of their own, so they can
|
|
6
|
+
* be pinned with direct unit tests independent of the connection lifecycle.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Resolve which CDP target the `simulator` MCP tools should drive.
|
|
10
|
+
*
|
|
11
|
+
* Default (non-native) path: the localhost:7788 simulator shell — identical
|
|
12
|
+
* to the original behavior; `activeBridgeId` is ignored.
|
|
13
|
+
*
|
|
14
|
+
* Native-host path: the active render-host <webview> guest
|
|
15
|
+
* (pageFrame.html?...bridgeId=<id>), preferring the guest matching
|
|
16
|
+
* `activeBridgeId`, then any pageFrame guest, then degrading to the shell.
|
|
17
|
+
*/
|
|
18
|
+
export declare function selectSimulatorTarget<T extends {
|
|
19
|
+
url?: string;
|
|
20
|
+
type?: string;
|
|
21
|
+
}>(targets: T[], opts: {
|
|
22
|
+
nativeHost: boolean;
|
|
23
|
+
activeBridgeId: string | null;
|
|
24
|
+
}): T | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* Resolve which CDP target the `workbench` MCP tools should drive.
|
|
27
|
+
*
|
|
28
|
+
* `projectPath` is the active project window's path, fixed when that window
|
|
29
|
+
* opened; null when no project window is open, and then the project list is
|
|
30
|
+
* the only workbench surface.
|
|
31
|
+
*
|
|
32
|
+
* A project window names its own renderer from the moment it exists, so the
|
|
33
|
+
* match is exact or nothing: another project's workbench page, or the project
|
|
34
|
+
* list standing in for a project that IS open, would leave every workbench
|
|
35
|
+
* tool answering for the wrong window with nothing to correct it.
|
|
36
|
+
*
|
|
37
|
+
* Matching is on the renderer ENTRY, never on "the URL mentions the project
|
|
38
|
+
* directory" — the service-host window carries the same directory in its own
|
|
39
|
+
* `pkgRoot` query and would win a substring match.
|
|
40
|
+
*/
|
|
41
|
+
export declare function selectWorkbenchTarget<T extends {
|
|
42
|
+
url?: string;
|
|
43
|
+
type?: string;
|
|
44
|
+
}>(candidates: T[], opts: {
|
|
45
|
+
projectPath: string | null;
|
|
46
|
+
}): T | undefined;
|
|
47
|
+
//# sourceMappingURL=target-selection.d.ts.map
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure candidate-ranking rules for the two MCP CDP targets.
|
|
3
|
+
*
|
|
4
|
+
* Split out of target-manager.ts: these functions only rank a raw CDP.List
|
|
5
|
+
* result by URL shape and carry no connection state of their own, so they can
|
|
6
|
+
* be pinned with direct unit tests independent of the connection lifecycle.
|
|
7
|
+
*/
|
|
8
|
+
import { DMB_PAGEFRAME_DOC_NAME } from '../../../shared/dmb-resource-url.js';
|
|
9
|
+
import { targetQuery } from './connection-owner.js';
|
|
10
|
+
const SIMULATOR_URL_PATTERN = 'localhost:7788';
|
|
11
|
+
// The two renderer entries MCP can drive: a project's workbench window and the
|
|
12
|
+
// always-present project list.
|
|
13
|
+
const WORKBENCH_ENTRY = 'entries/workbench/index.html';
|
|
14
|
+
const PROJECT_LIST_ENTRY = 'entries/main/index.html';
|
|
15
|
+
// Native-host: the real mini-app page runs in a nested render-host <webview>
|
|
16
|
+
// guest whose CDP target URL carries the render frame + the page's bridgeId.
|
|
17
|
+
// Import the shared reserved doc name rather than hand-writing a second
|
|
18
|
+
// literal — that duplication is exactly what let this pattern drift out of
|
|
19
|
+
// sync with the actual document URL shape (dmb-resource-url.ts).
|
|
20
|
+
const RENDER_GUEST_PATTERN = DMB_PAGEFRAME_DOC_NAME;
|
|
21
|
+
/**
|
|
22
|
+
* Resolve which CDP target the `simulator` MCP tools should drive.
|
|
23
|
+
*
|
|
24
|
+
* Default (non-native) path: the localhost:7788 simulator shell — identical
|
|
25
|
+
* to the original behavior; `activeBridgeId` is ignored.
|
|
26
|
+
*
|
|
27
|
+
* Native-host path: the active render-host <webview> guest
|
|
28
|
+
* (pageFrame.html?...bridgeId=<id>), preferring the guest matching
|
|
29
|
+
* `activeBridgeId`, then any pageFrame guest, then degrading to the shell.
|
|
30
|
+
*/
|
|
31
|
+
export function selectSimulatorTarget(targets, opts) {
|
|
32
|
+
if (!opts.nativeHost) {
|
|
33
|
+
return targets.find((t) => t.url?.includes(SIMULATOR_URL_PATTERN));
|
|
34
|
+
}
|
|
35
|
+
// 1) Active-bridge guest takes priority over list order.
|
|
36
|
+
if (opts.activeBridgeId !== null) {
|
|
37
|
+
const bridgeMatch = `bridgeId=${opts.activeBridgeId}`;
|
|
38
|
+
const active = targets.find((t) => t.url?.includes(RENDER_GUEST_PATTERN) && t.url.includes(bridgeMatch));
|
|
39
|
+
if (active)
|
|
40
|
+
return active;
|
|
41
|
+
}
|
|
42
|
+
// 2) Any render guest (no active match / no active bridge).
|
|
43
|
+
const anyGuest = targets.find((t) => t.url?.includes(RENDER_GUEST_PATTERN));
|
|
44
|
+
if (anyGuest)
|
|
45
|
+
return anyGuest;
|
|
46
|
+
// 3) Degrade to the localhost:7788 shell when no render guest exists yet.
|
|
47
|
+
return targets.find((t) => t.url?.includes(SIMULATOR_URL_PATTERN));
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Resolve which CDP target the `workbench` MCP tools should drive.
|
|
51
|
+
*
|
|
52
|
+
* `projectPath` is the active project window's path, fixed when that window
|
|
53
|
+
* opened; null when no project window is open, and then the project list is
|
|
54
|
+
* the only workbench surface.
|
|
55
|
+
*
|
|
56
|
+
* A project window names its own renderer from the moment it exists, so the
|
|
57
|
+
* match is exact or nothing: another project's workbench page, or the project
|
|
58
|
+
* list standing in for a project that IS open, would leave every workbench
|
|
59
|
+
* tool answering for the wrong window with nothing to correct it.
|
|
60
|
+
*
|
|
61
|
+
* Matching is on the renderer ENTRY, never on "the URL mentions the project
|
|
62
|
+
* directory" — the service-host window carries the same directory in its own
|
|
63
|
+
* `pkgRoot` query and would win a substring match.
|
|
64
|
+
*/
|
|
65
|
+
export function selectWorkbenchTarget(candidates, opts) {
|
|
66
|
+
const pages = candidates.filter((t) => t.type === 'page' && !t.url?.includes(SIMULATOR_URL_PATTERN));
|
|
67
|
+
if (opts.projectPath === null)
|
|
68
|
+
return pages.find((t) => t.url?.includes(PROJECT_LIST_ENTRY));
|
|
69
|
+
return pages.find((t) => t.url?.includes(WORKBENCH_ENTRY) && targetQuery(t.url, 'path') === opts.projectPath);
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=target-selection.js.map
|
|
@@ -136,8 +136,21 @@ export function registerContextTools(server) {
|
|
|
136
136
|
return { content: [{ type: 'text', text: JSON.stringify(payload, null, 2) }] };
|
|
137
137
|
}
|
|
138
138
|
let result;
|
|
139
|
+
// Snapshot the provider AND the console/network summaries in the same
|
|
140
|
+
// tick as `getClient`: the provider reads the active window live off
|
|
141
|
+
// `resolveActiveOwner()`, and the buffers are process-wide and get
|
|
142
|
+
// cleared and re-owned the moment a reconnect lands on another window.
|
|
143
|
+
// Both awaits below (the CDP probe, the native provider) are windows the
|
|
144
|
+
// user can switch projects during; reading either after them would mix
|
|
145
|
+
// this window's probe with whichever window is active by then.
|
|
146
|
+
let nativeOverviewProvider;
|
|
147
|
+
let consoleSum;
|
|
148
|
+
let networkSum;
|
|
139
149
|
try {
|
|
140
150
|
const c = getClient('simulator');
|
|
151
|
+
nativeOverviewProvider = getNativeOverviewProvider();
|
|
152
|
+
consoleSum = summarizeConsole('simulator');
|
|
153
|
+
networkSum = summarizeNetwork('simulator');
|
|
141
154
|
result = await c.Runtime.evaluate({ expression: SIMULATOR_PROBE_EXPR, returnByValue: true });
|
|
142
155
|
}
|
|
143
156
|
catch {
|
|
@@ -160,7 +173,6 @@ export function registerContextTools(server) {
|
|
|
160
173
|
isError: true,
|
|
161
174
|
};
|
|
162
175
|
}
|
|
163
|
-
const nativeOverviewProvider = getNativeOverviewProvider();
|
|
164
176
|
if (nativeOverviewProvider) {
|
|
165
177
|
try {
|
|
166
178
|
const nativeOverview = await nativeOverviewProvider();
|
|
@@ -182,8 +194,6 @@ export function registerContextTools(server) {
|
|
|
182
194
|
hints.push('no active miniapp page (empty page stack)');
|
|
183
195
|
if (probe.storageCount > MAX_KEYS)
|
|
184
196
|
hints.push(`storageKeys truncated to first ${MAX_KEYS} of ${probe.storageCount}`);
|
|
185
|
-
const consoleSum = summarizeConsole('simulator');
|
|
186
|
-
const networkSum = summarizeNetwork('simulator');
|
|
187
197
|
const payload = {
|
|
188
198
|
connected: true,
|
|
189
199
|
url: probe.url,
|
|
@@ -213,8 +223,15 @@ export function registerContextTools(server) {
|
|
|
213
223
|
return { content: [{ type: 'text', text: JSON.stringify(payload, null, 2) }] };
|
|
214
224
|
}
|
|
215
225
|
let result;
|
|
226
|
+
// Same snapshot rule as the simulator overview: the buffers belong to
|
|
227
|
+
// the connection `getClient` just vouched for, so they are read before
|
|
228
|
+
// the probe's await, not after it.
|
|
229
|
+
let consoleSum;
|
|
230
|
+
let networkSum;
|
|
216
231
|
try {
|
|
217
232
|
const c = getClient('workbench');
|
|
233
|
+
consoleSum = summarizeConsole('workbench');
|
|
234
|
+
networkSum = summarizeNetwork('workbench');
|
|
218
235
|
result = await c.Runtime.evaluate({ expression: WORKBENCH_PROBE_EXPR, returnByValue: true });
|
|
219
236
|
}
|
|
220
237
|
catch {
|
|
@@ -237,8 +254,6 @@ export function registerContextTools(server) {
|
|
|
237
254
|
isError: true,
|
|
238
255
|
};
|
|
239
256
|
}
|
|
240
|
-
const consoleSum = summarizeConsole('workbench');
|
|
241
|
-
const networkSum = summarizeNetwork('workbench');
|
|
242
257
|
const payload = {
|
|
243
258
|
connected: true,
|
|
244
259
|
url: probe.url,
|