From 010948767aa9477e9a9fd02886bc4f1129fcf25b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Flor=C3=AAncio?= Date: Sun, 14 Jun 2026 21:40:02 +0100 Subject: [PATCH] feat: add file-backed prompt attachments (#1367) --- README.md | 2 +- apps/backend/cmd/kandev/adapters.go | 9 +- .../agent/runtime/lifecycle/session.go | 9 +- .../internal/agent/runtime/lifecycle/types.go | 9 +- .../adapter/transport/acp/adapter_prompt.go | 84 +++++--- .../transport/acp/adapter_prompt_test.go | 126 ++++++++++- .../adapter/transport/shared/attachments.go | 77 ++++++- .../transport/shared/attachments_test.go | 203 +++++++++++++++++- .../orchestrator/event_handlers_agent.go | 8 +- .../orchestrator/event_handlers_workflow.go | 16 +- .../orchestrator/handlers/queue_handlers.go | 17 ++ .../handlers/queue_handlers_test.go | 35 +++ .../orchestrator/messagequeue/types.go | 8 +- .../task/handlers/message_handlers.go | 3 + .../task/handlers/task_http_handlers.go | 3 + .../task/handlers/task_http_handlers_test.go | 35 +++ apps/backend/pkg/api/v1/task.go | 13 +- apps/backend/pkg/api/v1/task_test.go | 25 +++ .../components/task-create-dialog-helpers.ts | 9 +- .../task/changes-panel-file-row.test.tsx | 30 +++ .../task/changes-panel-file-row.tsx | 5 + .../task/chat/chat-input-container.tsx | 1 + .../task/chat/context-items/context-chip.tsx | 20 +- .../task/chat/context-items/image-item.tsx | 69 +++++- .../task/chat/file-attachment.test.ts | 2 + .../components/task/chat/file-attachment.ts | 3 + .../task/chat/use-chat-input-state.ts | 35 ++- .../task/new-session-form-actions.test.ts | 1 + apps/web/e2e/helpers/api-client.ts | 37 +++- .../chat/attachment-delivery-mode.spec.ts | 124 +++++++++++ apps/web/e2e/tests/ssh/launch-task.spec.ts | 122 ++++++++++- apps/web/hooks/domains/session/use-queue.ts | 2 + apps/web/hooks/use-message-handler.ts | 1 + apps/web/lib/api/domains/kanban-api.ts | 8 +- apps/web/lib/api/domains/queue-api.ts | 16 +- apps/web/lib/local-storage.test.ts | 32 +++ apps/web/lib/local-storage.ts | 22 +- .../lib/services/session-launch-service.ts | 1 + apps/web/lib/state/slices/session/types.ts | 8 +- apps/web/lib/types/context.ts | 1 + docs/screenshots.md | 12 ++ docs/screenshots/mobile-changes.webp | Bin 0 -> 36918 bytes docs/screenshots/mobile-chat.webp | Bin 0 -> 41744 bytes docs/screenshots/mobile-diff.webp | Bin 0 -> 49184 bytes 44 files changed, 1147 insertions(+), 96 deletions(-) create mode 100644 apps/backend/pkg/api/v1/task_test.go create mode 100644 apps/web/e2e/tests/chat/attachment-delivery-mode.spec.ts create mode 100644 docs/screenshots/mobile-changes.webp create mode 100644 docs/screenshots/mobile-chat.webp create mode 100644 docs/screenshots/mobile-diff.webp diff --git a/README.md b/README.md index e917a18606..fca8f5096d 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Manage and run tasks in parallel. Orchestrate agents. Review changes. Ship value Kandev Demo

-[See all screenshots](docs/screenshots.md) +[See desktop and mobile screenshots](docs/screenshots.md) ## What diff --git a/apps/backend/cmd/kandev/adapters.go b/apps/backend/cmd/kandev/adapters.go index 3580e8fd7e..bbaee6b21f 100644 --- a/apps/backend/cmd/kandev/adapters.go +++ b/apps/backend/cmd/kandev/adapters.go @@ -216,10 +216,11 @@ func convertToLifecycleAttachments(attachments []v1.MessageAttachment) []lifecyc result := make([]lifecycle.MessageAttachment, len(attachments)) for i, att := range attachments { result[i] = lifecycle.MessageAttachment{ - Type: att.Type, - Data: att.Data, - MimeType: att.MimeType, - Name: att.Name, + Type: att.Type, + Data: att.Data, + MimeType: att.MimeType, + Name: att.Name, + DeliveryMode: att.DeliveryMode, } } return result diff --git a/apps/backend/internal/agent/runtime/lifecycle/session.go b/apps/backend/internal/agent/runtime/lifecycle/session.go index 83a7e04969..caf59e9632 100644 --- a/apps/backend/internal/agent/runtime/lifecycle/session.go +++ b/apps/backend/internal/agent/runtime/lifecycle/session.go @@ -411,10 +411,11 @@ func convertAttachments(attachments []MessageAttachment) []v1.MessageAttachment result := make([]v1.MessageAttachment, 0, len(attachments)) for _, att := range attachments { result = append(result, v1.MessageAttachment{ - Type: att.Type, - Data: att.Data, - MimeType: att.MimeType, - Name: att.Name, + Type: att.Type, + Data: att.Data, + MimeType: att.MimeType, + Name: att.Name, + DeliveryMode: att.DeliveryMode, }) } return result diff --git a/apps/backend/internal/agent/runtime/lifecycle/types.go b/apps/backend/internal/agent/runtime/lifecycle/types.go index bc7e8cac5b..598ce616ba 100644 --- a/apps/backend/internal/agent/runtime/lifecycle/types.go +++ b/apps/backend/internal/agent/runtime/lifecycle/types.go @@ -425,10 +425,11 @@ func (r *LaunchRequest) RepoSpecs() []RepoLaunchSpec { // MessageAttachment represents an image or file attachment for agent prompts. type MessageAttachment struct { - Type string // "image", "audio", or "resource" - Data string // base64-encoded data - MimeType string // MIME type - Name string // optional filename for resource attachments + Type string // "image", "audio", or "resource" + Data string // base64-encoded data + MimeType string // MIME type + Name string // optional filename for resource attachments + DeliveryMode string // "prompt" (native/default) or "path" } // CredentialsManager interface for credential retrieval diff --git a/apps/backend/internal/agentctl/server/adapter/transport/acp/adapter_prompt.go b/apps/backend/internal/agentctl/server/adapter/transport/acp/adapter_prompt.go index 11e9f736eb..955f1199c4 100644 --- a/apps/backend/internal/agentctl/server/adapter/transport/acp/adapter_prompt.go +++ b/apps/backend/internal/agentctl/server/adapter/transport/acp/adapter_prompt.go @@ -77,32 +77,7 @@ func (a *Adapter) sendPrompt(ctx context.Context, message string, attachments [] zap.Int("context_length", len(pendingContext))) } - // Build content blocks: text first, then images - contentBlocks := []acp.ContentBlock{acp.TextBlock(finalMessage)} - - // Add media attachments as typed content blocks - for _, att := range attachments { - switch att.Type { - case contentTypeImage: - contentBlocks = append(contentBlocks, acp.ImageBlock(att.Data, att.MimeType)) - case contentTypeAudio: - contentBlocks = append(contentBlocks, acp.AudioBlock(att.Data, att.MimeType)) - case contentTypeResource: - if a.capabilities.PromptCapabilities.EmbeddedContext { - contentBlocks = append(contentBlocks, buildResourceBlock(att)) - } else { - // Agent doesn't support embedded resources — save to workspace and reference in text - saved, saveErr := a.attachMgr.SaveAttachments([]v1.MessageAttachment{att}) - if saveErr != nil || len(saved) == 0 { - a.logger.Warn("failed to save attachment to workspace, falling back to resource block", - zap.String("name", att.Name), zap.Error(saveErr)) - contentBlocks = append(contentBlocks, buildResourceBlock(att)) - } else { - contentBlocks = append(contentBlocks, acp.TextBlock(shared.BuildAttachmentPrompt(saved))) - } - } - } - } + contentBlocks := a.buildPromptContentBlocks(finalMessage, attachments) // Start prompt span — notification spans become children via getPromptTraceCtx() traceCtx, promptSpan := shared.TraceProtocolRequest(ctx, shared.ProtocolACP, a.agentID, "prompt") @@ -225,12 +200,63 @@ func (a *Adapter) sendPrompt(ctx context.Context, message string, attachments [] Usage: usage, }) - // Clean up saved attachments — agent has finished reading them - a.attachMgr.Cleanup() - return nil } +func (a *Adapter) buildPromptContentBlocks(message string, attachments []v1.MessageAttachment) []acp.ContentBlock { + contentBlocks := []acp.ContentBlock{acp.TextBlock(message)} + + for _, att := range attachments { + if att.DeliveryMode == "path" { + saved, saveErr := a.attachMgr.SaveAttachments([]v1.MessageAttachment{att}) + if saveErr != nil || len(saved) == 0 { + a.logger.Warn("failed to save path-mode attachment to workspace", + zap.String("name", att.Name), zap.Error(saveErr)) + contentBlocks = append(contentBlocks, buildAttachmentFallbackBlock(att)) + continue + } + contentBlocks = append(contentBlocks, acp.TextBlock(shared.BuildAttachmentPrompt(saved, true))) + continue + } + + switch att.Type { + case contentTypeImage: + contentBlocks = append(contentBlocks, acp.ImageBlock(att.Data, att.MimeType)) + case contentTypeAudio: + contentBlocks = append(contentBlocks, acp.AudioBlock(att.Data, att.MimeType)) + case contentTypeResource: + if a.capabilities.PromptCapabilities.EmbeddedContext { + contentBlocks = append(contentBlocks, buildResourceBlock(att)) + } else { + // Agent doesn't support embedded resources — save to workspace and reference in text. + saved, saveErr := a.attachMgr.SaveAttachments([]v1.MessageAttachment{att}) + if saveErr != nil || len(saved) == 0 { + a.logger.Warn("failed to save attachment to workspace, falling back to resource block", + zap.String("name", att.Name), zap.Error(saveErr)) + contentBlocks = append(contentBlocks, buildResourceBlock(att)) + } else { + contentBlocks = append(contentBlocks, acp.TextBlock(shared.BuildAttachmentPrompt(saved, false))) + } + } + } + } + + return contentBlocks +} + +func buildAttachmentFallbackBlock(att v1.MessageAttachment) acp.ContentBlock { + switch att.Type { + case contentTypeImage: + return acp.ImageBlock(att.Data, att.MimeType) + case contentTypeAudio: + return acp.AudioBlock(att.Data, att.MimeType) + case contentTypeResource: + return buildResourceBlock(att) + default: + return acp.TextBlock("The user attached a file, but Kandev could not save it to the workspace.") + } +} + // fireWakeup is invoked by wakeupScheduler when a ScheduleWakeup timer // elapses. It issues a synthetic session/prompt so the upstream // @agentclientprotocol/claude-agent-acp bridge drains the SDK's queued wakeup diff --git a/apps/backend/internal/agentctl/server/adapter/transport/acp/adapter_prompt_test.go b/apps/backend/internal/agentctl/server/adapter/transport/acp/adapter_prompt_test.go index 38a753a605..9e4ffb4c0b 100644 --- a/apps/backend/internal/agentctl/server/adapter/transport/acp/adapter_prompt_test.go +++ b/apps/backend/internal/agentctl/server/adapter/transport/acp/adapter_prompt_test.go @@ -1,10 +1,16 @@ package acp import ( + "encoding/base64" + "os" + "path/filepath" + "strings" "testing" - "github.com/coder/acp-go-sdk" + acp "github.com/coder/acp-go-sdk" + "github.com/kandev/kandev/internal/agentctl/server/adapter/transport/shared" "github.com/kandev/kandev/internal/agentctl/types/streams" + v1 "github.com/kandev/kandev/pkg/api/v1" ) // TestCancelActiveToolCalls_PreservesSubagentTask pins the fix for the @@ -50,6 +56,124 @@ func TestCancelActiveToolCalls_PreservesSubagentTask(t *testing.T) { } } +func TestBuildPromptContentBlocks_PathModeAttachmentSavesWritableFile(t *testing.T) { + a := newTestAdapter() + t.Cleanup(func() { _ = a.Close() }) + + workDir := t.TempDir() + a.attachMgr = shared.NewAttachmentManager(workDir, a.logger.Zap()) + a.attachMgr.SetSessionID("sess-path") + a.capabilities = acp.AgentCapabilities{ + PromptCapabilities: acp.PromptCapabilities{ + Image: true, + EmbeddedContext: true, + }, + } + + encoded := base64.StdEncoding.EncodeToString([]byte("remote bytes")) + blocks := a.buildPromptContentBlocks("inspect this", []v1.MessageAttachment{{ + Type: "image", + Data: encoded, + MimeType: "image/png", + Name: "shot.png", + DeliveryMode: "path", + }}) + + if len(blocks) != 2 { + t.Fatalf("expected text prompt plus attachment path prompt, got %d blocks", len(blocks)) + } + if blocks[1].Text == nil { + t.Fatalf("expected path-mode attachment to be sent as text, got %#v", blocks[1]) + } + if blocks[1].Image != nil { + t.Fatalf("path-mode attachment should not be sent as an image block") + } + text := blocks[1].Text.Text + if !strings.Contains(text, ".kandev/attachments/sess-path/shot.png") { + t.Fatalf("attachment prompt did not include saved path: %q", text) + } + if !strings.Contains(text, "writable") { + t.Fatalf("attachment prompt did not include writable contract: %q", text) + } + + savedPath := filepath.Join(workDir, ".kandev", "attachments", "sess-path", "shot.png") + data, err := os.ReadFile(savedPath) + if err != nil { + t.Fatalf("expected attachment to be written to workspace: %v", err) + } + if string(data) != "remote bytes" { + t.Fatalf("saved attachment = %q, want %q", string(data), "remote bytes") + } +} + +func TestBuildPromptContentBlocks_PathModeSaveFailureFallsBackToNativeBlock(t *testing.T) { + a := newTestAdapter() + t.Cleanup(func() { _ = a.Close() }) + + a.attachMgr = shared.NewAttachmentManager("", a.logger.Zap()) + a.attachMgr.SetSessionID("sess-path") + a.capabilities = acp.AgentCapabilities{ + PromptCapabilities: acp.PromptCapabilities{ + Image: true, + }, + } + + encoded := base64.StdEncoding.EncodeToString([]byte("image bytes")) + blocks := a.buildPromptContentBlocks("inspect this", []v1.MessageAttachment{{ + Type: "image", + Data: encoded, + MimeType: "image/png", + Name: "shot.png", + DeliveryMode: "path", + }}) + + if len(blocks) != 2 { + t.Fatalf("expected text prompt plus native fallback block, got %d blocks", len(blocks)) + } + if blocks[1].Image == nil { + t.Fatalf("expected path-mode save failure to fall back to an image block, got %#v", blocks[1]) + } + if blocks[1].Text != nil { + t.Fatalf("fallback image should not be replaced by a text path prompt") + } +} + +func TestBuildPromptContentBlocks_UnsupportedEmbeddedResourceSavesReadOnlyFile(t *testing.T) { + a := newTestAdapter() + t.Cleanup(func() { _ = a.Close() }) + + workDir := t.TempDir() + a.attachMgr = shared.NewAttachmentManager(workDir, a.logger.Zap()) + a.attachMgr.SetSessionID("sess-resource") + a.capabilities = acp.AgentCapabilities{ + PromptCapabilities: acp.PromptCapabilities{ + EmbeddedContext: false, + }, + } + + encoded := base64.StdEncoding.EncodeToString([]byte("doc bytes")) + blocks := a.buildPromptContentBlocks("read this", []v1.MessageAttachment{{ + Type: "resource", + Data: encoded, + MimeType: "application/pdf", + Name: "doc.pdf", + }}) + + if len(blocks) != 2 { + t.Fatalf("expected text prompt plus attachment path prompt, got %d blocks", len(blocks)) + } + if blocks[1].Text == nil { + t.Fatalf("expected unsupported embedded resource to be sent as text path prompt, got %#v", blocks[1]) + } + text := blocks[1].Text.Text + if !strings.Contains(text, ".kandev/attachments/sess-resource/doc.pdf") { + t.Fatalf("attachment prompt did not include saved path: %q", text) + } + if strings.Contains(text, "writable") || strings.Contains(text, "modify") { + t.Fatalf("fallback resource prompt should be read-only, got: %q", text) + } +} + // TestCancelActiveToolCalls_SubagentLateUpdate_LandsAsComplete drives the full // race scenario end-to-end through the real adapter methods (no mocks): // diff --git a/apps/backend/internal/agentctl/server/adapter/transport/shared/attachments.go b/apps/backend/internal/agentctl/server/adapter/transport/shared/attachments.go index 11e31c0880..5b40088741 100644 --- a/apps/backend/internal/agentctl/server/adapter/transport/shared/attachments.go +++ b/apps/backend/internal/agentctl/server/adapter/transport/shared/attachments.go @@ -2,6 +2,7 @@ package shared import ( "encoding/base64" + "errors" "fmt" "os" "path/filepath" @@ -64,6 +65,7 @@ func (m *AttachmentManager) SaveAttachments(attachments []v1.MessageAttachment) } var saved []SavedAttachment + usedNames := make(map[string]bool, len(attachments)) for _, att := range attachments { name := att.Name if name == "" { @@ -75,18 +77,18 @@ func (m *AttachmentManager) SaveAttachments(attachments []v1.MessageAttachment) m.logger.Warn("skipping attachment with invalid name", zap.String("original_name", att.Name)) continue } - decoded, err := base64.StdEncoding.DecodeString(att.Data) if err != nil { m.logger.Warn("failed to decode attachment", zap.String("name", name), zap.Error(err)) continue } - absPath := filepath.Join(dir, name) - if err := os.WriteFile(absPath, decoded, 0o644); err != nil { + name, absPath, err := writeUniqueAttachmentFile(dir, name, usedNames, decoded) + if err != nil { m.logger.Warn("failed to write attachment", zap.String("path", absPath), zap.Error(err)) continue } + usedNames[name] = true relPath := filepath.Join(".kandev", "attachments", m.sessionID, name) saved = append(saved, SavedAttachment{ @@ -117,7 +119,7 @@ func (m *AttachmentManager) Cleanup() { // BuildAttachmentPrompt generates prompt text referencing saved attachment files. // Used by adapters that don't support native multimodal content. -func BuildAttachmentPrompt(saved []SavedAttachment) string { +func BuildAttachmentPrompt(saved []SavedAttachment, writable bool) string { if len(saved) == 0 { return "" } @@ -125,17 +127,72 @@ func BuildAttachmentPrompt(saved []SavedAttachment) string { var sb strings.Builder if len(saved) == 1 { s := saved[0] - fmt.Fprintf(&sb, "The user attached a file: %s (saved to %s in the workspace). Use your file reading tools to access it.\n\n", s.Name, s.RelPath) - } else { - sb.WriteString("The user attached files that you should read and analyze:\n") - for _, s := range saved { - fmt.Fprintf(&sb, "- %s (saved to %s)\n", s.Name, s.RelPath) + name := sanitizePromptValue(s.Name) + relPath := sanitizePromptValue(s.RelPath) + if writable { + fmt.Fprintf(&sb, "The user attached a writable file: %s (saved to %s in the workspace). Use your file reading tools to access or modify it.\n\n", name, relPath) + } else { + fmt.Fprintf(&sb, "The user attached a file: %s (saved to %s in the workspace). Use your file reading tools to access it.\n\n", name, relPath) + } + } else { + if writable { + sb.WriteString("The user attached writable files that you should read and analyze:\n") + } else { + sb.WriteString("The user attached files that you should read and analyze:\n") + } + for _, s := range saved { + fmt.Fprintf(&sb, "- %s (saved to %s)\n", sanitizePromptValue(s.Name), sanitizePromptValue(s.RelPath)) + } + if writable { + sb.WriteString("\nUse your file reading tools to access or modify them.\n\n") + } else { + sb.WriteString("\nUse your file reading tools to access them.\n\n") } - sb.WriteString("\nUse your file reading tools to access them.\n\n") } return sb.String() } +func writeUniqueAttachmentFile(dir, name string, used map[string]bool, data []byte) (string, string, error) { + ext := filepath.Ext(name) + base := strings.TrimSuffix(name, ext) + for i := 1; ; i++ { + candidate := name + if i > 1 { + candidate = fmt.Sprintf("%s-%d%s", base, i, ext) + } + if used[candidate] { + continue + } + + absPath := filepath.Join(dir, candidate) + file, err := os.OpenFile(absPath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0o644) + if errors.Is(err, os.ErrExist) { + used[candidate] = true + continue + } + if err != nil { + return "", absPath, err + } + + _, writeErr := file.Write(data) + closeErr := file.Close() + if writeErr != nil { + _ = os.Remove(absPath) + return "", absPath, writeErr + } + if closeErr != nil { + _ = os.Remove(absPath) + return "", absPath, closeErr + } + return candidate, absPath, nil + } +} + +func sanitizePromptValue(value string) string { + replacer := strings.NewReplacer("\r", " ", "\n", " ", "<", "(", ">", ")", "`", "'") + return strings.TrimSpace(replacer.Replace(value)) +} + // generateName creates a filename for attachments that don't have a Name field. func (m *AttachmentManager) generateName(att v1.MessageAttachment) string { ext := extensionFromMimeType(att.MimeType) diff --git a/apps/backend/internal/agentctl/server/adapter/transport/shared/attachments_test.go b/apps/backend/internal/agentctl/server/adapter/transport/shared/attachments_test.go index daf459e8c6..7017dd20f5 100644 --- a/apps/backend/internal/agentctl/server/adapter/transport/shared/attachments_test.go +++ b/apps/backend/internal/agentctl/server/adapter/transport/shared/attachments_test.go @@ -2,8 +2,10 @@ package shared import ( "encoding/base64" + "fmt" "os" "path/filepath" + "sync" "testing" v1 "github.com/kandev/kandev/pkg/api/v1" @@ -172,6 +174,157 @@ func TestSaveAttachments_MultipleAttachments(t *testing.T) { } } +func TestSaveAttachments_DuplicateNamesDoNotClobber(t *testing.T) { + workDir := t.TempDir() + mgr := NewAttachmentManager(workDir, testLogger()) + mgr.SetSessionID("sess-dupe") + + first := base64.StdEncoding.EncodeToString([]byte("first")) + second := base64.StdEncoding.EncodeToString([]byte("second")) + third := base64.StdEncoding.EncodeToString([]byte("third")) + + saved, err := mgr.SaveAttachments([]v1.MessageAttachment{ + {Type: "resource", Data: first, MimeType: "text/plain", Name: "report.txt"}, + {Type: "resource", Data: second, MimeType: "text/plain", Name: "report.txt"}, + {Type: "resource", Data: third, MimeType: "text/plain", Name: "report.txt"}, + }) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if len(saved) != 3 { + t.Fatalf("expected 3 saved, got %d", len(saved)) + } + + wantNames := []string{"report.txt", "report-2.txt", "report-3.txt"} + wantContents := []string{"first", "second", "third"} + for i := range saved { + if saved[i].Name != wantNames[i] { + t.Errorf("saved[%d].Name = %q, want %q", i, saved[i].Name, wantNames[i]) + } + data, err := os.ReadFile(saved[i].AbsPath) + if err != nil { + t.Fatalf("failed to read saved[%d]: %v", i, err) + } + if string(data) != wantContents[i] { + t.Errorf("saved[%d] content = %q, want %q", i, string(data), wantContents[i]) + } + } +} + +func TestSaveAttachments_DuplicateNamesAcrossCallsDoNotClobber(t *testing.T) { + workDir := t.TempDir() + mgr := NewAttachmentManager(workDir, testLogger()) + mgr.SetSessionID("sess-dupe-calls") + + first := base64.StdEncoding.EncodeToString([]byte("first")) + second := base64.StdEncoding.EncodeToString([]byte("second")) + + firstSaved, err := mgr.SaveAttachments([]v1.MessageAttachment{ + {Type: "resource", Data: first, MimeType: "text/plain", Name: "report.txt"}, + }) + if err != nil { + t.Fatalf("unexpected first save error: %v", err) + } + secondSaved, err := mgr.SaveAttachments([]v1.MessageAttachment{ + {Type: "resource", Data: second, MimeType: "text/plain", Name: "report.txt"}, + }) + if err != nil { + t.Fatalf("unexpected second save error: %v", err) + } + + if firstSaved[0].Name != "report.txt" { + t.Fatalf("first name = %q, want report.txt", firstSaved[0].Name) + } + if secondSaved[0].Name != "report-2.txt" { + t.Fatalf("second name = %q, want report-2.txt", secondSaved[0].Name) + } + + firstData, err := os.ReadFile(firstSaved[0].AbsPath) + if err != nil { + t.Fatalf("failed to read first file: %v", err) + } + secondData, err := os.ReadFile(secondSaved[0].AbsPath) + if err != nil { + t.Fatalf("failed to read second file: %v", err) + } + if string(firstData) != "first" { + t.Errorf("first content = %q, want first", string(firstData)) + } + if string(secondData) != "second" { + t.Errorf("second content = %q, want second", string(secondData)) + } +} + +func TestSaveAttachments_ConcurrentDuplicateNamesDoNotClobber(t *testing.T) { + workDir := t.TempDir() + const workers = 20 + + var wg sync.WaitGroup + savedCh := make(chan SavedAttachment, workers) + errCh := make(chan error, workers) + + for i := 0; i < workers; i++ { + i := i + wg.Add(1) + go func() { + defer wg.Done() + + mgr := NewAttachmentManager(workDir, testLogger()) + mgr.SetSessionID("sess-concurrent") + + content := fmt.Sprintf("payload-%02d", i) + saved, err := mgr.SaveAttachments([]v1.MessageAttachment{ + { + Type: "resource", + Data: base64.StdEncoding.EncodeToString([]byte(content)), + MimeType: "text/plain", + Name: "report.txt", + }, + }) + if err != nil { + errCh <- err + return + } + if len(saved) != 1 { + errCh <- fmt.Errorf("saved count = %d, want 1", len(saved)) + return + } + savedCh <- saved[0] + }() + } + + wg.Wait() + close(savedCh) + close(errCh) + + for err := range errCh { + if err != nil { + t.Fatalf("unexpected save error: %v", err) + } + } + + names := make(map[string]bool, workers) + contents := make(map[string]bool, workers) + for saved := range savedCh { + if names[saved.Name] { + t.Fatalf("duplicate saved name %q", saved.Name) + } + names[saved.Name] = true + + data, err := os.ReadFile(saved.AbsPath) + if err != nil { + t.Fatalf("failed to read %s: %v", saved.AbsPath, err) + } + contents[string(data)] = true + } + if len(names) != workers { + t.Fatalf("saved unique names = %d, want %d", len(names), workers) + } + if len(contents) != workers { + t.Fatalf("saved unique contents = %d, want %d", len(contents), workers) + } +} + func TestSaveAttachments_NoName_GeneratesFromMime(t *testing.T) { workDir := t.TempDir() mgr := NewAttachmentManager(workDir, testLogger()) @@ -303,27 +456,48 @@ func TestCleanup_SessionIsolation(t *testing.T) { } func TestBuildAttachmentPrompt_Empty(t *testing.T) { - result := BuildAttachmentPrompt(nil) + result := BuildAttachmentPrompt(nil, true) if result != "" { t.Errorf("expected empty string, got %q", result) } } -func TestBuildAttachmentPrompt_SingleFile(t *testing.T) { +func TestBuildAttachmentPrompt_SingleWritableFile(t *testing.T) { saved := []SavedAttachment{ {RelPath: ".kandev/attachments/s1/report.pdf", Name: "report.pdf"}, } - result := BuildAttachmentPrompt(saved) + result := BuildAttachmentPrompt(saved, true) if result == "" { t.Fatal("expected non-empty result") } - // Should mention the file name and path if !contains(result, "report.pdf") { t.Errorf("result should contain filename, got: %q", result) } if !contains(result, ".kandev/attachments/s1/report.pdf") { t.Errorf("result should contain path, got: %q", result) } + if !contains(result, "writable") { + t.Errorf("result should tell the agent the file is writable, got: %q", result) + } +} + +func TestBuildAttachmentPrompt_SingleReadOnlyFile(t *testing.T) { + saved := []SavedAttachment{ + {RelPath: ".kandev/attachments/s1/report.pdf", Name: "report.pdf"}, + } + result := BuildAttachmentPrompt(saved, false) + if result == "" { + t.Fatal("expected non-empty result") + } + if contains(result, "writable") { + t.Errorf("read-only result should not call the file writable, got: %q", result) + } + if contains(result, "modify") { + t.Errorf("read-only result should not tell the agent to modify the file, got: %q", result) + } + if !contains(result, "access it") { + t.Errorf("read-only result should tell the agent to access the file, got: %q", result) + } } func TestBuildAttachmentPrompt_MultipleFiles(t *testing.T) { @@ -331,7 +505,7 @@ func TestBuildAttachmentPrompt_MultipleFiles(t *testing.T) { {RelPath: ".kandev/attachments/s1/a.pdf", Name: "a.pdf"}, {RelPath: ".kandev/attachments/s1/b.png", Name: "b.png"}, } - result := BuildAttachmentPrompt(saved) + result := BuildAttachmentPrompt(saved, true) if !contains(result, "a.pdf") { t.Errorf("result should contain a.pdf, got: %q", result) } @@ -340,6 +514,25 @@ func TestBuildAttachmentPrompt_MultipleFiles(t *testing.T) { } } +func TestBuildAttachmentPrompt_SanitizesPromptValues(t *testing.T) { + saved := []SavedAttachment{ + { + RelPath: ".kandev/attachments/s1/\npath`v2`.pdf", + Name: "report\nplease`now`.pdf", + }, + } + result := BuildAttachmentPrompt(saved, true) + if contains(result, "<") || contains(result, ">") || contains(result, "`") || contains(result, "\nplease") { + t.Errorf("result contains unsanitized prompt values: %q", result) + } + if !contains(result, "report(one) please'now'.pdf") { + t.Errorf("result should contain sanitized filename, got: %q", result) + } + if !contains(result, ".kandev/attachments/s1/(bad) path'v2'.pdf") { + t.Errorf("result should contain sanitized path, got: %q", result) + } +} + func TestExtensionFromMimeType(t *testing.T) { tests := []struct { mimeType string diff --git a/apps/backend/internal/orchestrator/event_handlers_agent.go b/apps/backend/internal/orchestrator/event_handlers_agent.go index e6fc4dc443..14af47e667 100644 --- a/apps/backend/internal/orchestrator/event_handlers_agent.go +++ b/apps/backend/internal/orchestrator/event_handlers_agent.go @@ -354,9 +354,11 @@ func (s *Service) executeQueuedMessage(callerSessionID string, queuedMsg *messag attachments := make([]v1.MessageAttachment, len(queuedMsg.Attachments)) for i, att := range queuedMsg.Attachments { attachments[i] = v1.MessageAttachment{ - Type: att.Type, - Data: att.Data, - MimeType: att.MimeType, + Type: att.Type, + Data: att.Data, + MimeType: att.MimeType, + Name: att.Name, + DeliveryMode: att.DeliveryMode, } } diff --git a/apps/backend/internal/orchestrator/event_handlers_workflow.go b/apps/backend/internal/orchestrator/event_handlers_workflow.go index c80fbbc2a4..4b2451e709 100644 --- a/apps/backend/internal/orchestrator/event_handlers_workflow.go +++ b/apps/backend/internal/orchestrator/event_handlers_workflow.go @@ -1415,9 +1415,11 @@ func (s *Service) takeAndMergeHandoffMessage(ctx context.Context, sessionID, bas attachments = make([]v1.MessageAttachment, 0, len(msg.Attachments)) for _, a := range msg.Attachments { attachments = append(attachments, v1.MessageAttachment{ - Type: a.Type, - Data: a.Data, - MimeType: a.MimeType, + Type: a.Type, + Data: a.Data, + MimeType: a.MimeType, + Name: a.Name, + DeliveryMode: a.DeliveryMode, }) } } @@ -1495,9 +1497,11 @@ func toQueuedAttachments(attachments []v1.MessageAttachment) []messagequeue.Mess queued := make([]messagequeue.MessageAttachment, 0, len(attachments)) for _, attachment := range attachments { queued = append(queued, messagequeue.MessageAttachment{ - Type: attachment.Type, - Data: attachment.Data, - MimeType: attachment.MimeType, + Type: attachment.Type, + Data: attachment.Data, + MimeType: attachment.MimeType, + Name: attachment.Name, + DeliveryMode: attachment.DeliveryMode, }) } return queued diff --git a/apps/backend/internal/orchestrator/handlers/queue_handlers.go b/apps/backend/internal/orchestrator/handlers/queue_handlers.go index 4b8b5f0867..06fa145b22 100644 --- a/apps/backend/internal/orchestrator/handlers/queue_handlers.go +++ b/apps/backend/internal/orchestrator/handlers/queue_handlers.go @@ -100,6 +100,10 @@ func (h *QueueHandlers) wsQueueMessage(ctx context.Context, msg *ws.Message) (*w if req.Content == "" && len(req.Attachments) == 0 { return ws.NewError(msg.ID, msg.Action, ws.ErrorCodeValidation, "content or attachments are required", nil) } + if invalid := firstInvalidDeliveryMode(req.Attachments); invalid >= 0 { + return ws.NewError(msg.ID, msg.Action, ws.ErrorCodeValidation, "attachment delivery_mode must be prompt or path", + map[string]interface{}{"attachment_index": invalid}) + } if req.UserID == messagequeue.QueuedByAgent { return ws.NewError(msg.ID, msg.Action, ws.ErrorCodeValidation, "user_id may not impersonate the agent identity", nil) } @@ -233,6 +237,10 @@ func (h *QueueHandlers) wsUpdateMessage(ctx context.Context, msg *ws.Message) (* if req.Content == "" && len(req.Attachments) == 0 { return ws.NewError(msg.ID, msg.Action, ws.ErrorCodeValidation, "content or attachments are required", nil) } + if invalid := firstInvalidDeliveryMode(req.Attachments); invalid >= 0 { + return ws.NewError(msg.ID, msg.Action, ws.ErrorCodeValidation, "attachment delivery_mode must be prompt or path", + map[string]interface{}{"attachment_index": invalid}) + } // Reject any client-supplied identity that would impersonate the agent. // Without this guard a hostile WS client could send user_id="agent" to @@ -260,6 +268,15 @@ func (h *QueueHandlers) wsUpdateMessage(ctx context.Context, msg *ws.Message) (* return ws.NewResponse(msg.ID, msg.Action, map[string]interface{}{fieldEntryID: req.EntryID}) } +func firstInvalidDeliveryMode(attachments []messagequeue.MessageAttachment) int { + for i, att := range attachments { + if att.DeliveryMode != "" && att.DeliveryMode != "prompt" && att.DeliveryMode != "path" { + return i + } + } + return -1 +} + type wsRemoveEntryRequest struct { SessionID string `json:"session_id"` EntryID string `json:"entry_id"` diff --git a/apps/backend/internal/orchestrator/handlers/queue_handlers_test.go b/apps/backend/internal/orchestrator/handlers/queue_handlers_test.go index 49472e58a1..9c9669465b 100644 --- a/apps/backend/internal/orchestrator/handlers/queue_handlers_test.go +++ b/apps/backend/internal/orchestrator/handlers/queue_handlers_test.go @@ -151,6 +151,41 @@ func TestWsQueueMessage(t *testing.T) { }) } +func TestFirstInvalidDeliveryMode(t *testing.T) { + tests := []struct { + name string + attachments []messagequeue.MessageAttachment + want int + }{ + {name: "empty list", attachments: nil, want: -1}, + { + name: "valid modes", + attachments: []messagequeue.MessageAttachment{ + {DeliveryMode: ""}, + {DeliveryMode: "prompt"}, + {DeliveryMode: "path"}, + }, + want: -1, + }, + { + name: "first invalid mode", + attachments: []messagequeue.MessageAttachment{ + {DeliveryMode: "prompt"}, + {DeliveryMode: "inline"}, + {DeliveryMode: "path"}, + }, + want: 1, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := firstInvalidDeliveryMode(tt.attachments) + assert.Equal(t, tt.want, got) + }) + } +} + func TestWsCancelAll(t *testing.T) { t.Run("clears the queue", func(t *testing.T) { handlers, svc := setupQueueHandlers(t) diff --git a/apps/backend/internal/orchestrator/messagequeue/types.go b/apps/backend/internal/orchestrator/messagequeue/types.go index 1e809d673f..72566c9f04 100644 --- a/apps/backend/internal/orchestrator/messagequeue/types.go +++ b/apps/backend/internal/orchestrator/messagequeue/types.go @@ -51,9 +51,11 @@ type QueuedMessage struct { // MessageAttachment represents an attachment (image) in a queued message. type MessageAttachment struct { - Type string `json:"type"` - Data string `json:"data"` - MimeType string `json:"mime_type"` + Type string `json:"type"` + Data string `json:"data"` + MimeType string `json:"mime_type"` + Name string `json:"name,omitempty"` + DeliveryMode string `json:"delivery_mode,omitempty"` } // QueueStatus is the per-session view returned to clients: full ordered list of diff --git a/apps/backend/internal/task/handlers/message_handlers.go b/apps/backend/internal/task/handlers/message_handlers.go index d25d626e1c..30220f00ef 100644 --- a/apps/backend/internal/task/handlers/message_handlers.go +++ b/apps/backend/internal/task/handlers/message_handlers.go @@ -298,6 +298,9 @@ func validateAddMessageRequest(req wsAddMessageRequest) string { if req.Content == "" && len(req.Attachments) == 0 { return "content or attachments are required" } + if err := validateAttachments(req.Attachments); err != nil { + return err.Error() + } return "" } diff --git a/apps/backend/internal/task/handlers/task_http_handlers.go b/apps/backend/internal/task/handlers/task_http_handlers.go index e4c171399d..1e288ca31e 100644 --- a/apps/backend/internal/task/handlers/task_http_handlers.go +++ b/apps/backend/internal/task/handlers/task_http_handlers.go @@ -461,6 +461,9 @@ func validateAttachments(items []v1.MessageAttachment) error { if len(a.Data) > maxAttachmentDataBytes { return fmt.Errorf("attachment[%d] data exceeds size limit", i) } + if !a.HasValidDeliveryMode() { + return fmt.Errorf("attachment[%d] delivery_mode must be prompt or path", i) + } totalSize += len(a.Data) } if totalSize > maxAttachmentDataBytes { diff --git a/apps/backend/internal/task/handlers/task_http_handlers_test.go b/apps/backend/internal/task/handlers/task_http_handlers_test.go index 0be3deccf2..e18aceaaba 100644 --- a/apps/backend/internal/task/handlers/task_http_handlers_test.go +++ b/apps/backend/internal/task/handlers/task_http_handlers_test.go @@ -19,6 +19,7 @@ import ( "github.com/kandev/kandev/internal/orchestrator" "github.com/kandev/kandev/internal/task/models" "github.com/kandev/kandev/internal/task/service" + v1 "github.com/kandev/kandev/pkg/api/v1" ) // captureOrchestrator records every LaunchSession request so tests can assert @@ -185,6 +186,40 @@ func TestHTTPCreateTask_ProjectIDReachesOfficePath(t *testing.T) { assert.Equal(t, "wf-office", repo.captured.WorkflowID, "office workflow should be auto-resolved") } +func TestValidateAttachments_DeliveryMode(t *testing.T) { + base := v1.MessageAttachment{ + Type: "resource", + MimeType: "text/plain", + Data: "dGVzdA==", + } + + tests := []struct { + name string + deliveryMode string + wantErr string + }{ + {name: "empty uses default", deliveryMode: ""}, + {name: "prompt is valid", deliveryMode: "prompt"}, + {name: "path is valid", deliveryMode: "path"}, + {name: "inline is rejected", deliveryMode: "inline", wantErr: "delivery_mode must be prompt or path"}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + attachment := base + attachment.DeliveryMode = tt.deliveryMode + + err := validateAttachments([]v1.MessageAttachment{attachment}) + if tt.wantErr == "" { + require.NoError(t, err) + return + } + require.Error(t, err) + assert.Contains(t, err.Error(), tt.wantErr) + }) + } +} + func newTestLogger(t *testing.T) *logger.Logger { t.Helper() log, err := logger.NewLogger(logger.LoggingConfig{ diff --git a/apps/backend/pkg/api/v1/task.go b/apps/backend/pkg/api/v1/task.go index 6d1816de23..1c9d8ff74e 100644 --- a/apps/backend/pkg/api/v1/task.go +++ b/apps/backend/pkg/api/v1/task.go @@ -138,10 +138,15 @@ type TaskEvent struct { // Type determines the ACP content block: "image" → ImageBlock, "audio" → AudioBlock, // "resource" → ResourceBlock (text or blob based on MIME type). type MessageAttachment struct { - Type string `json:"type"` // "image", "audio", "resource" - Data string `json:"data,omitempty"` // Base64-encoded data - MimeType string `json:"mime_type,omitempty"` // MIME type (e.g., "image/png") - Name string `json:"name,omitempty"` // Display name (e.g., filename) + Type string `json:"type"` // "image", "audio", "resource" + Data string `json:"data,omitempty"` // Base64-encoded data + MimeType string `json:"mime_type,omitempty"` // MIME type (e.g., "image/png") + Name string `json:"name,omitempty"` // Display name (e.g., filename) + DeliveryMode string `json:"delivery_mode,omitempty"` // "prompt" (native/default) or "path" +} + +func (a MessageAttachment) HasValidDeliveryMode() bool { + return a.DeliveryMode == "" || a.DeliveryMode == "prompt" || a.DeliveryMode == "path" } // ContextFileMeta represents a context file reference attached to a message diff --git a/apps/backend/pkg/api/v1/task_test.go b/apps/backend/pkg/api/v1/task_test.go new file mode 100644 index 0000000000..481274d131 --- /dev/null +++ b/apps/backend/pkg/api/v1/task_test.go @@ -0,0 +1,25 @@ +package v1 + +import "testing" + +func TestMessageAttachmentHasValidDeliveryMode(t *testing.T) { + tests := []struct { + name string + deliveryMode string + want bool + }{ + {name: "empty defaults to prompt", deliveryMode: "", want: true}, + {name: "prompt", deliveryMode: "prompt", want: true}, + {name: "path", deliveryMode: "path", want: true}, + {name: "invalid", deliveryMode: "inline", want: false}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := (MessageAttachment{DeliveryMode: tt.deliveryMode}).HasValidDeliveryMode() + if got != tt.want { + t.Fatalf("HasValidDeliveryMode() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/apps/web/components/task-create-dialog-helpers.ts b/apps/web/components/task-create-dialog-helpers.ts index 61367db5f4..d5efc6312d 100644 --- a/apps/web/components/task-create-dialog-helpers.ts +++ b/apps/web/components/task-create-dialog-helpers.ts @@ -30,12 +30,19 @@ export function toMessageAttachments( if (attachments.length === 0) return undefined; return attachments.map((att) => att.isImage - ? { type: "image" as const, data: att.data, mime_type: att.mimeType } + ? { + type: "image" as const, + data: att.data, + mime_type: att.mimeType, + name: att.fileName, + ...(att.deliveryMode === "path" && { delivery_mode: "path" as const }), + } : { type: "resource" as const, data: att.data, mime_type: att.mimeType, name: att.fileName, + delivery_mode: "path" as const, }, ); } diff --git a/apps/web/components/task/changes-panel-file-row.test.tsx b/apps/web/components/task/changes-panel-file-row.test.tsx index 2a08eb137f..a3da1200a9 100644 --- a/apps/web/components/task/changes-panel-file-row.test.tsx +++ b/apps/web/components/task/changes-panel-file-row.test.tsx @@ -107,6 +107,36 @@ describe("FileRow truncation (regression: path overlaps diff stats in narrow pan repositoryName: "frontend", }); }); + + it("opens image files in the file preview instead of the diff viewer", () => { + const onOpenDiff = vi.fn(); + const onEditFile = vi.fn(); + const { container } = render( + +
    + +
+
, + ); + + const row = container.querySelector( + "[data-changes-file='docs/screenshots/mobile-chat.webp']", + ) as HTMLElement | null; + expect(row).not.toBeNull(); + fireEvent.click(row!); + + expect(onEditFile).toHaveBeenCalledWith("docs/screenshots/mobile-chat.webp"); + expect(onOpenDiff).not.toHaveBeenCalled(); + }); }); describe("FileRow hover swap (stats <-> actions occupy same cell)", () => { diff --git a/apps/web/components/task/changes-panel-file-row.tsx b/apps/web/components/task/changes-panel-file-row.tsx index c8650b45a1..fd63957f54 100644 --- a/apps/web/components/task/changes-panel-file-row.tsx +++ b/apps/web/components/task/changes-panel-file-row.tsx @@ -14,6 +14,7 @@ import { cn } from "@/lib/utils"; import { Tooltip, TooltipContent, TooltipTrigger } from "@kandev/ui/tooltip"; import { LineStat } from "@/components/diff-stat"; import { FileIcon } from "@/components/ui/file-icon"; +import { getFileCategory } from "@/lib/utils/file-types"; import { FileStatusIcon } from "./file-status-icon"; import type { ChangedFile } from "./changes-panel-helpers"; import type { OpenDiffOptions } from "./changes-diff-target"; @@ -74,6 +75,10 @@ export function FileRow({ if (e.button === 2) return; const consumed = onSelect?.(file.path, e); if (!consumed) { + if (getFileCategory(file.path) === "image") { + onEditFile(file.path); + return; + } onOpenDiff(file.path, { source: "uncommitted", repositoryName: file.repositoryName, diff --git a/apps/web/components/task/chat/chat-input-container.tsx b/apps/web/components/task/chat/chat-input-container.tsx index 22ffd9cd9d..d2caa0d445 100644 --- a/apps/web/components/task/chat/chat-input-container.tsx +++ b/apps/web/components/task/chat/chat-input-container.tsx @@ -29,6 +29,7 @@ export type MessageAttachment = { data: string; mime_type: string; name?: string; + delivery_mode?: "prompt" | "path"; }; export type ChatInputContainerHandle = { diff --git a/apps/web/components/task/chat/context-items/context-chip.tsx b/apps/web/components/task/chat/context-items/context-chip.tsx index 3655b633ac..1a076f7fec 100644 --- a/apps/web/components/task/chat/context-items/context-chip.tsx +++ b/apps/web/components/task/chat/context-items/context-chip.tsx @@ -33,6 +33,7 @@ type ContextChipProps = { preview?: ReactNode; /** Data URL to render as a tiny thumbnail instead of the default icon */ thumbnail?: string; + leadingIcon?: ReactNode; onClick?: () => void; onUnpin?: () => void; onRemove?: () => void; @@ -44,23 +45,30 @@ export const ContextChip = memo(function ContextChip({ pinned, preview, thumbnail, + leadingIcon, onClick, onUnpin, onRemove, }: ContextChipProps) { const Icon = ICON_BY_KIND[kind]; + let iconNode: ReactNode; + if (leadingIcon) { + iconNode = leadingIcon; + } else if (thumbnail) { + iconNode = ( + // eslint-disable-next-line @next/next/no-img-element -- base64 thumbnail + + ); + } else { + iconNode = ; + } const chip = (
- {thumbnail ? ( - // eslint-disable-next-line @next/next/no-img-element -- base64 thumbnail - - ) : ( - - )} + {iconNode} {label} {pinned && onUnpin && ( + +
+

{deliveryDescription}

+ + )} ) : undefined; + if (deliveryMode === "path") { + leadingIcon = ( + + ); + } else if (!previewSrc) { + leadingIcon = ; + } return ( <> { expect(attachment!.id).toMatch(UUID_V4_REGEX); expect(attachment!.isImage).toBe(false); expect(attachment!.fileName).toBe("notes.txt"); + expect(attachment!.deliveryMode).toBe("path"); }); it("assigns a fallback UUID to image attachments when crypto.randomUUID is unavailable", async () => { @@ -56,6 +57,7 @@ describe("processFile in insecure context (HTTP, no crypto.randomUUID)", () => { expect(attachment).not.toBeNull(); expect(attachment!.id).toMatch(UUID_V4_REGEX); expect(attachment!.isImage).toBe(true); + expect(attachment!.deliveryMode).toBe("prompt"); expect(attachment!.preview).toMatch(/^data:image\/png;base64,/); }); diff --git a/apps/web/components/task/chat/file-attachment.ts b/apps/web/components/task/chat/file-attachment.ts index 1c835378cc..d33b9789f8 100644 --- a/apps/web/components/task/chat/file-attachment.ts +++ b/apps/web/components/task/chat/file-attachment.ts @@ -13,6 +13,7 @@ export type FileAttachment = { size: number; // File size in bytes preview?: string; // Data URL for image preview (only for images) isImage: boolean; // Whether this is a previewable image + deliveryMode: "prompt" | "path"; // Native prompt block or writable executor file path }; export const PREVIEWABLE_IMAGE_TYPES = ["image/png", "image/jpeg", "image/gif", "image/webp"]; @@ -79,6 +80,7 @@ export function processFile(file: File): Promise { size: file.size, preview: dataUrl, isImage: true, + deliveryMode: "prompt", }); }; img.onerror = () => resolve(null); @@ -91,6 +93,7 @@ export function processFile(file: File): Promise { fileName: file.name, size: file.size, isImage: false, + deliveryMode: "path", }); } }; diff --git a/apps/web/components/task/chat/use-chat-input-state.ts b/apps/web/components/task/chat/use-chat-input-state.ts index fded7ac142..20d35e5e84 100644 --- a/apps/web/components/task/chat/use-chat-input-state.ts +++ b/apps/web/components/task/chat/use-chat-input-state.ts @@ -52,8 +52,20 @@ function collectComments( function toMessageAttachments(attachments: FileAttachment[]): MessageAttachment[] { return attachments.map((att) => att.isImage - ? { type: "image" as const, data: att.data, mime_type: att.mimeType } - : { type: "resource" as const, data: att.data, mime_type: att.mimeType, name: att.fileName }, + ? { + type: "image" as const, + data: att.data, + mime_type: att.mimeType, + name: att.fileName, + ...(att.deliveryMode === "path" && { delivery_mode: "path" as const }), + } + : { + type: "resource" as const, + data: att.data, + mime_type: att.mimeType, + name: att.fileName, + delivery_mode: "path" as const, + }, ); } @@ -117,7 +129,19 @@ function useAttachments(sessionId: string | null) { ); const handleRemoveAttachment = useCallback((id: string) => { - setAttachments((prev) => prev.filter((att) => att.id !== id)); + setAttachments((prev) => { + const next = prev.filter((att) => att.id !== id); + attachmentsRef.current = next; + return next; + }); + }, []); + + const handleDeliveryModeChange = useCallback((id: string, deliveryMode: "prompt" | "path") => { + setAttachments((prev) => { + const next = prev.map((att) => (att.id === id ? { ...att, deliveryMode } : att)); + attachmentsRef.current = next; + return next; + }); }, []); const getAttachments = useCallback( @@ -131,6 +155,7 @@ function useAttachments(sessionId: string | null) { setAttachments, addFiles, handleRemoveAttachment, + handleDeliveryModeChange, getAttachments, }; } @@ -158,6 +183,7 @@ export function useChatInputState({ setAttachments, addFiles, handleRemoveAttachment, + handleDeliveryModeChange, getAttachments, } = useAttachments(sessionId); @@ -225,6 +251,7 @@ export function useChatInputState({ label: `Image (${formatBytes(att.size)})`, attachment: att, onRemove: () => handleRemoveAttachment(att.id), + onDeliveryModeChange: (mode) => handleDeliveryModeChange(att.id, mode), } as ImageContextItem) : ({ kind: "file-attachment" as const, @@ -235,7 +262,7 @@ export function useChatInputState({ } as FileAttachmentContextItem), ); return [...contextItems, ...attachmentItems]; - }, [contextItems, attachments, handleRemoveAttachment]); + }, [contextItems, attachments, handleRemoveAttachment, handleDeliveryModeChange]); // prettier-ignore return { value, attachments, inputRef, addFiles, handleChange, handleSubmit, allItems, getAttachments }; diff --git a/apps/web/components/task/new-session-form-actions.test.ts b/apps/web/components/task/new-session-form-actions.test.ts index d23a2806fa..b4b0831bbb 100644 --- a/apps/web/components/task/new-session-form-actions.test.ts +++ b/apps/web/components/task/new-session-form-actions.test.ts @@ -41,6 +41,7 @@ const ATTACHMENT: FileAttachment = { fileName: "notes.txt", size: 42, isImage: false, + deliveryMode: "path", }; const TASK_ID = "task-1"; const PROFILE_ID = "profile-a"; diff --git a/apps/web/e2e/helpers/api-client.ts b/apps/web/e2e/helpers/api-client.ts index f1482a7c22..b21556156f 100644 --- a/apps/web/e2e/helpers/api-client.ts +++ b/apps/web/e2e/helpers/api-client.ts @@ -84,6 +84,8 @@ type CreateTaskOpts = { repositories?: Array<{ repository_id: string; base_branch?: string; checkout_branch?: string }>; plan_mode?: boolean; metadata?: Record; + parent_id?: string; + attachments?: MessageAttachmentInput[]; }; function buildTaskMetadata(opts: CreateTaskOpts): Record | undefined { @@ -112,11 +114,20 @@ function buildCreateTaskBody( "repositories", opts?.repositories ?? opts?.repository_ids?.map((id) => ({ repository_id: id })), ); + setIf(body, "attachments", opts?.attachments); if (opts?.plan_mode) body.plan_mode = true; setIf(body, "parent_id", opts?.parent_id); return body; } +type MessageAttachmentInput = { + type: string; + data: string; + mime_type: string; + name?: string; + delivery_mode?: "prompt" | "path"; +}; + type OptionalAgentTaskOpts = { workflow_id?: string; workflow_step_id?: string; @@ -126,6 +137,7 @@ type OptionalAgentTaskOpts = { executor_profile_id?: string; metadata?: Record; parent_id?: string; + attachments?: MessageAttachmentInput[]; }; /** `repositories` (with per-entry branches) takes precedence over the shorthand @@ -147,6 +159,7 @@ function buildOptionalAgentTaskFields(opts?: OptionalAgentTaskOpts): Record; /** Parent task ID for subtasks. */ parent_id?: string; + attachments?: MessageAttachmentInput[]; }, ): Promise { return this.request("POST", "/api/v1/tasks", buildCreateTaskBody(workspaceId, title, opts)); @@ -415,6 +429,7 @@ export class ApiClient { metadata?: Record; /** Parent task ID for subtasks. */ parent_id?: string; + attachments?: MessageAttachmentInput[]; }, ): Promise { return this.request("POST", "/api/v1/tasks", { @@ -1311,11 +1326,31 @@ export class ApiClient { * Use after the auto-started agent finishes so the session is in a state * that accepts new prompts. */ - async addUserMessage(taskId: string, sessionId: string, content: string): Promise { + async addUserMessage( + taskId: string, + sessionId: string, + content: string, + attachments?: MessageAttachmentInput[], + ): Promise { await this.wsRequest("message.add", { task_id: taskId, session_id: sessionId, content, + attachments, + }); + } + + async queueMessage( + taskId: string, + sessionId: string, + content: string, + attachments?: MessageAttachmentInput[], + ): Promise { + await this.wsRequest("message.queue.add", { + task_id: taskId, + session_id: sessionId, + content, + attachments, }); } diff --git a/apps/web/e2e/tests/chat/attachment-delivery-mode.spec.ts b/apps/web/e2e/tests/chat/attachment-delivery-mode.spec.ts new file mode 100644 index 0000000000..b8d11bca19 --- /dev/null +++ b/apps/web/e2e/tests/chat/attachment-delivery-mode.spec.ts @@ -0,0 +1,124 @@ +import fs from "node:fs"; +import path from "node:path"; +import { test, expect } from "../../fixtures/test-base"; +import type { ApiClient } from "../../helpers/api-client"; +import { openTaskSession, waitForLatestSessionDone } from "../../helpers/session"; + +type PersistedAttachment = { + type?: string; + name?: string; + mime_type?: string; + delivery_mode?: string; +}; + +async function waitForUserAttachment( + apiClient: ApiClient, + sessionId: string, + content: string, +): Promise { + await expect + .poll( + async () => { + const { messages } = await apiClient.listSessionMessages(sessionId); + const message = messages.find( + (m) => m.author_type === "user" && m.content.includes(content), + ); + const attachments = message?.metadata?.attachments; + return Array.isArray(attachments) ? attachments.length : 0; + }, + { timeout: 15_000, message: `Wait for persisted attachment on "${content}"` }, + ) + .toBeGreaterThan(0); + + const { messages } = await apiClient.listSessionMessages(sessionId); + const message = messages.find((m) => m.author_type === "user" && m.content.includes(content)); + const attachments = message?.metadata?.attachments; + if (!Array.isArray(attachments)) throw new Error("Persisted user message has no attachments"); + return attachments[0] as PersistedAttachment; +} + +test.describe("chat attachment delivery mode", () => { + test("shows a Prompt/File selector for supported images and sends unsupported files by path", async ({ + testPage, + apiClient, + seedData, + }, testInfo) => { + test.setTimeout(90_000); + const task = await apiClient.createTaskWithAgent( + seedData.workspaceId, + "Attachment delivery selector", + seedData.agentProfileId, + { + description: "/e2e:simple-message", + workflow_id: seedData.workflowId, + workflow_step_id: seedData.startStepId, + repository_ids: [seedData.repositoryId], + }, + ); + if (!task.session_id) throw new Error("createTaskWithAgent did not return a session_id"); + await waitForLatestSessionDone(apiClient, task.id, 1, "Wait for initial attachment task"); + const session = await openTaskSession(testPage, task.id); + await session.waitForChatIdle({ timeout: 30_000 }); + fs.mkdirSync(testInfo.outputDir, { recursive: true }); + + const imagePath = path.join(testInfo.outputDir, "tiny.png"); + fs.writeFileSync( + imagePath, + Buffer.from( + "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMB/6X3pZQAAAAASUVORK5CYII=", + "base64", + ), + ); + + await testPage.locator('input[type="file"]').setInputFiles(imagePath); + const imageChip = testPage.getByText(/Image \(/).first(); + await expect(imageChip).toBeVisible({ timeout: 10_000 }); + await imageChip.hover(); + + const promptButton = testPage.getByTestId("attachment-delivery-prompt"); + const pathButton = testPage.getByTestId("attachment-delivery-path"); + await expect(promptButton).toBeVisible({ timeout: 10_000 }); + await expect(pathButton).toBeVisible(); + await expect(promptButton).toHaveAttribute("data-selected", "true"); + + await pathButton.click(); + await expect(pathButton).toHaveAttribute("data-selected", "true"); + await session.sendMessageViaButton("send image as file path"); + const imageAttachment = await waitForUserAttachment( + apiClient, + task.session_id, + "send image as file path", + ); + expect(imageAttachment).toMatchObject({ + type: "image", + name: "tiny.png", + mime_type: "image/png", + delivery_mode: "path", + }); + + await session.waitForChatIdle({ timeout: 30_000 }); + const textPath = path.join(testInfo.outputDir, "notes.txt"); + fs.writeFileSync(textPath, "plain text attachment"); + + await testPage.locator('input[type="file"]').setInputFiles(textPath); + await expect(testPage.getByText("notes.txt", { exact: true })).toBeVisible({ + timeout: 10_000, + }); + await testPage.getByText("notes.txt", { exact: true }).hover(); + await expect(testPage.getByTestId("attachment-delivery-prompt")).toHaveCount(0); + await expect(testPage.getByTestId("attachment-delivery-path")).toHaveCount(0); + + await session.sendMessageViaButton("send unsupported file"); + const textAttachment = await waitForUserAttachment( + apiClient, + task.session_id, + "send unsupported file", + ); + expect(textAttachment).toMatchObject({ + type: "resource", + name: "notes.txt", + mime_type: "text/plain", + delivery_mode: "path", + }); + }); +}); diff --git a/apps/web/e2e/tests/ssh/launch-task.spec.ts b/apps/web/e2e/tests/ssh/launch-task.spec.ts index 80dd9d0633..cafee06daf 100644 --- a/apps/web/e2e/tests/ssh/launch-task.spec.ts +++ b/apps/web/e2e/tests/ssh/launch-task.spec.ts @@ -1,5 +1,10 @@ import { test, expect } from "../../fixtures/ssh-test-base"; -import { listRemoteDir, readRemoteFile, remotePathExists } from "../../helpers/ssh"; +import { + execInContainer, + listRemoteDir, + readRemoteFile, + remotePathExists, +} from "../../helpers/ssh"; import { waitForLatestSessionDone } from "../../helpers/session"; /** @@ -165,6 +170,121 @@ test.describe("ssh executor — task launch", () => { expect(row!.remote_agentctl_port).toBeGreaterThan(0); }); + test("uploads path-mode attachments into the remote executor workspace", async ({ + apiClient, + seedData, + }) => { + test.setTimeout(180_000); + const content = "remote attachment bytes"; + const task = await apiClient.createTaskWithAgent( + seedData.workspaceId, + "H6 attachment upload", + seedData.agentProfileId, + { + description: "Inspect the attached file.", + workflow_id: seedData.workflowId, + workflow_step_id: seedData.startStepId, + repository_ids: [seedData.repositoryId], + executor_profile_id: seedData.sshExecutorProfileId, + attachments: [ + { + type: "resource", + data: Buffer.from(content, "utf8").toString("base64"), + mime_type: "text/plain", + name: "remote-note.txt", + delivery_mode: "path", + }, + ], + }, + ); + await waitForLatestSessionDone(apiClient, task.id, 1, "Wait for attachment upload"); + + await expect + .poll( + async () => { + const sessions = await apiClient.listSSHSessions(seedData.sshExecutorId); + return sessions.find((s) => s.task_id === task.id)?.remote_task_dir ?? ""; + }, + { timeout: 60_000, message: "Wait for SSH session row" }, + ) + .not.toBe(""); + + const sessions = await apiClient.listSSHSessions(seedData.sshExecutorId); + const row = sessions.find((s) => s.task_id === task.id); + expect(row?.remote_task_dir).toBeTruthy(); + const savedPath = execInContainer(seedData.sshTarget, [ + "sh", + "-c", + `find ${JSON.stringify(row!.remote_task_dir)}/.kandev/attachments -name remote-note.txt -type f -print -quit`, + ]).trim(); + expect(savedPath).toContain("/.kandev/attachments/"); + expect(readRemoteFile(seedData.sshTarget, savedPath)).toBe(content); + }); + + test("uploads path-mode attachments queued while the remote task is running", async ({ + apiClient, + seedData, + }) => { + test.setTimeout(180_000); + const content = "remote follow-up attachment bytes"; + const task = await apiClient.createTaskWithAgent( + seedData.workspaceId, + "H6 running attachment upload", + seedData.agentProfileId, + { + description: "/slow 20s", + workflow_id: seedData.workflowId, + workflow_step_id: seedData.startStepId, + repository_ids: [seedData.repositoryId], + executor_profile_id: seedData.sshExecutorProfileId, + }, + ); + if (!task.session_id) throw new Error("createTaskWithAgent did not return a session_id"); + + await apiClient.queueMessage(task.id, task.session_id, "Inspect the follow-up file.", [ + { + type: "resource", + data: Buffer.from(content, "utf8").toString("base64"), + mime_type: "text/plain", + name: "remote-followup.txt", + delivery_mode: "path", + }, + ]); + + await expect + .poll( + async () => { + const sessions = await apiClient.listSSHSessions(seedData.sshExecutorId); + return sessions.find((s) => s.task_id === task.id)?.remote_task_dir ?? ""; + }, + { timeout: 60_000, message: "Wait for SSH session row" }, + ) + .not.toBe(""); + + const sessions = await apiClient.listSSHSessions(seedData.sshExecutorId); + const row = sessions.find((s) => s.task_id === task.id); + const taskDir = row?.remote_task_dir; + expect(taskDir).toBeTruthy(); + + const findAttachment = () => + execInContainer(seedData.sshTarget, [ + "sh", + "-c", + `find ${JSON.stringify(taskDir)}/.kandev/attachments -name remote-followup.txt -type f -print -quit 2>/dev/null || true`, + ]).trim(); + + await expect + .poll(findAttachment, { + timeout: 120_000, + message: "Wait for queued attachment to upload remotely", + }) + .not.toBe(""); + + const attachmentPath = findAttachment(); + expect(attachmentPath).toContain("/.kandev/attachments/"); + expect(readRemoteFile(seedData.sshTarget, attachmentPath)).toBe(content); + }); + test("stopping the session cleans up the session runtime dir but leaves the task dir", async ({ apiClient, seedData, diff --git a/apps/web/hooks/domains/session/use-queue.ts b/apps/web/hooks/domains/session/use-queue.ts index c4b841b15b..3336d485bf 100644 --- a/apps/web/hooks/domains/session/use-queue.ts +++ b/apps/web/hooks/domains/session/use-queue.ts @@ -17,6 +17,8 @@ export type MessageAttachment = { type: string; data: string; mime_type: string; + name?: string; + delivery_mode?: "prompt" | "path"; }; /** Selectors over the queue slice for one session. */ diff --git a/apps/web/hooks/use-message-handler.ts b/apps/web/hooks/use-message-handler.ts index 25bcf4e0e5..2983fec930 100644 --- a/apps/web/hooks/use-message-handler.ts +++ b/apps/web/hooks/use-message-handler.ts @@ -227,6 +227,7 @@ export function useMessageHandler({ data: att.data, mime_type: att.mime_type, name: att.name, + delivery_mode: att.delivery_mode, })); await queue(taskId, finalMessage, modelToSend, planModeEnabled, queueAttachments); return; diff --git a/apps/web/lib/api/domains/kanban-api.ts b/apps/web/lib/api/domains/kanban-api.ts index c378adde9b..2d867c723d 100644 --- a/apps/web/lib/api/domains/kanban-api.ts +++ b/apps/web/lib/api/domains/kanban-api.ts @@ -71,7 +71,13 @@ export async function createTask( executor_id?: string; executor_profile_id?: string; plan_mode?: boolean; - attachments?: Array<{ type: string; data: string; mime_type: string; name?: string }>; + attachments?: Array<{ + type: string; + data: string; + mime_type: string; + name?: string; + delivery_mode?: "prompt" | "path"; + }>; parent_id?: string; workspace_path?: string; priority?: string; diff --git a/apps/web/lib/api/domains/queue-api.ts b/apps/web/lib/api/domains/queue-api.ts index 2dfd9fbc5a..a3ace66edb 100644 --- a/apps/web/lib/api/domains/queue-api.ts +++ b/apps/web/lib/api/domains/queue-api.ts @@ -68,7 +68,13 @@ export type QueueMessageParams = { content: string; model?: string; plan_mode?: boolean; - attachments?: Array<{ type: string; data: string; mime_type: string }>; + attachments?: Array<{ + type: string; + data: string; + mime_type: string; + name?: string; + delivery_mode?: "prompt" | "path"; + }>; user_id?: string; }; @@ -140,7 +146,13 @@ export async function updateQueuedMessage(params: { session_id: string; entry_id: string; content: string; - attachments?: Array<{ type: string; data: string; mime_type: string }>; + attachments?: Array<{ + type: string; + data: string; + mime_type: string; + name?: string; + delivery_mode?: "prompt" | "path"; + }>; user_id?: string; }): Promise<{ entry_id: string }> { const client = getWebSocketClient(); diff --git a/apps/web/lib/local-storage.test.ts b/apps/web/lib/local-storage.test.ts index ade72f0ed0..07c3fde030 100644 --- a/apps/web/lib/local-storage.test.ts +++ b/apps/web/lib/local-storage.test.ts @@ -5,6 +5,7 @@ import { getGlobalSidebarWidth, markPRClosedBannerDismissed, markPRMergedBannerDismissed, + restoreAttachmentPreview, setGlobalSidebarWidth, wasPRClosedBannerDismissed, wasPRMergedBannerDismissed, @@ -103,3 +104,34 @@ describe("global sidebar width storage", () => { expect(getGlobalSidebarWidth()).toBe(320); }); }); + +describe("chat draft attachment storage", () => { + it("normalizes invalid restored image delivery modes to prompt", () => { + const restored = restoreAttachmentPreview({ + id: "att-1", + data: "abc", + mimeType: "image/png", + fileName: "shot.png", + size: 3, + isImage: true, + deliveryMode: "inline" as "prompt", + }); + + expect(restored.deliveryMode).toBe("prompt"); + expect(restored.preview).toBe("data:image/png;base64,abc"); + }); + + it("normalizes invalid restored file delivery modes to path", () => { + const restored = restoreAttachmentPreview({ + id: "att-2", + data: "abc", + mimeType: "application/pdf", + fileName: "doc.pdf", + size: 3, + isImage: false, + deliveryMode: "inline" as "path", + }); + + expect(restored.deliveryMode).toBe("path"); + }); +}); diff --git a/apps/web/lib/local-storage.ts b/apps/web/lib/local-storage.ts index 69c73e2d9b..abb17c2c58 100644 --- a/apps/web/lib/local-storage.ts +++ b/apps/web/lib/local-storage.ts @@ -542,6 +542,7 @@ type StoredFileAttachment = { fileName: string; size: number; isImage: boolean; + deliveryMode?: "prompt" | "path"; }; export function getChatDraftText(sessionId: string): string { @@ -576,6 +577,13 @@ export function getChatDraftAttachments(sessionId: string): StoredFileAttachment ); } +function normalizeAttachmentDeliveryMode( + value: unknown, + fallback: "prompt" | "path", +): "prompt" | "path" { + return value === "prompt" || value === "path" ? value : fallback; +} + export function setChatDraftAttachments( sessionId: string, attachments: Array<{ @@ -585,6 +593,7 @@ export function setChatDraftAttachments( fileName: string; size: number; isImage: boolean; + deliveryMode?: "prompt" | "path"; preview?: string; }>, ): void { @@ -593,13 +602,14 @@ export function setChatDraftAttachments( } else { // Strip `preview` to halve storage cost — reconstructed on load for images const stored: StoredFileAttachment[] = attachments.map( - ({ id, data, mimeType, fileName, size, isImage }) => ({ + ({ id, data, mimeType, fileName, size, isImage, deliveryMode }) => ({ id, data, mimeType, fileName, size, isImage, + deliveryMode, }), ); setSessionStorage(`${CHAT_DRAFT_ATTACHMENTS_KEY}.${sessionId}`, stored); @@ -611,11 +621,15 @@ export function setChatDraftAttachments( */ export function restoreAttachmentPreview( att: StoredFileAttachment, -): StoredFileAttachment & { preview?: string } { +): StoredFileAttachment & { deliveryMode: "prompt" | "path"; preview?: string } { if (att.isImage) { - return { ...att, preview: `data:${att.mimeType};base64,${att.data}` }; + return { + ...att, + deliveryMode: normalizeAttachmentDeliveryMode(att.deliveryMode, "prompt"), + preview: `data:${att.mimeType};base64,${att.data}`, + }; } - return att; + return { ...att, deliveryMode: normalizeAttachmentDeliveryMode(att.deliveryMode, "path") }; } export function getChatInputHeight(sessionId: string): number | null { diff --git a/apps/web/lib/services/session-launch-service.ts b/apps/web/lib/services/session-launch-service.ts index cd13546718..b7e276cd0e 100644 --- a/apps/web/lib/services/session-launch-service.ts +++ b/apps/web/lib/services/session-launch-service.ts @@ -13,6 +13,7 @@ export type MessageAttachment = { data: string; mime_type: string; name?: string; + delivery_mode?: "prompt" | "path"; }; export type LaunchSessionRequest = { diff --git a/apps/web/lib/state/slices/session/types.ts b/apps/web/lib/state/slices/session/types.ts index 8576aa7b44..81b2db2a87 100644 --- a/apps/web/lib/state/slices/session/types.ts +++ b/apps/web/lib/state/slices/session/types.ts @@ -102,7 +102,13 @@ export type QueuedMessage = { content: string; model?: string; plan_mode: boolean; - attachments?: Array<{ type: string; data: string; mime_type: string }>; + attachments?: Array<{ + type: string; + data: string; + mime_type: string; + name?: string; + delivery_mode?: "prompt" | "path"; + }>; metadata?: QueuedMessageMetadata; queued_at: string; queued_by?: string; diff --git a/apps/web/lib/types/context.ts b/apps/web/lib/types/context.ts index c6391dcb39..75446a3942 100644 --- a/apps/web/lib/types/context.ts +++ b/apps/web/lib/types/context.ts @@ -44,6 +44,7 @@ export type PlanCommentContextItem = ContextItemBase & { export type ImageContextItem = ContextItemBase & { kind: "image"; attachment: FileAttachment; + onDeliveryModeChange?: (mode: "prompt" | "path") => void; }; export type FileAttachmentContextItem = ContextItemBase & { diff --git a/docs/screenshots.md b/docs/screenshots.md index be0e7cba31..56627a875e 100644 --- a/docs/screenshots.md +++ b/docs/screenshots.md @@ -1,5 +1,17 @@ # Screenshots +## Mobile + + + + + + + +
Mobile Chat
Mobile Chat
Mobile Changes
Mobile Changes
Mobile Diff Review
Mobile Diff Review
+ +## Desktop + diff --git a/docs/screenshots/mobile-changes.webp b/docs/screenshots/mobile-changes.webp new file mode 100644 index 0000000000000000000000000000000000000000..2ea5285bf9264e1f582d91db5e8fc6a63e48a645 GIT binary patch literal 36918 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%0D&%Qu>vwZEpo4<5FbuU9n#CuF< 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 J00000003-YAdLV3 literal 0 HcmV?d00001 diff --git a/docs/screenshots/mobile-diff.webp b/docs/screenshots/mobile-diff.webp new file mode 100644 index 0000000000000000000000000000000000000000..0e033f39100df57f246ce0e7c87f6c8efdcf2c26 GIT binary patch literal 49184 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 literal 0 HcmV?d00001
Kanban
Kanban