remoat 0.2.0

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 (200) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +297 -0
  3. package/dist/bin/cli.d.ts +2 -0
  4. package/dist/bin/cli.js +80 -0
  5. package/dist/bin/cli.js.map +1 -0
  6. package/dist/bin/commands/doctor.d.ts +1 -0
  7. package/dist/bin/commands/doctor.js +211 -0
  8. package/dist/bin/commands/doctor.js.map +1 -0
  9. package/dist/bin/commands/open.d.ts +1 -0
  10. package/dist/bin/commands/open.js +187 -0
  11. package/dist/bin/commands/open.js.map +1 -0
  12. package/dist/bin/commands/setup.d.ts +1 -0
  13. package/dist/bin/commands/setup.js +267 -0
  14. package/dist/bin/commands/setup.js.map +1 -0
  15. package/dist/bin/commands/start.d.ts +2 -0
  16. package/dist/bin/commands/start.js +39 -0
  17. package/dist/bin/commands/start.js.map +1 -0
  18. package/dist/bot/index.d.ts +2 -0
  19. package/dist/bot/index.js +1393 -0
  20. package/dist/bot/index.js.map +1 -0
  21. package/dist/commands/chatCommandHandler.d.ts +20 -0
  22. package/dist/commands/chatCommandHandler.js +30 -0
  23. package/dist/commands/chatCommandHandler.js.map +1 -0
  24. package/dist/commands/cleanupCommandHandler.d.ts +21 -0
  25. package/dist/commands/cleanupCommandHandler.js +40 -0
  26. package/dist/commands/cleanupCommandHandler.js.map +1 -0
  27. package/dist/commands/joinCommandHandler.d.ts +19 -0
  28. package/dist/commands/joinCommandHandler.js +27 -0
  29. package/dist/commands/joinCommandHandler.js.map +1 -0
  30. package/dist/commands/messageParser.d.ts +7 -0
  31. package/dist/commands/messageParser.js +29 -0
  32. package/dist/commands/messageParser.js.map +1 -0
  33. package/dist/commands/slashCommandHandler.d.ts +21 -0
  34. package/dist/commands/slashCommandHandler.js +105 -0
  35. package/dist/commands/slashCommandHandler.js.map +1 -0
  36. package/dist/commands/workspaceCommandHandler.d.ts +16 -0
  37. package/dist/commands/workspaceCommandHandler.js +29 -0
  38. package/dist/commands/workspaceCommandHandler.js.map +1 -0
  39. package/dist/database/chatSessionRepository.d.ts +59 -0
  40. package/dist/database/chatSessionRepository.js +110 -0
  41. package/dist/database/chatSessionRepository.js.map +1 -0
  42. package/dist/database/scheduleRepository.d.ts +60 -0
  43. package/dist/database/scheduleRepository.js +106 -0
  44. package/dist/database/scheduleRepository.js.map +1 -0
  45. package/dist/database/templateRepository.d.ts +51 -0
  46. package/dist/database/templateRepository.js +90 -0
  47. package/dist/database/templateRepository.js.map +1 -0
  48. package/dist/database/workspaceBindingRepository.d.ts +48 -0
  49. package/dist/database/workspaceBindingRepository.js +92 -0
  50. package/dist/database/workspaceBindingRepository.js.map +1 -0
  51. package/dist/index.d.ts +1 -0
  52. package/dist/index.js +11 -0
  53. package/dist/index.js.map +1 -0
  54. package/dist/middleware/auth.d.ts +5 -0
  55. package/dist/middleware/auth.js +14 -0
  56. package/dist/middleware/auth.js.map +1 -0
  57. package/dist/middleware/sanitize.d.ts +1 -0
  58. package/dist/middleware/sanitize.js +18 -0
  59. package/dist/middleware/sanitize.js.map +1 -0
  60. package/dist/services/antigravityLauncher.d.ts +7 -0
  61. package/dist/services/antigravityLauncher.js +94 -0
  62. package/dist/services/antigravityLauncher.js.map +1 -0
  63. package/dist/services/approvalDetector.d.ts +97 -0
  64. package/dist/services/approvalDetector.js +394 -0
  65. package/dist/services/approvalDetector.js.map +1 -0
  66. package/dist/services/assistantDomExtractor.d.ts +49 -0
  67. package/dist/services/assistantDomExtractor.js +340 -0
  68. package/dist/services/assistantDomExtractor.js.map +1 -0
  69. package/dist/services/autoAcceptService.d.ts +14 -0
  70. package/dist/services/autoAcceptService.js +81 -0
  71. package/dist/services/autoAcceptService.js.map +1 -0
  72. package/dist/services/cdpBridgeManager.d.ts +50 -0
  73. package/dist/services/cdpBridgeManager.js +355 -0
  74. package/dist/services/cdpBridgeManager.js.map +1 -0
  75. package/dist/services/cdpConnectionPool.d.ts +88 -0
  76. package/dist/services/cdpConnectionPool.js +235 -0
  77. package/dist/services/cdpConnectionPool.js.map +1 -0
  78. package/dist/services/cdpService.d.ts +214 -0
  79. package/dist/services/cdpService.js +1423 -0
  80. package/dist/services/cdpService.js.map +1 -0
  81. package/dist/services/chatSessionService.d.ts +89 -0
  82. package/dist/services/chatSessionService.js +738 -0
  83. package/dist/services/chatSessionService.js.map +1 -0
  84. package/dist/services/errorPopupDetector.d.ts +89 -0
  85. package/dist/services/errorPopupDetector.js +274 -0
  86. package/dist/services/errorPopupDetector.js.map +1 -0
  87. package/dist/services/modeService.d.ts +44 -0
  88. package/dist/services/modeService.js +74 -0
  89. package/dist/services/modeService.js.map +1 -0
  90. package/dist/services/modelService.d.ts +36 -0
  91. package/dist/services/modelService.js +64 -0
  92. package/dist/services/modelService.js.map +1 -0
  93. package/dist/services/planningDetector.d.ts +87 -0
  94. package/dist/services/planningDetector.js +321 -0
  95. package/dist/services/planningDetector.js.map +1 -0
  96. package/dist/services/processManager.d.ts +18 -0
  97. package/dist/services/processManager.js +62 -0
  98. package/dist/services/processManager.js.map +1 -0
  99. package/dist/services/progressSender.d.ts +20 -0
  100. package/dist/services/progressSender.js +65 -0
  101. package/dist/services/progressSender.js.map +1 -0
  102. package/dist/services/promptDispatcher.d.ts +38 -0
  103. package/dist/services/promptDispatcher.js +42 -0
  104. package/dist/services/promptDispatcher.js.map +1 -0
  105. package/dist/services/quotaService.d.ts +21 -0
  106. package/dist/services/quotaService.js +191 -0
  107. package/dist/services/quotaService.js.map +1 -0
  108. package/dist/services/responseMonitor.d.ts +129 -0
  109. package/dist/services/responseMonitor.js +996 -0
  110. package/dist/services/responseMonitor.js.map +1 -0
  111. package/dist/services/scheduleService.d.ts +58 -0
  112. package/dist/services/scheduleService.js +135 -0
  113. package/dist/services/scheduleService.js.map +1 -0
  114. package/dist/services/screenshotService.d.ts +55 -0
  115. package/dist/services/screenshotService.js +86 -0
  116. package/dist/services/screenshotService.js.map +1 -0
  117. package/dist/services/telegramTopicManager.d.ts +40 -0
  118. package/dist/services/telegramTopicManager.js +103 -0
  119. package/dist/services/telegramTopicManager.js.map +1 -0
  120. package/dist/services/titleGeneratorService.d.ts +32 -0
  121. package/dist/services/titleGeneratorService.js +114 -0
  122. package/dist/services/titleGeneratorService.js.map +1 -0
  123. package/dist/services/updateCheckService.d.ts +16 -0
  124. package/dist/services/updateCheckService.js +148 -0
  125. package/dist/services/updateCheckService.js.map +1 -0
  126. package/dist/services/userMessageDetector.d.ts +57 -0
  127. package/dist/services/userMessageDetector.js +222 -0
  128. package/dist/services/userMessageDetector.js.map +1 -0
  129. package/dist/services/workspaceService.d.ts +33 -0
  130. package/dist/services/workspaceService.js +65 -0
  131. package/dist/services/workspaceService.js.map +1 -0
  132. package/dist/ui/autoAcceptUi.d.ts +6 -0
  133. package/dist/ui/autoAcceptUi.js +22 -0
  134. package/dist/ui/autoAcceptUi.js.map +1 -0
  135. package/dist/ui/modeUi.d.ts +12 -0
  136. package/dist/ui/modeUi.js +40 -0
  137. package/dist/ui/modeUi.js.map +1 -0
  138. package/dist/ui/modelsUi.d.ts +12 -0
  139. package/dist/ui/modelsUi.js +101 -0
  140. package/dist/ui/modelsUi.js.map +1 -0
  141. package/dist/ui/projectListUi.d.ts +11 -0
  142. package/dist/ui/projectListUi.js +59 -0
  143. package/dist/ui/projectListUi.js.map +1 -0
  144. package/dist/ui/screenshotUi.d.ts +6 -0
  145. package/dist/ui/screenshotUi.js +28 -0
  146. package/dist/ui/screenshotUi.js.map +1 -0
  147. package/dist/ui/sessionPickerUi.d.ts +8 -0
  148. package/dist/ui/sessionPickerUi.js +32 -0
  149. package/dist/ui/sessionPickerUi.js.map +1 -0
  150. package/dist/ui/templateUi.d.ts +5 -0
  151. package/dist/ui/templateUi.js +44 -0
  152. package/dist/ui/templateUi.js.map +1 -0
  153. package/dist/utils/cdpPorts.d.ts +2 -0
  154. package/dist/utils/cdpPorts.js +6 -0
  155. package/dist/utils/cdpPorts.js.map +1 -0
  156. package/dist/utils/config.d.ts +14 -0
  157. package/dist/utils/config.js +12 -0
  158. package/dist/utils/config.js.map +1 -0
  159. package/dist/utils/configLoader.d.ts +23 -0
  160. package/dist/utils/configLoader.js +153 -0
  161. package/dist/utils/configLoader.js.map +1 -0
  162. package/dist/utils/htmlToTelegramMarkdown.d.ts +6 -0
  163. package/dist/utils/htmlToTelegramMarkdown.js +189 -0
  164. package/dist/utils/htmlToTelegramMarkdown.js.map +1 -0
  165. package/dist/utils/i18n.d.ts +3 -0
  166. package/dist/utils/i18n.js +78 -0
  167. package/dist/utils/i18n.js.map +1 -0
  168. package/dist/utils/imageHandler.d.ts +35 -0
  169. package/dist/utils/imageHandler.js +155 -0
  170. package/dist/utils/imageHandler.js.map +1 -0
  171. package/dist/utils/lockfile.d.ts +7 -0
  172. package/dist/utils/lockfile.js +117 -0
  173. package/dist/utils/lockfile.js.map +1 -0
  174. package/dist/utils/logger.d.ts +23 -0
  175. package/dist/utils/logger.js +85 -0
  176. package/dist/utils/logger.js.map +1 -0
  177. package/dist/utils/logo.d.ts +1 -0
  178. package/dist/utils/logo.js +14 -0
  179. package/dist/utils/logo.js.map +1 -0
  180. package/dist/utils/metadataExtractor.d.ts +5 -0
  181. package/dist/utils/metadataExtractor.js +16 -0
  182. package/dist/utils/metadataExtractor.js.map +1 -0
  183. package/dist/utils/pathUtils.d.ts +23 -0
  184. package/dist/utils/pathUtils.js +58 -0
  185. package/dist/utils/pathUtils.js.map +1 -0
  186. package/dist/utils/processLogBuffer.d.ts +17 -0
  187. package/dist/utils/processLogBuffer.js +108 -0
  188. package/dist/utils/processLogBuffer.js.map +1 -0
  189. package/dist/utils/streamMessageFormatter.d.ts +18 -0
  190. package/dist/utils/streamMessageFormatter.js +91 -0
  191. package/dist/utils/streamMessageFormatter.js.map +1 -0
  192. package/dist/utils/telegramFormatter.d.ts +37 -0
  193. package/dist/utils/telegramFormatter.js +445 -0
  194. package/dist/utils/telegramFormatter.js.map +1 -0
  195. package/dist/utils/voiceHandler.d.ts +23 -0
  196. package/dist/utils/voiceHandler.js +169 -0
  197. package/dist/utils/voiceHandler.js.map +1 -0
  198. package/locales/en.json +85 -0
  199. package/locales/ja.json +109 -0
  200. package/package.json +84 -0
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Check if Antigravity is running with CDP ports.
3
+ * If not running, output a warning log (no auto-start or restart).
4
+ *
5
+ * Called during Bot initialization.
6
+ */
7
+ export declare function ensureAntigravityRunning(): Promise<void>;
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.ensureAntigravityRunning = ensureAntigravityRunning;
37
+ const logger_1 = require("../utils/logger");
38
+ const cdpPorts_1 = require("../utils/cdpPorts");
39
+ const pathUtils_1 = require("../utils/pathUtils");
40
+ const http = __importStar(require("http"));
41
+ /**
42
+ * Check if CDP responds on the specified port.
43
+ */
44
+ function checkPort(port) {
45
+ return new Promise((resolve) => {
46
+ const req = http.get(`http://127.0.0.1:${port}/json/list`, (res) => {
47
+ let data = '';
48
+ res.on('data', (chunk) => (data += chunk));
49
+ res.on('end', () => {
50
+ try {
51
+ const parsed = JSON.parse(data);
52
+ resolve(Array.isArray(parsed));
53
+ }
54
+ catch {
55
+ resolve(false);
56
+ }
57
+ });
58
+ });
59
+ req.on('error', () => resolve(false));
60
+ req.setTimeout(2000, () => {
61
+ req.destroy();
62
+ resolve(false);
63
+ });
64
+ });
65
+ }
66
+ /**
67
+ * Check if Antigravity is running with CDP ports.
68
+ * If not running, output a warning log (no auto-start or restart).
69
+ *
70
+ * Called during Bot initialization.
71
+ */
72
+ async function ensureAntigravityRunning() {
73
+ logger_1.logger.debug('[AntigravityLauncher] Checking CDP ports...');
74
+ const results = await Promise.all(cdpPorts_1.CDP_PORTS.map((port) => checkPort(port)));
75
+ const foundIndex = results.indexOf(true);
76
+ if (foundIndex !== -1) {
77
+ logger_1.logger.debug(`[AntigravityLauncher] OK — Port ${cdpPorts_1.CDP_PORTS[foundIndex]} responding`);
78
+ return;
79
+ }
80
+ logger_1.logger.warn('');
81
+ logger_1.logger.warn('='.repeat(70));
82
+ logger_1.logger.warn(' Antigravity CDP ports are not responding');
83
+ logger_1.logger.warn('');
84
+ logger_1.logger.warn(' Launch Antigravity with CDP enabled:');
85
+ logger_1.logger.warn(' remoat open');
86
+ logger_1.logger.warn('');
87
+ logger_1.logger.warn(' Or manually:');
88
+ logger_1.logger.warn(` ${(0, pathUtils_1.getAntigravityCdpHint)(9222)}`);
89
+ logger_1.logger.warn('');
90
+ logger_1.logger.warn(' The bot will auto-connect once Antigravity is running.');
91
+ logger_1.logger.warn('='.repeat(70));
92
+ logger_1.logger.warn('');
93
+ }
94
+ //# sourceMappingURL=antigravityLauncher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"antigravityLauncher.js","sourceRoot":"","sources":["../../src/services/antigravityLauncher.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCA,4DAuBC;AA3DD,4CAAyC;AACzC,gDAA8C;AAC9C,kDAA2D;AAC3D,2CAA6B;AAE7B;;GAEG;AACH,SAAS,SAAS,CAAC,IAAY;IAC3B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC3B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,oBAAoB,IAAI,YAAY,EAAE,CAAC,GAAG,EAAE,EAAE;YAC/D,IAAI,IAAI,GAAG,EAAE,CAAC;YACd,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC;YAC3C,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;gBACf,IAAI,CAAC;oBACD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;oBAChC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;gBACnC,CAAC;gBAAC,MAAM,CAAC;oBACL,OAAO,CAAC,KAAK,CAAC,CAAC;gBACnB,CAAC;YACL,CAAC,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;QACH,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QACtC,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,EAAE;YACtB,GAAG,CAAC,OAAO,EAAE,CAAC;YACd,OAAO,CAAC,KAAK,CAAC,CAAC;QACnB,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AACP,CAAC;AAED;;;;;GAKG;AACI,KAAK,UAAU,wBAAwB;IAC1C,eAAM,CAAC,KAAK,CAAC,6CAA6C,CAAC,CAAC;IAE5D,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,oBAAS,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC5E,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACzC,IAAI,UAAU,KAAK,CAAC,CAAC,EAAE,CAAC;QACpB,eAAM,CAAC,KAAK,CAAC,mCAAmC,oBAAS,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;QACpF,OAAO;IACX,CAAC;IAED,eAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChB,eAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5B,eAAM,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAC;IAC1D,eAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChB,eAAM,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC;IACtD,eAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAC/B,eAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChB,eAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAC9B,eAAM,CAAC,IAAI,CAAC,OAAO,IAAA,iCAAqB,EAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAClD,eAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChB,eAAM,CAAC,IAAI,CAAC,0DAA0D,CAAC,CAAC;IACxE,eAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5B,eAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACpB,CAAC"}
@@ -0,0 +1,97 @@
1
+ import { CdpService } from './cdpService';
2
+ /** Approval button information */
3
+ export interface ApprovalInfo {
4
+ /** Allow button text (e.g. "Allow") */
5
+ approveText: string;
6
+ /** Per-conversation allow button text (e.g. "Allow This Conversation") */
7
+ alwaysAllowText?: string;
8
+ /** Deny button text (e.g. "Deny") */
9
+ denyText: string;
10
+ /** Action description (e.g. "write to file.ts") */
11
+ description: string;
12
+ }
13
+ export interface ApprovalDetectorOptions {
14
+ /** CDP service instance */
15
+ cdpService: CdpService;
16
+ /** Poll interval in milliseconds (default: 1500ms) */
17
+ pollIntervalMs?: number;
18
+ /** Callback when an approval button is detected */
19
+ onApprovalRequired: (info: ApprovalInfo) => void;
20
+ /** Callback when a previously detected approval is resolved (buttons disappeared) */
21
+ onResolved?: () => void;
22
+ }
23
+ /**
24
+ * Generate a CDP script that clicks a button
25
+ *
26
+ * @param buttonText Text of the button to click
27
+ */
28
+ export declare function buildClickScript(buttonText: string): string;
29
+ /**
30
+ * Class that detects approval buttons in the Antigravity UI via polling.
31
+ *
32
+ * Notifies detected button info through the onApprovalRequired callback,
33
+ * and performs the actual click operations via approveButton() / denyButton() methods.
34
+ */
35
+ export declare class ApprovalDetector {
36
+ private cdpService;
37
+ private pollIntervalMs;
38
+ private onApprovalRequired;
39
+ private onResolved?;
40
+ private pollTimer;
41
+ private isRunning;
42
+ /** Key of the last detected button info (for duplicate notification prevention) */
43
+ private lastDetectedKey;
44
+ /** Full ApprovalInfo from the last detection (used for clicking) */
45
+ private lastDetectedInfo;
46
+ constructor(options: ApprovalDetectorOptions);
47
+ /**
48
+ * Start monitoring.
49
+ */
50
+ start(): void;
51
+ /**
52
+ * Stop monitoring.
53
+ */
54
+ stop(): Promise<void>;
55
+ /**
56
+ * Return the last detected approval button info.
57
+ * Returns null if nothing has been detected.
58
+ */
59
+ getLastDetectedInfo(): ApprovalInfo | null;
60
+ /** Schedule the next poll */
61
+ private schedulePoll;
62
+ /**
63
+ * Single poll iteration:
64
+ * 1. Get approval button info from DOM (with contextId)
65
+ * 2. Notify via callback only on new detection (prevent duplicates)
66
+ * 3. Reset lastDetectedKey / lastDetectedInfo when buttons disappear
67
+ */
68
+ private poll;
69
+ /**
70
+ * Click the approve button with the specified text via CDP.
71
+ * @param buttonText Text of the button to click (default: detected approveText or "Allow")
72
+ * @returns true if click succeeded
73
+ */
74
+ approveButton(buttonText?: string): Promise<boolean>;
75
+ /**
76
+ * Select "Allow This Conversation / Always Allow".
77
+ * If the button is not directly visible, expand the Allow Once dropdown and select it.
78
+ */
79
+ alwaysAllowButton(): Promise<boolean>;
80
+ /**
81
+ * Click the deny button with the specified text via CDP.
82
+ * @param buttonText Text of the button to click (default: detected denyText or "Deny")
83
+ * @returns true if click succeeded
84
+ */
85
+ denyButton(buttonText?: string): Promise<boolean>;
86
+ /**
87
+ * Internal click handler (shared implementation for approveButton / denyButton).
88
+ * Specifies contextId to click in the correct execution context.
89
+ */
90
+ private clickButton;
91
+ /**
92
+ * Execute Runtime.evaluate with contextId and return result.value.
93
+ */
94
+ private runEvaluateScript;
95
+ /** Returns whether monitoring is currently active */
96
+ isActive(): boolean;
97
+ }
@@ -0,0 +1,394 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ApprovalDetector = void 0;
4
+ exports.buildClickScript = buildClickScript;
5
+ const logger_1 = require("../utils/logger");
6
+ /**
7
+ * Approval button detection script for the Antigravity UI
8
+ *
9
+ * Detects allow/deny button pairs and extracts descriptions with fallbacks.
10
+ */
11
+ const DETECT_APPROVAL_SCRIPT = `(() => {
12
+ const ALLOW_ONCE_PATTERNS = ['allow once', 'allow one time', '今回のみ許可', '1回のみ許可', '一度許可'];
13
+ const ALWAYS_ALLOW_PATTERNS = [
14
+ 'allow this conversation',
15
+ 'allow this chat',
16
+ 'always allow',
17
+ '常に許可',
18
+ 'この会話を許可',
19
+ ];
20
+ const ALLOW_PATTERNS = ['allow', 'permit', '許可', '承認', '確認'];
21
+ const DENY_PATTERNS = ['deny', '拒否', 'decline'];
22
+
23
+ const normalize = (text) => (text || '').toLowerCase().replace(/\\s+/g, ' ').trim();
24
+
25
+ const allButtons = Array.from(document.querySelectorAll('button'))
26
+ .filter(btn => btn.offsetParent !== null);
27
+
28
+ let approveBtn = allButtons.find(btn => {
29
+ const t = normalize(btn.textContent || '');
30
+ return ALLOW_ONCE_PATTERNS.some(p => t.includes(p));
31
+ }) || null;
32
+
33
+ if (!approveBtn) {
34
+ approveBtn = allButtons.find(btn => {
35
+ const t = normalize(btn.textContent || '');
36
+ const isAlways = ALWAYS_ALLOW_PATTERNS.some(p => t.includes(p));
37
+ return !isAlways && ALLOW_PATTERNS.some(p => t.includes(p));
38
+ }) || null;
39
+ }
40
+
41
+ if (!approveBtn) return null;
42
+
43
+ const container = approveBtn.closest('[role="dialog"], .modal, .dialog, .approval-container, .permission-dialog')
44
+ || approveBtn.parentElement?.parentElement
45
+ || approveBtn.parentElement
46
+ || document.body;
47
+
48
+ const containerButtons = Array.from(container.querySelectorAll('button'))
49
+ .filter(btn => btn.offsetParent !== null);
50
+
51
+ const denyBtn = containerButtons.find(btn => {
52
+ const t = normalize(btn.textContent || '');
53
+ return DENY_PATTERNS.some(p => t.includes(p));
54
+ }) || null;
55
+
56
+ if (!denyBtn) return null;
57
+
58
+ const alwaysAllowBtn = containerButtons.find(btn => {
59
+ const t = normalize(btn.textContent || '');
60
+ return ALWAYS_ALLOW_PATTERNS.some(p => t.includes(p));
61
+ }) || null;
62
+
63
+ const approveText = (approveBtn.textContent || '').trim();
64
+ const alwaysAllowText = alwaysAllowBtn ? (alwaysAllowBtn.textContent || '').trim() : '';
65
+ const denyText = (denyBtn.textContent || '').trim();
66
+
67
+ // Description extraction (multiple fallbacks)
68
+ let description = '';
69
+
70
+ // 1. p or .description inside dialog/modal
71
+ const dialog = container;
72
+ if (dialog) {
73
+ const descEl = dialog.querySelector('p, .description, [data-testid="description"]');
74
+ if (descEl) {
75
+ description = (descEl.textContent || '').trim();
76
+ }
77
+ }
78
+
79
+ // 2. Parent element text (excluding button text)
80
+ if (!description) {
81
+ const parent = approveBtn.parentElement?.parentElement || approveBtn.parentElement;
82
+ if (parent) {
83
+ const clone = parent.cloneNode(true);
84
+ const buttons = clone.querySelectorAll('button');
85
+ buttons.forEach(b => b.remove());
86
+ const parentText = (clone.textContent || '').trim();
87
+ if (parentText.length > 5 && parentText.length < 500) {
88
+ description = parentText;
89
+ }
90
+ }
91
+ }
92
+
93
+ // 3. aria-label fallback
94
+ if (!description) {
95
+ const ariaLabel = approveBtn.getAttribute('aria-label') || '';
96
+ if (ariaLabel) description = ariaLabel;
97
+ }
98
+
99
+ return { approveText, alwaysAllowText, denyText, description };
100
+ })()`;
101
+ /**
102
+ * Press the toggle on the right side of Allow Once to expand the Always Allow dropdown.
103
+ */
104
+ const EXPAND_ALWAYS_ALLOW_MENU_SCRIPT = `(() => {
105
+ const ALLOW_ONCE_PATTERNS = ['allow once', 'allow one time', '今回のみ許可', '1回のみ許可', '一度許可'];
106
+ const ALWAYS_ALLOW_PATTERNS = [
107
+ 'allow this conversation',
108
+ 'allow this chat',
109
+ 'always allow',
110
+ '常に許可',
111
+ 'この会話を許可',
112
+ ];
113
+
114
+ const normalize = (text) => (text || '').toLowerCase().replace(/\\s+/g, ' ').trim();
115
+ const visibleButtons = Array.from(document.querySelectorAll('button'))
116
+ .filter(btn => btn.offsetParent !== null);
117
+
118
+ const directAlways = visibleButtons.find(btn => {
119
+ const t = normalize(btn.textContent || '');
120
+ return ALWAYS_ALLOW_PATTERNS.some(p => t.includes(p));
121
+ });
122
+ if (directAlways) return { ok: true, reason: 'already-visible' };
123
+
124
+ const allowOnceBtn = visibleButtons.find(btn => {
125
+ const t = normalize(btn.textContent || '');
126
+ return ALLOW_ONCE_PATTERNS.some(p => t.includes(p));
127
+ });
128
+ if (!allowOnceBtn) return { ok: false, error: 'allow-once button not found' };
129
+
130
+ const container = allowOnceBtn.closest('[role="dialog"], .modal, .dialog, .approval-container, .permission-dialog')
131
+ || allowOnceBtn.parentElement?.parentElement
132
+ || allowOnceBtn.parentElement
133
+ || document.body;
134
+
135
+ const containerButtons = Array.from(container.querySelectorAll('button'))
136
+ .filter(btn => btn.offsetParent !== null);
137
+
138
+ const toggleBtn = containerButtons.find(btn => {
139
+ if (btn === allowOnceBtn) return false;
140
+ const text = normalize(btn.textContent || '');
141
+ const aria = normalize(btn.getAttribute('aria-label') || '');
142
+ const hasPopup = btn.getAttribute('aria-haspopup');
143
+ if (hasPopup === 'menu' || hasPopup === 'listbox') return true;
144
+ if (text === '') return true;
145
+ return /menu|more|expand|options|dropdown|chevron|arrow/.test(aria);
146
+ });
147
+
148
+ if (toggleBtn) {
149
+ toggleBtn.click();
150
+ return { ok: true, reason: 'toggle-button' };
151
+ }
152
+
153
+ const rect = allowOnceBtn.getBoundingClientRect();
154
+ if (!rect || rect.width <= 0 || rect.height <= 0) {
155
+ return { ok: false, error: 'allow-once button rect unavailable' };
156
+ }
157
+
158
+ const clickX = rect.right - Math.max(4, Math.min(12, rect.width * 0.15));
159
+ const clickY = rect.top + rect.height / 2;
160
+
161
+ const events = ['pointerdown', 'mousedown', 'mouseup', 'click'];
162
+ for (const type of events) {
163
+ allowOnceBtn.dispatchEvent(new MouseEvent(type, {
164
+ bubbles: true,
165
+ cancelable: true,
166
+ view: window,
167
+ clientX: clickX,
168
+ clientY: clickY,
169
+ }));
170
+ }
171
+ return { ok: true, reason: 'allow-once-right-edge' };
172
+ })()`;
173
+ /**
174
+ * Generate a CDP script that clicks a button
175
+ *
176
+ * @param buttonText Text of the button to click
177
+ */
178
+ function buildClickScript(buttonText) {
179
+ const safeText = JSON.stringify(buttonText);
180
+ return `(() => {
181
+ const normalize = (text) => (text || '').toLowerCase().replace(/\\s+/g, ' ').trim();
182
+ const text = ${safeText};
183
+ const wanted = normalize(text);
184
+ const allButtons = Array.from(document.querySelectorAll('button'));
185
+ const target = allButtons.find(btn => {
186
+ if (!btn.offsetParent) return false;
187
+ const buttonText = normalize(btn.textContent || '');
188
+ const ariaLabel = normalize(btn.getAttribute('aria-label') || '');
189
+ return buttonText === wanted ||
190
+ ariaLabel === wanted ||
191
+ buttonText.includes(wanted) ||
192
+ ariaLabel.includes(wanted);
193
+ });
194
+ if (!target) return { ok: false, error: 'Button not found: ' + text };
195
+ target.click();
196
+ return { ok: true };
197
+ })()`;
198
+ }
199
+ /**
200
+ * Class that detects approval buttons in the Antigravity UI via polling.
201
+ *
202
+ * Notifies detected button info through the onApprovalRequired callback,
203
+ * and performs the actual click operations via approveButton() / denyButton() methods.
204
+ */
205
+ class ApprovalDetector {
206
+ cdpService;
207
+ pollIntervalMs;
208
+ onApprovalRequired;
209
+ onResolved;
210
+ pollTimer = null;
211
+ isRunning = false;
212
+ /** Key of the last detected button info (for duplicate notification prevention) */
213
+ lastDetectedKey = null;
214
+ /** Full ApprovalInfo from the last detection (used for clicking) */
215
+ lastDetectedInfo = null;
216
+ constructor(options) {
217
+ this.cdpService = options.cdpService;
218
+ this.pollIntervalMs = options.pollIntervalMs ?? 1500;
219
+ this.onApprovalRequired = options.onApprovalRequired;
220
+ this.onResolved = options.onResolved;
221
+ }
222
+ /**
223
+ * Start monitoring.
224
+ */
225
+ start() {
226
+ if (this.isRunning)
227
+ return;
228
+ this.isRunning = true;
229
+ this.lastDetectedKey = null;
230
+ this.lastDetectedInfo = null;
231
+ this.schedulePoll();
232
+ }
233
+ /**
234
+ * Stop monitoring.
235
+ */
236
+ async stop() {
237
+ this.isRunning = false;
238
+ if (this.pollTimer) {
239
+ clearTimeout(this.pollTimer);
240
+ this.pollTimer = null;
241
+ }
242
+ }
243
+ /**
244
+ * Return the last detected approval button info.
245
+ * Returns null if nothing has been detected.
246
+ */
247
+ getLastDetectedInfo() {
248
+ return this.lastDetectedInfo;
249
+ }
250
+ /** Schedule the next poll */
251
+ schedulePoll() {
252
+ if (!this.isRunning)
253
+ return;
254
+ this.pollTimer = setTimeout(async () => {
255
+ await this.poll();
256
+ if (this.isRunning) {
257
+ this.schedulePoll();
258
+ }
259
+ }, this.pollIntervalMs);
260
+ }
261
+ /**
262
+ * Single poll iteration:
263
+ * 1. Get approval button info from DOM (with contextId)
264
+ * 2. Notify via callback only on new detection (prevent duplicates)
265
+ * 3. Reset lastDetectedKey / lastDetectedInfo when buttons disappear
266
+ */
267
+ async poll() {
268
+ try {
269
+ const contextId = this.cdpService.getPrimaryContextId();
270
+ const callParams = {
271
+ expression: DETECT_APPROVAL_SCRIPT,
272
+ returnByValue: true,
273
+ awaitPromise: false,
274
+ };
275
+ if (contextId !== null) {
276
+ callParams.contextId = contextId;
277
+ }
278
+ const result = await this.cdpService.call('Runtime.evaluate', callParams);
279
+ const info = result?.result?.value ?? null;
280
+ if (info) {
281
+ // Duplicate prevention: use approveText + description combination as key
282
+ const key = `${info.approveText}::${info.description}`;
283
+ if (key !== this.lastDetectedKey) {
284
+ this.lastDetectedKey = key;
285
+ this.lastDetectedInfo = info;
286
+ Promise.resolve(this.onApprovalRequired(info)).catch((err) => {
287
+ logger_1.logger.error('[ApprovalDetector] onApprovalRequired callback failed:', err);
288
+ });
289
+ }
290
+ }
291
+ else {
292
+ // Reset when buttons disappear (prepare for next approval detection)
293
+ const wasDetected = this.lastDetectedKey !== null;
294
+ this.lastDetectedKey = null;
295
+ this.lastDetectedInfo = null;
296
+ if (wasDetected && this.onResolved) {
297
+ this.onResolved();
298
+ }
299
+ }
300
+ }
301
+ catch (error) {
302
+ // Ignore CDP errors and continue monitoring
303
+ const message = error instanceof Error ? error.message : String(error);
304
+ if (message.includes('WebSocket is not connected')) {
305
+ return;
306
+ }
307
+ logger_1.logger.error('[ApprovalDetector] Error during polling:', error);
308
+ }
309
+ }
310
+ /**
311
+ * Click the approve button with the specified text via CDP.
312
+ * @param buttonText Text of the button to click (default: detected approveText or "Allow")
313
+ * @returns true if click succeeded
314
+ */
315
+ async approveButton(buttonText) {
316
+ const text = buttonText ?? this.lastDetectedInfo?.approveText ?? 'Allow';
317
+ return this.clickButton(text);
318
+ }
319
+ /**
320
+ * Select "Allow This Conversation / Always Allow".
321
+ * If the button is not directly visible, expand the Allow Once dropdown and select it.
322
+ */
323
+ async alwaysAllowButton() {
324
+ const directCandidates = [
325
+ this.lastDetectedInfo?.alwaysAllowText,
326
+ 'Allow This Conversation',
327
+ 'Allow This Chat',
328
+ 'この会話を許可',
329
+ 'Always Allow',
330
+ '常に許可',
331
+ ].filter((value) => typeof value === 'string' && value.trim().length > 0);
332
+ for (const candidate of directCandidates) {
333
+ if (await this.clickButton(candidate))
334
+ return true;
335
+ }
336
+ const expanded = await this.runEvaluateScript(EXPAND_ALWAYS_ALLOW_MENU_SCRIPT);
337
+ if (expanded?.ok !== true) {
338
+ return false;
339
+ }
340
+ for (let i = 0; i < 5; i++) {
341
+ for (const candidate of directCandidates) {
342
+ if (await this.clickButton(candidate))
343
+ return true;
344
+ }
345
+ await new Promise((resolve) => setTimeout(resolve, 120));
346
+ }
347
+ return false;
348
+ }
349
+ /**
350
+ * Click the deny button with the specified text via CDP.
351
+ * @param buttonText Text of the button to click (default: detected denyText or "Deny")
352
+ * @returns true if click succeeded
353
+ */
354
+ async denyButton(buttonText) {
355
+ const text = buttonText ?? this.lastDetectedInfo?.denyText ?? 'Deny';
356
+ return this.clickButton(text);
357
+ }
358
+ /**
359
+ * Internal click handler (shared implementation for approveButton / denyButton).
360
+ * Specifies contextId to click in the correct execution context.
361
+ */
362
+ async clickButton(buttonText) {
363
+ try {
364
+ const result = await this.runEvaluateScript(buildClickScript(buttonText));
365
+ return result?.ok === true;
366
+ }
367
+ catch (error) {
368
+ logger_1.logger.error('[ApprovalDetector] Error while clicking button:', error);
369
+ return false;
370
+ }
371
+ }
372
+ /**
373
+ * Execute Runtime.evaluate with contextId and return result.value.
374
+ */
375
+ async runEvaluateScript(expression) {
376
+ const contextId = this.cdpService.getPrimaryContextId();
377
+ const callParams = {
378
+ expression,
379
+ returnByValue: true,
380
+ awaitPromise: false,
381
+ };
382
+ if (contextId !== null) {
383
+ callParams.contextId = contextId;
384
+ }
385
+ const result = await this.cdpService.call('Runtime.evaluate', callParams);
386
+ return result?.result?.value;
387
+ }
388
+ /** Returns whether monitoring is currently active */
389
+ isActive() {
390
+ return this.isRunning;
391
+ }
392
+ }
393
+ exports.ApprovalDetector = ApprovalDetector;
394
+ //# sourceMappingURL=approvalDetector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"approvalDetector.js","sourceRoot":"","sources":["../../src/services/approvalDetector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Structured DOM extraction for Antigravity assistant responses.
3
+ *
4
+ * Provides two functions:
5
+ * - extractAssistantSegmentsPayloadScript() — Returns a CDP-evaluatable IIFE string
6
+ * that walks the DOM and returns a typed segment array.
7
+ * - classifyAssistantSegments(payload) — Node.js-side classifier that converts
8
+ * the raw payload into finalOutputText, activityLines, feedback, and diagnostics.
9
+ */
10
+ export interface AssistantDomSegment {
11
+ kind: 'assistant-body' | 'thinking' | 'tool-call' | 'tool-result' | 'feedback';
12
+ text: string;
13
+ role: 'assistant';
14
+ messageIndex: number;
15
+ domPath: string;
16
+ }
17
+ export interface AssistantDomSegmentPayload {
18
+ source: 'dom-structured';
19
+ extractedAt: number;
20
+ segments: AssistantDomSegment[];
21
+ }
22
+ export interface ClassifyResult {
23
+ finalOutputText: string;
24
+ activityLines: string[];
25
+ feedback: string[];
26
+ diagnostics: {
27
+ source: 'dom-structured' | 'legacy-fallback';
28
+ segmentCounts: Record<string, number>;
29
+ fallbackReason?: string;
30
+ };
31
+ }
32
+ /**
33
+ * Classify an AssistantDomSegmentPayload into output text, activity lines,
34
+ * feedback, and diagnostics.
35
+ *
36
+ * If the payload is invalid, returns a legacy-fallback result with empty fields.
37
+ */
38
+ export declare function classifyAssistantSegments(payload: unknown): ClassifyResult;
39
+ /**
40
+ * Return a CDP-evaluatable IIFE string that walks the Antigravity DOM
41
+ * and returns an AssistantDomSegmentPayload object.
42
+ *
43
+ * The IIFE extracts:
44
+ * - assistant-body segments (innerHTML for Markdown conversion)
45
+ * - thinking segments (from <details> summary text)
46
+ * - tool-call / tool-result segments (from <details> content)
47
+ * - feedback segments (Good/Bad buttons)
48
+ */
49
+ export declare function extractAssistantSegmentsPayloadScript(): string;