Commit Graph

81 Commits

Author SHA1 Message Date
morgmart 481af65328 context panel: default closed, widget UI, and worktree list (#98)
- Default context panel to closed; persist open/close state per session
  in chatSessionStore (in-memory, not localStorage)
- Redesign panel sections as widget cards with bordered containers and
  filled headers, replacing the accordion pattern
- Show worktree list directly in workspace widget instead of count text
- Migrate icons from lucide-react to @tabler/icons-react
- Clean up placeholder section copy
2026-04-03 14:07:58 -07:00
Wes 97b5ba393a fix: refresh sidebar when project is edited (#95)
* fix: refresh sidebar when project is edited from Projects page

Route loadProjects() through the Zustand projectStore instead of
calling listProjects() directly so mutations update the sidebar.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: prevent project edit dialog from resetting form fields mid-typing

The useEffect that populated form fields ran on every editingProject prop
change. Since AppShell recreated this object on every render, any parent
re-render would reset all form fields, losing user input.

- Track dialog open transition with prevOpenRef to only populate on open
- Track editingProject.id with prevEditingIdRef for project identity changes
- Memoize editingProject prop in AppShell to stabilize object reference
- Add 12 tests covering form state preservation behavior

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: use stable Zustand selector to prevent fetch loop in ProjectsView

Address PR review feedback: useProjectStore() subscribed to the full
store, causing loadProjects to be recreated on every state change and
triggering repeated IPC calls. Select fetchProjects directly for a
stable reference.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-03 12:03:52 -07:00
morgmart 7f6db5bcc1 polish chat toolbar and sidebar with provider icons and cleaner labels (#93)
* UI polish: provider icons, dynamic placeholder, sidebar refinements

- Add provider icons (Goose, Claude Code, Codex) to the provider
  selector dropdown and trigger button
- Make chat input placeholder dynamic based on selected provider
  ("Message Claude Code, @ to mention personas")
- Lighten placeholder text color and font weight
- Update toolbar button variant to use text-foreground
- Fix dropdown icon alignment for single-line vs multi-line items
- Hide sidebar scrollbar while preserving scroll functionality
- Shrink sidebar collapse toggle button from 32px to 24px
- Add right padding to chat row for ellipsis menu breathing room
- Extract formatProviderLabel as shared utility

* fix code review issues: lint, dead code, theme token, tests

- Remove unused Plus import and onNewChat prop from Sidebar
- Fix Biome formatting in ChatInputToolbar, ProviderIcons, HomeScreen
- Fix invalid text-foreground-muted token to text-muted-foreground
- Remove dead onCreateProjectFromFolder prop chain across all components
- Fix CodexIcon hardcoded white fill to transparent
- Update tests for renamed labels (provider, project, placeholder)
- Remove extra blank line in Sidebar

* fix e2e smoke test for updated placeholder text

Update Playwright regex to match new placeholder format
"Message {name}, @ to mention personas".

* fix keyboard accessibility for show-on-hover sidebar buttons

Add group-focus-within:visible and group-focus-within:opacity-100
so the "New project" and item menu buttons are reachable via tab
navigation, not just mouse hover.
2026-04-03 10:53:53 -07:00
Nahiyan Khan 970d99b982 fix: sidebar hover text and project item styling (#89)
* fix: sidebar project/recent items hover text and styling

- Style project items to match recent chat row appearance (padding, gap, font-light)
- Fix hover text color on project and recent items by adding relative z-10
  to the projects section so it renders above the sliding highlight overlay
- Use group-hover for consistent text color change across the full row
- Switch sidebar settings to top bar, remove overflow-hidden on main

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: resolve biome lint errors

Replace `any` with `unknown` in debounce, remove unused biome-ignore
comments, fix exhaustive-deps warning, and suppress static element
interaction lint for hover wrapper div.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor: extract useSidebarHighlight hook to stay under file size limit

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 22:59:11 -04:00
morgmart a0bbe236ca add context panel with git workspace details to chat view (#92)
* feat(chat): add context panel toggle to ChatView

- Introduced a context panel in ChatView that can be opened or closed via a button, enhancing the user interface by allowing users to manage context visibility.
- Updated the layout to accommodate the context panel, ensuring a responsive design that maintains usability.
- Added imports for new components and adjusted state management to handle the context panel's open/close state.

This change improves the overall chat experience by providing users with more control over the interface elements they wish to view.

* feat(chat): integrate @tabler/icons-react for context panel toggle

- Added @tabler/icons-react to the project dependencies to enhance icon usage.
- Replaced existing icon imports in ChatView with Tabler icons for better visual consistency.
- Updated the context panel toggle button to utilize the new icons, improving the user interface.
- Refactored the ContextPanel component to implement tabs for better organization of content.

This update enhances the chat interface by providing a more modern and visually appealing icon set, while also improving the overall user experience with better content organization.

* chore: transition from lucide-react to @tabler/icons-react for icon usage

- Updated AGENTS.md to reflect the migration from `lucide-react` to `@tabler/icons-react` for icon components.
- Adjusted ChatView to maintain existing `lucide-react` usage until full migration is complete.
- Enhanced documentation to guide future icon implementation.

This change ensures a consistent iconography across the project while preparing for a complete transition to the new icon library.

* refactor(git): streamline git state retrieval and improve code readability

- Consolidated the retrieval of the current repository root and branch into a more concise format.
- Enhanced the readability of the code by restructuring the way worktree paths and branches are processed.
- Improved the handling of dirty file counts by maintaining consistent function calls.

These changes optimize the git state retrieval process and enhance code clarity, making future maintenance easier.
2026-04-02 19:48:36 -07:00
Nahiyan Khan 9660b4af65 Remove unused use-text-animator hook (#90)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 19:21:25 -04:00
Wes d6e9359fca fix: update E2E tests for Radix dialog component changes (#87)
The Tailwind v4 upgrade (#85) replaced dialog components with Radix UI
primitives that use aria-labelledby instead of aria-label. Update E2E
tests to check DialogTitle h2 text instead of missing aria-label attrs,
and use getByRole("button", { name: "Close" }) for the X close button.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 15:13:19 -07:00
Wes ffed31739a Sort project chats newest-first and increase show-more limit to 5 (#84)
- Add descending updatedAt sort for project chat lists in sidebar so new chats appear at the top instead of the bottom
- Increase MAX_VISIBLE_CHATS from 3 to 5 so more chats are visible before the 'Show more' button
2026-04-02 14:57:02 -07:00
morgmart a22980320a resize large images before sending and preserve images across home-to-chat transition (#86)
* feat(chat): enhance image handling in chat input and views

- Added image resizing functionality to optimize pasted images before sending.
- Updated ChatInput to utilize the new resizing feature when adding images.
- Modified ChatView and AppShell to support initial image state and handle images in message sending.
- Adjusted HomeScreen to pass images along with messages during chat initiation.

This improves the user experience by ensuring images are properly processed and displayed in the chat interface.

* refactor(chat): centralize PastedImage type definition

- Moved the PastedImage type definition from ChatInput to a shared types file for better code organization and reusability.
- Updated imports in ChatInput, ChatView, HomeScreen, and AppShell to reference the new location of PastedImage.

This change enhances maintainability by ensuring a single source of truth for the PastedImage type across the application.

* refactor(chat): extract resizeImage to lib and fix formatting

* fix(chat): enhance initial message handling in ChatView

- Updated the condition for sending the initial message to include checks for both initialMessage and initialImages, ensuring that images are also sent when available.
- This change improves the functionality of the chat interface by allowing for a more comprehensive initial message setup.

* fix(chat): fix formatting and type error in initial message handler
2026-04-02 14:54:26 -07:00
Taylor Ho 99a4d62b07 feat: import boss-ui components + Tailwind v4 upgrade (#85)
* feat: import boss-ui components + upgrade to Tailwind v4

- Upgrade Tailwind CSS v3 → v4 with @tailwindcss/postcss, tw-animate-css
- Replace tailwind.config.js with CSS @theme blocks in globals.css
- Import boss-ui token system (semantic backgrounds, borders, text, shadows,
  shapes, typography scale, animations, layout tokens)
- Import 49 shared UI components from squareup/boss-ui
- Import 48 AI element components from squareup/boss-ui
- Import 4 hooks from squareup/boss-ui
- Install all required dependencies (Radix UI primitives, UI libs, content
  libs, form/utility libs)
- Migrate all 35+ feature files from custom tokens to standard shadcn/boss-ui
  tokens (bg-background, text-foreground, bg-accent, text-muted-foreground,
  border-border, etc.)
- Align to boss-ui visual language: flat border-driven design, no elevation
  on sidebars/inputs, shadow-popover for menus, shadow-card for dialogs
- Fix low-contrast text by removing opacity modifiers on text-muted-foreground
- Update biome.json, tsconfig.json, check-file-sizes.mjs for imported code
- Re-add custom Button variants (toolbar, xs, icon-sm, icon-lg)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor: swap vanilla HTML to boss-ui components

- Replace hand-rolled dialogs with Dialog/DialogContent in
  CreateSkillDialog, CreateProjectDialog, PersonaEditor
- Replace delete confirmations with AlertDialog in AgentsView,
  ProjectsView, SkillsView, SettingsModal, DoctorCheckRow
- Replace raw <input> with Input component (6 instances)
- Replace raw <textarea> with Textarea component (3 instances)
- Replace raw <select> with Select/SelectTrigger/SelectContent/
  SelectItem (5 instances)
- Replace raw <label> with Label component throughout
- Replace <input type="checkbox"> with Checkbox component
- Replace div border-t dividers with Separator in settings
- Fix Radix SelectItem empty-string value crash by using sentinel
- Set sidebar to bg-background

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: use default Button variant for send and remove focus ring on textarea

Use the boss-ui Button default variant (bg-primary) for the send button
instead of custom bg-foreground overrides. Suppress the global
focus-visible ring on the chat textarea to prevent the black outline.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add Cash Sans Wide display font to headlines

- Download Cash Sans Wide font files (5 weights) from boss-ui
- Add @font-face declarations in globals.css
- Switch page titles, settings headings, home clock/greeting, and
  chat empty state to font-display (Cash Sans Wide) with tracking-tight
- Use Badge component with secondary variant for PersonaCard pills
- Remove redundant "Personas" section subtitle
- Upgrade "Active Agents" heading to display font

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor: swap remaining vanilla HTML to boss-ui components

Replace ~56 raw <button> elements across 20 files with the Button
component, hand-rolled toggle groups with ToggleGroup, img/div avatar
patterns with Avatar, animate-pulse skeletons with Skeleton, and a
raw <input> with Input.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor: move ai-elements into shared/ui directory

Relocate src/components/ai-elements/ to src/shared/ui/ai-elements/
to colocate with the rest of the boss-ui component library. No import
updates needed as these components are not yet consumed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* style: remove mono font from skill names

Use default sans-serif for skill names in the list and create dialog
to match persona card styling. Keep mono only for instructions textarea.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor: swap chat sub-components to boss-ui ai-elements

Replace hand-rolled ToolCallCard, ThinkingBlock, and MarkdownContent
with the ai-elements Tool, Reasoning, and MessageResponse compounds.
Action buttons now use MessageAction with built-in tooltip support.
Add @source for streamdown so Tailwind generates its utility classes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: prevent whole chat pane from scrolling

Add overflow-hidden to main content area so the flex layout chain
properly constrains scrolling to the MessageTimeline, keeping the
chat input and status bar pinned at the bottom.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: prevent document-level scrolling in chat view

Two issues caused the entire page to scroll when viewing chat:

1. scrollIntoView() in MessageTimeline scrolls all ancestors including
   the document. Replaced with container.scrollTo() which only scrolls
   within the message timeline container.

2. Tailwind v4 preflight doesn't set height/overflow on html/body like
   v3 did. Added height: 100% + overflow: hidden on html, body, #root
   outside @layer base so the cascade can't override them.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: prevent tool call results from overflowing chat viewport

Add min-w-0 and w-full to message content containers so flex items
respect the max-w-[85%] boundary. Wrap tool output pre blocks with
whitespace-pre-wrap so result text flows within the code block.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: use accent color for text selection highlight

The previous selection background (#1a1a1a) was nearly invisible against
the dark input background. Now uses the user's accent color at 60% opacity.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: minimize tool call UI — remove icon, borders, and completed badge

Strip visual noise from collapsed tool calls: remove wrench icon
(via optional showIcon prop), remove border/rounded container, replace
status pill with plain text, hide "Completed" status entirely, and
use inline chevron caret next to the tool name.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: center sidebar icons in collapsed state

Add gap-0 to collapsed button styles to prevent hidden text spans
(w-0 opacity-0) from creating flex gaps that shift icons off-center.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: align button, input-group, and toggle to pill shape

Restore rounded-full on button base and remove redundant rounded-md
from size variants. Update input-group container to rounded-full and
toggle to rounded-full to match the pill design language.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: override browser text-align:center default on buttons

Browsers default <button> to text-align:center. This causes short text
inside flex-1 spans to appear centered even when justify-start is set,
since justify-start controls flex child positioning but text-align
controls text within those children.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: replace main's color tokens with our theme tokens

The merge from main brought in color tokens (foreground-tertiary,
foreground-secondary, background-primary, background-tertiary, etc.)
that don't exist in our theme. Map them to our equivalents:

- foreground-tertiary/secondary → muted-foreground
- foreground-danger → destructive
- background-primary → background
- background-tertiary → accent
- background-danger → destructive
- border-border-secondary → border-border

Fixes invisible send button arrow (text-background-primary → text-background).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: add compat color scales and register brand/danger in theme

The Tailwind v4 theme resets all colors with --color-*: initial then
only declares a minimal palette. This silently broke ~120 class usages
across ai-elements that rely on standard Tailwind scales (red-400,
green-600, zinc-800, etc.).

Add compat color stops for the specific scales actually used:
- red-{50,400,500,600,700,900}
- green-{400,500,600,700,900}
- blue-{400,500,600,700,900}
- yellow-{400,500,600,700,900}
- orange-{100,400,600,700,900}
- zinc-{100,400,800,950}
- amber-500

Also register brand and danger in @theme inline so Tailwind can
generate text-brand, bg-brand, text-danger, etc. utilities.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: address PR review — SidebarRail type + artifact link policy

1. Add type="button" to SidebarRail button to prevent accidental form
   submissions per AGENTS.md requirement.

2. Restore artifact policy enforcement for markdown links in chat.
   The switch to MessageResponse/Streamdown lost the link interception
   that enforced allowed roots. Extract useArtifactLinkHandler hook
   that intercepts local link clicks via event delegation and routes
   them through useArtifactPolicyContext.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: restore artifact open-file actions in tool call cards

The switch from ToolCallCard to ToolCallAdapter dropped the artifact
policy integration that showed "Open file" buttons on tool results.
Add ArtifactActions component that uses resolveToolCardDisplay from
ArtifactPolicyContext to render primary and secondary open actions
with path safety enforcement.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: add confidence labels, blocked reasons, and artifact policy tests

ArtifactActions was missing "detected" labels for low-confidence
candidates and per-candidate blockedReason text. This made the
feature appear broken even though the plumbing was correct. Also
adds test coverage for ToolCallAdapter artifact integration and
useArtifactLinkHandler to prevent future regressions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 13:59:46 -07:00
tulsi e6e7c8b7cd Allow opening explicit outputs outside artifact roots (#82)
* Allow opening explicit outputs outside artifact roots

* fix: tighten artifact path opening rules
2026-04-02 10:45:30 -07:00
morgmart 7b09bdcc18 add project colors and icon support to chat input toolbar (#83)
* feat(chat): enhance chat input components with project color and icon support

- Added optional `color` property to `ProjectOption` interface for project color representation.
- Updated `ChatInputSelectorItem` to include an optional `icon` property for enhanced item display.
- Introduced `ProjectDot` component in `ChatInputToolbar` to visually represent project colors.
- Modified `ChatView` and `HomeScreen` to utilize the new `color` property for projects.
- Improved button components to support left and right icons for better UI flexibility.

* fix: apply biome formatting and guard asChild against icon props
2026-04-02 10:45:08 -07:00
Wes 15f512eae3 fix: restore sidebar goose icon (#81) 2026-04-02 09:25:58 -07:00
Wes 9d268e6463 document setup flow and clean node_modules (#80) 2026-04-02 08:38:25 -07:00
Matt Toohey 4b1d9e70c5 fix: add new project includes to the bottom instead of the top (#77)
* fix: add new project includes to the bottom instead of the top

Previously, `buildEditorText` placed `include:` lines at the top of
the editor text, above the prompt. This meant clicking "Add directory"
would insert the new include above any text the user had already typed.

Now includes are placed at the bottom of the editor as a trailing block,
and `parseEditorText` collects them from the bottom instead of the top.
This feels more natural — the user's prompt text stays at the top and
directory includes accumulate below it.

No migration needed: workingDirs and prompt are stored separately in
project.json, and `buildEditorText` reconstructs the editor text in
the new layout when the dialog opens.

* fix: parse project includes anywhere in prompt editor
2026-04-02 21:12:47 +11:00
Matt Toohey 1915aa4e3d fix: persist ACP streaming messages incrementally (#76)
* feat(chat): persist ACP assistant messages while streaming

* perf(chat): batch ACP persistence at content boundaries

* fix(chat): resolve ACP streaming stop races

* fix(chat): resolve ACP terminal-state races
2026-04-02 17:06:58 +11:00
Matt Toohey 8036e814b5 fix: set binary name to 'Goose' for macOS Dock and App Switcher (#75)
Without an explicit [[bin]] section, Cargo uses the package name 'goose2'
as the binary name. macOS uses the process/binary name for the Dock and
App Switcher labels in dev mode, so the app appeared as 'goose2' instead
of 'Goose'.
2026-04-02 17:04:19 +11:00
Matt Toohey 096baecd06 fix: resolve ACP working directories to absolute paths (#72)
* fix(acp): validate and absolutize session working dir

* fix(chat): show ACP session errors in history

* fix(chat): surface tauri invoke error messages

* fix(acp): expand tilde working directories

* fix(acp): recreate missing working directories

* refactor(chat): simplify ACP error handling

* style: format rust changes
2026-04-02 16:04:08 +11:00
Matt Toohey d15244758a fix: prevent file drags from replacing the app view (#71)
* fix: prevent dropped files from replacing the app view

* test: use drag events in app navigation test
2026-04-02 13:42:32 +11:00
Matt Toohey 25710dc534 refactor: remove top-level chat tabs (#70)
* refactor: remove top-level tabs

Replace tab-based navigation with a single active session flow in the app shell and sidebar. Remove the persisted ui_state save/load path from the frontend and Tauri backend, keeping only the unrelated home-directory command in a dedicated system command module. Update affected tests and fixtures to match the new session-only model.

* feat: restore top bar home button
2026-04-02 12:00:21 +11:00
morgmart 905c85775f feat: add image paste support to chat input (#68)
* feat: add image paste support to chat input

Users can now paste screenshots and images directly into the chat input with Cmd+V. Pasted images show as thumbnails with a click-to-expand lightbox and a hover-reveal remove button. Images are forwarded to the ACP agent as base64 content blocks alongside the text prompt.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: update ChatInput tests for new images argument

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: scope object URL cleanup to unmount only

Revoke only runs on component unmount (via a ref to latest images),
not on every add/remove. Previously the effect's cleanup re-ran on
every images state change, revoking URLs that were still in use.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: render image content blocks in message timeline

Add 'image' case to renderContentBlock in MessageBubble so pasted
images appear in the chat history after sending. Base64 sources are
rendered as data: URLs; URL sources rendered directly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: handle image-only sends and clean up debug logs

- Pass a single space as prompt when images are present but text is empty,
  preventing goose from rejecting empty-text ACP content blocks
- Make images in the message timeline clickable via lightbox (ClickableImage)
- Suppress Radix Dialog aria-describedby warning in ImageLightbox
- Remove temporary debug console.logs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat: add drag-and-drop image support to chat input

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* refactor: extract ClickableImage to fix file-size lint limit

MessageBubble.tsx was 516 lines (limit 500). Moves ClickableImage
into its own file to bring it under the limit.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 17:10:09 -07:00
Wes 8d8a2fd3bd Prevent tab name text from being selectable (#67)
Add select-none to the tab container className, consistent with
how other interactive elements like dropdown menus are styled.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-01 15:24:44 -07:00
Wes d3408296a6 fix: update chat title immediately on send (#66)
When a user sends a message from a "New Chat" tab, the session title
now updates instantly from the message text instead of waiting for the
full AI response to complete (acp:done) or the backend title generation
(acp:session_info). This gives immediate feedback in the sidebar and
tab bar.

The backend-generated title from acp:session_info will still overwrite
this initial title if it arrives later, providing the best of both
worlds: instant feedback + quality titles.
2026-04-01 14:40:15 -07:00
tulsi 517e59c603 ship artifact v1 file viewing with ranked open actions (#63)
* fix ACP artifact persistence and default artifact working dir

* add artifact path policy core helpers

* add artifact policy ranking and scope tests

* wire artifact policy context into chat and markdown links

* add ranked artifact actions to tool call cards

* collapse internal tool steps and document artifact rollout

* test: ensure localStorage API in vitest setup

* fix artifact path resolution edge cases and remove retro doc
2026-04-01 14:26:32 -07:00
Wes a0bd7cbf25 Make Cmd+W close the active tab instead of the window (#64)
Intercepts the Cmd+W keydown event in the AppShell keyboard handler
to close the current active tab via closeAndCleanupTab. When no tab
is active, the shortcut is swallowed with no effect.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-01 13:53:14 -07:00
Wes 64eaaa7b4a track chat activity and unread state per session (#62)
* feat: isolate chat session runtime state

* fix: initialize per-session chat runtime
2026-04-01 13:30:36 -07:00
morgmart 1af6e66c00 polish sidebar hierarchy and speed up sidebar reloads (#61)
* Polish sidebar hierarchy and speed up sidebar hydration

* Avoid clobbering tab selection during startup

* Refine active chat row and project spacing
2026-04-01 13:28:28 -07:00
morgmart 38423edd55 centralize provider selection state in agentStore (#54)
* feat: centralize provider selection state in agentStore

Move provider discovery and selection from per-component state to a
shared store, ensuring the selected provider persists across screens
and is loaded once on app startup. Adds loading state for the provider
dropdown and removes hardcoded provider labels in favor of API data.

* fix: restore default provider after persona override
2026-04-01 11:37:03 -07:00
Wes 396ab4154b feat: surface ACP model and token info in status bar and chat input (#53)
* feat: wire ACP token/context info into status bar and chat input

Surface model name and context window usage in the UI:
- Redesign StatusBar with Bot icon and model name display
- Add contextLimit to TokenState for context window tracking
- Wire tokenState from chatStore through ChatView to ChatInput
- Add acp:usage_update event listener in useAcpStream (ready for
  backend plumbing)

The ContextRing in ChatInputToolbar will activate once the backend
emits acp:usage_update events with context window size data.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: show truncated session ID next to copy button in status bar

The previous change hid the session ID text and only showed the copy
icon. Restore the first 8 characters of the session ID as visible text.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: remove always-red status dot from StatusBar

The status dot was permanently red because `setConnected(true)` is
never called anywhere in the codebase. Remove the dead code: the dot,
the statusColor map, the status prop, and the connectionStatus
derivation in AppShell.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: use npx for biome in justfile fmt-check recipe

The bare `biome` command fails when invoked from lefthook's pre-push
hook because node_modules/.bin isn't on PATH. Use `npx biome` to
match the pattern used in pre-commit hooks.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: respect direct accumulatedTotal in updateTokenState reducer

The reducer always recomputed accumulatedTotal as accumulatedInput +
accumulatedOutput, silently dropping any directly-passed value. This
meant acp:usage_update events (which only provide a total used count)
were ignored, keeping the context ring at 0.

Now partial.accumulatedTotal takes precedence when provided, falling
back to the input + output sum otherwise.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-01 11:12:04 -07:00
Wes 10632df518 chore: migrate biome from hermit to pnpm devDependency (#52)
- Pin @biomejs/biome to exact version 2.4.9 (was ^2.4.6)
- Remove biome hermit package (bin/biome, bin/.biome-2.4.9.pkg)
- Update justfile fmt-check to resolve biome via pnpm exec

This ensures the VS Code extension, pre-commit hooks, and CI all
resolve biome from node_modules consistently, without relying on
hermit PATH activation.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-01 10:39:14 -07:00
Wes c515bb48c2 feat: make personas optional (#51)
* feat: make personas optional — allow chatting without a persona

Adds a "Goose" / no-persona option to the persona picker so users can
chat directly with the agent without any persona system prompt injected.
HomeScreen and ChatView now default to no persona selected.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: update HomeScreen test for optional persona default

The HomeScreen now defaults to no persona selected, so the placeholder
reads "Message Goose..." instead of "Message Solo...".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-01 10:19:53 -07:00
Wes 188ca21ac0 feat: add e2e tests for personas and skills views (#50)
Add comprehensive Playwright e2e tests for the Personas and Skills
features (34 new tests). Includes a Tauri IPC mock fixture that injects
window.__TAURI_INTERNALS__ via page.addInitScript(), enabling tests to
run against the static build without the Tauri backend.

Tests cover: navigation, card/list rendering, create/edit dialogs,
form validation, dropdown menus, delete confirmations, search filtering,
empty states, and built-in vs custom persona behavior.

Also fixes lefthook pre-commit format hook to use npx for biome.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-01 09:59:56 -07:00
morgmart 5bdb225a07 fix: restore project prompt editor workflow (#49) 2026-04-01 09:24:08 -07:00
Wes 93f3509906 centralize built-in personas in the backend (#48)
* Update built-in personas to Solo, Scout, and Ralph

Replace the previous 4 built-in personas (Goose, Scout, Reviewer, Architect)
with 3 new ones pulled from Sprout: Solo (default), Scout, and Ralph.
Avatars resized from 128x128 to 64x64 to match UI display sizes.
Persona constants extracted to builtin_personas.rs to stay under file size limit.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Refactor: remove duplicated system prompts from frontend

Replace the ~300-line BUILTIN_PERSONAS array (which duplicated all system
prompts from the Rust backend) with minimal BUILTIN_PERSONA_STUBS that
only carry metadata. The backend is the single source of truth for
system prompts, served via listPersonas() on startup.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: remove legacy frontend persona stubs

* style: fix rust formatting

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-01 09:14:49 -07:00
Alex Hancock b056a77a4f fix: adjust protocol name in AGENTS.md (#47) 2026-04-01 08:29:19 -07:00
Bradley Axen 71d5c94137 refactor: use ~/.agents/skills as standard skill storage path (#46)
* feat: use ~/.agents/skills as standard skill storage path

Migrate skill storage from ~/.goose/skills/ to ~/.agents/skills/ to
align with the cross-agent standard (agentskills.io) convention where
global skills live at ~/.agents/skills/ and local skills at
<project>/.agents/skills/.

Changes:
- Update skills_dir() in Rust backend to use .agents/skills
- Add AGENTS_STANDARD_DIR and SKILLS_DIR constants to storage.ts
- Existing .goose/ constants preserved for other goose-specific data

* chore: remove dead storage.ts constants file

Delete src/shared/constants/storage.ts and the now-empty constants/
directory. None of the constants (GOOSE_DIR, RECIPES_DIR, AGENTS_DIR,
SESSIONS_DIR, EXTENSIONS_DIR, AGENTS_STANDARD_DIR, SKILLS_DIR) were
imported anywhere in the frontend codebase.

Storage path logic lives entirely in the Rust backend (e.g.
skills_dir() in src-tauri/src/commands/skills.rs), and the frontend
communicates through Tauri invoke() commands. Keeping unused path
constants in the frontend was misleading dead code.
2026-04-01 08:26:37 -07:00
Bradley Axen 6bf9eff796 Remove unused goosed sidecar and HTTP fetch infrastructure (#45)
The app communicates with AI backends exclusively through ACP
(stdin/stdout JSON-RPC), not through goosed's HTTP API. The sidecar
was spawned and health-checked but none of its endpoints were ever
called — apiFetch had zero callers and useSidecar had zero importers.

Removed:
- src-tauri/src/commands/sidecar.rs (SidecarState, start/stop/health commands)
- src/shared/hooks/useSidecar.ts (unused React hook)
- src/shared/api/fetch.ts (apiFetch/clearServerConfigCache, zero callers)
- reqwest and rand Cargo dependencies (only used by sidecar)

Updated AGENTS.md to document ACP
2026-04-01 07:17:35 -07:00
Matt Toohey 39fbd47825 feat: add local persona avatars with drag-and-drop upload (#44)
Local persona avatars now support both dropped URLs and uploaded image files. Local files are stored in ~/.goose/avatars/, exposed through Tauri's asset protocol, and rendered through shared avatar resolution helpers.

The persona editor now uses a drag-and-drop avatar picker, and all persona avatar surfaces were updated to handle local avatar sources correctly.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 18:35:03 +11:00
Matt Toohey 903f78a93b feat: add multi-persona chat context and attribution (#42)
* feat: add persona targeting fields to message metadata

Add target_persona_id, target_persona_name, and acp_session_key fields
to message metadata in both Rust and TypeScript types.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add composite key storage and persona-filtered messages to ACP store

Support per-persona ACP sessions via {sessionId}__{personaId} composite keys,
and add persona-based message filtering for multi-persona chat.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add catch-up context builder for multi-persona conversations

Add persona_name field to Rust MessageMetadata. Create catchup module
that builds context text from intervening messages when switching
between personas, so each persona stays informed about conversation
activity from other participants.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: wire persona params through AcpService with catch-up context

Set persona metadata on user and assistant messages. Build catch-up
context from intervening messages and include it in the effective
prompt sent to the ACP driver.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: pass persona params through frontend API to Tauri backend

Add personaId and personaName parameters to acpSendMessage so the
frontend can target specific personas when sending messages.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: set persona target metadata on user messages in useChat hook

When personaInfo is provided, set targetPersonaId and targetPersonaName
on the user message metadata so downstream systems can identify which
persona each message is addressed to.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: use composite session key in ACP registry for per-persona cancellation

Update registry register/deregister/cancel to use composite keys
({sessionId}__{personaId}) so cancelling one persona's stream doesn't
affect another persona's active session.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add persona selector UI and message attribution display

Add dropdown persona picker in chat input for selecting which persona
to address. Display persona attribution on message bubbles showing
sender/recipient persona names.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: resolve code review issues in multi-persona chat

- Fix UTF-8 panic in truncate_text by using char_indices instead of byte slicing
- Remove dead code in catchup.rs (unreachable else branch after early return)
- Pass persona params through to acpSendMessage in useChat hook
- Deduplicate composite key logic by delegating store.effective_key to make_composite_key

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: address remaining multi-persona review issues

Stabilize catch-up context by excluding the current prompt by message ID instead of array position. Preserve original persona targeting on retry, split composite registry keys in running-session payloads, keep assistant agent names visible alongside persona badges, and remove unused acpSessionKey metadata.

* fix: use per-message persona names in chat history

* fix: restore classic assistant name styling

* fix: remove user persona attribution from chat history

* fix: resolve multi-persona review follow-ups

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 17:15:00 +11:00
morgmart 5ae02923f0 unify chat input project and provider controls (#43)
* feat: unify chat input project and provider controls

* fix: apply code review fixes for formatting and type safety

* test: mock syntax highlighter in vitest setup

* test: update smoke placeholder assertion
2026-03-31 23:07:55 -07:00
morgmart 5cf78e7dc3 expand design system primitives with shadcn compatibility (#41)
Add shadcn CSS variable compatibility layer, new button variants (toolbar, icon sizes), and complete dropdown menu components (checkbox, radio, sub-menus). Fix focus styles to use focus-visible for keyboard-only indicators.

Made-with: Cursor
2026-03-31 22:36:41 -07:00
Matt Toohey 76495b5e6c feat: add prompt editor to project creation (#40)
* feat: change ProjectInfo working_dir to working_dirs Vec<String>

Update backend data model to support multiple working directories.
Add backward-compatible deserialization for old workingDir format.
Update create_project and update_project command signatures.
Exclude .agents from biome to fix pre-existing Markdown check errors.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: update TS API layer for workingDirs array

Change ProjectInfo.workingDir to workingDirs: string[] and update
createProject/updateProject function signatures.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: add PromptEditor component with blue capsule rendering

ContentEditable component that renders include: lines as styled
blue capsules while keeping plain text editing for other lines.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: integrate PromptEditor into CreateProjectDialog

Replace dedicated working directory input with unified prompt editor.
Add directory button inserts include: lines. Parse on save extracts
workingDirs array from include: lines.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: update chatProjectContext for workingDirs array

getProjectFolderOption returns array of folder options.
buildProjectSystemPrompt lists all working directories.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat: update UI components for workingDirs array

Update AppShell, ProjectsView, ChatView, and other components
to use workingDirs instead of workingDir.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: resolve code review feedback for PromptEditor and CreateProjectDialog

- Revert biome.json ignoreUnknown back to false (exclude alone suffices)
- Extract shared INCLUDE_RE regex to lib/includePattern.ts
- Only parse include: lines from beginning of text, not anywhere
- Fix contentEditable cursor jumping with lastPushedValue ref
- Add onPaste handler to ensure only plain text is inserted
- Add accessibility attrs (role, tabIndex, aria-multiline, aria-label)
- Add overflow-y-auto so resize-y works on the contentEditable div
- Add dark:text-blue-400 for capsule text contrast in dark mode
- Fix biome lint warnings (useTemplate, noUselessContinue)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: re-render PromptEditor HTML on every input to sync capsule styling

The contentEditable div was not re-rendering its innerHTML on user
input, so blue capsule styling from include: lines persisted even
after the text was edited to no longer match the regex. Now handleInput
re-renders via renderLines on every keystroke, with caret position
save/restore to avoid cursor jumping.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: use line/column caret positioning in PromptEditor re-render

The flat character offset approach (range.toString().length) did not
count implicit newlines between contentEditable <div> elements,
causing the caret to land in the wrong position after re-rendering.
Switch to line/column positioning that maps directly to the
div-per-line DOM structure.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: show instructions in edit dialog after project creation

handleSave called onClose() (the prop) instead of handleClose(),
so form state was never reset. When reopening the edit dialog for
the same project, the prompt state matched the stale value, React
skipped the re-render, and PromptEditor's innerHTML was never set.

Two fixes:
- handleSave now calls handleClose() to reset form state after save
- PromptEditor initializes lastPushedValue to null so innerHTML is
  always set on mount, not just on external changes

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: stop PromptEditor from reordering characters when typing quickly

The contentEditable innerHTML was being destroyed and recreated on
every keystroke to update capsule styling, which caused the browser
to insert queued characters at wrong positions. Now only re-render
innerHTML when the set of include: lines actually changes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: address prompt editor review issues

* fix: preserve PromptEditor cursor when typing include lines

* fix: clear stale include styling in prompt editor

* fix: append selected project directories and skip duplicates

Append Add directory selections to the bottom of the prompt editor instead of inserting them ahead of the prompt body.

Skip duplicate directory insertions by normalizing include paths against the user's home directory so ~/... and absolute paths compare as the same location.

* fix: tighten project working dirs parsing

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 16:27:24 +11:00
morgmart 3085e1558b add shadcn compatibility layer and separate brand from accent colors (#39)
Split the semantic "accent" color into two concepts: brand (user-customizable
accent color) and accent (shadcn's neutral hover state). This enables using
shadcn/ui components with minimal modification while preserving the existing
theming system.
2026-03-31 21:44:13 -07:00
Matt Toohey 3eff914e60 refactor: consume shared doctor crate from builderbot (#38)
* refactor: consume shared doctor crate from builderbot

Replace the local doctor module (agents.rs, checks.rs, mod.rs, resolve.rs,
types.rs) with thin Tauri command wrappers that delegate to the shared
doctor crate extracted into block/builderbot.

- Add doctor git dependency pointing to the doctor branch in builderbot
- Delete src-tauri/src/commands/doctor/ directory (5 files, ~37KB)
- Create src-tauri/src/commands/doctor.rs with run_doctor and
  run_doctor_fix wrappers plus pub use re-exports of shared types
- No changes needed to commands/mod.rs (Rust resolves doctor.rs
  automatically) or lib.rs (same command function names)

* build: pin doctor dependency to merged commit

Switch the doctor crate from tracking the `doctor` branch to a specific
rev pin (bfce292) now that the branch has been merged into main.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: remove unused doctor imports flagged by clippy

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 15:23:13 +11:00
morgmart 7d5d789687 Revert "maximize desktop window on startup (#33)" (#37) 2026-03-31 18:57:10 -07:00
Matt Toohey 7c127eacba refactor: split doctor.rs and acp.rs into sub-modules (#36)
* refactor: split doctor.rs and acp.rs into sub-modules

Split two large files into directory modules to remove file size
exceptions from check-file-sizes.mjs:

- commands/doctor.rs (997 lines) → doctor/{mod,types,resolve,checks,agents}.rs
- services/acp.rs (509 lines) → acp/{mod,payloads,writer,store,registry}.rs

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: narrow acp payload struct visibility from pub(crate) to pub(super)

These structs are only used within the acp module itself, so pub(super)
is the minimal correct visibility, consistent with the doctor module.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 12:24:51 +11:00
Matt Toohey 971064cfa5 fix: resume existing ACP sessions instead of always creating new ones (#35)
* fix: resume existing ACP sessions instead of always creating new ones

Each message was spawning a fresh ACP session because send_prompt always
passed None as the agent_session_id. The TauriStore already persisted
the agent-to-session mapping via set_agent_session_id, but never read it
back. Added get_agent_session_id to TauriStore and wired it into
send_prompt so subsequent messages in a chat resume the existing session.

Also excludes .agents/ from biome checks to fix pre-existing hook failure
on markdown skill files.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: address code review comments on ACP session resumption

Use a typed Deserialize struct instead of serde_json::Value for
get_agent_session_id to catch schema drift at compile time, and fix
missing space after // in section divider comments.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* style: fix Rust formatting and simplify get_agent_session_id

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: remove unused Deserialize import in acp.rs

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* style: restore section divider comments in acp.rs

The previous formatting commits inadvertently stripped the
`// ---------------------------------------------------------------------------`
section dividers. Restore them for all five sections and add a narrow
file-size exception (550 lines) since the dividers push the file just
past the 500-line default.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 11:59:48 +11:00
morgmart 21af4ce4da fix: reuse open empty new chat tabs (#34) 2026-03-31 17:22:00 -07:00
morgmart 8341420435 maximize desktop window on startup (#33) 2026-03-31 16:29:01 -07:00
morgmart bd459e25d4 add shared agent skills for code-review and create-pr (#32)
Skills are stored in .agents/skills/ as the single source of truth,
with symlinks from .cursor/, .claude/, and .codex/ so all three
coding agents can discover them.

Made-with: Cursor
2026-03-31 16:00:31 -07:00