@planckspace/cli 0.1.1 → 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 (190) hide show
  1. package/README.md +24 -1
  2. package/dist/anomaly/constants.d.ts +13 -0
  3. package/dist/anomaly/constants.d.ts.map +1 -0
  4. package/dist/anomaly/constants.js +13 -0
  5. package/dist/anomaly/constants.js.map +1 -0
  6. package/dist/anomaly/detector.d.ts +12 -0
  7. package/dist/anomaly/detector.d.ts.map +1 -0
  8. package/dist/anomaly/detector.js +98 -0
  9. package/dist/anomaly/detector.js.map +1 -0
  10. package/dist/anomaly/types.d.ts +19 -0
  11. package/dist/anomaly/types.d.ts.map +1 -0
  12. package/dist/anomaly/types.js +2 -0
  13. package/dist/anomaly/types.js.map +1 -0
  14. package/dist/commands/budget.d.ts +26 -0
  15. package/dist/commands/budget.d.ts.map +1 -0
  16. package/dist/commands/budget.js +91 -0
  17. package/dist/commands/budget.js.map +1 -0
  18. package/dist/commands/config.d.ts +4 -0
  19. package/dist/commands/config.d.ts.map +1 -0
  20. package/dist/commands/config.js +45 -0
  21. package/dist/commands/config.js.map +1 -0
  22. package/dist/commands/connect.d.ts +17 -0
  23. package/dist/commands/connect.d.ts.map +1 -0
  24. package/dist/commands/connect.js +191 -0
  25. package/dist/commands/connect.js.map +1 -0
  26. package/dist/commands/daemon.d.ts +8 -0
  27. package/dist/commands/daemon.d.ts.map +1 -0
  28. package/dist/commands/daemon.js +310 -0
  29. package/dist/commands/daemon.js.map +1 -0
  30. package/dist/commands/diagnose.d.ts +2 -0
  31. package/dist/commands/diagnose.d.ts.map +1 -0
  32. package/dist/commands/diagnose.js +81 -0
  33. package/dist/commands/diagnose.js.map +1 -0
  34. package/dist/commands/doctor.d.ts +2 -0
  35. package/dist/commands/doctor.d.ts.map +1 -0
  36. package/dist/commands/doctor.js +67 -0
  37. package/dist/commands/doctor.js.map +1 -0
  38. package/dist/commands/export.d.ts +40 -0
  39. package/dist/commands/export.d.ts.map +1 -0
  40. package/dist/commands/export.js +184 -0
  41. package/dist/commands/export.js.map +1 -0
  42. package/dist/commands/init.d.ts +3 -1
  43. package/dist/commands/init.d.ts.map +1 -1
  44. package/dist/commands/init.js +14 -1
  45. package/dist/commands/init.js.map +1 -1
  46. package/dist/commands/insights.d.ts +2 -0
  47. package/dist/commands/insights.d.ts.map +1 -0
  48. package/dist/commands/insights.js +71 -0
  49. package/dist/commands/insights.js.map +1 -0
  50. package/dist/commands/inspect.d.ts +2 -0
  51. package/dist/commands/inspect.d.ts.map +1 -0
  52. package/dist/commands/inspect.js +81 -0
  53. package/dist/commands/inspect.js.map +1 -0
  54. package/dist/commands/integrations.d.ts +2 -0
  55. package/dist/commands/integrations.d.ts.map +1 -0
  56. package/dist/commands/integrations.js +46 -0
  57. package/dist/commands/integrations.js.map +1 -0
  58. package/dist/commands/login.d.ts +1 -1
  59. package/dist/commands/login.d.ts.map +1 -1
  60. package/dist/commands/login.js +45 -6
  61. package/dist/commands/login.js.map +1 -1
  62. package/dist/commands/metrics.d.ts +6 -0
  63. package/dist/commands/metrics.d.ts.map +1 -0
  64. package/dist/commands/metrics.js +85 -0
  65. package/dist/commands/metrics.js.map +1 -0
  66. package/dist/commands/reconcile.d.ts +2 -0
  67. package/dist/commands/reconcile.d.ts.map +1 -0
  68. package/dist/commands/reconcile.js +63 -0
  69. package/dist/commands/reconcile.js.map +1 -0
  70. package/dist/commands/scan.d.ts.map +1 -1
  71. package/dist/commands/scan.js +53 -10
  72. package/dist/commands/scan.js.map +1 -1
  73. package/dist/commands/status.d.ts +1 -1
  74. package/dist/commands/status.d.ts.map +1 -1
  75. package/dist/commands/status.js +84 -14
  76. package/dist/commands/status.js.map +1 -1
  77. package/dist/commands/subscription.d.ts +15 -0
  78. package/dist/commands/subscription.d.ts.map +1 -0
  79. package/dist/commands/subscription.js +62 -0
  80. package/dist/commands/subscription.js.map +1 -0
  81. package/dist/commands/sync.d.ts +1 -1
  82. package/dist/commands/sync.d.ts.map +1 -1
  83. package/dist/commands/sync.js +77 -10
  84. package/dist/commands/sync.js.map +1 -1
  85. package/dist/commands/value.d.ts +5 -0
  86. package/dist/commands/value.d.ts.map +1 -0
  87. package/dist/commands/value.js +95 -0
  88. package/dist/commands/value.js.map +1 -0
  89. package/dist/config.d.ts +28 -3
  90. package/dist/config.d.ts.map +1 -1
  91. package/dist/config.js +9 -1
  92. package/dist/config.js.map +1 -1
  93. package/dist/correlate.d.ts +7 -0
  94. package/dist/correlate.d.ts.map +1 -1
  95. package/dist/correlate.js +102 -15
  96. package/dist/correlate.js.map +1 -1
  97. package/dist/daemon/daemon.d.ts +2 -0
  98. package/dist/daemon/daemon.d.ts.map +1 -0
  99. package/dist/daemon/daemon.js +188 -0
  100. package/dist/daemon/daemon.js.map +1 -0
  101. package/dist/daemon/daemonState.d.ts +25 -0
  102. package/dist/daemon/daemonState.d.ts.map +1 -0
  103. package/dist/daemon/daemonState.js +82 -0
  104. package/dist/daemon/daemonState.js.map +1 -0
  105. package/dist/daemon/logger.d.ts +7 -0
  106. package/dist/daemon/logger.d.ts.map +1 -0
  107. package/dist/daemon/logger.js +61 -0
  108. package/dist/daemon/logger.js.map +1 -0
  109. package/dist/daemon/syncLoop.d.ts +38 -0
  110. package/dist/daemon/syncLoop.d.ts.map +1 -0
  111. package/dist/daemon/syncLoop.js +119 -0
  112. package/dist/daemon/syncLoop.js.map +1 -0
  113. package/dist/daemon/watcher.d.ts +26 -0
  114. package/dist/daemon/watcher.d.ts.map +1 -0
  115. package/dist/daemon/watcher.js +187 -0
  116. package/dist/daemon/watcher.js.map +1 -0
  117. package/dist/db/store.d.ts +123 -2
  118. package/dist/db/store.d.ts.map +1 -1
  119. package/dist/db/store.js +397 -11
  120. package/dist/db/store.js.map +1 -1
  121. package/dist/detectors/cache-gap.d.ts +3 -0
  122. package/dist/detectors/cache-gap.d.ts.map +1 -0
  123. package/dist/detectors/cache-gap.js +70 -0
  124. package/dist/detectors/cache-gap.js.map +1 -0
  125. package/dist/detectors/context-bloat.d.ts +3 -0
  126. package/dist/detectors/context-bloat.d.ts.map +1 -0
  127. package/dist/detectors/context-bloat.js +68 -0
  128. package/dist/detectors/context-bloat.js.map +1 -0
  129. package/dist/detectors/fileTokens.d.ts +3 -0
  130. package/dist/detectors/fileTokens.d.ts.map +1 -0
  131. package/dist/detectors/fileTokens.js +12 -0
  132. package/dist/detectors/fileTokens.js.map +1 -0
  133. package/dist/detectors/index.d.ts +20 -0
  134. package/dist/detectors/index.d.ts.map +1 -0
  135. package/dist/detectors/index.js +41 -0
  136. package/dist/detectors/index.js.map +1 -0
  137. package/dist/detectors/model-routing.d.ts +3 -0
  138. package/dist/detectors/model-routing.d.ts.map +1 -0
  139. package/dist/detectors/model-routing.js +71 -0
  140. package/dist/detectors/model-routing.js.map +1 -0
  141. package/dist/detectors/repeat-read.d.ts +3 -0
  142. package/dist/detectors/repeat-read.d.ts.map +1 -0
  143. package/dist/detectors/repeat-read.js +69 -0
  144. package/dist/detectors/repeat-read.js.map +1 -0
  145. package/dist/detectors/seat-efficiency.d.ts +4 -0
  146. package/dist/detectors/seat-efficiency.d.ts.map +1 -0
  147. package/dist/detectors/seat-efficiency.js +86 -0
  148. package/dist/detectors/seat-efficiency.js.map +1 -0
  149. package/dist/detectors/types.d.ts +46 -0
  150. package/dist/detectors/types.d.ts.map +1 -0
  151. package/dist/detectors/types.js +2 -0
  152. package/dist/detectors/types.js.map +1 -0
  153. package/dist/health.d.ts +59 -0
  154. package/dist/health.d.ts.map +1 -0
  155. package/dist/health.js +106 -0
  156. package/dist/health.js.map +1 -0
  157. package/dist/index.js +389 -5
  158. package/dist/index.js.map +1 -1
  159. package/dist/metrics.d.ts +29 -0
  160. package/dist/metrics.d.ts.map +1 -0
  161. package/dist/metrics.js +205 -0
  162. package/dist/metrics.js.map +1 -0
  163. package/dist/scrapers/claudeCode.d.ts +1 -0
  164. package/dist/scrapers/claudeCode.d.ts.map +1 -1
  165. package/dist/scrapers/claudeCode.js +43 -13
  166. package/dist/scrapers/claudeCode.js.map +1 -1
  167. package/dist/scrapers/cursor.d.ts +3 -2
  168. package/dist/scrapers/cursor.d.ts.map +1 -1
  169. package/dist/scrapers/cursor.js +56 -16
  170. package/dist/scrapers/cursor.js.map +1 -1
  171. package/dist/scrapers/jetbrains.d.ts +15 -0
  172. package/dist/scrapers/jetbrains.d.ts.map +1 -0
  173. package/dist/scrapers/jetbrains.js +232 -0
  174. package/dist/scrapers/jetbrains.js.map +1 -0
  175. package/dist/scrapers/types.d.ts +4 -1
  176. package/dist/scrapers/types.d.ts.map +1 -1
  177. package/dist/scrapers/windsurf.d.ts +3 -2
  178. package/dist/scrapers/windsurf.d.ts.map +1 -1
  179. package/dist/scrapers/windsurf.js +25 -9
  180. package/dist/scrapers/windsurf.js.map +1 -1
  181. package/dist/sync/payload.d.ts +4 -5
  182. package/dist/sync/payload.d.ts.map +1 -1
  183. package/dist/sync/payload.js +88 -7
  184. package/dist/sync/payload.js.map +1 -1
  185. package/dist/sync/syncEngine.d.ts +19 -3
  186. package/dist/sync/syncEngine.d.ts.map +1 -1
  187. package/dist/sync/syncEngine.js +116 -10
  188. package/dist/sync/syncEngine.js.map +1 -1
  189. package/install.sh +27 -10
  190. package/package.json +43 -42
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jetbrains.d.ts","sourceRoot":"","sources":["../../src/scrapers/jetbrains.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AA8ChD,sEAAsE;AACtE,wBAAgB,mBAAmB,IAAI,MAAM,CAS5C;AAED,yFAAyF;AACzF,wBAAgB,wBAAwB,IAAI,MAAM,EAAE,CAWnD;AAkID;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,IAAI,aAAa,EAAE,CA0DnD"}
@@ -0,0 +1,232 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import os from "os";
4
+ // ── JetBrains AI Assistant — detection + initial capture path ────────────────────
5
+ //
6
+ // JetBrains AI Assistant is a plugin shipped with JetBrains IDEs (IntelliJ IDEA,
7
+ // PyCharm, WebStorm, Rider, GoLand, CLion, etc.) since ~2024. It stores AI chat
8
+ // history in the per-product config directory under the user home:
9
+ //
10
+ // macOS ~/Library/Application Support/JetBrains/<ProductVersion>/
11
+ // Linux ~/.config/JetBrains/<ProductVersion>/
12
+ // Windows %APPDATA%\JetBrains\<ProductVersion>\
13
+ //
14
+ // AI Assistant data is likely in one of:
15
+ // • options/ai-assistant.xml — IntelliJ XML-format chat history
16
+ // • grazie/ — Grazie language-tool service storage
17
+ // • llm/ or ai/ — newer conversation storage dirs
18
+ //
19
+ // HONEST LIMITS (see docs/COVERAGE.md):
20
+ // • This is a *foothold* implementation: we detect installations, locate
21
+ // candidate files, and report clearly what we find.
22
+ // • We parse whatever XML/JSON we can confidently interpret; anything we
23
+ // cannot map to ParsedSession shape is reported but not fabricated.
24
+ // • On machines without JetBrains this returns [] silently.
25
+ // • The schema has not been verified against a real install (June 2026);
26
+ // verified coverage will be promoted in a future release.
27
+ // ── Product version directory pattern ───────────────────────────────────────────
28
+ // JetBrains names config dirs like "IntelliJIdea2024.3", "PyCharm2025.1", etc.
29
+ const JETBRAINS_PRODUCT_RE = /^(IntelliJIdea|PyCharm|WebStorm|GoLand|CLion|Rider|PhpStorm|RubyMine|AppCode|DataGrip|Aqua|DataSpell|Fleet|MPS)\d{4}\.\d/;
30
+ // Names of files that might hold AI conversation history.
31
+ const AI_FILE_PATTERNS = [
32
+ "ai-assistant.xml",
33
+ "ai_assistant.xml",
34
+ "AIAssistant.xml",
35
+ "llm.xml",
36
+ "grazie.xml",
37
+ ];
38
+ // Subdirectories that might hold AI session data.
39
+ const AI_DIR_NAMES = ["llm", "ai", "grazie", "ai-assistant"];
40
+ // ── OS path resolution ──────────────────────────────────────────────────────────
41
+ /** Base directory that contains per-product JetBrains config dirs. */
42
+ export function jetBrainsConfigBase() {
43
+ const home = os.homedir();
44
+ if (process.platform === "darwin") {
45
+ return path.join(home, "Library", "Application Support", "JetBrains");
46
+ }
47
+ if (process.platform === "win32") {
48
+ return path.join(process.env.APPDATA ?? path.join(home, "AppData", "Roaming"), "JetBrains");
49
+ }
50
+ return path.join(home, ".config", "JetBrains");
51
+ }
52
+ /** Returns all recognised JetBrains product-version config directories found on disk. */
53
+ export function findJetBrainsProductDirs() {
54
+ const base = jetBrainsConfigBase();
55
+ if (!fs.existsSync(base))
56
+ return [];
57
+ try {
58
+ return fs
59
+ .readdirSync(base, { withFileTypes: true })
60
+ .filter((e) => e.isDirectory() && JETBRAINS_PRODUCT_RE.test(e.name))
61
+ .map((e) => path.join(base, e.name));
62
+ }
63
+ catch {
64
+ return [];
65
+ }
66
+ }
67
+ function findAiCandidates(productDir) {
68
+ const candidates = [];
69
+ const optionsDir = path.join(productDir, "options");
70
+ // Check for known AI XML files under options/
71
+ if (fs.existsSync(optionsDir)) {
72
+ for (const name of AI_FILE_PATTERNS) {
73
+ const fp = path.join(optionsDir, name);
74
+ if (fs.existsSync(fp))
75
+ candidates.push({ filePath: fp, category: "xml" });
76
+ }
77
+ // Also do a broader scan for any XML file whose name contains "ai" or "llm"
78
+ try {
79
+ for (const entry of fs.readdirSync(optionsDir)) {
80
+ if (!/\.(xml|json)$/i.test(entry))
81
+ continue;
82
+ const lower = entry.toLowerCase();
83
+ if ((lower.includes("ai") || lower.includes("llm") || lower.includes("assistant")) &&
84
+ !candidates.some((c) => c.filePath.endsWith(entry))) {
85
+ candidates.push({
86
+ filePath: path.join(optionsDir, entry),
87
+ category: entry.endsWith(".json") ? "json" : "xml",
88
+ });
89
+ }
90
+ }
91
+ }
92
+ catch {
93
+ /* ignore read errors */
94
+ }
95
+ }
96
+ // Check for known AI subdirectories directly under productDir
97
+ for (const dirName of AI_DIR_NAMES) {
98
+ const dp = path.join(productDir, dirName);
99
+ if (fs.existsSync(dp) && fs.statSync(dp).isDirectory()) {
100
+ candidates.push({ filePath: dp, category: "dir" });
101
+ }
102
+ }
103
+ return candidates;
104
+ }
105
+ function parseIntelliJXml(xmlText, filePath) {
106
+ const sessions = [];
107
+ // Look for component elements that might hold chat sessions
108
+ const componentRe = /<component\s+name="([^"]+)"/g;
109
+ let componentMatch;
110
+ while ((componentMatch = componentRe.exec(xmlText)) !== null) {
111
+ const componentName = componentMatch[1];
112
+ if (!componentName.toLowerCase().includes("ai") &&
113
+ !componentName.toLowerCase().includes("llm") &&
114
+ !componentName.toLowerCase().includes("assistant") &&
115
+ !componentName.toLowerCase().includes("chat")) {
116
+ continue;
117
+ }
118
+ // Found a component with a relevant name — extract any timestamp-like values
119
+ // as evidence that real data exists.
120
+ const tsRe = /\b(\d{13})\b/g; // 13-digit epoch ms
121
+ const timestamps = [];
122
+ let tsMatch;
123
+ while ((tsMatch = tsRe.exec(xmlText)) !== null) {
124
+ const ms = parseInt(tsMatch[1], 10);
125
+ const d = new Date(ms);
126
+ if (d.getFullYear() >= 2023 && d.getFullYear() <= 2030) {
127
+ timestamps.push(d.toISOString());
128
+ }
129
+ }
130
+ if (timestamps.length > 0) {
131
+ sessions.push({
132
+ id: `jb:${path.basename(filePath)}:${componentName}`,
133
+ messages: timestamps.map((ts) => ({ role: "unknown", timestamp: ts })),
134
+ productDir: path.dirname(path.dirname(filePath)),
135
+ });
136
+ }
137
+ }
138
+ return sessions;
139
+ }
140
+ // ── ParsedSession builder ────────────────────────────────────────────────────────
141
+ function toParsedSession(jbs) {
142
+ const timestamps = jbs.messages
143
+ .map((m) => m.timestamp)
144
+ .filter((t) => t !== null)
145
+ .sort();
146
+ if (timestamps.length === 0)
147
+ return null;
148
+ return {
149
+ sessionId: `jetbrains:${jbs.id}`,
150
+ tool: "jetbrains",
151
+ model: "unknown",
152
+ startedAt: timestamps[0],
153
+ endedAt: timestamps[timestamps.length - 1],
154
+ inputTokens: 0,
155
+ outputTokens: 0,
156
+ cacheReadTokens: 0,
157
+ cacheWriteTokens: 0,
158
+ costUsd: 0,
159
+ costType: "imputed",
160
+ subscriptionPlan: null,
161
+ unmatchedTurns: 0,
162
+ turns: [],
163
+ workingDir: jbs.productDir,
164
+ turnCount: jbs.messages.filter((m) => m.role === "user" || m.role === "unknown").length,
165
+ filesTouchedCount: 0,
166
+ repoName: null,
167
+ gitBranch: null,
168
+ };
169
+ }
170
+ // ── Main entrypoint ─────────────────────────────────────────────────────────────
171
+ /**
172
+ * Scan JetBrains AI Assistant history.
173
+ *
174
+ * Returns parsed sessions if data is interpretable. If JetBrains IDEs are
175
+ * installed but the AI data format is not yet recognised, prints a single
176
+ * diagnostic line and returns []. If JetBrains is not installed, returns []
177
+ * silently.
178
+ */
179
+ export function scanJetBrainsLogs() {
180
+ const productDirs = findJetBrainsProductDirs();
181
+ if (productDirs.length === 0)
182
+ return []; // Not installed — expected, silent.
183
+ const productNames = productDirs.map((d) => path.basename(d));
184
+ const allCandidates = [];
185
+ for (const pd of productDirs) {
186
+ for (const f of findAiCandidates(pd)) {
187
+ allCandidates.push({ file: f, productDir: pd });
188
+ }
189
+ }
190
+ if (allCandidates.length === 0) {
191
+ // JetBrains found but no AI Assistant data files located.
192
+ console.warn(`[jetbrains] Detected ${productNames.join(", ")} but found no AI Assistant data ` +
193
+ `files in config directory. Full capture support coming in v2.1.`);
194
+ return [];
195
+ }
196
+ const sessions = [];
197
+ let parsedFiles = 0;
198
+ let unrecognisedFiles = 0;
199
+ for (const { file } of allCandidates) {
200
+ if (file.category === "dir")
201
+ continue; // directories handled indirectly
202
+ try {
203
+ const text = fs.readFileSync(file.filePath, "utf-8");
204
+ if (file.category === "xml") {
205
+ const jbSessions = parseIntelliJXml(text, file.filePath);
206
+ if (jbSessions.length > 0) {
207
+ parsedFiles++;
208
+ for (const jbs of jbSessions) {
209
+ const ps = toParsedSession(jbs);
210
+ if (ps)
211
+ sessions.push(ps);
212
+ }
213
+ }
214
+ else {
215
+ unrecognisedFiles++;
216
+ }
217
+ }
218
+ }
219
+ catch {
220
+ unrecognisedFiles++;
221
+ }
222
+ }
223
+ if (sessions.length === 0) {
224
+ // Files were found but none matched a recognised schema.
225
+ console.warn(`[jetbrains] Found JetBrains AI Assistant installation (${productNames.join(", ")}) ` +
226
+ `and located ${allCandidates.length} candidate file(s), but the data format ` +
227
+ `was not recognised. Current data capture is not yet supported — see roadmap ` +
228
+ `for v2.1. No sessions were fabricated.`);
229
+ }
230
+ return sessions;
231
+ }
232
+ //# sourceMappingURL=jetbrains.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jetbrains.js","sourceRoot":"","sources":["../../src/scrapers/jetbrains.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  /** AI coding tool a session came from. Mirrors `@planckspace/core`'s telemetry enum. */
2
- export type Tool = "claude_code" | "cursor" | "windsurf";
2
+ export type Tool = "claude_code" | "cursor" | "windsurf" | "jetbrains";
3
3
  export type Turn = {
4
4
  sequence: number;
5
5
  model: string;
@@ -26,6 +26,9 @@ export type ParsedSession = {
26
26
  cacheReadTokens: number;
27
27
  cacheWriteTokens: number;
28
28
  costUsd: number;
29
+ costType: "billed" | "imputed";
30
+ subscriptionPlan: string | null;
31
+ unmatchedTurns: number;
29
32
  turns: Turn[];
30
33
  workingDir: string;
31
34
  turnCount: number;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/scrapers/types.ts"],"names":[],"mappings":"AAIA,wFAAwF;AACxF,MAAM,MAAM,IAAI,GAAG,aAAa,GAAG,QAAQ,GAAG,UAAU,CAAC;AAEzD,MAAM,MAAM,IAAI,GAAG;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC7C,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,IAAI,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/scrapers/types.ts"],"names":[],"mappings":"AAIA,wFAAwF;AACxF,MAAM,MAAM,IAAI,GAAG,aAAa,GAAG,QAAQ,GAAG,UAAU,GAAG,WAAW,CAAC;AAEvE,MAAM,MAAM,IAAI,GAAG;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC7C,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,IAAI,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAGhB,QAAQ,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC/B,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAEhC,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,CAAC"}
@@ -3,7 +3,8 @@ import type { ParsedSession } from "./types.js";
3
3
  export declare function windsurfDbPaths(): string[];
4
4
  /**
5
5
  * Scan Windsurf's global state DB(s) for Cascade conversations.
6
- * @param dbPaths override the DB locations (used by tests). Defaults to OS paths.
6
+ * @param dbPaths Override the DB locations (used by tests). Defaults to OS paths.
7
+ * @param billingMode "billed" if the user registered windsurf with plan=api; else "imputed".
7
8
  */
8
- export declare function scanWindsurfLogs(dbPaths?: string[]): ParsedSession[];
9
+ export declare function scanWindsurfLogs(dbPaths?: string[], billingMode?: "billed" | "imputed"): ParsedSession[];
9
10
  //# sourceMappingURL=windsurf.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"windsurf.d.ts","sourceRoot":"","sources":["../../src/scrapers/windsurf.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAQ,aAAa,EAAE,MAAM,YAAY,CAAC;AAwDtD,mFAAmF;AACnF,wBAAgB,eAAe,IAAI,MAAM,EAAE,CAa1C;AAsJD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,MAAM,EAAsB,GAAG,aAAa,EAAE,CAkEvF"}
1
+ {"version":3,"file":"windsurf.d.ts","sourceRoot":"","sources":["../../src/scrapers/windsurf.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAQ,aAAa,EAAE,MAAM,YAAY,CAAC;AAyDtD,mFAAmF;AACnF,wBAAgB,eAAe,IAAI,MAAM,EAAE,CAa1C;AAsKD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,GAAE,MAAM,EAAsB,EACrC,WAAW,GAAE,QAAQ,GAAG,SAAqB,GAC5C,aAAa,EAAE,CAkEjB"}
@@ -2,7 +2,7 @@ import fs from "fs";
2
2
  import path from "path";
3
3
  import os from "os";
4
4
  import Database from "better-sqlite3";
5
- import { computeCostUsd } from "@planckspace/core";
5
+ import { computeCostUsd, UnknownModelError } from "@planckspace/core";
6
6
  import { resolveRepo } from "./repo.js";
7
7
  // ── Status: BETA / UNVERIFIED (see docs/COVERAGE.md) ────────────────────────────
8
8
  //
@@ -10,9 +10,10 @@ import { resolveRepo } from "./repo.js";
10
10
  // layout as VS Code / Cursor: <appSupport>/Windsurf/User/globalStorage/state.vscdb
11
11
  // (an `ItemTable` key-value store), with its "Cascade" agent history kept there.
12
12
  //
13
- // IMPORTANT HONESTY NOTE: no Windsurf installation was available when this scraper
14
- // was written, so its exact Cascade key names and message schema could NOT be
15
- // verified against real data the way Cursor's were. This scraper therefore:
13
+ // IMPORTANT HONESTY NOTE: no Windsurf installation was available for schema
14
+ // verification when this scraper was written (or when it was last reviewed, June
15
+ // 2026). Unlike Cursor, whose schema was verified against a live DB, Windsurf's
16
+ // exact Cascade key names and message schema remain UNVERIFIED. This scraper:
16
17
  // • locates Windsurf's state DB across macOS / Linux / Windows (incl. "- Next"),
17
18
  // • reads ONLY values under keys that plausibly hold Cascade conversations,
18
19
  // • extracts only structurally-unambiguous fields (timestamps, message counts,
@@ -100,7 +101,7 @@ function asConversation(value) {
100
101
  return null;
101
102
  return { ...obj, messages };
102
103
  }
103
- function buildSession(conv, fallbackId) {
104
+ function buildSession(conv, fallbackId, billingMode) {
104
105
  const messages = conv.messages ?? [];
105
106
  const timestamps = messages
106
107
  .map(messageTimestamp)
@@ -111,6 +112,7 @@ function buildSession(conv, fallbackId) {
111
112
  let totalInput = 0;
112
113
  let totalOutput = 0;
113
114
  let totalCost = 0;
115
+ let unmatchedTurns = 0;
114
116
  const turns = [];
115
117
  let current = null;
116
118
  let sessionModel = "unknown";
@@ -157,7 +159,17 @@ function buildSession(conv, fallbackId) {
157
159
  const { input, output } = messageTokens(m);
158
160
  current.inputTokens += input;
159
161
  current.outputTokens += output;
160
- current.costUsd += computeCostUsd({ inputTokens: input, outputTokens: output, cacheReadTokens: 0, cacheWriteTokens: 0 }, model);
162
+ try {
163
+ current.costUsd += computeCostUsd({ inputTokens: input, outputTokens: output, cacheReadTokens: 0, cacheWriteTokens: 0 }, model);
164
+ }
165
+ catch (err) {
166
+ if (err instanceof UnknownModelError) {
167
+ unmatchedTurns++;
168
+ }
169
+ else {
170
+ throw err;
171
+ }
172
+ }
161
173
  if (model && model !== "unknown")
162
174
  current.model = model;
163
175
  totalInput += input;
@@ -179,6 +191,9 @@ function buildSession(conv, fallbackId) {
179
191
  cacheReadTokens: 0,
180
192
  cacheWriteTokens: 0,
181
193
  costUsd: totalCost,
194
+ costType: billingMode,
195
+ subscriptionPlan: null,
196
+ unmatchedTurns,
182
197
  turns,
183
198
  workingDir,
184
199
  turnCount: turns.length,
@@ -190,9 +205,10 @@ function buildSession(conv, fallbackId) {
190
205
  // ── Main entrypoint ─────────────────────────────────────────────────────────────
191
206
  /**
192
207
  * Scan Windsurf's global state DB(s) for Cascade conversations.
193
- * @param dbPaths override the DB locations (used by tests). Defaults to OS paths.
208
+ * @param dbPaths Override the DB locations (used by tests). Defaults to OS paths.
209
+ * @param billingMode "billed" if the user registered windsurf with plan=api; else "imputed".
194
210
  */
195
- export function scanWindsurfLogs(dbPaths = windsurfDbPaths()) {
211
+ export function scanWindsurfLogs(dbPaths = windsurfDbPaths(), billingMode = "imputed") {
196
212
  const existing = dbPaths.filter((p) => fs.existsSync(p));
197
213
  if (existing.length === 0)
198
214
  return []; // Windsurf not installed — expected, silent.
@@ -229,7 +245,7 @@ export function scanWindsurfLogs(dbPaths = windsurfDbPaths()) {
229
245
  const conv = asConversation(candidates[i]);
230
246
  if (!conv)
231
247
  continue;
232
- const session = buildSession(conv, `${row.key}:${i}`);
248
+ const session = buildSession(conv, `${row.key}:${i}`, billingMode);
233
249
  if (session) {
234
250
  sessions.push(session);
235
251
  recognised++;
@@ -1 +1 @@
1
- {"version":3,"file":"windsurf.js","sourceRoot":"","sources":["../../src/scrapers/windsurf.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"windsurf.js","sourceRoot":"","sources":["../../src/scrapers/windsurf.ts"],"names":[],"mappings":"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"}
@@ -1,14 +1,13 @@
1
1
  import type { TelemetryPayload } from "@planckspace/core";
2
2
  import type { SessionRow } from "../db/store.js";
3
- /** The shape returned by getUnsyncedSessions() — SessionRow with turnsJson stripped. */
4
- export type UnsyncedSession = Omit<SessionRow, "turnsJson">;
5
3
  /**
6
4
  * Build the wire payload for a single session — METADATA ONLY.
7
5
  *
8
6
  * PRIVACY INVARIANT: this function maps each TelemetryPayload field EXPLICITLY.
9
- * It never spreads the row and never references turnsJson, prompt text, response
10
- * text, or file contents. Anything not listed below is, by construction, not sent.
7
+ * It never spreads the row and never forwards prompt text, response text, or file
8
+ * contents. Per-turn metadata (tokens, tool call names, repo-relative file paths)
9
+ * is fine to send — it is not user-generated content.
11
10
  * The privacy guard test (payload.privacy.test.ts) enforces this and must always pass.
12
11
  */
13
- export declare function buildTelemetryPayload(row: UnsyncedSession, workspaceId: string): TelemetryPayload;
12
+ export declare function buildTelemetryPayload(row: SessionRow, workspaceId: string): TelemetryPayload;
14
13
  //# sourceMappingURL=payload.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"payload.d.ts","sourceRoot":"","sources":["../../src/sync/payload.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD,wFAAwF;AACxF,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;AAE5D;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,eAAe,EACpB,WAAW,EAAE,MAAM,GAClB,gBAAgB,CA0BlB"}
1
+ {"version":3,"file":"payload.d.ts","sourceRoot":"","sources":["../../src/sync/payload.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAiB,MAAM,mBAAmB,CAAC;AACzE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAGjD;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,UAAU,EACf,WAAW,EAAE,MAAM,GAClB,gBAAgB,CAmClB"}
@@ -1,16 +1,19 @@
1
+ import path from "path";
1
2
  /**
2
3
  * Build the wire payload for a single session — METADATA ONLY.
3
4
  *
4
5
  * PRIVACY INVARIANT: this function maps each TelemetryPayload field EXPLICITLY.
5
- * It never spreads the row and never references turnsJson, prompt text, response
6
- * text, or file contents. Anything not listed below is, by construction, not sent.
6
+ * It never spreads the row and never forwards prompt text, response text, or file
7
+ * contents. Per-turn metadata (tokens, tool call names, repo-relative file paths)
8
+ * is fine to send — it is not user-generated content.
7
9
  * The privacy guard test (payload.privacy.test.ts) enforces this and must always pass.
8
10
  */
9
11
  export function buildTelemetryPayload(row, workspaceId) {
12
+ const rawTurns = parseTurnsJson(row.turnsJson);
13
+ const telemetryTurns = rawTurns.map((t) => toTelemetryTurn(t, row.workingDir));
14
+ const reReadPatterns = buildReReadPatterns(telemetryTurns);
10
15
  return {
11
16
  sessionId: row.id,
12
- // The DB only ever holds scraper-sourced Claude Code sessions today; the cast
13
- // narrows the stored string to the core enum without widening the wire contract.
14
17
  tool: row.tool,
15
18
  model: row.model,
16
19
  startedAt: row.startedAt,
@@ -20,17 +23,95 @@ export function buildTelemetryPayload(row, workspaceId) {
20
23
  cacheReadTokens: row.cacheReadTokens,
21
24
  cacheWriteTokens: row.cacheWriteTokens,
22
25
  costUsd: row.costUsd,
23
- // Backend schema requires a non-empty repoName.
26
+ costType: (row.costType ?? "imputed"),
27
+ subscriptionPlan: row.subscriptionPlan ?? null,
28
+ consumptionValueUsd: row.costUsd,
24
29
  repoName: row.repoName ?? "unknown",
25
30
  gitBranch: row.gitBranch,
26
- // Recorded by git correlation (the repo's `user.email`), not from prompt
27
- // content. May differ from the login email — the cloud maps it to a member.
28
31
  gitAuthorEmail: row.gitAuthorEmail,
29
32
  outcome: row.outcome,
30
33
  turnCount: row.turnCount,
31
34
  filesTouchedCount: row.filesTouchedCount,
32
35
  source: "scraper",
33
36
  workspaceId,
37
+ turns: telemetryTurns,
38
+ reReadPatterns,
39
+ unmatchedTurns: row.unmatchedTurns,
40
+ mergedPrNumber: row.mergedPrNumber ?? null,
41
+ mergedAt: row.mergedAt ?? null,
34
42
  };
35
43
  }
44
+ // ── Helpers ───────────────────────────────────────────────────────────────────
45
+ function parseTurnsJson(turnsJson) {
46
+ try {
47
+ const parsed = JSON.parse(turnsJson);
48
+ if (!Array.isArray(parsed))
49
+ return [];
50
+ return parsed;
51
+ }
52
+ catch {
53
+ return [];
54
+ }
55
+ }
56
+ /**
57
+ * Convert an internal Turn to a TelemetryTurn.
58
+ * Paths are made repo-relative; any fields not in TelemetryTurn are silently dropped.
59
+ */
60
+ function toTelemetryTurn(t, workingDir) {
61
+ return {
62
+ sequence: t.sequence,
63
+ model: t.model,
64
+ inputTokens: t.inputTokens,
65
+ outputTokens: t.outputTokens,
66
+ cacheReadTokens: t.cacheReadTokens,
67
+ cacheCreationInputTokens: t.cacheWriteTokens,
68
+ toolCalls: t.toolCalls.map((tc) => ({ name: tc.name, count: tc.count })),
69
+ filesTouched: t.filesTouched.map((p) => toRepoRelative(p, workingDir)),
70
+ timestamp: t.timestamp,
71
+ costUsd: t.costUsd,
72
+ };
73
+ }
74
+ /**
75
+ * Strip the absolute working-directory prefix from a file path.
76
+ * If the path is already relative or outside workingDir, return basename only
77
+ * so we never leak machine-specific directory structure.
78
+ * Always uses forward slashes so the output is platform-independent on the wire.
79
+ */
80
+ function toRepoRelative(filePath, workingDir) {
81
+ if (!filePath)
82
+ return filePath;
83
+ if (!path.isAbsolute(filePath))
84
+ return filePath.replace(/\\/g, "/");
85
+ if (!workingDir)
86
+ return path.basename(filePath);
87
+ try {
88
+ const rel = path.relative(workingDir, filePath);
89
+ // On Windows, cross-drive path.relative() returns the absolute path unchanged
90
+ // (can't express inter-drive relative paths). Catch both escape cases.
91
+ if (rel.startsWith("..") || path.isAbsolute(rel))
92
+ return path.basename(filePath);
93
+ return rel.replace(/\\/g, "/");
94
+ }
95
+ catch {
96
+ return path.basename(filePath);
97
+ }
98
+ }
99
+ /**
100
+ * For each file path touched in the session, count how many distinct turns
101
+ * include it in their filesTouched list.
102
+ */
103
+ function buildReReadPatterns(turns) {
104
+ const counts = new Map();
105
+ for (const t of turns) {
106
+ // Use a Set per turn so a file touched twice in one turn is counted once.
107
+ const seen = new Set(t.filesTouched);
108
+ for (const p of seen) {
109
+ counts.set(p, (counts.get(p) ?? 0) + 1);
110
+ }
111
+ }
112
+ return [...counts.entries()]
113
+ .filter(([, count]) => count > 1) // only files that appear in more than one turn
114
+ .map(([p, count]) => ({ path: p, count }))
115
+ .sort((a, b) => b.count - a.count || a.path.localeCompare(b.path));
116
+ }
36
117
  //# sourceMappingURL=payload.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"payload.js","sourceRoot":"","sources":["../../src/sync/payload.ts"],"names":[],"mappings":"AAMA;;;;;;;GAOG;AACH,MAAM,UAAU,qBAAqB,CACnC,GAAoB,EACpB,WAAmB;IAEnB,OAAO;QACL,SAAS,EAAE,GAAG,CAAC,EAAE;QACjB,8EAA8E;QAC9E,iFAAiF;QACjF,IAAI,EAAE,GAAG,CAAC,IAAgC;QAC1C,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,WAAW,EAAE,GAAG,CAAC,WAAW;QAC5B,YAAY,EAAE,GAAG,CAAC,YAAY;QAC9B,eAAe,EAAE,GAAG,CAAC,eAAe;QACpC,gBAAgB,EAAE,GAAG,CAAC,gBAAgB;QACtC,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,gDAAgD;QAChD,QAAQ,EAAE,GAAG,CAAC,QAAQ,IAAI,SAAS;QACnC,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,yEAAyE;QACzE,4EAA4E;QAC5E,cAAc,EAAE,GAAG,CAAC,cAAc;QAClC,OAAO,EAAE,GAAG,CAAC,OAAsC;QACnD,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,iBAAiB,EAAE,GAAG,CAAC,iBAAiB;QACxC,MAAM,EAAE,SAAS;QACjB,WAAW;KACZ,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"payload.js","sourceRoot":"","sources":["../../src/sync/payload.ts"],"names":[],"mappings":"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"}
@@ -1,16 +1,32 @@
1
+ import type { SubscriptionContext, Budget } from "../config.js";
1
2
  export type SyncDeps = {
2
3
  apiUrl: string;
3
4
  token: string;
4
5
  workspaceId: string;
6
+ /** Workspace-declared subscriptions to push alongside session telemetry. */
7
+ workspaceSubscriptions?: SubscriptionContext[];
8
+ /** Configured budgets to sync to the backend dashboard. */
9
+ budgets?: Budget[];
5
10
  };
6
11
  export type SyncResult = {
7
12
  synced: number;
8
13
  failed: number;
14
+ /** Number of workspace subscriptions included in the last successful ingest batch. */
15
+ subscriptionCount: number;
16
+ /** Labels of optional endpoints that returned 404 (not yet deployed by backend). */
17
+ pending: string[];
18
+ /** Labels of endpoints that returned 401/403 (token may be invalid). */
19
+ authWarnings: string[];
20
+ /** Whether productivity metrics were included in this sync. */
21
+ metricsIncluded: boolean;
9
22
  };
10
23
  /**
11
- * Push all unsynced sessions to {apiUrl}/api/ingest in batches of up to 100.
12
- * Successful batches are marked synced; failed batches record lastError and stay
13
- * unsynced for the next run. Transient failures retry with exponential backoff.
24
+ * Push all unsynced sessions and insights to {apiUrl}/api/ingest in one envelope.
25
+ * Insights ride in the first batch (or the empty-sessions batch) so the backend
26
+ * sees them as soon as they exist, without waiting for a separate endpoint.
27
+ *
28
+ * Transient failures (network / 5xx / 429) retry with exponential backoff.
29
+ * Auth failures (401/403) abort remaining batches and add a warning to the result.
14
30
  */
15
31
  export declare function syncOnce(deps: SyncDeps): Promise<SyncResult>;
16
32
  //# sourceMappingURL=syncEngine.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"syncEngine.d.ts","sourceRoot":"","sources":["../../src/sync/syncEngine.ts"],"names":[],"mappings":"AAUA,MAAM,MAAM,QAAQ,GAAG;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAkD5D;;;;GAIG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,CA+BlE"}
1
+ {"version":3,"file":"syncEngine.d.ts","sourceRoot":"","sources":["../../src/sync/syncEngine.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAShE,MAAM,MAAM,QAAQ,GAAG;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,4EAA4E;IAC5E,sBAAsB,CAAC,EAAE,mBAAmB,EAAE,CAAC;IAC/C,2DAA2D;IAC3D,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,sFAAsF;IACtF,iBAAiB,EAAE,MAAM,CAAC;IAC1B,oFAAoF;IACpF,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,wEAAwE;IACxE,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,+DAA+D;IAC/D,eAAe,EAAE,OAAO,CAAC;CAC1B,CAAC;AA0GF;;;;;;;GAOG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,CAoFlE"}