@thinkrun/cli 0.1.27

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 (183) hide show
  1. package/README.md +349 -0
  2. package/dist/bin/thinkrun.d.ts +6 -0
  3. package/dist/bin/thinkrun.d.ts.map +1 -0
  4. package/dist/bin/thinkrun.js +124 -0
  5. package/dist/bin/thinkrun.js.map +1 -0
  6. package/dist/scripts/browse.sh +1107 -0
  7. package/dist/src/adapters/cloud.d.ts +79 -0
  8. package/dist/src/adapters/cloud.d.ts.map +1 -0
  9. package/dist/src/adapters/cloud.js +637 -0
  10. package/dist/src/adapters/cloud.js.map +1 -0
  11. package/dist/src/adapters/index.d.ts +47 -0
  12. package/dist/src/adapters/index.d.ts.map +1 -0
  13. package/dist/src/adapters/index.js +211 -0
  14. package/dist/src/adapters/index.js.map +1 -0
  15. package/dist/src/adapters/local-command-retry.d.ts +12 -0
  16. package/dist/src/adapters/local-command-retry.d.ts.map +1 -0
  17. package/dist/src/adapters/local-command-retry.js +224 -0
  18. package/dist/src/adapters/local-command-retry.js.map +1 -0
  19. package/dist/src/adapters/local.d.ts +136 -0
  20. package/dist/src/adapters/local.d.ts.map +1 -0
  21. package/dist/src/adapters/local.js +1273 -0
  22. package/dist/src/adapters/local.js.map +1 -0
  23. package/dist/src/adapters/types.d.ts +45 -0
  24. package/dist/src/adapters/types.d.ts.map +1 -0
  25. package/dist/src/adapters/types.js +6 -0
  26. package/dist/src/adapters/types.js.map +1 -0
  27. package/dist/src/commands/actions.d.ts +135 -0
  28. package/dist/src/commands/actions.d.ts.map +1 -0
  29. package/dist/src/commands/actions.js +2207 -0
  30. package/dist/src/commands/actions.js.map +1 -0
  31. package/dist/src/commands/agent-init.d.ts +16 -0
  32. package/dist/src/commands/agent-init.d.ts.map +1 -0
  33. package/dist/src/commands/agent-init.js +222 -0
  34. package/dist/src/commands/agent-init.js.map +1 -0
  35. package/dist/src/commands/analyze.d.ts +11 -0
  36. package/dist/src/commands/analyze.d.ts.map +1 -0
  37. package/dist/src/commands/analyze.js +238 -0
  38. package/dist/src/commands/analyze.js.map +1 -0
  39. package/dist/src/commands/cache.d.ts +6 -0
  40. package/dist/src/commands/cache.d.ts.map +1 -0
  41. package/dist/src/commands/cache.js +147 -0
  42. package/dist/src/commands/cache.js.map +1 -0
  43. package/dist/src/commands/cloud.d.ts +6 -0
  44. package/dist/src/commands/cloud.d.ts.map +1 -0
  45. package/dist/src/commands/cloud.js +332 -0
  46. package/dist/src/commands/cloud.js.map +1 -0
  47. package/dist/src/commands/config.d.ts +7 -0
  48. package/dist/src/commands/config.d.ts.map +1 -0
  49. package/dist/src/commands/config.js +208 -0
  50. package/dist/src/commands/config.js.map +1 -0
  51. package/dist/src/commands/doctor.d.ts +127 -0
  52. package/dist/src/commands/doctor.d.ts.map +1 -0
  53. package/dist/src/commands/doctor.js +684 -0
  54. package/dist/src/commands/doctor.js.map +1 -0
  55. package/dist/src/commands/evaluate-helpers.d.ts +6 -0
  56. package/dist/src/commands/evaluate-helpers.d.ts.map +1 -0
  57. package/dist/src/commands/evaluate-helpers.js +13 -0
  58. package/dist/src/commands/evaluate-helpers.js.map +1 -0
  59. package/dist/src/commands/install.d.ts +118 -0
  60. package/dist/src/commands/install.d.ts.map +1 -0
  61. package/dist/src/commands/install.js +975 -0
  62. package/dist/src/commands/install.js.map +1 -0
  63. package/dist/src/commands/release.d.ts +7 -0
  64. package/dist/src/commands/release.d.ts.map +1 -0
  65. package/dist/src/commands/release.js +123 -0
  66. package/dist/src/commands/release.js.map +1 -0
  67. package/dist/src/commands/reset-connection.d.ts +17 -0
  68. package/dist/src/commands/reset-connection.d.ts.map +1 -0
  69. package/dist/src/commands/reset-connection.js +141 -0
  70. package/dist/src/commands/reset-connection.js.map +1 -0
  71. package/dist/src/commands/session-debug.d.ts +23 -0
  72. package/dist/src/commands/session-debug.d.ts.map +1 -0
  73. package/dist/src/commands/session-debug.js +267 -0
  74. package/dist/src/commands/session-debug.js.map +1 -0
  75. package/dist/src/commands/setup.d.ts +53 -0
  76. package/dist/src/commands/setup.d.ts.map +1 -0
  77. package/dist/src/commands/setup.js +249 -0
  78. package/dist/src/commands/setup.js.map +1 -0
  79. package/dist/src/config/store.d.ts +39 -0
  80. package/dist/src/config/store.d.ts.map +1 -0
  81. package/dist/src/config/store.js +290 -0
  82. package/dist/src/config/store.js.map +1 -0
  83. package/dist/src/daemon/access.d.ts +53 -0
  84. package/dist/src/daemon/access.d.ts.map +1 -0
  85. package/dist/src/daemon/access.js +87 -0
  86. package/dist/src/daemon/access.js.map +1 -0
  87. package/dist/src/daemon/bridge-envelope.d.ts +96 -0
  88. package/dist/src/daemon/bridge-envelope.d.ts.map +1 -0
  89. package/dist/src/daemon/bridge-envelope.js +235 -0
  90. package/dist/src/daemon/bridge-envelope.js.map +1 -0
  91. package/dist/src/daemon/utils.d.ts +43 -0
  92. package/dist/src/daemon/utils.d.ts.map +1 -0
  93. package/dist/src/daemon/utils.js +134 -0
  94. package/dist/src/daemon/utils.js.map +1 -0
  95. package/dist/src/errors.d.ts +60 -0
  96. package/dist/src/errors.d.ts.map +1 -0
  97. package/dist/src/errors.js +87 -0
  98. package/dist/src/errors.js.map +1 -0
  99. package/dist/src/local-bridge-timing.d.ts +31 -0
  100. package/dist/src/local-bridge-timing.d.ts.map +1 -0
  101. package/dist/src/local-bridge-timing.js +41 -0
  102. package/dist/src/local-bridge-timing.js.map +1 -0
  103. package/dist/src/obstacle-recovery/classify-script.d.ts +16 -0
  104. package/dist/src/obstacle-recovery/classify-script.d.ts.map +1 -0
  105. package/dist/src/obstacle-recovery/classify-script.js +53 -0
  106. package/dist/src/obstacle-recovery/classify-script.js.map +1 -0
  107. package/dist/src/obstacle-recovery/obstacle-classifier.d.ts +21 -0
  108. package/dist/src/obstacle-recovery/obstacle-classifier.d.ts.map +1 -0
  109. package/dist/src/obstacle-recovery/obstacle-classifier.js +37 -0
  110. package/dist/src/obstacle-recovery/obstacle-classifier.js.map +1 -0
  111. package/dist/src/obstacle-recovery/state-fingerprint.d.ts +26 -0
  112. package/dist/src/obstacle-recovery/state-fingerprint.d.ts.map +1 -0
  113. package/dist/src/obstacle-recovery/state-fingerprint.js +85 -0
  114. package/dist/src/obstacle-recovery/state-fingerprint.js.map +1 -0
  115. package/dist/src/obstacle-recovery/types.d.ts +44 -0
  116. package/dist/src/obstacle-recovery/types.d.ts.map +1 -0
  117. package/dist/src/obstacle-recovery/types.js +16 -0
  118. package/dist/src/obstacle-recovery/types.js.map +1 -0
  119. package/dist/src/output/formatter.d.ts +55 -0
  120. package/dist/src/output/formatter.d.ts.map +1 -0
  121. package/dist/src/output/formatter.js +55 -0
  122. package/dist/src/output/formatter.js.map +1 -0
  123. package/dist/src/output/mode.d.ts +11 -0
  124. package/dist/src/output/mode.d.ts.map +1 -0
  125. package/dist/src/output/mode.js +16 -0
  126. package/dist/src/output/mode.js.map +1 -0
  127. package/dist/src/protected-flow/detector.d.ts +26 -0
  128. package/dist/src/protected-flow/detector.d.ts.map +1 -0
  129. package/dist/src/protected-flow/detector.js +75 -0
  130. package/dist/src/protected-flow/detector.js.map +1 -0
  131. package/dist/src/protected-flow/types.d.ts +24 -0
  132. package/dist/src/protected-flow/types.d.ts.map +1 -0
  133. package/dist/src/protected-flow/types.js +28 -0
  134. package/dist/src/protected-flow/types.js.map +1 -0
  135. package/dist/src/session/agent-identity.d.ts +65 -0
  136. package/dist/src/session/agent-identity.d.ts.map +1 -0
  137. package/dist/src/session/agent-identity.js +133 -0
  138. package/dist/src/session/agent-identity.js.map +1 -0
  139. package/dist/src/session/cli-session-sync.d.ts +72 -0
  140. package/dist/src/session/cli-session-sync.d.ts.map +1 -0
  141. package/dist/src/session/cli-session-sync.js +244 -0
  142. package/dist/src/session/cli-session-sync.js.map +1 -0
  143. package/dist/src/session/context.d.ts +24 -0
  144. package/dist/src/session/context.d.ts.map +1 -0
  145. package/dist/src/session/context.js +165 -0
  146. package/dist/src/session/context.js.map +1 -0
  147. package/dist/src/session/continuity.d.ts +33 -0
  148. package/dist/src/session/continuity.d.ts.map +1 -0
  149. package/dist/src/session/continuity.js +179 -0
  150. package/dist/src/session/continuity.js.map +1 -0
  151. package/dist/src/session/errors.d.ts +9 -0
  152. package/dist/src/session/errors.d.ts.map +1 -0
  153. package/dist/src/session/errors.js +31 -0
  154. package/dist/src/session/errors.js.map +1 -0
  155. package/dist/src/session/local-continuity.d.ts +16 -0
  156. package/dist/src/session/local-continuity.d.ts.map +1 -0
  157. package/dist/src/session/local-continuity.js +146 -0
  158. package/dist/src/session/local-continuity.js.map +1 -0
  159. package/dist/src/session/signal-handler.d.ts +24 -0
  160. package/dist/src/session/signal-handler.d.ts.map +1 -0
  161. package/dist/src/session/signal-handler.js +35 -0
  162. package/dist/src/session/signal-handler.js.map +1 -0
  163. package/dist/src/shared/local-recovery-policy.d.ts +40 -0
  164. package/dist/src/shared/local-recovery-policy.d.ts.map +1 -0
  165. package/dist/src/shared/local-recovery-policy.js +59 -0
  166. package/dist/src/shared/local-recovery-policy.js.map +1 -0
  167. package/dist/src/shared/recovery-state.d.ts +3 -0
  168. package/dist/src/shared/recovery-state.d.ts.map +1 -0
  169. package/dist/src/shared/recovery-state.js +9 -0
  170. package/dist/src/shared/recovery-state.js.map +1 -0
  171. package/dist/src/types.d.ts +131 -0
  172. package/dist/src/types.d.ts.map +1 -0
  173. package/dist/src/types.js +5 -0
  174. package/dist/src/types.js.map +1 -0
  175. package/dist/src/utils.d.ts +50 -0
  176. package/dist/src/utils.d.ts.map +1 -0
  177. package/dist/src/utils.js +147 -0
  178. package/dist/src/utils.js.map +1 -0
  179. package/dist/src/working-location.d.ts +107 -0
  180. package/dist/src/working-location.d.ts.map +1 -0
  181. package/dist/src/working-location.js +651 -0
  182. package/dist/src/working-location.js.map +1 -0
  183. package/package.json +65 -0
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Shared local-bridge timing contract.
3
+ *
4
+ * This file is the checked-in source of truth for the reconnect/retry numbers
5
+ * that have to fit together across the native host and both CLI entrypoints.
6
+ *
7
+ * Contract:
8
+ * - Native host keeps the HTTP bridge alive for 90s after extension disconnect.
9
+ * - Typed CLI requests stay responsive with a 10s routine timeout and a 30s
10
+ * health probe timeout.
11
+ * - The typed adapter gets at most one immediate replay after a route change
12
+ * or successful live revalidation (2 attempts total).
13
+ * - The shell wrapper only does short patient retries for safe observational
14
+ * reads: 3 attempts total with 1s then 2s delays (3s total backoff budget).
15
+ *
16
+ * The retry budgets are intentionally much smaller than the native-host grace
17
+ * window so a flapping bridge fails fast instead of being hidden behind long,
18
+ * contradictory patient retry loops.
19
+ */
20
+ export const LOCAL_BRIDGE_RECONNECT_GRACE_MS = 90_000;
21
+ export const LOCAL_BRIDGE_HEALTH_PROBE_TIMEOUT_MS = 30_000;
22
+ export const LOCAL_BRIDGE_REQUEST_TIMEOUT_MS = 10_000;
23
+ export const LOCAL_BRIDGE_TYPED_TRANSPORT_RECOVERY_ATTEMPTS = 2;
24
+ export const LOCAL_BRIDGE_TYPED_EXTENSION_REVALIDATION_DELAYS_MS = [250, 500, 1_000];
25
+ export const LOCAL_BRIDGE_TYPED_RECENT_DISCONNECT_GRACE_MS = 5_000;
26
+ export const LOCAL_BRIDGE_SHELL_SAFE_READ_RETRY_MAX_ATTEMPTS = 3;
27
+ export const LOCAL_BRIDGE_SHELL_SAFE_READ_RETRY_INITIAL_DELAY_MS = 1_000;
28
+ export const LOCAL_BRIDGE_SHELL_SAFE_READ_RETRY_BACKOFF_MULTIPLIER = 2;
29
+ export function getLocalBridgeShellSafeReadRetryDelaysMs() {
30
+ const delays = [];
31
+ let delay = LOCAL_BRIDGE_SHELL_SAFE_READ_RETRY_INITIAL_DELAY_MS;
32
+ for (let attempt = 1; attempt < LOCAL_BRIDGE_SHELL_SAFE_READ_RETRY_MAX_ATTEMPTS; attempt += 1) {
33
+ delays.push(delay);
34
+ delay *= LOCAL_BRIDGE_SHELL_SAFE_READ_RETRY_BACKOFF_MULTIPLIER;
35
+ }
36
+ return delays;
37
+ }
38
+ export function getLocalBridgeShellSafeReadRetryBudgetMs() {
39
+ return getLocalBridgeShellSafeReadRetryDelaysMs().reduce((sum, delay) => sum + delay, 0);
40
+ }
41
+ //# sourceMappingURL=local-bridge-timing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-bridge-timing.js","sourceRoot":"","sources":["../../src/local-bridge-timing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,MAAM,CAAC,MAAM,+BAA+B,GAAG,MAAM,CAAC;AAEtD,MAAM,CAAC,MAAM,oCAAoC,GAAG,MAAM,CAAC;AAC3D,MAAM,CAAC,MAAM,+BAA+B,GAAG,MAAM,CAAC;AAEtD,MAAM,CAAC,MAAM,8CAA8C,GAAG,CAAC,CAAC;AAChE,MAAM,CAAC,MAAM,mDAAmD,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,CAAU,CAAC;AAC9F,MAAM,CAAC,MAAM,6CAA6C,GAAG,KAAK,CAAC;AAEnE,MAAM,CAAC,MAAM,+CAA+C,GAAG,CAAC,CAAC;AACjE,MAAM,CAAC,MAAM,mDAAmD,GAAG,KAAK,CAAC;AACzE,MAAM,CAAC,MAAM,qDAAqD,GAAG,CAAC,CAAC;AAEvE,MAAM,UAAU,wCAAwC;IACtD,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,KAAK,GAAG,mDAAmD,CAAC;IAChE,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,+CAA+C,EAAE,OAAO,IAAI,CAAC,EAAE,CAAC;QAC9F,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnB,KAAK,IAAI,qDAAqD,CAAC;IACjE,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,wCAAwC;IACtD,OAAO,wCAAwC,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC;AAC3F,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Shared inline JS diagnostic script for element obstacle classification.
3
+ * Used by both CLI obstacle-classifier (via evaluateFn) and backend obstacle-detector (via page.evaluate).
4
+ * Also duplicated in extension/background/browser-commands.ts (classifyElementFailure) which uses
5
+ * chrome.scripting.executeScript with a func parameter — that copy must be maintained separately
6
+ * as it cannot import this module, but should match this logic.
7
+ *
8
+ * IMPORTANT: When updating this script, also update the extension copy in browser-commands.ts.
9
+ */
10
+ export declare const CLASSIFY_ELEMENT_SCRIPT = "(() => {\n const selector = __SELECTOR__;\n let el;\n try { el = document.querySelector(selector); } catch(e) { return null; }\n if (el) {\n const style = getComputedStyle(el);\n if (style.display === 'none' || style.visibility === 'hidden') return 'not_visible';\n if (el.hasAttribute('disabled') || style.pointerEvents === 'none') return 'not_interactive';\n const rect = el.getBoundingClientRect();\n if (rect.bottom < 0 || rect.top > window.innerHeight || rect.right < 0 || rect.left > window.innerWidth) return 'off_screen';\n return null;\n }\n const iframes = document.querySelectorAll('iframe');\n let crossOriginIframeFound = false;\n for (const iframe of iframes) {\n try {\n const doc = iframe.contentDocument;\n if (doc === null) { crossOriginIframeFound = true; continue; }\n if (doc.querySelector(selector)) return 'element_in_iframe';\n } catch (e) { crossOriginIframeFound = true; }\n }\n function searchShadow(root) {\n for (const child of root.querySelectorAll('*')) {\n if (child.shadowRoot) {\n try {\n if (child.shadowRoot.querySelector(selector)) return true;\n if (searchShadow(child.shadowRoot)) return true;\n } catch (e) {}\n }\n }\n return false;\n }\n if (searchShadow(document.documentElement)) return 'element_in_shadow_dom';\n if (crossOriginIframeFound) return 'cross_origin_blocked';\n return 'element_not_found';\n})()";
11
+ /**
12
+ * Build the classification script with a specific selector safely embedded.
13
+ * Uses JSON.stringify to prevent XSS injection via selector content.
14
+ */
15
+ export declare function buildClassifyScript(selector: string): string;
16
+ //# sourceMappingURL=classify-script.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classify-script.d.ts","sourceRoot":"","sources":["../../../src/obstacle-recovery/classify-script.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,eAAO,MAAM,uBAAuB,q7CAmC/B,CAAC;AAEN;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE5D"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Shared inline JS diagnostic script for element obstacle classification.
3
+ * Used by both CLI obstacle-classifier (via evaluateFn) and backend obstacle-detector (via page.evaluate).
4
+ * Also duplicated in extension/background/browser-commands.ts (classifyElementFailure) which uses
5
+ * chrome.scripting.executeScript with a func parameter — that copy must be maintained separately
6
+ * as it cannot import this module, but should match this logic.
7
+ *
8
+ * IMPORTANT: When updating this script, also update the extension copy in browser-commands.ts.
9
+ */
10
+ export const CLASSIFY_ELEMENT_SCRIPT = `(() => {
11
+ const selector = __SELECTOR__;
12
+ let el;
13
+ try { el = document.querySelector(selector); } catch(e) { return null; }
14
+ if (el) {
15
+ const style = getComputedStyle(el);
16
+ if (style.display === 'none' || style.visibility === 'hidden') return 'not_visible';
17
+ if (el.hasAttribute('disabled') || style.pointerEvents === 'none') return 'not_interactive';
18
+ const rect = el.getBoundingClientRect();
19
+ if (rect.bottom < 0 || rect.top > window.innerHeight || rect.right < 0 || rect.left > window.innerWidth) return 'off_screen';
20
+ return null;
21
+ }
22
+ const iframes = document.querySelectorAll('iframe');
23
+ let crossOriginIframeFound = false;
24
+ for (const iframe of iframes) {
25
+ try {
26
+ const doc = iframe.contentDocument;
27
+ if (doc === null) { crossOriginIframeFound = true; continue; }
28
+ if (doc.querySelector(selector)) return 'element_in_iframe';
29
+ } catch (e) { crossOriginIframeFound = true; }
30
+ }
31
+ function searchShadow(root) {
32
+ for (const child of root.querySelectorAll('*')) {
33
+ if (child.shadowRoot) {
34
+ try {
35
+ if (child.shadowRoot.querySelector(selector)) return true;
36
+ if (searchShadow(child.shadowRoot)) return true;
37
+ } catch (e) {}
38
+ }
39
+ }
40
+ return false;
41
+ }
42
+ if (searchShadow(document.documentElement)) return 'element_in_shadow_dom';
43
+ if (crossOriginIframeFound) return 'cross_origin_blocked';
44
+ return 'element_not_found';
45
+ })()`;
46
+ /**
47
+ * Build the classification script with a specific selector safely embedded.
48
+ * Uses JSON.stringify to prevent XSS injection via selector content.
49
+ */
50
+ export function buildClassifyScript(selector) {
51
+ return CLASSIFY_ELEMENT_SCRIPT.replace('__SELECTOR__', JSON.stringify(selector));
52
+ }
53
+ //# sourceMappingURL=classify-script.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classify-script.js","sourceRoot":"","sources":["../../../src/obstacle-recovery/classify-script.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAmClC,CAAC;AAEN;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAAgB;IAClD,OAAO,uBAAuB,CAAC,OAAO,CAAC,cAAc,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;AACnF,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Obstacle classifier — diagnoses WHY a selector lookup failed.
3
+ *
4
+ * Runs a single evaluate call with a diagnostic JS script that checks
5
+ * visibility, interactivity, viewport bounds, iframes, and shadow DOM
6
+ * before falling back to 'element_not_found'.
7
+ */
8
+ import type { ObstacleType } from './types.js';
9
+ /**
10
+ * Classify why an element selector lookup failed by running diagnostic
11
+ * JavaScript on the page via the provided evaluate function.
12
+ *
13
+ * The selector is embedded safely using JSON.stringify to prevent XSS
14
+ * (handled by buildClassifyScript).
15
+ *
16
+ * @param selector CSS selector that failed to match or interact
17
+ * @param evaluateFn Executes a JS script string on the page and returns the result
18
+ * @returns The classified obstacle type
19
+ */
20
+ export declare function classifyElementFailure(selector: string, evaluateFn: (script: string) => Promise<any>): Promise<ObstacleType>;
21
+ //# sourceMappingURL=obstacle-classifier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"obstacle-classifier.d.ts","sourceRoot":"","sources":["../../../src/obstacle-recovery/obstacle-classifier.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG/C;;;;;;;;;;GAUG;AACH,wBAAsB,sBAAsB,CAC1C,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,CAAC,GAC3C,OAAO,CAAC,YAAY,CAAC,CAevB"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Obstacle classifier — diagnoses WHY a selector lookup failed.
3
+ *
4
+ * Runs a single evaluate call with a diagnostic JS script that checks
5
+ * visibility, interactivity, viewport bounds, iframes, and shadow DOM
6
+ * before falling back to 'element_not_found'.
7
+ */
8
+ import { buildClassifyScript } from './classify-script.js';
9
+ /**
10
+ * Classify why an element selector lookup failed by running diagnostic
11
+ * JavaScript on the page via the provided evaluate function.
12
+ *
13
+ * The selector is embedded safely using JSON.stringify to prevent XSS
14
+ * (handled by buildClassifyScript).
15
+ *
16
+ * @param selector CSS selector that failed to match or interact
17
+ * @param evaluateFn Executes a JS script string on the page and returns the result
18
+ * @returns The classified obstacle type
19
+ */
20
+ export async function classifyElementFailure(selector, evaluateFn) {
21
+ const script = buildClassifyScript(selector);
22
+ // 3s timeout — classification is best-effort, must not block the error path
23
+ let timeoutId;
24
+ const timeoutPromise = new Promise(r => { timeoutId = setTimeout(() => r(null), 3000); });
25
+ let result;
26
+ try {
27
+ result = await Promise.race([evaluateFn(script), timeoutPromise]);
28
+ }
29
+ finally {
30
+ if (timeoutId)
31
+ clearTimeout(timeoutId);
32
+ }
33
+ // null means element was found and appeared healthy — no obstacle detected,
34
+ // but we still ended up here because the action failed. Fall back to generic.
35
+ return (result ?? 'element_not_found');
36
+ }
37
+ //# sourceMappingURL=obstacle-classifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"obstacle-classifier.js","sourceRoot":"","sources":["../../../src/obstacle-recovery/obstacle-classifier.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAE3D;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,QAAgB,EAChB,UAA4C;IAE5C,MAAM,MAAM,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAC;IAE7C,4EAA4E;IAC5E,IAAI,SAAoD,CAAC;IACzD,MAAM,cAAc,GAAG,IAAI,OAAO,CAAO,CAAC,CAAC,EAAE,GAAG,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAChG,IAAI,MAAW,CAAC;IAChB,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,cAAc,CAAC,CAAC,CAAC;IACpE,CAAC;YAAS,CAAC;QACT,IAAI,SAAS;YAAE,YAAY,CAAC,SAAS,CAAC,CAAC;IACzC,CAAC;IACD,4EAA4E;IAC5E,8EAA8E;IAC9E,OAAO,CAAC,MAAM,IAAI,mBAAmB,CAAiB,CAAC;AACzD,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * State fingerprint capture and comparison for obstacle recovery.
3
+ *
4
+ * Captures a lightweight snapshot of page state (URL, title, focused element,
5
+ * form values) before and after an action so the agent can detect whether
6
+ * the action had any effect.
7
+ */
8
+ import type { StateFingerprint, StateComparisonResult } from './types.js';
9
+ /**
10
+ * Capture a state fingerprint by evaluating a script on the current page.
11
+ *
12
+ * @param evaluateFn - mirrors the adapter's `evaluate()`: takes a JS string,
13
+ * returns the serialized result.
14
+ * @returns A StateFingerprint, or a fallback fingerprint with empty values
15
+ * if the evaluate call fails (e.g. page crashed, navigation in progress).
16
+ */
17
+ export declare function captureFingerprint(evaluateFn: (script: string) => Promise<any>): Promise<StateFingerprint>;
18
+ /**
19
+ * Compare two state fingerprints and classify the change.
20
+ *
21
+ * - `'navigated'` — the URL changed (different page entirely).
22
+ * - `'unchanged'` — every field matches (action had no visible effect).
23
+ * - `'changed'` — same URL but something else differs.
24
+ */
25
+ export declare function compareFingerprints(before: StateFingerprint, after: StateFingerprint): StateComparisonResult;
26
+ //# sourceMappingURL=state-fingerprint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-fingerprint.d.ts","sourceRoot":"","sources":["../../../src/obstacle-recovery/state-fingerprint.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAsB1E;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,CAAC,GAC3C,OAAO,CAAC,gBAAgB,CAAC,CAyB3B;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,gBAAgB,EACxB,KAAK,EAAE,gBAAgB,GACtB,qBAAqB,CAcvB"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * State fingerprint capture and comparison for obstacle recovery.
3
+ *
4
+ * Captures a lightweight snapshot of page state (URL, title, focused element,
5
+ * form values) before and after an action so the agent can detect whether
6
+ * the action had any effect.
7
+ */
8
+ /**
9
+ * JavaScript snippet executed on the page to collect serializable state.
10
+ * Returns a plain object — no DOM references — so it survives the
11
+ * evaluate round-trip.
12
+ */
13
+ const CAPTURE_SCRIPT = `(() => {
14
+ const focused = document.activeElement
15
+ ? document.activeElement.tagName + '#' + (document.activeElement.id || '') + '.' + (document.activeElement.className || '')
16
+ : null;
17
+ const formValues = Array.from(document.querySelectorAll('input,select,textarea'))
18
+ .map(function(e) { var t = e.type; var k = e.name || e.id || ''; return (t === 'checkbox' || t === 'radio') ? k + '=' + e.checked : k + '=' + e.value; })
19
+ .join('&');
20
+ return {
21
+ url: location.href,
22
+ title: document.title,
23
+ focusedElement: focused,
24
+ formValues: formValues
25
+ };
26
+ })()`;
27
+ /**
28
+ * Capture a state fingerprint by evaluating a script on the current page.
29
+ *
30
+ * @param evaluateFn - mirrors the adapter's `evaluate()`: takes a JS string,
31
+ * returns the serialized result.
32
+ * @returns A StateFingerprint, or a fallback fingerprint with empty values
33
+ * if the evaluate call fails (e.g. page crashed, navigation in progress).
34
+ */
35
+ export async function captureFingerprint(evaluateFn) {
36
+ try {
37
+ const result = await evaluateFn(CAPTURE_SCRIPT);
38
+ // Defensively validate the shape — the page could return anything.
39
+ if (result &&
40
+ typeof result === 'object' &&
41
+ typeof result.url === 'string' &&
42
+ typeof result.title === 'string') {
43
+ return {
44
+ url: result.url,
45
+ title: result.title,
46
+ focusedElement: result.focusedElement != null ? String(result.focusedElement) : null,
47
+ formValues: result.formValues != null ? String(result.formValues) : '',
48
+ };
49
+ }
50
+ // Result was truthy but wrong shape — return empty fingerprint.
51
+ return emptyFingerprint();
52
+ }
53
+ catch {
54
+ // Evaluate failed (page crash, navigation, timeout, etc.)
55
+ return emptyFingerprint();
56
+ }
57
+ }
58
+ /**
59
+ * Compare two state fingerprints and classify the change.
60
+ *
61
+ * - `'navigated'` — the URL changed (different page entirely).
62
+ * - `'unchanged'` — every field matches (action had no visible effect).
63
+ * - `'changed'` — same URL but something else differs.
64
+ */
65
+ export function compareFingerprints(before, after) {
66
+ if (before.url !== after.url) {
67
+ return 'navigated';
68
+ }
69
+ if (before.title === after.title &&
70
+ before.focusedElement === after.focusedElement &&
71
+ before.formValues === after.formValues) {
72
+ return 'unchanged';
73
+ }
74
+ return 'changed';
75
+ }
76
+ /** Returns a fingerprint with safe empty defaults. */
77
+ function emptyFingerprint() {
78
+ return {
79
+ url: '',
80
+ title: '',
81
+ focusedElement: null,
82
+ formValues: '',
83
+ };
84
+ }
85
+ //# sourceMappingURL=state-fingerprint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-fingerprint.js","sourceRoot":"","sources":["../../../src/obstacle-recovery/state-fingerprint.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH;;;;GAIG;AACH,MAAM,cAAc,GAAG;;;;;;;;;;;;;KAalB,CAAC;AAEN;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,UAA4C;IAE5C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,cAAc,CAAC,CAAC;QAChD,mEAAmE;QACnE,IACE,MAAM;YACN,OAAO,MAAM,KAAK,QAAQ;YAC1B,OAAO,MAAM,CAAC,GAAG,KAAK,QAAQ;YAC9B,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ,EAChC,CAAC;YACD,OAAO;gBACL,GAAG,EAAE,MAAM,CAAC,GAAG;gBACf,KAAK,EAAE,MAAM,CAAC,KAAK;gBACnB,cAAc,EACZ,MAAM,CAAC,cAAc,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,IAAI;gBACtE,UAAU,EACR,MAAM,CAAC,UAAU,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE;aAC7D,CAAC;QACJ,CAAC;QACD,gEAAgE;QAChE,OAAO,gBAAgB,EAAE,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,0DAA0D;QAC1D,OAAO,gBAAgB,EAAE,CAAC;IAC5B,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CACjC,MAAwB,EACxB,KAAuB;IAEvB,IAAI,MAAM,CAAC,GAAG,KAAK,KAAK,CAAC,GAAG,EAAE,CAAC;QAC7B,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,IACE,MAAM,CAAC,KAAK,KAAK,KAAK,CAAC,KAAK;QAC5B,MAAM,CAAC,cAAc,KAAK,KAAK,CAAC,cAAc;QAC9C,MAAM,CAAC,UAAU,KAAK,KAAK,CAAC,UAAU,EACtC,CAAC;QACD,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,sDAAsD;AACtD,SAAS,gBAAgB;IACvB,OAAO;QACL,GAAG,EAAE,EAAE;QACP,KAAK,EAAE,EAAE;QACT,cAAc,EAAE,IAAI;QACpB,UAAU,EAAE,EAAE;KACf,CAAC;AACJ,CAAC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Obstacle recovery types for agent resilience.
3
+ * Used by state fingerprinting, obstacle classification, and escalation orchestrator.
4
+ */
5
+ /** Why an element lookup or action failed — enriches ELEMENT_NOT_FOUND with actionable context. */
6
+ export type ObstacleType = 'element_not_found' | 'element_in_iframe' | 'element_in_shadow_dom' | 'not_visible' | 'not_interactive' | 'off_screen' | 'action_no_op' | 'cross_origin_blocked';
7
+ /** Lightweight page state for pre/post action comparison. */
8
+ export interface StateFingerprint {
9
+ url: string;
10
+ title: string;
11
+ /** Tag name + id/class of the focused element, or null. */
12
+ focusedElement: string | null;
13
+ /** Serialized form values of the target region (or page-wide). */
14
+ formValues: string;
15
+ /** Optional hash of visible text content near the target element. */
16
+ targetHash?: string;
17
+ }
18
+ /** Result of comparing two state fingerprints. */
19
+ export type StateComparisonResult = 'changed' | 'unchanged' | 'navigated';
20
+ /** Which escalation tier resolved the action. */
21
+ export type EscalationTier = 'css' | 'scroll_retry' | 'shadow_pierce' | 'frame_search' | 'coordinate_click' | 'keyboard' | 'handoff';
22
+ /** Audit entry for one escalation attempt. */
23
+ export interface EscalationAttempt {
24
+ tier: EscalationTier;
25
+ selector: string;
26
+ result: 'success' | 'fail' | 'no_op';
27
+ obstacleType?: ObstacleType;
28
+ timeMs: number;
29
+ }
30
+ /** Result of running the full escalation ladder for one action. */
31
+ export interface EscalationResult {
32
+ success: boolean;
33
+ /** Which tier ultimately resolved the action (or 'handoff' if all failed). */
34
+ resolvedBy: EscalationTier;
35
+ /** Full audit trail of every tier attempted. */
36
+ attempts: EscalationAttempt[];
37
+ /** Total time across all tiers. */
38
+ totalTimeMs: number;
39
+ /** Obstacle classification from the final failure, if any. */
40
+ obstacleType?: ObstacleType;
41
+ }
42
+ /** Human-facing hints for each obstacle type. */
43
+ export declare const OBSTACLE_HINTS: Record<ObstacleType, string>;
44
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/obstacle-recovery/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,mGAAmG;AACnG,MAAM,MAAM,YAAY,GACpB,mBAAmB,GACnB,mBAAmB,GACnB,uBAAuB,GACvB,aAAa,GACb,iBAAiB,GACjB,YAAY,GACZ,cAAc,GACd,sBAAsB,CAAC;AAE3B,6DAA6D;AAC7D,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,2DAA2D;IAC3D,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,kEAAkE;IAClE,UAAU,EAAE,MAAM,CAAC;IACnB,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,kDAAkD;AAClD,MAAM,MAAM,qBAAqB,GAAG,SAAS,GAAG,WAAW,GAAG,WAAW,CAAC;AAE1E,iDAAiD;AACjD,MAAM,MAAM,cAAc,GACtB,KAAK,GACL,cAAc,GACd,eAAe,GACf,cAAc,GACd,kBAAkB,GAClB,UAAU,GACV,SAAS,CAAC;AAEd,8CAA8C;AAC9C,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,cAAc,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC;IACrC,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,mEAAmE;AACnE,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,8EAA8E;IAC9E,UAAU,EAAE,cAAc,CAAC;IAC3B,gDAAgD;IAChD,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B,mCAAmC;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,8DAA8D;IAC9D,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED,iDAAiD;AACjD,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,YAAY,EAAE,MAAM,CASvD,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Obstacle recovery types for agent resilience.
3
+ * Used by state fingerprinting, obstacle classification, and escalation orchestrator.
4
+ */
5
+ /** Human-facing hints for each obstacle type. */
6
+ export const OBSTACLE_HINTS = {
7
+ element_not_found: 'Selector matched nothing. Run `thinkrun snapshot` to inspect page structure.',
8
+ element_in_iframe: 'Element is inside an iframe. Try a frame-aware selector or coordinate click.',
9
+ element_in_shadow_dom: 'Element is inside a shadow DOM. Use `>>>` syntax: `host >>> inner-selector`.',
10
+ not_visible: 'Element exists but is hidden (display:none or visibility:hidden). Wait for it to become visible.',
11
+ not_interactive: 'Element is disabled or has pointer-events:none. Wait for it to become interactive.',
12
+ off_screen: 'Element exists but is outside the viewport. Scroll to it first.',
13
+ action_no_op: 'Action fired but page state did not change. The element may need a different interaction method.',
14
+ cross_origin_blocked: 'Element is in a cross-origin iframe. Use coordinate click or human handoff.',
15
+ };
16
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/obstacle-recovery/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA4DH,iDAAiD;AACjD,MAAM,CAAC,MAAM,cAAc,GAAiC;IAC1D,iBAAiB,EAAE,8EAA8E;IACjG,iBAAiB,EAAE,8EAA8E;IACjG,qBAAqB,EAAE,8EAA8E;IACrG,WAAW,EAAE,kGAAkG;IAC/G,eAAe,EAAE,oFAAoF;IACrG,UAAU,EAAE,iEAAiE;IAC7E,YAAY,EAAE,kGAAkG;IAChH,oBAAoB,EAAE,6EAA6E;CACpG,CAAC"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Output formatting utilities.
3
+ * Handles JSON vs pretty output modes.
4
+ *
5
+ * Use `createSpinner(text)` instead of ora() directly so that spinners
6
+ * are automatically suppressed in JSON mode. Use `emitJson(envelope)`
7
+ * to output machine-readable results in JSON mode.
8
+ */
9
+ export interface JsonEnvelope {
10
+ success: boolean;
11
+ command?: string;
12
+ durationMs?: number;
13
+ data?: any;
14
+ error?: string;
15
+ code?: string;
16
+ hint?: string;
17
+ retryable?: boolean;
18
+ blocked?: boolean;
19
+ /** Resolved execution mode (when available). */
20
+ mode?: 'local' | 'cloud';
21
+ /** How mode was determined: explicit flag, context, or fallback. */
22
+ modeSource?: string;
23
+ }
24
+ /**
25
+ * Emit a single JSON line to stdout. Always one line — no pretty-print —
26
+ * so agents can reliably parse line-by-line.
27
+ */
28
+ export declare function emitJson(envelope: JsonEnvelope): void;
29
+ type SpinnerLike = {
30
+ succeed(msg?: string): void;
31
+ fail(msg?: string): void;
32
+ stop(): void;
33
+ set text(val: string);
34
+ };
35
+ /**
36
+ * Returns an ora spinner in TTY mode, or a no-op object in JSON mode.
37
+ * Callers should always call `spinner.succeed()` / `spinner.fail()` —
38
+ * in JSON mode these are silent and `emitJson()` handles output.
39
+ */
40
+ export declare function createSpinner(text: string): SpinnerLike;
41
+ export interface FormattedOutput {
42
+ success: boolean;
43
+ data?: any;
44
+ error?: string;
45
+ code?: string;
46
+ }
47
+ export declare function formatOutput(result: FormattedOutput, options?: {
48
+ json?: boolean;
49
+ quiet?: boolean;
50
+ }): void;
51
+ export declare function shouldUseJSON(globalOptions?: {
52
+ json?: boolean;
53
+ }): boolean;
54
+ export {};
55
+ //# sourceMappingURL=formatter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatter.d.ts","sourceRoot":"","sources":["../../../src/output/formatter.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAUH,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,gDAAgD;IAChD,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IACzB,oEAAoE;IACpE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAMD;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI,CAErD;AAMD,KAAK,WAAW,GAAG;IACjB,OAAO,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,IAAI,IAAI,IAAI,CAAC;IACb,IAAI,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE;CACvB,CAAC;AASF;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAGvD;AAMD,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,eAAe,EAAE,OAAO,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAWzG;AAED,wBAAgB,aAAa,CAAC,aAAa,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAEzE"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Output formatting utilities.
3
+ * Handles JSON vs pretty output modes.
4
+ *
5
+ * Use `createSpinner(text)` instead of ora() directly so that spinners
6
+ * are automatically suppressed in JSON mode. Use `emitJson(envelope)`
7
+ * to output machine-readable results in JSON mode.
8
+ */
9
+ import chalk from 'chalk';
10
+ import ora from 'ora';
11
+ import { isJsonMode } from './mode.js';
12
+ // ------------------------------------------------------------------
13
+ // JSON output
14
+ // ------------------------------------------------------------------
15
+ /**
16
+ * Emit a single JSON line to stdout. Always one line — no pretty-print —
17
+ * so agents can reliably parse line-by-line.
18
+ */
19
+ export function emitJson(envelope) {
20
+ console.log(JSON.stringify(envelope));
21
+ }
22
+ const NOOP_SPINNER = {
23
+ succeed: () => { },
24
+ fail: () => { },
25
+ stop: () => { },
26
+ set text(_) { },
27
+ };
28
+ /**
29
+ * Returns an ora spinner in TTY mode, or a no-op object in JSON mode.
30
+ * Callers should always call `spinner.succeed()` / `spinner.fail()` —
31
+ * in JSON mode these are silent and `emitJson()` handles output.
32
+ */
33
+ export function createSpinner(text) {
34
+ if (isJsonMode())
35
+ return NOOP_SPINNER;
36
+ return ora(text).start();
37
+ }
38
+ export function formatOutput(result, options) {
39
+ if (options?.quiet && result.success)
40
+ return;
41
+ if (options?.json || !process.stdout.isTTY) {
42
+ console.log(JSON.stringify(result, null, 2));
43
+ }
44
+ else {
45
+ if (!result.success && result.error) {
46
+ console.error(chalk.red('Error:'), result.error);
47
+ if (result.code)
48
+ console.error(chalk.gray(`Code: ${result.code}`));
49
+ }
50
+ }
51
+ }
52
+ export function shouldUseJSON(globalOptions) {
53
+ return globalOptions?.json === true || !process.stdout.isTTY;
54
+ }
55
+ //# sourceMappingURL=formatter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatter.js","sourceRoot":"","sources":["../../../src/output/formatter.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAsBvC,qEAAqE;AACrE,cAAc;AACd,qEAAqE;AAErE;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAC,QAAsB;IAC7C,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;AACxC,CAAC;AAaD,MAAM,YAAY,GAAgB;IAChC,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC;IACjB,IAAI,EAAE,GAAG,EAAE,GAAE,CAAC;IACd,IAAI,EAAE,GAAG,EAAE,GAAE,CAAC;IACd,IAAI,IAAI,CAAC,CAAS,IAAG,CAAC;CACvB,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,IAAI,UAAU,EAAE;QAAE,OAAO,YAAY,CAAC;IACtC,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;AAC3B,CAAC;AAaD,MAAM,UAAU,YAAY,CAAC,MAAuB,EAAE,OAA6C;IACjG,IAAI,OAAO,EAAE,KAAK,IAAI,MAAM,CAAC,OAAO;QAAE,OAAO;IAE7C,IAAI,OAAO,EAAE,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAC3C,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC/C,CAAC;SAAM,CAAC;QACN,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACpC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;YACjD,IAAI,MAAM,CAAC,IAAI;gBAAE,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACrE,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,aAAkC;IAC9D,OAAO,aAAa,EAAE,IAAI,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC;AAC/D,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * JSON mode singleton — shared across all commands.
3
+ * Set once at program startup via `setJsonMode(true)`.
4
+ *
5
+ * isJsonMode() returns true when:
6
+ * 1. Explicitly set via --json flag (setJsonMode(true))
7
+ * 2. stdout is not a TTY (piped/redirected — agent/script context)
8
+ */
9
+ export declare function setJsonMode(val: boolean): void;
10
+ export declare function isJsonMode(): boolean;
11
+ //# sourceMappingURL=mode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mode.d.ts","sourceRoot":"","sources":["../../../src/output/mode.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAE9C;AAED,wBAAgB,UAAU,IAAI,OAAO,CAEpC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * JSON mode singleton — shared across all commands.
3
+ * Set once at program startup via `setJsonMode(true)`.
4
+ *
5
+ * isJsonMode() returns true when:
6
+ * 1. Explicitly set via --json flag (setJsonMode(true))
7
+ * 2. stdout is not a TTY (piped/redirected — agent/script context)
8
+ */
9
+ let _jsonMode = false;
10
+ export function setJsonMode(val) {
11
+ _jsonMode = val;
12
+ }
13
+ export function isJsonMode() {
14
+ return _jsonMode || !process.stdout.isTTY;
15
+ }
16
+ //# sourceMappingURL=mode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mode.js","sourceRoot":"","sources":["../../../src/output/mode.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,IAAI,SAAS,GAAG,KAAK,CAAC;AAEtB,MAAM,UAAU,WAAW,CAAC,GAAY;IACtC,SAAS,GAAG,GAAG,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,OAAO,SAAS,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC;AAC5C,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Protected-flow classification: detect when an action did not change state or hit a protected element.
3
+ */
4
+ import type { BlockedOutcome, BlockerCategory } from './types.js';
5
+ import type { StateFingerprint } from '../obstacle-recovery/types.js';
6
+ /** Bridge can send this in action result data to signal blocked/handoff. */
7
+ export interface BridgeBlockedHint {
8
+ blocked?: boolean;
9
+ blockedReason?: BlockerCategory | string;
10
+ handoffRequired?: boolean;
11
+ target?: string;
12
+ }
13
+ /**
14
+ * Classify a bridge result into a blocked outcome when the bridge signals blocked.
15
+ * Returns null when the result does not indicate a blocked flow.
16
+ */
17
+ export declare function classifyFromBridgeResult(data: unknown): BlockedOutcome | null;
18
+ /**
19
+ * Classify from pre/post state comparison using StateFingerprint objects.
20
+ * Detects no-op actions by comparing page state before and after the action.
21
+ *
22
+ * Returns null if states differ (action had an effect) or if fingerprints are missing.
23
+ * Returns BlockedOutcome with 'no_op_click' if page state is unchanged.
24
+ */
25
+ export declare function classifyFromStateCheck(actionType: 'click' | 'type' | 'fill' | 'select', preState: StateFingerprint | string | undefined, postState: StateFingerprint | string | undefined): BlockedOutcome | null;
26
+ //# sourceMappingURL=detector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detector.d.ts","sourceRoot":"","sources":["../../../src/protected-flow/detector.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAEtE,4EAA4E;AAC5E,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,aAAa,CAAC,EAAE,eAAe,GAAG,MAAM,CAAC;IACzC,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,OAAO,GACZ,cAAc,GAAG,IAAI,CAWvB;AAgBD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,EAChD,QAAQ,EAAE,gBAAgB,GAAG,MAAM,GAAG,SAAS,EAC/C,SAAS,EAAE,gBAAgB,GAAG,MAAM,GAAG,SAAS,GAC/C,cAAc,GAAG,IAAI,CAgCvB"}