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.

@@ -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`
@@ -29,7 +29,7 @@ Example:
29
29
  from .api import generate_paper
30
30
  from .models import ProgressUpdate, PaperResult, PaperMetadata, PaperFiles
31
31
 
32
- __version__ = "2.2.3"
32
+ __version__ = "2.3.0"
33
33
  __author__ = "K-Dense"
34
34
  __license__ = "MIT"
35
35
 
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=f"Processed {len(processed_info['all_files'])} data file(s)",
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
- cwd = Path.cwd() # User's current working directory
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📁 Output folder: {output_folder}")
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(" • Data files → copied to paper's data/ folder")
96
- print(" • Images → copied to paper's figures/ folder")
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
- data_count = len(processed_info['data_files'])
158
- image_count = len(processed_info['image_files'])
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
- data_count = len(processed_info['data_files'])
216
- image_count = len(processed_info['image_files'])
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
- Images go to figures/, other files go to data/.
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
- if file_ext in image_extensions:
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
- if processed_info['data_files']:
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['image_files']:
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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: scientific-writer
3
- Version: 2.2.3
3
+ Version: 2.3.0
4
4
  Summary: AI-powered scientific writing with programmatic API and CLI - powered by Claude Sonnet 4.5 and the Claude Agents SDK
5
5
  License: MIT
6
6
  License-File: LICENSE
@@ -1,10 +1,10 @@
1
- scientific_writer/__init__.py,sha256=9BVGd3cosRJSt25lC0pEHoZBxHlbvmepGPx1AXsnagc,1159
2
- scientific_writer/api.py,sha256=E2PKi3gszuw_PZU8edswkvk8enBOfhIM8S_KxNWRcUc,12872
3
- scientific_writer/cli.py,sha256=PzwcNwPY_af4VcLFtIBSTk3xJQ7D79dSfOXUZxIcBM0,14940
4
- scientific_writer/core.py,sha256=EXhh9p_y0gkuXFD0a47F9vlVaRipQ6W5Ng5Lyzieg4A,7656
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=O-ThWtw-XJmeZF8MqGoF_bwGq3XNRKsF_Xog81k_3FM,32256
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.2.3.dist-info/METADATA,sha256=2vKPGJa5r18o5uw_Mgyaav94gBA74cLldMEjUV4iX20,9992
309
- scientific_writer-2.2.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
310
- scientific_writer-2.2.3.dist-info/entry_points.txt,sha256=pI1zUsWVV6eMkNEKfEmkKozOlLRZnhAZfXBsEyqXtqg,69
311
- scientific_writer-2.2.3.dist-info/licenses/LICENSE,sha256=H6FOLY6X6QMEnqcbDoq5BM0sBf-K-e1SIBAv0zSwxa4,1070
312
- scientific_writer-2.2.3.dist-info/RECORD,,
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,,