feat: record created_at/completed_at on reasoning ChatMessageParts (#24789)

Records reasoning start and end times on persisted reasoning
`ChatMessagePart`s so reasoning duration can be computed for stored
chats. Backend-only: no SSE changes and no frontend rendering ship in
this PR.

The `created_at` field on `ChatMessagePart` is extended to also be
present on `reasoning` parts (it previously appeared only on `tool-call`
and `tool-result`), and a new `completed_at` field is added for
`reasoning` parts.

### How timestamps are recorded

- `StreamPartTypeReasoningStart`: stamp `startedAt = dbtime.Now()` on
the active reasoning state.
- `StreamPartTypeReasoningEnd`: stamp `completedAt = dbtime.Now()` and
append both into parallel `[]time.Time` slices on `stepResult`.
- Persistence reads the slices in occurrence order (reasoning has no
provider-side ID) and applies them to the matching `ChatMessagePart` via
`buildAssistantPartsForPersist`. The first reasoning block's stamps go
onto the first reasoning part, and so on.
- `flushActiveState` flushes partial reasoning interrupted before
`StreamPartTypeReasoningEnd` with `startedAt` from the active state and
`completedAt = dbtime.Now()` at the interruption.

### Why two fields, not one?

Tool calls and results are point events. The frontend computes their
duration by subtracting the call's `created_at` from the result's
`created_at`. Reasoning is one assistant part that brackets a span, so
we record both endpoints on the part itself.

### Why not stamp in `PartFromContent`?

Same rationale as #24101: `PartFromContent` is called during both SSE
publishing and persistence. Stamping there would yield incorrect
persistence-time timestamps for reasoning blocks that finished much
earlier in the step. Instead we capture in the chatloop and apply during
persistence.

<details><summary>Implementation plan</summary>

- `codersdk/chats.go`: extend `CreatedAt`'s `variants` to include
`reasoning?`; add `CompletedAt *time.Time` with `variants:"reasoning?"`.
- `coderd/x/chatd/chatloop/chatloop.go`: extend `reasoningState` with
`startedAt`; extend `stepResult` and `PersistedStep` with parallel
`[]time.Time` reasoning slices; stamp on
`ReasoningStart`/`ReasoningEnd`; thread the slices through all
`PersistStep` call sites including the interrupt-safe path; record
partial reasoning in `flushActiveState`.
- `coderd/x/chatd/attachments.go`: walk reasoning parts in occurrence
order and apply `step.ReasoningStartedAt[i]` to `part.CreatedAt` and
`step.ReasoningCompletedAt[i]` to `part.CompletedAt`.

### Tests

- `codersdk/chats_test.go` round-trips `created_at` + `completed_at` on
reasoning parts and verifies omission when absent and partial
interrupted parts.
- `coderd/x/chatd/chatprompt/chatprompt_test.go` asserts
`PartFromContent(ReasoningContent{})` does NOT stamp timestamps.
- `coderd/x/chatd/chatloop/chatloop_test.go`
`TestRun_ReasoningTimestamps` drives a stream with two reasoning blocks
and verifies parallel slices, monotonicity, ordering, non-zero values,
and content-block ordering.
`TestRun_InterruptedReasoningFlushesTimestamps` cancels mid-reasoning
and verifies `flushActiveState` records a non-zero pair.
- `coderd/x/chatd/attachments_test.go` covers
`buildAssistantPartsForPersist` for normal interleaved reasoning,
partial (zero `completed_at`), and missing slices.

</details>

> Generated by Coder Agents.

Co-authored-by: Coder Agent <agent@coder.com>
This commit is contained in:
Kyle Carberry
2026-05-18 12:30:30 -04:00
committed by GitHub
parent 46821525f7
commit 385146000b
12 changed files with 661 additions and 179 deletions
+124 -105
View File
@@ -88,6 +88,7 @@ Experimental: this endpoint is subject to change.
0
],
"args_delta": "string",
"completed_at": "2019-08-24T14:15:22Z",
"content": "string",
"context_file_agent_id": {
"uuid": "string",
@@ -172,111 +173,112 @@ Experimental: this endpoint is subject to change.
Status Code **200**
| Name | Type | Required | Restrictions | Description |
|-----------------------------------|------------------------------------------------------------------------|----------|--------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `[array item]` | array | false | | |
| `» agent_id` | string(uuid) | false | | |
| `» archived` | boolean | false | | |
| `» build_id` | string(uuid) | false | | |
| `» children` | [codersdk.Chat](schemas.md#codersdkchat) | false | | Children holds child (subagent) chats nested under this root chat. Always initialized to an empty slice so the JSON field is present as []. Child chats cannot create their own subagents, so nesting depth is capped at 1 and this slice is always empty for child chats. |
| `» client_type` | [codersdk.ChatClientType](schemas.md#codersdkchatclienttype) | false | | |
| `» created_at` | string(date-time) | false | | |
| `» diff_status` | [codersdk.ChatDiffStatus](schemas.md#codersdkchatdiffstatus) | false | | |
| `»» additions` | integer | false | | |
| `»» approved` | boolean | false | | |
| `»» author_avatar_url` | string | false | | |
| `»» author_login` | string | false | | |
| `»» base_branch` | string | false | | |
| `»» changed_files` | integer | false | | |
| `»» changes_requested` | boolean | false | | |
| `»» chat_id` | string(uuid) | false | | |
| `»» commits` | integer | false | | |
| `»» deletions` | integer | false | | |
| `»» head_branch` | string | false | | |
| `»» pr_number` | integer | false | | |
| `»» pull_request_draft` | boolean | false | | |
| `»» pull_request_state` | string | false | | |
| `»» pull_request_title` | string | false | | |
| `»» refreshed_at` | string(date-time) | false | | |
| `»» reviewer_count` | integer | false | | |
| `»» stale_at` | string(date-time) | false | | |
| `»» url` | string | false | | |
| `» files` | array | false | | |
| `»» created_at` | string(date-time) | false | | |
| `»» id` | string(uuid) | false | | |
| `»» mime_type` | string | false | | |
| `»» name` | string | false | | |
| `»» organization_id` | string(uuid) | false | | |
| `»» owner_id` | string(uuid) | false | | |
| `» has_unread` | boolean | false | | Has unread is true when assistant messages exist beyond the owner's read cursor, which updates on stream connect and disconnect. |
| `» id` | string(uuid) | false | | |
| `» labels` | object | false | | |
| `»» [any property]` | string | false | | |
| `» last_error` | [codersdk.ChatError](schemas.md#codersdkchaterror) | false | | |
| `»» detail` | string | false | | Detail is optional provider-specific context shown alongside the normalized error message when available. |
| `»» kind` | [codersdk.ChatErrorKind](schemas.md#codersdkchaterrorkind) | false | | Kind classifies the error for consistent client rendering. |
| `»» message` | string | false | | Message is the normalized, user-facing error message. |
| `»» provider` | string | false | | Provider identifies the upstream model provider when known. |
| `»» retryable` | boolean | false | | Retryable reports whether the underlying error is transient. |
| `»» status_code` | integer | false | | Status code is the best-effort upstream HTTP status code. |
| `» last_injected_context` | array | false | | Last injected context holds the most recently persisted injected context parts (AGENTS.md files and skills). It is updated only when context changes, on first workspace attach or agent change. |
| `»» args` | array | false | | |
| `»» args_delta` | string | false | | |
| `»» content` | string | false | | The code content from the diff that was commented on. |
| `»» context_file_agent_id` | [uuid.NullUUID](schemas.md#uuidnulluuid) | false | | Context file agent ID is the workspace agent that provided this context file. Used to detect when the agent changes (e.g. workspace rebuilt) so instruction files can be re-persisted with fresh content. |
| `»»» uuid` | string | false | | |
| `»»» valid` | boolean | false | | Valid is true if UUID is not NULL |
| `»» context_file_content` | string | false | | Context file content holds the file content sent to the LLM. Internal only: stripped before API responses to keep payloads small. The backend reads it when building the prompt via partsToMessageParts. |
| `»» context_file_directory` | string | false | | Context file directory is the working directory of the workspace agent. Internal only: same purpose as ContextFileOS. |
| `»» context_file_os` | string | false | | Context file os is the operating system of the workspace agent. Internal only: used during prompt expansion so the LLM knows the OS even on turns where InsertSystem is not called. |
| `»» context_file_path` | string | false | | Context file path is the absolute path of a file loaded into the LLM context (e.g. an AGENTS.md instruction file). |
| `»» context_file_skill_meta_file` | string | false | | Context file skill meta file is the basename of the skill meta file (e.g. "SKILL.md") at the time of persistence. Internal only: restored on subsequent turns so the read_skill tool uses the correct filename even when the agent configured a non-default value. |
| `»» context_file_truncated` | boolean | false | | Context file truncated indicates the file exceeded the 64KiB instruction file limit and was truncated. |
| `»» created_at` | string(date-time) | false | | Created at records when this part was produced. Present on tool-call and tool-result parts so the frontend can compute tool execution duration. |
| `»» data` | array | false | | |
| `»» end_line` | integer | false | | |
| `»» file_id` | [uuid.NullUUID](schemas.md#uuidnulluuid) | false | | |
| `»»» uuid` | string | false | | |
| `»»» valid` | boolean | false | | Valid is true if UUID is not NULL |
| `»» file_name` | string | false | | |
| `»» is_error` | boolean | false | | |
| `»» is_media` | boolean | false | | |
| `»» mcp_server_config_id` | [uuid.NullUUID](schemas.md#uuidnulluuid) | false | | |
| `»»» uuid` | string | false | | |
| `»»» valid` | boolean | false | | Valid is true if UUID is not NULL |
| `»» media_type` | string | false | | |
| `»» name` | string | false | | |
| `»» provider_executed` | boolean | false | | Provider executed indicates the tool call was executed by the provider (e.g. Anthropic computer use). |
| `»» provider_metadata` | array | false | | Provider metadata holds provider-specific response metadata (e.g. Anthropic cache control hints) as raw JSON. Internal only: stripped by db2sdk before API responses. |
| `»» result` | array | false | | |
| `»» result_delta` | string | false | | |
| `»» result_reset` | boolean | false | | |
| `»» signature` | string | false | | |
| `»» skill_description` | string | false | | Skill description is the short description from the skill's SKILL.md frontmatter. |
| `»» skill_dir` | string | false | | Skill dir is the absolute path to the skill directory inside the workspace filesystem. Internal only: used by read_skill/read_skill_file tools to locate skill files. |
| `»» skill_name` | string | false | | Skill name is the kebab-case name of a discovered skill from the workspace's .agents/skills/ directory. |
| `»» source_id` | string | false | | |
| `»» start_line` | integer | false | | |
| `»» text` | string | false | | |
| `»» title` | string | false | | |
| `»» tool_call_id` | string | false | | |
| `»» tool_name` | string | false | | |
| `»» type` | [codersdk.ChatMessagePartType](schemas.md#codersdkchatmessageparttype) | false | | |
| `»» url` | string | false | | |
| last_model_config_id` | string(uuid) | false | | |
| `» last_turn_summary` | string | false | | |
| mcp_server_ids` | array | false | | |
| organization_id` | string(uuid) | false | | |
| `» owner_id` | string(uuid) | false | | |
| parent_chat_id` | string(uuid) | false | | |
| `» pin_order` | integer | false | | |
| `» plan_mode` | [codersdk.ChatPlanMode](schemas.md#codersdkchatplanmode) | false | | |
| root_chat_id` | string(uuid) | false | | |
| status` | [codersdk.ChatStatus](schemas.md#codersdkchatstatus) | false | | |
| title` | string | false | | |
| updated_at` | string(date-time) | false | | |
| warnings` | array | false | | |
| `» workspace_id` | string(uuid) | false | | |
| Name | Type | Required | Restrictions | Description |
|-----------------------------------|------------------------------------------------------------------------|----------|--------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `[array item]` | array | false | | |
| `» agent_id` | string(uuid) | false | | |
| `» archived` | boolean | false | | |
| `» build_id` | string(uuid) | false | | |
| `» children` | [codersdk.Chat](schemas.md#codersdkchat) | false | | Children holds child (subagent) chats nested under this root chat. Always initialized to an empty slice so the JSON field is present as []. Child chats cannot create their own subagents, so nesting depth is capped at 1 and this slice is always empty for child chats. |
| `» client_type` | [codersdk.ChatClientType](schemas.md#codersdkchatclienttype) | false | | |
| `» created_at` | string(date-time) | false | | |
| `» diff_status` | [codersdk.ChatDiffStatus](schemas.md#codersdkchatdiffstatus) | false | | |
| `»» additions` | integer | false | | |
| `»» approved` | boolean | false | | |
| `»» author_avatar_url` | string | false | | |
| `»» author_login` | string | false | | |
| `»» base_branch` | string | false | | |
| `»» changed_files` | integer | false | | |
| `»» changes_requested` | boolean | false | | |
| `»» chat_id` | string(uuid) | false | | |
| `»» commits` | integer | false | | |
| `»» deletions` | integer | false | | |
| `»» head_branch` | string | false | | |
| `»» pr_number` | integer | false | | |
| `»» pull_request_draft` | boolean | false | | |
| `»» pull_request_state` | string | false | | |
| `»» pull_request_title` | string | false | | |
| `»» refreshed_at` | string(date-time) | false | | |
| `»» reviewer_count` | integer | false | | |
| `»» stale_at` | string(date-time) | false | | |
| `»» url` | string | false | | |
| `» files` | array | false | | |
| `»» created_at` | string(date-time) | false | | |
| `»» id` | string(uuid) | false | | |
| `»» mime_type` | string | false | | |
| `»» name` | string | false | | |
| `»» organization_id` | string(uuid) | false | | |
| `»» owner_id` | string(uuid) | false | | |
| `» has_unread` | boolean | false | | Has unread is true when assistant messages exist beyond the owner's read cursor, which updates on stream connect and disconnect. |
| `» id` | string(uuid) | false | | |
| `» labels` | object | false | | |
| `»» [any property]` | string | false | | |
| `» last_error` | [codersdk.ChatError](schemas.md#codersdkchaterror) | false | | |
| `»» detail` | string | false | | Detail is optional provider-specific context shown alongside the normalized error message when available. |
| `»» kind` | [codersdk.ChatErrorKind](schemas.md#codersdkchaterrorkind) | false | | Kind classifies the error for consistent client rendering. |
| `»» message` | string | false | | Message is the normalized, user-facing error message. |
| `»» provider` | string | false | | Provider identifies the upstream model provider when known. |
| `»» retryable` | boolean | false | | Retryable reports whether the underlying error is transient. |
| `»» status_code` | integer | false | | Status code is the best-effort upstream HTTP status code. |
| `» last_injected_context` | array | false | | Last injected context holds the most recently persisted injected context parts (AGENTS.md files and skills). It is updated only when context changes, on first workspace attach or agent change. |
| `»» args` | array | false | | |
| `»» args_delta` | string | false | | |
| `»» completed_at` | string(date-time) | false | | Completed at is the time a reasoning part finished streaming, so reasoning duration can be computed as completed_at minus created_at. For interrupted reasoning, this is the interruption time. Absent when reasoning timestamp data was not recorded (e.g. messages persisted before this feature was added). |
| `»» content` | string | false | | The code content from the diff that was commented on. |
| `»» context_file_agent_id` | [uuid.NullUUID](schemas.md#uuidnulluuid) | false | | Context file agent ID is the workspace agent that provided this context file. Used to detect when the agent changes (e.g. workspace rebuilt) so instruction files can be re-persisted with fresh content. |
| `»»» uuid` | string | false | | |
| `»»» valid` | boolean | false | | Valid is true if UUID is not NULL |
| `»» context_file_content` | string | false | | Context file content holds the file content sent to the LLM. Internal only: stripped before API responses to keep payloads small. The backend reads it when building the prompt via partsToMessageParts. |
| `»» context_file_directory` | string | false | | Context file directory is the working directory of the workspace agent. Internal only: same purpose as ContextFileOS. |
| `»» context_file_os` | string | false | | Context file os is the operating system of the workspace agent. Internal only: used during prompt expansion so the LLM knows the OS even on turns where InsertSystem is not called. |
| `»» context_file_path` | string | false | | Context file path is the absolute path of a file loaded into the LLM context (e.g. an AGENTS.md instruction file). |
| `»» context_file_skill_meta_file` | string | false | | Context file skill meta file is the basename of the skill meta file (e.g. "SKILL.md") at the time of persistence. Internal only: restored on subsequent turns so the read_skill tool uses the correct filename even when the agent configured a non-default value. |
| `»» context_file_truncated` | boolean | false | | Context file truncated indicates the file exceeded the 64KiB instruction file limit and was truncated. |
| `»» created_at` | string(date-time) | false | | Created at is the timestamp this part carries. The semantics depend on the part type: for tool-call and tool-result parts it is the time the call was emitted or the result was produced (tool duration is the result's created_at minus the call's created_at); for reasoning parts it is the time reasoning started streaming. |
| `»» data` | array | false | | |
| `»» end_line` | integer | false | | |
| `»» file_id` | [uuid.NullUUID](schemas.md#uuidnulluuid) | false | | |
| `»»» uuid` | string | false | | |
| `»»» valid` | boolean | false | | Valid is true if UUID is not NULL |
| `»» file_name` | string | false | | |
| `»» is_error` | boolean | false | | |
| `»» is_media` | boolean | false | | |
| `»» mcp_server_config_id` | [uuid.NullUUID](schemas.md#uuidnulluuid) | false | | |
| `»»» uuid` | string | false | | |
| `»»» valid` | boolean | false | | Valid is true if UUID is not NULL |
| `»» media_type` | string | false | | |
| `»» name` | string | false | | |
| `»» provider_executed` | boolean | false | | Provider executed indicates the tool call was executed by the provider (e.g. Anthropic computer use). |
| `»» provider_metadata` | array | false | | Provider metadata holds provider-specific response metadata (e.g. Anthropic cache control hints) as raw JSON. Internal only: stripped by db2sdk before API responses. |
| `»» result` | array | false | | |
| `»» result_delta` | string | false | | |
| `»» result_reset` | boolean | false | | |
| `»» signature` | string | false | | |
| `»» skill_description` | string | false | | Skill description is the short description from the skill's SKILL.md frontmatter. |
| `»» skill_dir` | string | false | | Skill dir is the absolute path to the skill directory inside the workspace filesystem. Internal only: used by read_skill/read_skill_file tools to locate skill files. |
| `»» skill_name` | string | false | | Skill name is the kebab-case name of a discovered skill from the workspace's .agents/skills/ directory. |
| `»» source_id` | string | false | | |
| `»» start_line` | integer | false | | |
| `»» text` | string | false | | |
| `»» title` | string | false | | |
| `»» tool_call_id` | string | false | | |
| `»» tool_name` | string | false | | |
| `»» type` | [codersdk.ChatMessagePartType](schemas.md#codersdkchatmessageparttype) | false | | |
| » url` | string | false | | |
| `» last_model_config_id` | string(uuid) | false | | |
| last_turn_summary` | string | false | | |
| mcp_server_ids` | array | false | | |
| `» organization_id` | string(uuid) | false | | |
| owner_id` | string(uuid) | false | | |
| `» parent_chat_id` | string(uuid) | false | | |
| `» pin_order` | integer | false | | |
| plan_mode` | [codersdk.ChatPlanMode](schemas.md#codersdkchatplanmode) | false | | |
| root_chat_id` | string(uuid) | false | | |
| status` | [codersdk.ChatStatus](schemas.md#codersdkchatstatus) | false | | |
| title` | string | false | | |
| updated_at` | string(date-time) | false | | |
| `» warnings` | array | false | | |
| `» workspace_id` | string(uuid) | false | | |
#### Enumerated Values
@@ -420,6 +422,7 @@ Experimental: this endpoint is subject to change.
0
],
"args_delta": "string",
"completed_at": "2019-08-24T14:15:22Z",
"content": "string",
"context_file_agent_id": {
"uuid": "string",
@@ -545,6 +548,7 @@ Experimental: this endpoint is subject to change.
0
],
"args_delta": "string",
"completed_at": "2019-08-24T14:15:22Z",
"content": "string",
"context_file_agent_id": {
"uuid": "string",
@@ -821,6 +825,7 @@ Experimental: this endpoint is subject to change.
0
],
"args_delta": "string",
"completed_at": "2019-08-24T14:15:22Z",
"content": "string",
"context_file_agent_id": {
"uuid": "string",
@@ -1000,6 +1005,7 @@ Experimental: this endpoint is subject to change.
0
],
"args_delta": "string",
"completed_at": "2019-08-24T14:15:22Z",
"content": "string",
"context_file_agent_id": {
"uuid": "string",
@@ -1125,6 +1131,7 @@ Experimental: this endpoint is subject to change.
0
],
"args_delta": "string",
"completed_at": "2019-08-24T14:15:22Z",
"content": "string",
"context_file_agent_id": {
"uuid": "string",
@@ -1385,6 +1392,7 @@ Experimental: this endpoint is subject to change.
0
],
"args_delta": "string",
"completed_at": "2019-08-24T14:15:22Z",
"content": "string",
"context_file_agent_id": {
"uuid": "string",
@@ -1510,6 +1518,7 @@ Experimental: this endpoint is subject to change.
0
],
"args_delta": "string",
"completed_at": "2019-08-24T14:15:22Z",
"content": "string",
"context_file_agent_id": {
"uuid": "string",
@@ -1631,6 +1640,7 @@ Experimental: this endpoint is subject to change.
0
],
"args_delta": "string",
"completed_at": "2019-08-24T14:15:22Z",
"content": "string",
"context_file_agent_id": {
"uuid": "string",
@@ -1708,6 +1718,7 @@ Experimental: this endpoint is subject to change.
0
],
"args_delta": "string",
"completed_at": "2019-08-24T14:15:22Z",
"content": "string",
"context_file_agent_id": {
"uuid": "string",
@@ -1837,6 +1848,7 @@ Experimental: this endpoint is subject to change.
0
],
"args_delta": "string",
"completed_at": "2019-08-24T14:15:22Z",
"content": "string",
"context_file_agent_id": {
"uuid": "string",
@@ -1913,6 +1925,7 @@ Experimental: this endpoint is subject to change.
0
],
"args_delta": "string",
"completed_at": "2019-08-24T14:15:22Z",
"content": "string",
"context_file_agent_id": {
"uuid": "string",
@@ -2040,6 +2053,7 @@ Experimental: this endpoint is subject to change.
0
],
"args_delta": "string",
"completed_at": "2019-08-24T14:15:22Z",
"content": "string",
"context_file_agent_id": {
"uuid": "string",
@@ -2225,6 +2239,7 @@ Experimental: this endpoint is subject to change.
0
],
"args_delta": "string",
"completed_at": "2019-08-24T14:15:22Z",
"content": "string",
"context_file_agent_id": {
"uuid": "string",
@@ -2298,6 +2313,7 @@ Experimental: this endpoint is subject to change.
0
],
"args_delta": "string",
"completed_at": "2019-08-24T14:15:22Z",
"content": "string",
"context_file_agent_id": {
"uuid": "string",
@@ -2360,6 +2376,7 @@ Experimental: this endpoint is subject to change.
0
],
"args_delta": "string",
"completed_at": "2019-08-24T14:15:22Z",
"content": "string",
"context_file_agent_id": {
"uuid": "string",
@@ -2609,6 +2626,7 @@ Experimental: this endpoint is subject to change.
0
],
"args_delta": "string",
"completed_at": "2019-08-24T14:15:22Z",
"content": "string",
"context_file_agent_id": {
"uuid": "string",
@@ -2734,6 +2752,7 @@ Experimental: this endpoint is subject to change.
0
],
"args_delta": "string",
"completed_at": "2019-08-24T14:15:22Z",
"content": "string",
"context_file_agent_id": {
"uuid": "string",
+55 -39
View File
@@ -2182,6 +2182,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
0
],
"args_delta": "string",
"completed_at": "2019-08-24T14:15:22Z",
"content": "string",
"context_file_agent_id": {
"uuid": "string",
@@ -2307,6 +2308,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
0
],
"args_delta": "string",
"completed_at": "2019-08-24T14:15:22Z",
"content": "string",
"context_file_agent_id": {
"uuid": "string",
@@ -2644,6 +2646,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
0
],
"args_delta": "string",
"completed_at": "2019-08-24T14:15:22Z",
"content": "string",
"context_file_agent_id": {
"uuid": "string",
@@ -2734,6 +2737,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
0
],
"args_delta": "string",
"completed_at": "2019-08-24T14:15:22Z",
"content": "string",
"context_file_agent_id": {
"uuid": "string",
@@ -2789,45 +2793,46 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
### Properties
| Name | Type | Required | Restrictions | Description |
|--------------------------------|--------------------------------------------------------------|----------|--------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `args` | array of integer | false | | |
| `args_delta` | string | false | | |
| `content` | string | false | | The code content from the diff that was commented on. |
| `context_file_agent_id` | [uuid.NullUUID](#uuidnulluuid) | false | | Context file agent ID is the workspace agent that provided this context file. Used to detect when the agent changes (e.g. workspace rebuilt) so instruction files can be re-persisted with fresh content. |
| `context_file_content` | string | false | | Context file content holds the file content sent to the LLM. Internal only: stripped before API responses to keep payloads small. The backend reads it when building the prompt via partsToMessageParts. |
| `context_file_directory` | string | false | | Context file directory is the working directory of the workspace agent. Internal only: same purpose as ContextFileOS. |
| `context_file_os` | string | false | | Context file os is the operating system of the workspace agent. Internal only: used during prompt expansion so the LLM knows the OS even on turns where InsertSystem is not called. |
| `context_file_path` | string | false | | Context file path is the absolute path of a file loaded into the LLM context (e.g. an AGENTS.md instruction file). |
| `context_file_skill_meta_file` | string | false | | Context file skill meta file is the basename of the skill meta file (e.g. "SKILL.md") at the time of persistence. Internal only: restored on subsequent turns so the read_skill tool uses the correct filename even when the agent configured a non-default value. |
| `context_file_truncated` | boolean | false | | Context file truncated indicates the file exceeded the 64KiB instruction file limit and was truncated. |
| `created_at` | string | false | | Created at records when this part was produced. Present on tool-call and tool-result parts so the frontend can compute tool execution duration. |
| `data` | array of integer | false | | |
| `end_line` | integer | false | | |
| `file_id` | [uuid.NullUUID](#uuidnulluuid) | false | | |
| `file_name` | string | false | | |
| `is_error` | boolean | false | | |
| `is_media` | boolean | false | | |
| `mcp_server_config_id` | [uuid.NullUUID](#uuidnulluuid) | false | | |
| `media_type` | string | false | | |
| `name` | string | false | | |
| `provider_executed` | boolean | false | | Provider executed indicates the tool call was executed by the provider (e.g. Anthropic computer use). |
| `provider_metadata` | array of integer | false | | Provider metadata holds provider-specific response metadata (e.g. Anthropic cache control hints) as raw JSON. Internal only: stripped by db2sdk before API responses. |
| `result` | array of integer | false | | |
| `result_delta` | string | false | | |
| `result_reset` | boolean | false | | |
| `signature` | string | false | | |
| `skill_description` | string | false | | Skill description is the short description from the skill's SKILL.md frontmatter. |
| `skill_dir` | string | false | | Skill dir is the absolute path to the skill directory inside the workspace filesystem. Internal only: used by read_skill/read_skill_file tools to locate skill files. |
| `skill_name` | string | false | | Skill name is the kebab-case name of a discovered skill from the workspace's .agents/skills/ directory. |
| `source_id` | string | false | | |
| `start_line` | integer | false | | |
| `text` | string | false | | |
| `title` | string | false | | |
| `tool_call_id` | string | false | | |
| `tool_name` | string | false | | |
| `type` | [codersdk.ChatMessagePartType](#codersdkchatmessageparttype) | false | | |
| `url` | string | false | | |
| Name | Type | Required | Restrictions | Description |
|--------------------------------|--------------------------------------------------------------|----------|--------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `args` | array of integer | false | | |
| `args_delta` | string | false | | |
| `completed_at` | string | false | | Completed at is the time a reasoning part finished streaming, so reasoning duration can be computed as completed_at minus created_at. For interrupted reasoning, this is the interruption time. Absent when reasoning timestamp data was not recorded (e.g. messages persisted before this feature was added). |
| `content` | string | false | | The code content from the diff that was commented on. |
| `context_file_agent_id` | [uuid.NullUUID](#uuidnulluuid) | false | | Context file agent ID is the workspace agent that provided this context file. Used to detect when the agent changes (e.g. workspace rebuilt) so instruction files can be re-persisted with fresh content. |
| `context_file_content` | string | false | | Context file content holds the file content sent to the LLM. Internal only: stripped before API responses to keep payloads small. The backend reads it when building the prompt via partsToMessageParts. |
| `context_file_directory` | string | false | | Context file directory is the working directory of the workspace agent. Internal only: same purpose as ContextFileOS. |
| `context_file_os` | string | false | | Context file os is the operating system of the workspace agent. Internal only: used during prompt expansion so the LLM knows the OS even on turns where InsertSystem is not called. |
| `context_file_path` | string | false | | Context file path is the absolute path of a file loaded into the LLM context (e.g. an AGENTS.md instruction file). |
| `context_file_skill_meta_file` | string | false | | Context file skill meta file is the basename of the skill meta file (e.g. "SKILL.md") at the time of persistence. Internal only: restored on subsequent turns so the read_skill tool uses the correct filename even when the agent configured a non-default value. |
| `context_file_truncated` | boolean | false | | Context file truncated indicates the file exceeded the 64KiB instruction file limit and was truncated. |
| `created_at` | string | false | | Created at is the timestamp this part carries. The semantics depend on the part type: for tool-call and tool-result parts it is the time the call was emitted or the result was produced (tool duration is the result's created_at minus the call's created_at); for reasoning parts it is the time reasoning started streaming. |
| `data` | array of integer | false | | |
| `end_line` | integer | false | | |
| `file_id` | [uuid.NullUUID](#uuidnulluuid) | false | | |
| `file_name` | string | false | | |
| `is_error` | boolean | false | | |
| `is_media` | boolean | false | | |
| `mcp_server_config_id` | [uuid.NullUUID](#uuidnulluuid) | false | | |
| `media_type` | string | false | | |
| `name` | string | false | | |
| `provider_executed` | boolean | false | | Provider executed indicates the tool call was executed by the provider (e.g. Anthropic computer use). |
| `provider_metadata` | array of integer | false | | Provider metadata holds provider-specific response metadata (e.g. Anthropic cache control hints) as raw JSON. Internal only: stripped by db2sdk before API responses. |
| `result` | array of integer | false | | |
| `result_delta` | string | false | | |
| `result_reset` | boolean | false | | |
| `signature` | string | false | | |
| `skill_description` | string | false | | Skill description is the short description from the skill's SKILL.md frontmatter. |
| `skill_dir` | string | false | | Skill dir is the absolute path to the skill directory inside the workspace filesystem. Internal only: used by read_skill/read_skill_file tools to locate skill files. |
| `skill_name` | string | false | | Skill name is the kebab-case name of a discovered skill from the workspace's .agents/skills/ directory. |
| `source_id` | string | false | | |
| `start_line` | integer | false | | |
| `text` | string | false | | |
| `title` | string | false | | |
| `tool_call_id` | string | false | | |
| `tool_name` | string | false | | |
| `type` | [codersdk.ChatMessagePartType](#codersdkchatmessageparttype) | false | | |
| `url` | string | false | | |
## codersdk.ChatMessagePartType
@@ -2897,6 +2902,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
0
],
"args_delta": "string",
"completed_at": "2019-08-24T14:15:22Z",
"content": "string",
"context_file_agent_id": {
"uuid": "string",
@@ -2974,6 +2980,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
0
],
"args_delta": "string",
"completed_at": "2019-08-24T14:15:22Z",
"content": "string",
"context_file_agent_id": {
"uuid": "string",
@@ -3191,6 +3198,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
0
],
"args_delta": "string",
"completed_at": "2019-08-24T14:15:22Z",
"content": "string",
"context_file_agent_id": {
"uuid": "string",
@@ -3337,6 +3345,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
0
],
"args_delta": "string",
"completed_at": "2019-08-24T14:15:22Z",
"content": "string",
"context_file_agent_id": {
"uuid": "string",
@@ -3410,6 +3419,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
0
],
"args_delta": "string",
"completed_at": "2019-08-24T14:15:22Z",
"content": "string",
"context_file_agent_id": {
"uuid": "string",
@@ -3472,6 +3482,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
0
],
"args_delta": "string",
"completed_at": "2019-08-24T14:15:22Z",
"content": "string",
"context_file_agent_id": {
"uuid": "string",
@@ -3582,6 +3593,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
0
],
"args_delta": "string",
"completed_at": "2019-08-24T14:15:22Z",
"content": "string",
"context_file_agent_id": {
"uuid": "string",
@@ -3766,6 +3778,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
0
],
"args_delta": "string",
"completed_at": "2019-08-24T14:15:22Z",
"content": "string",
"context_file_agent_id": {
"uuid": "string",
@@ -4179,6 +4192,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
0
],
"args_delta": "string",
"completed_at": "2019-08-24T14:15:22Z",
"content": "string",
"context_file_agent_id": {
"uuid": "string",
@@ -4255,6 +4269,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
0
],
"args_delta": "string",
"completed_at": "2019-08-24T14:15:22Z",
"content": "string",
"context_file_agent_id": {
"uuid": "string",
@@ -6667,6 +6682,7 @@ CreateWorkspaceRequest provides options for creating a new workspace. Only one o
0
],
"args_delta": "string",
"completed_at": "2019-08-24T14:15:22Z",
"content": "string",
"context_file_agent_id": {
"uuid": "string",