@yeyuan98/opencode-bioresearcher-plugin 1.3.0 → 1.3.1-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.
package/README.md CHANGED
@@ -1,137 +1,140 @@
1
- # BioResearcher Plugin
2
-
3
- OpenCode plugin that adds agents and tools for biomedical and pharmaceutical research.
4
-
5
- ## Overview
6
-
7
- No nonsense and powerful. Agents and tools that just work for your typical biomedical and pharmaceutical research needs.
8
-
9
- Tab to activate and start asking right away:
10
-
11
- - The **Bioresearcher Agent** is jack-of-all-trades.
12
- - The **BioresearcherDR Agent** is a specialist for biomed/pharma deep research (DR).
13
-
14
- ## Agents
15
-
16
- ### BioresearcherDR
17
-
18
- By default, it will conduct **highly detailed and in-depth** research, easily surpassing all general purpose LLM applications.
19
-
20
- To reduce research depth and make research process faster, start your question with `light-research`:
21
-
22
- ```text
23
- light-research Significance of KRAS for cancer?
24
- ```
25
-
26
- To skip the Question-Clarification cycle, prompt your question with `no-interview`:
27
-
28
- ```text
29
- no-interview light-research Significance of KRAS for cancer?
30
- ```
31
-
32
- ## Tools
33
-
34
- ### Table Tools
35
-
36
- Manipulate Excel, CSV, and ODS files with precision and smart parsing for dates, numbers, and data types.
37
-
38
- **Enable LLMs to wrangle huge tables WITHOUT overwhelming model context.**
39
-
40
- ```text
41
- What are tools for table processing?
42
- What are column names in XXX.xlsx?
43
- Analyze XXX.xlsx - group by Y column, and report unique values of Z column.
44
- ```
45
-
46
- ### Calculator
47
-
48
- Evaluate mathematical expressions with full support for brackets, powers, and scientific notation.
49
-
50
- **Make your model accurate with numbers. No more 3.11 > 3.9 nor 1+2=5.**
51
-
52
- ```text
53
- Use the calculator tool: (3+1.5*6-1/2)^3
54
- ```
55
-
56
- ### Blocking Timer
57
-
58
- Pause execution for testing or pacing operations.
59
-
60
- **Respect API rate limits. No more IP bans/blocks.**
61
-
62
- ```text
63
- Query XXX API. You MUST include a 0.5 second delay between two API calls with the blockingTimer tool.
64
- ```
65
-
66
- ### PubMed Parser
67
-
68
- Parse PubMed XML files to markdown or Excel format. Supports `.xml` and `.xml.gz` files.
69
-
70
- **Analyze years of publication articles in one go. Simple and powerful.**
71
-
72
- ```text
73
- Download pubmed article data from https://ftp.ncbi.nlm.nih.gov/pubmed/updatefiles/pubmed26n1340.xml.gz and parse to Excel format.
74
- ```
75
-
76
- Reference: [PubMed Download Data](https://pubmed.ncbi.nlm.nih.gov/download/).
77
-
78
- ## Skills
79
-
80
- Skills are reusable prompt templates discovered from multiple paths:
81
-
82
- | Path | Scope |
83
- |------|-------|
84
- | `.opencode/skills/` | Project |
85
- | `~/.config/opencode/skills/` | Global |
86
- | `.claude/skills/` | Claude Code compatible |
87
- | `.agents/skills/` | Agents compatible |
88
-
89
- This plugin provides a skill tool that overrides Opencode's built-in to support plugin-shipped skills.
90
-
91
- See [skill-tools/README.md](skill-tools/README.md) for full documentation.
92
-
93
- ### Supplied skills
94
-
95
- - `demo-skill`: showcase skill tool mechanisms.
96
- - `python-setup-uv`: setup python runtime in your working directory with uv.
97
-
98
- Prompt the following and follow along:
99
-
100
- ```txt
101
- Setup python uv with skill
102
- ```
103
-
104
- ## Installation
105
-
106
- Add the plugin to your `opencode.json`:
107
-
108
- ```json
109
- {
110
- "$schema": "https://opencode.ai/config.json",
111
- "plugin": [
112
- "@yeyuan98/opencode-bioresearcher-plugin",
113
- ],
114
- "mcp": {
115
- "biomcp": {
116
- "type": "local",
117
- "command": ["uv", "run", "--with", "biomcp-python", "biomcp", "run"],
118
- "enabled": true,
119
- "timeout": 120000
120
- }
121
- }
122
- }
123
- ```
124
-
125
- BioMCP is absolutely required and might take time to load. You will need to have `uv` installed on your system too. Refer to [BioMCP guide](https://biomcp.org/getting-started) for details.
126
-
127
- ## Common Issues and Solutions
128
-
129
- | Issue | Solution |
130
- |-------|----------|
131
- | Agent not appearing | Check plugin in opencode.json is typed correctly |
132
- | BioMCP tool failures | Make sure you have BioMCP [installed and enabled](https://opencode.ai/docs/mcp-servers/#enable) |
133
- | Research taking a long time | Check whether subagents are generating outputs; could be slow model / API throttle / overcomplicated query / etc. |
134
-
135
- ## License
136
-
137
- CC BY-NC-ND 4.0
1
+ # BioResearcher Plugin
2
+
3
+ ![NPM Downloads](https://img.shields.io/npm/dm/%40yeyuan98%2Fopencode-bioresearcher-plugin)
4
+
5
+ OpenCode plugin that adds agents and tools for biomedical and pharmaceutical research.
6
+
7
+ ## Overview
8
+
9
+ No nonsense and powerful. Agents and tools that just work for your typical biomedical and pharmaceutical research needs.
10
+
11
+ Tab to activate and start asking right away:
12
+
13
+ - The **Bioresearcher Agent** is jack-of-all-trades.
14
+ - The **BioresearcherDR Agent** is a specialist for biomed/pharma deep research (DR).
15
+
16
+ ## Agents
17
+
18
+ ### BioresearcherDR
19
+
20
+ By default, it will conduct **highly detailed and in-depth** research, easily surpassing all general purpose LLM applications.
21
+
22
+ To reduce research depth and make research process faster, start your question with `light-research`:
23
+
24
+ ```text
25
+ light-research Significance of KRAS for cancer?
26
+ ```
27
+
28
+ To skip the Question-Clarification cycle, prompt your question with `no-interview`:
29
+
30
+ ```text
31
+ no-interview light-research Significance of KRAS for cancer?
32
+ ```
33
+
34
+ ## Tools
35
+
36
+ ### Table Tools
37
+
38
+ Manipulate Excel, CSV, and ODS files with precision and smart parsing for dates, numbers, and data types.
39
+
40
+ **Enable LLMs to wrangle huge tables WITHOUT overwhelming model context.**
41
+
42
+ ```text
43
+ What are tools for table processing?
44
+ What are column names in XXX.xlsx?
45
+ Analyze XXX.xlsx - group by Y column, and report unique values of Z column.
46
+ ```
47
+
48
+ ### Calculator
49
+
50
+ Evaluate mathematical expressions with full support for brackets, powers, and scientific notation.
51
+
52
+ **Make your model accurate with numbers. No more 3.11 > 3.9 nor 1+2=5.**
53
+
54
+ ```text
55
+ Use the calculator tool: (3+1.5*6-1/2)^3
56
+ ```
57
+
58
+ ### Blocking Timer
59
+
60
+ Pause execution for testing or pacing operations.
61
+
62
+ **Respect API rate limits. No more IP bans/blocks.**
63
+
64
+ ```text
65
+ Query XXX API. You MUST include a 0.5 second delay between two API calls with the blockingTimer tool.
66
+ ```
67
+
68
+ ### PubMed Parser
69
+
70
+ Parse PubMed XML files to markdown or Excel format. Supports `.xml` and `.xml.gz` files.
71
+
72
+ **Analyze years of publication articles in one go. Simple and powerful.**
73
+
74
+ ```text
75
+ Download pubmed article data from https://ftp.ncbi.nlm.nih.gov/pubmed/updatefiles/pubmed26n1340.xml.gz and parse to Excel format.
76
+ ```
77
+
78
+ Reference: [PubMed Download Data](https://pubmed.ncbi.nlm.nih.gov/download/).
79
+
80
+ ## Skills
81
+
82
+ Skills are reusable prompt templates discovered from multiple paths:
83
+
84
+ | Path | Scope |
85
+ |------|-------|
86
+ | `.opencode/skills/` | Project |
87
+ | `~/.config/opencode/skills/` | Global |
88
+ | `.claude/skills/` | Claude Code compatible |
89
+ | `.agents/skills/` | Agents compatible |
90
+
91
+ This plugin provides a skill tool that overrides Opencode's built-in to support plugin-shipped skills.
92
+
93
+ See [skill-tools/README.md](skill-tools/README.md) for full documentation.
94
+
95
+ ### Supplied skills
96
+
97
+ - `demo-skill`: showcase skill tool mechanisms.
98
+ - `python-setup-uv`: setup python runtime in your working directory with uv.
99
+ - `pubmed-weekly`: automated download of pubmed daily update files over the past one week.
100
+
101
+ Prompt the following and follow along:
102
+
103
+ ```txt
104
+ Setup python uv with skill
105
+ ```
106
+
107
+ ## Installation
108
+
109
+ Add the plugin to your `opencode.json`:
110
+
111
+ ```json
112
+ {
113
+ "$schema": "https://opencode.ai/config.json",
114
+ "plugin": [
115
+ "@yeyuan98/opencode-bioresearcher-plugin",
116
+ ],
117
+ "mcp": {
118
+ "biomcp": {
119
+ "type": "local",
120
+ "command": ["uv", "run", "--with", "biomcp-python", "biomcp", "run"],
121
+ "enabled": true,
122
+ "timeout": 120000
123
+ }
124
+ }
125
+ }
126
+ ```
127
+
128
+ BioMCP is absolutely required and might take time to load. You will need to have `uv` installed on your system too. Refer to [BioMCP guide](https://biomcp.org/getting-started) for details.
129
+
130
+ ## Common Issues and Solutions
131
+
132
+ | Issue | Solution |
133
+ |-------|----------|
134
+ | Agent not appearing | Check plugin in opencode.json is typed correctly |
135
+ | BioMCP tool failures | Make sure you have BioMCP [installed and enabled](https://opencode.ai/docs/mcp-servers/#enable) |
136
+ | Research taking a long time | Check whether subagents are generating outputs; could be slow model / API throttle / overcomplicated query / etc. |
137
+
138
+ ## License
139
+
140
+ CC BY-NC-ND 4.0
@@ -1,41 +1,41 @@
1
- ---
2
- name: demo-skill
3
- description: Demo skill showcasing the plugin skill integration system
4
- allowedTools:
5
- - Bash
6
- - Read
7
- ---
8
-
9
- # Demo Skill
10
-
11
- This skill demonstrates the plugin skill integration system.
12
-
13
- ## Features Demonstrated
14
-
15
- 1. **Skill Discovery** - This skill is discovered from `plugin/skills/`
16
- 2. **allowedTools** - Listed above (documentation only)
17
- 3. **Bundled Resources** - Files in this directory are accessible
18
-
19
- ## Test Resource Resolution
20
-
21
- Run the bundled script to verify resources are properly resolved:
22
-
23
- ```bash
24
- python demo_script.py
25
- ```
26
-
27
- Expected output:
28
- ```
29
- Demo Skill - Resource Resolution Test
30
- =====================================
31
- Skill directory: <path to skill>
32
- Status: Resources resolved correctly!
33
- ```
34
-
35
- ## How It Works
36
-
37
- 1. Plugin builds with `npm run build`
38
- 2. `skills/` directory copied to `dist/skills/`
39
- 3. Skill tool discovers all `SKILL.md` files
40
- 4. Agent calls `skill` tool with skill name
41
- 5. Skill content + file list returned to agent
1
+ ---
2
+ name: demo-skill
3
+ description: Demo skill showcasing the plugin skill integration system
4
+ allowedTools:
5
+ - Bash
6
+ - Read
7
+ ---
8
+
9
+ # Demo Skill
10
+
11
+ This skill demonstrates the plugin skill integration system.
12
+
13
+ ## Features Demonstrated
14
+
15
+ 1. **Skill Discovery** - This skill is discovered from `plugin/skills/`
16
+ 2. **allowedTools** - Listed above (documentation only)
17
+ 3. **Bundled Resources** - Files in this directory are accessible
18
+
19
+ ## Test Resource Resolution
20
+
21
+ Run the bundled script to verify resources are properly resolved:
22
+
23
+ ```bash
24
+ python demo_script.py
25
+ ```
26
+
27
+ Expected output:
28
+ ```
29
+ Demo Skill - Resource Resolution Test
30
+ =====================================
31
+ Skill directory: <path to skill>
32
+ Status: Resources resolved correctly!
33
+ ```
34
+
35
+ ## How It Works
36
+
37
+ 1. Plugin builds with `npm run build`
38
+ 2. `skills/` directory copied to `dist/skills/`
39
+ 3. Skill tool discovers all `SKILL.md` files
40
+ 4. Agent calls `skill` tool with skill name
41
+ 5. Skill content + file list returned to agent
@@ -1,23 +1,23 @@
1
- #!/usr/bin/env python
2
- """Demo script to verify skill resource resolution."""
3
-
4
- import os
5
- import sys
6
-
7
-
8
- def main():
9
- print("Demo Skill - Resource Resolution Test")
10
- print("=" * 40)
11
- print(f"Script location: {os.path.abspath(__file__)}")
12
- print(f"Python version: {sys.version.split()[0]}")
13
- print()
14
- print("Status: Resources resolved correctly!")
15
- print()
16
- print("This confirms:")
17
- print(" - Skill files bundled at build time")
18
- print(" - Resources discoverable via skill tool")
19
- print(" - Scripts executable from skill directory")
20
-
21
-
22
- if __name__ == "__main__":
23
- main()
1
+ #!/usr/bin/env python
2
+ """Demo script to verify skill resource resolution."""
3
+
4
+ import os
5
+ import sys
6
+
7
+
8
+ def main():
9
+ print("Demo Skill - Resource Resolution Test")
10
+ print("=" * 40)
11
+ print(f"Script location: {os.path.abspath(__file__)}")
12
+ print(f"Python version: {sys.version.split()[0]}")
13
+ print()
14
+ print("Status: Resources resolved correctly!")
15
+ print()
16
+ print("This confirms:")
17
+ print(" - Skill files bundled at build time")
18
+ print(" - Resources discoverable via skill tool")
19
+ print(" - Scripts executable from skill directory")
20
+
21
+
22
+ if __name__ == "__main__":
23
+ main()
@@ -0,0 +1,260 @@
1
+ ---
2
+ name: pubmed-weekly
3
+ description: Download PubMed daily update xml.gz files from the past week from NCBI FTP server
4
+ allowedTools:
5
+ - Bash
6
+ - Read
7
+ - Write
8
+ - Question
9
+ ---
10
+
11
+ # PubMed Weekly Daily Updates Download
12
+
13
+ This skill downloads PubMed daily update xml.gz files from the past week (Monday-Sunday).
14
+
15
+ ## Workflow Overview
16
+
17
+ 1. **Python Environment Setup** (automatic): Checks for uv, installs via `python-setup-uv` skill if needed
18
+ 2. **Date Calculation**: Calculates the past week's date range (Monday-Sunday)
19
+ 3. **FTP Listing**: Fetches available xml.gz files from NCBI FTP server
20
+ 4. **Filtering**: Filters files to include only those from the past week
21
+ 5. **Download**: Downloads filtered files with retry logic (max 3 attempts per file)
22
+
23
+ ## Prerequisites
24
+ - Internet connection
25
+ - Access to NCBI FTP server
26
+ - uv package manager (will be automatically installed if not present)
27
+
28
+ ## Integration with python-setup-uv
29
+
30
+ This skill integrates with the `python-setup-uv` skill to ensure Python environment is properly configured.
31
+
32
+ ### Prerequisite Check
33
+
34
+ Before starting the download process:
35
+
36
+ 1. **Check if uv is installed:**
37
+ ```bash
38
+ if [ -f "uv" ] || [ -f "uv.exe" ]; then
39
+ echo "uv already installed"
40
+ else
41
+ echo "uv not found, setting up..."
42
+ fi
43
+ ```
44
+
45
+ 2. **If uv is not installed:**
46
+ - Load the `python-setup-uv` skill using the skill tool
47
+ - Follow all steps EXACTLY as specified in the python-setup-uv skill
48
+ - Wait for uv installation to complete
49
+ - Continue with this skill's Step 1 below
50
+
51
+ 3. **After uv is installed:**
52
+ - All Python commands in this skill will use the bash tool with `workdir` parameter
53
+ - Use `./uv run python` (Unix-like) or `uv.exe run python` (Windows cmd.exe)
54
+ - The bundled script `pubmed_weekly.py` will be executed using uv
55
+
56
+ ## Path Resolution Strategy
57
+
58
+ This skill uses the bash tool's `workdir` parameter to handle portable script execution:
59
+
60
+ 1. **Extract skill directory path** from `<skill_files>` section in skill tool output
61
+ - Example: `<file>C:\Users\...\plugin\skills\pubmed-weekly\pubmed_weekly.py</file>`
62
+ - Extract directory: `C:\Users\...\plugin\skills\pubmed-weekly\`
63
+
64
+ 2. **Get current working directory** using the bash tool
65
+ ```bash
66
+ WORKING_DIR=$(pwd) # Unix-like
67
+ # or use the default working directory from bash tool
68
+ ```
69
+
70
+ 3. **Use bash tool with workdir** to run Python scripts from skill directory
71
+ ```bash
72
+ # bash tool will handle the workdir parameter
73
+ # Python's os.getcwd() will give skill directory
74
+ # Downloads go to working directory via --working-dir argument
75
+ ```
76
+
77
+ ## Steps
78
+
79
+ Follow these steps EXACTLY as described.
80
+
81
+ ### Step 1: Calculate Week Date Range
82
+
83
+ First, determine the date range for the past week (Monday through Sunday).
84
+
85
+ Use the bash tool with:
86
+ - `workdir` set to the skill directory (extracted from `<skill_files>`)
87
+ - `command` to run the Python script
88
+
89
+ **For Unix-like shells (Git Bash / macOS / Linux):**
90
+ ```bash
91
+ ./uv run python pubmed_weekly.py calculate_week --working-dir="$(pwd)"
92
+ ```
93
+
94
+ **For Windows cmd.exe:**
95
+ ```bash
96
+ uv.exe run python pubmed_weekly.py calculate_week --working-dir="%CD%"
97
+ ```
98
+
99
+ This will output the week folder name in format `YYYYMMDD-YYYYMMDD`.
100
+
101
+ **Expected output format:**
102
+ ```
103
+ 20250217-20250223
104
+ ```
105
+
106
+ ### Step 2: Create Download Directory
107
+
108
+ Create the directory structure for the week in the working directory:
109
+
110
+ ```bash
111
+ mkdir -p .download/pubmed-daily/<WEEK>
112
+ ```
113
+
114
+ Replace `<WEEK>` with the actual week folder name from Step 1.
115
+
116
+ ### Step 3: Fetch FTP File List
117
+
118
+ Use the bash tool with `workdir` set to the skill directory to fetch the list of files from the NCBI FTP server:
119
+
120
+ **For Unix-like shells:**
121
+ ```bash
122
+ ./uv run python pubmed_weekly.py fetch_files --working-dir="$(pwd)"
123
+ ```
124
+
125
+ **For Windows cmd.exe:**
126
+ ```bash
127
+ uv.exe run python pubmed_weekly.py fetch_files --working-dir="%CD%"
128
+ ```
129
+
130
+ This will list all daily update xml.gz files available on the FTP server.
131
+
132
+ **Expected output:**
133
+ ```
134
+ pubmed24n1234.xml.gz pubmed24n1235.xml.gz pubmed24n1236.xml.gz
135
+ ```
136
+
137
+ ### Step 4: Filter Files for Past Week
138
+
139
+ Use the bash tool with `workdir` set to the skill directory to filter the file list for the past week's daily updates:
140
+
141
+ **For Unix-like shells:**
142
+ ```bash
143
+ ./uv run python pubmed_weekly.py filter_files "<WEEK>" "<FILE_LIST>" --working-dir="$(pwd)"
144
+ ```
145
+
146
+ **For Windows cmd.exe:**
147
+ ```bash
148
+ uv.exe run python pubmed_weekly.py filter_files "<WEEK>" "<FILE_LIST>" --working-dir="%CD%"
149
+ ```
150
+
151
+ Where:
152
+ - `<WEEK>` is the week folder name (e.g., `20250217-20250223`)
153
+ - `<FILE_LIST>` is the output from Step 3 (space-separated filenames, use quotes)
154
+
155
+ This will return a space-separated list of xml.gz files from the past week.
156
+
157
+ **Expected output:**
158
+ ```
159
+ pubmed24n1234.xml.gz pubmed24n1235.xml.gz pubmed24n1236.xml.gz
160
+ ```
161
+
162
+ ### Step 5: Download Files with Retry
163
+
164
+ For each file in the filtered list, download to the target directory with retry logic:
165
+
166
+ **For Unix-like shells:**
167
+ ```bash
168
+ for file in <FILE_LIST>; do
169
+ ./uv run python pubmed_weekly.py download_file <WEEK> $file --working-dir="$(pwd)"
170
+ done
171
+ ```
172
+
173
+ **For Windows cmd.exe:**
174
+ ```bash
175
+ for %f in (<FILE_LIST>) do uv.exe run python pubmed_weekly.py download_file <WEEK> %f --working-dir="%CD%"
176
+ ```
177
+
178
+ Replace `<FILE_LIST>` with the space-separated list from Step 4.
179
+
180
+ **Download behavior:**
181
+ - Downloads one file at a time
182
+ - Retries up to 3 times if download fails
183
+ - Waits 2 seconds between retry attempts
184
+ - After 3 failed attempts, asks user whether to abort
185
+
186
+ **If a download fails after 3 retries:**
187
+ Use the question tool to ask:
188
+ - "Abort remaining downloads?" (options: "Yes" / "No")
189
+
190
+ If user selects "Yes", stop the process and report summary.
191
+ If user selects "No", skip the failed file and continue with the next one.
192
+
193
+ ### Step 6: Verify Downloads
194
+
195
+ After all downloads complete (or are aborted), verify the downloaded files:
196
+
197
+ ```bash
198
+ ls -lh .download/pubmed-daily/<WEEK>/
199
+ ```
200
+
201
+ Count the number of files downloaded and report the summary to the user.
202
+
203
+ ## Python Script Details
204
+
205
+ The skill includes a bundled Python script at `pubmed_weekly.py` with the following functions:
206
+
207
+ ### 1. `calculate_week()` - Calculate week date range
208
+
209
+ Returns week folder name in format `YYYYMMDD-YYYYMMDD` for the past week (Monday-Sunday).
210
+
211
+ ### 2. `fetch_files()` - Fetch FTP file list
212
+
213
+ Returns list of all xml.gz filenames from NCBI FTP server.
214
+
215
+ ### 3. `filter_files(week_name, file_list)` - Filter files for the week
216
+
217
+ Parameters:
218
+ - `week_name`: Week folder name (e.g., `20250217-20250223`)
219
+ - `file_list`: List of filenames from FTP server
220
+
221
+ Returns: Space-separated list of xml.gz files that fall within the date range.
222
+
223
+ ### 4. `download_file(week_name, filename)` - Download single file with retry
224
+
225
+ Parameters:
226
+ - `week_name`: Week folder name
227
+ - `filename`: XML.gz filename to download
228
+
229
+ Behavior:
230
+ - Downloads from `ftp://ftp.ncbi.nlm.nih.gov/pubmed/updatefiles/<filename>`
231
+ - Saves to `<working_dir>/.download/pubmed-daily/<week_name>/<filename>`
232
+ - Uses `--working-dir` argument if provided, otherwise uses current directory
233
+ - Retries up to 3 times on failure
234
+ - Returns exit code 0 on success, 1 on failure (after all retries)
235
+
236
+ ## Output Summary
237
+
238
+ After completion, provide the user with:
239
+
240
+ 1. Week date range processed
241
+ 2. Number of files found for the week
242
+ 3. Number of files successfully downloaded
243
+ 4. Number of files failed to download (if any)
244
+ 5. Download location: `.download/pubmed-daily/<WEEK>/`
245
+
246
+ ## Notes
247
+
248
+ - This skill automatically checks for and installs uv using the `python-setup-uv` skill if not present
249
+ - The Python script is bundled with this skill at `pubmed_weekly.py`
250
+ - All Python commands use the bash tool's `workdir` parameter to run from skill directory
251
+ - The `--working-dir` argument ensures downloads go to the user's working directory
252
+ - The FTP server path is: `ftp://ftp.ncbi.nlm.nih.gov/pubmed/updatefiles/`
253
+ - Only `.xml.gz` files are downloaded
254
+ - Downloads are sequential (one file at a time)
255
+ - Retry logic includes 2-second delays between attempts
256
+ - User has control to abort on persistent failures
257
+ - The script uses Python's built-in `urllib.request` for FTP operations - no additional Python package dependencies required
258
+ - Skill directory path is extracted from `<skill_files>` section for portability
259
+ - Windows with Git Bash: Follow Unix-like shell instructions
260
+ - Windows cmd.exe: Use `uv.exe run python` syntax and `%CD%` for working directory
@@ -0,0 +1,293 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ PubMed Weekly Daily Updates Downloader
4
+
5
+ This script handles:
6
+ - Calculating the past week's date range (Monday-Sunday)
7
+ - Fetching FTP file list from NCBI
8
+ - Filtering files for the specific week
9
+ - Downloading files with retry logic
10
+ """
11
+
12
+ import os
13
+ import sys
14
+ import re
15
+ import time
16
+ import urllib.request
17
+ import argparse
18
+ from datetime import datetime, timedelta
19
+ from typing import List, Tuple
20
+
21
+ # Global working directory for downloads (set via --working-dir argument)
22
+ WORKING_DIR = None
23
+
24
+
25
+ def calculate_week() -> str:
26
+ """Calculate the past week's date range (Monday-Sunday).
27
+
28
+ Returns:
29
+ Week folder name in format 'YYYYMMDD-YYYYMMDD' for the PREVIOUS week
30
+ """
31
+ today = datetime.now()
32
+
33
+ # Find the most recent Monday of the current week
34
+ days_since_monday = today.weekday() # Monday = 0, Sunday = 6
35
+ current_monday = today - timedelta(days=days_since_monday)
36
+
37
+ # Go back one week to get the previous week's Monday
38
+ previous_week_monday = current_monday - timedelta(days=7)
39
+
40
+ # Calculate the previous week's Sunday (6 days after Monday)
41
+ previous_week_sunday = previous_week_monday + timedelta(days=6)
42
+
43
+ week_start = previous_week_monday.strftime("%Y%m%d")
44
+ week_end = previous_week_sunday.strftime("%Y%m%d")
45
+
46
+ return f"{week_start}-{week_end}"
47
+
48
+
49
+ def parse_date_from_filename(filename: str) -> datetime | None:
50
+ """Extract date from PubMed filename.
51
+
52
+ PubMed filenames are in format: pubmed24nYYYYMMDD.xml.gz
53
+ The date is embedded in the number following 'n'
54
+
55
+ Args:
56
+ filename: PubMed filename (e.g., pubmed24n1234.xml.gz)
57
+
58
+ Returns:
59
+ datetime object or None if date cannot be parsed
60
+ """
61
+ # Pattern to extract the numeric part after 'n'
62
+ match = re.match(r"pubmed\d+n(\d+)\.xml\.gz", filename)
63
+ if not match:
64
+ return None
65
+
66
+ number = match.group(1)
67
+
68
+ # PubMed daily update files use a specific numbering scheme
69
+ # The first 4 digits represent the year (e.g., 2024)
70
+ # The next 4 digits represent a sequential number within the year
71
+ # We need to convert this to a date
72
+
73
+ # For daily updates, NCBI uses a sequential number that increments daily
74
+ # We need to look up the actual date from the FTP directory listing
75
+ # which includes modification time
76
+
77
+ return None
78
+
79
+ number = match.group(1)
80
+
81
+ # PubMed daily update files use a specific numbering scheme
82
+ # The first 4 digits represent the year (e.g., 2024)
83
+ # The next 4 digits represent a sequential number within the year
84
+ # We need to convert this to a date
85
+
86
+ # For daily updates, NCBI uses a sequential number that increments daily
87
+ # We need to look up the actual date from the FTP directory listing
88
+ # which includes modification time
89
+
90
+ return None
91
+
92
+
93
+ def fetch_ftp_file_list() -> List[str]:
94
+ """Fetch list of xml.gz files from NCBI FTP server.
95
+
96
+ Returns:
97
+ List of xml.gz filenames from the FTP server
98
+ """
99
+ url = "ftp://ftp.ncbi.nlm.nih.gov/pubmed/updatefiles/"
100
+
101
+ try:
102
+ with urllib.request.urlopen(url) as response:
103
+ html_content = response.read().decode("utf-8")
104
+
105
+ # Parse HTML to extract filenames
106
+ # FTP directory listing returns HTML with links
107
+ filenames = []
108
+ for line in html_content.split("\n"):
109
+ match = re.search(r"pubmed\d+n\d+\.xml\.gz", line)
110
+ if match:
111
+ filename = match.group(0)
112
+ if filename not in filenames:
113
+ filenames.append(filename)
114
+
115
+ return sorted(filenames)
116
+
117
+ except Exception as e:
118
+ print(f"Error fetching FTP file list: {e}", file=sys.stderr)
119
+ sys.exit(1)
120
+
121
+
122
+ def filter_files_by_date(week_name: str, file_list: List[str]) -> List[str]:
123
+ """Filter files to include only those from the past week.
124
+
125
+ Since PubMed files don't encode the date directly in the filename,
126
+ we need to download the directory listing with timestamps and filter
127
+ based on modification date.
128
+
129
+ Args:
130
+ week_name: Week folder name (YYYYMMDD-YYYYMMDD)
131
+ file_list: List of all xml.gz filenames
132
+
133
+ Returns:
134
+ List of filenames that fall within the date range
135
+ """
136
+ # Parse week dates
137
+ start_date_str, end_date_str = week_name.split("-")
138
+ start_date = datetime.strptime(start_date_str, "%Y%m%d")
139
+ end_date = datetime.strptime(end_date_str, "%Y%m%d").replace(
140
+ hour=23, minute=59, second=59
141
+ )
142
+
143
+ # Fetch directory listing with timestamps
144
+ url = "ftp://ftp.ncbi.nlm.nih.gov/pubmed/updatefiles/"
145
+
146
+ try:
147
+ with urllib.request.urlopen(url) as response:
148
+ content = response.read().decode("utf-8", errors="ignore")
149
+
150
+ # Parse file listings with dates
151
+ # NCBI FTP format uses ISO date: "2026-01-30 14:02"
152
+ file_dates = {}
153
+
154
+ for filename in file_list:
155
+ # Find the line containing this file
156
+ # Pattern: filename followed by non-digits, then date YYYY-MM-DD HH:MM
157
+ pattern = re.escape(filename)
158
+ match = re.search(
159
+ rf"({pattern})[^0-9]*(\d{{4}}-\d{{2}}-\d{{2}})\s+(\d{{2}}:\d{{2}})",
160
+ content,
161
+ )
162
+
163
+ if match:
164
+ date_str = match.group(2)
165
+ time_str = match.group(3)
166
+ try:
167
+ # Parse date in ISO format: "2026-01-30 14:02"
168
+ file_date = datetime.strptime(
169
+ f"{date_str} {time_str}", "%Y-%m-%d %H:%M"
170
+ )
171
+
172
+ file_dates[filename] = file_date
173
+ except ValueError:
174
+ continue
175
+
176
+ # Filter files within date range
177
+ filtered_files = [
178
+ filename
179
+ for filename, file_date in file_dates.items()
180
+ if start_date <= file_date <= end_date
181
+ ]
182
+
183
+ return sorted(filtered_files)
184
+
185
+ except Exception as e:
186
+ print(f"Error filtering files by date: {e}", file=sys.stderr)
187
+ sys.exit(1)
188
+
189
+
190
+ def download_file(week_name: str, filename: str, max_retries: int = 3) -> int:
191
+ """Download a single file from NCBI FTP server with retry logic.
192
+
193
+ Args:
194
+ week_name: Week folder name
195
+ filename: XML.gz filename to download
196
+ max_retries: Maximum number of retry attempts
197
+
198
+ Returns:
199
+ 0 on success, 1 on failure (after all retries)
200
+ """
201
+ base_url = "ftp://ftp.ncbi.nlm.nih.gov/pubmed/updatefiles/"
202
+ url = f"{base_url}{filename}"
203
+
204
+ # Create download directory - use WORKING_DIR if set, otherwise current directory
205
+ base_dir = WORKING_DIR if WORKING_DIR else os.getcwd()
206
+ download_dir = os.path.join(base_dir, ".download", "pubmed-daily", week_name)
207
+ os.makedirs(download_dir, exist_ok=True)
208
+
209
+ filepath = os.path.join(download_dir, filename)
210
+
211
+ for attempt in range(max_retries):
212
+ try:
213
+ print(f"Downloading {filename} (attempt {attempt + 1}/{max_retries})...")
214
+
215
+ urllib.request.urlretrieve(url, filepath)
216
+
217
+ # Verify file was downloaded and has content
218
+ if os.path.exists(filepath) and os.path.getsize(filepath) > 0:
219
+ print(f"Successfully downloaded {filename}")
220
+ return 0
221
+ else:
222
+ raise Exception("Downloaded file is empty or missing")
223
+
224
+ except Exception as e:
225
+ print(f"Error downloading {filename}: {e}", file=sys.stderr)
226
+
227
+ if attempt < max_retries - 1:
228
+ print(f"Retrying in 2 seconds...")
229
+ time.sleep(2)
230
+ else:
231
+ print(f"Failed to download {filename} after {max_retries} attempts")
232
+ return 1
233
+
234
+ return 1
235
+
236
+
237
+ def main():
238
+ """Main entry point for command-line usage."""
239
+ parser = argparse.ArgumentParser(
240
+ description="PubMed Weekly Daily Updates Downloader"
241
+ )
242
+ parser.add_argument(
243
+ "--working-dir",
244
+ type=str,
245
+ help="Working directory for downloads (default: current directory)",
246
+ )
247
+ parser.add_argument("command", type=str, help="Command to execute")
248
+ parser.add_argument("args", nargs="*", help="Command arguments")
249
+
250
+ parsed = parser.parse_args()
251
+
252
+ # Set global working directory if provided
253
+ global WORKING_DIR
254
+ if parsed.working_dir:
255
+ WORKING_DIR = parsed.working_dir
256
+
257
+ command = parsed.command
258
+ args = parsed.args
259
+
260
+ if command == "calculate_week":
261
+ week = calculate_week()
262
+ print(week)
263
+
264
+ elif command == "fetch_files":
265
+ files = fetch_ftp_file_list()
266
+ print(" ".join(files))
267
+
268
+ elif command == "filter_files":
269
+ if len(args) < 2:
270
+ print("Usage: python pubmed_weekly.py filter_files <week_name> <file_list>")
271
+ sys.exit(1)
272
+
273
+ week_name = args[0]
274
+ file_list = args[1].split()
275
+ filtered = filter_files_by_date(week_name, file_list)
276
+ print(" ".join(filtered))
277
+
278
+ elif command == "download_file":
279
+ if len(args) < 2:
280
+ print("Usage: python pubmed_weekly.py download_file <week_name> <filename>")
281
+ sys.exit(1)
282
+
283
+ week_name = args[0]
284
+ filename = args[1]
285
+ sys.exit(download_file(week_name, filename))
286
+
287
+ else:
288
+ print(f"Unknown command: {command}")
289
+ sys.exit(1)
290
+
291
+
292
+ if __name__ == "__main__":
293
+ main()
@@ -1,141 +1,141 @@
1
- ---
2
- name: python-setup-uv
3
- description: Setup Python environment with uv package manager - download binaries, create symlink, and install packages
4
- allowedTools:
5
- - Bash
6
- - Read
7
- ---
8
-
9
- # Python Environment Setup with uv
10
-
11
- This skill sets up a Python environment using the uv package manager.
12
-
13
- ## Prerequisites
14
- - Internet connection for downloading uv
15
- - Python 3.8+ should be available on PATH (or uv will prompt to install it)
16
-
17
- ## Steps
18
-
19
- **ABSOLUTE RULE:** Follow steps below EXACTLY AS IS. Do NOT skip/modify steps (nor detailed subtasks in each step) nor assume anything based on user platform information. Use URLs below EXACTLY AS IS. Follow steps below INCLUDING ALL DETAILS AND SUBSTEPS EXACTLY AS IS.
20
-
21
- ### Step 1: Ask user question about which installer to use
22
-
23
- Use the question tool to ask which installer should be used:
24
-
25
- - Official astral-uv installer (https://astral.sh)
26
- - China mainland uv-custom installer (https://gitee.com/wangnov/uv-custom)
27
-
28
- ### Step 2: Detect Shell and Download uv Binary
29
-
30
- First, detect your shell environment:
31
-
32
- ```bash
33
- # Detect shell type
34
- # MSYSTEM is set by Git Bash, MINGW_PREFIX by MSYS2
35
- if [ -n "$MSYSTEM" ] || [ -n "$MINGW_PREFIX" ] || command -v curl >/dev/null 2>&1; then
36
- echo "Unix-like shell detected (Git Bash, bash, zsh, etc.)"
37
- IS_UNIX_SHELL=true
38
- else
39
- echo "Windows cmd.exe detected"
40
- IS_UNIX_SHELL=false
41
- fi
42
- ```
43
-
44
- Then download uv based on your shell (see below).
45
-
46
- Choose the correct `UV_INSTALLER_URL` depending on answer you received in Step 1 from the user:
47
-
48
- - If opted "Official astral-uv", UV_INSTALLER_URL should be `https://astral.sh/uv/install.sh` (Unix-like) or `https://astral.sh/uv/install.ps1` (Windows)
49
- - If opted "China mainland uv-custom", UV_INSTALLER_URL should be `https://gitee.com/wangnov/uv-custom/releases/download/latest/uv-installer-custom.sh` (Unix-like) or `https://gitee.com/wangnov/uv-custom/releases/download/latest/uv-installer-custom.ps1` (Windows)
50
-
51
- **For Unix-like shells (Git Bash / macOS / Linux; use correct UV_INSTALLER_URL):**
52
- ```bash
53
- mkdir -p .uv
54
- curl -LsSf UV_INSTALLER_URL | UV_INSTALL_DIR="$(pwd)/.uv" sh
55
- ```
56
-
57
- **For Windows cmd.exe (if Git Bash unavailable; use correct UV_INSTALLER_URL):**
58
- ```bash
59
- powershell -NoProfile -Command "New-Item -ItemType Directory -Force -Path .uv | Out-Null; $env:UV_INSTALL_DIR = (Get-Location).Path + '\.uv'; Invoke-RestMethod UV_INSTALLER_URL | Invoke-Expression"
60
- ```
61
-
62
- ### Step 3: Create Symlink or Copy uv to Working Directory
63
-
64
- **For Unix-like shells (Git Bash / macOS / Linux):**
65
- ```bash
66
- ln -sf .uv/uv uv
67
- ```
68
-
69
- **For Windows cmd.exe:**
70
-
71
- Try symlink first, fall back to copy if no Admin rights:
72
- ```bash
73
- cmd /c "(mklink uv .uv\uv.exe) 2>nul || copy /Y .uv\uv.exe uv.exe"
74
- ```
75
-
76
- ### Step 4: Create Virtual Environment and Install pandas
77
-
78
- NOTE: this step (package installation) may timeout. If timed out, use the question tool to ask if the user would like to retry package installation. If successful, do NOT ask any question and continue to Step 5.
79
-
80
- **For Unix-like shells:**
81
- ```bash
82
- ./uv venv
83
- ./uv pip install pandas
84
- ```
85
-
86
- **For Windows cmd.exe:**
87
- ```bash
88
- uv.exe venv
89
- uv.exe pip install pandas
90
- ```
91
-
92
- ### Step 5: Verification
93
-
94
- **For Unix-like shells:**
95
- ```bash
96
- ./uv --version
97
- ./uv run python -c "import pandas; print(pandas.__version__)"
98
- ```
99
-
100
- **For Windows cmd.exe:**
101
- ```bash
102
- uv.exe --version
103
- uv.exe run python -c "import pandas; print(pandas.__version__)"
104
- ```
105
-
106
- ### Step 6: Update AGENTS.md
107
-
108
- Use the question tool to ask if the user want to update AGENTS.md in WORKING DIRECTORY to "direct agents to use the installed UV Python" (options: "Yes" / "No"). If received no answer, continue to Step 7 (do NOT modify AGENTS.md NOR create directories). If received yes answer, follow steps belows.
109
-
110
- 1. If AGENTS.md not found in WORKING DIR, create an empty AGENTS.md.
111
- 2. Inspect AGENTS.md content. If you do not see the content block below, APPEND EXACTLY AS IS to end of AGENTS.md.
112
- 3. Check if `./.code/py` exist. If not, create the directories.
113
-
114
- Content block:
115
-
116
- ```md
117
- ## Important note about Python
118
-
119
- ALWAYS use the uv package manager available in WORKING DIRECTORY, including `uv add ...` or `uv pip ...` for package management and `uv run ...` to run python package executables.
120
-
121
- ALWAYS save python scripts under path `./.code/py/` and run the script with `uv run python ...` whenever your work involves executing python scripts. Your script MUST contain concise docstrings and comments and use good engineering practices including separation of concerns.
122
- ```
123
-
124
- ### Step 7: Return summary to user (Usage After Setup)
125
-
126
- **For Unix-like shells:**
127
- ```bash
128
- ./uv run python your_script.py
129
- ```
130
-
131
- **For Windows cmd.exe:**
132
- ```bash
133
- uv.exe run python your_script.py
134
- ```
135
-
136
- ## Notes
137
- - Add `.uv/` and `.venv/` to `.gitignore`
138
- - `uv run` handles venv activation automatically
139
- - Use `./uv add <package>` (Unix) or `uv.exe add <package>` (Windows cmd.exe) for project dependencies
140
- - Windows with Git Bash: Follow Unix-like shell instructions
141
- - Windows cmd.exe without Admin rights: `uv.exe` is copied instead of symlinked
1
+ ---
2
+ name: python-setup-uv
3
+ description: Setup Python environment with uv package manager - download binaries, create symlink, and install packages
4
+ allowedTools:
5
+ - Bash
6
+ - Read
7
+ ---
8
+
9
+ # Python Environment Setup with uv
10
+
11
+ This skill sets up a Python environment using the uv package manager.
12
+
13
+ ## Prerequisites
14
+ - Internet connection for downloading uv
15
+ - Python 3.8+ should be available on PATH (or uv will prompt to install it)
16
+
17
+ ## Steps
18
+
19
+ **ABSOLUTE RULE:** Follow steps below EXACTLY AS IS. Do NOT skip/modify steps (nor detailed subtasks in each step) nor assume anything based on user platform information. Use URLs below EXACTLY AS IS. Follow steps below INCLUDING ALL DETAILS AND SUBSTEPS EXACTLY AS IS.
20
+
21
+ ### Step 1: Ask user question about which installer to use
22
+
23
+ Use the question tool to ask which installer should be used:
24
+
25
+ - Official astral-uv installer (https://astral.sh)
26
+ - China mainland uv-custom installer (https://gitee.com/wangnov/uv-custom)
27
+
28
+ ### Step 2: Detect Shell and Download uv Binary
29
+
30
+ First, detect your shell environment:
31
+
32
+ ```bash
33
+ # Detect shell type
34
+ # MSYSTEM is set by Git Bash, MINGW_PREFIX by MSYS2
35
+ if [ -n "$MSYSTEM" ] || [ -n "$MINGW_PREFIX" ] || command -v curl >/dev/null 2>&1; then
36
+ echo "Unix-like shell detected (Git Bash, bash, zsh, etc.)"
37
+ IS_UNIX_SHELL=true
38
+ else
39
+ echo "Windows cmd.exe detected"
40
+ IS_UNIX_SHELL=false
41
+ fi
42
+ ```
43
+
44
+ Then download uv based on your shell (see below).
45
+
46
+ Choose the correct `UV_INSTALLER_URL` depending on answer you received in Step 1 from the user:
47
+
48
+ - If opted "Official astral-uv", UV_INSTALLER_URL should be `https://astral.sh/uv/install.sh` (Unix-like) or `https://astral.sh/uv/install.ps1` (Windows)
49
+ - If opted "China mainland uv-custom", UV_INSTALLER_URL should be `https://gitee.com/wangnov/uv-custom/releases/download/latest/uv-installer-custom.sh` (Unix-like) or `https://gitee.com/wangnov/uv-custom/releases/download/latest/uv-installer-custom.ps1` (Windows)
50
+
51
+ **For Unix-like shells (Git Bash / macOS / Linux; use correct UV_INSTALLER_URL):**
52
+ ```bash
53
+ mkdir -p .uv
54
+ curl -LsSf UV_INSTALLER_URL | UV_INSTALL_DIR="$(pwd)/.uv" sh
55
+ ```
56
+
57
+ **For Windows cmd.exe (if Git Bash unavailable; use correct UV_INSTALLER_URL):**
58
+ ```bash
59
+ powershell -NoProfile -Command "New-Item -ItemType Directory -Force -Path .uv | Out-Null; $env:UV_INSTALL_DIR = (Get-Location).Path + '\.uv'; Invoke-RestMethod UV_INSTALLER_URL | Invoke-Expression"
60
+ ```
61
+
62
+ ### Step 3: Create Symlink or Copy uv to Working Directory
63
+
64
+ **For Unix-like shells (Git Bash / macOS / Linux):**
65
+ ```bash
66
+ ln -sf .uv/uv uv
67
+ ```
68
+
69
+ **For Windows cmd.exe:**
70
+
71
+ Try symlink first, fall back to copy if no Admin rights:
72
+ ```bash
73
+ cmd /c "(mklink uv .uv\uv.exe) 2>nul || copy /Y .uv\uv.exe uv.exe"
74
+ ```
75
+
76
+ ### Step 4: Create Virtual Environment and Install pandas
77
+
78
+ NOTE: this step (package installation) may timeout. If timed out, use the question tool to ask if the user would like to retry package installation. If successful, do NOT ask any question and continue to Step 5.
79
+
80
+ **For Unix-like shells:**
81
+ ```bash
82
+ ./uv venv
83
+ ./uv pip install pandas
84
+ ```
85
+
86
+ **For Windows cmd.exe:**
87
+ ```bash
88
+ uv.exe venv
89
+ uv.exe pip install pandas
90
+ ```
91
+
92
+ ### Step 5: Verification
93
+
94
+ **For Unix-like shells:**
95
+ ```bash
96
+ ./uv --version
97
+ ./uv run python -c "import pandas; print(pandas.__version__)"
98
+ ```
99
+
100
+ **For Windows cmd.exe:**
101
+ ```bash
102
+ uv.exe --version
103
+ uv.exe run python -c "import pandas; print(pandas.__version__)"
104
+ ```
105
+
106
+ ### Step 6: Update AGENTS.md
107
+
108
+ Use the question tool to ask if the user want to update AGENTS.md in WORKING DIRECTORY to "direct agents to use the installed UV Python" (options: "Yes" / "No"). If received no answer, continue to Step 7 (do NOT modify AGENTS.md NOR create directories). If received yes answer, follow steps belows.
109
+
110
+ 1. If AGENTS.md not found in WORKING DIR, create an empty AGENTS.md.
111
+ 2. Inspect AGENTS.md content. If you do not see the content block below, APPEND EXACTLY AS IS to end of AGENTS.md.
112
+ 3. Check if `./.code/py` exist. If not, create the directories.
113
+
114
+ Content block:
115
+
116
+ ```md
117
+ ## Important note about Python
118
+
119
+ ALWAYS use the uv package manager available in WORKING DIRECTORY, including `uv add ...` or `uv pip ...` for package management and `uv run ...` to run python package executables.
120
+
121
+ ALWAYS save python scripts under path `./.code/py/` and run the script with `uv run python ...` whenever your work involves executing python scripts. Your script MUST contain concise docstrings and comments and use good engineering practices including separation of concerns.
122
+ ```
123
+
124
+ ### Step 7: Return summary to user (Usage After Setup)
125
+
126
+ **For Unix-like shells:**
127
+ ```bash
128
+ ./uv run python your_script.py
129
+ ```
130
+
131
+ **For Windows cmd.exe:**
132
+ ```bash
133
+ uv.exe run python your_script.py
134
+ ```
135
+
136
+ ## Notes
137
+ - Add `.uv/` and `.venv/` to `.gitignore`
138
+ - `uv run` handles venv activation automatically
139
+ - Use `./uv add <package>` (Unix) or `uv.exe add <package>` (Windows cmd.exe) for project dependencies
140
+ - Windows with Git Bash: Follow Unix-like shell instructions
141
+ - Windows cmd.exe without Admin rights: `uv.exe` is copied instead of symlinked
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yeyuan98/opencode-bioresearcher-plugin",
3
- "version": "1.3.0",
3
+ "version": "1.3.1-alpha.0",
4
4
  "description": "OpenCode plugin that adds a bioresearcher agent",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",