Skip to content

port goose2 chat attachments into goose#8534

Merged
tulsi-builder merged 9 commits intomainfrom
tulsi/port-attachments
Apr 14, 2026
Merged

port goose2 chat attachments into goose#8534
tulsi-builder merged 9 commits intomainfrom
tulsi/port-attachments

Conversation

@tulsi-builder
Copy link
Copy Markdown
Collaborator

@tulsi-builder tulsi-builder commented Apr 14, 2026

Category: new-feature
User Impact: Users can now attach files, folders, and images to Goose 2 desktop chats in this repo, with the follow-up loading and path-dedupe fixes included.
Problem: Goose 2 was ported into this monorepo before the original attachment PRs fully landed here, which risked losing desktop chat support for file and folder attachments and the hardening fixes that followed. Without this port, the new desktop app would miss mixed attachment intake, reliable attachment-only chat behavior, and the follow-up safeguards around picker errors, path dedupe, and oversized images.
Solution: This branch ports the full Goose 2 attachment feature into ui/goose2 and carries over the follow-up fixes from the old repo. The result keeps the original attachment UX intact while preserving the later reliability work for platform-aware dedupe, guarded image loading, and deterministic attachment error handling.

File changes

ui/goose2/scripts/check-file-sizes.mjs
Raises the size-budget exception for the expanded desktop system command surface. This keeps the file-size guard aligned with the new attachment helpers and follow-up hardening.

ui/goose2/src-tauri/Cargo.lock
Captures the Rust dependency updates needed for attachment inspection and local image loading. This keeps the Tauri backend reproducible after the port.

ui/goose2/src-tauri/Cargo.toml
Adds backend crates for attachment MIME inspection and base64 image handling. These dependencies support path-based attachment intake from the desktop app.

ui/goose2/src-tauri/src/commands/system.rs
Adds attachment-path inspection and local image loading commands for files, folders, and images. It also includes the follow-up platform-aware dedupe logic and the 20 MB guard for path-based image encoding.

ui/goose2/src-tauri/src/lib.rs
Registers the new attachment-related Tauri commands with the app. This wires the frontend attachment flow into the native backend.

ui/goose2/src-tauri/src/services/acp/manager/session_ops/prompt_ops.rs
Builds ACP content blocks so image blocks are sent before the prompt text. This preserves correct mixed-attachment ordering for the first prompt.

ui/goose2/src-tauri/src/services/acp/manager/session_ops/tests.rs
Adds backend regression coverage for mixed attachment ordering. This protects the ACP prompt construction path during future changes.

ui/goose2/src-tauri/tauri.conf.json
Re-enables native drag-and-drop delivery in the Tauri window config. This lets Finder drops reach the desktop app again.

ui/goose2/src/app/AppShell.tsx
Threads generalized chat attachments through app-level chat startup state. This allows new sessions launched from the shell to preserve pending attachments.

ui/goose2/src/app/ui/AppShellContent.tsx
Updates shell content props to pass attachment drafts into chat creation flows. This keeps the ported shell wiring consistent with the new attachment model.

ui/goose2/src/features/chat/hooks/ArtifactPolicyContext.tsx
Stops read-only file inspection tool calls from surfacing as artifact pills. This keeps the artifact UI focused on created outputs rather than inspected inputs.

ui/goose2/src/features/chat/hooks/tests/ArtifactPolicyContext.test.tsx
Adds regression tests proving read-only file and path inspection no longer create artifact pills. This protects the intended transcript behavior.

ui/goose2/src/features/chat/hooks/tests/useChat.attachments.test.ts
Splits attachment-specific send-path coverage into dedicated tests. These tests cover mixed attachments and attachment-aware prompt construction.

ui/goose2/src/features/chat/hooks/tests/useChat.test.ts
Keeps the base chat hook tests focused on the non-attachment flow. This reduces noise now that attachment behavior has its own test file.

ui/goose2/src/features/chat/hooks/tests/useMessageQueue.test.ts
Updates queue tests to cover attachment-aware draft persistence and replay. This ensures queued sends preserve attachment metadata correctly.

ui/goose2/src/features/chat/hooks/useAttachmentDropTarget.ts
Introduces a mixed attachment drop target for files, folders, and browser file drops. This replaces the earlier image-only drop handling.

ui/goose2/src/features/chat/hooks/useChat.ts
Generalizes send logic to accept attachment drafts, build attachment-aware prompts, and derive titles for attachment-only sessions. This is the core chat-layer support for the feature.

ui/goose2/src/features/chat/hooks/useChatInputAttachments.ts
Extracts attachment draft creation, normalization, preview handling, and dedupe into a dedicated hook. It also carries the platform-aware dedupe fix from the follow-up PR.

ui/goose2/src/features/chat/hooks/useImageDropTarget.ts
Removes the obsolete image-only drop hook. Mixed attachment handling now lives in the shared attachment drop target.

ui/goose2/src/features/chat/hooks/useMessageQueue.ts
Updates queued message handling so attachment metadata survives delayed sends. This keeps queued messages aligned with the new transcript model.

ui/goose2/src/features/chat/lib/artifactPathPolicy.ts
Exports the path policy helper used to distinguish read-only path access from created artifacts. This supports the updated artifact pill logic.

ui/goose2/src/features/chat/lib/attachments.ts
Adds helpers for attachment metadata, prompt preambles, and conversion between local attachments and message content. This centralizes the attachment formatting logic.

ui/goose2/src/features/chat/lib/sessionTitle.test.ts
Adds tests for deterministic titles when chats start with attachments only. This prevents blank or confusing sidebar labels.

ui/goose2/src/features/chat/lib/sessionTitle.ts
Introduces fallback attachment-only session titles like “Attached file”. This improves chat discoverability when no typed text is sent.

ui/goose2/src/features/chat/stores/chatStore.ts
Updates chat store typing to carry generalized attachments instead of image-only drafts. This aligns app state with the new attachment model.

ui/goose2/src/features/chat/ui/ChatInput.tsx
Refactors the composer to support shared attachment drafts, file and folder picker actions, drag-and-drop, and attachment-only sends. It also includes the follow-up fix to await async path loading inside the picker error boundary.

ui/goose2/src/features/chat/ui/ChatInputAttachments.tsx
Adds the composer attachment strip for image previews plus file and folder chips. This gives users a clear pre-send view of attached items.

ui/goose2/src/features/chat/ui/ChatInputToolbar.tsx
Adds the attach menu with separate file and folder entry points. This exposes the new attachment capabilities from the chat toolbar.

ui/goose2/src/features/chat/ui/ChatView.tsx
Passes generalized attachments through the chat view and session-creation wiring. This keeps the view layer aligned with the new draft shape.

ui/goose2/src/features/chat/ui/MessageBubble.tsx
Renders sent file and folder attachment chips in the transcript and lets users open their underlying paths. This makes sent attachments visible and actionable after send.

ui/goose2/src/features/chat/ui/tests/ChatInput.attachments.test.tsx
Adds dedicated composer tests for attach actions, mixed attachment rendering, drag overlays, and the follow-up dedupe behavior on case-insensitive platforms. This protects the main user-facing entry points.

ui/goose2/src/features/chat/ui/tests/MessageBubble.test.tsx
Adds transcript coverage for file and folder attachment chips. This verifies the post-send attachment rendering path.

ui/goose2/src/features/home/ui/HomeScreen.tsx
Updates the home screen chat launch flow to preserve generalized attachments into new sessions. This keeps attachment starts consistent across entry points.

ui/goose2/src/shared/api/system.ts
Adds frontend wrappers for attachment path inspection and local image loading commands. This is the frontend bridge into the new Tauri backend surface.

ui/goose2/src/shared/i18n/locales/en/chat.json
Adds English strings for attachment menus, drag-and-drop copy, open actions, and attachment-only titles. This completes the attachment UX copy.

ui/goose2/src/shared/i18n/locales/es/chat.json
Adds the Spanish translations for the new attachment UX. This keeps the feature localized alongside the rest of the chat surface.

ui/goose2/src/shared/types/messages.ts
Expands shared message types to describe image, file, and directory attachment drafts and metadata. This unifies attachment typing across the app.

Reproduction Steps

  1. Open Goose 2 from ui/goose2 and start a new desktop chat.
  2. Use the attach button to pick a file, a folder, and an image, or drag those items into the composer from Finder.
  3. Send once with message text and once with attachments only.
  4. Confirm the composer shows image previews plus file and folder chips, and the sent message renders matching attachment chips in the transcript.
  5. Confirm an attachment-only chat gets a stable sidebar title instead of a blank label.
  6. Ask the assistant what attachments it can see and confirm the first response accounts for the mixed attachment set.
  7. Let the assistant inspect attached files and confirm read-only path access does not create artifact pills.
  8. Try attaching a very large local image and confirm the app rejects it instead of attempting to encode and send it.

Screenshots/Demos

Validated locally in the Tauri desktop app after porting the old Goose 2 attachment work into this repo. No screenshots are attached to this PR.

Screen.Recording.2026-04-13.at.2.03.43.PM.mov

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cf5e0cf3b3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread ui/goose2/src-tauri/src/commands/system.rs Outdated
Signed-off-by: tulsi <tulsi@block.xyz>
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 76c808576b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread ui/goose2/src/features/chat/hooks/useAttachmentDropTarget.ts
Signed-off-by: tulsi <tulsi@block.xyz>
Signed-off-by: tulsi <tulsi@block.xyz>
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bbacc3e864

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread ui/goose2/src/features/chat/lib/attachments.ts Outdated
Comment thread ui/goose2/src/features/chat/hooks/useChatInputAttachments.ts Outdated
Signed-off-by: tulsi <tulsi@block.xyz>
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 20100e6630

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread ui/goose2/src/features/chat/hooks/useAttachmentDropTarget.ts
Signed-off-by: tulsi <tulsi@block.xyz>
Signed-off-by: tulsi <tulsi@block.xyz>
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5cb0906af4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

path: attachmentPath.path,
mimeType: image.mimeType,
base64: image.base64,
previewUrl: pathToPreviewUrl(attachmentPath.path),
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Use an attachment preview source that bypasses asset scope

Path-based image attachments now set previewUrl with convertFileSrc(attachmentPath.path), but the app’s asset protocol scope is limited to the avatars directory, so files dropped/selected from normal project paths cannot be rendered through asset:// URLs. In practice, users can attach and send these images, but the thumbnail/lightbox preview is broken for most local files even though readImageAttachment already fetched usable bytes.

Useful? React with 👍 / 👎.

Comment thread ui/goose2/src-tauri/tauri.conf.json
// When images are present with no text, pass a single space so the ACP
// driver doesn't send an empty text content block that goose rejects.
const acpPrompt = text.trim() || (images?.length ? " " : text);
const attachmentPromptPreamble =
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

regarding the comment above this, does something need to change in the goose agent loop to accept these without this additional text?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I don’t think anything needs to change in the Goose loop for this PR. The attachment flow now always prepends a non-empty Attached items: preamble, so attachment-only sends no longer rely on that fallback space to avoid an empty text block. At this point the " " looks redundant rather than functionally necessary, so I’d treat removing it as cleanup.

@jamadeo
Copy link
Copy Markdown
Member

jamadeo commented Apr 14, 2026

Looks good to me, note that this will be wired up differently once we have moved to having JS talk ACP+ directly. But this just increases the surface area of that migration a bit, and doesn't make it more complicated

@tulsi-builder tulsi-builder added this pull request to the merge queue Apr 14, 2026
Merged via the queue into main with commit 210ef52 Apr 14, 2026
24 checks passed
@tulsi-builder tulsi-builder deleted the tulsi/port-attachments branch April 14, 2026 21:41
michaelneale added a commit that referenced this pull request Apr 15, 2026
…rning

* origin/main:
  move agent skills to repo root for tool discoverability (#8535)
  port goose2 chat attachments into goose (#8534)
  chore(release): bump version to 1.31.0 (minor) (#8527)
  feature: provider & model config (#8515)
  Move goose2 (#8516)
  feat: onboarding UX for the TUI (#8513)
  Set MACOSX_DEPLOYMENT_TARGET=12.0 in build-cli.yml (#8525)
  Improve local inference settings and model downloader (#8467)
  Add prompt injection mitigation logging back (#8518)
  feat(providers): add llama-swap declarative provider (#8462)
  fix: Unable to Run `goose update` on Linux (#8465)
  Add vision/image support for local inference models (#8442)
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.

2 participants