Skip to content

fix(studio): Fix sometimes not being able to select an option on the Code Agent#490

Open
htolentino-nvidia wants to merge 3 commits into
mainfrom
studio-fix-code-agent-input/htolentino
Open

fix(studio): Fix sometimes not being able to select an option on the Code Agent#490
htolentino-nvidia wants to merge 3 commits into
mainfrom
studio-fix-code-agent-input/htolentino

Conversation

@htolentino-nvidia

@htolentino-nvidia htolentino-nvidia commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features
    • Studio-mediated permission/input requests now explicitly report when they expire, allowing the chat runtime to recover by moving to the next queued request.
    • Send action in decision flows is now always visible and clearly labeled.
  • Bug Fixes
    • Send is disabled until the selected choice is ready to submit (e.g., required text input provided).
    • Dataset file blocking inputs no longer allow submission until a dataset file is selected.
    • Decision flow selection state now resets correctly when requests change, preventing stale disabled states.

Signed-off-by: Henrique Tolentino <htolentino@nvidia.com>
@htolentino-nvidia htolentino-nvidia requested review from a team as code owners June 26, 2026 20:06
@github-actions github-actions Bot added the fix label Jun 26, 2026
@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: e70246ec-4855-4f52-9555-445300d4295c

📥 Commits

Reviewing files that changed from the base of the PR and between 7952a4e and 8e3c42f.

📒 Files selected for processing (1)
  • web/packages/studio/src/routes/agents/ClaudeCodeChatRoute/useClaudeCodeChatRuntime.ts

📝 Walkthrough

Walkthrough

Studio now emits expired permission/input events, forwards them through SSE, clears matching runtime state, and updates agent submit behavior so Send and file submit are disabled until inputs are ready.

Changes

Claude expiration events and input gating

Layer / File(s) Summary
Backend expiration signals
services/studio/src/nmp/studio/coding_agents.py
Timeouts now enqueue permission_expired and input_expired events, and _stream_claude forwards those queued events to Studio SSE.
Stream handler expiration support
web/packages/studio/src/routes/agents/ClaudeCodeChatRoute/types.ts, web/packages/studio/src/routes/agents/ClaudeCodeChatRoute/api.ts, web/packages/studio/src/routes/agents/ClaudeCodeChatRoute/api.test.ts
The SSE handler interface and parser now recognize expiration events, and tests cover the new callbacks for expired permission and input requests.
Runtime and thread reset
web/packages/studio/src/routes/agents/ClaudeCodeChatRoute/useClaudeCodeChatRuntime.ts, web/packages/studio/src/routes/agents/ClaudeCodeChatRoute/ClaudeCodeChatThread.tsx
Expired events clear active permission/input state and dequeue the next request, and decision inputs are keyed by request ID.
Decision and fileset submit gates
web/packages/studio/src/components/agents/AgentDecisionInput/index.tsx, web/packages/studio/src/components/agents/AgentDecisionInput/index.test.tsx, web/packages/studio/src/components/agents/AgentBlockingInput/FilesetFileBlockingInput.tsx
AgentDecisionInput keeps Send visible with input-aware disabling, its tests reflect the new request-reset behavior, and fileset blocking input disables submit until a dataset file is selected.

Possibly related PRs

Suggested reviewers

  • dmariali
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the main fix: Code Agent option/input selection can now complete reliably.
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
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch studio-fix-code-agent-input/htolentino

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

@github-actions

github-actions Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor
Suite Lines Covered Line Rate Branch Rate
Unit Tests 21898/28725 76.2% 61.0%
Integration Tests 12583/27405 45.9% 19.2%

Signed-off-by: Henrique Tolentino <htolentino@nvidia.com>

@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 `@web/packages/studio/src/routes/agents/ClaudeCodeChatRoute/api.ts`:
- Around line 392-406: The permission_expired and input_expired handlers in
ClaudeCodeChatRoute/api.ts currently return success even when payload.request_id
is missing or invalid, which lets malformed expiration events get dropped
silently. Update the event handling in the same switch/if chain that processes
permission_request and input_request so these branches fail closed: parse the
payload, validate request_id, and if it is absent or not a string, call
handlers.onError with a clear message instead of returning true. Keep the
existing onPermissionExpired/onInputExpired calls only for valid request_id
values.
🪄 Autofix (Beta)

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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: c6775a72-6287-47f7-84ac-b523b69256f0

📥 Commits

Reviewing files that changed from the base of the PR and between 9dc2e8d and 7952a4e.

📒 Files selected for processing (7)
  • services/studio/src/nmp/studio/coding_agents.py
  • web/packages/studio/src/components/agents/AgentDecisionInput/index.test.tsx
  • web/packages/studio/src/routes/agents/ClaudeCodeChatRoute/ClaudeCodeChatThread.tsx
  • web/packages/studio/src/routes/agents/ClaudeCodeChatRoute/api.test.ts
  • web/packages/studio/src/routes/agents/ClaudeCodeChatRoute/api.ts
  • web/packages/studio/src/routes/agents/ClaudeCodeChatRoute/types.ts
  • web/packages/studio/src/routes/agents/ClaudeCodeChatRoute/useClaudeCodeChatRuntime.ts
✅ Files skipped from review due to trivial changes (1)
  • web/packages/studio/src/routes/agents/ClaudeCodeChatRoute/types.ts

Comment on lines +392 to +406
if (event.event === 'permission_expired') {
const payload = parseJsonObject(event.data);
if (isRecord(payload) && typeof payload.request_id === 'string') {
handlers.onPermissionExpired?.(payload.request_id);
}
return true;
}

if (event.event === 'input_expired') {
const payload = parseJsonObject(event.data);
if (isRecord(payload) && typeof payload.request_id === 'string') {
handlers.onInputExpired?.(payload.request_id);
}
return true;
}

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 | 🟡 Minor | ⚡ Quick win

Fail closed on malformed expiration events.

If request_id is missing here, the event is silently dropped and the blocking UI never clears. Match the permission_request / input_request branches and surface onError instead of returning success.

Suggested fix
   if (event.event === 'permission_expired') {
     const payload = parseJsonObject(event.data);
-    if (isRecord(payload) && typeof payload.request_id === 'string') {
-      handlers.onPermissionExpired?.(payload.request_id);
-    }
-    return true;
+    if (!isRecord(payload) || typeof payload.request_id !== 'string') {
+      handlers.onError(new Error('Claude Code permission expiration was malformed'));
+      return false;
+    }
+    handlers.onPermissionExpired?.(payload.request_id);
+    return true;
   }

   if (event.event === 'input_expired') {
     const payload = parseJsonObject(event.data);
-    if (isRecord(payload) && typeof payload.request_id === 'string') {
-      handlers.onInputExpired?.(payload.request_id);
-    }
-    return true;
+    if (!isRecord(payload) || typeof payload.request_id !== 'string') {
+      handlers.onError(new Error('Claude Code input expiration was malformed'));
+      return false;
+    }
+    handlers.onInputExpired?.(payload.request_id);
+    return true;
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (event.event === 'permission_expired') {
const payload = parseJsonObject(event.data);
if (isRecord(payload) && typeof payload.request_id === 'string') {
handlers.onPermissionExpired?.(payload.request_id);
}
return true;
}
if (event.event === 'input_expired') {
const payload = parseJsonObject(event.data);
if (isRecord(payload) && typeof payload.request_id === 'string') {
handlers.onInputExpired?.(payload.request_id);
}
return true;
}
if (event.event === 'permission_expired') {
const payload = parseJsonObject(event.data);
if (!isRecord(payload) || typeof payload.request_id !== 'string') {
handlers.onError(new Error('Claude Code permission expiration was malformed'));
return false;
}
handlers.onPermissionExpired?.(payload.request_id);
return true;
}
if (event.event === 'input_expired') {
const payload = parseJsonObject(event.data);
if (!isRecord(payload) || typeof payload.request_id !== 'string') {
handlers.onError(new Error('Claude Code input expiration was malformed'));
return false;
}
handlers.onInputExpired?.(payload.request_id);
return true;
}
🤖 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 `@web/packages/studio/src/routes/agents/ClaudeCodeChatRoute/api.ts` around
lines 392 - 406, The permission_expired and input_expired handlers in
ClaudeCodeChatRoute/api.ts currently return success even when payload.request_id
is missing or invalid, which lets malformed expiration events get dropped
silently. Update the event handling in the same switch/if chain that processes
permission_request and input_request so these branches fail closed: parse the
payload, validate request_id, and if it is absent or not a string, call
handlers.onError with a clear message instead of returning true. Keep the
existing onPermissionExpired/onInputExpired calls only for valid request_id
values.

Signed-off-by: Henrique Tolentino <htolentino@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant