@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.
- package/README.md +24 -1
- package/dist/anomaly/constants.d.ts +13 -0
- package/dist/anomaly/constants.d.ts.map +1 -0
- package/dist/anomaly/constants.js +13 -0
- package/dist/anomaly/constants.js.map +1 -0
- package/dist/anomaly/detector.d.ts +12 -0
- package/dist/anomaly/detector.d.ts.map +1 -0
- package/dist/anomaly/detector.js +98 -0
- package/dist/anomaly/detector.js.map +1 -0
- package/dist/anomaly/types.d.ts +19 -0
- package/dist/anomaly/types.d.ts.map +1 -0
- package/dist/anomaly/types.js +2 -0
- package/dist/anomaly/types.js.map +1 -0
- package/dist/commands/budget.d.ts +26 -0
- package/dist/commands/budget.d.ts.map +1 -0
- package/dist/commands/budget.js +91 -0
- package/dist/commands/budget.js.map +1 -0
- package/dist/commands/config.d.ts +4 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +45 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/connect.d.ts +17 -0
- package/dist/commands/connect.d.ts.map +1 -0
- package/dist/commands/connect.js +191 -0
- package/dist/commands/connect.js.map +1 -0
- package/dist/commands/daemon.d.ts +8 -0
- package/dist/commands/daemon.d.ts.map +1 -0
- package/dist/commands/daemon.js +310 -0
- package/dist/commands/daemon.js.map +1 -0
- package/dist/commands/diagnose.d.ts +2 -0
- package/dist/commands/diagnose.d.ts.map +1 -0
- package/dist/commands/diagnose.js +81 -0
- package/dist/commands/diagnose.js.map +1 -0
- package/dist/commands/doctor.d.ts +2 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +67 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/export.d.ts +40 -0
- package/dist/commands/export.d.ts.map +1 -0
- package/dist/commands/export.js +184 -0
- package/dist/commands/export.js.map +1 -0
- package/dist/commands/init.d.ts +3 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +14 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/insights.d.ts +2 -0
- package/dist/commands/insights.d.ts.map +1 -0
- package/dist/commands/insights.js +71 -0
- package/dist/commands/insights.js.map +1 -0
- package/dist/commands/inspect.d.ts +2 -0
- package/dist/commands/inspect.d.ts.map +1 -0
- package/dist/commands/inspect.js +81 -0
- package/dist/commands/inspect.js.map +1 -0
- package/dist/commands/integrations.d.ts +2 -0
- package/dist/commands/integrations.d.ts.map +1 -0
- package/dist/commands/integrations.js +46 -0
- package/dist/commands/integrations.js.map +1 -0
- package/dist/commands/login.d.ts +1 -1
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +45 -6
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/metrics.d.ts +6 -0
- package/dist/commands/metrics.d.ts.map +1 -0
- package/dist/commands/metrics.js +85 -0
- package/dist/commands/metrics.js.map +1 -0
- package/dist/commands/reconcile.d.ts +2 -0
- package/dist/commands/reconcile.d.ts.map +1 -0
- package/dist/commands/reconcile.js +63 -0
- package/dist/commands/reconcile.js.map +1 -0
- package/dist/commands/scan.d.ts.map +1 -1
- package/dist/commands/scan.js +53 -10
- package/dist/commands/scan.js.map +1 -1
- package/dist/commands/status.d.ts +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +84 -14
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/subscription.d.ts +15 -0
- package/dist/commands/subscription.d.ts.map +1 -0
- package/dist/commands/subscription.js +62 -0
- package/dist/commands/subscription.js.map +1 -0
- package/dist/commands/sync.d.ts +1 -1
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +77 -10
- package/dist/commands/sync.js.map +1 -1
- package/dist/commands/value.d.ts +5 -0
- package/dist/commands/value.d.ts.map +1 -0
- package/dist/commands/value.js +95 -0
- package/dist/commands/value.js.map +1 -0
- package/dist/config.d.ts +28 -3
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +9 -1
- package/dist/config.js.map +1 -1
- package/dist/correlate.d.ts +7 -0
- package/dist/correlate.d.ts.map +1 -1
- package/dist/correlate.js +102 -15
- package/dist/correlate.js.map +1 -1
- package/dist/daemon/daemon.d.ts +2 -0
- package/dist/daemon/daemon.d.ts.map +1 -0
- package/dist/daemon/daemon.js +188 -0
- package/dist/daemon/daemon.js.map +1 -0
- package/dist/daemon/daemonState.d.ts +25 -0
- package/dist/daemon/daemonState.d.ts.map +1 -0
- package/dist/daemon/daemonState.js +82 -0
- package/dist/daemon/daemonState.js.map +1 -0
- package/dist/daemon/logger.d.ts +7 -0
- package/dist/daemon/logger.d.ts.map +1 -0
- package/dist/daemon/logger.js +61 -0
- package/dist/daemon/logger.js.map +1 -0
- package/dist/daemon/syncLoop.d.ts +38 -0
- package/dist/daemon/syncLoop.d.ts.map +1 -0
- package/dist/daemon/syncLoop.js +119 -0
- package/dist/daemon/syncLoop.js.map +1 -0
- package/dist/daemon/watcher.d.ts +26 -0
- package/dist/daemon/watcher.d.ts.map +1 -0
- package/dist/daemon/watcher.js +187 -0
- package/dist/daemon/watcher.js.map +1 -0
- package/dist/db/store.d.ts +123 -2
- package/dist/db/store.d.ts.map +1 -1
- package/dist/db/store.js +397 -11
- package/dist/db/store.js.map +1 -1
- package/dist/detectors/cache-gap.d.ts +3 -0
- package/dist/detectors/cache-gap.d.ts.map +1 -0
- package/dist/detectors/cache-gap.js +70 -0
- package/dist/detectors/cache-gap.js.map +1 -0
- package/dist/detectors/context-bloat.d.ts +3 -0
- package/dist/detectors/context-bloat.d.ts.map +1 -0
- package/dist/detectors/context-bloat.js +68 -0
- package/dist/detectors/context-bloat.js.map +1 -0
- package/dist/detectors/fileTokens.d.ts +3 -0
- package/dist/detectors/fileTokens.d.ts.map +1 -0
- package/dist/detectors/fileTokens.js +12 -0
- package/dist/detectors/fileTokens.js.map +1 -0
- package/dist/detectors/index.d.ts +20 -0
- package/dist/detectors/index.d.ts.map +1 -0
- package/dist/detectors/index.js +41 -0
- package/dist/detectors/index.js.map +1 -0
- package/dist/detectors/model-routing.d.ts +3 -0
- package/dist/detectors/model-routing.d.ts.map +1 -0
- package/dist/detectors/model-routing.js +71 -0
- package/dist/detectors/model-routing.js.map +1 -0
- package/dist/detectors/repeat-read.d.ts +3 -0
- package/dist/detectors/repeat-read.d.ts.map +1 -0
- package/dist/detectors/repeat-read.js +69 -0
- package/dist/detectors/repeat-read.js.map +1 -0
- package/dist/detectors/seat-efficiency.d.ts +4 -0
- package/dist/detectors/seat-efficiency.d.ts.map +1 -0
- package/dist/detectors/seat-efficiency.js +86 -0
- package/dist/detectors/seat-efficiency.js.map +1 -0
- package/dist/detectors/types.d.ts +46 -0
- package/dist/detectors/types.d.ts.map +1 -0
- package/dist/detectors/types.js +2 -0
- package/dist/detectors/types.js.map +1 -0
- package/dist/health.d.ts +59 -0
- package/dist/health.d.ts.map +1 -0
- package/dist/health.js +106 -0
- package/dist/health.js.map +1 -0
- package/dist/index.js +389 -5
- package/dist/index.js.map +1 -1
- package/dist/metrics.d.ts +29 -0
- package/dist/metrics.d.ts.map +1 -0
- package/dist/metrics.js +205 -0
- package/dist/metrics.js.map +1 -0
- package/dist/scrapers/claudeCode.d.ts +1 -0
- package/dist/scrapers/claudeCode.d.ts.map +1 -1
- package/dist/scrapers/claudeCode.js +43 -13
- package/dist/scrapers/claudeCode.js.map +1 -1
- package/dist/scrapers/cursor.d.ts +3 -2
- package/dist/scrapers/cursor.d.ts.map +1 -1
- package/dist/scrapers/cursor.js +56 -16
- package/dist/scrapers/cursor.js.map +1 -1
- package/dist/scrapers/jetbrains.d.ts +15 -0
- package/dist/scrapers/jetbrains.d.ts.map +1 -0
- package/dist/scrapers/jetbrains.js +232 -0
- package/dist/scrapers/jetbrains.js.map +1 -0
- package/dist/scrapers/types.d.ts +4 -1
- package/dist/scrapers/types.d.ts.map +1 -1
- package/dist/scrapers/windsurf.d.ts +3 -2
- package/dist/scrapers/windsurf.d.ts.map +1 -1
- package/dist/scrapers/windsurf.js +25 -9
- package/dist/scrapers/windsurf.js.map +1 -1
- package/dist/sync/payload.d.ts +4 -5
- package/dist/sync/payload.d.ts.map +1 -1
- package/dist/sync/payload.js +88 -7
- package/dist/sync/payload.js.map +1 -1
- package/dist/sync/syncEngine.d.ts +19 -3
- package/dist/sync/syncEngine.d.ts.map +1 -1
- package/dist/sync/syncEngine.js +116 -10
- package/dist/sync/syncEngine.js.map +1 -1
- package/install.sh +27 -10
- 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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"}
|
package/dist/scrapers/types.d.ts
CHANGED
|
@@ -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;
|
|
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
|
|
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;
|
|
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
|
|
14
|
-
//
|
|
15
|
-
//
|
|
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
|
-
|
|
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
|
|
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":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"windsurf.js","sourceRoot":"","sources":["../../src/scrapers/windsurf.ts"],"names":[],"mappings":"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"}
|
package/dist/sync/payload.d.ts
CHANGED
|
@@ -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
|
|
10
|
-
*
|
|
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:
|
|
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":"
|
|
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"}
|
package/dist/sync/payload.js
CHANGED
|
@@ -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
|
|
6
|
-
*
|
|
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
|
-
|
|
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
|
package/dist/sync/payload.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"payload.js","sourceRoot":"","sources":["../../src/sync/payload.ts"],"names":[],"mappings":"
|
|
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
|
|
12
|
-
*
|
|
13
|
-
*
|
|
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":"
|
|
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"}
|