Skip to content

fix(agent): stop cutting the transcript at the 800th word - #256

Open
EtienneLescot wants to merge 2 commits into
mainfrom
fix/transcript-no-cap
Open

fix(agent): stop cutting the transcript at the 800th word#256
EtienneLescot wants to merge 2 commits into
mainfrom
fix/transcript-no-cap

Conversation

@EtienneLescot

@EtienneLescot EtienneLescot commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

Summary

Ask the agent to remove the silences from a 30-minute recording and it works on the first five minutes, then reports the job done.

getTranscript sliced at 800 segments:

// ponytail: segments only — words would blow the context for long
// recordings and the segment text already carries the content.
const segments = transcript.segments.slice(0, 800).map(...)

The comment is inverted. On the production path a segment is one wordsrc/lib/captioning/transcribe.ts maps whisper's word timings one-to-one, and the real fixture has 129 words for 129 segments. So the cap cut at the 800th word, not the 800th phrase.

The arithmetic lands on the reported symptom: 129 words / 66.15 s = 1.95 words/s puts word 800 at 6 min 50 s; at 160 wpm it is 300 s exactly. Five minutes out of thirty.

And it was silent. The payload is {assetId, language, segments} — no truncated, no totalSegments — while the tool description promises the transcript for the asset. The model had no way to know it was reading a fifth of the recording, so it trimmed what it saw and called it finished. getCursorTrack next door does report truncation, with a comment saying that is how the model learns it.

Saying "continue" does not recover it: the history sent back to the model carries message text, not tool results, so the next turn re-reads the same 800 words.

Removed rather than raised. A whole 30-minute transcript is ~285k characters, ~70k tokens — well inside every model this app talks to. The cap was a guess, not a measurement. If a recording ever does approach a context window, the fix is to know the window; there is no per-model context budget in the app today, and picking a new number here would only move the silence somewhere else.

Related issue

Refs #217 — the measured-leads document describes this class of defect (absence treated as a non-event); this is an instance of it found from a user report.

Type of change

  • Bug fix

Release impact

  • Patch

Desktop impact

  • Not platform-specific

Testing

New case in agent-tools.test.ts: a 4000-word transcript (about half an hour of speech) must come back whole. It asserts the last word, not just the count — a cap keeps the head and drops the tail, so the tail is what proves it is gone. Restoring the .slice(0, 800) turns it red (expected […] to have a length of 4000 but got 800) and leaves the other sixty green.

  • npm test: 137 files, 1626 passed.
  • npm run wb:l0: unchanged (44 pre-existing failures, all the unversioned real fixture).
  • npx tsc --noEmit and biome clean.

The workbench already carried a longTranscript fixture whose comment documented this exact defect — never wired to a scenario. Its comment now states the behaviour instead of a to-do.

Known follow-up

Even with the whole transcript, replaceTimeline is forbidden for cut-silences by its own description, so the agent must emit one addTrim per silence, serially. On thirty minutes that is hundreds of round trips. That is the batch-tool lead in #217 and is not addressed here.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Fixed transcript retrieval truncation for long transcripts.
    • AI-assisted transcript access now returns all available word-level segments, including the final segment.
  • Documentation

    • Updated transcript tool documentation to reflect that no 800-segment limit applies.

`getTranscript` sliced at 800 segments under a comment reading "segments only —
words would blow the context", written believing a segment was a phrase. On the
production path a segment IS one word: whisper's word timings are mapped
one-to-one in src/lib/captioning/transcribe.ts, and the real fixture has 129
words for 129 segments.

So the cap cut at the 800th WORD. At a normal speaking rate that is the fifth
minute, and nothing in the payload said so — the model read a sixth of a
half-hour recording, trimmed the silences it could see, and reported the job
done. Asking it afterwards does not help either: the history sent back carries
message text, not tool results, so the next turn re-reads the same 800 words.

A whole 30-minute transcript is ~285k characters, ~70k tokens — well inside every
model this app talks to. The cap was a guess, not a measurement, so it is gone
rather than raised. If a recording ever does approach a window, the fix is to
know the window; there is no per-model context budget in the app today, and
picking another number here would only move the silence.

The workbench already carried a `longTranscript` fixture documenting this defect
and never wired it to a scenario. Its comment is now true instead of a to-do.
@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

getTranscript no longer limits results to 800 segments. A regression test validates 4,000 segments, and documentation plus fixture comments describe the uncapped behavior.

Changes

Transcript retrieval

Layer / File(s) Summary
Remove transcript truncation
electron/ai-edition/agent-tools.ts, electron/ai-edition/agent-tools.test.ts
getTranscript now returns every transcript segment. The regression test checks all 4,000 segments and the final segment.
Update transcript references
technical-documentation/architecture/ai-agent.md, workbench/lib/fixtures.ts
Documentation and fixture comments describe transcript handling without the former 800-segment limit.

Estimated code review effort: 2 (Simple) | ~10 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main fix: preventing getTranscript from truncating transcripts at 800 words.
Description check ✅ Passed The description covers the change, related issue, classification, release and desktop impact, testing, and known follow-up.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/transcript-no-cap

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

`ai-agent.md` still announced "up to 800 transcript segments" — the number this
branch removed, and the one that quietly cut a half-hour recording at its fifth
minute. Reference that repeats a limit the code dropped is how the limit gets
re-added.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@electron/ai-edition/agent-tools.test.ts`:
- Around line 215-221: Update the generated segment objects in the transcript
fixture around the segments array to include the required wordIds field, using
an empty array for every segment while preserving the existing id, timing, kind,
and text values.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 257d65f3-b1c4-4668-8318-3fb46ddd31da

📥 Commits

Reviewing files that changed from the base of the PR and between 1749d84 and 526f4e1.

📒 Files selected for processing (4)
  • electron/ai-edition/agent-tools.test.ts
  • electron/ai-edition/agent-tools.ts
  • technical-documentation/architecture/ai-agent.md
  • workbench/lib/fixtures.ts

Comment on lines +215 to +221
const segments = Array.from({ length: 4000 }, (_, i) => ({
id: `seg_${i}`,
kind: "speech" as const,
startSec: i * 0.45,
endSec: i * 0.45 + 0.4,
text: `mot${i}`,
}));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n -C 3 '\bwordIds\b' electron/ai-edition workbench/lib --glob '*.ts'

Repository: getopenscreen/openscreen

Length of output: 4739


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the relevant test file and any AxcutDocument/type declarations used by the failing line.
sed -n '1,260p' electron/ai-edition/agent-tools.test.ts
printf '\n--- type references in files ---\n'
rg -n 'interface AxcutDocument|type AxcutDocument|AxcutDocument|documentSchema|wordIds' --glob '*.ts' .

Repository: getopenscreen/openscreen

Length of output: 50380


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- schema transcript definitions --- '
rg -n -C 4 'AxcutTranscriptSegment|wordIds|transcript' src/lib/ai-edition/schema.ts
printf '\n--- schema file outline around definitions ---\n'
nl -ba src/lib/ai-edition/schema.ts | sed -n '1,260p'

printf '\n--- read-only structural check: generated segments lack wordIds ---\n'
python3 - <<'PY'
from pathlib import Path
text = Path("electron/ai-edition/agent-tools.test.ts").read_text()
needle = 'const segments = Array.from({ length: 4000 }, (_, i) => ({'
idx = text.index(needle)
block = text[idx:text.find("\n\t\t});", idx)]
print("wordIds" in block)
print(block)
PY

Repository: getopenscreen/openscreen

Length of output: 330


🏁 Script executed:

#!/bin/bash
set -euo pipefail

fd -a 'schema\.ts$' . | sed 's#^\./##'
printf '%s\n' '--- schema path candidates ---'
for f in $(fd 'schema\.ts$' .); do
  echo "FOUND $f"
done

printf '%s\n' '--- references to schema module ---'
rg -n 'from ["'\''][^"'\'']*ai-edition/schema' --glob '*.ts' .

Repository: getopenscreen/openscreen

Length of output: 4841


Add wordIds to each generated transcript segment.

This is an AxcutDocument, so transcript segments need the schema field shown in the other transcript fixtures. Add wordIds: [] to the generated objects.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@electron/ai-edition/agent-tools.test.ts` around lines 215 - 221, Update the
generated segment objects in the transcript fixture around the segments array to
include the required wordIds field, using an empty array for every segment while
preserving the existing id, timing, kind, and text values.

Source: Linters/SAST tools

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant