@ait-co/devtools 0.1.40 → 0.1.43

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;;;UCkB/C,mBAAA;ED/BY;ECiC3B,SAAA,GAAY,SAAA;AAAA;;iBAIE,eAAA,CAAgB,IAAA,GAAM,mBAAA,GAA2B,MAAA;;iBA6D3C,YAAA,CAAA,GAAgB,OAAA"}
@@ -3,7 +3,7 @@ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
3
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
4
  import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
5
5
  //#region src/mcp/ait-http-source.ts
6
- function isObject(value) {
6
+ function isObject$1(value) {
7
7
  return typeof value === "object" && value !== null;
8
8
  }
9
9
  var HttpAitSource = class {
@@ -17,7 +17,7 @@ var HttpAitSource = class {
17
17
  const res = await this.fetchImpl(this.stateEndpoint);
18
18
  if (!res.ok) throw new Error(`Failed to fetch mock state from ${this.stateEndpoint}: HTTP ${res.status} ${res.statusText}. Ensure the Vite dev server is running with the @ait-co/devtools unplugin option \`mcp: true\`.`);
19
19
  const body = await res.json();
20
- return isObject(body) ? body : {};
20
+ return isObject$1(body) ? body : {};
21
21
  }
22
22
  async get(method) {
23
23
  switch (method) {
@@ -37,6 +37,144 @@ var HttpAitSource = class {
37
37
  }
38
38
  }
39
39
  };
40
+ //#endregion
41
+ //#region src/mcp/sdk-signatures.ts
42
+ function isObject(v) {
43
+ return typeof v === "object" && v !== null && !Array.isArray(v);
44
+ }
45
+ function describeArgs(args) {
46
+ try {
47
+ return JSON.stringify(args);
48
+ } catch {
49
+ return String(args);
50
+ }
51
+ }
52
+ /**
53
+ * 등록된 메서드 목록.
54
+ *
55
+ * 시그니처 출처 확인:
56
+ * - 함수가 인자를 받지 않으면 args[0] 없음 → `args.length === 0`을 체크하지 않고
57
+ * 그냥 통과시킨다(args 무시하는 stub가 많아서 noArgs 체크가 noise).
58
+ * - 실 SDK 시그니처는 `src/__typecheck.ts`의 `Assert<Mock, Original>` 줄로 보장.
59
+ */
60
+ const SIGNATURES = [
61
+ {
62
+ name: "setDeviceOrientation",
63
+ validateArgs(args) {
64
+ const arg = args[0];
65
+ if (!isObject(arg)) return {
66
+ ok: false,
67
+ expected: "{ type: 'portrait' | 'landscape' }",
68
+ received: describeArgs(args)
69
+ };
70
+ const type = arg.type;
71
+ if (type !== "portrait" && type !== "landscape") return {
72
+ ok: false,
73
+ expected: "{ type: 'portrait' | 'landscape' }",
74
+ received: describeArgs(args)
75
+ };
76
+ return { ok: true };
77
+ },
78
+ example: "call_sdk('setDeviceOrientation', [{ type: 'landscape' }])"
79
+ },
80
+ {
81
+ name: "setIosSwipeGestureEnabled",
82
+ validateArgs(args) {
83
+ const arg = args[0];
84
+ if (!isObject(arg) || typeof arg.isEnabled !== "boolean") return {
85
+ ok: false,
86
+ expected: "{ isEnabled: boolean }",
87
+ received: describeArgs(args)
88
+ };
89
+ return { ok: true };
90
+ },
91
+ example: "call_sdk('setIosSwipeGestureEnabled', [{ isEnabled: false }])"
92
+ },
93
+ {
94
+ name: "setSecureScreen",
95
+ validateArgs(args) {
96
+ const arg = args[0];
97
+ if (!isObject(arg) || typeof arg.enabled !== "boolean") return {
98
+ ok: false,
99
+ expected: "{ enabled: boolean }",
100
+ received: describeArgs(args)
101
+ };
102
+ return { ok: true };
103
+ },
104
+ example: "call_sdk('setSecureScreen', [{ enabled: true }])"
105
+ },
106
+ {
107
+ name: "setScreenAwakeMode",
108
+ validateArgs(args) {
109
+ const arg = args[0];
110
+ if (!isObject(arg) || typeof arg.enabled !== "boolean") return {
111
+ ok: false,
112
+ expected: "{ enabled: boolean }",
113
+ received: describeArgs(args)
114
+ };
115
+ return { ok: true };
116
+ },
117
+ example: "call_sdk('setScreenAwakeMode', [{ enabled: true }])"
118
+ },
119
+ {
120
+ name: "getOperationalEnvironment",
121
+ validateArgs(_args) {
122
+ return { ok: true };
123
+ },
124
+ example: "call_sdk('getOperationalEnvironment', [])"
125
+ },
126
+ {
127
+ name: "getPlatformOS",
128
+ validateArgs(_args) {
129
+ return { ok: true };
130
+ },
131
+ example: "call_sdk('getPlatformOS', [])"
132
+ },
133
+ {
134
+ name: "getDeviceId",
135
+ validateArgs(_args) {
136
+ return { ok: true };
137
+ },
138
+ example: "call_sdk('getDeviceId', [])"
139
+ },
140
+ {
141
+ name: "getLocale",
142
+ validateArgs(_args) {
143
+ return { ok: true };
144
+ },
145
+ example: "call_sdk('getLocale', [])"
146
+ },
147
+ {
148
+ name: "getNetworkStatus",
149
+ validateArgs(_args) {
150
+ return { ok: true };
151
+ },
152
+ example: "call_sdk('getNetworkStatus', [])"
153
+ },
154
+ {
155
+ name: "getSchemeUri",
156
+ validateArgs(_args) {
157
+ return { ok: true };
158
+ },
159
+ example: "call_sdk('getSchemeUri', [])"
160
+ },
161
+ {
162
+ name: "requestReview",
163
+ validateArgs(_args) {
164
+ return { ok: true };
165
+ },
166
+ example: "call_sdk('requestReview', [])"
167
+ },
168
+ {
169
+ name: "closeView",
170
+ validateArgs(_args) {
171
+ return { ok: true };
172
+ },
173
+ example: "call_sdk('closeView', [])"
174
+ }
175
+ ];
176
+ new Map(SIGNATURES.map((s) => [s.name, s]));
177
+ SIGNATURES.map((s) => s.name);
40
178
  new Set([
41
179
  {
42
180
  name: "list_console_messages",
@@ -45,7 +183,8 @@ new Set([
45
183
  type: "object",
46
184
  properties: {},
47
185
  required: []
48
- }
186
+ },
187
+ availableIn: "both"
49
188
  },
50
189
  {
51
190
  name: "list_network_requests",
@@ -54,16 +193,18 @@ new Set([
54
193
  type: "object",
55
194
  properties: {},
56
195
  required: []
57
- }
196
+ },
197
+ availableIn: "both"
58
198
  },
59
199
  {
60
200
  name: "list_pages",
61
- description: "Lists the mini-app page(s) the Chii relay currently sees attached, plus whether the cloudflared tunnel is up and the public wss relay URL the phone uses to attach. Call this first to confirm a page is attached before reading console/network.",
201
+ 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.",
62
202
  inputSchema: {
63
203
  type: "object",
64
204
  properties: {},
65
205
  required: []
66
- }
206
+ },
207
+ availableIn: "both"
67
208
  },
68
209
  {
69
210
  name: "build_attach_url",
@@ -85,7 +226,8 @@ new Set([
85
226
  }
86
227
  },
87
228
  required: ["scheme_url"]
88
- }
229
+ },
230
+ availableIn: "relay"
89
231
  },
90
232
  {
91
233
  name: "get_dom_document",
@@ -94,7 +236,8 @@ new Set([
94
236
  type: "object",
95
237
  properties: {},
96
238
  required: []
97
- }
239
+ },
240
+ availableIn: "both"
98
241
  },
99
242
  {
100
243
  name: "take_snapshot",
@@ -103,7 +246,8 @@ new Set([
103
246
  type: "object",
104
247
  properties: {},
105
248
  required: []
106
- }
249
+ },
250
+ availableIn: "both"
107
251
  },
108
252
  {
109
253
  name: "take_screenshot",
@@ -112,16 +256,18 @@ new Set([
112
256
  type: "object",
113
257
  properties: {},
114
258
  required: []
115
- }
259
+ },
260
+ availableIn: "both"
116
261
  },
117
262
  {
118
263
  name: "measure_safe_area",
119
- 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.",
264
+ 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.",
120
265
  inputSchema: {
121
266
  type: "object",
122
267
  properties: {},
123
268
  required: []
124
- }
269
+ },
270
+ availableIn: "both"
125
271
  },
126
272
  {
127
273
  name: "evaluate",
@@ -133,11 +279,25 @@ new Set([
133
279
  description: "JavaScript expression to evaluate in the page context."
134
280
  } },
135
281
  required: ["expression"]
136
- }
282
+ },
283
+ availableIn: "both"
284
+ },
285
+ {
286
+ name: "list_exceptions",
287
+ description: "Lists JS-level exceptions captured via `Runtime.exceptionThrown` from the relay attached page. Includes timestamp, exception text, source URL/line, and stack trace. Use to root-cause SDK throws that may precede a Toss app crash (#265 / #267). The buffer holds up to 50 most recent exceptions and survives target replaced/crashed/destroyed events so an exception just before a crash is preserved. Returns up to 50 most recent by default.",
288
+ inputSchema: {
289
+ type: "object",
290
+ properties: { limit: {
291
+ type: "number",
292
+ description: "Maximum number of exceptions to return (default 50, max 50)."
293
+ } },
294
+ required: []
295
+ },
296
+ availableIn: "both"
137
297
  },
138
298
  {
139
299
  name: "call_sdk",
140
- description: "Calls a dogfood SDK method via the window.__sdkCall bridge (exported by @apps-in-toss/web-framework only in __DEBUG_BUILD__ bundles). NOT read-only — SDK calls have side effects (navigation, payments, permissions, etc.). On env 2/3 (real device relay) this hits the real SDK; on env 1 (local mock) it hits the mock SDK. Requires the relay to be attached — call list_pages first. Returns {ok: true, value} on success or {ok: false, error} on failure. Returns a clear error if window.__sdkCall is not available (non-dogfood bundle).",
300
+ description: "Calls a dogfood SDK method via the window.__sdkCall bridge (exported by @apps-in-toss/web-framework only in __DEBUG_BUILD__ bundles). NOT read-only — SDK calls have side effects (navigation, payments, permissions, etc.). On env 2/3 (real device relay) this hits the real SDK; on env 1 (local mock) it hits the mock SDK. Requires the relay to be attached — call list_pages first. Returns {ok: true, value} on success or {ok: false, error} on failure. If a Runtime.exceptionThrown event was observed within [callStart-50ms, callEnd+200ms], the result also includes `recentException` for crash triage. Returns a clear error if window.__sdkCall is not available (non-dogfood bundle).\n\nIMPORTANT — 인자 시그니처 (잘못된 인자로 호출하면 토스 앱 crash 위험):\n setDeviceOrientation: call_sdk(\"setDeviceOrientation\", [{ type: \"landscape\" }]) // NOT \"landscape\"\n setIosSwipeGestureEnabled: call_sdk(\"setIosSwipeGestureEnabled\", [{ isEnabled: false }])\n setSecureScreen: call_sdk(\"setSecureScreen\", [{ enabled: true }])\n setScreenAwakeMode: call_sdk(\"setScreenAwakeMode\", [{ enabled: true }])\n getOperationalEnvironment: call_sdk(\"getOperationalEnvironment\", [])\n getPlatformOS: call_sdk(\"getPlatformOS\", [])\n getDeviceId: call_sdk(\"getDeviceId\", [])\n getLocale: call_sdk(\"getLocale\", [])\n getNetworkStatus: call_sdk(\"getNetworkStatus\", [])\n getSchemeUri: call_sdk(\"getSchemeUri\", [])\n requestReview: call_sdk(\"requestReview\", [])\n closeView: call_sdk(\"closeView\", [])",
141
301
  inputSchema: {
142
302
  type: "object",
143
303
  properties: {
@@ -152,7 +312,8 @@ new Set([
152
312
  }
153
313
  },
154
314
  required: ["name"]
155
- }
315
+ },
316
+ availableIn: "both"
156
317
  },
157
318
  {
158
319
  name: "AIT.getSdkCallHistory",
@@ -161,7 +322,8 @@ new Set([
161
322
  type: "object",
162
323
  properties: {},
163
324
  required: []
164
- }
325
+ },
326
+ availableIn: "both"
165
327
  },
166
328
  {
167
329
  name: "AIT.getMockState",
@@ -170,7 +332,8 @@ new Set([
170
332
  type: "object",
171
333
  properties: {},
172
334
  required: []
173
- }
335
+ },
336
+ availableIn: "both"
174
337
  },
175
338
  {
176
339
  name: "AIT.getOperationalEnvironment",
@@ -179,7 +342,8 @@ new Set([
179
342
  type: "object",
180
343
  properties: {},
181
344
  required: []
182
- }
345
+ },
346
+ availableIn: "both"
183
347
  }
184
348
  ].map((t) => t.name));
185
349
  `
@@ -200,17 +364,28 @@ new Set([
200
364
  };
201
365
  document.documentElement.removeChild(el);
202
366
  var sdkInsets = null;
367
+ var sdkInsetsSource = null;
203
368
  var sdkInsetsError = undefined;
204
369
  try {
205
370
  var sdk = window.__sdk;
371
+ var ait = window.__ait;
206
372
  if (sdk && sdk.SafeAreaInsets && typeof sdk.SafeAreaInsets.get === 'function') {
207
373
  sdkInsets = sdk.SafeAreaInsets.get();
374
+ sdkInsetsSource = 'window.__sdk';
208
375
  } else if (sdk && typeof sdk.getSafeAreaInsets === 'function') {
209
376
  sdkInsets = sdk.getSafeAreaInsets();
210
- } else if (!sdk) {
211
- sdkInsetsError = 'window.__sdk not available (non-dogfood bundle)';
212
- } else {
377
+ sdkInsetsSource = 'window.__sdk';
378
+ } else if (ait && ait.state && ait.state.safeAreaInsets &&
379
+ typeof ait.state.safeAreaInsets.top === 'number') {
380
+ var s = ait.state.safeAreaInsets;
381
+ sdkInsets = { top: s.top, bottom: s.bottom, left: s.left, right: s.right };
382
+ sdkInsetsSource = 'window.__ait';
383
+ } else if (!sdk && !ait) {
384
+ sdkInsetsError = 'neither window.__sdk (relay) nor window.__ait (mock) available';
385
+ } else if (sdk) {
213
386
  sdkInsetsError = 'neither SafeAreaInsets.get nor getSafeAreaInsets found on window.__sdk';
387
+ } else {
388
+ sdkInsetsError = 'window.__ait.state.safeAreaInsets is missing or malformed';
214
389
  }
215
390
  } catch(e) {
216
391
  sdkInsetsError = String(e && e.message || e);
@@ -227,6 +402,7 @@ new Set([
227
402
  var result = {
228
403
  cssEnv: cssEnv,
229
404
  sdkInsets: sdkInsets,
405
+ sdkInsetsSource: sdkInsetsSource,
230
406
  navBarHeight: navBarHeight,
231
407
  navBarHeightSource: navBarHeightSource,
232
408
  innerWidth: window.innerWidth,
@@ -297,7 +473,13 @@ function getOperationalEnvironment(source) {
297
473
  * }
298
474
  * }
299
475
  */
300
- /** Tool descriptors served by the dev-mode server. */
476
+ /**
477
+ * Tool descriptors served by the dev-mode server.
478
+ *
479
+ * All dev-mode tools are Tier C (both envs) per RFC #277 — the dev-mode server
480
+ * itself is the mock-side embodiment of those Tier C tools. `availableIn` is
481
+ * declared so the surface stays consistent with the debug-mode registry.
482
+ */
301
483
  const DEV_TOOL_DEFINITIONS = [
302
484
  {
303
485
  name: "AIT.getMockState",
@@ -306,7 +488,8 @@ const DEV_TOOL_DEFINITIONS = [
306
488
  type: "object",
307
489
  properties: {},
308
490
  required: []
309
- }
491
+ },
492
+ availableIn: "both"
310
493
  },
311
494
  {
312
495
  name: "AIT.getOperationalEnvironment",
@@ -315,7 +498,8 @@ const DEV_TOOL_DEFINITIONS = [
315
498
  type: "object",
316
499
  properties: {},
317
500
  required: []
318
- }
501
+ },
502
+ availableIn: "both"
319
503
  },
320
504
  {
321
505
  name: "AIT.getSdkCallHistory",
@@ -324,7 +508,8 @@ const DEV_TOOL_DEFINITIONS = [
324
508
  type: "object",
325
509
  properties: {},
326
510
  required: []
327
- }
511
+ },
512
+ availableIn: "both"
328
513
  },
329
514
  {
330
515
  name: "devtools_get_mock_state",
@@ -333,7 +518,8 @@ const DEV_TOOL_DEFINITIONS = [
333
518
  type: "object",
334
519
  properties: {},
335
520
  required: []
336
- }
521
+ },
522
+ availableIn: "both"
337
523
  }
338
524
  ];
339
525
  const DEV_TOOL_NAMES = new Set(DEV_TOOL_DEFINITIONS.map((t) => t.name));
@@ -343,7 +529,7 @@ function createDevServer(deps = {}) {
343
529
  const aitSource = deps.aitSource ?? new HttpAitSource({ stateEndpoint });
344
530
  const server = new Server({
345
531
  name: "ait-devtools",
346
- version: "0.1.40"
532
+ version: "0.1.43"
347
533
  }, { capabilities: { tools: {} } });
348
534
  server.setRequestHandler(ListToolsRequestSchema, () => ({ tools: DEV_TOOL_DEFINITIONS.map((tool) => ({ ...tool })) }));
349
535
  server.setRequestHandler(CallToolRequestSchema, async (request) => {