release: ksadk-web 0.3.2 durable interaction and runtime v2 UI - #9
Merged
Conversation
Add remark-breaks so single newlines in assistant output render as hard breaks instead of collapsing to a space, fixing lost line breaks in streamed/plain-text agent replies. Applied to both the plain and math-enabled markdown renderers. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
整体风格向 wework 看齐,覆盖配色/字体/侧边栏/输入框/消息区/工具渲染/错误展示: - 设计 token: primary 改 teal、surface/text-*/sidebar 独立灰阶对齐 wework 精确值, 字体栈加 PingFang SC/Microsoft YaHei, 基础圆角 0.5rem - 侧边栏: 会话行 h-[30px] rounded-[10px] + sidebar 灰阶, 右侧操作按钮 hover 才显示, 时间 label hover 时让位避免与删除按钮重叠 - 输入框: 双层 26px 圆角(外层 surface 软阴影/内层 background 细边), 底部工具栏左组(附件+model+思考 chip)右组(上下文环+发送钮), model/思考改 wework 自定义下拉 MenuChip(替代原生 select), 附件 badge 改色块+文件名/大小+悬浮圆形删除钮 - 上下文长度: wework 圆环指示器(conic-gradient 进度环,>=85% 转 red,hover 弹 tooltip) - 消息区: user 气泡 bg-muted 右对齐, assistant 居中窄栏平铺, hover 浮出操作行(复制+反馈快捷,opacity 切换) - 工具/审批卡: 审批按钮 rounded-full bg-foreground + ghost 拒绝, 去掉 emerald 绿 - 错误/限流: StatusBanner 内联状态条(限流 amber+倒计时/网络 spinner/失败重试), engine 识别 429 emit rate_limited 事件, 不再白屏 - 流式重连: 记录 lastSeqId, 网络断线改用 resumeRun(afterSeqId) 续订而非从头重跑 - 回到底部圆钮 + 流式思考占位 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- MessageMarkdown 去掉 prose-slate 套件,改 wework 语义 token + 紧凑标题字号 (h1→lg/h2→base/h3→sm),链接 text-primary,表格 border-border,行内 code bg-muted - CodeBlock 加 TextWrap 自动换行切换(仅 markdown 语言,按内容 key 记忆) - 历史消息刷新重建 blocks(buildBlocksFromHistory),不再还原成旧散装渲染 - TextRow 改回 MessageMarkdown,流式时标题/列表/粗体即时渲染(不再等刷新) - 移植 wework parseUnifiedDiff,ToolRow output 智能识别: unified diff → FileChangesCard(文件改动卡 +/− 统计), web_search → WebSearchSourcesChip(来源 chip + hover 列表), 否则回退通用 PayloadBlock。前端识别 tool_output,不动后端事件协议 - 输入框 textarea 对齐 wework(text-text-primary/14px/max-h-112), 发送钮 bg-[#1f1f1f],placeholder 简洁文案 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
When the control-plane sessionId changes (user picks another conversation or creates a new one), the terminal sessions bound to the previous sessionId were left running server-side, leaking pty processes. DELETE them before refreshing for the new sessionId so each conversation owns only its current terminal. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Introduce RuntimeItemReducer (src/core/stream/runtime-items.ts) as the single
canonical store for streaming output. It reduces identity-addressed item
operations into a per-run projection keyed by runId/scopeId/itemId/partId,
replacing the legacy v1 heuristic dedup (lastText / per-agent accumulator /
startswith / suffix overlap / text hash).
Ingress adapters normalize three sources into the same item operations:
- Responses SSE output item ids
- Session events Metadata.RuntimeItem
- Legacy server events (no identity) -> synthesized ${invocationId}:legacy-assistant
assistant_stream_snapshot -> replace, assistant_message -> complete. Nothing
inspects body text to decide identity.
npm test: 153 passed. build:ksadk + build:hosted pass.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Identity-aware runtime item reducer (Task 8). Counterpart of KsADK 0.8.1 canonical RuntimeEvent(schema_version=2). Hosted UI and Studio must ship this version to keep stream/replay output consistent with the Python canonical pipeline. npm test: 153 passed. build:ksadk + build:hosted pass. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Consume agent-kernel/v1 contracts (digest 69771d8d): strict zod decoders for AgentControlReceipt, RuntimeCapabilityMatrix, SessionEventEnvelope and AgentStatusSnapshot with unknown optional fields preserved in extensions; RunEngine control state distinguishes queued/retryable/ unsupported/confirming and reuses idempotency keys on retry; unified Session seq cursor dedupes/orders history and drives SubscribeSessionEvents reconnects; public runtime bundle exports the v1 types. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
gateway 只认 after_seq(app/lifecycle.py resolve_after_seq),web 侧 SubscribeSessionEvents 从 AfterSeq 对齐为 after_seq;类型导出不变。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
One Interaction/v1 client: Responses approvals, AG-UI interrupts, and Interaction/v1 SessionEvents normalize into a single Interaction shape with one submit path (SubmitInteraction, revision CAS + idempotency key, first-wins terminal semantics). Refresh/replay restores pending interactions without duplicating requests; A2UI v0.9.1 is validated with catalog digest and falls back to the JSON schema form or basic controls — never to an automatic approval. Old servers without interaction_v1 keep the 0.3.1 Responses/AG-UI callbacks. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
SubmitInteraction receipts only prove the command entered the durable Inbox; they are not terminal facts. The UI now stays resolving after an accepted/duplicate receipt and only a interaction.resolved/cancelled/ expired SessionEvent (dispatcher or replay) closes a record. Definitive receipt rejections (e.g. first-wins interaction_already_resolved) mark the submit failed with the server error instead of silently reverting; queue_full reverts to pending for retry; replay converges a resolving record when the event stream already carries the terminal fact. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- InteractionHistoryAnchor: expandable read-only resolved snapshot (actor_ref, resolved_at, request_schema top-level key summary) via native details/summary; no editable controls - InteractionStore: terminal merge preserves the requested snapshot fields (title/kind/message/request_schema/presentation) so history anchors render after resolution - App: legacy 0.3.1 fallback callbacks route through refs (they are captured once by useInteractions' useState initializer and previously pinned the first render's engine closures, breaking AG-UI resume) - e2e: agui fixture declares non-resumable RunLifecycle (direct stream); assertions updated to the unified tray/anchor semantics; new specs for multi-pending queueing, tray-never-obscures-composer layout, and resolved snapshot expansion Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
RunAgent on a kernel-backed agent returns an AgentControl receipt (JSON) instead of a Responses SSE stream. Detect the receipt body on the run stream, then subscribe to SubscribeSessionEvents and translate the raw kernel frames (runtime v2 item events, interaction v1 events, terminal control transitions) into legacy SessionEventRecords. The existing dispatcher paths keep building messages, merging recovered runs, and ingesting interactions unchanged; reconnects resume from the last observed kernel seq. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A kernel run pauses as interrupted while an interaction (approval) is pending and resumes after the decision; only completed/failed/cancelled end the subscription. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
interactionFromSessionEvent reads interaction facts from envelope.payload; the flattened kernel frame must be nested there for pending approvals to reach the shared interaction store. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Kernel subscriptions replay the backlog then close; while a run waits on an interaction the engine now resubscribes (advancing seq) instead of giving up, so post-approval output and terminal status still arrive. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The fake-approval canary runtime wedges under frequent concurrent SubscribeSessionEvents polls; 3s keeps live updates snappy without overloading the single-instance canary. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…eb-0.3.2 # Conflicts: # CHANGELOG.md # e2e/agui.spec.mjs # package-lock.json # package.json # src/App.tsx # src/__tests__/chat-message-list-contract.test.ts # src/components/chat/ChatMessageList.tsx # src/components/chat/ConnectedComposer.tsx # src/components/chat/ConnectedMessageList.tsx # src/components/chat/ProcessingBlocksView.tsx # src/core/api/facade.ts # src/core/api/types.ts # src/core/run/dispatcher.ts # src/core/run/engine.ts # src/core/run/types.ts # src/hooks/useSessionLifecycle.ts # src/stores/streaming.ts
# Conflicts: # CHANGELOG.md # src/__tests__/run-engine.test.ts # src/api/client.ts # src/core/run/engine.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Verification
npm test: 238 passednode --test tests/*.test.mjs: 115 passednpm run lint: passednpm run build:all: passednpm pack --dry-run --access public: passednpm audit --omit=dev: 0 vulnerabilitiesnpm run test:e2e:interaction: 12 passednpm run test:e2e:agui: 1 passednpm run test:e2e:reconnect: 3 passedPublication remains through the existing GitHub Release + npm Trusted Publishing workflow.