Skip to content

feat(frontend): @agenta/home-ui — the home overview, templates and agent roster leave the app - #5880

Draft
ardaerzin wants to merge 6 commits into
pkg/sessions-tabsfrom
pkg/home-ui
Draft

feat(frontend): @agenta/home-ui — the home overview, templates and agent roster leave the app#5880
ardaerzin wants to merge 6 commits into
pkg/sessions-tabsfrom
pkg/home-ui

Conversation

@ardaerzin

Copy link
Copy Markdown
Contributor

The home surface as a package: the overview, the template gallery and the agent roster.
Not run in a browser — static gates only (pnpm lint-fix 24/24, tsc --noEmit clean
for @agenta/shared, ui, entities, entity-ui, settings-ui, oss, ee, mobile).

Stacked on pkg/sessions-tabs; review only this lane's diff.

@ardaerzin

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@vercel

vercel Bot commented Aug 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
agenta-documentation Error Error Aug 11, 2026 5:10am

Request Review

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 2f77cb4f-4043-4a80-834d-10909ef0d2e9

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added coding-agent handoff actions with clipboard copying and confirmation toasts.
    • Introduced refreshed home and agents pages with shared layouts, search, activity details, usage metrics, and improved navigation.
    • Added searchable template galleries, category filters, responsive template details, and streamlined agent creation.
    • Added improved agent roster cards with activity, ownership, waiting-status indicators, and contextual actions.
  • Bug Fixes

    • Improved clipboard error handling and empty-input guidance.
    • Preserved fresh-session behavior for newly created sessions.

Walkthrough

The PR adds coding-agent clipboard support, centralizes starter-template contracts, introduces the shared @agenta/home-ui package, and migrates agent-home and agents pages to shared home, template, roster, and creation components.

Changes

Coding-agent handoff

Layer / File(s) Summary
Clipboard payload and feedback
web/oss/src/components/TemplateStrip/assets/*, web/oss/src/components/TemplateStrip/components/CopiedToast.tsx, web/oss/src/components/AgentChatSlice/hooks/useOnboardingChat.ts
Builds formatted coding-agent clipboard content, adds success-toast state, handles copy failures, and records copy intent.
Template-strip action wiring
web/oss/src/components/TemplateStrip/components/AgentIntentActions.tsx, web/oss/src/components/TemplateStrip/components/StripComposer.tsx
Adds a terminal action that invokes the coding-agent copy callback.

Shared template catalog and agent roster

Layer / File(s) Summary
Starter-template catalog API
web/packages/agenta-entities/src/workflow/*, web/packages/agenta-entities/tests/unit/agentTemplates.test.ts
Renames the template type, adds seed and lookup helpers, exports catalog metadata, and adds shared roster search state.
Template consumer migration
web/oss/src/components/TemplateStrip/*, web/oss/src/components/pages/agent-home/*, web/oss/src/state/url/template.*
Migrates template consumers to AgentStarterTemplate and shared workflow helpers.
Shared agent roster
web/packages/agenta-entity-ui/src/agent/*, web/oss/src/components/pages/agents/*
Adds AgentRosterGrid, optional card actions, shared search state, and filter-rail agent-page rendering.

Shared home surface

Layer / File(s) Summary
Home UI package
web/packages/agenta-home-ui/*
Adds package configuration and reusable home, activity, creation, template, analytics, usage, and session components.
Agent-home integration
web/oss/src/components/pages/agent-home/StripHome.tsx, web/oss/src/components/NewAgentButton/index.tsx, web/oss/src/components/pages/agent-home/components/*, web/oss/src/components/pages/agent-home/hooks/*
Replaces local home and template implementations with shared components and adapts routing, creation, session actions, and template selection.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

  • Agenta-AI/agenta#5098: Introduced the TemplateStrip components and related clipboard, toast, onboarding, and home flows.
  • Agenta-AI/agenta#5526: Modified the agent creation hook that this PR moves into shared @agenta/home-ui logic.
  • Agenta-AI/agenta#5569: Modified useOnboardingChat.ts, which this PR extends with coding-agent clipboard and toast handling.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the home UI package and its main overview, template, and agent roster changes.
Description check ✅ Passed The description directly summarizes the home UI package scope and reports the validation performed.
Docstring Coverage ✅ Passed Docstring coverage is 80.00% which is sufficient. The required threshold is 60.00%.
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 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch pkg/home-ui

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.

❤️ Share

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

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@ardaerzin

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@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: 6

🧹 Nitpick comments (15)
web/oss/src/components/TemplateStrip/components/CopiedToast.tsx (1)

8-12: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Shorten the implementation comment.

Lines 8-12 describe standard component behavior. Keep only a short comment if it documents an unusual constraint.

As per coding guidelines, keep in-code comments to one short line except for genuinely surprising constraints.

Source: Coding guidelines

web/packages/agenta-entities/src/workflow/agentTemplates.ts (1)

150-159: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use agentTemplateSeed at the template-create call sites.

OnboardingBrowseTemplates.tsx Line 34 and OnboardingConfigPanel.tsx Line 45 still construct templateBuilderMessage(template) and template.name separately. Use this helper in both places so template name and builder seed stay under one shared contract.

web/packages/agenta-entities/tests/unit/agentTemplates.test.ts (1)

3-3: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Cover the new helper contracts.

Add tests for agentTemplateSeed and agentTemplateByKey. Include a known key, an unknown key, an omitted key, and the builder-message fallback. These helpers drive template creation and URL resolution.

web/oss/src/components/pages/agent-home/hooks/useTemplateSelect.ts (1)

42-43: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Reduce this comment to one short line.

The repository limit is one short in-code comment. Move the longer rationale to documentation if it is required.

Source: Coding guidelines

web/packages/agenta-entity-ui/src/agent/AgentRosterGrid.tsx (1)

1-10: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Reduce multi-line implementation comments.

Replace these comments with one short line, or move detailed rationale to documentation.

  • web/packages/agenta-entity-ui/src/agent/AgentRosterGrid.tsx#L1-L10: reduce the module description.
  • web/packages/agenta-entity-ui/src/agent/AgentCard.tsx#L62-L63: reduce the optional-action description.
  • web/packages/agenta-entity-ui/src/agent/AgentCard.tsx#L137-L138: reduce the open-action description.
  • web/oss/src/components/pages/agents/AgentsGrid.tsx#L9-L11: reduce the roster mapping description.
  • web/oss/src/components/pages/agents/AgentsPage.tsx#L91-L92: reduce the filter-rail description.
  • web/oss/src/components/pages/agents/AgentsPage.tsx#L108-L109: reduce the archived-agent link description.
  • web/oss/src/components/pages/agents/AgentsPage.tsx#L118-L119: reduce the grid-padding description.
  • web/oss/src/components/pages/agents/store.ts#L16-L18: reduce the shared-search description.

As per coding guidelines, keep in-code comments to at most one short line except for genuinely surprising constraints.

Source: Coding guidelines

web/oss/src/components/pages/agents/AgentsPage.tsx (1)

102-105: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Debounce the agents roster search atom update.

SearchInput forwards every input change immediately, and agents WorkflowsQuery adds the search term to the TanStack query key, so typing changes the server query per keystroke. Apply a short delay before updating agentsSearchTermAtom.

Source: Coding guidelines

web/oss/src/components/pages/agent-home/StripHome.tsx (1)

3-4: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Merge the two imports from @agenta/entities/workflow.

Lines 3 and 4 both import from the same module specifier. import/no-duplicates flags this, so pnpm lint can fail on the file.

♻️ Proposed fix
-import {appTemplatesQueryAtom} from "`@agenta/entities/workflow`"
-import {AGENT_TEMPLATES, type AgentStarterTemplate} from "`@agenta/entities/workflow`"
+import {
+    AGENT_TEMPLATES,
+    appTemplatesQueryAtom,
+    type AgentStarterTemplate,
+} from "`@agenta/entities/workflow`"

As per coding guidelines: "Before committing frontend changes, run pnpm lint-fix from the web directory."

Source: Coding guidelines

web/oss/src/components/pages/agent-home/components/TemplatesGallery/index.tsx (1)

67-93: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

TemplateSetupDrawer is now unreachable on this page.

handleSelectTemplate navigates to the detail route, and nothing else calls setSetupTemplate. setupTemplate therefore stays null, open is always false, and handleTemplateCreate never runs. The drawer, its state, and the message.info stub are dead code on this page.

Either remove the drawer from this page until Phase B wires it, or restore an entry point that opens it. Do you want me to open an issue to track the Phase B wiring?

web/oss/src/components/pages/agent-home/hooks/useCreateAgent.ts (1)

47-47: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Stabilize the onError callback passed to useCreateAgentCore.

Line 47 creates a new options object and a new arrow on every render. The core hook lists onError in its useCallback dependencies, so the returned createAgent gets a new identity on every render. That identity then invalidates this hook's own useCallback (Line 91), useAgentHomeActions.onCreate, and StripHome.handleCreate. The whole create chain loses its memoization.

♻️ Proposed fix
-    const createAgent = useCreateAgentCore({onError: (text) => message.error(text)})
+    const onError = useCallback((text: string) => message.error(text), [message])
+    const createAgent = useCreateAgentCore({onError})

As per coding guidelines: "Minimize React re-renders with useMemo, useCallback, and React.memo where appropriate; avoid unstable inline functions and objects."

Source: Coding guidelines

web/packages/agenta-home-ui/src/useCreateAgent.ts (1)

49-63: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

A busy call and a failed call are indistinguishable to the host.

Line 50 returns null without calling onError when a create is already in flight. Every other failure path also returns null, but with onError. The host cannot tell the two apart.

web/oss/src/components/pages/agent-home/hooks/useCreateAgent.ts maps null to false, and StripHome.handleCreate then runs setLoading(false). A second click during an in-flight create therefore stops the spinner while the first create is still running, and the button reads as idle.

Return a discriminated result (for example {status: "busy" | "error" | "created"}), or expose an isCreating flag the host can render from.

web/packages/agenta-entities/src/session/core/freshSessions.ts (1)

14-18: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider keeping freshSessionIds module-private.

The three helpers cover mark, check, and clear. Exporting the raw Set lets any consumer mutate the tracker directly and bypass those helpers. If no consumer needs iteration, keep the Set local and drop it from the public re-export in web/packages/agenta-entities/src/session/index.ts.

♻️ Proposed change
-export const freshSessionIds = new Set<string>()
+const freshSessionIds = new Set<string>()

Then remove freshSessionIds from the export list in web/packages/agenta-entities/src/session/index.ts.

web/packages/agenta-home-ui/src/AgentsPanel.tsx (1)

66-76: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Make the recency comparator total for entries without a timestamp.

Date.parse("") returns NaN, so the comparator returns NaN for any entry that has neither agent.updatedAt nor createdAt. The specification treats a NaN comparator result as 0, so such an entry compares equal to every other entry. The comparator then becomes non-transitive and the resulting order depends on the engine's sort implementation. That defeats the stated purpose of sorting here, which is one identical order on every surface.

Map an unparseable date to 0 so undated entries sort last deterministically.

♻️ Proposed change
+const recency = (entry: AgentsPanelEntry) => {
+    const parsed = Date.parse(entry.agent.updatedAt ?? entry.createdAt ?? "")
+    return Number.isNaN(parsed) ? 0 : parsed
+}
+
 const DEFAULT_LIMIT = 5
     const shown = useMemo(
-        () =>
-            [...entries]
-                .sort(
-                    (a, b) =>
-                        Date.parse(b.agent.updatedAt ?? b.createdAt ?? "") -
-                        Date.parse(a.agent.updatedAt ?? a.createdAt ?? ""),
-                )
-                .slice(0, limit),
+        () => [...entries].sort((a, b) => recency(b) - recency(a)).slice(0, limit),
         [entries, limit],
     )
web/packages/agenta-home-ui/src/TemplateDetail.tsx (2)

249-292: 🚀 Performance & Scalability | 🔵 Trivial | ⚖️ Poor tradeoff

Both shells mount at every viewport.

identity, meta, and body are inserted into the phone shell (lines 268-270) and into FilterRailLayout (lines 283-290). React renders two independent instances of each tree, and only CSS hides one. Two effects follow. First, renderMarkdown(template.instructions) runs twice on every render, at every screen size. Second, the document contains two <h1> elements for the same template.

If the doubled markdown render becomes measurable, select one shell with a breakpoint value instead of lg:hidden / hidden lg:flex.


1-18: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Multi-paragraph rationale comments exceed the comment-length guideline. Each new component in this package opens with a long narrative block that explains design history and rejected alternatives. The guideline allows one short line, and reserves longer comments for genuinely surprising constraints such as bugs, races, or ordering requirements. Keep the parts that record a real constraint, for example the sticky-child padding note in HomeOverview.tsx line 61 and the import-cycle note in web/packages/agenta-entities/src/session/core/freshSessions.ts. Move the design rationale to the PR description or an ADR.

  • web/packages/agenta-home-ui/src/TemplateDetail.tsx#L1-L18: reduce the 18-line header to one line stating what the component renders; keep the host-supplied markdown renderer note.
  • web/packages/agenta-home-ui/src/AgentsPanel.tsx#L45-L53: reduce to one line; keep the creation-order constraint that justifies the local sort at lines 62-65.
  • web/packages/agenta-home-ui/src/HomeOverview.tsx#L32-L47: reduce to one line; keep the padding-cancellation constraint for host frames.
  • web/packages/agenta-home-ui/src/HomeTaskComposer.tsx#L24-L35: reduce to one line describing the composer's single action.
  • web/packages/agenta-home-ui/src/TemplateGallery.tsx#L1-L13: reduce to one line; keep the note on which decisions stay with the host.
  • web/packages/agenta-home-ui/src/UsageCard.tsx#L43-L51: reduce to one line; keep the reason cost and tokens sit behind Expand.
  • web/packages/agenta-home-ui/src/NewAgentButton.tsx#L43-L49: reduce to one line.
  • web/packages/agenta-home-ui/src/AgentActivity.tsx#L6-L12: reduce to one line.

Based on the coding guideline "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/packages/agenta-home-ui/src/TemplateGallery.tsx (1)

159-177: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Expose the active category to assistive technology.

The active category is conveyed only by the background color on line 167. A screen reader announces every entry identically. Add aria-pressed so the selected filter is programmatically determinable.

♿ Proposed change
                             <button
                                 key={item.value}
                                 type="button"
+                                aria-pressed={item.value === category}
                                 onClick={() => onCategoryChange(item.value)}

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: d9a1cef6-140d-4c09-abe9-aa3755cb4f3b

📥 Commits

Reviewing files that changed from the base of the PR and between 7d387ac and 6993e97.

📒 Files selected for processing (65)
  • web/oss/src/components/AgentChatSlice/hooks/useOnboardingChat.ts
  • web/oss/src/components/NewAgentButton/index.tsx
  • web/oss/src/components/TemplateStrip/assets/codingAgentClipboard.test.ts
  • web/oss/src/components/TemplateStrip/assets/codingAgentClipboard.ts
  • web/oss/src/components/TemplateStrip/assets/constants.ts
  • web/oss/src/components/TemplateStrip/components/AgentIntentActions.tsx
  • web/oss/src/components/TemplateStrip/components/CopiedToast.tsx
  • web/oss/src/components/TemplateStrip/components/IntegrationBadges.tsx
  • web/oss/src/components/TemplateStrip/components/StripCard.tsx
  • web/oss/src/components/TemplateStrip/components/StripComposer.tsx
  • web/oss/src/components/TemplateStrip/components/StripRow.tsx
  • web/oss/src/components/TemplateStrip/components/TemplateChip.tsx
  • web/oss/src/components/TemplateStrip/components/TemplateChipDock.tsx
  • web/oss/src/components/TemplateStrip/hooks/useTemplateProvenance.tsx
  • web/oss/src/components/TemplateStrip/index.tsx
  • web/oss/src/components/pages/agent-home/PlaygroundOnboarding/OnboardingBrowseTemplates.tsx
  • web/oss/src/components/pages/agent-home/PlaygroundOnboarding/OnboardingConfigPanel.tsx
  • web/oss/src/components/pages/agent-home/StripHome.tsx
  • web/oss/src/components/pages/agent-home/components/HomeAutomationsSection.tsx
  • web/oss/src/components/pages/agent-home/components/HomeSessionsSection.tsx
  • web/oss/src/components/pages/agent-home/components/TemplateDetail/index.tsx
  • web/oss/src/components/pages/agent-home/components/TemplateSetupDrawer/IntegrationRow.tsx
  • web/oss/src/components/pages/agent-home/components/TemplateSetupDrawer/ToolsPreview.tsx
  • web/oss/src/components/pages/agent-home/components/TemplateSetupDrawer/index.tsx
  • web/oss/src/components/pages/agent-home/components/TemplatesGallery/TemplateSection.tsx
  • web/oss/src/components/pages/agent-home/components/TemplatesGallery/index.tsx
  • web/oss/src/components/pages/agent-home/components/TemplatesSection/ProviderMarks.tsx
  • web/oss/src/components/pages/agent-home/components/TemplatesSection/TemplateCard.tsx
  • web/oss/src/components/pages/agent-home/components/TemplatesSection/index.tsx
  • web/oss/src/components/pages/agent-home/components/YourAgentsTable/index.tsx
  • web/oss/src/components/pages/agent-home/components/YourAgentsTable/useAgentActivity.ts
  • web/oss/src/components/pages/agent-home/hooks/useCreateAgent.ts
  • web/oss/src/components/pages/agent-home/hooks/useCreateAgentFromTemplate.ts
  • web/oss/src/components/pages/agent-home/hooks/useTemplateSelect.ts
  • web/oss/src/components/pages/agent-home/index.tsx
  • web/oss/src/components/pages/agents/AgentsGrid.tsx
  • web/oss/src/components/pages/agents/AgentsPage.tsx
  • web/oss/src/components/pages/agents/store.ts
  • web/oss/src/state/url/template.test.ts
  • web/oss/src/state/url/template.ts
  • web/packages/agenta-entities/src/session/core/freshSessions.ts
  • web/packages/agenta-entities/src/session/index.ts
  • web/packages/agenta-entities/src/workflow/agentTemplates.ts
  • web/packages/agenta-entities/src/workflow/index.ts
  • web/packages/agenta-entities/src/workflow/state/agentRoster.ts
  • web/packages/agenta-entities/src/workflow/state/index.ts
  • web/packages/agenta-entities/tests/unit/agentTemplates.test.ts
  • web/packages/agenta-entity-ui/src/agent/AgentCard.tsx
  • web/packages/agenta-entity-ui/src/agent/AgentRosterGrid.tsx
  • web/packages/agenta-entity-ui/src/agent/index.ts
  • web/packages/agenta-home-ui/eslint.config.mjs
  • web/packages/agenta-home-ui/package.json
  • web/packages/agenta-home-ui/src/AgentActivity.tsx
  • web/packages/agenta-home-ui/src/AgentsPanel.tsx
  • web/packages/agenta-home-ui/src/AnalyticsRangePicker.tsx
  • web/packages/agenta-home-ui/src/HomeOverview.tsx
  • web/packages/agenta-home-ui/src/HomeTaskComposer.tsx
  • web/packages/agenta-home-ui/src/NewAgentButton.tsx
  • web/packages/agenta-home-ui/src/TemplateDetail.tsx
  • web/packages/agenta-home-ui/src/TemplateGallery.tsx
  • web/packages/agenta-home-ui/src/UsageCard.tsx
  • web/packages/agenta-home-ui/src/index.ts
  • web/packages/agenta-home-ui/src/useAgentActivity.ts
  • web/packages/agenta-home-ui/src/useCreateAgent.ts
  • web/packages/agenta-home-ui/tsconfig.json
💤 Files with no reviewable changes (6)
  • web/oss/src/components/pages/agent-home/components/HomeAutomationsSection.tsx
  • web/oss/src/components/pages/agent-home/components/HomeSessionsSection.tsx
  • web/oss/src/components/pages/agent-home/components/TemplatesGallery/TemplateSection.tsx
  • web/oss/src/components/pages/agent-home/components/TemplatesSection/ProviderMarks.tsx
  • web/oss/src/components/pages/agent-home/components/TemplatesSection/TemplateCard.tsx
  • web/oss/src/components/pages/agent-home/hooks/useCreateAgentFromTemplate.ts

Comment on lines +206 to +212
usagePanel={
<UsageCard
expandedContent={
<AnalyticsDashboard layout="stack" showTimeRangeSelector={false} />
}
/>
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🚀 Performance & Scalability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check whether HeightCollapse unmounts children when closed, and how UsageCard renders the slot.
fd -i 'HeightCollapse' --type f | head
fd -i 'HeightCollapse' --type f --extension tsx --exec cat -n {}

echo '--- UsageCard ---'
fd 'UsageCard.tsx' --type f --exec sed -n '80,125p' {}

Repository: Agenta-AI/agenta

Length of output: 9203


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- StripHome relevant lines ---'
sed -n '1,80p' web/oss/src/components/pages/agent-home/StripHome.tsx
sed -n '180,225p' web/oss/src/components/pages/agent-home/StripHome.tsx

echo '--- UsageCard outline/lines ---'
wc -l web/packages/agenta-home-ui/src/UsageCard.tsx
sed -n '1,170p' web/packages/agenta-home-ui/src/UsageCard.tsx

echo '--- AnalyticsDashboard definitions/usages ---'
fd -i 'AnalyticsDashboard' --type f --exec sh -c 'echo "FILE $1"; sed -n "1,220p" "$1"' sh {}

echo '--- dynamic/import behavior scan ---'
rg -n "dynamic\\(|useObservabilityDashboard|AnalyticsDashboard|expandedContent|HeightCollapse" web/oss/src/components/pages/agent-home/StripHome.tsx web/packages/agenta-home-ui/src/UsageCard.tsx web/packages/agenta-sdk/src web/packages/agenta-ui/src -g '!**/node_modules/**'

Repository: Agenta-AI/agenta

Length of output: 23224


Gate the lazy analytics dashboard by the expand state.

AnalyticsDashboard is created and passed to UsageCard during returning-user Home rendering, and UsageCard always renders that node inside HeightCollapse. HeightCollapse animates height to collapsedHeight rather than unmounting its children, so the lazy-loaded analytics chunk and useObservabilityDashboard fetch can run before the user clicks Expand. Return null from ExpansionCard when expandedContent is not expanded, or pass a renderable render prop so the slot is mounted only when expanded is true.

Comment on lines 21 to 22
/** Owner-specified key (matches the design prototype; intentionally not "agenta:"-prefixed). */
export const STRIP_HIDDEN_STORAGE_KEY = "agenta-tpl-strip-hidden"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Use the required storage-key prefix.

STRIP_HIDDEN_STORAGE_KEY stores a persisted preference, but agenta-tpl-strip-hidden does not use the required agenta: prefix. Change it to a key such as agenta:tpl-strip-hidden.

As per coding guidelines, persisted preference storage keys must be prefixed with agenta:.

Source: Coding guidelines

visible ? "opacity-100" : "opacity-0"
}`}
>
<Check size={15} strokeWidth={2.4} className="shrink-0 text-[var(--ant-lime-6)]" />

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Use a semantic theme color for the icon.

--ant-lime-6 is a palette token. Replace it with an Ant Design semantic token or a supported var(--ag-color*) variable. Verify the result in light and dark themes.

As per coding guidelines, consume theme colors through semantic tokens or supported var(--ag-color*) variables. Based on learnings, validate both appearances when replacing a color token.

Sources: Coding guidelines, Learnings

Comment on lines +42 to +49
const [agentId, setAgentId] = useState<string | null>(null)

// Default to the most recently touched agent — the one you're most likely to want next.
const effectiveAgentId = agentId ?? agents[0]?.id ?? null
const selectedName = useMemo(
() => agents.find((agent) => agent.id === effectiveAgentId)?.name,
[agents, effectiveAgentId],
)

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 | 🟠 Major | ⚡ Quick win

Fall back to the default agent when the selected agent leaves the list.

effectiveAgentId short-circuits on any non-null agentId, so a stale selection survives changes to agents. If the selected agent is archived, renamed to a new id, or the project changes, two things follow: selectedName becomes undefined, so the trigger shows the robot icon with no label; and onStart receives an agentId that no longer exists. Validate the selection against the current list.

🐛 Proposed fix
-    // Default to the most recently touched agent — the one you're most likely to want next.
-    const effectiveAgentId = agentId ?? agents[0]?.id ?? null
-    const selectedName = useMemo(
-        () => agents.find((agent) => agent.id === effectiveAgentId)?.name,
-        [agents, effectiveAgentId],
-    )
+    // Default to the most recently touched agent; drop a selection that left the list.
+    const selected = useMemo(
+        () => agents.find((agent) => agent.id === agentId) ?? agents[0],
+        [agents, agentId],
+    )
+    const effectiveAgentId = selected?.id ?? null
+    const selectedName = selected?.name
📝 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
const [agentId, setAgentId] = useState<string | null>(null)
// Default to the most recently touched agent — the one you're most likely to want next.
const effectiveAgentId = agentId ?? agents[0]?.id ?? null
const selectedName = useMemo(
() => agents.find((agent) => agent.id === effectiveAgentId)?.name,
[agents, effectiveAgentId],
)
const [agentId, setAgentId] = useState<string | null>(null)
// Default to the most recently touched agent; drop a selection that left the list.
const selected = useMemo(
() => agents.find((agent) => agent.id === agentId) ?? agents[0],
[agents, agentId],
)
const effectiveAgentId = selected?.id ?? null
const selectedName = selected?.name

Comment on lines +52 to +59
<ChatComposer
onSubmit={async (text) => {
if (!effectiveAgentId) return
await onStart({agentId: effectiveAgentId, text})
}}
attachments={attachments}
placeholder="Describe the task, or start the conversation…"
disabled={!effectiveAgentId}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check how ChatComposer invokes and guards onSubmit.
fd -t f 'ChatComposer.tsx' web/packages --exec rg -n -C 15 'onSubmit' {} \;

Repository: Agenta-AI/agenta

Length of output: 4045


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Locate rich-chat-input files"
fd -t f 'rich-chat-input' web/packages --max-depth 5

echo
echo "Find handle types and use/receive of onSubmit"
rg -n -C 8 'RichChatInputHandle|onSubmit|executeSubmit|submit|handleSubmit|handleKeyPress' web/packages -g '*.ts' -g '*.tsx' | head -n 240

Repository: Agenta-AI/agenta

Length of output: 24450


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Read focused composer implementation without scanning broad files.
composer=$(fd -t f 'ChatComposer.tsx' web/packages 2>/dev/null | head -n 1)
echo "composer=$composer"
if [ -n "${composer:-}" ]; then
  wc -l "$composer"
  sed -n '1,180p' "$composer" | cat -n
fi

echo
echo "Find RichChatInput definition files by likely package path"
fd -t f 'RichChatInput.tsx|RichChatInput.ts' web/packages | xargs -r -n1 sh -c 'echo "===== $0 ====="; wc -l "$0"; sed -n "1,240p" "$0" | cat -n'

Repository: Agenta-AI/agenta

Length of output: 21923


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "SubmitPlugin implementation"
sed -n '1,260p' web/packages/agenta-ui/src/RichChatInput/plugins/SubmitPlugin.tsx | cat -n
echo
echo "Other onSubmit call sites in RichChatInput/RichChatInput.tsx"
rg -n -C 5 'onSubmit\(' web/packages/agenta-ui/src/RichChatInput/RichChatInput.tsx web/packages/agenta-ui/src/RichChatInput -g '*.tsx' -g '*.ts'

Repository: Agenta-AI/agenta

Length of output: 4644


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "RichChatInput submit helper:"
sed -n '1,70p' web/packages/agenta-ui/src/RichChatInput/assets/submit.ts | cat -n

echo
echo "Submit path from SendButton plugin:"
sed -n '1,90p' web/packages/agenta-ui/src/RichChatInput/plugins/SendButton.tsx | cat -n

Repository: Agenta-AI/agenta

Length of output: 6114


🏁 Script executed:

#!/bin/bash
set -euo pipefail

node - <<'JS'
function submitEditorAsMarkdown(trimmed, onSubmit, clearFn) {
  if (!trimmed) return {submitted: false}
  onSubmit(trimmed)
  clearFn()
  return {submitted: true}
}

function withComposerState(value, submit, clearFn) {
  let current = value
  try {
    submit()
    current = ''
    clearFn()
    return {current, submitted: true}
  } catch (e) {
    return {current, submitted: false, error: e.message}
  }
}

{
  const state = withComposerState('hello', () => {
    throw new Error('network failure')
  }, () => {})
  console.log('rejected:', state)
}

function submitWithCatchValue(value, onSubmit, clearFn) {
  try {
    submitEditorAsMarkdown(value, onSubmit, clearFn)
  } catch (e) {
    // The catch should ensure the clear path is skipped or deferred.
  }
  return value
}

{
  const state = submitWithCatchValue('hello', () => {
    throw new Error('network failure')
  }, () => {})
  console.log('caught_preservesValue:', state)
}
JS

Repository: Agenta-AI/agenta

Length of output: 258


Handle rejected onSubmit in ChatComposer.

onStart is awaited directly in HomeTaskComposer, so a rejection propagates through RichChatInput without restoration or failure reporting from the composer’s submit handler. Wrap the submission around the clear/update path or catch at the host boundary and keep showing the user's draft when onStart rejects.

Comment on lines +41 to +51
* A re-entry latch protects every caller (home button, composer, template cards) from a rapid
* double-click minting two agents; the UI-level disabled/loading guards don't cover every path.
*/
export const useCreateAgent = ({onError}: UseCreateAgentOptions = {}) => {
const commitFromEphemeral = useSetAtom(createWorkflowFromEphemeralAtom)
const inFlightRef = useRef(false)

return useCallback(
async ({name, entityId}: CreateAgentParams = {}): Promise<CreatedAgent | null> => {
if (inFlightRef.current) return null
inFlightRef.current = 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.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find the create surfaces that call the shared hook, and check whether more than one can mount together.
rg -nP --type=ts --type=tsx -C3 '\buseCreateAgent\s*\(' | head -60

Repository: Agenta-AI/agenta

Length of output: 186


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Files:"
git ls-files 'web/**/*.{ts,tsx}' | rg 'useCreateAgent|home|composer|template' || true

echo
echo "useCreateAgent usages:"
rg -n -C3 'useCreateAgent\s*\(' -g '*.ts' -g '*.tsx' web || true

echo
echo "useCreateAgent definition:"
file="$(git ls-files | rg '(^|/)useCreateAgent\.ts$' | head -1 || true)"
if [ -n "$file" ]; then
  wc -l "$file"
  sed -n '1,140p' "$file" | cat -n
fi

Repository: Agenta-AI/agenta

Length of output: 9339


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Locate `@agenta/home-ui` useCreateAgent source:"
fd -a 'useCreateAgent\.ts$|resources\.ts$|WorkflowApi|createWorkflowFrom' web/packages | sed 's#^\./##' | head -80 || true

file="$(git ls-files | rg 'packages/agenta-home-ui/src/useCreateAgent\.ts$|src/.*useCreateAgent\.ts$' | head -1 || true)"
if [ -n "$file" ]; then
  echo
  echo "Definition at $file:"
  wc -l "$file"
  sed -n '1,140p' "$file" | cat -n
fi

echo
echo "Imports/usages of `@agenta/home-ui` useCreateAgent and createWorkflowFrom:"
rg -n -C2 '`@agenta/home-ui`|createWorkflowFromEphemeralAtom|useCreateAgent\(\{|createWorkflowFromEphemeral' -g '*.ts' -g '*.tsx' web || true

echo
echo "Agents table/home buttons context:"
sed -n '1,220p' web/oss/src/components/pages/agent-home/index.tsx 2>/dev/null | cat -n || true
sed -n '1,180p' web/oss/src/components/pages/agent-home/hooks/useAgentHomeActions.ts 2>/dev/null | cat -n || true
sed -n '1,180p' web/oss/src/components/pages/agent-home/hooks/useConsumePendingTemplate.ts 2>/dev/null | cat -n || true
sed -n '1,180p' web/oss/src/components/pages/agent-home/hooks/useTemplateSelect.ts 2>/dev/null | cat -n || true

Repository: Agenta-AI/agenta

Length of output: 37271


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "web/packages/agenta-home-ui/src/useCreateAgent.ts:"
wc -l web/packages/agenta-home-ui/src/useCreateAgent.ts
sed -n '1,180p' web/packages/agenta-home-ui/src/useCreateAgent.ts

echo
echo "web/packages/agenta-entities/src/workflow/state/commit.ts atom section:"
sed -n '530,635p' web/packages/agenta-entities/src/workflow/state/commit.ts

echo
echo "Shared component create entry points:"
sed -n '1,220p' web/oss/src/components/pages/agent-home/hooks/useAgentHomeActions.ts
sed -n '1,180p' web/oss/src/components/pages/agent-home/hooks/useConsumePendingTemplate.ts
sed -n '1,180p' web/oss/src/components/pages/agent-home/hooks/useTemplateSelect.ts
sed -n '1,140p' web/packages/agenta-home-ui/src/index.ts

Repository: Agenta-AI/agenta

Length of output: 20129


Narrow or share the create-agent re-entry latch.

inFlightRef is local to each useCreateAgent() instance. Multiple create surfaces call separate hook instances, so the documented claim that this latch protects every caller across home button, composer, and template cards is too broad. Move it to module scope/Jotai if callers are expected to collide, or limit the comment to per-hook-instance repeats.

This lane reintroduces `first_agent_intent` call sites that the same fix on
`pkg/session-surfaces` couldn't see, so they still send the raw "describe your
agent" text under a `message` property. `truncateForCapture` only capped length —
a composer message can hold credentials, customer data or a pasted secret, and
none of that belongs in an analytics property.

`classifyAgentIntent` is the signal the module says it exists to capture: it
buckets the message into support/research/ops/content/coding/data/other. The two
free-text submit paths already sent that bucket alongside the raw text, so
dropping the text loses nothing there; both coding-agent-copy paths (the home
strip and the onboarding chat composer) gain the classification they never had.
`truncateForCapture` and `MESSAGE_CAPTURE_LIMIT` go with their last reference.
Two things the app's own copy of this composer already gets right, and mobile's
(the package one) did not:

- The selection short-circuited on any non-null id, so an agent that was archived,
  re-created under a new id, or lost to a project switch stayed "selected": the
  trigger rendered a robot icon with no label, and Send handed `onStart` an id that
  no longer resolves. Honour the selection only while it is still in the roster,
  else fall back to the head, else nothing — the app copy's approach.
- A rejected `onStart` was awaited with no catch. RichChatInput's submit is
  fire-and-forget, so the rejection went nowhere while the editor had already
  cleared: no message, no error, no idea the task never started. Put the draft back
  through the input handle and report it in the attachments strip, exactly as the
  mobile chat composer does for a send that can't carry its files.
`--ant-lime-6` is a raw antd palette variable that only exists where antd's CSS-var
theme is injected. The mark means "it worked", so it takes the semantic role
instead: `--ag-colorSuccess`, which the shared token layer defines for both themes
and mobile imports.
…nded

`HeightCollapse` clips its children rather than unmounting them, so whatever a host
passes as `expandedContent` mounts on the first paint of Home — desktop's slot is a
lazily-imported tremor dashboard with its own observability query, downloaded and
fired before anyone clicks Expand, on the page whose whole point is first paint.

Mount it on the first expand and keep it mounted after that. Keeping it beats
unmounting on collapse: the collapse animates height to 0 with the content still in
place, where dropping the node would animate an empty box. The prop stays a
ReactNode — building the element is free, it is the mount that costs — so both
callers (Home and the usage summary's strip variant) are fixed as they stand.
The comment claimed the latch protects every caller — the home button, the composer,
the template cards — but it was a ref inside the hook, and each of those surfaces
calls `useCreateAgent()` for itself (the classic home mounts three instances at
once). It only ever stopped one button from being double-clicked; clicking a
template card and then hitting send while the commit was in flight minted two
agents. Move the latch to module scope so the documented guarantee is the real one.
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