kimi-code/apps
liruifengv dad2b87cee
refactor(tui): split kimi-tui God-class into controllers and command modules (#142)
* refactor(tui): extract TasksBrowserController from KimiTUI

将 /tasks 浏览器相关的 16 个方法(~450 行)从 KimiTUI 提取到独立的
TasksBrowserController。KimiTUI 通过 Host 接口传 this 给 controller,
保留 4 个一行委托方法供外部调用点使用。

kimi-tui.ts: 6160 → 5711 行 (-449)

* refactor(tui): extract StreamingUIController from KimiTUI

将 Streaming Flush(15 个方法)和 Live Render Hooks(15 个方法)
共 ~475 行代码从 KimiTUI 提取到 StreamingUIController。这两个区域
之间紧密耦合(flush 方法直接调用 render hooks),合并提取避免循环依赖。

同时迁移了 5 个实例变量:flushTimer, lastFlushAt, pendingAssistantFlush,
pendingThinkingFlush, pendingToolCallFlushIds。

kimi-tui.ts: 5711 → 5268 行 (-443)

* refactor(tui): extract SessionEventHandler from KimiTUI

将 Session Events(39 个方法)和 Background Task Lifecycle(4 个方法)
共 ~960 行代码从 KimiTUI 提取到 SessionEventHandler。包含事件分发、
turn/step 生命周期、thinking/assistant delta 处理、tool call 管理、
compaction 流程、subagent 管理、MCP 状态渲染、background task 事件。

kimi-tui.ts: 5268 → 4316 行 (-952)

* refactor(tui): extract SessionReplayRenderer from KimiTUI

将 Session Replay 的 21 个方法(~410 行)从 KimiTUI 提取到
SessionReplayRenderer。包含会话历史回放水合(snapshot hydration)、
replay record 渲染、thinking/assistant/tool call 回放、skill 激活、
权限变更、审批结果、background task 通知等逻辑。

kimi-tui.ts: 4316 → 3911 行 (-405)

* refactor(tui): extract slash command handlers from KimiTUI

将 Slash Command Handlers 区域(~765 行)从 KimiTUI 提取到两个文件:
- slash-commands.ts (684 行):命令逻辑(plan/yolo/compact/editor/theme/
  model/title/fork/init/login/connect/logout/feedback)
- slash-command-prompts.ts (183 行):UI prompt 函数(platform selection、
  logout provider、feedback input、API key、model selector 等)

prompt 函数拆为独立模块避免 ESM 同模块内部调用 mock 不生效的问题。
测试改为 vi.mock 对应的 prompt 模块。

kimi-tui.ts: 3911 → 3163 行 (-748)

* refactor(tui): extract AuthFlowController from KimiTUI

将 Auth / Model Bootstrap 的 6 个方法(~115 行)从 KimiTUI 提取到
AuthFlowController。包含 refreshAvailableModels、
enterLoginRequiredStartupState、activateModelAfterLogin、
clearActiveSessionAfterLogout、refreshConfigAfterLogin、
refreshConfigAfterLogout。

kimi-tui.ts: 3163 → 3063 行 (-100)

* refactor(tui): clean up dead imports after controller extraction

移除 kimi-tui.ts 和 controller 文件中因代码提取而残留的 55+ 个
无用 import(SDK event types、OAuth 工具函数、catalog 类型等)。

kimi-tui.ts: 3063 → 3005 行 (-58)

* refactor(tui): remove delegate methods and direct controller references

Phase A: 删除 14 个零调用者的纯委托方法
Phase B: 内联 8 个少量调用者委托(调用处直接引用 controller)
Phase C: controller 之间通过 host 上的 controller 引用直接协作,
         不再绕 kimi-tui 中转(SessionEventHandler → tasksBrowserController,
         SlashCommands → authFlow)

kimi-tui.ts: 3005 → 2956 行 (-49)

* refactor(tui): move pickers, config apply, info commands to slash-commands controller

Phase D: 将 pickers(editor/model/theme/permission/settings)、
config apply(applyEditorChoice/applyThemeChoice/applyPermissionChoice/
performModelSwitch/persistModelSelection)、info commands
(showUsage/showStatusReport/showMcpServers + load* helpers)共 ~400 行
从 kimi-tui.ts 搬到 slash-commands controller。

Phase E: handleBuiltInSlashCommand 中所有 case 直接调用 slashCommands.*,
删除全部 13 个 slash command 委托方法。测试改为直接调用 controller 函数。

kimi-tui.ts: 2956 → 2566 行 (-390)

* refactor(tui): final cleanup — remove last delegates and dead imports

删除 finalizeTurn 和 activateModelAfterLogin 委托方法,
slash-commands 直接通过 host.streamingUI / host.authFlow 调用。
清理 15 个因搬运产生的 dead import。

kimi-tui.ts: 2566 → 2545 行 (-21)

* refactor(tui): clean up dead imports and empty import blocks

清理第二轮搬运后残留的 19 个 dead import 和 3 个空 import 块
(api-key-input-dialog、feedback-input-dialog、settings-selector、
feedback constants 等已搬到 slash-commands controller)。

kimi-tui.ts: 2545 → 2517 行 (-28)

* refactor(tui): inline last auth delegate methods

将 refreshAvailableModels 和 enterLoginRequiredStartupState 的
调用方改为直接访问 this.authFlow.*,删除最后两个委托方法。

kimi-tui.ts: 2517 → 2510 行 (-7)

* refactor(tui): move slash command dispatch to slash-commands controller

将 executeSlashCommand(~45 行)和 handleBuiltInSlashCommand(~80 行)
从 kimi-tui.ts 搬到 slash-commands controller。kimi-tui.ts 的
handleUserInput 现在只做空检查、replay guard、历史持久化,
然后调 slashCommands.dispatchInput(this, text)。

kimi-tui.ts: 2510 → 2367 行 (-143)

* refactor(tui): clean up 38 dead imports and 3 dead interfaces

移除因前几轮搬运残留的 import(message-replay、mcp-server-status、
background-*-status、hook-result-format、event-payload utils、
streaming/theme constants 等)和 SessionUsageResult / RuntimeStatusResult /
ManagedUsageResult 接口定义。

kimi-tui.ts: 2367 → 2311 行 (-56)

* refactor(tui): deduplicate combineStartupNotice and isOAuthLoginRequiredError

将 combineStartupNotice(kimi-tui.ts + auth-flow.ts 各一份)和
isOAuthLoginRequiredError 统一到 constant/kimi-tui.ts,两边改为 import。

kimi-tui.ts: 2311 → 2296 行 (-15)

* refactor(tui): move startup utils out of constant/kimi-tui

combineStartupNotice 和 isOAuthLoginRequiredError 是工具函数不是常量,
从 constant/kimi-tui.ts 移到 utils/startup.ts。

* refactor(tui): remove last session event/replay delegate methods

删除 handleEvent、startSessionEventSubscription、
hydrateTranscriptFromReplay 三个委托方法。
kimi-tui 内部和 auth-flow controller 改为直接访问
sessionEventHandler.startSubscription() 和
sessionReplay.hydrateFromReplay()。
测试改为通过 driver.sessionEventHandler 直接调用。

kimi-tui.ts: 2296 → 2278 行 (-18)

* refactor(tui): reduce TUIState fields by removing redundancy and merging pairs

Delete 4 redundant fields (AppState.yolo, AppState.isStreaming,
TUIState.backgroundAgents, TUIState.assistantStreamActive) that were
derivable from existing state. Merge 4 pairs of always-coupled fields
into single objects (streamingBlock, subagentInfo, activitySpinner,
activeDialog). Demote 3 fields only used by KimiTUI itself to private
class fields. Net reduction: AppState 22→20, TUIState 55→48 fields.

* refactor(tui): extract TUIState types and move streaming state into StreamingUIController

Break the type-level circular dependency where controllers imported
TUIState from kimi-tui.ts while kimi-tui.ts imported runtime values
from controllers. Shared types now live in tui-state.ts (TUIState,
createTUIState) and types.ts (KimiTUIOptions, LoginProgressSpinnerHandle,
etc.) so the import graph is strictly unidirectional.

Move 12 streaming-related fields (currentTurnId, currentStep,
assistantDraft, thinkingDraft, streamingBlock, activeThinkingComponent,
activeCompactionBlock, activeToolCalls, streamingToolCallArguments,
pendingToolComponents, pendingAgentGroup, pendingReadGroup) from the
flat TUIState bag into StreamingUIController as instance properties,
along with 3 dispose methods. TUIState shrinks from 40+ to 28 fields.

* refactor(tui): split slash-commands.ts by domain into 4 focused modules

Extract the 1223-line slash-commands.ts into domain-specific files:

- auth-commands.ts (~350 lines): login, logout, connect, OAuth flows
- config-commands.ts (~380 lines): plan, yolo, compact, model/theme/
  editor/permission pickers and apply logic
- info-commands.ts (~185 lines): feedback, usage, status, mcp reports
- session-commands.ts (~105 lines): title, fork, init

slash-commands.ts is now a slim routing hub (~210 lines) that owns
SlashCommandHost, dispatchInput, and the builtin command switch. All
public handlers are re-exported so existing consumers are unaffected.

* refactor(tui): move command handlers from controllers/ to commands/

Relocate the 6 command-related files into the existing commands/
directory where parsing and routing logic already lives:

  controllers/slash-commands.ts       → commands/dispatch.ts
  controllers/slash-command-prompts.ts → commands/prompts.ts
  controllers/auth-commands.ts        → commands/auth.ts
  controllers/config-commands.ts      → commands/config.ts
  controllers/info-commands.ts        → commands/info.ts
  controllers/session-commands.ts     → commands/session.ts

controllers/ now contains only state/lifecycle controllers
(auth-flow, session-event-handler, session-replay, streaming-ui,
tasks-browser). commands/index.ts re-exports all public symbols.

* refactor(tui): move background/render-dedup state into SessionEventHandler

Move 7 fields from TUIState into SessionEventHandler as instance
properties: backgroundAgentMetadata, backgroundTasks,
backgroundTaskTranscriptedTerminal, subagentInfo,
renderedSkillActivationIds, renderedMcpServerStatusKeys,
mcpServerStatusSpinners.

Add resetRuntimeState() to SessionEventHandler that clears all 7
fields in one call. TUIState shrinks from 28 to 21 fields.

TasksBrowserHost.backgroundTasks is now a top-level ReadonlyMap
property instead of being embedded in the state subset, with a
getter on KimiTUI that delegates to sessionEventHandler.

* refactor(tui): encapsulate StreamingUIController internal state behind semantic methods

Make 12 fields private and expose 18 semantic methods instead of letting
SessionEventHandler, SessionReplayRenderer, and KimiTUI directly
manipulate internal maps and counters. Key methods: registerToolCall(),
accumulateToolCallDelta(), completeToolResult(), markStepTruncated(),
appendThinkingDelta(), appendAssistantDelta(), cleanupAfterReplay().

* refactor(tui): extract EditorKeyboardController from KimiTUI

Move editor callback wiring, pending-exit state, clipboard media
handling, and external editor logic into a dedicated controller.
KimiTUI drops from 2070 to 1814 lines.

* refactor(tui): clean up kimi-tui.ts — strip noise comments, reorganize sections

Remove ~70 single-line comments that merely restated the method name.
Condense multi-paragraph inline comments (signal handlers, start()) to
one-liners that capture the WHY. Reorganize sections: merge the one-
method "Layout" section into Lifecycle, rename "Startup Helpers" to
"Autocomplete & Skill Commands", move stray accessors into "State &
Accessors", delete the empty trailing section, relocate input-history
helpers next to each other. 1814 → 1639 lines.

* refactor(tui): route TUIState field mutations through host methods

Controllers may still read host.state freely, but all direct field
assignments now go through setter methods on the host: setStartupReady,
clearQueuedMessages, shiftQueuedMessage, pushTranscriptEntry,
setExternalEditorRunning, setTasksBrowser. This prevents controllers
from silently mutating shared state without KimiTUI's knowledge.

* chore(tui): drop merge analysis docs, add changeset, fix 2 lint errors

- delete docs/refactor-kimi-tui-{analysis,merge-plan}.md (working notes)
- add changeset for the kimi-tui split refactor
- session-event-handler.ts: drop unused `state` destructure in finishCompaction
- editor-keyboard.ts: void-mark fire-and-forget session.cancel() promise

* chore(changeset): simplify wording
2026-05-28 14:14:20 +08:00
..
kimi-code refactor(tui): split kimi-tui God-class into controllers and command modules (#142) 2026-05-28 14:14:20 +08:00
vis refactor(vis): rewrite for new agent-core protocol (#34) 2026-05-26 17:57:49 +08:00