research-copilot 0.1.0
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/LICENSE +21 -0
- package/README.md +190 -0
- package/app/build/icon.icns +0 -0
- package/app/build/icon.ico +0 -0
- package/app/build/icon.png +0 -0
- package/app/out/main/index.mjs +6719 -0
- package/app/out/preload/index.js +141 -0
- package/app/out/renderer/assets/Inter-Variable-Latin-8kRkwJBP.woff2 +0 -0
- package/app/out/renderer/assets/Inter-Variable-LatinExt-B_-bZUTo.woff2 +0 -0
- package/app/out/renderer/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- package/app/out/renderer/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- package/app/out/renderer/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- package/app/out/renderer/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- package/app/out/renderer/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- package/app/out/renderer/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- package/app/out/renderer/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- package/app/out/renderer/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- package/app/out/renderer/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- package/app/out/renderer/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- package/app/out/renderer/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- package/app/out/renderer/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- package/app/out/renderer/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- package/app/out/renderer/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- package/app/out/renderer/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- package/app/out/renderer/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- package/app/out/renderer/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- package/app/out/renderer/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- package/app/out/renderer/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- package/app/out/renderer/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- package/app/out/renderer/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- package/app/out/renderer/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- package/app/out/renderer/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- package/app/out/renderer/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- package/app/out/renderer/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- package/app/out/renderer/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- package/app/out/renderer/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- package/app/out/renderer/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- package/app/out/renderer/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- package/app/out/renderer/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- package/app/out/renderer/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- package/app/out/renderer/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- package/app/out/renderer/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- package/app/out/renderer/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- package/app/out/renderer/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- package/app/out/renderer/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- package/app/out/renderer/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- package/app/out/renderer/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- package/app/out/renderer/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- package/app/out/renderer/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- package/app/out/renderer/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- package/app/out/renderer/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- package/app/out/renderer/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- package/app/out/renderer/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- package/app/out/renderer/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- package/app/out/renderer/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- package/app/out/renderer/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- package/app/out/renderer/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- package/app/out/renderer/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- package/app/out/renderer/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- package/app/out/renderer/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- package/app/out/renderer/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- package/app/out/renderer/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- package/app/out/renderer/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- package/app/out/renderer/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- package/app/out/renderer/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- package/app/out/renderer/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- package/app/out/renderer/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- package/app/out/renderer/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- package/app/out/renderer/assets/MilkdownMarkdownEditor-bLPxrCVb.js +89821 -0
- package/app/out/renderer/assets/MilkdownMarkdownEditor-tTNRIB2K.css +2555 -0
- package/app/out/renderer/assets/Tableau10-BqnYsPR6.js +9 -0
- package/app/out/renderer/assets/apl-fqmucPXA.js +140 -0
- package/app/out/renderer/assets/arc-J47ePHZ2.js +132 -0
- package/app/out/renderer/assets/array-DgktLKBx.js +6 -0
- package/app/out/renderer/assets/asciiarmor-DucZyvP0.js +56 -0
- package/app/out/renderer/assets/asn1-BnOEsgAm.js +144 -0
- package/app/out/renderer/assets/asterisk-QAlztEwS.js +345 -0
- package/app/out/renderer/assets/blockDiagram-c4efeb88-5uRQXgQJ.js +1817 -0
- package/app/out/renderer/assets/brainfuck-DZVCuF_t.js +53 -0
- package/app/out/renderer/assets/c4Diagram-c83219d4-C4iCTPEL.js +2464 -0
- package/app/out/renderer/assets/channel-ZAmhHE3g.js +7 -0
- package/app/out/renderer/assets/classDiagram-beda092f-7NOZxq_W.js +357 -0
- package/app/out/renderer/assets/classDiagram-v2-2358418a-5fPT-cUH.js +291 -0
- package/app/out/renderer/assets/clike-xqXYL6ge.js +805 -0
- package/app/out/renderer/assets/clojure-BhXMqnxz.js +849 -0
- package/app/out/renderer/assets/clone-CsnzsYXQ.js +8 -0
- package/app/out/renderer/assets/cmake-BGaNd9E7.js +71 -0
- package/app/out/renderer/assets/cobol-4yqQntpt.js +120 -0
- package/app/out/renderer/assets/coffeescript-D2dXvhEc.js +308 -0
- package/app/out/renderer/assets/commonlisp-CF_VNHQR.js +130 -0
- package/app/out/renderer/assets/createText-1719965b-Cji7KN4K.js +4904 -0
- package/app/out/renderer/assets/crystal-DyuLTqLs.js +398 -0
- package/app/out/renderer/assets/css-c-jst79C.js +1783 -0
- package/app/out/renderer/assets/cypher-Dlu_3r4V.js +121 -0
- package/app/out/renderer/assets/d-UURgV0Ux.js +179 -0
- package/app/out/renderer/assets/diff-B_Bi2Crb.js +25 -0
- package/app/out/renderer/assets/dockerfile-Bvk733Ga.js +201 -0
- package/app/out/renderer/assets/dtd-Dy74G54E.js +114 -0
- package/app/out/renderer/assets/dylan-TSb-Nfix.js +314 -0
- package/app/out/renderer/assets/ebnf-DAomQUbD.js +139 -0
- package/app/out/renderer/assets/ecl-B59qGGVg.js +178 -0
- package/app/out/renderer/assets/edges-96097737-CD0EvAZQ.js +1844 -0
- package/app/out/renderer/assets/eiffel-Dze7nlu3.js +134 -0
- package/app/out/renderer/assets/elm-DG7jkhNZ.js +176 -0
- package/app/out/renderer/assets/erDiagram-0228fc6a-DRYXBpi7.js +1321 -0
- package/app/out/renderer/assets/erlang-BO6gOnGA.js +674 -0
- package/app/out/renderer/assets/factor-CMxFHDqz.js +65 -0
- package/app/out/renderer/assets/fcl-CDDUNjTj.js +141 -0
- package/app/out/renderer/assets/flowDb-c6c81e3f-CuoIN-Cy.js +1713 -0
- package/app/out/renderer/assets/flowDiagram-50d868cf-CPWPLOml.js +1272 -0
- package/app/out/renderer/assets/flowDiagram-v2-4f6560a1-C_R12s4S.js +33 -0
- package/app/out/renderer/assets/flowchart-elk-definition-6af322e1-BdKUSFpi.js +92921 -0
- package/app/out/renderer/assets/forth-B9D2JCeE.js +116 -0
- package/app/out/renderer/assets/fortran-CAG2BFbe.js +467 -0
- package/app/out/renderer/assets/ganttDiagram-a2739b55-ygqT5HlG.js +3399 -0
- package/app/out/renderer/assets/gas-d3KEcW3x.js +294 -0
- package/app/out/renderer/assets/gherkin-DhZlEZiy.js +115 -0
- package/app/out/renderer/assets/gitGraphDiagram-82fe8481-D97GT4iA.js +1791 -0
- package/app/out/renderer/assets/graph-DpC13d95.js +1237 -0
- package/app/out/renderer/assets/groovy-CpwJiBl7.js +223 -0
- package/app/out/renderer/assets/haskell-BlGBCCe3.js +459 -0
- package/app/out/renderer/assets/haxe-7MlzfeYV.js +514 -0
- package/app/out/renderer/assets/http-BqypyemW.js +79 -0
- package/app/out/renderer/assets/idl-4HIGJlDI.js +985 -0
- package/app/out/renderer/assets/index-4-ziknCv.js +292 -0
- package/app/out/renderer/assets/index-5325376f-Bbs7Fbqr.js +663 -0
- package/app/out/renderer/assets/index-B2jip-rk.js +2489 -0
- package/app/out/renderer/assets/index-BKTVfokE.js +312 -0
- package/app/out/renderer/assets/index-BiJbFgVG.js +118 -0
- package/app/out/renderer/assets/index-Bn433Fat.js +83 -0
- package/app/out/renderer/assets/index-BqDyyRCx.js +39679 -0
- package/app/out/renderer/assets/index-BzFMeMPn.js +158 -0
- package/app/out/renderer/assets/index-C-_uCjZJ.css +2701 -0
- package/app/out/renderer/assets/index-C1ithNW1.js +1765 -0
- package/app/out/renderer/assets/index-CAJkRYkO.js +407 -0
- package/app/out/renderer/assets/index-CleO0-yj.js +690 -0
- package/app/out/renderer/assets/index-Cq4MH3sY.js +1020 -0
- package/app/out/renderer/assets/index-CtA0Xj22.js +705 -0
- package/app/out/renderer/assets/index-CvAZkqBZ.js +83 -0
- package/app/out/renderer/assets/index-D3UDN-5c.js +152 -0
- package/app/out/renderer/assets/index-D4F9R5ao.js +179 -0
- package/app/out/renderer/assets/index-D6RguhZ5.js +328 -0
- package/app/out/renderer/assets/index-DnEowqXv.js +386 -0
- package/app/out/renderer/assets/index-K8c8Mqdy.js +98 -0
- package/app/out/renderer/assets/index-Kh14gO6K.js +62 -0
- package/app/out/renderer/assets/index-WFd2jRnA.js +333 -0
- package/app/out/renderer/assets/index-WgMfkRFp.js +313 -0
- package/app/out/renderer/assets/index-Y4lKyF6t.js +1042 -0
- package/app/out/renderer/assets/index-fx307_f1.js +643 -0
- package/app/out/renderer/assets/infoDiagram-8eee0895-ptaVSwzq.js +511 -0
- package/app/out/renderer/assets/init-ZxktEp_H.js +16 -0
- package/app/out/renderer/assets/javascript-C3MnDRiU.js +994 -0
- package/app/out/renderer/assets/journeyDiagram-c64418c1-aloEGOQp.js +1184 -0
- package/app/out/renderer/assets/julia-Bs6JJhYG.js +407 -0
- package/app/out/renderer/assets/layout-ZeuHE_aY.js +2217 -0
- package/app/out/renderer/assets/line-CAgaGl-S.js +45 -0
- package/app/out/renderer/assets/linear-DIg7lTe1.js +539 -0
- package/app/out/renderer/assets/livescript-DmzgM3Yt.js +296 -0
- package/app/out/renderer/assets/lua-8cJgIlqe.js +256 -0
- package/app/out/renderer/assets/mathematica-DNLOL9PQ.js +110 -0
- package/app/out/renderer/assets/mbox-Ga7d4MMN.js +117 -0
- package/app/out/renderer/assets/mindmap-definition-8da855dc-B8XVoUxz.js +36054 -0
- package/app/out/renderer/assets/mirc-Dma3B8rS.js +107 -0
- package/app/out/renderer/assets/mllike-DHn7xckP.js +334 -0
- package/app/out/renderer/assets/modelica-0d55jYY0.js +147 -0
- package/app/out/renderer/assets/mscgen-DdqZYINH.js +135 -0
- package/app/out/renderer/assets/mumps-Btr8VblO.js +93 -0
- package/app/out/renderer/assets/nginx-DTDtBDVN.js +141 -0
- package/app/out/renderer/assets/nsis-3zG7tgur.js +62 -0
- package/app/out/renderer/assets/ntriples-CvgOYMpL.js +153 -0
- package/app/out/renderer/assets/octave-DYBj3-tl.js +200 -0
- package/app/out/renderer/assets/ordinal-DSZU4PqD.js +76 -0
- package/app/out/renderer/assets/oz-R_e8WMIi.js +231 -0
- package/app/out/renderer/assets/pascal-GD8iposT.js +105 -0
- package/app/out/renderer/assets/path-Cp2qmpkd.js +109 -0
- package/app/out/renderer/assets/perl-DL9mHpoi.js +1105 -0
- package/app/out/renderer/assets/pieDiagram-a8764435-DlwoeBU2.js +770 -0
- package/app/out/renderer/assets/pig-C_4T4YIV.js +101 -0
- package/app/out/renderer/assets/powershell-B0suO7Vd.js +328 -0
- package/app/out/renderer/assets/properties-BR-vP1aU.js +58 -0
- package/app/out/renderer/assets/protobuf-BxgpyhoW.js +77 -0
- package/app/out/renderer/assets/pug-By0kVCfm.js +405 -0
- package/app/out/renderer/assets/puppet-Bdao66PW.js +137 -0
- package/app/out/renderer/assets/python-CvWbmiX4.js +427 -0
- package/app/out/renderer/assets/q-CrbCVq4a.js +131 -0
- package/app/out/renderer/assets/quadrantDiagram-1e28029f-BaSi1XB4.js +1200 -0
- package/app/out/renderer/assets/r-V7nswm59.js +170 -0
- package/app/out/renderer/assets/requirementDiagram-08caed73-D3EFyegZ.js +1092 -0
- package/app/out/renderer/assets/rpm-C-DLY-If.js +109 -0
- package/app/out/renderer/assets/ruby-JDKLJNK0.js +330 -0
- package/app/out/renderer/assets/sankeyDiagram-a04cb91d-Cv44AsnM.js +1174 -0
- package/app/out/renderer/assets/sas-D2UG-yhZ.js +207 -0
- package/app/out/renderer/assets/scheme-BKzrkGJD.js +222 -0
- package/app/out/renderer/assets/sequenceDiagram-c5b8d532-CuUBu-x4.js +3337 -0
- package/app/out/renderer/assets/shell-BlsXDxCn.js +222 -0
- package/app/out/renderer/assets/sieve-CjwBwOY5.js +135 -0
- package/app/out/renderer/assets/simple-mode-DMneyfDu.js +130 -0
- package/app/out/renderer/assets/smalltalk-BOIGQuhN.js +121 -0
- package/app/out/renderer/assets/solr-CwD7U71z.js +69 -0
- package/app/out/renderer/assets/sparql-DYskk2vE.js +249 -0
- package/app/out/renderer/assets/spreadsheet-Bgtt3oLP.js +87 -0
- package/app/out/renderer/assets/sql-BSrOzCRI.js +354 -0
- package/app/out/renderer/assets/stateDiagram-1ecb1508-BOU34Zp4.js +454 -0
- package/app/out/renderer/assets/stateDiagram-v2-c2b004d7-BgRoffou.js +326 -0
- package/app/out/renderer/assets/stex-B6LNC55o.js +231 -0
- package/app/out/renderer/assets/styles-b4e223ce-BMr9TPuj.js +1483 -0
- package/app/out/renderer/assets/styles-ca3715f6-DgbNw99p.js +1363 -0
- package/app/out/renderer/assets/styles-d45a18b0-DtRYKYKf.js +574 -0
- package/app/out/renderer/assets/stylus-BkS-boTH.js +565 -0
- package/app/out/renderer/assets/svgDrawCommon-b86b1483-Bein03PD.js +100 -0
- package/app/out/renderer/assets/swift-FRZi1uvB.js +291 -0
- package/app/out/renderer/assets/tcl-CUcaCdmq.js +114 -0
- package/app/out/renderer/assets/textile-BnFpjsrl.js +414 -0
- package/app/out/renderer/assets/tiddlywiki-CjprD-Qp.js +218 -0
- package/app/out/renderer/assets/tiki-B4EPSQ1G.js +265 -0
- package/app/out/renderer/assets/timeline-definition-faaaa080-BlWpLE_4.js +1212 -0
- package/app/out/renderer/assets/toml-BOuWGMcf.js +76 -0
- package/app/out/renderer/assets/troff-E1bJ0PPL.js +61 -0
- package/app/out/renderer/assets/ttcn-cfg-Dc39-fIP.js +133 -0
- package/app/out/renderer/assets/ttcn-tKd4HLu4.js +192 -0
- package/app/out/renderer/assets/turtle-Dq7-1WAf.js +124 -0
- package/app/out/renderer/assets/vb-Dp90gtsv.js +196 -0
- package/app/out/renderer/assets/vbscript-CI6_mxxU.js +479 -0
- package/app/out/renderer/assets/velocity-BwIZK1TH.js +149 -0
- package/app/out/renderer/assets/verilog-DDCYnHN8.js +430 -0
- package/app/out/renderer/assets/vhdl-DCkMIyT9.js +158 -0
- package/app/out/renderer/assets/webidl-BTLTThCm.js +204 -0
- package/app/out/renderer/assets/xquery-BgiOC5Ce.js +525 -0
- package/app/out/renderer/assets/xychartDiagram-f5964ef8-Bhga-YXm.js +1799 -0
- package/app/out/renderer/assets/yacas-b5lAVEIl.js +130 -0
- package/app/out/renderer/assets/z80-BZV19vqv.js +93 -0
- package/app/out/renderer/index.html +13 -0
- package/app/out/skills/community-builtin/README.md +29 -0
- package/app/out/skills/community-builtin/document-docx/SKILL.md +44 -0
- package/app/out/skills/community-builtin/document-docx/scripts/docx-to-markdown.sh +20 -0
- package/app/out/skills/community-builtin/document-docx/scripts/extract-docx-text.sh +28 -0
- package/app/out/skills/community-builtin/document-docx/scripts/init-docx-template.sh +32 -0
- package/app/out/skills/community-builtin/document-docx/scripts/setup-docx-tools.sh +10 -0
- package/app/out/skills/community-builtin/markitdown/SKILL.md +105 -0
- package/app/out/skills/community-builtin/markitdown/scripts/batch-convert.sh +40 -0
- package/app/out/skills/community-builtin/markitdown/scripts/convert-file.sh +24 -0
- package/app/out/skills/community-builtin/markitdown/scripts/setup-markitdown.sh +10 -0
- package/app/out/skills/community-builtin/repo-quick-audit/SKILL.md +27 -0
- package/app/out/skills/community-builtin/repo-quick-audit/scripts/audit-basics.sh +19 -0
- package/app/out/skills/research-pilot-default-project-skills/README.md +23 -0
- package/app/out/skills/research-pilot-default-project-skills/citation-management/SKILL.md +39 -0
- package/app/out/skills/research-pilot-default-project-skills/citation-management/scripts/doi-to-bibtex.sh +25 -0
- package/app/out/skills/research-pilot-default-project-skills/citation-management/scripts/normalize-bibtex-keys.sh +51 -0
- package/app/out/skills/research-pilot-default-project-skills/citation-management/scripts/setup-citation-tools.sh +10 -0
- package/app/out/skills/research-pilot-default-project-skills/citation-management/scripts/validate-bib.sh +31 -0
- package/app/out/skills/research-pilot-default-project-skills/matplotlib/SKILL.md +34 -0
- package/app/out/skills/research-pilot-default-project-skills/matplotlib/references/api_reference.md +412 -0
- package/app/out/skills/research-pilot-default-project-skills/matplotlib/references/common_issues.md +563 -0
- package/app/out/skills/research-pilot-default-project-skills/matplotlib/references/plot_types.md +476 -0
- package/app/out/skills/research-pilot-default-project-skills/matplotlib/references/styling_guide.md +589 -0
- package/app/out/skills/research-pilot-default-project-skills/matplotlib/references/subagent_quickstart.md +30 -0
- package/app/out/skills/research-pilot-default-project-skills/matplotlib/scripts/plot_template.py +401 -0
- package/app/out/skills/research-pilot-default-project-skills/matplotlib/scripts/style_configurator.py +409 -0
- package/app/out/skills/research-pilot-default-project-skills/research-grants/SKILL.md +38 -0
- package/app/out/skills/research-pilot-default-project-skills/research-grants/scripts/check-grant-compliance.sh +40 -0
- package/app/out/skills/research-pilot-default-project-skills/research-grants/scripts/grant-summary-card.sh +32 -0
- package/app/out/skills/research-pilot-default-project-skills/research-grants/scripts/init-grant-structure.sh +70 -0
- package/app/package.json +77 -0
- package/bin/cli.mjs +56 -0
- package/lib/README.md +145 -0
- package/lib/skills/_generated.ts +13 -0
- package/lib/skills/builtin/brainstorming-research-ideas/SKILL.md +280 -0
- package/lib/skills/builtin/coding/SKILL.md +114 -0
- package/lib/skills/builtin/creative-thinking-for-research/SKILL.md +273 -0
- package/lib/skills/builtin/matplotlib/SKILL.md +361 -0
- package/lib/skills/builtin/matplotlib/references/api_reference.md +412 -0
- package/lib/skills/builtin/matplotlib/references/common_issues.md +563 -0
- package/lib/skills/builtin/matplotlib/references/plot_types.md +476 -0
- package/lib/skills/builtin/matplotlib/references/styling_guide.md +589 -0
- package/lib/skills/builtin/matplotlib/scripts/plot_template.py +401 -0
- package/lib/skills/builtin/matplotlib/scripts/style_configurator.py +409 -0
- package/lib/skills/builtin/paper-writing/SKILL.md +554 -0
- package/lib/skills/builtin/paper-writing/references/checklists.md +524 -0
- package/lib/skills/builtin/paper-writing/references/citation-workflow.md +562 -0
- package/lib/skills/builtin/paper-writing/references/reviewer-guidelines.md +462 -0
- package/lib/skills/builtin/paper-writing/references/sources.md +189 -0
- package/lib/skills/builtin/paper-writing/references/systems-conferences.md +260 -0
- package/lib/skills/builtin/paper-writing/references/writing-guide.md +476 -0
- package/lib/skills/builtin/paper-writing/templates/README.md +408 -0
- package/lib/skills/builtin/paper-writing/templates/aaai2026/README.md +534 -0
- package/lib/skills/builtin/paper-writing/templates/aaai2026/aaai2026-unified-supp.tex +144 -0
- package/lib/skills/builtin/paper-writing/templates/aaai2026/aaai2026-unified-template.tex +952 -0
- package/lib/skills/builtin/paper-writing/templates/aaai2026/aaai2026.bib +111 -0
- package/lib/skills/builtin/paper-writing/templates/aaai2026/aaai2026.bst +1493 -0
- package/lib/skills/builtin/paper-writing/templates/aaai2026/aaai2026.sty +315 -0
- package/lib/skills/builtin/paper-writing/templates/acl/README.md +50 -0
- package/lib/skills/builtin/paper-writing/templates/acl/acl.sty +312 -0
- package/lib/skills/builtin/paper-writing/templates/acl/acl_latex.tex +377 -0
- package/lib/skills/builtin/paper-writing/templates/acl/acl_lualatex.tex +101 -0
- package/lib/skills/builtin/paper-writing/templates/acl/acl_natbib.bst +1940 -0
- package/lib/skills/builtin/paper-writing/templates/acl/anthology.bib.txt +26 -0
- package/lib/skills/builtin/paper-writing/templates/acl/custom.bib +70 -0
- package/lib/skills/builtin/paper-writing/templates/acl/formatting.md +326 -0
- package/lib/skills/builtin/paper-writing/templates/asplos2027/main.tex +459 -0
- package/lib/skills/builtin/paper-writing/templates/asplos2027/references.bib +135 -0
- package/lib/skills/builtin/paper-writing/templates/colm2025/README.md +3 -0
- package/lib/skills/builtin/paper-writing/templates/colm2025/colm2025_conference.bib +11 -0
- package/lib/skills/builtin/paper-writing/templates/colm2025/colm2025_conference.bst +1440 -0
- package/lib/skills/builtin/paper-writing/templates/colm2025/colm2025_conference.pdf +0 -0
- package/lib/skills/builtin/paper-writing/templates/colm2025/colm2025_conference.sty +218 -0
- package/lib/skills/builtin/paper-writing/templates/colm2025/colm2025_conference.tex +305 -0
- package/lib/skills/builtin/paper-writing/templates/colm2025/fancyhdr.sty +485 -0
- package/lib/skills/builtin/paper-writing/templates/colm2025/math_commands.tex +508 -0
- package/lib/skills/builtin/paper-writing/templates/colm2025/natbib.sty +1246 -0
- package/lib/skills/builtin/paper-writing/templates/iclr2026/fancyhdr.sty +485 -0
- package/lib/skills/builtin/paper-writing/templates/iclr2026/iclr2026_conference.bib +24 -0
- package/lib/skills/builtin/paper-writing/templates/iclr2026/iclr2026_conference.bst +1440 -0
- package/lib/skills/builtin/paper-writing/templates/iclr2026/iclr2026_conference.pdf +0 -0
- package/lib/skills/builtin/paper-writing/templates/iclr2026/iclr2026_conference.sty +246 -0
- package/lib/skills/builtin/paper-writing/templates/iclr2026/iclr2026_conference.tex +414 -0
- package/lib/skills/builtin/paper-writing/templates/iclr2026/math_commands.tex +508 -0
- package/lib/skills/builtin/paper-writing/templates/iclr2026/natbib.sty +1246 -0
- package/lib/skills/builtin/paper-writing/templates/icml2026/algorithm.sty +79 -0
- package/lib/skills/builtin/paper-writing/templates/icml2026/algorithmic.sty +201 -0
- package/lib/skills/builtin/paper-writing/templates/icml2026/example_paper.bib +75 -0
- package/lib/skills/builtin/paper-writing/templates/icml2026/example_paper.pdf +0 -0
- package/lib/skills/builtin/paper-writing/templates/icml2026/example_paper.tex +662 -0
- package/lib/skills/builtin/paper-writing/templates/icml2026/fancyhdr.sty +864 -0
- package/lib/skills/builtin/paper-writing/templates/icml2026/icml2026.bst +1443 -0
- package/lib/skills/builtin/paper-writing/templates/icml2026/icml2026.sty +767 -0
- package/lib/skills/builtin/paper-writing/templates/icml2026/icml_numpapers.pdf +0 -0
- package/lib/skills/builtin/paper-writing/templates/neurips2025/Makefile +36 -0
- package/lib/skills/builtin/paper-writing/templates/neurips2025/extra_pkgs.tex +53 -0
- package/lib/skills/builtin/paper-writing/templates/neurips2025/main.tex +38 -0
- package/lib/skills/builtin/paper-writing/templates/neurips2025/neurips.sty +382 -0
- package/lib/skills/builtin/paper-writing/templates/nsdi2027/main.tex +426 -0
- package/lib/skills/builtin/paper-writing/templates/nsdi2027/references.bib +151 -0
- package/lib/skills/builtin/paper-writing/templates/nsdi2027/usenix-2020-09.sty +83 -0
- package/lib/skills/builtin/paper-writing/templates/osdi2026/main.tex +429 -0
- package/lib/skills/builtin/paper-writing/templates/osdi2026/references.bib +150 -0
- package/lib/skills/builtin/paper-writing/templates/osdi2026/usenix-2020-09.sty +83 -0
- package/lib/skills/builtin/paper-writing/templates/sosp2026/main.tex +532 -0
- package/lib/skills/builtin/paper-writing/templates/sosp2026/references.bib +148 -0
- package/lib/skills/builtin/research-grants/SKILL.md +958 -0
- package/lib/skills/builtin/research-grants/assets/budget_justification_template.md +453 -0
- package/lib/skills/builtin/research-grants/assets/nih_specific_aims_template.md +166 -0
- package/lib/skills/builtin/research-grants/assets/nsf_project_summary_template.md +92 -0
- package/lib/skills/builtin/research-grants/references/README.md +285 -0
- package/lib/skills/builtin/research-grants/references/broader_impacts.md +392 -0
- package/lib/skills/builtin/research-grants/references/darpa_guidelines.md +636 -0
- package/lib/skills/builtin/research-grants/references/doe_guidelines.md +586 -0
- package/lib/skills/builtin/research-grants/references/nih_guidelines.md +851 -0
- package/lib/skills/builtin/research-grants/references/nsf_guidelines.md +570 -0
- package/lib/skills/builtin/research-grants/references/nstc_guidelines.md +733 -0
- package/lib/skills/builtin/research-grants/references/specific_aims_guide.md +458 -0
- package/lib/skills/builtin/rewrite-humanize/SKILL.md +116 -0
- package/lib/skills/builtin/rewrite-humanize/references/cs-venue-tone.md +57 -0
- package/lib/skills/builtin/rewrite-humanize/references/lexicon.md +50 -0
- package/lib/skills/builtin/scholar-evaluation/SKILL.md +300 -0
- package/lib/skills/builtin/scholar-evaluation/references/evaluation_framework.md +663 -0
- package/lib/skills/builtin/scholar-evaluation/scripts/calculate_scores.py +379 -0
- package/lib/skills/builtin/scientific-schematics/SKILL.md +603 -0
- package/lib/skills/builtin/scientific-schematics/references/QUICK_REFERENCE.md +182 -0
- package/lib/skills/builtin/scientific-schematics/references/README.md +292 -0
- package/lib/skills/builtin/scientific-schematics/references/best_practices.md +560 -0
- package/lib/skills/builtin/scientific-schematics/scripts/__pycache__/generate_schematic.cpython-312.pyc +0 -0
- package/lib/skills/builtin/scientific-schematics/scripts/__pycache__/generate_schematic_ai.cpython-312.pyc +0 -0
- package/lib/skills/builtin/scientific-schematics/scripts/example_usage.sh +85 -0
- package/lib/skills/builtin/scientific-schematics/scripts/generate_schematic.py +141 -0
- package/lib/skills/builtin/scientific-schematics/scripts/generate_schematic_ai.py +910 -0
- package/lib/skills/builtin/scientific-visualization/SKILL.md +749 -0
- package/lib/skills/builtin/scientific-visualization/assets/color_palettes.py +197 -0
- package/lib/skills/builtin/scientific-visualization/assets/nature.mplstyle +63 -0
- package/lib/skills/builtin/scientific-visualization/assets/presentation.mplstyle +61 -0
- package/lib/skills/builtin/scientific-visualization/assets/publication.mplstyle +68 -0
- package/lib/skills/builtin/scientific-visualization/references/color_palettes.md +348 -0
- package/lib/skills/builtin/scientific-visualization/references/journal_requirements.md +320 -0
- package/lib/skills/builtin/scientific-visualization/references/matplotlib_examples.md +620 -0
- package/lib/skills/builtin/scientific-visualization/references/publication_guidelines.md +205 -0
- package/lib/skills/builtin/scientific-visualization/scripts/figure_export.py +343 -0
- package/lib/skills/builtin/scientific-visualization/scripts/style_presets.py +416 -0
- package/lib/skills/builtin/scientific-writing/SKILL.md +745 -0
- package/lib/skills/builtin/scientific-writing/assets/REPORT_FORMATTING_GUIDE.md +574 -0
- package/lib/skills/builtin/scientific-writing/assets/scientific_report.sty +606 -0
- package/lib/skills/builtin/scientific-writing/assets/scientific_report_template.tex +449 -0
- package/lib/skills/builtin/scientific-writing/references/citation_styles.md +720 -0
- package/lib/skills/builtin/scientific-writing/references/figures_tables.md +806 -0
- package/lib/skills/builtin/scientific-writing/references/imrad_structure.md +686 -0
- package/lib/skills/builtin/scientific-writing/references/professional_report_formatting.md +664 -0
- package/lib/skills/builtin/scientific-writing/references/reporting_guidelines.md +748 -0
- package/lib/skills/builtin/scientific-writing/references/writing_principles.md +824 -0
- package/lib/skills/builtin/seaborn/SKILL.md +674 -0
- package/lib/skills/builtin/seaborn/references/examples.md +822 -0
- package/lib/skills/builtin/seaborn/references/function_reference.md +770 -0
- package/lib/skills/builtin/seaborn/references/objects_interface.md +964 -0
- package/lib/skills/data-analysis/SKILL.md +285 -0
- package/lib/skills/generate-skill-content.mjs +58 -0
- package/lib/skills/index.ts +34 -0
- package/lib/skills/loader.ts +452 -0
- package/package.json +62 -0
|
@@ -0,0 +1,452 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skills loader for Research Copilot.
|
|
3
|
+
*
|
|
4
|
+
* Discovers and parses SKILL.md files from three locations:
|
|
5
|
+
* 1. Built-in skills: lib/skills/builtin/ (shipped with app)
|
|
6
|
+
* 2. Workspace skills: .research-pilot/skills/ (per-project)
|
|
7
|
+
* 3. User skills: ~/.research-pilot/skills/ (user-global)
|
|
8
|
+
*
|
|
9
|
+
* Adapted from myRAM's skills.ts with simplified settings.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import fs from 'node:fs'
|
|
13
|
+
import os from 'node:os'
|
|
14
|
+
import path from 'node:path'
|
|
15
|
+
import { fileURLToPath } from 'node:url'
|
|
16
|
+
|
|
17
|
+
const SKILL_FILE_NAME = 'SKILL.md'
|
|
18
|
+
const MAX_SCAN_DEPTH = 3
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Override for the builtin skills root directory.
|
|
22
|
+
* Must be set by the host (e.g. Electron main process) before loading skills,
|
|
23
|
+
* because `import.meta.url` resolves incorrectly after Vite bundling.
|
|
24
|
+
*/
|
|
25
|
+
let _builtinSkillsRoot: string | null = null
|
|
26
|
+
|
|
27
|
+
export function setBuiltinSkillsRoot(dir: string): void {
|
|
28
|
+
_builtinSkillsRoot = dir
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface SkillEntry {
|
|
32
|
+
name: string
|
|
33
|
+
description: string
|
|
34
|
+
category: string
|
|
35
|
+
depends: string[]
|
|
36
|
+
tags: string[]
|
|
37
|
+
triggers: string[] // Keywords/phrases that should trigger this skill
|
|
38
|
+
path: string
|
|
39
|
+
dir: string // Absolute path to skill directory (for running scripts)
|
|
40
|
+
source: 'builtin' | 'user' | 'workspace'
|
|
41
|
+
content: string
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface SkillCatalogItem {
|
|
45
|
+
name: string
|
|
46
|
+
description: string
|
|
47
|
+
path: string
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
51
|
+
// Internal helpers
|
|
52
|
+
// ---------------------------------------------------------------------------
|
|
53
|
+
|
|
54
|
+
function safeReadText(filePath: string): string | null {
|
|
55
|
+
try {
|
|
56
|
+
return fs.readFileSync(filePath, 'utf8')
|
|
57
|
+
} catch {
|
|
58
|
+
return null
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Parse a top-level field from YAML frontmatter.
|
|
64
|
+
* Only matches lines that are NOT indented (top-level keys).
|
|
65
|
+
*/
|
|
66
|
+
function parseFrontmatterField(content: string, field: string): string | undefined {
|
|
67
|
+
const match = content.match(/^---\n([\s\S]*?)\n---/)
|
|
68
|
+
if (!match) return undefined
|
|
69
|
+
const body = match[1]
|
|
70
|
+
const line = body
|
|
71
|
+
.split('\n')
|
|
72
|
+
.find((l) => l.match(new RegExp(`^${field}:\\s`)))
|
|
73
|
+
if (!line) return undefined
|
|
74
|
+
const value = line.slice(field.length + 1).trim().replace(/^["']|["']$/g, '')
|
|
75
|
+
return value || undefined
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Parse a YAML inline array field like `tags: [a, b, c]` or `depends: [x, y]`.
|
|
80
|
+
*/
|
|
81
|
+
function parseFrontmatterArrayField(content: string, field: string): string[] {
|
|
82
|
+
const raw = parseFrontmatterField(content, field)
|
|
83
|
+
if (!raw) return []
|
|
84
|
+
// Handle inline YAML array: [item1, item2, item3]
|
|
85
|
+
const arrayMatch = raw.match(/^\[(.*)\]$/)
|
|
86
|
+
if (arrayMatch) {
|
|
87
|
+
return arrayMatch[1]
|
|
88
|
+
.split(',')
|
|
89
|
+
.map((s) => s.trim().replace(/^["']|["']$/g, ''))
|
|
90
|
+
.filter(Boolean)
|
|
91
|
+
}
|
|
92
|
+
// Single value
|
|
93
|
+
return raw ? [raw] : []
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function discoverSkillFiles(rootDir: string): string[] {
|
|
97
|
+
const files: string[] = []
|
|
98
|
+
const stack: Array<{ dir: string; depth: number }> = [{ dir: rootDir, depth: 0 }]
|
|
99
|
+
|
|
100
|
+
while (stack.length > 0) {
|
|
101
|
+
const current = stack.pop()
|
|
102
|
+
if (!current) continue
|
|
103
|
+
let entries: fs.Dirent[] = []
|
|
104
|
+
try {
|
|
105
|
+
entries = fs.readdirSync(current.dir, { withFileTypes: true })
|
|
106
|
+
} catch {
|
|
107
|
+
continue
|
|
108
|
+
}
|
|
109
|
+
for (const entry of entries) {
|
|
110
|
+
const abs = path.join(current.dir, entry.name)
|
|
111
|
+
if (entry.isFile() && entry.name === SKILL_FILE_NAME) {
|
|
112
|
+
files.push(abs)
|
|
113
|
+
continue
|
|
114
|
+
}
|
|
115
|
+
if (!entry.isDirectory()) continue
|
|
116
|
+
if (entry.name.startsWith('.')) continue
|
|
117
|
+
if (current.depth >= MAX_SCAN_DEPTH) continue
|
|
118
|
+
stack.push({ dir: abs, depth: current.depth + 1 })
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return files
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Parse a SKILL.md file into a SkillEntry.
|
|
127
|
+
* Requires frontmatter with `name:` and `description:`.
|
|
128
|
+
* Returns null if either is missing.
|
|
129
|
+
*/
|
|
130
|
+
function parseSkillFile(skillFile: string, displayPath: string, source: SkillEntry['source']): SkillEntry | null {
|
|
131
|
+
const content = safeReadText(skillFile)
|
|
132
|
+
if (!content) return null
|
|
133
|
+
const name = parseFrontmatterField(content, 'name')
|
|
134
|
+
// Accept both 'description' and 'shortDescription' (myRAM compat)
|
|
135
|
+
const description = parseFrontmatterField(content, 'description')
|
|
136
|
+
?? parseFrontmatterField(content, 'shortDescription')
|
|
137
|
+
if (!name || !description) return null
|
|
138
|
+
const category = parseFrontmatterField(content, 'category') ?? inferCategory(name, description)
|
|
139
|
+
const depends = parseFrontmatterArrayField(content, 'depends')
|
|
140
|
+
const tags = parseFrontmatterArrayField(content, 'tags')
|
|
141
|
+
const triggers = parseFrontmatterArrayField(content, 'triggers')
|
|
142
|
+
return {
|
|
143
|
+
name,
|
|
144
|
+
description,
|
|
145
|
+
category,
|
|
146
|
+
depends,
|
|
147
|
+
tags,
|
|
148
|
+
triggers,
|
|
149
|
+
path: displayPath,
|
|
150
|
+
dir: path.dirname(skillFile),
|
|
151
|
+
source,
|
|
152
|
+
content
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/** Infer a category from skill name/description when not explicitly set. */
|
|
157
|
+
function inferCategory(name: string, description: string): string {
|
|
158
|
+
const text = `${name} ${description}`.toLowerCase()
|
|
159
|
+
if (/writ|manuscript|draft|prose|humaniz/.test(text)) return 'Writing & Review'
|
|
160
|
+
if (/visual|plot|chart|matplotlib|seaborn|figure/.test(text)) return 'Visualization'
|
|
161
|
+
if (/data|analy|statistic|ml|model/.test(text)) return 'Data & Analysis'
|
|
162
|
+
if (/literature|paper|search|review|academic|citation/.test(text)) return 'Literature & Search'
|
|
163
|
+
if (/grant|proposal|funding/.test(text)) return 'Grants & Proposals'
|
|
164
|
+
if (/evaluat|scholar|critique|assess/.test(text)) return 'Evaluation'
|
|
165
|
+
return 'General'
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// ---------------------------------------------------------------------------
|
|
169
|
+
// Public API
|
|
170
|
+
// ---------------------------------------------------------------------------
|
|
171
|
+
|
|
172
|
+
/** Load built-in skills that ship with the software. */
|
|
173
|
+
export function loadBuiltinSkills(): SkillEntry[] {
|
|
174
|
+
// Use override if set (required in bundled Electron builds), else fallback to import.meta.url
|
|
175
|
+
const skillsRoot = _builtinSkillsRoot ?? path.dirname(fileURLToPath(import.meta.url))
|
|
176
|
+
if (!fs.existsSync(skillsRoot) || !fs.statSync(skillsRoot).isDirectory()) {
|
|
177
|
+
return []
|
|
178
|
+
}
|
|
179
|
+
const files = discoverSkillFiles(skillsRoot)
|
|
180
|
+
// Deduplicate by name (later files override earlier)
|
|
181
|
+
const byName = new Map<string, SkillEntry>()
|
|
182
|
+
for (const file of files) {
|
|
183
|
+
const entry = parseSkillFile(file, `[builtin] ${path.relative(skillsRoot, file)}`, 'builtin')
|
|
184
|
+
if (entry) byName.set(entry.name, entry)
|
|
185
|
+
}
|
|
186
|
+
return Array.from(byName.values()).sort((a, b) => a.name.localeCompare(b.name))
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/** Load workspace-level skills from .research-pilot/skills/. */
|
|
190
|
+
export function loadWorkspaceSkills(workspacePath: string): SkillEntry[] {
|
|
191
|
+
const skillRoot = path.resolve(workspacePath, '.research-pilot', 'skills')
|
|
192
|
+
if (!fs.existsSync(skillRoot) || !fs.statSync(skillRoot).isDirectory()) {
|
|
193
|
+
return []
|
|
194
|
+
}
|
|
195
|
+
const files = discoverSkillFiles(skillRoot)
|
|
196
|
+
const entries = files
|
|
197
|
+
.map((file) => parseSkillFile(file, path.relative(workspacePath, file), 'workspace'))
|
|
198
|
+
.filter((entry): entry is SkillEntry => entry !== null)
|
|
199
|
+
return entries.sort((a, b) => a.name.localeCompare(b.name))
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/** Load user-global skills from ~/.research-pilot/skills/. */
|
|
203
|
+
function loadUserSkills(): SkillEntry[] {
|
|
204
|
+
const userRoot = path.resolve(os.homedir(), '.research-pilot', 'skills')
|
|
205
|
+
if (!fs.existsSync(userRoot) || !fs.statSync(userRoot).isDirectory()) {
|
|
206
|
+
return []
|
|
207
|
+
}
|
|
208
|
+
const files = discoverSkillFiles(userRoot)
|
|
209
|
+
const entries = files
|
|
210
|
+
.map((file) => parseSkillFile(file, `[user] ~/.research-pilot/skills/${path.relative(userRoot, file)}`, 'user'))
|
|
211
|
+
.filter((entry): entry is SkillEntry => entry !== null)
|
|
212
|
+
return entries.sort((a, b) => a.name.localeCompare(b.name))
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Load all skills: built-in + user-global + workspace.
|
|
217
|
+
* Override order (highest wins): workspace > user-global > built-in.
|
|
218
|
+
*/
|
|
219
|
+
export function loadAllSkills(workspacePath: string): SkillEntry[] {
|
|
220
|
+
const builtin = loadBuiltinSkills()
|
|
221
|
+
const user = loadUserSkills()
|
|
222
|
+
const workspace = loadWorkspaceSkills(workspacePath)
|
|
223
|
+
|
|
224
|
+
const userNames = new Set(user.map((s) => s.name))
|
|
225
|
+
const workspaceNames = new Set(workspace.map((s) => s.name))
|
|
226
|
+
const merged = [
|
|
227
|
+
...builtin.filter((s) => !userNames.has(s.name) && !workspaceNames.has(s.name)),
|
|
228
|
+
...user.filter((s) => !workspaceNames.has(s.name)),
|
|
229
|
+
...workspace
|
|
230
|
+
]
|
|
231
|
+
return merged.sort((a, b) => a.name.localeCompare(b.name))
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// ---------------------------------------------------------------------------
|
|
235
|
+
// Enabled skills config (persisted per-workspace)
|
|
236
|
+
// ---------------------------------------------------------------------------
|
|
237
|
+
|
|
238
|
+
export interface SkillManifest {
|
|
239
|
+
name: string
|
|
240
|
+
description: string
|
|
241
|
+
category: string
|
|
242
|
+
depends: string[]
|
|
243
|
+
tags: string[]
|
|
244
|
+
source: 'builtin' | 'user' | 'workspace'
|
|
245
|
+
enabled: boolean
|
|
246
|
+
enabledReason: 'direct' | 'dependency' | null
|
|
247
|
+
dependencyOf: string[] // Which directly-selected skills pulled this in
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// ---------------------------------------------------------------------------
|
|
251
|
+
// Dependency resolution (BFS transitive)
|
|
252
|
+
// ---------------------------------------------------------------------------
|
|
253
|
+
|
|
254
|
+
interface ResolvedSkill {
|
|
255
|
+
reason: 'direct' | 'dependency'
|
|
256
|
+
dependencyOf: string[]
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Resolve skill dependencies using BFS.
|
|
261
|
+
* Returns a map of skill name -> resolution info.
|
|
262
|
+
*/
|
|
263
|
+
export function resolveSkillDependencies(
|
|
264
|
+
allSkills: SkillEntry[],
|
|
265
|
+
directSelection: string[]
|
|
266
|
+
): Map<string, ResolvedSkill> {
|
|
267
|
+
const byName = new Map(allSkills.map((s) => [s.name, s]))
|
|
268
|
+
const result = new Map<string, ResolvedSkill>()
|
|
269
|
+
const queue: string[] = []
|
|
270
|
+
|
|
271
|
+
// Seed with directly selected skills
|
|
272
|
+
for (const name of directSelection) {
|
|
273
|
+
if (!byName.has(name)) continue
|
|
274
|
+
result.set(name, { reason: 'direct', dependencyOf: [] })
|
|
275
|
+
queue.push(name)
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// BFS: resolve transitive dependencies
|
|
279
|
+
while (queue.length > 0) {
|
|
280
|
+
const current = queue.shift()!
|
|
281
|
+
const skill = byName.get(current)
|
|
282
|
+
if (!skill) continue
|
|
283
|
+
|
|
284
|
+
for (const depName of skill.depends) {
|
|
285
|
+
if (!byName.has(depName)) continue // skip unknown deps
|
|
286
|
+
|
|
287
|
+
const existing = result.get(depName)
|
|
288
|
+
if (existing) {
|
|
289
|
+
// Already resolved — just track who else depends on it
|
|
290
|
+
if (!existing.dependencyOf.includes(current)) {
|
|
291
|
+
existing.dependencyOf.push(current)
|
|
292
|
+
}
|
|
293
|
+
} else {
|
|
294
|
+
result.set(depName, { reason: 'dependency', dependencyOf: [current] })
|
|
295
|
+
queue.push(depName)
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
return result
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/** Read enabled skills list from workspace config. Returns null if not set (= all enabled). */
|
|
304
|
+
export function readEnabledSkills(workspacePath: string): string[] | null {
|
|
305
|
+
const configPath = path.resolve(workspacePath, '.research-pilot', 'skills-config.json')
|
|
306
|
+
try {
|
|
307
|
+
const raw = fs.readFileSync(configPath, 'utf8')
|
|
308
|
+
const config = JSON.parse(raw)
|
|
309
|
+
if (Array.isArray(config.enabledSkills)) return config.enabledSkills
|
|
310
|
+
} catch {
|
|
311
|
+
// no config yet
|
|
312
|
+
}
|
|
313
|
+
return null
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/** Write enabled skills list to workspace config. */
|
|
317
|
+
export function writeEnabledSkills(workspacePath: string, enabledSkills: string[]): void {
|
|
318
|
+
const configDir = path.resolve(workspacePath, '.research-pilot')
|
|
319
|
+
if (!fs.existsSync(configDir)) fs.mkdirSync(configDir, { recursive: true })
|
|
320
|
+
const configPath = path.join(configDir, 'skills-config.json')
|
|
321
|
+
fs.writeFileSync(configPath, JSON.stringify({ enabledSkills }, null, 2), 'utf8')
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/** Build manifests for the UI: all skills with their enabled state and dependency info. */
|
|
325
|
+
export function buildSkillManifests(workspacePath: string): SkillManifest[] {
|
|
326
|
+
const allSkills = loadAllSkills(workspacePath)
|
|
327
|
+
const enabledList = readEnabledSkills(workspacePath)
|
|
328
|
+
|
|
329
|
+
// If no config, all are directly enabled
|
|
330
|
+
const directSelection = enabledList ?? allSkills.map((s) => s.name)
|
|
331
|
+
const resolved = resolveSkillDependencies(allSkills, directSelection)
|
|
332
|
+
|
|
333
|
+
return allSkills.map((s) => {
|
|
334
|
+
const r = resolved.get(s.name)
|
|
335
|
+
return {
|
|
336
|
+
name: s.name,
|
|
337
|
+
description: s.description,
|
|
338
|
+
category: s.category,
|
|
339
|
+
depends: s.depends,
|
|
340
|
+
tags: s.tags,
|
|
341
|
+
source: s.source,
|
|
342
|
+
enabled: !!r,
|
|
343
|
+
enabledReason: r?.reason ?? null,
|
|
344
|
+
dependencyOf: r?.dependencyOf ?? []
|
|
345
|
+
}
|
|
346
|
+
})
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/** Install a skill from a directory into workspace skills. */
|
|
350
|
+
export function installSkillToWorkspace(
|
|
351
|
+
workspacePath: string,
|
|
352
|
+
skillName: string,
|
|
353
|
+
skillDir: string
|
|
354
|
+
): void {
|
|
355
|
+
const destDir = path.resolve(workspacePath, '.research-pilot', 'skills', skillName)
|
|
356
|
+
if (!fs.existsSync(destDir)) fs.mkdirSync(destDir, { recursive: true })
|
|
357
|
+
// Copy all files from skillDir to destDir
|
|
358
|
+
copyDirSync(skillDir, destDir)
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
function copyDirSync(src: string, dest: string): void {
|
|
362
|
+
const entries = fs.readdirSync(src, { withFileTypes: true })
|
|
363
|
+
for (const entry of entries) {
|
|
364
|
+
const srcPath = path.join(src, entry.name)
|
|
365
|
+
const destPath = path.join(dest, entry.name)
|
|
366
|
+
if (entry.isDirectory()) {
|
|
367
|
+
if (!fs.existsSync(destPath)) fs.mkdirSync(destPath, { recursive: true })
|
|
368
|
+
copyDirSync(srcPath, destPath)
|
|
369
|
+
} else {
|
|
370
|
+
fs.copyFileSync(srcPath, destPath)
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/** Build a catalog (summary without content) for UI display. */
|
|
376
|
+
export function buildSkillsCatalog(entries: SkillEntry[]): SkillCatalogItem[] {
|
|
377
|
+
return entries.map((entry) => ({
|
|
378
|
+
name: entry.name,
|
|
379
|
+
description: entry.description,
|
|
380
|
+
path: entry.path
|
|
381
|
+
}))
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/** Find a skill by name (fuzzy: also tries substring match). */
|
|
385
|
+
export function getSkillByName(entries: SkillEntry[], name: string): SkillEntry | undefined {
|
|
386
|
+
const trimmed = name.trim()
|
|
387
|
+
if (!trimmed) return undefined
|
|
388
|
+
return entries.find((entry) => entry.name === trimmed)
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Build a prompt section that lists available skills for the LLM.
|
|
393
|
+
* Injected into the system prompt so the agent knows what skills exist
|
|
394
|
+
* and can call `load_skill` to load full instructions on demand.
|
|
395
|
+
*/
|
|
396
|
+
export function buildSkillsCatalogPrompt(entries: SkillEntry[]): string {
|
|
397
|
+
if (entries.length === 0) return ''
|
|
398
|
+
const lines = entries.map((e) => `- **${e.name}** [${e.category}]: ${e.description}`)
|
|
399
|
+
return [
|
|
400
|
+
'## Skills',
|
|
401
|
+
'You have the following skills available. Call `load_skill(name)` to load full procedures for any skill before relying on it.',
|
|
402
|
+
'',
|
|
403
|
+
...lines,
|
|
404
|
+
'',
|
|
405
|
+
'Some skills may be pre-loaded as summaries below based on this request. Call `load_skill` for full procedures when needed.'
|
|
406
|
+
].join('\n')
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Build a compact skill summary (~500 tokens) for system prompt injection.
|
|
411
|
+
* Extracts frontmatter + Overview section from SKILL.md.
|
|
412
|
+
* Used by LLM skill matching to give the agent a richer hint than the one-line
|
|
413
|
+
* catalog description, without loading the full skill content.
|
|
414
|
+
*/
|
|
415
|
+
export function buildSkillSummary(entry: SkillEntry, maxChars = 2000): string {
|
|
416
|
+
// Strip frontmatter
|
|
417
|
+
const bodyMatch = entry.content.match(/^---\n[\s\S]*?\n---\n*([\s\S]*)$/)
|
|
418
|
+
const body = bodyMatch?.[1] ?? entry.content
|
|
419
|
+
|
|
420
|
+
// Extract Overview + When to Use sections (typically the first ~500 tokens)
|
|
421
|
+
const sections = body.split(/\n## /)
|
|
422
|
+
const overview = sections[0]?.trim() ?? '' // text before first ## or the # heading section
|
|
423
|
+
const whenToUse = sections.find(s => /^When to Use/i.test(s))
|
|
424
|
+
const summaryParts = [overview]
|
|
425
|
+
if (whenToUse) summaryParts.push(`## ${whenToUse}`)
|
|
426
|
+
|
|
427
|
+
let summary = summaryParts.join('\n\n').trim()
|
|
428
|
+
if (summary.length > maxChars) {
|
|
429
|
+
summary = summary.slice(0, maxChars) + '\n\n[... call load_skill for full procedures]'
|
|
430
|
+
}
|
|
431
|
+
return summary
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* Build the full skill context string for a loaded skill.
|
|
436
|
+
* Returned as the tool result when `load_skill` is called.
|
|
437
|
+
*/
|
|
438
|
+
export function buildSkillContext(entry: SkillEntry, maxChars = 50_000): string {
|
|
439
|
+
const header = [
|
|
440
|
+
'Skill context loaded for this request. Follow these instructions where applicable.',
|
|
441
|
+
'',
|
|
442
|
+
`### Skill: ${entry.name}`,
|
|
443
|
+
`Path: ${entry.path}`,
|
|
444
|
+
`Directory: ${entry.dir}`,
|
|
445
|
+
''
|
|
446
|
+
].join('\n')
|
|
447
|
+
|
|
448
|
+
const body = entry.content.length > maxChars
|
|
449
|
+
? entry.content.slice(0, maxChars) + '\n\n[... truncated]'
|
|
450
|
+
: entry.content
|
|
451
|
+
return header + body
|
|
452
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "research-copilot",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "AI-powered research assistant for scientists — literature search, data analysis, academic writing, and project management",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"research-copilot": "./bin/cli.mjs"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"bin/",
|
|
11
|
+
"app/out/",
|
|
12
|
+
"app/build/",
|
|
13
|
+
"app/package.json",
|
|
14
|
+
"lib/skills/",
|
|
15
|
+
"README.md",
|
|
16
|
+
"LICENSE"
|
|
17
|
+
],
|
|
18
|
+
"workspaces": [
|
|
19
|
+
"app",
|
|
20
|
+
"lib",
|
|
21
|
+
"shared-ui",
|
|
22
|
+
"shared-electron"
|
|
23
|
+
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"dev": "cd app && npx electron-vite dev",
|
|
26
|
+
"build": "cd app && npx electron-vite build",
|
|
27
|
+
"clean": "rm -rf app/out app/dist",
|
|
28
|
+
"prepublishOnly": "npm run build"
|
|
29
|
+
},
|
|
30
|
+
"keywords": [
|
|
31
|
+
"research",
|
|
32
|
+
"ai",
|
|
33
|
+
"academic",
|
|
34
|
+
"literature-search",
|
|
35
|
+
"data-analysis",
|
|
36
|
+
"electron",
|
|
37
|
+
"desktop"
|
|
38
|
+
],
|
|
39
|
+
"author": "daidong",
|
|
40
|
+
"license": "MIT",
|
|
41
|
+
"repository": {
|
|
42
|
+
"type": "git",
|
|
43
|
+
"url": "git+https://github.com/daidong/PiPilot.git"
|
|
44
|
+
},
|
|
45
|
+
"homepage": "https://daidong.github.io/PiPilot/",
|
|
46
|
+
"engines": {
|
|
47
|
+
"node": ">=18"
|
|
48
|
+
},
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"@mariozechner/pi-agent-core": "^0.61.1",
|
|
51
|
+
"@mariozechner/pi-ai": "^0.61.1",
|
|
52
|
+
"@mariozechner/pi-coding-agent": "^0.61.1",
|
|
53
|
+
"@sinclair/typebox": "^0.34.48",
|
|
54
|
+
"adm-zip": "^0.5.16",
|
|
55
|
+
"ajv": "^8.18.0",
|
|
56
|
+
"ajv-formats": "^3.0.1",
|
|
57
|
+
"electron": "^33.3.1",
|
|
58
|
+
"ignore": "^7.0.5",
|
|
59
|
+
"minimatch": "^10.2.4",
|
|
60
|
+
"node-pty": "^1.1.0"
|
|
61
|
+
}
|
|
62
|
+
}
|