@ait-co/devtools 0.1.141 → 0.1.142
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/README.en.md +4 -4
- package/README.md +4 -4
- package/dist/{attach-orchestrator-BG8TGJOZ.js → attach-orchestrator-0F0m_UqQ.js} +71 -9
- package/dist/{attach-orchestrator-BG8TGJOZ.js.map → attach-orchestrator-0F0m_UqQ.js.map} +1 -1
- package/dist/{attach-orchestrator-6kz_ZdWL.js → attach-orchestrator-D65KxFy_.js} +71 -9
- package/dist/{attach-orchestrator-6kz_ZdWL.js.map → attach-orchestrator-D65KxFy_.js.map} +1 -1
- package/dist/{attach-orchestrator-BEiz3wAx.js → attach-orchestrator-DL3NQ9ca.js} +71 -9
- package/dist/{attach-orchestrator-BEiz3wAx.js.map → attach-orchestrator-DL3NQ9ca.js.map} +1 -1
- package/dist/{cell-BMlFh08P.js → cell-BaLvusOl.js} +2 -2
- package/dist/{cell-BMlFh08P.js.map → cell-BaLvusOl.js.map} +1 -1
- package/dist/{cell-Dtgtusog.js → cell-CBUS3-nT.js} +2 -2
- package/dist/{cell-Dtgtusog.js.map → cell-CBUS3-nT.js.map} +1 -1
- package/dist/{cell-KsRXFdDs.js → cell-EBKKpAAT.js} +2 -2
- package/dist/{cell-KsRXFdDs.js.map → cell-EBKKpAAT.js.map} +1 -1
- package/dist/{debug-server-DWat7d-9.js → debug-server-B3ABDrRI.js} +4 -4
- package/dist/{debug-server-DWat7d-9.js.map → debug-server-B3ABDrRI.js.map} +1 -1
- package/dist/{debug-server-6c22qSWa.js → debug-server-BWhwrVXa.js} +4 -4
- package/dist/{debug-server-6c22qSWa.js.map → debug-server-BWhwrVXa.js.map} +1 -1
- package/dist/{debug-server-BQHbaKPT.js → debug-server-CfQNxxGW.js} +6 -6
- package/dist/{debug-server-BQHbaKPT.js.map → debug-server-CfQNxxGW.js.map} +1 -1
- package/dist/in-app/auto.js +299 -3
- package/dist/in-app/auto.js.map +1 -1
- package/dist/in-app/index.d.ts +161 -14
- package/dist/in-app/index.d.ts.map +1 -1
- package/dist/in-app/index.js +300 -4
- package/dist/in-app/index.js.map +1 -1
- package/dist/mcp/cli.js +82 -16
- package/dist/mcp/cli.js.map +1 -1
- package/dist/mcp/server.js +1 -1
- package/dist/mock/index.d.ts +124 -89
- package/dist/mock/index.d.ts.map +1 -1
- package/dist/mock/index.js +21 -2
- package/dist/mock/index.js.map +1 -1
- package/dist/panel/index.js +7 -2
- package/dist/panel/index.js.map +1 -1
- package/dist/{qr-http-server-Cz1mA07b.cjs → qr-http-server--gl2-WKc.cjs} +9 -5
- package/dist/qr-http-server--gl2-WKc.cjs.map +1 -0
- package/dist/{qr-http-server-D4rGz8M7.js → qr-http-server-Bb7lMeqi.js} +9 -5
- package/dist/qr-http-server-Bb7lMeqi.js.map +1 -0
- package/dist/{qr-http-server-D1hpoyBF.js → qr-http-server-C_lqOrgc.js} +9 -5
- package/dist/qr-http-server-C_lqOrgc.js.map +1 -0
- package/dist/{qr-http-server-CTLdclg_.js → qr-http-server-CopuMbub.js} +9 -5
- package/dist/qr-http-server-CopuMbub.js.map +1 -0
- package/dist/{qr-http-server-D16Lq2ag.cjs → qr-http-server-D-Off6K1.cjs} +9 -5
- package/dist/qr-http-server-D-Off6K1.cjs.map +1 -0
- package/dist/{qr-http-server-DIjCV7h_.js → qr-http-server-DrbIVDjO.js} +9 -5
- package/dist/qr-http-server-DrbIVDjO.js.map +1 -0
- package/dist/qr-http-server-n1twN18z.js +1644 -0
- package/dist/qr-http-server-n1twN18z.js.map +1 -0
- package/dist/{relay-factory-C1X3G3WY.js → relay-factory-N9QobQxG.js} +6 -6
- package/dist/{relay-factory-C1X3G3WY.js.map → relay-factory-N9QobQxG.js.map} +1 -1
- package/dist/{relay-worker-BUXI0K0b.js → relay-worker-B5HKkGUY.js} +4 -4
- package/dist/{relay-worker-BUXI0K0b.js.map → relay-worker-B5HKkGUY.js.map} +1 -1
- package/dist/relay-worker-DcyboK43.d.ts.map +1 -1
- package/dist/test-runner/bin.js +8 -8
- package/dist/test-runner/bin.js.map +1 -1
- package/dist/test-runner/config.js +1 -1
- package/dist/test-runner/pool.js +1 -1
- package/dist/test-runner/relay-factory.js +5 -5
- package/dist/test-runner/relay-worker.js +1 -1
- package/dist/{tunnel-DjtSENJU.cjs → tunnel-BVSMXctM.cjs} +2 -2
- package/dist/{tunnel-DjtSENJU.cjs.map → tunnel-BVSMXctM.cjs.map} +1 -1
- package/dist/{tunnel-5eBncITa.js → tunnel-D7xkimBu.js} +2 -2
- package/dist/{tunnel-5eBncITa.js.map → tunnel-D7xkimBu.js.map} +1 -1
- package/dist/unplugin/index.cjs +1 -1
- package/dist/unplugin/index.js +1 -1
- package/dist/unplugin/tunnel.cjs +1 -1
- package/dist/unplugin/tunnel.js +1 -1
- package/package.json +2 -2
- package/dist/qr-http-server-CTLdclg_.js.map +0 -1
- package/dist/qr-http-server-Cz1mA07b.cjs.map +0 -1
- package/dist/qr-http-server-D16Lq2ag.cjs.map +0 -1
- package/dist/qr-http-server-D1hpoyBF.js.map +0 -1
- package/dist/qr-http-server-D4rGz8M7.js.map +0 -1
- package/dist/qr-http-server-DIjCV7h_.js.map +0 -1
- package/dist/qr-http-server-wy3L7Yut.js +0 -1640
- package/dist/qr-http-server-wy3L7Yut.js.map +0 -1
package/dist/mcp/cli.js
CHANGED
|
@@ -2077,7 +2077,7 @@ async function readMcpSdkVersion() {
|
|
|
2077
2077
|
* some test environments that skip the build step).
|
|
2078
2078
|
*/
|
|
2079
2079
|
function readDevtoolsVersion() {
|
|
2080
|
-
return "0.1.
|
|
2080
|
+
return "0.1.142";
|
|
2081
2081
|
}
|
|
2082
2082
|
/**
|
|
2083
2083
|
* Derives the next recommended action from a completed diagnostics snapshot.
|
|
@@ -2793,7 +2793,7 @@ async function renderAndMaybeWait(deps, prep, waitForAttach, callTimeoutMs, conn
|
|
|
2793
2793
|
let totpIssuedAt = nowMs();
|
|
2794
2794
|
let reminted = 0;
|
|
2795
2795
|
const relayUrl = parts.wssUrl;
|
|
2796
|
-
const header = "This tool result is shown to the user directly — do NOT re-print the QR below in your reply (it wastes output tokens). Just tell the user to scan the QR in this output (Ctrl+O to expand if collapsed)
|
|
2796
|
+
const header = "This tool result is shown to the user directly — do NOT re-print the QR below in your reply (it wastes output tokens). Just tell the user to scan the QR in this output (Ctrl+O to expand if collapsed).\n\n테스트가 끝날 때까지 앱을 화면 앞에 유지하세요 — 백그라운드로 전환하면 디버그 세션이 끊어집니다.";
|
|
2797
2797
|
const warningPrefix = authorityWarning ? `⚠️ scheme_url 경고: ${authorityWarning}\n\n` : "";
|
|
2798
2798
|
const guiAvailable = canOpenBrowserFn();
|
|
2799
2799
|
/** Builds the totp object surfaced in results (fresh expiresAt + reminted). */
|
|
@@ -2919,9 +2919,35 @@ async function renderAndMaybeWait(deps, prep, waitForAttach, callTimeoutMs, conn
|
|
|
2919
2919
|
}, null, 2)}\n\n${qr}`);
|
|
2920
2920
|
}
|
|
2921
2921
|
/**
|
|
2922
|
+
* How long the disconnected badge stays on screen before it fades and removes
|
|
2923
|
+
* itself (#748). Long enough to read, short enough not to linger; a reconnect
|
|
2924
|
+
* within this window cancels the self-dismiss (transient tunnel blips do not
|
|
2925
|
+
* flash-remove the badge).
|
|
2926
|
+
*/
|
|
2927
|
+
const INDICATOR_SELF_DISMISS_MS = 5e3;
|
|
2928
|
+
/** Fade duration before the self-dismissed badge is detached from the DOM. */
|
|
2929
|
+
const INDICATOR_FADE_MS = 400;
|
|
2930
|
+
/**
|
|
2931
|
+
* Heartbeat / pending-call render tick (#749). 1 Hz — cheap enough to be
|
|
2932
|
+
* invisible (a single text write per second, no layout thrash) while making a
|
|
2933
|
+
* JS main-thread wedge obvious: the compositor-driven pulse dot keeps animating
|
|
2934
|
+
* but this JS-driven `♥<beats>` token freezes. Pending-call elapsed times are
|
|
2935
|
+
* recomputed on the same tick so they advance without any bridge event.
|
|
2936
|
+
*/
|
|
2937
|
+
const INDICATOR_HEARTBEAT_MS = 1e3;
|
|
2938
|
+
/**
|
|
2939
|
+
* Display-side staleness guard (#749): the badge skips rendering a pending call
|
|
2940
|
+
* older than this. A safety net independent of the in-app observer's own prune
|
|
2941
|
+
* (`bridge-observer.ts` MAX_PENDING_AGE_MS) — kept local so the daemon-graph
|
|
2942
|
+
* expression builder never imports the in-app module (install-graph invariant).
|
|
2943
|
+
* Generous enough that a genuinely slow native call still shows while plausibly
|
|
2944
|
+
* in flight.
|
|
2945
|
+
*/
|
|
2946
|
+
const INDICATOR_PENDING_STALE_MS = 12e4;
|
|
2947
|
+
/**
|
|
2922
2948
|
* Builds a self-contained IIFE DOM expression that renders a LIVE
|
|
2923
|
-
* "Debugger Connected" /
|
|
2924
|
-
*
|
|
2949
|
+
* "Debugger Connected" / disconnected badge on the bottom-left of the phone
|
|
2950
|
+
* screen (#730), with a graceful self-dismiss on disconnect (#748).
|
|
2925
2951
|
*
|
|
2926
2952
|
* **Pure function** — returns a JS expression string; does NOT inject it.
|
|
2927
2953
|
* Injection is performed by {@link injectDebugIndicator} in `cell.ts`.
|
|
@@ -2938,7 +2964,18 @@ async function renderAndMaybeWait(deps, prep, waitForAttach, callTimeoutMs, conn
|
|
|
2938
2964
|
* 3. A `pointerdown` listener dismisses (hides) the badge on tap — dismiss
|
|
2939
2965
|
* is NON-terminal: a later state transition un-dismisses it, so a
|
|
2940
2966
|
* genuine disconnect after a dismissed tap is still visible.
|
|
2941
|
-
* 4.
|
|
2967
|
+
* 4. **Graceful self-dismiss (#748)** — the disconnected badge is NON-BLOCKING
|
|
2968
|
+
* (`pointer-events:none` the moment it flips to disconnected, so it can
|
|
2969
|
+
* never absorb a tap) and SELF-DISMISSING (it fades and detaches itself
|
|
2970
|
+
* after {@link INDICATOR_SELF_DISMISS_MS}). This is why a run that ends
|
|
2971
|
+
* with `close()` injecting `{ state: 'disconnected' }` no longer leaves a
|
|
2972
|
+
* permanent grey "Debugger Disconnected" element on the phone. A reconnect
|
|
2973
|
+
* (`setState(c, 'attached')`) cancels the pending self-dismiss and
|
|
2974
|
+
* re-mounts the badge if it had already detached — transient tunnel blips
|
|
2975
|
+
* do not flash-remove it, and a genuine re-attach restores it. The
|
|
2976
|
+
* controller object is retained across dismiss (never `delete`d), so a
|
|
2977
|
+
* later re-injection reuses it and never double-wraps `window.WebSocket`.
|
|
2978
|
+
* 5. Observes relay-socket lifecycle WITHOUT opening any new connection:
|
|
2942
2979
|
* - Preferred path: if the in-app module (`src/in-app/attach.ts`) has
|
|
2943
2980
|
* already installed its relay-WS observer (`window.__ait_relay_ws_observed`),
|
|
2944
2981
|
* subscribe to the `ait:relay-ws-state` CustomEvent it broadcasts.
|
|
@@ -2946,23 +2983,48 @@ async function renderAndMaybeWait(deps, prep, waitForAttach, callTimeoutMs, conn
|
|
|
2946
2983
|
* by PATHNAME SHAPE only (`/target/`) — never by host/wss value — so a
|
|
2947
2984
|
* bare CDP-injected badge (no in-app bundle) still reacts to the
|
|
2948
2985
|
* chii target socket's own open/close lifecycle.
|
|
2986
|
+
* 6. **Freeze/spinner triage (#749)** — renders three debug-only signals so a
|
|
2987
|
+
* real-device spinner is attributable at a glance (run7):
|
|
2988
|
+
* - **Main-thread heartbeat**: a compositor-driven pulse dot
|
|
2989
|
+
* (`Element.animate`, keeps running during JS jank) PLUS a JS-driven
|
|
2990
|
+
* `♥<beats>` token incremented by a 1 Hz `setInterval`. `CSS pulse alive
|
|
2991
|
+
* + ♥ frozen = JS main-thread wedge`.
|
|
2992
|
+
* - **Pending bridge calls**: in-flight native calls (API name + live
|
|
2993
|
+
* elapsed) read from `window.__ait_bridge` (published by the in-app
|
|
2994
|
+
* bridge observer, `src/in-app/bridge-observer.ts`). `⏳ present =
|
|
2995
|
+
* native/Toss-app spinner`.
|
|
2996
|
+
* - **Last SDK call stamp**: the most recent call's API name + wall-clock.
|
|
2997
|
+
* `no ⏳ + heartbeat healthy = the miniapp's own UI`.
|
|
2998
|
+
* The `title` tooltip states this mapping. When no in-app observer is
|
|
2999
|
+
* present (env 2 mock / no bridge) the pending/last lines are simply empty
|
|
3000
|
+
* — the heartbeat still renders. The 1 Hz interval is stored on the
|
|
3001
|
+
* controller (`c.hb`) and stopped by `c.stop()` (called from
|
|
3002
|
+
* `detachDebugSurface`) and by the self-dismiss removal, so no timer leaks
|
|
3003
|
+
* past detach (#748 lifecycle).
|
|
2949
3004
|
*
|
|
2950
3005
|
* The expression intentionally contains NO relay URLs, wss addresses, TOTP
|
|
2951
|
-
* codes, or any other secrets.
|
|
3006
|
+
* codes, or any other secrets. `window.__ait_bridge` holds API NAMES + timings
|
|
3007
|
+
* only (never call arguments/results — see `bridge-observer.ts`
|
|
3008
|
+
* SECRET-HANDLING). It is pure DOM UI text + enum/name state only.
|
|
2952
3009
|
*
|
|
2953
3010
|
* SECRET-HANDLING: this expression contains no secrets, relay URLs, wss
|
|
2954
3011
|
* addresses, or TOTP codes whatsoever — DOM label text + a structural
|
|
2955
3012
|
* pathname match (`/target/`) only.
|
|
2956
3013
|
*
|
|
2957
3014
|
* @param opts.label - Attached-state badge text (default: `'Debugger Connected'`).
|
|
2958
|
-
* @param opts.disconnectedLabel - Disconnected-state badge text
|
|
3015
|
+
* @param opts.disconnectedLabel - Disconnected-state badge text. Default is the
|
|
3016
|
+
* Korean notice `'디버거 연결 끊김'` (ko-primary in-app string convention) —
|
|
3017
|
+
* shown briefly then self-dismissed.
|
|
2959
3018
|
* @param opts.state - Initial/forced state for THIS injection call (default: `'attached'`).
|
|
2960
3019
|
* @returns A JS expression string suitable for `Runtime.evaluate`.
|
|
2961
3020
|
*/
|
|
2962
3021
|
function buildIndicatorExpression(opts) {
|
|
2963
3022
|
const label = opts?.label ?? "Debugger Connected";
|
|
2964
|
-
const disconnectedLabel = opts?.disconnectedLabel ?? "
|
|
2965
|
-
|
|
3023
|
+
const disconnectedLabel = opts?.disconnectedLabel ?? "디버거 연결 끊김";
|
|
3024
|
+
const safeLabel = JSON.stringify(label);
|
|
3025
|
+
const safeDisconnectedLabel = JSON.stringify(disconnectedLabel);
|
|
3026
|
+
const safeState = JSON.stringify(opts?.state ?? "attached");
|
|
3027
|
+
return `(() => {var W = window;function pad2(n) { return (n < 10 ? '0' : '') + n; }function clock(ms) { var d = new Date(ms); return pad2(d.getHours()) + ':' + pad2(d.getMinutes()) + ':' + pad2(d.getSeconds()); }function renderDetail(c) {c.beatEl.textContent = ' \\u2665' + c.beats;var b = W.__ait_bridge;var now = Date.now();var lines = [];if (b) {if (b.last) { lines.push('last: ' + b.last.method + ' ' + clock(b.last.at)); }var p = b.pending || {};var ids = Object.keys(p);var shown = 0;for (var i = 0; i < ids.length; i++) {var e = p[ids[i]];if (!e || now - e.startedAt > ${INDICATOR_PENDING_STALE_MS}) { continue; }if (shown < 3) { lines.push('\\u23f3 ' + e.method + ' ' + Math.max(0, Math.round((now - e.startedAt) / 1000)) + 's'); }shown++;}if (shown > 3) { lines.push('+' + (shown - 3) + ' more'); }}c.detailEl.textContent = lines.join('\\n');}function mount(c) { if (!c.el.isConnected && document.body) { document.body.appendChild(c.el); } }function render(c) {if (c.removed) { c.el.style.display = 'none'; return; }mount(c);if (c.dismissed) { c.el.style.display = 'none'; return; }c.el.style.display = 'block';c.el.style.opacity = '1';var up = c.state !== 'disconnected';c.el.style.background = up ? '#e5484d' : '#8a8f98';c.el.style.pointerEvents = up ? 'auto' : 'none';c.labelEl.textContent = up ? ${safeLabel} : ${safeDisconnectedLabel};c.dotEl.style.display = up ? 'inline-block' : 'none';c.beatEl.style.display = up ? 'inline' : 'none';c.detailEl.style.display = up ? 'block' : 'none';if (up) { renderDetail(c); } else { c.beatEl.textContent = ''; c.detailEl.textContent = ''; }}function clearTimers(c) { if (c.t1) { clearTimeout(c.t1); c.t1 = 0; } if (c.t2) { clearTimeout(c.t2); c.t2 = 0; } }function setState(c, next) {clearTimers(c);c.state = next; c.dismissed = false; c.removed = false;render(c);if (next === 'disconnected') {c.t1 = setTimeout(function () {try { c.el.style.transition = 'opacity ${INDICATOR_FADE_MS}ms ease'; c.el.style.opacity = '0'; } catch (_) {}c.t2 = setTimeout(function () { c.removed = true; if (c.hb) { clearInterval(c.hb); c.hb = 0; } if (c.el.parentNode) { c.el.parentNode.removeChild(c.el); } }, ${INDICATOR_FADE_MS});}, ${INDICATOR_SELF_DISMISS_MS});}}var c = W.__ait_indicator;if (!c) {var el = document.createElement('div');el.id = '__ait_debug_indicator';try { el.title = ${JSON.stringify("⏳ 네이티브 호출 대기 = 토스앱 스피너 · ♥ 정지 = JS 멈춤 · ⏳ 없고 ♥ 정상 = 앱 UI")}; } catch (_) {}el.style.cssText = ['position:fixed','left:max(12px,calc(env(safe-area-inset-left,0px) + 8px))','bottom:max(12px,calc(env(safe-area-inset-bottom,0px) + 8px))','z-index:2147483647','color:#fff','font:bold 11px/1.2 system-ui,sans-serif','padding:5px 9px','border-radius:6px','max-width:72vw','pointer-events:auto','user-select:none',].join(';');var dotEl = document.createElement('span');dotEl.style.cssText = 'display:inline-block;width:6px;height:6px;border-radius:50%;background:#fff;margin-right:5px;vertical-align:middle';var labelEl = document.createElement('span');labelEl.id = '__ait_indicator_label';var beatEl = document.createElement('span');beatEl.style.cssText = 'font-weight:normal;opacity:0.85;margin-left:6px';var detailEl = document.createElement('div');detailEl.style.cssText = 'font-weight:normal;font-size:10px;line-height:1.35;margin-top:3px;white-space:pre-line;opacity:0.95';el.appendChild(dotEl); el.appendChild(labelEl); el.appendChild(beatEl); el.appendChild(detailEl);document.body.appendChild(el);c = { el: el, dotEl: dotEl, labelEl: labelEl, beatEl: beatEl, detailEl: detailEl, state: 'attached', dismissed: false, removed: false, beats: 0, t1: 0, t2: 0, hb: 0 };try { dotEl.animate([{ opacity: 1 }, { opacity: 0.25 }, { opacity: 1 }], { duration: 1400, iterations: Infinity }); } catch (_) {}c.hb = (typeof setInterval !== 'undefined') ? setInterval(function () {if (c.removed || !c.el.isConnected) { if (c.hb) { clearInterval(c.hb); c.hb = 0; } return; }c.beats = (c.beats || 0) + 1;if (c.state !== 'disconnected' && !c.dismissed) { renderDetail(c); }}, ${INDICATOR_HEARTBEAT_MS}) : 0;c.stop = function () { clearTimers(c); if (c.hb) { clearInterval(c.hb); c.hb = 0; } };el.addEventListener('pointerdown', function () { c.dismissed = true; render(c); }, { passive: true });W.addEventListener('ait:bridge-call', function () { if (c.state !== 'disconnected' && !c.dismissed && !c.removed) { renderDetail(c); } });W.__ait_indicator = c;if (W.__ait_relay_ws_observed) {W.addEventListener('ait:relay-ws-state', function (e) {setState(c, e.detail && e.detail.state === 'open' ? 'attached' : 'disconnected');});} else {try {var Native = W.WebSocket;W.WebSocket = new Proxy(Native, {construct: function (t, a) {var ws = Reflect.construct(t, a);try {var u = new URL(String(a[0]), location.href);if (/\\/target\\//.test(u.pathname)) {ws.addEventListener('open', function () { setState(c, 'attached'); });ws.addEventListener('close', function () { setState(c, 'disconnected'); });ws.addEventListener('error', function () { setState(c, 'disconnected'); });}} catch (_) {}return ws;},});} catch (_) {}}}setState(c, ${safeState});})()`;
|
|
2966
3028
|
}
|
|
2967
3029
|
//#endregion
|
|
2968
3030
|
//#region src/test-runner/cell.ts
|
|
@@ -4585,7 +4647,7 @@ async function runTestFilesOverRelay(connection, files, opts) {
|
|
|
4585
4647
|
if (retryResult !== null) fileEntry = retryResult;
|
|
4586
4648
|
else fileEntry = {
|
|
4587
4649
|
file,
|
|
4588
|
-
result: { error: `${EVALUATE_TIMEOUT_MARKER} ${opts?.timeoutMs ?? 6e4}ms (after retry)` }
|
|
4650
|
+
result: { error: `${EVALUATE_TIMEOUT_MARKER} ${opts?.timeoutMs ?? 6e4}ms (after retry) — the device's app may have been backgrounded` }
|
|
4589
4651
|
};
|
|
4590
4652
|
}
|
|
4591
4653
|
} catch (e) {
|
|
@@ -5924,6 +5986,7 @@ const en = {
|
|
|
5924
5986
|
"attach.sandbox.step1": "Launch the launcher PWA icon on your home screen (if the Safari address bar is visible, it is not standalone).",
|
|
5925
5987
|
"attach.sandbox.step2": "Scan this QR code with <strong>\"Scan QR with camera\"</strong> inside the launcher.",
|
|
5926
5988
|
"attach.sandbox.step3": "The mini-app opens fullscreen and the debug session attaches automatically.",
|
|
5989
|
+
"attach.sandbox.step4": "<strong>Keep the app in the foreground until the test run finishes</strong> — backgrounding it will drop the debug session.",
|
|
5927
5990
|
"attach.sandbox.faq.notInstalled": "<strong>Launcher is not installed</strong> — open <code>devtools.aitc.dev/launcher/</code> once and add it to your home screen",
|
|
5928
5991
|
"attach.sandbox.faq.cameraApp": "<strong>Scanning with the camera app opens a Safari tab (bottom tab bar visible)</strong> — relaunch from the launcher icon and use the in-app scanner",
|
|
5929
5992
|
"attach.sandbox.faq.totp": "<strong>QR expired (TOTP — 30-second step, ±6 steps (~3 min) accepted)</strong> — scan a fresh QR code",
|
|
@@ -5932,6 +5995,7 @@ const en = {
|
|
|
5932
5995
|
"attach.intoss.step2": "Scan the QR code with your phone camera app.",
|
|
5933
5996
|
"attach.intoss.step3": "Tap <strong>\"Open in Toss\"</strong> when the popup appears.",
|
|
5934
5997
|
"attach.intoss.step4": "The mini-app opens and the debug session attaches automatically.",
|
|
5998
|
+
"attach.intoss.step5": "<strong>Keep the Toss app in the foreground until the test run finishes</strong> — backgrounding it will drop the debug session.",
|
|
5935
5999
|
"attach.intoss.faq.appNotOpen": "<strong>Toss app does not open</strong> — check app version; scan with the system camera app (not the Toss in-app QR reader)",
|
|
5936
6000
|
"attach.intoss.faq.prepare": "<strong>Mini-app stuck in PREPARE state</strong> — verify the deep-link has a <code>_deploymentId</code> parameter",
|
|
5937
6001
|
"attach.intoss.faq.chii": "<strong>Chii injection failure / console is empty</strong> — verify the mini-app bundle has an <code>in-app</code> debug import",
|
|
@@ -6167,6 +6231,7 @@ const tables = {
|
|
|
6167
6231
|
"attach.sandbox.step1": "홈 화면의 launcher PWA 아이콘으로 실행하세요 (Safari 주소창이 보이면 standalone이 아닙니다).",
|
|
6168
6232
|
"attach.sandbox.step2": "launcher 안의 <strong>\"QR 카메라로 스캔\"</strong>으로 이 QR 코드를 스캔하세요.",
|
|
6169
6233
|
"attach.sandbox.step3": "미니앱이 풀스크린으로 열리고 디버그 세션이 자동으로 attach됩니다.",
|
|
6234
|
+
"attach.sandbox.step4": "<strong>테스트가 끝날 때까지 앱을 화면 앞에 유지하세요</strong> — 백그라운드로 전환하면 디버그 세션이 끊어집니다.",
|
|
6170
6235
|
"attach.sandbox.faq.notInstalled": "<strong>launcher가 설치돼 있지 않은 경우</strong> — <code>devtools.aitc.dev/launcher/</code>를 한 번 열어 홈 화면에 추가하세요",
|
|
6171
6236
|
"attach.sandbox.faq.cameraApp": "<strong>카메라 앱으로 스캔하면 Safari 탭으로 열립니다 (하단 탭 바 노출)</strong> — launcher 아이콘으로 다시 실행해 인앱 스캔을 사용하세요",
|
|
6172
6237
|
"attach.sandbox.faq.totp": "<strong>QR이 만료된 경우 (TOTP — 코드 1개는 30초 창, 만료 후 ~3분(±6 step) 이내 소급 허용)</strong> — 새 QR을 다시 스캔하세요",
|
|
@@ -6175,6 +6240,7 @@ const tables = {
|
|
|
6175
6240
|
"attach.intoss.step2": "폰 카메라 앱으로 QR 코드를 스캔하세요.",
|
|
6176
6241
|
"attach.intoss.step3": "팝업이 뜨면 <strong>\"토스로 열기\"</strong>를 탭하세요.",
|
|
6177
6242
|
"attach.intoss.step4": "미니앱이 열리고 디버그 세션이 자동으로 attach됩니다.",
|
|
6243
|
+
"attach.intoss.step5": "<strong>테스트가 끝날 때까지 토스 앱을 화면 앞에 유지하세요</strong> — 백그라운드로 전환하면 디버그 세션이 끊어집니다.",
|
|
6178
6244
|
"attach.intoss.faq.appNotOpen": "<strong>토스 앱이 안 열리는 경우</strong> — 앱 버전 확인, 카메라 앱으로 스캔 (토스 앱 내 QR 리더 X)",
|
|
6179
6245
|
"attach.intoss.faq.prepare": "<strong>미니앱이 PREPARE 상태에서 멈추는 경우</strong> — deep-link에 <code>_deploymentId</code> 파라미터가 있는지 확인",
|
|
6180
6246
|
"attach.intoss.faq.chii": "<strong>Chii 주입 실패 / 콘솔이 비어 있는 경우</strong> — 미니앱 번들에 <code>in-app</code> debug import가 있는지 확인",
|
|
@@ -6377,7 +6443,7 @@ hr { border: none; border-top: 1px solid #21262d; width: 100%; margin: 0.5rem 0;
|
|
|
6377
6443
|
}
|
|
6378
6444
|
.inspector-link:hover { background: #388bfd; }
|
|
6379
6445
|
.inspector-hint { display: inline-block; margin-top: 0.5rem; font-size: 0.8rem; opacity: 0.45; }
|
|
6380
|
-
</style></head><body><h1>AIT 디버그 세션 — QR 스캔</h1>__MODE_LABEL____LANG_SWITCHER__<div id="attach-section"><img class="qr" src="__QR_DATA_URL__" alt="attach QR"/></div><section><h2>스캔 절차</h2><ol><li>홈 화면의 launcher PWA 아이콘으로 실행하세요 (Safari 주소창이 보이면 standalone이 아닙니다).</li><li>launcher 안의 <strong>"QR 카메라로 스캔"</strong>으로 이 QR 코드를 스캔하세요.</li><li>미니앱이 풀스크린으로 열리고 디버그 세션이 자동으로 attach됩니다.</li></ol></section><hr/><section><h2>진단 체크리스트</h2><ul><li><strong>launcher가 설치돼 있지 않은 경우</strong> — <code>devtools.aitc.dev/launcher/</code>를 한 번 열어 홈 화면에 추가하세요</li><li><strong>카메라 앱으로 스캔하면 Safari 탭으로 열립니다 (하단 탭 바 노출)</strong> — launcher 아이콘으로 다시 실행해 인앱 스캔을 사용하세요</li><li><strong>QR이 만료된 경우 (TOTP — 코드 1개는 30초 창, 만료 후 ~3분(±6 step) 이내 소급 허용)</strong> — 새 QR을 다시 스캔하세요</li><li><strong>Chii 주입 실패 / 콘솔이 비어 있는 경우</strong> — 미니앱 번들에 <code>in-app</code> debug import가 있는지 확인</li></ul></section><hr/><section id="url-section"><h2>URL (fallback)</h2><div class="url-row"><p class="url-box" id="url-box">__SAFE_ATTACH_URL__</p><button class="copy-btn" id="copy-btn" type="button" aria-label="복사">복사</button></div></section><hr/><section id="inspector-section"><h2>인스펙터</h2>__INSPECTOR_SECTION__</section></body></html>`;
|
|
6446
|
+
</style></head><body><h1>AIT 디버그 세션 — QR 스캔</h1>__MODE_LABEL____LANG_SWITCHER__<div id="attach-section"><img class="qr" src="__QR_DATA_URL__" alt="attach QR"/></div><section><h2>스캔 절차</h2><ol><li>홈 화면의 launcher PWA 아이콘으로 실행하세요 (Safari 주소창이 보이면 standalone이 아닙니다).</li><li>launcher 안의 <strong>"QR 카메라로 스캔"</strong>으로 이 QR 코드를 스캔하세요.</li><li>미니앱이 풀스크린으로 열리고 디버그 세션이 자동으로 attach됩니다.</li><li><strong>테스트가 끝날 때까지 앱을 화면 앞에 유지하세요</strong> — 백그라운드로 전환하면 디버그 세션이 끊어집니다.</li></ol></section><hr/><section><h2>진단 체크리스트</h2><ul><li><strong>launcher가 설치돼 있지 않은 경우</strong> — <code>devtools.aitc.dev/launcher/</code>를 한 번 열어 홈 화면에 추가하세요</li><li><strong>카메라 앱으로 스캔하면 Safari 탭으로 열립니다 (하단 탭 바 노출)</strong> — launcher 아이콘으로 다시 실행해 인앱 스캔을 사용하세요</li><li><strong>QR이 만료된 경우 (TOTP — 코드 1개는 30초 창, 만료 후 ~3분(±6 step) 이내 소급 허용)</strong> — 새 QR을 다시 스캔하세요</li><li><strong>Chii 주입 실패 / 콘솔이 비어 있는 경우</strong> — 미니앱 번들에 <code>in-app</code> debug import가 있는지 확인</li></ul></section><hr/><section id="url-section"><h2>URL (fallback)</h2><div class="url-row"><p class="url-box" id="url-box">__SAFE_ATTACH_URL__</p><button class="copy-btn" id="copy-btn" type="button" aria-label="복사">복사</button></div></section><hr/><section id="inspector-section"><h2>인스펙터</h2>__INSPECTOR_SECTION__</section></body></html>`;
|
|
6381
6447
|
const attachChromeHtmlKoIntoss = `<!DOCTYPE html>
|
|
6382
6448
|
<html lang="ko"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="preload" as="image" href="__QR_DATA_URL__"/><title>AIT 디버그 세션 — QR 스캔</title><style>
|
|
6383
6449
|
*, *::before, *::after { box-sizing: border-box; }
|
|
@@ -6437,7 +6503,7 @@ hr { border: none; border-top: 1px solid #21262d; width: 100%; margin: 0.5rem 0;
|
|
|
6437
6503
|
}
|
|
6438
6504
|
.inspector-link:hover { background: #388bfd; }
|
|
6439
6505
|
.inspector-hint { display: inline-block; margin-top: 0.5rem; font-size: 0.8rem; opacity: 0.45; }
|
|
6440
|
-
</style></head><body><h1>AIT 디버그 세션 — QR 스캔</h1>__MODE_LABEL____LANG_SWITCHER__<p class="label">deployment: __SAFE_LABEL__</p><div id="attach-section"><img class="qr" src="__QR_DATA_URL__" alt="attach QR"/></div><section><h2>스캔 절차</h2><ol><li>토스 앱을 실행하세요.</li><li>폰 카메라 앱으로 QR 코드를 스캔하세요.</li><li>팝업이 뜨면 <strong>"토스로 열기"</strong>를 탭하세요.</li><li>미니앱이 열리고 디버그 세션이 자동으로 attach됩니다.</li></ol></section><hr/><section><h2>진단 체크리스트</h2><ul><li><strong>토스 앱이 안 열리는 경우</strong> — 앱 버전 확인, 카메라 앱으로 스캔 (토스 앱 내 QR 리더 X)</li><li><strong>미니앱이 PREPARE 상태에서 멈추는 경우</strong> — deep-link에 <code>_deploymentId</code> 파라미터가 있는지 확인</li><li><strong>Chii 주입 실패 / 콘솔이 비어 있는 경우</strong> — 미니앱 번들에 <code>in-app</code> debug import가 있는지 확인</li><li><strong>TOTP gate Layer C가 비활성인 경우</strong> — relay 서버에 <code>AIT_DEBUG_TOTP_SECRET</code>이 설정돼 있는지 확인</li></ul></section><hr/><section id="url-section"><h2>URL (fallback)</h2><div class="url-row"><p class="url-box" id="url-box">__SAFE_ATTACH_URL__</p><button class="copy-btn" id="copy-btn" type="button" aria-label="복사">복사</button></div></section><hr/><section id="inspector-section"><h2>인스펙터</h2>__INSPECTOR_SECTION__</section></body></html>`;
|
|
6506
|
+
</style></head><body><h1>AIT 디버그 세션 — QR 스캔</h1>__MODE_LABEL____LANG_SWITCHER__<p class="label">deployment: __SAFE_LABEL__</p><div id="attach-section"><img class="qr" src="__QR_DATA_URL__" alt="attach QR"/></div><section><h2>스캔 절차</h2><ol><li>토스 앱을 실행하세요.</li><li>폰 카메라 앱으로 QR 코드를 스캔하세요.</li><li>팝업이 뜨면 <strong>"토스로 열기"</strong>를 탭하세요.</li><li>미니앱이 열리고 디버그 세션이 자동으로 attach됩니다.</li><li><strong>테스트가 끝날 때까지 토스 앱을 화면 앞에 유지하세요</strong> — 백그라운드로 전환하면 디버그 세션이 끊어집니다.</li></ol></section><hr/><section><h2>진단 체크리스트</h2><ul><li><strong>토스 앱이 안 열리는 경우</strong> — 앱 버전 확인, 카메라 앱으로 스캔 (토스 앱 내 QR 리더 X)</li><li><strong>미니앱이 PREPARE 상태에서 멈추는 경우</strong> — deep-link에 <code>_deploymentId</code> 파라미터가 있는지 확인</li><li><strong>Chii 주입 실패 / 콘솔이 비어 있는 경우</strong> — 미니앱 번들에 <code>in-app</code> debug import가 있는지 확인</li><li><strong>TOTP gate Layer C가 비활성인 경우</strong> — relay 서버에 <code>AIT_DEBUG_TOTP_SECRET</code>이 설정돼 있는지 확인</li></ul></section><hr/><section id="url-section"><h2>URL (fallback)</h2><div class="url-row"><p class="url-box" id="url-box">__SAFE_ATTACH_URL__</p><button class="copy-btn" id="copy-btn" type="button" aria-label="복사">복사</button></div></section><hr/><section id="inspector-section"><h2>인스펙터</h2>__INSPECTOR_SECTION__</section></body></html>`;
|
|
6441
6507
|
const dashboardChromeHtmlEn = `<!DOCTYPE html>
|
|
6442
6508
|
<html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><title>AIT Debug Dashboard</title><style>
|
|
6443
6509
|
*, *::before, *::after { box-sizing: border-box; }
|
|
@@ -6558,7 +6624,7 @@ hr { border: none; border-top: 1px solid #21262d; width: 100%; margin: 0.5rem 0;
|
|
|
6558
6624
|
}
|
|
6559
6625
|
.inspector-link:hover { background: #388bfd; }
|
|
6560
6626
|
.inspector-hint { display: inline-block; margin-top: 0.5rem; font-size: 0.8rem; opacity: 0.45; }
|
|
6561
|
-
</style></head><body><h1>AIT Debug Session — QR Scan</h1>__MODE_LABEL____LANG_SWITCHER__<div id="attach-section"><img class="qr" src="__QR_DATA_URL__" alt="attach QR"/></div><section><h2>How to scan</h2><ol><li>Launch the launcher PWA icon on your home screen (if the Safari address bar is visible, it is not standalone).</li><li>Scan this QR code with <strong>"Scan QR with camera"</strong> inside the launcher.</li><li>The mini-app opens fullscreen and the debug session attaches automatically.</li></ol></section><hr/><section><h2>Troubleshooting checklist</h2><ul><li><strong>Launcher is not installed</strong> — open <code>devtools.aitc.dev/launcher/</code> once and add it to your home screen</li><li><strong>Scanning with the camera app opens a Safari tab (bottom tab bar visible)</strong> — relaunch from the launcher icon and use the in-app scanner</li><li><strong>QR expired (TOTP — 30-second step, ±6 steps (~3 min) accepted)</strong> — scan a fresh QR code</li><li><strong>Chii injection failure / console is empty</strong> — verify the mini-app bundle has an <code>in-app</code> debug import</li></ul></section><hr/><section id="url-section"><h2>URL (fallback)</h2><div class="url-row"><p class="url-box" id="url-box">__SAFE_ATTACH_URL__</p><button class="copy-btn" id="copy-btn" type="button" aria-label="Copy">Copy</button></div></section><hr/><section id="inspector-section"><h2>Inspector</h2>__INSPECTOR_SECTION__</section></body></html>`;
|
|
6627
|
+
</style></head><body><h1>AIT Debug Session — QR Scan</h1>__MODE_LABEL____LANG_SWITCHER__<div id="attach-section"><img class="qr" src="__QR_DATA_URL__" alt="attach QR"/></div><section><h2>How to scan</h2><ol><li>Launch the launcher PWA icon on your home screen (if the Safari address bar is visible, it is not standalone).</li><li>Scan this QR code with <strong>"Scan QR with camera"</strong> inside the launcher.</li><li>The mini-app opens fullscreen and the debug session attaches automatically.</li><li><strong>Keep the app in the foreground until the test run finishes</strong> — backgrounding it will drop the debug session.</li></ol></section><hr/><section><h2>Troubleshooting checklist</h2><ul><li><strong>Launcher is not installed</strong> — open <code>devtools.aitc.dev/launcher/</code> once and add it to your home screen</li><li><strong>Scanning with the camera app opens a Safari tab (bottom tab bar visible)</strong> — relaunch from the launcher icon and use the in-app scanner</li><li><strong>QR expired (TOTP — 30-second step, ±6 steps (~3 min) accepted)</strong> — scan a fresh QR code</li><li><strong>Chii injection failure / console is empty</strong> — verify the mini-app bundle has an <code>in-app</code> debug import</li></ul></section><hr/><section id="url-section"><h2>URL (fallback)</h2><div class="url-row"><p class="url-box" id="url-box">__SAFE_ATTACH_URL__</p><button class="copy-btn" id="copy-btn" type="button" aria-label="Copy">Copy</button></div></section><hr/><section id="inspector-section"><h2>Inspector</h2>__INSPECTOR_SECTION__</section></body></html>`;
|
|
6562
6628
|
const attachChromeHtmlEnIntoss = `<!DOCTYPE html>
|
|
6563
6629
|
<html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="preload" as="image" href="__QR_DATA_URL__"/><title>AIT Debug Session — QR Scan</title><style>
|
|
6564
6630
|
*, *::before, *::after { box-sizing: border-box; }
|
|
@@ -6618,7 +6684,7 @@ hr { border: none; border-top: 1px solid #21262d; width: 100%; margin: 0.5rem 0;
|
|
|
6618
6684
|
}
|
|
6619
6685
|
.inspector-link:hover { background: #388bfd; }
|
|
6620
6686
|
.inspector-hint { display: inline-block; margin-top: 0.5rem; font-size: 0.8rem; opacity: 0.45; }
|
|
6621
|
-
</style></head><body><h1>AIT Debug Session — QR Scan</h1>__MODE_LABEL____LANG_SWITCHER__<p class="label">deployment: __SAFE_LABEL__</p><div id="attach-section"><img class="qr" src="__QR_DATA_URL__" alt="attach QR"/></div><section><h2>How to scan</h2><ol><li>Open the Toss app.</li><li>Scan the QR code with your phone camera app.</li><li>Tap <strong>"Open in Toss"</strong> when the popup appears.</li><li>The mini-app opens and the debug session attaches automatically.</li></ol></section><hr/><section><h2>Troubleshooting checklist</h2><ul><li><strong>Toss app does not open</strong> — check app version; scan with the system camera app (not the Toss in-app QR reader)</li><li><strong>Mini-app stuck in PREPARE state</strong> — verify the deep-link has a <code>_deploymentId</code> parameter</li><li><strong>Chii injection failure / console is empty</strong> — verify the mini-app bundle has an <code>in-app</code> debug import</li><li><strong>TOTP gate Layer C is inactive</strong> — check that <code>AIT_DEBUG_TOTP_SECRET</code> is set on the relay server</li></ul></section><hr/><section id="url-section"><h2>URL (fallback)</h2><div class="url-row"><p class="url-box" id="url-box">__SAFE_ATTACH_URL__</p><button class="copy-btn" id="copy-btn" type="button" aria-label="Copy">Copy</button></div></section><hr/><section id="inspector-section"><h2>Inspector</h2>__INSPECTOR_SECTION__</section></body></html>`;
|
|
6687
|
+
</style></head><body><h1>AIT Debug Session — QR Scan</h1>__MODE_LABEL____LANG_SWITCHER__<p class="label">deployment: __SAFE_LABEL__</p><div id="attach-section"><img class="qr" src="__QR_DATA_URL__" alt="attach QR"/></div><section><h2>How to scan</h2><ol><li>Open the Toss app.</li><li>Scan the QR code with your phone camera app.</li><li>Tap <strong>"Open in Toss"</strong> when the popup appears.</li><li>The mini-app opens and the debug session attaches automatically.</li><li><strong>Keep the Toss app in the foreground until the test run finishes</strong> — backgrounding it will drop the debug session.</li></ol></section><hr/><section><h2>Troubleshooting checklist</h2><ul><li><strong>Toss app does not open</strong> — check app version; scan with the system camera app (not the Toss in-app QR reader)</li><li><strong>Mini-app stuck in PREPARE state</strong> — verify the deep-link has a <code>_deploymentId</code> parameter</li><li><strong>Chii injection failure / console is empty</strong> — verify the mini-app bundle has an <code>in-app</code> debug import</li><li><strong>TOTP gate Layer C is inactive</strong> — check that <code>AIT_DEBUG_TOTP_SECRET</code> is set on the relay server</li></ul></section><hr/><section id="url-section"><h2>URL (fallback)</h2><div class="url-row"><p class="url-box" id="url-box">__SAFE_ATTACH_URL__</p><button class="copy-btn" id="copy-btn" type="button" aria-label="Copy">Copy</button></div></section><hr/><section id="inspector-section"><h2>Inspector</h2>__INSPECTOR_SECTION__</section></body></html>`;
|
|
6622
6688
|
/** Map from Locale to the precompiled dashboard chrome string. */
|
|
6623
6689
|
const dashboardChromeByLocale = {
|
|
6624
6690
|
ko: dashboardChromeHtmlKo,
|
|
@@ -7488,7 +7554,7 @@ function createDebugServer(deps) {
|
|
|
7488
7554
|
};
|
|
7489
7555
|
const server = new Server({
|
|
7490
7556
|
name: "ait-debug",
|
|
7491
|
-
version: "0.1.
|
|
7557
|
+
version: "0.1.142"
|
|
7492
7558
|
}, { capabilities: { tools: { listChanged: true } } });
|
|
7493
7559
|
server.setRequestHandler(ListToolsRequestSchema, () => {
|
|
7494
7560
|
const conn = router.active;
|
|
@@ -9479,7 +9545,7 @@ function createDevServer(deps = {}) {
|
|
|
9479
9545
|
const aitSource = deps.aitSource ?? new HttpAitSource({ stateEndpoint });
|
|
9480
9546
|
const server = new Server({
|
|
9481
9547
|
name: "ait-devtools",
|
|
9482
|
-
version: "0.1.
|
|
9548
|
+
version: "0.1.142"
|
|
9483
9549
|
}, { capabilities: { tools: {} } });
|
|
9484
9550
|
server.setRequestHandler(ListToolsRequestSchema, () => ({ tools: DEV_TOOL_DEFINITIONS.map((tool) => ({ ...tool })) }));
|
|
9485
9551
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|