agentreel 0.3.3 → 0.3.4

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/bin/agentreel.mjs CHANGED
@@ -30,6 +30,7 @@ function parseArgs() {
30
30
  else if (arg === "--output" || arg === "-o") flags.output = args[++i];
31
31
  else if (arg === "--music") flags.music = args[++i];
32
32
  else if (arg === "--auth" || arg === "-a") flags.auth = args[++i];
33
+ else if (arg === "--guidelines" || arg === "-g") flags.guidelines = args[++i];
33
34
  else if (arg === "--no-share") flags.noShare = true;
34
35
  }
35
36
  return flags;
@@ -49,6 +50,7 @@ Flags:
49
50
  -t, --title <text> video title
50
51
  -o, --output <file> output file (default: agentreel.mp4)
51
52
  -a, --auth <file> Playwright storage state (cookies/auth) for browser demos
53
+ -g, --guidelines <text> guidelines for highlight generation (e.g. "focus on speed")
52
54
  --music <file> path to background music mp3
53
55
  --no-share skip the share prompt
54
56
  -h, --help show help
@@ -111,13 +113,14 @@ function recordCLI(command, workDir, context) {
111
113
  return outFile;
112
114
  }
113
115
 
114
- function extractHighlightsFromCast(castPath, context) {
116
+ function extractHighlightsFromCast(castPath, context, guidelines) {
115
117
  const python = findPython();
116
118
  const script = join(ROOT, "scripts", "cli_demo.py");
117
119
  const outFile = castPath + "-highlights.json";
118
120
 
119
121
  const args = [script, "--highlights", castPath, outFile];
120
122
  if (context) args.push(context);
123
+ if (guidelines) args.push(guidelines);
121
124
 
122
125
  execFileSync(python, args, { stdio: ["ignore", "inherit", "inherit"], env: process.env });
123
126
  return outFile;
@@ -160,12 +163,28 @@ function extractBrowserHighlights(videoPath, task) {
160
163
 
161
164
  // ── Browser Highlight Builder ───────────────────────────────
162
165
 
163
- function buildBrowserHighlights(clicks, videoPath, task) {
166
+ function buildBrowserHighlights(clicks, videoPath, task, guidelines) {
164
167
  const CLIP_DUR = 7;
165
168
  const MIN_HIGHLIGHTS = 3;
166
169
  const MAX_HIGHLIGHTS = 4;
167
- const labels = ["Overview", "Interact", "Navigate", "Result"];
168
- const overlays = ["**First look**", "**Key action**", "**Exploring**", "**The result**"];
170
+ // Ask Claude to generate labels/overlays based on the task
171
+ let labels, overlays;
172
+ try {
173
+ const guidelinesLine = guidelines ? `\nGuidelines: ${guidelines}` : "";
174
+ const genPrompt = `Generate exactly 4 highlight labels and overlay captions for a short browser demo video.
175
+ Task: ${task}${guidelinesLine}
176
+
177
+ Return a JSON object: {"labels": ["word1", "word2", "word3", "word4"], "overlays": ["**caption1**", "**caption2**", "**caption3**", "**caption4**"]}
178
+ Labels: 1-2 words each, specific to this app (not generic). Overlays: short punchy captions with **markdown bold** for emphasis. Return ONLY JSON.`;
179
+ const result = execFileSync("claude", ["-p", genPrompt, "--output-format", "text"], {
180
+ encoding: "utf-8", timeout: 30000, stdio: ["ignore", "pipe", "ignore"],
181
+ }).trim();
182
+ const parsed = JSON.parse(result.replace(/```json?\n?/g, "").replace(/```/g, "").trim());
183
+ labels = parsed.labels?.length >= 4 ? parsed.labels : null;
184
+ overlays = parsed.overlays?.length >= 4 ? parsed.overlays : null;
185
+ } catch { /* fall through */ }
186
+ if (!labels) labels = ["Overview", "Interact", "Navigate", "Result"];
187
+ if (!overlays) overlays = ["**First look**", "**Key action**", "**Exploring**", "**The result**"];
169
188
 
170
189
  // Estimate video duration from last click or default to 25s
171
190
  const lastClickTime = clicks.length > 0 ? clicks[clicks.length - 1].timeSec : 0;
@@ -409,7 +428,7 @@ async function main() {
409
428
  const castPath = recordCLI(demoCmd, process.cwd(), prompt);
410
429
 
411
430
  console.error("Step 2/3: Extracting highlights...");
412
- const highlightsPath = extractHighlightsFromCast(castPath, prompt);
431
+ const highlightsPath = extractHighlightsFromCast(castPath, prompt, flags.guidelines);
413
432
  const highlights = JSON.parse(readFileSync(highlightsPath, "utf-8"));
414
433
  console.error(` ${highlights.length} highlights extracted`);
415
434
 
@@ -449,7 +468,7 @@ async function main() {
449
468
  console.error(` ${allClicks.length} clicks captured`);
450
469
  }
451
470
 
452
- const highlights = buildBrowserHighlights(allClicks, videoPath, task);
471
+ const highlights = buildBrowserHighlights(allClicks, videoPath, task, flags.guidelines);
453
472
 
454
473
  console.error("Step 3/3: Rendering video...");
455
474
  await renderVideo({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentreel",
3
- "version": "0.3.3",
3
+ "version": "0.3.4",
4
4
  "description": "Turn your web apps and CLIs into viral clips",
5
5
  "bin": {
6
6
  "agentreel": "./bin/agentreel.mjs"
@@ -195,7 +195,7 @@ def record_demo(steps: list[dict], workdir: str, output_path: str):
195
195
  print(f"Saved: {output_path}", file=sys.stderr)
196
196
 
197
197
 
198
- def extract_highlights(cast_path: str, context: str) -> list[dict]:
198
+ def extract_highlights(cast_path: str, context: str, guidelines: str = "") -> list[dict]:
199
199
  """Ask Claude to pick 3-4 highlight moments from the recorded session."""
200
200
  # Read the asciicast and strip to just the text content
201
201
  lines_output = []
@@ -214,13 +214,15 @@ def extract_highlights(cast_path: str, context: str) -> list[dict]:
214
214
  # Clean ANSI for Claude to read, but keep the raw for display
215
215
  clean = re.sub(r'\x1b\[[0-9;]*[a-zA-Z]', '', raw_output)
216
216
 
217
+ guidelines_block = f"\n\nAdditional guidelines: {guidelines}" if guidelines else ""
218
+
217
219
  prompt = f"""You are creating a highlights reel for a CLI tool demo video. Here is the full terminal output:
218
220
 
219
221
  ---
220
222
  {clean[:3000]}
221
223
  ---
222
224
 
223
- Context: {context}
225
+ Context: {context}{guidelines_block}
224
226
 
225
227
  Pick 3-4 highlight moments that would look impressive in a short video. For each highlight, return:
226
228
  - "label": short label (1-2 words) like "Initialize", "Configure", "Run", "Results"
@@ -274,8 +276,9 @@ if __name__ == "__main__":
274
276
  cast_file = sys.argv[2]
275
277
  output = sys.argv[3]
276
278
  context = sys.argv[4] if len(sys.argv) > 4 else ""
279
+ guidelines = sys.argv[5] if len(sys.argv) > 5 else ""
277
280
  print(f"Extracting highlights from: {cast_file}", file=sys.stderr)
278
- highlights = extract_highlights(cast_file, context)
281
+ highlights = extract_highlights(cast_file, context, guidelines)
279
282
  with open(output, "w") as f:
280
283
  json.dump(highlights, f, indent=2)
281
284
  print(f"Saved {len(highlights)} highlights to: {output}", file=sys.stderr)