research-copilot 0.2.16 → 0.2.20

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.
Files changed (70) hide show
  1. package/README.md +6 -0
  2. package/app/out/main/index.mjs +124 -7
  3. package/app/out/preload/index.js +2 -0
  4. package/app/out/renderer/assets/{MilkdownMarkdownEditor-CuTa5j4S.js → MilkdownMarkdownEditor-Bj7JSjF5.js} +93 -51
  5. package/app/out/renderer/assets/{MilkdownMarkdownEditor-tTNRIB2K.css → MilkdownMarkdownEditor-CCdZ2mtg.css} +88 -15
  6. package/app/out/renderer/assets/{arc-BAWS3N-F.js → arc-CPL9nDFE.js} +1 -1
  7. package/app/out/renderer/assets/{blockDiagram-c4efeb88-BHadwPqY.js → blockDiagram-c4efeb88-BFOajDNs.js} +8 -8
  8. package/app/out/renderer/assets/{c4Diagram-c83219d4-B3kOxRad.js → c4Diagram-c83219d4-LeqnQ2-5.js} +3 -3
  9. package/app/out/renderer/assets/{channel-Bll9CBqI.js → channel-jk5Np8ud.js} +1 -1
  10. package/app/out/renderer/assets/{classDiagram-beda092f-Dv7owGyx.js → classDiagram-beda092f-CxOqB6OU.js} +6 -6
  11. package/app/out/renderer/assets/{classDiagram-v2-2358418a-cWrqk5tQ.js → classDiagram-v2-2358418a-CyP_5qLa.js} +10 -10
  12. package/app/out/renderer/assets/{clone-D-DQ4nnY.js → clone-PHFwh58n.js} +1 -1
  13. package/app/out/renderer/assets/{createText-1719965b-ciE8YuqI.js → createText-1719965b-CE_0jsfj.js} +2 -2
  14. package/app/out/renderer/assets/{edges-96097737-DycnAYk_.js → edges-96097737-DBk1JhZS.js} +3 -3
  15. package/app/out/renderer/assets/{erDiagram-0228fc6a-Sv78YNMY.js → erDiagram-0228fc6a-DnR_LkSB.js} +5 -5
  16. package/app/out/renderer/assets/{flowDb-c6c81e3f-BiOarg9b.js → flowDb-c6c81e3f-CJrZUKlS.js} +1 -1
  17. package/app/out/renderer/assets/{flowDiagram-50d868cf-19J80nxU.js → flowDiagram-50d868cf-CfNfrt17.js} +12 -12
  18. package/app/out/renderer/assets/{flowDiagram-v2-4f6560a1-c-kGsubV.js → flowDiagram-v2-4f6560a1-BGQtiK3j.js} +12 -12
  19. package/app/out/renderer/assets/{flowchart-elk-definition-6af322e1-DRrYbiSC.js → flowchart-elk-definition-6af322e1-BXLraghz.js} +6 -6
  20. package/app/out/renderer/assets/{ganttDiagram-a2739b55-BadmpvMy.js → ganttDiagram-a2739b55-CAwaEMMm.js} +3 -3
  21. package/app/out/renderer/assets/{gitGraphDiagram-82fe8481-BdVoj60Q.js → gitGraphDiagram-82fe8481-vuSEC6ny.js} +2 -2
  22. package/app/out/renderer/assets/{graph-jZhookGR.js → graph-CZfltE7S.js} +1 -1
  23. package/app/out/renderer/assets/{index-5325376f-CbxmatXv.js → index-5325376f-DWTrHDEo.js} +6 -6
  24. package/app/out/renderer/assets/{index-DEO9Jh2Y.js → index-7dcVwInU.js} +5 -5
  25. package/app/out/renderer/assets/{index-BTE0dEKO.js → index-B4V7cFWJ.js} +6 -6
  26. package/app/out/renderer/assets/{index-DQwFQR1s.js → index-B5Mkpo9f.js} +3 -3
  27. package/app/out/renderer/assets/{index-CirXkIv2.js → index-B6f2bVW_.js} +3 -3
  28. package/app/out/renderer/assets/{index-DO5LsHlM.js → index-BgAs-p8D.js} +1 -1
  29. package/app/out/renderer/assets/{index-DOUTte7i.js → index-BpdWQuss.js} +3 -3
  30. package/app/out/renderer/assets/{index-B9kkJj3J.js → index-C2tqvXjC.js} +6 -6
  31. package/app/out/renderer/assets/{index-D-ZMmLhv.js → index-CMfKxpBP.js} +3 -3
  32. package/app/out/renderer/assets/{index-B2UUF9y9.js → index-CUsEKU8Q.js} +1199 -386
  33. package/app/out/renderer/assets/{index-BXpNbFhG.js → index-CaYWMBXT.js} +3 -3
  34. package/app/out/renderer/assets/{index-47oNNEnx.js → index-Cc9coKGN.js} +6 -6
  35. package/app/out/renderer/assets/{index-lAZsmnj1.css → index-CogwQwDN.css} +185 -32
  36. package/app/out/renderer/assets/{index-CAlpJ3-o.js → index-CwPfquqm.js} +4 -4
  37. package/app/out/renderer/assets/{index-CZX0435B.js → index-CyDfvefg.js} +6 -6
  38. package/app/out/renderer/assets/{index-BUcSHPha.js → index-DB8ImtMy.js} +3 -3
  39. package/app/out/renderer/assets/{index-B8fh500_.js → index-DIZJXKQ6.js} +3 -3
  40. package/app/out/renderer/assets/{index-CMGDsC_t.js → index-D_7yOLk3.js} +6 -6
  41. package/app/out/renderer/assets/{index-B110aKST.js → index-Di3HmXc-.js} +3 -3
  42. package/app/out/renderer/assets/{index-HCRA2-Q6.js → index-DiCqe1UR.js} +6 -6
  43. package/app/out/renderer/assets/{index-BWCwSkxb.js → index-DpXI4mHb.js} +3 -3
  44. package/app/out/renderer/assets/{index-cavFRVgM.js → index-EaGZvaBp.js} +3 -3
  45. package/app/out/renderer/assets/{index-DF_C6DjR.js → index-K0o5fHYG.js} +3 -3
  46. package/app/out/renderer/assets/{index-BBUnWjLe.js → index-Ul-Kq9b2.js} +3 -3
  47. package/app/out/renderer/assets/{index-g91Iwgxa.js → index-t0-md-MG.js} +4 -4
  48. package/app/out/renderer/assets/{infoDiagram-8eee0895-DpVt3Scv.js → infoDiagram-8eee0895-BmPESCfj.js} +2 -2
  49. package/app/out/renderer/assets/{journeyDiagram-c64418c1-RYKX5mcV.js → journeyDiagram-c64418c1-BGsCbfr_.js} +4 -4
  50. package/app/out/renderer/assets/{layout-BsbNXXgR.js → layout-5MwFTPs7.js} +2 -2
  51. package/app/out/renderer/assets/{line-OzQTpJsh.js → line-D0U74KO0.js} +1 -1
  52. package/app/out/renderer/assets/{linear-DO5pdnqi.js → linear-BclyBoiT.js} +1 -1
  53. package/app/out/renderer/assets/{mindmap-definition-8da855dc-D3zWs3h1.js → mindmap-definition-8da855dc-un1bPKBj.js} +3 -3
  54. package/app/out/renderer/assets/{pieDiagram-a8764435-DDoNhSgQ.js → pieDiagram-a8764435-B7KM3duv.js} +3 -3
  55. package/app/out/renderer/assets/{quadrantDiagram-1e28029f-ZO85SsRM.js → quadrantDiagram-1e28029f-C8i5m3Os.js} +3 -3
  56. package/app/out/renderer/assets/{requirementDiagram-08caed73-C-vKE6g8.js → requirementDiagram-08caed73-FjqENNN5.js} +5 -5
  57. package/app/out/renderer/assets/{sankeyDiagram-a04cb91d-Cbqb2K-X.js → sankeyDiagram-a04cb91d-BKV22yuJ.js} +2 -2
  58. package/app/out/renderer/assets/{sequenceDiagram-c5b8d532-BK4uvpEA.js → sequenceDiagram-c5b8d532-DWO-Z2i3.js} +3 -3
  59. package/app/out/renderer/assets/{stateDiagram-1ecb1508-DXa_YqNi.js → stateDiagram-1ecb1508-BqohgALA.js} +6 -6
  60. package/app/out/renderer/assets/{stateDiagram-v2-c2b004d7-Dm203Z8l.js → stateDiagram-v2-c2b004d7-B3sEkrB8.js} +10 -10
  61. package/app/out/renderer/assets/{styles-b4e223ce-BV4b1eAh.js → styles-b4e223ce-BGytHk8n.js} +1 -1
  62. package/app/out/renderer/assets/{styles-ca3715f6-CKhYSe7r.js → styles-ca3715f6-B0PvBknL.js} +1 -1
  63. package/app/out/renderer/assets/{styles-d45a18b0-DTCMfE-4.js → styles-d45a18b0-C6F384ai.js} +4 -4
  64. package/app/out/renderer/assets/{svgDrawCommon-b86b1483-DK4i-dfJ.js → svgDrawCommon-b86b1483-BXgThwM_.js} +1 -1
  65. package/app/out/renderer/assets/{timeline-definition-faaaa080-CE2LmuDH.js → timeline-definition-faaaa080-iNn5igPR.js} +3 -3
  66. package/app/out/renderer/assets/{xychartDiagram-f5964ef8-Bd8KT9X9.js → xychartDiagram-f5964ef8-oF_gxlk1.js} +5 -5
  67. package/app/out/renderer/index.html +2 -2
  68. package/package.json +2 -1
  69. package/scripts/backfill-papers.mjs +142 -0
  70. package/scripts/fix-node-pty-perms.mjs +32 -0
package/README.md CHANGED
@@ -206,6 +206,12 @@ Research Copilot stores its data in the workspace under `.research-pilot/`:
206
206
  └── session-summaries/
207
207
  ```
208
208
 
209
+ ## Community & Support
210
+
211
+ - **[Discussions](https://github.com/daidong/PiPilot/discussions)** — questions, ideas, usage tips, and general Q&A
212
+ - **[Issues](https://github.com/daidong/PiPilot/issues)** — bug reports and feature requests
213
+ - **[Wiki](https://github.com/daidong/PiPilot/wiki)** — setup walkthroughs, troubleshooting, and how-tos
214
+
209
215
  ## License
210
216
 
211
217
  [MIT](LICENSE)
@@ -1,9 +1,10 @@
1
- import { app, shell, ipcMain, BrowserWindow, dialog, Menu } from "electron";
1
+ import { app, shell, ipcMain, BrowserWindow, dialog, protocol, Menu } from "electron";
2
2
  import { setMaxListeners } from "node:events";
3
3
  import fs, { existsSync as existsSync$1 } from "node:fs";
4
+ import fsp, { readFile } from "node:fs/promises";
4
5
  import { execFile, spawn, execSync } from "node:child_process";
5
- import path, { resolve, join, sep, isAbsolute, extname, dirname, basename, relative } from "path";
6
- import { existsSync, statSync, readdirSync as readdirSync$1, readFileSync, writeFileSync, mkdirSync, appendFileSync, rmSync, unlinkSync, renameSync, openSync, constants, writeSync, closeSync, watch } from "fs";
6
+ import path, { resolve, join, sep, isAbsolute, basename, extname, dirname, relative } from "path";
7
+ import { existsSync, statSync, readdirSync as readdirSync$1, readFileSync, cpSync, writeFileSync, mkdirSync, appendFileSync, rmSync, unlinkSync, renameSync, openSync, constants, writeSync, closeSync, watch } from "fs";
7
8
  import os$1, { homedir } from "os";
8
9
  import { createHash, randomUUID } from "crypto";
9
10
  import { Agent } from "@mariozechner/pi-agent-core";
@@ -12,7 +13,6 @@ import { createCodingTools, createGrepTool, createFindTool, createLsTool, DEFAUL
12
13
  import { Type } from "@sinclair/typebox";
13
14
  import { mkdir, writeFile } from "fs/promises";
14
15
  import path$1 from "node:path";
15
- import fsp from "node:fs/promises";
16
16
  import crypto$1, { createHash as createHash$1 } from "node:crypto";
17
17
  import { promisify } from "node:util";
18
18
  import os from "node:os";
@@ -496,6 +496,38 @@ function registerFileHandlers(handle, getCtx) {
496
496
  return { success: false, error: err.message };
497
497
  }
498
498
  });
499
+ handle("file:reveal", (filePath) => {
500
+ const { projectPath } = getCtx();
501
+ const absPath = isAbsolute(filePath) ? filePath : resolve(projectPath, filePath);
502
+ if (!existsSync(absPath)) return { success: false, error: "Path not found." };
503
+ shell.showItemInFolder(absPath);
504
+ return { success: true };
505
+ });
506
+ handle("file:copy-item", (srcRelPath, destDirRelPath) => {
507
+ const { projectPath } = getCtx();
508
+ if (!projectPath) return { success: false, error: "No project folder selected." };
509
+ const srcAbs = isAbsolute(srcRelPath) ? srcRelPath : resolve(projectPath, srcRelPath);
510
+ const destDirAbs = isAbsolute(destDirRelPath) ? destDirRelPath : resolve(projectPath, destDirRelPath);
511
+ if (!isWithinRoot(projectPath, srcAbs)) return { success: false, error: "Source is outside workspace." };
512
+ if (!isWithinRoot(projectPath, destDirAbs)) return { success: false, error: "Destination is outside workspace." };
513
+ if (!existsSync(srcAbs)) return { success: false, error: "Source not found." };
514
+ const name = basename(srcAbs);
515
+ const ext = extname(name);
516
+ const stem = ext ? name.slice(0, -ext.length) : name;
517
+ let destAbs = join(destDirAbs, name);
518
+ let counter = 1;
519
+ while (existsSync(destAbs)) {
520
+ const suffix = counter === 1 ? " copy" : ` copy ${counter}`;
521
+ destAbs = join(destDirAbs, ext ? `${stem}${suffix}${ext}` : `${stem}${suffix}`);
522
+ counter++;
523
+ }
524
+ try {
525
+ cpSync(srcAbs, destAbs, { recursive: true });
526
+ return { success: true, destPath: destAbs };
527
+ } catch (err) {
528
+ return { success: false, error: err.message };
529
+ }
530
+ });
499
531
  handle("file:drop-to-dir", (fileName, base64Content, targetDirRelPath) => {
500
532
  const { projectPath } = getCtx();
501
533
  if (!projectPath) return { success: false, error: "No project folder selected." };
@@ -11346,6 +11378,46 @@ function scanForNewContent(projectPaths) {
11346
11378
  byCanonicalKey.set(identity.canonicalKey, existing);
11347
11379
  }
11348
11380
  }
11381
+ {
11382
+ const byArxivId = /* @__PURE__ */ new Map();
11383
+ for (const [key, entries] of byCanonicalKey) {
11384
+ for (const { artifact } of entries) {
11385
+ if (artifact.arxivId && isValidArxivId(artifact.arxivId)) {
11386
+ const bareId = artifact.arxivId.replace(/^https?:\/\/arxiv\.org\/abs\//, "").replace(/v\d+$/, "");
11387
+ const keys = byArxivId.get(bareId);
11388
+ if (keys) {
11389
+ if (!keys.includes(key)) keys.push(key);
11390
+ } else {
11391
+ byArxivId.set(bareId, [key]);
11392
+ }
11393
+ }
11394
+ }
11395
+ }
11396
+ for (const [, keys] of byArxivId) {
11397
+ if (keys.length < 2) continue;
11398
+ let winnerKey = null;
11399
+ const keyPriority = (k) => k.startsWith("doi:") ? 3 : k.startsWith("arxiv:") ? 2 : 1;
11400
+ for (const k of keys) {
11401
+ for (const entry of byCanonicalKey.get(k) || []) {
11402
+ const ident = computeCanonicalKey(entry.artifact);
11403
+ if (!winnerKey || keyPriority(ident.canonicalKey) > keyPriority(winnerKey)) {
11404
+ winnerKey = ident.canonicalKey;
11405
+ }
11406
+ }
11407
+ }
11408
+ if (!winnerKey || !keys.includes(winnerKey)) {
11409
+ winnerKey = keys.reduce((a, b) => keyPriority(a) > keyPriority(b) ? a : b);
11410
+ }
11411
+ for (const loserKey of keys) {
11412
+ if (loserKey === winnerKey) continue;
11413
+ const loserEntries = byCanonicalKey.get(loserKey);
11414
+ if (!loserEntries) continue;
11415
+ const winnerEntries = byCanonicalKey.get(winnerKey);
11416
+ winnerEntries.push(...loserEntries);
11417
+ byCanonicalKey.delete(loserKey);
11418
+ }
11419
+ }
11420
+ }
11349
11421
  for (const [canonicalKey, entries] of byCanonicalKey) {
11350
11422
  const best = entries.reduce((a, b) => {
11351
11423
  if (a.artifact.fulltextPath && !b.artifact.fulltextPath) return a;
@@ -12321,9 +12393,9 @@ function classifyKey(canonicalKey) {
12321
12393
  return "title";
12322
12394
  }
12323
12395
  const TIER_RANK = {
12324
- arxiv: 3,
12325
- // prefer real arxiv
12326
- doi: 2,
12396
+ doi: 3,
12397
+ // DOI > arXiv > title — matches computeCanonicalKey priority
12398
+ arxiv: 2,
12327
12399
  title: 1,
12328
12400
  bogus: 0
12329
12401
  };
@@ -13957,6 +14029,35 @@ function destroyAllTerminals() {
13957
14029
  terminals.delete(id);
13958
14030
  }
13959
14031
  }
14032
+ protocol.registerSchemesAsPrivileged([
14033
+ {
14034
+ scheme: "workspace-asset",
14035
+ privileges: {
14036
+ standard: true,
14037
+ secure: true,
14038
+ supportFetchAPI: true,
14039
+ stream: true,
14040
+ corsEnabled: true
14041
+ }
14042
+ }
14043
+ ]);
14044
+ function mimeForExtension(p) {
14045
+ const ext = (p.split(".").pop() || "").toLowerCase();
14046
+ const table = {
14047
+ png: "image/png",
14048
+ jpg: "image/jpeg",
14049
+ jpeg: "image/jpeg",
14050
+ gif: "image/gif",
14051
+ webp: "image/webp",
14052
+ svg: "image/svg+xml",
14053
+ bmp: "image/bmp",
14054
+ avif: "image/avif",
14055
+ ico: "image/x-icon",
14056
+ heic: "image/heic",
14057
+ heif: "image/heif"
14058
+ };
14059
+ return table[ext] || "application/octet-stream";
14060
+ }
13960
14061
  setMaxListeners(20);
13961
14062
  loadApiKeysFromConfig();
13962
14063
  if (!process.env.PI_CACHE_RETENTION) {
@@ -14026,6 +14127,22 @@ app.whenReady().then(() => {
14026
14127
  if (iconPath && process.platform === "darwin") {
14027
14128
  app.dock?.setIcon(iconPath);
14028
14129
  }
14130
+ protocol.handle("workspace-asset", async (request) => {
14131
+ try {
14132
+ const url = new URL(request.url);
14133
+ const absPath = decodeURIComponent(url.pathname);
14134
+ const data = await readFile(absPath);
14135
+ return new Response(data, {
14136
+ status: 200,
14137
+ headers: {
14138
+ "Content-Type": mimeForExtension(absPath),
14139
+ "Cache-Control": "no-cache"
14140
+ }
14141
+ });
14142
+ } catch {
14143
+ return new Response("", { status: 404 });
14144
+ }
14145
+ });
14029
14146
  registerIpcHandlers();
14030
14147
  registerTerminalHandlers();
14031
14148
  registerWindow(createWindow());
@@ -130,6 +130,8 @@ const api = {
130
130
  createDir: (relativePath) => electron.ipcRenderer.invoke("file:create-dir", relativePath),
131
131
  renameFile: (oldPath, newPath) => electron.ipcRenderer.invoke("file:rename", oldPath, newPath),
132
132
  trashFile: (filePath) => electron.ipcRenderer.invoke("file:trash", filePath),
133
+ revealInFinder: (filePath) => electron.ipcRenderer.invoke("file:reveal", filePath),
134
+ copyItem: (srcRelPath, destDirRelPath) => electron.ipcRenderer.invoke("file:copy-item", srcRelPath, destDirRelPath),
133
135
  dropToDir: (fileName, base64Content, targetDirRelPath) => electron.ipcRenderer.invoke("file:drop-to-dir", fileName, base64Content, targetDirRelPath),
134
136
  dropFile: (fileName, content, tab) => electron.ipcRenderer.invoke("file:drop", fileName, content, tab),
135
137
  enrichAllPapers: (paperIds) => electron.ipcRenderer.invoke("cmd:enrich-papers", paperIds),