@ait-co/devtools 0.1.132 → 0.1.134

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.
Files changed (85) hide show
  1. package/dist/{attach-orchestrator-ca34r46y.js → attach-orchestrator-CE0S09YU.js} +110 -5
  2. package/dist/attach-orchestrator-CE0S09YU.js.map +1 -0
  3. package/dist/{attach-orchestrator-BiaYiNOr.js → attach-orchestrator-CMoDuG2A.js} +110 -5
  4. package/dist/attach-orchestrator-CMoDuG2A.js.map +1 -0
  5. package/dist/{cdp-connection-D7AYQck2.d.ts → cdp-connection-BYE9meXe.d.ts} +12 -2
  6. package/dist/{cdp-connection-D7AYQck2.d.ts.map → cdp-connection-BYE9meXe.d.ts.map} +1 -1
  7. package/dist/cell-BIdSQb9T.js +201 -0
  8. package/dist/cell-BIdSQb9T.js.map +1 -0
  9. package/dist/{cell-Cw4fVOl2.js → cell-D1y4shoV.js} +1 -21
  10. package/dist/cell-D1y4shoV.js.map +1 -0
  11. package/dist/cell-DHA578lX.js +200 -0
  12. package/dist/cell-DHA578lX.js.map +1 -0
  13. package/dist/{debug-server-Ch5p0ryv.js → debug-server-BcSBrajf.js} +19 -9
  14. package/dist/debug-server-BcSBrajf.js.map +1 -0
  15. package/dist/{debug-server-DoWAtTNj.js → debug-server-D9SmprUI.js} +7 -8
  16. package/dist/{debug-server-DoWAtTNj.js.map → debug-server-D9SmprUI.js.map} +1 -1
  17. package/dist/{debug-server-BBUzxZSf.js → debug-server-DnNCoNiR.js} +7 -7
  18. package/dist/{debug-server-BBUzxZSf.js.map → debug-server-DnNCoNiR.js.map} +1 -1
  19. package/dist/mcp/cli.js +149 -16
  20. package/dist/mcp/cli.js.map +1 -1
  21. package/dist/mcp/server.js +1 -1
  22. package/dist/panel/index.js +1 -1
  23. package/dist/{pool-BtLh7U1y.d.ts → pool-C6TgrcyW.d.ts} +3 -3
  24. package/dist/{pool-BtLh7U1y.d.ts.map → pool-C6TgrcyW.d.ts.map} +1 -1
  25. package/dist/{qr-http-server-KB147M-S.js → qr-http-server-C_DTp9WU.js} +1 -1
  26. package/dist/{qr-http-server-KB147M-S.js.map → qr-http-server-C_DTp9WU.js.map} +1 -1
  27. package/dist/{relay-factory-cNgPfrWg.js → relay-factory-CsVO9o25.js} +6 -6
  28. package/dist/{relay-factory-cNgPfrWg.js.map → relay-factory-CsVO9o25.js.map} +1 -1
  29. package/dist/{relay-secret-store-CFc9n0OA.js → relay-secret-store-CLEGyHou.js} +2 -2
  30. package/dist/{relay-secret-store-CFc9n0OA.js.map → relay-secret-store-CLEGyHou.js.map} +1 -1
  31. package/dist/{relay-secret-store-DzxDsK6S.js → relay-secret-store-DGduVJhs.js} +2 -2
  32. package/dist/{relay-secret-store-DzxDsK6S.js.map → relay-secret-store-DGduVJhs.js.map} +1 -1
  33. package/dist/{relay-url-store-D3rY-GJJ.js → relay-url-store-B0X8TsGr.js} +2 -2
  34. package/dist/{relay-url-store-D3rY-GJJ.js.map → relay-url-store-B0X8TsGr.js.map} +1 -1
  35. package/dist/{relay-url-store-DGQ-HPQC.js → relay-url-store-CKW8RQzf.js} +2 -2
  36. package/dist/{relay-url-store-DGQ-HPQC.js.map → relay-url-store-CKW8RQzf.js.map} +1 -1
  37. package/dist/{relay-worker-BMSnlyls.d.ts → relay-worker-Dw3aIzIK.d.ts} +15 -3
  38. package/dist/relay-worker-Dw3aIzIK.d.ts.map +1 -0
  39. package/dist/{relay-worker-l34xNuci.js → relay-worker-UK0nBfDX.js} +25 -11
  40. package/dist/relay-worker-UK0nBfDX.js.map +1 -0
  41. package/dist/rolldown-runtime-DGkTqVfb.js +15 -0
  42. package/dist/rolldown-runtime-DUslC3ob.js +14 -0
  43. package/dist/{runtime-9xhN9pr8.d.ts → runtime-DfHHZms2.d.ts} +34 -5
  44. package/dist/runtime-DfHHZms2.d.ts.map +1 -0
  45. package/dist/test-runner/bin.js +47 -112
  46. package/dist/test-runner/bin.js.map +1 -1
  47. package/dist/test-runner/config.d.ts +1 -1
  48. package/dist/test-runner/config.js +1 -1
  49. package/dist/test-runner/pool.d.ts +1 -1
  50. package/dist/test-runner/pool.js +1 -1
  51. package/dist/test-runner/relay-factory.d.ts +12 -2
  52. package/dist/test-runner/relay-factory.d.ts.map +1 -1
  53. package/dist/test-runner/relay-factory.js +3 -3
  54. package/dist/test-runner/relay-worker.d.ts +1 -1
  55. package/dist/test-runner/relay-worker.js +1 -1
  56. package/dist/test-runner/report.d.ts +11 -2
  57. package/dist/test-runner/report.d.ts.map +1 -1
  58. package/dist/test-runner/report.js +1 -0
  59. package/dist/test-runner/report.js.map +1 -1
  60. package/dist/test-runner/rpc.d.ts +8 -5
  61. package/dist/test-runner/rpc.d.ts.map +1 -1
  62. package/dist/test-runner/rpc.js +15 -4
  63. package/dist/test-runner/rpc.js.map +1 -1
  64. package/dist/test-runner/runtime.d.ts +2 -2
  65. package/dist/test-runner/runtime.js +30 -4
  66. package/dist/test-runner/runtime.js.map +1 -1
  67. package/dist/test-runner/task-graph.d.ts +1 -1
  68. package/dist/{totp-DvOYkYim.js → totp-CZLLKfOC.js} +2 -14
  69. package/dist/{totp-DvOYkYim.js.map → totp-CZLLKfOC.js.map} +1 -1
  70. package/dist/totp-DAxys-r0.js +199 -0
  71. package/dist/totp-DAxys-r0.js.map +1 -0
  72. package/package.json +1 -1
  73. package/dist/attach-orchestrator-BiaYiNOr.js.map +0 -1
  74. package/dist/attach-orchestrator-ca34r46y.js.map +0 -1
  75. package/dist/cell-Bi8MAPA8.js +0 -88
  76. package/dist/cell-Bi8MAPA8.js.map +0 -1
  77. package/dist/cell-Cw4fVOl2.js.map +0 -1
  78. package/dist/cell-rr6gL9AT.js +0 -89
  79. package/dist/cell-rr6gL9AT.js.map +0 -1
  80. package/dist/debug-server-Ch5p0ryv.js.map +0 -1
  81. package/dist/log-CUik_tHp.js +0 -95
  82. package/dist/log-CUik_tHp.js.map +0 -1
  83. package/dist/relay-worker-BMSnlyls.d.ts.map +0 -1
  84. package/dist/relay-worker-l34xNuci.js.map +0 -1
  85. package/dist/runtime-9xhN9pr8.d.ts.map +0 -1
package/dist/mcp/cli.js CHANGED
@@ -2024,7 +2024,7 @@ async function readMcpSdkVersion() {
2024
2024
  * some test environments that skip the build step).
2025
2025
  */
2026
2026
  function readDevtoolsVersion() {
2027
- return "0.1.132";
2027
+ return "0.1.134";
2028
2028
  }
2029
2029
  /**
2030
2030
  * Derives the next recommended action from a completed diagnostics snapshot.
@@ -2932,6 +2932,110 @@ function buildIndicatorExpression(opts) {
2932
2932
  * Node-only. react-free. CdpConnection only.
2933
2933
  */
2934
2934
  /**
2935
+ * `__AIT_PERMS__` key → SDK function name whose `.getPermission()` is probed
2936
+ * (devtools#739). This is the exact contract sdk-example#265 consumes — do
2937
+ * not rename keys without a coordinated sdk-example update.
2938
+ *
2939
+ * Each SDK function is reached via `window.__sdk` — the SAME page-global
2940
+ * bridge `src/in-app/auto.ts` installs for `call_sdk`/`__sdkCall` (see
2941
+ * `src/test-runner/bundle.ts`'s `sdkRedirectPlugin`, which redirects bundled
2942
+ * `@apps-in-toss/web-framework` imports to this same object at runtime). The
2943
+ * test-runner bundle owns no independent SDK import — `window.__sdk` is a
2944
+ * page global regardless of whether a bundle has been injected yet, so this
2945
+ * preflight runs standalone via `injectGlobals`'s `Runtime.evaluate`
2946
+ * mechanism BEFORE the first bundle, rather than being prepended into
2947
+ * `rpc.ts#buildRunTestsExpression`. (Design choice documented in PR #739 —
2948
+ * bundle-prepend was the fallback plan if the SDK were only reachable from
2949
+ * inside bundle scope, which reality ruled out.)
2950
+ */
2951
+ const PERMISSION_PROBE_MAP = {
2952
+ clipboardRead: "getClipboardText",
2953
+ clipboardWrite: "setClipboardText",
2954
+ album: "fetchAlbumPhotos",
2955
+ camera: "openCamera",
2956
+ contacts: "fetchContacts",
2957
+ location: "getCurrentLocation"
2958
+ };
2959
+ /** Non-fatal bound for the permission preflight `Runtime.evaluate` round-trip. */
2960
+ const PERMISSION_PREFLIGHT_TIMEOUT_MS = 1e4;
2961
+ /**
2962
+ * Builds the `Runtime.evaluate` expression for the permission-state preflight
2963
+ * (devtools#739). Evaluated ONCE per relay session, before the first test
2964
+ * bundle is injected (see `relay-worker.ts#runTestFilesOverRelay`).
2965
+ *
2966
+ * For each entry in {@link PERMISSION_PROBE_MAP}, probes
2967
+ * `window.__sdk.<fn>.getPermission()` — a NON-blocking query (never
2968
+ * `openPermissionDialog`/`requestPermission`, which open native UI) — and
2969
+ * assigns the resolved `'allowed'|'denied'|'notDetermined'` status to
2970
+ * `globalThis.__AIT_PERMS__[<key>]`. A probe that is absent, throws, or
2971
+ * rejects resolves to `'unavailable'` — this expression never throws to its
2972
+ * caller, and a single slow/broken permission must not fail the others (each
2973
+ * probe is awaited independently, not short-circuited).
2974
+ *
2975
+ * Tests (sdk-example#265) read `globalThis.__AIT_PERMS__` to branch
2976
+ * deterministically per permission state instead of blanket outcome-branching.
2977
+ *
2978
+ * Returns a JSON-serialised string (the same double-serialisation pattern
2979
+ * `rpc.ts#buildRunTestsExpression` uses) rather than relying on CDP
2980
+ * `returnByValue` structural fidelity for a plain object across the Chii
2981
+ * relay — the Node side re-parses via `JSON.parse`.
2982
+ *
2983
+ * Pure function — no I/O, no CDP call. Callers pass the returned string to
2984
+ * `Runtime.evaluate`.
2985
+ */
2986
+ function buildPermissionPreflightExpression() {
2987
+ return `(async () => { const probe = async (fnName) => { try { const fn = globalThis.__sdk && globalThis.__sdk[fnName]; if (!fn || typeof fn.getPermission !== 'function') return 'unavailable'; const status = await fn.getPermission(); if (status === 'allowed' || status === 'denied' || status === 'notDetermined') return status; return 'unavailable'; } catch (e) { return 'unavailable'; } }; const result = {};${Object.entries(PERMISSION_PROBE_MAP).map(([key, fnName]) => ` result[${JSON.stringify(key)}] = await probe(${JSON.stringify(fnName)});`).join("\n")}\n globalThis.__AIT_PERMS__ = result; return JSON.stringify(result);})()`;
2988
+ }
2989
+ /**
2990
+ * Runs the permission-state preflight (devtools#739) via `Runtime.evaluate`
2991
+ * and returns the collected `__AIT_PERMS__` map, or `undefined` when the
2992
+ * preflight itself failed or timed out.
2993
+ *
2994
+ * NON-FATAL by design: any failure (CDP exception, timeout, page-side throw)
2995
+ * is caught here, logged as ONE stderr line, and swallowed — the whole test
2996
+ * run must proceed even when the preflight cannot complete (e.g. `window.__sdk`
2997
+ * not yet installed, or a page navigation mid-attach). Callers that want the
2998
+ * result for report provenance (`RelayRunReport.preflight`) get `undefined`
2999
+ * in that case, which downstream code treats the same as "not run".
3000
+ *
3001
+ * SECRET-HANDLING: no relay/wss/secret values are read or logged; only
3002
+ * permission-state strings cross this boundary.
3003
+ *
3004
+ * @param conn - The live CDP connection (relay-attached page).
3005
+ * @param timeoutMs - Round-trip bound. Defaults to {@link PERMISSION_PREFLIGHT_TIMEOUT_MS}.
3006
+ */
3007
+ async function runPermissionPreflight(conn, timeoutMs = PERMISSION_PREFLIGHT_TIMEOUT_MS) {
3008
+ const TIMEOUT_SENTINEL = Symbol("permission-preflight-timeout");
3009
+ const timeoutPromise = new Promise((resolve) => setTimeout(() => resolve(TIMEOUT_SENTINEL), timeoutMs));
3010
+ try {
3011
+ const evalPromise = conn.send("Runtime.evaluate", {
3012
+ expression: buildPermissionPreflightExpression(),
3013
+ returnByValue: true,
3014
+ awaitPromise: true
3015
+ });
3016
+ const raceResult = await Promise.race([evalPromise.then((v) => ({
3017
+ tag: "eval",
3018
+ v
3019
+ })), timeoutPromise.then(() => ({ tag: "timeout" }))]);
3020
+ if (raceResult.tag === "timeout") {
3021
+ process.stderr.write(`test-runner: permission preflight timed out after ${timeoutMs}ms — proceeding with __AIT_PERMS__ unset\n`);
3022
+ return;
3023
+ }
3024
+ if (raceResult.v.exceptionDetails) {
3025
+ process.stderr.write("test-runner: permission preflight threw — proceeding with __AIT_PERMS__ unset\n");
3026
+ return;
3027
+ }
3028
+ const rawValue = raceResult.v.result.value;
3029
+ if (typeof rawValue !== "string") return void 0;
3030
+ const parsed = JSON.parse(rawValue);
3031
+ if (typeof parsed !== "object" || parsed === null) return void 0;
3032
+ return parsed;
3033
+ } catch (e) {
3034
+ process.stderr.write(`test-runner: permission preflight failed (${e instanceof Error ? e.message : String(e)}) — proceeding with __AIT_PERMS__ unset\n`);
3035
+ return;
3036
+ }
3037
+ }
3038
+ /**
2935
3039
  * Injects each key of `globals` into `globalThis` in the page via a single
2936
3040
  * `Runtime.evaluate` call. Must be called BEFORE the first `bundleTestFile`
2937
3041
  * inject — the cell is session-global and applies to all subsequent files.
@@ -3409,9 +3513,13 @@ var ChiiCdpConnection = class {
3409
3513
  /**
3410
3514
  * Issue a CDP command and resolve with its result (Phase 2). Rejects on a CDP
3411
3515
  * error frame or when no websocket is open (no page attached yet).
3516
+ *
3517
+ * @param opts.timeoutMs - Per-call override for this connection's command
3518
+ * watchdog (devtools#747) — see the `CdpConnection.send` docblock for the
3519
+ * contract callers racing their own longer timeout must follow.
3412
3520
  */
3413
- send(method, params) {
3414
- return this.sendCommand(method, params ?? {});
3521
+ send(method, params, opts) {
3522
+ return this.sendCommand(method, params ?? {}, opts);
3415
3523
  }
3416
3524
  /**
3417
3525
  * Issue an arbitrary request→response command over the relay and resolve with
@@ -3422,16 +3530,22 @@ var ChiiCdpConnection = class {
3422
3530
  * auto-reconnect). Caller should re-run `list_pages` or `enableDomains` to
3423
3531
  * reattach.
3424
3532
  *
3425
- * Times out after `commandTimeoutMs` (default 30s, env
3426
- * `AIT_CDP_COMMAND_TIMEOUT_MS`). On timeout the pending entry is cleaned up
3427
- * and the promise rejects with a descriptive Korean error.
3533
+ * Times out after `opts.timeoutMs` when given, else `commandTimeoutMs`
3534
+ * (default 30s, env `AIT_CDP_COMMAND_TIMEOUT_MS`) see devtools#747: the
3535
+ * default 30s watchdog used to undercut the test-runner's own longer
3536
+ * file-evaluate race no matter what `--timeout` the caller asked for. On
3537
+ * timeout the pending entry is cleaned up and the promise rejects with a
3538
+ * descriptive Korean error. `Number.isFinite` guards against a non-finite
3539
+ * override (e.g. `Infinity`, mirroring `waitForFirstTarget`'s convention)
3540
+ * so an intentional "no watchdog" override doesn't get clamped by
3541
+ * `setTimeout`.
3428
3542
  */
3429
- sendCommand(method, params = {}) {
3543
+ sendCommand(method, params = {}, opts) {
3430
3544
  if (this.connectionState === "disconnected") return Promise.reject(/* @__PURE__ */ new Error(`relay에 연결되어 있지 않습니다 (${method}). list_pages로 attach 상태를 확인하고 enableDomains()로 재연결하세요.`));
3431
3545
  if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return Promise.reject(/* @__PURE__ */ new Error("No mini-app page attached to the Chii relay yet. Call enableDomains() first."));
3432
3546
  const id = this.nextCommandId++;
3433
3547
  const ws = this.ws;
3434
- const timeoutMs = this.commandTimeoutMs;
3548
+ const timeoutMs = opts?.timeoutMs !== void 0 && Number.isFinite(opts.timeoutMs) && opts.timeoutMs > 0 ? opts.timeoutMs : this.commandTimeoutMs;
3435
3549
  return new Promise((resolve, reject) => {
3436
3550
  const handle = setTimeout(() => {
3437
3551
  this.pending.delete(id);
@@ -4016,6 +4130,14 @@ function parseCaptureLines(raw) {
4016
4130
  /** Maximum milliseconds to wait for a single evaluate round-trip. */
4017
4131
  const DEFAULT_TIMEOUT_MS = 6e4;
4018
4132
  /**
4133
+ * Extra headroom (ms) added on top of the rpc-level `timeoutMs` when telling
4134
+ * the underlying `CdpConnection` its per-command watchdog budget (devtools#747).
4135
+ * The rpc-level race above is the authoritative file timeout — this margin
4136
+ * only ensures the connection's own (shorter-by-default) watchdog never fires
4137
+ * first and masks the rpc-level timeout error with a connection-level one.
4138
+ */
4139
+ const CONNECTION_TIMEOUT_MARGIN_MS = 5e3;
4140
+ /**
4019
4141
  * Wraps bundle code in a self-executing IIFE that:
4020
4142
  * 1. Evaluates the bundle (registering describe/it/test).
4021
4143
  * 2. Calls `__testBundle.runTestModule(...)` — the entry the runtime exports.
@@ -4062,12 +4184,15 @@ function parseRunTestsResult(rawValue) {
4062
4184
  * Injects `bundleCode` into the attached page and awaits test execution.
4063
4185
  *
4064
4186
  * Uses `Runtime.evaluate` with `awaitPromise: true` to wait for the
4065
- * async IIFE to settle. The 30-second CDP command timeout covers even
4066
- * long-running test suites; split into smaller files if you hit it.
4187
+ * async IIFE to settle. `timeoutMs` (default 60s) is the authoritative file
4188
+ * timeout this function races it against the evaluate call AND (devtools#747)
4189
+ * threads it down to the underlying `CdpConnection`'s own per-command watchdog
4190
+ * (plus a small margin) so that watchdog can never undercut this race. Split
4191
+ * into smaller files if you hit the timeout.
4067
4192
  *
4068
4193
  * @param connection - Active CDP connection (relay or local).
4069
4194
  * @param bundleCode - IIFE bundle string from `bundleTestFile`.
4070
- * @param timeoutMs - Override the default 30 s timeout.
4195
+ * @param timeoutMs - Override the default 60 s timeout.
4071
4196
  *
4072
4197
  * SECRET-HANDLING: `bundleCode` and the raw CDP result value are never logged.
4073
4198
  */
@@ -4079,7 +4204,7 @@ async function injectAndRunBundle(connection, bundleCode, timeoutMs = DEFAULT_TI
4079
4204
  expression,
4080
4205
  returnByValue: true,
4081
4206
  awaitPromise: true
4082
- });
4207
+ }, { timeoutMs: timeoutMs + CONNECTION_TIMEOUT_MARGIN_MS });
4083
4208
  const raceResult = await Promise.race([evalPromise.then((v) => ({
4084
4209
  tag: "eval",
4085
4210
  v
@@ -4178,6 +4303,8 @@ async function runTestFilesOverRelay(connection, files, opts) {
4178
4303
  const manualFiles = opts?.manualFiles;
4179
4304
  const manualTotal = manualFiles?.size ?? 0;
4180
4305
  let manualIndex = 0;
4306
+ let preflightPermissions;
4307
+ if (files.length > 0) preflightPermissions = await runPermissionPreflight(connection);
4181
4308
  try {
4182
4309
  for (const file of files) {
4183
4310
  if (pendingReconnectCheck) {
@@ -4280,7 +4407,8 @@ async function runTestFilesOverRelay(connection, files, opts) {
4280
4407
  duration: Date.now() - wallStart,
4281
4408
  files: fileResults,
4282
4409
  totals,
4283
- captures
4410
+ captures,
4411
+ ...preflightPermissions ? { preflight: { permissions: preflightPermissions } } : {}
4284
4412
  };
4285
4413
  }
4286
4414
  /**
@@ -5137,8 +5265,13 @@ var LocalCdpConnection = class {
5137
5265
  /**
5138
5266
  * Issue a CDP command and resolve with its typed result. Rejects on a CDP
5139
5267
  * error frame or when no websocket is open.
5268
+ *
5269
+ * `opts.timeoutMs` is accepted for `CdpConnection` interface parity but
5270
+ * ignored — this connection has no per-command watchdog of its own
5271
+ * (devtools#747 only affects `ChiiCdpConnection`, which layers a
5272
+ * relay-command watchdog on top of the caller's own race).
5140
5273
  */
5141
- send(method, params) {
5274
+ send(method, params, _opts) {
5142
5275
  return this.sendCommand(method, params ?? {});
5143
5276
  }
5144
5277
  /**
@@ -7012,7 +7145,7 @@ function createDebugServer(deps) {
7012
7145
  };
7013
7146
  const server = new Server({
7014
7147
  name: "ait-debug",
7015
- version: "0.1.132"
7148
+ version: "0.1.134"
7016
7149
  }, { capabilities: { tools: { listChanged: true } } });
7017
7150
  server.setRequestHandler(ListToolsRequestSchema, () => {
7018
7151
  const conn = router.active;
@@ -8996,7 +9129,7 @@ function createDevServer(deps = {}) {
8996
9129
  const aitSource = deps.aitSource ?? new HttpAitSource({ stateEndpoint });
8997
9130
  const server = new Server({
8998
9131
  name: "ait-devtools",
8999
- version: "0.1.132"
9132
+ version: "0.1.134"
9000
9133
  }, { capabilities: { tools: {} } });
9001
9134
  server.setRequestHandler(ListToolsRequestSchema, () => ({ tools: DEV_TOOL_DEFINITIONS.map((tool) => ({ ...tool })) }));
9002
9135
  server.setRequestHandler(CallToolRequestSchema, async (request) => {