research-copilot 0.2.2 → 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 +124 -49
- package/app/out/preload/index.js +6 -0
- package/app/out/renderer/assets/{MilkdownMarkdownEditor-jaF-aGPn.js → MilkdownMarkdownEditor-G1iOHwc_.js} +50 -50
- package/app/out/renderer/assets/{arc-C1kBmvvR.js → arc-4dzvPWwv.js} +1 -1
- package/app/out/renderer/assets/{blockDiagram-c4efeb88-Do93X2rs.js → blockDiagram-c4efeb88-Cj5lBciZ.js} +8 -8
- package/app/out/renderer/assets/{c4Diagram-c83219d4-DgxxcZWC.js → c4Diagram-c83219d4-D4wJF4Nk.js} +3 -3
- package/app/out/renderer/assets/{channel-Co_M0Svj.js → channel-DRHGMFu6.js} +1 -1
- package/app/out/renderer/assets/{classDiagram-beda092f-CQlHgE6H.js → classDiagram-beda092f-DrBIQ4Da.js} +6 -6
- package/app/out/renderer/assets/{classDiagram-v2-2358418a-CkGG3aI2.js → classDiagram-v2-2358418a-yBhKnZh4.js} +10 -10
- package/app/out/renderer/assets/{clone-C18Y6dgC.js → clone-ChFuWsyG.js} +1 -1
- package/app/out/renderer/assets/{createText-1719965b-DGRc6nys.js → createText-1719965b-dtk9hA3P.js} +2 -2
- package/app/out/renderer/assets/{edges-96097737-BXvJ4fAK.js → edges-96097737-D_e1x_h6.js} +3 -3
- package/app/out/renderer/assets/{erDiagram-0228fc6a-CXjPp0pt.js → erDiagram-0228fc6a-CrZBuvPZ.js} +5 -5
- package/app/out/renderer/assets/{flowDb-c6c81e3f-CNhpbtw_.js → flowDb-c6c81e3f-DtZC9Fq3.js} +1 -1
- package/app/out/renderer/assets/{flowDiagram-50d868cf-KZ_BUCPA.js → flowDiagram-50d868cf-VzlFN6Qf.js} +12 -12
- package/app/out/renderer/assets/{flowDiagram-v2-4f6560a1-IMv50KZP.js → flowDiagram-v2-4f6560a1-BWNPZGSS.js} +12 -12
- package/app/out/renderer/assets/{flowchart-elk-definition-6af322e1-BFwFiPvq.js → flowchart-elk-definition-6af322e1-BRS2deVY.js} +6 -6
- package/app/out/renderer/assets/{ganttDiagram-a2739b55-D0-ehN-T.js → ganttDiagram-a2739b55-DRChnjlR.js} +3 -3
- package/app/out/renderer/assets/{gitGraphDiagram-82fe8481-DUyIR0Dv.js → gitGraphDiagram-82fe8481-BVfXECHD.js} +2 -2
- package/app/out/renderer/assets/{graph-DnTq2_3F.js → graph-Dl3bczvk.js} +1 -1
- package/app/out/renderer/assets/{index-5325376f-CBwuFbRF.js → index-5325376f-DjPany76.js} +6 -6
- package/app/out/renderer/assets/{index-u0FZRZON.js → index-6EerDbdL.js} +4 -4
- package/app/out/renderer/assets/{index-BHcU72Rm.js → index-B9tygoLQ.js} +3 -3
- package/app/out/renderer/assets/{index-DWU4ia28.js → index-BNdWI-dg.js} +6 -6
- package/app/out/renderer/assets/{index-D6r8msaQ.js → index-BPwe457Y.js} +3 -3
- package/app/out/renderer/assets/{index-DuhageEr.js → index-BQHeBYdD.js} +3 -3
- package/app/out/renderer/assets/{index-C1oXjI4L.js → index-BUUZSVeh.js} +3 -3
- package/app/out/renderer/assets/{index-Diy30-34.js → index-Bg-eDX1p.js} +4 -4
- package/app/out/renderer/assets/{index-CKXwBmK7.js → index-BkB91HdR.js} +5 -5
- package/app/out/renderer/assets/{index-BB-a1ajC.js → index-BlpusrHE.js} +136 -19
- package/app/out/renderer/assets/{index-gH-w4EHk.js → index-C226G81f.js} +3 -3
- package/app/out/renderer/assets/{index-DZbrRR7w.js → index-C4rx4LuD.js} +6 -6
- package/app/out/renderer/assets/{index-BpKrXGYD.js → index-C8-8M1o_.js} +3 -3
- package/app/out/renderer/assets/{index-CjffvluT.js → index-CLSRcr1i.js} +6 -6
- package/app/out/renderer/assets/{index-7hDGClrI.js → index-CMSALyTS.js} +3 -3
- package/app/out/renderer/assets/{index-yanwpi6t.js → index-CU9ZRB66.js} +6 -6
- package/app/out/renderer/assets/{index-bMe3RSkw.js → index-CgEKFTyJ.js} +6 -6
- package/app/out/renderer/assets/{index-D6jljsup.js → index-CllWzrq7.js} +3 -3
- package/app/out/renderer/assets/{index-ESFHcvWy.js → index-DHmQz4fM.js} +3 -3
- package/app/out/renderer/assets/{index-h_fNksib.js → index-DxziAmqO.js} +3 -3
- package/app/out/renderer/assets/{index-COZSDrEw.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-BQ7qz1CD.js → index-dvpto11c.js} +3 -3
- package/app/out/renderer/assets/{index-BVYoMX5H.js → index-hVorRCxO.js} +3 -3
- package/app/out/renderer/assets/{index-JT8OCsRP.js → index-nk-me1QW.js} +1 -1
- package/app/out/renderer/assets/{infoDiagram-8eee0895-Qra4japr.js → infoDiagram-8eee0895-CRzw5OpC.js} +2 -2
- package/app/out/renderer/assets/{journeyDiagram-c64418c1-BTN9SgOL.js → journeyDiagram-c64418c1-CYFcrwy9.js} +4 -4
- package/app/out/renderer/assets/{layout-DGrHHJdN.js → layout-2qUs4rWy.js} +2 -2
- package/app/out/renderer/assets/{line-DXtxdS2B.js → line-zEaIEY7C.js} +1 -1
- package/app/out/renderer/assets/{linear-CexrSQK6.js → linear-B-lut2jS.js} +1 -1
- package/app/out/renderer/assets/{mindmap-definition-8da855dc-pvG2hzEB.js → mindmap-definition-8da855dc--G6w66OU.js} +3 -3
- package/app/out/renderer/assets/{pieDiagram-a8764435-D_neFVMq.js → pieDiagram-a8764435-B1aj6YO1.js} +3 -3
- package/app/out/renderer/assets/{quadrantDiagram-1e28029f-C47W3UMp.js → quadrantDiagram-1e28029f-WcQ-5B6J.js} +3 -3
- package/app/out/renderer/assets/{requirementDiagram-08caed73-DW4Bo_fu.js → requirementDiagram-08caed73-DVS_F7Ld.js} +5 -5
- package/app/out/renderer/assets/{sankeyDiagram-a04cb91d-D_3PD7JI.js → sankeyDiagram-a04cb91d-C9DI8I5c.js} +2 -2
- package/app/out/renderer/assets/{sequenceDiagram-c5b8d532-BW6nGtuQ.js → sequenceDiagram-c5b8d532-BbjlXU_R.js} +3 -3
- package/app/out/renderer/assets/{stateDiagram-1ecb1508-CDgBJ3-T.js → stateDiagram-1ecb1508-D-RBhWue.js} +6 -6
- package/app/out/renderer/assets/{stateDiagram-v2-c2b004d7-CBw5TtXo.js → stateDiagram-v2-c2b004d7-5WeKw5B9.js} +10 -10
- package/app/out/renderer/assets/{styles-b4e223ce-DeeiEsuW.js → styles-b4e223ce-FiETMPKg.js} +1 -1
- package/app/out/renderer/assets/{styles-ca3715f6-CMpiebrG.js → styles-ca3715f6-DOyTWqN-.js} +1 -1
- package/app/out/renderer/assets/{styles-d45a18b0-CZe9hU7H.js → styles-d45a18b0-D2yoeLkD.js} +4 -4
- package/app/out/renderer/assets/{svgDrawCommon-b86b1483-CmJZfZzJ.js → svgDrawCommon-b86b1483-7THlOYFk.js} +1 -1
- package/app/out/renderer/assets/{timeline-definition-faaaa080-Beo2kiiz.js → timeline-definition-faaaa080-BVp4ikHz.js} +3 -3
- package/app/out/renderer/assets/{xychartDiagram-f5964ef8-DYmo7moz.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
|
@@ -6841,7 +6841,8 @@ async function createCoordinator(config) {
|
|
|
6841
6841
|
const routerByProvider = {
|
|
6842
6842
|
anthropic: "claude-haiku-4-5-20251001",
|
|
6843
6843
|
openai: "gpt-5.4-nano",
|
|
6844
|
-
"openai-codex": "gpt-5.4-
|
|
6844
|
+
"openai-codex": "gpt-5.4-mini",
|
|
6845
|
+
// nano not available in openai-codex provider
|
|
6845
6846
|
google: "gemini-2.0-flash-lite"
|
|
6846
6847
|
};
|
|
6847
6848
|
let mainProvider = null;
|
|
@@ -7039,7 +7040,7 @@ The conversation continues below.`,
|
|
|
7039
7040
|
});
|
|
7040
7041
|
}
|
|
7041
7042
|
async function clearSessionMemory() {
|
|
7042
|
-
agent.
|
|
7043
|
+
agent.reset();
|
|
7043
7044
|
compactionSummary = void 0;
|
|
7044
7045
|
}
|
|
7045
7046
|
async function maybeGenerateSummary() {
|
|
@@ -7096,7 +7097,7 @@ ${historyText}`,
|
|
|
7096
7097
|
if (process.env.ENABLE_LOCAL_COMPUTE === "1") {
|
|
7097
7098
|
probeStaticProfile().then((profile) => {
|
|
7098
7099
|
const envGuidance = generateAgentGuidance(profile);
|
|
7099
|
-
agent.
|
|
7100
|
+
agent.state.systemPrompt = baseSystemPrompt + "\n\n" + envGuidance;
|
|
7100
7101
|
}).catch(() => {
|
|
7101
7102
|
});
|
|
7102
7103
|
}
|
|
@@ -7155,7 +7156,7 @@ ${historyText}`,
|
|
|
7155
7156
|
|
|
7156
7157
|
${agentMdContent}`;
|
|
7157
7158
|
}
|
|
7158
|
-
agent.
|
|
7159
|
+
agent.state.systemPrompt = enrichedSystem;
|
|
7159
7160
|
const contextParts = [];
|
|
7160
7161
|
if (summaryContext) contextParts.push(summaryContext);
|
|
7161
7162
|
if (skillSummariesPrompt) contextParts.push(skillSummariesPrompt);
|
|
@@ -7233,6 +7234,10 @@ ${message}` : message;
|
|
|
7233
7234
|
}
|
|
7234
7235
|
},
|
|
7235
7236
|
clearSessionMemory,
|
|
7237
|
+
/** Stop the current LLM turn without tearing down tools. */
|
|
7238
|
+
abort() {
|
|
7239
|
+
agent.abort();
|
|
7240
|
+
},
|
|
7236
7241
|
async destroy() {
|
|
7237
7242
|
agent.abort();
|
|
7238
7243
|
await destroyResearchTools();
|
|
@@ -7905,11 +7910,11 @@ function getCachedMarkdown(filePath, projectPath) {
|
|
|
7905
7910
|
const mtime = stat.mtimeMs;
|
|
7906
7911
|
const cacheDir = join(projectPath, PATHS.documentCache);
|
|
7907
7912
|
const cacheKey2 = getCacheKey(filePath, mtime);
|
|
7908
|
-
const
|
|
7909
|
-
if (!existsSync(
|
|
7913
|
+
const cachePath = join(cacheDir, cacheKey2);
|
|
7914
|
+
if (!existsSync(cachePath)) {
|
|
7910
7915
|
return null;
|
|
7911
7916
|
}
|
|
7912
|
-
const entry = JSON.parse(readFileSync(
|
|
7917
|
+
const entry = JSON.parse(readFileSync(cachePath, "utf-8"));
|
|
7913
7918
|
if (entry.sourcePath !== filePath || entry.sourceMtime !== mtime) {
|
|
7914
7919
|
return null;
|
|
7915
7920
|
}
|
|
@@ -7924,14 +7929,14 @@ function setCachedMarkdown(filePath, markdown, projectPath) {
|
|
|
7924
7929
|
const mtime = stat.mtimeMs;
|
|
7925
7930
|
const cacheDir = ensureCacheDir(projectPath);
|
|
7926
7931
|
const cacheKey2 = getCacheKey(filePath, mtime);
|
|
7927
|
-
const
|
|
7932
|
+
const cachePath = join(cacheDir, cacheKey2);
|
|
7928
7933
|
const entry = {
|
|
7929
7934
|
sourcePath: filePath,
|
|
7930
7935
|
sourceMtime: mtime,
|
|
7931
7936
|
markdown,
|
|
7932
7937
|
cachedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
7933
7938
|
};
|
|
7934
|
-
writeFileSync(
|
|
7939
|
+
writeFileSync(cachePath, JSON.stringify(entry, null, 2), "utf-8");
|
|
7935
7940
|
} catch (err) {
|
|
7936
7941
|
console.warn("[document-cache] Failed to cache markdown:", err);
|
|
7937
7942
|
}
|
|
@@ -8122,35 +8127,36 @@ const SKIP_DIRS = /* @__PURE__ */ new Set([
|
|
|
8122
8127
|
".venv",
|
|
8123
8128
|
"venv"
|
|
8124
8129
|
]);
|
|
8125
|
-
|
|
8126
|
-
|
|
8127
|
-
let
|
|
8128
|
-
|
|
8129
|
-
|
|
8130
|
-
|
|
8131
|
-
cachedFiles = [];
|
|
8132
|
-
cachedProjectPath = projectPath;
|
|
8133
|
-
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);
|
|
8134
8136
|
}
|
|
8137
|
+
return c;
|
|
8138
|
+
}
|
|
8139
|
+
async function getFileList(projectPath) {
|
|
8140
|
+
const c = getOrCreateCache(projectPath);
|
|
8135
8141
|
const now = Date.now();
|
|
8136
|
-
if (
|
|
8137
|
-
return
|
|
8142
|
+
if (c.files.length > 0 && now - c.lastRefreshAt < REFRESH_THROTTLE_MS) {
|
|
8143
|
+
return c.files;
|
|
8138
8144
|
}
|
|
8139
|
-
if (refreshPromise) return refreshPromise;
|
|
8140
|
-
refreshPromise = refreshFileList(projectPath).finally(() => {
|
|
8141
|
-
refreshPromise = null;
|
|
8145
|
+
if (c.refreshPromise) return c.refreshPromise;
|
|
8146
|
+
c.refreshPromise = refreshFileList(projectPath, c).finally(() => {
|
|
8147
|
+
c.refreshPromise = null;
|
|
8142
8148
|
});
|
|
8143
|
-
return refreshPromise;
|
|
8149
|
+
return c.refreshPromise;
|
|
8144
8150
|
}
|
|
8145
|
-
async function refreshFileList(projectPath) {
|
|
8151
|
+
async function refreshFileList(projectPath, c) {
|
|
8146
8152
|
try {
|
|
8147
8153
|
const files = await gitLsFiles(projectPath);
|
|
8148
|
-
|
|
8154
|
+
c.files = files.slice(0, MAX_FILES);
|
|
8149
8155
|
} catch {
|
|
8150
|
-
|
|
8156
|
+
c.files = walkFilesSync(projectPath);
|
|
8151
8157
|
}
|
|
8152
|
-
lastRefreshAt = Date.now();
|
|
8153
|
-
return
|
|
8158
|
+
c.lastRefreshAt = Date.now();
|
|
8159
|
+
return c.files;
|
|
8154
8160
|
}
|
|
8155
8161
|
function gitLsFiles(cwd) {
|
|
8156
8162
|
return new Promise((resolve2, reject) => {
|
|
@@ -8200,20 +8206,24 @@ function walk(root, rel, depth, out) {
|
|
|
8200
8206
|
}
|
|
8201
8207
|
}
|
|
8202
8208
|
}
|
|
8203
|
-
|
|
8204
|
-
let cachePath = "";
|
|
8209
|
+
const caches = /* @__PURE__ */ new Map();
|
|
8205
8210
|
function getEntityCache(projectPath) {
|
|
8206
|
-
|
|
8207
|
-
|
|
8211
|
+
let c = caches.get(projectPath);
|
|
8212
|
+
if (c) return c;
|
|
8213
|
+
c = {
|
|
8208
8214
|
notes: listNotes(projectPath),
|
|
8209
8215
|
papers: listLiterature(projectPath),
|
|
8210
8216
|
data: listData(projectPath)
|
|
8211
8217
|
};
|
|
8212
|
-
|
|
8213
|
-
return
|
|
8218
|
+
caches.set(projectPath, c);
|
|
8219
|
+
return c;
|
|
8214
8220
|
}
|
|
8215
|
-
function invalidateEntityCache() {
|
|
8216
|
-
|
|
8221
|
+
function invalidateEntityCache(projectPath) {
|
|
8222
|
+
if (projectPath) {
|
|
8223
|
+
caches.delete(projectPath);
|
|
8224
|
+
} else {
|
|
8225
|
+
caches.clear();
|
|
8226
|
+
}
|
|
8217
8227
|
}
|
|
8218
8228
|
const SCORE_MATCH = 16;
|
|
8219
8229
|
const BONUS_FIRST_CHAR = 8;
|
|
@@ -9115,7 +9125,7 @@ async function ensureCoordinator(state, win, model, options) {
|
|
|
9115
9125
|
if ((tool === "artifact-create" || tool === "artifact-update") && result && typeof result === "object" && "success" in result) {
|
|
9116
9126
|
const r2 = result;
|
|
9117
9127
|
if (r2.success) {
|
|
9118
|
-
invalidateEntityCache();
|
|
9128
|
+
invalidateEntityCache(runProjectPath);
|
|
9119
9129
|
if (tool === "artifact-create") {
|
|
9120
9130
|
safeSend(win, "agent:entity-created", {
|
|
9121
9131
|
type: r2.data?.type || "artifact",
|
|
@@ -9345,7 +9355,7 @@ function registerIpcHandlers() {
|
|
|
9345
9355
|
});
|
|
9346
9356
|
handleWindow("agent:stop", ({ state }) => {
|
|
9347
9357
|
if (state.coordinator) {
|
|
9348
|
-
state.coordinator.
|
|
9358
|
+
state.coordinator.abort();
|
|
9349
9359
|
}
|
|
9350
9360
|
});
|
|
9351
9361
|
handleWindow("agent:clear-memory", async ({ state }) => {
|
|
@@ -9371,15 +9381,25 @@ function registerIpcHandlers() {
|
|
|
9371
9381
|
});
|
|
9372
9382
|
handleWindow("cmd:delete", ({ state }, id) => {
|
|
9373
9383
|
if (!state.projectPath) return { success: false, error: "No project folder selected." };
|
|
9374
|
-
|
|
9384
|
+
const result = deleteEntity(id, state.projectPath);
|
|
9385
|
+
invalidateEntityCache(state.projectPath);
|
|
9386
|
+
return result;
|
|
9375
9387
|
});
|
|
9376
9388
|
handleWindow("cmd:artifact-create", ({ state }, input) => {
|
|
9377
9389
|
if (!state.projectPath) return { success: false, error: "No project folder selected." };
|
|
9378
|
-
|
|
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;
|
|
9379
9395
|
});
|
|
9380
9396
|
handleWindow("cmd:artifact-update", ({ state }, artifactId, patch) => {
|
|
9381
9397
|
if (!state.projectPath) return { success: false, error: "No project folder selected." };
|
|
9382
|
-
|
|
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;
|
|
9383
9403
|
});
|
|
9384
9404
|
handleWindow("cmd:artifact-get", ({ state }, artifactId) => {
|
|
9385
9405
|
if (!state.projectPath) return null;
|
|
@@ -9395,7 +9415,11 @@ function registerIpcHandlers() {
|
|
|
9395
9415
|
});
|
|
9396
9416
|
handleWindow("cmd:artifact-delete", ({ state }, artifactId) => {
|
|
9397
9417
|
if (!state.projectPath) return { success: false, error: "No project folder selected." };
|
|
9398
|
-
|
|
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;
|
|
9399
9423
|
});
|
|
9400
9424
|
handleWindow("cmd:turn-explain-get", ({ state }) => {
|
|
9401
9425
|
if (!state.projectPath) return { success: false, error: "No project folder selected." };
|
|
@@ -9741,16 +9765,56 @@ function registerIpcHandlers() {
|
|
|
9741
9765
|
return null;
|
|
9742
9766
|
}
|
|
9743
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
|
+
});
|
|
9744
9812
|
handleWindow("project:pick-folder", async ({ win, state }) => {
|
|
9745
9813
|
const result = await dialog.showOpenDialog(win, {
|
|
9746
9814
|
properties: ["openDirectory", "createDirectory"]
|
|
9747
9815
|
});
|
|
9748
9816
|
if (!result.canceled && result.filePaths[0]) {
|
|
9749
9817
|
if (state.coordinator) {
|
|
9750
|
-
try {
|
|
9751
|
-
state.coordinator.agent.stop();
|
|
9752
|
-
} catch {
|
|
9753
|
-
}
|
|
9754
9818
|
try {
|
|
9755
9819
|
await state.coordinator.destroy();
|
|
9756
9820
|
} catch {
|
|
@@ -9792,6 +9856,7 @@ function registerIpcHandlers() {
|
|
|
9792
9856
|
}).catch(() => {
|
|
9793
9857
|
});
|
|
9794
9858
|
}
|
|
9859
|
+
win.setTitle(basename(state.projectPath));
|
|
9795
9860
|
return { projectPath: state.projectPath, sessionId: state.sessionId };
|
|
9796
9861
|
}
|
|
9797
9862
|
return null;
|
|
@@ -9801,8 +9866,7 @@ function registerIpcHandlers() {
|
|
|
9801
9866
|
try {
|
|
9802
9867
|
if (state.coordinator) {
|
|
9803
9868
|
try {
|
|
9804
|
-
;
|
|
9805
|
-
state.coordinator.agent.stop();
|
|
9869
|
+
state.coordinator.abort();
|
|
9806
9870
|
} catch {
|
|
9807
9871
|
}
|
|
9808
9872
|
}
|
|
@@ -9817,6 +9881,8 @@ function registerIpcHandlers() {
|
|
|
9817
9881
|
state.realtimeBuffer.reset();
|
|
9818
9882
|
state.projectPath = "";
|
|
9819
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");
|
|
9820
9886
|
state.currentModel = "openai:gpt-5.4";
|
|
9821
9887
|
state.currentReasoningEffort = "medium";
|
|
9822
9888
|
state.currentAuthMode = "none";
|
|
@@ -10012,6 +10078,15 @@ function buildMenu() {
|
|
|
10012
10078
|
}
|
|
10013
10079
|
},
|
|
10014
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" },
|
|
10015
10090
|
{
|
|
10016
10091
|
label: "Close Project",
|
|
10017
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),
|