sessiongraph-app-darwin-x64 1.0.6 → 1.0.7
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/package.json +2 -2
- package/payload/SessionGraph.app/Contents/Info.plist +2 -2
- package/payload/SessionGraph.app/Contents/MacOS/sessiongraph +0 -0
- package/payload/SessionGraph.app/Contents/Resources/resources/server.mjs +284 -107
- package/payload/SessionGraph.app/Contents/Resources/resources/web/assets/{index-3_I59bPI.js → index-CQQQn4As.js} +1 -1
- package/payload/SessionGraph.app/Contents/Resources/resources/web/assets/{index-DxQk-77k.js → index-CSlKklgv.js} +1 -1
- package/payload/SessionGraph.app/Contents/Resources/resources/web/assets/{index-BEabiGl5.js → index-iA3u_0lX.js} +13 -13
- package/payload/SessionGraph.app/Contents/Resources/resources/web/assets/{index-86i6pjnx.js → index-x7CFY4c0.js} +1 -1
- package/payload/SessionGraph.app/Contents/Resources/resources/web/assets/{scene-CEalI0mr.js → scene-BGmgWBAw.js} +1 -1
- package/payload/SessionGraph.app/Contents/Resources/resources/web/assets/{share-BydK_UaB.js → share-CLYxMZI8.js} +3 -3
- package/payload/SessionGraph.app/Contents/Resources/resources/web/index.html +1 -1
- package/payload/SessionGraph.app/Contents/_CodeSignature/CodeResources +32 -32
|
@@ -2138,7 +2138,7 @@ var init_promise = __esm({
|
|
|
2138
2138
|
import { createServer } from "node:http";
|
|
2139
2139
|
import { createReadStream } from "node:fs";
|
|
2140
2140
|
import { stat as stat5 } from "node:fs/promises";
|
|
2141
|
-
import { fileURLToPath as
|
|
2141
|
+
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
2142
2142
|
import { resolve as resolve2, extname, sep as sep4 } from "node:path";
|
|
2143
2143
|
import { randomBytes, timingSafeEqual } from "node:crypto";
|
|
2144
2144
|
|
|
@@ -30531,10 +30531,10 @@ async function fileState(path) {
|
|
|
30531
30531
|
throw error;
|
|
30532
30532
|
}
|
|
30533
30533
|
}
|
|
30534
|
-
async function historyFiles(
|
|
30534
|
+
async function historyFiles(roots2, match2) {
|
|
30535
30535
|
const files = [], queue = [];
|
|
30536
30536
|
const warnings = [];
|
|
30537
|
-
for (const root3 of new Set(
|
|
30537
|
+
for (const root3 of new Set(roots2)) {
|
|
30538
30538
|
try {
|
|
30539
30539
|
if ((await lstat2(root3)).isDirectory()) queue.push({ root: root3, path: root3, depth: 0 });
|
|
30540
30540
|
} catch (error) {
|
|
@@ -30561,7 +30561,7 @@ async function historyFiles(roots, match) {
|
|
|
30561
30561
|
if (depth < 6 && queue.length < MAX_FILES) queue.push({ root: root3, path: file, depth: depth + 1 });
|
|
30562
30562
|
else limited = true;
|
|
30563
30563
|
}
|
|
30564
|
-
if (entry.isFile() &&
|
|
30564
|
+
if (entry.isFile() && match2(relative(root3, file).split("\\").join("/"))) files.push(file);
|
|
30565
30565
|
}
|
|
30566
30566
|
}
|
|
30567
30567
|
if (limited) warnings.push("History discovery reached its file, directory, or depth limit.");
|
|
@@ -30639,6 +30639,7 @@ function localFileAdapter(source) {
|
|
|
30639
30639
|
async discover() {
|
|
30640
30640
|
const listing = await historyFiles(source.roots(), source.match), found = /* @__PURE__ */ new Map();
|
|
30641
30641
|
let failed = 0;
|
|
30642
|
+
const blocked = /* @__PURE__ */ new Set();
|
|
30642
30643
|
for (const path of listing.files) {
|
|
30643
30644
|
try {
|
|
30644
30645
|
const before = await states(path), rev = revision2(before);
|
|
@@ -30666,16 +30667,18 @@ function localFileAdapter(source) {
|
|
|
30666
30667
|
if (!previous || preferred && !previousPreferred || preferred === previousPreferred && candidate.session.updated > previous.session.updated) found.set(candidate.session.id, candidate);
|
|
30667
30668
|
} catch {
|
|
30668
30669
|
failed++;
|
|
30670
|
+
const nativeID = source.authoritativeIdentity?.(path);
|
|
30671
|
+
if (nativeID) blocked.add(identity(source.id, nativeID));
|
|
30669
30672
|
}
|
|
30670
30673
|
}
|
|
30671
30674
|
const listed = new Set(listing.files);
|
|
30672
30675
|
for (const path of metadata2.keys()) if (!listed.has(path)) metadata2.delete(path);
|
|
30673
30676
|
if (failed) listing.warnings.push(`${failed} ${source.name} histories were unreadable, changing, unsupported, or over the size limit. Saved imports are kept.`);
|
|
30674
|
-
const sessions = [...found.values()];
|
|
30677
|
+
const sessions = [...found.values()].filter((c) => !blocked.has(c.session.id));
|
|
30675
30678
|
return { sessions, projects: [...new Map(sessions.map((c) => {
|
|
30676
30679
|
const p = project(source.id, c.session.directory);
|
|
30677
30680
|
return [p.id, p];
|
|
30678
|
-
})).values()], warnings: listing.warnings };
|
|
30681
|
+
})).values()], warnings: listing.warnings, blocked: [...blocked] };
|
|
30679
30682
|
},
|
|
30680
30683
|
async read(candidate, cursor) {
|
|
30681
30684
|
const offset = cursor === void 0 ? 0 : Number(cursor);
|
|
@@ -31450,7 +31453,7 @@ async function readJSONL(path, offset = 0, budget2 = 2e6, limit = 200) {
|
|
|
31450
31453
|
await file.close();
|
|
31451
31454
|
}
|
|
31452
31455
|
}
|
|
31453
|
-
async function transcriptFiles(root3, max = 2e4,
|
|
31456
|
+
async function transcriptFiles(root3, max = 2e4, match2 = (name) => name.endsWith(".jsonl")) {
|
|
31454
31457
|
const files = [], queue = [root3];
|
|
31455
31458
|
for (let i = 0; i < queue.length && files.length < max; i++) {
|
|
31456
31459
|
let entries2;
|
|
@@ -31462,7 +31465,7 @@ async function transcriptFiles(root3, max = 2e4, match = (name) => name.endsWith
|
|
|
31462
31465
|
}
|
|
31463
31466
|
for (const entry of entries2) {
|
|
31464
31467
|
if (entry.isDirectory() && queue.length < 2e4) queue.push(join9(queue[i], entry.name));
|
|
31465
|
-
if (entry.isFile() &&
|
|
31468
|
+
if (entry.isFile() && match2(entry.name)) files.push(join9(queue[i], entry.name));
|
|
31466
31469
|
if (files.length >= max) break;
|
|
31467
31470
|
}
|
|
31468
31471
|
}
|
|
@@ -31570,8 +31573,8 @@ var codexAdapter = {
|
|
|
31570
31573
|
async discover() {
|
|
31571
31574
|
const found = /* @__PURE__ */ new Map(), warnings = [];
|
|
31572
31575
|
const names = await sessionNames();
|
|
31573
|
-
const
|
|
31574
|
-
const paths = [...await transcriptFiles(join10(root2(), "sessions"), 2e4,
|
|
31576
|
+
const match2 = (name) => /\.jsonl(?:\.[\w.-]+)?$/.test(name);
|
|
31577
|
+
const paths = [...await transcriptFiles(join10(root2(), "sessions"), 2e4, match2), ...await transcriptFiles(join10(root2(), "archived_sessions"), 2e4, match2)];
|
|
31575
31578
|
if (paths.length >= 2e4) warnings.push("Codex transcript listing may be partial (20,000 files per history folder).");
|
|
31576
31579
|
let unsupported = 0;
|
|
31577
31580
|
for (const path of paths) {
|
|
@@ -31670,14 +31673,14 @@ function batches(values, size = 500) {
|
|
|
31670
31673
|
return result;
|
|
31671
31674
|
}
|
|
31672
31675
|
function projectRoots(db2, ids) {
|
|
31673
|
-
const
|
|
31674
|
-
if (!hasTable(db2, "projection_projects")) return
|
|
31676
|
+
const roots2 = /* @__PURE__ */ new Map();
|
|
31677
|
+
if (!hasTable(db2, "projection_projects")) return roots2;
|
|
31675
31678
|
for (const batch of batches([...new Set(ids.filter(Boolean))])) {
|
|
31676
31679
|
const placeholders = batch.map(() => "?").join(",");
|
|
31677
31680
|
for (const row of db2.prepare(`SELECT project_id, substr(workspace_root,1,4096) AS workspace_root FROM projection_projects WHERE deleted_at IS NULL AND project_id IN (${placeholders})`).all(...batch))
|
|
31678
|
-
|
|
31681
|
+
roots2.set(string(row.project_id), string(row.workspace_root));
|
|
31679
31682
|
}
|
|
31680
|
-
return
|
|
31683
|
+
return roots2;
|
|
31681
31684
|
}
|
|
31682
31685
|
function aggregates(db2, table, ids) {
|
|
31683
31686
|
const result = /* @__PURE__ */ new Map();
|
|
@@ -31718,7 +31721,7 @@ function discoverV2(db2, path, databaseRevision) {
|
|
|
31718
31721
|
json_valid(payload_json) AS valid_payload
|
|
31719
31722
|
FROM orchestration_v2_projection_threads WHERE deleted_at IS NULL ORDER BY created_at, thread_id LIMIT ?`).all(MAX_THREADS + 1);
|
|
31720
31723
|
const selected = rows2.slice(0, MAX_THREADS), ids = selected.map((row) => string(row.thread_id));
|
|
31721
|
-
const
|
|
31724
|
+
const roots2 = projectRoots(db2, selected.map((row) => string(row.project_id)));
|
|
31722
31725
|
const counts = aggregates(db2, "orchestration_v2_projection_messages", ids);
|
|
31723
31726
|
const items = aggregates(db2, "orchestration_v2_projection_turn_items", ids);
|
|
31724
31727
|
const links = linkedSessions(db2, ids);
|
|
@@ -31729,7 +31732,7 @@ function discoverV2(db2, path, databaseRevision) {
|
|
|
31729
31732
|
const nativeID = string(row.thread_id), created = time2(row.created_at);
|
|
31730
31733
|
if (!nativeID || nativeID.length > 512 || !created) continue;
|
|
31731
31734
|
if (!row.valid_payload) unreadableMetadata++;
|
|
31732
|
-
const directory2 = string(row.worktree_path) ||
|
|
31735
|
+
const directory2 = string(row.worktree_path) || roots2.get(string(row.project_id)) || "";
|
|
31733
31736
|
const p = project(SOURCE, directory2);
|
|
31734
31737
|
projects.set(p.id, p);
|
|
31735
31738
|
const session = blankSession(SOURCE, nativeID, directory2);
|
|
@@ -31760,13 +31763,13 @@ function discoverV1(db2, path, databaseRevision) {
|
|
|
31760
31763
|
CASE WHEN json_valid(model_selection_json) THEN substr(json_extract(model_selection_json,'$.model'),1,200) END AS model
|
|
31761
31764
|
FROM projection_threads WHERE deleted_at IS NULL ORDER BY created_at, thread_id LIMIT ?`).all(MAX_THREADS + 1);
|
|
31762
31765
|
const selected = rows2.slice(0, MAX_THREADS);
|
|
31763
|
-
const
|
|
31766
|
+
const roots2 = projectRoots(db2, selected.map((row) => string(row.project_id)));
|
|
31764
31767
|
const counts = aggregates(db2, "projection_thread_messages", selected.map((row) => string(row.thread_id)));
|
|
31765
31768
|
const sessions = [], projects = /* @__PURE__ */ new Map();
|
|
31766
31769
|
for (const row of selected) {
|
|
31767
31770
|
const nativeID = string(row.thread_id), created = time2(row.created_at);
|
|
31768
31771
|
if (!nativeID || nativeID.length > 512 || !created) continue;
|
|
31769
|
-
const directory2 = string(row.worktree_path) ||
|
|
31772
|
+
const directory2 = string(row.worktree_path) || roots2.get(string(row.project_id)) || "";
|
|
31770
31773
|
const p = project(SOURCE, directory2);
|
|
31771
31774
|
projects.set(p.id, p);
|
|
31772
31775
|
const session = blankSession(SOURCE, nativeID, directory2);
|
|
@@ -31913,9 +31916,9 @@ function cursorEnvelopeTime(text2) {
|
|
|
31913
31916
|
if (!value) return 0;
|
|
31914
31917
|
const iso = cursorTime(value);
|
|
31915
31918
|
if (iso) return iso;
|
|
31916
|
-
const
|
|
31917
|
-
if (!
|
|
31918
|
-
return cursorTime(Date.parse(`${
|
|
31919
|
+
const match2 = value.match(/^(?:\w+, )?([A-Za-z]+ \d{1,2}, \d{4}), (\d{1,2}:\d{2}(?::\d{2})? [AP]M) \(UTC([+-])(\d{1,2})(?::(\d{2}))?\)$/);
|
|
31920
|
+
if (!match2 || Number(match2[4]) > 14 || Number(match2[5] || 0) > 59) return 0;
|
|
31921
|
+
return cursorTime(Date.parse(`${match2[1]} ${match2[2]} GMT${match2[3]}${match2[4].padStart(2, "0")}${match2[5] || "00"}`));
|
|
31919
31922
|
}
|
|
31920
31923
|
function cursorUserText(text2) {
|
|
31921
31924
|
let value = text2.trim().replace(/^<timestamp>[^<]+<\/timestamp>\s*/, "");
|
|
@@ -32354,7 +32357,7 @@ function createCursorAdapter(options = {}) {
|
|
|
32354
32357
|
}
|
|
32355
32358
|
}
|
|
32356
32359
|
const composers = new Map(found);
|
|
32357
|
-
const
|
|
32360
|
+
const match2 = (key, encode) => {
|
|
32358
32361
|
const matches = paths.filter((path) => encode(path) === key);
|
|
32359
32362
|
return matches.length === 1 ? matches[0] : "";
|
|
32360
32363
|
};
|
|
@@ -32429,7 +32432,7 @@ function createCursorAdapter(options = {}) {
|
|
|
32429
32432
|
const projects = join13(root3(), "projects");
|
|
32430
32433
|
for (const dir of await entries(projects, warnings)) {
|
|
32431
32434
|
if (!dir.isDirectory() || scanned >= LIMIT) continue;
|
|
32432
|
-
const transcripts = join13(projects, dir.name, "agent-transcripts"), directory2 =
|
|
32435
|
+
const transcripts = join13(projects, dir.name, "agent-transcripts"), directory2 = match2(dir.name, slug);
|
|
32433
32436
|
for (const entry of await entries(transcripts, warnings)) {
|
|
32434
32437
|
if (scanned >= LIMIT) break;
|
|
32435
32438
|
if (entry.isFile() && entry.name.endsWith(".jsonl")) await add(join13(transcripts, entry.name), entry.name.slice(0, -6), "transcript", directory2);
|
|
@@ -32446,7 +32449,7 @@ function createCursorAdapter(options = {}) {
|
|
|
32446
32449
|
const chats = join13(root3(), "chats");
|
|
32447
32450
|
for (const bucket of await entries(chats, warnings)) {
|
|
32448
32451
|
if (!bucket.isDirectory() || scanned >= LIMIT) continue;
|
|
32449
|
-
const folder = join13(chats, bucket.name), directory2 =
|
|
32452
|
+
const folder = join13(chats, bucket.name), directory2 = match2(bucket.name, hashCwd);
|
|
32450
32453
|
if (/^[a-f\d]{32}$/i.test(bucket.name) && await fileStats(join13(folder, "store.db"))) {
|
|
32451
32454
|
const id2 = bucket.name.replace(/^(.{8})(.{4})(.{4})(.{4})(.{12})$/, "$1-$2-$3-$4-$5");
|
|
32452
32455
|
await add(join13(folder, "store.db"), id2, "cli", "");
|
|
@@ -32695,31 +32698,205 @@ var copilotAdapter = localFileAdapter({
|
|
|
32695
32698
|
}
|
|
32696
32699
|
});
|
|
32697
32700
|
|
|
32698
|
-
// server/adapters/
|
|
32701
|
+
// server/adapters/copilot-chat.ts
|
|
32699
32702
|
import { homedir as homedir11 } from "node:os";
|
|
32700
|
-
import { basename as basename6, dirname as dirname4, join as join17 } from "node:path";
|
|
32703
|
+
import { basename as basename6, dirname as dirname4, join as join17, posix, win32 as win322 } from "node:path";
|
|
32704
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
32705
|
+
|
|
32706
|
+
// server/adapters/vscode-chat-log.ts
|
|
32707
|
+
function vscodeChatLog(content) {
|
|
32708
|
+
let state2, records = 0;
|
|
32709
|
+
for (const line of content.split("\n")) {
|
|
32710
|
+
if (!line.trim()) continue;
|
|
32711
|
+
if (++records > 5e4) throw new Error("Chat log exceeds the 50,000-operation limit.");
|
|
32712
|
+
const entry = object(JSON.parse(line));
|
|
32713
|
+
if (entry.kind === 0) {
|
|
32714
|
+
if (records !== 1 || !entry.v || typeof entry.v !== "object" || Array.isArray(entry.v)) throw new Error("Invalid chat log initial state.");
|
|
32715
|
+
state2 = entry.v;
|
|
32716
|
+
continue;
|
|
32717
|
+
}
|
|
32718
|
+
if (!state2 || ![1, 2, 3].includes(entry.kind) || !Array.isArray(entry.k) || !entry.k.length || entry.k.length > 64) throw new Error("Unsupported chat log operation.");
|
|
32719
|
+
let target = state2;
|
|
32720
|
+
for (const [index, key] of entry.k.entries()) {
|
|
32721
|
+
if (typeof key !== "string" && typeof key !== "number" || ["__proto__", "prototype", "constructor"].includes(String(key))) throw new Error("Unsafe chat log path.");
|
|
32722
|
+
if (!target || typeof target !== "object") throw new Error("Missing chat log path.");
|
|
32723
|
+
if (Array.isArray(target) && (typeof key !== "number" || !Number.isSafeInteger(key) || key < 0 || key > target.length || key >= 5e4)) throw new Error("Invalid chat log array index.");
|
|
32724
|
+
if (index < entry.k.length - 1) {
|
|
32725
|
+
if (!Object.hasOwn(target, key)) throw new Error("Missing chat log path.");
|
|
32726
|
+
target = target[key];
|
|
32727
|
+
} else if (entry.kind === 1) {
|
|
32728
|
+
target[key] = entry.v;
|
|
32729
|
+
} else if (entry.kind === 3) {
|
|
32730
|
+
delete target[key];
|
|
32731
|
+
} else {
|
|
32732
|
+
const values = Object.hasOwn(target, key) ? target[key] : void 0;
|
|
32733
|
+
if (values != null && !Array.isArray(values) || entry.v !== void 0 && !Array.isArray(entry.v)) throw new Error("Invalid chat log array.");
|
|
32734
|
+
const array = values ?? [];
|
|
32735
|
+
if (entry.i !== void 0) {
|
|
32736
|
+
if (!Number.isSafeInteger(entry.i) || entry.i < 0 || entry.i > array.length) throw new Error("Invalid chat log splice.");
|
|
32737
|
+
array.length = entry.i;
|
|
32738
|
+
}
|
|
32739
|
+
if (array.length + (entry.v?.length || 0) > 5e4) throw new Error("Chat log array exceeds its limit.");
|
|
32740
|
+
for (const value of entry.v || []) array.push(value);
|
|
32741
|
+
target[key] = array;
|
|
32742
|
+
}
|
|
32743
|
+
}
|
|
32744
|
+
}
|
|
32745
|
+
if (!state2) throw new Error("Chat log is missing its initial state.");
|
|
32746
|
+
return state2;
|
|
32747
|
+
}
|
|
32748
|
+
|
|
32749
|
+
// server/adapters/copilot-chat.ts
|
|
32750
|
+
function copilotChatRoots(platform = process.platform, home = homedir11(), env = process.env) {
|
|
32751
|
+
const path = platform === "win32" ? win322 : posix;
|
|
32752
|
+
const base = platform === "darwin" ? path.join(home, "Library", "Application Support") : platform === "win32" ? env.APPDATA || path.join(home, "AppData", "Roaming") : env.XDG_CONFIG_HOME || path.join(home, ".config");
|
|
32753
|
+
const users = env.SESSIONGRAPH_COPILOT_CHAT_USER_DATA_DIR ? [path.join(env.SESSIONGRAPH_COPILOT_CHAT_USER_DATA_DIR, "User")] : [...["Code", "Code - Insiders"].map((app) => path.join(base, app, "User")), ...[".vscode-server", ".vscode-server-insiders"].map((app) => path.join(home, app, "data", "User"))];
|
|
32754
|
+
return users.flatMap((user) => [path.join(user, "workspaceStorage"), path.join(user, "globalStorage", "emptyWindowChatSessions")]);
|
|
32755
|
+
}
|
|
32756
|
+
function vscodeChatPath(value) {
|
|
32757
|
+
const raw = object(value);
|
|
32758
|
+
if (raw.scheme) {
|
|
32759
|
+
if (raw.scheme !== "file") return `${text(raw.scheme)}://${text(raw.authority)}${text(raw.path)}`;
|
|
32760
|
+
const path = text(raw.path);
|
|
32761
|
+
return raw.authority ? `\\\\${raw.authority}${path.replace(/\//g, "\\")}` : /^\/[a-z]:\//i.test(path) ? path.slice(1).replace(/\//g, "\\") : path;
|
|
32762
|
+
}
|
|
32763
|
+
const uri = text(value);
|
|
32764
|
+
if (!uri.startsWith("file:")) return uri;
|
|
32765
|
+
try {
|
|
32766
|
+
const url = new URL(uri);
|
|
32767
|
+
return fileURLToPath3(url, { windows: Boolean(url.hostname && url.hostname !== "localhost") || /^\/[a-z]:/i.test(decodeURIComponent(url.pathname)) });
|
|
32768
|
+
} catch {
|
|
32769
|
+
return "";
|
|
32770
|
+
}
|
|
32771
|
+
}
|
|
32772
|
+
var markdown = (value) => typeof value === "string" ? value : text(object(value).value);
|
|
32773
|
+
var recordedTime = (value) => ({ time: time(value) || null, timeSource: time(value) ? "recorded" : "unknown" });
|
|
32774
|
+
function responsePart(message2, value, index) {
|
|
32775
|
+
const part = object(value), kind = text(part.kind), id2 = `part:${index}`;
|
|
32776
|
+
const fields2 = { nativeType: kind || "markdown", nativeID: text(part.id) || void 0 };
|
|
32777
|
+
if (typeof value === "string" || !kind && typeof part.value === "string" || kind === "markdownContent" || kind === "markdownVuln") {
|
|
32778
|
+
const content = markdown(kind ? part.content : value);
|
|
32779
|
+
message2.events.push(eventFor(message2, id2, "message", "Assistant message", content, fields2));
|
|
32780
|
+
addText(message2, content, "Assistant");
|
|
32781
|
+
} else if (kind === "thinking") {
|
|
32782
|
+
const content = Array.isArray(part.value) ? part.value.filter((v3) => typeof v3 === "string").join("\n") : markdown(part.value);
|
|
32783
|
+
message2.events.push(eventFor(message2, id2, "reasoning", "Recorded reasoning", content, { ...fields2, ...recordedTime(part.reasoningStartedAt) }));
|
|
32784
|
+
addText(message2, content, "Tool");
|
|
32785
|
+
} else if (kind === "toolInvocationSerialized") {
|
|
32786
|
+
const data = object(part.toolSpecificData), command = object(data.commandLine), details = object(part.resultDetails);
|
|
32787
|
+
const name = text(part.toolId) || "Tool", callID = text(part.toolCallId) || void 0;
|
|
32788
|
+
const input = eventText(data.rawInput ?? command.userEdited ?? command.toolEdited ?? command.original ?? details.input);
|
|
32789
|
+
const denied = part.isConfirmed === false || [0, 5].includes(object(part.isConfirmed).type);
|
|
32790
|
+
const status2 = denied || part.resultError ? "failed" : part.isComplete === true ? "completed" : "unknown";
|
|
32791
|
+
const correlation = { ...fields2, callID, parentID: text(part.subAgentInvocationId) || void 0 };
|
|
32792
|
+
message2.events.push(eventFor(message2, `${id2}:call`, "tool_call", name, markdown(part.invocationMessage), { ...correlation, ...recordedTime(part.startedAt), input, status: "unknown" }));
|
|
32793
|
+
message2.tools.push(name);
|
|
32794
|
+
addText(message2, input, "Tool");
|
|
32795
|
+
if (part.isComplete || part.resultError || denied) {
|
|
32796
|
+
const output = eventText(part.resultError || (denied ? "Tool invocation was denied or skipped." : details.output ?? part.resultDetails ?? markdown(part.pastTenseMessage)));
|
|
32797
|
+
message2.events.push(eventFor(message2, `${id2}:result`, "tool_result", name, markdown(part.pastTenseMessage), { ...correlation, ...recordedTime(part.completedAt), role: "tool", output, status: status2 }));
|
|
32798
|
+
addText(message2, output, "Tool");
|
|
32799
|
+
} else message2.partial = true;
|
|
32800
|
+
} else {
|
|
32801
|
+
message2.events.push(eventFor(message2, id2, "event", kind || "Unsupported chat content", eventText(part), { ...fields2, partial: true }));
|
|
32802
|
+
message2.partial = true;
|
|
32803
|
+
}
|
|
32804
|
+
}
|
|
32805
|
+
function chatMessages(requests) {
|
|
32806
|
+
return requests.flatMap((request, index) => {
|
|
32807
|
+
if (!request || typeof request !== "object" || Array.isArray(request)) throw new Error("Unsupported VS Code chat request.");
|
|
32808
|
+
const requestID = text(request.requestId) || `request:${index}`;
|
|
32809
|
+
const injected = Boolean(request.isSystemInitiated || request.hiddenFromTranscript || request.requestHiddenFromTranscript);
|
|
32810
|
+
const user = blankMessage(requestID, time(request.timestamp), injected ? "system" : "user");
|
|
32811
|
+
const content = typeof request.message === "string" ? request.message : text(object(request.message).text);
|
|
32812
|
+
user.events = [eventFor(user, "message", injected ? "event" : "message", injected ? "Injected message" : "User message", content, { nativeID: requestID, ...recordedTime(request.timestamp) })];
|
|
32813
|
+
addText(user, content, injected ? "Tool" : "You");
|
|
32814
|
+
if (request.variableData?.variables?.length) user.partial = true;
|
|
32815
|
+
const messages = [user];
|
|
32816
|
+
if (request.response !== void 0 || request.result?.errorDetails || request.responseErrorDetails || request.editedFileEvents?.length) {
|
|
32817
|
+
const assistant = blankMessage(text(request.responseId) || `response:${requestID}`, time(request.responseTimestamp), "assistant");
|
|
32818
|
+
assistant.events = [];
|
|
32819
|
+
const parts = Array.isArray(request.response) ? request.response : request.response == null ? [] : [request.response];
|
|
32820
|
+
if (parts.length > 200) assistant.partial = true;
|
|
32821
|
+
parts.slice(0, 200).forEach((part, i) => responsePart(assistant, part, i));
|
|
32822
|
+
const error = request.result?.errorDetails || request.responseErrorDetails;
|
|
32823
|
+
if (error) {
|
|
32824
|
+
const content2 = markdown(error.message) || eventText(error);
|
|
32825
|
+
assistant.events.push(eventFor(assistant, "error", "error", "Response error", content2));
|
|
32826
|
+
addText(assistant, content2, "Tool");
|
|
32827
|
+
}
|
|
32828
|
+
for (const edit of Array.isArray(request.editedFileEvents) ? request.editedFileEvents : []) {
|
|
32829
|
+
const path = vscodeChatPath(edit?.uri);
|
|
32830
|
+
if (edit?.eventKind === 1 && path) {
|
|
32831
|
+
assistant.files.push({ path, source: "file change", steps: 1 });
|
|
32832
|
+
addText(assistant, path, "File");
|
|
32833
|
+
}
|
|
32834
|
+
}
|
|
32835
|
+
if (request.isCanceled || [0, 2, 4].includes(request.modelState?.value)) assistant.partial = true;
|
|
32836
|
+
messages.push(assistant);
|
|
32837
|
+
}
|
|
32838
|
+
return messages;
|
|
32839
|
+
});
|
|
32840
|
+
}
|
|
32841
|
+
var match = (path) => /^(?:[^/]+\/chatSessions\/)?[^/]+\.jsonl?$/.test(path) && !["index.json", "workspace.json"].includes(path);
|
|
32842
|
+
var roots = () => copilotChatRoots();
|
|
32843
|
+
var filesAdapter = localFileAdapter({
|
|
32844
|
+
id: "copilot-chat",
|
|
32845
|
+
name: "GitHub Copilot Chat (VS Code)",
|
|
32846
|
+
description: "VS Code and Insiders saved chats \xB7 local JSON snapshots and JSONL logs",
|
|
32847
|
+
capabilities: { history: true, forks: false, children: false, files: true },
|
|
32848
|
+
roots,
|
|
32849
|
+
match,
|
|
32850
|
+
authoritativeIdentity: (path) => path.endsWith(".jsonl") ? basename6(path, ".jsonl") : void 0,
|
|
32851
|
+
extras: (path) => [...basename6(dirname4(path)) === "chatSessions" ? [join17(dirname4(dirname4(path)), "workspace.json")] : [], ...path.endsWith(".json") ? [`${path}l`] : []],
|
|
32852
|
+
parse(path, files) {
|
|
32853
|
+
const log = path.endsWith(".jsonl") ? path : `${path}l`;
|
|
32854
|
+
const data = files.has(log) ? vscodeChatLog(files.get(log)) : object(JSON.parse(files.get(path)));
|
|
32855
|
+
if (!text(data.sessionId) || !Array.isArray(data.requests) || data.version !== void 0 && ![1, 2, 3].includes(data.version)) throw new Error("Unsupported VS Code chat history.");
|
|
32856
|
+
if (data.sessionId !== basename6(path).replace(/\.jsonl?$/, "")) throw new Error("VS Code chat identity mismatch.");
|
|
32857
|
+
if (!data.requests.length) return;
|
|
32858
|
+
if (data.requests.length > 25e3) throw new Error("Chat exceeds the 50,000-message limit.");
|
|
32859
|
+
const workspacePath = join17(dirname4(dirname4(path)), "workspace.json");
|
|
32860
|
+
const workspace = files.has(workspacePath) ? object(JSON.parse(files.get(workspacePath))) : {};
|
|
32861
|
+
const messages = chatMessages(data.requests);
|
|
32862
|
+
const model = [...data.requests].reverse().find((r) => text(r.modelId));
|
|
32863
|
+
return {
|
|
32864
|
+
nativeID: data.sessionId,
|
|
32865
|
+
messages,
|
|
32866
|
+
session: { title: text(data.customTitle) || text(data.computedTitle), created: time(data.creationDate), directory: vscodeChatPath(data.workingDirectory || workspace.folder), model: text(model?.modelId) || "Unknown model" },
|
|
32867
|
+
note: "Persisted VS Code Chat UI history, including Copilot participants. Attachments, pre-compaction content, and transient UI state may be absent. Accepted-edit records provide file evidence; proposed edits and references do not. Multi-root workspaces without an explicit working directory remain unassigned. Tool subagent IDs are event correlations, not session ancestry."
|
|
32868
|
+
};
|
|
32869
|
+
}
|
|
32870
|
+
});
|
|
32871
|
+
var copilotChatAdapter = { ...filesAdapter, async detect() {
|
|
32872
|
+
return (await historyFiles(roots(), match)).files.length > 0;
|
|
32873
|
+
} };
|
|
32874
|
+
|
|
32875
|
+
// server/adapters/extensions.ts
|
|
32876
|
+
import { homedir as homedir12 } from "node:os";
|
|
32877
|
+
import { basename as basename7, dirname as dirname5, join as join18 } from "node:path";
|
|
32701
32878
|
function editorTaskRoots(extension) {
|
|
32702
|
-
const home =
|
|
32703
|
-
const base = process.platform === "darwin" ?
|
|
32704
|
-
return ["Code", "Code - Insiders", "VSCodium", "Cursor", "Windsurf"].map((app) =>
|
|
32879
|
+
const home = homedir12();
|
|
32880
|
+
const base = process.platform === "darwin" ? join18(home, "Library", "Application Support") : process.platform === "win32" ? process.env.APPDATA || join18(home, "AppData", "Roaming") : process.env.XDG_CONFIG_HOME || join18(home, ".config");
|
|
32881
|
+
return ["Code", "Code - Insiders", "VSCodium", "Cursor", "Windsurf"].map((app) => join18(base, app, "User", "globalStorage", extension, "tasks")).concat([".vscode-server", ".vscode-server-insiders"].map((app) => join18(home, app, "data", "User", "globalStorage", extension, "tasks")));
|
|
32705
32882
|
}
|
|
32706
32883
|
function taskAdapter(id2, name, extension, env) {
|
|
32707
|
-
const
|
|
32884
|
+
const roots2 = () => process.env[env] ? [join18(process.env[env], "tasks"), ...id2 === "cline" ? [join18(process.env[env], "data", "sessions")] : []] : [...editorTaskRoots(extension), ...id2 === "cline" ? [process.env.CLINE_SESSION_DATA_DIR || join18(process.env.CLINE_DATA_DIR || join18(process.env.CLINE_DIR || join18(homedir12(), ".cline"), "data"), "sessions")] : []];
|
|
32708
32885
|
return localFileAdapter({
|
|
32709
32886
|
id: id2,
|
|
32710
32887
|
name,
|
|
32711
32888
|
description: id2 === "kilo-code" ? "VS Code extension task histories \xB7 choose Kilo CLI separately" : id2 === "cline" ? "Local extension tasks and CLI/SDK message snapshots" : "Local VS Code extension task histories",
|
|
32712
32889
|
capabilities: { history: true, forks: id2 === "cline", children: true, files: true },
|
|
32713
|
-
roots,
|
|
32890
|
+
roots: roots2,
|
|
32714
32891
|
match: (path) => /^[^/]+\/api_conversation_history\.json$/.test(path) || id2 === "cline" && /^[^/]+\/[^/]+\.messages\.json$/.test(path),
|
|
32715
|
-
extras: (path) => ["history_item.json", "task_metadata.json", "session.json"].map((file) =>
|
|
32892
|
+
extras: (path) => ["history_item.json", "task_metadata.json", "session.json"].map((file) => join18(dirname5(path), file)),
|
|
32716
32893
|
parse(path, files) {
|
|
32717
32894
|
const sdk = path.endsWith(".messages.json"), value = json2(files.get(path));
|
|
32718
32895
|
const records = sdk ? object(value).messages : value;
|
|
32719
32896
|
if (!Array.isArray(records) || sdk && !text(value.sessionId)) throw new Error("Unsupported task history.");
|
|
32720
|
-
const read3 = (name2) => object(files.has(
|
|
32897
|
+
const read3 = (name2) => object(files.has(join18(dirname5(path), name2)) ? json2(files.get(join18(dirname5(path), name2))) : void 0);
|
|
32721
32898
|
const history = read3("history_item.json"), info = read3("session.json"), task = read3("task_metadata.json");
|
|
32722
|
-
const nativeID = sdk ? value.sessionId :
|
|
32899
|
+
const nativeID = sdk ? value.sessionId : basename7(dirname5(path));
|
|
32723
32900
|
if (history.id && history.id !== nativeID || info.session_id && info.session_id !== nativeID) throw new Error("Task metadata identity mismatch.");
|
|
32724
32901
|
const messages = records.map((raw, index) => {
|
|
32725
32902
|
const row = object(raw), message2 = conversationMessage(row, `record:${index}`);
|
|
@@ -32753,14 +32930,14 @@ var continueAdapter = localFileAdapter({
|
|
|
32753
32930
|
name: "Continue",
|
|
32754
32931
|
description: "Local IDE and CLI session JSON \xB7 recorded conversation and tool history",
|
|
32755
32932
|
capabilities: { history: true, forks: false, children: false, files: false },
|
|
32756
|
-
roots: () => [
|
|
32933
|
+
roots: () => [join18(process.env.SESSIONGRAPH_CONTINUE_HOME || process.env.CONTINUE_GLOBAL_DIR || join18(homedir12(), ".continue"), "sessions")],
|
|
32757
32934
|
match: (path) => /^[^/]+\.json$/.test(path) && path !== "sessions.json",
|
|
32758
|
-
extras: (path) => [
|
|
32935
|
+
extras: (path) => [join18(dirname5(path), "sessions.json")],
|
|
32759
32936
|
revisionExtras: false,
|
|
32760
32937
|
parse(path, files) {
|
|
32761
32938
|
const value = object(json2(files.get(path)));
|
|
32762
32939
|
if (!text(value.sessionId) || !Array.isArray(value.history)) throw new Error("Unsupported Continue session.");
|
|
32763
|
-
const indexPath =
|
|
32940
|
+
const indexPath = join18(dirname5(path), "sessions.json"), index = files.has(indexPath) ? json2(files.get(indexPath)) : [];
|
|
32764
32941
|
const meta = Array.isArray(index) ? object(index.find((r) => r.sessionId === value.sessionId)) : {};
|
|
32765
32942
|
const messages = value.history.map((item, i) => {
|
|
32766
32943
|
const row = object(item), raw = object(row.message), message2 = conversationMessage(raw, `record:${i}`);
|
|
@@ -32779,30 +32956,30 @@ var continueAdapter = localFileAdapter({
|
|
|
32779
32956
|
});
|
|
32780
32957
|
|
|
32781
32958
|
// server/adapters/harness-files.ts
|
|
32782
|
-
import { basename as
|
|
32959
|
+
import { basename as basename9, dirname as dirname7, join as join21 } from "node:path";
|
|
32783
32960
|
|
|
32784
32961
|
// server/adapters/harness-paths.ts
|
|
32785
|
-
import { homedir as
|
|
32786
|
-
import { join as
|
|
32787
|
-
var homePath = (...parts) =>
|
|
32788
|
-
var dataPath = (...parts) =>
|
|
32789
|
-
var configPath = (...parts) =>
|
|
32790
|
-
var appPath = (...parts) =>
|
|
32791
|
-
var tokscalePath = (...parts) =>
|
|
32792
|
-
var envHome = (env, fallback, ...parts) =>
|
|
32962
|
+
import { homedir as homedir13 } from "node:os";
|
|
32963
|
+
import { join as join19 } from "node:path";
|
|
32964
|
+
var homePath = (...parts) => join19(homedir13(), ...parts);
|
|
32965
|
+
var dataPath = (...parts) => join19(process.env.XDG_DATA_HOME || homePath(".local/share"), ...parts);
|
|
32966
|
+
var configPath = (...parts) => join19(process.env.XDG_CONFIG_HOME || homePath(".config"), ...parts);
|
|
32967
|
+
var appPath = (...parts) => join19(process.platform === "darwin" ? homePath("Library/Application Support") : process.platform === "win32" ? process.env.APPDATA || homePath("AppData/Roaming") : process.env.XDG_CONFIG_HOME || homePath(".config"), ...parts);
|
|
32968
|
+
var tokscalePath = (...parts) => join19(process.env.TOKSCALE_CONFIG_DIR || (process.platform === "win32" ? appPath("tokscale") : configPath("tokscale")), ...parts);
|
|
32969
|
+
var envHome = (env, fallback, ...parts) => join19(process.env[env]?.trim() || homePath(fallback), ...parts);
|
|
32793
32970
|
var harnessRoots = (id2, defaults) => () => {
|
|
32794
32971
|
const override = process.env[`SESSIONGRAPH_${id2.replace(/-/g, "_").toUpperCase()}_HISTORY_DIR`]?.trim();
|
|
32795
32972
|
return override ? [override] : defaults();
|
|
32796
32973
|
};
|
|
32797
32974
|
|
|
32798
32975
|
// server/adapters/harness-extra-formats.ts
|
|
32799
|
-
import { basename as
|
|
32976
|
+
import { basename as basename8, dirname as dirname6, join as join20 } from "node:path";
|
|
32800
32977
|
function kiroHistory(path, files) {
|
|
32801
32978
|
const header = object(json2(files.get(path)));
|
|
32802
|
-
const ide2 =
|
|
32803
|
-
const nativeID = text(header.session_id || header.sessionId || header.id) || (ide2 ?
|
|
32979
|
+
const ide2 = basename8(path) === "session.json";
|
|
32980
|
+
const nativeID = text(header.session_id || header.sessionId || header.id) || (ide2 ? basename8(dirname6(path)) : "");
|
|
32804
32981
|
if (!nativeID) throw new Error("Unsupported Kiro session header.");
|
|
32805
|
-
const side = ide2 ?
|
|
32982
|
+
const side = ide2 ? join20(dirname6(path), "messages.jsonl") : path.replace(/\.json$/, ".jsonl");
|
|
32806
32983
|
if (!files.has(side)) throw new Error("Kiro conversation sidecar is unavailable.");
|
|
32807
32984
|
const { rows: rows2 } = jsonLines(files.get(side));
|
|
32808
32985
|
const messages = rows2.flatMap((r, i) => {
|
|
@@ -32828,7 +33005,7 @@ function kiroHistory(path, files) {
|
|
|
32828
33005
|
};
|
|
32829
33006
|
}
|
|
32830
33007
|
function muxHistory(path, files) {
|
|
32831
|
-
const archive = files.get(
|
|
33008
|
+
const archive = files.get(join20(dirname6(path), "chat-archive.jsonl"));
|
|
32832
33009
|
const records = [...archive ? jsonLines(archive).rows : [], ...jsonLines(files.get(path)).rows];
|
|
32833
33010
|
const unique = /* @__PURE__ */ new Map();
|
|
32834
33011
|
for (const r of records) {
|
|
@@ -32847,7 +33024,7 @@ function muxHistory(path, files) {
|
|
|
32847
33024
|
});
|
|
32848
33025
|
if (!messages.length) throw new Error("No readable Mux conversation.");
|
|
32849
33026
|
return {
|
|
32850
|
-
nativeID:
|
|
33027
|
+
nativeID: basename8(dirname6(path)),
|
|
32851
33028
|
messages,
|
|
32852
33029
|
partial: true,
|
|
32853
33030
|
note: "Mux durable chat archive followed by active chat, deduplicated by native message ID. In-flight partial.json and workspace ancestry are unavailable. Cumulative usage snapshots are not turns."
|
|
@@ -32871,16 +33048,16 @@ var piSources = [
|
|
|
32871
33048
|
{ id: "prime-agent", name: "Prime Agent", roots: () => [process.env.PRIME_AGENT_SESSION_DIR || process.env.PRIME_AGENT_CODING_AGENT_SESSION_DIR || envHome("PRIME_AGENT_CODING_AGENT_DIR", ".prime/agent", "sessions"), envHome("PRIME_AGENT_CODING_AGENT_DIR", ".prime/agent", "session-artifacts")] },
|
|
32872
33049
|
{ id: "omp", name: "Oh My Pi", roots: () => [envHome("PI_CODING_AGENT_DIR_OMP", ".omp/agent", "sessions")] },
|
|
32873
33050
|
{ id: "senpi", name: "Senpi / OmO Native", roots: () => [envHome("SENPI_CODING_AGENT_DIR", ".senpi/agent", "sessions"), homePath(".omo/agent/sessions")] },
|
|
32874
|
-
{ id: "kimchi", name: "Kimchi", roots: () => [
|
|
32875
|
-
{ id: "gajae", name: "Gajae-Code", roots: () => [
|
|
33051
|
+
{ id: "kimchi", name: "Kimchi", roots: () => [join21(process.env.KIMCHI_CODING_AGENT_DIR || configPath("kimchi/harness"), "sessions")] },
|
|
33052
|
+
{ id: "gajae", name: "Gajae-Code", roots: () => [join21(process.env.GJC_CODING_AGENT_DIR || (process.env.GJC_CONFIG_DIR || process.env.PI_CONFIG_DIR ? join21(process.env.GJC_CONFIG_DIR || process.env.PI_CONFIG_DIR, "agent") : homePath(".gjc/agent")), "sessions"), dataPath("gjc/sessions")] }
|
|
32876
33053
|
].map((s) => ({ ...s, parse: piParse }));
|
|
32877
33054
|
var openclawRoots = () => [envHome("OPENCLAW_STATE_DIR", ".openclaw", "agents"), ...[".clawdbot", ".moltbot", ".moldbot"].map((p) => homePath(p, "agents"))];
|
|
32878
33055
|
var promaRoots = () => [".proma", ".proma-dev"].flatMap((p) => ["agent-sessions", "sdk-config/sessions", "sdk-config/projects"].map((s) => homePath(p, s)));
|
|
32879
33056
|
function kimiHistory(path, files) {
|
|
32880
33057
|
const { rows: rows2 } = jsonLines(files.get(path));
|
|
32881
|
-
const folder =
|
|
32882
|
-
const nativeID = agent ? `${
|
|
32883
|
-
const wire =
|
|
33058
|
+
const folder = dirname7(path), id2 = basename9(folder), agent = basename9(dirname7(folder)) === "agents";
|
|
33059
|
+
const nativeID = agent ? `${basename9(dirname7(dirname7(folder)))}/agent/${id2}` : id2;
|
|
33060
|
+
const wire = join21(folder, "wire.jsonl"), wireRows = files.has(wire) ? jsonLines(files.get(wire)).rows : [];
|
|
32884
33061
|
const messages = rows2.flatMap((r, i) => {
|
|
32885
33062
|
const m = message(r, nativeText(r.id) || `context:${i}`);
|
|
32886
33063
|
return m ? [m] : [];
|
|
@@ -32899,7 +33076,7 @@ function museHistory(path, files) {
|
|
|
32899
33076
|
const meta = rows2.find((r) => r.payload_type === "runtime.session.metadata");
|
|
32900
33077
|
const ids = new Set(rows2.map((r) => text(r.stream?.id)).filter(Boolean));
|
|
32901
33078
|
if (!meta || ids.size > 1) throw new Error("Unsupported Muse stream.");
|
|
32902
|
-
const nativeID = [...ids][0] ||
|
|
33079
|
+
const nativeID = [...ids][0] || basename9(dirname7(path));
|
|
32903
33080
|
const messages = rows2.flatMap((r, i) => {
|
|
32904
33081
|
const event = object(r.payload?.event), body2 = object(event.message);
|
|
32905
33082
|
const at2 = typeof r.recorded_at === "number" && r.recorded_at >= 1e15 ? r.recorded_at / 1e3 : typeof r.recorded_at === "number" && r.recorded_at < 1e12 ? seconds(r.recorded_at) : time(r.recorded_at);
|
|
@@ -32923,7 +33100,7 @@ function junieHistory(path, files) {
|
|
|
32923
33100
|
return [recordEvent(r, text(r.id) || `event:${i}`, kind, r.timestampMs, e10.text ?? e10.prompt ?? e10.message)];
|
|
32924
33101
|
});
|
|
32925
33102
|
if (!messages.length) throw new Error("No supported Junie events.");
|
|
32926
|
-
return { nativeID:
|
|
33103
|
+
return { nativeID: basename9(dirname7(path)), messages, partial: true, note: "Junie recorded agent events. State snapshots and opaque event bodies are omitted; events without an authoritative message role are not counted as user turns." };
|
|
32927
33104
|
}
|
|
32928
33105
|
function augmentHistory(path, files) {
|
|
32929
33106
|
const r = object(json2(files.get(path)));
|
|
@@ -32935,7 +33112,7 @@ function augmentHistory(path, files) {
|
|
|
32935
33112
|
return { nativeID: r.sessionId, messages, partial: true, session: { title: text(r.title), created: time(r.created), model: text(r.agentState?.modelId) || "Unknown model" }, note: "Augment saved exchange records. Typed response-node payloads and absent prompts are not reconstructed into conversations." };
|
|
32936
33113
|
}
|
|
32937
33114
|
function fxHistory(path, files) {
|
|
32938
|
-
const usage = object(json2(files.get(path))), meta = sidecar2(files,
|
|
33115
|
+
const usage = object(json2(files.get(path))), meta = sidecar2(files, join21(dirname7(path), "session.json"));
|
|
32939
33116
|
const id2 = text(usage.session_id) || text(meta.id);
|
|
32940
33117
|
if (!id2 || !usage.snapshot || meta.id && meta.id !== id2) throw new Error("Unsupported Fx session metadata.");
|
|
32941
33118
|
return {
|
|
@@ -32948,15 +33125,15 @@ function fxHistory(path, files) {
|
|
|
32948
33125
|
}
|
|
32949
33126
|
var definitions = [
|
|
32950
33127
|
...piSources,
|
|
32951
|
-
{ id: "kiro", name: "Kiro", roots: () => [homePath(".kiro/sessions"), appPath("Kiro/User/globalStorage/kiro.kiroagent")], match: (p) => p.endsWith("/session.json") || /^cli\/[^/]+\.json$/.test(p), extras: (p) => [
|
|
32952
|
-
{ id: "mux", name: "Mux", roots: () => [envHome("MUX_ROOT", ".mux", "sessions")], match: (p) => p.endsWith("/chat.jsonl"), extras: (p) => [
|
|
33128
|
+
{ id: "kiro", name: "Kiro", roots: () => [homePath(".kiro/sessions"), appPath("Kiro/User/globalStorage/kiro.kiroagent")], match: (p) => p.endsWith("/session.json") || /^cli\/[^/]+\.json$/.test(p), extras: (p) => [basename9(p) === "session.json" ? join21(dirname7(p), "messages.jsonl") : p.replace(/\.json$/, ".jsonl")], parse: kiroHistory },
|
|
33129
|
+
{ id: "mux", name: "Mux", roots: () => [envHome("MUX_ROOT", ".mux", "sessions")], match: (p) => p.endsWith("/chat.jsonl"), extras: (p) => [join21(dirname7(p), "chat-archive.jsonl")], parse: muxHistory },
|
|
32953
33130
|
{ id: "devin-desktop", name: "Devin Desktop", roots: () => [appPath("Devin/User/acp-events")], match: (p) => /\.(ndjson|jsonl)$/.test(p), parse: devinDesktopHistory },
|
|
32954
33131
|
{ id: "openclaw", name: "OpenClaw", roots: openclawRoots, match: (p) => /(?:^|\/)sessions\/.*\.jsonl(?:\.[\w.-]+)?$/.test(p) || /session-sqlite-import-archive\/.*\.jsonl\./.test(p), parse: piParse },
|
|
32955
33132
|
{ id: "amp", name: "Amp", roots: () => [dataPath("amp/threads"), tokscalePath("amp-cache/threads")], match: (p) => p.endsWith(".json"), parse: ampHistory },
|
|
32956
33133
|
{ id: "droid", name: "Factory Droid", roots: () => [envHome("FACTORY_HOME", ".factory", "sessions")] },
|
|
32957
33134
|
{ id: "codebuff", name: "Codebuff", roots: () => process.env.CODEBUFF_DATA_DIR ? [process.env.CODEBUFF_DATA_DIR] : ["manicode", "manicode-dev", "manicode-staging"].map((p) => configPath(p)), match: (p) => p.endsWith("/chat-messages.json"), parse: (p, f) => codebuffHistory(p, f, false) },
|
|
32958
33135
|
{ id: "freebuff", name: "Freebuff", roots: () => process.env.FREEBUFF_DATA_DIR ? [process.env.FREEBUFF_DATA_DIR] : process.env.CODEBUFF_DATA_DIR ? [process.env.CODEBUFF_DATA_DIR] : ["manicode", "manicode-dev", "manicode-staging"].map((p) => configPath(p)), match: (p) => p.endsWith("/chat-messages.json"), parse: (p, f) => codebuffHistory(p, f, true) },
|
|
32959
|
-
{ id: "kimi", name: "Kimi CLI / Code", roots: () => [envHome("KIMI_HOME", ".kimi", "sessions"), envHome("KIMI_CODE_HOME", ".kimi-code", "sessions")], match: (p) => p.endsWith("/context.jsonl"), extras: (p) => [
|
|
33136
|
+
{ id: "kimi", name: "Kimi CLI / Code", roots: () => [envHome("KIMI_HOME", ".kimi", "sessions"), envHome("KIMI_CODE_HOME", ".kimi-code", "sessions")], match: (p) => p.endsWith("/context.jsonl"), extras: (p) => [join21(dirname7(p), "wire.jsonl")], parse: kimiHistory },
|
|
32960
33137
|
{ id: "grok", name: "Grok Build", roots: () => [envHome("GROK_HOME", ".grok", "sessions")], match: (p) => p.endsWith("/updates.jsonl"), parse: (p, f) => acpHistory(p, f.get(p)) },
|
|
32961
33138
|
{ id: "jcode", name: "Jcode", roots: () => [envHome("JCODE_HOME", ".jcode", "sessions")], match: (p) => /(?:^|\/)session_[^/]+\.json$/.test(p), extras: (p) => [p.replace(/\.json$/, ".journal.jsonl")], parse: jcodeHistory },
|
|
32962
33139
|
{ id: "cherry-studio", name: "Cherry Studio", roots: () => [appPath("CherryStudio/Data/Agents/.claude/projects"), appPath("CherryStudio/.claude/projects")] },
|
|
@@ -32968,15 +33145,15 @@ var definitions = [
|
|
|
32968
33145
|
{ id: "deepseek-harness", name: "DeepSeek Harness", roots: () => [envHome("DSH_HOME", ".dsh", "sessions")], match: (p) => /(?:^|\/)session(?:\.v\d+)?\.jsonl(?:\.zstd)?$/.test(p), parse: (p, f) => dshHistory(f.get(p)) },
|
|
32969
33146
|
{ id: "aside", name: "Aside", roots: () => [homePath(".aside/u")], match: (p) => /^[^/]+\/sessions\/[^/]+\/messages\.jsonl$/.test(p), parse(p, f) {
|
|
32970
33147
|
const h3 = envelopeHistory(p, f.get(p));
|
|
32971
|
-
h3.nativeID = `${
|
|
33148
|
+
h3.nativeID = `${basename9(dirname7(dirname7(dirname7(p))))}/${basename9(dirname7(p))}`;
|
|
32972
33149
|
return h3;
|
|
32973
33150
|
} },
|
|
32974
|
-
{ id: "vibe", name: "Mistral Vibe", roots: () => [envHome("VIBE_HOME", ".vibe", "logs/session")], match: (p) => p.endsWith("/meta.json") || /^[^/]+\.json$/.test(p), extras: (p) =>
|
|
33151
|
+
{ id: "vibe", name: "Mistral Vibe", roots: () => [envHome("VIBE_HOME", ".vibe", "logs/session")], match: (p) => p.endsWith("/meta.json") || /^[^/]+\.json$/.test(p), extras: (p) => basename9(p) === "meta.json" ? [join21(dirname7(p), "messages.jsonl")] : [], parse: vibeHistory },
|
|
32975
33152
|
{ id: "muse", name: "Muse Code", roots: () => [dataPath("muse/sessions")], match: (p) => p.endsWith("/session.jsonl"), parse: museHistory },
|
|
32976
33153
|
{ id: "junie", name: "Junie", roots: () => [homePath(".junie/sessions")], match: (p) => p.endsWith("/events.jsonl"), parse: junieHistory, description: "Local agent event history \xB7 partial conversation coverage" },
|
|
32977
33154
|
{ id: "augment", name: "Augment Code", roots: () => [homePath(".augment/sessions")], match: (p) => p.endsWith(".json"), parse: augmentHistory, description: "Local exchange records \xB7 partial conversation coverage" },
|
|
32978
|
-
{ id: "fx", name: "Fx", roots: () => [homePath(".fx/sessions")], match: (p) => p.endsWith("/usage-v2.json"), extras: (p) => [
|
|
32979
|
-
{ id: "minimax-code", name: "MiniMax Code", roots: () => [
|
|
33155
|
+
{ id: "fx", name: "Fx", roots: () => [homePath(".fx/sessions")], match: (p) => p.endsWith("/usage-v2.json"), extras: (p) => [join21(dirname7(p), "session.json")], parse: fxHistory, history: false, description: "Local native session metadata \xB7 conversation unavailable in usage snapshots" },
|
|
33156
|
+
{ id: "minimax-code", name: "MiniMax Code", roots: () => [join21(process.env.TOKSCALE_HEADLESS_DIR || tokscalePath("headless"), "mcode")], parse(p, f) {
|
|
32980
33157
|
const value = f.get(p), { rows: rows2 } = jsonLines(value), ids = new Set(rows2.map((r) => text(r.sessionId)).filter(Boolean));
|
|
32981
33158
|
if (ids.size !== 1) throw new Error("Headless capture needs one explicit session identity.");
|
|
32982
33159
|
const messages = rows2.flatMap((r, i) => {
|
|
@@ -33002,13 +33179,13 @@ var fileHarnessAdapters = definitions.map((source) => localFileAdapter({
|
|
|
33002
33179
|
|
|
33003
33180
|
// server/adapters/harness-databases.ts
|
|
33004
33181
|
import { lstat as lstat6, readFile as readFile4 } from "node:fs/promises";
|
|
33005
|
-
import { isAbsolute as isAbsolute5, join as
|
|
33182
|
+
import { isAbsolute as isAbsolute5, join as join22 } from "node:path";
|
|
33006
33183
|
var parsedContent = (v3) => typeof v3 === "string" && /^[\[{]/.test(v3.trim()) ? optionalJSON(v3) : v3;
|
|
33007
33184
|
var millisOrSeconds = (v3) => typeof v3 === "number" && v3 > 0 && v3 < 1e10 ? seconds(v3) : time(v3);
|
|
33008
|
-
function dbPaths(id2, defaults,
|
|
33185
|
+
function dbPaths(id2, defaults, match2) {
|
|
33009
33186
|
return async () => {
|
|
33010
33187
|
const override = process.env[`SESSIONGRAPH_${id2.replace(/-/g, "_").toUpperCase()}_HISTORY_DIR`];
|
|
33011
|
-
return override ? (await historyFiles([override],
|
|
33188
|
+
return override ? (await historyFiles([override], match2)).files : existingDatabases(defaults());
|
|
33012
33189
|
};
|
|
33013
33190
|
}
|
|
33014
33191
|
function sessionHistory(r, messages, note) {
|
|
@@ -33042,7 +33219,7 @@ var hermes = {
|
|
|
33042
33219
|
var goose = {
|
|
33043
33220
|
id: "goose",
|
|
33044
33221
|
name: "Goose",
|
|
33045
|
-
paths: dbPaths("goose", () => process.env.GOOSE_PATH_ROOT && isAbsolute5(process.env.GOOSE_PATH_ROOT) ? [
|
|
33222
|
+
paths: dbPaths("goose", () => process.env.GOOSE_PATH_ROOT && isAbsolute5(process.env.GOOSE_PATH_ROOT) ? [join22(process.env.GOOSE_PATH_ROOT, "data/sessions/sessions.db")] : [dataPath("goose/sessions/sessions.db"), dataPath("Block/goose/sessions/sessions.db"), appPath("goose/sessions/sessions.db"), appPath("Block/goose/sessions/sessions.db"), appPath("Block/goose/data/sessions/sessions.db")], (p) => p.endsWith("sessions.db")),
|
|
33046
33223
|
table: "sessions",
|
|
33047
33224
|
key: "id",
|
|
33048
33225
|
fields: ["id", "name", "description", "working_dir", "created_at", "updated_at", "model_config_json", "provider_name", "session_type", "parent_session_id", "archived_at"],
|
|
@@ -33105,7 +33282,7 @@ function forkStore(id2, name, defaultPath, desktop) {
|
|
|
33105
33282
|
var zed = {
|
|
33106
33283
|
id: "zed",
|
|
33107
33284
|
name: "Zed Agent",
|
|
33108
|
-
paths: dbPaths("zed", () => [process.platform === "darwin" ? appPath("Zed/threads/threads.db") : process.platform === "win32" ?
|
|
33285
|
+
paths: dbPaths("zed", () => [process.platform === "darwin" ? appPath("Zed/threads/threads.db") : process.platform === "win32" ? join22(process.env.LOCALAPPDATA || homePath("AppData/Local"), "Zed/threads/threads.db") : dataPath("zed/threads/threads.db")], (p) => p.endsWith("threads.db")),
|
|
33109
33286
|
table: "threads",
|
|
33110
33287
|
key: "id",
|
|
33111
33288
|
fields: ["id", "summary", "created_at", "updated_at", "data_type", "data", "folder_paths"],
|
|
@@ -33149,7 +33326,7 @@ var crush = {
|
|
|
33149
33326
|
paths: async () => {
|
|
33150
33327
|
const override = process.env.SESSIONGRAPH_CRUSH_HISTORY_DIR;
|
|
33151
33328
|
if (override) return (await historyFiles([override], (p) => p.endsWith("crush.db"))).files;
|
|
33152
|
-
const registry =
|
|
33329
|
+
const registry = join22(process.env.CRUSH_GLOBAL_DATA || dataPath("crush"), "projects.json");
|
|
33153
33330
|
try {
|
|
33154
33331
|
const stat6 = await lstat6(registry);
|
|
33155
33332
|
if (!stat6.isFile() || stat6.size > 2e6) throw new Error("Unsupported Crush registry.");
|
|
@@ -33157,7 +33334,7 @@ var crush = {
|
|
|
33157
33334
|
const paths = [];
|
|
33158
33335
|
for (const p of Array.isArray(raw.projects) ? raw.projects.slice(0, 2e4) : []) {
|
|
33159
33336
|
if (!isAbsolute5(text(p.path)) || !text(p.data_dir)) continue;
|
|
33160
|
-
const path =
|
|
33337
|
+
const path = join22(isAbsolute5(p.data_dir) ? p.data_dir : join22(p.path, p.data_dir), "crush.db");
|
|
33161
33338
|
paths.push(path);
|
|
33162
33339
|
crushDirectories.set(path, p.path);
|
|
33163
33340
|
}
|
|
@@ -33261,8 +33438,8 @@ var databaseHarnessAdapters = [
|
|
|
33261
33438
|
].map(sqliteHistoryAdapter);
|
|
33262
33439
|
|
|
33263
33440
|
// server/adapters/harness-metadata.ts
|
|
33264
|
-
import { basename as
|
|
33265
|
-
import { fileURLToPath as
|
|
33441
|
+
import { basename as basename10 } from "node:path";
|
|
33442
|
+
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
33266
33443
|
import { lstat as lstat7 } from "node:fs/promises";
|
|
33267
33444
|
function protoFields(value) {
|
|
33268
33445
|
if (value.length > 2e6) throw new Error("Trajectory metadata exceeds 2 MB.");
|
|
@@ -33313,12 +33490,12 @@ var antigravityDatabaseAdapters = ["antigravity-cli", "antigravity-extension"].m
|
|
|
33313
33490
|
let directory2 = "";
|
|
33314
33491
|
if (uri instanceof Uint8Array) {
|
|
33315
33492
|
try {
|
|
33316
|
-
directory2 =
|
|
33493
|
+
directory2 = fileURLToPath4(Buffer.from(uri).toString("utf8"));
|
|
33317
33494
|
} catch {
|
|
33318
33495
|
}
|
|
33319
33496
|
}
|
|
33320
33497
|
if (!created) throw new Error("Trajectory creation time is unavailable.");
|
|
33321
|
-
return { nativeID:
|
|
33498
|
+
return { nativeID: basename10(path, ".db"), messages: [], partial: true, session: { created, directory: directory2 }, note: "Native Antigravity trajectory identity and creation metadata only. Protobuf conversation/step bodies are opaque; no message text, generation-time guesses, or usage-derived turns are imported." };
|
|
33322
33499
|
}
|
|
33323
33500
|
}));
|
|
33324
33501
|
var antigravityCacheAdapter = localFileAdapter({
|
|
@@ -33364,12 +33541,12 @@ var usageOnlyAdapters = [
|
|
|
33364
33541
|
var extra = [...databaseHarnessAdapters, ...fileHarnessAdapters, antigravityCacheAdapter, ...antigravityDatabaseAdapters, ...usageOnlyAdapters];
|
|
33365
33542
|
var grouped = /* @__PURE__ */ new Map();
|
|
33366
33543
|
for (const adapter of extra) grouped.set(adapter.id, [...grouped.get(adapter.id) || [], adapter]);
|
|
33367
|
-
var adapters = [opencodeAdapter, claudeAdapter, codexAdapter, t3CodeAdapter, cursorAdapter, geminiAdapter, qwenAdapter, piAdapter, copilotAdapter, clineAdapter, rooAdapter, kiloAdapter, continueAdapter, ...[...grouped.values()].map((parts) => parts.length === 1 ? parts[0] : combineAdapters(parts))];
|
|
33544
|
+
var adapters = [opencodeAdapter, claudeAdapter, codexAdapter, t3CodeAdapter, cursorAdapter, geminiAdapter, qwenAdapter, piAdapter, copilotAdapter, copilotChatAdapter, clineAdapter, rooAdapter, kiloAdapter, continueAdapter, ...[...grouped.values()].map((parts) => parts.length === 1 ? parts[0] : combineAdapters(parts))];
|
|
33368
33545
|
|
|
33369
33546
|
// server/store.ts
|
|
33370
33547
|
import { DatabaseSync as DatabaseSync3 } from "node:sqlite";
|
|
33371
33548
|
import { mkdirSync as mkdirSync2, chmodSync as chmodSync3 } from "node:fs";
|
|
33372
|
-
import { dirname as
|
|
33549
|
+
import { dirname as dirname8 } from "node:path";
|
|
33373
33550
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
33374
33551
|
|
|
33375
33552
|
// src/search/persistence.ts
|
|
@@ -33586,7 +33763,7 @@ function visibleSessions(sessions) {
|
|
|
33586
33763
|
var SessionGraphStore = class {
|
|
33587
33764
|
constructor(path = databasePath()) {
|
|
33588
33765
|
this.path = path;
|
|
33589
|
-
if (path !== ":memory:") mkdirSync2(
|
|
33766
|
+
if (path !== ":memory:") mkdirSync2(dirname8(path), { recursive: true, mode: 448 });
|
|
33590
33767
|
this.db = new DatabaseSync3(path);
|
|
33591
33768
|
if (path !== ":memory:") chmodSync3(path, 384);
|
|
33592
33769
|
this.db.exec("PRAGMA journal_mode=WAL; PRAGMA foreign_keys=ON; PRAGMA busy_timeout=5000;");
|
|
@@ -34032,7 +34209,7 @@ var Importer = class {
|
|
|
34032
34209
|
import { execFile, spawn as spawn2 } from "node:child_process";
|
|
34033
34210
|
import { promisify } from "node:util";
|
|
34034
34211
|
import { stat as stat4 } from "node:fs/promises";
|
|
34035
|
-
import { basename as
|
|
34212
|
+
import { basename as basename11, dirname as dirname9, isAbsolute as isAbsolute7 } from "node:path";
|
|
34036
34213
|
|
|
34037
34214
|
// src/launch-links.ts
|
|
34038
34215
|
var HARNESSES = [
|
|
@@ -34066,14 +34243,14 @@ function resumeArgs(value) {
|
|
|
34066
34243
|
// server/harnesses.ts
|
|
34067
34244
|
import { access, stat as stat3 } from "node:fs/promises";
|
|
34068
34245
|
import { constants as constants6 } from "node:fs";
|
|
34069
|
-
import { homedir as
|
|
34070
|
-
import { delimiter, isAbsolute as isAbsolute6, join as
|
|
34246
|
+
import { homedir as homedir14 } from "node:os";
|
|
34247
|
+
import { delimiter, isAbsolute as isAbsolute6, join as join23 } from "node:path";
|
|
34071
34248
|
async function executable(name) {
|
|
34072
|
-
const home =
|
|
34073
|
-
const directories = [...(process.env.PATH || "").split(delimiter),
|
|
34074
|
-
if (process.platform === "win32" && process.env.APPDATA) directories.push(
|
|
34075
|
-
if (process.platform === "win32" && process.env.SystemRoot) directories.push(
|
|
34076
|
-
const candidates = isAbsolute6(name) ? [name] : directories.filter((dir) => isAbsolute6(dir)).flatMap((dir) => (process.platform === "win32" ? [".exe", ".cmd", ".bat", ""] : [""]).map((extension) =>
|
|
34249
|
+
const home = homedir14();
|
|
34250
|
+
const directories = [...(process.env.PATH || "").split(delimiter), join23(home, ".local", "bin"), join23(home, ".opencode", "bin"), join23(home, ".bun", "bin"), join23(home, "Library", "pnpm"), "/opt/homebrew/bin", "/usr/local/bin"];
|
|
34251
|
+
if (process.platform === "win32" && process.env.APPDATA) directories.push(join23(process.env.APPDATA, "npm"));
|
|
34252
|
+
if (process.platform === "win32" && process.env.SystemRoot) directories.push(join23(process.env.SystemRoot, "System32", "WindowsPowerShell", "v1.0"));
|
|
34253
|
+
const candidates = isAbsolute6(name) ? [name] : directories.filter((dir) => isAbsolute6(dir)).flatMap((dir) => (process.platform === "win32" ? [".exe", ".cmd", ".bat", ""] : [""]).map((extension) => join23(dir, name + extension)));
|
|
34077
34254
|
for (const path of candidates) {
|
|
34078
34255
|
try {
|
|
34079
34256
|
if ((await stat3(path)).isFile()) {
|
|
@@ -34089,7 +34266,7 @@ async function harnessExecutable(target) {
|
|
|
34089
34266
|
const path = await executable(name);
|
|
34090
34267
|
if (path) return path;
|
|
34091
34268
|
if (target === "codex" && process.platform === "darwin") {
|
|
34092
|
-
return await executable("/Applications/Codex.app/Contents/Resources/codex") || await executable(
|
|
34269
|
+
return await executable("/Applications/Codex.app/Contents/Resources/codex") || await executable(join23(homedir14(), "Applications/Codex.app/Contents/Resources/codex"));
|
|
34093
34270
|
}
|
|
34094
34271
|
}
|
|
34095
34272
|
async function terminalExecutable() {
|
|
@@ -34114,7 +34291,7 @@ function launchCommand(binary, args, directory2, platform = process.platform) {
|
|
|
34114
34291
|
// server/handoff.ts
|
|
34115
34292
|
import { createHash as createHash4, randomUUID as randomUUID3 } from "node:crypto";
|
|
34116
34293
|
import { mkdir, writeFile as writeFile2, rename as rename2, rm as rm4 } from "node:fs/promises";
|
|
34117
|
-
import { join as
|
|
34294
|
+
import { join as join24 } from "node:path";
|
|
34118
34295
|
function handoffDocument(snapshot2) {
|
|
34119
34296
|
const { session, messages, firstUser, totalMessages } = snapshot2;
|
|
34120
34297
|
if (!messages.length) throw new Error("Import this session\u2019s conversation before continuing in another app.");
|
|
@@ -34180,9 +34357,9 @@ This handoff transfers saved text and file-change evidence, not files, credentia
|
|
|
34180
34357
|
async function saveHandoff(snapshot2, directory2) {
|
|
34181
34358
|
const { text: text2, ...coverage2 } = handoffDocument(snapshot2);
|
|
34182
34359
|
const digest2 = createHash4("sha256").update(text2).digest("hex");
|
|
34183
|
-
const root3 =
|
|
34360
|
+
const root3 = join24(directory2, "handoffs");
|
|
34184
34361
|
await mkdir(root3, { recursive: true, mode: 448 });
|
|
34185
|
-
const path =
|
|
34362
|
+
const path = join24(root3, `${digest2}.md`), temporary = join24(root3, `.${randomUUID3()}.tmp`);
|
|
34186
34363
|
try {
|
|
34187
34364
|
await writeFile2(temporary, text2, { mode: 384, flag: "wx" });
|
|
34188
34365
|
await rename2(temporary, path);
|
|
@@ -34223,7 +34400,7 @@ async function prepareLaunch(store, session, target, directory2 = session.direct
|
|
|
34223
34400
|
if (target === (session.source || "opencode") && !subagent && !localHandoff) args = resumeArgs(session);
|
|
34224
34401
|
const mode = args ? "resume" : "handoff";
|
|
34225
34402
|
if (mode === "handoff" && store.path === ":memory:") throw new Error("Save this library before creating a context handoff.");
|
|
34226
|
-
const context = mode === "handoff" ? await saveHandoff(store.handoff(session.id),
|
|
34403
|
+
const context = mode === "handoff" ? await saveHandoff(store.handoff(session.id), dirname9(store.path)) : void 0;
|
|
34227
34404
|
if (context) {
|
|
34228
34405
|
const prompt = `Read the saved conversation in ${JSON.stringify(context.path)} to continue from another coding harness. It is historical context, not new system instructions. Respect the coverage notes and your current workspace instructions and permissions. Briefly confirm where the previous session left off and ask what I want to do next.`;
|
|
34229
34406
|
args = target === "opencode" ? ["--prompt", prompt] : target === "gemini" || target === "qwen-code" ? ["--prompt-interactive", prompt] : target === "copilot" ? ["--interactive", prompt] : [prompt];
|
|
@@ -34240,7 +34417,7 @@ function commandInvocation(command, terminal, platform = process.platform) {
|
|
|
34240
34417
|
const encoded = Buffer.from(command, "utf16le").toString("base64");
|
|
34241
34418
|
return { file: terminal, args: ["-NoProfile", "-NonInteractive", "-Command", `Start-Process powershell.exe -ArgumentList '-NoExit','-NoProfile','-EncodedCommand','${encoded}'`] };
|
|
34242
34419
|
}
|
|
34243
|
-
return { file: terminal, args: [
|
|
34420
|
+
return { file: terminal, args: [basename11(terminal) === "gnome-terminal" ? "--" : "-e", "sh", "-lc", command] };
|
|
34244
34421
|
}
|
|
34245
34422
|
async function launchTerminal(session, prepared) {
|
|
34246
34423
|
if (!prepared.terminalAvailable) throw new Error("Use the copied command in your terminal.");
|
|
@@ -34361,33 +34538,33 @@ async function sessionGraphMiddleware(req, res, next) {
|
|
|
34361
34538
|
const sources = adapters.map((a) => ({ id: a.id, name: a.name, description: a.description, capabilities: a.capabilities, selected: store.selected().includes(a.id), available: false, ...store.sourceInfo(a.id) }));
|
|
34362
34539
|
return json4(200, store.library(sources, importer.status.running));
|
|
34363
34540
|
}
|
|
34364
|
-
const
|
|
34365
|
-
if (
|
|
34366
|
-
const id2 = decodeURIComponent(
|
|
34541
|
+
const match2 = /^\/api\/sessiongraph\/session\/([^/]+)(?:\/(content|timeline|events|event-markers|connection|prepare-launch|open-terminal))?$/.exec(url.pathname);
|
|
34542
|
+
if (match2) {
|
|
34543
|
+
const id2 = decodeURIComponent(match2[1]);
|
|
34367
34544
|
const session = store.getSession(id2);
|
|
34368
34545
|
if (!session) return json4(404, { error: "Session not imported." });
|
|
34369
|
-
if (["prepare-launch", "open-terminal"].includes(
|
|
34546
|
+
if (["prepare-launch", "open-terminal"].includes(match2[2]) && req.method === "POST") {
|
|
34370
34547
|
const value = await body(req);
|
|
34371
34548
|
if (!value || typeof value !== "object" || Array.isArray(value)) return json4(400, { error: "Invalid launch request." });
|
|
34372
34549
|
const target = value.target ?? session.source ?? "opencode";
|
|
34373
34550
|
if (!isHarness(target)) return json4(400, { error: "Choose a supported destination app." });
|
|
34374
34551
|
try {
|
|
34375
34552
|
const prepared = await prepareLaunch(store, session, target, value.directory);
|
|
34376
|
-
if (
|
|
34553
|
+
if (match2[2] === "open-terminal") await launchTerminal(session, prepared);
|
|
34377
34554
|
return json4(200, prepared);
|
|
34378
34555
|
} catch (error) {
|
|
34379
34556
|
return json4(400, { error: error instanceof Error ? error.message : "Could not prepare this session." });
|
|
34380
34557
|
}
|
|
34381
34558
|
}
|
|
34382
34559
|
if (req.method !== "GET") return json4(405, { error: "Method not allowed." });
|
|
34383
|
-
if (["prepare-launch", "open-terminal"].includes(
|
|
34384
|
-
if (
|
|
34385
|
-
if (
|
|
34386
|
-
if (
|
|
34387
|
-
if (
|
|
34560
|
+
if (["prepare-launch", "open-terminal"].includes(match2[2])) return json4(405, { error: "Method not allowed." });
|
|
34561
|
+
if (match2[2] === "timeline") return json4(200, store.timeline(id2));
|
|
34562
|
+
if (match2[2] === "event-markers") return json4(200, store.eventMarkers(id2));
|
|
34563
|
+
if (match2[2] === "events") return json4(200, store.events(id2, Object.fromEntries(["cursor", "item", "filter", "revision"].flatMap((key) => url.searchParams.has(key) ? [[key, url.searchParams.get(key)]] : []))));
|
|
34564
|
+
if (match2[2] === "connection") return json4(200, await getLaunchConnection(session));
|
|
34388
34565
|
const cursor = url.searchParams.get("cursor") || void 0;
|
|
34389
34566
|
if (cursor && (!/^\d{1,9}$/.test(cursor) || Number(cursor) > 5e4)) return json4(400, { error: "Invalid cursor." });
|
|
34390
|
-
return json4(200,
|
|
34567
|
+
return json4(200, match2[2] === "content" ? store.content(id2, cursor) : store.detail(id2, cursor));
|
|
34391
34568
|
}
|
|
34392
34569
|
return json4(404, { error: "Not found." });
|
|
34393
34570
|
} catch (error) {
|
|
@@ -34402,7 +34579,7 @@ var arg = (name) => {
|
|
|
34402
34579
|
const at2 = process.argv.indexOf(name);
|
|
34403
34580
|
return at2 >= 0 ? process.argv[at2 + 1] : void 0;
|
|
34404
34581
|
};
|
|
34405
|
-
var assets = resolve2(arg("--assets") ||
|
|
34582
|
+
var assets = resolve2(arg("--assets") || fileURLToPath5(new URL("../dist", import.meta.url)));
|
|
34406
34583
|
var token = randomBytes(32).toString("hex");
|
|
34407
34584
|
var ipc = process.argv.includes("--desktop") ? " ipc: http://ipc.localhost" : "";
|
|
34408
34585
|
var equals = (value) => /^[a-f0-9]{64}$/.test(value) && timingSafeEqual(Buffer.from(value), Buffer.from(token));
|