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,114 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TitleGeneratorService = void 0;
4
+ /**
5
+ * Script to generate channel name titles using Gemini Flash within the Antigravity UI.
6
+ * Makes LLM calls via Antigravity's internal API (language_server).
7
+ * Infers API endpoint and token from existing DOM components.
8
+ */
9
+ const GENERATE_TITLE_SCRIPT = `(async (userPrompt) => {
10
+ try {
11
+ // Generate title using Antigravity's internal fetch API
12
+ // Look for configuration from __NEXT_DATA__ or window.__remixContext
13
+ const configs = [
14
+ window.__NEXT_DATA__,
15
+ window.__remixContext,
16
+ window.__APP_CONFIG__,
17
+ ].filter(Boolean);
18
+
19
+ // Fallback: extract leading text from prompt
20
+ const fallbackTitle = userPrompt
21
+ .replace(/^\\[.*?\\]\\n?/, '')
22
+ .substring(0, 40)
23
+ .trim();
24
+
25
+ return { ok: true, title: fallbackTitle, method: 'text-extract' };
26
+ } catch (e) {
27
+ return { ok: false, error: e.message };
28
+ }
29
+ })`;
30
+ /**
31
+ * Service for generating chat session titles.
32
+ *
33
+ * Strategy:
34
+ * 1. Call Antigravity's Gemini Flash API via CdpService (future implementation)
35
+ * 2. Fallback: extract and sanitize leading text from the user prompt
36
+ */
37
+ class TitleGeneratorService {
38
+ /**
39
+ * Generate a short title from the user's prompt
40
+ * @param prompt User's prompt
41
+ * @param cdpService Optional CdpService instance
42
+ */
43
+ async generateTitle(prompt, cdpService) {
44
+ // Attempt to use Antigravity's LLM via CDP
45
+ if (cdpService) {
46
+ try {
47
+ const title = await this.generateViaCdp(prompt, cdpService);
48
+ if (title)
49
+ return title;
50
+ }
51
+ catch {
52
+ // Fall through to fallback
53
+ }
54
+ }
55
+ // Fallback: text extraction
56
+ return this.extractTitleFromText(prompt);
57
+ }
58
+ /**
59
+ * Generate a title by calling Antigravity's LLM API via CDP
60
+ */
61
+ async generateViaCdp(prompt, cdpService) {
62
+ try {
63
+ const contextId = cdpService.getPrimaryContextId();
64
+ const cleanPrompt = this.stripWorkspacePrefix(prompt);
65
+ const callParams = {
66
+ expression: `${GENERATE_TITLE_SCRIPT}(${JSON.stringify(cleanPrompt)})`,
67
+ returnByValue: true,
68
+ awaitPromise: true,
69
+ };
70
+ if (contextId !== null) {
71
+ callParams.contextId = contextId;
72
+ }
73
+ const result = await cdpService.call('Runtime.evaluate', callParams);
74
+ const value = result?.result?.value;
75
+ if (value?.ok && value?.title) {
76
+ return this.sanitizeForChannelName(value.title);
77
+ }
78
+ }
79
+ catch {
80
+ // Fall through to fallback
81
+ }
82
+ return null;
83
+ }
84
+ /**
85
+ * Extract a title from the prompt text (fallback)
86
+ */
87
+ extractTitleFromText(prompt) {
88
+ const cleanPrompt = this.stripWorkspacePrefix(prompt);
89
+ const truncated = cleanPrompt.substring(0, 40).trim();
90
+ return this.sanitizeForChannelName(truncated) || 'untitled';
91
+ }
92
+ /**
93
+ * Strip the workspace prefix
94
+ */
95
+ stripWorkspacePrefix(prompt) {
96
+ return prompt.replace(/^\[ワークスペース:.*?\]\n?/, '');
97
+ }
98
+ /**
99
+ * Sanitize text into a format suitable for topic/channel names
100
+ */
101
+ sanitizeForChannelName(text) {
102
+ const sanitized = text
103
+ .toLowerCase()
104
+ .replace(/\s+/g, '-')
105
+ // Allowed: alphanumeric, hyphen, underscore, CJK characters
106
+ .replace(/[^a-z0-9\-_\u3000-\u303f\u3040-\u309f\u30a0-\u30ff\uff00-\uff9f\u4e00-\u9faf]/g, '-')
107
+ .replace(/-{2,}/g, '-')
108
+ .replace(/^-+|-+$/g, '')
109
+ .substring(0, 80);
110
+ return sanitized || 'untitled';
111
+ }
112
+ }
113
+ exports.TitleGeneratorService = TitleGeneratorService;
114
+ //# sourceMappingURL=titleGeneratorService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"titleGeneratorService.js","sourceRoot":"","sources":["../../src/services/titleGeneratorService.ts"],"names":[],"mappings":";;;AAEA;;;;GAIG;AACH,MAAM,qBAAqB,GAAG;;;;;;;;;;;;;;;;;;;;GAoB3B,CAAC;AAEJ;;;;;;GAMG;AACH,MAAa,qBAAqB;IAC9B;;;;OAIG;IACH,KAAK,CAAC,aAAa,CAAC,MAAc,EAAE,UAAuB;QACvD,2CAA2C;QAC3C,IAAI,UAAU,EAAE,CAAC;YACb,IAAI,CAAC;gBACD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;gBAC5D,IAAI,KAAK;oBAAE,OAAO,KAAK,CAAC;YAC5B,CAAC;YAAC,MAAM,CAAC;gBACL,2BAA2B;YAC/B,CAAC;QACL,CAAC;QAED,4BAA4B;QAC5B,OAAO,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC7C,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,cAAc,CAAC,MAAc,EAAE,UAAsB;QAC/D,IAAI,CAAC;YACD,MAAM,SAAS,GAAG,UAAU,CAAC,mBAAmB,EAAE,CAAC;YACnD,MAAM,WAAW,GAAG,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC;YAEtD,MAAM,UAAU,GAA4B;gBACxC,UAAU,EAAE,GAAG,qBAAqB,IAAI,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,GAAG;gBACtE,aAAa,EAAE,IAAI;gBACnB,YAAY,EAAE,IAAI;aACrB,CAAC;YACF,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;gBACrB,UAAU,CAAC,SAAS,GAAG,SAAS,CAAC;YACrC,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,kBAAkB,EAAE,UAAU,CAAC,CAAC;YACrE,MAAM,KAAK,GAAG,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC;YAEpC,IAAI,KAAK,EAAE,EAAE,IAAI,KAAK,EAAE,KAAK,EAAE,CAAC;gBAC5B,OAAO,IAAI,CAAC,sBAAsB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACpD,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACL,2BAA2B;QAC/B,CAAC;QAED,OAAO,IAAI,CAAC;IAChB,CAAC;IAED;;OAEG;IACK,oBAAoB,CAAC,MAAc;QACvC,MAAM,WAAW,GAAG,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC;QACtD,MAAM,SAAS,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACtD,OAAO,IAAI,CAAC,sBAAsB,CAAC,SAAS,CAAC,IAAI,UAAU,CAAC;IAChE,CAAC;IAED;;OAEG;IACK,oBAAoB,CAAC,MAAc;QACvC,OAAO,MAAM,CAAC,OAAO,CAAC,qBAAqB,EAAE,EAAE,CAAC,CAAC;IACrD,CAAC;IAED;;OAEG;IACI,sBAAsB,CAAC,IAAY;QACtC,MAAM,SAAS,GAAG,IAAI;aACjB,WAAW,EAAE;aACb,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;YACrB,4DAA4D;aAC3D,OAAO,CAAC,gFAAgF,EAAE,GAAG,CAAC;aAC9F,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC;aACtB,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;aACvB,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAEtB,OAAO,SAAS,IAAI,UAAU,CAAC;IACnC,CAAC;CACJ;AAlFD,sDAkFC"}
@@ -0,0 +1,16 @@
1
+ export declare const UPDATE_CHECK_FILE = "update-check.json";
2
+ export declare const COOLDOWN_MS: number;
3
+ /**
4
+ * Determine whether enough time has elapsed since the last update check.
5
+ * Returns true if we should query the registry.
6
+ */
7
+ export declare function shouldCheckForUpdates(): boolean;
8
+ /**
9
+ * Query the npm registry for the latest published version.
10
+ */
11
+ export declare function fetchLatestVersion(): Promise<string>;
12
+ /**
13
+ * Non-blocking update check. Call at startup (fire-and-forget).
14
+ * Respects a 24-hour cooldown via a local cache file.
15
+ */
16
+ export declare function checkForUpdates(currentVersion: string): Promise<void>;
@@ -0,0 +1,148 @@
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.COOLDOWN_MS = exports.UPDATE_CHECK_FILE = void 0;
37
+ exports.shouldCheckForUpdates = shouldCheckForUpdates;
38
+ exports.fetchLatestVersion = fetchLatestVersion;
39
+ exports.checkForUpdates = checkForUpdates;
40
+ const https = __importStar(require("https"));
41
+ const fs = __importStar(require("fs"));
42
+ const os = __importStar(require("os"));
43
+ const path = __importStar(require("path"));
44
+ const CONFIG_DIR = '.remoat';
45
+ exports.UPDATE_CHECK_FILE = 'update-check.json';
46
+ exports.COOLDOWN_MS = 24 * 60 * 60 * 1000; // 24 hours
47
+ const REGISTRY_URL = 'https://registry.npmjs.org/remoat/latest';
48
+ const REQUEST_TIMEOUT_MS = 5000;
49
+ function getCachePath() {
50
+ return path.join(os.homedir(), CONFIG_DIR, exports.UPDATE_CHECK_FILE);
51
+ }
52
+ /**
53
+ * Determine whether enough time has elapsed since the last update check.
54
+ * Returns true if we should query the registry.
55
+ */
56
+ function shouldCheckForUpdates() {
57
+ const cachePath = getCachePath();
58
+ try {
59
+ if (!fs.existsSync(cachePath))
60
+ return true;
61
+ const raw = fs.readFileSync(cachePath, 'utf-8');
62
+ const cache = JSON.parse(raw);
63
+ return Date.now() - cache.lastCheck >= exports.COOLDOWN_MS;
64
+ }
65
+ catch {
66
+ return true;
67
+ }
68
+ }
69
+ /**
70
+ * Query the npm registry for the latest published version.
71
+ */
72
+ function fetchLatestVersion() {
73
+ return new Promise((resolve, reject) => {
74
+ const req = https.get(REGISTRY_URL, { timeout: REQUEST_TIMEOUT_MS }, (res) => {
75
+ if (res.statusCode !== 200) {
76
+ reject(new Error(`HTTP ${res.statusCode}`));
77
+ return;
78
+ }
79
+ let body = '';
80
+ res.on('data', (chunk) => {
81
+ body += chunk;
82
+ });
83
+ res.on('end', () => {
84
+ try {
85
+ const data = JSON.parse(body);
86
+ resolve(data.version);
87
+ }
88
+ catch (err) {
89
+ reject(err);
90
+ }
91
+ });
92
+ });
93
+ req.on('error', reject);
94
+ req.on('timeout', () => {
95
+ req.destroy();
96
+ reject(new Error('Request timed out'));
97
+ });
98
+ });
99
+ }
100
+ function writeCache() {
101
+ const cachePath = getCachePath();
102
+ const dir = path.dirname(cachePath);
103
+ try {
104
+ if (!fs.existsSync(dir)) {
105
+ fs.mkdirSync(dir, { recursive: true });
106
+ }
107
+ const cache = { lastCheck: Date.now() };
108
+ fs.writeFileSync(cachePath, JSON.stringify(cache), 'utf-8');
109
+ }
110
+ catch {
111
+ // Silently ignore cache write failures
112
+ }
113
+ }
114
+ /**
115
+ * Compare two semver strings. Returns:
116
+ * -1 if a < b, 0 if a === b, 1 if a > b
117
+ */
118
+ function compareSemver(a, b) {
119
+ const partsA = a.split('.').map(Number);
120
+ const partsB = b.split('.').map(Number);
121
+ for (let i = 0; i < 3; i++) {
122
+ const diff = (partsA[i] ?? 0) - (partsB[i] ?? 0);
123
+ if (diff < 0)
124
+ return -1;
125
+ if (diff > 0)
126
+ return 1;
127
+ }
128
+ return 0;
129
+ }
130
+ /**
131
+ * Non-blocking update check. Call at startup (fire-and-forget).
132
+ * Respects a 24-hour cooldown via a local cache file.
133
+ */
134
+ async function checkForUpdates(currentVersion) {
135
+ if (!shouldCheckForUpdates())
136
+ return;
137
+ try {
138
+ const latest = await fetchLatestVersion();
139
+ writeCache();
140
+ if (compareSemver(currentVersion, latest) < 0) {
141
+ console.info(`\n Update available: ${currentVersion} \u2192 ${latest} \u2014 run \x1b[36mnpm i -g remoat\x1b[0m\n`);
142
+ }
143
+ }
144
+ catch {
145
+ // Silently ignore — update check should never block startup
146
+ }
147
+ }
148
+ //# sourceMappingURL=updateCheckService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"updateCheckService.js","sourceRoot":"","sources":["../../src/services/updateCheckService.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ import { CdpService } from './cdpService';
2
+ /** User message information detected from the DOM */
3
+ export interface UserMessageInfo {
4
+ /** Message text content */
5
+ text: string;
6
+ }
7
+ export interface UserMessageDetectorOptions {
8
+ /** CDP service instance */
9
+ cdpService: CdpService;
10
+ /** Poll interval in milliseconds (default: 2000ms) */
11
+ pollIntervalMs?: number;
12
+ /** Callback when a new user message is detected */
13
+ onUserMessage: (info: UserMessageInfo) => void;
14
+ }
15
+ /**
16
+ * Detects user messages posted directly in the Antigravity UI (e.g., from a PC).
17
+ * Follows the ApprovalDetector polling pattern.
18
+ */
19
+ export declare class UserMessageDetector {
20
+ private readonly cdpService;
21
+ private readonly pollIntervalMs;
22
+ private readonly onUserMessage;
23
+ private pollTimer;
24
+ private isRunning;
25
+ /** Hash of the last detected message (for duplicate prevention) */
26
+ private lastDetectedHash;
27
+ /** Set of echo hashes — messages sent by Remoat that should be ignored */
28
+ private readonly echoHashes;
29
+ /** Set of all previously detected message hashes (defense-in-depth dedup) */
30
+ private readonly seenHashes;
31
+ private static readonly MAX_SEEN_HASHES;
32
+ /** True during the first poll — seeds existing DOM state without firing callback */
33
+ private isPriming;
34
+ constructor(options: UserMessageDetectorOptions);
35
+ /**
36
+ * Register a message hash as an echo (sent by Remoat).
37
+ * When this message is detected in the DOM, it will be skipped.
38
+ */
39
+ addEchoHash(text: string): void;
40
+ /** Start monitoring. The first poll seeds the current DOM state without firing the callback. */
41
+ start(): void;
42
+ /** Stop monitoring. */
43
+ stop(): void;
44
+ /** Returns whether monitoring is currently active. */
45
+ isActive(): boolean;
46
+ /** Add a hash to the seenHashes set, evicting the oldest entry if at capacity. */
47
+ private addToSeenHashes;
48
+ /** Schedule the next poll. */
49
+ private schedulePoll;
50
+ /**
51
+ * Single poll iteration:
52
+ * 1. Get latest user message from DOM
53
+ * 2. Check for duplicates and echoes
54
+ * 3. Notify via callback on new detection
55
+ */
56
+ private poll;
57
+ }
@@ -0,0 +1,222 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UserMessageDetector = void 0;
4
+ const node_crypto_1 = require("node:crypto");
5
+ const logger_1 = require("../utils/logger");
6
+ /**
7
+ * Script to detect the latest user message in the Antigravity chat.
8
+ *
9
+ * Antigravity user message DOM structure:
10
+ * <div class="bg-gray-500/15 p-2 rounded-lg w-full text-sm select-text">
11
+ * <div class="flex flex-row items-end gap-2">
12
+ * <div class="flex-1 flex flex-col gap-2">
13
+ * <div>
14
+ * <div class="whitespace-pre-wrap text-sm" style="word-break: break-word;">
15
+ * {user message text}
16
+ * </div>
17
+ * </div>
18
+ * </div>
19
+ * <div> <!-- undo button --> </div>
20
+ * </div>
21
+ * </div>
22
+ */
23
+ const DETECT_USER_MESSAGE_SCRIPT = `(() => {
24
+ const panel = document.querySelector('.antigravity-agent-side-panel');
25
+ const scope = panel || document;
26
+
27
+ // Strategy A (primary): Query .whitespace-pre-wrap elements directly inside
28
+ // user bubble containers. This avoids the parent-container problem where
29
+ // querySelectorAll matches a wrapper that contains multiple bubbles.
30
+ const textEls = scope.querySelectorAll(
31
+ '[class*="bg-gray-500/15"][class*="select-text"] .whitespace-pre-wrap'
32
+ );
33
+
34
+ if (textEls.length > 0) {
35
+ const lastTextEl = textEls[textEls.length - 1];
36
+ const text = (lastTextEl.textContent || '').trim();
37
+ if (text.length > 0) return { text };
38
+ }
39
+
40
+ // Strategy B (fallback): Find individual bubble containers, filtering out
41
+ // any element that itself contains nested bubble elements (i.e., a parent wrapper).
42
+ const userBubbles = Array.from(scope.querySelectorAll(
43
+ '[class*="bg-gray-500/15"][class*="rounded-lg"][class*="select-text"]'
44
+ )).filter(el => !el.querySelector('[class*="bg-gray-500/15"][class*="select-text"]'));
45
+
46
+ if (userBubbles.length === 0) return null;
47
+
48
+ const lastBubble = userBubbles[userBubbles.length - 1];
49
+ const textEl = lastBubble.querySelector('.whitespace-pre-wrap')
50
+ || lastBubble.querySelector('[style*="word-break"]');
51
+
52
+ const text = textEl
53
+ ? (textEl.textContent || '').trim()
54
+ : (lastBubble.textContent || '').trim();
55
+
56
+ if (!text || text.length < 1) return null;
57
+
58
+ return { text };
59
+ })()`;
60
+ /**
61
+ * Normalize text for echo hash comparison.
62
+ * Trims, collapses whitespace, and takes first 200 chars.
63
+ */
64
+ function normalizeForHash(text) {
65
+ return text.trim().replace(/\s+/g, ' ').slice(0, 200);
66
+ }
67
+ /**
68
+ * Compute a short hash for echo prevention.
69
+ */
70
+ function computeEchoHash(text) {
71
+ return (0, node_crypto_1.createHash)('sha256').update(normalizeForHash(text)).digest('hex').slice(0, 16);
72
+ }
73
+ /**
74
+ * Detects user messages posted directly in the Antigravity UI (e.g., from a PC).
75
+ * Follows the ApprovalDetector polling pattern.
76
+ */
77
+ class UserMessageDetector {
78
+ cdpService;
79
+ pollIntervalMs;
80
+ onUserMessage;
81
+ pollTimer = null;
82
+ isRunning = false;
83
+ /** Hash of the last detected message (for duplicate prevention) */
84
+ lastDetectedHash = null;
85
+ /** Set of echo hashes — messages sent by Remoat that should be ignored */
86
+ echoHashes = new Set();
87
+ /** Set of all previously detected message hashes (defense-in-depth dedup) */
88
+ seenHashes = new Set();
89
+ static MAX_SEEN_HASHES = 50;
90
+ /** True during the first poll — seeds existing DOM state without firing callback */
91
+ isPriming = false;
92
+ constructor(options) {
93
+ this.cdpService = options.cdpService;
94
+ this.pollIntervalMs = options.pollIntervalMs ?? 2000;
95
+ this.onUserMessage = options.onUserMessage;
96
+ }
97
+ /**
98
+ * Register a message hash as an echo (sent by Remoat).
99
+ * When this message is detected in the DOM, it will be skipped.
100
+ */
101
+ addEchoHash(text) {
102
+ const hash = computeEchoHash(text);
103
+ this.echoHashes.add(hash);
104
+ // Auto-cleanup: remove after 60s to prevent memory leak
105
+ setTimeout(() => {
106
+ this.echoHashes.delete(hash);
107
+ }, 60000);
108
+ }
109
+ /** Start monitoring. The first poll seeds the current DOM state without firing the callback. */
110
+ start() {
111
+ if (this.isRunning)
112
+ return;
113
+ this.isRunning = true;
114
+ this.lastDetectedHash = null;
115
+ this.seenHashes.clear();
116
+ this.isPriming = true;
117
+ // echoHashes are intentionally NOT cleared — they have their own 60s TTL
118
+ // and keeping them prevents false echo pickup during rapid stop/start cycles.
119
+ this.schedulePoll();
120
+ }
121
+ /** Stop monitoring. */
122
+ stop() {
123
+ this.isRunning = false;
124
+ if (this.pollTimer) {
125
+ clearTimeout(this.pollTimer);
126
+ this.pollTimer = null;
127
+ }
128
+ }
129
+ /** Returns whether monitoring is currently active. */
130
+ isActive() {
131
+ return this.isRunning;
132
+ }
133
+ /** Add a hash to the seenHashes set, evicting the oldest entry if at capacity. */
134
+ addToSeenHashes(hash) {
135
+ if (this.seenHashes.size >= UserMessageDetector.MAX_SEEN_HASHES) {
136
+ // Evict the oldest entry (first inserted)
137
+ const oldest = this.seenHashes.values().next().value;
138
+ if (oldest !== undefined) {
139
+ this.seenHashes.delete(oldest);
140
+ }
141
+ }
142
+ this.seenHashes.add(hash);
143
+ }
144
+ /** Schedule the next poll. */
145
+ schedulePoll() {
146
+ if (!this.isRunning)
147
+ return;
148
+ this.pollTimer = setTimeout(async () => {
149
+ await this.poll();
150
+ if (this.isRunning) {
151
+ this.schedulePoll();
152
+ }
153
+ }, this.pollIntervalMs);
154
+ }
155
+ /**
156
+ * Single poll iteration:
157
+ * 1. Get latest user message from DOM
158
+ * 2. Check for duplicates and echoes
159
+ * 3. Notify via callback on new detection
160
+ */
161
+ async poll() {
162
+ try {
163
+ const contextId = this.cdpService.getPrimaryContextId();
164
+ const callParams = {
165
+ expression: DETECT_USER_MESSAGE_SCRIPT,
166
+ returnByValue: true,
167
+ awaitPromise: false,
168
+ };
169
+ if (contextId !== null) {
170
+ callParams.contextId = contextId;
171
+ }
172
+ const result = await this.cdpService.call('Runtime.evaluate', callParams);
173
+ const info = result?.result?.value ?? null;
174
+ // Clear priming flag even if DOM is empty (e.g., new/empty chat)
175
+ if (this.isPriming && (!info || !info.text)) {
176
+ this.isPriming = false;
177
+ logger_1.logger.debug('[UserMessageDetector] Primed with empty DOM');
178
+ return;
179
+ }
180
+ if (info && info.text) {
181
+ const hash = computeEchoHash(info.text);
182
+ const preview = info.text.slice(0, 40);
183
+ // First poll: seed the current DOM state without firing callback
184
+ if (this.isPriming) {
185
+ this.isPriming = false;
186
+ this.lastDetectedHash = hash;
187
+ this.addToSeenHashes(hash);
188
+ logger_1.logger.debug(`[UserMessageDetector] Primed with existing message: "${preview}..."`);
189
+ return;
190
+ }
191
+ // Skip if same as last detected message
192
+ if (hash === this.lastDetectedHash)
193
+ return;
194
+ // Skip if already seen (defense-in-depth dedup)
195
+ if (this.seenHashes.has(hash)) {
196
+ logger_1.logger.debug(`[UserMessageDetector] seenHash hit, skipping: "${preview}..."`);
197
+ this.lastDetectedHash = hash;
198
+ return;
199
+ }
200
+ // Skip if this is an echo (sent by Remoat)
201
+ if (this.echoHashes.has(hash)) {
202
+ logger_1.logger.debug(`[UserMessageDetector] Echo hash match, skipping: "${preview}..."`);
203
+ this.lastDetectedHash = hash;
204
+ this.addToSeenHashes(hash);
205
+ return;
206
+ }
207
+ this.lastDetectedHash = hash;
208
+ this.addToSeenHashes(hash);
209
+ logger_1.logger.debug(`[UserMessageDetector] New message detected: "${preview}..."`);
210
+ this.onUserMessage(info);
211
+ }
212
+ }
213
+ catch (error) {
214
+ const message = error instanceof Error ? error.message : String(error);
215
+ if (message.includes('WebSocket is not connected'))
216
+ return;
217
+ logger_1.logger.error('[UserMessageDetector] Error during polling:', error);
218
+ }
219
+ }
220
+ }
221
+ exports.UserMessageDetector = UserMessageDetector;
222
+ //# sourceMappingURL=userMessageDetector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"userMessageDetector.js","sourceRoot":"","sources":["../../src/services/userMessageDetector.ts"],"names":[],"mappings":";;;AAAA,6CAAyC;AACzC,4CAAyC;AAkBzC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,0BAA0B,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAoC9B,CAAC;AAEN;;;GAGG;AACH,SAAS,gBAAgB,CAAC,IAAY;IAClC,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAC1D,CAAC;AAED;;GAEG;AACH,SAAS,eAAe,CAAC,IAAY;IACjC,OAAO,IAAA,wBAAU,EAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAC1F,CAAC;AAED;;;GAGG;AACH,MAAa,mBAAmB;IACX,UAAU,CAAa;IACvB,cAAc,CAAS;IACvB,aAAa,CAAkC;IAExD,SAAS,GAA0B,IAAI,CAAC;IACxC,SAAS,GAAY,KAAK,CAAC;IACnC,mEAAmE;IAC3D,gBAAgB,GAAkB,IAAI,CAAC;IAC/C,0EAA0E;IACzD,UAAU,GAAG,IAAI,GAAG,EAAU,CAAC;IAChD,6EAA6E;IAC5D,UAAU,GAAG,IAAI,GAAG,EAAU,CAAC;IACxC,MAAM,CAAU,eAAe,GAAG,EAAE,CAAC;IAC7C,oFAAoF;IAC5E,SAAS,GAAY,KAAK,CAAC;IAEnC,YAAY,OAAmC;QAC3C,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;QACrC,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,IAAI,CAAC;QACrD,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;IAC/C,CAAC;IAED;;;OAGG;IACH,WAAW,CAAC,IAAY;QACpB,MAAM,IAAI,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC1B,wDAAwD;QACxD,UAAU,CAAC,GAAG,EAAE;YACZ,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACjC,CAAC,EAAE,KAAK,CAAC,CAAC;IACd,CAAC;IAED,gGAAgG;IAChG,KAAK;QACD,IAAI,IAAI,CAAC,SAAS;YAAE,OAAO;QAC3B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;QAC7B,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;QACxB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,yEAAyE;QACzE,8EAA8E;QAC9E,IAAI,CAAC,YAAY,EAAE,CAAC;IACxB,CAAC;IAED,uBAAuB;IACvB,IAAI;QACA,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACvB,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACjB,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC7B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QAC1B,CAAC;IACL,CAAC;IAED,sDAAsD;IACtD,QAAQ;QACJ,OAAO,IAAI,CAAC,SAAS,CAAC;IAC1B,CAAC;IAED,kFAAkF;IAC1E,eAAe,CAAC,IAAY;QAChC,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,IAAI,mBAAmB,CAAC,eAAe,EAAE,CAAC;YAC9D,0CAA0C;YAC1C,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;YACrD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACvB,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACnC,CAAC;QACL,CAAC;QACD,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC;IAED,8BAA8B;IACtB,YAAY;QAChB,IAAI,CAAC,IAAI,CAAC,SAAS;YAAE,OAAO;QAC5B,IAAI,CAAC,SAAS,GAAG,UAAU,CAAC,KAAK,IAAI,EAAE;YACnC,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;YAClB,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;gBACjB,IAAI,CAAC,YAAY,EAAE,CAAC;YACxB,CAAC;QACL,CAAC,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;IAC5B,CAAC;IAED;;;;;OAKG;IACK,KAAK,CAAC,IAAI;QACd,IAAI,CAAC;YACD,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,mBAAmB,EAAE,CAAC;YACxD,MAAM,UAAU,GAA4B;gBACxC,UAAU,EAAE,0BAA0B;gBACtC,aAAa,EAAE,IAAI;gBACnB,YAAY,EAAE,KAAK;aACtB,CAAC;YACF,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;gBACrB,UAAU,CAAC,SAAS,GAAG,SAAS,CAAC;YACrC,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,kBAAkB,EAAE,UAAU,CAAC,CAAC;YAC1E,MAAM,IAAI,GAA2B,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI,IAAI,CAAC;YAEnE,iEAAiE;YACjE,IAAI,IAAI,CAAC,SAAS,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC1C,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;gBACvB,eAAM,CAAC,KAAK,CAAC,6CAA6C,CAAC,CAAC;gBAC5D,OAAO;YACX,CAAC;YAED,IAAI,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBACpB,MAAM,IAAI,GAAG,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACxC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBAEvC,iEAAiE;gBACjE,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;oBACjB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;oBACvB,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;oBAC7B,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;oBAC3B,eAAM,CAAC,KAAK,CAAC,wDAAwD,OAAO,MAAM,CAAC,CAAC;oBACpF,OAAO;gBACX,CAAC;gBAED,wCAAwC;gBACxC,IAAI,IAAI,KAAK,IAAI,CAAC,gBAAgB;oBAAE,OAAO;gBAE3C,gDAAgD;gBAChD,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC5B,eAAM,CAAC,KAAK,CAAC,kDAAkD,OAAO,MAAM,CAAC,CAAC;oBAC9E,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;oBAC7B,OAAO;gBACX,CAAC;gBAED,2CAA2C;gBAC3C,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC5B,eAAM,CAAC,KAAK,CAAC,qDAAqD,OAAO,MAAM,CAAC,CAAC;oBACjF,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;oBAC7B,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;oBAC3B,OAAO;gBACX,CAAC;gBAED,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;gBAC7B,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;gBAC3B,eAAM,CAAC,KAAK,CAAC,gDAAgD,OAAO,MAAM,CAAC,CAAC;gBAC5E,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;YAC7B,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvE,IAAI,OAAO,CAAC,QAAQ,CAAC,4BAA4B,CAAC;gBAAE,OAAO;YAC3D,eAAM,CAAC,KAAK,CAAC,6CAA6C,EAAE,KAAK,CAAC,CAAC;QACvE,CAAC;IACL,CAAC;;AA1JL,kDA2JC"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Service for workspace filesystem operations and path validation.
3
+ * Manages directories under WORKSPACE_BASE_DIR.
4
+ */
5
+ export declare class WorkspaceService {
6
+ private readonly baseDir;
7
+ constructor(baseDir: string);
8
+ /**
9
+ * Ensure the base directory exists, creating it if necessary
10
+ */
11
+ ensureBaseDir(): void;
12
+ /**
13
+ * Return a list of subdirectories in the base directory
14
+ */
15
+ scanWorkspaces(): string[];
16
+ /**
17
+ * Validate a relative path and return a safe absolute path
18
+ * @throws On path traversal detection
19
+ */
20
+ validatePath(relativePath: string): string;
21
+ /**
22
+ * Get the base directory path
23
+ */
24
+ getBaseDir(): string;
25
+ /**
26
+ * Return the absolute path of the specified workspace
27
+ */
28
+ getWorkspacePath(workspaceName: string): string;
29
+ /**
30
+ * Check if the specified workspace exists
31
+ */
32
+ exists(workspaceName: string): boolean;
33
+ }