@ait-co/devtools 0.1.41 → 0.1.44

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.
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","names":[],"sources":["../../src/mcp/ait-source.ts","../../src/mcp/server.ts"],"mappings":";;;;;;;AAsBA;;;;;AAGA;;;;;;;;;;;;;KAHY,kBAAA;AAqBZ;AAAA,UAlBiB,UAAA;;EAEf,MAAA;EAiBiB;EAfjB,IAAA;EAwBsB;EAtBtB,SAAA;EAsByB;EApBzB,MAAA;EAuBe;EArBf,MAAA;;EAEA,KAAA;EAuBU;EArBV,QAAA,EAAU,kBAAA;AAAA;;UAIK,iBAAA;EACf,KAAA,EAAO,UAAA;AAAA;;;;;;;KASG,YAAA,GAAe,MAAA;;UAGV,yBAAA;EAW2C;EAT1D,WAAA;EAYuB;EAVvB,UAAA;AAAA;;UAIe,YAAA;EACf,uBAAA,EAAyB,iBAAA;EACzB,kBAAA,EAAoB,YAAA;EACpB,+BAAA,EAAiC,yBAAA;AAAA;AAAA,KAGvB,aAAA,SAAsB,YAAA;;;;;UAMjB,SAAA;EACf,GAAA,WAAc,aAAA,EAAe,MAAA,EAAQ,CAAA,GAAI,OAAA,CAAQ,YAAA,CAAa,CAAA;AAAA;;;UCO/C,mBAAA;EDpBY;ECsB3B,SAAA,GAAY,SAAA;AAAA;;iBAIE,eAAA,CAAgB,IAAA,GAAM,mBAAA,GAA2B,MAAA;;iBA6D3C,YAAA,CAAA,GAAgB,OAAA"}
1
+ {"version":3,"file":"server.d.ts","names":[],"sources":["../../src/mcp/ait-source.ts","../../src/mcp/server.ts"],"mappings":";;;;;;;AAsBA;;;;;AAGA;;;;;;;;;;;;;KAHY,kBAAA;AAqBZ;AAAA,UAlBiB,UAAA;;EAEf,MAAA;EAiBiB;EAfjB,IAAA;EAwBsB;EAtBtB,SAAA;EAsByB;EApBzB,MAAA;EAuBe;EArBf,MAAA;;EAEA,KAAA;EAuBU;EArBV,QAAA,EAAU,kBAAA;AAAA;;UAIK,iBAAA;EACf,KAAA,EAAO,UAAA;AAAA;;;;;;;KASG,YAAA,GAAe,MAAA;;UAGV,yBAAA;EAW2C;EAT1D,WAAA;EAYuB;EAVvB,UAAA;AAAA;;UAIe,YAAA;EACf,uBAAA,EAAyB,iBAAA;EACzB,kBAAA,EAAoB,YAAA;EACpB,+BAAA,EAAiC,yBAAA;AAAA;AAAA,KAGvB,aAAA,SAAsB,YAAA;;;;;UAMjB,SAAA;EACf,GAAA,WAAc,aAAA,EAAe,MAAA,EAAQ,CAAA,GAAI,OAAA,CAAQ,YAAA,CAAa,CAAA;AAAA;;;UCmB/C,mBAAA;EDhCY;ECkC3B,SAAA,GAAY,SAAA;AAAA;;iBAIE,eAAA,CAAgB,IAAA,GAAM,mBAAA,GAA2B,MAAA;;iBAsD3C,YAAA,CAAA,GAAgB,OAAA"}
@@ -38,6 +38,22 @@ var HttpAitSource = class {
38
38
  }
39
39
  };
40
40
  //#endregion
41
+ //#region src/mcp/errors.ts
42
+ /**
43
+ * 한국어 한 줄 "원인 + 다음 행동" 포맷으로 에러 결과를 빌드한다.
44
+ *
45
+ * @param message - 사용자에게 보여줄 에러 본문 (원인 + 다음 행동 포함).
46
+ */
47
+ function mcpError(message) {
48
+ return {
49
+ content: [{
50
+ type: "text",
51
+ text: message
52
+ }],
53
+ isError: true
54
+ };
55
+ }
56
+ //#endregion
41
57
  //#region src/mcp/sdk-signatures.ts
42
58
  function isObject(v) {
43
59
  return typeof v === "object" && v !== null && !Array.isArray(v);
@@ -183,7 +199,8 @@ new Set([
183
199
  type: "object",
184
200
  properties: {},
185
201
  required: []
186
- }
202
+ },
203
+ availableIn: "both"
187
204
  },
188
205
  {
189
206
  name: "list_network_requests",
@@ -192,16 +209,18 @@ new Set([
192
209
  type: "object",
193
210
  properties: {},
194
211
  required: []
195
- }
212
+ },
213
+ availableIn: "both"
196
214
  },
197
215
  {
198
216
  name: "list_pages",
199
- description: "Returns the single active page (at most one) the relay sees attached. When a second page attaches, the previous one is evicted (last-attach wins — single-attach model). The result includes `singleAttachModel: true` so the agent knows the array is always 0 or 1 entries. Also returns whether the cloudflared tunnel is up and the public wss relay URL. Each page entry includes a `lastSeenAt` ISO timestamp (last inbound CDP message from that target — useful to detect stale entries when the phone app backgrounded). The result also includes `crashDetectedAt` (ISO timestamp or null): when non-null, a page crash was detected via Inspector.targetCrashed / Target.targetDestroyed since the last attach, the pages list will be empty, and `crashWarning` shows a Korean hint to re-attach. Call this first to confirm a page is attached before reading console/network.",
217
+ description: "Returns the single active page (at most one) the relay sees attached. When a second page attaches, the previous one is evicted (last-attach wins — single-attach model). The result includes `singleAttachModel: true` so the agent knows the array is always 0 or 1 entries. Also returns whether the cloudflared tunnel is up and the public wss relay URL. The `tunnel` field includes `droppedAt` (ISO timestamp or null/undefined): when non-null the tunnel has permanently dropped after 3 failed reissue attempts — restart the debug server with `npx @ait-co/devtools devtools-mcp`. Each page entry includes a `lastSeenAt` ISO timestamp (last inbound CDP message from that target — useful to detect stale entries when the phone app backgrounded). The result also includes `crashDetectedAt` (ISO timestamp or null): when non-null, a page crash was detected via Inspector.targetCrashed / Target.targetDestroyed since the last attach, the pages list will be empty, and `crashWarning` shows a Korean hint to re-attach. Call this first to confirm a page is attached before reading console/network.",
200
218
  inputSchema: {
201
219
  type: "object",
202
220
  properties: {},
203
221
  required: []
204
- }
222
+ },
223
+ availableIn: "both"
205
224
  },
206
225
  {
207
226
  name: "build_attach_url",
@@ -223,7 +242,8 @@ new Set([
223
242
  }
224
243
  },
225
244
  required: ["scheme_url"]
226
- }
245
+ },
246
+ availableIn: "relay"
227
247
  },
228
248
  {
229
249
  name: "get_dom_document",
@@ -232,7 +252,8 @@ new Set([
232
252
  type: "object",
233
253
  properties: {},
234
254
  required: []
235
- }
255
+ },
256
+ availableIn: "both"
236
257
  },
237
258
  {
238
259
  name: "take_snapshot",
@@ -241,7 +262,8 @@ new Set([
241
262
  type: "object",
242
263
  properties: {},
243
264
  required: []
244
- }
265
+ },
266
+ availableIn: "both"
245
267
  },
246
268
  {
247
269
  name: "take_screenshot",
@@ -250,16 +272,18 @@ new Set([
250
272
  type: "object",
251
273
  properties: {},
252
274
  required: []
253
- }
275
+ },
276
+ availableIn: "both"
254
277
  },
255
278
  {
256
279
  name: "measure_safe_area",
257
- description: "Runs a safe-area probe on the attached mini-app page via Runtime.evaluate and returns normalized safe-area insets, viewport geometry, device pixel ratio, and User-Agent. Read-only — does not modify page state. Use in a relay session (phone attached) to get ground-truth values for upgrading a viewport preset from extrapolated/placeholder to measured. Requires the relay to be attached — call list_pages first.",
280
+ description: "Runs a safe-area probe on the attached mini-app page via Runtime.evaluate and returns normalized safe-area insets, viewport geometry, device pixel ratio, and User-Agent. Read-only — does not modify page state. Tier C per RFC #277: the same Runtime.evaluate probe runs in both `mock` (devtools panel page with window.__ait state) and `relay` (real-device WebView with window.__sdk). The result includes a `source: \"mock\" | \"relay\"` field so consumers can identify provenance without inspecting payload values. Use in a relay session (phone attached) to get ground-truth values for upgrading a viewport preset from extrapolated/placeholder to measured. Requires a page to be attached — call list_pages first.",
258
281
  inputSchema: {
259
282
  type: "object",
260
283
  properties: {},
261
284
  required: []
262
- }
285
+ },
286
+ availableIn: "both"
263
287
  },
264
288
  {
265
289
  name: "evaluate",
@@ -271,7 +295,8 @@ new Set([
271
295
  description: "JavaScript expression to evaluate in the page context."
272
296
  } },
273
297
  required: ["expression"]
274
- }
298
+ },
299
+ availableIn: "both"
275
300
  },
276
301
  {
277
302
  name: "list_exceptions",
@@ -283,7 +308,8 @@ new Set([
283
308
  description: "Maximum number of exceptions to return (default 50, max 50)."
284
309
  } },
285
310
  required: []
286
- }
311
+ },
312
+ availableIn: "both"
287
313
  },
288
314
  {
289
315
  name: "call_sdk",
@@ -302,7 +328,8 @@ new Set([
302
328
  }
303
329
  },
304
330
  required: ["name"]
305
- }
331
+ },
332
+ availableIn: "both"
306
333
  },
307
334
  {
308
335
  name: "AIT.getSdkCallHistory",
@@ -311,7 +338,8 @@ new Set([
311
338
  type: "object",
312
339
  properties: {},
313
340
  required: []
314
- }
341
+ },
342
+ availableIn: "both"
315
343
  },
316
344
  {
317
345
  name: "AIT.getMockState",
@@ -320,7 +348,8 @@ new Set([
320
348
  type: "object",
321
349
  properties: {},
322
350
  required: []
323
- }
351
+ },
352
+ availableIn: "both"
324
353
  },
325
354
  {
326
355
  name: "AIT.getOperationalEnvironment",
@@ -329,7 +358,21 @@ new Set([
329
358
  type: "object",
330
359
  properties: {},
331
360
  required: []
332
- }
361
+ },
362
+ availableIn: "both"
363
+ },
364
+ {
365
+ name: "get_diagnostics",
366
+ description: "Returns a single-call server status snapshot so the agent can diagnose \"why is this not working?\" without calling multiple tools. Fields: mcpVersion (MCP SDK version), devtoolsVersion (@ait-co/devtools package version), tunnel (up/wssUrl/pid/startedAt), pages (list_pages result + lastSeenAt stats), lastAttachAt, lastDetachAt, recentErrors (last N server-side errors, PII/secret redacted), environment (getEnvironment() result + reason), serverLockHolder (pid + startedAt from the lock file, or null). All fields are nullable — missing data is null, not an error. Tier C (both mock and relay). Call this first when debugging session state.",
367
+ inputSchema: {
368
+ type: "object",
369
+ properties: { recent_errors_limit: {
370
+ type: "number",
371
+ description: "Maximum number of recent server-side errors to include (default 10, max 50)."
372
+ } },
373
+ required: []
374
+ },
375
+ availableIn: "both"
333
376
  }
334
377
  ].map((t) => t.name));
335
378
  `
@@ -350,17 +393,28 @@ new Set([
350
393
  };
351
394
  document.documentElement.removeChild(el);
352
395
  var sdkInsets = null;
396
+ var sdkInsetsSource = null;
353
397
  var sdkInsetsError = undefined;
354
398
  try {
355
399
  var sdk = window.__sdk;
400
+ var ait = window.__ait;
356
401
  if (sdk && sdk.SafeAreaInsets && typeof sdk.SafeAreaInsets.get === 'function') {
357
402
  sdkInsets = sdk.SafeAreaInsets.get();
403
+ sdkInsetsSource = 'window.__sdk';
358
404
  } else if (sdk && typeof sdk.getSafeAreaInsets === 'function') {
359
405
  sdkInsets = sdk.getSafeAreaInsets();
360
- } else if (!sdk) {
361
- sdkInsetsError = 'window.__sdk not available (non-dogfood bundle)';
362
- } else {
406
+ sdkInsetsSource = 'window.__sdk';
407
+ } else if (ait && ait.state && ait.state.safeAreaInsets &&
408
+ typeof ait.state.safeAreaInsets.top === 'number') {
409
+ var s = ait.state.safeAreaInsets;
410
+ sdkInsets = { top: s.top, bottom: s.bottom, left: s.left, right: s.right };
411
+ sdkInsetsSource = 'window.__ait';
412
+ } else if (!sdk && !ait) {
413
+ sdkInsetsError = 'neither window.__sdk (relay) nor window.__ait (mock) available';
414
+ } else if (sdk) {
363
415
  sdkInsetsError = 'neither SafeAreaInsets.get nor getSafeAreaInsets found on window.__sdk';
416
+ } else {
417
+ sdkInsetsError = 'window.__ait.state.safeAreaInsets is missing or malformed';
364
418
  }
365
419
  } catch(e) {
366
420
  sdkInsetsError = String(e && e.message || e);
@@ -377,6 +431,7 @@ new Set([
377
431
  var result = {
378
432
  cssEnv: cssEnv,
379
433
  sdkInsets: sdkInsets,
434
+ sdkInsetsSource: sdkInsetsSource,
380
435
  navBarHeight: navBarHeight,
381
436
  navBarHeightSource: navBarHeightSource,
382
437
  innerWidth: window.innerWidth,
@@ -447,7 +502,13 @@ function getOperationalEnvironment(source) {
447
502
  * }
448
503
  * }
449
504
  */
450
- /** Tool descriptors served by the dev-mode server. */
505
+ /**
506
+ * Tool descriptors served by the dev-mode server.
507
+ *
508
+ * All dev-mode tools are Tier C (both envs) per RFC #277 — the dev-mode server
509
+ * itself is the mock-side embodiment of those Tier C tools. `availableIn` is
510
+ * declared so the surface stays consistent with the debug-mode registry.
511
+ */
451
512
  const DEV_TOOL_DEFINITIONS = [
452
513
  {
453
514
  name: "AIT.getMockState",
@@ -456,7 +517,8 @@ const DEV_TOOL_DEFINITIONS = [
456
517
  type: "object",
457
518
  properties: {},
458
519
  required: []
459
- }
520
+ },
521
+ availableIn: "both"
460
522
  },
461
523
  {
462
524
  name: "AIT.getOperationalEnvironment",
@@ -465,7 +527,8 @@ const DEV_TOOL_DEFINITIONS = [
465
527
  type: "object",
466
528
  properties: {},
467
529
  required: []
468
- }
530
+ },
531
+ availableIn: "both"
469
532
  },
470
533
  {
471
534
  name: "AIT.getSdkCallHistory",
@@ -474,7 +537,8 @@ const DEV_TOOL_DEFINITIONS = [
474
537
  type: "object",
475
538
  properties: {},
476
539
  required: []
477
- }
540
+ },
541
+ availableIn: "both"
478
542
  },
479
543
  {
480
544
  name: "devtools_get_mock_state",
@@ -483,7 +547,8 @@ const DEV_TOOL_DEFINITIONS = [
483
547
  type: "object",
484
548
  properties: {},
485
549
  required: []
486
- }
550
+ },
551
+ availableIn: "both"
487
552
  }
488
553
  ];
489
554
  const DEV_TOOL_NAMES = new Set(DEV_TOOL_DEFINITIONS.map((t) => t.name));
@@ -493,47 +558,23 @@ function createDevServer(deps = {}) {
493
558
  const aitSource = deps.aitSource ?? new HttpAitSource({ stateEndpoint });
494
559
  const server = new Server({
495
560
  name: "ait-devtools",
496
- version: "0.1.41"
561
+ version: "0.1.44"
497
562
  }, { capabilities: { tools: {} } });
498
563
  server.setRequestHandler(ListToolsRequestSchema, () => ({ tools: DEV_TOOL_DEFINITIONS.map((tool) => ({ ...tool })) }));
499
564
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
500
565
  const name = request.params.name;
501
- if (!DEV_TOOL_NAMES.has(name)) return {
502
- content: [{
503
- type: "text",
504
- text: `Unknown tool: ${name}`
505
- }],
506
- isError: true
507
- };
566
+ if (!DEV_TOOL_NAMES.has(name)) return mcpError(`알 수 없는 tool: ${name}`);
508
567
  try {
509
568
  const effective = name === "devtools_get_mock_state" ? "AIT.getMockState" : name;
510
- if (!isAitToolName(effective)) return {
511
- content: [{
512
- type: "text",
513
- text: `Unknown tool: ${name}`
514
- }],
515
- isError: true
516
- };
569
+ if (!isAitToolName(effective)) return mcpError(`알 수 없는 tool: ${name}`);
517
570
  switch (effective) {
518
571
  case "AIT.getMockState": return jsonResult(await getMockState(aitSource));
519
572
  case "AIT.getOperationalEnvironment": return jsonResult(await getOperationalEnvironment(aitSource));
520
573
  case "AIT.getSdkCallHistory": return jsonResult(await getSdkCallHistory(aitSource));
521
- default: return {
522
- content: [{
523
- type: "text",
524
- text: `Unknown tool: ${name}`
525
- }],
526
- isError: true
527
- };
574
+ default: return mcpError(`알 수 없는 tool: ${name}`);
528
575
  }
529
576
  } catch (err) {
530
- return {
531
- content: [{
532
- type: "text",
533
- text: `${err instanceof Error ? err.message : String(err)}\nIs the Vite dev server running with the @ait-co/devtools unplugin option \`mcp: true\`? Is AIT_DEVTOOLS_URL set correctly?`
534
- }],
535
- isError: true
536
- };
577
+ return mcpError(`${name} 실패: ${err instanceof Error ? err.message : String(err)}\nVite dev 서버가 @ait-co/devtools unplugin \`mcp: true\` 옵션으로 실행 중인지 확인하세요. AIT_DEVTOOLS_URL 환경변수가 올바르게 설정됐는지도 확인하세요.`);
537
578
  }
538
579
  });
539
580
  return server;