@ait-co/devtools 0.1.140 → 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 +174 -97
  31. package/dist/mock/index.d.ts.map +1 -1
  32. package/dist/mock/index.js +78 -14
  33. package/dist/mock/index.js.map +1 -1
  34. package/dist/panel/index.js +7 -23
  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
@@ -1592,7 +1592,7 @@ async function renderAndMaybeWait(deps, prep, waitForAttach, callTimeoutMs, conn
1592
1592
  let totpIssuedAt = nowMs();
1593
1593
  let reminted = 0;
1594
1594
  const relayUrl = parts.wssUrl;
1595
- 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).";
1595
+ 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테스트가 끝날 때까지 앱을 화면 앞에 유지하세요 — 백그라운드로 전환하면 디버그 세션이 끊어집니다.";
1596
1596
  const warningPrefix = authorityWarning ? `⚠️ scheme_url 경고: ${authorityWarning}\n\n` : "";
1597
1597
  const guiAvailable = canOpenBrowserFn();
1598
1598
  /** Builds the totp object surfaced in results (fresh expiresAt + reminted). */
@@ -1718,9 +1718,35 @@ async function renderAndMaybeWait(deps, prep, waitForAttach, callTimeoutMs, conn
1718
1718
  }, null, 2)}\n\n${qr}`);
1719
1719
  }
1720
1720
  /**
1721
+ * How long the disconnected badge stays on screen before it fades and removes
1722
+ * itself (#748). Long enough to read, short enough not to linger; a reconnect
1723
+ * within this window cancels the self-dismiss (transient tunnel blips do not
1724
+ * flash-remove the badge).
1725
+ */
1726
+ const INDICATOR_SELF_DISMISS_MS = 5e3;
1727
+ /** Fade duration before the self-dismissed badge is detached from the DOM. */
1728
+ const INDICATOR_FADE_MS = 400;
1729
+ /**
1730
+ * Heartbeat / pending-call render tick (#749). 1 Hz — cheap enough to be
1731
+ * invisible (a single text write per second, no layout thrash) while making a
1732
+ * JS main-thread wedge obvious: the compositor-driven pulse dot keeps animating
1733
+ * but this JS-driven `♥<beats>` token freezes. Pending-call elapsed times are
1734
+ * recomputed on the same tick so they advance without any bridge event.
1735
+ */
1736
+ const INDICATOR_HEARTBEAT_MS = 1e3;
1737
+ /**
1738
+ * Display-side staleness guard (#749): the badge skips rendering a pending call
1739
+ * older than this. A safety net independent of the in-app observer's own prune
1740
+ * (`bridge-observer.ts` MAX_PENDING_AGE_MS) — kept local so the daemon-graph
1741
+ * expression builder never imports the in-app module (install-graph invariant).
1742
+ * Generous enough that a genuinely slow native call still shows while plausibly
1743
+ * in flight.
1744
+ */
1745
+ const INDICATOR_PENDING_STALE_MS = 12e4;
1746
+ /**
1721
1747
  * Builds a self-contained IIFE DOM expression that renders a LIVE
1722
- * "Debugger Connected" / "Debugger Disconnected" badge on the bottom-left of
1723
- * the phone screen (#730).
1748
+ * "Debugger Connected" / disconnected badge on the bottom-left of the phone
1749
+ * screen (#730), with a graceful self-dismiss on disconnect (#748).
1724
1750
  *
1725
1751
  * **Pure function** — returns a JS expression string; does NOT inject it.
1726
1752
  * Injection is performed by {@link injectDebugIndicator} in `cell.ts`.
@@ -1737,7 +1763,18 @@ async function renderAndMaybeWait(deps, prep, waitForAttach, callTimeoutMs, conn
1737
1763
  * 3. A `pointerdown` listener dismisses (hides) the badge on tap — dismiss
1738
1764
  * is NON-terminal: a later state transition un-dismisses it, so a
1739
1765
  * genuine disconnect after a dismissed tap is still visible.
1740
- * 4. Observes relay-socket lifecycle WITHOUT opening any new connection:
1766
+ * 4. **Graceful self-dismiss (#748)** the disconnected badge is NON-BLOCKING
1767
+ * (`pointer-events:none` the moment it flips to disconnected, so it can
1768
+ * never absorb a tap) and SELF-DISMISSING (it fades and detaches itself
1769
+ * after {@link INDICATOR_SELF_DISMISS_MS}). This is why a run that ends
1770
+ * with `close()` injecting `{ state: 'disconnected' }` no longer leaves a
1771
+ * permanent grey "Debugger Disconnected" element on the phone. A reconnect
1772
+ * (`setState(c, 'attached')`) cancels the pending self-dismiss and
1773
+ * re-mounts the badge if it had already detached — transient tunnel blips
1774
+ * do not flash-remove it, and a genuine re-attach restores it. The
1775
+ * controller object is retained across dismiss (never `delete`d), so a
1776
+ * later re-injection reuses it and never double-wraps `window.WebSocket`.
1777
+ * 5. Observes relay-socket lifecycle WITHOUT opening any new connection:
1741
1778
  * - Preferred path: if the in-app module (`src/in-app/attach.ts`) has
1742
1779
  * already installed its relay-WS observer (`window.__ait_relay_ws_observed`),
1743
1780
  * subscribe to the `ait:relay-ws-state` CustomEvent it broadcasts.
@@ -1745,25 +1782,50 @@ async function renderAndMaybeWait(deps, prep, waitForAttach, callTimeoutMs, conn
1745
1782
  * by PATHNAME SHAPE only (`/target/`) — never by host/wss value — so a
1746
1783
  * bare CDP-injected badge (no in-app bundle) still reacts to the
1747
1784
  * chii target socket's own open/close lifecycle.
1785
+ * 6. **Freeze/spinner triage (#749)** — renders three debug-only signals so a
1786
+ * real-device spinner is attributable at a glance (run7):
1787
+ * - **Main-thread heartbeat**: a compositor-driven pulse dot
1788
+ * (`Element.animate`, keeps running during JS jank) PLUS a JS-driven
1789
+ * `♥<beats>` token incremented by a 1 Hz `setInterval`. `CSS pulse alive
1790
+ * + ♥ frozen = JS main-thread wedge`.
1791
+ * - **Pending bridge calls**: in-flight native calls (API name + live
1792
+ * elapsed) read from `window.__ait_bridge` (published by the in-app
1793
+ * bridge observer, `src/in-app/bridge-observer.ts`). `⏳ present =
1794
+ * native/Toss-app spinner`.
1795
+ * - **Last SDK call stamp**: the most recent call's API name + wall-clock.
1796
+ * `no ⏳ + heartbeat healthy = the miniapp's own UI`.
1797
+ * The `title` tooltip states this mapping. When no in-app observer is
1798
+ * present (env 2 mock / no bridge) the pending/last lines are simply empty
1799
+ * — the heartbeat still renders. The 1 Hz interval is stored on the
1800
+ * controller (`c.hb`) and stopped by `c.stop()` (called from
1801
+ * `detachDebugSurface`) and by the self-dismiss removal, so no timer leaks
1802
+ * past detach (#748 lifecycle).
1748
1803
  *
1749
1804
  * The expression intentionally contains NO relay URLs, wss addresses, TOTP
1750
- * codes, or any other secrets. It is pure DOM UI text + enum state only.
1805
+ * codes, or any other secrets. `window.__ait_bridge` holds API NAMES + timings
1806
+ * only (never call arguments/results — see `bridge-observer.ts`
1807
+ * SECRET-HANDLING). It is pure DOM UI text + enum/name state only.
1751
1808
  *
1752
1809
  * SECRET-HANDLING: this expression contains no secrets, relay URLs, wss
1753
1810
  * addresses, or TOTP codes whatsoever — DOM label text + a structural
1754
1811
  * pathname match (`/target/`) only.
1755
1812
  *
1756
1813
  * @param opts.label - Attached-state badge text (default: `'Debugger Connected'`).
1757
- * @param opts.disconnectedLabel - Disconnected-state badge text (default: `'Debugger Disconnected'`).
1814
+ * @param opts.disconnectedLabel - Disconnected-state badge text. Default is the
1815
+ * Korean notice `'디버거 연결 끊김'` (ko-primary in-app string convention) —
1816
+ * shown briefly then self-dismissed.
1758
1817
  * @param opts.state - Initial/forced state for THIS injection call (default: `'attached'`).
1759
1818
  * @returns A JS expression string suitable for `Runtime.evaluate`.
1760
1819
  */
1761
1820
  function buildIndicatorExpression(opts) {
1762
1821
  const label = opts?.label ?? "Debugger Connected";
1763
- const disconnectedLabel = opts?.disconnectedLabel ?? "Debugger Disconnected";
1764
- 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")});})()`;
1822
+ const disconnectedLabel = opts?.disconnectedLabel ?? "디버거 연결 끊김";
1823
+ const safeLabel = JSON.stringify(label);
1824
+ const safeDisconnectedLabel = JSON.stringify(disconnectedLabel);
1825
+ const safeState = JSON.stringify(opts?.state ?? "attached");
1826
+ 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});})()`;
1765
1827
  }
1766
1828
  //#endregion
1767
1829
  export { RELAY_SANDBOX_STALE_PAGE_MS, START_ATTACH_REMINT_THRESHOLD_MS, START_ATTACH_SEGMENT_MS, startTunnelHealthProbe as a, buildIndicatorExpression, extractDeploymentId, startQuickTunnel as i, isSandboxPageFresh, mintAttachUrl, makeTunnelStatus as n, logError as o, prepareAttach, printAttachBanner as r, renderAndMaybeWait, logInfo as s, generateAttachToken as t };
1768
1830
 
1769
- //# sourceMappingURL=attach-orchestrator-6kz_ZdWL.js.map
1831
+ //# sourceMappingURL=attach-orchestrator-D65KxFy_.js.map