scientific-writer 2.1.1__py3-none-any.whl → 2.2.2__py3-none-any.whl

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.

Potentially problematic release.


This version of scientific-writer might be problematic. Click here for more details.

Files changed (311) hide show
  1. scientific_writer/.claude/settings.local.json +30 -0
  2. scientific_writer/.claude/skills/citation-management/SKILL.md +1046 -0
  3. scientific_writer/.claude/skills/citation-management/assets/bibtex_template.bib +264 -0
  4. scientific_writer/.claude/skills/citation-management/assets/citation_checklist.md +386 -0
  5. scientific_writer/.claude/skills/citation-management/references/bibtex_formatting.md +908 -0
  6. scientific_writer/.claude/skills/citation-management/references/citation_validation.md +794 -0
  7. scientific_writer/.claude/skills/citation-management/references/google_scholar_search.md +725 -0
  8. scientific_writer/.claude/skills/citation-management/references/metadata_extraction.md +870 -0
  9. scientific_writer/.claude/skills/citation-management/references/pubmed_search.md +839 -0
  10. scientific_writer/.claude/skills/citation-management/scripts/doi_to_bibtex.py +204 -0
  11. scientific_writer/.claude/skills/citation-management/scripts/extract_metadata.py +569 -0
  12. scientific_writer/.claude/skills/citation-management/scripts/format_bibtex.py +349 -0
  13. scientific_writer/.claude/skills/citation-management/scripts/search_google_scholar.py +282 -0
  14. scientific_writer/.claude/skills/citation-management/scripts/search_pubmed.py +398 -0
  15. scientific_writer/.claude/skills/citation-management/scripts/validate_citations.py +497 -0
  16. scientific_writer/.claude/skills/clinical-reports/IMPLEMENTATION_SUMMARY.md +641 -0
  17. scientific_writer/.claude/skills/clinical-reports/README.md +236 -0
  18. scientific_writer/.claude/skills/clinical-reports/SKILL.md +1088 -0
  19. scientific_writer/.claude/skills/clinical-reports/assets/case_report_template.md +352 -0
  20. scientific_writer/.claude/skills/clinical-reports/assets/clinical_trial_csr_template.md +353 -0
  21. scientific_writer/.claude/skills/clinical-reports/assets/clinical_trial_sae_template.md +359 -0
  22. scientific_writer/.claude/skills/clinical-reports/assets/consult_note_template.md +305 -0
  23. scientific_writer/.claude/skills/clinical-reports/assets/discharge_summary_template.md +453 -0
  24. scientific_writer/.claude/skills/clinical-reports/assets/hipaa_compliance_checklist.md +395 -0
  25. scientific_writer/.claude/skills/clinical-reports/assets/history_physical_template.md +305 -0
  26. scientific_writer/.claude/skills/clinical-reports/assets/lab_report_template.md +309 -0
  27. scientific_writer/.claude/skills/clinical-reports/assets/pathology_report_template.md +249 -0
  28. scientific_writer/.claude/skills/clinical-reports/assets/quality_checklist.md +338 -0
  29. scientific_writer/.claude/skills/clinical-reports/assets/radiology_report_template.md +318 -0
  30. scientific_writer/.claude/skills/clinical-reports/assets/soap_note_template.md +253 -0
  31. scientific_writer/.claude/skills/clinical-reports/references/case_report_guidelines.md +570 -0
  32. scientific_writer/.claude/skills/clinical-reports/references/clinical_trial_reporting.md +693 -0
  33. scientific_writer/.claude/skills/clinical-reports/references/data_presentation.md +530 -0
  34. scientific_writer/.claude/skills/clinical-reports/references/diagnostic_reports_standards.md +629 -0
  35. scientific_writer/.claude/skills/clinical-reports/references/medical_terminology.md +588 -0
  36. scientific_writer/.claude/skills/clinical-reports/references/patient_documentation.md +744 -0
  37. scientific_writer/.claude/skills/clinical-reports/references/peer_review_standards.md +585 -0
  38. scientific_writer/.claude/skills/clinical-reports/references/regulatory_compliance.md +577 -0
  39. scientific_writer/.claude/skills/clinical-reports/scripts/check_deidentification.py +346 -0
  40. scientific_writer/.claude/skills/clinical-reports/scripts/compliance_checker.py +78 -0
  41. scientific_writer/.claude/skills/clinical-reports/scripts/extract_clinical_data.py +102 -0
  42. scientific_writer/.claude/skills/clinical-reports/scripts/format_adverse_events.py +103 -0
  43. scientific_writer/.claude/skills/clinical-reports/scripts/generate_report_template.py +163 -0
  44. scientific_writer/.claude/skills/clinical-reports/scripts/terminology_validator.py +133 -0
  45. scientific_writer/.claude/skills/clinical-reports/scripts/validate_case_report.py +334 -0
  46. scientific_writer/.claude/skills/clinical-reports/scripts/validate_trial_report.py +89 -0
  47. scientific_writer/.claude/skills/document-skills/docx/LICENSE.txt +30 -0
  48. scientific_writer/.claude/skills/document-skills/docx/SKILL.md +197 -0
  49. scientific_writer/.claude/skills/document-skills/docx/docx-js.md +350 -0
  50. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
  51. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
  52. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
  53. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
  54. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
  55. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
  56. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
  57. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
  58. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
  59. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
  60. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
  61. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
  62. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
  63. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
  64. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
  65. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
  66. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
  67. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
  68. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
  69. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
  70. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
  71. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
  72. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
  73. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
  74. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
  75. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
  76. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
  77. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
  78. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
  79. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
  80. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
  81. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/mce/mc.xsd +75 -0
  82. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/microsoft/wml-2010.xsd +560 -0
  83. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/microsoft/wml-2012.xsd +67 -0
  84. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/microsoft/wml-2018.xsd +14 -0
  85. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/microsoft/wml-cex-2018.xsd +20 -0
  86. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/microsoft/wml-cid-2016.xsd +13 -0
  87. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
  88. scientific_writer/.claude/skills/document-skills/docx/ooxml/schemas/microsoft/wml-symex-2015.xsd +8 -0
  89. scientific_writer/.claude/skills/document-skills/docx/ooxml/scripts/pack.py +159 -0
  90. scientific_writer/.claude/skills/document-skills/docx/ooxml/scripts/unpack.py +29 -0
  91. scientific_writer/.claude/skills/document-skills/docx/ooxml/scripts/validate.py +69 -0
  92. scientific_writer/.claude/skills/document-skills/docx/ooxml/scripts/validation/__init__.py +15 -0
  93. scientific_writer/.claude/skills/document-skills/docx/ooxml/scripts/validation/base.py +951 -0
  94. scientific_writer/.claude/skills/document-skills/docx/ooxml/scripts/validation/docx.py +274 -0
  95. scientific_writer/.claude/skills/document-skills/docx/ooxml/scripts/validation/pptx.py +315 -0
  96. scientific_writer/.claude/skills/document-skills/docx/ooxml/scripts/validation/redlining.py +279 -0
  97. scientific_writer/.claude/skills/document-skills/docx/ooxml.md +610 -0
  98. scientific_writer/.claude/skills/document-skills/docx/scripts/__init__.py +1 -0
  99. scientific_writer/.claude/skills/document-skills/docx/scripts/document.py +1276 -0
  100. scientific_writer/.claude/skills/document-skills/docx/scripts/templates/comments.xml +3 -0
  101. scientific_writer/.claude/skills/document-skills/docx/scripts/templates/commentsExtended.xml +3 -0
  102. scientific_writer/.claude/skills/document-skills/docx/scripts/templates/commentsExtensible.xml +3 -0
  103. scientific_writer/.claude/skills/document-skills/docx/scripts/templates/commentsIds.xml +3 -0
  104. scientific_writer/.claude/skills/document-skills/docx/scripts/templates/people.xml +3 -0
  105. scientific_writer/.claude/skills/document-skills/docx/scripts/utilities.py +374 -0
  106. scientific_writer/.claude/skills/document-skills/pdf/LICENSE.txt +30 -0
  107. scientific_writer/.claude/skills/document-skills/pdf/SKILL.md +294 -0
  108. scientific_writer/.claude/skills/document-skills/pdf/forms.md +205 -0
  109. scientific_writer/.claude/skills/document-skills/pdf/reference.md +612 -0
  110. scientific_writer/.claude/skills/document-skills/pdf/scripts/check_bounding_boxes.py +70 -0
  111. scientific_writer/.claude/skills/document-skills/pdf/scripts/check_bounding_boxes_test.py +226 -0
  112. scientific_writer/.claude/skills/document-skills/pdf/scripts/check_fillable_fields.py +12 -0
  113. scientific_writer/.claude/skills/document-skills/pdf/scripts/convert_pdf_to_images.py +35 -0
  114. scientific_writer/.claude/skills/document-skills/pdf/scripts/create_validation_image.py +41 -0
  115. scientific_writer/.claude/skills/document-skills/pdf/scripts/extract_form_field_info.py +152 -0
  116. scientific_writer/.claude/skills/document-skills/pdf/scripts/fill_fillable_fields.py +114 -0
  117. scientific_writer/.claude/skills/document-skills/pdf/scripts/fill_pdf_form_with_annotations.py +108 -0
  118. scientific_writer/.claude/skills/document-skills/pptx/LICENSE.txt +30 -0
  119. scientific_writer/.claude/skills/document-skills/pptx/SKILL.md +484 -0
  120. scientific_writer/.claude/skills/document-skills/pptx/html2pptx.md +625 -0
  121. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
  122. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
  123. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
  124. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
  125. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
  126. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
  127. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
  128. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
  129. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
  130. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
  131. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
  132. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
  133. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
  134. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
  135. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
  136. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
  137. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
  138. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
  139. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
  140. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
  141. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
  142. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
  143. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
  144. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
  145. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
  146. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
  147. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
  148. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
  149. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
  150. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
  151. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
  152. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/mce/mc.xsd +75 -0
  153. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-2010.xsd +560 -0
  154. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-2012.xsd +67 -0
  155. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-2018.xsd +14 -0
  156. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-cex-2018.xsd +20 -0
  157. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-cid-2016.xsd +13 -0
  158. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
  159. scientific_writer/.claude/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-symex-2015.xsd +8 -0
  160. scientific_writer/.claude/skills/document-skills/pptx/ooxml/scripts/pack.py +159 -0
  161. scientific_writer/.claude/skills/document-skills/pptx/ooxml/scripts/unpack.py +29 -0
  162. scientific_writer/.claude/skills/document-skills/pptx/ooxml/scripts/validate.py +69 -0
  163. scientific_writer/.claude/skills/document-skills/pptx/ooxml/scripts/validation/__init__.py +15 -0
  164. scientific_writer/.claude/skills/document-skills/pptx/ooxml/scripts/validation/base.py +951 -0
  165. scientific_writer/.claude/skills/document-skills/pptx/ooxml/scripts/validation/docx.py +274 -0
  166. scientific_writer/.claude/skills/document-skills/pptx/ooxml/scripts/validation/pptx.py +315 -0
  167. scientific_writer/.claude/skills/document-skills/pptx/ooxml/scripts/validation/redlining.py +279 -0
  168. scientific_writer/.claude/skills/document-skills/pptx/ooxml.md +427 -0
  169. scientific_writer/.claude/skills/document-skills/pptx/scripts/html2pptx.js +979 -0
  170. scientific_writer/.claude/skills/document-skills/pptx/scripts/inventory.py +1020 -0
  171. scientific_writer/.claude/skills/document-skills/pptx/scripts/rearrange.py +231 -0
  172. scientific_writer/.claude/skills/document-skills/pptx/scripts/replace.py +385 -0
  173. scientific_writer/.claude/skills/document-skills/pptx/scripts/thumbnail.py +450 -0
  174. scientific_writer/.claude/skills/document-skills/xlsx/LICENSE.txt +30 -0
  175. scientific_writer/.claude/skills/document-skills/xlsx/SKILL.md +289 -0
  176. scientific_writer/.claude/skills/document-skills/xlsx/recalc.py +178 -0
  177. scientific_writer/.claude/skills/hypothesis-generation/SKILL.md +155 -0
  178. scientific_writer/.claude/skills/hypothesis-generation/assets/hypothesis_output_template.md +302 -0
  179. scientific_writer/.claude/skills/hypothesis-generation/references/experimental_design_patterns.md +327 -0
  180. scientific_writer/.claude/skills/hypothesis-generation/references/hypothesis_quality_criteria.md +196 -0
  181. scientific_writer/.claude/skills/hypothesis-generation/references/literature_search_strategies.md +505 -0
  182. scientific_writer/.claude/skills/latex-posters/README.md +417 -0
  183. scientific_writer/.claude/skills/latex-posters/SKILL.md +919 -0
  184. scientific_writer/.claude/skills/latex-posters/assets/baposter_template.tex +257 -0
  185. scientific_writer/.claude/skills/latex-posters/assets/beamerposter_template.tex +244 -0
  186. scientific_writer/.claude/skills/latex-posters/assets/poster_quality_checklist.md +358 -0
  187. scientific_writer/.claude/skills/latex-posters/assets/tikzposter_template.tex +251 -0
  188. scientific_writer/.claude/skills/latex-posters/references/latex_poster_packages.md +745 -0
  189. scientific_writer/.claude/skills/latex-posters/references/poster_content_guide.md +748 -0
  190. scientific_writer/.claude/skills/latex-posters/references/poster_design_principles.md +806 -0
  191. scientific_writer/.claude/skills/latex-posters/references/poster_layout_design.md +900 -0
  192. scientific_writer/.claude/skills/latex-posters/scripts/review_poster.sh +214 -0
  193. scientific_writer/.claude/skills/literature-review/SKILL.md +546 -0
  194. scientific_writer/.claude/skills/literature-review/assets/review_template.md +412 -0
  195. scientific_writer/.claude/skills/literature-review/references/citation_styles.md +166 -0
  196. scientific_writer/.claude/skills/literature-review/references/database_strategies.md +381 -0
  197. scientific_writer/.claude/skills/literature-review/scripts/generate_pdf.py +176 -0
  198. scientific_writer/.claude/skills/literature-review/scripts/search_databases.py +303 -0
  199. scientific_writer/.claude/skills/literature-review/scripts/verify_citations.py +222 -0
  200. scientific_writer/.claude/skills/markitdown/INSTALLATION_GUIDE.md +318 -0
  201. scientific_writer/.claude/skills/markitdown/LICENSE.txt +22 -0
  202. scientific_writer/.claude/skills/markitdown/OPENROUTER_INTEGRATION.md +359 -0
  203. scientific_writer/.claude/skills/markitdown/QUICK_REFERENCE.md +309 -0
  204. scientific_writer/.claude/skills/markitdown/README.md +184 -0
  205. scientific_writer/.claude/skills/markitdown/SKILL.md +450 -0
  206. scientific_writer/.claude/skills/markitdown/SKILL_SUMMARY.md +307 -0
  207. scientific_writer/.claude/skills/markitdown/assets/example_usage.md +463 -0
  208. scientific_writer/.claude/skills/markitdown/references/api_reference.md +399 -0
  209. scientific_writer/.claude/skills/markitdown/references/file_formats.md +542 -0
  210. scientific_writer/.claude/skills/markitdown/scripts/batch_convert.py +228 -0
  211. scientific_writer/.claude/skills/markitdown/scripts/convert_literature.py +283 -0
  212. scientific_writer/.claude/skills/markitdown/scripts/convert_with_ai.py +243 -0
  213. scientific_writer/.claude/skills/paper-2-web/SKILL.md +455 -0
  214. scientific_writer/.claude/skills/paper-2-web/references/installation.md +141 -0
  215. scientific_writer/.claude/skills/paper-2-web/references/paper2poster.md +346 -0
  216. scientific_writer/.claude/skills/paper-2-web/references/paper2video.md +305 -0
  217. scientific_writer/.claude/skills/paper-2-web/references/paper2web.md +187 -0
  218. scientific_writer/.claude/skills/paper-2-web/references/usage_examples.md +436 -0
  219. scientific_writer/.claude/skills/peer-review/SKILL.md +375 -0
  220. scientific_writer/.claude/skills/peer-review/references/common_issues.md +552 -0
  221. scientific_writer/.claude/skills/peer-review/references/reporting_standards.md +290 -0
  222. scientific_writer/.claude/skills/research-grants/README.md +285 -0
  223. scientific_writer/.claude/skills/research-grants/SKILL.md +896 -0
  224. scientific_writer/.claude/skills/research-grants/assets/budget_justification_template.md +453 -0
  225. scientific_writer/.claude/skills/research-grants/assets/nih_specific_aims_template.md +166 -0
  226. scientific_writer/.claude/skills/research-grants/assets/nsf_project_summary_template.md +92 -0
  227. scientific_writer/.claude/skills/research-grants/references/broader_impacts.md +392 -0
  228. scientific_writer/.claude/skills/research-grants/references/darpa_guidelines.md +636 -0
  229. scientific_writer/.claude/skills/research-grants/references/doe_guidelines.md +586 -0
  230. scientific_writer/.claude/skills/research-grants/references/nih_guidelines.md +851 -0
  231. scientific_writer/.claude/skills/research-grants/references/nsf_guidelines.md +570 -0
  232. scientific_writer/.claude/skills/research-grants/references/specific_aims_guide.md +458 -0
  233. scientific_writer/.claude/skills/research-lookup/README.md +116 -0
  234. scientific_writer/.claude/skills/research-lookup/SKILL.md +443 -0
  235. scientific_writer/.claude/skills/research-lookup/examples.py +174 -0
  236. scientific_writer/.claude/skills/research-lookup/lookup.py +93 -0
  237. scientific_writer/.claude/skills/research-lookup/research_lookup.py +335 -0
  238. scientific_writer/.claude/skills/research-lookup/scripts/research_lookup.py +261 -0
  239. scientific_writer/.claude/skills/scholar-evaluation/SKILL.md +254 -0
  240. scientific_writer/.claude/skills/scholar-evaluation/references/evaluation_framework.md +663 -0
  241. scientific_writer/.claude/skills/scholar-evaluation/scripts/calculate_scores.py +378 -0
  242. scientific_writer/.claude/skills/scientific-critical-thinking/SKILL.md +530 -0
  243. scientific_writer/.claude/skills/scientific-critical-thinking/references/common_biases.md +364 -0
  244. scientific_writer/.claude/skills/scientific-critical-thinking/references/evidence_hierarchy.md +484 -0
  245. scientific_writer/.claude/skills/scientific-critical-thinking/references/experimental_design.md +496 -0
  246. scientific_writer/.claude/skills/scientific-critical-thinking/references/logical_fallacies.md +478 -0
  247. scientific_writer/.claude/skills/scientific-critical-thinking/references/scientific_method.md +169 -0
  248. scientific_writer/.claude/skills/scientific-critical-thinking/references/statistical_pitfalls.md +506 -0
  249. scientific_writer/.claude/skills/scientific-schematics/SKILL.md +2035 -0
  250. scientific_writer/.claude/skills/scientific-schematics/assets/block_diagram_template.tex +199 -0
  251. scientific_writer/.claude/skills/scientific-schematics/assets/circuit_template.tex +159 -0
  252. scientific_writer/.claude/skills/scientific-schematics/assets/flowchart_template.tex +161 -0
  253. scientific_writer/.claude/skills/scientific-schematics/assets/pathway_template.tex +162 -0
  254. scientific_writer/.claude/skills/scientific-schematics/assets/tikz_styles.tex +422 -0
  255. scientific_writer/.claude/skills/scientific-schematics/references/best_practices.md +562 -0
  256. scientific_writer/.claude/skills/scientific-schematics/references/diagram_types.md +637 -0
  257. scientific_writer/.claude/skills/scientific-schematics/references/python_libraries.md +791 -0
  258. scientific_writer/.claude/skills/scientific-schematics/references/tikz_guide.md +734 -0
  259. scientific_writer/.claude/skills/scientific-schematics/scripts/circuit_generator.py +307 -0
  260. scientific_writer/.claude/skills/scientific-schematics/scripts/compile_tikz.py +292 -0
  261. scientific_writer/.claude/skills/scientific-schematics/scripts/generate_flowchart.py +281 -0
  262. scientific_writer/.claude/skills/scientific-schematics/scripts/pathway_diagram.py +406 -0
  263. scientific_writer/.claude/skills/scientific-writing/SKILL.md +443 -0
  264. scientific_writer/.claude/skills/scientific-writing/references/citation_styles.md +720 -0
  265. scientific_writer/.claude/skills/scientific-writing/references/figures_tables.md +806 -0
  266. scientific_writer/.claude/skills/scientific-writing/references/imrad_structure.md +658 -0
  267. scientific_writer/.claude/skills/scientific-writing/references/reporting_guidelines.md +748 -0
  268. scientific_writer/.claude/skills/scientific-writing/references/writing_principles.md +824 -0
  269. scientific_writer/.claude/skills/treatment-plans/README.md +483 -0
  270. scientific_writer/.claude/skills/treatment-plans/SKILL.md +817 -0
  271. scientific_writer/.claude/skills/treatment-plans/assets/chronic_disease_management_plan.tex +636 -0
  272. scientific_writer/.claude/skills/treatment-plans/assets/general_medical_treatment_plan.tex +616 -0
  273. scientific_writer/.claude/skills/treatment-plans/assets/mental_health_treatment_plan.tex +745 -0
  274. scientific_writer/.claude/skills/treatment-plans/assets/pain_management_plan.tex +770 -0
  275. scientific_writer/.claude/skills/treatment-plans/assets/perioperative_care_plan.tex +724 -0
  276. scientific_writer/.claude/skills/treatment-plans/assets/quality_checklist.md +471 -0
  277. scientific_writer/.claude/skills/treatment-plans/assets/rehabilitation_treatment_plan.tex +727 -0
  278. scientific_writer/.claude/skills/treatment-plans/references/goal_setting_frameworks.md +411 -0
  279. scientific_writer/.claude/skills/treatment-plans/references/intervention_guidelines.md +507 -0
  280. scientific_writer/.claude/skills/treatment-plans/references/regulatory_compliance.md +476 -0
  281. scientific_writer/.claude/skills/treatment-plans/references/specialty_specific_guidelines.md +607 -0
  282. scientific_writer/.claude/skills/treatment-plans/references/treatment_plan_standards.md +456 -0
  283. scientific_writer/.claude/skills/treatment-plans/scripts/check_completeness.py +318 -0
  284. scientific_writer/.claude/skills/treatment-plans/scripts/generate_template.py +244 -0
  285. scientific_writer/.claude/skills/treatment-plans/scripts/timeline_generator.py +369 -0
  286. scientific_writer/.claude/skills/treatment-plans/scripts/validate_treatment_plan.py +367 -0
  287. scientific_writer/.claude/skills/venue-templates/SKILL.md +590 -0
  288. scientific_writer/.claude/skills/venue-templates/assets/grants/nih_specific_aims.tex +235 -0
  289. scientific_writer/.claude/skills/venue-templates/assets/grants/nsf_proposal_template.tex +375 -0
  290. scientific_writer/.claude/skills/venue-templates/assets/journals/nature_article.tex +171 -0
  291. scientific_writer/.claude/skills/venue-templates/assets/journals/neurips_article.tex +283 -0
  292. scientific_writer/.claude/skills/venue-templates/assets/journals/plos_one.tex +317 -0
  293. scientific_writer/.claude/skills/venue-templates/assets/posters/beamerposter_academic.tex +311 -0
  294. scientific_writer/.claude/skills/venue-templates/references/conferences_formatting.md +564 -0
  295. scientific_writer/.claude/skills/venue-templates/references/grants_requirements.md +787 -0
  296. scientific_writer/.claude/skills/venue-templates/references/journals_formatting.md +486 -0
  297. scientific_writer/.claude/skills/venue-templates/references/posters_guidelines.md +628 -0
  298. scientific_writer/.claude/skills/venue-templates/scripts/customize_template.py +206 -0
  299. scientific_writer/.claude/skills/venue-templates/scripts/query_template.py +260 -0
  300. scientific_writer/.claude/skills/venue-templates/scripts/validate_format.py +255 -0
  301. scientific_writer/CLAUDE.md +748 -0
  302. scientific_writer/__init__.py +2 -2
  303. scientific_writer/api.py +14 -7
  304. scientific_writer/cli.py +12 -7
  305. scientific_writer/core.py +27 -5
  306. {scientific_writer-2.1.1.dist-info → scientific_writer-2.2.2.dist-info}/METADATA +5 -1
  307. scientific_writer-2.2.2.dist-info/RECORD +312 -0
  308. scientific_writer-2.1.1.dist-info/RECORD +0 -11
  309. {scientific_writer-2.1.1.dist-info → scientific_writer-2.2.2.dist-info}/WHEEL +0 -0
  310. {scientific_writer-2.1.1.dist-info → scientific_writer-2.2.2.dist-info}/entry_points.txt +0 -0
  311. {scientific_writer-2.1.1.dist-info → scientific_writer-2.2.2.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,93 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Research Lookup Tool for Claude Code
4
+ Performs research queries using Perplexity Sonar Pro via OpenRouter.
5
+ """
6
+
7
+ import os
8
+ import sys
9
+ import json
10
+ from typing import Dict, List, Optional
11
+
12
+ # Import the main research lookup class
13
+ sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'scripts'))
14
+ from research_lookup import ResearchLookup
15
+
16
+
17
+ def format_response(result: Dict) -> str:
18
+ """Format the research result for display."""
19
+ if not result["success"]:
20
+ return f"❌ Research lookup failed: {result['error']}"
21
+
22
+ response = result["response"]
23
+ citations = result["citations"]
24
+
25
+ # Format the output for Claude Code
26
+ output = f"""🔍 **Research Results**
27
+
28
+ **Query:** {result['query']}
29
+ **Model:** {result['model']}
30
+ **Timestamp:** {result['timestamp']}
31
+
32
+ ---
33
+
34
+ {response}
35
+
36
+ """
37
+
38
+ if citations:
39
+ output += f"\n**Extracted Citations ({len(citations)}):**\n"
40
+ for i, citation in enumerate(citations, 1):
41
+ if citation.get("doi"):
42
+ output += f"{i}. DOI: {citation['doi']}\n"
43
+ elif citation.get("authors") and citation.get("year"):
44
+ output += f"{i}. {citation['authors']} ({citation['year']})\n"
45
+ else:
46
+ output += f"{i}. {citation}\n"
47
+
48
+ if result.get("usage"):
49
+ usage = result["usage"]
50
+ output += f"\n**Usage:** {usage.get('total_tokens', 'N/A')} tokens"
51
+
52
+ return output
53
+
54
+
55
+ def main():
56
+ """Main entry point for Claude Code tool."""
57
+ # Check for API key
58
+ if not os.getenv("OPENROUTER_API_KEY"):
59
+ print("❌ Error: OPENROUTER_API_KEY environment variable not set")
60
+ print("Please set it in your .env file or export it:")
61
+ print(" export OPENROUTER_API_KEY='your_openrouter_api_key'")
62
+ return 1
63
+
64
+ # Get query from command line arguments
65
+ if len(sys.argv) < 2:
66
+ print("❌ Error: No query provided")
67
+ print("Usage: python lookup.py 'your research query here'")
68
+ return 1
69
+
70
+ query = " ".join(sys.argv[1:])
71
+
72
+ try:
73
+ # Initialize research tool
74
+ research = ResearchLookup()
75
+
76
+ # Perform lookup
77
+ print(f"🔍 Researching: {query}")
78
+ result = research.lookup(query)
79
+
80
+ # Format and output result
81
+ formatted_output = format_response(result)
82
+ print(formatted_output)
83
+
84
+ # Return success code
85
+ return 0 if result["success"] else 1
86
+
87
+ except Exception as e:
88
+ print(f"❌ Error: {str(e)}")
89
+ return 1
90
+
91
+
92
+ if __name__ == "__main__":
93
+ exit(main())
@@ -0,0 +1,335 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Research Information Lookup Tool
4
+ Uses Perplexity's Sonar Pro or Sonar Reasoning Pro models through OpenRouter.
5
+ Automatically selects the appropriate model based on query complexity.
6
+ """
7
+
8
+ import os
9
+ import json
10
+ import requests
11
+ import time
12
+ from datetime import datetime
13
+ from typing import Dict, List, Optional, Any
14
+ from urllib.parse import quote
15
+
16
+
17
+ class ResearchLookup:
18
+ """Research information lookup using Perplexity Sonar models via OpenRouter."""
19
+
20
+ # Complexity indicators for determining which model to use
21
+ REASONING_KEYWORDS = [
22
+ 'compare', 'contrast', 'analyze', 'analysis', 'synthesis', 'meta-analysis',
23
+ 'systematic review', 'evaluate', 'critique', 'trade-off', 'tradeoff',
24
+ 'relationship', 'versus', 'vs', 'vs.', 'compared to',
25
+ 'mechanism', 'why', 'how does', 'how do', 'explain', 'theoretical framework',
26
+ 'implications', 'debate', 'controversy', 'conflicting', 'paradox',
27
+ 'reconcile', 'integrate', 'multifaceted', 'complex interaction',
28
+ 'causal relationship', 'underlying mechanism', 'interpret', 'reasoning',
29
+ 'pros and cons', 'advantages and disadvantages', 'critical analysis',
30
+ 'differences between', 'similarities', 'trade offs'
31
+ ]
32
+
33
+ def __init__(self, force_model: Optional[str] = None):
34
+ """
35
+ Initialize the research lookup tool.
36
+
37
+ Args:
38
+ force_model: Optional model override ('pro' or 'reasoning').
39
+ If None, automatically selects based on query complexity.
40
+ """
41
+ self.api_key = os.getenv("OPENROUTER_API_KEY")
42
+ if not self.api_key:
43
+ raise ValueError("OPENROUTER_API_KEY environment variable not set")
44
+
45
+ self.base_url = "https://openrouter.ai/api/v1"
46
+ self.model_pro = "perplexity/sonar-pro" # Fast, efficient lookup
47
+ self.model_reasoning = "perplexity/sonar-reasoning-pro" # Deep analysis
48
+ self.force_model = force_model
49
+ self.headers = {
50
+ "Authorization": f"Bearer {self.api_key}",
51
+ "Content-Type": "application/json",
52
+ "HTTP-Referer": "https://scientific-writer.local", # Replace with your domain
53
+ "X-Title": "Scientific Writer Research Tool"
54
+ }
55
+
56
+ def _assess_query_complexity(self, query: str) -> str:
57
+ """
58
+ Assess query complexity to determine which model to use.
59
+
60
+ Returns:
61
+ 'reasoning' for complex analytical queries, 'pro' for straightforward lookups
62
+ """
63
+ query_lower = query.lower()
64
+
65
+ # Count reasoning keywords
66
+ reasoning_count = sum(1 for keyword in self.REASONING_KEYWORDS if keyword in query_lower)
67
+
68
+ # Count questions (multiple questions suggest complexity)
69
+ question_count = query.count('?')
70
+
71
+ # Check for multiple clauses (complexity indicators)
72
+ clause_indicators = [' and ', ' or ', ' but ', ' however ', ' whereas ', ' although ']
73
+ clause_count = sum(1 for indicator in clause_indicators if indicator in query_lower)
74
+
75
+ # Complexity score
76
+ complexity_score = (
77
+ reasoning_count * 3 + # Reasoning keywords heavily weighted
78
+ question_count * 2 + # Multiple questions indicate complexity
79
+ clause_count * 1.5 + # Multiple clauses suggest nuance
80
+ (1 if len(query) > 150 else 0) # Long queries often more complex
81
+ )
82
+
83
+ # Threshold for using reasoning model (lowered to 3 to catch single reasoning keywords)
84
+ return 'reasoning' if complexity_score >= 3 else 'pro'
85
+
86
+ def _select_model(self, query: str) -> str:
87
+ """Select the appropriate model based on query complexity or force override."""
88
+ if self.force_model:
89
+ return self.model_reasoning if self.force_model == 'reasoning' else self.model_pro
90
+
91
+ complexity_level = self._assess_query_complexity(query)
92
+ return self.model_reasoning if complexity_level == 'reasoning' else self.model_pro
93
+
94
+ def _make_request(self, messages: List[Dict[str, str]], model: str, **kwargs) -> Dict[str, Any]:
95
+ """Make a request to the OpenRouter API."""
96
+ data = {
97
+ "model": model,
98
+ "messages": messages,
99
+ "max_tokens": 4000,
100
+ "temperature": 0.1, # Low temperature for factual research
101
+ "provider": {
102
+ "order": ["Perplexity"],
103
+ "allow_fallbacks": False
104
+ },
105
+ **kwargs
106
+ }
107
+
108
+ try:
109
+ response = requests.post(
110
+ f"{self.base_url}/chat/completions",
111
+ headers=self.headers,
112
+ json=data,
113
+ timeout=90 # Increased timeout for reasoning model
114
+ )
115
+ response.raise_for_status()
116
+ return response.json()
117
+ except requests.exceptions.RequestException as e:
118
+ raise Exception(f"API request failed: {str(e)}")
119
+
120
+ def _format_research_prompt(self, query: str) -> str:
121
+ """Format the query for optimal research results."""
122
+ return f"""You are an expert research assistant. Please provide comprehensive, accurate research information for the following query: "{query}"
123
+
124
+ IMPORTANT INSTRUCTIONS:
125
+ 1. Focus on ACADEMIC and SCIENTIFIC sources (peer-reviewed papers, reputable journals, institutional research)
126
+ 2. Include RECENT information (prioritize 2020-2024 publications)
127
+ 3. Provide COMPLETE citations with authors, title, journal/conference, year, and DOI when available
128
+ 4. Structure your response with clear sections and proper attribution
129
+ 5. Be comprehensive but concise - aim for 800-1200 words
130
+ 6. Include key findings, methodologies, and implications when relevant
131
+ 7. Note any controversies, limitations, or conflicting evidence
132
+
133
+ RESPONSE FORMAT:
134
+ - Start with a brief summary (2-3 sentences)
135
+ - Present key findings and studies in organized sections
136
+ - End with future directions or research gaps if applicable
137
+ - Include 5-8 high-quality citations at the end
138
+
139
+ Remember: This is for academic research purposes. Prioritize accuracy, completeness, and proper attribution."""
140
+
141
+ def lookup(self, query: str) -> Dict[str, Any]:
142
+ """Perform a research lookup for the given query."""
143
+ timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
144
+
145
+ # Select the appropriate model based on query complexity
146
+ selected_model = self._select_model(query)
147
+ model_type = "reasoning" if "reasoning" in selected_model else "standard"
148
+
149
+ print(f"[Research] Using {selected_model} (detected complexity: {model_type})")
150
+
151
+ # Format the research prompt
152
+ research_prompt = self._format_research_prompt(query)
153
+
154
+ # Prepare messages for the API with system message for academic mode
155
+ messages = [
156
+ {
157
+ "role": "system",
158
+ "content": "You are an academic research assistant. Focus exclusively on scholarly sources: peer-reviewed journals, academic papers, research institutions, and reputable scientific publications. Prioritize recent academic literature (2020-2024) and provide complete citations with DOIs. Use academic/scholarly search mode."
159
+ },
160
+ {"role": "user", "content": research_prompt}
161
+ ]
162
+
163
+ try:
164
+ # Make the API request with selected model
165
+ response = self._make_request(messages, model=selected_model)
166
+
167
+ # Extract the response content
168
+ if "choices" in response and len(response["choices"]) > 0:
169
+ choice = response["choices"][0]
170
+ if "message" in choice and "content" in choice["message"]:
171
+ content = choice["message"]["content"]
172
+
173
+ # Extract citations if present (basic regex extraction)
174
+ citations = self._extract_citations(content)
175
+
176
+ return {
177
+ "success": True,
178
+ "query": query,
179
+ "response": content,
180
+ "citations": citations,
181
+ "timestamp": timestamp,
182
+ "model": selected_model,
183
+ "model_type": model_type,
184
+ "usage": response.get("usage", {})
185
+ }
186
+ else:
187
+ raise Exception("Invalid response format from API")
188
+ else:
189
+ raise Exception("No response choices received from API")
190
+
191
+ except Exception as e:
192
+ return {
193
+ "success": False,
194
+ "query": query,
195
+ "error": str(e),
196
+ "timestamp": timestamp,
197
+ "model": selected_model,
198
+ "model_type": model_type
199
+ }
200
+
201
+ def _extract_citations(self, text: str) -> List[Dict[str, str]]:
202
+ """Extract potential citations from the response text."""
203
+ # This is a simple citation extractor - in practice, you might want
204
+ # to use a more sophisticated approach or rely on the model's structured output
205
+
206
+ citations = []
207
+
208
+ # Look for common citation patterns
209
+ import re
210
+
211
+ # Pattern for author et al. year
212
+ author_pattern = r'([A-Z][a-z]+(?:\s+[A-Z]\.)*(?:\s+et\s+al\.)?)\s*\((\d{4})\)'
213
+ matches = re.findall(author_pattern, text)
214
+
215
+ for author, year in matches:
216
+ citations.append({
217
+ "authors": author,
218
+ "year": year,
219
+ "type": "extracted"
220
+ })
221
+
222
+ # Look for DOI patterns
223
+ doi_pattern = r'doi:\s*([^\s\)\]]+)'
224
+ doi_matches = re.findall(doi_pattern, text, re.IGNORECASE)
225
+
226
+ for doi in doi_matches:
227
+ citations.append({
228
+ "doi": doi.strip(),
229
+ "type": "doi"
230
+ })
231
+
232
+ return citations
233
+
234
+ def batch_lookup(self, queries: List[str], delay: float = 1.0) -> List[Dict[str, Any]]:
235
+ """Perform multiple research lookups with optional delay between requests."""
236
+ results = []
237
+
238
+ for i, query in enumerate(queries):
239
+ if i > 0 and delay > 0:
240
+ time.sleep(delay) # Rate limiting
241
+
242
+ result = self.lookup(query)
243
+ results.append(result)
244
+
245
+ # Print progress
246
+ print(f"[Research] Completed query {i+1}/{len(queries)}: {query[:50]}...")
247
+
248
+ return results
249
+
250
+ def get_model_info(self) -> Dict[str, Any]:
251
+ """Get information about available models from OpenRouter."""
252
+ try:
253
+ response = requests.get(
254
+ f"{self.base_url}/models",
255
+ headers=self.headers,
256
+ timeout=30
257
+ )
258
+ response.raise_for_status()
259
+ return response.json()
260
+ except Exception as e:
261
+ return {"error": str(e)}
262
+
263
+
264
+ def main():
265
+ """Command-line interface for testing the research lookup tool."""
266
+ import argparse
267
+
268
+ parser = argparse.ArgumentParser(description="Research Information Lookup Tool")
269
+ parser.add_argument("query", nargs="?", help="Research query to look up")
270
+ parser.add_argument("--model-info", action="store_true", help="Show available models")
271
+ parser.add_argument("--batch", nargs="+", help="Run multiple queries")
272
+ parser.add_argument("--force-model", choices=['pro', 'reasoning'],
273
+ help="Force use of specific model (pro=fast lookup, reasoning=deep analysis)")
274
+
275
+ args = parser.parse_args()
276
+
277
+ # Check for API key
278
+ if not os.getenv("OPENROUTER_API_KEY"):
279
+ print("Error: OPENROUTER_API_KEY environment variable not set")
280
+ print("Please set it in your .env file or export it:")
281
+ print(" export OPENROUTER_API_KEY='your_openrouter_api_key'")
282
+ return 1
283
+
284
+ try:
285
+ research = ResearchLookup(force_model=args.force_model)
286
+
287
+ if args.model_info:
288
+ print("Available models from OpenRouter:")
289
+ models = research.get_model_info()
290
+ if "data" in models:
291
+ for model in models["data"]:
292
+ if "perplexity" in model["id"].lower():
293
+ print(f" - {model['id']}: {model.get('name', 'N/A')}")
294
+ return 0
295
+
296
+ if not args.query and not args.batch:
297
+ parser.print_help()
298
+ return 1
299
+
300
+ if args.batch:
301
+ print(f"Running batch research for {len(args.batch)} queries...")
302
+ results = research.batch_lookup(args.batch)
303
+ else:
304
+ print(f"Researching: {args.query}")
305
+ results = [research.lookup(args.query)]
306
+
307
+ # Display results
308
+ for i, result in enumerate(results):
309
+ if result["success"]:
310
+ print(f"\n{'='*80}")
311
+ print(f"Query {i+1}: {result['query']}")
312
+ print(f"Timestamp: {result['timestamp']}")
313
+ print(f"Model: {result['model']} ({result.get('model_type', 'unknown')})")
314
+ print(f"{'='*80}")
315
+ print(result["response"])
316
+
317
+ if result["citations"]:
318
+ print(f"\nExtracted Citations ({len(result['citations'])}):")
319
+ for j, citation in enumerate(result["citations"]):
320
+ print(f" {j+1}. {citation}")
321
+
322
+ if result["usage"]:
323
+ print(f"\nUsage: {result['usage']}")
324
+ else:
325
+ print(f"\nError in query {i+1}: {result['error']}")
326
+
327
+ return 0
328
+
329
+ except Exception as e:
330
+ print(f"Error: {str(e)}")
331
+ return 1
332
+
333
+
334
+ if __name__ == "__main__":
335
+ exit(main())
@@ -0,0 +1,261 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Research Information Lookup Tool
4
+ Uses Perplexity's Sonar Pro model through OpenRouter for academic research queries.
5
+ """
6
+
7
+ import os
8
+ import json
9
+ import requests
10
+ import time
11
+ from datetime import datetime
12
+ from typing import Dict, List, Optional, Any
13
+ from urllib.parse import quote
14
+
15
+
16
+ class ResearchLookup:
17
+ """Research information lookup using Perplexity Sonar Pro via OpenRouter."""
18
+
19
+ def __init__(self):
20
+ """Initialize the research lookup tool."""
21
+ self.api_key = os.getenv("OPENROUTER_API_KEY")
22
+ if not self.api_key:
23
+ raise ValueError("OPENROUTER_API_KEY environment variable not set")
24
+
25
+ self.base_url = "https://openrouter.ai/api/v1"
26
+ self.model = "perplexity/sonar-reasoning-pro" # Perplexity Sonar Pro with online search
27
+ self.headers = {
28
+ "Authorization": f"Bearer {self.api_key}",
29
+ "Content-Type": "application/json",
30
+ "HTTP-Referer": "https://scientific-writer.local", # Replace with your domain
31
+ "X-Title": "Scientific Writer Research Tool"
32
+ }
33
+
34
+ def _make_request(self, messages: List[Dict[str, str]], **kwargs) -> Dict[str, Any]:
35
+ """Make a request to the OpenRouter API."""
36
+ data = {
37
+ "model": self.model,
38
+ "messages": messages,
39
+ "max_tokens": 8000,
40
+ "temperature": 0.1, # Low temperature for factual research
41
+ **kwargs
42
+ }
43
+
44
+ try:
45
+ response = requests.post(
46
+ f"{self.base_url}/chat/completions",
47
+ headers=self.headers,
48
+ json=data,
49
+ timeout=60
50
+ )
51
+ response.raise_for_status()
52
+ return response.json()
53
+ except requests.exceptions.RequestException as e:
54
+ raise Exception(f"API request failed: {str(e)}")
55
+
56
+ def _format_research_prompt(self, query: str) -> str:
57
+ """Format the query for optimal research results."""
58
+ return f"""You are an expert research assistant. Please provide comprehensive, accurate research information for the following query: "{query}"
59
+
60
+ IMPORTANT INSTRUCTIONS:
61
+ 1. Focus on ACADEMIC and SCIENTIFIC sources (peer-reviewed papers, reputable journals, institutional research)
62
+ 2. Include RECENT information (prioritize 2020-2024 publications)
63
+ 3. Provide COMPLETE citations with authors, title, journal/conference, year, and DOI when available
64
+ 4. Structure your response with clear sections and proper attribution
65
+ 5. Be comprehensive but concise - aim for 800-1200 words
66
+ 6. Include key findings, methodologies, and implications when relevant
67
+ 7. Note any controversies, limitations, or conflicting evidence
68
+
69
+ RESPONSE FORMAT:
70
+ - Start with a brief summary (2-3 sentences)
71
+ - Present key findings and studies in organized sections
72
+ - End with future directions or research gaps if applicable
73
+ - Include 5-8 high-quality citations at the end
74
+
75
+ Remember: This is for academic research purposes. Prioritize accuracy, completeness, and proper attribution."""
76
+
77
+ def lookup(self, query: str) -> Dict[str, Any]:
78
+ """Perform a research lookup for the given query."""
79
+ timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
80
+
81
+ # Format the research prompt
82
+ research_prompt = self._format_research_prompt(query)
83
+
84
+ # Prepare messages for the API with system message for academic mode
85
+ messages = [
86
+ {
87
+ "role": "system",
88
+ "content": "You are an academic research assistant. Focus exclusively on scholarly sources: peer-reviewed journals, academic papers, research institutions, and reputable scientific publications. Prioritize recent academic literature (2020-2024) and provide complete citations with DOIs. Use academic/scholarly search mode."
89
+ },
90
+ {"role": "user", "content": research_prompt}
91
+ ]
92
+
93
+ try:
94
+ # Make the API request
95
+ response = self._make_request(messages)
96
+
97
+ # Extract the response content
98
+ if "choices" in response and len(response["choices"]) > 0:
99
+ choice = response["choices"][0]
100
+ if "message" in choice and "content" in choice["message"]:
101
+ content = choice["message"]["content"]
102
+
103
+ # Extract citations if present (basic regex extraction)
104
+ citations = self._extract_citations(content)
105
+
106
+ return {
107
+ "success": True,
108
+ "query": query,
109
+ "response": content,
110
+ "citations": citations,
111
+ "timestamp": timestamp,
112
+ "model": self.model,
113
+ "usage": response.get("usage", {})
114
+ }
115
+ else:
116
+ raise Exception("Invalid response format from API")
117
+ else:
118
+ raise Exception("No response choices received from API")
119
+
120
+ except Exception as e:
121
+ return {
122
+ "success": False,
123
+ "query": query,
124
+ "error": str(e),
125
+ "timestamp": timestamp,
126
+ "model": self.model
127
+ }
128
+
129
+ def _extract_citations(self, text: str) -> List[Dict[str, str]]:
130
+ """Extract potential citations from the response text."""
131
+ # This is a simple citation extractor - in practice, you might want
132
+ # to use a more sophisticated approach or rely on the model's structured output
133
+
134
+ citations = []
135
+
136
+ # Look for common citation patterns
137
+ import re
138
+
139
+ # Pattern for author et al. year
140
+ author_pattern = r'([A-Z][a-z]+(?:\s+[A-Z]\.)*(?:\s+et\s+al\.)?)\s*\((\d{4})\)'
141
+ matches = re.findall(author_pattern, text)
142
+
143
+ for author, year in matches:
144
+ citations.append({
145
+ "authors": author,
146
+ "year": year,
147
+ "type": "extracted"
148
+ })
149
+
150
+ # Look for DOI patterns
151
+ doi_pattern = r'doi:\s*([^\s\)\]]+)'
152
+ doi_matches = re.findall(doi_pattern, text, re.IGNORECASE)
153
+
154
+ for doi in doi_matches:
155
+ citations.append({
156
+ "doi": doi.strip(),
157
+ "type": "doi"
158
+ })
159
+
160
+ return citations
161
+
162
+ def batch_lookup(self, queries: List[str], delay: float = 1.0) -> List[Dict[str, Any]]:
163
+ """Perform multiple research lookups with optional delay between requests."""
164
+ results = []
165
+
166
+ for i, query in enumerate(queries):
167
+ if i > 0 and delay > 0:
168
+ time.sleep(delay) # Rate limiting
169
+
170
+ result = self.lookup(query)
171
+ results.append(result)
172
+
173
+ # Print progress
174
+ print(f"[Research] Completed query {i+1}/{len(queries)}: {query[:50]}...")
175
+
176
+ return results
177
+
178
+ def get_model_info(self) -> Dict[str, Any]:
179
+ """Get information about available models from OpenRouter."""
180
+ try:
181
+ response = requests.get(
182
+ f"{self.base_url}/models",
183
+ headers=self.headers,
184
+ timeout=30
185
+ )
186
+ response.raise_for_status()
187
+ return response.json()
188
+ except Exception as e:
189
+ return {"error": str(e)}
190
+
191
+
192
+ def main():
193
+ """Command-line interface for testing the research lookup tool."""
194
+ import argparse
195
+
196
+ parser = argparse.ArgumentParser(description="Research Information Lookup Tool")
197
+ parser.add_argument("query", nargs="?", help="Research query to look up")
198
+ parser.add_argument("--model-info", action="store_true", help="Show available models")
199
+ parser.add_argument("--batch", nargs="+", help="Run multiple queries")
200
+
201
+ args = parser.parse_args()
202
+
203
+ # Check for API key
204
+ if not os.getenv("OPENROUTER_API_KEY"):
205
+ print("Error: OPENROUTER_API_KEY environment variable not set")
206
+ print("Please set it in your .env file or export it:")
207
+ print(" export OPENROUTER_API_KEY='your_openrouter_api_key'")
208
+ return 1
209
+
210
+ try:
211
+ research = ResearchLookup()
212
+
213
+ if args.model_info:
214
+ print("Available models from OpenRouter:")
215
+ models = research.get_model_info()
216
+ if "data" in models:
217
+ for model in models["data"]:
218
+ if "perplexity" in model["id"].lower():
219
+ print(f" - {model['id']}: {model.get('name', 'N/A')}")
220
+ return 0
221
+
222
+ if not args.query and not args.batch:
223
+ print("Error: No query provided. Use --model-info to see available models.")
224
+ return 1
225
+
226
+ if args.batch:
227
+ print(f"Running batch research for {len(args.batch)} queries...")
228
+ results = research.batch_lookup(args.batch)
229
+ else:
230
+ print(f"Researching: {args.query}")
231
+ results = [research.lookup(args.query)]
232
+
233
+ # Display results
234
+ for i, result in enumerate(results):
235
+ if result["success"]:
236
+ print(f"\n{'='*80}")
237
+ print(f"Query {i+1}: {result['query']}")
238
+ print(f"Timestamp: {result['timestamp']}")
239
+ print(f"Model: {result['model']}")
240
+ print(f"{'='*80}")
241
+ print(result["response"])
242
+
243
+ if result["citations"]:
244
+ print(f"\nExtracted Citations ({len(result['citations'])}):")
245
+ for j, citation in enumerate(result["citations"]):
246
+ print(f" {j+1}. {citation}")
247
+
248
+ if result["usage"]:
249
+ print(f"\nUsage: {result['usage']}")
250
+ else:
251
+ print(f"\nError in query {i+1}: {result['error']}")
252
+
253
+ return 0
254
+
255
+ except Exception as e:
256
+ print(f"Error: {str(e)}")
257
+ return 1
258
+
259
+
260
+ if __name__ == "__main__":
261
+ exit(main())