fix(agentex-ui): hydrate agent from task on deep-link, drop inaccessible task_id#356
Open
erichwoo-scale wants to merge 1 commit into
Open
fix(agentex-ui): hydrate agent from task on deep-link, drop inaccessible task_id#356erichwoo-scale wants to merge 1 commit into
erichwoo-scale wants to merge 1 commit into
Conversation
60ba5cc to
1ddd754
Compare
…ble task_id A URL carrying only task_id (a shared or hand-built link) left the agent pill empty, and a task the caller can't see showed a phantom task view. - ChatView fills agent_name from the task's own (access-checked) agent when the URL omits it, and drops task_id on a 403/404 retrieve instead of leaving a phantom. - agentex-ui-root no longer restores the last-used agent from storage while a task is open, so it can't override the task's agent. Access is unchanged: the BFF attaches credentials server-side and account_id is only a selector, so this can only surface tasks/agents the caller was already authorized to load. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1ddd754 to
32bd3f2
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
A URL carrying only
task_id(a shared link, or one built by hand) had two rough edges:agent_name), andtask_idthe caller can't access (or one that doesn't exist) showed a phantom task view instead of failing cleanly.Fix
chat-view.tsx— hydrateagent_namefrom the task's own agent (task.agents[0].name) when the URL omits it. That agent comes from the access-checked task retrieve (relationships: ['agents']), so it can only ever be an agent the caller was already allowed to load.chat-view.tsx— if the task retrieve fails 403/404, cleartask_id(+agent_name) so you land on the home grid rather than a phantom. Other errors (5xx/network) are treated as transient and left alone — matching the existinguseAgentByNameconvention.agentex-ui-root.tsx— don't restore the last-used agent fromlocalStoragewhile a task is open; the task defines the agent, so this prevents storage from overriding the hydrated value.Security note
Access control is unchanged and enforced server-side: the BFF attaches credentials server-side (session token / cookies) and
account_idis only a selector, never a credential. The browser holds no token to forge. So URL manipulation can't reach a task/agent the authenticated principal isn't authorized for — a craftedtask_idresolves only if the API authorizes it, otherwise it 403/404s and this PR drops it.Test plan
npm run typecheck✓npx vitest run— 47/47 ✓npm run lint✓?task_id=<own task>with noagent_name→ pill fills from the task;?task_id=<foreign/bogus>→ 403/404 → returns to home grid.Independent of #355 (no file overlap); merges in any order.
Greptile Summary
This PR fixes two rough edges with deep-link
?task_id=navigation: the agent pill now hydrates from the task's own agent when the URL omitsagent_name, and an inaccessible or nonexistenttask_id(4xx) is cleared instead of showing a phantom task view.chat-view.tsx— addsuseTask(withrelationships: ['agents']) to populateagent_namein the URL when it is absent, and a second effect that drops bothtask_idandagent_nameon any non-401/non-429 4xx response.agentex-ui-root.tsx— adds!taskIDguards to the validate/clear and localStorage-restore branches, preventing the ping-pong described in the prior review thread where the root's clearing effect fought ChatView's hydration effect when the task's agent was non-Ready.use-tasks.ts— tightens the retry policy so 4xx errors fail fast (no retry backoff) while 5xx/network errors still retry up to 3 times.Confidence Score: 5/5
Safe to merge — the change is well-scoped, correctly handles the known edge cases, and the prior ping-pong concern has been addressed.
All three modified files contain focused, defensive logic. The hydration effect correctly guards on both agentName and taskAgentName, the 4xx-clear effect's status range matches the retry predicate in useTask, and the !taskID guards in the root break the previously-reported cycle. React Query deduplicates the extra useTask call added to ChatView against whatever the inner TaskProvider fetches with the same query key.
No files require special attention.
Important Files Changed
Sequence Diagram
%%{init: {'theme': 'neutral'}}%% sequenceDiagram participant URL as URL / Router participant Root as AgentexUIRoot participant ChatView as ChatView participant API as Backend API note over URL: ?task_id=TASK-123 (no agent_name) Root->>Root: "effect runs — taskID truthy,<br/>!taskID guards skip both branches" ChatView->>API: "useTask(TASK-123, {relationships: ['agents']})" alt Task accessible (2xx) API-->>ChatView: "task { agents: [{name: "my-agent"}] }" ChatView->>URL: "updateParams({ agent_name: "my-agent" }, replace)" Root->>Root: "effect re-runs — agentName set,<br/>taskID set — both branches still skip" else Task inaccessible (403/404) API-->>ChatView: "APIError { status: 403 }" note over ChatView: retry policy: no retry for 4xx ChatView->>URL: "updateParams({ task_id: null, agent_name: null }, replace)" note over Root: taskID is now null Root->>Root: "effect re-runs — !taskID now true<br/>restores localAgentName if present" note over URL: User lands on home grid end%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%% sequenceDiagram participant URL as URL / Router participant Root as AgentexUIRoot participant ChatView as ChatView participant API as Backend API note over URL: ?task_id=TASK-123 (no agent_name) Root->>Root: "effect runs — taskID truthy,<br/>!taskID guards skip both branches" ChatView->>API: "useTask(TASK-123, {relationships: ['agents']})" alt Task accessible (2xx) API-->>ChatView: "task { agents: [{name: "my-agent"}] }" ChatView->>URL: "updateParams({ agent_name: "my-agent" }, replace)" Root->>Root: "effect re-runs — agentName set,<br/>taskID set — both branches still skip" else Task inaccessible (403/404) API-->>ChatView: "APIError { status: 403 }" note over ChatView: retry policy: no retry for 4xx ChatView->>URL: "updateParams({ task_id: null, agent_name: null }, replace)" note over Root: taskID is now null Root->>Root: "effect re-runs — !taskID now true<br/>restores localAgentName if present" note over URL: User lands on home grid endReviews (4): Last reviewed commit: "fix(agentex-ui): hydrate agent from task..." | Re-trigger Greptile