Merge remote-tracking branch 'origin/master' into xtr/trajectory-timeline

# Conflicts:
#	apps/web/tests/code-mode-fixture.snapshot.ts
#	apps/web/tests/navigation-panes.e2e.ts
#	apps/web/tests/snapshots/navigation-panes/details-open.expected.md
#	packages/client/runtime/src/client/index.ts
#	packages/client/runtime/src/client/sessions/fold-adapter.ts
#	packages/client/ui-trajectory/tests/views.spec.tsx
This commit is contained in:
_Kerman
2026-07-28 18:06:04 +08:00
185 changed files with 4826 additions and 966 deletions
@@ -3,6 +3,7 @@
// substructures keep their references (the React.memo premise). callId/approvalId stay plain
// string here (narrow to real brands when convenient).
import type { CommandId } from '@deepseek-ai/dsh-commands/brand'
import type { ContentBlock } from '@deepseek-ai/dsh-llm/types'
import type { TodoItem } from '@deepseek-ai/dsh-session/types'
import type {
@@ -152,6 +153,31 @@ export interface UnknownSurfaceNode {
data: unknown
}
/**
* One slash-command lifecycle folded from the log-only `command/run` /
* `command/done` pair (paired by commandId, mirroring tool call↔result).
* Log-only events never enter the surface fold, so the FoldAdapter indexes
* them separately and merges the nodes into the flow by seq. A window cut
* between the pair soft-falls like tool pairs: a done with no in-window run
* still builds a node (name/args null), and a run with no done renders as
* still executing.
*/
export interface CommandNode {
kind: 'command'
/** Seq of the command/run event; the done event's seq when only the done is in-window. */
seq: number
/** Unix epoch ms of the anchoring event. */
time: number
/** Pairing id minted by the host executor. */
commandId: CommandId
/** Command name (run payload's structured field); null when the run fell outside the window. */
name: string | null
/** Verbatim rawInput after the name, separator whitespace included (run payload); null when the run fell outside the window. */
args: string | null
/** Settlement outcome (done payload); null while the command is still executing. */
outcome: { kind: 'success' | 'error'; text?: string } | null
}
/** Finalized conversation node union (kind discriminates; seq is the React key). */
export type ConversationNode =
| UserMessageNode
@@ -159,6 +185,7 @@ export type ConversationNode =
| SteeringMessageNode
| ContextMessageNode
| ToolResultNode
| CommandNode
| UnknownSurfaceNode
/**
@@ -277,7 +304,4 @@ export interface ConversationSnapshot {
*/
blank: boolean
lastAgentError: string | null
/** Current whole-list `todo/write` projection — the tail page's full-log value, then each live
* write (last write wins); empty = the log holds no plan. */
todos: readonly TodoItem[]
}