@ait-co/devtools 0.1.100 → 0.1.102
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/mcp/cli.js +107 -19
- package/dist/mcp/cli.js.map +1 -1
- package/dist/mcp/server.js +1 -1
- package/dist/panel/index.js +2 -2
- package/dist/{qr-http-server-Clvk1weS.cjs → qr-http-server-B7DsRdN1.cjs} +13 -6
- package/dist/{qr-http-server-Clvk1weS.cjs.map → qr-http-server-B7DsRdN1.cjs.map} +1 -1
- package/dist/{qr-http-server-B1fmICC4.js → qr-http-server-CK-ZT_pC.js} +13 -6
- package/dist/{qr-http-server-B1fmICC4.js.map → qr-http-server-CK-ZT_pC.js.map} +1 -1
- package/dist/{qr-http-server-ofopTUL-.js → qr-http-server-DI3A6f5L.js} +13 -6
- package/dist/{qr-http-server-ofopTUL-.js.map → qr-http-server-DI3A6f5L.js.map} +1 -1
- package/dist/{qr-http-server-C9NUBysQ.cjs → qr-http-server-Dqb3GQju.cjs} +13 -6
- package/dist/{qr-http-server-C9NUBysQ.cjs.map → qr-http-server-Dqb3GQju.cjs.map} +1 -1
- package/dist/{relay-secret-store-J0SUUXjH.js → relay-secret-store-B0DH-8Qb.js} +46 -3
- package/dist/relay-secret-store-B0DH-8Qb.js.map +1 -0
- package/dist/{relay-secret-store-B5WAozDv.cjs → relay-secret-store-CqDaaFW1.cjs} +43 -2
- package/dist/relay-secret-store-CqDaaFW1.cjs.map +1 -0
- package/dist/{relay-secret-store-BvNWdSjV.js → relay-secret-store-DKuoAJmA.js} +43 -2
- package/dist/relay-secret-store-DKuoAJmA.js.map +1 -0
- package/dist/{relay-url-store-RKcao_yG.js → relay-url-store-BPeUZsiY.js} +2 -2
- package/dist/{relay-url-store-RKcao_yG.js.map → relay-url-store-BPeUZsiY.js.map} +1 -1
- package/dist/{relay-url-store-D2lX9POP.cjs → relay-url-store-CIZlFBkR.cjs} +2 -2
- package/dist/{relay-url-store-D2lX9POP.cjs.map → relay-url-store-CIZlFBkR.cjs.map} +1 -1
- package/dist/{relay-url-store-1CXVqNDL.js → relay-url-store-DASEZiT9.js} +2 -2
- package/dist/{relay-url-store-1CXVqNDL.js.map → relay-url-store-DASEZiT9.js.map} +1 -1
- package/dist/{tunnel-C_qpse3-.js → tunnel-CepDBgEc.js} +2 -2
- package/dist/{tunnel-C_qpse3-.js.map → tunnel-CepDBgEc.js.map} +1 -1
- package/dist/{tunnel-BmDfjkQI.cjs → tunnel-D0QnxKsF.cjs} +2 -2
- package/dist/{tunnel-BmDfjkQI.cjs.map → tunnel-D0QnxKsF.cjs.map} +1 -1
- package/dist/unplugin/index.cjs +3 -3
- package/dist/unplugin/index.js +3 -3
- package/dist/unplugin/tunnel.cjs +1 -1
- package/dist/unplugin/tunnel.js +1 -1
- package/package.json +1 -1
- package/dist/relay-secret-store-B5WAozDv.cjs.map +0 -1
- package/dist/relay-secret-store-BvNWdSjV.js.map +0 -1
- package/dist/relay-secret-store-J0SUUXjH.js.map +0 -1
package/dist/mcp/cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { i as generateTotp, n as assertRelayAuthConfigured, r as buildRelayVerifyAuth } from "../totp-Xq3ACwkm.js";
|
|
3
|
-
import { t as loadRelaySecretReadOnly } from "../relay-secret-store-
|
|
3
|
+
import { t as loadRelaySecretReadOnly } from "../relay-secret-store-B0DH-8Qb.js";
|
|
4
4
|
import { createRequire } from "node:module";
|
|
5
5
|
import { existsSync, mkdirSync, readFileSync, realpathSync, rmSync, writeFileSync } from "node:fs";
|
|
6
6
|
import { argv } from "node:process";
|
|
@@ -1933,7 +1933,7 @@ function findFreePort() {
|
|
|
1933
1933
|
else resolve(port);
|
|
1934
1934
|
});
|
|
1935
1935
|
});
|
|
1936
|
-
server.
|
|
1936
|
+
server.on("error", reject);
|
|
1937
1937
|
});
|
|
1938
1938
|
}
|
|
1939
1939
|
/**
|
|
@@ -3003,7 +3003,7 @@ function buildLangSwitcher(path, existingParams, locale, s) {
|
|
|
3003
3003
|
* - tunnel wssUrl은 "터널 연결됨" 상태 표시에서 UP/DOWN만 노출.
|
|
3004
3004
|
* wssUrl 값 자체는 dashboard HTML에 넣지 않는다.
|
|
3005
3005
|
*/
|
|
3006
|
-
function buildDashboardHtml(state, qrDataUrl, locale, path = "/", params = new URLSearchParams()) {
|
|
3006
|
+
function buildDashboardHtml(state, qrDataUrl, locale, path = "/", params = new URLSearchParams(), devtoolsEntryUrl = null) {
|
|
3007
3007
|
const s = resolveLocaleStrings(locale);
|
|
3008
3008
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
3009
3009
|
const tunnelStatus = state.tunnel.up ? s("dashboard.tunnel.up") : s("dashboard.tunnel.down");
|
|
@@ -3016,7 +3016,7 @@ function buildDashboardHtml(state, qrDataUrl, locale, path = "/", params = new U
|
|
|
3016
3016
|
} else attachSection = `<p class="hint">${escapeHtml(s("dashboard.attach.hint"))}</p>`;
|
|
3017
3017
|
const pagesAttached = Array.isArray(state.pages) && state.pages.length > 0;
|
|
3018
3018
|
let inspectorSection;
|
|
3019
|
-
if (pagesAttached &&
|
|
3019
|
+
if (pagesAttached && devtoolsEntryUrl) inspectorSection = `<a class="inspector-link" id="inspector-link" href="${escapeHtml(devtoolsEntryUrl)}" target="_blank" rel="noopener noreferrer">${escapeHtml(s("dashboard.inspector.open"))}</a>`;
|
|
3020
3020
|
else inspectorSection = `<span class="inspector-hint" id="inspector-link">${escapeHtml(s("dashboard.inspector.waiting"))}</span>`;
|
|
3021
3021
|
const pagesSection = state.pages === null ? "" : `<hr /><section id="pages-section"><h2>${escapeHtml(s("dashboard.pages.section"))}</h2><ul id="pages-list">${state.pages.length > 0 ? state.pages.map((p) => {
|
|
3022
3022
|
return `<li><span class="page-id">${escapeHtml(p.id)}</span> <span class="page-url">${escapeHtml(p.url.slice(0, 120))}</span></li>`;
|
|
@@ -3301,7 +3301,13 @@ async function startQrHttpServer(getDashboardState, options) {
|
|
|
3301
3301
|
errorCorrectionLevel: "M"
|
|
3302
3302
|
});
|
|
3303
3303
|
} catch {}
|
|
3304
|
-
const
|
|
3304
|
+
const devtoolsEntryUrl = (() => {
|
|
3305
|
+
if (!options?.getDirectInspectorUrl) return null;
|
|
3306
|
+
const addr = server.address();
|
|
3307
|
+
if (!addr || typeof addr === "string") return null;
|
|
3308
|
+
return `http://127.0.0.1:${addr.port}/devtools/`;
|
|
3309
|
+
})();
|
|
3310
|
+
const html = buildDashboardHtml(state, qrDataUrl, locale, path, params, devtoolsEntryUrl);
|
|
3305
3311
|
res.writeHead(200, {
|
|
3306
3312
|
"Content-Type": "text/html; charset=utf-8",
|
|
3307
3313
|
"Cache-Control": "no-store"
|
|
@@ -3369,11 +3375,12 @@ async function startQrHttpServer(getDashboardState, options) {
|
|
|
3369
3375
|
});
|
|
3370
3376
|
return;
|
|
3371
3377
|
}
|
|
3372
|
-
if (path === "/inspector") {
|
|
3378
|
+
if (path === "/inspector" || path === "/devtools" || path === "/devtools/") {
|
|
3373
3379
|
const getDirectInspectorUrl = options?.getDirectInspectorUrl;
|
|
3374
3380
|
if (!getDirectInspectorUrl) {
|
|
3381
|
+
const body = path === "/inspector" ? "Inspector endpoint is not available in this server mode." : "relay 연결 세션에서만 DevTools UI를 열 수 있습니다.";
|
|
3375
3382
|
res.writeHead(503, { "Content-Type": "text/plain; charset=utf-8" });
|
|
3376
|
-
res.end(
|
|
3383
|
+
res.end(body);
|
|
3377
3384
|
return;
|
|
3378
3385
|
}
|
|
3379
3386
|
const result = getDirectInspectorUrl();
|
|
@@ -4858,7 +4865,7 @@ async function readMcpSdkVersion() {
|
|
|
4858
4865
|
* some test environments that skip the build step).
|
|
4859
4866
|
*/
|
|
4860
4867
|
function readDevtoolsVersion() {
|
|
4861
|
-
return "0.1.
|
|
4868
|
+
return "0.1.102";
|
|
4862
4869
|
}
|
|
4863
4870
|
/**
|
|
4864
4871
|
* Derives the next recommended action from a completed diagnostics snapshot.
|
|
@@ -5313,6 +5320,52 @@ function makeTunnelStatus(up, wssUrl, droppedAt = null, reissueAttempts = 0) {
|
|
|
5313
5320
|
* Node-only.
|
|
5314
5321
|
*/
|
|
5315
5322
|
/**
|
|
5323
|
+
* Maximum age (ms) of a page's `lastSeenAt` before it is treated as a ghost
|
|
5324
|
+
* and excluded from the `wait_for_attach` short-circuit in `build_attach_url`
|
|
5325
|
+
* (issue #610).
|
|
5326
|
+
*
|
|
5327
|
+
* Rationale: the env-2 relay is owned by the dev server (unplugin), so every
|
|
5328
|
+
* `dev:phone:cdp` restart produces a new quick-tunnel. The old relay goes
|
|
5329
|
+
* offline immediately, but the daemon's warm `ChiiCdpConnection` still lists
|
|
5330
|
+
* the last-seen target — its `lastSeenAt` freezes at the moment the old relay
|
|
5331
|
+
* died. A 5-minute threshold is large enough to be invisible in normal usage
|
|
5332
|
+
* (active CDP sessions see a message every few seconds) while being small
|
|
5333
|
+
* enough to catch a relay that went down before the daemon was re-entered.
|
|
5334
|
+
*
|
|
5335
|
+
* Injectable for tests via {@link DebugServerDeps.stalePageThresholdMs}.
|
|
5336
|
+
*/
|
|
5337
|
+
const RELAY_SANDBOX_STALE_PAGE_MS = 300 * 1e3;
|
|
5338
|
+
/**
|
|
5339
|
+
* Predicate used by `build_attach_url`'s `wait_for_attach` loop to decide
|
|
5340
|
+
* whether the relay-sandbox connection has a genuinely fresh page attached.
|
|
5341
|
+
*
|
|
5342
|
+
* Stale-ghost gating (issue #610): when the dev server restarts with a new
|
|
5343
|
+
* quick-tunnel, the warm `ChiiCdpConnection` still lists the last-seen target
|
|
5344
|
+
* but its `lastSeenAt` is frozen. A page whose `lastSeenAt` exceeds
|
|
5345
|
+
* `stalePageThresholdMs` is a ghost from the dead relay — it must NOT
|
|
5346
|
+
* short-circuit `wait_for_attach`.
|
|
5347
|
+
*
|
|
5348
|
+
* Rules:
|
|
5349
|
+
* - `pages.length === 0` → false (nothing attached).
|
|
5350
|
+
* - Connection has no `getLastSeenAt` (test fakes, local-browser) → falls back
|
|
5351
|
+
* to `pages.length > 0` (regression-safe).
|
|
5352
|
+
* - `seenMs === null` → treat as fresh (no CDP message received yet, first
|
|
5353
|
+
* message pending — the connection is alive).
|
|
5354
|
+
* - Otherwise: at least one page must satisfy `nowMs - seenMs <=
|
|
5355
|
+
* stalePageThresholdMs`.
|
|
5356
|
+
*
|
|
5357
|
+
* Exported for unit testing.
|
|
5358
|
+
*/
|
|
5359
|
+
function isSandboxPageFresh(pages, getLastSeenAt, nowMs, stalePageThresholdMs) {
|
|
5360
|
+
if (pages.length === 0) return false;
|
|
5361
|
+
if (getLastSeenAt === null) return true;
|
|
5362
|
+
return pages.some((p) => {
|
|
5363
|
+
const seenMs = getLastSeenAt(p.id);
|
|
5364
|
+
if (seenMs === null) return true;
|
|
5365
|
+
return nowMs - seenMs <= stalePageThresholdMs;
|
|
5366
|
+
});
|
|
5367
|
+
}
|
|
5368
|
+
/**
|
|
5316
5369
|
* Parses `_deploymentId` from the query string of a scheme URL.
|
|
5317
5370
|
*
|
|
5318
5371
|
* Returns `null` when the param is absent or empty — callers treat that as
|
|
@@ -5395,7 +5448,7 @@ function waitForAttachWithEvents(connection, filterFn, timeoutMs, pollIntervalMs
|
|
|
5395
5448
|
* naturally via `enableDomains`). The tier only controls visibility.
|
|
5396
5449
|
*/
|
|
5397
5450
|
function createDebugServer(deps) {
|
|
5398
|
-
const { connection, router: routerDep, aitSource, getTunnelStatus, waitForAttachTimeoutMs = 6e4, qrHttpServer, getEnvironment: getEnvDep, getEnvironmentReason: getEnvReasonDep, diagnosticsCollector: collectorDep, totpSecret, onAttachUrlBuilt, getTunnelChildPid, readLock: readLockDep } = deps;
|
|
5451
|
+
const { connection, router: routerDep, aitSource, getTunnelStatus, waitForAttachTimeoutMs = 6e4, qrHttpServer, getEnvironment: getEnvDep, getEnvironmentReason: getEnvReasonDep, diagnosticsCollector: collectorDep, totpSecret, onAttachUrlBuilt, getTunnelChildPid, readLock: readLockDep, stalePageThresholdMs = RELAY_SANDBOX_STALE_PAGE_MS, nowMs = () => Date.now() } = deps;
|
|
5399
5452
|
const getTotpSecret = deps.getTotpSecret ?? (() => totpSecret);
|
|
5400
5453
|
const readLockFn = readLockDep ?? readServerLock;
|
|
5401
5454
|
const router = routerDep ?? makeSingleConnectionRouter(connection);
|
|
@@ -5404,7 +5457,7 @@ function createDebugServer(deps) {
|
|
|
5404
5457
|
const collector = collectorDep ?? new InMemoryDiagnosticsCollector();
|
|
5405
5458
|
const server = new Server({
|
|
5406
5459
|
name: "ait-debug",
|
|
5407
|
-
version: "0.1.
|
|
5460
|
+
version: "0.1.102"
|
|
5408
5461
|
}, { capabilities: { tools: { listChanged: true } } });
|
|
5409
5462
|
server.setRequestHandler(ListToolsRequestSchema, () => {
|
|
5410
5463
|
const conn = router.active;
|
|
@@ -5492,7 +5545,7 @@ function createDebugServer(deps) {
|
|
|
5492
5545
|
const buildProjectRoot = typeof rawBuildProjectRoot === "string" ? rawBuildProjectRoot : void 0;
|
|
5493
5546
|
let tunnelHttpUrl = process.env.AIT_TUNNEL_BASE_URL?.trim() ?? "";
|
|
5494
5547
|
if (tunnelHttpUrl === "" && buildProjectRoot !== void 0) {
|
|
5495
|
-
const { readRelayUrls } = await import("../relay-url-store-
|
|
5548
|
+
const { readRelayUrls } = await import("../relay-url-store-BPeUZsiY.js");
|
|
5496
5549
|
tunnelHttpUrl = (await readRelayUrls({ projectRoot: buildProjectRoot }))?.tunnelBaseUrl ?? "";
|
|
5497
5550
|
}
|
|
5498
5551
|
if (tunnelHttpUrl === "") return mcpError("build_attach_url(mobile): AIT_TUNNEL_BASE_URL이 설정되지 않았습니다. dev 서버가 tunnel:{cdp:true}로 기동 중이면 .ait_urls 파일이 자동 생성돼 있어야 합니다. 자동 발견이 되지 않을 경우 앱 HTTP 터널 URL을 AIT_TUNNEL_BASE_URL 환경변수로 직접 전달하세요.");
|
|
@@ -5533,7 +5586,10 @@ function createDebugServer(deps) {
|
|
|
5533
5586
|
});
|
|
5534
5587
|
const relayUrl = tunnelStatus.wssUrl;
|
|
5535
5588
|
const totp = totpMeta;
|
|
5536
|
-
const
|
|
5589
|
+
const connAsAny = conn;
|
|
5590
|
+
const getLastSeenAt = typeof connAsAny.getTargetLastSeenAt === "function" ? (id) => connAsAny.getTargetLastSeenAt(id) : null;
|
|
5591
|
+
const callNow = nowMs();
|
|
5592
|
+
const isMatchingPage = (pages) => isSandboxPageFresh(pages, getLastSeenAt, callNow, stalePageThresholdMs);
|
|
5537
5593
|
const buildTimeoutError = (baseText, timeoutSec, observed) => {
|
|
5538
5594
|
const observedUrls = observed.slice(0, 3).map((p) => p.url.slice(0, 80)).join(", ");
|
|
5539
5595
|
return `${baseText}\n\nNo page attached within ${timeoutSec}s${observed.length > 0 ? ` — previously attached pages: [${observedUrls}]` : ""} — launcher QR을 폰 카메라로 스캔한 뒤 call list_pages를 다시 호출하세요.`;
|
|
@@ -6242,7 +6298,7 @@ async function readRelayLocalUrl(env = process.env, projectRoot) {
|
|
|
6242
6298
|
const envValue = (env.AIT_RELAY_LOCAL_URL ?? "").trim();
|
|
6243
6299
|
if (envValue !== "") return envValue;
|
|
6244
6300
|
if (projectRoot !== void 0) try {
|
|
6245
|
-
const { readRelayUrls } = await import("../relay-url-store-
|
|
6301
|
+
const { readRelayUrls } = await import("../relay-url-store-BPeUZsiY.js");
|
|
6246
6302
|
const stored = await readRelayUrls({ projectRoot });
|
|
6247
6303
|
if (stored?.relayLocalUrl) return stored.relayLocalUrl;
|
|
6248
6304
|
} catch {}
|
|
@@ -6296,7 +6352,7 @@ async function readMobileRelayBaseUrl(env = process.env, projectRoot) {
|
|
|
6296
6352
|
const envValue = typeof raw === "string" ? raw.trim() : "";
|
|
6297
6353
|
if (envValue !== "") return envValue;
|
|
6298
6354
|
if (projectRoot !== void 0) {
|
|
6299
|
-
const { readRelayUrls } = await import("../relay-url-store-
|
|
6355
|
+
const { readRelayUrls } = await import("../relay-url-store-BPeUZsiY.js");
|
|
6300
6356
|
const stored = await readRelayUrls({ projectRoot });
|
|
6301
6357
|
if (stored?.relayBaseUrl !== void 0) return stored.relayBaseUrl;
|
|
6302
6358
|
}
|
|
@@ -6459,10 +6515,39 @@ var DualConnectionRouter = class {
|
|
|
6459
6515
|
* `projectRoot` is forwarded to `bootLazyFor` so `relay-sandbox` boot can
|
|
6460
6516
|
* fall back to `.ait_urls` file discovery (#424) when `AIT_RELAY_BASE_URL` is
|
|
6461
6517
|
* not set in the environment.
|
|
6518
|
+
*
|
|
6519
|
+
* **Relay-sandbox stale-URL rebuild (issue #610):** when the `relay-sandbox`
|
|
6520
|
+
* family is already warm, reads the current relay URL via
|
|
6521
|
+
* `deps.readSandboxRelayUrl` and compares it against the cached
|
|
6522
|
+
* `relayHttpUrl`. If they differ (dev server was restarted → new tunnel),
|
|
6523
|
+
* the stale family is torn down, evicted from the map, and a fresh one is
|
|
6524
|
+
* booted. If they match, or if the URL cannot be read, the warm family is
|
|
6525
|
+
* reused (fail-open — no unnecessary teardown on transient read errors).
|
|
6526
|
+
*
|
|
6527
|
+
* SECRET-HANDLING: fresh and cached relay URLs carry the tunnel host. The
|
|
6528
|
+
* comparison result (same/different) is the only thing surfaced — URLs are
|
|
6529
|
+
* never logged.
|
|
6462
6530
|
*/
|
|
6463
6531
|
async familyFor(key, projectRoot) {
|
|
6464
6532
|
const warm = this.lazyFamilies.get(key);
|
|
6465
|
-
if (warm)
|
|
6533
|
+
if (warm) {
|
|
6534
|
+
if (key === "relay-sandbox" && this.deps.readSandboxRelayUrl !== void 0) {
|
|
6535
|
+
let freshUrl = null;
|
|
6536
|
+
try {
|
|
6537
|
+
freshUrl = await this.deps.readSandboxRelayUrl(projectRoot);
|
|
6538
|
+
} catch {
|
|
6539
|
+
freshUrl = null;
|
|
6540
|
+
}
|
|
6541
|
+
if (freshUrl !== null && freshUrl !== warm.relayHttpUrl) {
|
|
6542
|
+
warm.stop();
|
|
6543
|
+
this.lazyFamilies.delete(key);
|
|
6544
|
+
const booted = await this.deps.bootLazyFor(key, projectRoot);
|
|
6545
|
+
this.lazyFamilies.set(key, booted);
|
|
6546
|
+
return booted;
|
|
6547
|
+
}
|
|
6548
|
+
}
|
|
6549
|
+
return warm;
|
|
6550
|
+
}
|
|
6466
6551
|
const booted = await this.deps.bootLazyFor(key, projectRoot);
|
|
6467
6552
|
this.lazyFamilies.set(key, booted);
|
|
6468
6553
|
return booted;
|
|
@@ -6522,7 +6607,8 @@ async function runDebugServer(options = {}) {
|
|
|
6522
6607
|
diagnosticsCollector,
|
|
6523
6608
|
devtoolsOpener,
|
|
6524
6609
|
onPageAttach: () => qrServer?.notifyStateChange(),
|
|
6525
|
-
getInspectorStableUrl: () => qrServer?.inspectorStableUrl ?? null
|
|
6610
|
+
getInspectorStableUrl: () => qrServer?.inspectorStableUrl ?? null,
|
|
6611
|
+
readSandboxRelayUrl: (pr) => readMobileRelayBaseUrl(process.env, pr).catch(() => null)
|
|
6526
6612
|
});
|
|
6527
6613
|
const aitSource = new RoutingAitSource(() => {
|
|
6528
6614
|
return router.active;
|
|
@@ -6734,7 +6820,8 @@ async function runLocalDebugServer(options = {}) {
|
|
|
6734
6820
|
diagnosticsCollector,
|
|
6735
6821
|
devtoolsOpener,
|
|
6736
6822
|
onPageAttach: () => qrServer?.notifyStateChange(),
|
|
6737
|
-
getInspectorStableUrl: () => qrServer?.inspectorStableUrl ?? null
|
|
6823
|
+
getInspectorStableUrl: () => qrServer?.inspectorStableUrl ?? null,
|
|
6824
|
+
readSandboxRelayUrl: (pr) => readMobileRelayBaseUrl(process.env, pr).catch(() => null)
|
|
6738
6825
|
});
|
|
6739
6826
|
const aitSource = new RoutingAitSource(() => {
|
|
6740
6827
|
return router.active;
|
|
@@ -6929,7 +7016,8 @@ async function runMobileDebugServer(options = {}) {
|
|
|
6929
7016
|
diagnosticsCollector,
|
|
6930
7017
|
devtoolsOpener,
|
|
6931
7018
|
onPageAttach: () => qrServer?.notifyStateChange(),
|
|
6932
|
-
getInspectorStableUrl: () => qrServer?.inspectorStableUrl ?? null
|
|
7019
|
+
getInspectorStableUrl: () => qrServer?.inspectorStableUrl ?? null,
|
|
7020
|
+
readSandboxRelayUrl: (pr) => readMobileRelayBaseUrl(process.env, pr ?? options.projectRoot ?? process.cwd()).catch(() => null)
|
|
6933
7021
|
});
|
|
6934
7022
|
const aitSource = new RoutingAitSource(() => {
|
|
6935
7023
|
return router.active;
|
|
@@ -7503,7 +7591,7 @@ function createDevServer(deps = {}) {
|
|
|
7503
7591
|
const aitSource = deps.aitSource ?? new HttpAitSource({ stateEndpoint });
|
|
7504
7592
|
const server = new Server({
|
|
7505
7593
|
name: "ait-devtools",
|
|
7506
|
-
version: "0.1.
|
|
7594
|
+
version: "0.1.102"
|
|
7507
7595
|
}, { capabilities: { tools: {} } });
|
|
7508
7596
|
server.setRequestHandler(ListToolsRequestSchema, () => ({ tools: DEV_TOOL_DEFINITIONS.map((tool) => ({ ...tool })) }));
|
|
7509
7597
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|