@cloudcli-ai/cloudcli 1.30.0 → 1.31.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 (237) hide show
  1. package/dist/assets/{index-DI22MZMb.css → index-DF8TTVHl.css} +1 -1
  2. package/dist/assets/index-DbZAcc9z.js +1262 -0
  3. package/dist/index.html +2 -2
  4. package/dist-server/server/index.js +115 -955
  5. package/dist-server/server/index.js.map +1 -1
  6. package/dist-server/server/middleware/auth.js +1 -1
  7. package/dist-server/server/middleware/auth.js.map +1 -1
  8. package/dist-server/server/modules/database/connection.js +125 -0
  9. package/dist-server/server/modules/database/connection.js.map +1 -0
  10. package/dist-server/server/modules/database/index.js +13 -0
  11. package/dist-server/server/modules/database/index.js.map +1 -0
  12. package/dist-server/server/modules/database/init-db.js +18 -0
  13. package/dist-server/server/modules/database/init-db.js.map +1 -0
  14. package/dist-server/server/modules/database/migrations.js +370 -0
  15. package/dist-server/server/modules/database/migrations.js.map +1 -0
  16. package/dist-server/server/modules/database/repositories/api-keys.js +72 -0
  17. package/dist-server/server/modules/database/repositories/api-keys.js.map +1 -0
  18. package/dist-server/server/modules/database/repositories/app-config.js +47 -0
  19. package/dist-server/server/modules/database/repositories/app-config.js.map +1 -0
  20. package/dist-server/server/modules/database/repositories/credentials.js +68 -0
  21. package/dist-server/server/modules/database/repositories/credentials.js.map +1 -0
  22. package/dist-server/server/modules/database/repositories/github-tokens.js +54 -0
  23. package/dist-server/server/modules/database/repositories/github-tokens.js.map +1 -0
  24. package/dist-server/server/modules/database/repositories/notification-preferences.js +72 -0
  25. package/dist-server/server/modules/database/repositories/notification-preferences.js.map +1 -0
  26. package/dist-server/server/modules/database/repositories/projects.db.integration.test.js +64 -0
  27. package/dist-server/server/modules/database/repositories/projects.db.integration.test.js.map +1 -0
  28. package/dist-server/server/modules/database/repositories/projects.db.js +160 -0
  29. package/dist-server/server/modules/database/repositories/projects.db.js.map +1 -0
  30. package/dist-server/server/modules/database/repositories/push-subscriptions.js +49 -0
  31. package/dist-server/server/modules/database/repositories/push-subscriptions.js.map +1 -0
  32. package/dist-server/server/modules/database/repositories/scan-state.db.js +31 -0
  33. package/dist-server/server/modules/database/repositories/scan-state.db.js.map +1 -0
  34. package/dist-server/server/modules/database/repositories/sessions.db.js +109 -0
  35. package/dist-server/server/modules/database/repositories/sessions.db.js.map +1 -0
  36. package/dist-server/server/modules/database/repositories/users.js +88 -0
  37. package/dist-server/server/modules/database/repositories/users.js.map +1 -0
  38. package/dist-server/server/modules/database/repositories/vapid-keys.js +38 -0
  39. package/dist-server/server/modules/database/repositories/vapid-keys.js.map +1 -0
  40. package/dist-server/server/modules/database/schema.js +143 -0
  41. package/dist-server/server/modules/database/schema.js.map +1 -0
  42. package/dist-server/server/modules/projects/index.js +4 -0
  43. package/dist-server/server/modules/projects/index.js.map +1 -0
  44. package/dist-server/server/modules/projects/projects.routes.js +188 -0
  45. package/dist-server/server/modules/projects/projects.routes.js.map +1 -0
  46. package/dist-server/server/modules/projects/services/project-clone.service.js +219 -0
  47. package/dist-server/server/modules/projects/services/project-clone.service.js.map +1 -0
  48. package/dist-server/server/modules/projects/services/project-delete.service.js +65 -0
  49. package/dist-server/server/modules/projects/services/project-delete.service.js.map +1 -0
  50. package/dist-server/server/modules/projects/services/project-management.service.js +93 -0
  51. package/dist-server/server/modules/projects/services/project-management.service.js.map +1 -0
  52. package/dist-server/server/modules/projects/services/project-star.service.js +60 -0
  53. package/dist-server/server/modules/projects/services/project-star.service.js.map +1 -0
  54. package/dist-server/server/modules/projects/services/projects-has-taskmaster.service.js +167 -0
  55. package/dist-server/server/modules/projects/services/projects-has-taskmaster.service.js.map +1 -0
  56. package/dist-server/server/modules/projects/services/projects-with-sessions-fetch.service.js +169 -0
  57. package/dist-server/server/modules/projects/services/projects-with-sessions-fetch.service.js.map +1 -0
  58. package/dist-server/server/modules/projects/tests/project-clone.service.test.js +126 -0
  59. package/dist-server/server/modules/projects/tests/project-clone.service.test.js.map +1 -0
  60. package/dist-server/server/modules/projects/tests/project-management.service.test.js +85 -0
  61. package/dist-server/server/modules/projects/tests/project-management.service.test.js.map +1 -0
  62. package/dist-server/server/modules/projects/tests/project-star.service.test.js +95 -0
  63. package/dist-server/server/modules/projects/tests/project-star.service.test.js.map +1 -0
  64. package/dist-server/server/modules/projects/tests/projects-has-taskmaster.service.test.js +87 -0
  65. package/dist-server/server/modules/projects/tests/projects-has-taskmaster.service.test.js.map +1 -0
  66. package/dist-server/server/modules/providers/index.js +4 -0
  67. package/dist-server/server/modules/providers/index.js.map +1 -0
  68. package/dist-server/server/modules/providers/list/claude/claude-session-synchronizer.provider.js +63 -0
  69. package/dist-server/server/modules/providers/list/claude/claude-session-synchronizer.provider.js.map +1 -0
  70. package/dist-server/server/modules/providers/list/claude/claude-sessions.provider.js +144 -7
  71. package/dist-server/server/modules/providers/list/claude/claude-sessions.provider.js.map +1 -1
  72. package/dist-server/server/modules/providers/list/claude/claude.provider.js +2 -0
  73. package/dist-server/server/modules/providers/list/claude/claude.provider.js.map +1 -1
  74. package/dist-server/server/modules/providers/list/codex/codex-session-synchronizer.provider.js +71 -0
  75. package/dist-server/server/modules/providers/list/codex/codex-session-synchronizer.provider.js.map +1 -0
  76. package/dist-server/server/modules/providers/list/codex/codex-sessions.provider.js +225 -13
  77. package/dist-server/server/modules/providers/list/codex/codex-sessions.provider.js.map +1 -1
  78. package/dist-server/server/modules/providers/list/codex/codex.provider.js +2 -0
  79. package/dist-server/server/modules/providers/list/codex/codex.provider.js.map +1 -1
  80. package/dist-server/server/modules/providers/list/cursor/cursor-session-synchronizer.provider.js +127 -0
  81. package/dist-server/server/modules/providers/list/cursor/cursor-session-synchronizer.provider.js.map +1 -0
  82. package/dist-server/server/modules/providers/list/cursor/cursor.provider.js +2 -0
  83. package/dist-server/server/modules/providers/list/cursor/cursor.provider.js.map +1 -1
  84. package/dist-server/server/modules/providers/list/gemini/gemini-session-synchronizer.provider.js +296 -0
  85. package/dist-server/server/modules/providers/list/gemini/gemini-session-synchronizer.provider.js.map +1 -0
  86. package/dist-server/server/modules/providers/list/gemini/gemini-sessions.provider.js +277 -10
  87. package/dist-server/server/modules/providers/list/gemini/gemini-sessions.provider.js.map +1 -1
  88. package/dist-server/server/modules/providers/list/gemini/gemini.provider.js +2 -0
  89. package/dist-server/server/modules/providers/list/gemini/gemini.provider.js.map +1 -1
  90. package/dist-server/server/modules/providers/provider.routes.js +172 -0
  91. package/dist-server/server/modules/providers/provider.routes.js.map +1 -1
  92. package/dist-server/server/modules/providers/services/session-conversations-search.service.js +868 -0
  93. package/dist-server/server/modules/providers/services/session-conversations-search.service.js.map +1 -0
  94. package/dist-server/server/modules/providers/services/session-synchronizer.service.js +56 -0
  95. package/dist-server/server/modules/providers/services/session-synchronizer.service.js.map +1 -0
  96. package/dist-server/server/modules/providers/services/sessions-watcher.service.js +234 -0
  97. package/dist-server/server/modules/providers/services/sessions-watcher.service.js.map +1 -0
  98. package/dist-server/server/modules/providers/services/sessions.service.js +78 -3
  99. package/dist-server/server/modules/providers/services/sessions.service.js.map +1 -1
  100. package/dist-server/server/modules/providers/shared/base/abstract.provider.js.map +1 -1
  101. package/dist-server/server/modules/websocket/index.js +3 -0
  102. package/dist-server/server/modules/websocket/index.js.map +1 -0
  103. package/dist-server/server/modules/websocket/services/chat-websocket.service.js +188 -0
  104. package/dist-server/server/modules/websocket/services/chat-websocket.service.js.map +1 -0
  105. package/dist-server/server/modules/websocket/services/plugin-websocket-proxy.service.js +52 -0
  106. package/dist-server/server/modules/websocket/services/plugin-websocket-proxy.service.js.map +1 -0
  107. package/dist-server/server/modules/websocket/services/shell-websocket.service.js +334 -0
  108. package/dist-server/server/modules/websocket/services/shell-websocket.service.js.map +1 -0
  109. package/dist-server/server/modules/websocket/services/websocket-auth.service.js +32 -0
  110. package/dist-server/server/modules/websocket/services/websocket-auth.service.js.map +1 -0
  111. package/dist-server/server/modules/websocket/services/websocket-server.service.js +36 -0
  112. package/dist-server/server/modules/websocket/services/websocket-server.service.js.map +1 -0
  113. package/dist-server/server/modules/websocket/services/websocket-state.service.js +14 -0
  114. package/dist-server/server/modules/websocket/services/websocket-state.service.js.map +1 -0
  115. package/dist-server/server/modules/websocket/services/websocket-writer.service.js +32 -0
  116. package/dist-server/server/modules/websocket/services/websocket-writer.service.js.map +1 -0
  117. package/dist-server/server/routes/agent.js +10 -17
  118. package/dist-server/server/routes/agent.js.map +1 -1
  119. package/dist-server/server/routes/auth.js +3 -1
  120. package/dist-server/server/routes/auth.js.map +1 -1
  121. package/dist-server/server/routes/commands.js +1 -1
  122. package/dist-server/server/routes/commands.js.map +1 -1
  123. package/dist-server/server/routes/gemini.js +2 -2
  124. package/dist-server/server/routes/gemini.js.map +1 -1
  125. package/dist-server/server/routes/git.js +33 -29
  126. package/dist-server/server/routes/git.js.map +1 -1
  127. package/dist-server/server/routes/settings.js +1 -1
  128. package/dist-server/server/routes/settings.js.map +1 -1
  129. package/dist-server/server/routes/taskmaster.js +97 -110
  130. package/dist-server/server/routes/taskmaster.js.map +1 -1
  131. package/dist-server/server/routes/user.js +1 -1
  132. package/dist-server/server/routes/user.js.map +1 -1
  133. package/dist-server/server/services/notification-orchestrator.js +2 -2
  134. package/dist-server/server/services/notification-orchestrator.js.map +1 -1
  135. package/dist-server/server/services/vapid-keys.js +2 -1
  136. package/dist-server/server/services/vapid-keys.js.map +1 -1
  137. package/dist-server/server/shared/types.js +0 -1
  138. package/dist-server/server/shared/types.js.map +1 -1
  139. package/dist-server/server/shared/utils.js +408 -7
  140. package/dist-server/server/shared/utils.js.map +1 -1
  141. package/dist-server/server/utils/taskmaster-websocket.js +18 -12
  142. package/dist-server/server/utils/taskmaster-websocket.js.map +1 -1
  143. package/dist-server/shared/modelConstants.js +2 -1
  144. package/dist-server/shared/modelConstants.js.map +1 -1
  145. package/package.json +3 -1
  146. package/server/index.js +146 -1012
  147. package/server/middleware/auth.js +1 -1
  148. package/server/modules/database/connection.ts +143 -0
  149. package/server/modules/database/index.ts +12 -0
  150. package/server/modules/database/init-db.ts +17 -0
  151. package/server/modules/database/migrations.ts +442 -0
  152. package/server/modules/database/repositories/api-keys.ts +119 -0
  153. package/server/modules/database/repositories/app-config.ts +53 -0
  154. package/server/modules/database/repositories/credentials.ts +106 -0
  155. package/server/modules/database/repositories/github-tokens.ts +100 -0
  156. package/server/modules/database/repositories/notification-preferences.ts +103 -0
  157. package/server/modules/database/repositories/projects.db.integration.test.ts +72 -0
  158. package/server/modules/database/repositories/projects.db.ts +183 -0
  159. package/server/modules/database/repositories/push-subscriptions.ts +80 -0
  160. package/server/modules/database/repositories/scan-state.db.ts +42 -0
  161. package/server/modules/database/repositories/sessions.db.ts +174 -0
  162. package/server/modules/database/repositories/users.ts +140 -0
  163. package/server/modules/database/repositories/vapid-keys.ts +57 -0
  164. package/server/modules/database/schema.ts +152 -0
  165. package/server/modules/projects/index.ts +6 -0
  166. package/server/modules/projects/projects.routes.ts +247 -0
  167. package/server/modules/projects/services/project-clone.service.ts +321 -0
  168. package/server/modules/projects/services/project-delete.service.ts +75 -0
  169. package/server/modules/projects/services/project-management.service.ts +150 -0
  170. package/server/modules/projects/services/project-star.service.ts +78 -0
  171. package/server/modules/projects/services/projects-has-taskmaster.service.ts +248 -0
  172. package/server/modules/projects/services/projects-with-sessions-fetch.service.ts +285 -0
  173. package/server/modules/projects/tests/project-clone.service.test.ts +183 -0
  174. package/server/modules/projects/tests/project-management.service.test.ts +117 -0
  175. package/server/modules/projects/tests/project-star.service.test.ts +123 -0
  176. package/server/modules/projects/tests/projects-has-taskmaster.service.test.ts +105 -0
  177. package/server/modules/providers/index.ts +4 -0
  178. package/server/modules/providers/list/claude/claude-session-synchronizer.provider.ts +110 -0
  179. package/server/modules/providers/list/claude/claude-sessions.provider.ts +182 -13
  180. package/server/modules/providers/list/claude/claude.provider.ts +3 -1
  181. package/server/modules/providers/list/codex/codex-session-synchronizer.provider.ts +119 -0
  182. package/server/modules/providers/list/codex/codex-sessions.provider.ts +262 -17
  183. package/server/modules/providers/list/codex/codex.provider.ts +3 -1
  184. package/server/modules/providers/list/cursor/cursor-session-synchronizer.provider.ts +176 -0
  185. package/server/modules/providers/list/cursor/cursor.provider.ts +3 -1
  186. package/server/modules/providers/list/gemini/gemini-session-synchronizer.provider.ts +401 -0
  187. package/server/modules/providers/list/gemini/gemini-sessions.provider.ts +327 -13
  188. package/server/modules/providers/list/gemini/gemini.provider.ts +3 -1
  189. package/server/modules/providers/provider.routes.ts +220 -12
  190. package/server/modules/providers/services/session-conversations-search.service.ts +1167 -0
  191. package/server/modules/providers/services/session-synchronizer.service.ts +74 -0
  192. package/server/modules/providers/services/sessions-watcher.service.ts +283 -0
  193. package/server/modules/providers/services/sessions.service.ts +89 -4
  194. package/server/modules/providers/shared/base/abstract.provider.ts +8 -1
  195. package/server/modules/websocket/README.md +267 -0
  196. package/server/modules/websocket/index.ts +2 -0
  197. package/server/modules/websocket/services/chat-websocket.service.ts +271 -0
  198. package/server/modules/websocket/services/plugin-websocket-proxy.service.ts +65 -0
  199. package/server/modules/websocket/services/shell-websocket.service.ts +453 -0
  200. package/server/modules/websocket/services/websocket-auth.service.ts +54 -0
  201. package/server/modules/websocket/services/websocket-server.service.ts +58 -0
  202. package/server/modules/websocket/services/websocket-state.service.ts +16 -0
  203. package/server/modules/websocket/services/websocket-writer.service.ts +38 -0
  204. package/server/routes/agent.js +11 -16
  205. package/server/routes/auth.js +4 -2
  206. package/server/routes/commands.js +1 -1
  207. package/server/routes/gemini.js +3 -2
  208. package/server/routes/git.js +33 -28
  209. package/server/routes/settings.js +1 -1
  210. package/server/routes/taskmaster.js +108 -111
  211. package/server/routes/user.js +1 -1
  212. package/server/services/notification-orchestrator.js +3 -2
  213. package/server/services/vapid-keys.js +2 -1
  214. package/server/shared/interfaces.ts +39 -1
  215. package/server/shared/types.ts +185 -30
  216. package/server/shared/utils.ts +485 -9
  217. package/server/utils/taskmaster-websocket.js +19 -13
  218. package/shared/modelConstants.js +2 -1
  219. package/dist/assets/index-RX-W_g_Q.js +0 -1262
  220. package/dist-server/server/database/db.js +0 -535
  221. package/dist-server/server/database/db.js.map +0 -1
  222. package/dist-server/server/database/schema.js +0 -97
  223. package/dist-server/server/database/schema.js.map +0 -1
  224. package/dist-server/server/projects.js +0 -2325
  225. package/dist-server/server/projects.js.map +0 -1
  226. package/dist-server/server/routes/codex.js +0 -18
  227. package/dist-server/server/routes/codex.js.map +0 -1
  228. package/dist-server/server/routes/messages.js +0 -56
  229. package/dist-server/server/routes/messages.js.map +0 -1
  230. package/dist-server/server/routes/projects.js +0 -505
  231. package/dist-server/server/routes/projects.js.map +0 -1
  232. package/server/database/db.js +0 -593
  233. package/server/database/schema.js +0 -102
  234. package/server/projects.js +0 -2555
  235. package/server/routes/codex.js +0 -19
  236. package/server/routes/messages.js +0 -61
  237. package/server/routes/projects.js +0 -548
@@ -1,11 +1,13 @@
1
1
  import { AbstractProvider } from '../../../../modules/providers/shared/base/abstract.provider.js';
2
2
  import { CodexProviderAuth } from '../../../../modules/providers/list/codex/codex-auth.provider.js';
3
3
  import { CodexMcpProvider } from '../../../../modules/providers/list/codex/codex-mcp.provider.js';
4
+ import { CodexSessionSynchronizer } from '../../../../modules/providers/list/codex/codex-session-synchronizer.provider.js';
4
5
  import { CodexSessionsProvider } from '../../../../modules/providers/list/codex/codex-sessions.provider.js';
5
6
  export class CodexProvider extends AbstractProvider {
6
7
  mcp = new CodexMcpProvider();
7
8
  auth = new CodexProviderAuth();
8
9
  sessions = new CodexSessionsProvider();
10
+ sessionSynchronizer = new CodexSessionSynchronizer();
9
11
  constructor() {
10
12
  super('codex');
11
13
  }
@@ -1 +1 @@
1
- {"version":3,"file":"codex.provider.js","sourceRoot":"","sources":["../../../../../../server/modules/providers/list/codex/codex.provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sDAAsD,CAAC;AACxF,OAAO,EAAE,iBAAiB,EAAE,MAAM,uDAAuD,CAAC;AAC1F,OAAO,EAAE,gBAAgB,EAAE,MAAM,sDAAsD,CAAC;AACxF,OAAO,EAAE,qBAAqB,EAAE,MAAM,2DAA2D,CAAC;AAGlG,MAAM,OAAO,aAAc,SAAQ,gBAAgB;IACxC,GAAG,GAAG,IAAI,gBAAgB,EAAE,CAAC;IAC7B,IAAI,GAAkB,IAAI,iBAAiB,EAAE,CAAC;IAC9C,QAAQ,GAAsB,IAAI,qBAAqB,EAAE,CAAC;IAEnE;QACE,KAAK,CAAC,OAAO,CAAC,CAAC;IACjB,CAAC;CACF"}
1
+ {"version":3,"file":"codex.provider.js","sourceRoot":"","sources":["../../../../../../server/modules/providers/list/codex/codex.provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sDAAsD,CAAC;AACxF,OAAO,EAAE,iBAAiB,EAAE,MAAM,uDAAuD,CAAC;AAC1F,OAAO,EAAE,gBAAgB,EAAE,MAAM,sDAAsD,CAAC;AACxF,OAAO,EAAE,wBAAwB,EAAE,MAAM,uEAAuE,CAAC;AACjH,OAAO,EAAE,qBAAqB,EAAE,MAAM,2DAA2D,CAAC;AAGlG,MAAM,OAAO,aAAc,SAAQ,gBAAgB;IACxC,GAAG,GAAG,IAAI,gBAAgB,EAAE,CAAC;IAC7B,IAAI,GAAkB,IAAI,iBAAiB,EAAE,CAAC;IAC9C,QAAQ,GAAsB,IAAI,qBAAqB,EAAE,CAAC;IAC1D,mBAAmB,GAAiC,IAAI,wBAAwB,EAAE,CAAC;IAE5F;QACE,KAAK,CAAC,OAAO,CAAC,CAAC;IACjB,CAAC;CACF"}
@@ -0,0 +1,127 @@
1
+ import crypto from 'node:crypto';
2
+ import fs from 'node:fs';
3
+ import fsp from 'node:fs/promises';
4
+ import os from 'node:os';
5
+ import path from 'node:path';
6
+ import readline from 'node:readline';
7
+ import { sessionsDb } from '../../../../modules/database/index.js';
8
+ import { extractFirstValidJsonlData, findFilesRecursivelyCreatedAfter, normalizeSessionName, readFileTimestamps, } from '../../../../shared/utils.js';
9
+ /**
10
+ * Returns directory entries or an empty list when the folder is missing.
11
+ */
12
+ async function listDirectoryEntriesSafe(directoryPath) {
13
+ try {
14
+ return await fsp.readdir(directoryPath, { withFileTypes: true });
15
+ }
16
+ catch {
17
+ return [];
18
+ }
19
+ }
20
+ /**
21
+ * Session indexer for Cursor transcript artifacts.
22
+ */
23
+ export class CursorSessionSynchronizer {
24
+ provider = 'cursor';
25
+ cursorHome = path.join(os.homedir(), '.cursor');
26
+ /**
27
+ * Scans Cursor chats and upserts discovered sessions into DB.
28
+ */
29
+ async synchronize(since) {
30
+ const projectsDir = path.join(this.cursorHome, 'projects');
31
+ const projectEntries = await listDirectoryEntriesSafe(projectsDir);
32
+ const seenProjectPaths = new Set();
33
+ let processed = 0;
34
+ for (const entry of projectEntries) {
35
+ if (!entry.isDirectory()) {
36
+ continue;
37
+ }
38
+ const workerLogPath = path.join(projectsDir, entry.name, 'worker.log');
39
+ const projectPath = await this.extractProjectPathFromWorkerLog(workerLogPath);
40
+ if (!projectPath || seenProjectPaths.has(projectPath)) {
41
+ continue;
42
+ }
43
+ seenProjectPaths.add(projectPath);
44
+ const projectHash = this.md5(projectPath);
45
+ const chatsDir = path.join(this.cursorHome, 'chats', projectHash);
46
+ const files = await findFilesRecursivelyCreatedAfter(chatsDir, '.jsonl', since ?? null);
47
+ for (const filePath of files) {
48
+ const parsed = await this.processSessionFile(filePath);
49
+ if (!parsed) {
50
+ continue;
51
+ }
52
+ const timestamps = await readFileTimestamps(filePath);
53
+ sessionsDb.createSession(parsed.sessionId, this.provider, parsed.projectPath, parsed.sessionName, timestamps.createdAt, timestamps.updatedAt, filePath);
54
+ processed += 1;
55
+ }
56
+ }
57
+ return processed;
58
+ }
59
+ /**
60
+ * Parses and upserts one Cursor session JSONL file.
61
+ */
62
+ async synchronizeFile(filePath) {
63
+ if (!filePath.endsWith('.jsonl')) {
64
+ return null;
65
+ }
66
+ const parsed = await this.processSessionFile(filePath);
67
+ if (!parsed) {
68
+ return null;
69
+ }
70
+ const timestamps = await readFileTimestamps(filePath);
71
+ return sessionsDb.createSession(parsed.sessionId, this.provider, parsed.projectPath, parsed.sessionName, timestamps.createdAt, timestamps.updatedAt, filePath);
72
+ }
73
+ /**
74
+ * Produces the same project hash Cursor uses in chat directory names.
75
+ */
76
+ md5(input) {
77
+ return crypto.createHash('md5').update(input).digest('hex');
78
+ }
79
+ /**
80
+ * Extracts project path from Cursor worker.log.
81
+ */
82
+ async extractProjectPathFromWorkerLog(filePath) {
83
+ try {
84
+ const fileStream = fs.createReadStream(filePath, { encoding: 'utf8' });
85
+ const lineReader = readline.createInterface({ input: fileStream, crlfDelay: Infinity });
86
+ for await (const line of lineReader) {
87
+ const match = line.match(/workspacePath=(.*)$/);
88
+ const projectPath = match?.[1]?.trim();
89
+ if (projectPath) {
90
+ lineReader.close();
91
+ fileStream.close();
92
+ return projectPath;
93
+ }
94
+ }
95
+ }
96
+ catch {
97
+ // Missing worker logs are valid for partial or incomplete session data.
98
+ }
99
+ return null;
100
+ }
101
+ /**
102
+ * Extracts session metadata from one Cursor JSONL session file.
103
+ */
104
+ async processSessionFile(filePath) {
105
+ const sessionId = path.basename(filePath, '.jsonl');
106
+ const grandparentDir = path.dirname(path.dirname(filePath));
107
+ const workerLogPath = path.join(grandparentDir, 'worker.log');
108
+ const projectPath = await this.extractProjectPathFromWorkerLog(workerLogPath);
109
+ if (!projectPath) {
110
+ return null;
111
+ }
112
+ return extractFirstValidJsonlData(filePath, (rawData) => {
113
+ const data = rawData;
114
+ if (data.role !== 'user') {
115
+ return null;
116
+ }
117
+ const text = typeof data.message?.content?.[0]?.text === 'string' ? data.message.content[0].text : '';
118
+ const firstLine = text.replace(/<\/?user_query>/g, '').trim().split('\n')[0];
119
+ return {
120
+ sessionId,
121
+ projectPath,
122
+ sessionName: normalizeSessionName(firstLine, 'Untitled Cursor Session'),
123
+ };
124
+ });
125
+ }
126
+ }
127
+ //# sourceMappingURL=cursor-session-synchronizer.provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cursor-session-synchronizer.provider.js","sourceRoot":"","sources":["../../../../../../server/modules/providers/list/cursor/cursor-session-synchronizer.provider.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,GAAG,MAAM,kBAAkB,CAAC;AACnC,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,QAAQ,MAAM,eAAe,CAAC;AAErC,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACzD,OAAO,EACL,0BAA0B,EAC1B,gCAAgC,EAChC,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,mBAAmB,CAAC;AAS3B;;GAEG;AACH,KAAK,UAAU,wBAAwB,CACrC,aAAqB;IAErB,IAAI,CAAC;QACH,OAAO,MAAM,GAAG,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IACnE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,OAAO,yBAAyB;IACnB,QAAQ,GAAG,QAAiB,CAAC;IAC7B,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;IAEjE;;OAEG;IACH,KAAK,CAAC,WAAW,CAAC,KAAY;QAC5B,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;QAC3D,MAAM,cAAc,GAAG,MAAM,wBAAwB,CAAC,WAAW,CAAC,CAAC;QACnE,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAU,CAAC;QAE3C,IAAI,SAAS,GAAG,CAAC,CAAC;QAClB,KAAK,MAAM,KAAK,IAAI,cAAc,EAAE,CAAC;YACnC,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;gBACzB,SAAS;YACX,CAAC;YAED,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;YACvE,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,+BAA+B,CAAC,aAAa,CAAC,CAAC;YAC9E,IAAI,CAAC,WAAW,IAAI,gBAAgB,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;gBACtD,SAAS;YACX,CAAC;YAED,gBAAgB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YAClC,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YAC1C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC;YAClE,MAAM,KAAK,GAAG,MAAM,gCAAgC,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,IAAI,IAAI,CAAC,CAAC;YAExF,KAAK,MAAM,QAAQ,IAAI,KAAK,EAAE,CAAC;gBAC7B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC;gBACvD,IAAI,CAAC,MAAM,EAAE,CAAC;oBACZ,SAAS;gBACX,CAAC;gBAED,MAAM,UAAU,GAAG,MAAM,kBAAkB,CAAC,QAAQ,CAAC,CAAC;gBACtD,UAAU,CAAC,aAAa,CACtB,MAAM,CAAC,SAAS,EAChB,IAAI,CAAC,QAAQ,EACb,MAAM,CAAC,WAAW,EAClB,MAAM,CAAC,WAAW,EAClB,UAAU,CAAC,SAAS,EACpB,UAAU,CAAC,SAAS,EACpB,QAAQ,CACT,CAAC;gBACF,SAAS,IAAI,CAAC,CAAC;YACjB,CAAC;QACH,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,eAAe,CAAC,QAAgB;QACpC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YACjC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC;QACvD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,UAAU,GAAG,MAAM,kBAAkB,CAAC,QAAQ,CAAC,CAAC;QACtD,OAAO,UAAU,CAAC,aAAa,CAC7B,MAAM,CAAC,SAAS,EAChB,IAAI,CAAC,QAAQ,EACb,MAAM,CAAC,WAAW,EAClB,MAAM,CAAC,WAAW,EAClB,UAAU,CAAC,SAAS,EACpB,UAAU,CAAC,SAAS,EACpB,QAAQ,CACT,CAAC;IACJ,CAAC;IAED;;OAEG;IACK,GAAG,CAAC,KAAa;QACvB,OAAO,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC9D,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,+BAA+B,CAAC,QAAgB;QAC5D,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,EAAE,CAAC,gBAAgB,CAAC,QAAQ,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;YACvE,MAAM,UAAU,GAAG,QAAQ,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;YAExF,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;gBACpC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;gBAChD,MAAM,WAAW,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;gBACvC,IAAI,WAAW,EAAE,CAAC;oBAChB,UAAU,CAAC,KAAK,EAAE,CAAC;oBACnB,UAAU,CAAC,KAAK,EAAE,CAAC;oBACnB,OAAO,WAAW,CAAC;gBACrB,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,wEAAwE;QAC1E,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,kBAAkB,CAAC,QAAgB;QAC/C,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACpD,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC5D,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,YAAY,CAAC,CAAC;QAC9D,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,+BAA+B,CAAC,aAAa,CAAC,CAAC;QAE9E,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,0BAA0B,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,EAAE;YACtD,MAAM,IAAI,GAAG,OAA8B,CAAC;YAC5C,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBACzB,OAAO,IAAI,CAAC;YACd,CAAC;YAED,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YACtG,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YAE7E,OAAO;gBACL,SAAS;gBACT,WAAW;gBACX,WAAW,EAAE,oBAAoB,CAAC,SAAS,EAAE,yBAAyB,CAAC;aACxE,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
@@ -1,11 +1,13 @@
1
1
  import { AbstractProvider } from '../../../../modules/providers/shared/base/abstract.provider.js';
2
2
  import { CursorProviderAuth } from '../../../../modules/providers/list/cursor/cursor-auth.provider.js';
3
3
  import { CursorMcpProvider } from '../../../../modules/providers/list/cursor/cursor-mcp.provider.js';
4
+ import { CursorSessionSynchronizer } from '../../../../modules/providers/list/cursor/cursor-session-synchronizer.provider.js';
4
5
  import { CursorSessionsProvider } from '../../../../modules/providers/list/cursor/cursor-sessions.provider.js';
5
6
  export class CursorProvider extends AbstractProvider {
6
7
  mcp = new CursorMcpProvider();
7
8
  auth = new CursorProviderAuth();
8
9
  sessions = new CursorSessionsProvider();
10
+ sessionSynchronizer = new CursorSessionSynchronizer();
9
11
  constructor() {
10
12
  super('cursor');
11
13
  }
@@ -1 +1 @@
1
- {"version":3,"file":"cursor.provider.js","sourceRoot":"","sources":["../../../../../../server/modules/providers/list/cursor/cursor.provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sDAAsD,CAAC;AACxF,OAAO,EAAE,kBAAkB,EAAE,MAAM,yDAAyD,CAAC;AAC7F,OAAO,EAAE,iBAAiB,EAAE,MAAM,wDAAwD,CAAC;AAC3F,OAAO,EAAE,sBAAsB,EAAE,MAAM,6DAA6D,CAAC;AAGrG,MAAM,OAAO,cAAe,SAAQ,gBAAgB;IACzC,GAAG,GAAG,IAAI,iBAAiB,EAAE,CAAC;IAC9B,IAAI,GAAkB,IAAI,kBAAkB,EAAE,CAAC;IAC/C,QAAQ,GAAsB,IAAI,sBAAsB,EAAE,CAAC;IAEpE;QACE,KAAK,CAAC,QAAQ,CAAC,CAAC;IAClB,CAAC;CACF"}
1
+ {"version":3,"file":"cursor.provider.js","sourceRoot":"","sources":["../../../../../../server/modules/providers/list/cursor/cursor.provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sDAAsD,CAAC;AACxF,OAAO,EAAE,kBAAkB,EAAE,MAAM,yDAAyD,CAAC;AAC7F,OAAO,EAAE,iBAAiB,EAAE,MAAM,wDAAwD,CAAC;AAC3F,OAAO,EAAE,yBAAyB,EAAE,MAAM,yEAAyE,CAAC;AACpH,OAAO,EAAE,sBAAsB,EAAE,MAAM,6DAA6D,CAAC;AAGrG,MAAM,OAAO,cAAe,SAAQ,gBAAgB;IACzC,GAAG,GAAG,IAAI,iBAAiB,EAAE,CAAC;IAC9B,IAAI,GAAkB,IAAI,kBAAkB,EAAE,CAAC;IAC/C,QAAQ,GAAsB,IAAI,sBAAsB,EAAE,CAAC;IAC3D,mBAAmB,GAAiC,IAAI,yBAAyB,EAAE,CAAC;IAE7F;QACE,KAAK,CAAC,QAAQ,CAAC,CAAC;IAClB,CAAC;CACF"}
@@ -0,0 +1,296 @@
1
+ import crypto from 'node:crypto';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+ import { readFile } from 'node:fs/promises';
5
+ import { projectsDb, sessionsDb } from '../../../../modules/database/index.js';
6
+ import { findFilesRecursivelyCreatedAfter, normalizeProjectPath, normalizeSessionName, readFileTimestamps, } from '../../../../shared/utils.js';
7
+ /**
8
+ * Session indexer for Gemini transcript artifacts.
9
+ */
10
+ export class GeminiSessionSynchronizer {
11
+ provider = 'gemini';
12
+ geminiHome = path.join(os.homedir(), '.gemini');
13
+ /**
14
+ * Scans Gemini legacy JSON and new JSONL artifacts and upserts sessions into DB.
15
+ */
16
+ async synchronize(since) {
17
+ const projectHashLookup = this.buildProjectHashLookup();
18
+ const legacySessionFiles = await findFilesRecursivelyCreatedAfter(path.join(this.geminiHome, 'sessions'), '.json', since ?? null);
19
+ const legacyTempFiles = await findFilesRecursivelyCreatedAfter(path.join(this.geminiHome, 'tmp'), '.json', since ?? null);
20
+ const jsonlSessionFiles = await findFilesRecursivelyCreatedAfter(path.join(this.geminiHome, 'sessions'), '.jsonl', since ?? null);
21
+ const jsonlTempFiles = await findFilesRecursivelyCreatedAfter(path.join(this.geminiHome, 'tmp'), '.jsonl', since ?? null);
22
+ // Process legacy JSON first, then JSONL. If both exist for a session id,
23
+ // the JSONL artifact becomes the canonical jsonl_path via upsert.
24
+ const files = [
25
+ ...legacySessionFiles,
26
+ ...legacyTempFiles,
27
+ ...jsonlSessionFiles,
28
+ ...jsonlTempFiles,
29
+ ];
30
+ let processed = 0;
31
+ for (const filePath of files) {
32
+ if (this.shouldSkipTempArtifact(filePath)) {
33
+ continue;
34
+ }
35
+ const parsed = filePath.endsWith('.jsonl')
36
+ ? await this.processJsonlSessionFile(filePath, projectHashLookup)
37
+ : await this.processLegacySessionFile(filePath);
38
+ if (!parsed) {
39
+ continue;
40
+ }
41
+ const timestamps = await readFileTimestamps(filePath);
42
+ sessionsDb.createSession(parsed.sessionId, this.provider, parsed.projectPath, parsed.sessionName, timestamps.createdAt, timestamps.updatedAt, filePath);
43
+ processed += 1;
44
+ }
45
+ return processed;
46
+ }
47
+ /**
48
+ * Parses and upserts one Gemini legacy JSON or JSONL artifact.
49
+ */
50
+ async synchronizeFile(filePath) {
51
+ if (!filePath.endsWith('.json') && !filePath.endsWith('.jsonl')) {
52
+ return null;
53
+ }
54
+ if (this.shouldSkipTempArtifact(filePath)) {
55
+ return null;
56
+ }
57
+ const parsed = filePath.endsWith('.jsonl')
58
+ ? await this.processJsonlSessionFile(filePath, this.buildProjectHashLookup())
59
+ : await this.processLegacySessionFile(filePath);
60
+ if (!parsed) {
61
+ return null;
62
+ }
63
+ const timestamps = await readFileTimestamps(filePath);
64
+ return sessionsDb.createSession(parsed.sessionId, this.provider, parsed.projectPath, parsed.sessionName, timestamps.createdAt, timestamps.updatedAt, filePath);
65
+ }
66
+ /**
67
+ * Extracts session metadata from one Gemini legacy JSON artifact.
68
+ */
69
+ async processLegacySessionFile(filePath) {
70
+ try {
71
+ const content = await readFile(filePath, 'utf8');
72
+ const data = JSON.parse(content);
73
+ const sessionId = typeof data.sessionId === 'string'
74
+ ? data.sessionId
75
+ : typeof data.id === 'string'
76
+ ? data.id
77
+ : undefined;
78
+ if (!sessionId) {
79
+ return null;
80
+ }
81
+ const workspaceProjectPath = await this.resolveProjectPathFromChatWorkspace(filePath);
82
+ const projectPath = typeof data.projectPath === 'string' && data.projectPath.trim().length > 0
83
+ ? data.projectPath
84
+ : workspaceProjectPath;
85
+ if (!projectPath) {
86
+ return null;
87
+ }
88
+ const messages = Array.isArray(data.messages) ? data.messages : [];
89
+ const firstMessage = messages[0];
90
+ let rawName;
91
+ if (Array.isArray(firstMessage?.content) && typeof firstMessage.content[0]?.text === 'string') {
92
+ rawName = firstMessage.content[0].text;
93
+ }
94
+ else if (typeof firstMessage?.content === 'string') {
95
+ rawName = firstMessage.content;
96
+ }
97
+ return {
98
+ sessionId,
99
+ projectPath,
100
+ sessionName: normalizeSessionName(rawName, 'New Gemini Chat'),
101
+ };
102
+ }
103
+ catch {
104
+ return null;
105
+ }
106
+ }
107
+ /**
108
+ * Extracts session metadata from one Gemini JSONL artifact.
109
+ */
110
+ async processJsonlSessionFile(filePath, projectHashLookup) {
111
+ const metadata = await this.extractJsonlMetadata(filePath);
112
+ if (!metadata) {
113
+ return null;
114
+ }
115
+ let projectPath = typeof metadata.projectPath === 'string' ? metadata.projectPath.trim() : '';
116
+ if (!projectPath) {
117
+ const workspaceProjectPath = await this.resolveProjectPathFromChatWorkspace(filePath);
118
+ if (workspaceProjectPath) {
119
+ projectPath = workspaceProjectPath;
120
+ }
121
+ }
122
+ if (!projectPath && typeof metadata.projectHash === 'string') {
123
+ projectPath = projectHashLookup.get(metadata.projectHash.trim().toLowerCase()) ?? '';
124
+ }
125
+ if (!projectPath) {
126
+ return null;
127
+ }
128
+ // Once we resolve a project hash/path pair, keep it in-memory for this sync run.
129
+ if (typeof metadata.projectHash === 'string' && metadata.projectHash.trim()) {
130
+ projectHashLookup.set(metadata.projectHash.trim().toLowerCase(), projectPath);
131
+ }
132
+ return {
133
+ sessionId: metadata.sessionId,
134
+ projectPath,
135
+ sessionName: normalizeSessionName(metadata.firstUserMessage, 'New Gemini Chat'),
136
+ };
137
+ }
138
+ /**
139
+ * Reads first useful metadata from Gemini JSONL files.
140
+ */
141
+ async extractJsonlMetadata(filePath) {
142
+ try {
143
+ const content = await readFile(filePath, 'utf8');
144
+ const lines = content.split('\n');
145
+ let sessionId;
146
+ let projectPath;
147
+ let projectHash;
148
+ let firstUserMessage;
149
+ for (const line of lines) {
150
+ const trimmed = line.trim();
151
+ if (!trimmed) {
152
+ continue;
153
+ }
154
+ let parsed;
155
+ try {
156
+ parsed = JSON.parse(trimmed);
157
+ }
158
+ catch {
159
+ continue;
160
+ }
161
+ if (!sessionId && typeof parsed.sessionId === 'string') {
162
+ sessionId = parsed.sessionId;
163
+ }
164
+ if (!projectPath && typeof parsed.projectPath === 'string') {
165
+ projectPath = parsed.projectPath;
166
+ }
167
+ if (!projectHash && typeof parsed.projectHash === 'string') {
168
+ projectHash = parsed.projectHash;
169
+ }
170
+ if (!firstUserMessage && parsed.type === 'user') {
171
+ firstUserMessage = this.extractGeminiTextContent(parsed.content);
172
+ }
173
+ if (sessionId && (projectPath || projectHash) && firstUserMessage) {
174
+ break;
175
+ }
176
+ }
177
+ if (!sessionId) {
178
+ return null;
179
+ }
180
+ return {
181
+ sessionId,
182
+ projectPath,
183
+ projectHash,
184
+ firstUserMessage,
185
+ };
186
+ }
187
+ catch {
188
+ return null;
189
+ }
190
+ }
191
+ /**
192
+ * Tries to resolve project root from Gemini tmp chat workspaces.
193
+ */
194
+ async resolveProjectPathFromChatWorkspace(filePath) {
195
+ if (!filePath.includes(`${path.sep}chats${path.sep}`)) {
196
+ return '';
197
+ }
198
+ const chatsDir = path.dirname(filePath);
199
+ const workspaceDir = path.dirname(chatsDir);
200
+ const projectRootPath = path.join(workspaceDir, '.project_root');
201
+ try {
202
+ const rootContent = await readFile(projectRootPath, 'utf8');
203
+ return rootContent.trim();
204
+ }
205
+ catch {
206
+ return '';
207
+ }
208
+ }
209
+ /**
210
+ * Builds a hash->path lookup for Gemini JSONL metadata that stores projectHash.
211
+ */
212
+ buildProjectHashLookup() {
213
+ const lookup = new Map();
214
+ const knownPaths = new Set();
215
+ for (const project of projectsDb.getProjectPaths()) {
216
+ if (typeof project.project_path === 'string' && project.project_path.trim()) {
217
+ knownPaths.add(project.project_path.trim());
218
+ }
219
+ }
220
+ for (const session of sessionsDb.getAllSessions()) {
221
+ if (session.provider === this.provider && typeof session.project_path === 'string' && session.project_path.trim()) {
222
+ knownPaths.add(session.project_path.trim());
223
+ }
224
+ }
225
+ for (const knownPath of knownPaths) {
226
+ this.addProjectHashCandidates(lookup, knownPath);
227
+ }
228
+ return lookup;
229
+ }
230
+ /**
231
+ * Adds likely Gemini hash variants for one project path.
232
+ */
233
+ addProjectHashCandidates(lookup, projectPath) {
234
+ const trimmed = projectPath.trim();
235
+ if (!trimmed) {
236
+ return;
237
+ }
238
+ const normalized = normalizeProjectPath(trimmed);
239
+ const resolved = path.resolve(trimmed);
240
+ const resolvedNormalized = normalizeProjectPath(resolved);
241
+ const candidates = new Set([
242
+ trimmed,
243
+ normalized,
244
+ resolved,
245
+ resolvedNormalized,
246
+ ]);
247
+ if (process.platform === 'win32') {
248
+ for (const candidate of [...candidates]) {
249
+ candidates.add(candidate.toLowerCase());
250
+ }
251
+ }
252
+ for (const candidate of candidates) {
253
+ if (!candidate) {
254
+ continue;
255
+ }
256
+ const hash = this.sha256(candidate);
257
+ if (!lookup.has(hash)) {
258
+ lookup.set(hash, trimmed);
259
+ }
260
+ }
261
+ }
262
+ /**
263
+ * Returns first user text from Gemini content payload shapes.
264
+ */
265
+ extractGeminiTextContent(content) {
266
+ if (typeof content === 'string' && content.trim().length > 0) {
267
+ return content;
268
+ }
269
+ if (!Array.isArray(content)) {
270
+ return undefined;
271
+ }
272
+ for (const part of content) {
273
+ if (typeof part === 'string' && part.trim().length > 0) {
274
+ return part;
275
+ }
276
+ if (part && typeof part === 'object' && typeof part.text === 'string') {
277
+ const text = part.text;
278
+ if (text.trim().length > 0) {
279
+ return text;
280
+ }
281
+ }
282
+ }
283
+ return undefined;
284
+ }
285
+ /**
286
+ * Keeps tmp scanning scoped to chat artifacts only.
287
+ */
288
+ shouldSkipTempArtifact(filePath) {
289
+ return (filePath.startsWith(path.join(this.geminiHome, 'tmp'))
290
+ && !filePath.includes(`${path.sep}chats${path.sep}`));
291
+ }
292
+ sha256(value) {
293
+ return crypto.createHash('sha256').update(value).digest('hex');
294
+ }
295
+ }
296
+ //# sourceMappingURL=gemini-session-synchronizer.provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini-session-synchronizer.provider.js","sourceRoot":"","sources":["../../../../../../server/modules/providers/list/gemini/gemini-session-synchronizer.provider.ts"],"names":[],"mappings":"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"}