@ascenda-one/history-import 0.1.12
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 +127 -0
- package/dist/cli.js +3889 -0
- package/dist/cli.js.map +1 -0
- package/dist/daySlice.js +98 -0
- package/dist/daySlice.js.map +1 -0
- package/dist/extractors/claudeCode.js +779 -0
- package/dist/extractors/claudeCode.js.map +1 -0
- package/dist/extractors/cursor.js +601 -0
- package/dist/extractors/cursor.js.map +1 -0
- package/dist/extractors/git.js +9 -0
- package/dist/extractors/git.js.map +1 -0
- package/dist/extractors/vscode.js +615 -0
- package/dist/extractors/vscode.js.map +1 -0
- package/dist/localHandoff.js +238 -0
- package/dist/localHandoff.js.map +1 -0
- package/dist/retention.js +68 -0
- package/dist/retention.js.map +1 -0
- package/dist/scan.js +220 -0
- package/dist/scan.js.map +1 -0
- package/dist/ship.js +208 -0
- package/dist/ship.js.map +1 -0
- package/dist/staging.js +121 -0
- package/dist/staging.js.map +1 -0
- package/dist/stores.js +25 -0
- package/dist/stores.js.map +1 -0
- package/dist/types.js +74 -0
- package/dist/types.js.map +1 -0
- package/package.json +32 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cursor.js","sourceRoot":"","sources":["../../src/extractors/cursor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-unused-vars, require-yield */
|
|
2
|
+
export async function* extractGit(snapshotDir, extractionId) {
|
|
3
|
+
// Open work. Unlike the other stores git needs no staging copy — history
|
|
4
|
+
// is immutable; `git log --format` against the live repo is the extraction.
|
|
5
|
+
// The snapshotDir parameter is accepted for interface uniformity and
|
|
6
|
+
// ignored.
|
|
7
|
+
throw new Error("extractGit is not implemented yet — scaffolded 2026-08-18; see docs/HISTORICAL_TELEMETRY_IMPORT.md in the Flow workspace");
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=git.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/extractors/git.ts"],"names":[],"mappings":"AAYA,qEAAqE;AACrE,MAAM,CAAC,KAAK,SAAS,CAAC,CAAC,UAAU,CAC/B,WAAmB,EACnB,YAAoB;IAEpB,yEAAyE;IACzE,4EAA4E;IAC5E,qEAAqE;IACrE,WAAW;IACX,MAAM,IAAI,KAAK,CACb,0HAA0H,CAC3H,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,615 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VS Code extractor — the deep baseline (stable stores, ~9 months observed),
|
|
3
|
+
* safe to run in a background pass after Claude Code and Cursor.
|
|
4
|
+
*
|
|
5
|
+
* Two independent stores, one extractor:
|
|
6
|
+
* - `User/History/<hash>/entries.json` — Timeline local history. One
|
|
7
|
+
* directory per tracked FILE (not per workspace), format self-labels
|
|
8
|
+
* `{"version":1,"resource","entries"}`. The decisive per-entry field is
|
|
9
|
+
* `source: "Chat Edit: '<prompt>'"` — 13,780 of 14,928 entries on the
|
|
10
|
+
* reference machine (verified 2026-08-18). The PROMPT TEXT inside that
|
|
11
|
+
* string is content: only the `"Chat Edit:"` prefix is ever read: the
|
|
12
|
+
* extractor counts and timestamps Chat Edits, never ships the string.
|
|
13
|
+
* - `workspaceStorage/<ws>/chatSessions/*.{json,jsonl}` — Copilot sessions,
|
|
14
|
+
* self-label `"version":3` on the reference machine. Each `requests[]`
|
|
15
|
+
* entry carries `message`/`response` (content — never read past checking
|
|
16
|
+
* they exist) and `modelId`/`timestamp`/`isCanceled`/`result.errorDetails`
|
|
17
|
+
* (metrics).
|
|
18
|
+
*
|
|
19
|
+
* Workspace identity for BOTH stores comes from the same source:
|
|
20
|
+
* `workspaceStorage/<hash>/workspace.json`'s `folder` field is the real path
|
|
21
|
+
* VS Code itself resolved for that workspace hash — not a guess at path
|
|
22
|
+
* segments. `buildWorkspaceFolderIndex` reads every one of those once and a
|
|
23
|
+
* Timeline-history file's `resource` path is matched against it by longest
|
|
24
|
+
* prefix (verified 2026-08-18: 3,726 of 3,792 resource paths on the
|
|
25
|
+
* reference machine resolve this way; the remainder are `/tmp` scratch files
|
|
26
|
+
* and files under paths VS Code never opened as a workspace — real gaps, not
|
|
27
|
+
* bugs, and they fall back to the file's own containing directory rather
|
|
28
|
+
* than a fabricated workspace name). Multi-root workspaces (`workspace.json`
|
|
29
|
+
* pointing at `workspace` instead of `folder`, itself a pointer into
|
|
30
|
+
* `Code/Workspaces/…`) are outside this store's own snapshot boundary and
|
|
31
|
+
* are deliberately left unresolved rather than followed into a second store
|
|
32
|
+
* this extractor was not handed.
|
|
33
|
+
*
|
|
34
|
+
* Emission (aggregate before shipping — never one event per Timeline entry
|
|
35
|
+
* or per bubble):
|
|
36
|
+
* - `editor_activity` per (day, workspace) with ≥1 Timeline-history
|
|
37
|
+
* entry: chat-edit count vs. total entry count. This alone reproduces the
|
|
38
|
+
* adoption arc (the May-2026 cliff) once rolled up to months downstream —
|
|
39
|
+
* provenance historical_derived (a fold across many raw entries).
|
|
40
|
+
* - `ai_prompt_submitted` per Copilot chat request (canonical type, no
|
|
41
|
+
* metrics — same content-free shape claudeCode.ts uses for human
|
|
42
|
+
* prompts), provenance historical_direct.
|
|
43
|
+
* - `create_focus_session` per Copilot chat session: request count,
|
|
44
|
+
* model mix, after-hours count, cancellation/error counts, duration —
|
|
45
|
+
* provenance historical_derived.
|
|
46
|
+
* - `after_hours_ai_session` / `tool_failure` per session with ≥1 of that
|
|
47
|
+
* signal (canonical types, aggregate — same shape claudeCode.ts uses).
|
|
48
|
+
* - one `extraction_epoch` (local only — filtered before the wire) for
|
|
49
|
+
* the store's observed window, folding
|
|
50
|
+
* in unparsed/malformed counts from both sub-stores so a partial import
|
|
51
|
+
* is visible rather than silently read as complete.
|
|
52
|
+
* Metrics carry counts, ids and timestamps only — never prompt/response text
|
|
53
|
+
* or file contents.
|
|
54
|
+
*/
|
|
55
|
+
import * as fs from "node:fs/promises";
|
|
56
|
+
import * as path from "node:path";
|
|
57
|
+
import { fileURLToPath } from "node:url";
|
|
58
|
+
import { bucketDurationMs, isAfterHours } from "@ascenda-one/tool-kit";
|
|
59
|
+
import { HISTORICAL_PROVENANCE } from "../types.js";
|
|
60
|
+
import { sliceSessionByLocalDay } from "../daySlice.js";
|
|
61
|
+
/** Self-labelled schema versions this extractor has a fixture for. Anything
|
|
62
|
+
* else sniffs as unparsed — counted, never guessed at (the same
|
|
63
|
+
* contract-test discipline claudeCode.ts's `sniffClaudeLine` follows). */
|
|
64
|
+
const KNOWN_HISTORY_VERSION = 1;
|
|
65
|
+
const KNOWN_CHAT_SESSION_VERSION = 3;
|
|
66
|
+
/** Only this prefix is ever inspected on a Timeline-history entry's
|
|
67
|
+
* `source` field — the prompt text after it is content. */
|
|
68
|
+
const CHAT_EDIT_PREFIX = "Chat Edit:";
|
|
69
|
+
function uriToPath(uri) {
|
|
70
|
+
if (typeof uri !== "string" || !uri.startsWith("file://"))
|
|
71
|
+
return null;
|
|
72
|
+
try {
|
|
73
|
+
return fileURLToPath(uri);
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* One entry per resolvable `workspaceStorage/<hash>/workspace.json`, sorted
|
|
81
|
+
* longest-path-first so a nested folder wins over an ancestor during
|
|
82
|
+
* matching. Hash directories with no `workspace.json`, an unparsable one, or
|
|
83
|
+
* only a multi-root `workspace` pointer are silently skipped — they simply
|
|
84
|
+
* don't contribute an entry, which is the correct behaviour (their sessions
|
|
85
|
+
* fall back to directory-based grouping, never a fabricated folder).
|
|
86
|
+
*/
|
|
87
|
+
async function buildWorkspaceFolderIndex(workspaceStorageDir) {
|
|
88
|
+
let hashDirs = [];
|
|
89
|
+
try {
|
|
90
|
+
hashDirs = (await fs.readdir(workspaceStorageDir, { withFileTypes: true }))
|
|
91
|
+
.filter((e) => e.isDirectory())
|
|
92
|
+
.map((e) => e.name);
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
return [];
|
|
96
|
+
}
|
|
97
|
+
const folders = [];
|
|
98
|
+
for (const hash of hashDirs) {
|
|
99
|
+
let raw;
|
|
100
|
+
try {
|
|
101
|
+
raw = await fs.readFile(path.join(workspaceStorageDir, hash, "workspace.json"), "utf8");
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
let parsed;
|
|
107
|
+
try {
|
|
108
|
+
parsed = JSON.parse(raw);
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
if (typeof parsed !== "object" || parsed === null)
|
|
114
|
+
continue;
|
|
115
|
+
const folderPath = uriToPath(parsed.folder);
|
|
116
|
+
if (folderPath)
|
|
117
|
+
folders.push({ folderPath });
|
|
118
|
+
}
|
|
119
|
+
return folders.sort((a, b) => b.folderPath.length - a.folderPath.length);
|
|
120
|
+
}
|
|
121
|
+
/** Resolves a file path to its workspace root via longest-prefix match
|
|
122
|
+
* against the index. Falls back to the file's own containing directory when
|
|
123
|
+
* nothing matches — real, never fabricated, just coarser than a true
|
|
124
|
+
* workspace root. */
|
|
125
|
+
function workspaceRootOf(filePath, index) {
|
|
126
|
+
for (const folder of index) {
|
|
127
|
+
const withSlash = folder.folderPath.endsWith("/") ? folder.folderPath : `${folder.folderPath}/`;
|
|
128
|
+
if (filePath === folder.folderPath || filePath.startsWith(withSlash)) {
|
|
129
|
+
return folder.folderPath;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return path.dirname(filePath);
|
|
133
|
+
}
|
|
134
|
+
/** Parses one `entries.json`. Returns null for anything that isn't valid
|
|
135
|
+
* JSON, isn't `version: 1`, or is missing the fields this extractor reads —
|
|
136
|
+
* every one of those is a file-level `unparsed`, not a half-read. */
|
|
137
|
+
function sniffHistoryFile(raw) {
|
|
138
|
+
let parsed;
|
|
139
|
+
try {
|
|
140
|
+
parsed = JSON.parse(raw);
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
if (typeof parsed !== "object" || parsed === null)
|
|
146
|
+
return null;
|
|
147
|
+
const record = parsed;
|
|
148
|
+
if (record.version !== KNOWN_HISTORY_VERSION)
|
|
149
|
+
return null;
|
|
150
|
+
if (typeof record.resource !== "string" || !Array.isArray(record.entries))
|
|
151
|
+
return null;
|
|
152
|
+
return { resource: record.resource, entries: record.entries };
|
|
153
|
+
}
|
|
154
|
+
async function foldEditDays(historyDir, index) {
|
|
155
|
+
const result = {
|
|
156
|
+
days: new Map(),
|
|
157
|
+
unparsedFiles: 0,
|
|
158
|
+
malformedEntries: 0,
|
|
159
|
+
oldest: null,
|
|
160
|
+
newest: null
|
|
161
|
+
};
|
|
162
|
+
let hashDirs = [];
|
|
163
|
+
try {
|
|
164
|
+
hashDirs = (await fs.readdir(historyDir, { withFileTypes: true }))
|
|
165
|
+
.filter((e) => e.isDirectory())
|
|
166
|
+
.map((e) => e.name);
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
return result; // No Timeline history in this snapshot — not an error.
|
|
170
|
+
}
|
|
171
|
+
for (const hash of hashDirs.sort()) {
|
|
172
|
+
let raw;
|
|
173
|
+
try {
|
|
174
|
+
raw = await fs.readFile(path.join(historyDir, hash, "entries.json"), "utf8");
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
continue; // A hash directory without entries.json isn't this store's concern.
|
|
178
|
+
}
|
|
179
|
+
const sniffed = sniffHistoryFile(raw);
|
|
180
|
+
if (!sniffed) {
|
|
181
|
+
result.unparsedFiles += 1;
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
const resourcePath = uriToPath(sniffed.resource);
|
|
185
|
+
if (!resourcePath) {
|
|
186
|
+
result.unparsedFiles += 1; // Self-labelled version 1 but the resource URI didn't decode.
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
const workspaceRoot = workspaceRootOf(resourcePath, index);
|
|
190
|
+
for (const entry of sniffed.entries) {
|
|
191
|
+
const ts = typeof entry.timestamp === "number" && Number.isFinite(entry.timestamp) ? entry.timestamp : null;
|
|
192
|
+
if (ts === null) {
|
|
193
|
+
result.malformedEntries += 1;
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
const iso = new Date(ts).toISOString();
|
|
197
|
+
const date = iso.slice(0, 10);
|
|
198
|
+
if (!result.oldest || iso < result.oldest)
|
|
199
|
+
result.oldest = iso;
|
|
200
|
+
if (!result.newest || iso > result.newest)
|
|
201
|
+
result.newest = iso;
|
|
202
|
+
const key = `${date}\0${workspaceRoot}`;
|
|
203
|
+
let fold = result.days.get(key);
|
|
204
|
+
if (!fold) {
|
|
205
|
+
fold = { date, workspaceRoot, chatEditCount: 0, totalEntryCount: 0, lastTs: iso };
|
|
206
|
+
result.days.set(key, fold);
|
|
207
|
+
}
|
|
208
|
+
fold.totalEntryCount += 1;
|
|
209
|
+
if (iso > fold.lastTs)
|
|
210
|
+
fold.lastTs = iso;
|
|
211
|
+
// Only the prefix is read here — everything after it is the prompt,
|
|
212
|
+
// which never leaves this function.
|
|
213
|
+
if (typeof entry.source === "string" && entry.source.startsWith(CHAT_EDIT_PREFIX)) {
|
|
214
|
+
fold.chatEditCount += 1;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return result;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* A `.jsonl` chat session is a keypath-delta log, not a document: line 1 is
|
|
222
|
+
* `{kind:0, v:<the session object>}` and every later line mutates it —
|
|
223
|
+
* `{kind:1, k:[...path], v}` sets a value, `{kind:2, k:[...path], v:[...], i?}`
|
|
224
|
+
* splices into an array (appending when `i` is absent).
|
|
225
|
+
*
|
|
226
|
+
* Folding the deltas is not optional. On the reference machine the `kind:0`
|
|
227
|
+
* headers alone carry 579 requests across 1,161 sessions; folding recovers
|
|
228
|
+
* 6,869. Reading only the header would have restored the sessions with ~92%
|
|
229
|
+
* of their prompts missing — a quieter wrong answer than the empty months it
|
|
230
|
+
* replaced, because nothing downstream would flag a deflated count.
|
|
231
|
+
*/
|
|
232
|
+
const JSONL_KIND_HEADER = 0;
|
|
233
|
+
const JSONL_KIND_SET = 1;
|
|
234
|
+
const JSONL_KIND_SPLICE = 2;
|
|
235
|
+
/** Walks `path` from `root`, returning the container it addresses, or null if
|
|
236
|
+
* any segment is missing — a delta against a path the header never had is
|
|
237
|
+
* dropped, never conjured into existence. */
|
|
238
|
+
function resolvePath(root, path) {
|
|
239
|
+
let cur = root;
|
|
240
|
+
for (const seg of path) {
|
|
241
|
+
if (typeof seg === "number") {
|
|
242
|
+
if (!Array.isArray(cur) || seg >= cur.length)
|
|
243
|
+
return null;
|
|
244
|
+
cur = cur[seg];
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
if (typeof cur !== "object" || cur === null || Array.isArray(cur))
|
|
248
|
+
return null;
|
|
249
|
+
cur = cur[seg];
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
return cur ?? null;
|
|
253
|
+
}
|
|
254
|
+
function applySet(root, path, value) {
|
|
255
|
+
if (path.length === 0)
|
|
256
|
+
return;
|
|
257
|
+
const parent = resolvePath(root, path.slice(0, -1));
|
|
258
|
+
const last = path[path.length - 1];
|
|
259
|
+
if (typeof last === "number") {
|
|
260
|
+
if (!Array.isArray(parent))
|
|
261
|
+
return;
|
|
262
|
+
while (parent.length <= last)
|
|
263
|
+
parent.push(null);
|
|
264
|
+
parent[last] = value;
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
if (typeof parent !== "object" || parent === null || Array.isArray(parent))
|
|
268
|
+
return;
|
|
269
|
+
parent[last] = value;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
function applySplice(root, path, values, index) {
|
|
273
|
+
const target = resolvePath(root, path);
|
|
274
|
+
if (!Array.isArray(target))
|
|
275
|
+
return;
|
|
276
|
+
if (index !== null && index >= 0 && index <= target.length)
|
|
277
|
+
target.splice(index, 0, ...values);
|
|
278
|
+
else
|
|
279
|
+
target.push(...values);
|
|
280
|
+
}
|
|
281
|
+
/** Folds one `.jsonl` session into the same record shape the `.json` reader
|
|
282
|
+
* produces, so both formats converge before any counting happens. */
|
|
283
|
+
export function parseJsonlChatSession(raw) {
|
|
284
|
+
let malformedLines = 0;
|
|
285
|
+
let record = null;
|
|
286
|
+
for (const line of raw.split("\n")) {
|
|
287
|
+
const trimmed = line.trim();
|
|
288
|
+
if (trimmed === "")
|
|
289
|
+
continue;
|
|
290
|
+
let parsed;
|
|
291
|
+
try {
|
|
292
|
+
parsed = JSON.parse(trimmed);
|
|
293
|
+
}
|
|
294
|
+
catch {
|
|
295
|
+
malformedLines += 1;
|
|
296
|
+
continue;
|
|
297
|
+
}
|
|
298
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
299
|
+
malformedLines += 1;
|
|
300
|
+
continue;
|
|
301
|
+
}
|
|
302
|
+
const delta = parsed;
|
|
303
|
+
if (delta.kind === JSONL_KIND_HEADER) {
|
|
304
|
+
// The header is the document. A second one would mean a concatenated
|
|
305
|
+
// log; keep the first, which is the session's own creation record.
|
|
306
|
+
if (record === null && typeof delta.v === "object" && delta.v !== null) {
|
|
307
|
+
record = delta.v;
|
|
308
|
+
}
|
|
309
|
+
continue;
|
|
310
|
+
}
|
|
311
|
+
if (record === null || !Array.isArray(delta.k))
|
|
312
|
+
continue;
|
|
313
|
+
const keyPath = delta.k.filter((seg) => typeof seg === "string" || typeof seg === "number");
|
|
314
|
+
if (keyPath.length !== delta.k.length)
|
|
315
|
+
continue;
|
|
316
|
+
if (delta.kind === JSONL_KIND_SET) {
|
|
317
|
+
applySet(record, keyPath, delta.v);
|
|
318
|
+
}
|
|
319
|
+
else if (delta.kind === JSONL_KIND_SPLICE && Array.isArray(delta.v)) {
|
|
320
|
+
applySplice(record, keyPath, delta.v, typeof delta.i === "number" ? delta.i : null);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
return { record, malformedLines };
|
|
324
|
+
}
|
|
325
|
+
function topModel(models) {
|
|
326
|
+
let best = null;
|
|
327
|
+
let bestCount = 0;
|
|
328
|
+
for (const [model, count] of models) {
|
|
329
|
+
if (count > bestCount) {
|
|
330
|
+
best = model;
|
|
331
|
+
bestCount = count;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
return best;
|
|
335
|
+
}
|
|
336
|
+
async function foldChatSessions(workspaceStorageDir) {
|
|
337
|
+
const result = {
|
|
338
|
+
sessions: [],
|
|
339
|
+
unparsedFiles: 0,
|
|
340
|
+
unrecognisedFiles: 0,
|
|
341
|
+
emptyDrafts: 0,
|
|
342
|
+
malformedLines: 0
|
|
343
|
+
};
|
|
344
|
+
let wsHashes = [];
|
|
345
|
+
try {
|
|
346
|
+
wsHashes = (await fs.readdir(workspaceStorageDir, { withFileTypes: true }))
|
|
347
|
+
.filter((e) => e.isDirectory())
|
|
348
|
+
.map((e) => e.name);
|
|
349
|
+
}
|
|
350
|
+
catch {
|
|
351
|
+
return result;
|
|
352
|
+
}
|
|
353
|
+
for (const hash of wsHashes.sort()) {
|
|
354
|
+
const wsDir = path.join(workspaceStorageDir, hash);
|
|
355
|
+
let workspaceRoot = null;
|
|
356
|
+
try {
|
|
357
|
+
const raw = await fs.readFile(path.join(wsDir, "workspace.json"), "utf8");
|
|
358
|
+
const parsed = JSON.parse(raw);
|
|
359
|
+
workspaceRoot = uriToPath(parsed.folder);
|
|
360
|
+
}
|
|
361
|
+
catch {
|
|
362
|
+
// No workspace.json, or a multi-root pointer — left unresolved, not guessed.
|
|
363
|
+
}
|
|
364
|
+
let files = [];
|
|
365
|
+
try {
|
|
366
|
+
const entries = await fs.readdir(path.join(wsDir, "chatSessions"));
|
|
367
|
+
files = entries.filter((f) => f.endsWith(".json") || f.endsWith(".jsonl"));
|
|
368
|
+
// Anything else in here is a store shape this extractor does not know.
|
|
369
|
+
// Counted, never silently skipped — see `unrecognisedFiles`.
|
|
370
|
+
result.unrecognisedFiles += entries.length - files.length;
|
|
371
|
+
}
|
|
372
|
+
catch {
|
|
373
|
+
continue; // Most workspaces have no chatSessions dir — the norm.
|
|
374
|
+
}
|
|
375
|
+
for (const file of files.sort()) {
|
|
376
|
+
let raw;
|
|
377
|
+
try {
|
|
378
|
+
raw = await fs.readFile(path.join(wsDir, "chatSessions", file), "utf8");
|
|
379
|
+
}
|
|
380
|
+
catch {
|
|
381
|
+
continue;
|
|
382
|
+
}
|
|
383
|
+
// Two on-disk shapes, one record. `.json` is the whole session; `.jsonl`
|
|
384
|
+
// is a delta log whose header plus deltas fold to the same thing. Both
|
|
385
|
+
// must clear the same version gate below — the migration changed the
|
|
386
|
+
// container, not the session schema (still version 3).
|
|
387
|
+
let record = null;
|
|
388
|
+
if (file.endsWith(".jsonl")) {
|
|
389
|
+
const folded = parseJsonlChatSession(raw);
|
|
390
|
+
result.malformedLines += folded.malformedLines;
|
|
391
|
+
record = folded.record;
|
|
392
|
+
}
|
|
393
|
+
else {
|
|
394
|
+
try {
|
|
395
|
+
const parsed = JSON.parse(raw);
|
|
396
|
+
if (typeof parsed === "object" && parsed !== null) {
|
|
397
|
+
record = parsed;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
catch {
|
|
401
|
+
record = null;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
if (record === null) {
|
|
405
|
+
result.unparsedFiles += 1;
|
|
406
|
+
continue;
|
|
407
|
+
}
|
|
408
|
+
if (record.version !== KNOWN_CHAT_SESSION_VERSION) {
|
|
409
|
+
result.unparsedFiles += 1;
|
|
410
|
+
continue;
|
|
411
|
+
}
|
|
412
|
+
const requests = Array.isArray(record.requests) ? record.requests : [];
|
|
413
|
+
if (requests.length === 0) {
|
|
414
|
+
result.emptyDrafts += 1; // An empty draft — no real usage to fold.
|
|
415
|
+
continue;
|
|
416
|
+
}
|
|
417
|
+
const fold = {
|
|
418
|
+
sessionId: typeof record.sessionId === "string"
|
|
419
|
+
? record.sessionId
|
|
420
|
+
: path.basename(file, path.extname(file)),
|
|
421
|
+
workspaceRoot,
|
|
422
|
+
firstTs: null,
|
|
423
|
+
lastTs: null,
|
|
424
|
+
requestCount: 0,
|
|
425
|
+
afterHoursRequests: 0,
|
|
426
|
+
canceledCount: 0,
|
|
427
|
+
errorCount: 0,
|
|
428
|
+
models: new Map(),
|
|
429
|
+
requestTimestamps: []
|
|
430
|
+
};
|
|
431
|
+
for (const r of requests) {
|
|
432
|
+
if (typeof r !== "object" || r === null)
|
|
433
|
+
continue;
|
|
434
|
+
const req = r;
|
|
435
|
+
const ts = typeof req.timestamp === "number" && Number.isFinite(req.timestamp) ? req.timestamp : null;
|
|
436
|
+
if (ts === null)
|
|
437
|
+
continue; // No usable timestamp — not a human-prompt event, not a session anchor.
|
|
438
|
+
const iso = new Date(ts).toISOString();
|
|
439
|
+
fold.requestCount += 1;
|
|
440
|
+
fold.requestTimestamps.push(iso);
|
|
441
|
+
if (!fold.firstTs || iso < fold.firstTs)
|
|
442
|
+
fold.firstTs = iso;
|
|
443
|
+
if (!fold.lastTs || iso > fold.lastTs)
|
|
444
|
+
fold.lastTs = iso;
|
|
445
|
+
if (isAfterHours(new Date(iso)))
|
|
446
|
+
fold.afterHoursRequests += 1;
|
|
447
|
+
if (req.isCanceled === true)
|
|
448
|
+
fold.canceledCount += 1;
|
|
449
|
+
const requestResult = req.result;
|
|
450
|
+
if (requestResult && requestResult.errorDetails)
|
|
451
|
+
fold.errorCount += 1;
|
|
452
|
+
if (typeof req.modelId === "string") {
|
|
453
|
+
fold.models.set(req.modelId, (fold.models.get(req.modelId) ?? 0) + 1);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
if (fold.requestCount > 0)
|
|
457
|
+
result.sessions.push(fold);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
return result;
|
|
461
|
+
}
|
|
462
|
+
/* ------------------------------------------------------------------------ *
|
|
463
|
+
* Extraction entry point
|
|
464
|
+
* ------------------------------------------------------------------------ */
|
|
465
|
+
/**
|
|
466
|
+
* Expects `snapshotDir` to contain `history/` (a copy of
|
|
467
|
+
* `Code/User/History`) and `workspaceStorage/` (a copy of
|
|
468
|
+
* `Code/User/workspaceStorage`, surgically limited to `workspace.json` and
|
|
469
|
+
* `chatSessions/*.json` per hash — see `snapshotVsCodeWorkspaceStorage` in
|
|
470
|
+
* `staging.ts`, which is what the CLI's `import` command stages this store
|
|
471
|
+
* with).
|
|
472
|
+
*/
|
|
473
|
+
export async function* extractVsCode(snapshotDir, extractionId) {
|
|
474
|
+
const historyDir = path.join(snapshotDir, "history");
|
|
475
|
+
const workspaceStorageDir = path.join(snapshotDir, "workspaceStorage");
|
|
476
|
+
const index = await buildWorkspaceFolderIndex(workspaceStorageDir);
|
|
477
|
+
const editDays = await foldEditDays(historyDir, index);
|
|
478
|
+
const chatSessions = await foldChatSessions(workspaceStorageDir);
|
|
479
|
+
let windowOldest = editDays.oldest;
|
|
480
|
+
let windowNewest = editDays.newest;
|
|
481
|
+
const sortedDays = [...editDays.days.values()].sort((a, b) => `${a.date}\0${a.workspaceRoot}`.localeCompare(`${b.date}\0${b.workspaceRoot}`));
|
|
482
|
+
for (const fold of sortedDays) {
|
|
483
|
+
yield {
|
|
484
|
+
occurredAt: fold.lastTs,
|
|
485
|
+
store: "vscode",
|
|
486
|
+
sourceVersion: String(KNOWN_HISTORY_VERSION),
|
|
487
|
+
sessionRef: null,
|
|
488
|
+
repoRef: fold.workspaceRoot,
|
|
489
|
+
eventKind: "editor_activity",
|
|
490
|
+
metrics: {
|
|
491
|
+
date: fold.date,
|
|
492
|
+
chatEditCount: fold.chatEditCount,
|
|
493
|
+
totalEntryCount: fold.totalEntryCount
|
|
494
|
+
},
|
|
495
|
+
provenance: HISTORICAL_PROVENANCE.derived,
|
|
496
|
+
extractionId
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
let sessionCount = 0;
|
|
500
|
+
for (const fold of chatSessions.sessions) {
|
|
501
|
+
if (!fold.firstTs || !fold.lastTs)
|
|
502
|
+
continue;
|
|
503
|
+
sessionCount += 1;
|
|
504
|
+
if (!windowOldest || fold.firstTs < windowOldest)
|
|
505
|
+
windowOldest = fold.firstTs;
|
|
506
|
+
if (!windowNewest || fold.lastTs > windowNewest)
|
|
507
|
+
windowNewest = fold.lastTs;
|
|
508
|
+
for (const ts of fold.requestTimestamps) {
|
|
509
|
+
yield {
|
|
510
|
+
occurredAt: ts,
|
|
511
|
+
store: "vscode",
|
|
512
|
+
sourceVersion: String(KNOWN_CHAT_SESSION_VERSION),
|
|
513
|
+
sessionRef: fold.sessionId,
|
|
514
|
+
repoRef: fold.workspaceRoot,
|
|
515
|
+
eventKind: "ai_prompt_submitted",
|
|
516
|
+
metrics: {},
|
|
517
|
+
provenance: HISTORICAL_PROVENANCE.direct,
|
|
518
|
+
extractionId
|
|
519
|
+
};
|
|
520
|
+
}
|
|
521
|
+
const durationMs = Date.parse(fold.lastTs) - Date.parse(fold.firstTs);
|
|
522
|
+
const sessionMetrics = {
|
|
523
|
+
requestCount: fold.requestCount,
|
|
524
|
+
afterHoursRequests: fold.afterHoursRequests,
|
|
525
|
+
canceledCount: fold.canceledCount,
|
|
526
|
+
errorCount: fold.errorCount,
|
|
527
|
+
modelCount: fold.models.size,
|
|
528
|
+
sessionStartedAt: fold.firstTs
|
|
529
|
+
};
|
|
530
|
+
const primaryModel = topModel(fold.models);
|
|
531
|
+
if (primaryModel)
|
|
532
|
+
sessionMetrics.primaryModel = primaryModel;
|
|
533
|
+
if (Number.isFinite(durationMs) && durationMs >= 0) {
|
|
534
|
+
sessionMetrics.sessionMinutes = Math.round(durationMs / 60_000);
|
|
535
|
+
const bucket = bucketDurationMs(durationMs);
|
|
536
|
+
if (bucket)
|
|
537
|
+
sessionMetrics.durationBucket = bucket;
|
|
538
|
+
}
|
|
539
|
+
yield {
|
|
540
|
+
occurredAt: fold.lastTs,
|
|
541
|
+
store: "vscode",
|
|
542
|
+
sourceVersion: String(KNOWN_CHAT_SESSION_VERSION),
|
|
543
|
+
sessionRef: fold.sessionId,
|
|
544
|
+
repoRef: fold.workspaceRoot,
|
|
545
|
+
eventKind: "create_focus_session",
|
|
546
|
+
metrics: sessionMetrics,
|
|
547
|
+
dayBreakdown: sliceSessionByLocalDay(fold.requestTimestamps),
|
|
548
|
+
provenance: HISTORICAL_PROVENANCE.derived,
|
|
549
|
+
extractionId
|
|
550
|
+
};
|
|
551
|
+
if (fold.afterHoursRequests > 0) {
|
|
552
|
+
yield {
|
|
553
|
+
occurredAt: fold.lastTs,
|
|
554
|
+
store: "vscode",
|
|
555
|
+
sourceVersion: String(KNOWN_CHAT_SESSION_VERSION),
|
|
556
|
+
sessionRef: fold.sessionId,
|
|
557
|
+
repoRef: fold.workspaceRoot,
|
|
558
|
+
eventKind: "after_hours_ai_session",
|
|
559
|
+
metrics: { afterHoursPrompts: fold.afterHoursRequests },
|
|
560
|
+
provenance: HISTORICAL_PROVENANCE.derived,
|
|
561
|
+
extractionId
|
|
562
|
+
};
|
|
563
|
+
}
|
|
564
|
+
if (fold.errorCount > 0) {
|
|
565
|
+
yield {
|
|
566
|
+
occurredAt: fold.lastTs,
|
|
567
|
+
store: "vscode",
|
|
568
|
+
sourceVersion: String(KNOWN_CHAT_SESSION_VERSION),
|
|
569
|
+
sessionRef: fold.sessionId,
|
|
570
|
+
repoRef: fold.workspaceRoot,
|
|
571
|
+
eventKind: "tool_failure",
|
|
572
|
+
metrics: { toolFailureCount: fold.errorCount },
|
|
573
|
+
provenance: HISTORICAL_PROVENANCE.derived,
|
|
574
|
+
extractionId
|
|
575
|
+
};
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
// A store that yielded nothing readable still has something to report. The
|
|
579
|
+
// window guard alone suppressed the epoch in exactly that case, so the
|
|
580
|
+
// counters that exist to expose an unreadable store were themselves hidden
|
|
581
|
+
// by it — the same shape of blind spot as the `.json`-only glob. Emit
|
|
582
|
+
// whenever there is either a window or a read failure to declare.
|
|
583
|
+
const readFailures = editDays.unparsedFiles +
|
|
584
|
+
editDays.malformedEntries +
|
|
585
|
+
chatSessions.unparsedFiles +
|
|
586
|
+
chatSessions.unrecognisedFiles +
|
|
587
|
+
chatSessions.malformedLines;
|
|
588
|
+
if ((windowOldest && windowNewest) || readFailures > 0) {
|
|
589
|
+
const window = windowOldest && windowNewest ? { windowOldest, windowNewest } : {};
|
|
590
|
+
yield {
|
|
591
|
+
// No window means nothing datable was read; the only honest timestamp
|
|
592
|
+
// left is when the read happened.
|
|
593
|
+
occurredAt: windowNewest ?? new Date().toISOString(),
|
|
594
|
+
store: "vscode",
|
|
595
|
+
sourceVersion: null,
|
|
596
|
+
sessionRef: null,
|
|
597
|
+
repoRef: null,
|
|
598
|
+
eventKind: "extraction_epoch",
|
|
599
|
+
metrics: {
|
|
600
|
+
...window,
|
|
601
|
+
editDayCount: editDays.days.size,
|
|
602
|
+
sessionCount,
|
|
603
|
+
unparsedHistoryFiles: editDays.unparsedFiles,
|
|
604
|
+
malformedHistoryEntries: editDays.malformedEntries,
|
|
605
|
+
unparsedChatSessionFiles: chatSessions.unparsedFiles,
|
|
606
|
+
unrecognisedChatSessionFiles: chatSessions.unrecognisedFiles,
|
|
607
|
+
emptyChatSessions: chatSessions.emptyDrafts,
|
|
608
|
+
malformedChatSessionLines: chatSessions.malformedLines
|
|
609
|
+
},
|
|
610
|
+
provenance: HISTORICAL_PROVENANCE.derived,
|
|
611
|
+
extractionId
|
|
612
|
+
};
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
//# sourceMappingURL=vscode.js.map
|