Skip to content

feat(cli+web): inline image display for all agent flavors #956

Description

@heavygee

Summary

HAPI chat can render inline images via the generated-image message type (web fetches bytes from CLI via hub RPC). PR #700 added the display_image MCP tool and wired prompts for some flavors, but image display is not reliable for all agents today.

Parent: #697. Related: #508 (tool-result image blocks), #511 (composer thumbnails).

What PR #700 actually shipped (merged 2026-05-27)

Not Claude-only. Partial cross-flavor wiring:

  • CLI MCP tool display_image in startHappyServer.ts — reads local file, registers in generatedImages, emits type: 'generated-image' agent message
  • Codex: stdio MCP bridge forwards display_image; system prompt hint; plus native generated_image app-server events in codexRemoteLauncher.ts
  • Claude: MCP via startHappyServer + system prompt hint
  • OpenCode: system prompt hint + buildHapiMcpBridge MCP
  • Web: flavor-agnostic — ToolMessage.tsx GeneratedImageCard, normalizeAgent.ts, hub route GET /sessions/:id/generated-images/:imageId

Gaps (why "all agents" still fails)

1. MCP wired but agents not told to use it

These flavors start buildHapiMcpBridge() (which uses startHappyServer — tool exists) but have no system prompt hint to call display_image:

  • Cursor (ACP)
  • Gemini (ACP)
  • Kimi (ACP)
  • Pi

buildHapiMcpBridge also only sets explicit tool approval for change_title; display_image should be auto-approved (yolo-safe read-only display).

2. ACP agent-native image blocks dropped

cli/src/agent/backends/acp/AcpMessageHandler.ts returns null for inner content { type: 'image', ... } — Cursor/Gemini/Kimi/OpenCode ACP responses that include image blocks never reach the hub/web.

3. Tool results still text-only (#508)

web/src/components/ToolCard/views/_results.tsx extracts text blocks only. Read/bash/chart outputs with embedded image content are invisible even when the agent did produce image data.

4. User attachment previews (#511)

MessageAttachments.tsx can render previewUrl thumbnails but many attachment paths still show filename chips only.

Proposed fix (v1 — cross-flavor parity)

CLI (all remote flavors using MCP bridge):

  1. Add shared display_image system prompt snippet; inject into Cursor, Gemini, Kimi, Pi launchers (match Claude/Codex/OpenCode pattern)
  2. Extend buildHapiMcpBridge tools config: display_image: { approval_mode: 'approve' } (or auto where flavor supports it)

ACP path:

  1. Teach AcpMessageHandler to convert ACP image content blocks into generated-image session messages (register bytes/path via generatedImages helper)

Web (optional v1.1 or same PR if small):

  1. Render base64/image blocks in tool results per [Enhancement] Render images inline in tool results and attachments with lightbox preview #508 (reuse ImagePreview / lightbox)

Acceptance criteria

  • Cursor session: agent saves PNG locally, calls HAPI display_image (or ACP emits image block) → image visible inline in web chat
  • Same for Gemini and Kimi (minimum); Pi if trivial
  • Codex + Claude paths unchanged (regression)
  • No flavor-specific web rendering forks — reuse existing generated-image pipeline
  • Tests: MCP tool handler, ACP image block conversion, web normalize/render smoke

Non-goals (v1)

References

  • cli/src/claude/utils/startHappyServer.tsdisplay_image implementation
  • cli/src/codex/utils/buildHapiMcpBridge.ts — shared MCP bridge (missing prompt + tool approval)
  • cli/src/agent/backends/acp/AcpMessageHandler.ts:326 — image blocks dropped
  • web/src/components/AssistantChat/messages/ToolMessage.tsx — existing inline renderer

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:cliCLI, runner, agent wrappersarea:webWeb PWA / React clientenhancementNew feature or requeststatus:pr-openFix PR open

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions