Agent improvements: image passthrough, context fixes, thinking indicator, observability #50
Open
ryan
wants to merge 5 commits from
agent-improvements into main
pull from: agent-improvements
merge into: ryan:main
ryan:main
ryan:docs/efficiency-tickets
ryan:docs/immich-mcp-tickets
ryan:fix/reindex-targets
ryan:docs/immich-mcp-design
ryan:fix/ci-frontend-yarn
ryan:feat/obsidian-write-sync
ryan:perf/prune-checkpoints
ryan:perf/obsidian-sync-off-loop
ryan:perf/full-search-chunks
ryan:perf/concise-answers
ryan:fix/image-ownership
ryan:fix/scheduled-messages-migration
ryan:feat/application-foundation
ryan:feat/config-ci
ryan:perf/stable-prompt-prefix
ryan:perf/fk-indexes
ryan:perf/offload-image-processing
ryan:perf/ynab-sync-interval
ryan:perf/batch-paperless-embeddings
ryan:feat/context-quality
ryan:fix/ynab-outflow-consistency
ryan:feat/ynab-report-totals
ryan:feat/context-management
ryan:fix/stream-stall-timeout
ryan:feat/cowork-file-drop
ryan:feat/cowork-artifact-panel
ryan:feat/cowork-timeline
ryan:feat/prompt-current-date
ryan:feat/cowork-tool-artifacts
ryan:feat/ynab-mirror
ryan:feat/cowork-stream
ryan:plan/cowork-ui
ryan:fix/access-token-auth
ryan:fix/access-token-auth-backend
ryan:explore/desktop-client
ryan:feat/homebox-set-item
ryan:feat/bookstack-mcp
ryan:feat/homebox-mcp
ryan:stream-observability
ryan:agent-image-and-context-fixes
ryan:feature/math-and-split-bill-tools
ryan:imessage-image-upload
ryan:paste-image-upload
ryan:llama-timeouts
ryan:fix-answer-bubble-react-import
ryan:copy-answer-messages
ryan:update-claude-md
ryan:mobile-drawer-conversation-pagination
ryan:conversation-routing
ryan:frontend-interactions-cleanup
ryan:eversweet-ultra-support
ryan:refactor/frontend-hooks
ryan:fix/obsidian-sync-setup
ryan:feat/improve-system-prompt
ryan:refactor/chromadb-to-pgvector
ryan:feat/rename-conversations-command
ryan:fix/mobile-conversation-launch
ryan:feat/conversation-name-truncation
ryan:feat/user-memory
ryan:feat/conversation-ordering-and-naming
ryan:fix/oidc-null-groups
ryan:extend-jwt-expiration
ryan:fix/mobile-input-performance
ryan:feat/makefile-redeploy
ryan:fix/image-in-existing-conversations
ryan:fix/image-presigned-urls
ryan:test/unit-tests
ryan:fix/ynab-transaction-limit
ryan:worktree-crispy-whistling-snowglobe
ryan:feature/llama-cpp-integration
ryan:rc/langchain-migration
ryan:rc/01012025-retitling
ryan:mobile-responsive-layout
ryan:async-reindexing
ryan:update-favicon-and-title
ryan:conversation-uplift
ryan:quart-login
ryan:user-support
ryan:rc/9-metadata-date-filtering
ryan:data-preprocessing
ryan:better-embeddings
5 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
d52c934b9a |
Add structured timing log to stream_query for slow-request diagnosis
Every SSE request emits a JSON summary line to the logger on completion,
cancellation, or error:
{"event":"stream_request","conv":"...","user":"ryan",
"total_ms":45210,"thinking_ms":38100,"ttft_ms":38200,
"tokens":112,"tools":[{"tool":"web_search","ms":820}],
"model":"llama","cancelled":false}
Fields:
- total_ms end-to-end wall time
- thinking_ms time from first LLM call to first content token (reasoning)
- ttft_ms time to first content token from request start
- tokens approximate content token count (stream deltas)
- tools each tool invoked with wall-clock duration
- model LLM name from LangChain metadata (catches fallback to OpenAI)
- cancelled true when client disconnected mid-stream
Tool timers use the LangChain run_id to correctly pair start/end even
when the same tool is called multiple times in one turn.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
||
|
|
d28dfb9435 |
Don't cancel stream on navigation away
Aborting the fetch on component unmount sent a disconnect to the server, which cancelled the in-flight generation. Now the stream runs to completion in the background (isMountedRef guards prevent stale state updates), the response is persisted, and it's there when the user returns to the conversation. stopGeneration() still aborts immediately on explicit user cancel. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|
|
b530974438 |
Show a thinking indicator while the model reasons
qwen3.8-27b is a reasoning model: it can think for hundreds of tokens
before any visible content streams. The SSE stream only forwarded
content deltas, so the UI showed dead air for the whole think and long
answers looked hung (users cancel ~1 min in).
The stream now emits a throttled {"type": "thinking"} heartbeat while
the current model turn has produced no content yet, and the frontend
renders a pulsing "Thinking..." pill until content or a tool call
arrives. The heartbeat also keeps bytes flowing on the SSE connection
during long thinks, so idle-timeout disconnects in the proxy chain
can't kill the stream.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
||
|
|
395c97958f |
Fix history roles and persist tool results for cross-turn context
Two fixes for the agent losing track of conversation context: - History replay compared msg.speaker (a Speaker enum) to the string "user", which is always false, so every prior message — including the user's — was sent to the LLM with role "assistant". Compare against Speaker.USER instead. Affected web, iMessage, WhatsApp, and email. - Tool outputs (web searches, RAG chunks) were discarded after each turn, so follow-up questions about fetched content had nothing to reference. Persist them as speaker="tool" messages (capped at 4000 chars) and replay them in history as assistant context. The conversation GET endpoint serves only their header line so the UI tool pill stays compact. Also bumps the replayed history window from 10 to 20 messages since tool messages now share it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
0389ec45c8 |
Pass images directly to the agent as multimodal content
Image messages previously ran two sequential LLM generations: a full non-streamed vision call to describe the image, then a second agent call with the description pasted in as text. The agent's llama-server model is already vision-capable, so attach the image to the user message as an OpenAI-style image_url content part and let the single agent call see it. Roughly halves image-turn latency and streams from the start. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |