Skip to content

Request batches and obs-batch - #9

Merged
Tom-R-Main merged 2 commits into
mainfrom
improve/batch
Sep 24, 2026
Merged

Tom-R-Main merged 2 commits into
mainfrom
improve/batch

Conversation

@Tom-R-Main

Copy link
Copy Markdown
Owner

Stacked on #8.

What

  • client.sendBatch(requests, {executionType, haltOnFailure}) sends one RequestBatch (op 8) and returns a result per request. One failed request doesn't fail the rest. The timeout grows by the batch's own Sleep time.
  • New obs-batch tool: serial-realtime, serial-frame (one request per rendered frame, so changes to two sources land on the same frame) or parallel, with Sleep between requests.
    • Refuses unknown request types.
    • Refuses Sleep in parallel batches.
    • Reports what succeeded, what failed and what was skipped.
  • With OBS_MCP_CONFIRM_LIVE, obs-batch and obs-call-request now ask before sending StopStream, ToggleStream, StopRecord or ToggleRecord. Before this, obs-call-request could stop a stream without asking.
  • obs-preflight reads every input's audio state in one batch (2×N requests became 1 message). obs-capture-window silences the capture in one batch.
  • Fake OBS: answers batches from the same scripts and responders, and records each batched request in history().

obs-batch has no outputSchema: a cancelled confirmation returns {message}, which would fail it. It still returns structuredContent, like obs-call-request.

Tests

  • npm run check passes: 125 unit, 11 e2e. Tool count is now 159; the contract snapshot is updated.
  • Live read-only suite against OBS 32.2.2: 5 passed, 2 skipped. This includes a new read-only batch test (parallel with one missing input; serial-frame with Sleep 6 frames). It ran with OBS_MCP_READ_OBS_CONFIG=1 from Opt-in: use the WebSocket password OBS saved #8, so no password was exported.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Vjn8uBEa4mJshaQU3pFuqX

The client's sendBatch sends several requests in one RequestBatch message
and returns each request's result; a failed request no longer fails its
neighbours. obs-batch exposes it with the three OBS execution types, so a
serial-frame batch can change two sources on the same frame and pause with
Sleep. With OBS_MCP_CONFIRM_LIVE, obs-batch and obs-call-request now ask
before sending a request that stops or toggles a stream or recording.

obs-preflight reads every input's mute state and tracks in one batch, and
obs-capture-window silences a capture in one. The fake OBS answers batches
from the same scripts and responders, and records each batched request.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vjn8uBEa4mJshaQU3pFuqX
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-24T00:42:55.937430Z 39b7331 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 39b73313ec

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/tools/protocol.ts
}

try {
const batch = await client.sendBatch(requests, { executionType: EXECUTION_TYPES[executionType], haltOnFailure });

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Disallow halt-on-failure in parallel mode

When executionType is parallel and haltOnFailure is true, forwarding both options cannot provide the promised “skip remaining requests” behavior: OBS starts the requests concurrently, so a later mutation may already execute before an earlier failure is observed. This is especially dangerous when callers treat the reported skipped count as proof that those mutations did not run; reject this combination or avoid claiming that omitted parallel results were skipped.

Useful? React with 👍 / 👎.

Comment thread src/client.ts
Comment on lines +194 to +200
/** Wall-clock time a batch spends in Sleep requests, assuming 30 fps for frames. */
function batchSleepMillis(requests: readonly BatchRequest[]): number {
let total = 0;
for (const { requestType, requestData } of requests) {
if (requestType !== "Sleep" || !isObject(requestData)) continue;
if (typeof requestData.sleepMillis === "number") total += requestData.sleepMillis;
if (typeof requestData.sleepFrames === "number") total += (requestData.sleepFrames / 30) * 1000;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Base frame-sleep timeouts on OBS's actual frame rate

For a serial-frame batch, sleepFrames is measured at OBS's configured frame rate, but this timeout extension hard-codes 30 fps. At 24 fps, for example, a valid 10,000-frame sleep takes about 417 seconds while the client times out after about 343 seconds; OBS is not cancelled by that local timeout and can subsequently execute the remaining requests after the tool has reported failure. Derive the duration from OBS's video settings or otherwise use a conservative timeout for frame sleeps.

Useful? React with 👍 / 👎.

In obs-websocket 5.7, a parallel batch holds a thread-pool thread while it
waits for its requests on the same pool (RequestBatchHandler.cpp), so a few
concurrent parallel batches deadlock the WebSocket server until OBS
restarts. Its results are also collected in completion order, so they came
back matched to the wrong requests: live, GetInputSettings for a color
source was reported as failing with "does not support audio".

Every internal batch now runs serial-realtime, still one round trip.
obs-batch no longer offers parallel. Each batched request carries its index
as its ID and results are matched by ID. The live test now checks each
result's position.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vjn8uBEa4mJshaQU3pFuqX
@Tom-R-Main

Copy link
Copy Markdown
Owner Author

Update: parallel batches are removed. obs-websocket 5.7 returns parallel results in completion order (mismatched to their requests) and deadlocks its WebSocket server under concurrent parallel batches. See commit "Stop using parallel request batches". Every internal batch is now serial, and obs-batch no longer offers parallel.

@Tom-R-Main
Tom-R-Main changed the base branch from improve/password-fallback to main September 24, 2026 05:11
@Tom-R-Main
Tom-R-Main merged commit bae59fe into main Sep 24, 2026
4 checks passed
@Tom-R-Main
Tom-R-Main deleted the improve/batch branch September 24, 2026 05:13
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