kimi-code/apps/vis/web
Kai 42e37eb898
feat(timing): split TTFT into api-server and client portions (#1228)
* feat(timing): split TTFT into api-server and client portions

Time-to-first-token previously lumped in-process request building
(message serialization, param assembly) together with network + server
latency, making it impossible to tell whether a slow turn was the client
or the API server.

Add an `onRequestSent` hook to kosong's GenerateOptions, fired by every
provider immediately before it dispatches the network call. The window
from request start to dispatch is attributed to the client; the window
from dispatch to the first streamed token is attributed to the API
server. The split flows through the step.end / turn.step.completed
events (and therefore wire.jsonl) and is surfaced in three places:

- KIMI_CODE_DEBUG=1: `TTFT: 2.5s (api 2.4s + client 100ms)`
- session log: new `llm response` line with the timing breakdown
- vis: firstToken/api + firstToken/client rows and timeline label

The split is omitted (total only) when a provider does not report the
boundary, preserving backward compatibility.

* feat(timing): split the decode window into server vs client time

Time-to-first-token now reports a client/server split, but the slow part
of a long turn is the decode window (inter-token streaming), which was
still a single opaque number. Profiling long sessions showed decode
throughput halving over a session's lifetime independent of context
size, which the synchronous per-chunk stream pipeline can cause: kosong
awaits the host callback for every streamed part, so a loaded main
thread throttles how fast tokens are pulled off the wire.

Account for this directly in the stream loop: the time awaiting the next
part (server + network) versus the time spent processing each part
in-process (deep copy, host callback, part merge). The split is reported
through onStreamEnd and flows through the step.end / turn.step.completed
events (and wire.jsonl) into the same three surfaces as the TTFT split:

- KIMI_CODE_DEBUG=1: `TPS: 40.0 tok/s (200 tokens in 5.0s; server 4.6s + client 400ms)`
- session log: serverDecodeMs / clientConsumeMs on the `llm response` line
- vis: streamDuration/server + streamDuration/client rows and timeline label

A large, growing client share confirms host-side throttling; a dominant
server share points at the server/connection. The per-chunk accounting is
wrapped in try/finally so it stays correct across `continue` and aborts,
and is omitted when the stream reports nothing.
2026-06-30 19:15:02 +08:00
..
src feat(timing): split TTFT into api-server and client portions (#1228) 2026-06-30 19:15:02 +08:00
test feat(vis): full session debugging — tasks/cron, execution timeline, retries & tool progress (#1210) 2026-06-30 13:40:37 +08:00
index.html Kimi For Coding 2026-05-22 15:54:50 +08:00
package.json feat(vis): full session debugging — tasks/cron, execution timeline, retries & tool progress (#1210) 2026-06-30 13:40:37 +08:00
tsconfig.json feat(web): introduce Kimi web app and daemon gateway (#625) 2026-06-17 20:53:46 +08:00
vite.config.ts feat(vis): faithful wire.jsonl rendering + built-in kimi vis command (#788) 2026-06-16 16:54:14 +08:00
vitest.config.ts feat(vis): full session debugging — tasks/cron, execution timeline, retries & tool progress (#1210) 2026-06-30 13:40:37 +08:00