-
Notifications
You must be signed in to change notification settings - Fork 473
Updates to prepare for v0.12 launch #2434
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Caution Review failedThe pull request is closed. WalkthroughDocumentation: removes AI Presets content and redirects AI configuration references to a new Wave AI docs page; adds a Wave AI card and updates keybindings. Frontend: introduces a BlockModel singleton and BlockHighlightType for per-block highlight atoms; AIToolUse emits hover-driven highlights (via new blockid on tooluse), BlockFrame renders highlight overlay, workspace filters the AI widget based on hasCustomAIPresetsAtom, and a new hasCustomAIPresets atom is exported. Types: WaveUIDataTypes.tooluse gains optional blockid. Backend: UIMessageDataToolUse gains BlockId; WaveChatOpts gains TabId and TabStateGenerator now returns tabId; tool-use creation and several aiusechat handlers now resolve block IDs via new wcore.ResolveBlockIdFromPrefix; an older local resolver was removed. Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Pre-merge checks and finishing touches❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
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. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
docs/docs/presets.mdx (1)
20-20
: Remove outdatedpresets/ai.json
reference.Line 20 still points readers to
presets/ai.json
, but the rest of the page (and the PR) removes AI presets entirely. Keeping that path is misleading—folks will go hunting for a file we just deprecated. Please drop the AI example (or replace it with another background-focused one).- All presets are aggregated regardless of which file they're in, so you can use the `presets` directory to organize them (e.g., `presets/bg.json`, `presets/ai.json`). + All presets are aggregated regardless of which file they're in, so you can use the `presets` directory to organize them (e.g., `presets/bg.json`).
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
package-lock.json
is excluded by!**/package-lock.json
📒 Files selected for processing (22)
docs/docs/ai-presets.mdx
(1 hunks)docs/docs/customization.mdx
(0 hunks)docs/docs/faq.mdx
(0 hunks)docs/docs/gettingstarted.mdx
(2 hunks)docs/docs/index.mdx
(1 hunks)docs/docs/keybindings.mdx
(1 hunks)docs/docs/presets.mdx
(3 hunks)frontend/app/aipanel/aimessage.tsx
(2 hunks)frontend/app/aipanel/aitypes.ts
(1 hunks)frontend/app/block/block-model.ts
(1 hunks)frontend/app/block/blockframe.tsx
(5 hunks)frontend/app/store/global.ts
(2 hunks)frontend/app/workspace/widgets.tsx
(2 hunks)frontend/types/custom.d.ts
(1 hunks)pkg/aiusechat/openai/openai-backend.go
(4 hunks)pkg/aiusechat/tools.go
(0 hunks)pkg/aiusechat/tools_screenshot.go
(2 hunks)pkg/aiusechat/tools_term.go
(2 hunks)pkg/aiusechat/tools_web.go
(1 hunks)pkg/aiusechat/uctypes/usechat-types.go
(2 hunks)pkg/aiusechat/usechat.go
(2 hunks)pkg/wcore/wcore.go
(2 hunks)
💤 Files with no reviewable changes (3)
- docs/docs/customization.mdx
- pkg/aiusechat/tools.go
- docs/docs/faq.mdx
🧰 Additional context used
🧬 Code graph analysis (8)
pkg/aiusechat/tools_term.go (1)
pkg/wcore/wcore.go (1)
ResolveBlockIdFromPrefix
(114-131)
frontend/app/block/blockframe.tsx (1)
frontend/app/block/block-model.ts (1)
BlockModel
(12-51)
pkg/aiusechat/tools_web.go (1)
pkg/wcore/wcore.go (1)
ResolveBlockIdFromPrefix
(114-131)
pkg/aiusechat/usechat.go (2)
pkg/aiusechat/uctypes/usechat-types.go (1)
ToolDefinition
(78-90)pkg/aiusechat/tools.go (1)
GenerateTabStateAndTools
(88-140)
frontend/app/aipanel/aimessage.tsx (1)
frontend/app/block/block-model.ts (1)
BlockModel
(12-51)
pkg/aiusechat/openai/openai-backend.go (2)
pkg/aiusechat/uctypes/usechat-types.go (3)
ToolDefinition
(78-90)WaveChatOpts
(420-435)UIMessageDataToolUse
(136-144)pkg/wcore/wcore.go (1)
ResolveBlockIdFromPrefix
(114-131)
pkg/wcore/wcore.go (2)
pkg/wstore/wstore_dbops.go (1)
DBMustGet
(138-149)pkg/waveobj/wtype.go (2)
Tab
(183-190)Tab
(192-194)
pkg/aiusechat/tools_screenshot.go (1)
pkg/wcore/wcore.go (1)
ResolveBlockIdFromPrefix
(114-131)
🪛 LanguageTool
docs/docs/keybindings.mdx
[grammar] ~84-~84: There might be a mistake here.
Context: ... | Function | | ----------------------- | ------------...
(QB_NEW_EN)
[grammar] ~85-~85: There might be a mistake here.
Context: ...------------ | ----------------------- | | | Toggle WaveA...
(QB_NEW_EN)
[grammar] ~86-~86: There might be a mistake here.
Context: ...:Shift:a"/> | Toggle WaveAI panel | | | Focus WaveAI...
(QB_NEW_EN)
[grammar] ~87-~87: There might be a mistake here.
Context: ...l:Shift:0"/> | Focus WaveAI input | | | Clear AI Cha...
(QB_NEW_EN)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: Analyze (go)
- GitHub Check: Analyze (javascript-typescript)
- GitHub Check: Build Docsite
- GitHub Check: Build for TestDriver.ai
- GitHub Check: merge-gatekeeper
🔇 Additional comments (26)
frontend/app/aipanel/aitypes.ts (1)
20-20
: LGTM!The optional
blockid
field addition correctly extends the tooluse data shape to support block highlighting in the UI.frontend/app/block/block-model.ts (1)
12-51
: LGTM on the singleton pattern and caching strategy.The singleton pattern is correctly implemented with proper getInstance/resetInstance methods. The atom caching in
getBlockHighlightAtom
efficiently creates derived atoms per block ID.frontend/types/custom.d.ts (1)
17-17
: LGTM!The type declaration for
hasCustomAIPresetsAtom
is correct and consistent with other atom declarations in the interface.frontend/app/workspace/widgets.tsx (2)
72-72
: LGTM!The
hasCustomAIPresetsAtom
is correctly consumed to control AI widget visibility.
97-101
: LGTM on the conditional filtering logic.The implementation correctly removes the AI widget (
defwidget@ai
) when no custom AI presets exist, aligning with the PR objective to hide the AI widget from the sidebar unless customized.pkg/aiusechat/tools_web.go (1)
89-92
: LGTM on the centralized block ID resolution.The refactoring to use
wcore.ResolveBlockIdFromPrefix
centralizes the resolution logic and simplifies error handling. The implementation is consistent with the new pattern.frontend/app/store/global.ts (2)
107-118
: LGTM on the derived atom implementation.The
hasCustomAIPresetsAtom
correctly derives the presence of custom AI presets by checking for keys starting with"ai@"
while excluding the default"ai@global"
and"ai@wave"
presets.
175-175
: LGTM!The atom is correctly exported in the global atoms object, making it available throughout the application.
frontend/app/aipanel/aimessage.tsx (3)
4-4
: LGTM!The BlockModel import is correctly added to support the block highlighting feature.
242-255
: LGTM on the mouse event handlers.The handlers correctly manage block highlighting:
handleMouseEnter
sets the highlight when a blockid existshandleMouseLeave
clears the highlight- Both properly check for blockid presence before acting
258-264
: LGTM on the UI updates.The container correctly:
- Applies
cursor-pointer
style when blockid exists to indicate interactivity- Wires up the mouse event handlers
- Maintains existing styling and classes
pkg/aiusechat/tools_screenshot.go (2)
12-12
: LGTM!The import is correctly updated to use the centralized wcore package.
33-36
: LGTM on the centralized block ID resolution.The refactoring to use
wcore.ResolveBlockIdFromPrefix
is consistent with the broader PR pattern of centralizing block ID resolution logic.pkg/aiusechat/tools_term.go (1)
14-14
: LGTM! Centralized block ID resolution.The refactor to use
wcore.ResolveBlockIdFromPrefix
consolidates the block ID resolution logic, reducing code duplication across tool files while maintaining proper error handling.Also applies to: 123-126
pkg/wcore/wcore.go (1)
114-131
: LGTM! Centralized block ID resolution with proper validation.The new
ResolveBlockIdFromPrefix
function consolidates block ID resolution logic with appropriate validation (8-character prefix) and clear error messages. The linear search throughtab.BlockIds
is acceptable for typical tab sizes.pkg/aiusechat/uctypes/usechat-types.go (4)
143-143
: LGTM! BlockId field enables block highlighting.The
BlockId
field addition toUIMessageDataToolUse
enables the frontend to identify and highlight specific blocks associated with tool usage, supporting the new hover-to-highlight feature.
426-426
: LGTM! TabStateGenerator signature extended for tab context propagation.The updated signature returning four values (including
tabId
) enables proper propagation of tab context through the chat workflow, supporting block ID resolution in tool usage.
431-431
: LGTM! Comment typo corrected.Fixed: "emphemeral" → "ephemeral".
434-434
: LGTM! TabId field enables tab-scoped operations.The
TabId
field inWaveChatOpts
allows tab-scoped tool operations and block ID resolution, completing the tab context propagation chain.pkg/aiusechat/openai/openai-backend.go (1)
23-23
: LGTM! BlockId resolution integrated into tool usage flow.The
createToolUseData
signature extension and new resolution logic appropriately populateBlockId
when bothTabId
andwidget_id
are available. The 2-second timeout forwcore.ResolveBlockIdFromPrefix
is reasonable, and graceful error handling (silently skipping BlockId assignment on error) prevents disruption of the tool usage flow.Also applies to: 817-817, 845-886
frontend/app/block/blockframe.tsx (4)
4-4
: LGTM! BlockModel integration for highlight state.The imports and singleton access pattern properly integrate block highlighting into the frame rendering logic.
Also applies to: 30-30, 488-488
513-515
: LGTM! Conditional highlight border application.The logic correctly applies a default highlight border (
rgb(59, 130, 246)
) only whenblockHighlight
exists and no explicit border color is already set, preventing override of user-configured borders.
525-533
: LGTM! Block highlight rendering with appropriate priority.The conditional rendering correctly prioritizes layout mode overlay over block highlight, and the highlight icon rendering (48px, 50% opacity) provides clear visual feedback without being intrusive.
536-536
: LGTM! Background highlight styling.The
bg-blue-500/10
class provides subtle visual feedback when block highlighting is active, complementing the border and icon indicators.pkg/aiusechat/usechat.go (2)
365-370
: LGTM! Tab context propagation in chat flow.The
TabStateGenerator
call and assignment logic correctly handle the extended signature, propagatingtabId
through the chat workflow only when generation succeeds (notabErr
).
625-628
: LGTM! TabStateGenerator lambda updated for 4-tuple return.The lambda correctly calls
GenerateTabStateAndTools
and returns the 4-tuple includingreq.TabId
, maintaining consistency with the updatedTabStateGenerator
signature.
private static instance: BlockModel | null = null; | ||
private blockHighlightAtomCache = new Map<string, jotai.Atom<BlockHighlightType | null>>(); | ||
|
||
blockHighlightAtom: jotai.PrimitiveAtom<BlockHighlightType> = jotai.atom(null) as jotai.PrimitiveAtom<BlockHighlightType>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix the type declaration to match the nullable initialization.
The atom is initialized with null
but typed as PrimitiveAtom<BlockHighlightType>
(non-nullable). This type mismatch could lead to type safety issues.
Apply this diff to fix the type:
- blockHighlightAtom: jotai.PrimitiveAtom<BlockHighlightType> = jotai.atom(null) as jotai.PrimitiveAtom<BlockHighlightType>;
+ blockHighlightAtom: jotai.PrimitiveAtom<BlockHighlightType | null> = jotai.atom<BlockHighlightType | null>(null);
📝 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.
blockHighlightAtom: jotai.PrimitiveAtom<BlockHighlightType> = jotai.atom(null) as jotai.PrimitiveAtom<BlockHighlightType>; | |
blockHighlightAtom: jotai.PrimitiveAtom<BlockHighlightType | null> = jotai.atom<BlockHighlightType | null>(null); |
🤖 Prompt for AI Agents
In frontend/app/block/block-model.ts around line 16, the atom is initialized
with null but typed as jotai.PrimitiveAtom<BlockHighlightType> (non-nullable);
change the type to include null (jotai.PrimitiveAtom<BlockHighlightType | null>)
and/or annotate the atom generic as jotai.atom<BlockHighlightType | null>(null)
so the declared type matches the nullable initialization.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Nitpick comments (3)
docs/docs/presets.mdx (3)
9-12
: Tighten intro (single-item list → sentence).Reads cleaner as a sentence since only one use-case is listed.
-Wave's preset system allows you to save and apply multiple configuration settings at once. Presets are used for: - -- Tab backgrounds: Apply visual styles to your tabs +Wave's preset system allows you to save and apply multiple configuration settings at once. Currently, presets are used for tab backgrounds (apply visual styles to your tabs).
20-23
: Minor MDX hygiene around admonition start.Ensure exactly one blank line before
:::info
and no trailing double-spaces at the end of Line 20 to avoid odd rendering. The content is fine.
25-28
: Consider adding directory-creation hint for presets folder.Some users may not have
~/.config/waveterm/presets/
yet.wsh editconfig presets.json # Edit main presets file wsh editconfig presets/bg.json # Edit background presets +# If the presets directory doesn't exist yet: +# mkdir -p ~/.config/waveterm/presets
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
docs/docs/presets.mdx
(3 hunks)frontend/app/aipanel/aimessage.tsx
(4 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
frontend/app/aipanel/aimessage.tsx (1)
frontend/app/block/block-model.ts (1)
BlockModel
(12-51)
🪛 LanguageTool
docs/docs/presets.mdx
[grammar] ~22-~22: There might be a mistake here.
Context: ...them (e.g., presets/bg.json
). :::info You can easily edit your presets using t...
(QB_NEW_EN)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Build for TestDriver.ai
- GitHub Check: Analyze (go)
🔇 Additional comments (1)
frontend/app/aipanel/aimessage.tsx (1)
205-206
: Well-structured hover highlight implementation.The use of refs to manage the timeout and track highlighted state is appropriate for this side-effect scenario. The cleanup effect properly prevents memory leaks, and the conditional cursor styling based on
blockid
presence is good UX.Also applies to: 228-234, 252-293
When a preset is applied, it overrides the default configuration values for that tab or block. Using `bg:*` will clear any previously overridden values, setting them back to defaults. It's recommended to include this key in your presets to ensure a clean slate. | ||
::: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
🧩 Analysis chain
Clarify scope: “tab or block” vs. tab-only bg presets.
The “preset-type” section lists only bg
(tab menu). If block-level application isn’t supported, remove “or block”; if it is, mention that in the preset-type list.
-When a preset is applied, it overrides the default configuration values for that tab or block. Using `bg:*` will clear any previously overridden values, setting them back to defaults. It's recommended to include this key in your presets to ensure a clean slate.
+When a preset is applied, it overrides the default configuration values for that tab. Using `bg:*` will clear any previously overridden values, setting them back to defaults. It's recommended to include this key in your presets to ensure a clean slate.
Alternatively (if blocks are supported), add a second bullet under “The preset-type
determines...” to document block usage.
🏁 Script executed:
#!/bin/bash
rg -n -C2 'preset-type' docs/docs/presets.mdx
rg -n 'block' docs/docs/presets.mdx
Length of output: 861
Add block-level details to preset-type
docs
The bg
preset-type also configures block-level backgrounds (e.g., bg:bordercolor
, bg:activebordercolor
). Under “The preset-type
determines…,” add a second bullet noting block usage:
bg
: Appears in the “Backgrounds” submenu when right-clicking a tab, and applies to blocks via keys likebg:bordercolor
andbg:activebordercolor
.
🤖 Prompt for AI Agents
In docs/docs/presets.mdx around lines 59-60, add a second bullet under “The
`preset-type` determines…” explaining that the `bg` preset-type not only appears
in the “Backgrounds” submenu when right-clicking a tab but also configures
block-level backgrounds via keys like `bg:bordercolor` and
`bg:activebordercolor`; update that section to include this concise bullet so
readers know `bg` applies to both tabs and blocks with those example keys.
const handleMouseEnter = () => { | ||
if (!toolData.blockid) return; | ||
|
||
if (highlightTimeoutRef.current) { | ||
clearTimeout(highlightTimeoutRef.current); | ||
} | ||
|
||
highlightedBlockIdRef.current = toolData.blockid; | ||
BlockModel.getInstance().setBlockHighlight({ | ||
blockId: toolData.blockid, | ||
icon: "sparkles", | ||
}); | ||
|
||
highlightTimeoutRef.current = setTimeout(() => { | ||
if (highlightedBlockIdRef.current === toolData.blockid) { | ||
BlockModel.getInstance().setBlockHighlight(null); | ||
highlightedBlockIdRef.current = null; | ||
} | ||
}, 2000); | ||
}; | ||
|
||
const handleMouseLeave = () => { | ||
if (!toolData.blockid) return; | ||
|
||
if (highlightTimeoutRef.current) { | ||
clearTimeout(highlightTimeoutRef.current); | ||
highlightTimeoutRef.current = null; | ||
} | ||
|
||
if (highlightedBlockIdRef.current === toolData.blockid) { | ||
BlockModel.getInstance().setBlockHighlight(null); | ||
highlightedBlockIdRef.current = null; | ||
} | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Race condition: timeout can clear another component's active highlight.
When multiple AIToolUse
components are hovered in quick succession, the timeout from an earlier component can incorrectly clear the highlight set by a later component. The check highlightedBlockIdRef.current === toolData.blockid
only validates the local ref, not whether the global highlight still corresponds to this component's blockid.
Scenario:
- Hover over Tool A (block1) → sets highlight to block1, schedules 2s timeout.
- Hover over Tool B (block2) → sets highlight to block2, schedules 2s timeout (A's timeout still pending).
- A's timeout fires → checks
highlightedBlockIdRef.current === toolData.blockid
(true) → clears global highlight. - Result: B's highlight vanishes prematurely even though the user is still interacting with B.
Apply this diff to verify the global state before clearing:
highlightTimeoutRef.current = setTimeout(() => {
- if (highlightedBlockIdRef.current === toolData.blockid) {
+ const currentHighlight = globalStore.get(BlockModel.getInstance().blockHighlightAtom);
+ if (highlightedBlockIdRef.current === toolData.blockid && currentHighlight?.blockId === toolData.blockid) {
BlockModel.getInstance().setBlockHighlight(null);
highlightedBlockIdRef.current = null;
}
}, 2000);
Also update handleMouseLeave
for consistency:
const handleMouseLeave = () => {
if (!toolData.blockid) return;
if (highlightTimeoutRef.current) {
clearTimeout(highlightTimeoutRef.current);
highlightTimeoutRef.current = null;
}
- if (highlightedBlockIdRef.current === toolData.blockid) {
+ const currentHighlight = globalStore.get(BlockModel.getInstance().blockHighlightAtom);
+ if (highlightedBlockIdRef.current === toolData.blockid && currentHighlight?.blockId === toolData.blockid) {
BlockModel.getInstance().setBlockHighlight(null);
highlightedBlockIdRef.current = null;
}
};
You'll need to import globalStore
:
+import { globalStore } from "@/app/store/global";
📝 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.
const handleMouseEnter = () => { | |
if (!toolData.blockid) return; | |
if (highlightTimeoutRef.current) { | |
clearTimeout(highlightTimeoutRef.current); | |
} | |
highlightedBlockIdRef.current = toolData.blockid; | |
BlockModel.getInstance().setBlockHighlight({ | |
blockId: toolData.blockid, | |
icon: "sparkles", | |
}); | |
highlightTimeoutRef.current = setTimeout(() => { | |
if (highlightedBlockIdRef.current === toolData.blockid) { | |
BlockModel.getInstance().setBlockHighlight(null); | |
highlightedBlockIdRef.current = null; | |
} | |
}, 2000); | |
}; | |
const handleMouseLeave = () => { | |
if (!toolData.blockid) return; | |
if (highlightTimeoutRef.current) { | |
clearTimeout(highlightTimeoutRef.current); | |
highlightTimeoutRef.current = null; | |
} | |
if (highlightedBlockIdRef.current === toolData.blockid) { | |
BlockModel.getInstance().setBlockHighlight(null); | |
highlightedBlockIdRef.current = null; | |
} | |
}; | |
// at the top of the file, alongside your other imports | |
import { globalStore } from "@/app/store/global"; | |
const handleMouseEnter = () => { | |
if (!toolData.blockid) return; | |
if (highlightTimeoutRef.current) { | |
clearTimeout(highlightTimeoutRef.current); | |
} | |
highlightedBlockIdRef.current = toolData.blockid; | |
BlockModel.getInstance().setBlockHighlight({ | |
blockId: toolData.blockid, | |
icon: "sparkles", | |
}); | |
highlightTimeoutRef.current = setTimeout(() => { | |
const currentHighlight = globalStore.get( | |
BlockModel.getInstance().blockHighlightAtom | |
); | |
if ( | |
highlightedBlockIdRef.current === toolData.blockid && | |
currentHighlight?.blockId === toolData.blockid | |
) { | |
BlockModel.getInstance().setBlockHighlight(null); | |
highlightedBlockIdRef.current = null; | |
} | |
}, 2000); | |
}; | |
const handleMouseLeave = () => { | |
if (!toolData.blockid) return; | |
if (highlightTimeoutRef.current) { | |
clearTimeout(highlightTimeoutRef.current); | |
highlightTimeoutRef.current = null; | |
} | |
const currentHighlight = globalStore.get( | |
BlockModel.getInstance().blockHighlightAtom | |
); | |
if ( | |
highlightedBlockIdRef.current === toolData.blockid && | |
currentHighlight?.blockId === toolData.blockid | |
) { | |
BlockModel.getInstance().setBlockHighlight(null); | |
highlightedBlockIdRef.current = null; | |
} | |
}; |
🤖 Prompt for AI Agents
In frontend/app/aipanel/aimessage.tsx around lines 252 to 285, the timeout
handler and mouse-leave logic can clear another component's global highlight
because they only check the component-local ref; update both handlers to verify
the global store's highlighted block id matches this component's
toolData.blockid before clearing the global highlight, and only clear if it
matches (i.e., read globalStore.getHighlightedBlockId() or equivalent and
compare to toolData.blockid), keep clearing and nulling the local timeout/ref as
before, and import globalStore at the top of the file.
<div | ||
className={cn("flex items-start gap-2 p-2 rounded bg-gray-800 border border-gray-700", statusColor, { | ||
"cursor-pointer": toolData.blockid, | ||
})} | ||
onMouseEnter={handleMouseEnter} | ||
onMouseLeave={handleMouseLeave} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add keyboard navigation and ARIA attributes for accessibility.
The div becomes interactive when toolData.blockid
is present (cursor-pointer), but lacks keyboard support and ARIA attributes, preventing keyboard-only users from triggering the highlight.
Consider adding keyboard support:
<div
className={cn("flex items-start gap-2 p-2 rounded bg-gray-800 border border-gray-700", statusColor, {
"cursor-pointer": toolData.blockid,
})}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
+ tabIndex={toolData.blockid ? 0 : undefined}
+ onFocus={handleMouseEnter}
+ onBlur={handleMouseLeave}
+ role={toolData.blockid ? "button" : undefined}
+ aria-label={toolData.blockid ? `Highlight block ${toolData.blockid}` : undefined}
>
📝 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.
<div | |
className={cn("flex items-start gap-2 p-2 rounded bg-gray-800 border border-gray-700", statusColor, { | |
"cursor-pointer": toolData.blockid, | |
})} | |
onMouseEnter={handleMouseEnter} | |
onMouseLeave={handleMouseLeave} | |
<div | |
className={cn( | |
"flex items-start gap-2 p-2 rounded bg-gray-800 border border-gray-700", | |
statusColor, | |
{ "cursor-pointer": toolData.blockid }, | |
)} | |
onMouseEnter={handleMouseEnter} | |
onMouseLeave={handleMouseLeave} | |
tabIndex={toolData.blockid ? 0 : undefined} | |
onFocus={handleMouseEnter} | |
onBlur={handleMouseLeave} | |
role={toolData.blockid ? "button" : undefined} | |
aria-label={toolData.blockid ? `Highlight block ${toolData.blockid}` : undefined} | |
> |
🤖 Prompt for AI Agents
In frontend/app/aipanel/aimessage.tsx around lines 288-293, the interactive div
that is clickable when toolData.blockid exists lacks keyboard support and ARIA
attributes; update it so that when toolData.blockid is present it receives
role="button" and tabIndex={0}, add an onKeyDown handler that triggers the same
highlight/interaction on Enter and Space, include an appropriate aria-label or
aria-pressed (depending on semantics) that describes the action, and ensure
focus-visible styling is applied via className so keyboard users can see focus;
keep these additions conditional on toolData.blockid to avoid making
non-interactive elements tabbable.
Documentation Updates (removing AI Widget Information / deprecation)
Hover effect on tool calls shows which widget is effected
Remove AI Widget from sidebar unless there is customized presets
Backend now provides blockid (if available) to frontend for tool calls