@yeyuan98/opencode-bioresearcher-plugin 1.6.6 → 1.6.8-alpha.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.
Files changed (200) hide show
  1. package/LICENSE +0 -0
  2. package/README.md +0 -0
  3. package/dist/agents/bioresearcher/index.d.ts +0 -0
  4. package/dist/agents/bioresearcher/index.js +0 -0
  5. package/dist/agents/bioresearcher/prompt.d.ts +0 -0
  6. package/dist/agents/bioresearcher/prompt.js +0 -0
  7. package/dist/agents/bioresearcherDR/index.d.ts +0 -0
  8. package/dist/agents/bioresearcherDR/index.js +0 -0
  9. package/dist/agents/bioresearcherDR/prompt.d.ts +0 -0
  10. package/dist/agents/bioresearcherDR/prompt.js +0 -0
  11. package/dist/agents/bioresearcherDR_worker/index.d.ts +0 -0
  12. package/dist/agents/bioresearcherDR_worker/index.js +0 -0
  13. package/dist/agents/bioresearcherDR_worker/prompt.d.ts +0 -0
  14. package/dist/agents/bioresearcherDR_worker/prompt.js +0 -0
  15. package/dist/index.d.ts +0 -0
  16. package/dist/index.js +4 -3
  17. package/dist/shared/skill-sync.d.ts +0 -0
  18. package/dist/shared/skill-sync.js +0 -0
  19. package/dist/shared/tool-restrictions.d.ts +0 -0
  20. package/dist/shared/tool-restrictions.js +0 -0
  21. package/dist/skills/bioresearcher-core/README.md +0 -0
  22. package/dist/skills/bioresearcher-core/SKILL.md +0 -0
  23. package/dist/skills/bioresearcher-core/examples/contexts.json +0 -0
  24. package/dist/skills/bioresearcher-core/examples/data-exchange-example.md +0 -0
  25. package/dist/skills/bioresearcher-core/examples/template.md +0 -0
  26. package/dist/skills/bioresearcher-core/patterns/bioresearcher/analysis-methods.md +0 -0
  27. package/dist/skills/bioresearcher-core/patterns/bioresearcher/best-practices.md +0 -0
  28. package/dist/skills/bioresearcher-core/patterns/bioresearcher/python-standards.md +0 -0
  29. package/dist/skills/bioresearcher-core/patterns/bioresearcher/report-template.md +0 -0
  30. package/dist/skills/bioresearcher-core/patterns/bioresearcher/tool-selection.md +0 -0
  31. package/dist/skills/bioresearcher-core/patterns/calculator.md +0 -0
  32. package/dist/skills/bioresearcher-core/patterns/citations.md +0 -0
  33. package/dist/skills/bioresearcher-core/patterns/data-exchange.md +0 -0
  34. package/dist/skills/bioresearcher-core/patterns/json-tools.md +0 -0
  35. package/dist/skills/bioresearcher-core/patterns/progress.md +0 -0
  36. package/dist/skills/bioresearcher-core/patterns/rate-limiting.md +0 -0
  37. package/dist/skills/bioresearcher-core/patterns/retry.md +0 -0
  38. package/dist/skills/bioresearcher-core/patterns/shell-commands.md +0 -0
  39. package/dist/skills/bioresearcher-core/patterns/subagent-waves.md +0 -0
  40. package/dist/skills/bioresearcher-core/patterns/table-tools.md +0 -0
  41. package/dist/skills/bioresearcher-core/patterns/user-confirmation.md +0 -0
  42. package/dist/skills/bioresearcher-core/python/template.md +0 -0
  43. package/dist/skills/bioresearcher-core/python/template.py +0 -0
  44. package/dist/skills/bioresearcher-tests/README.md +0 -0
  45. package/dist/skills/bioresearcher-tests/SKILL.md +0 -0
  46. package/dist/skills/bioresearcher-tests/pyproject.toml +0 -0
  47. package/dist/skills/bioresearcher-tests/resources/json_samples/in_markdown.md.gz +0 -0
  48. package/dist/skills/bioresearcher-tests/resources/json_samples/nested_object.json.gz +0 -0
  49. package/dist/skills/bioresearcher-tests/resources/json_samples/schema_draft7.json.gz +0 -0
  50. package/dist/skills/bioresearcher-tests/resources/json_samples/simple_array.json.gz +0 -0
  51. package/dist/skills/bioresearcher-tests/resources/json_samples/simple_object.json.gz +0 -0
  52. package/dist/skills/bioresearcher-tests/resources/obo_sample.obo.gz +0 -0
  53. package/dist/skills/bioresearcher-tests/resources/pubmed_sample.xml.gz +0 -0
  54. package/dist/skills/bioresearcher-tests/resources/table_sample.xlsx.gz +0 -0
  55. package/dist/skills/bioresearcher-tests/test_cases/json_tests.md +0 -0
  56. package/dist/skills/bioresearcher-tests/test_cases/misc_tests.md +0 -0
  57. package/dist/skills/bioresearcher-tests/test_cases/parser_tests.md +0 -0
  58. package/dist/skills/bioresearcher-tests/test_cases/skill_tests.md +0 -0
  59. package/dist/skills/bioresearcher-tests/test_cases/table_tests.md +0 -0
  60. package/dist/skills/bioresearcher-tests/test_runner.py +0 -0
  61. package/dist/skills/demo-skill/SKILL.md +0 -0
  62. package/dist/skills/demo-skill/demo_script.py +0 -0
  63. package/dist/skills/env-jsonc-setup/SKILL.md +0 -0
  64. package/dist/skills/gromacs-guides/SKILL.md +0 -0
  65. package/dist/skills/gromacs-guides/guides/create_index.md +96 -96
  66. package/dist/skills/gromacs-guides/guides/inspect_tpr.md +160 -160
  67. package/dist/skills/long-table-summary/SKILL.md +0 -0
  68. package/dist/skills/long-table-summary/combine_outputs.py +0 -0
  69. package/dist/skills/long-table-summary/generate_prompts.py +0 -0
  70. package/dist/skills/long-table-summary/pyproject.toml +0 -0
  71. package/dist/skills/pubmed-weekly/SKILL.md +0 -0
  72. package/dist/skills/pubmed-weekly/pubmed_weekly.py +0 -0
  73. package/dist/skills/pubmed-weekly/pyproject.toml +0 -0
  74. package/dist/skills/python-setup-uv/SKILL.md +0 -0
  75. package/dist/tools/db/backends/index.d.ts +0 -0
  76. package/dist/tools/db/backends/index.js +0 -0
  77. package/dist/tools/db/backends/mongodb/backend.d.ts +0 -0
  78. package/dist/tools/db/backends/mongodb/backend.js +0 -0
  79. package/dist/tools/db/backends/mongodb/connection.d.ts +0 -0
  80. package/dist/tools/db/backends/mongodb/connection.js +0 -0
  81. package/dist/tools/db/backends/mongodb/index.d.ts +0 -0
  82. package/dist/tools/db/backends/mongodb/index.js +0 -0
  83. package/dist/tools/db/backends/mongodb/translator.d.ts +0 -0
  84. package/dist/tools/db/backends/mongodb/translator.js +0 -0
  85. package/dist/tools/db/backends/mysql/backend.d.ts +0 -0
  86. package/dist/tools/db/backends/mysql/backend.js +0 -0
  87. package/dist/tools/db/backends/mysql/connection.d.ts +0 -0
  88. package/dist/tools/db/backends/mysql/connection.js +0 -0
  89. package/dist/tools/db/backends/mysql/index.d.ts +0 -0
  90. package/dist/tools/db/backends/mysql/index.js +0 -0
  91. package/dist/tools/db/backends/mysql/translator.d.ts +0 -0
  92. package/dist/tools/db/backends/mysql/translator.js +0 -0
  93. package/dist/tools/db/core/base.d.ts +0 -0
  94. package/dist/tools/db/core/base.js +0 -0
  95. package/dist/tools/db/core/config-loader.d.ts +0 -0
  96. package/dist/tools/db/core/config-loader.js +0 -0
  97. package/dist/tools/db/core/index.d.ts +0 -0
  98. package/dist/tools/db/core/index.js +0 -0
  99. package/dist/tools/db/core/jsonc-parser.d.ts +0 -0
  100. package/dist/tools/db/core/jsonc-parser.js +0 -0
  101. package/dist/tools/db/core/validator.d.ts +0 -0
  102. package/dist/tools/db/core/validator.js +0 -0
  103. package/dist/tools/db/index.d.ts +0 -0
  104. package/dist/tools/db/index.js +0 -0
  105. package/dist/tools/db/interface/backend.d.ts +0 -0
  106. package/dist/tools/db/interface/backend.js +0 -0
  107. package/dist/tools/db/interface/connection.d.ts +0 -0
  108. package/dist/tools/db/interface/connection.js +0 -0
  109. package/dist/tools/db/interface/index.d.ts +0 -0
  110. package/dist/tools/db/interface/index.js +0 -0
  111. package/dist/tools/db/interface/query.d.ts +0 -0
  112. package/dist/tools/db/interface/query.js +0 -0
  113. package/dist/tools/db/interface/schema.d.ts +0 -0
  114. package/dist/tools/db/interface/schema.js +0 -0
  115. package/dist/tools/db/tools.d.ts +0 -0
  116. package/dist/tools/db/tools.js +0 -0
  117. package/dist/tools/db/utils.d.ts +0 -0
  118. package/dist/tools/db/utils.js +0 -0
  119. package/dist/tools/misc/calculator.d.ts +0 -0
  120. package/dist/tools/misc/calculator.js +0 -0
  121. package/dist/tools/misc/index.d.ts +1 -0
  122. package/dist/tools/misc/index.js +1 -0
  123. package/dist/tools/misc/json-extract.d.ts +0 -0
  124. package/dist/tools/misc/json-extract.js +0 -0
  125. package/dist/tools/misc/json-infer.d.ts +0 -0
  126. package/dist/tools/misc/json-infer.js +0 -0
  127. package/dist/tools/misc/json-validate.d.ts +0 -0
  128. package/dist/tools/misc/json-validate.js +0 -0
  129. package/dist/tools/misc/markdown-to-html.d.ts +19 -0
  130. package/dist/tools/misc/markdown-to-html.js +109 -0
  131. package/dist/tools/misc/marked-bundle.d.ts +1 -0
  132. package/dist/tools/misc/marked-bundle.js +1 -0
  133. package/dist/tools/misc/timer.d.ts +0 -0
  134. package/dist/tools/misc/timer.js +0 -0
  135. package/dist/tools/parser/obo/index.d.ts +0 -0
  136. package/dist/tools/parser/obo/index.js +0 -0
  137. package/dist/tools/parser/obo/obo.d.ts +0 -0
  138. package/dist/tools/parser/obo/obo.js +0 -0
  139. package/dist/tools/parser/obo/types.d.ts +0 -0
  140. package/dist/tools/parser/obo/types.js +0 -0
  141. package/dist/tools/parser/obo/utils.d.ts +0 -0
  142. package/dist/tools/parser/obo/utils.js +0 -0
  143. package/dist/tools/parser/pubmed/index.d.ts +0 -0
  144. package/dist/tools/parser/pubmed/index.js +0 -0
  145. package/dist/tools/parser/pubmed/pubmed.d.ts +0 -0
  146. package/dist/tools/parser/pubmed/pubmed.js +0 -0
  147. package/dist/tools/parser/pubmed/types.d.ts +0 -0
  148. package/dist/tools/parser/pubmed/types.js +0 -0
  149. package/dist/tools/parser/pubmed/utils.d.ts +0 -0
  150. package/dist/tools/parser/pubmed/utils.js +0 -0
  151. package/dist/tools/sandbox/bash-parser.d.ts +0 -0
  152. package/dist/tools/sandbox/bash-parser.js +0 -0
  153. package/dist/tools/sandbox/escape-scenarios.test.d.ts +0 -0
  154. package/dist/tools/sandbox/escape-scenarios.test.js +0 -0
  155. package/dist/tools/sandbox/expander.d.ts +0 -0
  156. package/dist/tools/sandbox/expander.js +0 -0
  157. package/dist/tools/sandbox/final-verification.test.d.ts +0 -0
  158. package/dist/tools/sandbox/final-verification.test.js +0 -0
  159. package/dist/tools/sandbox/hooks.d.ts +0 -0
  160. package/dist/tools/sandbox/hooks.js +0 -0
  161. package/dist/tools/sandbox/index.d.ts +0 -0
  162. package/dist/tools/sandbox/index.js +0 -0
  163. package/dist/tools/sandbox/manager.d.ts +0 -0
  164. package/dist/tools/sandbox/manager.js +0 -0
  165. package/dist/tools/sandbox/sandbox.integration.test.d.ts +0 -0
  166. package/dist/tools/sandbox/sandbox.integration.test.js +0 -0
  167. package/dist/tools/sandbox/sandbox.test.d.ts +0 -0
  168. package/dist/tools/sandbox/sandbox.test.js +0 -0
  169. package/dist/tools/sandbox/tool.d.ts +0 -0
  170. package/dist/tools/sandbox/tool.js +0 -0
  171. package/dist/tools/sandbox/types.d.ts +0 -0
  172. package/dist/tools/sandbox/types.js +0 -0
  173. package/dist/tools/sandbox/validator.d.ts +0 -0
  174. package/dist/tools/sandbox/validator.js +0 -0
  175. package/dist/tools/skill/frontmatter.d.ts +0 -0
  176. package/dist/tools/skill/frontmatter.js +0 -0
  177. package/dist/tools/skill/index.d.ts +0 -0
  178. package/dist/tools/skill/index.js +0 -0
  179. package/dist/tools/skill/registry.d.ts +0 -0
  180. package/dist/tools/skill/registry.js +0 -0
  181. package/dist/tools/skill/tool.d.ts +0 -0
  182. package/dist/tools/skill/tool.js +0 -0
  183. package/dist/tools/skill/types.d.ts +0 -0
  184. package/dist/tools/skill/types.js +0 -0
  185. package/dist/tools/table/index.d.ts +0 -0
  186. package/dist/tools/table/index.js +0 -0
  187. package/dist/tools/table/tools.d.ts +0 -0
  188. package/dist/tools/table/tools.js +0 -0
  189. package/dist/tools/table/utils.d.ts +0 -0
  190. package/dist/tools/table/utils.js +0 -0
  191. package/dist/version.d.ts +1 -1
  192. package/dist/version.js +1 -1
  193. package/package.json +3 -2
  194. package/dist/skills/pzfx-io/SKILL.md +0 -111
  195. package/dist/skills/pzfx-io/guides/convert.md +0 -102
  196. package/dist/skills/pzfx-io/guides/read-parse.md +0 -116
  197. package/dist/skills/pzfx-io/guides/schema-reference.md +0 -167
  198. package/dist/skills/pzfx-io/guides/write-edit.md +0 -150
  199. package/dist/skills/pzfx-io/pyproject.toml +0 -6
  200. package/dist/skills/pzfx-io/pzfx.py +0 -1156
@@ -1,160 +1,160 @@
1
- # Inspecting TPR Files for Molecule Information
2
-
3
- ## Quick Summary
4
-
5
- ```bash
6
- gmx dump -s <tpr_file> 2>&1 | grep -A 5 "moltype"
7
- ```
8
-
9
- ## Detailed Breakdown
10
-
11
- ```bash
12
- # Full dump (verbose)
13
- gmx dump -s <tpr_file>
14
-
15
- # Extract molecule block info
16
- gmx dump -s <tpr_file> 2>&1 | grep -E "(molblock|#molecules|moltype.*=)"
17
- ```
18
-
19
- **Output interpretation:**
20
- ```
21
- molblock (N):
22
- moltype = M "MoleculeName" # Molecule type name
23
- #molecules = X # Number of copies in system
24
-
25
- moltype (M):
26
- name="MoleculeName"
27
- atoms:
28
- atom (N): # N atoms in this molecule type
29
- ```
30
-
31
- **Note:** Atoms are 0-indexed. `atom (275):` means 276 atoms with indices 0-275.
32
-
33
- ## Key Information to Extract
34
-
35
- | Information | How to Find |
36
- |-------------|-------------|
37
- | Molecule type names | `grep 'moltype.*='` after `gmx dump` |
38
- | Molecule counts | `grep '#molecules'` after `gmx dump` |
39
- | Atoms per molecule type | Check `atom (N):` line under each `moltype` section |
40
- | Solvent molecule count | Find SOL/Water moltype, read `#molecules` |
41
- | Ion counts by type | Find NA, CL, etc. moltypes, read `#molecules` each |
42
- | Protein molecule chains | Count moltypes with "Protein" or similar in name |
43
-
44
- ## Detecting Cyclic Molecule Configuration
45
-
46
- For protein chains, check if the molecule is cyclic (e.g., cyclic peptides) by examining bonds within the moltype.
47
-
48
- **Detection strategy:**
49
- 1. Get atom count for the moltype from `atom (N):` line (N atoms, indexed 0 to N-1)
50
- 2. Search the Bond section for a bond between atom 0 and the C-terminal atom (typically atom N-2, which is the C atom before the terminal O)
51
- 3. If such a bond exists, the molecule is cyclic
52
-
53
- If no bond is found between atom 0 and the C-terminal atom, the molecule is linear (non-cyclic).
54
-
55
- **Bond format in gmx dump:**
56
- ```
57
- Bond:
58
- nr: <count>
59
- iatoms:
60
- 0 type=441 (BONDS) 0 2
61
- 1 type=442 (BONDS) 0 273 <-- bond from atom 0 to atom 273
62
- ```
63
-
64
- **Example:** For a 275-atom cyclic peptide (atoms 0-274):
65
- - Atom 0: N-terminal N
66
- - Atom 273: C-terminal C (the backbone carbon)
67
- - Atom 274: C-terminal O
68
- - A bond `0 273` indicates the N-C cyclization
69
-
70
- **Quick check for cyclic bond:**
71
- ```bash
72
- # Get atom count for a protein moltype
73
- gmx dump -s <tpr_file> 2>&1 | grep -A 1 "atom (" | head -4
74
-
75
- # Search for bonds involving atom 0 and the C-terminal atom (N-2)
76
- # Replace <N-2> with actual value (e.g., 273 for 275-atom molecule)
77
-
78
- # Standard pattern
79
- gmx dump -s <tpr_file> 2>&1 | grep -E "BONDS.*0.*<N-2>"
80
-
81
- # More robust pattern (explicit whitespace, works better on Windows)
82
- gmx dump -s <tpr_file> 2>&1 | grep -E "BONDS\ +0 +<N-2>"
83
- ```
84
-
85
- **Example command for 275-atom molecule:**
86
- ```bash
87
- gmx dump -s <tpr_file> 2>&1 | grep -E "BONDS.*0.*273"
88
- ```
89
-
90
- #### Verifying the C-Terminal Atom
91
-
92
- The C-terminal C atom is typically at index N-2, but this can vary by force field. Verify with:
93
- ```bash
94
- # Check atom type at index N-2 (e.g., 273 for 275-atom molecule)
95
- gmx dump -s <tpr_file> 2>&1 | grep -A2 "atom (273):"
96
- ```
97
- Look for `type="C"` to confirm it's the backbone carbon.
98
-
99
- #### Isolating Bonds for a Specific Moltype
100
-
101
- When multiple moltypes exist, grep captures all bonds. To isolate one moltype's bonds:
102
-
103
- **Method 1: sed range (Recommended)**
104
- ```bash
105
- # Extract bonds for moltype M (e.g., moltype 1)
106
- gmx dump -s <tpr_file> 2>&1 | sed -n '/moltype (1)/,/moltype (2)/p' | grep -E "BONDS.*0.*273"
107
- ```
108
-
109
- **Method 2: grep with context**
110
- ```bash
111
- # Get bonds within 200 lines after moltype declaration
112
- gmx dump -s <tpr_file> 2>&1 | grep -A200 "moltype (1)" | grep -E "BONDS.*0.*273"
113
- ```
114
- Replace moltype numbers and context lines as appropriate for your system.
115
-
116
- ## Checking Molecule Independence
117
-
118
- ```bash
119
- gmx dump -s <tpr_file> 2>&1 | grep "bIntermolecularInteractions"
120
- ```
121
- - `false` = Molecules are independent (correct for most simulations)
122
- - `true` = Bonded interactions exist between molecule types (unusual)
123
-
124
- ## Quick System Overview
125
-
126
- ```bash
127
- echo "q" | gmx make_ndx -f <tpr_file> 2>&1 | grep -E "(System|Protein|Water|Ion|atoms)"
128
- ```
129
-
130
- ## Standardized TPR Summary Template
131
-
132
- When users ask generic questions like "summarize this TPR" or "list all components", use this template for consistent output:
133
-
134
- ### <tpr_file> Analysis Summary
135
-
136
- | Component | Count | Atoms | Structure |
137
- |-----------|-------|-------|-----------|
138
- | <moltype_name> | <N_copies> | <atoms_per_copy> | <Linear/Cyclic/-> |
139
- | ... | ... | ... | ... |
140
- | **Total** | - | **<sum_atoms>** | - |
141
-
142
- **Key Information:**
143
- - **Total protein residues**: <X> (<Y> atoms total)
144
- - **Molecules are <independent/linked>** (bIntermolecularInteractions=<true/false>)
145
- - <Notable features>
146
-
147
- ### Populating the Template
148
-
149
- Use commands from:
150
- - **Key Information to Extract** table → Component, Count, Atoms columns
151
- - **Detecting Cyclic Molecule Configuration** → Structure column (Linear/Cyclic)
152
- - **Checking Molecule Independence** → bIntermolecularInteractions value
153
-
154
- ### Structure Column Values
155
-
156
- | Value | When to Use |
157
- |-------|-------------|
158
- | `Linear` | Standard protein/peptide without cyclization |
159
- | `**Cyclic** (bond 0→<N-2>)` | N-to-C cyclization detected |
160
- | `-` | Non-protein (solvent, ions, ligands) |
1
+ # Inspecting TPR Files for Molecule Information
2
+
3
+ ## Quick Summary
4
+
5
+ ```bash
6
+ gmx dump -s <tpr_file> 2>&1 | grep -A 5 "moltype"
7
+ ```
8
+
9
+ ## Detailed Breakdown
10
+
11
+ ```bash
12
+ # Full dump (verbose)
13
+ gmx dump -s <tpr_file>
14
+
15
+ # Extract molecule block info
16
+ gmx dump -s <tpr_file> 2>&1 | grep -E "(molblock|#molecules|moltype.*=)"
17
+ ```
18
+
19
+ **Output interpretation:**
20
+ ```
21
+ molblock (N):
22
+ moltype = M "MoleculeName" # Molecule type name
23
+ #molecules = X # Number of copies in system
24
+
25
+ moltype (M):
26
+ name="MoleculeName"
27
+ atoms:
28
+ atom (N): # N atoms in this molecule type
29
+ ```
30
+
31
+ **Note:** Atoms are 0-indexed. `atom (275):` means 276 atoms with indices 0-275.
32
+
33
+ ## Key Information to Extract
34
+
35
+ | Information | How to Find |
36
+ |-------------|-------------|
37
+ | Molecule type names | `grep 'moltype.*='` after `gmx dump` |
38
+ | Molecule counts | `grep '#molecules'` after `gmx dump` |
39
+ | Atoms per molecule type | Check `atom (N):` line under each `moltype` section |
40
+ | Solvent molecule count | Find SOL/Water moltype, read `#molecules` |
41
+ | Ion counts by type | Find NA, CL, etc. moltypes, read `#molecules` each |
42
+ | Protein molecule chains | Count moltypes with "Protein" or similar in name |
43
+
44
+ ## Detecting Cyclic Molecule Configuration
45
+
46
+ For protein chains, check if the molecule is cyclic (e.g., cyclic peptides) by examining bonds within the moltype.
47
+
48
+ **Detection strategy:**
49
+ 1. Get atom count for the moltype from `atom (N):` line (N atoms, indexed 0 to N-1)
50
+ 2. Search the Bond section for a bond between atom 0 and the C-terminal atom (typically atom N-2, which is the C atom before the terminal O)
51
+ 3. If such a bond exists, the molecule is cyclic
52
+
53
+ If no bond is found between atom 0 and the C-terminal atom, the molecule is linear (non-cyclic).
54
+
55
+ **Bond format in gmx dump:**
56
+ ```
57
+ Bond:
58
+ nr: <count>
59
+ iatoms:
60
+ 0 type=441 (BONDS) 0 2
61
+ 1 type=442 (BONDS) 0 273 <-- bond from atom 0 to atom 273
62
+ ```
63
+
64
+ **Example:** For a 275-atom cyclic peptide (atoms 0-274):
65
+ - Atom 0: N-terminal N
66
+ - Atom 273: C-terminal C (the backbone carbon)
67
+ - Atom 274: C-terminal O
68
+ - A bond `0 273` indicates the N-C cyclization
69
+
70
+ **Quick check for cyclic bond:**
71
+ ```bash
72
+ # Get atom count for a protein moltype
73
+ gmx dump -s <tpr_file> 2>&1 | grep -A 1 "atom (" | head -4
74
+
75
+ # Search for bonds involving atom 0 and the C-terminal atom (N-2)
76
+ # Replace <N-2> with actual value (e.g., 273 for 275-atom molecule)
77
+
78
+ # Standard pattern
79
+ gmx dump -s <tpr_file> 2>&1 | grep -E "BONDS.*0.*<N-2>"
80
+
81
+ # More robust pattern (explicit whitespace, works better on Windows)
82
+ gmx dump -s <tpr_file> 2>&1 | grep -E "BONDS\ +0 +<N-2>"
83
+ ```
84
+
85
+ **Example command for 275-atom molecule:**
86
+ ```bash
87
+ gmx dump -s <tpr_file> 2>&1 | grep -E "BONDS.*0.*273"
88
+ ```
89
+
90
+ #### Verifying the C-Terminal Atom
91
+
92
+ The C-terminal C atom is typically at index N-2, but this can vary by force field. Verify with:
93
+ ```bash
94
+ # Check atom type at index N-2 (e.g., 273 for 275-atom molecule)
95
+ gmx dump -s <tpr_file> 2>&1 | grep -A2 "atom (273):"
96
+ ```
97
+ Look for `type="C"` to confirm it's the backbone carbon.
98
+
99
+ #### Isolating Bonds for a Specific Moltype
100
+
101
+ When multiple moltypes exist, grep captures all bonds. To isolate one moltype's bonds:
102
+
103
+ **Method 1: sed range (Recommended)**
104
+ ```bash
105
+ # Extract bonds for moltype M (e.g., moltype 1)
106
+ gmx dump -s <tpr_file> 2>&1 | sed -n '/moltype (1)/,/moltype (2)/p' | grep -E "BONDS.*0.*273"
107
+ ```
108
+
109
+ **Method 2: grep with context**
110
+ ```bash
111
+ # Get bonds within 200 lines after moltype declaration
112
+ gmx dump -s <tpr_file> 2>&1 | grep -A200 "moltype (1)" | grep -E "BONDS.*0.*273"
113
+ ```
114
+ Replace moltype numbers and context lines as appropriate for your system.
115
+
116
+ ## Checking Molecule Independence
117
+
118
+ ```bash
119
+ gmx dump -s <tpr_file> 2>&1 | grep "bIntermolecularInteractions"
120
+ ```
121
+ - `false` = Molecules are independent (correct for most simulations)
122
+ - `true` = Bonded interactions exist between molecule types (unusual)
123
+
124
+ ## Quick System Overview
125
+
126
+ ```bash
127
+ echo "q" | gmx make_ndx -f <tpr_file> 2>&1 | grep -E "(System|Protein|Water|Ion|atoms)"
128
+ ```
129
+
130
+ ## Standardized TPR Summary Template
131
+
132
+ When users ask generic questions like "summarize this TPR" or "list all components", use this template for consistent output:
133
+
134
+ ### <tpr_file> Analysis Summary
135
+
136
+ | Component | Count | Atoms | Structure |
137
+ |-----------|-------|-------|-----------|
138
+ | <moltype_name> | <N_copies> | <atoms_per_copy> | <Linear/Cyclic/-> |
139
+ | ... | ... | ... | ... |
140
+ | **Total** | - | **<sum_atoms>** | - |
141
+
142
+ **Key Information:**
143
+ - **Total protein residues**: <X> (<Y> atoms total)
144
+ - **Molecules are <independent/linked>** (bIntermolecularInteractions=<true/false>)
145
+ - <Notable features>
146
+
147
+ ### Populating the Template
148
+
149
+ Use commands from:
150
+ - **Key Information to Extract** table → Component, Count, Atoms columns
151
+ - **Detecting Cyclic Molecule Configuration** → Structure column (Linear/Cyclic)
152
+ - **Checking Molecule Independence** → bIntermolecularInteractions value
153
+
154
+ ### Structure Column Values
155
+
156
+ | Value | When to Use |
157
+ |-------|-------------|
158
+ | `Linear` | Standard protein/peptide without cyclization |
159
+ | `**Cyclic** (bond 0→<N-2>)` | N-to-C cyclization detected |
160
+ | `-` | Non-protein (solvent, ions, ligands) |
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -3,3 +3,4 @@ export { calculator } from './calculator';
3
3
  export { jsonExtract } from './json-extract';
4
4
  export { jsonValidate } from './json-validate';
5
5
  export { jsonInfer } from './json-infer';
6
+ export { markdownToHtml } from './markdown-to-html';
@@ -3,3 +3,4 @@ export { calculator } from './calculator';
3
3
  export { jsonExtract } from './json-extract';
4
4
  export { jsonValidate } from './json-validate';
5
5
  export { jsonInfer } from './json-infer';
6
+ export { markdownToHtml } from './markdown-to-html';
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,19 @@
1
+ import { ToolContext } from '@opencode-ai/plugin/tool';
2
+ import { z } from 'zod';
3
+ export declare const markdownToHtml: {
4
+ description: string;
5
+ args: {
6
+ markdown: z.ZodOptional<z.ZodString>;
7
+ markdownPath: z.ZodOptional<z.ZodString>;
8
+ outputPath: z.ZodString;
9
+ title: z.ZodOptional<z.ZodString>;
10
+ css: z.ZodOptional<z.ZodString>;
11
+ };
12
+ execute(args: {
13
+ outputPath: string;
14
+ markdown?: string | undefined;
15
+ markdownPath?: string | undefined;
16
+ title?: string | undefined;
17
+ css?: string | undefined;
18
+ }, context: ToolContext): Promise<import("@opencode-ai/plugin").ToolResult>;
19
+ };
@@ -0,0 +1,109 @@
1
+ import { tool } from '@opencode-ai/plugin/tool';
2
+ import { z } from 'zod';
3
+ import { readFileSync, mkdirSync, existsSync, writeFileSync } from 'node:fs';
4
+ import { dirname, resolve, isAbsolute } from 'node:path';
5
+ import { MARKED_BUNDLE } from './marked-bundle';
6
+ const DEFAULT_CSS = `
7
+ body { max-width: 900px; margin: 2rem auto; padding: 0 1rem; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif; line-height: 1.6; color: #24292f; background: #ffffff; }
8
+ h1, h2, h3, h4, h5, h6 { margin-top: 1.5em; margin-bottom: 0.5em; font-weight: 600; line-height: 1.25; }
9
+ h1 { font-size: 2em; border-bottom: 1px solid #d0d7de; padding-bottom: 0.3em; }
10
+ h2 { font-size: 1.5em; border-bottom: 1px solid #d0d7de; padding-bottom: 0.3em; }
11
+ h3 { font-size: 1.25em; }
12
+ p { margin: 1em 0; }
13
+ a { color: #0969da; text-decoration: none; }
14
+ a:hover { text-decoration: underline; }
15
+ ul, ol { padding-left: 2em; margin: 1em 0; }
16
+ ul ul, ol ol, ul ol, ol ul { margin: 0; }
17
+ li { margin: 0.25em 0; }
18
+ blockquote { border-left: 4px solid #d0d7de; margin: 1em 0; padding: 0.5em 1em; color: #656d76; background: #f6f8fa; border-radius: 0 6px 6px 0; }
19
+ pre { background: #f6f8fa; padding: 1rem; border-radius: 6px; overflow-x: auto; border: 1px solid #d0d7de; }
20
+ code { background: #f6f8fa; padding: 0.2rem 0.4rem; border-radius: 3px; font-size: 85%; font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace; }
21
+ pre code { background: none; padding: 0; font-size: 100%; }
22
+ table { border-collapse: collapse; width: 100%; margin: 1em 0; }
23
+ th, td { border: 1px solid #d0d7de; padding: 0.5rem 0.75rem; text-align: left; }
24
+ th { background: #f6f8fa; font-weight: 600; }
25
+ tr:nth-child(even) { background: #f6f8fa; }
26
+ hr { border: none; border-top: 1px solid #d0d7de; margin: 2em 0; }
27
+ img { max-width: 100%; border-radius: 6px; }
28
+ `.trim();
29
+ function buildHtml(markdown, title, extraCss) {
30
+ const escapedMarkdown = JSON.stringify(markdown).replace(/<\//g, String.raw `<\/`);
31
+ const css = extraCss ? `${DEFAULT_CSS}\n${extraCss}` : DEFAULT_CSS;
32
+ const safeCss = css.replace(/<\/style/gi, String.raw `<\/style`);
33
+ return `<!DOCTYPE html>
34
+ <html lang="en">
35
+ <head>
36
+ <meta charset="utf-8"/>
37
+ <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
38
+ <title>${escapeHtml(title)}</title>
39
+ <style>${safeCss}</style>
40
+ </head>
41
+ <body>
42
+ <div id="content"></div>
43
+ <script>${MARKED_BUNDLE}</script>
44
+ <script>document.getElementById('content').innerHTML = marked.parse(${escapedMarkdown});</script>
45
+ </body>
46
+ </html>`;
47
+ }
48
+ function escapeHtml(str) {
49
+ return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
50
+ }
51
+ export const markdownToHtml = tool({
52
+ description: `Convert markdown to a standalone HTML file that can be opened in any browser. The generated HTML embeds marked.js fully — no internet access required. Accepts markdown as a string or from a file path. Raw HTML in markdown is rendered as-is; do not use with untrusted content.`,
53
+ args: {
54
+ markdown: z.string().optional()
55
+ .describe("Inline markdown content to render"),
56
+ markdownPath: z.string().optional()
57
+ .describe("Path to a markdown (.md) file to render"),
58
+ outputPath: z.string()
59
+ .describe("Output path for the generated HTML file"),
60
+ title: z.string().optional()
61
+ .describe("HTML page title (default: 'Markdown Document')"),
62
+ css: z.string().optional()
63
+ .describe("Additional CSS to embed in the HTML (appended after default styles)"),
64
+ },
65
+ execute: async (args, context) => {
66
+ await context.ask({ permission: "markdownToHtml", patterns: ["*"], always: ["*"], metadata: {} });
67
+ if (!args.markdown && !args.markdownPath) {
68
+ return "Error: exactly one of 'markdown' or 'markdownPath' must be provided";
69
+ }
70
+ if (args.markdown && args.markdownPath) {
71
+ return "Error: provide either 'markdown' or 'markdownPath', not both";
72
+ }
73
+ let markdown;
74
+ if (args.markdownPath) {
75
+ const mdPath = isAbsolute(args.markdownPath)
76
+ ? args.markdownPath
77
+ : resolve(context.directory, args.markdownPath);
78
+ if (!existsSync(mdPath)) {
79
+ return `Error: markdown file not found: ${mdPath}`;
80
+ }
81
+ try {
82
+ markdown = readFileSync(mdPath, 'utf-8');
83
+ }
84
+ catch (e) {
85
+ return `Error: failed to read markdown file: ${e instanceof Error ? e.message : String(e)}`;
86
+ }
87
+ }
88
+ else {
89
+ markdown = args.markdown;
90
+ }
91
+ const html = buildHtml(markdown, args.title ?? "Markdown Document", args.css);
92
+ const outPath = isAbsolute(args.outputPath)
93
+ ? args.outputPath
94
+ : resolve(context.directory, args.outputPath);
95
+ try {
96
+ mkdirSync(dirname(outPath), { recursive: true });
97
+ }
98
+ catch (e) {
99
+ return `Error: failed to create output directory: ${e instanceof Error ? e.message : String(e)}`;
100
+ }
101
+ try {
102
+ writeFileSync(outPath, html, 'utf-8');
103
+ }
104
+ catch (e) {
105
+ return `Error: failed to write HTML file: ${e instanceof Error ? e.message : String(e)}`;
106
+ }
107
+ return `HTML file written to: ${outPath}`;
108
+ }
109
+ });