Previously: setHistoricalMessages([]) + setCurrentThreadId() fired together,
causing a render where both thread.messages (cleared by switchThread) and
historicalMessages were empty → welcome screen shown.
Fix: await loadThreadState() first, then set historicalMessages/ui and
currentThreadId atomically. historicalMessages is populated before the
first render after the switch, so the welcome screen never flashes.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The threadJustSwitched suppression was too aggressive — it cleared
lastMessagesRef on every thread switch, then relied on historicalMessages
which loads async and may still be empty. Historical thread messages
would never appear.
Simplified fix: thread.switchThread() already clears thread.messages
when switching, so thread.messages is always safe to trust directly.
Use thread.messages when non-empty, else fall back to historicalMessages.
Removes threadJustSwitched / lastMessagesRef / lastThreadIdRef entirely.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 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>
- 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>
Wraps all LoadExternalComponent usages with CardErrorBoundary so
card rendering errors show an inline error message instead of
crashing the entire app.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tool call status cards and execution log panel now expand by default
so users can see CoT process and results without clicking.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace soc-langgraph Web App with Azure Container App (soc-cae environment)
- New URL: soc-langgraph.victorioussand-69befc84.southeastasia.azurecontainerapps.io
- Update deploy-langgraph.yml: Web App restart -> az containerapp update --image
- Update deploy-langgraph-ui.yml: VITE_LANGGRAPH_URL to Container App URL
- Container App: min 1 replica, max 3, CPU 1.0, Memory 2Gi, port 8080
- Update CLAUDE.md architecture and deployment docs
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
server.ts production mode crashes on startup (exit code 1).
Revert to langgraphjs dev until startServer() compatibility is resolved.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
server.ts uses createRequire to resolve @langchain/langgraph-api at startup.
With pnpm, indirect dependencies are not hoisted to node_modules/@langchain/,
causing "Cannot find module" error and container exit code 1 on Azure.
Adding it as an explicit dependency ensures pnpm creates the direct symlink.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add web-read-progress Gen-UI card for real-time web reading feedback
- Searcher tool-executor pushes loading→complete cards during web_read
- ToolCallStatus supports expanding during loading state
- Switch from langgraphjs dev to production mode (server.ts)
- Add Hono middleware to strip sensitive request headers
- Bundle splitting via Vite manualChunks (1.85MB → 8 chunks)
- SPA fallback via staticwebapp.config.json
- Agent model configs updated (sonnet 1M → standard sonnet)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Previously web_search_deep tool calls were missing from the UI_NAME_MAP,
causing their search-result cards to render as standalone cards instead of
being embedded within the ToolCallStatus component row.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When tool rounds hit MAX_ITERATIONS, the router was jumping directly to
END without giving the LLM a chance to produce a final text reply.
Added a `force-summary` node that invokes the LLM without tools,
ensuring a coherent Chinese summary is always generated after all
search results are collected.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The LangGraph API server injects all x-* request headers into
thread.config.configurable, which gets persisted and exposed via
POST /threads/search. This leaked Azure-injected headers (x-forwarded-for,
x-client-ip, x-arr-ssl, etc.) to any user.
Adds a Hono middleware (http.app) that strips sensitive infrastructure
headers at the HTTP layer before they reach the LangGraph API routes.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace single pendingSubmitRef with pendingQueueRef array supporting multiple queued messages
- Add SubmitPayload interface to snapshot text/file/tools/modelMode at submission time
- Rewrite handleSubmit/doSubmit to use payload snapshots instead of closures over mutable state
- Rewrite handleConcurrentQueue with polling loop that drains the queue sequentially
- Rewrite handleConcurrentInterrupt and handleConcurrentCancel for queue awareness
- StreamStatusBar queued state now shows count (N 条消息已排队) and inline cancel button
- Add key={concurrentStatus} to StreamStatusBar div for fade-in animation on status change
- Config panel summary button shows numeric badge instead of dot when tools are active
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- filterTools now actually filters by modelMode (flash excludes search tools)
- Hard limit of 3 tool calls per turn in preValidateToolCall
- Temperature default changed from 0.5 to 0.2 to match MODEL_PRESETS.auto
- ticket_list blocked when message contains specific ticket ID (TK-xxxx)
- google_search/web_search_deep blocked for internal knowledge queries
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace flat tool toggles + model selector bar with a default-collapsed
summary chip (e.g. "Auto · 已开启 3 个工具 ▾") that expands upward into
a compact panel. Panel auto-closes on outside mousedown click. Options
changes keep the panel open.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- Add showConcurrentDialog modal when submitting while AI is loading
- Offer interrupt (stop + submit) or queue (poll until done) options
- Remove disabled={thread.isLoading} from textarea and FileUploadButton
- Fix TS2352: cast BaseMessage to unknown first before Record
- Fix TS6133: rename unused toolName param to _toolName
- Fix TS2769: chart_type typed as union literal, not string
- Fix TS2322: separate cmdMap lookup from const declaration in soc-client
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- Add CornerDownRight, AlertCircle icons for fallback/partial states
- New isPartial/isFallback props on ToolCallRow with hint banners
- Read execution_log from thread.values in main.tsx, pass to ToolCallStatus
- Match by tc.name === entry.tool to determine partial/fallback per row
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
GOOGLE_API_KEY is not used at startup (no code calls config.google.apiKey).
DATABASE_URL is only needed for production checkpointer. Both are now
warned-but-not-fatal in dev (NODE_ENV != production) to allow local
development without these credentials.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- coder/tool-executor: push sandbox-result card with friendly message on
failure instead of raw error, guide user to local execution or retry
- enterprise/tool-executor: skip ticket-summary card when ticket_list
returns empty, only return hint in tool message to avoid blank UI
- searcher/tool-executor: auto-supplement web_search_deep with
google_search when results < 3, matching existing google_search behavior
- ticket_detail UUID: already correctly uses find() match (no change needed)
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- Fix ToolCallStatus label duplication: label span was shown twice when
failed/done; consolidate into a single span with correct copy
- Add animate-in fade-in duration-300 wrapper to standalone Gen-UI cards
and streaming orphan cards in main.tsx (already present in ToolCallStatus
expanded view)
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Cards with the same card_id in props are deduplicated to show only the
last (complete) version, replacing any earlier loading skeleton cards.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- Fix ticket_detail UUID resolution: use find() to match ticketNumber instead of tickets[0]
- Add sandbox fallback hint in coder tool-executor catch block
- Add ticket_list empty result friendly hint with suggestions
- Add google_search auto-supplement with Jina when results < 3
- Enhance enterprise tool-executor general catch with fallback_hint
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- Fix Daytona code execution endpoint from process/code-run (404) to process/execute
- Fix request body format to {command} with language-aware shell wrapping
- Add missing sourceType/confidence props to writer doc_edit and doc_translate ui.push
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>