sessiongraph-app-darwin-arm64 1.0.11 → 1.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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 +157 -53
- package/payload/SessionGraph.app/Contents/Resources/resources/web/assets/{external-links-CJk2OPKW.js → external-links-D0O8IeG0.js} +1 -1
- package/payload/SessionGraph.app/Contents/Resources/resources/web/assets/{index-JjTdnq9-.js → index-BS2Voifb.js} +1 -1
- package/payload/SessionGraph.app/Contents/Resources/resources/web/assets/{index-DPovJIlT.js → index-CIhs02tq.js} +5 -5
- package/payload/SessionGraph.app/Contents/Resources/resources/web/assets/{index-DhlS3ZId.js → index-GTrhxXlP.js} +1 -1
- package/payload/SessionGraph.app/Contents/Resources/resources/web/assets/{index-DOYyn-b_.js → index-Vq4WYmzW.js} +1 -1
- package/payload/SessionGraph.app/Contents/Resources/resources/web/assets/{publishing-CkVIjq_f.js → publishing-ofssf6d6.js} +1 -1
- package/payload/SessionGraph.app/Contents/Resources/resources/web/assets/{scene-BXs8B_Kk.js → scene-KCDTPCOD.js} +1 -1
- package/payload/SessionGraph.app/Contents/Resources/resources/web/assets/{share-jfOenMTA.js → share-DKeJCFAo.js} +3 -3
- package/payload/SessionGraph.app/Contents/Resources/resources/web/assets/worker-C10U_apJ.js +2 -0
- package/payload/SessionGraph.app/Contents/Resources/resources/web/index.html +1 -1
- package/payload/SessionGraph.app/Contents/_CodeSignature/CodeResources +44 -44
- package/payload/SessionGraph.app/Contents/Resources/resources/web/assets/worker-DwqxiDWY.js +0 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sessiongraph-app-darwin-arm64",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.12",
|
|
4
4
|
"description": "Explore & visualize all your LLM sessions — darwin/arm64",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"access": "public",
|
|
11
11
|
"registry": "https://registry.npmjs.org/"
|
|
12
12
|
},
|
|
13
|
-
"sessionGraphCommit": "
|
|
13
|
+
"sessionGraphCommit": "d99e40d05031062b93e980d62c5fd68e296d7e2c",
|
|
14
14
|
"os": [
|
|
15
15
|
"darwin"
|
|
16
16
|
],
|
|
@@ -17,9 +17,9 @@
|
|
|
17
17
|
<key>CFBundlePackageType</key>
|
|
18
18
|
<string>APPL</string>
|
|
19
19
|
<key>CFBundleShortVersionString</key>
|
|
20
|
-
<string>1.0.
|
|
20
|
+
<string>1.0.12</string>
|
|
21
21
|
<key>CFBundleVersion</key>
|
|
22
|
-
<string>1.0.
|
|
22
|
+
<string>1.0.12</string>
|
|
23
23
|
<key>CSResourcesFileMapped</key>
|
|
24
24
|
<true/>
|
|
25
25
|
<key>LSApplicationCategoryType</key>
|
|
Binary file
|
|
@@ -2627,12 +2627,12 @@ var serviceFile = (env = process.env) => env.SESSIONGRAPH_SERVICE_FILE || env.SE
|
|
|
2627
2627
|
function databasePath(env = process.env, platform = process.platform, home = homedir2()) {
|
|
2628
2628
|
const override = env.SESSIONGRAPH_DATA_DIR || env.SESSION_ATLAS_DATA_DIR || env.ATLAS_DATA_DIR;
|
|
2629
2629
|
const base = platform === "darwin" ? join2(home, "Library", "Application Support") : platform === "win32" ? env.LOCALAPPDATA || home : env.XDG_DATA_HOME || join2(home, ".local", "share");
|
|
2630
|
-
const
|
|
2630
|
+
const paths2 = [
|
|
2631
2631
|
join2(override || join2(base, platform === "linux" ? "sessiongraph" : "SessionGraph"), "sessiongraph.sqlite"),
|
|
2632
2632
|
join2(override || join2(base, platform === "linux" ? "session-atlas" : "Session Atlas"), "session-atlas.sqlite"),
|
|
2633
2633
|
join2(override || join2(base, platform === "linux" ? "atlas" : "Atlas"), "atlas.sqlite")
|
|
2634
2634
|
];
|
|
2635
|
-
return
|
|
2635
|
+
return paths2.find((path) => existsSync(path)) || paths2[0];
|
|
2636
2636
|
}
|
|
2637
2637
|
|
|
2638
2638
|
// src/playback-tokens.ts
|
|
@@ -2738,7 +2738,7 @@ function editedPaths(part) {
|
|
|
2738
2738
|
}
|
|
2739
2739
|
return [];
|
|
2740
2740
|
}
|
|
2741
|
-
function summarizeMessages(id2, messages,
|
|
2741
|
+
function summarizeMessages(id2, messages, nextCursor2) {
|
|
2742
2742
|
const files = /* @__PURE__ */ new Map();
|
|
2743
2743
|
const tools = /* @__PURE__ */ new Map();
|
|
2744
2744
|
const locations = [];
|
|
@@ -2770,8 +2770,8 @@ function summarizeMessages(id2, messages, nextCursor) {
|
|
|
2770
2770
|
locations,
|
|
2771
2771
|
messagesScanned: messages.length,
|
|
2772
2772
|
snapshotSteps,
|
|
2773
|
-
partial: Boolean(
|
|
2774
|
-
nextCursor,
|
|
2773
|
+
partial: Boolean(nextCursor2),
|
|
2774
|
+
nextCursor: nextCursor2,
|
|
2775
2775
|
loadedAt: Date.now()
|
|
2776
2776
|
};
|
|
2777
2777
|
}
|
|
@@ -30778,6 +30778,29 @@ function successfulEdits(messages, editNames) {
|
|
|
30778
30778
|
|
|
30779
30779
|
// server/adapters/pi.ts
|
|
30780
30780
|
import { homedir as homedir3 } from "node:os";
|
|
30781
|
+
|
|
30782
|
+
// server/source-paths.ts
|
|
30783
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
30784
|
+
var paths = new AsyncLocalStorage();
|
|
30785
|
+
var sourcePath = (id2) => paths.getStore()?.[id2];
|
|
30786
|
+
function withSourcePaths(adapter, configured) {
|
|
30787
|
+
return {
|
|
30788
|
+
...adapter,
|
|
30789
|
+
detect: () => paths.run(configured(), () => adapter.detect()),
|
|
30790
|
+
discover: () => paths.run(configured(), async () => {
|
|
30791
|
+
const result = await adapter.discover();
|
|
30792
|
+
if (!sourcePath(adapter.id)) return result;
|
|
30793
|
+
return { ...result, sessions: result.sessions.map((candidate) => ({ ...candidate, session: { ...candidate.session, nativeResume: false } })) };
|
|
30794
|
+
}),
|
|
30795
|
+
read: (candidate, cursor) => paths.run(configured(), async () => {
|
|
30796
|
+
const result = await adapter.read(candidate, cursor);
|
|
30797
|
+
if (sourcePath(adapter.id)) candidate.session.nativeResume = false;
|
|
30798
|
+
return result;
|
|
30799
|
+
})
|
|
30800
|
+
};
|
|
30801
|
+
}
|
|
30802
|
+
|
|
30803
|
+
// server/adapters/pi.ts
|
|
30781
30804
|
import { join as join5 } from "node:path";
|
|
30782
30805
|
function piHistory(value) {
|
|
30783
30806
|
const { rows: rows2, partial } = jsonLines(value);
|
|
@@ -30809,11 +30832,11 @@ var piAdapter = localFileAdapter({
|
|
|
30809
30832
|
name: "Pi",
|
|
30810
30833
|
description: "Local JSONL sessions \xB7 messages, tools, compaction, and branch entries",
|
|
30811
30834
|
capabilities: { history: true, forks: false, children: false, files: true },
|
|
30812
|
-
roots: () => [process.env.SESSIONGRAPH_PI_SESSIONS_DIR || join5(process.env.PI_CODING_AGENT_DIR || join5(homedir3(), ".pi", "agent"), "sessions")],
|
|
30835
|
+
roots: () => [sourcePath("pi") || process.env.SESSIONGRAPH_PI_SESSIONS_DIR || join5(process.env.PI_CODING_AGENT_DIR || join5(homedir3(), ".pi", "agent"), "sessions")],
|
|
30813
30836
|
match: (path) => path.endsWith(".jsonl"),
|
|
30814
30837
|
parse(path, files) {
|
|
30815
30838
|
const history = piHistory(files.get(path));
|
|
30816
|
-
history.session.nativeResume = Boolean(history.session.directory) && !process.env.SESSIONGRAPH_PI_SESSIONS_DIR;
|
|
30839
|
+
history.session.nativeResume = Boolean(history.session.directory) && !sourcePath("pi") && !process.env.SESSIONGRAPH_PI_SESSIONS_DIR;
|
|
30817
30840
|
return history;
|
|
30818
30841
|
}
|
|
30819
30842
|
});
|
|
@@ -31183,9 +31206,9 @@ function sqliteHistoryAdapter(source) {
|
|
|
31183
31206
|
}
|
|
31184
31207
|
};
|
|
31185
31208
|
}
|
|
31186
|
-
async function existingDatabases(
|
|
31209
|
+
async function existingDatabases(paths2) {
|
|
31187
31210
|
const found = [];
|
|
31188
|
-
for (const path of new Set(
|
|
31211
|
+
for (const path of new Set(paths2)) {
|
|
31189
31212
|
try {
|
|
31190
31213
|
if ((await lstat3(path)).isFile()) found.push(path);
|
|
31191
31214
|
} catch (e10) {
|
|
@@ -31230,7 +31253,7 @@ function combineAdapters(parts) {
|
|
|
31230
31253
|
}
|
|
31231
31254
|
|
|
31232
31255
|
// server/adapters/claude.ts
|
|
31233
|
-
var root = () => join8(process.env.CLAUDE_CONFIG_DIR || join8(homedir4(), ".claude"), "projects");
|
|
31256
|
+
var root = () => join8(sourcePath("claude-code") || process.env.CLAUDE_CONFIG_DIR || join8(homedir4(), ".claude"), "projects");
|
|
31234
31257
|
function claudeMessages(rows2, candidate, times) {
|
|
31235
31258
|
const calls = /* @__PURE__ */ new Map();
|
|
31236
31259
|
return rows2.map((row) => {
|
|
@@ -31275,7 +31298,7 @@ var sdkClaudeAdapter = {
|
|
|
31275
31298
|
},
|
|
31276
31299
|
async discover() {
|
|
31277
31300
|
const sessions = [], warnings = [];
|
|
31278
|
-
const infos = await I1t({ limit: 2e4, includeProgrammatic: true });
|
|
31301
|
+
const infos = sourcePath("claude-code") ? [] : await I1t({ limit: 2e4, includeProgrammatic: true });
|
|
31279
31302
|
if (infos.length === 2e4) warnings.push("Claude Code listing is limited to 20,000 sessions.");
|
|
31280
31303
|
const files = /* @__PURE__ */ new Map();
|
|
31281
31304
|
let unreadable = 0;
|
|
@@ -31368,7 +31391,7 @@ var exportedClaudeAdapter = localFileAdapter({
|
|
|
31368
31391
|
name: "Claude Code",
|
|
31369
31392
|
description: "Legacy local transcript exports",
|
|
31370
31393
|
capabilities: { history: true, forks: false, children: false, files: false },
|
|
31371
|
-
roots: () => [join8(process.env.CLAUDE_CONFIG_DIR || join8(homedir4(), ".claude"), "transcripts")],
|
|
31394
|
+
roots: () => [join8(sourcePath("claude-code") || process.env.CLAUDE_CONFIG_DIR || join8(homedir4(), ".claude"), "transcripts")],
|
|
31372
31395
|
match: (p) => p.endsWith(".jsonl"),
|
|
31373
31396
|
parse: (path, files) => envelopeHistory(path, files.get(path))
|
|
31374
31397
|
});
|
|
@@ -31473,7 +31496,7 @@ async function transcriptFiles(root3, max = 2e4, match2 = (name) => name.endsWit
|
|
|
31473
31496
|
}
|
|
31474
31497
|
|
|
31475
31498
|
// server/adapters/codex.ts
|
|
31476
|
-
var root2 = () => process.env.CODEX_HOME || join10(homedir5(), ".codex");
|
|
31499
|
+
var root2 = () => sourcePath("codex") || process.env.CODEX_HOME || join10(homedir5(), ".codex");
|
|
31477
31500
|
var revision = async (path) => {
|
|
31478
31501
|
const s = await stat2(path);
|
|
31479
31502
|
return digest([8, s.mtimeMs, s.size]);
|
|
@@ -31574,10 +31597,10 @@ var codexAdapter = {
|
|
|
31574
31597
|
const found = /* @__PURE__ */ new Map(), warnings = [];
|
|
31575
31598
|
const names = await sessionNames();
|
|
31576
31599
|
const match2 = (name) => /\.jsonl(?:\.[\w.-]+)?$/.test(name);
|
|
31577
|
-
const
|
|
31578
|
-
if (
|
|
31600
|
+
const paths2 = [...await transcriptFiles(join10(root2(), "sessions"), 2e4, match2), ...await transcriptFiles(join10(root2(), "archived_sessions"), 2e4, match2)];
|
|
31601
|
+
if (paths2.length >= 2e4) warnings.push("Codex transcript listing may be partial (20,000 files per history folder).");
|
|
31579
31602
|
let unsupported = 0;
|
|
31580
|
-
for (const path of
|
|
31603
|
+
for (const path of paths2) {
|
|
31581
31604
|
try {
|
|
31582
31605
|
const first = await readJSONL(path, 0, 2e6, 100);
|
|
31583
31606
|
const meta = first.rows.find((r) => r.value.type === "session_meta")?.value.payload;
|
|
@@ -31652,14 +31675,14 @@ function status(value) {
|
|
|
31652
31675
|
return ["pending", "running", "completed", "failed"].includes(string(value)) ? value : "unknown";
|
|
31653
31676
|
}
|
|
31654
31677
|
async function databasePath2() {
|
|
31655
|
-
const root3 = process.env.SESSIONGRAPH_T3_CODE_HISTORY_DIR || process.env.T3CODE_HOME || join11(homedir6(), ".t3");
|
|
31656
|
-
const
|
|
31678
|
+
const root3 = sourcePath("t3-code") || process.env.SESSIONGRAPH_T3_CODE_HISTORY_DIR || process.env.T3CODE_HOME || join11(homedir6(), ".t3");
|
|
31679
|
+
const paths2 = /\.sqlite$/.test(root3) ? [root3] : [
|
|
31657
31680
|
join11(root3, "userdata", "statev2.sqlite"),
|
|
31658
31681
|
join11(root3, "statev2.sqlite"),
|
|
31659
31682
|
join11(root3, "userdata", "state.sqlite"),
|
|
31660
31683
|
join11(root3, "state.sqlite")
|
|
31661
31684
|
];
|
|
31662
|
-
for (const path of
|
|
31685
|
+
for (const path of paths2) {
|
|
31663
31686
|
try {
|
|
31664
31687
|
if ((await lstat4(path)).isFile()) return path;
|
|
31665
31688
|
} catch (error) {
|
|
@@ -32314,7 +32337,7 @@ async function workspacePaths(root3, warnings) {
|
|
|
32314
32337
|
return stores;
|
|
32315
32338
|
}
|
|
32316
32339
|
function createCursorAdapter(options = {}) {
|
|
32317
|
-
const root3 = () => options.home || process.env.SESSIONGRAPH_CURSOR_HOME || process.env.SESSION_ATLAS_CURSOR_HOME || join13(homedir7(), ".cursor");
|
|
32340
|
+
const root3 = () => options.home || sourcePath("cursor") || process.env.SESSIONGRAPH_CURSOR_HOME || process.env.SESSION_ATLAS_CURSOR_HOME || join13(homedir7(), ".cursor");
|
|
32318
32341
|
const editor = () => options.userData || process.env.SESSIONGRAPH_CURSOR_USER_DATA_DIR || process.env.SESSION_ATLAS_CURSOR_USER_DATA_DIR || userData();
|
|
32319
32342
|
return {
|
|
32320
32343
|
id: "cursor",
|
|
@@ -32337,7 +32360,7 @@ function createCursorAdapter(options = {}) {
|
|
|
32337
32360
|
async discover() {
|
|
32338
32361
|
const warnings = [], found = /* @__PURE__ */ new Map(), blocked = /* @__PURE__ */ new Set();
|
|
32339
32362
|
const workspaceStores = await workspacePaths(editor(), warnings);
|
|
32340
|
-
const
|
|
32363
|
+
const paths2 = [...new Set([...workspaceStores.values()].filter(Boolean))];
|
|
32341
32364
|
const legacyStores = new Map([[join13(editor(), "User/globalStorage/state.vscdb"), ""], ...workspaceStores]);
|
|
32342
32365
|
for (const [path, workspace] of legacyStores) {
|
|
32343
32366
|
try {
|
|
@@ -32358,7 +32381,7 @@ function createCursorAdapter(options = {}) {
|
|
|
32358
32381
|
}
|
|
32359
32382
|
const composers = new Map(found);
|
|
32360
32383
|
const match2 = (key, encode) => {
|
|
32361
|
-
const matches =
|
|
32384
|
+
const matches = paths2.filter((path) => encode(path) === key);
|
|
32362
32385
|
return matches.length === 1 ? matches[0] : "";
|
|
32363
32386
|
};
|
|
32364
32387
|
let unreadable = 0, legacy = 0, scanned = 0;
|
|
@@ -32565,7 +32588,7 @@ var geminiAdapter = localFileAdapter({
|
|
|
32565
32588
|
name: "Gemini CLI",
|
|
32566
32589
|
description: "Local JSON and JSONL chats, including recorded subagent histories",
|
|
32567
32590
|
capabilities: { history: true, forks: false, children: true, files: true },
|
|
32568
|
-
roots: () => process.env.SESSIONGRAPH_GEMINI_HOME ? [join14(process.env.SESSIONGRAPH_GEMINI_HOME, "tmp")] : [join14(process.env.GEMINI_CLI_HOME || homedir8(), ".gemini", "tmp"), join14(process.env.GEMINI_CLI_HOME || homedir8(), ".cache", ".gemini", "tmp")],
|
|
32591
|
+
roots: () => sourcePath("gemini") || process.env.SESSIONGRAPH_GEMINI_HOME ? [join14(sourcePath("gemini") || process.env.SESSIONGRAPH_GEMINI_HOME, "tmp")] : [join14(process.env.GEMINI_CLI_HOME || homedir8(), ".gemini", "tmp"), join14(process.env.GEMINI_CLI_HOME || homedir8(), ".cache", ".gemini", "tmp")],
|
|
32569
32592
|
match: (path) => /^[^/]+\/chats\/(?:[^/]+\/)?[^/]+\.jsonl?$/.test(path),
|
|
32570
32593
|
extras: (path) => [projectRootFile(path)],
|
|
32571
32594
|
parse(path, files) {
|
|
@@ -32594,7 +32617,7 @@ var geminiAdapter = localFileAdapter({
|
|
|
32594
32617
|
messages,
|
|
32595
32618
|
parent: parent2,
|
|
32596
32619
|
partial,
|
|
32597
|
-
session: { directory: directory2, created: time(meta.startTime), title: text(meta.summary), model: text([...records].reverse().find((r) => r.model)?.model) || "Unknown model", provider: "Google", nativeResume: !parent2 && Boolean(directory2) && !process.env.SESSIONGRAPH_GEMINI_HOME && !path.includes(`${sep3}.cache${sep3}`) },
|
|
32620
|
+
session: { directory: directory2, created: time(meta.startTime), title: text(meta.summary), model: text([...records].reverse().find((r) => r.model)?.model) || "Unknown model", provider: "Google", nativeResume: !parent2 && Boolean(directory2) && !sourcePath("gemini") && !process.env.SESSIONGRAPH_GEMINI_HOME && !path.includes(`${sep3}.cache${sep3}`) },
|
|
32598
32621
|
note: "Local Gemini chat records with rewind and patch reconstruction. Only explicit subagent directories form parent links; workspace paths come from the project-root marker. Binary content is omitted."
|
|
32599
32622
|
};
|
|
32600
32623
|
}
|
|
@@ -32608,7 +32631,7 @@ var qwenAdapter = localFileAdapter({
|
|
|
32608
32631
|
name: "Qwen Code",
|
|
32609
32632
|
description: "Local project chat records \xB7 tool results, forks, and child sessions",
|
|
32610
32633
|
capabilities: { history: true, forks: true, children: true, files: true },
|
|
32611
|
-
roots: () => [join15(process.env.SESSIONGRAPH_QWEN_HOME || process.env.QWEN_RUNTIME_DIR || process.env.QWEN_HOME || join15(homedir9(), ".qwen"), "projects")],
|
|
32634
|
+
roots: () => [join15(sourcePath("qwen-code") || process.env.SESSIONGRAPH_QWEN_HOME || process.env.QWEN_RUNTIME_DIR || process.env.QWEN_HOME || join15(homedir9(), ".qwen"), "projects")],
|
|
32612
32635
|
match: (path) => /^[^/]+\/chats\/[^/]+\.jsonl$/.test(path),
|
|
32613
32636
|
parse(path, files) {
|
|
32614
32637
|
const { rows: rows2, partial } = jsonLines(files.get(path));
|
|
@@ -32638,7 +32661,7 @@ var qwenAdapter = localFileAdapter({
|
|
|
32638
32661
|
partial,
|
|
32639
32662
|
parent: text(parent2) || void 0,
|
|
32640
32663
|
fork: text(rows2.find((r) => r.forkedFrom?.sessionId)?.forkedFrom?.sessionId) || void 0,
|
|
32641
|
-
session: { directory: text(first.cwd), created: time(first.timestamp), title: text(title), model: text(latest.find((r) => r.model)?.model) || text(latest.find((r) => r.subtype === "session_model")?.systemPayload?.modelId) || "Unknown model", nativeResume: Boolean(first.cwd) && !process.env.SESSIONGRAPH_QWEN_HOME },
|
|
32664
|
+
session: { directory: text(first.cwd), created: time(first.timestamp), title: text(title), model: text(latest.find((r) => r.model)?.model) || text(latest.find((r) => r.subtype === "session_model")?.systemPayload?.modelId) || "Unknown model", nativeResume: Boolean(first.cwd) && !sourcePath("qwen-code") && !process.env.SESSIONGRAPH_QWEN_HOME },
|
|
32642
32665
|
note: "Local Qwen chat records, including compaction and branch events in source order. Parent and fork links use recorded session IDs. Managed-daemon-only and binary history may be unavailable."
|
|
32643
32666
|
};
|
|
32644
32667
|
}
|
|
@@ -32652,7 +32675,7 @@ var copilotAdapter = localFileAdapter({
|
|
|
32652
32675
|
name: "GitHub Copilot CLI",
|
|
32653
32676
|
description: "Local session event logs \xB7 conversations and completed file edits",
|
|
32654
32677
|
capabilities: { history: true, forks: false, children: true, files: true },
|
|
32655
|
-
roots: () => [join16(process.env.SESSIONGRAPH_COPILOT_HOME || join16(homedir10(), ".copilot"), "session-state")],
|
|
32678
|
+
roots: () => [join16(sourcePath("copilot") || process.env.SESSIONGRAPH_COPILOT_HOME || join16(homedir10(), ".copilot"), "session-state")],
|
|
32656
32679
|
match: (path) => /(?:^|\/)events\.jsonl$/.test(path),
|
|
32657
32680
|
parse(path, files) {
|
|
32658
32681
|
const { rows: rows2, partial } = jsonLines(files.get(path));
|
|
@@ -32692,7 +32715,7 @@ var copilotAdapter = localFileAdapter({
|
|
|
32692
32715
|
messages,
|
|
32693
32716
|
partial,
|
|
32694
32717
|
parent: text(meta.detachedFromSpawningParentSessionId) || void 0,
|
|
32695
|
-
session: { directory: text(meta.context?.cwd), created: time(meta.startTime || start?.timestamp), title: text(latest.find((r) => r.type === "session.title_changed")?.data?.title), model: text(latest.find((r) => r.type === "session.model_change")?.data?.newModel) || text(meta.selectedModel) || "Unknown model", provider: text(meta.providerId), nativeResume: Boolean(meta.context?.cwd) && !process.env.SESSIONGRAPH_COPILOT_HOME },
|
|
32718
|
+
session: { directory: text(meta.context?.cwd), created: time(meta.startTime || start?.timestamp), title: text(latest.find((r) => r.type === "session.title_changed")?.data?.title), model: text(latest.find((r) => r.type === "session.model_change")?.data?.newModel) || text(meta.selectedModel) || "Unknown model", provider: text(meta.providerId), nativeResume: Boolean(meta.context?.cwd) && !sourcePath("copilot") && !process.env.SESSIONGRAPH_COPILOT_HOME },
|
|
32696
32719
|
note: "Persisted Copilot CLI events only. Streaming deltas are excluded in favor of final messages. Tool-call parents are event correlations, not session ancestry. Cloud-only sessions and binary assets are unavailable."
|
|
32697
32720
|
};
|
|
32698
32721
|
}
|
|
@@ -32750,7 +32773,8 @@ function vscodeChatLog(content) {
|
|
|
32750
32773
|
function copilotChatRoots(platform = process.platform, home = homedir11(), env = process.env) {
|
|
32751
32774
|
const path = platform === "win32" ? win322 : posix;
|
|
32752
32775
|
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
|
|
32776
|
+
const override = sourcePath("copilot-chat") || env.SESSIONGRAPH_COPILOT_CHAT_USER_DATA_DIR;
|
|
32777
|
+
const users = override ? [path.join(override, "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
32778
|
return users.flatMap((user) => [path.join(user, "workspaceStorage"), path.join(user, "globalStorage", "emptyWindowChatSessions")]);
|
|
32755
32779
|
}
|
|
32756
32780
|
function vscodeChatPath(value) {
|
|
@@ -32881,7 +32905,8 @@ function editorTaskRoots(extension) {
|
|
|
32881
32905
|
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")));
|
|
32882
32906
|
}
|
|
32883
32907
|
function taskAdapter(id2, name, extension, env) {
|
|
32884
|
-
const
|
|
32908
|
+
const home = () => sourcePath(id2) || process.env[env];
|
|
32909
|
+
const roots2 = () => home() ? [join18(home(), "tasks"), ...id2 === "cline" ? [join18(home(), "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")] : []];
|
|
32885
32910
|
return localFileAdapter({
|
|
32886
32911
|
id: id2,
|
|
32887
32912
|
name,
|
|
@@ -32930,7 +32955,7 @@ var continueAdapter = localFileAdapter({
|
|
|
32930
32955
|
name: "Continue",
|
|
32931
32956
|
description: "Local IDE and CLI session JSON \xB7 recorded conversation and tool history",
|
|
32932
32957
|
capabilities: { history: true, forks: false, children: false, files: false },
|
|
32933
|
-
roots: () => [join18(process.env.SESSIONGRAPH_CONTINUE_HOME || process.env.CONTINUE_GLOBAL_DIR || join18(homedir12(), ".continue"), "sessions")],
|
|
32958
|
+
roots: () => [join18(sourcePath("continue") || process.env.SESSIONGRAPH_CONTINUE_HOME || process.env.CONTINUE_GLOBAL_DIR || join18(homedir12(), ".continue"), "sessions")],
|
|
32934
32959
|
match: (path) => /^[^/]+\.json$/.test(path) && path !== "sessions.json",
|
|
32935
32960
|
extras: (path) => [join18(dirname5(path), "sessions.json")],
|
|
32936
32961
|
revisionExtras: false,
|
|
@@ -32968,7 +32993,7 @@ var appPath = (...parts) => join19(process.platform === "darwin" ? homePath("Lib
|
|
|
32968
32993
|
var tokscalePath = (...parts) => join19(process.env.TOKSCALE_CONFIG_DIR || (process.platform === "win32" ? appPath("tokscale") : configPath("tokscale")), ...parts);
|
|
32969
32994
|
var envHome = (env, fallback, ...parts) => join19(process.env[env]?.trim() || homePath(fallback), ...parts);
|
|
32970
32995
|
var harnessRoots = (id2, defaults) => () => {
|
|
32971
|
-
const override = process.env[`SESSIONGRAPH_${id2.replace(/-/g, "_").toUpperCase()}_HISTORY_DIR`]?.trim();
|
|
32996
|
+
const override = sourcePath(id2) || process.env[`SESSIONGRAPH_${id2.replace(/-/g, "_").toUpperCase()}_HISTORY_DIR`]?.trim();
|
|
32972
32997
|
return override ? [override] : defaults();
|
|
32973
32998
|
};
|
|
32974
32999
|
|
|
@@ -33184,7 +33209,7 @@ var parsedContent = (v3) => typeof v3 === "string" && /^[\[{]/.test(v3.trim()) ?
|
|
|
33184
33209
|
var millisOrSeconds = (v3) => typeof v3 === "number" && v3 > 0 && v3 < 1e10 ? seconds(v3) : time(v3);
|
|
33185
33210
|
function dbPaths(id2, defaults, match2) {
|
|
33186
33211
|
return async () => {
|
|
33187
|
-
const override = process.env[`SESSIONGRAPH_${id2.replace(/-/g, "_").toUpperCase()}_HISTORY_DIR`];
|
|
33212
|
+
const override = sourcePath(id2) || process.env[`SESSIONGRAPH_${id2.replace(/-/g, "_").toUpperCase()}_HISTORY_DIR`];
|
|
33188
33213
|
return override ? (await historyFiles([override], match2)).files : existingDatabases(defaults());
|
|
33189
33214
|
};
|
|
33190
33215
|
}
|
|
@@ -33324,21 +33349,21 @@ var crush = {
|
|
|
33324
33349
|
key: "id",
|
|
33325
33350
|
fields: ["id", "title", "created_at", "updated_at", "cost"],
|
|
33326
33351
|
paths: async () => {
|
|
33327
|
-
const override = process.env.SESSIONGRAPH_CRUSH_HISTORY_DIR;
|
|
33352
|
+
const override = sourcePath("crush") || process.env.SESSIONGRAPH_CRUSH_HISTORY_DIR;
|
|
33328
33353
|
if (override) return (await historyFiles([override], (p) => p.endsWith("crush.db"))).files;
|
|
33329
33354
|
const registry = join22(process.env.CRUSH_GLOBAL_DATA || dataPath("crush"), "projects.json");
|
|
33330
33355
|
try {
|
|
33331
33356
|
const stat6 = await lstat6(registry);
|
|
33332
33357
|
if (!stat6.isFile() || stat6.size > 2e6) throw new Error("Unsupported Crush registry.");
|
|
33333
33358
|
const raw = JSON.parse(await readFile4(registry, "utf8"));
|
|
33334
|
-
const
|
|
33359
|
+
const paths2 = [];
|
|
33335
33360
|
for (const p of Array.isArray(raw.projects) ? raw.projects.slice(0, 2e4) : []) {
|
|
33336
33361
|
if (!isAbsolute5(text(p.path)) || !text(p.data_dir)) continue;
|
|
33337
33362
|
const path = join22(isAbsolute5(p.data_dir) ? p.data_dir : join22(p.path, p.data_dir), "crush.db");
|
|
33338
|
-
|
|
33363
|
+
paths2.push(path);
|
|
33339
33364
|
crushDirectories.set(path, p.path);
|
|
33340
33365
|
}
|
|
33341
|
-
return existingDatabases(
|
|
33366
|
+
return existingDatabases(paths2);
|
|
33342
33367
|
} catch (e10) {
|
|
33343
33368
|
if (e10.code === "ENOENT") return [];
|
|
33344
33369
|
throw e10;
|
|
@@ -33759,6 +33784,46 @@ function visibleSessions(sessions) {
|
|
|
33759
33784
|
}));
|
|
33760
33785
|
}
|
|
33761
33786
|
|
|
33787
|
+
// server/library-query.ts
|
|
33788
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
33789
|
+
|
|
33790
|
+
// packages/core/src/layout.ts
|
|
33791
|
+
var directoryPath = (directory2) => (/^(?:[a-z]:[\\/]|\\\\)/i.test(directory2) ? directory2.replace(/\\/g, "/") : directory2).replace(/\/+$/, "") || (directory2.startsWith("/") ? "/" : "");
|
|
33792
|
+
var laneKey = (session) => session.directory ? JSON.stringify(["directory", directoryPath(session.directory)]) : JSON.stringify(["project", session.source || "opencode", session.projectID || session.id]);
|
|
33793
|
+
|
|
33794
|
+
// server/library-query.ts
|
|
33795
|
+
var LibraryError = class extends Error {
|
|
33796
|
+
constructor(code, message2, exitCode = 1) {
|
|
33797
|
+
super(message2);
|
|
33798
|
+
this.code = code;
|
|
33799
|
+
this.exitCode = exitCode;
|
|
33800
|
+
}
|
|
33801
|
+
code;
|
|
33802
|
+
exitCode;
|
|
33803
|
+
};
|
|
33804
|
+
function invalid(message2) {
|
|
33805
|
+
throw new LibraryError("INVALID_ARGUMENT", message2, 2);
|
|
33806
|
+
}
|
|
33807
|
+
var fingerprint = (value) => createHash4("sha256").update(JSON.stringify(value)).digest("hex");
|
|
33808
|
+
function pageLimit(value = 50) {
|
|
33809
|
+
if (!Number.isSafeInteger(value) || value < 1 || value > 200) invalid("Limit must be an integer from 1 to 200.");
|
|
33810
|
+
return value;
|
|
33811
|
+
}
|
|
33812
|
+
function pageOffset(cursor, key) {
|
|
33813
|
+
if (!cursor) return 0;
|
|
33814
|
+
let parsed;
|
|
33815
|
+
try {
|
|
33816
|
+
if (cursor.length > 512 || !/^[\w-]+$/.test(cursor)) throw new Error();
|
|
33817
|
+
parsed = JSON.parse(Buffer.from(cursor, "base64url").toString());
|
|
33818
|
+
if (!parsed || !Number.isSafeInteger(parsed.offset) || parsed.offset < 0 || typeof parsed.key !== "string") throw new Error();
|
|
33819
|
+
} catch {
|
|
33820
|
+
return invalid("Invalid cursor. Use nextCursor from the previous response.");
|
|
33821
|
+
}
|
|
33822
|
+
if (parsed.key !== key) throw new LibraryError("STALE_CURSOR", "Saved history or query changed. Restart without --cursor.");
|
|
33823
|
+
return parsed.offset;
|
|
33824
|
+
}
|
|
33825
|
+
var nextCursor = (key, offset) => Buffer.from(JSON.stringify({ key, offset })).toString("base64url");
|
|
33826
|
+
|
|
33762
33827
|
// server/store.ts
|
|
33763
33828
|
var SessionGraphStore = class {
|
|
33764
33829
|
constructor(path = databasePath()) {
|
|
@@ -34008,6 +34073,41 @@ var SessionGraphStore = class {
|
|
|
34008
34073
|
truncated ||= this.getSession(id2)?.coverage?.history !== "complete";
|
|
34009
34074
|
return { id: id2, fragments, messages: page.messages.length, nextCursor: page.next, truncated };
|
|
34010
34075
|
}
|
|
34076
|
+
messages(id2, options = {}) {
|
|
34077
|
+
return this.readSnapshot(id2, (session) => {
|
|
34078
|
+
const key = fingerprint(["messages", id2, session.revision, session.coverage]);
|
|
34079
|
+
const offset = pageOffset(options.cursor, key), limit = pageLimit(options.limit);
|
|
34080
|
+
const rows2 = this.messagePage(id2, offset, limit);
|
|
34081
|
+
let remaining = 64e3, truncated = false;
|
|
34082
|
+
const messages = rows2.messages.map((message2) => {
|
|
34083
|
+
const fragments = message2.fragments.slice(0, 200).map((fragment) => {
|
|
34084
|
+
const text2 = fragment.text.slice(0, remaining);
|
|
34085
|
+
remaining -= text2.length;
|
|
34086
|
+
truncated ||= text2.length < fragment.text.length;
|
|
34087
|
+
return { ...fragment, text: text2, truncated: text2.length < fragment.text.length };
|
|
34088
|
+
});
|
|
34089
|
+
truncated ||= !!message2.partial;
|
|
34090
|
+
return {
|
|
34091
|
+
id: message2.id,
|
|
34092
|
+
time: messageTime(message2.time),
|
|
34093
|
+
role: message2.role,
|
|
34094
|
+
fragments,
|
|
34095
|
+
files: message2.files.slice(0, 200),
|
|
34096
|
+
tools: message2.tools.slice(0, 200),
|
|
34097
|
+
partial: !!message2.partial || message2.fragments.length > 200 || message2.files.length > 200 || message2.tools.length > 200 || fragments.some((f) => f.truncated)
|
|
34098
|
+
};
|
|
34099
|
+
});
|
|
34100
|
+
return {
|
|
34101
|
+
sessionID: id2,
|
|
34102
|
+
revision: session.revision,
|
|
34103
|
+
messages,
|
|
34104
|
+
order: "newest-first",
|
|
34105
|
+
nextCursor: rows2.next ? nextCursor(key, Number(rows2.next)) : null,
|
|
34106
|
+
partial: truncated || messages.some((m) => m.partial) || session.coverage?.history !== "complete",
|
|
34107
|
+
coverage: session.coverage
|
|
34108
|
+
};
|
|
34109
|
+
});
|
|
34110
|
+
}
|
|
34011
34111
|
detail(id2, cursor) {
|
|
34012
34112
|
return this.readSnapshot(id2, (session) => {
|
|
34013
34113
|
const page = this.messagePage(id2, Number(cursor || 0), 120);
|
|
@@ -34093,26 +34193,33 @@ import { setImmediate as yieldToIO } from "node:timers/promises";
|
|
|
34093
34193
|
var Importer = class {
|
|
34094
34194
|
constructor(store, adapters2) {
|
|
34095
34195
|
this.store = store;
|
|
34096
|
-
this.adapters = adapters2;
|
|
34196
|
+
this.adapters = adapters2.map((adapter) => withSourcePaths(adapter, () => this.store.setting("sourcePaths") || {}));
|
|
34097
34197
|
}
|
|
34098
34198
|
store;
|
|
34099
|
-
adapters;
|
|
34100
34199
|
status = { running: false, discovered: 0, imported: 0, unchanged: 0, failed: 0, errors: [] };
|
|
34101
34200
|
job;
|
|
34201
|
+
adapters;
|
|
34102
34202
|
async sources() {
|
|
34103
34203
|
return Promise.all(this.adapters.map(async (adapter) => ({ id: adapter.id, name: adapter.name, description: adapter.description, capabilities: adapter.capabilities, available: await adapter.detect().catch(() => false), selected: this.store.selected().includes(adapter.id), ...this.store.sourceInfo(adapter.id) })));
|
|
34104
34204
|
}
|
|
34105
34205
|
start(ids, automatic = false) {
|
|
34206
|
+
return this.begin(ids, automatic, true);
|
|
34207
|
+
}
|
|
34208
|
+
/** A one-off subset refresh never replaces the saved source selection. */
|
|
34209
|
+
sync(ids) {
|
|
34210
|
+
return this.begin(ids, false, false);
|
|
34211
|
+
}
|
|
34212
|
+
begin(ids, automatic, save) {
|
|
34106
34213
|
if (this.job) return this.status;
|
|
34107
34214
|
if (automatic && (!this.store.autoImportEnabled() || !this.store.selected().length)) return this.status;
|
|
34108
34215
|
if (ids?.some((id2) => !this.adapters.some((a) => a.id === id2))) throw new Error("Unknown session source.");
|
|
34109
34216
|
if (!this.store.acquireImport()) throw new Error("Another SessionGraph window is importing this library.");
|
|
34110
|
-
if (ids) {
|
|
34217
|
+
if (ids && save) {
|
|
34111
34218
|
this.store.setting("selected", [...new Set(ids)]);
|
|
34112
34219
|
}
|
|
34113
34220
|
this.status = { running: true, discovered: 0, imported: 0, unchanged: 0, failed: 0, errors: [] };
|
|
34114
34221
|
const heartbeat = setInterval(() => this.store.heartbeat(), 5e3);
|
|
34115
|
-
this.job = this.run().catch(() => {
|
|
34222
|
+
this.job = this.run(ids || this.store.selected()).catch(() => {
|
|
34116
34223
|
this.status.failed++;
|
|
34117
34224
|
this.status.errors.push("Import interrupted. Re-import to resume remaining sessions.");
|
|
34118
34225
|
}).finally(() => {
|
|
@@ -34127,8 +34234,8 @@ var Importer = class {
|
|
|
34127
34234
|
async settled() {
|
|
34128
34235
|
await this.job;
|
|
34129
34236
|
}
|
|
34130
|
-
async run() {
|
|
34131
|
-
for (const adapter of this.adapters.filter((a) =>
|
|
34237
|
+
async run(ids) {
|
|
34238
|
+
for (const adapter of this.adapters.filter((a) => ids.includes(a.id))) {
|
|
34132
34239
|
this.status.source = adapter.id;
|
|
34133
34240
|
try {
|
|
34134
34241
|
if (!await adapter.detect()) throw new Error(`${adapter.name} is unavailable. Saved imports remain available.`);
|
|
@@ -34225,6 +34332,7 @@ var HARNESSES = [
|
|
|
34225
34332
|
var isHarness = (value) => HARNESSES.some((h3) => h3.id === value);
|
|
34226
34333
|
var validSessionID = (id2) => /^ses[a-zA-Z0-9_-]+$/.test(id2);
|
|
34227
34334
|
function resumeArgs(value) {
|
|
34335
|
+
if (typeof value !== "string" && value.nativeResume === false) throw new Error("This saved history requires a context handoff.");
|
|
34228
34336
|
const source = typeof value === "string" ? "opencode" : value.source || "opencode";
|
|
34229
34337
|
const id2 = typeof value === "string" ? value : value.nativeID || value.id;
|
|
34230
34338
|
if (source !== "opencode") {
|
|
@@ -34289,7 +34397,7 @@ function launchCommand(binary, args, directory2, platform = process.platform) {
|
|
|
34289
34397
|
}
|
|
34290
34398
|
|
|
34291
34399
|
// server/handoff.ts
|
|
34292
|
-
import { createHash as
|
|
34400
|
+
import { createHash as createHash5, randomUUID as randomUUID3 } from "node:crypto";
|
|
34293
34401
|
import { mkdir, writeFile as writeFile2, rename as rename2, rm as rm4 } from "node:fs/promises";
|
|
34294
34402
|
import { join as join24 } from "node:path";
|
|
34295
34403
|
function handoffDocument(snapshot2) {
|
|
@@ -34356,7 +34464,7 @@ This handoff transfers saved text and file-change evidence, not files, credentia
|
|
|
34356
34464
|
}
|
|
34357
34465
|
async function saveHandoff(snapshot2, directory2) {
|
|
34358
34466
|
const { text: text2, ...coverage2 } = handoffDocument(snapshot2);
|
|
34359
|
-
const digest2 =
|
|
34467
|
+
const digest2 = createHash5("sha256").update(text2).digest("hex");
|
|
34360
34468
|
const root3 = join24(directory2, "handoffs");
|
|
34361
34469
|
await mkdir(root3, { recursive: true, mode: 448 });
|
|
34362
34470
|
const path = join24(root3, `${digest2}.md`), temporary = join24(root3, `.${randomUUID3()}.tmp`);
|
|
@@ -34396,7 +34504,7 @@ async function prepareLaunch(store, session, target, directory2 = session.direct
|
|
|
34396
34504
|
const [binary, terminal] = await Promise.all([harnessExecutable(target), terminalExecutable()]);
|
|
34397
34505
|
let args;
|
|
34398
34506
|
const subagent = session.source === "claude-code" && Boolean(session.parentID) && /^[\w-]+\/agent\/[\w-]+$/.test(session.nativeID || "");
|
|
34399
|
-
const localHandoff = ["cursor", "gemini", "qwen-code", "pi", "copilot"].includes(session.source || "") && (!session.nativeResume || directory2 !== session.directory);
|
|
34507
|
+
const localHandoff = session.nativeResume === false || ["cursor", "gemini", "qwen-code", "pi", "copilot"].includes(session.source || "") && (!session.nativeResume || directory2 !== session.directory);
|
|
34400
34508
|
if (target === (session.source || "opencode") && !subagent && !localHandoff) args = resumeArgs(session);
|
|
34401
34509
|
const mode = args ? "resume" : "handoff";
|
|
34402
34510
|
if (mode === "handoff" && store.path === ":memory:") throw new Error("Save this library before creating a context handoff.");
|
|
@@ -34442,14 +34550,10 @@ async function launchTerminal(session, prepared) {
|
|
|
34442
34550
|
}
|
|
34443
34551
|
|
|
34444
34552
|
// server/publishing.ts
|
|
34445
|
-
import { createHash as
|
|
34553
|
+
import { createHash as createHash6, randomBytes } from "node:crypto";
|
|
34446
34554
|
import { chmod, mkdir as mkdir2, readFile as readFile5, rename as rename3, rm as rm5, writeFile as writeFile3 } from "node:fs/promises";
|
|
34447
34555
|
import { dirname as dirname10, join as join25 } from "node:path";
|
|
34448
34556
|
|
|
34449
|
-
// packages/core/src/layout.ts
|
|
34450
|
-
var directoryPath = (directory2) => (/^(?:[a-z]:[\\/]|\\\\)/i.test(directory2) ? directory2.replace(/\\/g, "/") : directory2).replace(/\/+$/, "") || (directory2.startsWith("/") ? "/" : "");
|
|
34451
|
-
var laneKey = (session) => session.directory ? JSON.stringify(["directory", directoryPath(session.directory)]) : JSON.stringify(["project", session.source || "opencode", session.projectID || session.id]);
|
|
34452
|
-
|
|
34453
34557
|
// packages/core/src/sources.ts
|
|
34454
34558
|
var sources = {
|
|
34455
34559
|
opencode: { name: "OpenCode", icon: "opencode" },
|
|
@@ -34622,7 +34726,7 @@ var PublishingError = class extends Error {
|
|
|
34622
34726
|
status;
|
|
34623
34727
|
};
|
|
34624
34728
|
var SITE = "https://sessiongraph.ai";
|
|
34625
|
-
var hash = (value) =>
|
|
34729
|
+
var hash = (value) => createHash6("sha256").update(value).digest("hex");
|
|
34626
34730
|
var token = () => randomBytes(32).toString("base64url");
|
|
34627
34731
|
function preparePublicGraph(store, ids, inputSettings) {
|
|
34628
34732
|
if (!Array.isArray(ids) || !ids.length || ids.length > PUBLIC_GRAPH_MAX_SESSIONS || ids.some((id2) => typeof id2 !== "string") || new Set(ids).size !== ids.length) throw new PublishingError("Choose a valid set of sessions.");
|
|
@@ -34791,7 +34895,7 @@ function library() {
|
|
|
34791
34895
|
if (runtime.sessionGraphRuntime?.importer.status.running && runtime.sessionGraphRuntime.generation !== generation) {
|
|
34792
34896
|
for (const live of runtime.sessionGraphRuntime.importer.adapters) {
|
|
34793
34897
|
const updated = adapters.find((adapter) => adapter.id === live.id);
|
|
34794
|
-
if (updated) Object.assign(live, updated);
|
|
34898
|
+
if (updated) Object.assign(live, withSourcePaths(updated, () => runtime.sessionGraphRuntime.store.setting("sourcePaths") || {}));
|
|
34795
34899
|
}
|
|
34796
34900
|
}
|
|
34797
34901
|
if (runtime.sessionGraphRuntime && runtime.sessionGraphRuntime.generation !== generation && !runtime.sessionGraphRuntime.importer.status.running) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{n as u}from"./index-
|
|
1
|
+
import{n as u}from"./index-CIhs02tq.js";function p(t,e,c){t.open&&(t.addEventListener("close",()=>c(e),{once:!0}),t.close())}function b(t,e,c){const l=document.createDocumentFragment(),i=document.createElement("header");i.className="sharing-header";const s=document.createElement("h2");s.id=`sharing-${e}-title`,s.textContent="Share SessionGraph",t.setAttribute("aria-labelledby",s.id);const n=document.createElement("button");n.type="button",n.className="text-button",n.textContent="Close",n.setAttribute("aria-label","Close sharing"),n.onclick=()=>t.close(),i.append(s,n);const r=document.createElement("div");r.className="sharing-modes",r.setAttribute("role","group"),r.setAttribute("aria-label","Share method");for(const a of["publish","video"]){const o=document.createElement("button");o.type="button",o.dataset.shareMode=a,o.textContent=a==="publish"?"Publish":"Video",o.setAttribute("aria-pressed",String(a===e)),o.onclick=()=>{a!==e&&p(t,a,c)},r.append(o)}return l.append(i,r),l}async function d(t,e){await u("plugin:opener|open_url",{url:t,with:e})}function h(t){const e=new URL(t);if(!["https:","http:"].includes(e.protocol)||e.username||e.password)throw new Error("Choose a valid web link.");return e.href}async function f(t,e=d){await e(h(t))}export{h as e,f as o,b as s};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{R as a,n as i,C as R}from"./index-
|
|
1
|
+
import{R as a,n as i,C as R}from"./index-CIhs02tq.js";var w;(function(n){n[n.Audio=1]="Audio",n[n.Cache=2]="Cache",n[n.Config=3]="Config",n[n.Data=4]="Data",n[n.LocalData=5]="LocalData",n[n.Document=6]="Document",n[n.Download=7]="Download",n[n.Picture=8]="Picture",n[n.Public=9]="Public",n[n.Video=10]="Video",n[n.Resource=11]="Resource",n[n.Temp=12]="Temp",n[n.AppConfig=13]="AppConfig",n[n.AppData=14]="AppData",n[n.AppLocalData=15]="AppLocalData",n[n.AppCache=16]="AppCache",n[n.AppLog=17]="AppLog",n[n.Desktop=18]="Desktop",n[n.Executable=19]="Executable",n[n.Font=20]="Font",n[n.Home=21]="Home",n[n.Runtime=22]="Runtime",n[n.Template=23]="Template"})(w||(w={}));var d;(function(n){n[n.Start=0]="Start",n[n.Current=1]="Current",n[n.End=2]="End"})(d||(d={}));function u(n){return{isFile:n.isFile,isDirectory:n.isDirectory,isSymlink:n.isSymlink,size:n.size,mtime:n.mtime!==null?new Date(n.mtime):null,atime:n.atime!==null?new Date(n.atime):null,birthtime:n.birthtime!==null?new Date(n.birthtime):null,readonly:n.readonly,fileAttributes:n.fileAttributes,dev:n.dev,ino:n.ino,mode:n.mode,nlink:n.nlink,uid:n.uid,gid:n.gid,rdev:n.rdev,blksize:n.blksize,blocks:n.blocks}}function U(n){const e=new Uint8ClampedArray(n),t=e.byteLength;let o=0;for(let r=0;r<t;r++){const s=e[r];o*=256,o+=s}return o}class g extends a{async read(e){if(e.byteLength===0)return 0;const t=await i("plugin:fs|read",{rid:this.rid,len:e.byteLength}),o=U(t.slice(-8)),r=t instanceof ArrayBuffer?new Uint8Array(t):t;return e.set(r.slice(0,r.length-8)),o===0?null:o}async seek(e,t){return await i("plugin:fs|seek",{rid:this.rid,offset:e,whence:t})}async stat(){const e=await i("plugin:fs|fstat",{rid:this.rid});return u(e)}async truncate(e){await i("plugin:fs|ftruncate",{rid:this.rid,len:e})}async write(e){return await i("plugin:fs|write",{rid:this.rid,data:e})}}async function b(n,e){if(n instanceof URL&&n.protocol!=="file:")throw new TypeError("Must be a file URL.");const t=await i("plugin:fs|create",{path:n instanceof URL?n.toString():n,options:e});return new g(t)}async function p(n,e){if(n instanceof URL&&n.protocol!=="file:")throw new TypeError("Must be a file URL.");const t=await i("plugin:fs|open",{path:n instanceof URL?n.toString():n,options:e});return new g(t)}async function S(n,e,t){if(n instanceof URL&&n.protocol!=="file:"||e instanceof URL&&e.protocol!=="file:")throw new TypeError("Must be a file URL.");await i("plugin:fs|copy_file",{fromPath:n instanceof URL?n.toString():n,toPath:e instanceof URL?e.toString():e,options:t})}async function A(n,e){if(n instanceof URL&&n.protocol!=="file:")throw new TypeError("Must be a file URL.");await i("plugin:fs|mkdir",{path:n instanceof URL?n.toString():n,options:e})}async function T(n,e){if(n instanceof URL&&n.protocol!=="file:")throw new TypeError("Must be a file URL.");return await i("plugin:fs|read_dir",{path:n instanceof URL?n.toString():n,options:e})}async function E(n,e){if(n instanceof URL&&n.protocol!=="file:")throw new TypeError("Must be a file URL.");const t=await i("plugin:fs|read_file",{path:n instanceof URL?n.toString():n,options:e});return t instanceof ArrayBuffer?new Uint8Array(t):Uint8Array.from(t)}async function _(n,e){if(n instanceof URL&&n.protocol!=="file:")throw new TypeError("Must be a file URL.");const t=await i("plugin:fs|read_text_file",{path:n instanceof URL?n.toString():n,options:e}),o=t instanceof ArrayBuffer?t:Uint8Array.from(t);return new TextDecoder(e?.encoding??"utf-8").decode(o)}async function x(n,e){if(n instanceof URL&&n.protocol!=="file:")throw new TypeError("Must be a file URL.");const t=n instanceof URL?n.toString():n;return await Promise.resolve({path:t,rid:null,async next(){const o=new TextDecoder(e?.encoding??"utf-8");if(this.rid===null){const l=o.encoding;this.rid=await i("plugin:fs|read_text_file_lines",{path:t,options:e!=null?{...e,encoding:l}:void 0})}let r;try{r=await i("plugin:fs|read_text_file_lines_next",{rid:this.rid})}catch(l){throw this.rid=null,l}const s=r instanceof ArrayBuffer?new Uint8Array(r):Uint8Array.from(r),f=s[s.byteLength-1]===1;return f?(this.rid=null,{value:null,done:f}):{value:o.decode(s.slice(0,s.byteLength-1)),done:f}},async return(){if(this.rid!==null){const o=this.rid;this.rid=null,await new a(o).close()}return{value:null,done:!0}},[Symbol.asyncIterator](){return this}})}async function v(n,e){if(n instanceof URL&&n.protocol!=="file:")throw new TypeError("Must be a file URL.");await i("plugin:fs|remove",{path:n instanceof URL?n.toString():n,options:e})}async function M(n,e,t){if(n instanceof URL&&n.protocol!=="file:"||e instanceof URL&&e.protocol!=="file:")throw new TypeError("Must be a file URL.");await i("plugin:fs|rename",{oldPath:n instanceof URL?n.toString():n,newPath:e instanceof URL?e.toString():e,options:t})}async function C(n,e){const t=await i("plugin:fs|stat",{path:n instanceof URL?n.toString():n,options:e});return u(t)}async function k(n,e){const t=await i("plugin:fs|lstat",{path:n instanceof URL?n.toString():n,options:e});return u(t)}async function F(n,e,t){if(n instanceof URL&&n.protocol!=="file:")throw new TypeError("Must be a file URL.");await i("plugin:fs|truncate",{path:n instanceof URL?n.toString():n,len:e,options:t})}async function z(n,e,t){if(n instanceof URL&&n.protocol!=="file:")throw new TypeError("Must be a file URL.");if(e instanceof ReadableStream){const o=await p(n,{read:!1,create:!0,write:!0,...t,truncate:!t?.append}),r=e.getReader();try{for(;;){const{done:s,value:f}=await r.read();if(s)break;await o.write(f)}}finally{r.releaseLock(),await o.close()}}else await i("plugin:fs|write_file",e,{headers:{path:encodeURIComponent(n instanceof URL?n.toString():n),options:JSON.stringify(t)}})}async function I(n,e,t){if(n instanceof URL&&n.protocol!=="file:")throw new TypeError("Must be a file URL.");const o=new TextEncoder;await i("plugin:fs|write_text_file",o.encode(e),{headers:{path:encodeURIComponent(n instanceof URL?n.toString():n),options:JSON.stringify(t)}})}async function H(n,e){if(n instanceof URL&&n.protocol!=="file:")throw new TypeError("Must be a file URL.");return await i("plugin:fs|exists",{path:n instanceof URL?n.toString():n,options:e})}class y extends a{}async function L(n,e,t){const o=Array.isArray(n)?n:[n];for(const c of o)if(c instanceof URL&&c.protocol!=="file:")throw new TypeError("Must be a file URL.");const r=new R;r.onmessage=e;const s=await i("plugin:fs|watch",{paths:o.map(c=>c instanceof URL?c.toString():c),options:t,onEvent:r}),f=new y(s);return()=>{f.close()}}async function J(n,e,t){return await L(n,e,{delayMs:2e3,...t})}async function N(n,e,t){return await L(n,e,{...t,delayMs:void 0})}async function O(n,e){if(n instanceof URL&&n.protocol!=="file:")throw new TypeError("Must be a file URL.");return await i("plugin:fs|size",{path:n instanceof URL?n.toString():n,options:e})}async function V(n){if(n instanceof URL&&n.protocol!=="file:")throw new TypeError("Must be a file URL.");await i("plugin:fs|start_accessing_security_scoped_resource",{path:n instanceof URL?n.toString():n})}async function h(n){if(n instanceof URL&&n.protocol!=="file:")throw new TypeError("Must be a file URL.");await i("plugin:fs|stop_accessing_security_scoped_resource",{path:n instanceof URL?n.toString():n})}export{w as BaseDirectory,g as FileHandle,d as SeekMode,S as copyFile,b as create,H as exists,k as lstat,A as mkdir,p as open,T as readDir,E as readFile,_ as readTextFile,x as readTextFileLines,v as remove,M as rename,O as size,V as startAccessingSecurityScopedResource,C as stat,h as stopAccessingSecurityScopedResource,F as truncate,J as watch,N as watchImmediate,z as writeFile,I as writeTextFile};
|