Skip to content

fix(terminal): one automation-pacing composable that clears its timers, and i18n for the terminal output lines (#16396, #17942, #17946) - #17950

Merged
mrveiss merged 3 commits into
mainfrom
issue-16396-17942-automation-pacing
Oct 4, 2026
Merged

mrveiss merged 3 commits into
mainfrom
issue-16396-17942-automation-pacing

Conversation

@mrveiss

@mrveiss mrveiss commented Oct 4, 2026 •

Copy link
Copy Markdown
Owner

Thinking Path

#16396 reported uncleared automation-pacing setTimeout chains in two components. Those chains turned out to be one piece of logic implemented twice, inline in TerminalWindow.vue and in WorkflowAutomation.vue. Fixing the leak in both copies would have grown two oversized files and kept the duplicate. So the pacing moves into one composable that owns its timers and clears them on scope dispose (#17942), and the leak is fixed once.

Both files also wrote every terminal output line, and the duplicated demo workflow, in hard-coded English (#17946). Issues touching the same files go in one PR, so the i18n work rides here too.

#16395, filed alongside #16396, was already delivered by #16313's withTimeout and was closed with evidence; this PR does not touch it.

What Changed

  • composables/useAutomationPacing.ts (new). useAutomationPacing provides processNextAutomationStep, scheduleNextAutomationStep, startFirstAutomationStep and scheduleTracked. Every timer it starts is tracked and cleared in onScopeDispose. It also exposes:
    • buildAutomationSteps: the queue shape, previously built twice
    • workflowStartedLines
    • exampleWorkflow(t): the demo workflow, previously duplicated verbatim
    • named delay constants for the existing 1000/2000/1500 ms values
  • TerminalWindow.vue:
    • uses the composable
    • its two nested focus-retry timers ride scheduleTracked, so they are cleared on unmount too
    • the cursor-blink setInterval was never stored; it is now cleared in onUnmounted (found in review)
    • 1787 → 1726 lines
  • WorkflowAutomation.vue: uses the composable; 422 → 327 lines. Its props, emits and exposed methods are unchanged.
  • i18n: terminal.automation.* and terminal.events.* in all 11 locales, 31 keys with matching {command}/{name}/{count}/{step}/{total}/{description}/{message}/{error} placeholders. The only content: literal left in either file is the ${currentPrompt}${command} echo, which is not UI text.
  • Tests:

Merge order: the frontend file-size ratchet branch is held until this lands, coordinated with the session that owns it.

Follow-up filed, not in scope: #17943. TerminalWindow is half-decomposed, and four extracted components (WorkflowAutomation, TerminalInput, TerminalOutput, TerminalStatusBar) are mounted nowhere. It is blocked_by #17942.

Closes #16396
Closes #17942
Closes #17946

Verification

Local, in autobot-frontend/:

  • npx oxlint <changed files>: rc=0
  • npx eslint <changed files>: rc=0
  • npx vue-tsc --noEmit -p tsconfig.app.json: rc=0, 0 error TS
  • pre-commit hooks passed on all three commits, including check json, the t(plural-key, {count}) check, hardcoded values, and Canonical check — Frontend

The test suites run in CI; the repo rule is not to run codebase code locally.

A code-reviewer pass on the first commit found no blocking defects. Its two low findings were the missing per-component unmount test and the cursor-blink interval; both are fixed in f49b346208.

Model Used

Claude Opus 5.5 (claude-opus-5-5); review subagent on Sonnet.

🤖 Generated with Claude Code

…s on unmount (#16396, #17942)

TerminalWindow and WorkflowAutomation each carried a copy of the step
pacing (1000/2000/1500 ms setTimeout chains) and neither cleared it on
unmount. useAutomationPacing now owns the queue/step pacing, tracks every
timer and clears them in onScopeDispose; TerminalWindow's focus-retry
timers ride the same tracker. The workflow-start messages and the default
step description move to terminal.automation.* in all 11 locales.

TerminalWindow.vue 1787 -> 1755 lines, WorkflowAutomation.vue 422 -> 358.
…the cursor-blink interval (#16396, #17942)

Review of the composable commit: #16396 asks for a fake-timers test per
component, and the composable test only used a bare effectScope. The new
file mounts TerminalWindow and WorkflowAutomation and proves no pacing
callback fires after unmount. TerminalWindow's cursor-blink setInterval
was never stored or cleared; it is now cleared in onUnmounted.
…demo workflow once (#17946, #17942)

The 29 remaining hard-coded English output lines in TerminalWindow and
WorkflowAutomation move to terminal.automation.* and terminal.events.* in
all 11 locales. The demo workflow, duplicated verbatim in both components,
becomes exampleWorkflow(t) in useAutomationPacing.

TerminalWindow.vue 1758 -> 1726 lines, WorkflowAutomation.vue 358 -> 327.
@coderabbitai

coderabbitai Bot commented Oct 4, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 55 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Repository: mrveiss/AutoBot-AI/.coderabbit.yaml
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: a0433357-8416-4ea3-bf2b-6d96816f7a6a
📥 Commits

Reviewing files that changed from the base of the PR and between 5c02466 and 71c0dbc.

📒 Files selected for processing (16)
  • autobot-frontend/src/components/__tests__/TerminalAutomationUnmount.test.ts
  • autobot-frontend/src/components/terminal/TerminalWindow.vue
  • autobot-frontend/src/components/terminal/WorkflowAutomation.vue
  • autobot-frontend/src/composables/__tests__/useAutomationPacing.test.ts
  • autobot-frontend/src/composables/useAutomationPacing.ts
  • autobot-frontend/src/i18n/locales/ar.json
  • autobot-frontend/src/i18n/locales/de.json
  • autobot-frontend/src/i18n/locales/en.json
  • autobot-frontend/src/i18n/locales/es.json
  • autobot-frontend/src/i18n/locales/fa.json
  • autobot-frontend/src/i18n/locales/fr.json
  • autobot-frontend/src/i18n/locales/he.json
  • autobot-frontend/src/i18n/locales/lv.json
  • autobot-frontend/src/i18n/locales/pl.json
  • autobot-frontend/src/i18n/locales/pt.json
  • autobot-frontend/src/i18n/locales/ur.json
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@github-actions

github-actions Bot commented Oct 4, 2026

Copy link
Copy Markdown
Contributor

✅ SSOT Configuration Compliance: Passing

🎉 No new hardcoded values of either class — ssot and other both block.

Known backlog in pipeline-scripts/hardcoded_values_baseline.txt is suppressed and tracked in #14371.

@mrveiss
mrveiss merged commit 8bd2d70 into main Oct 4, 2026
61 of 66 checks passed
@mrveiss
mrveiss deleted the issue-16396-17942-automation-pacing branch October 4, 2026 09:45
mrveiss added a commit that referenced this pull request Oct 4, 2026
…lish (#17946)

#17950 shipped terminal.automation.manualCommand (es, pt) and
terminal.events.error (es) with values identical to English, so the
untranslated-strings ratchet failed: es 1665 > 1663, pt 2059 > 2058.
mrveiss added a commit that referenced this pull request Oct 4, 2026
…d the stream socket carries its credential (#13102, #17004)

* fix(voice): shape the spoken copy of replies for speech, and authenticate the TTS stream socket (#13102, #17004)

Replies were read aloud as symbol soup: markdown, URLs, file paths and
fenced code. createSpeechShaper (utils/ttsSentences) shapes only the
spoken copy -- links to their text, inline code to its contents, URLs and
paths to a localized placeholder, fenced blocks dropped with fence state
and a split ``` marker carried across streamed slices. ChatInterface's
streaming path and useVoiceConversation's reply path both use it; the
transcript and the streaming cursor still run on the raw text.

The TTS stream WebSocket opened with no credential, so the authenticated
/api/voice/stream route closed every connection with 4001. It now sends
the bearer subprotocol like the other migrated clients.

* test(voice): the pre-roll suite mocks the TTS socket's auth helper (#17004)

The bearer subprotocol comes from buildAuthenticatedWsSubprotocols, which
reads the user store. The pre-roll suite has no active Pinia, so the call
threw inside _connectTtsWs before the WebSocket was constructed and all 18
cases timed out waiting for the socket. Production always has Pinia.

* i18n(terminal): translate the three terminal strings es/pt had as English (#17946)

#17950 shipped terminal.automation.manualCommand (es, pt) and
terminal.events.error (es) with values identical to English, so the
untranslated-strings ratchet failed: es 1665 > 1663, pt 2059 > 2058.

* fix(voice): fences open and close only at line start by CommonMark's rules, the shaper sees exact spans, and priming reads skipped text (#13102, #17953)

Review on #17954:
- split('```') treated an inline ``` as a fence and dropped the prose after
  it, and let a shorter ``` line close a four-backtick block. Fences now open
  and close only at line start; a close needs the same character and at
  least the opening length. ~~~ fences are handled too (#17953, part).
- extractCompleteSentences also returns exact spans with their whole
  trailing whitespace, so a newline before a fence is never lost between
  slices; the stream-end remainder keeps its leading newline.
- _primeTtsCursor feeds the skipped text to a fresh shaper unspoken, so a
  fence already open when voice is enabled stays closed to TTS.
- Windows drive paths (C:\\Users\\...) are spoken as the path placeholder.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment