refactor: remove per-followup result attribution

This commit is contained in:
_Kerman
2026-07-30 16:48:28 +08:00
parent f6db60b52c
commit a6baddaaac
72 changed files with 586 additions and 1059 deletions

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write packages/sdk/sdk-protocol/README.md
README.md: 62b26d4a82d358fa4efcb7ab84036e5f4848057f
README.zh.md: 11677c6119c7da407d95ee38ad9f8f7a552c15de
README.md: 2120e6090fcc5d5f4a543424e9c5647e6009bad6
README.zh.md: 70b046cf1dedbf01031e3e0a4441f522d6153fbc

View File

@@ -15,14 +15,14 @@ The shared wire protocol for the DeepSeek Harness SDK runtime: one newline-delim
| Direction | Method | Types |
|---|---|---|
| client→server | `initialize` | `InitializeParams` → `InitializeResult` |
| client→server | `session/prompt` | `SessionPromptParams` → `SessionPromptResult` (answered only after turn settlement) |
| client→server | `session/prompt` | `SessionPromptParams` → `SessionPromptResult` (durable enqueue receipt) |
| client→server | `shutdown` | no params → `{}` |
| server→client | `session.event` | `SessionEventNotification` (every session in the runtime, unfiltered) |
| server→client | `session.finished` | `SessionFinishedNotification` (one per accepted prompt) |
| server→client | `session.status` | `SessionStatusNotification` (whole-agent `running`/`idle` transition) |
| server→client | `subagent.started` | `SubagentStartedNotification` |
| server→client | `subagent.finished` | `SubagentFinishedNotification` (in-process runs only) |
`HarnessSdkRequestMap` and `HarnessSdkNotificationMap` index these by method name. `InitializeParams.maxTokens` is an optional positive safe integer that caps each conversation-model output for SDK-created agents and their in-process descendants; omission leaves the provider default in control. The notification payload types depend on `SessionEvent` (`dsh-session`), `ContentBlock` (`dsh-llm`), and `SubagentStopReason` (`dsh-subagent`) — the protocol streams full session-log envelopes, so the session vocabulary is part of the wire contract. `serverInfo.name` stays the wire-stable `deepseek-harness-sdk-runtime`.
`HarnessSdkRequestMap` and `HarnessSdkNotificationMap` index these by method name. `SessionPromptResult.messageId` identifies the queued `UserMessage`; it does not identify a later assistant message, turn ending, or prompt result. Clients combine the open-ended `session.event` stream with agent-wide `session.status` according to their own activity ownership. `InitializeParams.maxTokens` is an optional positive safe integer that caps each conversation-model output for SDK-created agents and their in-process descendants; omission leaves the provider default in control. The notification payload types depend on `SessionEvent` (`dsh-session`), `ContentBlock` (`dsh-llm`), and `SubagentStopReason` (`dsh-subagent`) — the protocol streams full session-log envelopes, so the session vocabulary is part of the wire contract. `serverInfo.name` stays the wire-stable `deepseek-harness-sdk-runtime`.
## Model Experience

View File

@@ -15,14 +15,14 @@ DeepSeek Harness SDK 运行时的共享协议格式(wire format):一个按
| 方向 | 方法 | 类型 |
|---|---|---|
| client→server | `initialize` | `InitializeParams` → `InitializeResult` |
| client→server | `session/prompt` | `SessionPromptParams` → `SessionPromptResult`(仅在轮次结算完成后应答) |
| client→server | `session/prompt` | `SessionPromptParams` → `SessionPromptResult`(持久入队回执) |
| client→server | `shutdown` | 无参数 → `{}` |
| server→client | `session.event` | `SessionEventNotification`(运行时内每个会话,不过滤) |
| server→client | `session.finished` | `SessionFinishedNotification`(每个获准的提示词请求一条) |
| server→client | `session.status` | `SessionStatusNotification`(整个 agent(智能体)的 `running`/`idle` 转换) |
| server→client | `subagent.started` | `SubagentStartedNotification` |
| server→client | `subagent.finished` | `SubagentFinishedNotification`(仅进程内运行) |
`HarnessSdkRequestMap` 与 `HarnessSdkNotificationMap` 按方法名索引这些类型。`InitializeParams.maxTokens` 是可选的正的安全整数,用于限制 SDK 创建的 agent(智能体)及其进程内后代的每次对话模型输出;省略时由提供方默认值控制。通知载荷类型依赖 `SessionEvent`(`dsh-session`)、`ContentBlock`(`dsh-llm`)与 `SubagentStopReason`(`dsh-subagent`)——协议以完整会话日志封套进行流式传输,因此会话词汇是协议格式契约的一部分。`serverInfo.name` 的协议值固定为 `deepseek-harness-sdk-runtime`。
`HarnessSdkRequestMap` 与 `HarnessSdkNotificationMap` 按方法名索引这些类型。`SessionPromptResult.messageId` 标识已排队的 `UserMessage`;它不标识后续的助手消息、轮次结束或提示词结果。客户端根据自己对活动区间的所有权,组合持续开放的 `session.event` 流与 agent 级的 `session.status`。`InitializeParams.maxTokens` 是可选的正的安全整数,用于限制 SDK 创建的 agent 及其进程内后代的每次对话模型输出;省略时由提供方默认值控制。通知载荷类型依赖 `SessionEvent`(`dsh-session`)、`ContentBlock`(`dsh-llm`)与 `SubagentStopReason`(`dsh-subagent`)——协议以完整会话日志封套进行流式传输,因此会话词汇是协议格式契约的一部分。`serverInfo.name` 的协议值固定为 `deepseek-harness-sdk-runtime`。
## 模型体验

View File

@@ -17,7 +17,7 @@ export type {
InitializeResult,
SdkRunStatus,
SessionEventNotification,
SessionFinishedNotification,
SessionStatusNotification,
SessionPromptParams,
SessionPromptResult,
SubagentFinishedNotification,

View File

@@ -9,7 +9,7 @@
*/
import type { ContentBlock } from '@deepseek-ai/dsh-llm'
import type { SessionEvent, TurnEndReason } from '@deepseek-ai/dsh-session'
import type { SessionEvent } from '@deepseek-ai/dsh-session'
import type { SubagentStopReason } from '@deepseek-ai/dsh-subagent'
/** Parameters for the process-wide SDK handshake. */
@@ -38,10 +38,10 @@ export interface SessionPromptParams {
contentBlocks: ContentBlock[]
}
/** Prompt acceptance after turn settlement; outcome rides on `session.finished`. */
/** Durable enqueue receipt for one prompt. */
export interface SessionPromptResult {
/** Always `true`; the turn outcome is the paired `session.finished` notification. */
accepted: true
/** Identity of the queued user message. */
messageId: string
}
/** Deployment-mapped SDK outcome: `ok` for an accepted result, `error` otherwise. */
@@ -55,14 +55,12 @@ export interface SessionEventNotification {
event: SessionEvent
}
/** `session.finished` payload: one per accepted prompt, after turn settlement. */
export interface SessionFinishedNotification {
/** The settled session. */
/** Whole-agent lifecycle state for one session. */
export interface SessionStatusNotification {
/** Session whose live agent changed status. */
sessionId: string
/** Deployment-mapped turn outcome (see `maxTokensAsSuccess` on the server). */
status: SdkRunStatus
/** Why the last message-triggered turn ended; absent when no turn ran. */
reason: TurnEndReason | undefined
/** The whole-agent state after the transition. */
status: 'idle' | 'running'
}
/** `subagent.started` payload: an in-runtime child session was created. */
@@ -94,7 +92,7 @@ export interface SubagentFinishedNotification {
/** Server-to-client notifications by JSON-RPC method name. */
export interface HarnessSdkNotificationMap {
'session.event': SessionEventNotification
'session.finished': SessionFinishedNotification
'session.status': SessionStatusNotification
'subagent.started': SubagentStartedNotification
'subagent.finished': SubagentFinishedNotification
}

View File

@@ -29,11 +29,11 @@ describe('JsonRpcLineTransport', () => {
const response = await b.request('echo', { value: 42 })
expect(response).toEqual({ echoed: { value: 42 } })
a.notify('session.finished', { sessionId: 'main', status: 'ok' })
a.notify('session.status', { sessionId: 'main', status: 'idle' })
a.notify('heartbeat')
await new Promise(resolve => setTimeout(resolve, 10))
expect(notifications).toEqual([
{ method: 'session.finished', params: { sessionId: 'main', status: 'ok' } },
{ method: 'session.status', params: { sessionId: 'main', status: 'idle' } },
{ method: 'heartbeat', params: {} },
])