@mindstudio-ai/local-model-tunnel 0.5.27 → 0.5.29
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/{chunk-PH6M4GT4.js → chunk-OFJN2X3L.js} +12 -8
- package/dist/chunk-OFJN2X3L.js.map +1 -0
- package/dist/{chunk-N4J5ZGX6.js → chunk-VFI4LNTY.js} +2 -2
- package/dist/{chunk-JRLMRABX.js → chunk-XPXEBWOW.js} +300 -34
- package/dist/chunk-XPXEBWOW.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/headless.js +2 -2
- package/dist/index.js +3 -3
- package/dist/{tui-ZFW3NSXF.js → tui-RWW5C5SG.js} +8 -7
- package/dist/{tui-ZFW3NSXF.js.map → tui-RWW5C5SG.js.map} +1 -1
- package/package.json +1 -1
- package/dist/chunk-JRLMRABX.js.map +0 -1
- package/dist/chunk-PH6M4GT4.js.map +0 -1
- /package/dist/{chunk-N4J5ZGX6.js.map → chunk-VFI4LNTY.js.map} +0 -0
|
@@ -977,6 +977,63 @@ function formatErrorForDisplay(error) {
|
|
|
977
977
|
return parts.join("\n");
|
|
978
978
|
}
|
|
979
979
|
|
|
980
|
+
// src/dev/execution/agent-config.ts
|
|
981
|
+
import { readFileSync } from "fs";
|
|
982
|
+
import { join as join5, dirname as dirname2 } from "path";
|
|
983
|
+
function readAgentConfig(projectRoot, appConfig) {
|
|
984
|
+
const agentInterface = appConfig.interfaces.find(
|
|
985
|
+
(i) => i.type === "agent" && i.enabled !== false
|
|
986
|
+
);
|
|
987
|
+
if (!agentInterface) {
|
|
988
|
+
throw new Error("No agent interface configured in mindstudio.json");
|
|
989
|
+
}
|
|
990
|
+
const configPath = join5(projectRoot, agentInterface.path);
|
|
991
|
+
let raw;
|
|
992
|
+
try {
|
|
993
|
+
raw = readFileSync(configPath, "utf-8");
|
|
994
|
+
} catch {
|
|
995
|
+
throw new Error(
|
|
996
|
+
`Agent config not found at ${agentInterface.path} \u2014 run your build command`
|
|
997
|
+
);
|
|
998
|
+
}
|
|
999
|
+
const parsed = JSON.parse(raw);
|
|
1000
|
+
const config2 = parsed.agent ?? parsed;
|
|
1001
|
+
const agentDir = dirname2(configPath);
|
|
1002
|
+
const systemPromptPath = join5(agentDir, config2.systemPrompt);
|
|
1003
|
+
let systemPrompt;
|
|
1004
|
+
try {
|
|
1005
|
+
systemPrompt = readFileSync(systemPromptPath, "utf-8");
|
|
1006
|
+
} catch {
|
|
1007
|
+
throw new Error(
|
|
1008
|
+
`Agent system prompt not found at ${config2.systemPrompt} \u2014 run your build command`
|
|
1009
|
+
);
|
|
1010
|
+
}
|
|
1011
|
+
const tools = (config2.tools ?? []).map(
|
|
1012
|
+
(tool) => {
|
|
1013
|
+
const descPath = join5(agentDir, tool.description);
|
|
1014
|
+
let description;
|
|
1015
|
+
try {
|
|
1016
|
+
description = readFileSync(descPath, "utf-8");
|
|
1017
|
+
} catch {
|
|
1018
|
+
throw new Error(
|
|
1019
|
+
`Agent tool description not found at ${tool.description} for method "${tool.method}" \u2014 run your build command`
|
|
1020
|
+
);
|
|
1021
|
+
}
|
|
1022
|
+
return {
|
|
1023
|
+
name: tool.method,
|
|
1024
|
+
description
|
|
1025
|
+
};
|
|
1026
|
+
}
|
|
1027
|
+
);
|
|
1028
|
+
return {
|
|
1029
|
+
model: config2.model,
|
|
1030
|
+
temperature: config2.temperature,
|
|
1031
|
+
maxTokens: config2.maxTokens,
|
|
1032
|
+
systemPrompt,
|
|
1033
|
+
tools
|
|
1034
|
+
};
|
|
1035
|
+
}
|
|
1036
|
+
|
|
980
1037
|
// src/dev/execution/runner.ts
|
|
981
1038
|
var DevRunner = class {
|
|
982
1039
|
constructor(appId, projectRoot, startOpts = {}) {
|
|
@@ -991,6 +1048,7 @@ var DevRunner = class {
|
|
|
991
1048
|
hadConnectionWarning = false;
|
|
992
1049
|
proxyUrl;
|
|
993
1050
|
proxy = null;
|
|
1051
|
+
appConfig = null;
|
|
994
1052
|
roleOverride = null;
|
|
995
1053
|
// proxyUrl is sent on every poll request so the platform dashboard can
|
|
996
1054
|
// show the developer's preview URL. Also included in the start request
|
|
@@ -1002,6 +1060,9 @@ var DevRunner = class {
|
|
|
1002
1060
|
setProxy(proxy) {
|
|
1003
1061
|
this.proxy = proxy;
|
|
1004
1062
|
}
|
|
1063
|
+
setAppConfig(appConfig) {
|
|
1064
|
+
this.appConfig = appConfig;
|
|
1065
|
+
}
|
|
1005
1066
|
async start() {
|
|
1006
1067
|
if (this.isRunning) {
|
|
1007
1068
|
throw new Error("DevRunner is already running");
|
|
@@ -1263,16 +1324,35 @@ var DevRunner = class {
|
|
|
1263
1324
|
}
|
|
1264
1325
|
}
|
|
1265
1326
|
async handleRequest(request) {
|
|
1327
|
+
if (request.type === "get-agent-config") {
|
|
1328
|
+
await this.handleGetAgentConfig(request);
|
|
1329
|
+
return;
|
|
1330
|
+
}
|
|
1266
1331
|
const startTime = Date.now();
|
|
1332
|
+
const method = this.appConfig?.methods.find((m) => m.id === request.methodId);
|
|
1333
|
+
if (!method) {
|
|
1334
|
+
const message = `Unknown method ID: ${request.methodId}`;
|
|
1335
|
+
log.error("runner", message, { requestId: request.requestId, sessionId: this.session.sessionId });
|
|
1336
|
+
try {
|
|
1337
|
+
await submitDevResult(this.appId, this.session.sessionId, request.requestId, {
|
|
1338
|
+
type: "execute",
|
|
1339
|
+
success: false,
|
|
1340
|
+
error: { message }
|
|
1341
|
+
});
|
|
1342
|
+
} catch {
|
|
1343
|
+
}
|
|
1344
|
+
devRequestEvents.emitComplete({ id: request.requestId, success: false, duration: 0, error: message });
|
|
1345
|
+
return;
|
|
1346
|
+
}
|
|
1267
1347
|
devRequestEvents.emitStart({
|
|
1268
1348
|
id: request.requestId,
|
|
1269
1349
|
type: request.type,
|
|
1270
|
-
method:
|
|
1350
|
+
method: method.export,
|
|
1271
1351
|
timestamp: startTime
|
|
1272
1352
|
});
|
|
1273
|
-
log.info("runner", "Method received", { requestId: request.requestId, method:
|
|
1353
|
+
log.info("runner", "Method received", { requestId: request.requestId, method: method.export, source: "poll", sessionId: this.session.sessionId });
|
|
1274
1354
|
try {
|
|
1275
|
-
const transpiledPath = await this.transpiler.transpile(
|
|
1355
|
+
const transpiledPath = await this.transpiler.transpile(method.path);
|
|
1276
1356
|
const auth = request.roleOverride ? {
|
|
1277
1357
|
userId: this.session.auth.userId,
|
|
1278
1358
|
roleAssignments: request.roleOverride.map((roleName) => ({
|
|
@@ -1282,7 +1362,7 @@ var DevRunner = class {
|
|
|
1282
1362
|
} : this.session.auth;
|
|
1283
1363
|
const result = await executeMethod({
|
|
1284
1364
|
transpiledPath,
|
|
1285
|
-
methodExport:
|
|
1365
|
+
methodExport: method.export,
|
|
1286
1366
|
input: request.input,
|
|
1287
1367
|
auth,
|
|
1288
1368
|
databases: this.session.databases,
|
|
@@ -1307,11 +1387,11 @@ var DevRunner = class {
|
|
|
1307
1387
|
);
|
|
1308
1388
|
const duration = Date.now() - startTime;
|
|
1309
1389
|
if (result.success) {
|
|
1310
|
-
log.info("runner", "Method complete", { requestId: request.requestId, method:
|
|
1390
|
+
log.info("runner", "Method complete", { requestId: request.requestId, method: method.export, duration, sessionId: this.session.sessionId });
|
|
1311
1391
|
} else {
|
|
1312
1392
|
log.warn("runner", "Method failed", {
|
|
1313
1393
|
requestId: request.requestId,
|
|
1314
|
-
method:
|
|
1394
|
+
method: method.export,
|
|
1315
1395
|
duration,
|
|
1316
1396
|
error: result.error ? formatErrorForDisplay(result.error) : void 0,
|
|
1317
1397
|
sessionId: this.session.sessionId
|
|
@@ -1320,8 +1400,8 @@ var DevRunner = class {
|
|
|
1320
1400
|
logMethodExecution({
|
|
1321
1401
|
requestId: request.requestId,
|
|
1322
1402
|
sessionId: this.session.sessionId,
|
|
1323
|
-
methodExport:
|
|
1324
|
-
methodPath:
|
|
1403
|
+
methodExport: method.export,
|
|
1404
|
+
methodPath: method.path,
|
|
1325
1405
|
input: request.input,
|
|
1326
1406
|
roleOverride: request.roleOverride,
|
|
1327
1407
|
authorizationToken: request.authorizationToken,
|
|
@@ -1338,7 +1418,7 @@ var DevRunner = class {
|
|
|
1338
1418
|
} catch (error) {
|
|
1339
1419
|
const message = error instanceof Error ? error.message : "Unknown error";
|
|
1340
1420
|
const duration = Date.now() - startTime;
|
|
1341
|
-
log.error("runner", "Method execution error", { requestId: request.requestId, method:
|
|
1421
|
+
log.error("runner", "Method execution error", { requestId: request.requestId, method: method.export, duration, error: message, sessionId: this.session.sessionId });
|
|
1342
1422
|
try {
|
|
1343
1423
|
await submitDevResult(
|
|
1344
1424
|
this.appId,
|
|
@@ -1356,8 +1436,8 @@ var DevRunner = class {
|
|
|
1356
1436
|
logMethodExecution({
|
|
1357
1437
|
requestId: request.requestId,
|
|
1358
1438
|
sessionId: this.session.sessionId,
|
|
1359
|
-
methodExport:
|
|
1360
|
-
methodPath:
|
|
1439
|
+
methodExport: method.export,
|
|
1440
|
+
methodPath: method.path,
|
|
1361
1441
|
input: request.input,
|
|
1362
1442
|
roleOverride: request.roleOverride,
|
|
1363
1443
|
authorizationToken: request.authorizationToken,
|
|
@@ -1373,6 +1453,44 @@ var DevRunner = class {
|
|
|
1373
1453
|
});
|
|
1374
1454
|
}
|
|
1375
1455
|
}
|
|
1456
|
+
async handleGetAgentConfig(request) {
|
|
1457
|
+
const startTime = Date.now();
|
|
1458
|
+
log.info("runner", "Agent config requested", { requestId: request.requestId, sessionId: this.session.sessionId });
|
|
1459
|
+
try {
|
|
1460
|
+
if (!this.appConfig) {
|
|
1461
|
+
throw new Error("App config not available");
|
|
1462
|
+
}
|
|
1463
|
+
const bundle = readAgentConfig(this.projectRoot, this.appConfig);
|
|
1464
|
+
await submitDevResult(
|
|
1465
|
+
this.appId,
|
|
1466
|
+
this.session.sessionId,
|
|
1467
|
+
request.requestId,
|
|
1468
|
+
{
|
|
1469
|
+
type: "get-agent-config",
|
|
1470
|
+
success: true,
|
|
1471
|
+
output: bundle
|
|
1472
|
+
}
|
|
1473
|
+
);
|
|
1474
|
+
log.info("runner", "Agent config sent", { requestId: request.requestId, duration: Date.now() - startTime });
|
|
1475
|
+
} catch (err) {
|
|
1476
|
+
const message = err instanceof Error ? err.message : "Unknown error";
|
|
1477
|
+
log.error("runner", "Agent config failed", { requestId: request.requestId, error: message });
|
|
1478
|
+
try {
|
|
1479
|
+
await submitDevResult(
|
|
1480
|
+
this.appId,
|
|
1481
|
+
this.session.sessionId,
|
|
1482
|
+
request.requestId,
|
|
1483
|
+
{
|
|
1484
|
+
type: "get-agent-config",
|
|
1485
|
+
success: false,
|
|
1486
|
+
error: { message }
|
|
1487
|
+
}
|
|
1488
|
+
);
|
|
1489
|
+
} catch (submitErr) {
|
|
1490
|
+
log.error("runner", "Failed to report agent config error to platform", { error: submitErr instanceof Error ? submitErr.message : String(submitErr) });
|
|
1491
|
+
}
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1376
1494
|
/**
|
|
1377
1495
|
* Attempt to refresh expired auth credentials via the device auth flow.
|
|
1378
1496
|
* Opens the browser for the user to re-authorize, polls for the new token.
|
|
@@ -1450,6 +1568,7 @@ function closeBrowserLog() {
|
|
|
1450
1568
|
|
|
1451
1569
|
// src/dev/proxy/proxy.ts
|
|
1452
1570
|
import http from "http";
|
|
1571
|
+
import https from "https";
|
|
1453
1572
|
import { randomBytes as randomBytes4 } from "crypto";
|
|
1454
1573
|
import { WebSocketServer } from "ws";
|
|
1455
1574
|
|
|
@@ -1492,11 +1611,16 @@ var ClientRegistry = class {
|
|
|
1492
1611
|
let fallback = null;
|
|
1493
1612
|
for (const client of this.clients.values()) {
|
|
1494
1613
|
if (client.activeCommandId) continue;
|
|
1614
|
+
if (client.mode === "mirror") continue;
|
|
1495
1615
|
if (client.mode === "iframe") return client;
|
|
1496
1616
|
if (!fallback) fallback = client;
|
|
1497
1617
|
}
|
|
1498
1618
|
return fallback;
|
|
1499
1619
|
}
|
|
1620
|
+
/** Get all connected mirror-mode clients (for relaying mirror events). */
|
|
1621
|
+
getMirrorClients() {
|
|
1622
|
+
return [...this.clients.values()].filter((c) => c.mode === "mirror");
|
|
1623
|
+
}
|
|
1500
1624
|
getAll() {
|
|
1501
1625
|
return [...this.clients.values()];
|
|
1502
1626
|
}
|
|
@@ -1544,9 +1668,10 @@ var ClientRegistry = class {
|
|
|
1544
1668
|
|
|
1545
1669
|
// src/dev/proxy/proxy.ts
|
|
1546
1670
|
var DevProxy = class _DevProxy {
|
|
1547
|
-
constructor(upstreamPort, clientContext, bindAddress = "127.0.0.1", browserAgentUrl) {
|
|
1671
|
+
constructor(upstreamPort, clientContext, appId, bindAddress = "127.0.0.1", browserAgentUrl) {
|
|
1548
1672
|
this.upstreamPort = upstreamPort;
|
|
1549
1673
|
this.clientContext = clientContext;
|
|
1674
|
+
this.appId = appId;
|
|
1550
1675
|
this.bindAddress = bindAddress;
|
|
1551
1676
|
this.browserAgentUrl = browserAgentUrl;
|
|
1552
1677
|
}
|
|
@@ -1777,7 +1902,7 @@ var DevProxy = class _DevProxy {
|
|
|
1777
1902
|
return;
|
|
1778
1903
|
}
|
|
1779
1904
|
clearTimeout(helloTimeout);
|
|
1780
|
-
const mode = msg.mode === "iframe" ? "iframe" : "standalone";
|
|
1905
|
+
const mode = msg.mode === "iframe" ? "iframe" : msg.mode === "mirror" ? "mirror" : "standalone";
|
|
1781
1906
|
const viewport = msg.viewport || {
|
|
1782
1907
|
w: 0,
|
|
1783
1908
|
h: 0
|
|
@@ -1799,6 +1924,9 @@ var DevProxy = class _DevProxy {
|
|
|
1799
1924
|
appendBrowserLogEntries(msg.entries);
|
|
1800
1925
|
}
|
|
1801
1926
|
break;
|
|
1927
|
+
case "mirror":
|
|
1928
|
+
this.relayMirrorEvents(data.toString());
|
|
1929
|
+
break;
|
|
1802
1930
|
}
|
|
1803
1931
|
});
|
|
1804
1932
|
ws.on("pong", () => {
|
|
@@ -1950,6 +2078,10 @@ var DevProxy = class _DevProxy {
|
|
|
1950
2078
|
this.handleFontProxy(clientReq, clientRes);
|
|
1951
2079
|
return;
|
|
1952
2080
|
}
|
|
2081
|
+
if (clientReq.url === "/__mindstudio_dev__/mirror" && clientReq.method === "GET") {
|
|
2082
|
+
this.serveMirrorPage(clientRes);
|
|
2083
|
+
return;
|
|
2084
|
+
}
|
|
1953
2085
|
}
|
|
1954
2086
|
if (clientReq.method === "OPTIONS" && clientReq.headers.origin) {
|
|
1955
2087
|
clientRes.writeHead(204, {
|
|
@@ -1960,9 +2092,58 @@ var DevProxy = class _DevProxy {
|
|
|
1960
2092
|
clientRes.end();
|
|
1961
2093
|
return;
|
|
1962
2094
|
}
|
|
2095
|
+
if (clientReq.url?.startsWith("/_/")) {
|
|
2096
|
+
this.forwardToApi(clientReq, clientRes);
|
|
2097
|
+
return;
|
|
2098
|
+
}
|
|
1963
2099
|
this.forwardToUpstream(clientReq, clientRes);
|
|
1964
2100
|
}
|
|
1965
2101
|
// ---------------------------------------------------------------------------
|
|
2102
|
+
// API forwarding (/_/ same-origin routes)
|
|
2103
|
+
// ---------------------------------------------------------------------------
|
|
2104
|
+
forwardToApi(clientReq, clientRes) {
|
|
2105
|
+
const cors = this.corsHeaders(clientReq);
|
|
2106
|
+
const originalPath = clientReq.url;
|
|
2107
|
+
const rest = originalPath.slice(3);
|
|
2108
|
+
const apiPath = `/_internal/v2/apps/${this.appId}/${rest}`;
|
|
2109
|
+
const apiBaseUrl = getApiBaseUrl();
|
|
2110
|
+
const target = new URL(apiPath, apiBaseUrl);
|
|
2111
|
+
const isHttps = target.protocol === "https:";
|
|
2112
|
+
const httpModule = isHttps ? https : http;
|
|
2113
|
+
const headers = {
|
|
2114
|
+
...clientReq.headers,
|
|
2115
|
+
host: target.host
|
|
2116
|
+
};
|
|
2117
|
+
delete headers["connection"];
|
|
2118
|
+
delete headers["accept-encoding"];
|
|
2119
|
+
const proxyReq = httpModule.request(
|
|
2120
|
+
{
|
|
2121
|
+
hostname: target.hostname,
|
|
2122
|
+
port: target.port || (isHttps ? 443 : 80),
|
|
2123
|
+
path: target.pathname + target.search,
|
|
2124
|
+
method: clientReq.method,
|
|
2125
|
+
headers
|
|
2126
|
+
},
|
|
2127
|
+
(proxyRes) => {
|
|
2128
|
+
const responseHeaders = { ...proxyRes.headers, ...cors };
|
|
2129
|
+
responseHeaders["cache-control"] = "no-store";
|
|
2130
|
+
clientRes.writeHead(proxyRes.statusCode ?? 502, responseHeaders);
|
|
2131
|
+
proxyRes.pipe(clientRes);
|
|
2132
|
+
}
|
|
2133
|
+
);
|
|
2134
|
+
proxyReq.on("error", (err) => {
|
|
2135
|
+
log.warn("proxy", "API proxy error", {
|
|
2136
|
+
path: originalPath,
|
|
2137
|
+
error: err.message
|
|
2138
|
+
});
|
|
2139
|
+
if (!clientRes.headersSent) {
|
|
2140
|
+
clientRes.writeHead(502, cors);
|
|
2141
|
+
clientRes.end(`API proxy error: ${err.message}`);
|
|
2142
|
+
}
|
|
2143
|
+
});
|
|
2144
|
+
clientReq.pipe(proxyReq);
|
|
2145
|
+
}
|
|
2146
|
+
// ---------------------------------------------------------------------------
|
|
1966
2147
|
// Upstream forwarding
|
|
1967
2148
|
// ---------------------------------------------------------------------------
|
|
1968
2149
|
forwardToUpstream(clientReq, clientRes) {
|
|
@@ -2040,6 +2221,91 @@ var DevProxy = class _DevProxy {
|
|
|
2040
2221
|
clientRes.end();
|
|
2041
2222
|
});
|
|
2042
2223
|
}
|
|
2224
|
+
/** Relay a raw mirror message (already JSON-stringified) to all mirror viewers. */
|
|
2225
|
+
relayMirrorEvents(raw) {
|
|
2226
|
+
const mirrors = this.clients.getMirrorClients();
|
|
2227
|
+
for (const client of mirrors) {
|
|
2228
|
+
try {
|
|
2229
|
+
client.ws.send(raw);
|
|
2230
|
+
} catch {
|
|
2231
|
+
}
|
|
2232
|
+
}
|
|
2233
|
+
}
|
|
2234
|
+
/** Serve the mirror replay page — an rrweb Replayer in live mode. */
|
|
2235
|
+
serveMirrorPage(res) {
|
|
2236
|
+
const html = `<!DOCTYPE html>
|
|
2237
|
+
<html>
|
|
2238
|
+
<head>
|
|
2239
|
+
<meta charset="utf-8">
|
|
2240
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
2241
|
+
<title>Mobile Mirror</title>
|
|
2242
|
+
<style>
|
|
2243
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
2244
|
+
html, body { height: 100%; background: #111; overflow: hidden; }
|
|
2245
|
+
#player { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; }
|
|
2246
|
+
.replayer-wrapper { box-shadow: 0 0 40px rgba(0,0,0,0.5); border-radius: 4px; overflow: hidden; }
|
|
2247
|
+
#status { position: fixed; bottom: 16px; left: 50%; transform: translateX(-50%); color: #666; font-family: -apple-system, system-ui, sans-serif; font-size: 13px; }
|
|
2248
|
+
</style>
|
|
2249
|
+
</head>
|
|
2250
|
+
<body>
|
|
2251
|
+
<div id="player"></div>
|
|
2252
|
+
<div id="status">Waiting for mobile device...</div>
|
|
2253
|
+
<script src="https://cdn.jsdelivr.net/npm/rrweb@2.0.0-alpha.13/dist/rrweb.umd.cjs.js"></script>
|
|
2254
|
+
<script>
|
|
2255
|
+
(function() {
|
|
2256
|
+
var proto = location.protocol === 'https:' ? 'wss:' : 'ws:';
|
|
2257
|
+
var ws = new WebSocket(proto + '//' + location.host + '/__mindstudio_dev__/ws');
|
|
2258
|
+
var replayer = null;
|
|
2259
|
+
var status = document.getElementById('status');
|
|
2260
|
+
|
|
2261
|
+
ws.onopen = function() {
|
|
2262
|
+
ws.send(JSON.stringify({
|
|
2263
|
+
type: 'hello',
|
|
2264
|
+
mode: 'mirror',
|
|
2265
|
+
url: location.href,
|
|
2266
|
+
viewport: { w: window.innerWidth, h: window.innerHeight }
|
|
2267
|
+
}));
|
|
2268
|
+
};
|
|
2269
|
+
|
|
2270
|
+
ws.onmessage = function(e) {
|
|
2271
|
+
var msg;
|
|
2272
|
+
try { msg = JSON.parse(e.data); } catch(e) { return; }
|
|
2273
|
+
|
|
2274
|
+
if (msg.type !== 'mirror' || !Array.isArray(msg.events)) return;
|
|
2275
|
+
|
|
2276
|
+
for (var i = 0; i < msg.events.length; i++) {
|
|
2277
|
+
var event = msg.events[i];
|
|
2278
|
+
if (!replayer) {
|
|
2279
|
+
replayer = new rrweb.Replayer([], {
|
|
2280
|
+
root: document.getElementById('player'),
|
|
2281
|
+
liveMode: true,
|
|
2282
|
+
insertStyleRules: [
|
|
2283
|
+
'.replayer-wrapper { position: relative !important; }',
|
|
2284
|
+
],
|
|
2285
|
+
});
|
|
2286
|
+
replayer.startLive(Date.now() - 500);
|
|
2287
|
+
status.textContent = 'Connected';
|
|
2288
|
+
setTimeout(function() { status.style.opacity = '0'; }, 2000);
|
|
2289
|
+
}
|
|
2290
|
+
replayer.addEvent(event);
|
|
2291
|
+
}
|
|
2292
|
+
};
|
|
2293
|
+
|
|
2294
|
+
ws.onclose = function() {
|
|
2295
|
+
status.style.opacity = '1';
|
|
2296
|
+
status.textContent = 'Disconnected \u2014 reconnecting...';
|
|
2297
|
+
setTimeout(function() { location.reload(); }, 2000);
|
|
2298
|
+
};
|
|
2299
|
+
})();
|
|
2300
|
+
</script>
|
|
2301
|
+
</body>
|
|
2302
|
+
</html>`;
|
|
2303
|
+
res.writeHead(200, {
|
|
2304
|
+
"content-type": "text/html; charset=utf-8",
|
|
2305
|
+
"cache-control": "no-store"
|
|
2306
|
+
});
|
|
2307
|
+
res.end(html);
|
|
2308
|
+
}
|
|
2043
2309
|
/**
|
|
2044
2310
|
* Proxy a cross-origin font stylesheet or font file through our server,
|
|
2045
2311
|
* adding CORS headers so the browser agent can read the @font-face rules.
|
|
@@ -2143,13 +2409,13 @@ ${agentScript}`;
|
|
|
2143
2409
|
};
|
|
2144
2410
|
|
|
2145
2411
|
// src/dev/config/app-config.ts
|
|
2146
|
-
import { readFileSync, existsSync as existsSync2 } from "fs";
|
|
2147
|
-
import { join as
|
|
2412
|
+
import { readFileSync as readFileSync2, existsSync as existsSync2 } from "fs";
|
|
2413
|
+
import { join as join6, dirname as dirname3 } from "path";
|
|
2148
2414
|
function detectAppConfig(cwd = process.cwd()) {
|
|
2149
|
-
const appJsonPath =
|
|
2415
|
+
const appJsonPath = join6(cwd, "mindstudio.json");
|
|
2150
2416
|
if (!existsSync2(appJsonPath)) return null;
|
|
2151
2417
|
try {
|
|
2152
|
-
const raw =
|
|
2418
|
+
const raw = readFileSync2(appJsonPath, "utf-8");
|
|
2153
2419
|
const parsed = JSON.parse(raw);
|
|
2154
2420
|
if (!parsed.name || !Array.isArray(parsed.methods)) {
|
|
2155
2421
|
return null;
|
|
@@ -2185,12 +2451,12 @@ function getWebInterfaceConfig(appConfig, cwd = process.cwd()) {
|
|
|
2185
2451
|
if (!webInterface) {
|
|
2186
2452
|
return null;
|
|
2187
2453
|
}
|
|
2188
|
-
const configPath =
|
|
2454
|
+
const configPath = join6(cwd, webInterface.path);
|
|
2189
2455
|
if (!existsSync2(configPath)) {
|
|
2190
2456
|
return null;
|
|
2191
2457
|
}
|
|
2192
2458
|
try {
|
|
2193
|
-
const raw =
|
|
2459
|
+
const raw = readFileSync2(configPath, "utf-8");
|
|
2194
2460
|
const parsed = JSON.parse(raw);
|
|
2195
2461
|
const web = parsed.web;
|
|
2196
2462
|
if (!web || typeof web !== "object") {
|
|
@@ -2211,18 +2477,18 @@ function getWebProjectDir(appConfig, cwd = process.cwd()) {
|
|
|
2211
2477
|
if (!webInterface) {
|
|
2212
2478
|
return null;
|
|
2213
2479
|
}
|
|
2214
|
-
return
|
|
2480
|
+
return dirname3(join6(cwd, webInterface.path));
|
|
2215
2481
|
}
|
|
2216
2482
|
function readTableSources(appConfig, cwd = process.cwd()) {
|
|
2217
2483
|
const results = [];
|
|
2218
2484
|
for (const table of appConfig.tables) {
|
|
2219
|
-
const filePath =
|
|
2485
|
+
const filePath = join6(cwd, table.path);
|
|
2220
2486
|
if (!existsSync2(filePath)) {
|
|
2221
2487
|
log.warn("config", "Table source file not found", { table: table.export, path: table.path });
|
|
2222
2488
|
continue;
|
|
2223
2489
|
}
|
|
2224
2490
|
try {
|
|
2225
|
-
const source =
|
|
2491
|
+
const source = readFileSync2(filePath, "utf-8");
|
|
2226
2492
|
const name = table.export;
|
|
2227
2493
|
results.push({ name, source });
|
|
2228
2494
|
} catch (err) {
|
|
@@ -2240,9 +2506,9 @@ function findDirsNeedingInstall(appConfig, cwd = process.cwd()) {
|
|
|
2240
2506
|
const firstMethodPath = appConfig.methods[0].path;
|
|
2241
2507
|
const parts = firstMethodPath.split("/");
|
|
2242
2508
|
for (let i = parts.length - 1; i >= 1; i--) {
|
|
2243
|
-
const candidate =
|
|
2244
|
-
if (existsSync2(
|
|
2245
|
-
if (!existsSync2(
|
|
2509
|
+
const candidate = join6(cwd, ...parts.slice(0, i));
|
|
2510
|
+
if (existsSync2(join6(candidate, "package.json"))) {
|
|
2511
|
+
if (!existsSync2(join6(candidate, "node_modules"))) {
|
|
2246
2512
|
dirs.push(candidate);
|
|
2247
2513
|
}
|
|
2248
2514
|
break;
|
|
@@ -2250,8 +2516,8 @@ function findDirsNeedingInstall(appConfig, cwd = process.cwd()) {
|
|
|
2250
2516
|
}
|
|
2251
2517
|
}
|
|
2252
2518
|
const webProjectDir = getWebProjectDir(appConfig, cwd);
|
|
2253
|
-
if (webProjectDir && existsSync2(
|
|
2254
|
-
if (!existsSync2(
|
|
2519
|
+
if (webProjectDir && existsSync2(join6(webProjectDir, "package.json"))) {
|
|
2520
|
+
if (!existsSync2(join6(webProjectDir, "node_modules"))) {
|
|
2255
2521
|
dirs.push(webProjectDir);
|
|
2256
2522
|
}
|
|
2257
2523
|
}
|
|
@@ -2280,11 +2546,11 @@ function detectGitBranch() {
|
|
|
2280
2546
|
|
|
2281
2547
|
// src/dev/config/table-watcher.ts
|
|
2282
2548
|
import { watch } from "chokidar";
|
|
2283
|
-
import { join as
|
|
2549
|
+
import { join as join7, dirname as dirname4, basename as basename2 } from "path";
|
|
2284
2550
|
function watchTableFiles(tables, cwd, onChanged) {
|
|
2285
2551
|
if (tables.length === 0) return () => {
|
|
2286
2552
|
};
|
|
2287
|
-
const filePaths = tables.map((t) =>
|
|
2553
|
+
const filePaths = tables.map((t) => join7(cwd, t.path));
|
|
2288
2554
|
let syncTimer;
|
|
2289
2555
|
const watcher = watch(filePaths, {
|
|
2290
2556
|
ignoreInitial: true,
|
|
@@ -2297,8 +2563,8 @@ function watchTableFiles(tables, cwd, onChanged) {
|
|
|
2297
2563
|
});
|
|
2298
2564
|
const dirToFiles = /* @__PURE__ */ new Map();
|
|
2299
2565
|
for (const table of tables) {
|
|
2300
|
-
const absPath =
|
|
2301
|
-
const dir =
|
|
2566
|
+
const absPath = join7(cwd, table.path);
|
|
2567
|
+
const dir = dirname4(absPath);
|
|
2302
2568
|
const file = basename2(absPath);
|
|
2303
2569
|
if (!dirToFiles.has(dir)) dirToFiles.set(dir, /* @__PURE__ */ new Set());
|
|
2304
2570
|
dirToFiles.get(dir).add(file);
|
|
@@ -2315,9 +2581,9 @@ function watchTableFiles(tables, cwd, onChanged) {
|
|
|
2315
2581
|
|
|
2316
2582
|
// src/dev/config/config-watcher.ts
|
|
2317
2583
|
import { watch as watch2 } from "chokidar";
|
|
2318
|
-
import { join as
|
|
2584
|
+
import { join as join8 } from "path";
|
|
2319
2585
|
function watchConfigFile(cwd, onChanged) {
|
|
2320
|
-
const configPath =
|
|
2586
|
+
const configPath = join8(cwd, "mindstudio.json");
|
|
2321
2587
|
let debounceTimer;
|
|
2322
2588
|
const watcher = watch2(configPath, {
|
|
2323
2589
|
ignoreInitial: true,
|
|
@@ -2384,4 +2650,4 @@ export {
|
|
|
2384
2650
|
watchTableFiles,
|
|
2385
2651
|
watchConfigFile
|
|
2386
2652
|
};
|
|
2387
|
-
//# sourceMappingURL=chunk-
|
|
2653
|
+
//# sourceMappingURL=chunk-XPXEBWOW.js.map
|