- Show pre-tool plainTextContent above ToolCallStatus (was silently
dropped when hasThinking=false but plainText exists with tool_calls)
- Pre-tool thinking bubble gets proper bg-muted bubble styling and
isStreaming=false (thinking is complete once tool calls start)
- handleRegenerate now sets concurrentStatus="generating" for
consistent status bar feedback on regenerate
- Remove dead setConcurrentStatus prop from ChatInput interface/usage
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ConfigPanel (model mode + tool group chips) is no longer rendered in
the chat layout. Tool selection was surfaced below the input after the
previous refactor but users found it visually noisy. activeTools still
drives tool filtering on submit; UI selection can be re-exposed later
via a dedicated settings entry point.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove the "Auto · 云费用 1" summary toggle button that occupied a
dedicated line below the textarea. Model mode and tool group chips are
now displayed inline and always visible, eliminating the redundant
status row while keeping all selection controls accessible.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The "可分析工单、查知识库" / "已启用 X 个工具" hint paragraph
below the textarea was redundant — ConfigPanel already shows the
active tool count in its summary button. Removed the <p> block and
the now-unused activeTools destructuring in ChatInput.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add cloudcost_dashboard, cloudcost_metering, cloudcost_detail, cloudcost_alerts,
and cloudcost_accounts tools to the enterprise agent with full Gen-UI card support.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Change summaryExpanded default from false to true
- Long replies (>800 chars) now display full text immediately
- Users can still collapse with "收起" button if needed
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove opacity-0 group-hover from ThumbsUp/ThumbsDown buttons — always visible
- Fix thread title: update title whenever currentTitle is empty, not just first message
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add h-32 spacer before bottomRef to prevent last card from being hidden behind input bar
- Fix thread title not updating: check existing title instead of only first message
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add ThumbsUp/ThumbsDown feedback buttons on AI messages (hover reveal)
- Add ExportButton to export conversation as Markdown file
- Add global keyboard shortcuts: Ctrl+Shift+O (new thread), Ctrl+Shift+S (sidebar), / (focus input), Esc (stop)
- Unlock textarea during AI generation (remove disabled={thread.isLoading})
- Smart title truncation at word/punctuation boundary (30 chars)
- Show tool inputSummary in ToolCallStatus execution log
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- POST /api/client-log endpoint in http.ts (Hono, no auth, 204 response)
prints batched log entries to stdout so `docker compose logs` shows them
- New src/utils/remote-log.ts: remoteLog/remoteWarn batch to backend every 500ms
- Replace all bracket-tagged diagnostic console.log/warn calls in main.tsx and
ToolCallStatus.tsx with remoteLog/remoteWarn (tags: thread-ui, ui-debug,
render-msg, orphan-match, orphan-name-match, orphan-result, streaming-orphan,
tool-ui-match)
- Add /api/client-log proxy entry to vite.config.ts so dev server forwards
the request to the LangGraph backend (port 2024)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When modelMode is "pro", searcher/enterprise/coder agents now call the
Responses API directly via fetch to obtain reasoning summary blocks.
The reasoning text is injected as a { type: "thinking" } content block
in the AIMessage, while flash/auto modes remain unchanged using the
existing Chat Completions path through AzureChatOpenAI.
Key changes:
- create-llm.ts: add invokeWithReasoning() with inline zod-to-JSON-Schema
converter and Responses API output parser (reasoning/message/function_call)
- All three agent nodes: Pro branch converts LangChain messages to
Responses API format (developer role, function_call_output for tool
results, function_call for AI tool invocations)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Streaming orphan UI cards section was rendering all cards with message_id=NONE
as orphans, even when they were already claimed by the message-level orphan
matching logic via card_id. Added card_id+tool_call_id check to prevent
double rendering.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
With streamSubgraphs:true, subgraph values events push messages that
the parent Supervisor later merges, causing the same message.id to
appear multiple times in thread.messages. Similarly, the same card_id
can appear in both subgraph and parent values snapshots.
- Add deduplicateMessages() at module level: keeps the last (most
up-to-date) copy per message.id, eliminating duplicate AI messages
caused by subgraph-then-parent merge events.
- Apply deduplicateUiItems() to the full allUi array before per-message
card matching, so loading→done card pairs pushed by subgraphs and
parent are collapsed globally before orphan attribution runs.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Both thread.submit() calls now use streamMode: ["values", "messages"] so the
frontend receives real-time LLM token stream from subgraphs (searcher/coder/writer)
during the tool execution phase, eliminating the skeleton-only blank period.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add [thread-ui], [ui-debug], [tool-ui-match] console logs to trace
why searcher search-result cards show only skeleton after search completes.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add checkpoint guard in all 4 tool-executors ensuring every
tool_call_id gets a ToolMessage response
- Add cleanPollutedToolCalls utility to heal corrupted message history
- Add error banner with "重置此对话" button in frontend
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
SearchResultProps does not declare a card_id field, so passing it caused
TS2769 type errors. search-result cards do not need loading→done dedup
(each google_search/web_search_deep call produces a complete result in one
push), so the card_id and associated local variables are unnecessary.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Each search result card now carries a unique card_id containing the tool call id
(e.g. google-search-<tc.id>), enabling the ToolCallStatus exact-match logic to
correctly bind cards to their originating tool call without index-based offset errors.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add parallel_tool_calls: false to searcher agentNode bindTools call so the
LLM is forced to execute search tools one at a time (google_search first,
then web_read in a separate turn); prompt-level "strict禁止" alone cannot
override model-side parallel tool calling behaviour
- Remove card_id field from google_search and web_search_deep ui.push props;
SearchResultProps does not declare card_id so the field caused TS2769
overload errors; these cards do not need deduplication (each search is a
distinct query), while the card_id variables were introduced by a previous
commit and are now unused
- Clean up unused googleCardId and deepCardId local variables
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add web_read -> web-read-progress mapping to standaloneUiItems filter in main.tsx
so web-read-progress cards are no longer mistakenly treated as standalone
- Add web-read-progress to CARD_TYPE_PRIORITY (550) to ensure stable sort order
and prevent search-result cards (500) from being reordered relative to web-read cards
- Add unique card_id (containing tc.id) to google_search and web_search_deep ui.push
calls so each search result card can be precisely identified
- Improve uiItem matching in ToolCallStatus to first try exact match via card_id
containing tc.id, falling back to index-based matching only when necessary;
this prevents index offset bugs when multiple same-type tools run concurrently
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When LLM sends multiple parallel tool_calls but one throws unexpectedly,
Promise.all loses all results causing 400 error from OpenAI.
Promise.allSettled ensures every tool_call_id gets a response.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Azure Container App auto-deploy workflow replaces our manual
deploy-langgraph.yml. CD is now managed via Azure Portal.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
8s timeout caused Jina Reader failures on slower sites like news.cn.
Increased to 30s with 2 retries and 1s backoff.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>