videonut 1.2.8 ā 1.3.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 +272 -272
- package/USER_GUIDE.md +90 -90
- package/agents/core/eic.md +771 -771
- package/agents/creative/director.md +246 -246
- package/agents/creative/scriptwriter.md +207 -207
- package/agents/research/investigator.md +394 -394
- package/agents/technical/archivist.md +288 -288
- package/agents/technical/scavenger.md +247 -247
- package/config.yaml +61 -61
- package/docs/scriptwriter.md +42 -42
- package/file_validator.py +186 -186
- package/memory/short_term/asset_manifest.md +64 -64
- package/memory/short_term/investigation_dossier.md +31 -31
- package/memory/short_term/master_script.md +51 -51
- package/package.json +61 -64
- package/requirements.txt +8 -8
- package/tools/check_env.py +76 -76
- package/tools/downloaders/caption_reader.py +237 -237
- package/tools/downloaders/clip_grabber.py +82 -82
- package/tools/downloaders/image_grabber.py +105 -105
- package/tools/downloaders/pdf_reader.py +163 -163
- package/tools/downloaders/screenshotter.py +58 -58
- package/tools/downloaders/web_reader.py +69 -69
- package/tools/validators/link_checker.py +45 -45
- package/workflow_orchestrator.py +336 -336
- package/.claude/commands/archivist.toml +0 -12
- package/.claude/commands/director.toml +0 -12
- package/.claude/commands/eic.toml +0 -12
- package/.claude/commands/investigator.toml +0 -12
- package/.claude/commands/prompt.toml +0 -12
- package/.claude/commands/scavenger.toml +0 -12
- package/.claude/commands/scout.toml +0 -12
- package/.claude/commands/scriptwriter.toml +0 -12
- package/.claude/commands/seo.toml +0 -12
- package/.claude/commands/thumbnail.toml +0 -12
- package/.claude/commands/topic_scout.toml +0 -12
- package/.gemini/commands/archivist.toml +0 -12
- package/.gemini/commands/director.toml +0 -12
- package/.gemini/commands/eic.toml +0 -12
- package/.gemini/commands/investigator.toml +0 -12
- package/.gemini/commands/prompt.toml +0 -12
- package/.gemini/commands/scavenger.toml +0 -12
- package/.gemini/commands/scout.toml +0 -12
- package/.gemini/commands/scriptwriter.toml +0 -12
- package/.gemini/commands/seo.toml +0 -12
- package/.gemini/commands/thumbnail.toml +0 -12
- package/.gemini/commands/topic_scout.toml +0 -12
- package/.qwen/commands/archivist.toml +0 -12
- package/.qwen/commands/director.toml +0 -12
- package/.qwen/commands/eic.toml +0 -12
- package/.qwen/commands/investigator.toml +0 -12
- package/.qwen/commands/prompt.toml +0 -12
- package/.qwen/commands/scavenger.toml +0 -12
- package/.qwen/commands/scout.toml +0 -12
- package/.qwen/commands/scriptwriter.toml +0 -12
- package/.qwen/commands/seo.toml +0 -12
- package/.qwen/commands/thumbnail.toml +0 -12
- package/.qwen/commands/topic_scout.toml +0 -12
package/workflow_orchestrator.py
CHANGED
|
@@ -1,337 +1,337 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
VideoNut Workflow Orchestrator
|
|
4
|
-
Automates the agent workflow while maintaining manual control options
|
|
5
|
-
"""
|
|
6
|
-
import os
|
|
7
|
-
import sys
|
|
8
|
-
import subprocess
|
|
9
|
-
import argparse
|
|
10
|
-
import json
|
|
11
|
-
from datetime import datetime
|
|
12
|
-
import shutil
|
|
13
|
-
|
|
14
|
-
class VideoNutOrchestrator:
|
|
15
|
-
def __init__(self, project_path):
|
|
16
|
-
self.project_path = project_path
|
|
17
|
-
self.checkpoint_file = os.path.join(project_path, ".workflow_checkpoint.json")
|
|
18
|
-
self.checkpoints = self.load_checkpoints()
|
|
19
|
-
|
|
20
|
-
def load_checkpoints(self):
|
|
21
|
-
"""Load workflow progress from checkpoint file"""
|
|
22
|
-
if os.path.exists(self.checkpoint_file):
|
|
23
|
-
with open(self.checkpoint_file, 'r') as f:
|
|
24
|
-
return json.load(f)
|
|
25
|
-
return {
|
|
26
|
-
"investigation_complete": False,
|
|
27
|
-
"scriptwriting_complete": False,
|
|
28
|
-
"direction_complete": False,
|
|
29
|
-
"scavenging_complete": False,
|
|
30
|
-
"archiving_complete": False,
|
|
31
|
-
"last_step": "none"
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
def save_checkpoints(self):
|
|
35
|
-
"""Save workflow progress to checkpoint file"""
|
|
36
|
-
with open(self.checkpoint_file, 'w') as f:
|
|
37
|
-
json.dump(self.checkpoints, f, indent=2)
|
|
38
|
-
|
|
39
|
-
def run_command(self, cmd, description):
|
|
40
|
-
"""Execute a command with error handling"""
|
|
41
|
-
print(f"\nš {description}")
|
|
42
|
-
print(f"Command: {cmd}")
|
|
43
|
-
|
|
44
|
-
try:
|
|
45
|
-
result = subprocess.run(
|
|
46
|
-
cmd,
|
|
47
|
-
shell=True,
|
|
48
|
-
capture_output=True,
|
|
49
|
-
text=True,
|
|
50
|
-
cwd=self.project_path
|
|
51
|
-
)
|
|
52
|
-
|
|
53
|
-
if result.returncode == 0:
|
|
54
|
-
print(f"ā
{description} completed successfully")
|
|
55
|
-
return True
|
|
56
|
-
else:
|
|
57
|
-
print(f"ā {description} failed:")
|
|
58
|
-
print(f"STDOUT: {result.stdout}")
|
|
59
|
-
print(f"STDERR: {result.stderr}")
|
|
60
|
-
return False
|
|
61
|
-
|
|
62
|
-
except Exception as e:
|
|
63
|
-
print(f"ā Error running {description}: {str(e)}")
|
|
64
|
-
return False
|
|
65
|
-
|
|
66
|
-
def check_prerequisites(self):
|
|
67
|
-
"""Check if required files exist for each step"""
|
|
68
|
-
files_needed = {
|
|
69
|
-
"investigation": [],
|
|
70
|
-
"scriptwriting": [os.path.join(self.project_path, "truth_dossier.md")],
|
|
71
|
-
"direction": [os.path.join(self.project_path, "narrative_script.md")],
|
|
72
|
-
"scavenging": [os.path.join(self.project_path, "master_script.md")],
|
|
73
|
-
"archiving": [os.path.join(self.project_path, "asset_manifest.md")]
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
for step, required_files in files_needed.items():
|
|
77
|
-
for file_path in required_files:
|
|
78
|
-
if not os.path.exists(file_path):
|
|
79
|
-
print(f"ā Prerequisite missing for {step}: {file_path}")
|
|
80
|
-
return False
|
|
81
|
-
return True
|
|
82
|
-
|
|
83
|
-
def run_investigation(self):
|
|
84
|
-
"""Run investigation phase"""
|
|
85
|
-
if self.checkpoints["investigation_complete"]:
|
|
86
|
-
print("āļø Investigation already completed, skipping...")
|
|
87
|
-
return True
|
|
88
|
-
|
|
89
|
-
print("\nš Starting Investigation Phase...")
|
|
90
|
-
# This would typically require user input, so we'll note this step
|
|
91
|
-
print("Please run: /investigator and complete the investigation")
|
|
92
|
-
print("When complete, mark investigation as done by creating truth_dossier.md")
|
|
93
|
-
|
|
94
|
-
# For automation, we'd need to implement the actual investigator call
|
|
95
|
-
# For now, we'll just check if the output file exists
|
|
96
|
-
dossier_path = os.path.join(self.project_path, "truth_dossier.md")
|
|
97
|
-
if os.path.exists(dossier_path):
|
|
98
|
-
self.checkpoints["investigation_complete"] = True
|
|
99
|
-
self.checkpoints["last_step"] = "investigation"
|
|
100
|
-
self.save_checkpoints()
|
|
101
|
-
print("ā
Investigation step marked as complete")
|
|
102
|
-
return True
|
|
103
|
-
else:
|
|
104
|
-
print("ā Investigation output not found. Please complete investigation manually.")
|
|
105
|
-
return False
|
|
106
|
-
|
|
107
|
-
def run_scriptwriting(self):
|
|
108
|
-
"""Run scriptwriting phase"""
|
|
109
|
-
if self.checkpoints["scriptwriting_complete"]:
|
|
110
|
-
print("āļø Scriptwriting already completed, skipping...")
|
|
111
|
-
return True
|
|
112
|
-
|
|
113
|
-
print("\nāļø Starting Scriptwriting Phase...")
|
|
114
|
-
|
|
115
|
-
# Check if prerequisite exists
|
|
116
|
-
dossier_path = os.path.join(self.project_path, "truth_dossier.md")
|
|
117
|
-
if not os.path.exists(dossier_path):
|
|
118
|
-
print("ā Prerequisite file missing: truth_dossier.md")
|
|
119
|
-
return False
|
|
120
|
-
|
|
121
|
-
# Run the scriptwriter
|
|
122
|
-
cmd = f'python -c "import sys; sys.path.append(\'..\'); from tools.downloaders.caption_reader import *; exec(open(\'agents/creative/scriptwriter.md\').read())" 2>/dev/null || echo "Scriptwriter needs manual execution"'
|
|
123
|
-
# More realistic approach - just check if output exists
|
|
124
|
-
script_path = os.path.join(self.project_path, "narrative_script.md")
|
|
125
|
-
|
|
126
|
-
if os.path.exists(script_path):
|
|
127
|
-
self.checkpoints["scriptwriting_complete"] = True
|
|
128
|
-
self.checkpoints["last_step"] = "scriptwriting"
|
|
129
|
-
self.save_checkpoints()
|
|
130
|
-
print("ā
Scriptwriting step marked as complete")
|
|
131
|
-
return True
|
|
132
|
-
else:
|
|
133
|
-
print("ā Narrative script not found. Please run scriptwriter manually.")
|
|
134
|
-
return False
|
|
135
|
-
|
|
136
|
-
def run_direction(self):
|
|
137
|
-
"""Run direction phase"""
|
|
138
|
-
if self.checkpoints["direction_complete"]:
|
|
139
|
-
print("āļø Direction already completed, skipping...")
|
|
140
|
-
return True
|
|
141
|
-
|
|
142
|
-
print("\nš¬ Starting Direction Phase...")
|
|
143
|
-
|
|
144
|
-
# Check if prerequisite exists
|
|
145
|
-
script_path = os.path.join(self.project_path, "narrative_script.md")
|
|
146
|
-
if not os.path.exists(script_path):
|
|
147
|
-
print("ā Prerequisite file missing: narrative_script.md")
|
|
148
|
-
return False
|
|
149
|
-
|
|
150
|
-
# Check for output
|
|
151
|
-
master_script_path = os.path.join(self.project_path, "master_script.md")
|
|
152
|
-
if os.path.exists(master_script_path):
|
|
153
|
-
self.checkpoints["direction_complete"] = True
|
|
154
|
-
self.checkpoints["last_step"] = "direction"
|
|
155
|
-
self.save_checkpoints()
|
|
156
|
-
print("ā
Direction step marked as complete")
|
|
157
|
-
return True
|
|
158
|
-
else:
|
|
159
|
-
print("ā Master script not found. Please run director manually.")
|
|
160
|
-
return False
|
|
161
|
-
|
|
162
|
-
def run_scavenging(self):
|
|
163
|
-
"""Run scavenging phase"""
|
|
164
|
-
if self.checkpoints["scavenging_complete"]:
|
|
165
|
-
print("āļø Scavenging already completed, skipping...")
|
|
166
|
-
return True
|
|
167
|
-
|
|
168
|
-
print("\nš¦
Starting Scavenging Phase...")
|
|
169
|
-
|
|
170
|
-
# Check if prerequisite exists
|
|
171
|
-
master_script_path = os.path.join(self.project_path, "master_script.md")
|
|
172
|
-
if not os.path.exists(master_script_path):
|
|
173
|
-
print("ā Prerequisite file missing: master_script.md")
|
|
174
|
-
return False
|
|
175
|
-
|
|
176
|
-
# Check for output
|
|
177
|
-
manifest_path = os.path.join(self.project_path, "asset_manifest.md")
|
|
178
|
-
if os.path.exists(manifest_path):
|
|
179
|
-
self.checkpoints["scavenging_complete"] = True
|
|
180
|
-
self.checkpoints["last_step"] = "scavenging"
|
|
181
|
-
self.save_checkpoints()
|
|
182
|
-
print("ā
Scavenging step marked as complete")
|
|
183
|
-
return True
|
|
184
|
-
else:
|
|
185
|
-
print("ā Asset manifest not found. Please run scavenger manually.")
|
|
186
|
-
return False
|
|
187
|
-
|
|
188
|
-
def run_archiving(self):
|
|
189
|
-
"""Run archiving phase"""
|
|
190
|
-
if self.checkpoints["archiving_complete"]:
|
|
191
|
-
print("āļø Archiving already completed, skipping...")
|
|
192
|
-
return True
|
|
193
|
-
|
|
194
|
-
print("\nš¾ Starting Archiving Phase...")
|
|
195
|
-
|
|
196
|
-
# Check if prerequisite exists
|
|
197
|
-
manifest_path = os.path.join(self.project_path, "asset_manifest.md")
|
|
198
|
-
if not os.path.exists(manifest_path):
|
|
199
|
-
print("ā Prerequisite file missing: asset_manifest.md")
|
|
200
|
-
return False
|
|
201
|
-
|
|
202
|
-
# Run archivist
|
|
203
|
-
cmd = f'python -c "import sys; sys.path.append(\'..\'); exec(open(\'agents/technical/archivist.md\').read())" 2>/dev/null || echo "Archivist needs manual execution"'
|
|
204
|
-
|
|
205
|
-
# Check for output directory
|
|
206
|
-
assets_path = os.path.join(self.project_path, "assets")
|
|
207
|
-
if os.path.exists(assets_path):
|
|
208
|
-
self.checkpoints["archiving_complete"] = True
|
|
209
|
-
self.checkpoints["last_step"] = "archiving"
|
|
210
|
-
self.save_checkpoints()
|
|
211
|
-
print("ā
Archiving step marked as complete")
|
|
212
|
-
return True
|
|
213
|
-
else:
|
|
214
|
-
print("ā Assets directory not found. Please run archivist manually.")
|
|
215
|
-
return False
|
|
216
|
-
|
|
217
|
-
def run_full_workflow(self):
|
|
218
|
-
"""Run the complete VideoNut workflow"""
|
|
219
|
-
print("š¬ Starting VideoNut Video Production Workflow")
|
|
220
|
-
print(f"Project Path: {self.project_path}")
|
|
221
|
-
print(f"Last completed step: {self.checkpoints['last_step']}")
|
|
222
|
-
|
|
223
|
-
steps = [
|
|
224
|
-
("Investigation", self.run_investigation),
|
|
225
|
-
("Scriptwriting", self.run_scriptwriting),
|
|
226
|
-
("Direction", self.run_direction),
|
|
227
|
-
("Scavenging", self.run_scavenging),
|
|
228
|
-
("Archiving", self.run_archiving)
|
|
229
|
-
]
|
|
230
|
-
|
|
231
|
-
for step_name, step_func in steps:
|
|
232
|
-
print(f"\n--- {step_name.upper()} PHASE ---")
|
|
233
|
-
if not step_func():
|
|
234
|
-
print(f"ā {step_name} phase failed. Workflow stopped.")
|
|
235
|
-
return False
|
|
236
|
-
|
|
237
|
-
print("\nš All workflow phases completed successfully!")
|
|
238
|
-
print("Your video assets are ready for editing!")
|
|
239
|
-
return True
|
|
240
|
-
|
|
241
|
-
def main():
|
|
242
|
-
parser = argparse.ArgumentParser(description="VideoNut Workflow Orchestrator")
|
|
243
|
-
parser.add_argument("--project", required=True, help="Path to project directory")
|
|
244
|
-
parser.add_argument("--resume", action="store_true", help="Resume from last checkpoint")
|
|
245
|
-
parser.add_argument("--status", action="store_true", help="Show current workflow status")
|
|
246
|
-
parser.add_argument("--next", action="store_true", help="Show what to do next")
|
|
247
|
-
|
|
248
|
-
args = parser.parse_args()
|
|
249
|
-
|
|
250
|
-
if not os.path.exists(args.project):
|
|
251
|
-
print(f"ā Project directory does not exist: {args.project}")
|
|
252
|
-
sys.exit(1)
|
|
253
|
-
|
|
254
|
-
orchestrator = VideoNutOrchestrator(args.project)
|
|
255
|
-
|
|
256
|
-
# Status command - show current progress
|
|
257
|
-
if args.status:
|
|
258
|
-
print("š VideoNut Workflow Status")
|
|
259
|
-
print("=" * 50)
|
|
260
|
-
print(f"Project: {args.project}")
|
|
261
|
-
print(f"Last step: {orchestrator.checkpoints['last_step']}")
|
|
262
|
-
print()
|
|
263
|
-
|
|
264
|
-
status_icons = {True: "ā
", False: "ā³"}
|
|
265
|
-
steps = [
|
|
266
|
-
("Investigation", "investigation_complete", "truth_dossier.md"),
|
|
267
|
-
("Scriptwriting", "scriptwriting_complete", "narrative_script.md"),
|
|
268
|
-
("Direction", "direction_complete", "master_script.md"),
|
|
269
|
-
("Scavenging", "scavenging_complete", "asset_manifest.md"),
|
|
270
|
-
("Archiving", "archiving_complete", "assets/"),
|
|
271
|
-
]
|
|
272
|
-
|
|
273
|
-
for step_name, checkpoint_key, output_file in steps:
|
|
274
|
-
is_complete = orchestrator.checkpoints[checkpoint_key]
|
|
275
|
-
icon = status_icons[is_complete]
|
|
276
|
-
status = "Complete" if is_complete else "Pending"
|
|
277
|
-
print(f" {icon} {step_name}: {status} ā {output_file}")
|
|
278
|
-
|
|
279
|
-
print()
|
|
280
|
-
sys.exit(0)
|
|
281
|
-
|
|
282
|
-
# Next command - show what to do next
|
|
283
|
-
if args.next:
|
|
284
|
-
print("šÆ What to Do Next")
|
|
285
|
-
print("=" * 50)
|
|
286
|
-
|
|
287
|
-
next_steps = {
|
|
288
|
-
"none": ("Investigation", "/investigator", "Create truth_dossier.md with research findings"),
|
|
289
|
-
"investigation": ("Scriptwriting", "/scriptwriter", "Create narrative_script.md from the dossier"),
|
|
290
|
-
"scriptwriting": ("Direction", "/director", "Create master_script.md with visual directions"),
|
|
291
|
-
"direction": ("Scavenging", "/scavenger", "Create asset_manifest.md with URLs"),
|
|
292
|
-
"scavenging": ("Archiving", "/archivist", "Download all assets to assets/ folder"),
|
|
293
|
-
"archiving": ("Complete", None, "š All done! Your video assets are ready for editing."),
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
last_step = orchestrator.checkpoints['last_step']
|
|
297
|
-
step_name, command, description = next_steps.get(last_step, next_steps["none"])
|
|
298
|
-
|
|
299
|
-
print(f"š Current position: After '{last_step}'")
|
|
300
|
-
print(f"š Next step: {step_name}")
|
|
301
|
-
if command:
|
|
302
|
-
print(f"š§ Command: {command}")
|
|
303
|
-
print(f"š What to do: {description}")
|
|
304
|
-
print()
|
|
305
|
-
|
|
306
|
-
# Check for missing files
|
|
307
|
-
expected_files = {
|
|
308
|
-
"none": [],
|
|
309
|
-
"investigation": [("truth_dossier.md", "Run /investigator to create this file")],
|
|
310
|
-
"scriptwriting": [("narrative_script.md", "Run /scriptwriter to create this file")],
|
|
311
|
-
"direction": [("master_script.md", "Run /director to create this file")],
|
|
312
|
-
"scavenging": [("asset_manifest.md", "Run /scavenger to create this file")],
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
for filename, hint in expected_files.get(last_step, []):
|
|
316
|
-
filepath = os.path.join(args.project, filename)
|
|
317
|
-
if not os.path.exists(filepath):
|
|
318
|
-
print(f"ā ļø Missing: {filename}")
|
|
319
|
-
print(f" Fix: {hint}")
|
|
320
|
-
|
|
321
|
-
sys.exit(0)
|
|
322
|
-
|
|
323
|
-
if args.resume:
|
|
324
|
-
print("š Resuming workflow from last checkpoint...")
|
|
325
|
-
|
|
326
|
-
success = orchestrator.run_full_workflow()
|
|
327
|
-
|
|
328
|
-
if success:
|
|
329
|
-
print(f"\nā
Workflow completed! Checkpoint file: {orchestrator.checkpoint_file}")
|
|
330
|
-
else:
|
|
331
|
-
print(f"\nā Workflow failed. Checkpoint file: {orchestrator.checkpoint_file}")
|
|
332
|
-
print("\nš” TIP: Run with --next to see what to do next")
|
|
333
|
-
print("š” TIP: Run with --status to see full progress")
|
|
334
|
-
sys.exit(1)
|
|
335
|
-
|
|
336
|
-
if __name__ == "__main__":
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
VideoNut Workflow Orchestrator
|
|
4
|
+
Automates the agent workflow while maintaining manual control options
|
|
5
|
+
"""
|
|
6
|
+
import os
|
|
7
|
+
import sys
|
|
8
|
+
import subprocess
|
|
9
|
+
import argparse
|
|
10
|
+
import json
|
|
11
|
+
from datetime import datetime
|
|
12
|
+
import shutil
|
|
13
|
+
|
|
14
|
+
class VideoNutOrchestrator:
|
|
15
|
+
def __init__(self, project_path):
|
|
16
|
+
self.project_path = project_path
|
|
17
|
+
self.checkpoint_file = os.path.join(project_path, ".workflow_checkpoint.json")
|
|
18
|
+
self.checkpoints = self.load_checkpoints()
|
|
19
|
+
|
|
20
|
+
def load_checkpoints(self):
|
|
21
|
+
"""Load workflow progress from checkpoint file"""
|
|
22
|
+
if os.path.exists(self.checkpoint_file):
|
|
23
|
+
with open(self.checkpoint_file, 'r') as f:
|
|
24
|
+
return json.load(f)
|
|
25
|
+
return {
|
|
26
|
+
"investigation_complete": False,
|
|
27
|
+
"scriptwriting_complete": False,
|
|
28
|
+
"direction_complete": False,
|
|
29
|
+
"scavenging_complete": False,
|
|
30
|
+
"archiving_complete": False,
|
|
31
|
+
"last_step": "none"
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
def save_checkpoints(self):
|
|
35
|
+
"""Save workflow progress to checkpoint file"""
|
|
36
|
+
with open(self.checkpoint_file, 'w') as f:
|
|
37
|
+
json.dump(self.checkpoints, f, indent=2)
|
|
38
|
+
|
|
39
|
+
def run_command(self, cmd, description):
|
|
40
|
+
"""Execute a command with error handling"""
|
|
41
|
+
print(f"\nš {description}")
|
|
42
|
+
print(f"Command: {cmd}")
|
|
43
|
+
|
|
44
|
+
try:
|
|
45
|
+
result = subprocess.run(
|
|
46
|
+
cmd,
|
|
47
|
+
shell=True,
|
|
48
|
+
capture_output=True,
|
|
49
|
+
text=True,
|
|
50
|
+
cwd=self.project_path
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
if result.returncode == 0:
|
|
54
|
+
print(f"ā
{description} completed successfully")
|
|
55
|
+
return True
|
|
56
|
+
else:
|
|
57
|
+
print(f"ā {description} failed:")
|
|
58
|
+
print(f"STDOUT: {result.stdout}")
|
|
59
|
+
print(f"STDERR: {result.stderr}")
|
|
60
|
+
return False
|
|
61
|
+
|
|
62
|
+
except Exception as e:
|
|
63
|
+
print(f"ā Error running {description}: {str(e)}")
|
|
64
|
+
return False
|
|
65
|
+
|
|
66
|
+
def check_prerequisites(self):
|
|
67
|
+
"""Check if required files exist for each step"""
|
|
68
|
+
files_needed = {
|
|
69
|
+
"investigation": [],
|
|
70
|
+
"scriptwriting": [os.path.join(self.project_path, "truth_dossier.md")],
|
|
71
|
+
"direction": [os.path.join(self.project_path, "narrative_script.md")],
|
|
72
|
+
"scavenging": [os.path.join(self.project_path, "master_script.md")],
|
|
73
|
+
"archiving": [os.path.join(self.project_path, "asset_manifest.md")]
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
for step, required_files in files_needed.items():
|
|
77
|
+
for file_path in required_files:
|
|
78
|
+
if not os.path.exists(file_path):
|
|
79
|
+
print(f"ā Prerequisite missing for {step}: {file_path}")
|
|
80
|
+
return False
|
|
81
|
+
return True
|
|
82
|
+
|
|
83
|
+
def run_investigation(self):
|
|
84
|
+
"""Run investigation phase"""
|
|
85
|
+
if self.checkpoints["investigation_complete"]:
|
|
86
|
+
print("āļø Investigation already completed, skipping...")
|
|
87
|
+
return True
|
|
88
|
+
|
|
89
|
+
print("\nš Starting Investigation Phase...")
|
|
90
|
+
# This would typically require user input, so we'll note this step
|
|
91
|
+
print("Please run: /investigator and complete the investigation")
|
|
92
|
+
print("When complete, mark investigation as done by creating truth_dossier.md")
|
|
93
|
+
|
|
94
|
+
# For automation, we'd need to implement the actual investigator call
|
|
95
|
+
# For now, we'll just check if the output file exists
|
|
96
|
+
dossier_path = os.path.join(self.project_path, "truth_dossier.md")
|
|
97
|
+
if os.path.exists(dossier_path):
|
|
98
|
+
self.checkpoints["investigation_complete"] = True
|
|
99
|
+
self.checkpoints["last_step"] = "investigation"
|
|
100
|
+
self.save_checkpoints()
|
|
101
|
+
print("ā
Investigation step marked as complete")
|
|
102
|
+
return True
|
|
103
|
+
else:
|
|
104
|
+
print("ā Investigation output not found. Please complete investigation manually.")
|
|
105
|
+
return False
|
|
106
|
+
|
|
107
|
+
def run_scriptwriting(self):
|
|
108
|
+
"""Run scriptwriting phase"""
|
|
109
|
+
if self.checkpoints["scriptwriting_complete"]:
|
|
110
|
+
print("āļø Scriptwriting already completed, skipping...")
|
|
111
|
+
return True
|
|
112
|
+
|
|
113
|
+
print("\nāļø Starting Scriptwriting Phase...")
|
|
114
|
+
|
|
115
|
+
# Check if prerequisite exists
|
|
116
|
+
dossier_path = os.path.join(self.project_path, "truth_dossier.md")
|
|
117
|
+
if not os.path.exists(dossier_path):
|
|
118
|
+
print("ā Prerequisite file missing: truth_dossier.md")
|
|
119
|
+
return False
|
|
120
|
+
|
|
121
|
+
# Run the scriptwriter
|
|
122
|
+
cmd = f'python -c "import sys; sys.path.append(\'..\'); from tools.downloaders.caption_reader import *; exec(open(\'agents/creative/scriptwriter.md\').read())" 2>/dev/null || echo "Scriptwriter needs manual execution"'
|
|
123
|
+
# More realistic approach - just check if output exists
|
|
124
|
+
script_path = os.path.join(self.project_path, "narrative_script.md")
|
|
125
|
+
|
|
126
|
+
if os.path.exists(script_path):
|
|
127
|
+
self.checkpoints["scriptwriting_complete"] = True
|
|
128
|
+
self.checkpoints["last_step"] = "scriptwriting"
|
|
129
|
+
self.save_checkpoints()
|
|
130
|
+
print("ā
Scriptwriting step marked as complete")
|
|
131
|
+
return True
|
|
132
|
+
else:
|
|
133
|
+
print("ā Narrative script not found. Please run scriptwriter manually.")
|
|
134
|
+
return False
|
|
135
|
+
|
|
136
|
+
def run_direction(self):
|
|
137
|
+
"""Run direction phase"""
|
|
138
|
+
if self.checkpoints["direction_complete"]:
|
|
139
|
+
print("āļø Direction already completed, skipping...")
|
|
140
|
+
return True
|
|
141
|
+
|
|
142
|
+
print("\nš¬ Starting Direction Phase...")
|
|
143
|
+
|
|
144
|
+
# Check if prerequisite exists
|
|
145
|
+
script_path = os.path.join(self.project_path, "narrative_script.md")
|
|
146
|
+
if not os.path.exists(script_path):
|
|
147
|
+
print("ā Prerequisite file missing: narrative_script.md")
|
|
148
|
+
return False
|
|
149
|
+
|
|
150
|
+
# Check for output
|
|
151
|
+
master_script_path = os.path.join(self.project_path, "master_script.md")
|
|
152
|
+
if os.path.exists(master_script_path):
|
|
153
|
+
self.checkpoints["direction_complete"] = True
|
|
154
|
+
self.checkpoints["last_step"] = "direction"
|
|
155
|
+
self.save_checkpoints()
|
|
156
|
+
print("ā
Direction step marked as complete")
|
|
157
|
+
return True
|
|
158
|
+
else:
|
|
159
|
+
print("ā Master script not found. Please run director manually.")
|
|
160
|
+
return False
|
|
161
|
+
|
|
162
|
+
def run_scavenging(self):
|
|
163
|
+
"""Run scavenging phase"""
|
|
164
|
+
if self.checkpoints["scavenging_complete"]:
|
|
165
|
+
print("āļø Scavenging already completed, skipping...")
|
|
166
|
+
return True
|
|
167
|
+
|
|
168
|
+
print("\nš¦
Starting Scavenging Phase...")
|
|
169
|
+
|
|
170
|
+
# Check if prerequisite exists
|
|
171
|
+
master_script_path = os.path.join(self.project_path, "master_script.md")
|
|
172
|
+
if not os.path.exists(master_script_path):
|
|
173
|
+
print("ā Prerequisite file missing: master_script.md")
|
|
174
|
+
return False
|
|
175
|
+
|
|
176
|
+
# Check for output
|
|
177
|
+
manifest_path = os.path.join(self.project_path, "asset_manifest.md")
|
|
178
|
+
if os.path.exists(manifest_path):
|
|
179
|
+
self.checkpoints["scavenging_complete"] = True
|
|
180
|
+
self.checkpoints["last_step"] = "scavenging"
|
|
181
|
+
self.save_checkpoints()
|
|
182
|
+
print("ā
Scavenging step marked as complete")
|
|
183
|
+
return True
|
|
184
|
+
else:
|
|
185
|
+
print("ā Asset manifest not found. Please run scavenger manually.")
|
|
186
|
+
return False
|
|
187
|
+
|
|
188
|
+
def run_archiving(self):
|
|
189
|
+
"""Run archiving phase"""
|
|
190
|
+
if self.checkpoints["archiving_complete"]:
|
|
191
|
+
print("āļø Archiving already completed, skipping...")
|
|
192
|
+
return True
|
|
193
|
+
|
|
194
|
+
print("\nš¾ Starting Archiving Phase...")
|
|
195
|
+
|
|
196
|
+
# Check if prerequisite exists
|
|
197
|
+
manifest_path = os.path.join(self.project_path, "asset_manifest.md")
|
|
198
|
+
if not os.path.exists(manifest_path):
|
|
199
|
+
print("ā Prerequisite file missing: asset_manifest.md")
|
|
200
|
+
return False
|
|
201
|
+
|
|
202
|
+
# Run archivist
|
|
203
|
+
cmd = f'python -c "import sys; sys.path.append(\'..\'); exec(open(\'agents/technical/archivist.md\').read())" 2>/dev/null || echo "Archivist needs manual execution"'
|
|
204
|
+
|
|
205
|
+
# Check for output directory
|
|
206
|
+
assets_path = os.path.join(self.project_path, "assets")
|
|
207
|
+
if os.path.exists(assets_path):
|
|
208
|
+
self.checkpoints["archiving_complete"] = True
|
|
209
|
+
self.checkpoints["last_step"] = "archiving"
|
|
210
|
+
self.save_checkpoints()
|
|
211
|
+
print("ā
Archiving step marked as complete")
|
|
212
|
+
return True
|
|
213
|
+
else:
|
|
214
|
+
print("ā Assets directory not found. Please run archivist manually.")
|
|
215
|
+
return False
|
|
216
|
+
|
|
217
|
+
def run_full_workflow(self):
|
|
218
|
+
"""Run the complete VideoNut workflow"""
|
|
219
|
+
print("š¬ Starting VideoNut Video Production Workflow")
|
|
220
|
+
print(f"Project Path: {self.project_path}")
|
|
221
|
+
print(f"Last completed step: {self.checkpoints['last_step']}")
|
|
222
|
+
|
|
223
|
+
steps = [
|
|
224
|
+
("Investigation", self.run_investigation),
|
|
225
|
+
("Scriptwriting", self.run_scriptwriting),
|
|
226
|
+
("Direction", self.run_direction),
|
|
227
|
+
("Scavenging", self.run_scavenging),
|
|
228
|
+
("Archiving", self.run_archiving)
|
|
229
|
+
]
|
|
230
|
+
|
|
231
|
+
for step_name, step_func in steps:
|
|
232
|
+
print(f"\n--- {step_name.upper()} PHASE ---")
|
|
233
|
+
if not step_func():
|
|
234
|
+
print(f"ā {step_name} phase failed. Workflow stopped.")
|
|
235
|
+
return False
|
|
236
|
+
|
|
237
|
+
print("\nš All workflow phases completed successfully!")
|
|
238
|
+
print("Your video assets are ready for editing!")
|
|
239
|
+
return True
|
|
240
|
+
|
|
241
|
+
def main():
|
|
242
|
+
parser = argparse.ArgumentParser(description="VideoNut Workflow Orchestrator")
|
|
243
|
+
parser.add_argument("--project", required=True, help="Path to project directory")
|
|
244
|
+
parser.add_argument("--resume", action="store_true", help="Resume from last checkpoint")
|
|
245
|
+
parser.add_argument("--status", action="store_true", help="Show current workflow status")
|
|
246
|
+
parser.add_argument("--next", action="store_true", help="Show what to do next")
|
|
247
|
+
|
|
248
|
+
args = parser.parse_args()
|
|
249
|
+
|
|
250
|
+
if not os.path.exists(args.project):
|
|
251
|
+
print(f"ā Project directory does not exist: {args.project}")
|
|
252
|
+
sys.exit(1)
|
|
253
|
+
|
|
254
|
+
orchestrator = VideoNutOrchestrator(args.project)
|
|
255
|
+
|
|
256
|
+
# Status command - show current progress
|
|
257
|
+
if args.status:
|
|
258
|
+
print("š VideoNut Workflow Status")
|
|
259
|
+
print("=" * 50)
|
|
260
|
+
print(f"Project: {args.project}")
|
|
261
|
+
print(f"Last step: {orchestrator.checkpoints['last_step']}")
|
|
262
|
+
print()
|
|
263
|
+
|
|
264
|
+
status_icons = {True: "ā
", False: "ā³"}
|
|
265
|
+
steps = [
|
|
266
|
+
("Investigation", "investigation_complete", "truth_dossier.md"),
|
|
267
|
+
("Scriptwriting", "scriptwriting_complete", "narrative_script.md"),
|
|
268
|
+
("Direction", "direction_complete", "master_script.md"),
|
|
269
|
+
("Scavenging", "scavenging_complete", "asset_manifest.md"),
|
|
270
|
+
("Archiving", "archiving_complete", "assets/"),
|
|
271
|
+
]
|
|
272
|
+
|
|
273
|
+
for step_name, checkpoint_key, output_file in steps:
|
|
274
|
+
is_complete = orchestrator.checkpoints[checkpoint_key]
|
|
275
|
+
icon = status_icons[is_complete]
|
|
276
|
+
status = "Complete" if is_complete else "Pending"
|
|
277
|
+
print(f" {icon} {step_name}: {status} ā {output_file}")
|
|
278
|
+
|
|
279
|
+
print()
|
|
280
|
+
sys.exit(0)
|
|
281
|
+
|
|
282
|
+
# Next command - show what to do next
|
|
283
|
+
if args.next:
|
|
284
|
+
print("šÆ What to Do Next")
|
|
285
|
+
print("=" * 50)
|
|
286
|
+
|
|
287
|
+
next_steps = {
|
|
288
|
+
"none": ("Investigation", "/investigator", "Create truth_dossier.md with research findings"),
|
|
289
|
+
"investigation": ("Scriptwriting", "/scriptwriter", "Create narrative_script.md from the dossier"),
|
|
290
|
+
"scriptwriting": ("Direction", "/director", "Create master_script.md with visual directions"),
|
|
291
|
+
"direction": ("Scavenging", "/scavenger", "Create asset_manifest.md with URLs"),
|
|
292
|
+
"scavenging": ("Archiving", "/archivist", "Download all assets to assets/ folder"),
|
|
293
|
+
"archiving": ("Complete", None, "š All done! Your video assets are ready for editing."),
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
last_step = orchestrator.checkpoints['last_step']
|
|
297
|
+
step_name, command, description = next_steps.get(last_step, next_steps["none"])
|
|
298
|
+
|
|
299
|
+
print(f"š Current position: After '{last_step}'")
|
|
300
|
+
print(f"š Next step: {step_name}")
|
|
301
|
+
if command:
|
|
302
|
+
print(f"š§ Command: {command}")
|
|
303
|
+
print(f"š What to do: {description}")
|
|
304
|
+
print()
|
|
305
|
+
|
|
306
|
+
# Check for missing files
|
|
307
|
+
expected_files = {
|
|
308
|
+
"none": [],
|
|
309
|
+
"investigation": [("truth_dossier.md", "Run /investigator to create this file")],
|
|
310
|
+
"scriptwriting": [("narrative_script.md", "Run /scriptwriter to create this file")],
|
|
311
|
+
"direction": [("master_script.md", "Run /director to create this file")],
|
|
312
|
+
"scavenging": [("asset_manifest.md", "Run /scavenger to create this file")],
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
for filename, hint in expected_files.get(last_step, []):
|
|
316
|
+
filepath = os.path.join(args.project, filename)
|
|
317
|
+
if not os.path.exists(filepath):
|
|
318
|
+
print(f"ā ļø Missing: {filename}")
|
|
319
|
+
print(f" Fix: {hint}")
|
|
320
|
+
|
|
321
|
+
sys.exit(0)
|
|
322
|
+
|
|
323
|
+
if args.resume:
|
|
324
|
+
print("š Resuming workflow from last checkpoint...")
|
|
325
|
+
|
|
326
|
+
success = orchestrator.run_full_workflow()
|
|
327
|
+
|
|
328
|
+
if success:
|
|
329
|
+
print(f"\nā
Workflow completed! Checkpoint file: {orchestrator.checkpoint_file}")
|
|
330
|
+
else:
|
|
331
|
+
print(f"\nā Workflow failed. Checkpoint file: {orchestrator.checkpoint_file}")
|
|
332
|
+
print("\nš” TIP: Run with --next to see what to do next")
|
|
333
|
+
print("š” TIP: Run with --status to see full progress")
|
|
334
|
+
sys.exit(1)
|
|
335
|
+
|
|
336
|
+
if __name__ == "__main__":
|
|
337
337
|
main()
|