[feat] Slash commands in the agent playground chat composer - #5817
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository YAML (base), Organization UI (inherited) Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (11)
🚧 Files skipped from review as they are similar to previous changes (8)
📝 WalkthroughSummary by CodeRabbit
WalkthroughAdds slash-command parsing and palette support to ChangesSlash-command composer
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant RichChatInput
participant AgentComposerDock
participant useChatSlashCommands
participant PickerPanel
User->>RichChatInput: type slash command
RichChatInput->>AgentComposerDock: invoke selected command
AgentComposerDock->>useChatSlashCommands: open model, harness, or permissions picker
useChatSlashCommands->>PickerPanel: provide options and current configuration
User->>PickerPanel: select and apply option
PickerPanel->>useChatSlashCommands: return selected value
useChatSlashCommands->>AgentComposerDock: update draft and close picker
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
📝 Generate docstrings
🧪 Generate unit tests (beta)
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.
Actionable comments posted: 1
🧹 Nitpick comments (12)
web/packages/agenta-entity-ui/src/DrillInView/SchemaControls/agentTemplate/useModelHarness.tsx (1)
374-374: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse
DEFAULT_PERMISSION_POLICYinstead of the literal.
permissionPolicy.tsexportsDEFAULT_PERMISSION_POLICYwith the value"allow_reads". The literal here can drift from that constant.♻️ Proposed refactor
import { + DEFAULT_PERMISSION_POLICY, isPermissionPolicy, permissionPolicyLabel, permissionPolicyOptionsForEnum, } from "../permissionPolicy"- const currentRunnerPermission = runnerPermissionValue ?? "allow_reads" + const currentRunnerPermission = runnerPermissionValue ?? DEFAULT_PERMISSION_POLICYweb/packages/agenta-entity-ui/src/DrillInView/SchemaControls/harnessMeta.ts (1)
41-41: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueUse a theme token for the fallback avatar colour.
The per-harness colours in
HARNESS_METAare brand colours, so raw hex is justified there.#586673is a neutral UI colour for unknown harness ids. Consume it through a supportedvar(--ag-color*)variable so it follows the light and dark themes.As per coding guidelines: "Consume theme colors through Ant Design semantic tokens, Tailwind color utilities, or supported
var(--ag-color*)variables; do not use raw hex colors or--ag-c-*literals."Source: Coding guidelines
web/packages/agenta-entity-ui/src/DrillInView/SchemaControls/toolPermission.ts (1)
103-103: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueType the exported sets as
ReadonlySet<string>.
PLATFORM_OPSandCLIENT_TOOLSnow cross the package boundary, andgateRulePatternreads them to decide whether a tool needs a permission rule. AReadonlySet<string>annotation stops a consumer from mutating the gate lists.♻️ Proposed refactor
-export const PLATFORM_OPS = new Set([ +export const PLATFORM_OPS: ReadonlySet<string> = new Set([-export const CLIENT_TOOLS = new Set(["request_connection", "request_input"]) +export const CLIENT_TOOLS: ReadonlySet<string> = new Set(["request_connection", "request_input"])Also applies to: 127-127
web/oss/src/components/AgentChatSlice/hooks/useChatSlashCommands.tsx (1)
115-116: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueDrop the duplicated default label.
permissionPolicyLabel(DEFAULT_PERMISSION_POLICY)always resolves, becauseDEFAULT_PERMISSION_POLICYis one ofPERMISSION_POLICY_OPTIONS. The?? "Allow reads"branch is unreachable and repeats the label string thatpermissionPolicy.tsowns.♻️ Proposed refactor
- const currentPermissionLabel = - permissionPolicyLabel(currentPermission ?? DEFAULT_PERMISSION_POLICY) ?? "Allow reads" + const currentPermissionLabel = permissionPolicyLabel( + currentPermission ?? DEFAULT_PERMISSION_POLICY, + )
tailat Line 315 already interpolates the value, so anundefinedlabel would render asundefined ›. Keep a non-string-literal guard if you prefer belt and braces, for example?? DEFAULT_PERMISSION_POLICY.web/packages/agenta-ui/src/RichChatInput/plugins/SlashCommandPlugin.tsx (1)
275-280: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winGive each section wrapper a group role.
The section wrapper is a plain
divbetweenrole="listbox"and therole="option"rows. ARIA requires options to be owned by the listbox, directly or through agroup. The section titledivis also announced as generic content. Addrole="group"with a label, and mark the title as presentational, asSelectLLMProviderBasealready does for its grouped list.♿ Proposed grouping fix
visibleSections.map((section) => ( - <div key={section.key}> - <div className="px-[14px] pb-[5px] pt-[10px] text-[9.5px] font-semibold uppercase leading-none tracking-[.1em] text-[var(--ag-colorTextTertiary)]"> + <div key={section.key} role="group" aria-label={section.title}> + <div + role="presentation" + className="px-[14px] pb-[5px] pt-[10px] text-[9.5px] font-semibold uppercase leading-none tracking-[.1em] text-[var(--ag-colorTextTertiary)]" + > {section.title} </div>web/packages/agenta-entity-ui/tests/unit/agentConfigPatch.test.ts (1)
29-94: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueReplace the repeated
(next as any)casts with a typed helper.The package guideline forbids
anyin workspace packages. The helpers returnRecord<string, unknown> | null, so a small local reader keeps the assertions typed.♻️ Proposed typed accessor
+const rec = (value: unknown): Record<string, any> => value as Record<string, any> + describe("withModel", () => { it("writes the ModelRef under parameters.agent", () => { const next = withModel(nested(), {modelId: "claude-sonnet-4-5", provider: "anthropic"}) - expect((next as any).agent.llm).toEqual({ + expect(rec(next).agent.llm).toEqual({ model: "claude-sonnet-4-5", provider: "anthropic", }) })As per coding guidelines: "For workspace packages, respect the hierarchy
shared ← ui ← entities ← entity-ui ← playground ← playground-ui, avoidanyand legacy compatibility shims".Source: Coding guidelines
web/oss/src/components/AgentChatSlice/components/SlashCommand/useRovingList.ts (1)
85-96: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low valueClamp
activeIndexwhenitemsshrinks.The hook seeds the index once and then only moves it on key or hover events. If
itemsbecomes shorter (a re-filtered or reloaded catalog),activeIndexcan point past the end.items[activeIndex]is thenundefined, so Enter does nothing andaria-activedescendantnames a row that no longer exists.♻️ Proposed clamp
useEffect(() => { if (seededRef.current || !items.length) return seededRef.current = true setActiveIndex(initialIndex(items, current, isEqual, isDisabled)) }, [current, isDisabled, isEqual, items]) + + useEffect(() => { + setActiveIndex((i) => (i >= items.length ? firstEnabledIndex(items, isDisabled) : i)) + }, [isDisabled, items])web/oss/src/components/AgentChatSlice/components/AgentComposerDock.tsx (1)
374-413: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low valueMemoize
panelFooterand the inline handlers.
panelFooterbuilds new JSX on every dock render, andonOpenChangeandonDismissOutsideget new identities each render. The dock re-renders on every keystroke throughcomposer.handleComposerChange, so the picker receives new props each time. Wrap the footer inuseMemoand the handlers inuseCallback.♻️ Proposed memoization
+ const closeModelPicker = useCallback( + (next: boolean) => { + if (!next) closePicker() + }, + [closePicker], + ) + const markOutsideDismiss = useCallback(() => { + skipFocusRestoreRef.current = true + }, []) + const modelPanelFooter = useMemo( + () => ( + <div className="flex items-center gap-1.5 text-[10.5px] text-[var(--ag-colorTextTertiary)]"> + {/* …existing footer markup… */} + </div> + ), + [backToCommands, openModelHarnessConfig], + )Then pass
onOpenChange={closeModelPicker},onDismissOutside={markOutsideDismiss}, andpanelFooter={modelPanelFooter}.As per coding guidelines: "Memoize inline arrays containing objects or JSX when passing them as props to avoid unnecessary rerenders" and "avoid unstable inline functions and objects".
Source: Coding guidelines
web/oss/src/components/AgentChatSlice/components/SlashCommand/HarnessPickerPanel.tsx (2)
84-93: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low valueCompute the model groups once.
buildModelOptionGroups(capabilities, selected)runs twice per render, and it runs again on every arrow keypress. Compute it once and derive bothmodelCountandfallbackfrom that value.♻️ Proposed change
- const modelCount = selected - ? buildModelOptionGroups(capabilities, selected).reduce( - (n, group) => n + group.options.length, - 0, - ) - : 0 - const keepsModel = harnessAllowsModel(capabilities, selected, currentModel) - const fallback = keepsModel - ? null - : (buildModelOptionGroups(capabilities, selected)[0]?.options[0] ?? null) + const modelGroups = useMemo( + () => (selected ? buildModelOptionGroups(capabilities, selected) : []), + [capabilities, selected], + ) + const modelCount = modelGroups.reduce((n, group) => n + group.options.length, 0) + const keepsModel = harnessAllowsModel(capabilities, selected, currentModel) + const fallback = keepsModel ? null : (modelGroups[0]?.options[0] ?? null)
63-79: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winBoth panels copy the same outside-pointer and Escape dismissal effect. The shared root cause is missing extraction: each panel declares its own
rootRefand registers the same two capture-phase document listeners. A third panel, which the README checklist anticipates, will copy it again.
web/oss/src/components/AgentChatSlice/components/SlashCommand/HarnessPickerPanel.tsx#L63-L79: replace this effect and therootRefdeclaration with a sharedusePanelDismiss(onDismiss)hook placed besideuseRovingList.ts, and spread the returned ref on the panel root.web/oss/src/components/AgentChatSlice/components/SlashCommand/PermissionsPickerPanel.tsx#L44-L65: consume the same hook and delete the duplicated effect.web/oss/src/components/AgentChatSlice/components/SlashCommand/README.md (1)
16-18: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueState where
→drills in.
useRovingListhandles←for back-navigation only. No panel in this directory handles→. The sentence reads as a contract that every panel must implement. Scope it to the nested/modelcascade, which owns that key.web/storybook/stories/domain/RichChatInput.stories.tsx (1)
184-212: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse the workflow export for the mock contract.
HarnessCapabilitiesMapis exported from@agenta/entities/workflow, not@agenta/entities/workflow/state. Use a shared contract type instead ofas neverso this mock fails when the harness catalog shape changes.♻️ Proposed change
+import type {HarnessCapabilitiesMap} from "`@agenta/entities/workflow`" + /** Mocked harness catalog — the same shape `/inspect` publishes as `harness_capabilities`. */ -const MOCK_CAPABILITIES = { +const MOCK_CAPABILITIES = { pi_core: { @@ -} as never +} satisfies HarnessCapabilitiesMap
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 7834d065-3c0f-4234-bd85-abb319d95256
⛔ Files ignored due to path filters (1)
web/pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (28)
web/oss/src/components/AgentChatSlice/components/AgentComposerDock.tsxweb/oss/src/components/AgentChatSlice/components/SlashCommand/HarnessPickerPanel.tsxweb/oss/src/components/AgentChatSlice/components/SlashCommand/PermissionsPickerPanel.tsxweb/oss/src/components/AgentChatSlice/components/SlashCommand/README.mdweb/oss/src/components/AgentChatSlice/components/SlashCommand/useRovingList.test.tsweb/oss/src/components/AgentChatSlice/components/SlashCommand/useRovingList.tsweb/oss/src/components/AgentChatSlice/hooks/useChatSlashCommands.tsxweb/oss/tailwind.config.tsweb/packages/agenta-entity-ui/src/DrillInView/SchemaControls/HarnessSelectControl.tsxweb/packages/agenta-entity-ui/src/DrillInView/SchemaControls/agentConfigPatch.tsweb/packages/agenta-entity-ui/src/DrillInView/SchemaControls/agentTemplate/useModelHarness.tsxweb/packages/agenta-entity-ui/src/DrillInView/SchemaControls/harnessMeta.tsweb/packages/agenta-entity-ui/src/DrillInView/SchemaControls/index.tsweb/packages/agenta-entity-ui/src/DrillInView/SchemaControls/permissionPolicy.tsweb/packages/agenta-entity-ui/src/DrillInView/SchemaControls/toolPermission.tsweb/packages/agenta-entity-ui/src/DrillInView/index.tsweb/packages/agenta-entity-ui/tests/unit/agentConfigPatch.test.tsweb/packages/agenta-shared/src/state/draftConfigChangeSignal.tsweb/packages/agenta-ui/package.jsonweb/packages/agenta-ui/src/RichChatInput/RichChatInput.tsxweb/packages/agenta-ui/src/RichChatInput/assets/slashCommands.tsweb/packages/agenta-ui/src/RichChatInput/index.tsweb/packages/agenta-ui/src/RichChatInput/plugins/SlashCommandPlugin.tsxweb/packages/agenta-ui/src/SelectLLMProvider/SelectLLMProviderBase.tsxweb/packages/agenta-ui/src/SelectLLMProvider/types.tsweb/packages/agenta-ui/tests/unit/slashCommands.test.tsweb/packages/agenta-ui/vitest.config.tsweb/storybook/stories/domain/RichChatInput.stories.tsx
Railway Preview Environment
Updated at 2026-08-11T17:23:07.701Z |
mmabrouk
left a comment
There was a problem hiding this comment.
Requesting changes for three blocking behavior issues: selecting an open/action command can delete unrelated draft text, model changes can retain an incompatible named connection, and the advertised tool/MCP rows are hard-disabled. I also left inline comments for model-source parity, embedded skills, formatting boundaries, grouped-picker accessibility, unrelated docs history, and package test reporting. CI is mostly green, but the current unit coverage does not exercise these interaction paths.
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
web/oss/src/components/AgentChatSlice/hooks/useChatSlashCommands.tsx (1)
206-227: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winUse the full selectable model set for harness fallback.
modelGroupsincludesvaultModelGroups, butfallbackModelForonly reads catalog groups. If the target harness has a compatible vault-backed model but no catalog model,fallbackis null.applyHarnessthen saves the harness while retaining the incompatible current model.Build fallback candidates from the same catalog-plus-vault source as
/model. Preserve the selected option metadata when writing the fallback model so the provider and connection slug remain correct. Add a vault-only fallback test.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository YAML (base), Organization UI (inherited)
Review profile: CHILL
Plan: Pro Plus
Run ID: 7b380206-922f-4897-939e-07c24bfc90a2
📒 Files selected for processing (13)
web/oss/src/components/AgentChatSlice/components/AgentComposerDock.tsxweb/oss/src/components/AgentChatSlice/hooks/useChatSlashCommands.tsxweb/packages/agenta-entity-ui/src/DrillInView/SchemaControls/agentConfigPatch.tsweb/packages/agenta-entity-ui/src/DrillInView/SchemaControls/index.tsweb/packages/agenta-entity-ui/src/DrillInView/index.tsweb/packages/agenta-entity-ui/tests/unit/agentConfigPatch.test.tsweb/packages/agenta-ui/src/RichChatInput/RichChatInput.tsxweb/packages/agenta-ui/src/RichChatInput/assets/slashCommands.tsweb/packages/agenta-ui/src/RichChatInput/plugins/SlashCommandPlugin.tsxweb/packages/agenta-ui/src/SelectLLMProvider/SelectLLMProviderBase.tsxweb/packages/agenta-ui/tests/unit/slashCommands.test.tsweb/packages/agenta-ui/vitest.config.tsweb/storybook/stories/domain/RichChatInput.stories.tsx
🚧 Files skipped from review as they are similar to previous changes (9)
- web/packages/agenta-ui/vitest.config.ts
- web/storybook/stories/domain/RichChatInput.stories.tsx
- web/packages/agenta-entity-ui/tests/unit/agentConfigPatch.test.ts
- web/packages/agenta-entity-ui/src/DrillInView/SchemaControls/index.ts
- web/packages/agenta-entity-ui/src/DrillInView/index.ts
- web/oss/src/components/AgentChatSlice/components/AgentComposerDock.tsx
- web/packages/agenta-ui/src/RichChatInput/plugins/SlashCommandPlugin.tsx
- web/packages/agenta-entity-ui/src/DrillInView/SchemaControls/agentConfigPatch.ts
- web/packages/agenta-ui/src/RichChatInput/assets/slashCommands.ts
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (3)
web/packages/agenta-ui/src/RichChatInput/assets/slashCommands.ts (1)
1-7: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winReduce routine multi-line comments.
Keep only the detailed comments that describe surprising node-boundary or dismissal behavior. Replace routine API and algorithm descriptions with one short line or expressive identifiers.
As per coding guidelines, “Keep in-code comments to at most one short line; use longer comments only for genuinely surprising constraints such as bugs, races, or ordering requirements.”
Also applies to: 10-14, 51-54, 90-93, 107-110
Source: Coding guidelines
web/oss/src/components/AgentChatSlice/components/SlashCommand/PermissionsPickerPanel.tsx (1)
12-17: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueReduce routine multi-line comments.
These comments describe normal behavior. Replace them with one short comment or remove them.
web/oss/src/components/AgentChatSlice/components/SlashCommand/PermissionsPickerPanel.tsx#L12-L17: Reduce the component description to one short line.web/storybook/stories/domain/RichChatInput.stories.tsx#L159-L160: Remove or shorten theactionversusopenexplanation.web/storybook/stories/domain/RichChatInput.stories.tsx#L240-L245: Reduce the Storybook flow description to one short line.As per coding guidelines, “Keep in-code comments to at most one short line; use longer comments only for genuinely surprising constraints such as bugs, races, or ordering requirements.”
Source: Coding guidelines
web/storybook/stories/domain/RichChatInput.stories.tsx (1)
287-310: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueMemoize the
slashCommandsprop.When the palette is open, recreating
sectionsinvalidates the plugin’s filtered items and re-runs its keyboard-handler effect. Memoize the sections and stabilize the item callbacks.Source: Coding guidelines
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository YAML (base), Organization UI (inherited)
Review profile: CHILL
Plan: Pro Plus
Run ID: 9b217a59-1fc4-4f35-9d93-86b691e66e92
⛔ Files ignored due to path filters (1)
web/pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (33)
docs/docusaurus.config.tsdocs/src/components/GoogleColabButton.tsxdocs/src/css/custom.cssdocs/src/pages/roadmap.module.cssdocs/src/theme/Navbar/MobileSidebar/PrimaryMenu/index.tsxweb/oss/src/components/AgentChatSlice/components/AgentComposerDock.tsxweb/oss/src/components/AgentChatSlice/components/SlashCommand/HarnessPickerPanel.tsxweb/oss/src/components/AgentChatSlice/components/SlashCommand/PermissionsPickerPanel.tsxweb/oss/src/components/AgentChatSlice/components/SlashCommand/README.mdweb/oss/src/components/AgentChatSlice/components/SlashCommand/useRovingList.test.tsweb/oss/src/components/AgentChatSlice/components/SlashCommand/useRovingList.tsweb/oss/src/components/AgentChatSlice/hooks/useChatSlashCommands.tsxweb/oss/tailwind.config.tsweb/packages/agenta-entity-ui/src/DrillInView/SchemaControls/HarnessSelectControl.tsxweb/packages/agenta-entity-ui/src/DrillInView/SchemaControls/agentConfigPatch.tsweb/packages/agenta-entity-ui/src/DrillInView/SchemaControls/agentTemplate/useModelHarness.tsxweb/packages/agenta-entity-ui/src/DrillInView/SchemaControls/harnessMeta.tsweb/packages/agenta-entity-ui/src/DrillInView/SchemaControls/index.tsweb/packages/agenta-entity-ui/src/DrillInView/SchemaControls/permissionPolicy.tsweb/packages/agenta-entity-ui/src/DrillInView/SchemaControls/toolPermission.tsweb/packages/agenta-entity-ui/src/DrillInView/index.tsweb/packages/agenta-entity-ui/tests/unit/agentConfigPatch.test.tsweb/packages/agenta-shared/src/state/draftConfigChangeSignal.tsweb/packages/agenta-ui/package.jsonweb/packages/agenta-ui/src/RichChatInput/RichChatInput.tsxweb/packages/agenta-ui/src/RichChatInput/assets/slashCommands.tsweb/packages/agenta-ui/src/RichChatInput/index.tsweb/packages/agenta-ui/src/RichChatInput/plugins/SlashCommandPlugin.tsxweb/packages/agenta-ui/src/SelectLLMProvider/SelectLLMProviderBase.tsxweb/packages/agenta-ui/src/SelectLLMProvider/types.tsweb/packages/agenta-ui/tests/unit/slashCommands.test.tsweb/packages/agenta-ui/vitest.config.tsweb/storybook/stories/domain/RichChatInput.stories.tsx
🚧 Files skipped from review as they are similar to previous changes (25)
- web/packages/agenta-ui/package.json
- web/packages/agenta-ui/vitest.config.ts
- web/packages/agenta-entity-ui/src/DrillInView/index.ts
- web/packages/agenta-shared/src/state/draftConfigChangeSignal.ts
- web/oss/src/components/AgentChatSlice/components/SlashCommand/README.md
- web/packages/agenta-entity-ui/src/DrillInView/SchemaControls/permissionPolicy.ts
- web/packages/agenta-entity-ui/src/DrillInView/SchemaControls/agentTemplate/useModelHarness.tsx
- web/packages/agenta-ui/src/SelectLLMProvider/types.ts
- web/packages/agenta-entity-ui/src/DrillInView/SchemaControls/harnessMeta.ts
- web/oss/src/components/AgentChatSlice/components/SlashCommand/HarnessPickerPanel.tsx
- web/oss/tailwind.config.ts
- web/packages/agenta-entity-ui/tests/unit/agentConfigPatch.test.ts
- web/packages/agenta-ui/tests/unit/slashCommands.test.ts
- web/packages/agenta-entity-ui/src/DrillInView/SchemaControls/toolPermission.ts
- web/oss/src/components/AgentChatSlice/components/SlashCommand/useRovingList.test.ts
- web/oss/src/components/AgentChatSlice/components/SlashCommand/useRovingList.ts
- web/oss/src/components/AgentChatSlice/hooks/useChatSlashCommands.tsx
- web/packages/agenta-entity-ui/src/DrillInView/SchemaControls/agentConfigPatch.ts
- web/packages/agenta-ui/src/RichChatInput/plugins/SlashCommandPlugin.tsx
- web/packages/agenta-entity-ui/src/DrillInView/SchemaControls/HarnessSelectControl.tsx
- web/packages/agenta-ui/src/RichChatInput/index.ts
- web/packages/agenta-ui/src/RichChatInput/RichChatInput.tsx
- web/oss/src/components/AgentChatSlice/components/AgentComposerDock.tsx
- web/packages/agenta-entity-ui/src/DrillInView/SchemaControls/index.ts
- web/packages/agenta-ui/src/SelectLLMProvider/SelectLLMProviderBase.tsx
Typing `/` in the chat composer opens a command palette: `/model` and `/harness` drill into pickers that switch the agent, while the agent's configured tools and skills insert their slug into the message. Changing a model used to cost four steps — leave the chat, open the config drawer, find the model-harness section, change it, come back — and the chat never named the running model once a conversation started. The palette's command rows now carry the current model and harness, and switching happens where you are. - `SlashCommandPlugin` (Lexical) opens on a `/` that starts a block, so `and/or`, URLs, and paths never trigger it. It claims Enter at CRITICAL because SubmitPlugin holds HIGH, and deliberately declines it when nothing matches so a message that merely starts with a slash still sends. - `withModel` / `withHarnessKind` patch the draft agent config through `updateConfiguration`, the same write-through `useAlwaysAllowTool` uses — the change takes effect on the next send, no commit. Unit-tested against both parameter shapes. - A harness switch that strands the current model moves it to that harness's fallback and says so. The config drawer only flags the mismatch; in chat an unreachable model reads as a silent failure on the next run. - `SelectLLMProviderBase` gains optional controlled-open, anchor, and panel slots so the composer can drive it with no trigger of its own. Uncontrolled callers unchanged. - Harness identity moves to a shared `harnessMeta`, so a harness hidden in the drawer (`pi_agenta`) stays hidden in the palette. Tools and skills insert plain text and nothing more. Claude Code inserts text too, but its CLI strips the leading `/name` on send and dispatches it; Agenta's request carries text and file parts with no channel for invoking a tool. The inserted name is a hint the model usually follows, and no UI copy claims otherwise. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- Introduced a new `/permissions` command to manage agent permissions. - Updated `useChatSlashCommands` to handle permissions alongside model and harness. - Created `SlashConfirmationPill` for displaying confirmation messages for permissions changes. - Added animations for command panels in Tailwind configuration. - Implemented permission policy management in `agentConfigPatch` and related utilities. - Updated tests to cover new permissions functionality. - Enhanced UI components to support permissions selection and display.
…nce focus management
…d permissions handling - Implemented command run detection and parsing logic in slashCommands.ts - Added isSameRun utility for managing command dismissal states - Updated PermissionsPickerPanel to accept dynamic permission options - Refactored SlashCommandPlugin to improve command handling and accessibility - Introduced unit tests for command parsing and filtering logic - Updated package.json to include vitest for testing framework
…ing and new text insertion method
0febd99 to
444594a
Compare
mmabrouk
left a comment
There was a problem hiding this comment.
lgtm from product level.
@ardaerzin maybe you can review the code
…ta-chat-slash-commands-e07156 # Conflicts: # web/packages/agenta-entity-ui/src/DrillInView/SchemaControls/toolPermission.ts
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
web/packages/agenta-ui/src/RichChatInput/assets/slashCommands.ts (1)
1-6: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueCondense routine documentation blocks.
Keep these comments to one short line. Keep the longer comments that explain formatted-node boundaries and dismissal identity.
As per coding guidelines, “Keep in-code comments to at most one short line; use longer comments only for genuinely surprising constraints such as bugs, races, or ordering requirements.”
Also applies to: 10-13, 51-54, 90-92, 107-110
Source: Coding guidelines
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository YAML (base), Organization UI (inherited)
Review profile: CHILL
Plan: Pro Plus
Run ID: b88b3b5b-1729-4efd-bfb9-57a2f4b5bd3e
⛔ Files ignored due to path filters (1)
web/pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (28)
web/oss/src/components/AgentChatSlice/components/AgentComposerDock.tsxweb/oss/src/components/AgentChatSlice/components/SlashCommand/HarnessPickerPanel.tsxweb/oss/src/components/AgentChatSlice/components/SlashCommand/PermissionsPickerPanel.tsxweb/oss/src/components/AgentChatSlice/components/SlashCommand/README.mdweb/oss/src/components/AgentChatSlice/components/SlashCommand/useRovingList.test.tsweb/oss/src/components/AgentChatSlice/components/SlashCommand/useRovingList.tsweb/oss/src/components/AgentChatSlice/hooks/useChatSlashCommands.tsxweb/oss/tailwind.config.tsweb/packages/agenta-entity-ui/src/DrillInView/SchemaControls/HarnessSelectControl.tsxweb/packages/agenta-entity-ui/src/DrillInView/SchemaControls/agentConfigPatch.tsweb/packages/agenta-entity-ui/src/DrillInView/SchemaControls/agentTemplate/useModelHarness.tsxweb/packages/agenta-entity-ui/src/DrillInView/SchemaControls/harnessMeta.tsweb/packages/agenta-entity-ui/src/DrillInView/SchemaControls/index.tsweb/packages/agenta-entity-ui/src/DrillInView/SchemaControls/permissionPolicy.tsweb/packages/agenta-entity-ui/src/DrillInView/SchemaControls/toolPermission.tsweb/packages/agenta-entity-ui/src/DrillInView/index.tsweb/packages/agenta-entity-ui/tests/unit/agentConfigPatch.test.tsweb/packages/agenta-shared/src/state/draftConfigChangeSignal.tsweb/packages/agenta-ui/package.jsonweb/packages/agenta-ui/src/RichChatInput/RichChatInput.tsxweb/packages/agenta-ui/src/RichChatInput/assets/slashCommands.tsweb/packages/agenta-ui/src/RichChatInput/index.tsweb/packages/agenta-ui/src/RichChatInput/plugins/SlashCommandPlugin.tsxweb/packages/agenta-ui/src/SelectLLMProvider/SelectLLMProviderBase.tsxweb/packages/agenta-ui/src/SelectLLMProvider/types.tsweb/packages/agenta-ui/tests/unit/slashCommands.test.tsweb/packages/agenta-ui/vitest.config.tsweb/storybook/stories/domain/RichChatInput.stories.tsx
🚧 Files skipped from review as they are similar to previous changes (27)
- web/packages/agenta-shared/src/state/draftConfigChangeSignal.ts
- web/packages/agenta-ui/src/RichChatInput/index.ts
- web/oss/src/components/AgentChatSlice/components/SlashCommand/HarnessPickerPanel.tsx
- web/oss/src/components/AgentChatSlice/components/SlashCommand/README.md
- web/oss/tailwind.config.ts
- web/packages/agenta-ui/package.json
- web/packages/agenta-entity-ui/src/DrillInView/index.ts
- web/oss/src/components/AgentChatSlice/components/SlashCommand/PermissionsPickerPanel.tsx
- web/oss/src/components/AgentChatSlice/components/SlashCommand/useRovingList.test.ts
- web/storybook/stories/domain/RichChatInput.stories.tsx
- web/packages/agenta-ui/src/SelectLLMProvider/types.ts
- web/packages/agenta-ui/vitest.config.ts
- web/packages/agenta-entity-ui/src/DrillInView/SchemaControls/harnessMeta.ts
- web/packages/agenta-entity-ui/src/DrillInView/SchemaControls/agentTemplate/useModelHarness.tsx
- web/oss/src/components/AgentChatSlice/components/SlashCommand/useRovingList.ts
- web/packages/agenta-entity-ui/tests/unit/agentConfigPatch.test.ts
- web/oss/src/components/AgentChatSlice/components/AgentComposerDock.tsx
- web/packages/agenta-entity-ui/src/DrillInView/SchemaControls/permissionPolicy.ts
- web/packages/agenta-entity-ui/src/DrillInView/SchemaControls/index.ts
- web/packages/agenta-ui/src/RichChatInput/plugins/SlashCommandPlugin.tsx
- web/oss/src/components/AgentChatSlice/hooks/useChatSlashCommands.tsx
- web/packages/agenta-entity-ui/src/DrillInView/SchemaControls/toolPermission.ts
- web/packages/agenta-ui/src/RichChatInput/RichChatInput.tsx
- web/packages/agenta-entity-ui/src/DrillInView/SchemaControls/agentConfigPatch.ts
- web/packages/agenta-entity-ui/src/DrillInView/SchemaControls/HarnessSelectControl.tsx
- web/packages/agenta-ui/src/SelectLLMProvider/SelectLLMProviderBase.tsx
- web/packages/agenta-ui/tests/unit/slashCommands.test.ts
Code reviewFound 4 issues:
agenta/web/oss/src/components/AgentChatSlice/hooks/useChatSlashCommands.tsx Lines 217 to 219 in 95c5998
agenta/web/packages/agenta-ui/src/SelectLLMProvider/SelectLLMProviderBase.tsx Lines 305 to 309 in 95c5998
🤖 Generated with Claude Code - If this code review was useful, please react with 👍. Otherwise, react with 👎. |
Three call-site and lifecycle defects found in review: - Thread `customSecrets` and the stored connection slug into every `harnessAllowsModel` call. Both palette call sites passed three of five arguments, so a vault-hosted model skipped the vault lookup, fell through to the published catalog and reported a false "model not available" — the regression `connectionUtils.test.ts` already pins for the drawer. Adds `readModelConnectionSlug` beside `readModelId`, reusing the drawer's `connectionFromConfig`, plus a unit test. - Reset `SelectLLMProviderBase` on every close, not only the ones routed through `closeDropdown`. A controlled parent can drop `open` on its own — the composer's back-step and "Open config →" do — which fires no `onOpenChange`, so `/model` reopened holding a stale search term and an expanded provider column. - Point the two doc references at `README.md`; the file was renamed and the comments still named `AGENTS.md`. The story renders `HarnessPickerPanel` directly, so it takes the two new props; package typechecks do not cover stories.
Context
Changing the model, harness, or permission policy of an agent mid-conversation meant leaving the chat and digging through the config drawer. The composer now has a
/palette: type/to switch model, harness, or permissions in place, or to reference one of the agent's tools and skills by name.Changes
The palette (
@agenta/ui). A newSlashCommandPluginforRichChatInputopens on a/that starts a block or follows a space, soand/or, URLs, and file paths never trigger it. It filters as you type, with prefix matches ranked above substring matches. It claims Enter at CRITICAL priority (SubmitPlugin holds HIGH) so selecting an item does not send the message; with no matches it declines Enter, so a message that merely starts with a slash still sends. Hosts feed it sections via a newslashCommandsprop.Two item kinds.
openitems (/model,/harness,/permissions) drill into a picker anchored to the composer box, replacing the palette in place.insertitems (the agent's tools, MCP servers, and skills) type their slug into the message as plain text. The inserted name is a hint the agent usually follows, not a dispatch; platform ops and client tools are filtered out since a user never hints at those. Connected-app tools insert asintegration.action(e.g.gmail.send_email) instead of their long wire slug.The pickers.
/modelreusesSelectLLMProviderBase, which now supports controlled open, an external anchor, a hidden trigger, and a footer; anchored mode sizes the panel to the composer instead of the fixed 400px./harnessand/permissionsget new panels. When a harness switch strands the current model, the panel warns first and the apply moves the model to that harness's first available one; the drawer only flags this, but in chat a stranded model reads as a silent failure on the next send.The writes. New pure helpers in
@agenta/entity-ui/drill-in(agentConfigPatch.ts):withModel,withHarnessKind,withRunnerPermission, plus readers. They follow thewithToolPermissioncontract (parameters in, parameters out, located vialocateTemplate) and preserve what they don't touch: a model swap keeps the stored vault connection, a permission change keeps the rules list. Writes land on the draft config, so the change takes effect on the next send without a commit, and each one raises the draft-change signal (new originslash-command) so the matching config section pulses.Shared metadata. Harness identity (labels, avatars, the hidden
pi_agenta) moved fromHarnessSelectControlintoharnessMeta.ts, and the four permission policies fromuseModelHarnessintopermissionPolicy.ts, so the drawer and the palette cannot disagree.Tests / notes
agentConfigPatch(28 cases): both config shapes, connection and rules preservation, immutability, invalid input.RichChatInput.stories.tsx.tailwind.config.tsalso gains ablocklistentry: JIT scans comments, and an ellipsis insidevar(…)in a doc comment emitted invalid CSS that broke the build.What to QA
/. The palette lists Commands, then the agent's skills and tools. Typing filters;/moputs/modelfirst./model: pick a model. The composer clears, the Model & Harness section in the config panel pulses, and the next send runs on the new model with no commit./harness: pick a harness that cannot run the current model. The panel warns before applying, and applying moves the model to a fallback./permissions: pick a policy. The Advanced section pulses, and existing permission rules in the config drawer survive./in the composer./mid-word (and/or, a URL) does not open the palette; a message starting with an unmatched slash still sends on Enter; the config drawer's own model and harness pickers behave as before.Preview
slash-commands.mp4