@alsdd/t3-import 0.0.0-stage → 0.1.1-alsd.1
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/CHANGELOG.md +24 -0
- package/LICENSE +21 -0
- package/README.md +141 -2
- package/assets/fork-demo.gif +0 -0
- package/assets/fork-demo.png +0 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +399 -0
- package/dist/cli.js.map +1 -0
- package/dist/core/checkpoint.d.ts +25 -0
- package/dist/core/checkpoint.js +82 -0
- package/dist/core/checkpoint.js.map +1 -0
- package/dist/core/errors.d.ts +12 -0
- package/dist/core/errors.js +17 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/jsonl.d.ts +7 -0
- package/dist/core/jsonl.js +37 -0
- package/dist/core/jsonl.js.map +1 -0
- package/dist/core/providers.d.ts +6 -0
- package/dist/core/providers.js +17 -0
- package/dist/core/providers.js.map +1 -0
- package/dist/core/types.d.ts +247 -0
- package/dist/core/types.js +4 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/util.d.ts +14 -0
- package/dist/core/util.js +61 -0
- package/dist/core/util.js.map +1 -0
- package/dist/sources/claude.d.ts +6 -0
- package/dist/sources/claude.js +576 -0
- package/dist/sources/claude.js.map +1 -0
- package/dist/sources/codex.d.ts +11 -0
- package/dist/sources/codex.js +603 -0
- package/dist/sources/codex.js.map +1 -0
- package/dist/sources/codexAppServer.d.ts +24 -0
- package/dist/sources/codexAppServer.js +190 -0
- package/dist/sources/codexAppServer.js.map +1 -0
- package/dist/sources/files.d.ts +1 -0
- package/dist/sources/files.js +24 -0
- package/dist/sources/files.js.map +1 -0
- package/dist/sources/index.d.ts +3 -0
- package/dist/sources/index.js +15 -0
- package/dist/sources/index.js.map +1 -0
- package/dist/sources/opencode.d.ts +6 -0
- package/dist/sources/opencode.js +443 -0
- package/dist/sources/opencode.js.map +1 -0
- package/dist/target/cache.d.ts +14 -0
- package/dist/target/cache.js +155 -0
- package/dist/target/cache.js.map +1 -0
- package/dist/target/config.d.ts +22 -0
- package/dist/target/config.js +90 -0
- package/dist/target/config.js.map +1 -0
- package/dist/target/destination.d.ts +21 -0
- package/dist/target/destination.js +77 -0
- package/dist/target/destination.js.map +1 -0
- package/dist/target/importer.d.ts +86 -0
- package/dist/target/importer.js +597 -0
- package/dist/target/importer.js.map +1 -0
- package/dist/target/launch.d.ts +6 -0
- package/dist/target/launch.js +77 -0
- package/dist/target/launch.js.map +1 -0
- package/dist/target/ledger.d.ts +35 -0
- package/dist/target/ledger.js +174 -0
- package/dist/target/ledger.js.map +1 -0
- package/dist/target/reconciliation.d.ts +60 -0
- package/dist/target/reconciliation.js +259 -0
- package/dist/target/reconciliation.js.map +1 -0
- package/dist/target/replace.d.ts +9 -0
- package/dist/target/replace.js +341 -0
- package/dist/target/replace.js.map +1 -0
- package/dist/target/schema.d.ts +22 -0
- package/dist/target/schema.js +108 -0
- package/dist/target/schema.js.map +1 -0
- package/dist/target/sync.d.ts +34 -0
- package/dist/target/sync.js +879 -0
- package/dist/target/sync.js.map +1 -0
- package/dist/target/syncAll.d.ts +4 -0
- package/dist/target/syncAll.js +98 -0
- package/dist/target/syncAll.js.map +1 -0
- package/dist/target/v2.d.ts +18 -0
- package/dist/target/v2.js +267 -0
- package/dist/target/v2.js.map +1 -0
- package/dist/target/v2Profiles.d.ts +5 -0
- package/dist/target/v2Profiles.js +14 -0
- package/dist/target/v2Profiles.js.map +1 -0
- package/dist/tui.d.ts +49 -0
- package/dist/tui.js +560 -0
- package/dist/tui.js.map +1 -0
- package/package.json +93 -4
- package/vendor/t3-v010/LICENSE +21 -0
- package/vendor/t3-v010/THIRD-PARTY-NOTICES.txt +2274 -0
- package/vendor/t3-v010/reference.json +6 -0
- package/vendor/t3-v010/runtime.mjs +60364 -0
- package/vendor/t3-v010/schema-columns.json +568 -0
- package/vendor/t3-v011/LICENSE +21 -0
- package/vendor/t3-v011/THIRD-PARTY-NOTICES.txt +2274 -0
- package/vendor/t3-v011/reference.json +6 -0
- package/vendor/t3-v011/runtime.mjs +60993 -0
- package/vendor/t3-v011/schema-columns.json +526 -0
|
@@ -0,0 +1,443 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join, resolve } from "node:path";
|
|
4
|
+
import { statSync } from "node:fs";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
import Database from "better-sqlite3";
|
|
7
|
+
import { canonicalPath, deriveTitle, isObject, isoTimestamp, stringValue, truncate } from "../core/util.js";
|
|
8
|
+
import { sourceError } from "../core/errors.js";
|
|
9
|
+
const SESSION_COLUMNS = [
|
|
10
|
+
"id", "parent_id", "fork_session_id", "directory", "title", "version",
|
|
11
|
+
"agent", "model", "time_created", "time_updated", "time_idle", "idle_outcome",
|
|
12
|
+
];
|
|
13
|
+
const MESSAGE_COLUMNS = ["id", "session_id", "type", "seq", "time_created", "time_updated", "data"];
|
|
14
|
+
const MAX_INLINE_ATTACHMENT_BYTES = 8 * 1024 * 1024;
|
|
15
|
+
function databasePath() {
|
|
16
|
+
if (process.env.OPENCODE_DB?.trim())
|
|
17
|
+
return resolve(process.env.OPENCODE_DB.trim());
|
|
18
|
+
const dataHome = process.env.XDG_DATA_HOME?.trim() || join(homedir(), ".local", "share");
|
|
19
|
+
return join(dataHome, "opencode", "opencode.db");
|
|
20
|
+
}
|
|
21
|
+
function requiredColumns(db, table, required) {
|
|
22
|
+
const actual = new Set(db.prepare(`PRAGMA table_info(${table})`).all().map((column) => column.name));
|
|
23
|
+
return required.filter((column) => !actual.has(column));
|
|
24
|
+
}
|
|
25
|
+
function openDatabase(path) {
|
|
26
|
+
const db = new Database(path, { readonly: true, fileMustExist: true });
|
|
27
|
+
db.pragma("query_only = ON");
|
|
28
|
+
const tables = new Set(db.prepare("SELECT name FROM sqlite_master WHERE type = 'table'").all().map((row) => row.name));
|
|
29
|
+
if (!tables.has("session_v2") || !tables.has("session_message")) {
|
|
30
|
+
db.close();
|
|
31
|
+
throw sourceError("OpenCode database is not using the supported V2 session schema; expected session_v2 and session_message tables");
|
|
32
|
+
}
|
|
33
|
+
const missing = [
|
|
34
|
+
...requiredColumns(db, "session_v2", SESSION_COLUMNS).map((column) => `session_v2.${column}`),
|
|
35
|
+
...requiredColumns(db, "session_message", MESSAGE_COLUMNS).map((column) => `session_message.${column}`),
|
|
36
|
+
];
|
|
37
|
+
if (missing.length) {
|
|
38
|
+
db.close();
|
|
39
|
+
throw sourceError(`Unsupported OpenCode V2 database schema; missing columns: ${missing.join(", ")}`);
|
|
40
|
+
}
|
|
41
|
+
return db;
|
|
42
|
+
}
|
|
43
|
+
function readSnapshot(path, operation) {
|
|
44
|
+
let db;
|
|
45
|
+
try {
|
|
46
|
+
db = openDatabase(path);
|
|
47
|
+
db.exec("BEGIN");
|
|
48
|
+
const result = operation(db);
|
|
49
|
+
db.exec("COMMIT");
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
try {
|
|
54
|
+
db?.exec("ROLLBACK");
|
|
55
|
+
}
|
|
56
|
+
catch { /* transaction may not have started */ }
|
|
57
|
+
if (error instanceof Error && error.name === "ImporterError")
|
|
58
|
+
throw error;
|
|
59
|
+
throw sourceError(`Unable to read OpenCode database at ${path}`, error);
|
|
60
|
+
}
|
|
61
|
+
finally {
|
|
62
|
+
db?.close();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function parseJson(value, label) {
|
|
66
|
+
let parsed;
|
|
67
|
+
try {
|
|
68
|
+
parsed = JSON.parse(value);
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
throw sourceError(`Invalid ${label} JSON in OpenCode database`, error);
|
|
72
|
+
}
|
|
73
|
+
if (!isObject(parsed))
|
|
74
|
+
throw sourceError(`Invalid ${label} record in OpenCode database`);
|
|
75
|
+
return parsed;
|
|
76
|
+
}
|
|
77
|
+
function sessionQuery(db, id) {
|
|
78
|
+
const available = new Set(db.prepare("PRAGMA table_info(session_v2)").all().map((column) => column.name));
|
|
79
|
+
const fields = [...SESSION_COLUMNS, ...(available.has("time_archived") ? ["time_archived"] : [])].join(", ");
|
|
80
|
+
const rows = id
|
|
81
|
+
? db.prepare(`SELECT ${fields} FROM session_v2 WHERE id = ?`).all(id)
|
|
82
|
+
: db.prepare(`SELECT ${fields} FROM session_v2 ORDER BY time_updated DESC, id`).all();
|
|
83
|
+
return rows;
|
|
84
|
+
}
|
|
85
|
+
function messagesQuery(db, sessionId) {
|
|
86
|
+
return db.prepare(`SELECT ${MESSAGE_COLUMNS.join(", ")} FROM session_message WHERE session_id = ? ORDER BY seq, id`).all(sessionId);
|
|
87
|
+
}
|
|
88
|
+
function timestamp(value, fallback) {
|
|
89
|
+
return isoTimestamp(value, fallback);
|
|
90
|
+
}
|
|
91
|
+
function contentText(value) {
|
|
92
|
+
if (typeof value === "string")
|
|
93
|
+
return value;
|
|
94
|
+
if (Array.isArray(value))
|
|
95
|
+
return value.flatMap((part) => typeof part === "string" ? [part] : isObject(part) && typeof part.text === "string" ? [part.text] : []).join("\n");
|
|
96
|
+
return "";
|
|
97
|
+
}
|
|
98
|
+
function attachmentList(value, messageId) {
|
|
99
|
+
if (!Array.isArray(value))
|
|
100
|
+
return { attachments: [], warnings: [] };
|
|
101
|
+
const attachments = [];
|
|
102
|
+
const warnings = [];
|
|
103
|
+
for (const [index, entry] of value.entries()) {
|
|
104
|
+
if (!isObject(entry))
|
|
105
|
+
continue;
|
|
106
|
+
const mimeType = stringValue(entry.mime) ?? stringValue(entry.mimeType);
|
|
107
|
+
const rawPath = stringValue(entry.path);
|
|
108
|
+
const url = stringValue(entry.url);
|
|
109
|
+
let path;
|
|
110
|
+
let remoteUrl;
|
|
111
|
+
let data;
|
|
112
|
+
let actualMime = mimeType;
|
|
113
|
+
let sizeBytes = typeof entry.size === "number" && Number.isSafeInteger(entry.size) && entry.size >= 0 ? entry.size : undefined;
|
|
114
|
+
if (url?.startsWith("data:")) {
|
|
115
|
+
const match = /^data:([^;,]+)(?:;[^,]*)?;base64,([A-Za-z0-9+/]*={0,2})$/iu.exec(url);
|
|
116
|
+
if (!match || Math.floor(match[2].length * 3 / 4) > MAX_INLINE_ATTACHMENT_BYTES) {
|
|
117
|
+
warnings.push(`Skipped unsupported or oversized inline OpenCode attachment ${messageId}:${index}.`);
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
data = Buffer.from(match[2], "base64");
|
|
121
|
+
sizeBytes = data.length;
|
|
122
|
+
actualMime ??= match[1];
|
|
123
|
+
}
|
|
124
|
+
else if (url?.startsWith("file:")) {
|
|
125
|
+
try {
|
|
126
|
+
path = fileURLToPath(url);
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
warnings.push(`Skipped invalid file URL attachment ${messageId}:${index}.`);
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
else if (url && /^https:\/\//iu.test(url)) {
|
|
134
|
+
remoteUrl = url;
|
|
135
|
+
}
|
|
136
|
+
else if (url && /^[a-z][a-z0-9+.-]*:/iu.test(url)) {
|
|
137
|
+
warnings.push(`Skipped attachment with unsupported URL scheme ${messageId}:${index}.`);
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
path = rawPath ?? url;
|
|
142
|
+
}
|
|
143
|
+
if (!path && !remoteUrl && !data)
|
|
144
|
+
continue;
|
|
145
|
+
if (path && sizeBytes === undefined) {
|
|
146
|
+
try {
|
|
147
|
+
sizeBytes = statSync(path).size;
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
sizeBytes = 0;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
const name = stringValue(entry.filename) ?? stringValue(entry.name) ?? (path ? path.split(/[\\/]/u).at(-1) : `attachment-${index + 1}`);
|
|
154
|
+
attachments.push({
|
|
155
|
+
sourceId: `${messageId}:file:${index}`,
|
|
156
|
+
name,
|
|
157
|
+
mimeType: actualMime ?? "application/octet-stream",
|
|
158
|
+
sizeBytes: sizeBytes ?? 0,
|
|
159
|
+
...(path ? { path } : {}),
|
|
160
|
+
...(remoteUrl ? { remoteUrl } : {}),
|
|
161
|
+
...(data ? { data } : {}),
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
return { attachments, warnings };
|
|
165
|
+
}
|
|
166
|
+
function modelInfo(value) {
|
|
167
|
+
let parsed = value;
|
|
168
|
+
if (typeof value === "string" && value.trim().startsWith("{")) {
|
|
169
|
+
try {
|
|
170
|
+
parsed = JSON.parse(value);
|
|
171
|
+
}
|
|
172
|
+
catch {
|
|
173
|
+
return value.trim() ? { name: value.trim() } : {};
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
if (typeof parsed === "string")
|
|
177
|
+
return parsed.trim() ? { name: parsed.trim() } : {};
|
|
178
|
+
if (!isObject(parsed))
|
|
179
|
+
return {};
|
|
180
|
+
const provider = stringValue(parsed.providerID) ?? stringValue(parsed.providerId);
|
|
181
|
+
const model = stringValue(parsed.modelID) ?? stringValue(parsed.modelId) ?? stringValue(parsed.id);
|
|
182
|
+
const name = provider && model ? `${provider}/${model}` : model ?? provider;
|
|
183
|
+
const variant = stringValue(parsed.variant);
|
|
184
|
+
return {
|
|
185
|
+
...(name ? { name } : {}),
|
|
186
|
+
...(variant ? { variant } : {}),
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
function toolOutput(state) {
|
|
190
|
+
if (state.status === "error")
|
|
191
|
+
return state.error ?? state.content ?? state;
|
|
192
|
+
if (state.status === "completed")
|
|
193
|
+
return state.content ?? "";
|
|
194
|
+
return state.content ?? state;
|
|
195
|
+
}
|
|
196
|
+
function toTurn(turn) {
|
|
197
|
+
return {
|
|
198
|
+
id: turn.id,
|
|
199
|
+
startedAt: turn.startedAt,
|
|
200
|
+
...(turn.completedAt ? { completedAt: turn.completedAt } : {}),
|
|
201
|
+
status: turn.status,
|
|
202
|
+
...(turn.terminalReason ? { terminalReason: turn.terminalReason } : {}),
|
|
203
|
+
...(turn.terminalError ? { terminalError: turn.terminalError } : {}),
|
|
204
|
+
user: turn.user,
|
|
205
|
+
assistant: turn.assistant,
|
|
206
|
+
activities: turn.activities,
|
|
207
|
+
plans: [],
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
function parseThread(session, rows, includeIncomplete) {
|
|
211
|
+
if (!/^2\./u.test(session.version))
|
|
212
|
+
throw sourceError(`OpenCode session ${session.id} was created by unsupported version ${session.version}; this reader supports OpenCode 2.x sessions`);
|
|
213
|
+
const fallback = timestamp(session.time_created, new Date(0).toISOString());
|
|
214
|
+
const turns = [];
|
|
215
|
+
const pending = [];
|
|
216
|
+
let active;
|
|
217
|
+
let ignored = 0;
|
|
218
|
+
let model = modelInfo(session.model).name ?? "default";
|
|
219
|
+
let modelVariant = modelInfo(session.model).variant;
|
|
220
|
+
const warnings = [];
|
|
221
|
+
const settle = (status, time, reason, error) => {
|
|
222
|
+
if (!active)
|
|
223
|
+
return;
|
|
224
|
+
active.status = status;
|
|
225
|
+
active.completedAt = time;
|
|
226
|
+
if (reason)
|
|
227
|
+
active.terminalReason = reason;
|
|
228
|
+
const terminalError = error ?? (status === "failed" ? active.providerErrors.at(-1) : undefined);
|
|
229
|
+
if (terminalError)
|
|
230
|
+
active.terminalError = terminalError;
|
|
231
|
+
if (status === "failed" || status === "interrupted") {
|
|
232
|
+
active.activities.push({
|
|
233
|
+
sourceId: `${active.id}:terminal`,
|
|
234
|
+
timestamp: time,
|
|
235
|
+
tone: status === "failed" ? "error" : "info",
|
|
236
|
+
kind: status === "failed" ? "turn.failed" : "turn.interrupted",
|
|
237
|
+
summary: status === "failed" ? "Turn failed" : "Turn interrupted",
|
|
238
|
+
payload: { status, ...(reason ? { reason } : {}), ...(terminalError ? { detail: terminalError } : {}) },
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
turns.push(active);
|
|
242
|
+
active = undefined;
|
|
243
|
+
};
|
|
244
|
+
for (const row of rows) {
|
|
245
|
+
const data = parseJson(row.data, `session message ${row.id}`);
|
|
246
|
+
const time = timestamp(row.time_created, fallback);
|
|
247
|
+
if (row.type === "user") {
|
|
248
|
+
if (active) {
|
|
249
|
+
pending.push(active);
|
|
250
|
+
warnings.push(`OpenCode session contains an unsettled user message ${active.id} before ${row.id}; it remains incomplete.`);
|
|
251
|
+
active = undefined;
|
|
252
|
+
}
|
|
253
|
+
const text = contentText(data.text);
|
|
254
|
+
const attachments = attachmentList(data.files, row.id);
|
|
255
|
+
warnings.push(...attachments.warnings);
|
|
256
|
+
active = {
|
|
257
|
+
id: row.id,
|
|
258
|
+
sequence: row.seq,
|
|
259
|
+
startedAt: time,
|
|
260
|
+
status: "inProgress",
|
|
261
|
+
user: {
|
|
262
|
+
sourceId: row.id,
|
|
263
|
+
role: "user",
|
|
264
|
+
text: text || (Array.isArray(data.files) && data.files.length ? "[Attachment]" : ""),
|
|
265
|
+
timestamp: time,
|
|
266
|
+
attachments: attachments.attachments,
|
|
267
|
+
},
|
|
268
|
+
assistant: [],
|
|
269
|
+
activities: [],
|
|
270
|
+
providerErrors: [],
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
else if (row.type === "assistant") {
|
|
274
|
+
if (!active)
|
|
275
|
+
continue;
|
|
276
|
+
const assistantModel = modelInfo(data.model);
|
|
277
|
+
if (assistantModel.name) {
|
|
278
|
+
if (assistantModel.name !== model)
|
|
279
|
+
modelVariant = assistantModel.variant;
|
|
280
|
+
model = assistantModel.name;
|
|
281
|
+
}
|
|
282
|
+
else if (assistantModel.variant) {
|
|
283
|
+
modelVariant = assistantModel.variant;
|
|
284
|
+
}
|
|
285
|
+
if (modelVariant === "default")
|
|
286
|
+
modelVariant = undefined;
|
|
287
|
+
const parts = Array.isArray(data.content) ? data.content : [];
|
|
288
|
+
const textParts = [];
|
|
289
|
+
for (const [index, rawPart] of parts.entries()) {
|
|
290
|
+
if (!isObject(rawPart))
|
|
291
|
+
continue;
|
|
292
|
+
const sourceId = `${row.id}:${index}`;
|
|
293
|
+
if (rawPart.type === "text" && typeof rawPart.text === "string") {
|
|
294
|
+
if (rawPart.text.length)
|
|
295
|
+
textParts.push(rawPart.text);
|
|
296
|
+
}
|
|
297
|
+
else if (rawPart.type === "reasoning" && typeof rawPart.text === "string" && rawPart.text.trim()) {
|
|
298
|
+
active.activities.push({ sourceId, timestamp: time, tone: "info", kind: "reasoning.summary", summary: "Reasoning", payload: { data: { item: { text: rawPart.text } } } });
|
|
299
|
+
}
|
|
300
|
+
else if (rawPart.type === "tool") {
|
|
301
|
+
const state = isObject(rawPart.state) ? rawPart.state : {};
|
|
302
|
+
const name = stringValue(rawPart.name) ?? "Tool";
|
|
303
|
+
const failed = state.status === "error";
|
|
304
|
+
const output = toolOutput(state);
|
|
305
|
+
const detail = typeof output === "string" ? output : contentText(output);
|
|
306
|
+
const toolId = stringValue(rawPart.id) ?? sourceId;
|
|
307
|
+
active.activities.push({
|
|
308
|
+
sourceId: toolId,
|
|
309
|
+
timestamp: time,
|
|
310
|
+
tone: failed ? "error" : "tool",
|
|
311
|
+
kind: "tool.completed",
|
|
312
|
+
summary: truncate(name, 120),
|
|
313
|
+
payload: {
|
|
314
|
+
itemType: "dynamic_tool_call",
|
|
315
|
+
status: failed ? "failed" : state.status === "completed" ? "completed" : "inProgress",
|
|
316
|
+
title: name,
|
|
317
|
+
...(detail ? { detail: truncate(detail) } : {}),
|
|
318
|
+
data: { toolCallId: toolId, item: { name, input: state.input, output } },
|
|
319
|
+
},
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
if (textParts.length)
|
|
324
|
+
active.assistant.push({ sourceId: row.id, role: "assistant", text: textParts.join("\n"), timestamp: time, attachments: [] });
|
|
325
|
+
if (data.error !== undefined || data.finish === "error") {
|
|
326
|
+
const error = isObject(data.error)
|
|
327
|
+
? stringValue(data.error.message) ?? stringValue(data.error.name) ?? "OpenCode reported an error"
|
|
328
|
+
: stringValue(data.error) ?? "OpenCode reported an error";
|
|
329
|
+
active.providerErrors.push(error);
|
|
330
|
+
active.activities.push({ sourceId: `${row.id}:provider-error`, timestamp: time, tone: "error", kind: "provider.error", summary: "OpenCode provider error", payload: { detail: error, retryable: true } });
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
else if (row.type === "idle") {
|
|
334
|
+
if (!active)
|
|
335
|
+
continue;
|
|
336
|
+
const outcome = stringValue(data.outcome) ?? session.idle_outcome ?? "succeeded";
|
|
337
|
+
const status = outcome === "succeeded" ? "completed" : outcome === "failed" || outcome === "error" ? "failed" : "interrupted";
|
|
338
|
+
settle(status, time, outcome, status === "failed" && !active.providerErrors.length ? "OpenCode turn ended with an error" : undefined);
|
|
339
|
+
}
|
|
340
|
+
else if (row.type === "system" || row.type === "synthetic") {
|
|
341
|
+
warnings.push(`OpenCode ${row.type} message ${row.id} was retained in the original provider store and omitted from the visible transcript.`);
|
|
342
|
+
}
|
|
343
|
+
else {
|
|
344
|
+
warnings.push(`OpenCode message ${row.id} has unsupported type ${row.type}; it remains in the provider store and was omitted from the visible transcript.`);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
if (active)
|
|
348
|
+
ignored += 1;
|
|
349
|
+
ignored += pending.length;
|
|
350
|
+
if (!includeIncomplete && pending.some((incomplete) => turns.some((turn) => turn.sequence > incomplete.sequence))) {
|
|
351
|
+
throw sourceError(`OpenCode session ${session.id} has an incomplete user message before a later settled turn; reload with incomplete turns included to preserve the conversation history`);
|
|
352
|
+
}
|
|
353
|
+
const canonicalTurns = [
|
|
354
|
+
...turns.filter((turn) => includeIncomplete || turn.status !== "inProgress"),
|
|
355
|
+
...(includeIncomplete ? pending : []),
|
|
356
|
+
...(includeIncomplete && active ? [active] : []),
|
|
357
|
+
].sort((left, right) => left.sequence - right.sequence).map(toTurn);
|
|
358
|
+
if (!canonicalTurns.length && !active)
|
|
359
|
+
throw sourceError(`OpenCode session ${session.id} contains no importable turns`);
|
|
360
|
+
const firstTime = canonicalTurns[0]?.startedAt ?? pending[0]?.startedAt ?? active?.startedAt ?? fallback;
|
|
361
|
+
const lastTurn = canonicalTurns.at(-1);
|
|
362
|
+
const title = stringValue(session.title) ?? deriveTitle(canonicalTurns[0]?.user.text ?? active?.user.text ?? "");
|
|
363
|
+
const digest = createHash("sha256");
|
|
364
|
+
for (const row of rows)
|
|
365
|
+
digest.update(`${row.seq}\0${row.id}\0${row.type}\0${row.time_updated}\0${row.data}\n`);
|
|
366
|
+
const thread = {
|
|
367
|
+
source: "opencode",
|
|
368
|
+
sourceSessionId: session.id,
|
|
369
|
+
sourceKey: `opencode:${session.id}`,
|
|
370
|
+
currentBranch: true,
|
|
371
|
+
title,
|
|
372
|
+
workspace: session.directory,
|
|
373
|
+
model,
|
|
374
|
+
...(modelVariant ? { modelOptions: [{ id: "variant", value: modelVariant }] } : {}),
|
|
375
|
+
createdAt: firstTime,
|
|
376
|
+
updatedAt: lastTurn?.completedAt ?? lastTurn?.assistant.at(-1)?.timestamp ?? active?.assistant.at(-1)?.timestamp ?? active?.user.timestamp ?? timestamp(session.time_updated, fallback),
|
|
377
|
+
turns: canonicalTurns,
|
|
378
|
+
ignoredInProgressTurns: ignored,
|
|
379
|
+
...(turns.length ? { resumeCursor: { sessionId: session.id, headMessageId: turns.at(-1).user.sourceId } } : {}),
|
|
380
|
+
warnings: [...warnings, ...(session.fork_session_id ? ["OpenCode fork session; new prompts resume this fork session."] : [])],
|
|
381
|
+
};
|
|
382
|
+
return { thread, ignored, fingerprint: digest.digest("hex") };
|
|
383
|
+
}
|
|
384
|
+
export class OpenCodeSource {
|
|
385
|
+
name = "opencode";
|
|
386
|
+
async discover(options) {
|
|
387
|
+
const path = databasePath();
|
|
388
|
+
return readSnapshot(path, (db) => {
|
|
389
|
+
const summaries = [];
|
|
390
|
+
for (const session of sessionQuery(db)) {
|
|
391
|
+
if (!/^2\./u.test(session.version))
|
|
392
|
+
throw sourceError(`OpenCode session ${session.id} was created by unsupported version ${session.version}; this reader supports OpenCode 2.x sessions`);
|
|
393
|
+
if (session.time_archived != null)
|
|
394
|
+
continue;
|
|
395
|
+
if (session.parent_id)
|
|
396
|
+
continue;
|
|
397
|
+
if (options.workspace && canonicalPath(session.directory) !== canonicalPath(options.workspace))
|
|
398
|
+
continue;
|
|
399
|
+
const createdAt = timestamp(session.time_created, new Date(0).toISOString());
|
|
400
|
+
const updatedAt = timestamp(session.time_updated, createdAt);
|
|
401
|
+
if (options.since && new Date(updatedAt) < options.since)
|
|
402
|
+
continue;
|
|
403
|
+
const rows = messagesQuery(db, session.id);
|
|
404
|
+
const incomplete = rows.at(-1)?.type !== "idle";
|
|
405
|
+
summaries.push({
|
|
406
|
+
source: "opencode",
|
|
407
|
+
id: session.id,
|
|
408
|
+
title: stringValue(session.title) ?? "OpenCode conversation",
|
|
409
|
+
workspace: session.directory,
|
|
410
|
+
path: path,
|
|
411
|
+
createdAt,
|
|
412
|
+
updatedAt,
|
|
413
|
+
status: incomplete ? "incomplete" : "complete",
|
|
414
|
+
branches: 1,
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
return summaries;
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
async load(summary, options) {
|
|
421
|
+
const path = summary.path || databasePath();
|
|
422
|
+
return readSnapshot(path, (db) => {
|
|
423
|
+
const session = sessionQuery(db, summary.id)[0];
|
|
424
|
+
if (!session)
|
|
425
|
+
throw sourceError(`OpenCode session ${summary.id} was not found`);
|
|
426
|
+
if (session.parent_id && !summary.parentId)
|
|
427
|
+
throw sourceError(`OpenCode session ${summary.id} is a child session and was not selected explicitly`);
|
|
428
|
+
const rows = messagesQuery(db, session.id);
|
|
429
|
+
if (!rows.length)
|
|
430
|
+
throw sourceError(`OpenCode session ${session.id} has no messages`);
|
|
431
|
+
const parsed = parseThread(session, rows, options.includeIncomplete ?? false);
|
|
432
|
+
const thread = parsed.thread;
|
|
433
|
+
const visibleTurns = options.includeIncomplete ? thread.turns : thread.turns.filter((turn) => turn.status !== "inProgress");
|
|
434
|
+
thread.turns = visibleTurns;
|
|
435
|
+
return {
|
|
436
|
+
summary: { ...summary, title: thread.title, status: parsed.ignored ? "incomplete" : "complete" },
|
|
437
|
+
threads: [thread],
|
|
438
|
+
fingerprint: parsed.fingerprint,
|
|
439
|
+
};
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
//# sourceMappingURL=opencode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opencode.js","sourceRoot":"","sources":["../../src/sources/opencode.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { CacheResetResult, TargetPaths } from "../core/types.js";
|
|
2
|
+
export interface CacheDiscoveryOptions {
|
|
3
|
+
environment?: NodeJS.ProcessEnv;
|
|
4
|
+
platform?: NodeJS.Platform;
|
|
5
|
+
userHome?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface T3CacheProfile {
|
|
8
|
+
profilePath: string;
|
|
9
|
+
cachePaths: string[];
|
|
10
|
+
modifiedAt: number;
|
|
11
|
+
}
|
|
12
|
+
export declare function formatCacheResetResult(result: CacheResetResult): string;
|
|
13
|
+
export declare function discoverT3CacheProfiles(options?: CacheDiscoveryOptions): T3CacheProfile[];
|
|
14
|
+
export declare function resetT3RebuildableCache(paths: TargetPaths, options?: CacheDiscoveryOptions): Promise<CacheResetResult>;
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
2
|
+
import { cpSync, existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, } from "node:fs";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { basename, join, resolve } from "node:path";
|
|
5
|
+
import { safetyError, writeError } from "../core/errors.js";
|
|
6
|
+
import { assertT3Closed } from "./schema.js";
|
|
7
|
+
const PROFILE_NAMES = ["T3 Code (Alpha)", "T3 Code (Nightly)", "T3 Code", "t3code"];
|
|
8
|
+
const CACHE_NAMES = ["t3code_app_0.indexeddb.leveldb", "t3code_app_0.indexeddb.blob"];
|
|
9
|
+
export function formatCacheResetResult(result) {
|
|
10
|
+
if (result.status === "not-found") {
|
|
11
|
+
return "No T3 IndexedDB cache was found. Nothing was changed.";
|
|
12
|
+
}
|
|
13
|
+
return [
|
|
14
|
+
"T3 IndexedDB cache reset successfully.",
|
|
15
|
+
`Profile: ${result.profile}`,
|
|
16
|
+
`Backup: ${result.backup}`,
|
|
17
|
+
`Entries removed: ${result.entries.length}`,
|
|
18
|
+
...result.entries.map((entry) => ` - ${entry}`),
|
|
19
|
+
...result.warnings.map((warning) => `Warning: ${warning}`),
|
|
20
|
+
].join("\n");
|
|
21
|
+
}
|
|
22
|
+
function profileBase(environment, platform, userHome) {
|
|
23
|
+
if (platform === "win32")
|
|
24
|
+
return environment.APPDATA;
|
|
25
|
+
if (platform === "darwin")
|
|
26
|
+
return join(userHome, "Library", "Application Support");
|
|
27
|
+
return environment.XDG_CONFIG_HOME?.trim() || join(userHome, ".config");
|
|
28
|
+
}
|
|
29
|
+
function newestModification(path) {
|
|
30
|
+
if (!existsSync(path))
|
|
31
|
+
return 0;
|
|
32
|
+
const details = lstatSync(path);
|
|
33
|
+
if (!details.isDirectory())
|
|
34
|
+
return details.mtimeMs;
|
|
35
|
+
let newest = details.mtimeMs;
|
|
36
|
+
for (const name of readdirSync(path))
|
|
37
|
+
newest = Math.max(newest, newestModification(join(path, name)));
|
|
38
|
+
return newest;
|
|
39
|
+
}
|
|
40
|
+
export function discoverT3CacheProfiles(options = {}) {
|
|
41
|
+
const environment = options.environment ?? process.env;
|
|
42
|
+
const platform = options.platform ?? process.platform;
|
|
43
|
+
const userHome = options.userHome ?? homedir();
|
|
44
|
+
const override = environment.T3_CODE_USER_DATA?.trim();
|
|
45
|
+
const base = profileBase(environment, platform, userHome);
|
|
46
|
+
const candidates = override
|
|
47
|
+
? [resolve(override)]
|
|
48
|
+
: base
|
|
49
|
+
? PROFILE_NAMES.map((name) => join(base, name))
|
|
50
|
+
: [];
|
|
51
|
+
return candidates.flatMap((profilePath) => {
|
|
52
|
+
const indexedDb = join(profilePath, "IndexedDB");
|
|
53
|
+
const cachePaths = CACHE_NAMES.map((name) => join(indexedDb, name)).filter(existsSync);
|
|
54
|
+
if (cachePaths.length === 0)
|
|
55
|
+
return [];
|
|
56
|
+
return [{
|
|
57
|
+
profilePath,
|
|
58
|
+
cachePaths,
|
|
59
|
+
modifiedAt: Math.max(...cachePaths.map(newestModification)),
|
|
60
|
+
}];
|
|
61
|
+
}).sort((left, right) => right.modifiedAt - left.modifiedAt);
|
|
62
|
+
}
|
|
63
|
+
function files(path, root = path) {
|
|
64
|
+
const details = lstatSync(path);
|
|
65
|
+
if (details.isSymbolicLink())
|
|
66
|
+
throw writeError(`Refusing to back up a symbolic link in the T3 cache: ${path}`);
|
|
67
|
+
if (details.isFile()) {
|
|
68
|
+
return [{
|
|
69
|
+
relative: path.slice(root.length).replace(/^[/\\]+/u, ""),
|
|
70
|
+
hash: createHash("sha256").update(readFileSync(path)).digest("hex"),
|
|
71
|
+
size: details.size,
|
|
72
|
+
}];
|
|
73
|
+
}
|
|
74
|
+
return readdirSync(path).flatMap((name) => files(join(path, name), root));
|
|
75
|
+
}
|
|
76
|
+
function verifiedCopy(source, destination) {
|
|
77
|
+
cpSync(source, destination, { recursive: true, errorOnExist: true, force: false });
|
|
78
|
+
const sourceFiles = files(source).sort((a, b) => a.relative.localeCompare(b.relative));
|
|
79
|
+
const destinationFiles = files(destination).sort((a, b) => a.relative.localeCompare(b.relative));
|
|
80
|
+
if (JSON.stringify(sourceFiles) !== JSON.stringify(destinationFiles)) {
|
|
81
|
+
throw writeError(`T3 cache backup verification failed: ${destination}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function restoreMoved(staging, indexedDb, names) {
|
|
85
|
+
for (const name of [...names].reverse()) {
|
|
86
|
+
const staged = join(staging, name);
|
|
87
|
+
const original = join(indexedDb, name);
|
|
88
|
+
if (!existsSync(staged))
|
|
89
|
+
continue;
|
|
90
|
+
if (existsSync(original))
|
|
91
|
+
rmSync(original, { recursive: true, force: true });
|
|
92
|
+
renameSync(staged, original);
|
|
93
|
+
}
|
|
94
|
+
rmSync(staging, { recursive: true, force: true });
|
|
95
|
+
}
|
|
96
|
+
export async function resetT3RebuildableCache(paths, options = {}) {
|
|
97
|
+
await assertT3Closed(paths);
|
|
98
|
+
const profiles = discoverT3CacheProfiles(options);
|
|
99
|
+
if (profiles.length === 0) {
|
|
100
|
+
return { status: "not-found", backup: null, profile: null, entries: [], warnings: [] };
|
|
101
|
+
}
|
|
102
|
+
const profile = profiles[0];
|
|
103
|
+
const indexedDb = join(profile.profilePath, "IndexedDB");
|
|
104
|
+
const resolvedIndexedDb = resolve(indexedDb);
|
|
105
|
+
const entryNames = profile.cachePaths.map((cachePath) => basename(cachePath));
|
|
106
|
+
for (const cachePath of profile.cachePaths) {
|
|
107
|
+
const resolvedCache = resolve(cachePath);
|
|
108
|
+
if (!resolvedCache.startsWith(`${resolvedIndexedDb}${process.platform === "win32" ? "\\" : "/"}`)) {
|
|
109
|
+
throw safetyError(`Refusing to reset a cache outside T3's IndexedDB directory: ${cachePath}`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
const stamp = new Date().toISOString().replace(/[:.]/gu, "-");
|
|
113
|
+
const backup = join(paths.stateDir, "t3-import-backups", `indexeddb-before-cache-reset-${stamp}`);
|
|
114
|
+
const backupProfile = join(backup, basename(profile.profilePath));
|
|
115
|
+
const staging = join(profile.profilePath, `.t3-import-cache-reset-${randomUUID()}`);
|
|
116
|
+
mkdirSync(staging, { recursive: false });
|
|
117
|
+
const moved = [];
|
|
118
|
+
try {
|
|
119
|
+
for (const cachePath of profile.cachePaths) {
|
|
120
|
+
const name = basename(cachePath);
|
|
121
|
+
renameSync(cachePath, join(staging, name));
|
|
122
|
+
moved.push(name);
|
|
123
|
+
}
|
|
124
|
+
mkdirSync(backupProfile, { recursive: true });
|
|
125
|
+
for (const name of moved)
|
|
126
|
+
verifiedCopy(join(staging, name), join(backupProfile, name));
|
|
127
|
+
rmSync(staging, { recursive: true, force: true });
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
let restoreError;
|
|
131
|
+
try {
|
|
132
|
+
restoreMoved(staging, indexedDb, moved);
|
|
133
|
+
}
|
|
134
|
+
catch (cause) {
|
|
135
|
+
restoreError = cause;
|
|
136
|
+
}
|
|
137
|
+
if (!restoreError)
|
|
138
|
+
rmSync(backup, { recursive: true, force: true });
|
|
139
|
+
const detail = restoreError
|
|
140
|
+
? ` Cache restoration also failed; recovery files were preserved at ${existsSync(backup) ? backup : staging}.`
|
|
141
|
+
: "";
|
|
142
|
+
throw writeError(`Unable to reset T3's IndexedDB cache: ${error instanceof Error ? error.message : String(error)}.${detail}`, error);
|
|
143
|
+
}
|
|
144
|
+
const warnings = profiles.length > 1
|
|
145
|
+
? [`Reset the most recently used T3 profile; ${profiles.length - 1} older profile cache${profiles.length === 2 ? " was" : "s were"} left untouched.`]
|
|
146
|
+
: [];
|
|
147
|
+
return {
|
|
148
|
+
status: "reset",
|
|
149
|
+
backup,
|
|
150
|
+
profile: profile.profilePath,
|
|
151
|
+
entries: entryNames,
|
|
152
|
+
warnings,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=cache.js.map
|