Code Reader
首页
帮助
设计文档
首页
帮助
设计文档
  • Part

Part

Part 是消息的基本组成单元,使用联合类型支持多种类型的内容。

概述

Part 是 MessageV2 的核心内容容器。每个 Message 可以包含多个 Part,每个 Part 代表一种特定类型的内容(文本、文件、工具调用等)。这种设计允许灵活的消息内容组合和流式更新。

定义位置

packages/opencode/src/session/message-v2.ts:329-347

基础属性

所有 Part 都包含以下基础属性:

属性名类型必填说明
idstring是Part唯一标识符
sessionIDstring是所属会话ID
messageIDstring是所属消息ID
typestring是Part类型标识

Part 类型

1. TextPart - 文本部分

纯文本内容。

属性名类型必填说明
type"text"是类型标识
textstring是文本内容
syntheticboolean否是否为合成内容
ignoredboolean否是否被忽略
timeobject否时间信息
time.startnumber-开始时间
time.endnumber-结束时间
metadataRecord<string, any>否元数据

2. SubtaskPart - 子任务部分

表示触发的子任务(例如使用 Task 工具)。

属性名类型必填说明
type"subtask"是类型标识
promptstring是提示词
descriptionstring是任务描述
agentstring是执行的Agent
modelobject否模型配置
model.providerIDstring-提供商ID
model.modelIDstring-模型ID
commandstring否命令

3. ReasoningPart - 推理部分

AI 模型的推理内容(如 Chain of Thought)。

属性名类型必填说明
type"reasoning"是类型标识
textstring是推理内容
metadataRecord<string, any>否元数据
timeobject是时间信息
time.startnumber-开始时间
time.endnumber-结束时间

4. FilePart - 文件部分

文件或图像内容。

属性名类型必填说明
type"file"是类型标识
mimestring是MIME类型
filenamestring否文件名
urlstring是文件URL
sourceFileSource否文件来源信息

FileSource 类型:

类型说明
FileSource文件来源(包含 path)
SymbolSource符号来源(包含 path, range, name, kind)
ResourceSource资源来源(包含 clientName, uri)

5. ToolPart - 工具调用部分

工具调用及执行状态。

属性名类型必填说明
type"tool"是类型标识
callIDstring是调用ID
toolstring是工具名称
stateToolState是工具状态
metadataRecord<string, any>否元数据

ToolState 联合类型:

Pending 状态

属性名类型必填说明
status"pending"是状态标识
inputRecord<string, any>是输入参数
rawstring是原始输入

Running 状态

属性名类型必填说明
status"running"是状态标识
inputRecord<string, any>是输入参数
titlestring否显示标题
metadataRecord<string, any>否元数据
time.startnumber是开始时间

Completed 状态

属性名类型必填说明
status"completed"是状态标识
inputRecord<string, any>是输入参数
outputstring是输出结果
titlestring是显示标题
metadataRecord<string, any>是元数据
time.startnumber是开始时间
time.endnumber是结束时间
time.compactednumber否压缩时间
attachmentsFilePart[]否附件列表

Error 状态

属性名类型必填说明
status"error"是状态标识
inputRecord<string, any>是输入参数
errorstring是错误信息
metadataRecord<string, any>否元数据
time.startnumber是开始时间
time.endnumber是结束时间

6. StepStartPart - 步骤开始标记

表示一个新的推理步骤开始。

属性名类型必填说明
type"step-start"是类型标识
snapshotstring否快照ID

7. StepFinishPart - 步骤完成标记

表示推理步骤完成。

属性名类型必填说明
type"step-finish"是类型标识
reasonstring是完成原因
snapshotstring否快照ID
costnumber是成本
tokensobject是Token统计
tokens.inputnumber-输入Token数
tokens.outputnumber-输出Token数
tokens.reasoningnumber-推理Token数
tokens.cache.readnumber-缓存读取数
tokens.cache.writenumber-缓存写入数

8. SnapshotPart - 快照部分

代码快照引用。

属性名类型必填说明
type"snapshot"是类型标识
snapshotstring是快照ID

9. PatchPart - 补丁部分

Git 补丁信息。

属性名类型必填说明
type"patch"是类型标识
hashstring是补丁哈希
filesstring[]是影响的文件列表

10. AgentPart - Agent部分

Agent 切换标记。

属性名类型必填说明
type"agent"是类型标识
namestring是Agent名称
sourceobject否来源信息
source.valuestring-值
source.startnumber-开始位置
source.endnumber-结束位置

11. RetryPart - 重试部分

重试操作记录。

属性名类型必填说明
type"retry"是类型标识
attemptnumber是尝试次数
errorAPIError是错误信息
time.creatednumber是创建时间

12. CompactionPart - 压缩部分

历史消息压缩标记。

属性名类型必填说明
type"compaction"是类型标识
autoboolean是是否自动压缩

TypeScript 类型定义

export type Part =
  | TextPart
  | SubtaskPart
  | ReasoningPart
  | FilePart
  | ToolPart
  | StepStartPart
  | StepFinishPart
  | SnapshotPart
  | PatchPart
  | AgentPart
  | RetryPart
  | CompactionPart

存储键结构

;["part", messageID, partID]

典型使用场景

1. 添加文本Part(流式更新)

// 初始创建
const textPart: MessageV2.TextPart = {
  id: Identifier.ascending("part"),
  sessionID: session.id,
  messageID: message.id,
  type: "text",
  text: "",
  time: { start: Date.now() },
}

await Session.updatePart(textPart)

// 流式追加
await Session.updatePart({
  part: { ...textPart, text: "Hello " },
  delta: "Hello ",
})

await Session.updatePart({
  part: { ...textPart, text: "Hello World" },
  delta: "World",
})

2. 添加文件Part

const filePart: MessageV2.FilePart = {
  id: Identifier.ascending("part"),
  sessionID: session.id,
  messageID: message.id,
  type: "file",
  mime: "image/png",
  filename: "screenshot.png",
  url: "https://cdn.example.com/screenshot.png",
  source: {
    type: "file",
    path: "/path/to/screenshot.png",
    text: {
      value: "![screenshot](https://cdn.example.com/screenshot.png)",
      start: 0,
      end: 100,
    },
  },
}

await Session.updatePart(filePart)

3. 添加工具调用Part(完整生命周期)

// 1. 创建 Pending 状态
const toolPart: MessageV2.ToolPart = {
  id: Identifier.ascending("part"),
  sessionID: session.id,
  messageID: message.id,
  type: "tool",
  callID: Identifier.ascending("tool"),
  tool: "bash",
  state: {
    status: "pending",
    input: { command: "npm test" },
    raw: '{"command": "npm test"}',
  },
}
await Session.updatePart(toolPart)

// 2. 更新为 Running 状态
toolPart.state = {
  status: "running",
  input: toolPart.state.input,
  title: "Running npm test",
  metadata: {},
  time: { start: Date.now() },
}
await Session.updatePart(toolPart)

// 3. 更新为 Completed 状态
toolPart.state = {
  status: "completed",
  input: toolPart.state.input,
  output: "✓ All tests passed",
  title: "npm test",
  metadata: {},
  time: {
    start: toolPart.state.time.start,
    end: Date.now(),
  },
  attachments: [],
}
await Session.updatePart(toolPart)

4. 获取消息的所有Parts

const parts = await MessageV2.parts(messageID)

for (const part of parts) {
  switch (part.type) {
    case "text":
      console.log(`Text: ${part.text}`)
      break
    case "tool":
      console.log(`Tool: ${part.tool} (${part.state.status})`)
      break
    case "file":
      console.log(`File: ${part.filename}`)
      break
  }
}

5. 删除Part

await Session.removePart({
  sessionID: session.id,
  messageID: message.id,
  partID: part.id,
})

Part 状态转换图

Part 类型层次结构

变更历史

版本变更内容日期
v2引入 MessageV2 Part 架构-
v2.1添加 CompactionPart-
v2.2添加 SubtaskPart-

相关文档

  • Message - 消息对象
  • Tool - 工具系统