@dimina-kit/devtools 0.4.0-dev.20260728065133 → 0.4.0-dev.20260728095034
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/dist/main/app/app.js +11 -3
- package/dist/main/index.bundle.js +319 -81
- package/dist/main/ipc/settings.js +4 -0
- package/dist/main/services/mcp/server.d.ts +2 -1
- package/dist/main/services/mcp/server.js +6 -3
- package/dist/main/services/mcp/tools/project-tools.d.ts +49 -0
- package/dist/main/services/mcp/tools/project-tools.js +121 -0
- package/dist/main/services/notifications/renderer-notifier.d.ts +11 -0
- package/dist/main/services/notifications/renderer-notifier.js +3 -0
- package/dist/main/services/workbench-context.d.ts +14 -0
- package/dist/main/services/workbench-context.js +9 -1
- package/dist/main/services/workspace/compile-log-buffer.d.ts +40 -0
- package/dist/main/services/workspace/compile-log-buffer.js +41 -0
- package/dist/main/services/workspace/session-status-store.d.ts +47 -0
- package/dist/main/services/workspace/session-status-store.js +73 -0
- package/dist/main/services/workspace/status-tap.d.ts +20 -0
- package/dist/main/services/workspace/status-tap.js +32 -0
- package/dist/native-host/common/common.js +58 -154
- package/dist/native-host/container/pageFrame.css +1 -1
- package/dist/native-host/render/render.js +3297 -6602
- package/dist/native-host/service/service.js +2 -2
- package/dist/preload/windows/host-toolbar-runtime.cjs.map +2 -2
- package/dist/preload/windows/simulator.cjs.map +1 -1
- package/dist/renderer/assets/index-BJlFbXHb.js +49 -0
- package/dist/renderer/assets/{input-dsgeTmVX.js → input-xdmfv-eH.js} +2 -2
- package/dist/renderer/assets/{ipc-transport-BgFdT9bT.js → ipc-transport-B3EpmfNS.js} +2 -2
- package/dist/renderer/assets/popover-B88e2hkg.js +2 -0
- package/dist/renderer/assets/{select-DAw1hzkl.js → select-CD9CJyhI.js} +2 -2
- package/dist/renderer/assets/settings-44hf0QtO.js +2 -0
- package/dist/renderer/assets/settings-api-pJKPuP1M.js +2 -0
- package/dist/renderer/assets/workbenchSettings-DKD5U1Ql.js +8 -0
- package/dist/renderer/entries/main/index.html +5 -5
- package/dist/renderer/entries/popover/index.html +4 -4
- package/dist/renderer/entries/settings/index.html +4 -4
- package/dist/renderer/entries/workbench-settings/index.html +3 -3
- package/dist/shared/ipc-channels.d.ts +2 -0
- package/dist/shared/ipc-channels.js +2 -0
- package/package.json +6 -6
- package/dist/renderer/assets/index-M5NDq_vi.js +0 -49
- package/dist/renderer/assets/popover-Disfu1cx.js +0 -2
- package/dist/renderer/assets/settings-M_8GFW2M.js +0 -2
- package/dist/renderer/assets/settings-api-DFR5eDl_.js +0 -2
- package/dist/renderer/assets/workbenchSettings-CxdXeoOu.js +0 -8
|
@@ -419,6 +419,7 @@ var WorkbenchSettingsChannel = {
|
|
|
419
419
|
Get: "workbenchSettings:get",
|
|
420
420
|
Save: "workbenchSettings:save",
|
|
421
421
|
SetTheme: "workbenchSettings:setTheme",
|
|
422
|
+
Restart: "workbenchSettings:restart",
|
|
422
423
|
GetCdpStatus: "workbenchSettings:getCdpStatus",
|
|
423
424
|
GetMcpStatus: "workbenchSettings:getMcpStatus",
|
|
424
425
|
Init: "workbenchSettings:init",
|
|
@@ -531,6 +532,7 @@ var PopoverChannel = {
|
|
|
531
532
|
};
|
|
532
533
|
var WindowChannel = {
|
|
533
534
|
NavigateBack: "window:navigateBack",
|
|
535
|
+
OpenProject: "window:openProject",
|
|
534
536
|
// Renderer → main: the renderer's current top-level screen ('project' when
|
|
535
537
|
// inside a project screen, 'list' on the project list / landing). The
|
|
536
538
|
// renderer pushes this on every screen change, including the moment it enters
|
|
@@ -899,7 +901,7 @@ function registerProjectFsIpc(ctx) {
|
|
|
899
901
|
// src/main/app/app.ts
|
|
900
902
|
import { app as app15, BrowserWindow as BrowserWindow9, nativeImage, session as session4 } from "electron";
|
|
901
903
|
import fs13 from "fs";
|
|
902
|
-
import
|
|
904
|
+
import path26 from "path";
|
|
903
905
|
|
|
904
906
|
// src/main/utils/paths.ts
|
|
905
907
|
import fs3 from "fs";
|
|
@@ -1597,6 +1599,9 @@ function createRendererNotifier(ctx) {
|
|
|
1597
1599
|
windowNavigateBack() {
|
|
1598
1600
|
sendToMain(WindowChannel.NavigateBack);
|
|
1599
1601
|
},
|
|
1602
|
+
windowOpenProject(payload) {
|
|
1603
|
+
sendToMain(WindowChannel.OpenProject, payload);
|
|
1604
|
+
},
|
|
1600
1605
|
popoverClosed() {
|
|
1601
1606
|
sendToMain(PopoverChannel.Closed);
|
|
1602
1607
|
},
|
|
@@ -1628,6 +1633,104 @@ function createRendererNotifier(ctx) {
|
|
|
1628
1633
|
};
|
|
1629
1634
|
}
|
|
1630
1635
|
|
|
1636
|
+
// src/main/services/workspace/compile-log-buffer.ts
|
|
1637
|
+
var DEFAULT_CAPACITY = 1e3;
|
|
1638
|
+
var DEFAULT_READ_LIMIT = 100;
|
|
1639
|
+
function createCompileLogBuffer(capacity = DEFAULT_CAPACITY) {
|
|
1640
|
+
const entries = [];
|
|
1641
|
+
let seq = 0;
|
|
1642
|
+
return {
|
|
1643
|
+
append(entry) {
|
|
1644
|
+
entries.push({ seq: ++seq, ...entry });
|
|
1645
|
+
if (entries.length > capacity) entries.splice(0, entries.length - capacity);
|
|
1646
|
+
},
|
|
1647
|
+
read({ afterSeq = 0, limit = DEFAULT_READ_LIMIT, stream } = {}) {
|
|
1648
|
+
const matched = [];
|
|
1649
|
+
for (const entry of entries) {
|
|
1650
|
+
if (entry.seq <= afterSeq) continue;
|
|
1651
|
+
if (stream && entry.stream !== stream) continue;
|
|
1652
|
+
matched.push(entry);
|
|
1653
|
+
if (matched.length >= limit) break;
|
|
1654
|
+
}
|
|
1655
|
+
const last = matched[matched.length - 1];
|
|
1656
|
+
return { entries: matched, nextCursor: last ? last.seq : afterSeq };
|
|
1657
|
+
},
|
|
1658
|
+
clear() {
|
|
1659
|
+
entries.length = 0;
|
|
1660
|
+
}
|
|
1661
|
+
};
|
|
1662
|
+
}
|
|
1663
|
+
|
|
1664
|
+
// src/main/services/workspace/session-status-store.ts
|
|
1665
|
+
function toPhase(status2) {
|
|
1666
|
+
if (status2 === "compiling") return "compiling";
|
|
1667
|
+
if (status2 === "error") return "error";
|
|
1668
|
+
return "ready";
|
|
1669
|
+
}
|
|
1670
|
+
function createSessionStatusStore() {
|
|
1671
|
+
let snapshot = {
|
|
1672
|
+
phase: "idle",
|
|
1673
|
+
message: "",
|
|
1674
|
+
watcherAlive: true,
|
|
1675
|
+
updatedAt: 0,
|
|
1676
|
+
generation: 0
|
|
1677
|
+
};
|
|
1678
|
+
const waiters = /* @__PURE__ */ new Set();
|
|
1679
|
+
return {
|
|
1680
|
+
get: () => snapshot,
|
|
1681
|
+
record(payload) {
|
|
1682
|
+
const phase = toPhase(payload.status);
|
|
1683
|
+
snapshot = {
|
|
1684
|
+
phase,
|
|
1685
|
+
message: payload.message,
|
|
1686
|
+
// A dead watcher is a session-lifetime fact; only a NEW compile
|
|
1687
|
+
// (fresh open) resets it. Rebuild 'ready' chatter keeps it dead.
|
|
1688
|
+
watcherAlive: payload.watcher === "dead" ? false : phase === "compiling" ? true : snapshot.watcherAlive,
|
|
1689
|
+
updatedAt: Date.now(),
|
|
1690
|
+
generation: snapshot.generation + 1
|
|
1691
|
+
};
|
|
1692
|
+
for (const waiter of [...waiters]) waiter(snapshot);
|
|
1693
|
+
},
|
|
1694
|
+
waitForSettled({ afterGeneration = -1, timeoutMs }) {
|
|
1695
|
+
const isSettled = (s) => s.phase !== "compiling" && s.generation > afterGeneration;
|
|
1696
|
+
if (isSettled(snapshot)) return Promise.resolve(snapshot);
|
|
1697
|
+
return new Promise((resolve, reject) => {
|
|
1698
|
+
const timer = setTimeout(() => {
|
|
1699
|
+
waiters.delete(onRecord);
|
|
1700
|
+
reject(new Error(
|
|
1701
|
+
`timed out after ${timeoutMs}ms waiting for the compile to settle (last phase: ${snapshot.phase})`
|
|
1702
|
+
));
|
|
1703
|
+
}, timeoutMs);
|
|
1704
|
+
const onRecord = (s) => {
|
|
1705
|
+
if (!isSettled(s)) return;
|
|
1706
|
+
clearTimeout(timer);
|
|
1707
|
+
waiters.delete(onRecord);
|
|
1708
|
+
resolve(s);
|
|
1709
|
+
};
|
|
1710
|
+
waiters.add(onRecord);
|
|
1711
|
+
});
|
|
1712
|
+
}
|
|
1713
|
+
};
|
|
1714
|
+
}
|
|
1715
|
+
|
|
1716
|
+
// src/main/services/workspace/status-tap.ts
|
|
1717
|
+
function tapNotifierIntoStores(notify, status2, compileLogs) {
|
|
1718
|
+
return {
|
|
1719
|
+
...notify,
|
|
1720
|
+
projectStatus(payload) {
|
|
1721
|
+
if (payload.status === "compiling" && payload.hotReload !== true) {
|
|
1722
|
+
compileLogs.clear();
|
|
1723
|
+
}
|
|
1724
|
+
status2.record(payload);
|
|
1725
|
+
notify.projectStatus(payload);
|
|
1726
|
+
},
|
|
1727
|
+
compileLog(payload) {
|
|
1728
|
+
compileLogs.append(payload);
|
|
1729
|
+
notify.compileLog(payload);
|
|
1730
|
+
}
|
|
1731
|
+
};
|
|
1732
|
+
}
|
|
1733
|
+
|
|
1631
1734
|
// src/main/services/safe-area/index.ts
|
|
1632
1735
|
function guestInsets(device, isTabPage2) {
|
|
1633
1736
|
const top = device?.safeAreaInsets.top ?? 0;
|
|
@@ -4724,8 +4827,8 @@ function createHostToolbarView(ctx, reconciler, deps) {
|
|
|
4724
4827
|
hide() {
|
|
4725
4828
|
hideHostToolbar();
|
|
4726
4829
|
},
|
|
4727
|
-
setPreloadPath(
|
|
4728
|
-
hostToolbarPreloadOverride =
|
|
4830
|
+
setPreloadPath(path27) {
|
|
4831
|
+
hostToolbarPreloadOverride = path27;
|
|
4729
4832
|
},
|
|
4730
4833
|
setHeightMode(mode) {
|
|
4731
4834
|
if (mode !== "auto" && !(Number.isFinite(mode.fixed) && mode.fixed >= 0)) {
|
|
@@ -6153,7 +6256,13 @@ function createWorkbenchContext(opts) {
|
|
|
6153
6256
|
ctx.windows = createWindowService(opts.mainWindow);
|
|
6154
6257
|
ctx.views = createViewManager(ctx);
|
|
6155
6258
|
ctx.registry.add(() => ctx.views.disposeAll());
|
|
6156
|
-
ctx.
|
|
6259
|
+
ctx.sessionStatus = createSessionStatusStore();
|
|
6260
|
+
ctx.compileLogBuffer = createCompileLogBuffer();
|
|
6261
|
+
ctx.notify = tapNotifierIntoStores(
|
|
6262
|
+
createRendererNotifier(ctx),
|
|
6263
|
+
ctx.sessionStatus,
|
|
6264
|
+
ctx.compileLogBuffer
|
|
6265
|
+
);
|
|
6157
6266
|
ctx.openSettings = () => openSettingsWindow(ctx);
|
|
6158
6267
|
ctx.projectsProvider = opts.projectsProvider ?? createLocalProjectsProvider();
|
|
6159
6268
|
ctx.projectTemplates = resolveTemplates(
|
|
@@ -6734,6 +6843,9 @@ function registerSettingsIpc(ctx) {
|
|
|
6734
6843
|
args
|
|
6735
6844
|
);
|
|
6736
6845
|
applyTheme(theme);
|
|
6846
|
+
}).handle(WorkbenchSettingsChannel.Restart, () => {
|
|
6847
|
+
app9.relaunch();
|
|
6848
|
+
app9.quit();
|
|
6737
6849
|
}).handle(WorkbenchSettingsChannel.GetCdpStatus, () => {
|
|
6738
6850
|
const settings = loadWorkbenchSettings();
|
|
6739
6851
|
const switchValue = app9.commandLine.getSwitchValue("remote-debugging-port");
|
|
@@ -10813,10 +10925,127 @@ function registerContextTools(server) {
|
|
|
10813
10925
|
);
|
|
10814
10926
|
}
|
|
10815
10927
|
|
|
10816
|
-
// src/main/services/mcp/tools/
|
|
10928
|
+
// src/main/services/mcp/tools/project-tools.ts
|
|
10929
|
+
import path18 from "node:path";
|
|
10817
10930
|
import { z as z5 } from "zod";
|
|
10818
|
-
|
|
10819
|
-
|
|
10931
|
+
var DEFAULT_OPEN_TIMEOUT_MS = 18e4;
|
|
10932
|
+
var DEFAULT_WAIT_TIMEOUT_MS = 6e4;
|
|
10933
|
+
function text(payload) {
|
|
10934
|
+
return { content: [{ type: "text", text: JSON.stringify(payload, null, 2) }] };
|
|
10935
|
+
}
|
|
10936
|
+
function errorText(message) {
|
|
10937
|
+
return { content: [{ type: "text", text: `Error: ${message}` }], isError: true };
|
|
10938
|
+
}
|
|
10939
|
+
function publicPhase(snapshot, sessionActive) {
|
|
10940
|
+
if (!sessionActive && snapshot.phase === "ready") return "idle";
|
|
10941
|
+
return snapshot.phase;
|
|
10942
|
+
}
|
|
10943
|
+
function statusPayload(host) {
|
|
10944
|
+
const snapshot = host.sessionStatus.get();
|
|
10945
|
+
const sessionActive = host.workspace.hasActiveSession();
|
|
10946
|
+
return {
|
|
10947
|
+
phase: publicPhase(snapshot, sessionActive),
|
|
10948
|
+
message: snapshot.message,
|
|
10949
|
+
projectPath: host.workspace.getProjectPath(),
|
|
10950
|
+
sessionActive,
|
|
10951
|
+
watcherAlive: snapshot.watcherAlive,
|
|
10952
|
+
updatedAt: snapshot.updatedAt,
|
|
10953
|
+
generation: snapshot.generation
|
|
10954
|
+
};
|
|
10955
|
+
}
|
|
10956
|
+
function registerProjectTools(server, host) {
|
|
10957
|
+
server.tool(
|
|
10958
|
+
"project_open",
|
|
10959
|
+
"Open a mini-program project: registers the directory if needed, launches it in the simulator (compile + attach), and waits until the compile settles. Returns the settled status; on compile error, pull stderr via compile_logs.",
|
|
10960
|
+
{
|
|
10961
|
+
path: z5.string().describe("Absolute path to the mini-program project directory"),
|
|
10962
|
+
timeoutMs: z5.number().optional().default(DEFAULT_OPEN_TIMEOUT_MS).describe("Max time to wait for the compile to settle")
|
|
10963
|
+
},
|
|
10964
|
+
async ({ path: rawPath, timeoutMs }) => {
|
|
10965
|
+
const dir = path18.resolve(rawPath);
|
|
10966
|
+
const current = host.sessionStatus.get();
|
|
10967
|
+
if (host.workspace.getProjectPath() === dir && host.workspace.hasActiveSession() && current.phase === "ready") {
|
|
10968
|
+
return text({ ...statusPayload(host), note: "project already open" });
|
|
10969
|
+
}
|
|
10970
|
+
const invalid = await host.workspace.validateProjectDir(dir);
|
|
10971
|
+
if (invalid) return errorText(invalid);
|
|
10972
|
+
let project;
|
|
10973
|
+
if (await host.workspace.hasProject(dir)) {
|
|
10974
|
+
const known = (await host.workspace.listProjects()).find((p) => p.path === dir);
|
|
10975
|
+
project = known ?? { name: path18.basename(dir), path: dir };
|
|
10976
|
+
} else {
|
|
10977
|
+
project = await host.workspace.addProject(dir);
|
|
10978
|
+
}
|
|
10979
|
+
const afterGeneration = host.sessionStatus.get().generation;
|
|
10980
|
+
host.requestOpenInUi({ name: project.name, path: project.path });
|
|
10981
|
+
let settled;
|
|
10982
|
+
try {
|
|
10983
|
+
settled = await host.sessionStatus.waitForSettled({ afterGeneration, timeoutMs });
|
|
10984
|
+
} catch (err2) {
|
|
10985
|
+
return errorText(err2 instanceof Error ? err2.message : String(err2));
|
|
10986
|
+
}
|
|
10987
|
+
if (settled.phase === "error") {
|
|
10988
|
+
return errorText(
|
|
10989
|
+
`compile failed: ${settled.message} \u2014 call compile_logs (stream: "stderr") for details`
|
|
10990
|
+
);
|
|
10991
|
+
}
|
|
10992
|
+
return text(statusPayload(host));
|
|
10993
|
+
}
|
|
10994
|
+
);
|
|
10995
|
+
server.tool(
|
|
10996
|
+
"project_close",
|
|
10997
|
+
"Close the currently open project session and return the workbench to the project list.",
|
|
10998
|
+
{},
|
|
10999
|
+
async () => {
|
|
11000
|
+
if (!host.workspace.getProjectPath() && !host.workspace.hasActiveSession()) {
|
|
11001
|
+
return text({ closed: false, note: "no project is open" });
|
|
11002
|
+
}
|
|
11003
|
+
await host.workspace.closeProject();
|
|
11004
|
+
host.requestNavigateBack();
|
|
11005
|
+
return text({ closed: true });
|
|
11006
|
+
}
|
|
11007
|
+
);
|
|
11008
|
+
server.tool(
|
|
11009
|
+
"project_status",
|
|
11010
|
+
"Query the current project compile status (phase: idle | compiling | ready | error). Includes `generation` \u2014 pass it to project_wait_ready to await the NEXT settled state.",
|
|
11011
|
+
{},
|
|
11012
|
+
async () => text(statusPayload(host))
|
|
11013
|
+
);
|
|
11014
|
+
server.tool(
|
|
11015
|
+
"project_wait_ready",
|
|
11016
|
+
'Wait until the compile pipeline settles (phase leaves "compiling"). Watcher rebuilds emit no "compiling" phase, so to await a rebuild after editing files pass the `generation` from a prior project_status.',
|
|
11017
|
+
{
|
|
11018
|
+
afterGeneration: z5.number().optional().describe("Only accept states recorded after this generation (from project_status). Omit to accept the current state when already settled."),
|
|
11019
|
+
timeoutMs: z5.number().optional().default(DEFAULT_WAIT_TIMEOUT_MS).describe("Max time to wait")
|
|
11020
|
+
},
|
|
11021
|
+
async ({ afterGeneration, timeoutMs }) => {
|
|
11022
|
+
try {
|
|
11023
|
+
await host.sessionStatus.waitForSettled({ afterGeneration, timeoutMs });
|
|
11024
|
+
} catch (err2) {
|
|
11025
|
+
return errorText(err2 instanceof Error ? err2.message : String(err2));
|
|
11026
|
+
}
|
|
11027
|
+
return text(statusPayload(host));
|
|
11028
|
+
}
|
|
11029
|
+
);
|
|
11030
|
+
server.tool(
|
|
11031
|
+
"compile_logs",
|
|
11032
|
+
"Pull compile log lines incrementally. Pass the previous call's nextCursor as `cursor` to receive only new lines. The buffer resets on each fresh project open; watcher rebuilds append to the same timeline.",
|
|
11033
|
+
{
|
|
11034
|
+
cursor: z5.number().optional().default(0).describe("Return only lines after this cursor (0 = from the start of the buffer)"),
|
|
11035
|
+
limit: z5.number().optional().default(100).describe("Max lines to return"),
|
|
11036
|
+
stream: z5.enum(["stdout", "stderr"]).optional().describe("Only lines from this stream (stderr carries compile errors)")
|
|
11037
|
+
},
|
|
11038
|
+
async ({ cursor, limit, stream }) => {
|
|
11039
|
+
const read = host.compileLogs.read({ afterSeq: cursor, limit, stream });
|
|
11040
|
+
return text(read);
|
|
11041
|
+
}
|
|
11042
|
+
);
|
|
11043
|
+
}
|
|
11044
|
+
|
|
11045
|
+
// src/main/services/mcp/tools/simulator-tools.ts
|
|
11046
|
+
import { z as z6 } from "zod";
|
|
11047
|
+
function ok(text2) {
|
|
11048
|
+
return { content: [{ type: "text", text: text2 }] };
|
|
10820
11049
|
}
|
|
10821
11050
|
function err(msg) {
|
|
10822
11051
|
return { content: [{ type: "text", text: `Error: ${msg}` }], isError: true };
|
|
@@ -10872,8 +11101,8 @@ async function tapSelector(c, selector, nth) {
|
|
|
10872
11101
|
await clickAt(c, value.x, value.y);
|
|
10873
11102
|
return ok(`Tapped selector ${value.selector}[${value.index}] at (${value.x}, ${value.y}) within rect (${value.rect.left}, ${value.rect.top}, ${value.rect.width} x ${value.rect.height})`);
|
|
10874
11103
|
}
|
|
10875
|
-
async function typeText(c, selector, nth,
|
|
10876
|
-
if (!selector || typeof
|
|
11104
|
+
async function typeText(c, selector, nth, text2) {
|
|
11105
|
+
if (!selector || typeof text2 !== "string") return err("type requires selector and text");
|
|
10877
11106
|
const { root } = await c.DOM.getDocument({ depth: 0 });
|
|
10878
11107
|
const { nodeIds } = await c.DOM.querySelectorAll({ nodeId: root.nodeId, selector });
|
|
10879
11108
|
if (!nodeIds || nodeIds.length === 0) return err(`selector matched no elements: ${selector}`);
|
|
@@ -10881,13 +11110,13 @@ async function typeText(c, selector, nth, text) {
|
|
|
10881
11110
|
if (index < 0 || index >= nodeIds.length) return err(`nth ${index} out of range (matches: ${nodeIds.length})`);
|
|
10882
11111
|
await c.DOM.focus({ nodeId: nodeIds[index] });
|
|
10883
11112
|
try {
|
|
10884
|
-
await c.Input.insertText({ text });
|
|
11113
|
+
await c.Input.insertText({ text: text2 });
|
|
10885
11114
|
} catch {
|
|
10886
|
-
for (const ch of
|
|
11115
|
+
for (const ch of text2) {
|
|
10887
11116
|
await c.Input.dispatchKeyEvent({ type: "char", text: ch });
|
|
10888
11117
|
}
|
|
10889
11118
|
}
|
|
10890
|
-
return ok(`Typed ${
|
|
11119
|
+
return ok(`Typed ${text2.length} char(s) into ${selector}[${index}]`);
|
|
10891
11120
|
}
|
|
10892
11121
|
async function scrollAt(c, x, y, deltaX, deltaY) {
|
|
10893
11122
|
if (typeof x !== "number" || typeof y !== "number" || typeof deltaX !== "number" || typeof deltaY !== "number") {
|
|
@@ -10907,8 +11136,8 @@ async function dispatchKey(c, key) {
|
|
|
10907
11136
|
}
|
|
10908
11137
|
function registerSimulatorTools(server) {
|
|
10909
11138
|
server.tool("simulator_navigate", "Navigate the simulator to a URL, or reload the current page", {
|
|
10910
|
-
url:
|
|
10911
|
-
reload:
|
|
11139
|
+
url: z6.string().optional().describe("URL to navigate to"),
|
|
11140
|
+
reload: z6.boolean().optional().describe("If true, reload current page instead of navigating")
|
|
10912
11141
|
}, async ({ url, reload }) => {
|
|
10913
11142
|
const c = getClient("simulator");
|
|
10914
11143
|
if (reload) {
|
|
@@ -10923,16 +11152,16 @@ function registerSimulatorTools(server) {
|
|
|
10923
11152
|
return { content: [{ type: "text", text: "Error: either url or reload is required" }], isError: true };
|
|
10924
11153
|
});
|
|
10925
11154
|
server.tool("simulator_input", "Dispatch input to the simulator. `tap_coord` requires x and y. `tap_selector` requires selector and optional nth. `type` requires selector and text. `scroll` requires x, y, deltaX, and deltaY. `key` is best-effort for common keys such as Enter, Escape, Tab, Arrow* and Space.", {
|
|
10926
|
-
action:
|
|
10927
|
-
x:
|
|
10928
|
-
y:
|
|
10929
|
-
selector:
|
|
10930
|
-
nth:
|
|
10931
|
-
text:
|
|
10932
|
-
key:
|
|
10933
|
-
deltaX:
|
|
10934
|
-
deltaY:
|
|
10935
|
-
}, async ({ action, x, y, selector, nth, text, key, deltaX, deltaY }) => {
|
|
11155
|
+
action: z6.enum(["tap_coord", "tap_selector", "type", "scroll", "key"]).describe("Input action to dispatch"),
|
|
11156
|
+
x: z6.number().optional().describe("Viewport x coordinate for `tap_coord` or `scroll`"),
|
|
11157
|
+
y: z6.number().optional().describe("Viewport y coordinate for `tap_coord` or `scroll`"),
|
|
11158
|
+
selector: z6.string().optional().describe("CSS selector for `tap_selector` or `type`"),
|
|
11159
|
+
nth: z6.number().int().optional().describe("Zero-based index when selector matches multiple elements; defaults to 0"),
|
|
11160
|
+
text: z6.string().optional().describe("Text to insert for `type`"),
|
|
11161
|
+
key: z6.string().optional().describe("Best-effort keyboard key name for `key`; common keys such as Enter, Escape, Tab, Arrow* and Space work best"),
|
|
11162
|
+
deltaX: z6.number().optional().describe("Horizontal wheel delta for `scroll`"),
|
|
11163
|
+
deltaY: z6.number().optional().describe("Vertical wheel delta for `scroll`")
|
|
11164
|
+
}, async ({ action, x, y, selector, nth, text: text2, key, deltaX, deltaY }) => {
|
|
10936
11165
|
const c = getClient("simulator");
|
|
10937
11166
|
switch (action) {
|
|
10938
11167
|
case "tap_coord":
|
|
@@ -10940,7 +11169,7 @@ function registerSimulatorTools(server) {
|
|
|
10940
11169
|
case "tap_selector":
|
|
10941
11170
|
return tapSelector(c, selector, nth);
|
|
10942
11171
|
case "type":
|
|
10943
|
-
return typeText(c, selector, nth,
|
|
11172
|
+
return typeText(c, selector, nth, text2);
|
|
10944
11173
|
case "scroll":
|
|
10945
11174
|
return scrollAt(c, x, y, deltaX, deltaY);
|
|
10946
11175
|
case "key":
|
|
@@ -10963,7 +11192,7 @@ function registerWorkbenchTools(server) {
|
|
|
10963
11192
|
// src/main/services/mcp/server.ts
|
|
10964
11193
|
var require2 = createRequire(import.meta.url);
|
|
10965
11194
|
var pkg = require2("../../../../package.json");
|
|
10966
|
-
function buildServer() {
|
|
11195
|
+
function buildServer(projectHost) {
|
|
10967
11196
|
const server = new McpServer({
|
|
10968
11197
|
name: "@dimina-kit/devtools",
|
|
10969
11198
|
version: pkg.version
|
|
@@ -10973,9 +11202,10 @@ function buildServer() {
|
|
|
10973
11202
|
registerCommonTargetTools(server, "workbench");
|
|
10974
11203
|
registerWorkbenchTools(server);
|
|
10975
11204
|
registerContextTools(server);
|
|
11205
|
+
registerProjectTools(server, projectHost);
|
|
10976
11206
|
return server;
|
|
10977
11207
|
}
|
|
10978
|
-
function startMcpServer(resolvedCdpPort, mcpPort) {
|
|
11208
|
+
function startMcpServer(resolvedCdpPort, mcpPort, projectHost) {
|
|
10979
11209
|
setCdpPort(resolvedCdpPort);
|
|
10980
11210
|
connectTarget("simulator").catch(() => {
|
|
10981
11211
|
});
|
|
@@ -10989,7 +11219,7 @@ function startMcpServer(resolvedCdpPort, mcpPort) {
|
|
|
10989
11219
|
transports.set(transport.sessionId, transport);
|
|
10990
11220
|
res.on("close", () => transports.delete(transport.sessionId));
|
|
10991
11221
|
try {
|
|
10992
|
-
await buildServer().connect(transport);
|
|
11222
|
+
await buildServer(projectHost).connect(transport);
|
|
10993
11223
|
} catch (err2) {
|
|
10994
11224
|
transports.delete(transport.sessionId);
|
|
10995
11225
|
if (!res.headersSent) res.writeHead(500).end("MCP connect failed");
|
|
@@ -11206,7 +11436,7 @@ function setupSimulatorCurrentPage(host, options) {
|
|
|
11206
11436
|
|
|
11207
11437
|
// src/main/services/render-inspect/index.ts
|
|
11208
11438
|
import { readFileSync } from "node:fs";
|
|
11209
|
-
import
|
|
11439
|
+
import path19 from "node:path";
|
|
11210
11440
|
var DEFAULT_SOURCE_PATH = "dist/render-host/render-inspect.js";
|
|
11211
11441
|
var HIGHLIGHT_CONFIG = {
|
|
11212
11442
|
showInfo: true,
|
|
@@ -11232,7 +11462,7 @@ function withTimeout(p, ms) {
|
|
|
11232
11462
|
});
|
|
11233
11463
|
}
|
|
11234
11464
|
function createRenderInspector(options = {}) {
|
|
11235
|
-
const loadSource = options.loadSource ?? (() => readFileSync(
|
|
11465
|
+
const loadSource = options.loadSource ?? (() => readFileSync(path19.join(devtoolsPackageRoot, DEFAULT_SOURCE_PATH), "utf8"));
|
|
11236
11466
|
let cachedSource = null;
|
|
11237
11467
|
const injected = /* @__PURE__ */ new Set();
|
|
11238
11468
|
const broker = options.broker ?? createCdpSessionBroker({ connections: options.connections });
|
|
@@ -11344,13 +11574,13 @@ function createRenderInspector(options = {}) {
|
|
|
11344
11574
|
import { toDisposable as toDisposable6 } from "@dimina-kit/electron-deck/main";
|
|
11345
11575
|
|
|
11346
11576
|
// src/main/services/simulator-temp-files/store.ts
|
|
11347
|
-
function registerTempFile(store,
|
|
11577
|
+
function registerTempFile(store, path27, mime, bytes) {
|
|
11348
11578
|
const buf = Buffer.isBuffer(bytes) ? bytes : Buffer.from(new Uint8Array(bytes));
|
|
11349
|
-
store.delete(
|
|
11350
|
-
store.set(
|
|
11579
|
+
store.delete(path27);
|
|
11580
|
+
store.set(path27, { bytes: buf, mime });
|
|
11351
11581
|
}
|
|
11352
|
-
function revokeTempFile(store,
|
|
11353
|
-
store.delete(
|
|
11582
|
+
function revokeTempFile(store, path27) {
|
|
11583
|
+
store.delete(path27);
|
|
11354
11584
|
}
|
|
11355
11585
|
function revokeAllTempFiles(store) {
|
|
11356
11586
|
store.clear();
|
|
@@ -11358,14 +11588,14 @@ function revokeAllTempFiles(store) {
|
|
|
11358
11588
|
|
|
11359
11589
|
// src/shared/vpath.ts
|
|
11360
11590
|
import os from "node:os";
|
|
11361
|
-
import
|
|
11591
|
+
import path20 from "node:path";
|
|
11362
11592
|
var DIFILE_PREFIX = "difile://";
|
|
11363
11593
|
function sandboxBase() {
|
|
11364
11594
|
const env = typeof process !== "undefined" && process.env && process.env.DIMINA_HOME || "";
|
|
11365
11595
|
if (env) {
|
|
11366
|
-
return
|
|
11596
|
+
return path20.join(env, "files");
|
|
11367
11597
|
}
|
|
11368
|
-
return
|
|
11598
|
+
return path20.join(os.homedir(), ".dimina", "files");
|
|
11369
11599
|
}
|
|
11370
11600
|
function resolveVPath(url) {
|
|
11371
11601
|
if (typeof url !== "string") return null;
|
|
@@ -11399,15 +11629,15 @@ function resolveVPath(url) {
|
|
|
11399
11629
|
return { kind, writable };
|
|
11400
11630
|
}
|
|
11401
11631
|
const base = sandboxBase();
|
|
11402
|
-
const joined =
|
|
11403
|
-
const normalized =
|
|
11404
|
-
if (normalized !== base && !normalized.startsWith(base +
|
|
11632
|
+
const joined = path20.join(base, decoded);
|
|
11633
|
+
const normalized = path20.normalize(joined);
|
|
11634
|
+
if (normalized !== base && !normalized.startsWith(base + path20.sep)) return null;
|
|
11405
11635
|
return { kind, writable, realPath: normalized };
|
|
11406
11636
|
}
|
|
11407
11637
|
|
|
11408
11638
|
// src/main/services/simulator-temp-files/disk.ts
|
|
11409
11639
|
import fs9 from "node:fs/promises";
|
|
11410
|
-
import
|
|
11640
|
+
import path21 from "node:path";
|
|
11411
11641
|
var EXT_MIME = {
|
|
11412
11642
|
".txt": "text/plain",
|
|
11413
11643
|
".log": "text/plain",
|
|
@@ -11485,7 +11715,7 @@ function sniffMime(head) {
|
|
|
11485
11715
|
return hit ? hit.mime : null;
|
|
11486
11716
|
}
|
|
11487
11717
|
function extMime(realPath) {
|
|
11488
|
-
const ext =
|
|
11718
|
+
const ext = path21.extname(realPath).toLowerCase();
|
|
11489
11719
|
if (!ext) return null;
|
|
11490
11720
|
return EXT_MIME[ext] ?? null;
|
|
11491
11721
|
}
|
|
@@ -11559,7 +11789,7 @@ async function readDiskFile(realPath, opts) {
|
|
|
11559
11789
|
}
|
|
11560
11790
|
async function writeDiskFile(realPath, bytes) {
|
|
11561
11791
|
const buf = Buffer.isBuffer(bytes) ? bytes : Buffer.from(new Uint8Array(bytes));
|
|
11562
|
-
await fs9.mkdir(
|
|
11792
|
+
await fs9.mkdir(path21.dirname(realPath), { recursive: true });
|
|
11563
11793
|
await fs9.writeFile(realPath, buf);
|
|
11564
11794
|
}
|
|
11565
11795
|
async function readDiskDir(realPath) {
|
|
@@ -11701,28 +11931,28 @@ async function handleDifileRequest(ctx, req) {
|
|
|
11701
11931
|
|
|
11702
11932
|
// src/main/services/simulator-temp-files/fs-channels.ts
|
|
11703
11933
|
import fs10 from "node:fs/promises";
|
|
11704
|
-
import
|
|
11934
|
+
import path22 from "node:path";
|
|
11705
11935
|
async function enforceSandbox(realPath) {
|
|
11706
11936
|
if (typeof realPath !== "string" || realPath.length === 0) {
|
|
11707
11937
|
throw new Error("sandbox: realPath must be a non-empty string");
|
|
11708
11938
|
}
|
|
11709
11939
|
const base = sandboxBase();
|
|
11710
11940
|
const baseReal = await fs10.realpath(base).catch(() => base);
|
|
11711
|
-
const normalized =
|
|
11712
|
-
if (normalized !== base && !normalized.startsWith(base +
|
|
11941
|
+
const normalized = path22.normalize(realPath);
|
|
11942
|
+
if (normalized !== base && !normalized.startsWith(base + path22.sep)) {
|
|
11713
11943
|
throw new Error("sandbox: realPath escapes the user-data base");
|
|
11714
11944
|
}
|
|
11715
11945
|
let probe = normalized;
|
|
11716
|
-
while (probe !==
|
|
11946
|
+
while (probe !== path22.parse(probe).root) {
|
|
11717
11947
|
try {
|
|
11718
11948
|
const resolved = await fs10.realpath(probe);
|
|
11719
|
-
if (resolved !== baseReal && !resolved.startsWith(baseReal +
|
|
11949
|
+
if (resolved !== baseReal && !resolved.startsWith(baseReal + path22.sep)) {
|
|
11720
11950
|
throw new Error("sandbox: realPath escapes the user-data base via symlink");
|
|
11721
11951
|
}
|
|
11722
11952
|
break;
|
|
11723
11953
|
} catch (err2) {
|
|
11724
11954
|
if (err2.code === "ENOENT") {
|
|
11725
|
-
probe =
|
|
11955
|
+
probe = path22.dirname(probe);
|
|
11726
11956
|
continue;
|
|
11727
11957
|
}
|
|
11728
11958
|
throw err2;
|
|
@@ -11778,10 +12008,10 @@ function setupSimulatorTempFiles(simSession) {
|
|
|
11778
12008
|
const store = /* @__PURE__ */ new Map();
|
|
11779
12009
|
const pendingWaiters = /* @__PURE__ */ new Map();
|
|
11780
12010
|
let disposed = false;
|
|
11781
|
-
function drainWaiters(
|
|
11782
|
-
const list = pendingWaiters.get(
|
|
12011
|
+
function drainWaiters(path27) {
|
|
12012
|
+
const list = pendingWaiters.get(path27);
|
|
11783
12013
|
if (!list) return;
|
|
11784
|
-
pendingWaiters.delete(
|
|
12014
|
+
pendingWaiters.delete(path27);
|
|
11785
12015
|
for (const fn of list) fn();
|
|
11786
12016
|
}
|
|
11787
12017
|
function drainAllWaiters() {
|
|
@@ -11794,15 +12024,15 @@ function setupSimulatorTempFiles(simSession) {
|
|
|
11794
12024
|
const registry = new IpcRegistry(simulatorOnlyPolicy);
|
|
11795
12025
|
registry.on("simulator:temp-file:write", (_event, payload) => {
|
|
11796
12026
|
if (disposed) return;
|
|
11797
|
-
const { path:
|
|
11798
|
-
registerTempFile(store,
|
|
12027
|
+
const { path: path27, mime, bytes } = payload;
|
|
12028
|
+
registerTempFile(store, path27, mime, bytes);
|
|
11799
12029
|
enforceStoreCap(store);
|
|
11800
|
-
drainWaiters(
|
|
12030
|
+
drainWaiters(path27);
|
|
11801
12031
|
});
|
|
11802
12032
|
registry.on("simulator:temp-file:revoke", (_event, payload) => {
|
|
11803
12033
|
if (disposed) return;
|
|
11804
|
-
const { path:
|
|
11805
|
-
revokeTempFile(store,
|
|
12034
|
+
const { path: path27 } = payload;
|
|
12035
|
+
revokeTempFile(store, path27);
|
|
11806
12036
|
});
|
|
11807
12037
|
registry.on("simulator:temp-file:revoke-all", () => {
|
|
11808
12038
|
if (disposed) return;
|
|
@@ -11948,11 +12178,11 @@ function setupSimulatorSessionPolicy() {
|
|
|
11948
12178
|
import http2 from "node:http";
|
|
11949
12179
|
import nodeFs3 from "node:fs";
|
|
11950
12180
|
import fs11 from "node:fs/promises";
|
|
11951
|
-
import
|
|
12181
|
+
import path24 from "node:path";
|
|
11952
12182
|
|
|
11953
12183
|
// src/main/services/fs-watch-sse.ts
|
|
11954
12184
|
import nodeFs2 from "node:fs";
|
|
11955
|
-
import
|
|
12185
|
+
import path23 from "node:path";
|
|
11956
12186
|
|
|
11957
12187
|
// src/main/services/http-json.ts
|
|
11958
12188
|
function jsonRes(res, code, obj) {
|
|
@@ -11964,7 +12194,7 @@ function jsonRes(res, code, obj) {
|
|
|
11964
12194
|
// src/main/services/fs-watch-sse.ts
|
|
11965
12195
|
var WATCH_DEBOUNCE_MS = 80;
|
|
11966
12196
|
function shouldReportWatchPath(rel) {
|
|
11967
|
-
if (rel === "" || rel.startsWith("..") ||
|
|
12197
|
+
if (rel === "" || rel.startsWith("..") || path23.isAbsolute(rel)) return false;
|
|
11968
12198
|
return !rel.split("/").some((segment) => SKIP_DIRS.has(segment));
|
|
11969
12199
|
}
|
|
11970
12200
|
function handleFsWatchRequest(req, res, getProjectRoot) {
|
|
@@ -12005,7 +12235,7 @@ function handleFsWatchRequest(req, res, getProjectRoot) {
|
|
|
12005
12235
|
`);
|
|
12006
12236
|
}
|
|
12007
12237
|
function onChange(_event, filename) {
|
|
12008
|
-
const rel = filename ? filename.toString().split(
|
|
12238
|
+
const rel = filename ? filename.toString().split(path23.sep).join("/") : ".";
|
|
12009
12239
|
if (rel !== "." && !shouldReportWatchPath(rel)) return;
|
|
12010
12240
|
pending.add(rel);
|
|
12011
12241
|
if (!debounceTimer) {
|
|
@@ -12060,8 +12290,8 @@ function setIsolationHeaders(res) {
|
|
|
12060
12290
|
}
|
|
12061
12291
|
function containedStaticPath(root, pathname) {
|
|
12062
12292
|
const rel = pathname.replace(/^\/+/, "") || "index.html";
|
|
12063
|
-
const resolved =
|
|
12064
|
-
if (resolved !== root && !resolved.startsWith(root +
|
|
12293
|
+
const resolved = path24.resolve(root, rel);
|
|
12294
|
+
if (resolved !== root && !resolved.startsWith(root + path24.sep)) return null;
|
|
12065
12295
|
return resolved;
|
|
12066
12296
|
}
|
|
12067
12297
|
function serveStaticFile(res, root, pathname) {
|
|
@@ -12072,7 +12302,7 @@ function serveStaticFile(res, root, pathname) {
|
|
|
12072
12302
|
return;
|
|
12073
12303
|
}
|
|
12074
12304
|
Promise.all([fs11.realpath(root), fs11.realpath(candidate)]).then(([realRoot, realFile]) => {
|
|
12075
|
-
if (realFile !== realRoot && !realFile.startsWith(realRoot +
|
|
12305
|
+
if (realFile !== realRoot && !realFile.startsWith(realRoot + path24.sep)) {
|
|
12076
12306
|
res.writeHead(403);
|
|
12077
12307
|
res.end("Forbidden");
|
|
12078
12308
|
return;
|
|
@@ -12084,7 +12314,7 @@ function serveStaticFile(res, root, pathname) {
|
|
|
12084
12314
|
return;
|
|
12085
12315
|
}
|
|
12086
12316
|
res.writeHead(200, {
|
|
12087
|
-
"Content-Type": MIME[
|
|
12317
|
+
"Content-Type": MIME[path24.extname(realFile)] ?? "application/octet-stream",
|
|
12088
12318
|
"Content-Length": stat.size,
|
|
12089
12319
|
"Cache-Control": "no-store"
|
|
12090
12320
|
});
|
|
@@ -12238,7 +12468,7 @@ async function listFilesRecursive(dir, base = "") {
|
|
|
12238
12468
|
for (const e of entries) {
|
|
12239
12469
|
const rel = base ? `${base}/${e.name}` : e.name;
|
|
12240
12470
|
if (e.isDirectory()) {
|
|
12241
|
-
out.push(...await listFilesRecursive(
|
|
12471
|
+
out.push(...await listFilesRecursive(path24.join(dir, e.name), rel));
|
|
12242
12472
|
} else if (e.isFile()) {
|
|
12243
12473
|
out.push(rel);
|
|
12244
12474
|
}
|
|
@@ -12255,9 +12485,9 @@ async function readContributedExtensions(extensionsDir) {
|
|
|
12255
12485
|
}
|
|
12256
12486
|
for (const e of entries) {
|
|
12257
12487
|
if (!e.isDirectory()) continue;
|
|
12258
|
-
const extDir =
|
|
12488
|
+
const extDir = path24.join(extensionsDir, e.name);
|
|
12259
12489
|
try {
|
|
12260
|
-
const pkgRaw = await fs11.readFile(
|
|
12490
|
+
const pkgRaw = await fs11.readFile(path24.join(extDir, "package.json"), "utf8");
|
|
12261
12491
|
const files = await listFilesRecursive(extDir);
|
|
12262
12492
|
out.push({ dir: e.name, packageJson: JSON.parse(pkgRaw), files });
|
|
12263
12493
|
} catch {
|
|
@@ -12266,8 +12496,8 @@ async function readContributedExtensions(extensionsDir) {
|
|
|
12266
12496
|
return out;
|
|
12267
12497
|
}
|
|
12268
12498
|
async function startWorkbenchCoiServer(options) {
|
|
12269
|
-
const root =
|
|
12270
|
-
const contribRoot = options.extensionsDir ?
|
|
12499
|
+
const root = path24.resolve(options.rootDir);
|
|
12500
|
+
const contribRoot = options.extensionsDir ? path24.resolve(options.extensionsDir) : null;
|
|
12271
12501
|
const server = http2.createServer((req, res) => {
|
|
12272
12502
|
setIsolationHeaders(res);
|
|
12273
12503
|
const url = new URL(req.url ?? "/", "http://127.0.0.1");
|
|
@@ -12426,7 +12656,7 @@ var UpdateManager = class {
|
|
|
12426
12656
|
|
|
12427
12657
|
// src/main/services/update/github-release-checker.ts
|
|
12428
12658
|
import fs12 from "fs";
|
|
12429
|
-
import
|
|
12659
|
+
import path25 from "path";
|
|
12430
12660
|
import https from "https";
|
|
12431
12661
|
import { app as app14 } from "electron";
|
|
12432
12662
|
function createGitHubReleaseChecker(opts) {
|
|
@@ -12452,10 +12682,10 @@ function createGitHubReleaseChecker(opts) {
|
|
|
12452
12682
|
};
|
|
12453
12683
|
},
|
|
12454
12684
|
async downloadUpdate(info, onProgress) {
|
|
12455
|
-
const tmpDir =
|
|
12685
|
+
const tmpDir = path25.join(app14.getPath("temp"), `${opts.repo}-update`);
|
|
12456
12686
|
if (!fs12.existsSync(tmpDir)) fs12.mkdirSync(tmpDir, { recursive: true });
|
|
12457
|
-
const fileName =
|
|
12458
|
-
const filePath =
|
|
12687
|
+
const fileName = path25.basename(new URL(info.downloadUrl).pathname);
|
|
12688
|
+
const filePath = path25.join(tmpDir, fileName);
|
|
12459
12689
|
await downloadFile(info.downloadUrl, filePath, opts.token, onProgress);
|
|
12460
12690
|
return filePath;
|
|
12461
12691
|
}
|
|
@@ -12738,7 +12968,7 @@ async function disposeContext(ctx) {
|
|
|
12738
12968
|
function createConfiguredMainWindow(config, rendererDir2) {
|
|
12739
12969
|
const mainWindow = createMainWindow({
|
|
12740
12970
|
title: config.appName ?? "Dimina DevTools",
|
|
12741
|
-
indexHtml:
|
|
12971
|
+
indexHtml: path26.join(rendererDir2, "entries/main/index.html"),
|
|
12742
12972
|
width: config.window?.width,
|
|
12743
12973
|
height: config.window?.height,
|
|
12744
12974
|
minWidth: config.window?.minWidth,
|
|
@@ -12811,12 +13041,20 @@ async function setupAutomation(instance) {
|
|
|
12811
13041
|
console.log(`[automation] listening on ws://127.0.0.1:${server.port}`);
|
|
12812
13042
|
}
|
|
12813
13043
|
}
|
|
12814
|
-
function setupMcp() {
|
|
13044
|
+
function setupMcp(context) {
|
|
12815
13045
|
const settings = loadWorkbenchSettings();
|
|
12816
13046
|
if (!settings.mcp.enabled) return null;
|
|
12817
13047
|
const cdpPortSwitch = app15.commandLine.getSwitchValue("remote-debugging-port");
|
|
12818
13048
|
const cdpPort2 = cdpPortSwitch ? parseInt(cdpPortSwitch, 10) : settings.cdp.port;
|
|
12819
|
-
return startMcpServer(cdpPort2, settings.mcp.port
|
|
13049
|
+
return startMcpServer(cdpPort2, settings.mcp.port, {
|
|
13050
|
+
workspace: context.workspace,
|
|
13051
|
+
sessionStatus: context.sessionStatus,
|
|
13052
|
+
compileLogs: context.compileLogBuffer,
|
|
13053
|
+
// The renderer owns the open path (mounting ProjectRuntime compiles and
|
|
13054
|
+
// attaches the simulator), so project_open pushes it there.
|
|
13055
|
+
requestOpenInUi: (p) => context.notify.windowOpenProject(p),
|
|
13056
|
+
requestNavigateBack: () => context.notify.windowNavigateBack()
|
|
13057
|
+
});
|
|
12820
13058
|
}
|
|
12821
13059
|
function wireAppWindowEvents(config, instance, isOnProjectScreen) {
|
|
12822
13060
|
const { mainWindow, context } = instance;
|
|
@@ -12952,7 +13190,7 @@ async function createDevtoolsRuntime(config = {}, onInstanceCreated) {
|
|
|
12952
13190
|
context.registry.add(() => instance.updateManager.dispose());
|
|
12953
13191
|
}
|
|
12954
13192
|
await setupAutomation(instance);
|
|
12955
|
-
const mcp = setupMcp();
|
|
13193
|
+
const mcp = setupMcp(context);
|
|
12956
13194
|
if (mcp) context.registry.add(mcp);
|
|
12957
13195
|
const getActiveAppId = () => {
|
|
12958
13196
|
const session5 = context.workspace.getSession();
|
|
@@ -13063,8 +13301,8 @@ async function createDevtoolsRuntime(config = {}, onInstanceCreated) {
|
|
|
13063
13301
|
bridge: context.bridge
|
|
13064
13302
|
}));
|
|
13065
13303
|
}
|
|
13066
|
-
const bundleDir = config.editorViewConfig?.bundleDir ??
|
|
13067
|
-
if (!fs13.existsSync(
|
|
13304
|
+
const bundleDir = config.editorViewConfig?.bundleDir ?? path26.join(devtoolsPackageRoot, "dist/vscode-workbench");
|
|
13305
|
+
if (!fs13.existsSync(path26.join(bundleDir, "index.html"))) {
|
|
13068
13306
|
console.warn(
|
|
13069
13307
|
`[workbench] editor bundle not found at ${bundleDir} \u2014 skipping embedded editor assembly`
|
|
13070
13308
|
);
|