@dimina-kit/devtools 0.4.0-dev.20260728080958 → 0.4.0-dev.20260728110120
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 +320 -83
- package/dist/main/ipc/bridge-router.js +1 -2
- 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/views/native-simulator-view.js +4 -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/runtime/native-host.d.ts +8 -0
- package/dist/preload/runtime/native-host.js +2 -0
- package/dist/preload/windows/host-toolbar-runtime.cjs.map +2 -2
- package/dist/preload/windows/main.cjs.map +1 -1
- package/dist/preload/windows/simulator.cjs +1 -0
- package/dist/preload/windows/simulator.cjs.map +2 -2
- package/dist/preload/windows/simulator.js +1 -0
- package/dist/render-host/preload.cjs +18 -0
- 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/bridge-channels.d.ts +5 -2
- package/dist/shared/ipc-channels.d.ts +2 -0
- package/dist/shared/ipc-channels.js +2 -0
- package/dist/simulator/assets/{device-shell-Cs-rmP1f.js → device-shell-Sbkjw8Nb.js} +2 -2
- package/dist/simulator/assets/{simulator-BG-5CADK.js → simulator-CRyLSz1N.js} +3 -3
- package/dist/simulator/assets/{simulator-mini-app-DzfMfnVM.js → simulator-mini-app-w1Bhwkld.js} +2 -2
- package/dist/simulator/simulator.html +1 -1
- package/package.json +5 -5
- 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");
|
|
@@ -9506,8 +9618,7 @@ function resolveRootPagePath(manifest, requestedPagePath) {
|
|
|
9506
9618
|
function resolvePageWindowConfig(appConfig, pagePath) {
|
|
9507
9619
|
const normalized = normalizePagePath(pagePath);
|
|
9508
9620
|
const appWindow = appConfig.app?.window ?? {};
|
|
9509
|
-
const
|
|
9510
|
-
const pageWindow = pageEntry?.window ?? {};
|
|
9621
|
+
const pageWindow = appConfig.modules?.[normalized] ?? {};
|
|
9511
9622
|
return {
|
|
9512
9623
|
navigationBarTitleText: pageWindow.navigationBarTitleText ?? appWindow.navigationBarTitleText ?? "",
|
|
9513
9624
|
navigationBarBackgroundColor: pageWindow.navigationBarBackgroundColor ?? appWindow.navigationBarBackgroundColor ?? "#ffffff",
|
|
@@ -10813,10 +10924,127 @@ function registerContextTools(server) {
|
|
|
10813
10924
|
);
|
|
10814
10925
|
}
|
|
10815
10926
|
|
|
10816
|
-
// src/main/services/mcp/tools/
|
|
10927
|
+
// src/main/services/mcp/tools/project-tools.ts
|
|
10928
|
+
import path18 from "node:path";
|
|
10817
10929
|
import { z as z5 } from "zod";
|
|
10818
|
-
|
|
10819
|
-
|
|
10930
|
+
var DEFAULT_OPEN_TIMEOUT_MS = 18e4;
|
|
10931
|
+
var DEFAULT_WAIT_TIMEOUT_MS = 6e4;
|
|
10932
|
+
function text(payload) {
|
|
10933
|
+
return { content: [{ type: "text", text: JSON.stringify(payload, null, 2) }] };
|
|
10934
|
+
}
|
|
10935
|
+
function errorText(message) {
|
|
10936
|
+
return { content: [{ type: "text", text: `Error: ${message}` }], isError: true };
|
|
10937
|
+
}
|
|
10938
|
+
function publicPhase(snapshot, sessionActive) {
|
|
10939
|
+
if (!sessionActive && snapshot.phase === "ready") return "idle";
|
|
10940
|
+
return snapshot.phase;
|
|
10941
|
+
}
|
|
10942
|
+
function statusPayload(host) {
|
|
10943
|
+
const snapshot = host.sessionStatus.get();
|
|
10944
|
+
const sessionActive = host.workspace.hasActiveSession();
|
|
10945
|
+
return {
|
|
10946
|
+
phase: publicPhase(snapshot, sessionActive),
|
|
10947
|
+
message: snapshot.message,
|
|
10948
|
+
projectPath: host.workspace.getProjectPath(),
|
|
10949
|
+
sessionActive,
|
|
10950
|
+
watcherAlive: snapshot.watcherAlive,
|
|
10951
|
+
updatedAt: snapshot.updatedAt,
|
|
10952
|
+
generation: snapshot.generation
|
|
10953
|
+
};
|
|
10954
|
+
}
|
|
10955
|
+
function registerProjectTools(server, host) {
|
|
10956
|
+
server.tool(
|
|
10957
|
+
"project_open",
|
|
10958
|
+
"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.",
|
|
10959
|
+
{
|
|
10960
|
+
path: z5.string().describe("Absolute path to the mini-program project directory"),
|
|
10961
|
+
timeoutMs: z5.number().optional().default(DEFAULT_OPEN_TIMEOUT_MS).describe("Max time to wait for the compile to settle")
|
|
10962
|
+
},
|
|
10963
|
+
async ({ path: rawPath, timeoutMs }) => {
|
|
10964
|
+
const dir = path18.resolve(rawPath);
|
|
10965
|
+
const current = host.sessionStatus.get();
|
|
10966
|
+
if (host.workspace.getProjectPath() === dir && host.workspace.hasActiveSession() && current.phase === "ready") {
|
|
10967
|
+
return text({ ...statusPayload(host), note: "project already open" });
|
|
10968
|
+
}
|
|
10969
|
+
const invalid = await host.workspace.validateProjectDir(dir);
|
|
10970
|
+
if (invalid) return errorText(invalid);
|
|
10971
|
+
let project;
|
|
10972
|
+
if (await host.workspace.hasProject(dir)) {
|
|
10973
|
+
const known = (await host.workspace.listProjects()).find((p) => p.path === dir);
|
|
10974
|
+
project = known ?? { name: path18.basename(dir), path: dir };
|
|
10975
|
+
} else {
|
|
10976
|
+
project = await host.workspace.addProject(dir);
|
|
10977
|
+
}
|
|
10978
|
+
const afterGeneration = host.sessionStatus.get().generation;
|
|
10979
|
+
host.requestOpenInUi({ name: project.name, path: project.path });
|
|
10980
|
+
let settled;
|
|
10981
|
+
try {
|
|
10982
|
+
settled = await host.sessionStatus.waitForSettled({ afterGeneration, timeoutMs });
|
|
10983
|
+
} catch (err2) {
|
|
10984
|
+
return errorText(err2 instanceof Error ? err2.message : String(err2));
|
|
10985
|
+
}
|
|
10986
|
+
if (settled.phase === "error") {
|
|
10987
|
+
return errorText(
|
|
10988
|
+
`compile failed: ${settled.message} \u2014 call compile_logs (stream: "stderr") for details`
|
|
10989
|
+
);
|
|
10990
|
+
}
|
|
10991
|
+
return text(statusPayload(host));
|
|
10992
|
+
}
|
|
10993
|
+
);
|
|
10994
|
+
server.tool(
|
|
10995
|
+
"project_close",
|
|
10996
|
+
"Close the currently open project session and return the workbench to the project list.",
|
|
10997
|
+
{},
|
|
10998
|
+
async () => {
|
|
10999
|
+
if (!host.workspace.getProjectPath() && !host.workspace.hasActiveSession()) {
|
|
11000
|
+
return text({ closed: false, note: "no project is open" });
|
|
11001
|
+
}
|
|
11002
|
+
await host.workspace.closeProject();
|
|
11003
|
+
host.requestNavigateBack();
|
|
11004
|
+
return text({ closed: true });
|
|
11005
|
+
}
|
|
11006
|
+
);
|
|
11007
|
+
server.tool(
|
|
11008
|
+
"project_status",
|
|
11009
|
+
"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.",
|
|
11010
|
+
{},
|
|
11011
|
+
async () => text(statusPayload(host))
|
|
11012
|
+
);
|
|
11013
|
+
server.tool(
|
|
11014
|
+
"project_wait_ready",
|
|
11015
|
+
'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.',
|
|
11016
|
+
{
|
|
11017
|
+
afterGeneration: z5.number().optional().describe("Only accept states recorded after this generation (from project_status). Omit to accept the current state when already settled."),
|
|
11018
|
+
timeoutMs: z5.number().optional().default(DEFAULT_WAIT_TIMEOUT_MS).describe("Max time to wait")
|
|
11019
|
+
},
|
|
11020
|
+
async ({ afterGeneration, timeoutMs }) => {
|
|
11021
|
+
try {
|
|
11022
|
+
await host.sessionStatus.waitForSettled({ afterGeneration, timeoutMs });
|
|
11023
|
+
} catch (err2) {
|
|
11024
|
+
return errorText(err2 instanceof Error ? err2.message : String(err2));
|
|
11025
|
+
}
|
|
11026
|
+
return text(statusPayload(host));
|
|
11027
|
+
}
|
|
11028
|
+
);
|
|
11029
|
+
server.tool(
|
|
11030
|
+
"compile_logs",
|
|
11031
|
+
"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.",
|
|
11032
|
+
{
|
|
11033
|
+
cursor: z5.number().optional().default(0).describe("Return only lines after this cursor (0 = from the start of the buffer)"),
|
|
11034
|
+
limit: z5.number().optional().default(100).describe("Max lines to return"),
|
|
11035
|
+
stream: z5.enum(["stdout", "stderr"]).optional().describe("Only lines from this stream (stderr carries compile errors)")
|
|
11036
|
+
},
|
|
11037
|
+
async ({ cursor, limit, stream }) => {
|
|
11038
|
+
const read = host.compileLogs.read({ afterSeq: cursor, limit, stream });
|
|
11039
|
+
return text(read);
|
|
11040
|
+
}
|
|
11041
|
+
);
|
|
11042
|
+
}
|
|
11043
|
+
|
|
11044
|
+
// src/main/services/mcp/tools/simulator-tools.ts
|
|
11045
|
+
import { z as z6 } from "zod";
|
|
11046
|
+
function ok(text2) {
|
|
11047
|
+
return { content: [{ type: "text", text: text2 }] };
|
|
10820
11048
|
}
|
|
10821
11049
|
function err(msg) {
|
|
10822
11050
|
return { content: [{ type: "text", text: `Error: ${msg}` }], isError: true };
|
|
@@ -10872,8 +11100,8 @@ async function tapSelector(c, selector, nth) {
|
|
|
10872
11100
|
await clickAt(c, value.x, value.y);
|
|
10873
11101
|
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
11102
|
}
|
|
10875
|
-
async function typeText(c, selector, nth,
|
|
10876
|
-
if (!selector || typeof
|
|
11103
|
+
async function typeText(c, selector, nth, text2) {
|
|
11104
|
+
if (!selector || typeof text2 !== "string") return err("type requires selector and text");
|
|
10877
11105
|
const { root } = await c.DOM.getDocument({ depth: 0 });
|
|
10878
11106
|
const { nodeIds } = await c.DOM.querySelectorAll({ nodeId: root.nodeId, selector });
|
|
10879
11107
|
if (!nodeIds || nodeIds.length === 0) return err(`selector matched no elements: ${selector}`);
|
|
@@ -10881,13 +11109,13 @@ async function typeText(c, selector, nth, text) {
|
|
|
10881
11109
|
if (index < 0 || index >= nodeIds.length) return err(`nth ${index} out of range (matches: ${nodeIds.length})`);
|
|
10882
11110
|
await c.DOM.focus({ nodeId: nodeIds[index] });
|
|
10883
11111
|
try {
|
|
10884
|
-
await c.Input.insertText({ text });
|
|
11112
|
+
await c.Input.insertText({ text: text2 });
|
|
10885
11113
|
} catch {
|
|
10886
|
-
for (const ch of
|
|
11114
|
+
for (const ch of text2) {
|
|
10887
11115
|
await c.Input.dispatchKeyEvent({ type: "char", text: ch });
|
|
10888
11116
|
}
|
|
10889
11117
|
}
|
|
10890
|
-
return ok(`Typed ${
|
|
11118
|
+
return ok(`Typed ${text2.length} char(s) into ${selector}[${index}]`);
|
|
10891
11119
|
}
|
|
10892
11120
|
async function scrollAt(c, x, y, deltaX, deltaY) {
|
|
10893
11121
|
if (typeof x !== "number" || typeof y !== "number" || typeof deltaX !== "number" || typeof deltaY !== "number") {
|
|
@@ -10907,8 +11135,8 @@ async function dispatchKey(c, key) {
|
|
|
10907
11135
|
}
|
|
10908
11136
|
function registerSimulatorTools(server) {
|
|
10909
11137
|
server.tool("simulator_navigate", "Navigate the simulator to a URL, or reload the current page", {
|
|
10910
|
-
url:
|
|
10911
|
-
reload:
|
|
11138
|
+
url: z6.string().optional().describe("URL to navigate to"),
|
|
11139
|
+
reload: z6.boolean().optional().describe("If true, reload current page instead of navigating")
|
|
10912
11140
|
}, async ({ url, reload }) => {
|
|
10913
11141
|
const c = getClient("simulator");
|
|
10914
11142
|
if (reload) {
|
|
@@ -10923,16 +11151,16 @@ function registerSimulatorTools(server) {
|
|
|
10923
11151
|
return { content: [{ type: "text", text: "Error: either url or reload is required" }], isError: true };
|
|
10924
11152
|
});
|
|
10925
11153
|
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 }) => {
|
|
11154
|
+
action: z6.enum(["tap_coord", "tap_selector", "type", "scroll", "key"]).describe("Input action to dispatch"),
|
|
11155
|
+
x: z6.number().optional().describe("Viewport x coordinate for `tap_coord` or `scroll`"),
|
|
11156
|
+
y: z6.number().optional().describe("Viewport y coordinate for `tap_coord` or `scroll`"),
|
|
11157
|
+
selector: z6.string().optional().describe("CSS selector for `tap_selector` or `type`"),
|
|
11158
|
+
nth: z6.number().int().optional().describe("Zero-based index when selector matches multiple elements; defaults to 0"),
|
|
11159
|
+
text: z6.string().optional().describe("Text to insert for `type`"),
|
|
11160
|
+
key: z6.string().optional().describe("Best-effort keyboard key name for `key`; common keys such as Enter, Escape, Tab, Arrow* and Space work best"),
|
|
11161
|
+
deltaX: z6.number().optional().describe("Horizontal wheel delta for `scroll`"),
|
|
11162
|
+
deltaY: z6.number().optional().describe("Vertical wheel delta for `scroll`")
|
|
11163
|
+
}, async ({ action, x, y, selector, nth, text: text2, key, deltaX, deltaY }) => {
|
|
10936
11164
|
const c = getClient("simulator");
|
|
10937
11165
|
switch (action) {
|
|
10938
11166
|
case "tap_coord":
|
|
@@ -10940,7 +11168,7 @@ function registerSimulatorTools(server) {
|
|
|
10940
11168
|
case "tap_selector":
|
|
10941
11169
|
return tapSelector(c, selector, nth);
|
|
10942
11170
|
case "type":
|
|
10943
|
-
return typeText(c, selector, nth,
|
|
11171
|
+
return typeText(c, selector, nth, text2);
|
|
10944
11172
|
case "scroll":
|
|
10945
11173
|
return scrollAt(c, x, y, deltaX, deltaY);
|
|
10946
11174
|
case "key":
|
|
@@ -10963,7 +11191,7 @@ function registerWorkbenchTools(server) {
|
|
|
10963
11191
|
// src/main/services/mcp/server.ts
|
|
10964
11192
|
var require2 = createRequire(import.meta.url);
|
|
10965
11193
|
var pkg = require2("../../../../package.json");
|
|
10966
|
-
function buildServer() {
|
|
11194
|
+
function buildServer(projectHost) {
|
|
10967
11195
|
const server = new McpServer({
|
|
10968
11196
|
name: "@dimina-kit/devtools",
|
|
10969
11197
|
version: pkg.version
|
|
@@ -10973,9 +11201,10 @@ function buildServer() {
|
|
|
10973
11201
|
registerCommonTargetTools(server, "workbench");
|
|
10974
11202
|
registerWorkbenchTools(server);
|
|
10975
11203
|
registerContextTools(server);
|
|
11204
|
+
registerProjectTools(server, projectHost);
|
|
10976
11205
|
return server;
|
|
10977
11206
|
}
|
|
10978
|
-
function startMcpServer(resolvedCdpPort, mcpPort) {
|
|
11207
|
+
function startMcpServer(resolvedCdpPort, mcpPort, projectHost) {
|
|
10979
11208
|
setCdpPort(resolvedCdpPort);
|
|
10980
11209
|
connectTarget("simulator").catch(() => {
|
|
10981
11210
|
});
|
|
@@ -10989,7 +11218,7 @@ function startMcpServer(resolvedCdpPort, mcpPort) {
|
|
|
10989
11218
|
transports.set(transport.sessionId, transport);
|
|
10990
11219
|
res.on("close", () => transports.delete(transport.sessionId));
|
|
10991
11220
|
try {
|
|
10992
|
-
await buildServer().connect(transport);
|
|
11221
|
+
await buildServer(projectHost).connect(transport);
|
|
10993
11222
|
} catch (err2) {
|
|
10994
11223
|
transports.delete(transport.sessionId);
|
|
10995
11224
|
if (!res.headersSent) res.writeHead(500).end("MCP connect failed");
|
|
@@ -11206,7 +11435,7 @@ function setupSimulatorCurrentPage(host, options) {
|
|
|
11206
11435
|
|
|
11207
11436
|
// src/main/services/render-inspect/index.ts
|
|
11208
11437
|
import { readFileSync } from "node:fs";
|
|
11209
|
-
import
|
|
11438
|
+
import path19 from "node:path";
|
|
11210
11439
|
var DEFAULT_SOURCE_PATH = "dist/render-host/render-inspect.js";
|
|
11211
11440
|
var HIGHLIGHT_CONFIG = {
|
|
11212
11441
|
showInfo: true,
|
|
@@ -11232,7 +11461,7 @@ function withTimeout(p, ms) {
|
|
|
11232
11461
|
});
|
|
11233
11462
|
}
|
|
11234
11463
|
function createRenderInspector(options = {}) {
|
|
11235
|
-
const loadSource = options.loadSource ?? (() => readFileSync(
|
|
11464
|
+
const loadSource = options.loadSource ?? (() => readFileSync(path19.join(devtoolsPackageRoot, DEFAULT_SOURCE_PATH), "utf8"));
|
|
11236
11465
|
let cachedSource = null;
|
|
11237
11466
|
const injected = /* @__PURE__ */ new Set();
|
|
11238
11467
|
const broker = options.broker ?? createCdpSessionBroker({ connections: options.connections });
|
|
@@ -11344,13 +11573,13 @@ function createRenderInspector(options = {}) {
|
|
|
11344
11573
|
import { toDisposable as toDisposable6 } from "@dimina-kit/electron-deck/main";
|
|
11345
11574
|
|
|
11346
11575
|
// src/main/services/simulator-temp-files/store.ts
|
|
11347
|
-
function registerTempFile(store,
|
|
11576
|
+
function registerTempFile(store, path27, mime, bytes) {
|
|
11348
11577
|
const buf = Buffer.isBuffer(bytes) ? bytes : Buffer.from(new Uint8Array(bytes));
|
|
11349
|
-
store.delete(
|
|
11350
|
-
store.set(
|
|
11578
|
+
store.delete(path27);
|
|
11579
|
+
store.set(path27, { bytes: buf, mime });
|
|
11351
11580
|
}
|
|
11352
|
-
function revokeTempFile(store,
|
|
11353
|
-
store.delete(
|
|
11581
|
+
function revokeTempFile(store, path27) {
|
|
11582
|
+
store.delete(path27);
|
|
11354
11583
|
}
|
|
11355
11584
|
function revokeAllTempFiles(store) {
|
|
11356
11585
|
store.clear();
|
|
@@ -11358,14 +11587,14 @@ function revokeAllTempFiles(store) {
|
|
|
11358
11587
|
|
|
11359
11588
|
// src/shared/vpath.ts
|
|
11360
11589
|
import os from "node:os";
|
|
11361
|
-
import
|
|
11590
|
+
import path20 from "node:path";
|
|
11362
11591
|
var DIFILE_PREFIX = "difile://";
|
|
11363
11592
|
function sandboxBase() {
|
|
11364
11593
|
const env = typeof process !== "undefined" && process.env && process.env.DIMINA_HOME || "";
|
|
11365
11594
|
if (env) {
|
|
11366
|
-
return
|
|
11595
|
+
return path20.join(env, "files");
|
|
11367
11596
|
}
|
|
11368
|
-
return
|
|
11597
|
+
return path20.join(os.homedir(), ".dimina", "files");
|
|
11369
11598
|
}
|
|
11370
11599
|
function resolveVPath(url) {
|
|
11371
11600
|
if (typeof url !== "string") return null;
|
|
@@ -11399,15 +11628,15 @@ function resolveVPath(url) {
|
|
|
11399
11628
|
return { kind, writable };
|
|
11400
11629
|
}
|
|
11401
11630
|
const base = sandboxBase();
|
|
11402
|
-
const joined =
|
|
11403
|
-
const normalized =
|
|
11404
|
-
if (normalized !== base && !normalized.startsWith(base +
|
|
11631
|
+
const joined = path20.join(base, decoded);
|
|
11632
|
+
const normalized = path20.normalize(joined);
|
|
11633
|
+
if (normalized !== base && !normalized.startsWith(base + path20.sep)) return null;
|
|
11405
11634
|
return { kind, writable, realPath: normalized };
|
|
11406
11635
|
}
|
|
11407
11636
|
|
|
11408
11637
|
// src/main/services/simulator-temp-files/disk.ts
|
|
11409
11638
|
import fs9 from "node:fs/promises";
|
|
11410
|
-
import
|
|
11639
|
+
import path21 from "node:path";
|
|
11411
11640
|
var EXT_MIME = {
|
|
11412
11641
|
".txt": "text/plain",
|
|
11413
11642
|
".log": "text/plain",
|
|
@@ -11485,7 +11714,7 @@ function sniffMime(head) {
|
|
|
11485
11714
|
return hit ? hit.mime : null;
|
|
11486
11715
|
}
|
|
11487
11716
|
function extMime(realPath) {
|
|
11488
|
-
const ext =
|
|
11717
|
+
const ext = path21.extname(realPath).toLowerCase();
|
|
11489
11718
|
if (!ext) return null;
|
|
11490
11719
|
return EXT_MIME[ext] ?? null;
|
|
11491
11720
|
}
|
|
@@ -11559,7 +11788,7 @@ async function readDiskFile(realPath, opts) {
|
|
|
11559
11788
|
}
|
|
11560
11789
|
async function writeDiskFile(realPath, bytes) {
|
|
11561
11790
|
const buf = Buffer.isBuffer(bytes) ? bytes : Buffer.from(new Uint8Array(bytes));
|
|
11562
|
-
await fs9.mkdir(
|
|
11791
|
+
await fs9.mkdir(path21.dirname(realPath), { recursive: true });
|
|
11563
11792
|
await fs9.writeFile(realPath, buf);
|
|
11564
11793
|
}
|
|
11565
11794
|
async function readDiskDir(realPath) {
|
|
@@ -11701,28 +11930,28 @@ async function handleDifileRequest(ctx, req) {
|
|
|
11701
11930
|
|
|
11702
11931
|
// src/main/services/simulator-temp-files/fs-channels.ts
|
|
11703
11932
|
import fs10 from "node:fs/promises";
|
|
11704
|
-
import
|
|
11933
|
+
import path22 from "node:path";
|
|
11705
11934
|
async function enforceSandbox(realPath) {
|
|
11706
11935
|
if (typeof realPath !== "string" || realPath.length === 0) {
|
|
11707
11936
|
throw new Error("sandbox: realPath must be a non-empty string");
|
|
11708
11937
|
}
|
|
11709
11938
|
const base = sandboxBase();
|
|
11710
11939
|
const baseReal = await fs10.realpath(base).catch(() => base);
|
|
11711
|
-
const normalized =
|
|
11712
|
-
if (normalized !== base && !normalized.startsWith(base +
|
|
11940
|
+
const normalized = path22.normalize(realPath);
|
|
11941
|
+
if (normalized !== base && !normalized.startsWith(base + path22.sep)) {
|
|
11713
11942
|
throw new Error("sandbox: realPath escapes the user-data base");
|
|
11714
11943
|
}
|
|
11715
11944
|
let probe = normalized;
|
|
11716
|
-
while (probe !==
|
|
11945
|
+
while (probe !== path22.parse(probe).root) {
|
|
11717
11946
|
try {
|
|
11718
11947
|
const resolved = await fs10.realpath(probe);
|
|
11719
|
-
if (resolved !== baseReal && !resolved.startsWith(baseReal +
|
|
11948
|
+
if (resolved !== baseReal && !resolved.startsWith(baseReal + path22.sep)) {
|
|
11720
11949
|
throw new Error("sandbox: realPath escapes the user-data base via symlink");
|
|
11721
11950
|
}
|
|
11722
11951
|
break;
|
|
11723
11952
|
} catch (err2) {
|
|
11724
11953
|
if (err2.code === "ENOENT") {
|
|
11725
|
-
probe =
|
|
11954
|
+
probe = path22.dirname(probe);
|
|
11726
11955
|
continue;
|
|
11727
11956
|
}
|
|
11728
11957
|
throw err2;
|
|
@@ -11778,10 +12007,10 @@ function setupSimulatorTempFiles(simSession) {
|
|
|
11778
12007
|
const store = /* @__PURE__ */ new Map();
|
|
11779
12008
|
const pendingWaiters = /* @__PURE__ */ new Map();
|
|
11780
12009
|
let disposed = false;
|
|
11781
|
-
function drainWaiters(
|
|
11782
|
-
const list = pendingWaiters.get(
|
|
12010
|
+
function drainWaiters(path27) {
|
|
12011
|
+
const list = pendingWaiters.get(path27);
|
|
11783
12012
|
if (!list) return;
|
|
11784
|
-
pendingWaiters.delete(
|
|
12013
|
+
pendingWaiters.delete(path27);
|
|
11785
12014
|
for (const fn of list) fn();
|
|
11786
12015
|
}
|
|
11787
12016
|
function drainAllWaiters() {
|
|
@@ -11794,15 +12023,15 @@ function setupSimulatorTempFiles(simSession) {
|
|
|
11794
12023
|
const registry = new IpcRegistry(simulatorOnlyPolicy);
|
|
11795
12024
|
registry.on("simulator:temp-file:write", (_event, payload) => {
|
|
11796
12025
|
if (disposed) return;
|
|
11797
|
-
const { path:
|
|
11798
|
-
registerTempFile(store,
|
|
12026
|
+
const { path: path27, mime, bytes } = payload;
|
|
12027
|
+
registerTempFile(store, path27, mime, bytes);
|
|
11799
12028
|
enforceStoreCap(store);
|
|
11800
|
-
drainWaiters(
|
|
12029
|
+
drainWaiters(path27);
|
|
11801
12030
|
});
|
|
11802
12031
|
registry.on("simulator:temp-file:revoke", (_event, payload) => {
|
|
11803
12032
|
if (disposed) return;
|
|
11804
|
-
const { path:
|
|
11805
|
-
revokeTempFile(store,
|
|
12033
|
+
const { path: path27 } = payload;
|
|
12034
|
+
revokeTempFile(store, path27);
|
|
11806
12035
|
});
|
|
11807
12036
|
registry.on("simulator:temp-file:revoke-all", () => {
|
|
11808
12037
|
if (disposed) return;
|
|
@@ -11948,11 +12177,11 @@ function setupSimulatorSessionPolicy() {
|
|
|
11948
12177
|
import http2 from "node:http";
|
|
11949
12178
|
import nodeFs3 from "node:fs";
|
|
11950
12179
|
import fs11 from "node:fs/promises";
|
|
11951
|
-
import
|
|
12180
|
+
import path24 from "node:path";
|
|
11952
12181
|
|
|
11953
12182
|
// src/main/services/fs-watch-sse.ts
|
|
11954
12183
|
import nodeFs2 from "node:fs";
|
|
11955
|
-
import
|
|
12184
|
+
import path23 from "node:path";
|
|
11956
12185
|
|
|
11957
12186
|
// src/main/services/http-json.ts
|
|
11958
12187
|
function jsonRes(res, code, obj) {
|
|
@@ -11964,7 +12193,7 @@ function jsonRes(res, code, obj) {
|
|
|
11964
12193
|
// src/main/services/fs-watch-sse.ts
|
|
11965
12194
|
var WATCH_DEBOUNCE_MS = 80;
|
|
11966
12195
|
function shouldReportWatchPath(rel) {
|
|
11967
|
-
if (rel === "" || rel.startsWith("..") ||
|
|
12196
|
+
if (rel === "" || rel.startsWith("..") || path23.isAbsolute(rel)) return false;
|
|
11968
12197
|
return !rel.split("/").some((segment) => SKIP_DIRS.has(segment));
|
|
11969
12198
|
}
|
|
11970
12199
|
function handleFsWatchRequest(req, res, getProjectRoot) {
|
|
@@ -12005,7 +12234,7 @@ function handleFsWatchRequest(req, res, getProjectRoot) {
|
|
|
12005
12234
|
`);
|
|
12006
12235
|
}
|
|
12007
12236
|
function onChange(_event, filename) {
|
|
12008
|
-
const rel = filename ? filename.toString().split(
|
|
12237
|
+
const rel = filename ? filename.toString().split(path23.sep).join("/") : ".";
|
|
12009
12238
|
if (rel !== "." && !shouldReportWatchPath(rel)) return;
|
|
12010
12239
|
pending.add(rel);
|
|
12011
12240
|
if (!debounceTimer) {
|
|
@@ -12060,8 +12289,8 @@ function setIsolationHeaders(res) {
|
|
|
12060
12289
|
}
|
|
12061
12290
|
function containedStaticPath(root, pathname) {
|
|
12062
12291
|
const rel = pathname.replace(/^\/+/, "") || "index.html";
|
|
12063
|
-
const resolved =
|
|
12064
|
-
if (resolved !== root && !resolved.startsWith(root +
|
|
12292
|
+
const resolved = path24.resolve(root, rel);
|
|
12293
|
+
if (resolved !== root && !resolved.startsWith(root + path24.sep)) return null;
|
|
12065
12294
|
return resolved;
|
|
12066
12295
|
}
|
|
12067
12296
|
function serveStaticFile(res, root, pathname) {
|
|
@@ -12072,7 +12301,7 @@ function serveStaticFile(res, root, pathname) {
|
|
|
12072
12301
|
return;
|
|
12073
12302
|
}
|
|
12074
12303
|
Promise.all([fs11.realpath(root), fs11.realpath(candidate)]).then(([realRoot, realFile]) => {
|
|
12075
|
-
if (realFile !== realRoot && !realFile.startsWith(realRoot +
|
|
12304
|
+
if (realFile !== realRoot && !realFile.startsWith(realRoot + path24.sep)) {
|
|
12076
12305
|
res.writeHead(403);
|
|
12077
12306
|
res.end("Forbidden");
|
|
12078
12307
|
return;
|
|
@@ -12084,7 +12313,7 @@ function serveStaticFile(res, root, pathname) {
|
|
|
12084
12313
|
return;
|
|
12085
12314
|
}
|
|
12086
12315
|
res.writeHead(200, {
|
|
12087
|
-
"Content-Type": MIME[
|
|
12316
|
+
"Content-Type": MIME[path24.extname(realFile)] ?? "application/octet-stream",
|
|
12088
12317
|
"Content-Length": stat.size,
|
|
12089
12318
|
"Cache-Control": "no-store"
|
|
12090
12319
|
});
|
|
@@ -12238,7 +12467,7 @@ async function listFilesRecursive(dir, base = "") {
|
|
|
12238
12467
|
for (const e of entries) {
|
|
12239
12468
|
const rel = base ? `${base}/${e.name}` : e.name;
|
|
12240
12469
|
if (e.isDirectory()) {
|
|
12241
|
-
out.push(...await listFilesRecursive(
|
|
12470
|
+
out.push(...await listFilesRecursive(path24.join(dir, e.name), rel));
|
|
12242
12471
|
} else if (e.isFile()) {
|
|
12243
12472
|
out.push(rel);
|
|
12244
12473
|
}
|
|
@@ -12255,9 +12484,9 @@ async function readContributedExtensions(extensionsDir) {
|
|
|
12255
12484
|
}
|
|
12256
12485
|
for (const e of entries) {
|
|
12257
12486
|
if (!e.isDirectory()) continue;
|
|
12258
|
-
const extDir =
|
|
12487
|
+
const extDir = path24.join(extensionsDir, e.name);
|
|
12259
12488
|
try {
|
|
12260
|
-
const pkgRaw = await fs11.readFile(
|
|
12489
|
+
const pkgRaw = await fs11.readFile(path24.join(extDir, "package.json"), "utf8");
|
|
12261
12490
|
const files = await listFilesRecursive(extDir);
|
|
12262
12491
|
out.push({ dir: e.name, packageJson: JSON.parse(pkgRaw), files });
|
|
12263
12492
|
} catch {
|
|
@@ -12266,8 +12495,8 @@ async function readContributedExtensions(extensionsDir) {
|
|
|
12266
12495
|
return out;
|
|
12267
12496
|
}
|
|
12268
12497
|
async function startWorkbenchCoiServer(options) {
|
|
12269
|
-
const root =
|
|
12270
|
-
const contribRoot = options.extensionsDir ?
|
|
12498
|
+
const root = path24.resolve(options.rootDir);
|
|
12499
|
+
const contribRoot = options.extensionsDir ? path24.resolve(options.extensionsDir) : null;
|
|
12271
12500
|
const server = http2.createServer((req, res) => {
|
|
12272
12501
|
setIsolationHeaders(res);
|
|
12273
12502
|
const url = new URL(req.url ?? "/", "http://127.0.0.1");
|
|
@@ -12426,7 +12655,7 @@ var UpdateManager = class {
|
|
|
12426
12655
|
|
|
12427
12656
|
// src/main/services/update/github-release-checker.ts
|
|
12428
12657
|
import fs12 from "fs";
|
|
12429
|
-
import
|
|
12658
|
+
import path25 from "path";
|
|
12430
12659
|
import https from "https";
|
|
12431
12660
|
import { app as app14 } from "electron";
|
|
12432
12661
|
function createGitHubReleaseChecker(opts) {
|
|
@@ -12452,10 +12681,10 @@ function createGitHubReleaseChecker(opts) {
|
|
|
12452
12681
|
};
|
|
12453
12682
|
},
|
|
12454
12683
|
async downloadUpdate(info, onProgress) {
|
|
12455
|
-
const tmpDir =
|
|
12684
|
+
const tmpDir = path25.join(app14.getPath("temp"), `${opts.repo}-update`);
|
|
12456
12685
|
if (!fs12.existsSync(tmpDir)) fs12.mkdirSync(tmpDir, { recursive: true });
|
|
12457
|
-
const fileName =
|
|
12458
|
-
const filePath =
|
|
12686
|
+
const fileName = path25.basename(new URL(info.downloadUrl).pathname);
|
|
12687
|
+
const filePath = path25.join(tmpDir, fileName);
|
|
12459
12688
|
await downloadFile(info.downloadUrl, filePath, opts.token, onProgress);
|
|
12460
12689
|
return filePath;
|
|
12461
12690
|
}
|
|
@@ -12738,7 +12967,7 @@ async function disposeContext(ctx) {
|
|
|
12738
12967
|
function createConfiguredMainWindow(config, rendererDir2) {
|
|
12739
12968
|
const mainWindow = createMainWindow({
|
|
12740
12969
|
title: config.appName ?? "Dimina DevTools",
|
|
12741
|
-
indexHtml:
|
|
12970
|
+
indexHtml: path26.join(rendererDir2, "entries/main/index.html"),
|
|
12742
12971
|
width: config.window?.width,
|
|
12743
12972
|
height: config.window?.height,
|
|
12744
12973
|
minWidth: config.window?.minWidth,
|
|
@@ -12811,12 +13040,20 @@ async function setupAutomation(instance) {
|
|
|
12811
13040
|
console.log(`[automation] listening on ws://127.0.0.1:${server.port}`);
|
|
12812
13041
|
}
|
|
12813
13042
|
}
|
|
12814
|
-
function setupMcp() {
|
|
13043
|
+
function setupMcp(context) {
|
|
12815
13044
|
const settings = loadWorkbenchSettings();
|
|
12816
13045
|
if (!settings.mcp.enabled) return null;
|
|
12817
13046
|
const cdpPortSwitch = app15.commandLine.getSwitchValue("remote-debugging-port");
|
|
12818
13047
|
const cdpPort2 = cdpPortSwitch ? parseInt(cdpPortSwitch, 10) : settings.cdp.port;
|
|
12819
|
-
return startMcpServer(cdpPort2, settings.mcp.port
|
|
13048
|
+
return startMcpServer(cdpPort2, settings.mcp.port, {
|
|
13049
|
+
workspace: context.workspace,
|
|
13050
|
+
sessionStatus: context.sessionStatus,
|
|
13051
|
+
compileLogs: context.compileLogBuffer,
|
|
13052
|
+
// The renderer owns the open path (mounting ProjectRuntime compiles and
|
|
13053
|
+
// attaches the simulator), so project_open pushes it there.
|
|
13054
|
+
requestOpenInUi: (p) => context.notify.windowOpenProject(p),
|
|
13055
|
+
requestNavigateBack: () => context.notify.windowNavigateBack()
|
|
13056
|
+
});
|
|
12820
13057
|
}
|
|
12821
13058
|
function wireAppWindowEvents(config, instance, isOnProjectScreen) {
|
|
12822
13059
|
const { mainWindow, context } = instance;
|
|
@@ -12952,7 +13189,7 @@ async function createDevtoolsRuntime(config = {}, onInstanceCreated) {
|
|
|
12952
13189
|
context.registry.add(() => instance.updateManager.dispose());
|
|
12953
13190
|
}
|
|
12954
13191
|
await setupAutomation(instance);
|
|
12955
|
-
const mcp = setupMcp();
|
|
13192
|
+
const mcp = setupMcp(context);
|
|
12956
13193
|
if (mcp) context.registry.add(mcp);
|
|
12957
13194
|
const getActiveAppId = () => {
|
|
12958
13195
|
const session5 = context.workspace.getSession();
|
|
@@ -13063,8 +13300,8 @@ async function createDevtoolsRuntime(config = {}, onInstanceCreated) {
|
|
|
13063
13300
|
bridge: context.bridge
|
|
13064
13301
|
}));
|
|
13065
13302
|
}
|
|
13066
|
-
const bundleDir = config.editorViewConfig?.bundleDir ??
|
|
13067
|
-
if (!fs13.existsSync(
|
|
13303
|
+
const bundleDir = config.editorViewConfig?.bundleDir ?? path26.join(devtoolsPackageRoot, "dist/vscode-workbench");
|
|
13304
|
+
if (!fs13.existsSync(path26.join(bundleDir, "index.html"))) {
|
|
13068
13305
|
console.warn(
|
|
13069
13306
|
`[workbench] editor bundle not found at ${bundleDir} \u2014 skipping embedded editor assembly`
|
|
13070
13307
|
);
|