@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.
Files changed (77) hide show
  1. package/README.en.md +4 -4
  2. package/README.md +4 -4
  3. package/dist/{attach-orchestrator-BG8TGJOZ.js → attach-orchestrator-0F0m_UqQ.js} +71 -9
  4. package/dist/{attach-orchestrator-BG8TGJOZ.js.map → attach-orchestrator-0F0m_UqQ.js.map} +1 -1
  5. package/dist/{attach-orchestrator-6kz_ZdWL.js → attach-orchestrator-D65KxFy_.js} +71 -9
  6. package/dist/{attach-orchestrator-6kz_ZdWL.js.map → attach-orchestrator-D65KxFy_.js.map} +1 -1
  7. package/dist/{attach-orchestrator-BEiz3wAx.js → attach-orchestrator-DL3NQ9ca.js} +71 -9
  8. package/dist/{attach-orchestrator-BEiz3wAx.js.map → attach-orchestrator-DL3NQ9ca.js.map} +1 -1
  9. package/dist/{cell-BMlFh08P.js → cell-BaLvusOl.js} +2 -2
  10. package/dist/{cell-BMlFh08P.js.map → cell-BaLvusOl.js.map} +1 -1
  11. package/dist/{cell-Dtgtusog.js → cell-CBUS3-nT.js} +2 -2
  12. package/dist/{cell-Dtgtusog.js.map → cell-CBUS3-nT.js.map} +1 -1
  13. package/dist/{cell-KsRXFdDs.js → cell-EBKKpAAT.js} +2 -2
  14. package/dist/{cell-KsRXFdDs.js.map → cell-EBKKpAAT.js.map} +1 -1
  15. package/dist/{debug-server-DWat7d-9.js → debug-server-B3ABDrRI.js} +4 -4
  16. package/dist/{debug-server-DWat7d-9.js.map → debug-server-B3ABDrRI.js.map} +1 -1
  17. package/dist/{debug-server-6c22qSWa.js → debug-server-BWhwrVXa.js} +4 -4
  18. package/dist/{debug-server-6c22qSWa.js.map → debug-server-BWhwrVXa.js.map} +1 -1
  19. package/dist/{debug-server-BQHbaKPT.js → debug-server-CfQNxxGW.js} +6 -6
  20. package/dist/{debug-server-BQHbaKPT.js.map → debug-server-CfQNxxGW.js.map} +1 -1
  21. package/dist/in-app/auto.js +299 -3
  22. package/dist/in-app/auto.js.map +1 -1
  23. package/dist/in-app/index.d.ts +161 -14
  24. package/dist/in-app/index.d.ts.map +1 -1
  25. package/dist/in-app/index.js +300 -4
  26. package/dist/in-app/index.js.map +1 -1
  27. package/dist/mcp/cli.js +82 -16
  28. package/dist/mcp/cli.js.map +1 -1
  29. package/dist/mcp/server.js +1 -1
  30. package/dist/mock/index.d.ts +124 -89
  31. package/dist/mock/index.d.ts.map +1 -1
  32. package/dist/mock/index.js +21 -2
  33. package/dist/mock/index.js.map +1 -1
  34. package/dist/panel/index.js +7 -2
  35. package/dist/panel/index.js.map +1 -1
  36. package/dist/{qr-http-server-Cz1mA07b.cjs → qr-http-server--gl2-WKc.cjs} +9 -5
  37. package/dist/qr-http-server--gl2-WKc.cjs.map +1 -0
  38. package/dist/{qr-http-server-D4rGz8M7.js → qr-http-server-Bb7lMeqi.js} +9 -5
  39. package/dist/qr-http-server-Bb7lMeqi.js.map +1 -0
  40. package/dist/{qr-http-server-D1hpoyBF.js → qr-http-server-C_lqOrgc.js} +9 -5
  41. package/dist/qr-http-server-C_lqOrgc.js.map +1 -0
  42. package/dist/{qr-http-server-CTLdclg_.js → qr-http-server-CopuMbub.js} +9 -5
  43. package/dist/qr-http-server-CopuMbub.js.map +1 -0
  44. package/dist/{qr-http-server-D16Lq2ag.cjs → qr-http-server-D-Off6K1.cjs} +9 -5
  45. package/dist/qr-http-server-D-Off6K1.cjs.map +1 -0
  46. package/dist/{qr-http-server-DIjCV7h_.js → qr-http-server-DrbIVDjO.js} +9 -5
  47. package/dist/qr-http-server-DrbIVDjO.js.map +1 -0
  48. package/dist/qr-http-server-n1twN18z.js +1644 -0
  49. package/dist/qr-http-server-n1twN18z.js.map +1 -0
  50. package/dist/{relay-factory-C1X3G3WY.js → relay-factory-N9QobQxG.js} +6 -6
  51. package/dist/{relay-factory-C1X3G3WY.js.map → relay-factory-N9QobQxG.js.map} +1 -1
  52. package/dist/{relay-worker-BUXI0K0b.js → relay-worker-B5HKkGUY.js} +4 -4
  53. package/dist/{relay-worker-BUXI0K0b.js.map → relay-worker-B5HKkGUY.js.map} +1 -1
  54. package/dist/relay-worker-DcyboK43.d.ts.map +1 -1
  55. package/dist/test-runner/bin.js +8 -8
  56. package/dist/test-runner/bin.js.map +1 -1
  57. package/dist/test-runner/config.js +1 -1
  58. package/dist/test-runner/pool.js +1 -1
  59. package/dist/test-runner/relay-factory.js +5 -5
  60. package/dist/test-runner/relay-worker.js +1 -1
  61. package/dist/{tunnel-DjtSENJU.cjs → tunnel-BVSMXctM.cjs} +2 -2
  62. package/dist/{tunnel-DjtSENJU.cjs.map → tunnel-BVSMXctM.cjs.map} +1 -1
  63. package/dist/{tunnel-5eBncITa.js → tunnel-D7xkimBu.js} +2 -2
  64. package/dist/{tunnel-5eBncITa.js.map → tunnel-D7xkimBu.js.map} +1 -1
  65. package/dist/unplugin/index.cjs +1 -1
  66. package/dist/unplugin/index.js +1 -1
  67. package/dist/unplugin/tunnel.cjs +1 -1
  68. package/dist/unplugin/tunnel.js +1 -1
  69. package/package.json +2 -2
  70. package/dist/qr-http-server-CTLdclg_.js.map +0 -1
  71. package/dist/qr-http-server-Cz1mA07b.cjs.map +0 -1
  72. package/dist/qr-http-server-D16Lq2ag.cjs.map +0 -1
  73. package/dist/qr-http-server-D1hpoyBF.js.map +0 -1
  74. package/dist/qr-http-server-D4rGz8M7.js.map +0 -1
  75. package/dist/qr-http-server-DIjCV7h_.js.map +0 -1
  76. package/dist/qr-http-server-wy3L7Yut.js +0 -1640
  77. package/dist/qr-http-server-wy3L7Yut.js.map +0 -1
@@ -1607,7 +1607,7 @@ async function renderAndMaybeWait(deps, prep, waitForAttach, callTimeoutMs, conn
1607
1607
  let totpIssuedAt = nowMs();
1608
1608
  let reminted = 0;
1609
1609
  const relayUrl = parts.wssUrl;
1610
- 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).";
1610
+ 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테스트가 끝날 때까지 앱을 화면 앞에 유지하세요 — 백그라운드로 전환하면 디버그 세션이 끊어집니다.";
1611
1611
  const warningPrefix = authorityWarning ? `⚠️ scheme_url 경고: ${authorityWarning}\n\n` : "";
1612
1612
  const guiAvailable = canOpenBrowserFn();
1613
1613
  /** Builds the totp object surfaced in results (fresh expiresAt + reminted). */
@@ -1733,9 +1733,35 @@ async function renderAndMaybeWait(deps, prep, waitForAttach, callTimeoutMs, conn
1733
1733
  }, null, 2)}\n\n${qr}`);
1734
1734
  }
1735
1735
  /**
1736
+ * How long the disconnected badge stays on screen before it fades and removes
1737
+ * itself (#748). Long enough to read, short enough not to linger; a reconnect
1738
+ * within this window cancels the self-dismiss (transient tunnel blips do not
1739
+ * flash-remove the badge).
1740
+ */
1741
+ const INDICATOR_SELF_DISMISS_MS = 5e3;
1742
+ /** Fade duration before the self-dismissed badge is detached from the DOM. */
1743
+ const INDICATOR_FADE_MS = 400;
1744
+ /**
1745
+ * Heartbeat / pending-call render tick (#749). 1 Hz — cheap enough to be
1746
+ * invisible (a single text write per second, no layout thrash) while making a
1747
+ * JS main-thread wedge obvious: the compositor-driven pulse dot keeps animating
1748
+ * but this JS-driven `♥<beats>` token freezes. Pending-call elapsed times are
1749
+ * recomputed on the same tick so they advance without any bridge event.
1750
+ */
1751
+ const INDICATOR_HEARTBEAT_MS = 1e3;
1752
+ /**
1753
+ * Display-side staleness guard (#749): the badge skips rendering a pending call
1754
+ * older than this. A safety net independent of the in-app observer's own prune
1755
+ * (`bridge-observer.ts` MAX_PENDING_AGE_MS) — kept local so the daemon-graph
1756
+ * expression builder never imports the in-app module (install-graph invariant).
1757
+ * Generous enough that a genuinely slow native call still shows while plausibly
1758
+ * in flight.
1759
+ */
1760
+ const INDICATOR_PENDING_STALE_MS = 12e4;
1761
+ /**
1736
1762
  * Builds a self-contained IIFE DOM expression that renders a LIVE
1737
- * "Debugger Connected" / "Debugger Disconnected" badge on the bottom-left of
1738
- * the phone screen (#730).
1763
+ * "Debugger Connected" / disconnected badge on the bottom-left of the phone
1764
+ * screen (#730), with a graceful self-dismiss on disconnect (#748).
1739
1765
  *
1740
1766
  * **Pure function** — returns a JS expression string; does NOT inject it.
1741
1767
  * Injection is performed by {@link injectDebugIndicator} in `cell.ts`.
@@ -1752,7 +1778,18 @@ async function renderAndMaybeWait(deps, prep, waitForAttach, callTimeoutMs, conn
1752
1778
  * 3. A `pointerdown` listener dismisses (hides) the badge on tap — dismiss
1753
1779
  * is NON-terminal: a later state transition un-dismisses it, so a
1754
1780
  * genuine disconnect after a dismissed tap is still visible.
1755
- * 4. Observes relay-socket lifecycle WITHOUT opening any new connection:
1781
+ * 4. **Graceful self-dismiss (#748)** the disconnected badge is NON-BLOCKING
1782
+ * (`pointer-events:none` the moment it flips to disconnected, so it can
1783
+ * never absorb a tap) and SELF-DISMISSING (it fades and detaches itself
1784
+ * after {@link INDICATOR_SELF_DISMISS_MS}). This is why a run that ends
1785
+ * with `close()` injecting `{ state: 'disconnected' }` no longer leaves a
1786
+ * permanent grey "Debugger Disconnected" element on the phone. A reconnect
1787
+ * (`setState(c, 'attached')`) cancels the pending self-dismiss and
1788
+ * re-mounts the badge if it had already detached — transient tunnel blips
1789
+ * do not flash-remove it, and a genuine re-attach restores it. The
1790
+ * controller object is retained across dismiss (never `delete`d), so a
1791
+ * later re-injection reuses it and never double-wraps `window.WebSocket`.
1792
+ * 5. Observes relay-socket lifecycle WITHOUT opening any new connection:
1756
1793
  * - Preferred path: if the in-app module (`src/in-app/attach.ts`) has
1757
1794
  * already installed its relay-WS observer (`window.__ait_relay_ws_observed`),
1758
1795
  * subscribe to the `ait:relay-ws-state` CustomEvent it broadcasts.
@@ -1760,25 +1797,50 @@ async function renderAndMaybeWait(deps, prep, waitForAttach, callTimeoutMs, conn
1760
1797
  * by PATHNAME SHAPE only (`/target/`) — never by host/wss value — so a
1761
1798
  * bare CDP-injected badge (no in-app bundle) still reacts to the
1762
1799
  * chii target socket's own open/close lifecycle.
1800
+ * 6. **Freeze/spinner triage (#749)** — renders three debug-only signals so a
1801
+ * real-device spinner is attributable at a glance (run7):
1802
+ * - **Main-thread heartbeat**: a compositor-driven pulse dot
1803
+ * (`Element.animate`, keeps running during JS jank) PLUS a JS-driven
1804
+ * `♥<beats>` token incremented by a 1 Hz `setInterval`. `CSS pulse alive
1805
+ * + ♥ frozen = JS main-thread wedge`.
1806
+ * - **Pending bridge calls**: in-flight native calls (API name + live
1807
+ * elapsed) read from `window.__ait_bridge` (published by the in-app
1808
+ * bridge observer, `src/in-app/bridge-observer.ts`). `⏳ present =
1809
+ * native/Toss-app spinner`.
1810
+ * - **Last SDK call stamp**: the most recent call's API name + wall-clock.
1811
+ * `no ⏳ + heartbeat healthy = the miniapp's own UI`.
1812
+ * The `title` tooltip states this mapping. When no in-app observer is
1813
+ * present (env 2 mock / no bridge) the pending/last lines are simply empty
1814
+ * — the heartbeat still renders. The 1 Hz interval is stored on the
1815
+ * controller (`c.hb`) and stopped by `c.stop()` (called from
1816
+ * `detachDebugSurface`) and by the self-dismiss removal, so no timer leaks
1817
+ * past detach (#748 lifecycle).
1763
1818
  *
1764
1819
  * The expression intentionally contains NO relay URLs, wss addresses, TOTP
1765
- * codes, or any other secrets. It is pure DOM UI text + enum state only.
1820
+ * codes, or any other secrets. `window.__ait_bridge` holds API NAMES + timings
1821
+ * only (never call arguments/results — see `bridge-observer.ts`
1822
+ * SECRET-HANDLING). It is pure DOM UI text + enum/name state only.
1766
1823
  *
1767
1824
  * SECRET-HANDLING: this expression contains no secrets, relay URLs, wss
1768
1825
  * addresses, or TOTP codes whatsoever — DOM label text + a structural
1769
1826
  * pathname match (`/target/`) only.
1770
1827
  *
1771
1828
  * @param opts.label - Attached-state badge text (default: `'Debugger Connected'`).
1772
- * @param opts.disconnectedLabel - Disconnected-state badge text (default: `'Debugger Disconnected'`).
1829
+ * @param opts.disconnectedLabel - Disconnected-state badge text. Default is the
1830
+ * Korean notice `'디버거 연결 끊김'` (ko-primary in-app string convention) —
1831
+ * shown briefly then self-dismissed.
1773
1832
  * @param opts.state - Initial/forced state for THIS injection call (default: `'attached'`).
1774
1833
  * @returns A JS expression string suitable for `Runtime.evaluate`.
1775
1834
  */
1776
1835
  function buildIndicatorExpression(opts) {
1777
1836
  const label = opts?.label ?? "Debugger Connected";
1778
- const disconnectedLabel = opts?.disconnectedLabel ?? "Debugger Disconnected";
1779
- return `(() => {var W = window;function render(c) {if (c.dismissed) { c.el.style.display = 'none'; return; }c.el.style.display = 'block';var up = c.state !== 'disconnected';c.el.style.background = up ? '#e5484d' : '#8a8f98';c.el.textContent = up ? ${JSON.stringify(label)} : ${JSON.stringify(disconnectedLabel)};}function setState(c, next) { c.state = next; c.dismissed = false; render(c); }var c = W.__ait_indicator;if (!c) {var el = document.createElement('div');el.id = '__ait_debug_indicator';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 system-ui,sans-serif','padding:5px 9px','border-radius:6px','pointer-events:auto','user-select:none',].join(';');document.body.appendChild(el);c = { el: el, state: 'attached', dismissed: false };el.addEventListener('pointerdown', function () { c.dismissed = true; render(c); }, { passive: true });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, ${JSON.stringify(opts?.state ?? "attached")});})()`;
1837
+ const disconnectedLabel = opts?.disconnectedLabel ?? "디버거 연결 끊김";
1838
+ const safeLabel = JSON.stringify(label);
1839
+ const safeDisconnectedLabel = JSON.stringify(disconnectedLabel);
1840
+ const safeState = JSON.stringify(opts?.state ?? "attached");
1841
+ 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});})()`;
1780
1842
  }
1781
1843
  //#endregion
1782
1844
  export { buildIndicatorExpression as a, generateAttachToken as c, startQuickTunnel as d, startTunnelHealthProbe as f, attach_orchestrator_exports as i, makeTunnelStatus as l, logInfo as m, START_ATTACH_REMINT_THRESHOLD_MS as n, extractDeploymentId as o, logError as p, START_ATTACH_SEGMENT_MS as r, isSandboxPageFresh as s, RELAY_SANDBOX_STALE_PAGE_MS as t, printAttachBanner as u };
1783
1845
 
1784
- //# sourceMappingURL=attach-orchestrator-BEiz3wAx.js.map
1846
+ //# sourceMappingURL=attach-orchestrator-DL3NQ9ca.js.map