feat: release terminal conversation surface and stabilize tool/sub-run UX#21
feat: release terminal conversation surface and stabilize tool/sub-run UX#21whatevertogo merged 53 commits intomasterfrom
Conversation
…reams crates/protocol/src/http/terminal/v1.rs - Why: Add optional tool input field to terminal v1 DTO so tool call context is preserved in snapshots. - How: Extended TerminalToolCallBlockDto with optional input. crates/server/src/http/terminal_projection.rs - Why: Fix terminal projection block lifecycle across live and durable tool calls and support tool input propagation. - How: Reworked TurnBlockRefs state machine, preserved pending/historical block ids, carried tool input into tool call deltas, and tightened finalization of stream blocks. crates/session-runtime/src/turn/runner/step/mod.rs - Why: Prevent empty assistant final events from being persisted when there is no meaningful assistant output. - How: Only emit assistant final event when assistant content or reasoning content is persistable. crates/session-runtime/src/turn/runner/step/tests.rs - Why: Align test expectations with the new no-empty-assistant-final behavior. - How: Removed strict assistant-final presence assertion and added explicit empty-assistant-final guard. frontend/src/components/Chat/MessageList.tsx - Why: Display tool stream messages grouped under their parent tool call instead of as separate rows. - How: Collected adjacent toolStream messages for toolCall entries and updated row rendering traversal. frontend/src/components/Chat/ToolCallBlock.tsx - Why: Improve tool result rendering with structured args, JSON output, and stream output grouping. - How: Added tool stream rendering, shell/JSON formatting helpers, and richer fallback UI. frontend/src/lib/api/conversation.ts - Why: Keep tool call args from terminal blocks and avoid duplicate appended blocks during stream replay. - How: Map block input into tool call args and replace existing blocks by id when appending.
- Added cache metrics to PromptBuildOutput in various modules to track cache reuse hits and misses. - Updated assemble_prompt_request to carry prompt cache reuse counts and integrated related tests. - Enhanced ToolCallBlock to support child session navigation and improved rendering of tool call results. - Implemented utility functions to calculate prompt reuse rates and updated relevant components to display these metrics. - Modified conversation handling to support metadata updates for tool calls, enabling better tracking of spawned sessions. - Improved sub-run view logic to recover nested spawned sub-runs from tool metadata.
Reviewer's GuideUnifies the conversation/terminal projection across server, CLI, and web while completing the terminal chat surface, fixing tool/sub-run streaming semantics, and wiring real prompt cache metrics end‑to‑end. Sequence diagram for live tool call streaming and terminal projectionsequenceDiagram
actor User
participant CLI as CliClient
participant Server
participant SessionRuntime
participant SessionState
participant TerminalProj as TerminalDeltaProjector
participant Frontend
User->>CLI: invoke tool via chat
CLI->>Server: POST /conversation ...
Server->>SessionRuntime: run turn
Note over SessionRuntime: invoke_single_tool
SessionRuntime->>SessionState: append durable ToolCallStart event
SessionRuntime->>SessionState: broadcast_tool_start(turn_id, tool_call)
SessionState-->>Server: AgentEvent.ToolCallStart (Live)
Server->>TerminalProj: project ToolCallStart
TerminalProj->>TerminalProj: start_tool_call(turn_id, tool_call_id, tool_name, input, source=Live)
TerminalProj->>TerminalProj: split_after_live_tool_boundary() on TurnBlockRefs
TerminalProj-->>Frontend: TerminalDeltaDto.AppendBlock(ToolCall with input, metadata)
loop Tool stdout/stderr stream
SessionRuntime->>SessionState: broadcast_tool_output_delta
SessionState-->>Server: AgentEvent.ToolCallDelta (Live)
Server->>TerminalProj: project ToolCallDelta
TerminalProj-->>Frontend: TerminalDeltaDto.PatchBlock(append tool output)
end
SessionRuntime->>SessionState: append durable ToolCallResult event
SessionRuntime->>SessionState: broadcast_tool_result(turn_id, result{duration_ms, metadata})
SessionState-->>Server: AgentEvent.ToolCallResult (Live)
Server->>TerminalProj: project ToolCallResult
TerminalProj->>TerminalProj: replace_tool_summary
TerminalProj->>TerminalProj: replace_tool_metadata
TerminalProj-->>Frontend: TerminalDeltaDto.PatchBlock(ReplaceSummary)
TerminalProj-->>Frontend: TerminalDeltaDto.PatchBlock(ReplaceMetadata)
Frontend->>Frontend: applyConversationEnvelope(append_block/patch_block)
Frontend->>Frontend: projectConversationState -> ToolCallMessage + ToolStreamMessage
Frontend->>Frontend: MessageList groups ToolStream by toolCallId
Frontend->>Frontend: ToolCallBlock(streams=[...]) renders grouped tool result, args, child session entry
Class diagram for updated terminal projection block lifecycleclassDiagram
class TerminalDeltaProjector {
-blocks: Vec~TerminalBlockDto~
-block_index: HashMap~String, usize~
-turn_blocks: HashMap~String, TurnBlockRefs~
-tool_blocks: HashMap~String, ToolBlockRefs~
+append_markdown_streaming_block(turn_id: &str, delta: &str, kind: BlockKind) Vec~TerminalDeltaDto~
+start_tool_call(turn_id: &str, tool_call_id: &str, tool_name: &str, input: Option~Value~, source: ProjectionSource) Vec~TerminalDeltaDto~
+append_assistant_message(turn_id: &str, content: &str, reasoning_content: Option~&str~) Vec~TerminalDeltaDto~
+complete_turn_blocks(turn_id: &str) Vec~TerminalDeltaDto~
-replace_tool_metadata(index: usize, metadata: &Value) bool
}
class TurnBlockRefs {
+current_thinking: Option~String~
+current_assistant: Option~String~
+historical_thinking: Vec~String~
+historical_assistant: Vec~String~
+pending_thinking: Vec~String~
+pending_assistant: Vec~String~
+thinking_count: usize
+assistant_count: usize
+current_or_next_block_id(turn_id: &str, kind: BlockKind) String
+block_id_for_finalize(turn_id: &str, kind: BlockKind) String
+split_after_live_tool_boundary()
+split_after_durable_tool_boundary()
+all_block_ids() Vec~String~
}
class ToolBlockRefs {
+call_block_id: Option~String~
+stdout_block_id: Option~String~
+stderr_block_id: Option~String~
}
class ProjectionSource {
<<enum>>
Durable
Live
+is_durable(self) bool
+is_live(self) bool
}
class TerminalBlockDto {
<<enum>>
Thinking
Assistant
ToolCall
ToolStream
User
}
class TerminalToolCallBlockDto {
+id: String
+turn_id: Option~String~
+tool_call_id: Option~String~
+tool_name: String
+status: TerminalBlockStatusDto
+input: Option~Value~
+summary: Option~String~
+metadata: Option~Value~
}
class TerminalDeltaDto {
<<enum>>
AppendBlock
PatchBlock
ReplaceAll
}
class TerminalBlockPatchDto {
<<enum>>
ReplaceSummary(summary: String)
ReplaceMetadata(metadata: Value)
SetStatus(status: TerminalBlockStatusDto)
AppendMarkdown(markdown: String)
}
class BlockKind {
<<enum>>
Thinking
Assistant
}
TerminalDeltaProjector --> TurnBlockRefs : manages per-turn blocks
TerminalDeltaProjector --> ToolBlockRefs : manages per-tool blocks
TerminalDeltaProjector --> ProjectionSource : uses
TerminalDeltaProjector --> TerminalBlockDto : produces
TerminalDeltaProjector --> TerminalDeltaDto : emits
TerminalDeltaDto --> TerminalBlockPatchDto : PatchBlock
TerminalBlockDto --> TerminalToolCallBlockDto : ToolCall variant
TurnBlockRefs --> BlockKind
class Helpers {
+turn_scoped_block_id(turn_id: &str, role: &str, ordinal: usize) String
}
Helpers ..> TurnBlockRefs
Class diagram for prompt cache metrics propagationclassDiagram
class PromptBuildCacheMetrics {
<<struct>>
+reuse_hits: u32
+reuse_misses: u32
}
class PromptBuildOutput {
+system_prompt: String
+system_prompt_blocks: Vec~SystemPromptBlock~
+cache_metrics: PromptBuildCacheMetrics
+metadata: Value
}
class PromptProvider {
<<trait>>
+build_prompt(request: PromptBuildRequest) PromptBuildOutput
}
class ComposerPromptProvider {
+build_prompt(request: PromptBuildRequest) PromptBuildOutput
-summarize_prompt_cache_metrics(output: PromptBuildOutput) PromptBuildCacheMetrics
}
class KernelGateway {
+supports_cache_metrics() bool
}
class AssemblePromptRequest {
+gateway: KernelGateway
+step_index: usize
+prompt_facts_provider: PromptFactsProvider
+session_state: SessionState
}
class prompt_metrics_event {
+prompt_metrics_event(turn_id: &str, agent: &AgentEventContext, step_index: usize, snapshot: PromptTokenSnapshot, truncated_tool_results: usize, cache_metrics: PromptBuildCacheMetrics, provider_cache_metrics_supported: bool) StorageEvent
}
class apply_prompt_metrics_usage {
+apply_prompt_metrics_usage(events: &mut [StorageEvent], step_index: usize, usage: Option~LlmUsage~)
}
class StorageEvent {
+turn_id: Option~String~
+payload: StorageEventPayload
}
class StorageEventPayload {
<<enum>>
+PromptMetrics_variant: PromptMetrics
+other_variants: ...
}
class PromptMetrics {
+step_index: u32
+provider_input_tokens: Option~u32~
+provider_output_tokens: Option~u32~
+cache_creation_input_tokens: Option~u32~
+cache_read_input_tokens: Option~u32~
+provider_cache_metrics_supported: bool
+prompt_cache_reuse_hits: u32
+prompt_cache_reuse_misses: u32
+truncated_tool_results: u32
}
class LlmUsage {
+input_tokens: u32
+output_tokens: u32
+cache_creation_input_tokens: u32
+cache_read_input_tokens: u32
}
class RunStep {
+run_single_step_with(...)
}
PromptProvider <|.. ComposerPromptProvider
ComposerPromptProvider --> PromptBuildOutput : returns
PromptBuildOutput --> PromptBuildCacheMetrics
AssemblePromptRequest ..> KernelGateway
AssemblePromptRequest ..> PromptProvider
AssemblePromptRequest ..> prompt_metrics_event
prompt_metrics_event --> StorageEvent
StorageEvent --> StorageEventPayload
StorageEventPayload --> PromptMetrics
RunStep ..> apply_prompt_metrics_usage : after LLM output
apply_prompt_metrics_usage --> StorageEvent : mutates PromptMetrics
apply_prompt_metrics_usage ..> LlmUsage
class FrontendPromptMetricsMessage {
+providerInputTokens?: number
+providerOutputTokens?: number
+cacheCreationInputTokens?: number
+cacheReadInputTokens?: number
+providerCacheMetricsSupported: boolean
+promptCacheReuseHits: number
+promptCacheReuseMisses: number
}
class calculateCacheHitRatePercent {
+calculateCacheHitRatePercent(metrics: PromptMetricsMessage) number | null
}
class calculatePromptReuseRatePercent {
+calculatePromptReuseRatePercent(metrics: PromptMetricsMessage) number | null
}
StorageEventPayload --> FrontendPromptMetricsMessage : via HTTP projection
calculateCacheHitRatePercent ..> FrontendPromptMetricsMessage
calculatePromptReuseRatePercent ..> FrontendPromptMetricsMessage
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've found 1 issue, and left some high level feedback:
- In
TurnBlockRefs::block_id_for_finalizeyou usepending_*: Vec<String>withremove(0), which is O(n); if a turn can accumulate many pending blocks, consider switching these toVecDequeand usingpop_frontto avoid repeated shifting. - The new
useNestedScrollContainmenthook is attached to multiple scrollable components; to avoid subtle UX issues, you might want to guard against horizontal wheel events (e.g. trackpad two‑finger scroll) or modifier-key scrolling so they can still bubble to the outer container when appropriate.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In `TurnBlockRefs::block_id_for_finalize` you use `pending_*: Vec<String>` with `remove(0)`, which is O(n); if a turn can accumulate many pending blocks, consider switching these to `VecDeque` and using `pop_front` to avoid repeated shifting.
- The new `useNestedScrollContainment` hook is attached to multiple scrollable components; to avoid subtle UX issues, you might want to guard against horizontal wheel events (e.g. trackpad two‑finger scroll) or modifier-key scrolling so they can still bubble to the outer container when appropriate.
## Individual Comments
### Comment 1
<location path="frontend/src/components/Chat/useNestedScrollContainment.ts" line_range="11-20" />
<code_context>
+ return;
+ }
+
+ const onWheel = (event: WheelEvent) => {
+ const canScroll = container.scrollHeight > container.clientHeight + 1;
+ if (!canScroll) {
+ return;
+ }
+
+ const atTop = container.scrollTop <= 0 && event.deltaY < 0;
+ const atBottom =
+ container.scrollTop + container.clientHeight >= container.scrollHeight - 1 &&
+ event.deltaY > 0;
+
+ if (!atTop && !atBottom) {
+ event.stopPropagation();
+ return;
</code_context>
<issue_to_address>
**issue (bug_risk):** Scroll containment prevents parent scrolling at container boundaries due to `preventDefault`.
Because `event.preventDefault()` is still called when `atTop` or `atBottom`, neither the inner nor outer container scrolls at the edges, making the scroll feel stuck. Keep the current `stopPropagation` behavior in the middle of the content, but at the top/bottom let the event bubble (no `preventDefault`) so the parent can scroll. Adjust the conditions so `preventDefault` only applies while the inner container can continue scrolling, not when it has reached its bounds.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
There was a problem hiding this comment.
Pull request overview
This PR releases a complete “terminal conversation surface” and aligns the read-model/projection semantics across server/CLI/web, with a focus on stabilizing tool streaming, sub-run navigation, and prompt/provider cache metrics end-to-end.
Changes:
- Frontend: improve tool-call rendering (group tool streams, richer JSON/code surfaces, child-session entry) and fix prompt metrics display (provider KV cache + prompt reuse).
- Session/runtime & adapters: broadcast tool start/result live events and plumb prompt cache reuse metrics into PromptMetrics events.
- Protocol/server: extend terminal/conversation contracts to carry tool input/metadata and update terminal projection + fixtures/tests accordingly.
Reviewed changes
Copilot reviewed 35 out of 35 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| frontend/src/lib/utils.ts | Refines provider cache hit rate calculation and adds prompt reuse rate helper. |
| frontend/src/lib/toolDisplay.ts | Extracts child-session/sub-run navigation targets from tool metadata. |
| frontend/src/lib/subRunView.ts | Improves sub-run topology/fingerprint handling to recover nested spawned sub-runs. |
| frontend/src/lib/subRunView.test.ts | Adds coverage for recovering nested spawned sub-runs and fingerprint updates. |
| frontend/src/lib/api/conversation.ts | Projects tool args/metadata and makes append_block idempotent + adds replace_metadata patch handling. |
| frontend/src/lib/api/conversation.test.ts | Adds tests for append_block upsert behavior and replace_metadata patching. |
| frontend/src/components/Chat/useNestedScrollContainment.ts | Adds wheel-event containment hook for nested scroll regions. |
| frontend/src/components/Chat/ToolStreamBlock.tsx | Renders stdout tool stream as JSON when possible; otherwise uses a shared code panel. |
| frontend/src/components/Chat/ToolJsonView.tsx | Adds scroll modes/default open behavior and adjusts JSON rendering. |
| frontend/src/components/Chat/ToolCodePanel.tsx | Introduces a reusable code panel surface for tool outputs. |
| frontend/src/components/Chat/ToolCallBlock.tsx | Adds collapsible tool block UI, stream grouping, args/metadata surfaces, and child-session navigation. |
| frontend/src/components/Chat/ToolCallBlock.test.tsx | Adds SSR-based tests for tool block summary/body rendering and child-session CTA. |
| frontend/src/components/Chat/PromptMetricsMessage.tsx | Displays provider cache and prompt reuse metrics in prompt metrics card. |
| frontend/src/components/Chat/MessageList.tsx | Groups tool streams under tool calls during rendering. |
| frontend/src/components/Chat/AssistantMessage.tsx | Updates cache indicator logic to prefer provider KV cache and fallback to prompt reuse. |
| crates/session-runtime/src/turn/tool_cycle.rs | Broadcasts ToolCallStart/ToolCallResult over live channel; updates tests accordingly. |
| crates/session-runtime/src/turn/test_support.rs | Updates noop prompt provider to include cache_metrics; removes an assertion helper. |
| crates/session-runtime/src/turn/submit.rs | Updates test prompt provider output shape with cache_metrics. |
| crates/session-runtime/src/turn/runner/step/tests.rs | Adjusts step fixtures + asserts interrupted tool-only steps don’t persist empty AssistantFinal. |
| crates/session-runtime/src/turn/runner/step/mod.rs | Backfills prompt metrics with LLM usage and avoids persisting empty assistant finals. |
| crates/session-runtime/src/turn/request.rs | Emits prompt cache reuse counts + provider cache support flag; adds test coverage. |
| crates/session-runtime/src/turn/manual_compact.rs | Updates test prompt provider output shape with cache_metrics. |
| crates/session-runtime/src/turn/events.rs | Adds prompt cache reuse counts and backfills provider cache token usage into prompt metrics events. |
| crates/server/src/http/terminal_projection.rs | Supports multi-block assistant/thinking across tool boundaries; carries tool input/metadata into terminal blocks. |
| crates/server/src/bootstrap/capabilities.rs | Updates test prompt provider output shape with cache_metrics. |
| crates/protocol/tests/terminal_conformance.rs | Updates terminal snapshot conformance to include tool input field. |
| crates/protocol/tests/fixtures/terminal/v1/snapshot.json | Fixture update: tool_call blocks include input. |
| crates/protocol/src/http/terminal/v1.rs | Extends terminal tool_call DTO + adds replace_metadata patch. |
| crates/kernel/src/gateway/mod.rs | Exposes supports_cache_metrics on KernelGateway for prompt metrics flagging. |
| crates/core/src/ports.rs | Introduces PromptBuildCacheMetrics and adds cache_metrics to PromptBuildOutput. |
| crates/core/src/lib.rs | Re-exports PromptBuildCacheMetrics. |
| crates/cli/src/state/conversation.rs | Handles ReplaceMetadata patch for tool call blocks. |
| crates/application/src/agent/test_support.rs | Updates test prompt provider output shape with cache_metrics. |
| crates/adapter-prompt/src/core_port.rs | Summarizes prompt cache reuse hits/misses into PromptBuildOutput.cache_metrics. |
| crates/adapter-llm/src/anthropic.rs | Adds helper clarifying which system layers are cacheable. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| return; | ||
| } | ||
|
|
||
| event.preventDefault(); |
There was a problem hiding this comment.
useNestedScrollContainment calls event.preventDefault() when the nested scroller is already at the top/bottom. This can prevent the parent scroll container from scrolling, effectively trapping the user when they wheel past the boundary. Consider only stopping propagation while the element can still scroll, and at boundaries allow the event to bubble (or rely on CSS overscroll-behavior: contain for bounce control) instead of preventing default.
| return; | |
| } | |
| event.preventDefault(); | |
| } |
| if (typeof value === 'string') { | ||
| const truncated = | ||
| value.length > MAX_STRING_PREVIEW | ||
| ? `${value.slice(0, MAX_STRING_PREVIEW)}... (${value.length} chars)` | ||
| : value; | ||
| return ( | ||
| <span className="whitespace-pre-wrap overflow-wrap-anywhere text-json-string"> | ||
| "{truncated}" | ||
| "{value}" | ||
| </span> |
There was a problem hiding this comment.
renderPrimitiveValue now renders full string values with no truncation/preview. Large tool outputs (e.g., long file contents encoded in JSON) can create huge DOM/text nodes and noticeably degrade render performance. Consider restoring a length-limited preview with an expand action, or collapsing long strings behind a <details>.
protocol / conversation contract - Files: crates/protocol/src/http/conversation/v1.rs, crates/protocol/src/http/mod.rs, crates/protocol/tests/conversation_conformance.rs, crates/protocol/tests/fixtures/conversation/v1/snapshot.json, crates/protocol/tests/fixtures/conversation/v1/delta_patch_tool_stream.json, crates/protocol/tests/fixtures/conversation/v1/delta_rehydrate_required.json, crates/protocol/tests/terminal_conformance.rs, crates/protocol/tests/fixtures/terminal/v1/delta_patch_tool_metadata.json - Why: 旧 conversation surface 仍夹带 terminal alias 和 sibling tool stream 语义,工具展示合同不稳定,无法冻结 hydration/delta/reconnect 行为。 - How: 独立定义 conversation v1 DTO,把 tool display 收敛为单个 tool call block + stream patch,并补齐协议 conformance 测试与 fixture。 session-runtime query - Files: crates/session-runtime/src/query/conversation.rs, crates/session-runtime/src/query/mod.rs, crates/session-runtime/src/query/service.rs, crates/session-runtime/src/lib.rs - Why: authoritative tool display 真相长期停留在 server/frontend 侧拼装,违反单 session read model 边界。 - How: 新增 conversation query 子域,输出 snapshot/replay facts、tool block 聚合、live/durable 去重、child handoff 与 transcript error 分类,并从 service/lib 对外暴露稳定查询接口。 application conversation use cases - Files: crates/application/src/ports/app_session.rs, crates/application/src/terminal/mod.rs, crates/application/src/terminal_use_cases.rs - Why: application 之前继续上传 transcript/replay 原始材料,导致上层必须理解事件级细节才能恢复 conversation 真相。 - How: 改为直接消费 conversation snapshot/stream replay facts,调整 terminal summary、cursor 校验与 child summary 逻辑,只保留稳定 facts 编排职责。 server projection and routes - Files: crates/server/src/http/routes/conversation.rs, crates/server/src/http/terminal_projection.rs - Why: server route/projector 不应继续承担状态型 tool 聚合与 replay/live 对齐规则。 - How: 把 server 收回为 DTO 映射、rehydrate signalling 与 SSE framing 薄层,删除大部分 projector 内的工具聚合逻辑并改用 session-runtime authoritative facts。 tool execution coverage - Files: crates/session-runtime/src/turn/tool_cycle.rs - Why: 新的 tool display contract 需要证明 stderr 流同时覆盖 durable 与 live 通道,否则工具失败场景仍可能回归。 - How: 增加 streaming stderr probe tool 与相关测试,验证即时事件、持久化 delta 和 tool result 的一致性。 cli transcript rendering - Files: crates/cli/src/state/conversation.rs, crates/cli/src/state/transcript_cell.rs, crates/cli/src/ui/cells.rs - Why: CLI 仍保留旧的本地 regroup 思维,不能完整消费工具 block 的 streams、error、duration、truncated 与 child session 字段。 - How: 让 transcript cell 直接建模 tool call 的完整展示字段,并在 UI 中以内嵌 stdout/stderr/error/duration 渲染统一工具块。 frontend conversation model - Files: frontend/src/lib/api/conversation.ts, frontend/src/lib/api/conversation.test.ts, frontend/src/types.ts, frontend/src/lib/subRunView.ts, frontend/src/lib/toolDisplay.ts - Why: 前端此前依赖 tool_stream sibling regroup、metadata fallback 和 spawn 特判来重建工具展示与子会话拓扑,重连后容易漂移。 - How: 改为直接维护 authoritative tool block store,引入显式 childRef/streams 类型,补齐 patch 应用逻辑与 reconnect/并发工具测试,并删除 metadata fallback 推断路径。 frontend chat rendering - Files: frontend/src/components/Chat/MessageList.tsx, frontend/src/components/Chat/ToolCallBlock.tsx, frontend/src/components/Chat/ToolCallBlock.test.tsx, frontend/src/components/Chat/SubRunBlock.tsx, frontend/src/components/Chat/ToolStreamBlock.tsx - Why: UI 仍把 tool stream 当作独立 message 渲染,导致工具输出和终态字段分裂在多个块里。 - How: 删除 ToolStreamBlock 与 groupedToolStreams 扫描逻辑,让 ToolCallBlock 直接渲染嵌入式 stdout/stderr、失败态和 childRef 跳转。 docs and review artifacts - Files: README.md, PROJECT_ARCHITECTURE.md, CODE_REVIEW_ISSUES.md - Why: 实现已经收紧 conversation/tool display 边界,但仓库文档和评审结论还未反映新的权威读模型约束。 - How: 更新 README 与架构文档,明确 conversation surface、tool block contract 和前后端职责,并记录本轮代码评审发现。 openspec sync - Files: openspec/changes/2026-04-15-stabilize-conversation-surface/proposal.md, openspec/changes/2026-04-15-stabilize-conversation-surface/tasks.md, openspec/changes/archive/2026-04-16-refactor-tool-call-display-pipeline/.openspec.yaml, openspec/changes/archive/2026-04-16-refactor-tool-call-display-pipeline/design.md, openspec/changes/archive/2026-04-16-refactor-tool-call-display-pipeline/proposal.md, openspec/changes/archive/2026-04-16-refactor-tool-call-display-pipeline/specs/application-use-cases/spec.md, openspec/changes/archive/2026-04-16-refactor-tool-call-display-pipeline/specs/session-runtime-subdomain-boundaries/spec.md, openspec/changes/archive/2026-04-16-refactor-tool-call-display-pipeline/specs/terminal-chat-read-model/spec.md, openspec/changes/archive/2026-04-16-refactor-tool-call-display-pipeline/specs/terminal-chat-surface/spec.md, openspec/changes/archive/2026-04-16-refactor-tool-call-display-pipeline/tasks.md, openspec/specs/application-use-cases/spec.md, openspec/specs/session-runtime-subdomain-boundaries/spec.md, openspec/specs/terminal-chat-read-model/spec.md, openspec/specs/terminal-chat-surface/spec.md - Why: 这次重构改变了 conversation/tool display 的稳定边界,需要把 change、归档与主 specs 同步到实现后的状态。 - How: 归档旧 change,补齐 proposal/design/tasks,并同步 main specs 中 application、session-runtime 与 terminal chat surface 的要求。 agent runtime defaults - Files: crates/core/src/config.rs - Why: 现有单轮 spawn 默认预算过低,无法承载多视角 review 工作流。 - How: 将 DEFAULT_MAX_SPAWN_PER_TURN 从 3 提升到 6,与新的协作工作流保持一致。
crates/core/ - Why: 运行时内部长期同时维护重复的执行结果、协作结果和 child reference 真相,导致 tool metadata、sub-run 状态与类型边界持续分叉。 - How: 提取 `ExecutionResultCommon`,为 `ToolExecutionResult` 引入 typed `child_ref`,收口 `SubRunResult`/`CollaborationResult`/child identity/强类型 ID,并删除 legacy wire 兼容补洞。 crates/protocol/ crates/plugin/ crates/sdk/ - Why: plugin/protocol 边界之前维护了与 core 平行的 capability 描述体系,`CapabilityDescriptor` 既像 wire DTO 又像内部语义模型,架构边界不清晰。 - How: 将协议层能力描述改为显式 `CapabilityWireDescriptor` 并直接复用 `CapabilitySpec` 语义,升级 v5 fixtures 与 DTO 合同测试,删掉重复 mapper 与旧 debug HTTP surface。 crates/application/ crates/session-runtime/ crates/kernel/ crates/adapter-tools/ - Why: 子 agent 启动、工具结果映射和会话投影链路仍依赖 metadata 约定与手工拼装,导致协作语义无法稳定透传到 authoritative read model。 - How: 统一用 typed child refs 和 canonical helper 投影 child/session identity,补上 fork mode 父上下文继承逻辑,并同步治理、投影、测试与工具 schema。 crates/server/ src-tauri/ frontend/ - Why: 终端与桌面壳层仍暴露独立 debug workbench 入口,前端子运行展示也没有完全跟随新的 sub-run/cancelled/result contract。 - How: 删除 debug workbench 路由、窗口和前端入口,更新终端 conversation 映射、sub-run 视图与类型定义,使 `cancelled`、`token_exceeded` 和 child ref 展示与后端 contract 一致。 crates/debug-workbench/ openspec/specs/debug-workbench-read-model/ openspec/specs/server-http-debug-surface/ - Why: 独立 debug workbench 已不再符合当前“conversation/terminal authoritative surface”方向,继续保留只会扩大维护面和重复读模型。 - How: 移除 debug-workbench crate、相关前端页面与 OpenSpec 条目,并同步归档/任务文档中对调试面的描述。 README.md PROJECT_ARCHITECTURE.md docs/audit/core-type-audit.md AGENTS.md CLAUDE.md CODE_REVIEW_ISSUES.md ASTRCODE_EXPLORATION_REPORT.md - Why: 这轮调整同时改变了 capability 真相源、调试面边界和若干代码审查结论,需要文档与工程约束一起收敛,避免实现与文档继续漂移。 - How: 更新架构说明、仓库导览、审查报告和项目说明,明确 `CapabilitySpec`/`CapabilityWireDescriptor` 分工、debug workbench 删除结论与后续治理方向。
session-runtime/core/protocol - Why: 让 compact 从单次摘要动作升级为可恢复、可观测、可配置的上下文管理链路,并补齐事件与协议事实。 - How: 新增 compact trigger/meta、reserved_context_size、compact_max_retry_attempts、自定义 instructions、裁剪重试与更稳健的解析/输入整形逻辑;同步 conversation/control DTO 与事件投影。 application/agent/server/client - Why: 让手动 compact、deferred compact 和 observe 治理在应用层真正闭环,避免模型重复 observe 和 interrupted 后 compact 丢失。 - How: 新增 compact_session_with_options,支持传递 instructions;在 turn 结束和 interrupt 后统一消费 pending manual compact;为 observe 增加同 turn 未变化快照拒绝;同步 HTTP 路由与客户端请求面。 frontend - Why: 把 compact 从后台隐式动作升级为前端可见状态,并支持 /compact 自定义指令。 - How: 扩展 slash command、session API 和 conversation 投影,展示 compacting/pending 状态、compact meta、deferred trigger 与 compact 卡片细节;补上 favicon 资源。 validation - Why: 让升级后的契约、fixture 和代码结构在全量验证下稳定通过。 - How: 更新 protocol/cli fixture,收敛 conversation delta 结构与 clippy 告警,补齐相关测试并完成全量验证修复。
crates/core/src/{execution_control.rs,composer.rs,observability.rs,session_catalog.rs,config.rs,lib.rs,plugin/registry.rs}
- Why: ExecutionControl、composer/model/config 测试结果、runtime observability、session catalog 事件已经成为跨 core/application/protocol/server 共享的稳定语义,继续在多层重复定义会让 owner 漂移并放大维护成本。
- How: 新增 core canonical types 与 serde owner,把 observability/session catalog/composer/execution control/test connection 等共享结构统一收回 core,并补顶层导出与必要的序列化支持。
crates/application/src/{lib.rs,execution/control.rs,composer/mod.rs,config/mod.rs,observability/mod.rs,observability/metrics_snapshot.rs,mcp/mod.rs,session_use_cases.rs,agent_use_cases.rs,terminal/mod.rs,terminal_use_cases.rs}
- Why: server 不该继续承担 accepted response、runtime/config/status、conversation terminal UI 派生等业务投影;application 需要成为协议 DTO 之前的共享 summary owner。
- How: 将 application 侧重复类型改为复用 core,并新增 Config/Runtime/Prompt/Compact/SessionList/AgentExecute/SubRunStatus/ConversationAuthoritative 等 summary 输入与解析函数,统一承接 API key 脱敏、active selection、运行时摘要、conversation control/child/slash 派生规则。
crates/protocol/src/http/{agent.rs,composer.rs,config.rs,event.rs,model.rs,runtime.rs,session.rs,session_event.rs}
- Why: protocol 只应保留真正的协议壳和读模型,不应继续维护与 core/application 同形同义的镜像 DTO。
- How: 将 model/composer/test result/runtime metrics/plugin state/session catalog/agent 部分共享语义改为直接 alias core canonical type,仅保留协议外层 response/envelope/read-model。
crates/server/src/http/{auth.rs,mapper.rs,terminal_projection.rs,routes/mod.rs,routes/mcp.rs,routes/model.rs,routes/config.rs,routes/agents.rs,routes/conversation.rs,routes/sessions/mutation.rs,routes/sessions/query.rs}
- Why: HTTP 层此前同时承担协议包装和业务整形,导致 mapper/route 里充满字段直拷贝、fallback、UI capability 派生和 message 决策。
- How: auth/mcp/config/model/agent/session/conversation 路由改为消费 application summary 或 core alias,删除大批纯搬运映射;terminal_projection 只保留 summary -> DTO 重命名,conversation stream authoritative refresh 也改为围绕 application summary 运行而不再并行维护 raw terminal facts。
crates/session-runtime/src/{lib.rs,actor/mod.rs,catalog/mod.rs,command/mod.rs,query/mod.rs,query/service.rs,query/agent.rs,query/conversation.rs,query/text.rs,turn/mod.rs,turn/runner.rs,turn/tool_cycle.rs,context_window/mod.rs,state/mailbox.rs,context/mod.rs,factory/mod.rs}
- Why: session-runtime 对外 surface 过宽、查询辅助逻辑重复且等待 turn 终态依赖轮询,既增加耦合也拉低查询路径的可维护性。
- How: 收紧模块可见性与 re-export,删除无用 factory/context/mailbox 辅助,新增 query::text 统一摘要截断逻辑,并把 turn terminal snapshot 等查询改成基于 broadcaster 唤醒与单次 durable fallback 的实现,同时在 conversation replay 路径上拆分 seed/replay 历史避免重复加载。
♻️ refactor(skill_catalog): 引入读写保护器优化技能目录管理 ♻️ refactor(apply_patch): 使用 Map 优化补丁解析和元数据构建 ♻️ refactor(profiles): 引入读写保护器优化全局配置文件缓存管理 ♻️ refactor(mod): 使用 HeaderValue 优化 CORS 层配置
AGENTS.md - Why: 补充本仓库 TUI 风格与 ratatui 文本包装约定,避免后续终端界面继续走散乱实现。 - How: 新增 TUI style/code conventions,并引入 `codex-rs/tui/styles.md` 作为约束来源。 CODE_REVIEW_ISSUES.md - Why: 同步本轮 CLI 工作树评审结论,记录仍需关注的滚动逻辑与魔法数问题。 - How: 用新的 review 结果替换旧报告,更新质量、测试与架构章节。 crates/adapter-llm/src/anthropic.rs - Why: 旧 Anthropic provider 单文件过大,协议构建、请求发送、响应解析和 SSE 流式逻辑耦合过深,维护成本过高。 - How: 删除单体实现文件,将 DTO、provider、request、response 与 stream 逻辑迁移到独立子模块。 crates/adapter-llm/src/anthropic/dto.rs - Why: 需要把 Anthropic 协议数据结构从 provider 行为中拆出来,稳定消息与 usage 模型边界。 - How: 抽取 request/response 共享 DTO、usage 合并逻辑和序列化结构。 crates/adapter-llm/src/anthropic/mod.rs - Why: Anthropic 模块拆分后需要显式收口导出面,避免调用方继续依赖内部实现细节。 - How: 新增模块入口,声明并重导出 dto/provider/request/response/stream 子模块。 crates/adapter-llm/src/anthropic/provider.rs - Why: Provider 需要只保留构建请求、发送请求与 orchestrate 流程的职责,降低单函数复杂度。 - How: 抽离 `AnthropicProvider` 主体实现、重试发送逻辑、缓存跟踪和 generate 主流程。 crates/adapter-llm/src/anthropic/request.rs - Why: 请求构建涉及 system prompt、tool、thinking 和 cache breakpoint 规则,适合独立成可测试的构造层。 - How: 提取 request 构建、消息转换、工具定义转换与缓存策略相关辅助函数。 crates/adapter-llm/src/anthropic/response.rs - Why: 非流式响应解析与输出装配不应继续散落在 provider 主流程里。 - How: 抽出 response 到 `LlmOutput` 的转换、finish reason 与 usage 映射逻辑。 crates/adapter-llm/src/anthropic/stream.rs - Why: Anthropic SSE 解析分支最多、最容易演化,单独模块化后更易验证增量事件和错误映射。 - How: 提取 SSE block 解析、stream error 分类、usage 累加与 stream 相关测试。 crates/application/src/terminal/mod.rs - Why: 旧的“插入技能”中间动作会把 slash 流程人为分叉,不符合新的统一 palette 语义。 - How: 删除 `OpenSkillPalette` 动作及其摘要映射,让技能直接作为真实候选项出现。 crates/application/src/terminal_use_cases.rs - Why: slash 候选源需要与新的底部 palette 保持一致,去掉多余的 skill 面板入口。 - How: 移除内建 “插入技能” 候选,并补充测试断言 `skill` 不再作为中间候选出现。 crates/cli/src/app/coordinator.rs - Why: slash、resume 与输入框此前是多套状态源,导致 palette 与 composer 脱节。 - How: 将 overlay 流程改为 palette 流程,同步 composer 输入、resume 查询与 slash 查询刷新逻辑。 crates/cli/src/app/mod.rs - Why: 主事件循环仍围绕旧 overlay/child pane 设计,无法支撑 Claude 风格的 transcript + palette + footer 交互。 - How: 改为 palette 焦点模型,接管键盘事件、Ctrl+O thinking 展开、输入与 palette 联动、以及新的 transcript enter 语义。 crates/cli/src/command/mod.rs - Why: 命令层命名仍然绑定旧 overlay 语义,不利于新的 palette 状态模型。 - How: 将 `OverlayAction`/`overlay_action` 重命名为 `PaletteAction`/`palette_action`,并适配新的选择类型。 crates/cli/src/render/mod.rs - Why: 旧渲染器仍保留多面板/overlay 布局,不符合目标中的单屏 transcript + 底部 dock 架构。 - How: 重写布局为 transcript、贴边 palette 和四行 footer dock,并接入 transcript 选中滚动与 palette 可见性判断。 crates/cli/src/state/conversation.rs - Why: transcript 语义变化后,会话状态需要暴露更适合轻量文本渲染的派生数据。 - How: 调整会话视图与 transcript cell 更新路径,配合新的极简渲染和选中逻辑。 crates/cli/src/state/interaction.rs - Why: 旧交互层包含 overlay/nav/child pane 等过度泛化状态,已经与当前 TUI 目标不匹配。 - How: 收缩为 `Transcript / Composer / Palette` 三焦点模型,并重建 palette 选择、清理、循环和导航逻辑。 crates/cli/src/state/mod.rs - Why: CLI 根状态需要承接新的 palette、thinking 播放和 footer 驱动逻辑,替换旧 overlay 状态容器。 - How: 引入 `PaletteState`、新的 selection 类型、thinking 驱动接线以及配套的状态操作方法。 crates/cli/src/state/thinking.rs - Why: thinking 默认展示需要与后端原始块解耦,支持脚本化播放而不是直接回显原文。 - How: 新增本地片段池、稳定伪随机播放状态与 presentation 逻辑,供 transcript 渲染层调用。 crates/cli/src/state/transcript_cell.rs - Why: transcript cell 需要为轻量文本渲染提供更清晰的消息种类与展开状态支撑。 - How: 调整 cell 结构和 kind 派生字段,适配 thinking/tool/assistant/user 的新渲染协议。 crates/cli/src/ui/bottom_pane.rs - Why: 旧 bottom pane 模块对应的多区块布局已经退出主渲染路径,继续保留只会制造维护噪音。 - How: 删除废弃 bottom pane UI 实现。 crates/cli/src/ui/cells.rs - Why: 旧消息卡片和标签式渲染太厚重,和 Claude Code 风格的纯文本语法相冲突。 - How: 重写 transcript cell 渲染,将用户、助手、thinking、tool 和错误统一压成更轻的单列文本样式。 crates/cli/src/ui/footer.rs - Why: 需要独立的底部 dock 组件承接输入行、分隔线和状态行,而不是沿用旧 composer 面板。 - How: 新增 footer 渲染,输出 placeholder、输入内容与状态提示的四行 dock 文本。 crates/cli/src/ui/mod.rs - Why: UI 模块出口仍然暴露旧 overlay/bottom pane 思路,不利于围绕新语义收口。 - How: 改为导出 transcript/footer/palette/theme/cells 所需接口,并清理旧模块接线。 crates/cli/src/ui/overlay.rs - Why: 通用 overlay 方案已经被底部 palette 替代,继续保留会误导后续维护方向。 - How: 删除废弃 overlay UI 实现。 crates/cli/src/ui/palette.rs - Why: slash 和 resume 需要共享同一种无边框、单行候选的底部列表组件。 - How: 新增 palette 渲染、可见窗口滚动和单行截断逻辑,统一展示 commands、skills 与会话候选。 crates/cli/src/ui/theme.rs - Why: 新界面需要更接近 Claude Code 的极简深色主题和更窄的文本语义样式集。 - How: 重定义主题色板、背景/文本/强调色以及 `WrappedLineStyle` 到 `Style` 的映射,移除旧的垂直分隔语义。 crates/cli/src/ui/transcript.rs - Why: transcript 需要成为真正的主视图,承接空态、banner、thinking 播放与选中行范围计算。 - How: 新增 transcript 渲染输出结构,集中生成空态文案、banner 文本和 selected line range。
crates/cli/REVIEW.md - Why: 记录第一轮 CLI 复审已完成修复后的结论,给后续维护一个明确基线。 - How: 新增复审文档,总结已修复问题并注明实际执行过的 fmt 与测试验证。 crates/cli/REVIEW2.md - Why: 补充第二轮视觉、一致性、性能与最佳实践审查,沉淀剩余改进点。 - How: 新增审查报告,逐项列出观察、风险、建议和优先级。 crates/cli/src/app/coordinator.rs - Why: 异步动作派发和 composer 输入读取路径重复,维护成本偏高。 - How: 抽出 dispatch_async 统一发送 Action,并改为通过 ComposerState 访问当前输入。 crates/cli/src/app/mod.rs - Why: 终端恢复、重绘触发、键鼠输入和 bootstrap 刷新逻辑此前分散且容易遗漏边界。 - How: 引入 RAII 终端恢复守卫、可停止 tick 句柄、按 dirty frame 重绘,补齐鼠标和更多键盘导航,并收敛 bootstrap refresh 与 palette 查询逻辑。 crates/cli/src/command/mod.rs - Why: resume/slash 查询过滤逻辑重复,输入分类还依赖额外借用。 - How: 让 classify_input 直接接收 String,并抽出 fuzzy_contains 复用于 slash 与 session 过滤。 crates/cli/src/launcher/mod.rs - Why: Windows PATHEXT 每次探测都重复解析,存在不必要开销。 - How: 用 OnceLock 缓存可执行扩展名列表,只在首次访问时解析环境变量。 crates/cli/src/render/mod.rs - Why: transcript、footer、palette 每帧现算且布局语义混乱,不利于稳定滚动和光标定位。 - How: 引入统一 cache refresh 流程,显式定义 footer 高度,使用缓存渲染 transcript/footer/palette,并在 footer 中设置 composer 光标位置。 crates/cli/src/state/conversation.rs - Why: transcript block patch/complete 每次线性查找并双写 cell,流式更新路径偏重。 - How: 用 transcript_index 按 block_id 建索引,改为按需投影 TranscriptCell,并在缺失 block 时输出 debug 提示。 crates/cli/src/state/interaction.rs - Why: composer 只能尾部编辑,滚动与选中耦合,焦点切换 backward 分支也不对称。 - How: 为 ComposerState 增加 cursor、插入/删除/移动能力,补充按量滚动与 selection_drives_scroll,并修正 backward focus 与相关测试。 crates/cli/src/state/mod.rs - Why: 状态层没有集中驱动 dirty 区域,transcript cell 仍依赖缓存副本,thinking 动画条件也不够清晰。 - How: 将 WrappedLine 类型迁到 render state,所有输入/滚动/焦点操作都联动 render dirty 标记,改为按需投影 transcript cells,并显式判断 synthetic thinking 播放条件。 crates/cli/src/state/render.rs - Why: 原有 render state 只有 transcript cache,无法细粒度控制 footer、palette 与整帧刷新。 - How: 新增 footer/palette cache、dirty regions、frame_dirty 及对应更新/失效接口,并扩展 WrappedLineStyle 以承载新 UI 语义。 crates/cli/src/state/shell.rs - Why: 默认状态直接探测终端能力会让纯状态构造带入环境副作用。 - How: 将默认 capabilities 收敛为稳定的 ASCII/无色静态值,避免测试和初始化时隐式依赖宿主终端。 crates/cli/src/state/thinking.rs - Why: thinking 展示文案单一,摘要/提示信息不够结构化。 - How: 拆分 verb、summary、hint、preview 字段,引入动词池,并按 streaming/complete 状态生成更清晰的提示文案。 crates/cli/src/state/transcript_cell.rs - Why: 用户可见的错误码、system note 和 handoff kind 仍直接使用 Debug 文本,并存在多余 clone。 - How: 改为通过序列化提取 wire name 作为稳定展示值,同时移除不必要 clone。 crates/cli/src/ui/cells.rs - Why: cell 渲染对 Unicode 宽度、markdown 结构、thinking/tool 展示和 ascii fallback 处理都不够统一。 - How: 重写消息、thinking、tool 和 secondary 渲染路径,统一通过 theme glyph 取标记,新增 markdown/list/table/preformatted 包装逻辑与 synthetic thinking 行生成,并补充相关测试。 crates/cli/src/ui/footer.rs - Why: footer 只展示两行,既看不到完整状态层次,也无法正确表达输入光标位置。 - How: 重构为 status/input/hint 三行输出,返回 cursor_col,按焦点与 palette 状态切换提示,并基于显示宽度裁切当前输入视口。 crates/cli/src/ui/hero.rs - Why: 空 transcript 缺少结构化欢迎区,工作区、phase 和最近会话信息分散。 - How: 新增 hero card,支持横向/紧凑两种布局,汇总版本、会话、目录、phase、快捷键与最近活动。 crates/cli/src/ui/mod.rs - Why: UI 模块需要对外暴露新的 hero、text 与 footer 输出能力,同时避免重复构造 theme。 - How: 导出新模块与类型,并让 line_to_ratatui 直接复用外部传入的主题对象。 crates/cli/src/ui/palette.rs - Why: slash/resume palette 渲染基本重复,条目过多时缺少统一窗口控制和宽度裁切。 - How: 抽出通用 render_palette_items,限制可见条目数,统一选中态样式并用显示宽度裁切标题与元信息。 crates/cli/src/ui/text.rs - Why: 多处需要按终端显示宽度截断文本,不能继续用按字符数截断。 - How: 新增 truncate_to_width,基于 unicode-width 处理 CJK/emoji 宽度并保留省略号。 crates/cli/src/ui/theme.rs - Why: 新的 hero/footer/palette/cell 语义需要更细的样式映射,旧 palette surface 也与新布局不匹配。 - How: 扩展主题颜色与 WrappedLineStyle 映射,新增 selection/footer key/hero 等样式,并让 menu 使用统一背景。 crates/cli/src/ui/transcript.rs - Why: transcript 入口仍依赖旧 transcript_cells 缓存,空状态表现也不够完整。 - How: 改为消费按需投影的 transcript cells,统一接入 hero 区和 synthetic thinking 渲染,并保留选中行范围给滚动逻辑使用。
|
@codex review it |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5c0ad3d74c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
♻️ refactor(mod): 更新 selected_transcript_cell 方法以使用 project_transcript_cell ♻️ refactor(cells): 重构 render_message 函数以简化行前缀处理 ♻️ refactor(hero): 提取重复代码为 push_two_col_block 函数,优化卡片布局 ♻️ feat(event): 添加 generate_turn_id 函数以生成全局唯一的 turn ID ♻️ refactor(submit): 使用 generate_turn_id 函数简化 turn ID 生成逻辑 ♻️ chore(deny): 更新 deny.toml,添加新的依赖项以增强包管理
♻️ refactor(ui): 修改可见窗口函数参数类型,提升类型安全 ♻️ test(Chat): 增加 ToolCallBlock 组件的错误处理测试用例 ♻️ feat(Chat): 添加长字符串摘要功能,优化 JSON 视图展示 ♻️ test(Chat): 新增 useNestedScrollContainment 的单元测试 ♻️ feat(Chat): 实现嵌套滚动容器的事件处理逻辑
crates/core/src/tool_result_persist.rs - Why: 让大工具结果的持久化结果从脆弱的文本约定升级为稳定的结构化契约,避免后续链路继续解析文案。 - How: 引入 PersistedToolOutput/PersistedToolResult,输出绝对路径短引用,保留 preview metadata,并补充新 wrapper 解析测试。 crates/core/src/lib.rs - Why: 让运行时、工具层和前端适配层都能复用新的持久化类型与 helper。 - How: 重新导出 PersistedToolOutput、PersistedToolResult 和 persisted_output_absolute_path。 crates/core/src/event/types.rs - Why: durable event 需要携带完整的 persisted metadata,而不是只带相对路径字符串。 - How: 将 ToolResultReferenceApplied 的 persisted_relative_path 替换为 persisted_output。 crates/core/src/event/translate.rs - Why: runtime 聚合预算替换后的结果也要把 persisted metadata 投影给会话查询和前端。 - How: 将 ToolResultReferenceApplied 翻译为带 persistedOutput metadata 的 synthetic ToolCallResult。 crates/core/src/projection/agent_state.rs - Why: 状态投影测试需要跟上新的 durable payload 和 wrapper 文案。 - How: 用 persisted_output 夹具替换旧字段,并把断言更新到 ~/.astrcode 路径风格。 crates/session-runtime/src/turn/events.rs - Why: 事件构造函数需要和新的 ToolResultReferenceApplied 载荷保持一致。 - How: tool_result_reference_applied_event 改为接收 PersistedToolOutput。 crates/session-runtime/src/turn/tool_result_budget.rs - Why: 聚合预算替换要和工具侧落盘共用同一份 persisted contract,避免再解析旧 wrapper 文本。 - How: 记录 PersistedToolOutput、直接消费 persist_tool_result 返回值,并更新 durable replay 测试。 crates/session-runtime/src/context_window/compaction.rs - Why: 压缩总结 persisted tool output 时不该继续依赖旧的字符串格式。 - How: 改用 persisted_output_absolute_path 提取权威路径。 crates/session-runtime/src/query/conversation.rs - Why: synthetic persisted update 不应把已有工具耗时错误覆盖为 0。 - How: 在替换 duration 时跳过会抹掉已有耗时的 0ms 更新。 crates/adapter-tools/src/builtin_tools/fs_common.rs - Why: readFile 需要识别 session tool-results 的绝对路径,并统一挂载 persisted metadata。 - How: 新增 ResolvedReadTarget/resolve_read_target、绝对路径解析分支和 merge_persisted_tool_output_metadata helper。 crates/adapter-tools/src/builtin_tools/read_file.rs - Why: 已持久化工具结果应该分页读取而不是再次塞回上下文。 - How: 新增 charOffset 字符分页分支、persistedRead metadata、参数校验和覆盖专用读取语义的测试。 crates/adapter-tools/src/builtin_tools/grep.rs - Why: grep 的大结果落盘后需要让后续 readFile 直接按权威路径继续读取。 - How: 输出改用 PersistedToolResult,metadata 挂 persistedOutput,并把回归测试切到 absolutePath + charOffset 流程。 crates/adapter-tools/src/builtin_tools/find_files.rs - Why: findFiles 也要遵守统一的 persisted 输出契约。 - How: 使用 final_output.output 返回正文,并在 metadata 中合并 persistedOutput。 crates/adapter-tools/src/builtin_tools/shell.rs - Why: shell 在超长输出和超时场景下也需要保留终端展示信息并复用同一持久化契约。 - How: 重组 metadata map,统一写入 persistedOutput,并改为消费 PersistedToolResult.output。 crates/adapter-mcp/src/bridge/resource_tool.rs - Why: MCP 资源桥接层需要兼容 maybe_persist_tool_result 的新返回类型。 - How: 读取 rendered.output 作为最终文本字段。 crates/adapter-prompt/src/contributors/capability_prompt.rs - Why: 模型提示需要明确大工具结果的正确消费方式。 - How: 在 tool summary 中补充 persisted reference + readFile chunk 的工作流说明并更新测试。 frontend/src/lib/toolDisplay.ts - Why: 前端需要机器可读地识别 persisted tool result,而不是依赖原始 wrapper 文本。 - How: 新增 PersistedToolOutputMetadata/extractPersistedToolOutput,并在 metadata summary 中补 persisted pills。 frontend/src/components/Chat/ToolCallBlock.tsx - Why: persisted tool result 不应该被当作普通文本块展示。 - How: 根据 persistedOutput 渲染专用卡片,展示绝对路径、相对路径、大小、preview 和建议的 readFile 命令。 frontend/src/lib/toolDisplay.test.ts - Why: 新增的 persisted metadata 提取逻辑需要回归保护。 - How: 补充 persistedOutput 识别和 pill 摘要测试。 frontend/src/components/Chat/ToolCallBlock.test.tsx - Why: UI 需要证明 persisted 结果优先走卡片展示而不是原始 wrapper。 - How: 增加 persisted result card 渲染测试,并把示例路径统一成 ~/.astrcode 风格。
- Introduced `HistoryLine` struct to manage wrapped lines with rewrap policies. - Updated `line_to_ratatui` to handle styled spans for better text rendering. - Added functions for materializing wrapped lines and history lines based on width and rewrap policies. - Refactored `render_browser_overlay` to utilize new materialization functions for rendering lines. - Improved palette handling by simplifying wrapped line creation. - Expanded theme capabilities to include span styles for enhanced text formatting. - Added architecture diagram to documentation for better understanding of system structure and data flow.
♻️ refactor(wrap): 精简文本包装逻辑,移除不必要的内容类型分类
- Renamed mailbox module to input_queue and updated all references accordingly. - Adjusted session state to manage input queue projections instead of mailbox projections. - Updated event handling to append input queue events and removed mailbox-related logic. - Modified tests and documentation to reflect the changes from mailbox to input queue.
.gitignore
- Why: 新增 worktree 目录忽略
- How: 添加 `.worktrees/` 到 gitignore
crates/session-runtime/src/turn/fork.rs (新增)
- Why: 核心会话 fork 逻辑——从已有会话的稳定前缀创建新会话
- How: 实现 ForkPoint(Latest/TurnEnd/StorageSeq) 三种分叉点解析,校验目标前缀是已完成的稳定前缀,复制事件到新会话
crates/session-runtime/src/turn/branch.rs
- Why: 提取通用 fork 逻辑供 fork 模块复用
- How: 抽取 `fork_events_up_to()` 方法,原 `branch_session()` 改为调用它
crates/session-runtime/src/lib.rs
- Why: 导出新的 fork 公共类型
- How: 重导出 ForkPoint、ForkResult
crates/session-runtime/src/context_window/compaction.rs
- Why: 防止 compact 摘要携带过时的路由标识符导致后续 agent 路由错误
- How: 新增 `sanitize_compact_summary()` 在摘要生成时替换 agentId/subRunId/sessionId 为占位符,注入 Compact Boundary 提示;更新 `strip_child_agent_reference_hint` 和 `normalize_compaction_tool_content`
crates/session-runtime/src/context_window/templates/compact/base.md
- Why: 指导 LLM 不在摘要中保留历史路由 ID
- How: 添加压缩规则和指令说明
crates/session-runtime/src/turn/compaction_cycle.rs, manual_compact.rs
- Why: compact 上下文需要会话状态和当前 agent ID
- How: 传递 session_state 和 current_agent_id 参数
crates/application/src/ports/app_session.rs, session_use_cases.rs
- Why: 应用层暴露 fork 能力
- How: 新增 fork_session 用例和端口方法
crates/protocol/src/http/session.rs, mod.rs
- Why: 定义 fork 请求协议
- How: 新增 ForkSessionRequest DTO (turnId/storageSeq 互斥)
crates/server/src/http/routes/
- Why: 暴露 fork HTTP 端点
- How: 新增 POST /api/sessions/{id}/fork 路由和 handler
crates/adapter-tools/src/builtin_tools/shell.rs
- Why: 验证 shell 大输出持久化后可被 ReadFile 读取
- How: 新增集成测试
crates/session-runtime/src/turn/test_support.rs
- Why: 支持 fork/branch 测试所需的辅助事件构造
- How: 新增 root_assistant_final_event、root_turn_done_event 等 helper
crates/server/src/tests/session_contract_tests.rs
- Why: 验证 fork API 契约正确性
- How: 新增 5 个契约测试:默认 fork、指定 turnId、拒绝未完成 turn、互斥参数校验、404
frontend/src/lib/api/sessions.ts, sessions.test.ts
- Why: 前端调用 fork API
- How: 新增 forkSession() 函数及测试
frontend/src/lib/sessionFork.ts, sessionFork.test.ts
- Why: 判断消息是否可作为 fork 点的纯逻辑
- How: resolveForkTurnIdFromMessage() 排除子 agent 通知和活跃 turn
frontend/src/lib/api/conversation.ts, conversation.test.ts
- Why: compact 消息的 trigger 需要优先从 block 自身的 compactMeta 读取
- How: 解析 trigger 时回退到 control.lastCompactMeta
frontend/src/components/Chat/MessageList.tsx
- Why: 用户可通过右键菜单从任意消息处 fork 会话
- How: ForkableRow 组件包装消息行,右键显示"从此处 fork"上下文菜单
frontend/src/App.tsx, hooks/useAgent.ts, ChatScreenContext.tsx, ToolCallBlock.test.tsx
- Why: 贯通 fork 功能的前端调用链
- How: 传递 forkSession、onForkFromTurn 到各层
docs/ideas/notes.md
- Why: 更新想法笔记
- How: 补充多 agent 共享任务列表条目
openspec/changes/session-fork/ (新增)
- Why: fork 功能的 OpenSpec 设计文档
- How: 包含 proposal、design、spec、tasks
openspec/changes/collaboration-mode-system/ (新增)
- Why: 协作模式系统的 OpenSpec 设计文档
- How: 包含完整的 proposal、design、12 个子 spec 和 tasks
… mode features - Deleted specifications for artifact prompt injection, artifact renderer, artifact store, artifact types, builtin modes, mode catalog, mode compile, mode prompt, mode spec, mode switch command, mode switch tool, mode transition, mode truth, and tasks. - Introduced requirements for collaboration modes including Plan, Execute, and Review. - Implemented session state management for active artifacts and current collaboration mode. - Established a unified mode transition mechanism with entry policy checks and confirmation requirements. - Added support for switching modes via commands and tools, ensuring user control over transitions. - Integrated artifact management and rendering processes into the collaboration workflow. - Enhanced prompt generation to reflect current modes and available tools dynamically.
- Introduced new specifications for agent delegation surface, agent tool governance, capability router assembly, delegation policy surface, execution limits control, governance surface assembly, policy engine integration, and prompt facts governance linkage. - Established requirements ensuring all governance inputs are derived from a unified governance envelope, eliminating redundant assembly paths and ensuring consistency across different execution entry points. - Enhanced collaboration audit facts to include governance context, ensuring traceability and alignment with governance policies. - Cleaned up existing code to ensure that all governance-related parameters are sourced from the governance envelope, improving maintainability and clarity. - Added tasks for further cleanup and validation of the governance assembly process, ensuring adherence to architectural principles and project guidelines.
core/mode - Why: 建立治理模式的领域模型基础,支持声明式能力选择、动作策略和子代理策略 - How: 新增 ModeId、GovernanceModeSpec、CapabilitySelector、ActionPolicies、ResolvedTurnEnvelope 等核心类型,内置 code/plan/review 三种模式 application/governance_surface - Why: 将运行时治理决策(工具白名单、审批策略、协作指导 prompt)统一到一个装配层 - How: 新增 GovernanceSurfaceAssembler,按 session/root/child 场景编译治理面,生成 ResolvedTurnEnvelope 和 prompt declarations application/mode - Why: 需要统一的 mode 注册、编译和校验能力,支持内置模式和插件扩展模式 - How: 新增 ModeCatalog(builtin + plugin 模式注册)、compile_mode_envelope(能力解析→工具白名单→策略编译)、validate_mode_transition(合法转换校验) application/agent/context - Why: agent/mod.rs 职责过重,协作事实记录和 agent 上下文构建应独立 - How: 提取 CollaborationFactRecord 和 agent 上下文构建逻辑到 context.rs,routing.rs 新增治理面感知的子代理分发 application/terminal_queries - Why: terminal_use_cases.rs 过于庞大且混杂查询与用例逻辑 - How: 拆分为 cursor/resume/snapshot/summary 四个查询模块,删除 terminal_use_cases.rs application/lib.rs - Why: App 需要持有 governance_surface 和 mode_catalog 以服务各用例 - How: App 新增两个字段及访问器,清理 config 批量 re-export,session_use_cases 接入治理面编译和 mode 切换用例 session-runtime - Why: session 层需要持久化 mode 切换事件并提供 mode 状态查询 - How: 新增 switch_mode/session_mode_state,submit 使用 ResolvedTurnEnvelope 替代原始 runtime 透传,新增 ModeChanged 存储事件 core/event - Why: ModeChanged 需要纳入事件流以驱动 phase tracker 和 projection - How: 新增 StorageEventPayload::ModeChanged,phase/translate/projection 统一处理 core/projection - Why: AgentState 需要追踪当前 mode 以支持状态投影 - How: AgentState 新增 mode_id 字段,projector 处理 ModeChanged 事件 protocol - Why: 前端和 CLI 需要 mode 列表、状态查询和切换的 HTTP 接口 - How: 新增 ModeSummaryDto/SessionModeStateDto/SwitchModeRequest,插件握手协议扩展 modes 字段 server - Why: 暴露 mode 相关 HTTP 端点,bootstrap 组装 governance_surface 和 mode_catalog - How: 新增 /api/modes、/api/sessions/:id/mode 路由,runtime bootstrap 注入 assembler client - Why: CLI 需要通过 HTTP 调用 mode 相关 API - How: 新增 list_modes/get_session_mode/switch_mode 方法 cli - Why: 终端用户需要通过命令切换 session 治理模式 - How: 新增 Command::Mode 和 Command::ModeList,coordinator 处理 mode 切换交互 plugin - Why: 插件应能声明自定义治理模式以扩展系统能力 - How: InitializeResultData 新增 modes 字段,invoker 新增 declared_modes(),peer 握手传递 modes adapter-prompt/workflow_examples - Why: 协作指导 prompt 不再硬编码,改由治理面装配层注入 - How: 移除 child-collaboration-guidance 硬编码块,更新测试 adapter-tools/collab_result_mapping - Why: 简化 advisory projection 逻辑 - How: 用 Option::as_ref()? 替代显式 None 检查 observability/collector - Why: 协作事实需要携带治理版本和模式 ID - How: AgentCollaborationFact 新增 governance_revision 和 mode_id 字段,测试同步更新 test_support - Why: application 层测试需要轻量级 stub 而非依赖真实 session-runtime - How: 新增 StubSessionPort 实现 AppSessionPort + AgentSessionPort openspec - Why: 同步任务状态 - How: 更新 collaboration-mode-system 和 governance-surface-cleanup 任务清单
crates/core/src/policy/engine.rs - 移除从未消费的 ContextStrategy/ContextDecisionInput 类型和 decide_context_strategy trait 方法 crates/core/src/mode/mod.rs - 从 ActionPolicies 中移除 context_strategy 字段 crates/application/src/mode/catalog.rs - 移除 Plan/Review mode 对已删 context_strategy 的引用 crates/application/src/**/*.rs - 为 governance_surface、mode、agent、terminal_queries、ports、terminal、execution 等子域补充模块级文档 - 补充关键 inline 注释(limits 覆盖语义、工具白名单优先级、router 复用条件) crates/session-runtime/src/context_window/* - 在 auto_compact 和 settings 中记录设计决策:未来扩展应在显式参数上做,不恢复粗粒度策略枚举
crates/adapter-tools/src/builtin_tools/upsert_session_plan.rs - 新增 upsertSessionPlan 工具,作为 plan mode 唯一受限写入口 crates/application/src/session_plan.rs - 新增计划状态模型(Draft/AwaitingApproval/Approved/Superseded)与完整生命周期管理 - 实现中英文审批短语识别,检测到批准后自动切回 code mode - 支持计划 prompt 上下文注入(facts + reentry/exit/template 声明) crates/application/src/mode/builtin_prompts.rs + markdown 资源 - 将 mode prompt 从硬编码字符串提取为独立模块与 markdown 资源文件 crates/application/src/session_use_cases.rs - 集成审批流程:awaiting_approval 时检测用户批准短语,自动标记通过并切换模式 - fork session 时复制计划工件 crates/application/src/terminal/, crates/protocol/src/http/ - 新增 ActivePlanFacts / ConversationActivePlanDto,向前端暴露活跃计划状态 scripts/tauri-frontend.js - 优化 sidecar 拷贝:字节比对相同则跳过,减少开发时冗余 IO
crates/core/src/session_plan.rs
- 新增 session plan 领域模型(SessionPlanState/Status)和确定性 FNV-1a digest,
替代原先散落在 adapter-tools 和 application 的重复定义
crates/adapter-tools/src/builtin_tools/{enter,exit}_plan_mode.rs, mode_transition.rs
- 新增 enterPlanMode/exitPlanMode 工具,让模型通过工具调用显式切换 plan/code mode,
exitPlanMode 强制 plan 结构校验 + final-review 双重门控
crates/adapter-tools/src/builtin_tools/fs_common.rs, write_file.rs, edit_file.rs, apply_patch.rs
- 通用文件写工具拦截 canonical plan 目录的直写,强制走 upsertSessionPlan
crates/adapter-tools/src/builtin_tools/upsert_session_plan.rs, session_plan.rs
- 重构为共享 session_plan 辅助模块,简化参数(移除 slug/topic),优先复用已有 slug,
新增 legacy digest 兼容迁移
crates/application/src/session_plan.rs, session_use_cases.rs
- 审批时自动归档 plan snapshot 到 plan-archives/,基于 content digest 去重,
支持 legacy digest 无缝迁移
crates/core/src/compact_summary.rs, session-runtime/compaction, paths.rs
- compact 摘要注入旧 session event log 路径提示,解决压缩后历史丢失问题
crates/protocol/, crates/server/terminal_projection.rs, crates/cli/state/
- 新增 Plan block 类型投影到前端,control state 增加 currentModeId 和 plan slug,
CLI 将 Plan block 映射为 transcript cell
crates/application/src/terminal/, terminal_queries/resume.rs, summary.rs
- Terminal 层 active_plan 改为 PlanReferenceFacts(含 slug),
新增 session_plan_control_summary 聚合查询
crates/kernel/, session-runtime/turn/tool_cycle.rs
- CapabilityContext/ToolContext 透传 current_mode_id 到工具层
frontend/
- 新增 PlanMessage/PlanSurface 组件、plan block 渲染、API 类型与归档查询接口
…n 增强 core, adapter-llm - 将 FinishReason/LlmUsage/ModelLimits/LlmProvider trait 等重复类型统一收归 core::ports - 删除 adapter-llm/core_port.rs 与 adapter-storage/core_port.rs 桥接层 - adapter-llm 改为 re-export core 类型,消除双向转换开销 - 新增 max_output_tokens_override 支持请求级输出 token 上限覆盖 application - 引入 AppAgentPromptSubmission 替代直接依赖 session-runtime::AgentPromptSubmission - 拆分 routing.rs 为 child_send/parent_delivery/collaboration_flow 子模块 - 治理面与端口统一使用应用层提交载荷 session-runtime - 拆分 compaction.rs 为 protocol/sanitize/xml_parsing/tests 子模块 - 拆分 conversation.rs 为 facts/plan_projection/projection_support/tests 子模块 - 新增 keep_recent_user_messages、compact_max_output_tokens 配置 - compact 后注入 RecentUserContextDigest/RecentUserContext 保留用户上下文 adapter-prompt - 新增 ResponseStyleContributor 提供输出风格指导 - 更新 identity 默认文案 docs - 移除 ASTRCODE_EXPLORATION_REPORT 中过时章节,删除 CODE_REVIEW_ISSUES.md - 新增 openspec async-shell-terminal-sessions 变更提案
### 执行期 task 快照(taskWrite)
crates/core/src/execution_task.rs
- 新增执行期 task 领域模型(TaskSnapshot、ExecutionTaskItem、ExecutionTaskStatus)
crates/adapter-tools/src/builtin_tools/task_write.rs
- 新增 taskWrite 工具:维护当前 owner 的执行工作清单,支持 pending/in_progress/completed 三态
crates/session-runtime/src/state/tasks.rs
- 从事件流 replay task 快照,按 owner 隔离并增量维护 active_tasks 缓存
crates/session-runtime/src/turn/request.rs
- 将活跃 task 快照注入 system prompt(live_task_snapshot_declaration),仅注入 in_progress 与 pending
crates/application/src/terminal/mod.rs, terminal_queries/resume.rs
- 新增 TaskItemFacts 类型,从 session-runtime 读取 root owner 快照写入控制状态
crates/protocol/src/http/conversation/v1.rs
- 新增 ConversationTaskItemDto/ConversationTaskStatusDto,control state 携带 activeTasks
crates/server/src/http/terminal_projection.rs, routes/conversation.rs
- 服务端 DTO 映射与 SSE control state delta 推送
frontend/src/components/Chat/TaskPanel.tsx, index.tsx, types.ts, lib/api/conversation.ts
- 前端 TaskPanel 组件、类型定义、activeTasks 解析与 hydration
### 结果构造器重构
crates/core/src/action.rs, registry/router.rs
- 用 from_common 一步构造替代 with_common 二段式覆盖,消除 placeholder 字段
crates/kernel/src/registry/tool.rs, crates/plugin/src/invoker.rs
- 调用方迁移到 from_common
crates/adapter-tools/src/agent_tools/{result_mapping,collab_result_mapping}.rs
- 子运行与协作结果映射迁移到 from_common
### Prompt 缓存提示
crates/core/src/ports.rs
- 新增 PromptCacheHints、PromptLayerFingerprints,LlmRequest 携带 cache hints
crates/adapter-prompt/src/layered_builder.rs, core_port.rs
- 分层构建器收集 layer fingerprint 与 unchanged_layers,设置 cache_boundary
crates/core/src/event/types.rs, crates/session-runtime/src/turn/events.rs
- PromptMetricsPayload 携带 prompt_cache_unchanged_layers
### 修复
crates/adapter-llm/src/anthropic/dto.rs
- Thinking block 的 cache_control 误判为不可操作,统一四类 block 的 set_cache_control_if_allowed
crates/adapter-llm/src/anthropic/stream.rs
- flush_sse_buffer 仅处理单块导致尾部 block 丢失,改为循环处理所有完整块
frontend/src/App.tsx
- mode 切换后右上角 badge 被旧流式快照短暂覆盖,优先使用本地 activeModeId
crates/core/src/ports.rs
- 移除 RecoveredSessionState/SessionRecoveryCheckpoint 上不可满足的 PartialEq derive
### 文档与测试
crates/core/src/lib.rs
- 更新模块文档,按功能分类列出所有主要模块
…point 模块,重构 session state 构建
crates/adapter-storage/src/session/batch_appender.rs
- 从 repository.rs 提取批量事件写入逻辑,50ms drain window 合并高频事件减少 fsync 开销
crates/adapter-storage/src/session/checkpoint.rs
- 从 repository.rs 提取 checkpoint 持久化与恢复逻辑(两阶段提交:snapshot + log rotation + marker)
crates/adapter-storage/src/session/repository.rs
- 新增 batch append 与 checkpoint recovery 集成测试
crates/session-runtime/src/state/mod.rs
- 提取 SessionDerivedState 结构体,将 4 个派生状态字段打包传参,简化 new/from_parts 签名
crates/session-runtime/src/turn/interrupt.rs, submit.rs
- checkpoint_if_compacted 导入路径从 crate 级迁移到 state::,TurnFinalizeContext 携带 event_store
crates/adapter-llm/src/openai.rs
- build_request 8 参数列表重构为 OpenAiBuildRequestInput 结构体(消除位置参数混淆)
crates/adapter-prompt/src/layered_builder.rs
- CacheLookupResult::Hit 改用 Box<PromptBuildOutput> 减少栈拷贝开销
crates/core/src/lib.rs
- 模块文档链接统一为 [foo][] 风格
docs/特点/{event_log,server,capability_governance,plan_mode}.md
- 新增四篇架构设计文档:Event Log、Server-First、Capability 治理、Plan Mode
…of agent behavior - Add .openspec.yaml to define schema and creation date for the evaluation framework. - Create design document outlining the context, goals, decisions, and risks associated with the evaluation framework. - Implement proposal document detailing the need for a systematic evaluation system to drive framework quality iterations. - Define specifications for agent-tool evaluation, ensuring stable effectiveness scorecards are derived from raw facts. - Establish requirements for failure diagnosis, including a rule-based system to detect known failure patterns and generate structured reports. - Develop evaluation runner specifications, detailing how tasks are executed via server API, including workspace isolation and baseline comparison. - Introduce evaluation task specifications, supporting YAML-defined tasks with multi-dimensional behavior constraints. - Define evaluation trace model to convert StorageEvent JSONL logs into structured turn-level assessment data. - Modify runtime observability pipeline to support evaluation scenarios, ensuring metrics are collected and exported for assessment.
- Updated async-tool-execution spec to clarify background execution requirements and scenarios. - Expanded tasks documentation to include new requirements for background task notifications and terminal session structures. - Introduced a new evaluation framework design, distinguishing control and data paths for task evaluation. - Defined new evaluation trace models and extraction logic for structured evaluation data from JSONL logs. - Implemented requirements for execution task tracking, ensuring task independence from session plans and proper ownership management. - Enhanced terminal chat read model to expose authoritative active-task panel facts directly from the server.
…paction logic - Introduced DEFAULT_COMPACT_TOOL_CONTENT_MAX_CHARS constant in core config. - Updated application config to include compact_tool_content_max_chars. - Modified validation and runtime parameters to accommodate new configuration. - Enhanced compaction logic to respect tool content character limits during processing. - Refactored compaction functions to utilize the new character limit configuration. - Updated tests to verify the new character limit functionality and ensure proper behavior.
一、PR 概述
发布 terminal conversation surface,并统一 server / cli / web 的会话读模型,同时补齐工具流、子会话入口和 prompt cache metrics 的整条链路。
二、背景 / 动机
master缺少完整的 terminal chat surface,conversation surface 在 server / web / cli 之间语义分散;工具调用、子会话入口、prompt metrics 也存在投影和展示不一致。master上无法获得完整的 terminal 工作台体验,工具块和子会话相关行为也不稳定。三、改动内容
改动类型:
四、实现说明
crates/cli/**crates/client/**crates/protocol/src/http/conversation/**crates/protocol/src/http/terminal/**crates/server/src/http/routes/conversation.rscrates/server/src/http/terminal_projection.rscrates/session-runtime/src/query/**crates/session-runtime/src/turn/**frontend/src/lib/api/conversation.tsfrontend/src/lib/subRunView.tsfrontend/src/components/Chat/**五、行为变化(对外影响)
master没有完整 terminal chat surface;工具输出、子会话入口和 prompt metrics 在不同端表现不一致,部分能力会丢失或延后出现。六、测试与验证
自测结果:
测试命令:
七、Checklist
cargo fmt --all -- --checkcargo clippy --all-targets --all-features -- -D warningscargo test --workspace --exclude astrcodenpm run typechecknpm run lintnpm run format:check八、关联 Issue
暂无直接关联 Issue。
Summary by Sourcery
Release a unified terminal conversation surface and align tool, sub-run, and prompt metrics behavior across server, CLI, and web surfaces.
New Features:
Bug Fixes:
Enhancements:
Tests: