Skip to content

fix: support image paste attachments#791

Open
nrslib wants to merge 2 commits into
mainfrom
fix/image-clipboard-attachments
Open

fix: support image paste attachments#791
nrslib wants to merge 2 commits into
mainfrom
fix/image-clipboard-attachments

Conversation

@nrslib

@nrslib nrslib commented Jun 8, 2026

Copy link
Copy Markdown
Owner

Summary

  • support clipboard/terminal image paste in interactive input and pass referenced image paths through provider abstractions
  • stage task attachment paths into run context while preserving original task order content
  • mark stale running tasks as failed instead of recovering them to pending, and update docs/E2E coverage
  • fetch base branch commits into isolated clones before reset to avoid missing object failures

Tests

  • npm test -- src/tests/lineEditor.test.ts src/tests/task.test.ts src/tests/taskSpecContext.test.ts src/tests/resolveTask.test.ts src/tests/provider-image-attachments.test.ts src/tests/codex-client-retry.test.ts src/tests/selectAndExecute-skipTaskList.test.ts
  • npm test -- src/tests/claude-terminal-transcript-reader.test.ts src/tests/claude-terminal-client-abort-cleanup.test.ts
  • npm run test:e2e:mock -- e2e/specs/run-recovery.e2e.ts
  • npm run lint
  • npm run build
  • git diff --check

Review

  • Reviewed with codex exec twice; follow-up findings were addressed.

Summary by CodeRabbit

  • New Features

    • インタラクティブモードでクリップボード画像の貼り付けが可能に(/paste-image コマンド、対応メッセージあり)
    • AI呼び出しで画像添付を提供できるように強化
  • Behavior Changes

    • 中断された実行中タスクは次回起動時に「復旧(pending)」ではなく「failed」として扱われます
  • Improvements

    • タスク仕様内の添付パスを自動で正規化・管理するよう改善

@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 9884b6ef-a38b-4d0b-93df-1f46e40bca09

📥 Commits

Reviewing files that changed from the base of the PR and between 672b8f1 and bfac8df.

📒 Files selected for processing (10)
  • e2e/specs/run-recovery.e2e.ts
  • src/__tests__/imageAttachments.test.ts
  • src/__tests__/kiro-provider.test.ts
  • src/__tests__/provider-image-attachments.test.ts
  • src/features/interactive/imageAttachments.ts
  • src/features/interactive/lineEditor.ts
  • src/infra/claude/image-input.ts
  • src/infra/claude/types.ts
  • src/infra/codex/types.ts
  • src/infra/providers/kiro.ts
💤 Files with no reviewable changes (3)
  • src/infra/codex/types.ts
  • src/infra/claude/types.ts
  • e2e/specs/run-recovery.e2e.ts

📝 Walkthrough

Walkthrough

中断された running タスクは起動時に pending に戻すのではなく failed にマークされます。対話モードはクリップボード画像の貼り付けとネイティブ画像転送に対応し、Claude/Codex 向けの画像付きプロンプトを組み立てます。孤立クローンは base ブランチを refs/takt/base にフェッチします。

Changes

Interrupted Task Cleanup: Failed Status Instead of Recovery

Layer / File(s) Summary
Task lifecycle service and runner API
src/infra/task/taskLifecycleService.ts, src/infra/task/runner.ts, src/infra/task/taskRecordMutations.ts
recoverInterruptedRunningTasks を削除し、failInterruptedRunningTasks を導入して古い running タスクを failed に移行する。
Task execution flow: runAllTasks and watchTasks
src/features/tasks/execute/runAllTasks.ts, src/features/tasks/watch/index.ts
起動時に recover → pending ではなく failInterruptedRunningTasks を呼び出して failed にマークするよう変更。
Task spec staging and attachment path rewriting
src/features/tasks/execute/taskSpecContext.ts, src/features/tasks/execute/selectAndExecute.ts, src/features/tasks/attachments.ts
stagedOrderContent を追加し、attachments/... 参照をランコンテキストのパスへ書き換え。パストラバーサルを拒否。
E2E test coverage and docs
e2e/specs/run-recovery.e2e.ts, docs/testing/e2e.md, docs/task-management.md, docs/task-management.ja.md
E2E とドキュメントで「復旧」→「クリーンアップ(failed)」の期待値へ更新。

Clipboard / Native Image Input and Interactive Changes

Layer / File(s) Summary
Provider image contracts and capabilities
src/infra/providers/types.ts, src/infra/providers/provider-capabilities.ts
ProviderImageAttachment 型と supportsNativeImageInput フラグ、判定ヘルパーを追加。
Clipboard image reading and feedback
src/features/interactive/clipboardImage.ts, src/features/interactive/clipboardImageFeedback.ts
macOS 用のクリップボード画像読み取り(osascript + sips)、サイズ検査、エラーレポーターを実装。
Line editor async and clipboard integration
src/features/interactive/lineEditor.ts
escape parser を非同期化し、コールバックを Promise 対応に変更、エディタ操作キューを導入してクリップボード画像挿入をシリアライズ。
Image attachment helpers and prompt expansion
src/features/interactive/imageAttachments.ts, src/infra/providers/imageAttachmentPrompt.ts
createClipboardImagePasteHandlerresolvePromptImageAttachments、プレースホルダ展開ユーティリティを追加。
AI caller and provider payloads
src/features/interactive/aiCaller.ts, src/infra/claude/image-input.ts, src/infra/codex/client.ts, src/infra/claude/executor.ts
callAIWithRetry が imageAttachments を受け取りプレースホルダ展開を行い、ネイティブ対応プロバイダにのみ画像を渡す。Claude/Codex 側で画像付きプロンプトの組み立てを実装。
Interactive wiring and UI
src/features/interactive/conversationLoop.ts, src/features/interactive/interactiveInput.ts, src/features/interactive/interactive.ts, src/features/interactive/passthroughMode.ts, src/features/interactive/quietMode.ts, src/features/interactive/slashCommandRegistry.ts, src/shared/constants.ts, src/shared/i18n/labels_en.yaml, src/shared/i18n/labels_ja.yaml
対話ループと各モードでクリップボードハンドラを配線、/paste-image コマンドと i18n ラベルを追加し、利用不可時のメッセージを追加。

Provider implementations and transports

Layer / File(s) Summary
Provider capability flags and option forwarding
src/infra/providers/claude.ts, src/infra/providers/codex.ts, src/infra/providers/claude-headless.ts, src/infra/providers/claude-terminal.ts, src/infra/providers/copilot.ts, src/infra/providers/cursor.ts, src/infra/providers/kiro.ts, src/infra/providers/mock.ts, src/infra/providers/opencode.ts
各プロバイダに supportsNativeImageInput を宣言し、imageAttachments を options として伝搬。
Claude / Codex types and clients
src/infra/claude/types.ts, src/infra/codex/types.ts, src/infra/claude/client.ts, src/infra/codex/client.ts
呼び出しオプションに imageAttachments を追加し、クライアントで適切にペイロードを構成して送信。

Tests and test infrastructure

Layer / File(s) Summary
Test harness and mocks
src/__tests__/helpers/stdinSimulator.ts, vitest.config.e2e.mock.ts
MockProviderCapture に imageAttachments を追加、シナリオプロバイダでネイティブ対応を設定可能に。E2E 設定に run-recovery テストを含める。
Unit / e2e tests updated/added
src/__tests__/*, e2e/specs/run-recovery.e2e.ts
多数のユニット/E2E を追加・更新し、クリップボード貼付、プロンプト展開、プロバイダ画像フォワーディング、failed 中断タスクの期待などを検証。

Clone Infrastructure: Base Branch Fetch

Layer / File(s) Summary
Base branch fetch helpers
src/infra/task/clone-exec.ts
isolated clone 内で refs/takt/base/ を作るための同期/中止可フェッチヘルパを追加。
Clone manager integration
src/infra/task/clone.ts
isolated clone 作成後に base branch をフェッチしてから reset --hard を行うように。
Test expectation
src/__tests__/clone.test.ts
autoFetch テストを追加フェッチ呼び出しを期待するよう更新。

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/image-clipboard-attachments

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/infra/providers/kiro.ts (1)

9-24: ⚡ Quick win

Add warning for unsupported imageAttachments to match the established pattern.

The toKiroOptions function logs warnings for unsupported features (allowedTools, mcpServers, maxTurns, outputSchema, model), but does not warn when options.imageAttachments is provided. For consistency and better user feedback, add a similar check.

📝 Suggested addition
   if (options.model) {
     log.info('Kiro provider does not support model CLI flag; ignoring');
   }
+  if (options.imageAttachments && options.imageAttachments.length > 0) {
+    log.info('Kiro provider does not support imageAttachments; ignoring');
+  }
 
   return {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/infra/providers/kiro.ts` around lines 9 - 24, The toKiroOptions function
currently logs when several unsupported ProviderCallOptions fields are used but
omits imageAttachments; add a check in toKiroOptions that detects
options.imageAttachments (truthy length or presence) and calls log.info('Kiro
provider does not support imageAttachments; ignoring') to match the established
pattern and provide consistent user feedback.
src/infra/claude/image-input.ts (1)

25-43: Clarify error surfacing for image attachment file reads

readFile(attachment.path) in src/infra/claude/image-input.ts throws without local try/catch, but failures occurring during async prompt generation are wrapped by src/infra/claude/executor.ts’s outer try/catch (around the for await loop) and returned as ClaudeResult.error via getErrorMessage(error) (using the underlying Error.message, which for fs failures typically includes the missing/unreadable path).
Optional: wrap readFile to rethrow with attachment context (e.g., include attachment.path) so diagnostics stay clear even if the fs message is less descriptive.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/infra/claude/image-input.ts` around lines 25 - 43, In buildContentBlocks,
wrap the await readFile(attachment.path) call in a try/catch so FS errors are
rethrown with attachment context; catch the error, augment it (or throw a new
Error) that includes the attachment.path (and optionally
formatImageAttachmentPathReference(attachment) or attachment.id) before
rethrowing so executor.ts/getErrorMessage surfaces a clear, contextual message;
keep the rest of the block (image payload creation using inferMediaType and
base64) unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/features/interactive/imageAttachments.ts`:
- Around line 124-126: The current filter uses
prompt.includes(attachment.placeholder) which allows substring matches (e.g.,
"[Image `#1`]" matches "[Image `#10`]"); change the matching to exact token matching
by checking for whole-token equality—either split the prompt into tokens (e.g.,
prompt.split(/\s+/).includes(attachment.placeholder)) or build an escaped-regex
that enforces boundaries (e.g., new
RegExp(`(?<!\\S)${escapeRegex(attachment.placeholder)}(?!\\S)`).test(prompt));
update the filter in the attachments.filter(...) expression to use that
exact-match logic and add/implement an escapeRegex helper if using regex.

---

Nitpick comments:
In `@src/infra/claude/image-input.ts`:
- Around line 25-43: In buildContentBlocks, wrap the await
readFile(attachment.path) call in a try/catch so FS errors are rethrown with
attachment context; catch the error, augment it (or throw a new Error) that
includes the attachment.path (and optionally
formatImageAttachmentPathReference(attachment) or attachment.id) before
rethrowing so executor.ts/getErrorMessage surfaces a clear, contextual message;
keep the rest of the block (image payload creation using inferMediaType and
base64) unchanged.

In `@src/infra/providers/kiro.ts`:
- Around line 9-24: The toKiroOptions function currently logs when several
unsupported ProviderCallOptions fields are used but omits imageAttachments; add
a check in toKiroOptions that detects options.imageAttachments (truthy length or
presence) and calls log.info('Kiro provider does not support imageAttachments;
ignoring') to match the established pattern and provide consistent user
feedback.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 1252e22a-6d37-49f9-a86d-7ebb43f7937c

📥 Commits

Reviewing files that changed from the base of the PR and between 9a92764 and 672b8f1.

📒 Files selected for processing (65)
  • docs/task-management.ja.md
  • docs/task-management.md
  • docs/testing/e2e.md
  • e2e/specs/run-recovery.e2e.ts
  • src/__tests__/clone.test.ts
  • src/__tests__/codex-client-retry.test.ts
  • src/__tests__/commandMatcher.test.ts
  • src/__tests__/conversationLoop-resume.test.ts
  • src/__tests__/helpers/stdinSimulator.ts
  • src/__tests__/imageAttachments.test.ts
  • src/__tests__/interactiveInput.test.ts
  • src/__tests__/lineEditor.test.ts
  • src/__tests__/provider-capabilities.test.ts
  • src/__tests__/provider-image-attachments.test.ts
  • src/__tests__/provider-structured-output.test.ts
  • src/__tests__/runAllTasks-concurrency.test.ts
  • src/__tests__/saveTaskFile.test.ts
  • src/__tests__/selectAndExecute-skipTaskList.test.ts
  • src/__tests__/slashCommandRegistry.test.ts
  • src/__tests__/task.test.ts
  • src/__tests__/taskSpecContext.test.ts
  • src/__tests__/watchTasks.test.ts
  • src/features/interactive/aiCaller.ts
  • src/features/interactive/clipboardImage.ts
  • src/features/interactive/clipboardImageFeedback.ts
  • src/features/interactive/conversationLoop.ts
  • src/features/interactive/imageAttachments.ts
  • src/features/interactive/interactive.ts
  • src/features/interactive/interactiveInput.ts
  • src/features/interactive/lineEditor.ts
  • src/features/interactive/passthroughMode.ts
  • src/features/interactive/quietMode.ts
  • src/features/interactive/slashCommandRegistry.ts
  • src/features/tasks/attachments.ts
  • src/features/tasks/execute/runAllTasks.ts
  • src/features/tasks/execute/selectAndExecute.ts
  • src/features/tasks/execute/taskSpecContext.ts
  • src/features/tasks/watch/index.ts
  • src/infra/claude/client.ts
  • src/infra/claude/executor.ts
  • src/infra/claude/image-input.ts
  • src/infra/claude/types.ts
  • src/infra/codex/client.ts
  • src/infra/codex/types.ts
  • src/infra/providers/claude-headless.ts
  • src/infra/providers/claude-terminal.ts
  • src/infra/providers/claude.ts
  • src/infra/providers/codex.ts
  • src/infra/providers/copilot.ts
  • src/infra/providers/cursor.ts
  • src/infra/providers/imageAttachmentPrompt.ts
  • src/infra/providers/kiro.ts
  • src/infra/providers/mock.ts
  • src/infra/providers/opencode.ts
  • src/infra/providers/provider-capabilities.ts
  • src/infra/providers/types.ts
  • src/infra/task/clone-exec.ts
  • src/infra/task/clone.ts
  • src/infra/task/runner.ts
  • src/infra/task/taskLifecycleService.ts
  • src/infra/task/taskRecordMutations.ts
  • src/shared/constants.ts
  • src/shared/i18n/labels_en.yaml
  • src/shared/i18n/labels_ja.yaml
  • vitest.config.e2e.mock.ts
💤 Files with no reviewable changes (1)
  • src/infra/task/taskRecordMutations.ts

Comment thread src/features/interactive/imageAttachments.ts
@nrslib

nrslib commented Jun 8, 2026

Copy link
Copy Markdown
Owner Author

Summary

タスク指示書

タスク概要

PR #791 のレビューコメントを含めて対応する。Source Context に含まれる PR #791 のレビューコメントを事実情報として参照し、現在のコードに照合したうえで、まだ有効な指摘を実装・テスト・検証まで完了する。

対象 PR: PR #791

優先度: 高

src/features/interactive/imageAttachments.ts

Active Review Thread の指摘に対応する。

作業内容:

  • resolvePromptImageAttachments で、prompt.includes(attachment.placeholder) のような substring matching が使われている場合、placeholder の完全一致判定に変更する。
  • [Image #1] 相当の placeholder が [Image #10] 相当の placeholder に誤マッチしないようにする。
  • placeholder の実際の文字列表現は現在のコードで確認し、その形式に合わせて判定する。
  • 参照された placeholder の attachment のみ ProviderImageAttachment に変換されるようにする。

確認観点:

  • #1#10 が同時に存在する状態で、#10 のみ参照した prompt が #1 を誤って含めない。
  • 既存の placeholder 解決・provider 連携の動作を壊さない。

src/__tests__/imageAttachments.test.ts

作業内容:

  • resolvePromptImageAttachments の exact matching を検証するテストを追加または更新する。
  • #1 / #10 のような prefix 関係にある placeholder を使った回帰テストを含める。

確認観点:

  • 誤転送が再発しないことをテストで検証できる。

優先度: 中

src/infra/claude/image-input.ts

Nitpick comment の指摘に対応する。

作業内容:

  • buildContentBlocks などで readFile(attachment.path) が失敗した場合、throw される error message に対象 attachment の path が分かる文脈を含める。
  • 画像 payload 作成処理、media type 推定、base64 化の既存挙動は維持する。
  • 既存の executor.ts 側の error surfacing と整合する形にする。

確認観点:

  • 存在しない、または読めない attachment path の場合に、どの path で失敗したか分かる。
  • 正常系の Claude image input 生成結果は変わらない。

Claude image input 関連テスト

対象候補:

  • src/__tests__/provider-image-attachments.test.ts
  • 既存の Claude image input 関連テストファイル

作業内容:

  • 既存テスト構成を確認し、必要なテストを追加または更新する。
  • read failure 時に attachment path を含む error が返ることを検証する。

優先度: 中

src/infra/providers/kiro.ts

Nitpick comment の指摘に対応する。

作業内容:

  • toKiroOptions が unsupported options に対して info / warning ログを出す既存パターンを確認する。
  • options.imageAttachments が存在し、要素がある場合に、Kiro provider が imageAttachments をサポートしない旨のログを出す。
  • 既存の unsupported option handling のスタイル・文言・ログ API に合わせる。

確認観点:

  • imageAttachments ありの場合のみログが出る。
  • imageAttachments が空または未指定の場合に不要なログが出ない。
  • Kiro provider の既存 option 変換結果を壊さない。

Kiro provider 関連テスト

対象候補:

  • src/__tests__/provider-image-attachments.test.ts
  • src/__tests__/provider-capabilities.test.ts
  • Kiro provider の既存テストファイル

作業内容:

  • 既存テスト構成を確認し、必要なテストを追加または更新する。
  • unsupported imageAttachments のログ挙動を検証できる場合は検証する。

優先度: 低

PR コメント対応サマリー

作業内容:

  • Source Context に含まれる各レビューコメントについて、最終報告に以下をまとめる。
    • 対応したコメント
    • スキップしたコメント
    • スキップ理由
  • 現在のコードに当てはまらない指摘があれば、修正せず理由を記録する。

検証

少なくとも以下を実行する。

  • 関連 unit test
    • npm test -- src/__tests__/imageAttachments.test.ts
    • Claude image input / provider image attachment に関係する既存テスト
    • Kiro provider に関係する既存テスト
  • npm run lint
  • npm run build
  • git diff --check

全件実行できない場合は、未実行のコマンド、理由、代替確認を最終報告に明記する。

完了条件

  • PR fix: support image paste attachments #791 の対象レビューコメントが現在コードに照合されている。
  • 有効な指摘が実装で修正されている。
  • 必要なテストが追加または更新されている。
  • 関連テスト、lint、build、diff check の実行結果が報告されている。
  • 各レビューコメントの対応状況が最終報告に含まれている。

Execution Report

Workflow review-fix-takt-default completed successfully.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant