research-copilot 0.2.3 → 0.2.5
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 +154 -48
- package/app/out/preload/index.js +7 -0
- package/app/out/renderer/assets/{MilkdownMarkdownEditor-DjFLwyh4.js → MilkdownMarkdownEditor-2wg63TSu.js} +50 -50
- package/app/out/renderer/assets/{arc-7NllWjXF.js → arc-Bpvizsn8.js} +1 -1
- package/app/out/renderer/assets/{blockDiagram-c4efeb88-DsOU-_zA.js → blockDiagram-c4efeb88-BopVnbxX.js} +8 -8
- package/app/out/renderer/assets/{c4Diagram-c83219d4-U2jdevgc.js → c4Diagram-c83219d4-DYK03hOG.js} +3 -3
- package/app/out/renderer/assets/{channel-Cjd8jvi8.js → channel-CmlMCRa3.js} +1 -1
- package/app/out/renderer/assets/{classDiagram-beda092f-Yj0hyRiU.js → classDiagram-beda092f-oSGZIrY_.js} +6 -6
- package/app/out/renderer/assets/{classDiagram-v2-2358418a-CK0FL8Pk.js → classDiagram-v2-2358418a-BHM8844_.js} +10 -10
- package/app/out/renderer/assets/{clone-I16owcK3.js → clone-PITMMgBv.js} +1 -1
- package/app/out/renderer/assets/{createText-1719965b-D_GY3BGW.js → createText-1719965b-BN3FKtRi.js} +2 -2
- package/app/out/renderer/assets/{edges-96097737-DKD2znJk.js → edges-96097737-76OqZvY1.js} +3 -3
- package/app/out/renderer/assets/{erDiagram-0228fc6a-CxrCv4uP.js → erDiagram-0228fc6a-CtXOkjA1.js} +5 -5
- package/app/out/renderer/assets/{flowDb-c6c81e3f-8o4wFApi.js → flowDb-c6c81e3f-BCT1eQU9.js} +1 -1
- package/app/out/renderer/assets/{flowDiagram-50d868cf-B1eYKlZC.js → flowDiagram-50d868cf-BKR9gSZL.js} +12 -12
- package/app/out/renderer/assets/{flowDiagram-v2-4f6560a1-Y4_T8Xi1.js → flowDiagram-v2-4f6560a1-CBGrwW2p.js} +12 -12
- package/app/out/renderer/assets/{flowchart-elk-definition-6af322e1-BjDPU2Ol.js → flowchart-elk-definition-6af322e1-CQxHOjqj.js} +6 -6
- package/app/out/renderer/assets/{ganttDiagram-a2739b55-CdQAT7up.js → ganttDiagram-a2739b55-BVsEi_1s.js} +3 -3
- package/app/out/renderer/assets/{gitGraphDiagram-82fe8481-Bl7KP_G5.js → gitGraphDiagram-82fe8481-BlGuagiw.js} +2 -2
- package/app/out/renderer/assets/{graph-Bje_pjwC.js → graph-B-Uy9LVb.js} +1 -1
- package/app/out/renderer/assets/{index-5325376f-DB5UfMSQ.js → index-5325376f-DFVM9bEE.js} +6 -6
- package/app/out/renderer/assets/{index-BnGN3XMZ.js → index-9DibXU9f.js} +6 -6
- package/app/out/renderer/assets/{index-BWkpc_Fb.js → index-B8_hOntP.js} +3 -3
- package/app/out/renderer/assets/{index-TtJcntKb.js → index-BRtK-r6R.js} +3 -3
- package/app/out/renderer/assets/{index-CU1ei-Q-.js → index-BW7eNq5J.js} +6 -6
- package/app/out/renderer/assets/{index-BlSmCt8A.js → index-BcKf35dV.js} +6 -6
- package/app/out/renderer/assets/{index-CT1HtzVp.css → index-BllgkT3a.css} +83 -0
- package/app/out/renderer/assets/{index-CTrj2aB2.js → index-BrQ_Y-LE.js} +3 -3
- package/app/out/renderer/assets/{index-BX5-hWqk.js → index-C0Czl4Cv.js} +3 -3
- package/app/out/renderer/assets/{index-BHl_tELv.js → index-CoEolmNf.js} +5 -5
- package/app/out/renderer/assets/{index-CISiP4Vc.js → index-DFnA5GRw.js} +255 -63
- package/app/out/renderer/assets/{index-CDWVrn8L.js → index-Dk7Wa0Je.js} +3 -3
- package/app/out/renderer/assets/{index-UYsogkLv.js → index-DkVOuuVx.js} +6 -6
- package/app/out/renderer/assets/{index-bPpSppnq.js → index-DlRaaYEU.js} +3 -3
- package/app/out/renderer/assets/{index-K7KmUSPg.js → index-DlUgEE0Z.js} +3 -3
- package/app/out/renderer/assets/{index-D9YGyBA9.js → index-Dt57Xb0R.js} +3 -3
- package/app/out/renderer/assets/{index-DCr-i28b.js → index-PVPY9npp.js} +3 -3
- package/app/out/renderer/assets/{index-CoIRGlb6.js → index-SoluVSbR.js} +3 -3
- package/app/out/renderer/assets/{index-DihmTRDX.js → index-cLiUsMmu.js} +6 -6
- package/app/out/renderer/assets/{index-hI44wokU.js → index-i5J_uYOr.js} +6 -6
- package/app/out/renderer/assets/{index-DIB3jH2J.js → index-j9e1ML36.js} +1 -1
- package/app/out/renderer/assets/{index-BbbK94Tl.js → index-jJGUNJNs.js} +4 -4
- package/app/out/renderer/assets/{index-DkTtiwdL.js → index-jMygKcX_.js} +3 -3
- package/app/out/renderer/assets/{index-DRgsVAez.js → index-rMj6TAlT.js} +4 -4
- package/app/out/renderer/assets/{index-DFmh36hv.js → index-wvsLwV9F.js} +3 -3
- package/app/out/renderer/assets/{infoDiagram-8eee0895-Dfty_4jM.js → infoDiagram-8eee0895-C6WcmMAB.js} +2 -2
- package/app/out/renderer/assets/{journeyDiagram-c64418c1-BzDYpsjx.js → journeyDiagram-c64418c1-wkVqZcQW.js} +4 -4
- package/app/out/renderer/assets/{layout-DbHSNFr9.js → layout-C6Q0z3G5.js} +2 -2
- package/app/out/renderer/assets/{line-jV7QLjZ_.js → line-BDJIIoze.js} +1 -1
- package/app/out/renderer/assets/{linear-CIeuNnVa.js → linear-95dGQxH4.js} +1 -1
- package/app/out/renderer/assets/{mindmap-definition-8da855dc-CeDEmTB-.js → mindmap-definition-8da855dc-DWlj4Xm-.js} +3 -3
- package/app/out/renderer/assets/{pieDiagram-a8764435-Bpm1FcX3.js → pieDiagram-a8764435-CrdnVfOv.js} +3 -3
- package/app/out/renderer/assets/{quadrantDiagram-1e28029f-CEB7PxJa.js → quadrantDiagram-1e28029f-M3YRJdbH.js} +3 -3
- package/app/out/renderer/assets/{requirementDiagram-08caed73-CZJU8B_1.js → requirementDiagram-08caed73-C08ql71g.js} +5 -5
- package/app/out/renderer/assets/{sankeyDiagram-a04cb91d-JXpwgeE0.js → sankeyDiagram-a04cb91d-C8ADDrm7.js} +2 -2
- package/app/out/renderer/assets/{sequenceDiagram-c5b8d532-CtvDQG5X.js → sequenceDiagram-c5b8d532-gNfcaPex.js} +3 -3
- package/app/out/renderer/assets/{stateDiagram-1ecb1508-DQRUQm_b.js → stateDiagram-1ecb1508-CbYo7fPM.js} +6 -6
- package/app/out/renderer/assets/{stateDiagram-v2-c2b004d7-qWcRpqpV.js → stateDiagram-v2-c2b004d7-C9NIgZa5.js} +10 -10
- package/app/out/renderer/assets/{styles-b4e223ce-6DWryYQB.js → styles-b4e223ce-DgvzV6cM.js} +1 -1
- package/app/out/renderer/assets/{styles-ca3715f6-CZ9SeO17.js → styles-ca3715f6-Dxd4UtQU.js} +1 -1
- package/app/out/renderer/assets/{styles-d45a18b0-Bkmie_Qv.js → styles-d45a18b0-C0jzXR3J.js} +4 -4
- package/app/out/renderer/assets/{svgDrawCommon-b86b1483-BWRX1ZPq.js → svgDrawCommon-b86b1483-CjGKGyYF.js} +1 -1
- package/app/out/renderer/assets/{timeline-definition-faaaa080-XcgfjspK.js → timeline-definition-faaaa080-CRz7hPUx.js} +3 -3
- package/app/out/renderer/assets/{xychartDiagram-f5964ef8-C0CQzgr8.js → xychartDiagram-f5964ef8-BI-asLSS.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;
|
|
@@ -8866,6 +8875,15 @@ function resetUsageTotals(baseDir) {
|
|
|
8866
8875
|
writeAtomically(usagePath(baseDir), JSON.stringify(cleared, null, 2));
|
|
8867
8876
|
return cleared;
|
|
8868
8877
|
}
|
|
8878
|
+
function compareVersions(a, b) {
|
|
8879
|
+
const pa = a.split(".").map(Number);
|
|
8880
|
+
const pb = b.split(".").map(Number);
|
|
8881
|
+
for (let i = 0; i < 3; i++) {
|
|
8882
|
+
const diff = (pa[i] || 0) - (pb[i] || 0);
|
|
8883
|
+
if (diff !== 0) return diff;
|
|
8884
|
+
}
|
|
8885
|
+
return 0;
|
|
8886
|
+
}
|
|
8869
8887
|
function formatToolCall(tool, args) {
|
|
8870
8888
|
const a = args && typeof args === "object" ? args : {};
|
|
8871
8889
|
const config = getToolRenderConfig(tool);
|
|
@@ -9116,7 +9134,7 @@ async function ensureCoordinator(state, win, model, options) {
|
|
|
9116
9134
|
if ((tool === "artifact-create" || tool === "artifact-update") && result && typeof result === "object" && "success" in result) {
|
|
9117
9135
|
const r2 = result;
|
|
9118
9136
|
if (r2.success) {
|
|
9119
|
-
invalidateEntityCache();
|
|
9137
|
+
invalidateEntityCache(runProjectPath);
|
|
9120
9138
|
if (tool === "artifact-create") {
|
|
9121
9139
|
safeSend(win, "agent:entity-created", {
|
|
9122
9140
|
type: r2.data?.type || "artifact",
|
|
@@ -9261,6 +9279,29 @@ async function destroyAllCoordinators() {
|
|
|
9261
9279
|
function registerIpcHandlers() {
|
|
9262
9280
|
if (ipcHandlersRegistered) return;
|
|
9263
9281
|
ipcHandlersRegistered = true;
|
|
9282
|
+
let cachedUpdateInfo = null;
|
|
9283
|
+
const checkForUpdate = async () => {
|
|
9284
|
+
if (cachedUpdateInfo) return cachedUpdateInfo;
|
|
9285
|
+
try {
|
|
9286
|
+
const res = await fetch("https://registry.npmjs.org/research-copilot/latest", {
|
|
9287
|
+
signal: AbortSignal.timeout(5e3)
|
|
9288
|
+
});
|
|
9289
|
+
if (!res.ok) throw new Error(`npm registry returned ${res.status}`);
|
|
9290
|
+
const data = await res.json();
|
|
9291
|
+
const latest = data.version;
|
|
9292
|
+
const current = app.getVersion();
|
|
9293
|
+
const hasUpdate = latest !== current && compareVersions(latest, current) > 0;
|
|
9294
|
+
cachedUpdateInfo = { latest, current, hasUpdate };
|
|
9295
|
+
return cachedUpdateInfo;
|
|
9296
|
+
} catch {
|
|
9297
|
+
const current = app.getVersion();
|
|
9298
|
+
cachedUpdateInfo = { latest: current, current, hasUpdate: false };
|
|
9299
|
+
return cachedUpdateInfo;
|
|
9300
|
+
}
|
|
9301
|
+
};
|
|
9302
|
+
ipcMain.handle("app:check-update", () => checkForUpdate());
|
|
9303
|
+
checkForUpdate().catch(() => {
|
|
9304
|
+
});
|
|
9264
9305
|
const builtinSkillsRoot = app.isPackaged ? join(process.resourcesPath, "skills") : join(__dirname, "..", "..", "..", "lib", "skills");
|
|
9265
9306
|
setBuiltinSkillsRoot(builtinSkillsRoot);
|
|
9266
9307
|
const handleWindow = (channel, handler) => {
|
|
@@ -9346,7 +9387,7 @@ function registerIpcHandlers() {
|
|
|
9346
9387
|
});
|
|
9347
9388
|
handleWindow("agent:stop", ({ state }) => {
|
|
9348
9389
|
if (state.coordinator) {
|
|
9349
|
-
state.coordinator.
|
|
9390
|
+
state.coordinator.abort();
|
|
9350
9391
|
}
|
|
9351
9392
|
});
|
|
9352
9393
|
handleWindow("agent:clear-memory", async ({ state }) => {
|
|
@@ -9372,15 +9413,25 @@ function registerIpcHandlers() {
|
|
|
9372
9413
|
});
|
|
9373
9414
|
handleWindow("cmd:delete", ({ state }, id) => {
|
|
9374
9415
|
if (!state.projectPath) return { success: false, error: "No project folder selected." };
|
|
9375
|
-
|
|
9416
|
+
const result = deleteEntity(id, state.projectPath);
|
|
9417
|
+
invalidateEntityCache(state.projectPath);
|
|
9418
|
+
return result;
|
|
9376
9419
|
});
|
|
9377
9420
|
handleWindow("cmd:artifact-create", ({ state }, input) => {
|
|
9378
9421
|
if (!state.projectPath) return { success: false, error: "No project folder selected." };
|
|
9379
|
-
|
|
9422
|
+
const result = artifactCreate(input, { sessionId: state.sessionId, projectPath: state.projectPath });
|
|
9423
|
+
if (result && typeof result === "object" && "success" in result && result.success) {
|
|
9424
|
+
invalidateEntityCache(state.projectPath);
|
|
9425
|
+
}
|
|
9426
|
+
return result;
|
|
9380
9427
|
});
|
|
9381
9428
|
handleWindow("cmd:artifact-update", ({ state }, artifactId, patch) => {
|
|
9382
9429
|
if (!state.projectPath) return { success: false, error: "No project folder selected." };
|
|
9383
|
-
|
|
9430
|
+
const result = artifactUpdate(state.projectPath, artifactId, patch);
|
|
9431
|
+
if (result && typeof result === "object" && "success" in result && result.success) {
|
|
9432
|
+
invalidateEntityCache(state.projectPath);
|
|
9433
|
+
}
|
|
9434
|
+
return result;
|
|
9384
9435
|
});
|
|
9385
9436
|
handleWindow("cmd:artifact-get", ({ state }, artifactId) => {
|
|
9386
9437
|
if (!state.projectPath) return null;
|
|
@@ -9396,7 +9447,11 @@ function registerIpcHandlers() {
|
|
|
9396
9447
|
});
|
|
9397
9448
|
handleWindow("cmd:artifact-delete", ({ state }, artifactId) => {
|
|
9398
9449
|
if (!state.projectPath) return { success: false, error: "No project folder selected." };
|
|
9399
|
-
|
|
9450
|
+
const result = artifactDelete(state.projectPath, artifactId);
|
|
9451
|
+
if (result && typeof result === "object" && "success" in result && result.success) {
|
|
9452
|
+
invalidateEntityCache(state.projectPath);
|
|
9453
|
+
}
|
|
9454
|
+
return result;
|
|
9400
9455
|
});
|
|
9401
9456
|
handleWindow("cmd:turn-explain-get", ({ state }) => {
|
|
9402
9457
|
if (!state.projectPath) return { success: false, error: "No project folder selected." };
|
|
@@ -9742,16 +9797,56 @@ function registerIpcHandlers() {
|
|
|
9742
9797
|
return null;
|
|
9743
9798
|
}
|
|
9744
9799
|
});
|
|
9800
|
+
handleWindow("chat:export", async ({ win, state }) => {
|
|
9801
|
+
if (!state.projectPath || !state.sessionId) {
|
|
9802
|
+
return { success: false, error: "No project open" };
|
|
9803
|
+
}
|
|
9804
|
+
const file = join(state.projectPath, PATHS.sessions, `${state.sessionId}.jsonl`);
|
|
9805
|
+
if (!existsSync(file)) {
|
|
9806
|
+
return { success: false, error: "No chat history found" };
|
|
9807
|
+
}
|
|
9808
|
+
const lines = readFileSync(file, "utf-8").split("\n").filter(Boolean);
|
|
9809
|
+
if (lines.length === 0) {
|
|
9810
|
+
return { success: false, error: "Chat history is empty" };
|
|
9811
|
+
}
|
|
9812
|
+
const projectName = basename(state.projectPath);
|
|
9813
|
+
const mdParts = [`# Chat Export — ${projectName}
|
|
9814
|
+
`];
|
|
9815
|
+
mdParts.push(`> Exported on ${(/* @__PURE__ */ new Date()).toLocaleString()}
|
|
9816
|
+
`);
|
|
9817
|
+
for (const line of lines) {
|
|
9818
|
+
try {
|
|
9819
|
+
const msg = JSON.parse(line);
|
|
9820
|
+
const time = msg.timestamp ? new Date(msg.timestamp).toLocaleString() : "";
|
|
9821
|
+
const roleLabel = msg.role === "user" ? "**You**" : msg.role === "assistant" ? "**Assistant**" : "**System**";
|
|
9822
|
+
mdParts.push(`---
|
|
9823
|
+
|
|
9824
|
+
### ${roleLabel}
|
|
9825
|
+
<sub>${time}</sub>
|
|
9826
|
+
|
|
9827
|
+
${msg.content}
|
|
9828
|
+
`);
|
|
9829
|
+
} catch {
|
|
9830
|
+
}
|
|
9831
|
+
}
|
|
9832
|
+
const markdown = mdParts.join("\n");
|
|
9833
|
+
const result = await dialog.showSaveDialog(win, {
|
|
9834
|
+
title: "Export Chat History",
|
|
9835
|
+
defaultPath: join(app.getPath("documents"), `${projectName}-chat-export.md`),
|
|
9836
|
+
filters: [{ name: "Markdown", extensions: ["md"] }]
|
|
9837
|
+
});
|
|
9838
|
+
if (result.canceled || !result.filePath) {
|
|
9839
|
+
return { success: false, error: "Cancelled" };
|
|
9840
|
+
}
|
|
9841
|
+
writeFileSync(result.filePath, markdown, "utf-8");
|
|
9842
|
+
return { success: true, path: result.filePath };
|
|
9843
|
+
});
|
|
9745
9844
|
handleWindow("project:pick-folder", async ({ win, state }) => {
|
|
9746
9845
|
const result = await dialog.showOpenDialog(win, {
|
|
9747
9846
|
properties: ["openDirectory", "createDirectory"]
|
|
9748
9847
|
});
|
|
9749
9848
|
if (!result.canceled && result.filePaths[0]) {
|
|
9750
9849
|
if (state.coordinator) {
|
|
9751
|
-
try {
|
|
9752
|
-
state.coordinator.agent.stop();
|
|
9753
|
-
} catch {
|
|
9754
|
-
}
|
|
9755
9850
|
try {
|
|
9756
9851
|
await state.coordinator.destroy();
|
|
9757
9852
|
} catch {
|
|
@@ -9793,6 +9888,7 @@ function registerIpcHandlers() {
|
|
|
9793
9888
|
}).catch(() => {
|
|
9794
9889
|
});
|
|
9795
9890
|
}
|
|
9891
|
+
win.setTitle(basename(state.projectPath));
|
|
9796
9892
|
return { projectPath: state.projectPath, sessionId: state.sessionId };
|
|
9797
9893
|
}
|
|
9798
9894
|
return null;
|
|
@@ -9802,8 +9898,7 @@ function registerIpcHandlers() {
|
|
|
9802
9898
|
try {
|
|
9803
9899
|
if (state.coordinator) {
|
|
9804
9900
|
try {
|
|
9805
|
-
;
|
|
9806
|
-
state.coordinator.agent.stop();
|
|
9901
|
+
state.coordinator.abort();
|
|
9807
9902
|
} catch {
|
|
9808
9903
|
}
|
|
9809
9904
|
}
|
|
@@ -9818,6 +9913,8 @@ function registerIpcHandlers() {
|
|
|
9818
9913
|
state.realtimeBuffer.reset();
|
|
9819
9914
|
state.projectPath = "";
|
|
9820
9915
|
state.sessionId = crypto.randomUUID();
|
|
9916
|
+
const win = BrowserWindow.getAllWindows().find((w) => windowStates.get(w.webContents.id) === state);
|
|
9917
|
+
if (win) win.setTitle("Research Pilot");
|
|
9821
9918
|
state.currentModel = "openai:gpt-5.4";
|
|
9822
9919
|
state.currentReasoningEffort = "medium";
|
|
9823
9920
|
state.currentAuthMode = "none";
|
|
@@ -10013,6 +10110,15 @@ function buildMenu() {
|
|
|
10013
10110
|
}
|
|
10014
10111
|
},
|
|
10015
10112
|
{ type: "separator" },
|
|
10113
|
+
{
|
|
10114
|
+
label: "Export Chat…",
|
|
10115
|
+
accelerator: "CmdOrCtrl+Shift+E",
|
|
10116
|
+
click: () => {
|
|
10117
|
+
const target = BrowserWindow.getFocusedWindow() ?? BrowserWindow.getAllWindows()[0];
|
|
10118
|
+
if (target) target.webContents.send("menu:export-chat");
|
|
10119
|
+
}
|
|
10120
|
+
},
|
|
10121
|
+
{ type: "separator" },
|
|
10016
10122
|
{
|
|
10017
10123
|
label: "Close Project",
|
|
10018
10124
|
accelerator: "CmdOrCtrl+Shift+K",
|
package/app/out/preload/index.js
CHANGED
|
@@ -143,6 +143,13 @@ 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
|
+
checkForUpdate: () => electron.ipcRenderer.invoke("app:check-update"),
|
|
147
|
+
exportChat: () => electron.ipcRenderer.invoke("chat:export"),
|
|
148
|
+
onExportChat: (cb) => {
|
|
149
|
+
const handler = () => cb();
|
|
150
|
+
electron.ipcRenderer.on("menu:export-chat", handler);
|
|
151
|
+
return () => electron.ipcRenderer.removeListener("menu:export-chat", handler);
|
|
152
|
+
},
|
|
146
153
|
saveMessage: (sessionId, msg) => electron.ipcRenderer.invoke("session:save-message", sessionId, msg),
|
|
147
154
|
loadMessages: (sessionId, offset, limit) => electron.ipcRenderer.invoke("session:load-messages", sessionId, offset, limit),
|
|
148
155
|
getMessageCount: (sessionId) => electron.ipcRenderer.invoke("session:get-total-count", sessionId),
|