scientific-writer 2.2.3__py3-none-any.whl → 2.3.0__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.
- scientific_writer/.claude/WRITER.md +37 -0
- scientific_writer/__init__.py +1 -1
- scientific_writer/api.py +14 -4
- scientific_writer/cli.py +25 -9
- scientific_writer/core.py +37 -4
- {scientific_writer-2.2.3.dist-info → scientific_writer-2.3.0.dist-info}/METADATA +1 -1
- {scientific_writer-2.2.3.dist-info → scientific_writer-2.3.0.dist-info}/RECORD +10 -10
- {scientific_writer-2.2.3.dist-info → scientific_writer-2.3.0.dist-info}/WHEEL +0 -0
- {scientific_writer-2.2.3.dist-info → scientific_writer-2.3.0.dist-info}/entry_points.txt +0 -0
- {scientific_writer-2.2.3.dist-info → scientific_writer-2.3.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -186,6 +186,43 @@ paper_outputs/
|
|
|
186
186
|
└── supplementary.pdf
|
|
187
187
|
```
|
|
188
188
|
|
|
189
|
+
### CRITICAL: Manuscript Editing Workflow
|
|
190
|
+
|
|
191
|
+
**When manuscript files (.tex, .md, .docx, .pdf) are found in the data/ folder:**
|
|
192
|
+
|
|
193
|
+
1. **ALWAYS copy manuscript files to the drafts/ folder** (not the data/ folder)
|
|
194
|
+
- File types to treat as manuscripts: `.tex`, `.md`, `.docx`, `.pdf`
|
|
195
|
+
- These files should go to `drafts/` folder in the new paper directory
|
|
196
|
+
- This signals the task is an EDITING task, not creating from scratch
|
|
197
|
+
|
|
198
|
+
2. **Recognize this as an EDITING task:**
|
|
199
|
+
- When manuscript files are present in drafts/, your task is to EDIT the existing manuscript
|
|
200
|
+
- Print: `[HH:MM:SS] EDITING MODE: Found existing manuscript - [filename]`
|
|
201
|
+
- Print: `[HH:MM:SS] TASK: Editing and improving existing manuscript`
|
|
202
|
+
- Update progress.md to note this is an editing task
|
|
203
|
+
|
|
204
|
+
3. **Editing Workflow:**
|
|
205
|
+
- Read the existing manuscript file(s) from drafts/
|
|
206
|
+
- Identify the format (.tex, .md, .docx, .pdf)
|
|
207
|
+
- Follow the user's editing instructions
|
|
208
|
+
- Create new version with incremented number (v2, v3, etc.)
|
|
209
|
+
- Document all changes in revision_notes.md
|
|
210
|
+
- Print: `[HH:MM:SS] EDITING: Reading existing manuscript from drafts/[filename]`
|
|
211
|
+
- Print: `[HH:MM:SS] EDITING: Creating [version] with requested changes`
|
|
212
|
+
|
|
213
|
+
4. **What gets copied where:**
|
|
214
|
+
- **Manuscript files** (.tex, .md, .docx, .pdf) → `drafts/` folder
|
|
215
|
+
- **Image files** (.png, .jpg, .pdf figures, etc.) → `figures/` folder
|
|
216
|
+
- **Data files** (CSV, Excel, JSON, etc.) → `data/` folder
|
|
217
|
+
|
|
218
|
+
5. **Example Scenario:**
|
|
219
|
+
- User places `my_paper.tex` in `data/` folder
|
|
220
|
+
- System creates: `paper_outputs/20241104_143000_edit_paper/`
|
|
221
|
+
- System copies: `my_paper.tex` → `drafts/my_paper.tex`
|
|
222
|
+
- System recognizes: "This is an editing task"
|
|
223
|
+
- System prints: `[HH:MM:SS] EDITING MODE: Found manuscript my_paper.tex in drafts/`
|
|
224
|
+
- System applies edits and creates: `drafts/v2_my_paper.tex` or `drafts/v1_draft.tex` (based on instructions)
|
|
225
|
+
|
|
189
226
|
### Naming Conventions
|
|
190
227
|
|
|
191
228
|
- **Folders:** `lowercase_with_underscores`
|
scientific_writer/__init__.py
CHANGED
scientific_writer/api.py
CHANGED
|
@@ -77,8 +77,8 @@ async def generate_paper(
|
|
|
77
77
|
if cwd:
|
|
78
78
|
work_dir = Path(cwd).resolve()
|
|
79
79
|
else:
|
|
80
|
-
# Default to user's current working directory
|
|
81
|
-
work_dir = Path.cwd()
|
|
80
|
+
# Default to user's current working directory (absolute path)
|
|
81
|
+
work_dir = Path.cwd().resolve()
|
|
82
82
|
|
|
83
83
|
# Get package directory for copying skills to working directory
|
|
84
84
|
package_dir = Path(__file__).parent.absolute() # scientific_writer/ directory
|
|
@@ -100,7 +100,13 @@ async def generate_paper(
|
|
|
100
100
|
system_instructions = load_system_instructions(work_dir)
|
|
101
101
|
|
|
102
102
|
# Add conversation continuity instruction
|
|
103
|
-
system_instructions += "\n\n" + """
|
|
103
|
+
system_instructions += "\n\n" + f"""
|
|
104
|
+
IMPORTANT - WORKING DIRECTORY:
|
|
105
|
+
- Your working directory is: {work_dir}
|
|
106
|
+
- ALWAYS create paper_outputs folder in this directory: {work_dir}/paper_outputs/
|
|
107
|
+
- NEVER write to /tmp/ or any other temporary directory
|
|
108
|
+
- All paper outputs MUST go to: {work_dir}/paper_outputs/<timestamp>_<description>/
|
|
109
|
+
|
|
104
110
|
IMPORTANT - CONVERSATION CONTINUITY:
|
|
105
111
|
- This is a NEW paper request - create a new paper directory
|
|
106
112
|
- Create a unique timestamped directory in the paper_outputs folder
|
|
@@ -190,8 +196,12 @@ IMPORTANT - CONVERSATION CONTINUITY:
|
|
|
190
196
|
delete_originals=False # Don't delete when using programmatic API
|
|
191
197
|
)
|
|
192
198
|
if processed_info:
|
|
199
|
+
manuscript_count = len(processed_info.get('manuscript_files', []))
|
|
200
|
+
message = f"Processed {len(processed_info['all_files'])} file(s)"
|
|
201
|
+
if manuscript_count > 0:
|
|
202
|
+
message += f" ({manuscript_count} manuscript(s) copied to drafts/)"
|
|
193
203
|
yield ProgressUpdate(
|
|
194
|
-
message=
|
|
204
|
+
message=message,
|
|
195
205
|
stage="complete",
|
|
196
206
|
percentage=97,
|
|
197
207
|
).to_dict()
|
scientific_writer/cli.py
CHANGED
|
@@ -35,7 +35,8 @@ async def main():
|
|
|
35
35
|
sys.exit(1)
|
|
36
36
|
|
|
37
37
|
# Get the current working directory (user's directory) and package directory
|
|
38
|
-
|
|
38
|
+
# Capture and resolve the current working directory at CLI invocation time
|
|
39
|
+
cwd = Path.cwd().resolve() # User's current working directory (absolute path)
|
|
39
40
|
package_dir = Path(__file__).parent.absolute() # Package installation directory (scientific_writer/)
|
|
40
41
|
|
|
41
42
|
# Set up Claude skills in the working directory (includes WRITER.md)
|
|
@@ -50,7 +51,13 @@ async def main():
|
|
|
50
51
|
# Add conversation continuity instruction
|
|
51
52
|
# Note: The Python CLI handles session tracking via current_paper_path
|
|
52
53
|
# These instructions only apply WITHIN a single CLI session, not across different chat sessions
|
|
53
|
-
system_instructions += "\n\n" + """
|
|
54
|
+
system_instructions += "\n\n" + f"""
|
|
55
|
+
IMPORTANT - WORKING DIRECTORY:
|
|
56
|
+
- Your working directory is: {cwd}
|
|
57
|
+
- ALWAYS create paper_outputs folder in this directory: {cwd}/paper_outputs/
|
|
58
|
+
- NEVER write to /tmp/ or any other temporary directory
|
|
59
|
+
- All paper outputs MUST go to: {cwd}/paper_outputs/<timestamp>_<description>/
|
|
60
|
+
|
|
54
61
|
IMPORTANT - CONVERSATION CONTINUITY:
|
|
55
62
|
- The user will provide context in their prompt if they want to continue working on an existing paper
|
|
56
63
|
- If the prompt includes [CONTEXT: You are currently working on a paper in: ...], continue editing that paper
|
|
@@ -89,11 +96,13 @@ IMPORTANT - CONVERSATION CONTINUITY:
|
|
|
89
96
|
print(" 2. I'll provide continuous updates during the process")
|
|
90
97
|
print(" 3. All outputs saved to: paper_outputs/<timestamp_description>/")
|
|
91
98
|
print(" 4. Progress tracked in real-time in progress.md")
|
|
92
|
-
print(f"\n📁
|
|
99
|
+
print(f"\n📁 Working directory: {cwd}")
|
|
100
|
+
print(f"📁 Output folder: {output_folder}")
|
|
93
101
|
print(f"\n📦 Data Files:")
|
|
94
102
|
print(" • Place files in the 'data/' folder to include them in your paper")
|
|
95
|
-
print(" •
|
|
96
|
-
print(" •
|
|
103
|
+
print(" • Manuscript files (.tex, .md, .docx, .pdf) → copied to drafts/ for EDITING")
|
|
104
|
+
print(" • Data files (csv, txt, json, etc.) → copied to paper's data/ folder")
|
|
105
|
+
print(" • Images (png, jpg, svg, etc.) → copied to paper's figures/ folder")
|
|
97
106
|
print(" • Original files are automatically deleted after copying")
|
|
98
107
|
print("\n🤖 Intelligent Paper Detection:")
|
|
99
108
|
print(" • I automatically detect when you're referring to a previous paper")
|
|
@@ -154,8 +163,11 @@ IMPORTANT - CONVERSATION CONTINUITY:
|
|
|
154
163
|
processed_info = process_data_files(cwd, data_files, current_paper_path)
|
|
155
164
|
if processed_info:
|
|
156
165
|
data_context = create_data_context_message(processed_info)
|
|
157
|
-
|
|
158
|
-
|
|
166
|
+
manuscript_count = len(processed_info.get('manuscript_files', []))
|
|
167
|
+
data_count = len(processed_info.get('data_files', []))
|
|
168
|
+
image_count = len(processed_info.get('image_files', []))
|
|
169
|
+
if manuscript_count > 0:
|
|
170
|
+
print(f" ✓ Copied {manuscript_count} manuscript file(s) to drafts/ [EDITING MODE]")
|
|
159
171
|
if data_count > 0:
|
|
160
172
|
print(f" ✓ Copied {data_count} data file(s) to data/")
|
|
161
173
|
if image_count > 0:
|
|
@@ -212,8 +224,11 @@ User request: {user_input}"""
|
|
|
212
224
|
print(f"\n📦 Processing {len(remaining_data_files)} data file(s)...")
|
|
213
225
|
processed_info = process_data_files(cwd, remaining_data_files, current_paper_path)
|
|
214
226
|
if processed_info:
|
|
215
|
-
|
|
216
|
-
|
|
227
|
+
manuscript_count = len(processed_info.get('manuscript_files', []))
|
|
228
|
+
data_count = len(processed_info.get('data_files', []))
|
|
229
|
+
image_count = len(processed_info.get('image_files', []))
|
|
230
|
+
if manuscript_count > 0:
|
|
231
|
+
print(f" ✓ Copied {manuscript_count} manuscript file(s) to drafts/ [EDITING MODE]")
|
|
217
232
|
if data_count > 0:
|
|
218
233
|
print(f" ✓ Copied {data_count} data file(s) to data/")
|
|
219
234
|
if image_count > 0:
|
|
@@ -265,6 +280,7 @@ def _print_help():
|
|
|
265
280
|
print(" - SUMMARY.md - Project summary and instructions")
|
|
266
281
|
print("\n📦 Data Files:")
|
|
267
282
|
print(" Place files in the 'data/' folder at project root:")
|
|
283
|
+
print(" • Manuscript files (.tex, .md, .docx, .pdf) → copied to drafts/ for EDITING")
|
|
268
284
|
print(" • Data files (csv, txt, json, etc.) → copied to paper's data/")
|
|
269
285
|
print(" • Images (png, jpg, svg, etc.) → copied to paper's figures/")
|
|
270
286
|
print(" • Files are used as context for the paper")
|
scientific_writer/core.py
CHANGED
|
@@ -106,6 +106,11 @@ def get_image_extensions() -> set:
|
|
|
106
106
|
return {'.png', '.jpg', '.jpeg', '.gif', '.bmp', '.tiff', '.tif', '.svg', '.webp', '.ico'}
|
|
107
107
|
|
|
108
108
|
|
|
109
|
+
def get_manuscript_extensions() -> set:
|
|
110
|
+
"""Return a set of manuscript file extensions that should go to drafts/ folder."""
|
|
111
|
+
return {'.tex', '.md', '.docx', '.pdf'}
|
|
112
|
+
|
|
113
|
+
|
|
109
114
|
def get_data_files(cwd: Path, data_files: Optional[List[str]] = None) -> List[Path]:
|
|
110
115
|
"""
|
|
111
116
|
Get data files either from provided list or from data folder.
|
|
@@ -140,7 +145,8 @@ def process_data_files(
|
|
|
140
145
|
) -> Optional[Dict[str, Any]]:
|
|
141
146
|
"""
|
|
142
147
|
Process data files by copying them to the paper output folder.
|
|
143
|
-
|
|
148
|
+
Manuscript files (.tex, .md, .docx, .pdf) go to drafts/,
|
|
149
|
+
images go to figures/, other files go to data/.
|
|
144
150
|
|
|
145
151
|
Args:
|
|
146
152
|
cwd: Current working directory (project root).
|
|
@@ -157,15 +163,20 @@ def process_data_files(
|
|
|
157
163
|
paper_output = Path(paper_output_path)
|
|
158
164
|
data_output = paper_output / "data"
|
|
159
165
|
figures_output = paper_output / "figures"
|
|
166
|
+
drafts_output = paper_output / "drafts"
|
|
160
167
|
|
|
161
168
|
# Ensure output directories exist
|
|
162
169
|
data_output.mkdir(parents=True, exist_ok=True)
|
|
163
170
|
figures_output.mkdir(parents=True, exist_ok=True)
|
|
171
|
+
drafts_output.mkdir(parents=True, exist_ok=True)
|
|
164
172
|
|
|
165
173
|
image_extensions = get_image_extensions()
|
|
174
|
+
manuscript_extensions = get_manuscript_extensions()
|
|
175
|
+
|
|
166
176
|
processed_info = {
|
|
167
177
|
'data_files': [],
|
|
168
178
|
'image_files': [],
|
|
179
|
+
'manuscript_files': [],
|
|
169
180
|
'all_files': []
|
|
170
181
|
}
|
|
171
182
|
|
|
@@ -174,7 +185,17 @@ def process_data_files(
|
|
|
174
185
|
file_name = file_path.name
|
|
175
186
|
|
|
176
187
|
# Determine destination based on file type
|
|
177
|
-
|
|
188
|
+
# CRITICAL: Manuscript files go to drafts/ folder for editing workflow
|
|
189
|
+
if file_ext in manuscript_extensions:
|
|
190
|
+
destination = drafts_output / file_name
|
|
191
|
+
file_type = 'manuscript'
|
|
192
|
+
processed_info['manuscript_files'].append({
|
|
193
|
+
'name': file_name,
|
|
194
|
+
'path': str(destination),
|
|
195
|
+
'original': str(file_path),
|
|
196
|
+
'extension': file_ext
|
|
197
|
+
})
|
|
198
|
+
elif file_ext in image_extensions:
|
|
178
199
|
destination = figures_output / file_name
|
|
179
200
|
file_type = 'image'
|
|
180
201
|
processed_info['image_files'].append({
|
|
@@ -225,12 +246,24 @@ def create_data_context_message(processed_info: Optional[Dict[str, Any]]) -> str
|
|
|
225
246
|
|
|
226
247
|
context_parts = ["\n[DATA FILES AVAILABLE]"]
|
|
227
248
|
|
|
228
|
-
|
|
249
|
+
# CRITICAL: If manuscript files are present, this is an EDITING task
|
|
250
|
+
if processed_info.get('manuscript_files'):
|
|
251
|
+
context_parts.append("\n⚠️ EDITING MODE - Manuscript files detected!")
|
|
252
|
+
context_parts.append("\nManuscript files (in drafts/ folder for editing):")
|
|
253
|
+
for file_info in processed_info['manuscript_files']:
|
|
254
|
+
context_parts.append(f" - {file_info['name']} ({file_info['extension']}): {file_info['path']}")
|
|
255
|
+
context_parts.append("\n🔧 TASK: This is an EDITING task, not creating from scratch.")
|
|
256
|
+
context_parts.append(" → Read the existing manuscript from drafts/")
|
|
257
|
+
context_parts.append(" → Apply the requested changes/improvements")
|
|
258
|
+
context_parts.append(" → Create new version following version numbering protocol")
|
|
259
|
+
context_parts.append(" → Document changes in revision_notes.md")
|
|
260
|
+
|
|
261
|
+
if processed_info.get('data_files'):
|
|
229
262
|
context_parts.append("\nData files (in data/ folder):")
|
|
230
263
|
for file_info in processed_info['data_files']:
|
|
231
264
|
context_parts.append(f" - {file_info['name']}: {file_info['path']}")
|
|
232
265
|
|
|
233
|
-
if processed_info
|
|
266
|
+
if processed_info.get('image_files'):
|
|
234
267
|
context_parts.append("\nImage files (in figures/ folder):")
|
|
235
268
|
for file_info in processed_info['image_files']:
|
|
236
269
|
context_parts.append(f" - {file_info['name']}: {file_info['path']}")
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
scientific_writer/__init__.py,sha256=
|
|
2
|
-
scientific_writer/api.py,sha256=
|
|
3
|
-
scientific_writer/cli.py,sha256=
|
|
4
|
-
scientific_writer/core.py,sha256=
|
|
1
|
+
scientific_writer/__init__.py,sha256=HgoE10KEe_et14scVDkKWFJSK1pBLPERLVswyP1nXrU,1159
|
|
2
|
+
scientific_writer/api.py,sha256=16nrMWEMpSeIqZPYY0QZzw9QoV1N7D1RJouKtBC_nPA,13450
|
|
3
|
+
scientific_writer/cli.py,sha256=_xIXJ_ptpUlmzG-Ocq2OXRFZUsHuMkXHzCEz-9iN13Y,16172
|
|
4
|
+
scientific_writer/core.py,sha256=rpvoMalqS5zPq1xYLQ0heNUofx-ffGmt3OXf3dyOSc0,9428
|
|
5
5
|
scientific_writer/models.py,sha256=KjRjMjn4GtbHLIUrx2EZB4omGcZeLbflaTJmfNV1M6Y,2629
|
|
6
6
|
scientific_writer/utils.py,sha256=z2nX3PDEcfW4pN_w47TDDC6Kmdcw5uFUGrT8T6lZYSg,9032
|
|
7
|
-
scientific_writer/.claude/WRITER.md,sha256=
|
|
7
|
+
scientific_writer/.claude/WRITER.md,sha256=mFpAWIwGrSaHGwyQLE0GO9gllOflSbecNZ72HR9ovPo,34172
|
|
8
8
|
scientific_writer/.claude/settings.local.json,sha256=PVPFjrrlwJo6J3KgeGwxqfh2w0N4xW9r5cefTC36fX8,780
|
|
9
9
|
scientific_writer/.claude/skills/citation-management/SKILL.md,sha256=guNDqOIuvqK1YHbVc5JGiM4MwSmyiytoUqzahNZHrrw,29916
|
|
10
10
|
scientific_writer/.claude/skills/citation-management/assets/bibtex_template.bib,sha256=vwPMZG5rxqq6hdYyuOJbJsKDBBmJLzwXp9hEgF06ch4,9201
|
|
@@ -305,8 +305,8 @@ scientific_writer/.claude/skills/venue-templates/references/posters_guidelines.m
|
|
|
305
305
|
scientific_writer/.claude/skills/venue-templates/scripts/customize_template.py,sha256=ikTF2rMjexS4y3udwtZR8XauleXwU1drG9RDf1M2-Co,6875
|
|
306
306
|
scientific_writer/.claude/skills/venue-templates/scripts/query_template.py,sha256=RI0dzZB-igJZl8dJjbA7teiJy3T-j3reGf62sQpN8g4,8959
|
|
307
307
|
scientific_writer/.claude/skills/venue-templates/scripts/validate_format.py,sha256=acRsRY4hqDsHrkzKIHeRZT7vle9q5SEjkFG3S4Vc5PQ,8766
|
|
308
|
-
scientific_writer-2.
|
|
309
|
-
scientific_writer-2.
|
|
310
|
-
scientific_writer-2.
|
|
311
|
-
scientific_writer-2.
|
|
312
|
-
scientific_writer-2.
|
|
308
|
+
scientific_writer-2.3.0.dist-info/METADATA,sha256=AtjSeFWL1V-iMucgaZvdeJB4x6BABuM7Qq86mHj9pzI,9992
|
|
309
|
+
scientific_writer-2.3.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
310
|
+
scientific_writer-2.3.0.dist-info/entry_points.txt,sha256=pI1zUsWVV6eMkNEKfEmkKozOlLRZnhAZfXBsEyqXtqg,69
|
|
311
|
+
scientific_writer-2.3.0.dist-info/licenses/LICENSE,sha256=H6FOLY6X6QMEnqcbDoq5BM0sBf-K-e1SIBAv0zSwxa4,1070
|
|
312
|
+
scientific_writer-2.3.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|