research-copilot 0.2.3 → 0.2.4
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/app/out/main/index.mjs +122 -48
- package/app/out/preload/index.js +6 -0
- package/app/out/renderer/assets/{MilkdownMarkdownEditor-DjFLwyh4.js → MilkdownMarkdownEditor-G1iOHwc_.js} +50 -50
- package/app/out/renderer/assets/{arc-7NllWjXF.js → arc-4dzvPWwv.js} +1 -1
- package/app/out/renderer/assets/{blockDiagram-c4efeb88-DsOU-_zA.js → blockDiagram-c4efeb88-Cj5lBciZ.js} +8 -8
- package/app/out/renderer/assets/{c4Diagram-c83219d4-U2jdevgc.js → c4Diagram-c83219d4-D4wJF4Nk.js} +3 -3
- package/app/out/renderer/assets/{channel-Cjd8jvi8.js → channel-DRHGMFu6.js} +1 -1
- package/app/out/renderer/assets/{classDiagram-beda092f-Yj0hyRiU.js → classDiagram-beda092f-DrBIQ4Da.js} +6 -6
- package/app/out/renderer/assets/{classDiagram-v2-2358418a-CK0FL8Pk.js → classDiagram-v2-2358418a-yBhKnZh4.js} +10 -10
- package/app/out/renderer/assets/{clone-I16owcK3.js → clone-ChFuWsyG.js} +1 -1
- package/app/out/renderer/assets/{createText-1719965b-D_GY3BGW.js → createText-1719965b-dtk9hA3P.js} +2 -2
- package/app/out/renderer/assets/{edges-96097737-DKD2znJk.js → edges-96097737-D_e1x_h6.js} +3 -3
- package/app/out/renderer/assets/{erDiagram-0228fc6a-CxrCv4uP.js → erDiagram-0228fc6a-CrZBuvPZ.js} +5 -5
- package/app/out/renderer/assets/{flowDb-c6c81e3f-8o4wFApi.js → flowDb-c6c81e3f-DtZC9Fq3.js} +1 -1
- package/app/out/renderer/assets/{flowDiagram-50d868cf-B1eYKlZC.js → flowDiagram-50d868cf-VzlFN6Qf.js} +12 -12
- package/app/out/renderer/assets/{flowDiagram-v2-4f6560a1-Y4_T8Xi1.js → flowDiagram-v2-4f6560a1-BWNPZGSS.js} +12 -12
- package/app/out/renderer/assets/{flowchart-elk-definition-6af322e1-BjDPU2Ol.js → flowchart-elk-definition-6af322e1-BRS2deVY.js} +6 -6
- package/app/out/renderer/assets/{ganttDiagram-a2739b55-CdQAT7up.js → ganttDiagram-a2739b55-DRChnjlR.js} +3 -3
- package/app/out/renderer/assets/{gitGraphDiagram-82fe8481-Bl7KP_G5.js → gitGraphDiagram-82fe8481-BVfXECHD.js} +2 -2
- package/app/out/renderer/assets/{graph-Bje_pjwC.js → graph-Dl3bczvk.js} +1 -1
- package/app/out/renderer/assets/{index-5325376f-DB5UfMSQ.js → index-5325376f-DjPany76.js} +6 -6
- package/app/out/renderer/assets/{index-BbbK94Tl.js → index-6EerDbdL.js} +4 -4
- package/app/out/renderer/assets/{index-CTrj2aB2.js → index-B9tygoLQ.js} +3 -3
- package/app/out/renderer/assets/{index-UYsogkLv.js → index-BNdWI-dg.js} +6 -6
- package/app/out/renderer/assets/{index-DCr-i28b.js → index-BPwe457Y.js} +3 -3
- package/app/out/renderer/assets/{index-BX5-hWqk.js → index-BQHeBYdD.js} +3 -3
- package/app/out/renderer/assets/{index-D9YGyBA9.js → index-BUUZSVeh.js} +3 -3
- package/app/out/renderer/assets/{index-DRgsVAez.js → index-Bg-eDX1p.js} +4 -4
- package/app/out/renderer/assets/{index-BHl_tELv.js → index-BkB91HdR.js} +5 -5
- package/app/out/renderer/assets/{index-CISiP4Vc.js → index-BlpusrHE.js} +133 -16
- package/app/out/renderer/assets/{index-CoIRGlb6.js → index-C226G81f.js} +3 -3
- package/app/out/renderer/assets/{index-hI44wokU.js → index-C4rx4LuD.js} +6 -6
- package/app/out/renderer/assets/{index-CDWVrn8L.js → index-C8-8M1o_.js} +3 -3
- package/app/out/renderer/assets/{index-DihmTRDX.js → index-CLSRcr1i.js} +6 -6
- package/app/out/renderer/assets/{index-BWkpc_Fb.js → index-CMSALyTS.js} +3 -3
- package/app/out/renderer/assets/{index-BlSmCt8A.js → index-CU9ZRB66.js} +6 -6
- package/app/out/renderer/assets/{index-CU1ei-Q-.js → index-CgEKFTyJ.js} +6 -6
- package/app/out/renderer/assets/{index-K7KmUSPg.js → index-CllWzrq7.js} +3 -3
- package/app/out/renderer/assets/{index-DFmh36hv.js → index-DHmQz4fM.js} +3 -3
- package/app/out/renderer/assets/{index-bPpSppnq.js → index-DxziAmqO.js} +3 -3
- package/app/out/renderer/assets/{index-BnGN3XMZ.js → index-HZn90B-L.js} +6 -6
- package/app/out/renderer/assets/{index-CT1HtzVp.css → index-dNBQ09OL.css} +60 -0
- package/app/out/renderer/assets/{index-TtJcntKb.js → index-dvpto11c.js} +3 -3
- package/app/out/renderer/assets/{index-DkTtiwdL.js → index-hVorRCxO.js} +3 -3
- package/app/out/renderer/assets/{index-DIB3jH2J.js → index-nk-me1QW.js} +1 -1
- package/app/out/renderer/assets/{infoDiagram-8eee0895-Dfty_4jM.js → infoDiagram-8eee0895-CRzw5OpC.js} +2 -2
- package/app/out/renderer/assets/{journeyDiagram-c64418c1-BzDYpsjx.js → journeyDiagram-c64418c1-CYFcrwy9.js} +4 -4
- package/app/out/renderer/assets/{layout-DbHSNFr9.js → layout-2qUs4rWy.js} +2 -2
- package/app/out/renderer/assets/{line-jV7QLjZ_.js → line-zEaIEY7C.js} +1 -1
- package/app/out/renderer/assets/{linear-CIeuNnVa.js → linear-B-lut2jS.js} +1 -1
- package/app/out/renderer/assets/{mindmap-definition-8da855dc-CeDEmTB-.js → mindmap-definition-8da855dc--G6w66OU.js} +3 -3
- package/app/out/renderer/assets/{pieDiagram-a8764435-Bpm1FcX3.js → pieDiagram-a8764435-B1aj6YO1.js} +3 -3
- package/app/out/renderer/assets/{quadrantDiagram-1e28029f-CEB7PxJa.js → quadrantDiagram-1e28029f-WcQ-5B6J.js} +3 -3
- package/app/out/renderer/assets/{requirementDiagram-08caed73-CZJU8B_1.js → requirementDiagram-08caed73-DVS_F7Ld.js} +5 -5
- package/app/out/renderer/assets/{sankeyDiagram-a04cb91d-JXpwgeE0.js → sankeyDiagram-a04cb91d-C9DI8I5c.js} +2 -2
- package/app/out/renderer/assets/{sequenceDiagram-c5b8d532-CtvDQG5X.js → sequenceDiagram-c5b8d532-BbjlXU_R.js} +3 -3
- package/app/out/renderer/assets/{stateDiagram-1ecb1508-DQRUQm_b.js → stateDiagram-1ecb1508-D-RBhWue.js} +6 -6
- package/app/out/renderer/assets/{stateDiagram-v2-c2b004d7-qWcRpqpV.js → stateDiagram-v2-c2b004d7-5WeKw5B9.js} +10 -10
- package/app/out/renderer/assets/{styles-b4e223ce-6DWryYQB.js → styles-b4e223ce-FiETMPKg.js} +1 -1
- package/app/out/renderer/assets/{styles-ca3715f6-CZ9SeO17.js → styles-ca3715f6-DOyTWqN-.js} +1 -1
- package/app/out/renderer/assets/{styles-d45a18b0-Bkmie_Qv.js → styles-d45a18b0-D2yoeLkD.js} +4 -4
- package/app/out/renderer/assets/{svgDrawCommon-b86b1483-BWRX1ZPq.js → svgDrawCommon-b86b1483-7THlOYFk.js} +1 -1
- package/app/out/renderer/assets/{timeline-definition-faaaa080-XcgfjspK.js → timeline-definition-faaaa080-BVp4ikHz.js} +3 -3
- package/app/out/renderer/assets/{xychartDiagram-f5964ef8-C0CQzgr8.js → xychartDiagram-f5964ef8-Cdp51x2C.js} +5 -5
- package/app/out/renderer/index.html +2 -2
- package/lib/skills/builtin/paper-revision/SKILL.md +467 -0
- package/lib/skills/builtin/paper-revision/references/evidence-strengthening.md +101 -0
- package/lib/skills/builtin/paper-revision/references/framing-patterns.md +119 -0
- package/lib/skills/builtin/paper-revision/references/reviewer-attack-catalog.md +171 -0
- package/lib/skills/builtin/paper-revision/references/venue-strategies.md +114 -0
- package/lib/skills/builtin/paper-writing/SKILL.md +1 -0
- package/package.json +4 -4
package/app/out/main/index.mjs
CHANGED
|
@@ -7040,7 +7040,7 @@ The conversation continues below.`,
|
|
|
7040
7040
|
});
|
|
7041
7041
|
}
|
|
7042
7042
|
async function clearSessionMemory() {
|
|
7043
|
-
agent.
|
|
7043
|
+
agent.reset();
|
|
7044
7044
|
compactionSummary = void 0;
|
|
7045
7045
|
}
|
|
7046
7046
|
async function maybeGenerateSummary() {
|
|
@@ -7097,7 +7097,7 @@ ${historyText}`,
|
|
|
7097
7097
|
if (process.env.ENABLE_LOCAL_COMPUTE === "1") {
|
|
7098
7098
|
probeStaticProfile().then((profile) => {
|
|
7099
7099
|
const envGuidance = generateAgentGuidance(profile);
|
|
7100
|
-
agent.
|
|
7100
|
+
agent.state.systemPrompt = baseSystemPrompt + "\n\n" + envGuidance;
|
|
7101
7101
|
}).catch(() => {
|
|
7102
7102
|
});
|
|
7103
7103
|
}
|
|
@@ -7156,7 +7156,7 @@ ${historyText}`,
|
|
|
7156
7156
|
|
|
7157
7157
|
${agentMdContent}`;
|
|
7158
7158
|
}
|
|
7159
|
-
agent.
|
|
7159
|
+
agent.state.systemPrompt = enrichedSystem;
|
|
7160
7160
|
const contextParts = [];
|
|
7161
7161
|
if (summaryContext) contextParts.push(summaryContext);
|
|
7162
7162
|
if (skillSummariesPrompt) contextParts.push(skillSummariesPrompt);
|
|
@@ -7234,6 +7234,10 @@ ${message}` : message;
|
|
|
7234
7234
|
}
|
|
7235
7235
|
},
|
|
7236
7236
|
clearSessionMemory,
|
|
7237
|
+
/** Stop the current LLM turn without tearing down tools. */
|
|
7238
|
+
abort() {
|
|
7239
|
+
agent.abort();
|
|
7240
|
+
},
|
|
7237
7241
|
async destroy() {
|
|
7238
7242
|
agent.abort();
|
|
7239
7243
|
await destroyResearchTools();
|
|
@@ -7906,11 +7910,11 @@ function getCachedMarkdown(filePath, projectPath) {
|
|
|
7906
7910
|
const mtime = stat.mtimeMs;
|
|
7907
7911
|
const cacheDir = join(projectPath, PATHS.documentCache);
|
|
7908
7912
|
const cacheKey2 = getCacheKey(filePath, mtime);
|
|
7909
|
-
const
|
|
7910
|
-
if (!existsSync(
|
|
7913
|
+
const cachePath = join(cacheDir, cacheKey2);
|
|
7914
|
+
if (!existsSync(cachePath)) {
|
|
7911
7915
|
return null;
|
|
7912
7916
|
}
|
|
7913
|
-
const entry = JSON.parse(readFileSync(
|
|
7917
|
+
const entry = JSON.parse(readFileSync(cachePath, "utf-8"));
|
|
7914
7918
|
if (entry.sourcePath !== filePath || entry.sourceMtime !== mtime) {
|
|
7915
7919
|
return null;
|
|
7916
7920
|
}
|
|
@@ -7925,14 +7929,14 @@ function setCachedMarkdown(filePath, markdown, projectPath) {
|
|
|
7925
7929
|
const mtime = stat.mtimeMs;
|
|
7926
7930
|
const cacheDir = ensureCacheDir(projectPath);
|
|
7927
7931
|
const cacheKey2 = getCacheKey(filePath, mtime);
|
|
7928
|
-
const
|
|
7932
|
+
const cachePath = join(cacheDir, cacheKey2);
|
|
7929
7933
|
const entry = {
|
|
7930
7934
|
sourcePath: filePath,
|
|
7931
7935
|
sourceMtime: mtime,
|
|
7932
7936
|
markdown,
|
|
7933
7937
|
cachedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
7934
7938
|
};
|
|
7935
|
-
writeFileSync(
|
|
7939
|
+
writeFileSync(cachePath, JSON.stringify(entry, null, 2), "utf-8");
|
|
7936
7940
|
} catch (err) {
|
|
7937
7941
|
console.warn("[document-cache] Failed to cache markdown:", err);
|
|
7938
7942
|
}
|
|
@@ -8123,35 +8127,36 @@ const SKIP_DIRS = /* @__PURE__ */ new Set([
|
|
|
8123
8127
|
".venv",
|
|
8124
8128
|
"venv"
|
|
8125
8129
|
]);
|
|
8126
|
-
|
|
8127
|
-
|
|
8128
|
-
let
|
|
8129
|
-
|
|
8130
|
-
|
|
8131
|
-
|
|
8132
|
-
cachedFiles = [];
|
|
8133
|
-
cachedProjectPath = projectPath;
|
|
8134
|
-
lastRefreshAt = 0;
|
|
8130
|
+
const caches$1 = /* @__PURE__ */ new Map();
|
|
8131
|
+
function getOrCreateCache(projectPath) {
|
|
8132
|
+
let c = caches$1.get(projectPath);
|
|
8133
|
+
if (!c) {
|
|
8134
|
+
c = { files: [], lastRefreshAt: 0, refreshPromise: null };
|
|
8135
|
+
caches$1.set(projectPath, c);
|
|
8135
8136
|
}
|
|
8137
|
+
return c;
|
|
8138
|
+
}
|
|
8139
|
+
async function getFileList(projectPath) {
|
|
8140
|
+
const c = getOrCreateCache(projectPath);
|
|
8136
8141
|
const now = Date.now();
|
|
8137
|
-
if (
|
|
8138
|
-
return
|
|
8142
|
+
if (c.files.length > 0 && now - c.lastRefreshAt < REFRESH_THROTTLE_MS) {
|
|
8143
|
+
return c.files;
|
|
8139
8144
|
}
|
|
8140
|
-
if (refreshPromise) return refreshPromise;
|
|
8141
|
-
refreshPromise = refreshFileList(projectPath).finally(() => {
|
|
8142
|
-
refreshPromise = null;
|
|
8145
|
+
if (c.refreshPromise) return c.refreshPromise;
|
|
8146
|
+
c.refreshPromise = refreshFileList(projectPath, c).finally(() => {
|
|
8147
|
+
c.refreshPromise = null;
|
|
8143
8148
|
});
|
|
8144
|
-
return refreshPromise;
|
|
8149
|
+
return c.refreshPromise;
|
|
8145
8150
|
}
|
|
8146
|
-
async function refreshFileList(projectPath) {
|
|
8151
|
+
async function refreshFileList(projectPath, c) {
|
|
8147
8152
|
try {
|
|
8148
8153
|
const files = await gitLsFiles(projectPath);
|
|
8149
|
-
|
|
8154
|
+
c.files = files.slice(0, MAX_FILES);
|
|
8150
8155
|
} catch {
|
|
8151
|
-
|
|
8156
|
+
c.files = walkFilesSync(projectPath);
|
|
8152
8157
|
}
|
|
8153
|
-
lastRefreshAt = Date.now();
|
|
8154
|
-
return
|
|
8158
|
+
c.lastRefreshAt = Date.now();
|
|
8159
|
+
return c.files;
|
|
8155
8160
|
}
|
|
8156
8161
|
function gitLsFiles(cwd) {
|
|
8157
8162
|
return new Promise((resolve2, reject) => {
|
|
@@ -8201,20 +8206,24 @@ function walk(root, rel, depth, out) {
|
|
|
8201
8206
|
}
|
|
8202
8207
|
}
|
|
8203
8208
|
}
|
|
8204
|
-
|
|
8205
|
-
let cachePath = "";
|
|
8209
|
+
const caches = /* @__PURE__ */ new Map();
|
|
8206
8210
|
function getEntityCache(projectPath) {
|
|
8207
|
-
|
|
8208
|
-
|
|
8211
|
+
let c = caches.get(projectPath);
|
|
8212
|
+
if (c) return c;
|
|
8213
|
+
c = {
|
|
8209
8214
|
notes: listNotes(projectPath),
|
|
8210
8215
|
papers: listLiterature(projectPath),
|
|
8211
8216
|
data: listData(projectPath)
|
|
8212
8217
|
};
|
|
8213
|
-
|
|
8214
|
-
return
|
|
8218
|
+
caches.set(projectPath, c);
|
|
8219
|
+
return c;
|
|
8215
8220
|
}
|
|
8216
|
-
function invalidateEntityCache() {
|
|
8217
|
-
|
|
8221
|
+
function invalidateEntityCache(projectPath) {
|
|
8222
|
+
if (projectPath) {
|
|
8223
|
+
caches.delete(projectPath);
|
|
8224
|
+
} else {
|
|
8225
|
+
caches.clear();
|
|
8226
|
+
}
|
|
8218
8227
|
}
|
|
8219
8228
|
const SCORE_MATCH = 16;
|
|
8220
8229
|
const BONUS_FIRST_CHAR = 8;
|
|
@@ -9116,7 +9125,7 @@ async function ensureCoordinator(state, win, model, options) {
|
|
|
9116
9125
|
if ((tool === "artifact-create" || tool === "artifact-update") && result && typeof result === "object" && "success" in result) {
|
|
9117
9126
|
const r2 = result;
|
|
9118
9127
|
if (r2.success) {
|
|
9119
|
-
invalidateEntityCache();
|
|
9128
|
+
invalidateEntityCache(runProjectPath);
|
|
9120
9129
|
if (tool === "artifact-create") {
|
|
9121
9130
|
safeSend(win, "agent:entity-created", {
|
|
9122
9131
|
type: r2.data?.type || "artifact",
|
|
@@ -9346,7 +9355,7 @@ function registerIpcHandlers() {
|
|
|
9346
9355
|
});
|
|
9347
9356
|
handleWindow("agent:stop", ({ state }) => {
|
|
9348
9357
|
if (state.coordinator) {
|
|
9349
|
-
state.coordinator.
|
|
9358
|
+
state.coordinator.abort();
|
|
9350
9359
|
}
|
|
9351
9360
|
});
|
|
9352
9361
|
handleWindow("agent:clear-memory", async ({ state }) => {
|
|
@@ -9372,15 +9381,25 @@ function registerIpcHandlers() {
|
|
|
9372
9381
|
});
|
|
9373
9382
|
handleWindow("cmd:delete", ({ state }, id) => {
|
|
9374
9383
|
if (!state.projectPath) return { success: false, error: "No project folder selected." };
|
|
9375
|
-
|
|
9384
|
+
const result = deleteEntity(id, state.projectPath);
|
|
9385
|
+
invalidateEntityCache(state.projectPath);
|
|
9386
|
+
return result;
|
|
9376
9387
|
});
|
|
9377
9388
|
handleWindow("cmd:artifact-create", ({ state }, input) => {
|
|
9378
9389
|
if (!state.projectPath) return { success: false, error: "No project folder selected." };
|
|
9379
|
-
|
|
9390
|
+
const result = artifactCreate(input, { sessionId: state.sessionId, projectPath: state.projectPath });
|
|
9391
|
+
if (result && typeof result === "object" && "success" in result && result.success) {
|
|
9392
|
+
invalidateEntityCache(state.projectPath);
|
|
9393
|
+
}
|
|
9394
|
+
return result;
|
|
9380
9395
|
});
|
|
9381
9396
|
handleWindow("cmd:artifact-update", ({ state }, artifactId, patch) => {
|
|
9382
9397
|
if (!state.projectPath) return { success: false, error: "No project folder selected." };
|
|
9383
|
-
|
|
9398
|
+
const result = artifactUpdate(state.projectPath, artifactId, patch);
|
|
9399
|
+
if (result && typeof result === "object" && "success" in result && result.success) {
|
|
9400
|
+
invalidateEntityCache(state.projectPath);
|
|
9401
|
+
}
|
|
9402
|
+
return result;
|
|
9384
9403
|
});
|
|
9385
9404
|
handleWindow("cmd:artifact-get", ({ state }, artifactId) => {
|
|
9386
9405
|
if (!state.projectPath) return null;
|
|
@@ -9396,7 +9415,11 @@ function registerIpcHandlers() {
|
|
|
9396
9415
|
});
|
|
9397
9416
|
handleWindow("cmd:artifact-delete", ({ state }, artifactId) => {
|
|
9398
9417
|
if (!state.projectPath) return { success: false, error: "No project folder selected." };
|
|
9399
|
-
|
|
9418
|
+
const result = artifactDelete(state.projectPath, artifactId);
|
|
9419
|
+
if (result && typeof result === "object" && "success" in result && result.success) {
|
|
9420
|
+
invalidateEntityCache(state.projectPath);
|
|
9421
|
+
}
|
|
9422
|
+
return result;
|
|
9400
9423
|
});
|
|
9401
9424
|
handleWindow("cmd:turn-explain-get", ({ state }) => {
|
|
9402
9425
|
if (!state.projectPath) return { success: false, error: "No project folder selected." };
|
|
@@ -9742,16 +9765,56 @@ function registerIpcHandlers() {
|
|
|
9742
9765
|
return null;
|
|
9743
9766
|
}
|
|
9744
9767
|
});
|
|
9768
|
+
handleWindow("chat:export", async ({ win, state }) => {
|
|
9769
|
+
if (!state.projectPath || !state.sessionId) {
|
|
9770
|
+
return { success: false, error: "No project open" };
|
|
9771
|
+
}
|
|
9772
|
+
const file = join(state.projectPath, PATHS.sessions, `${state.sessionId}.jsonl`);
|
|
9773
|
+
if (!existsSync(file)) {
|
|
9774
|
+
return { success: false, error: "No chat history found" };
|
|
9775
|
+
}
|
|
9776
|
+
const lines = readFileSync(file, "utf-8").split("\n").filter(Boolean);
|
|
9777
|
+
if (lines.length === 0) {
|
|
9778
|
+
return { success: false, error: "Chat history is empty" };
|
|
9779
|
+
}
|
|
9780
|
+
const projectName = basename(state.projectPath);
|
|
9781
|
+
const mdParts = [`# Chat Export — ${projectName}
|
|
9782
|
+
`];
|
|
9783
|
+
mdParts.push(`> Exported on ${(/* @__PURE__ */ new Date()).toLocaleString()}
|
|
9784
|
+
`);
|
|
9785
|
+
for (const line of lines) {
|
|
9786
|
+
try {
|
|
9787
|
+
const msg = JSON.parse(line);
|
|
9788
|
+
const time = msg.timestamp ? new Date(msg.timestamp).toLocaleString() : "";
|
|
9789
|
+
const roleLabel = msg.role === "user" ? "**You**" : msg.role === "assistant" ? "**Assistant**" : "**System**";
|
|
9790
|
+
mdParts.push(`---
|
|
9791
|
+
|
|
9792
|
+
### ${roleLabel}
|
|
9793
|
+
<sub>${time}</sub>
|
|
9794
|
+
|
|
9795
|
+
${msg.content}
|
|
9796
|
+
`);
|
|
9797
|
+
} catch {
|
|
9798
|
+
}
|
|
9799
|
+
}
|
|
9800
|
+
const markdown = mdParts.join("\n");
|
|
9801
|
+
const result = await dialog.showSaveDialog(win, {
|
|
9802
|
+
title: "Export Chat History",
|
|
9803
|
+
defaultPath: join(app.getPath("documents"), `${projectName}-chat-export.md`),
|
|
9804
|
+
filters: [{ name: "Markdown", extensions: ["md"] }]
|
|
9805
|
+
});
|
|
9806
|
+
if (result.canceled || !result.filePath) {
|
|
9807
|
+
return { success: false, error: "Cancelled" };
|
|
9808
|
+
}
|
|
9809
|
+
writeFileSync(result.filePath, markdown, "utf-8");
|
|
9810
|
+
return { success: true, path: result.filePath };
|
|
9811
|
+
});
|
|
9745
9812
|
handleWindow("project:pick-folder", async ({ win, state }) => {
|
|
9746
9813
|
const result = await dialog.showOpenDialog(win, {
|
|
9747
9814
|
properties: ["openDirectory", "createDirectory"]
|
|
9748
9815
|
});
|
|
9749
9816
|
if (!result.canceled && result.filePaths[0]) {
|
|
9750
9817
|
if (state.coordinator) {
|
|
9751
|
-
try {
|
|
9752
|
-
state.coordinator.agent.stop();
|
|
9753
|
-
} catch {
|
|
9754
|
-
}
|
|
9755
9818
|
try {
|
|
9756
9819
|
await state.coordinator.destroy();
|
|
9757
9820
|
} catch {
|
|
@@ -9793,6 +9856,7 @@ function registerIpcHandlers() {
|
|
|
9793
9856
|
}).catch(() => {
|
|
9794
9857
|
});
|
|
9795
9858
|
}
|
|
9859
|
+
win.setTitle(basename(state.projectPath));
|
|
9796
9860
|
return { projectPath: state.projectPath, sessionId: state.sessionId };
|
|
9797
9861
|
}
|
|
9798
9862
|
return null;
|
|
@@ -9802,8 +9866,7 @@ function registerIpcHandlers() {
|
|
|
9802
9866
|
try {
|
|
9803
9867
|
if (state.coordinator) {
|
|
9804
9868
|
try {
|
|
9805
|
-
;
|
|
9806
|
-
state.coordinator.agent.stop();
|
|
9869
|
+
state.coordinator.abort();
|
|
9807
9870
|
} catch {
|
|
9808
9871
|
}
|
|
9809
9872
|
}
|
|
@@ -9818,6 +9881,8 @@ function registerIpcHandlers() {
|
|
|
9818
9881
|
state.realtimeBuffer.reset();
|
|
9819
9882
|
state.projectPath = "";
|
|
9820
9883
|
state.sessionId = crypto.randomUUID();
|
|
9884
|
+
const win = BrowserWindow.getAllWindows().find((w) => windowStates.get(w.webContents.id) === state);
|
|
9885
|
+
if (win) win.setTitle("Research Pilot");
|
|
9821
9886
|
state.currentModel = "openai:gpt-5.4";
|
|
9822
9887
|
state.currentReasoningEffort = "medium";
|
|
9823
9888
|
state.currentAuthMode = "none";
|
|
@@ -10013,6 +10078,15 @@ function buildMenu() {
|
|
|
10013
10078
|
}
|
|
10014
10079
|
},
|
|
10015
10080
|
{ type: "separator" },
|
|
10081
|
+
{
|
|
10082
|
+
label: "Export Chat…",
|
|
10083
|
+
accelerator: "CmdOrCtrl+Shift+E",
|
|
10084
|
+
click: () => {
|
|
10085
|
+
const target = BrowserWindow.getFocusedWindow() ?? BrowserWindow.getAllWindows()[0];
|
|
10086
|
+
if (target) target.webContents.send("menu:export-chat");
|
|
10087
|
+
}
|
|
10088
|
+
},
|
|
10089
|
+
{ type: "separator" },
|
|
10016
10090
|
{
|
|
10017
10091
|
label: "Close Project",
|
|
10018
10092
|
accelerator: "CmdOrCtrl+Shift+K",
|
package/app/out/preload/index.js
CHANGED
|
@@ -143,6 +143,12 @@ const api = {
|
|
|
143
143
|
setEnabledSkills: (enabledSkills) => electron.ipcRenderer.invoke("skills:set-enabled", enabledSkills),
|
|
144
144
|
uploadSkill: (fileName, base64Data) => electron.ipcRenderer.invoke("skills:upload", fileName, base64Data),
|
|
145
145
|
convertFileToText: (fileName, base64Data) => electron.ipcRenderer.invoke("file:convert-to-text", fileName, base64Data),
|
|
146
|
+
exportChat: () => electron.ipcRenderer.invoke("chat:export"),
|
|
147
|
+
onExportChat: (cb) => {
|
|
148
|
+
const handler = () => cb();
|
|
149
|
+
electron.ipcRenderer.on("menu:export-chat", handler);
|
|
150
|
+
return () => electron.ipcRenderer.removeListener("menu:export-chat", handler);
|
|
151
|
+
},
|
|
146
152
|
saveMessage: (sessionId, msg) => electron.ipcRenderer.invoke("session:save-message", sessionId, msg),
|
|
147
153
|
loadMessages: (sessionId, offset, limit) => electron.ipcRenderer.invoke("session:load-messages", sessionId, offset, limit),
|
|
148
154
|
getMessageCount: (sessionId) => electron.ipcRenderer.invoke("session:get-total-count", sessionId),
|