mirror of
https://github.com/openai/codex.git
synced 2026-04-14 01:35:00 +00:00
Compare commits
1 Commits
dev/shaqay
...
jgershen/a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
949ec1d929 |
@@ -5,6 +5,61 @@
|
||||
"description": "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.",
|
||||
"type": "string"
|
||||
},
|
||||
"ApprovalSummary": {
|
||||
"properties": {
|
||||
"abort_count": {
|
||||
"format": "uint16",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"approved_count": {
|
||||
"format": "uint16",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"approved_for_session_count": {
|
||||
"format": "uint16",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"approved_with_amendment_count": {
|
||||
"format": "uint16",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"approved_with_network_policy_allow_count": {
|
||||
"format": "uint16",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"denied_count": {
|
||||
"format": "uint16",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"denied_with_network_policy_deny_count": {
|
||||
"format": "uint16",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"request_count": {
|
||||
"format": "uint16",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"abort_count",
|
||||
"approved_count",
|
||||
"approved_for_session_count",
|
||||
"approved_with_amendment_count",
|
||||
"approved_with_network_policy_allow_count",
|
||||
"denied_count",
|
||||
"denied_with_network_policy_deny_count",
|
||||
"request_count"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"AppsListParams": {
|
||||
"description": "EXPERIMENTAL - list available apps/connectors.",
|
||||
"properties": {
|
||||
@@ -932,6 +987,21 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"PrimitiveMetadata": {
|
||||
"properties": {
|
||||
"approval_summary": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ApprovalSummary"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"ProductSurface": {
|
||||
"enum": [
|
||||
"chatgpt",
|
||||
@@ -1215,6 +1285,16 @@
|
||||
],
|
||||
"writeOnly": true
|
||||
},
|
||||
"primitive_metadata": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PrimitiveMetadata"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
"$ref": "#/definitions/LocalShellStatus"
|
||||
},
|
||||
@@ -1252,6 +1332,16 @@
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"primitive_metadata": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PrimitiveMetadata"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"function_call"
|
||||
@@ -1311,6 +1401,16 @@
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"primitive_metadata": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PrimitiveMetadata"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
"type": [
|
||||
"string",
|
||||
|
||||
@@ -93,6 +93,61 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"ApprovalSummary": {
|
||||
"properties": {
|
||||
"abort_count": {
|
||||
"format": "uint16",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"approved_count": {
|
||||
"format": "uint16",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"approved_for_session_count": {
|
||||
"format": "uint16",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"approved_with_amendment_count": {
|
||||
"format": "uint16",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"approved_with_network_policy_allow_count": {
|
||||
"format": "uint16",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"denied_count": {
|
||||
"format": "uint16",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"denied_with_network_policy_deny_count": {
|
||||
"format": "uint16",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"request_count": {
|
||||
"format": "uint16",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"abort_count",
|
||||
"approved_count",
|
||||
"approved_for_session_count",
|
||||
"approved_with_amendment_count",
|
||||
"approved_with_network_policy_allow_count",
|
||||
"denied_count",
|
||||
"denied_with_network_policy_deny_count",
|
||||
"request_count"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"AskForApproval": {
|
||||
"description": "Determines the conditions under which the user is consulted to approve running the command proposed by Codex.",
|
||||
"oneOf": [
|
||||
@@ -4061,6 +4116,21 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"PrimitiveMetadata": {
|
||||
"properties": {
|
||||
"approval_summary": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ApprovalSummary"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"RateLimitSnapshot": {
|
||||
"properties": {
|
||||
"credits": {
|
||||
@@ -4697,6 +4767,16 @@
|
||||
],
|
||||
"writeOnly": true
|
||||
},
|
||||
"primitive_metadata": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PrimitiveMetadata"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
"$ref": "#/definitions/LocalShellStatus"
|
||||
},
|
||||
@@ -4734,6 +4814,16 @@
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"primitive_metadata": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PrimitiveMetadata"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"function_call"
|
||||
@@ -4793,6 +4883,16 @@
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"primitive_metadata": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PrimitiveMetadata"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
"type": [
|
||||
"string",
|
||||
|
||||
@@ -7717,6 +7717,61 @@
|
||||
"AppToolsConfig": {
|
||||
"type": "object"
|
||||
},
|
||||
"ApprovalSummary": {
|
||||
"properties": {
|
||||
"abort_count": {
|
||||
"format": "uint16",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"approved_count": {
|
||||
"format": "uint16",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"approved_for_session_count": {
|
||||
"format": "uint16",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"approved_with_amendment_count": {
|
||||
"format": "uint16",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"approved_with_network_policy_allow_count": {
|
||||
"format": "uint16",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"denied_count": {
|
||||
"format": "uint16",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"denied_with_network_policy_deny_count": {
|
||||
"format": "uint16",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"request_count": {
|
||||
"format": "uint16",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"abort_count",
|
||||
"approved_count",
|
||||
"approved_for_session_count",
|
||||
"approved_with_amendment_count",
|
||||
"approved_with_network_policy_allow_count",
|
||||
"denied_count",
|
||||
"denied_with_network_policy_deny_count",
|
||||
"request_count"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"AppsConfig": {
|
||||
"properties": {
|
||||
"_default": {
|
||||
@@ -10687,6 +10742,21 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"PrimitiveMetadata": {
|
||||
"properties": {
|
||||
"approval_summary": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/v2/ApprovalSummary"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"ProductSurface": {
|
||||
"enum": [
|
||||
"chatgpt",
|
||||
@@ -11359,6 +11429,16 @@
|
||||
],
|
||||
"writeOnly": true
|
||||
},
|
||||
"primitive_metadata": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/v2/PrimitiveMetadata"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
"$ref": "#/definitions/v2/LocalShellStatus"
|
||||
},
|
||||
@@ -11396,6 +11476,16 @@
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"primitive_metadata": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/v2/PrimitiveMetadata"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"function_call"
|
||||
@@ -11455,6 +11545,16 @@
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"primitive_metadata": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/v2/PrimitiveMetadata"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
"type": [
|
||||
"string",
|
||||
|
||||
@@ -1,6 +1,61 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"definitions": {
|
||||
"ApprovalSummary": {
|
||||
"properties": {
|
||||
"abort_count": {
|
||||
"format": "uint16",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"approved_count": {
|
||||
"format": "uint16",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"approved_for_session_count": {
|
||||
"format": "uint16",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"approved_with_amendment_count": {
|
||||
"format": "uint16",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"approved_with_network_policy_allow_count": {
|
||||
"format": "uint16",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"denied_count": {
|
||||
"format": "uint16",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"denied_with_network_policy_deny_count": {
|
||||
"format": "uint16",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"request_count": {
|
||||
"format": "uint16",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"abort_count",
|
||||
"approved_count",
|
||||
"approved_for_session_count",
|
||||
"approved_with_amendment_count",
|
||||
"approved_with_network_policy_allow_count",
|
||||
"denied_count",
|
||||
"denied_with_network_policy_deny_count",
|
||||
"request_count"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ContentItem": {
|
||||
"oneOf": [
|
||||
{
|
||||
@@ -256,6 +311,21 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"PrimitiveMetadata": {
|
||||
"properties": {
|
||||
"approval_summary": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ApprovalSummary"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"ReasoningItemContent": {
|
||||
"oneOf": [
|
||||
{
|
||||
@@ -440,6 +510,16 @@
|
||||
],
|
||||
"writeOnly": true
|
||||
},
|
||||
"primitive_metadata": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PrimitiveMetadata"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
"$ref": "#/definitions/LocalShellStatus"
|
||||
},
|
||||
@@ -477,6 +557,16 @@
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"primitive_metadata": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PrimitiveMetadata"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"function_call"
|
||||
@@ -536,6 +626,16 @@
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"primitive_metadata": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PrimitiveMetadata"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
"type": [
|
||||
"string",
|
||||
|
||||
@@ -1,6 +1,61 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"definitions": {
|
||||
"ApprovalSummary": {
|
||||
"properties": {
|
||||
"abort_count": {
|
||||
"format": "uint16",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"approved_count": {
|
||||
"format": "uint16",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"approved_for_session_count": {
|
||||
"format": "uint16",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"approved_with_amendment_count": {
|
||||
"format": "uint16",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"approved_with_network_policy_allow_count": {
|
||||
"format": "uint16",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"denied_count": {
|
||||
"format": "uint16",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"denied_with_network_policy_deny_count": {
|
||||
"format": "uint16",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
},
|
||||
"request_count": {
|
||||
"format": "uint16",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"abort_count",
|
||||
"approved_count",
|
||||
"approved_for_session_count",
|
||||
"approved_with_amendment_count",
|
||||
"approved_with_network_policy_allow_count",
|
||||
"denied_count",
|
||||
"denied_with_network_policy_deny_count",
|
||||
"request_count"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"AskForApproval": {
|
||||
"oneOf": [
|
||||
{
|
||||
@@ -306,6 +361,21 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"PrimitiveMetadata": {
|
||||
"properties": {
|
||||
"approval_summary": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ApprovalSummary"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"ReasoningItemContent": {
|
||||
"oneOf": [
|
||||
{
|
||||
@@ -490,6 +560,16 @@
|
||||
],
|
||||
"writeOnly": true
|
||||
},
|
||||
"primitive_metadata": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PrimitiveMetadata"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
"$ref": "#/definitions/LocalShellStatus"
|
||||
},
|
||||
@@ -527,6 +607,16 @@
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"primitive_metadata": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PrimitiveMetadata"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"function_call"
|
||||
@@ -586,6 +676,16 @@
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"primitive_metadata": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PrimitiveMetadata"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
"type": [
|
||||
"string",
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
// GENERATED CODE! DO NOT MODIFY BY HAND!
|
||||
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export type ApprovalSummary = { request_count: number, approved_count: number, approved_with_amendment_count: number, approved_for_session_count: number, approved_with_network_policy_allow_count: number, denied_with_network_policy_deny_count: number, denied_count: number, abort_count: number, };
|
||||
@@ -0,0 +1,6 @@
|
||||
// GENERATED CODE! DO NOT MODIFY BY HAND!
|
||||
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { ApprovalSummary } from "./ApprovalSummary";
|
||||
|
||||
export type PrimitiveMetadata = { approval_summary?: ApprovalSummary, };
|
||||
@@ -7,6 +7,7 @@ import type { GhostCommit } from "./GhostCommit";
|
||||
import type { LocalShellAction } from "./LocalShellAction";
|
||||
import type { LocalShellStatus } from "./LocalShellStatus";
|
||||
import type { MessagePhase } from "./MessagePhase";
|
||||
import type { PrimitiveMetadata } from "./PrimitiveMetadata";
|
||||
import type { ReasoningItemContent } from "./ReasoningItemContent";
|
||||
import type { ReasoningItemReasoningSummary } from "./ReasoningItemReasoningSummary";
|
||||
import type { WebSearchAction } from "./WebSearchAction";
|
||||
@@ -15,4 +16,4 @@ export type ResponseItem = { "type": "message", role: string, content: Array<Con
|
||||
/**
|
||||
* Set when using the Responses API.
|
||||
*/
|
||||
call_id: string | null, status: LocalShellStatus, action: LocalShellAction, } | { "type": "function_call", name: string, arguments: string, call_id: string, } | { "type": "function_call_output", call_id: string, output: FunctionCallOutputPayload, } | { "type": "custom_tool_call", status?: string, call_id: string, name: string, input: string, } | { "type": "custom_tool_call_output", call_id: string, output: FunctionCallOutputPayload, } | { "type": "web_search_call", status?: string, action?: WebSearchAction, } | { "type": "ghost_snapshot", ghost_commit: GhostCommit, } | { "type": "compaction", encrypted_content: string, } | { "type": "other" };
|
||||
call_id: string | null, status: LocalShellStatus, action: LocalShellAction, primitive_metadata?: PrimitiveMetadata, } | { "type": "function_call", name: string, arguments: string, call_id: string, primitive_metadata?: PrimitiveMetadata, } | { "type": "function_call_output", call_id: string, output: FunctionCallOutputPayload, } | { "type": "custom_tool_call", status?: string, call_id: string, name: string, input: string, primitive_metadata?: PrimitiveMetadata, } | { "type": "custom_tool_call_output", call_id: string, output: FunctionCallOutputPayload, } | { "type": "web_search_call", status?: string, action?: WebSearchAction, } | { "type": "ghost_snapshot", ghost_commit: GhostCommit, } | { "type": "compaction", encrypted_content: string, } | { "type": "other" };
|
||||
|
||||
@@ -17,6 +17,7 @@ export type { AgentStatus } from "./AgentStatus";
|
||||
export type { ApplyPatchApprovalParams } from "./ApplyPatchApprovalParams";
|
||||
export type { ApplyPatchApprovalRequestEvent } from "./ApplyPatchApprovalRequestEvent";
|
||||
export type { ApplyPatchApprovalResponse } from "./ApplyPatchApprovalResponse";
|
||||
export type { ApprovalSummary } from "./ApprovalSummary";
|
||||
export type { ArchiveConversationParams } from "./ArchiveConversationParams";
|
||||
export type { ArchiveConversationResponse } from "./ArchiveConversationResponse";
|
||||
export type { AskForApproval } from "./AskForApproval";
|
||||
@@ -151,6 +152,7 @@ export type { PlanDeltaEvent } from "./PlanDeltaEvent";
|
||||
export type { PlanItem } from "./PlanItem";
|
||||
export type { PlanItemArg } from "./PlanItemArg";
|
||||
export type { PlanType } from "./PlanType";
|
||||
export type { PrimitiveMetadata } from "./PrimitiveMetadata";
|
||||
export type { Profile } from "./Profile";
|
||||
export type { RateLimitSnapshot } from "./RateLimitSnapshot";
|
||||
export type { RateLimitWindow } from "./RateLimitWindow";
|
||||
|
||||
@@ -179,6 +179,7 @@ impl ThreadHistoryBuilder {
|
||||
RolloutItem::Compacted(payload) => self.handle_compacted(payload),
|
||||
RolloutItem::TurnContext(_)
|
||||
| RolloutItem::SessionMeta(_)
|
||||
| RolloutItem::ResponseItemPrimitiveMetadataUpdate(_)
|
||||
| RolloutItem::ResponseItem(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -851,6 +851,7 @@ mod tests {
|
||||
name: "spawn_agent".to_string(),
|
||||
arguments: "{}".to_string(),
|
||||
call_id: parent_spawn_call_id.clone(),
|
||||
primitive_metadata: None,
|
||||
};
|
||||
parent_thread
|
||||
.codex
|
||||
@@ -933,6 +934,7 @@ mod tests {
|
||||
name: "spawn_agent".to_string(),
|
||||
arguments: "{}".to_string(),
|
||||
call_id: parent_spawn_call_id.clone(),
|
||||
primitive_metadata: None,
|
||||
};
|
||||
parent_thread
|
||||
.codex
|
||||
@@ -1008,6 +1010,7 @@ mod tests {
|
||||
name: "spawn_agent".to_string(),
|
||||
arguments: "{}".to_string(),
|
||||
call_id: parent_spawn_call_id.clone(),
|
||||
primitive_metadata: None,
|
||||
};
|
||||
parent_thread
|
||||
.codex
|
||||
|
||||
@@ -79,6 +79,7 @@ fn reserialize_shell_outputs(items: &mut [ResponseItem]) {
|
||||
call_id,
|
||||
name,
|
||||
input: _,
|
||||
..
|
||||
} => {
|
||||
if name == "apply_patch" {
|
||||
shell_call_ids.insert(call_id.clone());
|
||||
@@ -349,6 +350,7 @@ mod tests {
|
||||
name: "shell".to_string(),
|
||||
arguments: "{}".to_string(),
|
||||
call_id: "call-1".to_string(),
|
||||
primitive_metadata: None,
|
||||
},
|
||||
ResponseItem::FunctionCallOutput {
|
||||
call_id: "call-1".to_string(),
|
||||
@@ -360,6 +362,7 @@ mod tests {
|
||||
call_id: "call-2".to_string(),
|
||||
name: "apply_patch".to_string(),
|
||||
input: "*** Begin Patch".to_string(),
|
||||
primitive_metadata: None,
|
||||
},
|
||||
ResponseItem::CustomToolCallOutput {
|
||||
call_id: "call-2".to_string(),
|
||||
@@ -377,6 +380,7 @@ mod tests {
|
||||
name: "shell".to_string(),
|
||||
arguments: "{}".to_string(),
|
||||
call_id: "call-1".to_string(),
|
||||
primitive_metadata: None,
|
||||
},
|
||||
ResponseItem::FunctionCallOutput {
|
||||
call_id: "call-1".to_string(),
|
||||
@@ -388,6 +392,7 @@ mod tests {
|
||||
call_id: "call-2".to_string(),
|
||||
name: "apply_patch".to_string(),
|
||||
input: "*** Begin Patch".to_string(),
|
||||
primitive_metadata: None,
|
||||
},
|
||||
ResponseItem::CustomToolCallOutput {
|
||||
call_id: "call-2".to_string(),
|
||||
|
||||
@@ -77,8 +77,10 @@ use codex_protocol::items::PlanItem;
|
||||
use codex_protocol::items::TurnItem;
|
||||
use codex_protocol::items::UserMessageItem;
|
||||
use codex_protocol::mcp::CallToolResult;
|
||||
use codex_protocol::models::ApprovalSummary;
|
||||
use codex_protocol::models::BaseInstructions;
|
||||
use codex_protocol::models::PermissionProfile;
|
||||
use codex_protocol::models::PrimitiveMetadata;
|
||||
use codex_protocol::models::format_allow_prefixes;
|
||||
use codex_protocol::openai_models::ModelInfo;
|
||||
use codex_protocol::protocol::FileChange;
|
||||
@@ -86,6 +88,7 @@ use codex_protocol::protocol::HasLegacyEvent;
|
||||
use codex_protocol::protocol::ItemCompletedEvent;
|
||||
use codex_protocol::protocol::ItemStartedEvent;
|
||||
use codex_protocol::protocol::RawResponseItemEvent;
|
||||
use codex_protocol::protocol::ResponseItemPrimitiveMetadataUpdate;
|
||||
use codex_protocol::protocol::ReviewRequest;
|
||||
use codex_protocol::protocol::RolloutItem;
|
||||
use codex_protocol::protocol::SessionSource;
|
||||
@@ -2645,19 +2648,29 @@ impl Session {
|
||||
let effective_approval_id = approval_id.clone().unwrap_or_else(|| call_id.clone());
|
||||
// Add the tx_approve callback to the map before sending the request.
|
||||
let (tx_approve, rx_approve) = oneshot::channel();
|
||||
let prev_entry = {
|
||||
let (prev_entry, approval_summary) = {
|
||||
let mut active = self.active_turn.lock().await;
|
||||
match active.as_mut() {
|
||||
Some(at) => {
|
||||
let mut ts = at.turn_state.lock().await;
|
||||
ts.insert_pending_approval(effective_approval_id.clone(), tx_approve)
|
||||
let approval_summary = ts.record_approval_request(&call_id);
|
||||
let prev_entry = ts.insert_pending_approval(
|
||||
effective_approval_id.clone(),
|
||||
call_id.clone(),
|
||||
tx_approve,
|
||||
);
|
||||
(prev_entry, Some(approval_summary))
|
||||
}
|
||||
None => None,
|
||||
None => (None, None),
|
||||
}
|
||||
};
|
||||
if prev_entry.is_some() {
|
||||
warn!("Overwriting existing pending approval for call_id: {effective_approval_id}");
|
||||
}
|
||||
if let Some(approval_summary) = approval_summary {
|
||||
self.sync_work_item_approval_summary(&call_id, approval_summary)
|
||||
.await;
|
||||
}
|
||||
|
||||
let parsed_cmd = parse_command(&command);
|
||||
let proposed_network_policy_amendments = network_approval_context.as_ref().map(|context| {
|
||||
@@ -2709,19 +2722,29 @@ impl Session {
|
||||
// Add the tx_approve callback to the map before sending the request.
|
||||
let (tx_approve, rx_approve) = oneshot::channel();
|
||||
let approval_id = call_id.clone();
|
||||
let prev_entry = {
|
||||
let (prev_entry, approval_summary) = {
|
||||
let mut active = self.active_turn.lock().await;
|
||||
match active.as_mut() {
|
||||
Some(at) => {
|
||||
let mut ts = at.turn_state.lock().await;
|
||||
ts.insert_pending_approval(approval_id.clone(), tx_approve)
|
||||
let approval_summary = ts.record_approval_request(&call_id);
|
||||
let prev_entry = ts.insert_pending_approval(
|
||||
approval_id.clone(),
|
||||
call_id.clone(),
|
||||
tx_approve,
|
||||
);
|
||||
(prev_entry, Some(approval_summary))
|
||||
}
|
||||
None => None,
|
||||
None => (None, None),
|
||||
}
|
||||
};
|
||||
if prev_entry.is_some() {
|
||||
warn!("Overwriting existing pending approval for call_id: {approval_id}");
|
||||
}
|
||||
if let Some(approval_summary) = approval_summary {
|
||||
self.sync_work_item_approval_summary(&call_id, approval_summary)
|
||||
.await;
|
||||
}
|
||||
|
||||
let event = EventMsg::ApplyPatchApprovalRequest(ApplyPatchApprovalRequestEvent {
|
||||
call_id,
|
||||
@@ -2813,19 +2836,33 @@ impl Session {
|
||||
}
|
||||
|
||||
pub async fn notify_approval(&self, approval_id: &str, decision: ReviewDecision) {
|
||||
let entry = {
|
||||
let (entry, approval_update) = {
|
||||
let mut active = self.active_turn.lock().await;
|
||||
match active.as_mut() {
|
||||
Some(at) => {
|
||||
let mut ts = at.turn_state.lock().await;
|
||||
ts.remove_pending_approval(approval_id)
|
||||
match ts.remove_pending_approval(approval_id) {
|
||||
Some(entry) => {
|
||||
let approval_summary =
|
||||
ts.record_approval_decision(&entry.work_item_call_id, &decision);
|
||||
(
|
||||
Some(entry.tx),
|
||||
Some((entry.work_item_call_id, approval_summary)),
|
||||
)
|
||||
}
|
||||
None => (None, None),
|
||||
}
|
||||
}
|
||||
None => None,
|
||||
None => (None, None),
|
||||
}
|
||||
};
|
||||
match entry {
|
||||
Some(tx_approve) => {
|
||||
tx_approve.send(decision).ok();
|
||||
if let Some((work_item_call_id, approval_summary)) = approval_update {
|
||||
self.sync_work_item_approval_summary(&work_item_call_id, approval_summary)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
None => {
|
||||
warn!("No pending approval found for call_id: {approval_id}");
|
||||
@@ -2854,9 +2891,12 @@ impl Session {
|
||||
turn_context: &TurnContext,
|
||||
items: &[ResponseItem],
|
||||
) {
|
||||
self.record_into_history(items, turn_context).await;
|
||||
self.persist_rollout_response_items(items).await;
|
||||
self.send_raw_response_items(turn_context, items).await;
|
||||
let items = self
|
||||
.enrich_response_items_with_primitive_metadata(items)
|
||||
.await;
|
||||
self.record_into_history(&items, turn_context).await;
|
||||
self.persist_rollout_response_items(&items).await;
|
||||
self.send_raw_response_items(turn_context, &items).await;
|
||||
}
|
||||
|
||||
/// Append ResponseItems to the in-memory conversation history only.
|
||||
@@ -2962,6 +3002,58 @@ impl Session {
|
||||
self.persist_rollout_items(&rollout_items).await;
|
||||
}
|
||||
|
||||
async fn enrich_response_items_with_primitive_metadata(
|
||||
&self,
|
||||
items: &[ResponseItem],
|
||||
) -> Vec<ResponseItem> {
|
||||
let mut enriched = Vec::with_capacity(items.len());
|
||||
for item in items.iter().cloned() {
|
||||
let mut item = item;
|
||||
if let Some(call_id) = item.work_item_call_id().map(str::to_string)
|
||||
&& let Some(approval_summary) = self
|
||||
.approval_summary_for_active_turn_call_id(&call_id)
|
||||
.await
|
||||
{
|
||||
item.set_primitive_metadata(Some(PrimitiveMetadata::with_approval_summary(
|
||||
approval_summary,
|
||||
)));
|
||||
}
|
||||
enriched.push(item);
|
||||
}
|
||||
enriched
|
||||
}
|
||||
|
||||
async fn approval_summary_for_active_turn_call_id(
|
||||
&self,
|
||||
call_id: &str,
|
||||
) -> Option<ApprovalSummary> {
|
||||
let active = self.active_turn.lock().await;
|
||||
let turn_state = active.as_ref()?.turn_state.lock().await;
|
||||
turn_state.approval_summary(call_id)
|
||||
}
|
||||
|
||||
async fn sync_work_item_approval_summary(
|
||||
&self,
|
||||
call_id: &str,
|
||||
approval_summary: ApprovalSummary,
|
||||
) {
|
||||
let primitive_metadata = PrimitiveMetadata::with_approval_summary(approval_summary);
|
||||
let history_updated = {
|
||||
let mut state = self.state.lock().await;
|
||||
state.update_primitive_metadata(call_id, primitive_metadata.clone())
|
||||
};
|
||||
if !history_updated {
|
||||
return;
|
||||
}
|
||||
self.persist_rollout_items(&[RolloutItem::ResponseItemPrimitiveMetadataUpdate(
|
||||
ResponseItemPrimitiveMetadataUpdate {
|
||||
call_id: call_id.to_string(),
|
||||
primitive_metadata,
|
||||
},
|
||||
)])
|
||||
.await;
|
||||
}
|
||||
|
||||
pub fn enabled(&self, feature: Feature) -> bool {
|
||||
self.features.enabled(feature)
|
||||
}
|
||||
@@ -6736,6 +6828,7 @@ mod tests {
|
||||
name: name.to_string(),
|
||||
arguments: "{}".to_string(),
|
||||
call_id: call_id.to_string(),
|
||||
primitive_metadata: None,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -9485,6 +9578,7 @@ mod tests {
|
||||
call_id: "call-1".to_string(),
|
||||
name: "shell".to_string(),
|
||||
input: "{}".to_string(),
|
||||
primitive_metadata: None,
|
||||
};
|
||||
|
||||
let call = ToolRouter::build_tool_call(session.as_ref(), item.clone())
|
||||
|
||||
@@ -202,6 +202,7 @@ impl Session {
|
||||
}
|
||||
}
|
||||
RolloutItem::ResponseItem(_)
|
||||
| RolloutItem::ResponseItemPrimitiveMetadataUpdate(_)
|
||||
| RolloutItem::EventMsg(_)
|
||||
| RolloutItem::SessionMeta(_) => {}
|
||||
}
|
||||
@@ -243,6 +244,12 @@ impl Session {
|
||||
turn_context.truncation_policy,
|
||||
);
|
||||
}
|
||||
RolloutItem::ResponseItemPrimitiveMetadataUpdate(update) => {
|
||||
history.update_primitive_metadata(
|
||||
&update.call_id,
|
||||
update.primitive_metadata.clone(),
|
||||
);
|
||||
}
|
||||
RolloutItem::Compacted(compacted) => {
|
||||
if let Some(replacement_history) = &compacted.replacement_history {
|
||||
// This should actually never happen, because the reverse loop above (to build rollout_suffix)
|
||||
|
||||
@@ -4,7 +4,9 @@ use crate::protocol::CompactedItem;
|
||||
use crate::protocol::InitialHistory;
|
||||
use crate::protocol::ResumedHistory;
|
||||
use codex_protocol::ThreadId;
|
||||
use codex_protocol::models::ApprovalSummary;
|
||||
use codex_protocol::models::ContentItem;
|
||||
use codex_protocol::models::PrimitiveMetadata;
|
||||
use codex_protocol::models::ResponseItem;
|
||||
use pretty_assertions::assert_eq;
|
||||
use std::path::PathBuf;
|
||||
@@ -33,6 +35,24 @@ fn assistant_message(text: &str) -> ResponseItem {
|
||||
}
|
||||
}
|
||||
|
||||
fn approval_metadata(request_count: u16, denied_count: u16) -> PrimitiveMetadata {
|
||||
PrimitiveMetadata::with_approval_summary(ApprovalSummary {
|
||||
request_count,
|
||||
denied_count,
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
|
||||
fn function_call(call_id: &str) -> ResponseItem {
|
||||
ResponseItem::FunctionCall {
|
||||
id: None,
|
||||
name: "local_shell".to_string(),
|
||||
arguments: "{\"cmd\":\"pwd\"}".to_string(),
|
||||
call_id: call_id.to_string(),
|
||||
primitive_metadata: None,
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn record_initial_history_resumed_bare_turn_context_does_not_hydrate_previous_turn_settings()
|
||||
{
|
||||
@@ -71,6 +91,40 @@ async fn record_initial_history_resumed_bare_turn_context_does_not_hydrate_previ
|
||||
assert!(session.reference_context_item().await.is_none());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn record_initial_history_resumed_applies_response_item_metadata_updates() {
|
||||
let (session, _turn_context) = make_session_and_context().await;
|
||||
let rollout_items = vec![
|
||||
RolloutItem::ResponseItem(function_call("call-1")),
|
||||
RolloutItem::ResponseItemPrimitiveMetadataUpdate(
|
||||
codex_protocol::protocol::ResponseItemPrimitiveMetadataUpdate {
|
||||
call_id: "call-1".to_string(),
|
||||
primitive_metadata: approval_metadata(2, 1),
|
||||
},
|
||||
),
|
||||
];
|
||||
|
||||
session
|
||||
.record_initial_history(InitialHistory::Resumed(ResumedHistory {
|
||||
conversation_id: ThreadId::default(),
|
||||
history: rollout_items,
|
||||
rollout_path: PathBuf::from("/tmp/resume.jsonl"),
|
||||
}))
|
||||
.await;
|
||||
|
||||
let history = session.clone_history().await;
|
||||
assert_eq!(
|
||||
history.raw_items(),
|
||||
&[ResponseItem::FunctionCall {
|
||||
id: None,
|
||||
name: "local_shell".to_string(),
|
||||
arguments: "{\"cmd\":\"pwd\"}".to_string(),
|
||||
call_id: "call-1".to_string(),
|
||||
primitive_metadata: Some(approval_metadata(2, 1)),
|
||||
}]
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn record_initial_history_resumed_hydrates_previous_turn_settings_from_lifecycle_turn_with_missing_turn_context_id()
|
||||
{
|
||||
|
||||
@@ -522,6 +522,7 @@ mod tests {
|
||||
call_id: "call-1".to_string(),
|
||||
name: "tool".to_string(),
|
||||
input: "{}".to_string(),
|
||||
primitive_metadata: None,
|
||||
},
|
||||
}),
|
||||
})
|
||||
|
||||
@@ -11,6 +11,7 @@ use codex_protocol::models::ContentItem;
|
||||
use codex_protocol::models::FunctionCallOutputBody;
|
||||
use codex_protocol::models::FunctionCallOutputContentItem;
|
||||
use codex_protocol::models::FunctionCallOutputPayload;
|
||||
use codex_protocol::models::PrimitiveMetadata;
|
||||
use codex_protocol::models::ResponseItem;
|
||||
use codex_protocol::openai_models::InputModality;
|
||||
use codex_protocol::protocol::TokenUsage;
|
||||
@@ -163,6 +164,20 @@ impl ContextManager {
|
||||
self.items = items;
|
||||
}
|
||||
|
||||
pub(crate) fn update_primitive_metadata(
|
||||
&mut self,
|
||||
call_id: &str,
|
||||
primitive_metadata: PrimitiveMetadata,
|
||||
) -> bool {
|
||||
for item in self.items.iter_mut().rev() {
|
||||
if item.work_item_call_id() == Some(call_id) {
|
||||
item.set_primitive_metadata(Some(primitive_metadata));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
/// Replace image content in the last turn if it originated from a tool output.
|
||||
/// Returns true when a tool image was replaced, false otherwise.
|
||||
pub(crate) fn replace_last_turn_images(&mut self, placeholder: &str) -> bool {
|
||||
|
||||
@@ -2,6 +2,7 @@ use super::*;
|
||||
use crate::truncate;
|
||||
use crate::truncate::TruncationPolicy;
|
||||
use codex_git::GhostCommit;
|
||||
use codex_protocol::models::ApprovalSummary;
|
||||
use codex_protocol::models::BaseInstructions;
|
||||
use codex_protocol::models::ContentItem;
|
||||
use codex_protocol::models::FunctionCallOutputBody;
|
||||
@@ -10,6 +11,7 @@ use codex_protocol::models::FunctionCallOutputPayload;
|
||||
use codex_protocol::models::LocalShellAction;
|
||||
use codex_protocol::models::LocalShellExecAction;
|
||||
use codex_protocol::models::LocalShellStatus;
|
||||
use codex_protocol::models::PrimitiveMetadata;
|
||||
use codex_protocol::models::ReasoningItemContent;
|
||||
use codex_protocol::models::ReasoningItemReasoningSummary;
|
||||
use codex_protocol::openai_models::InputModality;
|
||||
@@ -64,6 +66,14 @@ fn user_input_text_msg(text: &str) -> ResponseItem {
|
||||
}
|
||||
}
|
||||
|
||||
fn approval_metadata(request_count: u16, approved_count: u16) -> PrimitiveMetadata {
|
||||
PrimitiveMetadata::with_approval_summary(ApprovalSummary {
|
||||
request_count,
|
||||
approved_count,
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
|
||||
fn custom_tool_call_output(call_id: &str, output: &str) -> ResponseItem {
|
||||
ResponseItem::CustomToolCallOutput {
|
||||
call_id: call_id.to_string(),
|
||||
@@ -161,6 +171,78 @@ fn filters_non_api_messages() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn update_primitive_metadata_updates_work_items_by_call_id() {
|
||||
let mut history = create_history_with_items(vec![
|
||||
ResponseItem::FunctionCall {
|
||||
id: None,
|
||||
name: "tool_a".to_string(),
|
||||
arguments: "{}".to_string(),
|
||||
call_id: "function-1".to_string(),
|
||||
primitive_metadata: None,
|
||||
},
|
||||
ResponseItem::CustomToolCall {
|
||||
id: None,
|
||||
status: None,
|
||||
call_id: "custom-1".to_string(),
|
||||
name: "tool_b".to_string(),
|
||||
input: "{}".to_string(),
|
||||
primitive_metadata: None,
|
||||
},
|
||||
ResponseItem::LocalShellCall {
|
||||
id: None,
|
||||
call_id: Some("shell-1".to_string()),
|
||||
status: LocalShellStatus::Completed,
|
||||
action: LocalShellAction::Exec(LocalShellExecAction {
|
||||
command: vec!["pwd".to_string()],
|
||||
timeout_ms: None,
|
||||
working_directory: None,
|
||||
env: None,
|
||||
user: None,
|
||||
}),
|
||||
primitive_metadata: None,
|
||||
},
|
||||
]);
|
||||
|
||||
assert!(history.update_primitive_metadata("function-1", approval_metadata(1, 1)));
|
||||
assert!(history.update_primitive_metadata("custom-1", approval_metadata(2, 1)));
|
||||
assert!(history.update_primitive_metadata("shell-1", approval_metadata(3, 2)));
|
||||
|
||||
assert_eq!(
|
||||
history.raw_items(),
|
||||
[
|
||||
ResponseItem::FunctionCall {
|
||||
id: None,
|
||||
name: "tool_a".to_string(),
|
||||
arguments: "{}".to_string(),
|
||||
call_id: "function-1".to_string(),
|
||||
primitive_metadata: Some(approval_metadata(1, 1)),
|
||||
},
|
||||
ResponseItem::CustomToolCall {
|
||||
id: None,
|
||||
status: None,
|
||||
call_id: "custom-1".to_string(),
|
||||
name: "tool_b".to_string(),
|
||||
input: "{}".to_string(),
|
||||
primitive_metadata: Some(approval_metadata(2, 1)),
|
||||
},
|
||||
ResponseItem::LocalShellCall {
|
||||
id: None,
|
||||
call_id: Some("shell-1".to_string()),
|
||||
status: LocalShellStatus::Completed,
|
||||
action: LocalShellAction::Exec(LocalShellExecAction {
|
||||
command: vec!["pwd".to_string()],
|
||||
timeout_ms: None,
|
||||
working_directory: None,
|
||||
env: None,
|
||||
user: None,
|
||||
}),
|
||||
primitive_metadata: Some(approval_metadata(3, 2)),
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn non_last_reasoning_tokens_return_zero_when_no_user_messages() {
|
||||
let history = create_history_with_items(vec![reasoning_with_encrypted_content(800)]);
|
||||
@@ -267,6 +349,7 @@ fn for_prompt_strips_images_when_model_does_not_support_images() {
|
||||
name: "view_image".to_string(),
|
||||
arguments: "{}".to_string(),
|
||||
call_id: "call-1".to_string(),
|
||||
primitive_metadata: None,
|
||||
},
|
||||
ResponseItem::FunctionCallOutput {
|
||||
call_id: "call-1".to_string(),
|
||||
@@ -285,6 +368,7 @@ fn for_prompt_strips_images_when_model_does_not_support_images() {
|
||||
call_id: "tool-1".to_string(),
|
||||
name: "js_repl".to_string(),
|
||||
input: "view_image".to_string(),
|
||||
primitive_metadata: None,
|
||||
},
|
||||
ResponseItem::CustomToolCallOutput {
|
||||
call_id: "tool-1".to_string(),
|
||||
@@ -326,6 +410,7 @@ fn for_prompt_strips_images_when_model_does_not_support_images() {
|
||||
name: "view_image".to_string(),
|
||||
arguments: "{}".to_string(),
|
||||
call_id: "call-1".to_string(),
|
||||
primitive_metadata: None,
|
||||
},
|
||||
ResponseItem::FunctionCallOutput {
|
||||
call_id: "call-1".to_string(),
|
||||
@@ -345,6 +430,7 @@ fn for_prompt_strips_images_when_model_does_not_support_images() {
|
||||
call_id: "tool-1".to_string(),
|
||||
name: "js_repl".to_string(),
|
||||
input: "view_image".to_string(),
|
||||
primitive_metadata: None,
|
||||
},
|
||||
ResponseItem::CustomToolCallOutput {
|
||||
call_id: "tool-1".to_string(),
|
||||
@@ -428,6 +514,7 @@ fn remove_first_item_removes_matching_output_for_function_call() {
|
||||
name: "do_it".to_string(),
|
||||
arguments: "{}".to_string(),
|
||||
call_id: "call-1".to_string(),
|
||||
primitive_metadata: None,
|
||||
},
|
||||
ResponseItem::FunctionCallOutput {
|
||||
call_id: "call-1".to_string(),
|
||||
@@ -451,6 +538,7 @@ fn remove_first_item_removes_matching_call_for_output() {
|
||||
name: "do_it".to_string(),
|
||||
arguments: "{}".to_string(),
|
||||
call_id: "call-2".to_string(),
|
||||
primitive_metadata: None,
|
||||
},
|
||||
];
|
||||
let mut h = create_history_with_items(items);
|
||||
@@ -467,6 +555,7 @@ fn remove_last_item_removes_matching_call_for_output() {
|
||||
name: "do_it".to_string(),
|
||||
arguments: "{}".to_string(),
|
||||
call_id: "call-delete-last".to_string(),
|
||||
primitive_metadata: None,
|
||||
},
|
||||
ResponseItem::FunctionCallOutput {
|
||||
call_id: "call-delete-last".to_string(),
|
||||
@@ -549,6 +638,7 @@ fn remove_first_item_handles_local_shell_pair() {
|
||||
env: None,
|
||||
user: None,
|
||||
}),
|
||||
primitive_metadata: None,
|
||||
},
|
||||
ResponseItem::FunctionCallOutput {
|
||||
call_id: "call-3".to_string(),
|
||||
@@ -705,6 +795,7 @@ fn remove_first_item_handles_custom_tool_pair() {
|
||||
call_id: "tool-1".to_string(),
|
||||
name: "my_tool".to_string(),
|
||||
input: "{}".to_string(),
|
||||
primitive_metadata: None,
|
||||
},
|
||||
ResponseItem::CustomToolCallOutput {
|
||||
call_id: "tool-1".to_string(),
|
||||
@@ -730,6 +821,7 @@ fn normalization_retains_local_shell_outputs() {
|
||||
env: None,
|
||||
user: None,
|
||||
}),
|
||||
primitive_metadata: None,
|
||||
},
|
||||
ResponseItem::FunctionCallOutput {
|
||||
call_id: "shell-1".to_string(),
|
||||
@@ -939,6 +1031,7 @@ fn normalize_adds_missing_output_for_function_call() {
|
||||
name: "do_it".to_string(),
|
||||
arguments: "{}".to_string(),
|
||||
call_id: "call-x".to_string(),
|
||||
primitive_metadata: None,
|
||||
}];
|
||||
let mut h = create_history_with_items(items);
|
||||
|
||||
@@ -952,6 +1045,7 @@ fn normalize_adds_missing_output_for_function_call() {
|
||||
name: "do_it".to_string(),
|
||||
arguments: "{}".to_string(),
|
||||
call_id: "call-x".to_string(),
|
||||
primitive_metadata: None,
|
||||
},
|
||||
ResponseItem::FunctionCallOutput {
|
||||
call_id: "call-x".to_string(),
|
||||
@@ -970,6 +1064,7 @@ fn normalize_adds_missing_output_for_custom_tool_call() {
|
||||
call_id: "tool-x".to_string(),
|
||||
name: "custom".to_string(),
|
||||
input: "{}".to_string(),
|
||||
primitive_metadata: None,
|
||||
}];
|
||||
let mut h = create_history_with_items(items);
|
||||
|
||||
@@ -984,6 +1079,7 @@ fn normalize_adds_missing_output_for_custom_tool_call() {
|
||||
call_id: "tool-x".to_string(),
|
||||
name: "custom".to_string(),
|
||||
input: "{}".to_string(),
|
||||
primitive_metadata: None,
|
||||
},
|
||||
ResponseItem::CustomToolCallOutput {
|
||||
call_id: "tool-x".to_string(),
|
||||
@@ -1007,6 +1103,7 @@ fn normalize_adds_missing_output_for_local_shell_call_with_id() {
|
||||
env: None,
|
||||
user: None,
|
||||
}),
|
||||
primitive_metadata: None,
|
||||
}];
|
||||
let mut h = create_history_with_items(items);
|
||||
|
||||
@@ -1026,6 +1123,7 @@ fn normalize_adds_missing_output_for_local_shell_call_with_id() {
|
||||
env: None,
|
||||
user: None,
|
||||
}),
|
||||
primitive_metadata: None,
|
||||
},
|
||||
ResponseItem::FunctionCallOutput {
|
||||
call_id: "shell-1".to_string(),
|
||||
@@ -1073,6 +1171,7 @@ fn normalize_mixed_inserts_and_removals() {
|
||||
name: "f1".to_string(),
|
||||
arguments: "{}".to_string(),
|
||||
call_id: "c1".to_string(),
|
||||
primitive_metadata: None,
|
||||
},
|
||||
// Orphan output that should be removed
|
||||
ResponseItem::FunctionCallOutput {
|
||||
@@ -1086,6 +1185,7 @@ fn normalize_mixed_inserts_and_removals() {
|
||||
call_id: "t1".to_string(),
|
||||
name: "tool".to_string(),
|
||||
input: "{}".to_string(),
|
||||
primitive_metadata: None,
|
||||
},
|
||||
// Local shell call also gets an inserted function call output
|
||||
ResponseItem::LocalShellCall {
|
||||
@@ -1099,6 +1199,7 @@ fn normalize_mixed_inserts_and_removals() {
|
||||
env: None,
|
||||
user: None,
|
||||
}),
|
||||
primitive_metadata: None,
|
||||
},
|
||||
];
|
||||
let mut h = create_history_with_items(items);
|
||||
@@ -1113,6 +1214,7 @@ fn normalize_mixed_inserts_and_removals() {
|
||||
name: "f1".to_string(),
|
||||
arguments: "{}".to_string(),
|
||||
call_id: "c1".to_string(),
|
||||
primitive_metadata: None,
|
||||
},
|
||||
ResponseItem::FunctionCallOutput {
|
||||
call_id: "c1".to_string(),
|
||||
@@ -1124,6 +1226,7 @@ fn normalize_mixed_inserts_and_removals() {
|
||||
call_id: "t1".to_string(),
|
||||
name: "tool".to_string(),
|
||||
input: "{}".to_string(),
|
||||
primitive_metadata: None,
|
||||
},
|
||||
ResponseItem::CustomToolCallOutput {
|
||||
call_id: "t1".to_string(),
|
||||
@@ -1140,6 +1243,7 @@ fn normalize_mixed_inserts_and_removals() {
|
||||
env: None,
|
||||
user: None,
|
||||
}),
|
||||
primitive_metadata: None,
|
||||
},
|
||||
ResponseItem::FunctionCallOutput {
|
||||
call_id: "s1".to_string(),
|
||||
@@ -1156,6 +1260,7 @@ fn normalize_adds_missing_output_for_function_call_inserts_output() {
|
||||
name: "do_it".to_string(),
|
||||
arguments: "{}".to_string(),
|
||||
call_id: "call-x".to_string(),
|
||||
primitive_metadata: None,
|
||||
}];
|
||||
let mut h = create_history_with_items(items);
|
||||
h.normalize_history(&default_input_modalities());
|
||||
@@ -1167,6 +1272,7 @@ fn normalize_adds_missing_output_for_function_call_inserts_output() {
|
||||
name: "do_it".to_string(),
|
||||
arguments: "{}".to_string(),
|
||||
call_id: "call-x".to_string(),
|
||||
primitive_metadata: None,
|
||||
},
|
||||
ResponseItem::FunctionCallOutput {
|
||||
call_id: "call-x".to_string(),
|
||||
@@ -1186,6 +1292,7 @@ fn normalize_adds_missing_output_for_custom_tool_call_panics_in_debug() {
|
||||
call_id: "tool-x".to_string(),
|
||||
name: "custom".to_string(),
|
||||
input: "{}".to_string(),
|
||||
primitive_metadata: None,
|
||||
}];
|
||||
let mut h = create_history_with_items(items);
|
||||
h.normalize_history(&default_input_modalities());
|
||||
@@ -1206,6 +1313,7 @@ fn normalize_adds_missing_output_for_local_shell_call_with_id_panics_in_debug()
|
||||
env: None,
|
||||
user: None,
|
||||
}),
|
||||
primitive_metadata: None,
|
||||
}];
|
||||
let mut h = create_history_with_items(items);
|
||||
h.normalize_history(&default_input_modalities());
|
||||
@@ -1245,6 +1353,7 @@ fn normalize_mixed_inserts_and_removals_panics_in_debug() {
|
||||
name: "f1".to_string(),
|
||||
arguments: "{}".to_string(),
|
||||
call_id: "c1".to_string(),
|
||||
primitive_metadata: None,
|
||||
},
|
||||
ResponseItem::FunctionCallOutput {
|
||||
call_id: "c2".to_string(),
|
||||
@@ -1256,6 +1365,7 @@ fn normalize_mixed_inserts_and_removals_panics_in_debug() {
|
||||
call_id: "t1".to_string(),
|
||||
name: "tool".to_string(),
|
||||
input: "{}".to_string(),
|
||||
primitive_metadata: None,
|
||||
},
|
||||
ResponseItem::LocalShellCall {
|
||||
id: None,
|
||||
@@ -1268,6 +1378,7 @@ fn normalize_mixed_inserts_and_removals_panics_in_debug() {
|
||||
env: None,
|
||||
user: None,
|
||||
}),
|
||||
primitive_metadata: None,
|
||||
},
|
||||
];
|
||||
let mut h = create_history_with_items(items);
|
||||
|
||||
@@ -1055,6 +1055,7 @@ async fn read_head_summary(path: &Path, head_limit: usize) -> io::Result<HeadTai
|
||||
.clone()
|
||||
.or_else(|| Some(rollout_line.timestamp.clone()));
|
||||
}
|
||||
RolloutItem::ResponseItemPrimitiveMetadataUpdate(_) => {}
|
||||
RolloutItem::TurnContext(_) => {
|
||||
// Not included in `head`; skip.
|
||||
}
|
||||
@@ -1112,7 +1113,8 @@ pub async fn read_head_for_summary(path: &Path) -> io::Result<Vec<serde_json::Va
|
||||
head.push(value);
|
||||
}
|
||||
}
|
||||
RolloutItem::Compacted(_)
|
||||
RolloutItem::ResponseItemPrimitiveMetadataUpdate(_)
|
||||
| RolloutItem::Compacted(_)
|
||||
| RolloutItem::TurnContext(_)
|
||||
| RolloutItem::EventMsg(_) => {}
|
||||
}
|
||||
|
||||
@@ -67,7 +67,8 @@ pub(crate) fn builder_from_items(
|
||||
) -> Option<ThreadMetadataBuilder> {
|
||||
if let Some(session_meta) = items.iter().find_map(|item| match item {
|
||||
RolloutItem::SessionMeta(meta_line) => Some(meta_line),
|
||||
RolloutItem::ResponseItem(_)
|
||||
RolloutItem::ResponseItemPrimitiveMetadataUpdate(_)
|
||||
| RolloutItem::ResponseItem(_)
|
||||
| RolloutItem::Compacted(_)
|
||||
| RolloutItem::TurnContext(_)
|
||||
| RolloutItem::EventMsg(_) => None,
|
||||
@@ -131,7 +132,8 @@ pub(crate) async fn extract_metadata_from_rollout(
|
||||
metadata,
|
||||
memory_mode: items.iter().rev().find_map(|item| match item {
|
||||
RolloutItem::SessionMeta(meta_line) => meta_line.meta.memory_mode.clone(),
|
||||
RolloutItem::ResponseItem(_)
|
||||
RolloutItem::ResponseItemPrimitiveMetadataUpdate(_)
|
||||
| RolloutItem::ResponseItem(_)
|
||||
| RolloutItem::Compacted(_)
|
||||
| RolloutItem::TurnContext(_)
|
||||
| RolloutItem::EventMsg(_) => None,
|
||||
|
||||
@@ -17,9 +17,10 @@ pub(crate) fn is_persisted_response_item(item: &RolloutItem, mode: EventPersiste
|
||||
RolloutItem::ResponseItem(item) => should_persist_response_item(item),
|
||||
RolloutItem::EventMsg(ev) => should_persist_event_msg(ev, mode),
|
||||
// Persist Codex executive markers so we can analyze flows (e.g., compaction, API turns).
|
||||
RolloutItem::Compacted(_) | RolloutItem::TurnContext(_) | RolloutItem::SessionMeta(_) => {
|
||||
true
|
||||
}
|
||||
RolloutItem::ResponseItemPrimitiveMetadataUpdate(_)
|
||||
| RolloutItem::Compacted(_)
|
||||
| RolloutItem::TurnContext(_)
|
||||
| RolloutItem::SessionMeta(_) => true,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -566,6 +566,9 @@ impl RolloutRecorder {
|
||||
RolloutItem::ResponseItem(item) => {
|
||||
items.push(RolloutItem::ResponseItem(item));
|
||||
}
|
||||
RolloutItem::ResponseItemPrimitiveMetadataUpdate(item) => {
|
||||
items.push(RolloutItem::ResponseItemPrimitiveMetadataUpdate(item));
|
||||
}
|
||||
RolloutItem::Compacted(item) => {
|
||||
items.push(RolloutItem::Compacted(item));
|
||||
}
|
||||
@@ -1012,6 +1015,7 @@ async fn resume_candidate_matches_cwd(
|
||||
&& let Some(latest_turn_context_cwd) = items.iter().rev().find_map(|item| match item {
|
||||
RolloutItem::TurnContext(turn_context) => Some(turn_context.cwd.as_path()),
|
||||
RolloutItem::SessionMeta(_)
|
||||
| RolloutItem::ResponseItemPrimitiveMetadataUpdate(_)
|
||||
| RolloutItem::ResponseItem(_)
|
||||
| RolloutItem::Compacted(_)
|
||||
| RolloutItem::EventMsg(_) => None,
|
||||
|
||||
@@ -123,6 +123,7 @@ mod tests {
|
||||
name: "tool".to_string(),
|
||||
arguments: "{}".to_string(),
|
||||
call_id: "c1".to_string(),
|
||||
primitive_metadata: None,
|
||||
},
|
||||
assistant_msg("a4"),
|
||||
];
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
//! Session-wide mutable state.
|
||||
|
||||
use codex_protocol::models::PrimitiveMetadata;
|
||||
use codex_protocol::models::ResponseItem;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::HashSet;
|
||||
@@ -85,6 +86,15 @@ impl SessionState {
|
||||
.set_reference_context_item(reference_context_item);
|
||||
}
|
||||
|
||||
pub(crate) fn update_primitive_metadata(
|
||||
&mut self,
|
||||
call_id: &str,
|
||||
primitive_metadata: PrimitiveMetadata,
|
||||
) -> bool {
|
||||
self.history
|
||||
.update_primitive_metadata(call_id, primitive_metadata)
|
||||
}
|
||||
|
||||
pub(crate) fn set_token_info(&mut self, info: Option<TokenUsageInfo>) {
|
||||
self.history.set_token_info(info);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ use tokio_util::sync::CancellationToken;
|
||||
use tokio_util::task::AbortOnDropHandle;
|
||||
|
||||
use codex_protocol::dynamic_tools::DynamicToolResponse;
|
||||
use codex_protocol::models::ApprovalSummary;
|
||||
use codex_protocol::models::ResponseInputItem;
|
||||
use codex_protocol::request_user_input::RequestUserInputResponse;
|
||||
use tokio::sync::oneshot;
|
||||
@@ -69,28 +70,64 @@ impl ActiveTurn {
|
||||
/// Mutable state for a single turn.
|
||||
#[derive(Default)]
|
||||
pub(crate) struct TurnState {
|
||||
pending_approvals: HashMap<String, oneshot::Sender<ReviewDecision>>,
|
||||
pending_approvals: HashMap<String, PendingApproval>,
|
||||
pending_user_input: HashMap<String, oneshot::Sender<RequestUserInputResponse>>,
|
||||
pending_dynamic_tools: HashMap<String, oneshot::Sender<DynamicToolResponse>>,
|
||||
pending_input: Vec<ResponseInputItem>,
|
||||
approval_summaries: HashMap<String, ApprovalSummary>,
|
||||
}
|
||||
|
||||
pub(crate) struct PendingApproval {
|
||||
pub(crate) tx: oneshot::Sender<ReviewDecision>,
|
||||
pub(crate) work_item_call_id: String,
|
||||
}
|
||||
|
||||
impl TurnState {
|
||||
pub(crate) fn insert_pending_approval(
|
||||
&mut self,
|
||||
key: String,
|
||||
work_item_call_id: String,
|
||||
tx: oneshot::Sender<ReviewDecision>,
|
||||
) -> Option<oneshot::Sender<ReviewDecision>> {
|
||||
self.pending_approvals.insert(key, tx)
|
||||
) -> Option<PendingApproval> {
|
||||
self.pending_approvals.insert(
|
||||
key,
|
||||
PendingApproval {
|
||||
tx,
|
||||
work_item_call_id,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn remove_pending_approval(
|
||||
&mut self,
|
||||
key: &str,
|
||||
) -> Option<oneshot::Sender<ReviewDecision>> {
|
||||
pub(crate) fn remove_pending_approval(&mut self, key: &str) -> Option<PendingApproval> {
|
||||
self.pending_approvals.remove(key)
|
||||
}
|
||||
|
||||
pub(crate) fn record_approval_request(&mut self, call_id: &str) -> ApprovalSummary {
|
||||
let summary = self
|
||||
.approval_summaries
|
||||
.entry(call_id.to_string())
|
||||
.or_default();
|
||||
summary.increment_request();
|
||||
*summary
|
||||
}
|
||||
|
||||
pub(crate) fn record_approval_decision(
|
||||
&mut self,
|
||||
call_id: &str,
|
||||
decision: &ReviewDecision,
|
||||
) -> ApprovalSummary {
|
||||
let summary = self
|
||||
.approval_summaries
|
||||
.entry(call_id.to_string())
|
||||
.or_default();
|
||||
summary.increment_decision(decision);
|
||||
*summary
|
||||
}
|
||||
|
||||
pub(crate) fn approval_summary(&self, call_id: &str) -> Option<ApprovalSummary> {
|
||||
self.approval_summaries.get(call_id).copied()
|
||||
}
|
||||
|
||||
pub(crate) fn clear_pending(&mut self) {
|
||||
self.pending_approvals.clear();
|
||||
self.pending_user_input.clear();
|
||||
|
||||
@@ -723,6 +723,7 @@ mod tests {
|
||||
call_id: "c1".to_string(),
|
||||
name: "tool".to_string(),
|
||||
arguments: "{}".to_string(),
|
||||
primitive_metadata: None,
|
||||
},
|
||||
assistant_msg("a4"),
|
||||
];
|
||||
|
||||
@@ -362,6 +362,7 @@ async fn resume_replays_legacy_js_repl_image_rollout_shapes() {
|
||||
call_id: "legacy-js-call".to_string(),
|
||||
name: "js_repl".to_string(),
|
||||
input: "console.log('legacy image flow')".to_string(),
|
||||
primitive_metadata: None,
|
||||
};
|
||||
let legacy_image_url = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR4nGP4z8DwHwAFAAH/iZk9HQAAAABJRU5ErkJggg==";
|
||||
let rollout = vec![
|
||||
@@ -1681,6 +1682,7 @@ async fn azure_responses_request_includes_store_and_reasoning_ids() {
|
||||
name: "do_thing".into(),
|
||||
arguments: "{}".into(),
|
||||
call_id: "function-call-id".into(),
|
||||
primitive_metadata: None,
|
||||
});
|
||||
prompt.input.push(ResponseItem::FunctionCallOutput {
|
||||
call_id: "function-call-id".into(),
|
||||
@@ -1697,6 +1699,7 @@ async fn azure_responses_request_includes_store_and_reasoning_ids() {
|
||||
env: None,
|
||||
user: None,
|
||||
}),
|
||||
primitive_metadata: None,
|
||||
});
|
||||
prompt.input.push(ResponseItem::CustomToolCall {
|
||||
id: Some("custom-tool-id".into()),
|
||||
@@ -1704,6 +1707,7 @@ async fn azure_responses_request_includes_store_and_reasoning_ids() {
|
||||
call_id: "custom-tool-call-id".into(),
|
||||
name: "custom_tool".into(),
|
||||
input: "{}".into(),
|
||||
primitive_metadata: None,
|
||||
});
|
||||
prompt.input.push(ResponseItem::CustomToolCallOutput {
|
||||
call_id: "custom-tool-call-id".into(),
|
||||
|
||||
@@ -14,8 +14,10 @@ use crate::protocol::AskForApproval;
|
||||
use crate::protocol::COLLABORATION_MODE_CLOSE_TAG;
|
||||
use crate::protocol::COLLABORATION_MODE_OPEN_TAG;
|
||||
use crate::protocol::NetworkAccess;
|
||||
use crate::protocol::NetworkPolicyRuleAction;
|
||||
use crate::protocol::REALTIME_CONVERSATION_CLOSE_TAG;
|
||||
use crate::protocol::REALTIME_CONVERSATION_OPEN_TAG;
|
||||
use crate::protocol::ReviewDecision;
|
||||
use crate::protocol::SandboxPolicy;
|
||||
use crate::protocol::WritableRoot;
|
||||
use crate::user_input::UserInput;
|
||||
@@ -191,6 +193,81 @@ pub enum MessagePhase {
|
||||
FinalAnswer,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema, TS)]
|
||||
pub struct ApprovalSummary {
|
||||
pub request_count: u16,
|
||||
pub approved_count: u16,
|
||||
pub approved_with_amendment_count: u16,
|
||||
pub approved_for_session_count: u16,
|
||||
pub approved_with_network_policy_allow_count: u16,
|
||||
pub denied_with_network_policy_deny_count: u16,
|
||||
pub denied_count: u16,
|
||||
pub abort_count: u16,
|
||||
}
|
||||
|
||||
impl ApprovalSummary {
|
||||
pub fn increment_request(&mut self) {
|
||||
self.request_count = self.request_count.saturating_add(1);
|
||||
}
|
||||
|
||||
pub fn increment_decision(&mut self, decision: &ReviewDecision) {
|
||||
match decision {
|
||||
ReviewDecision::Approved => {
|
||||
self.approved_count = self.approved_count.saturating_add(1);
|
||||
}
|
||||
ReviewDecision::ApprovedExecpolicyAmendment { .. } => {
|
||||
self.approved_with_amendment_count =
|
||||
self.approved_with_amendment_count.saturating_add(1);
|
||||
}
|
||||
ReviewDecision::ApprovedForSession => {
|
||||
self.approved_for_session_count = self.approved_for_session_count.saturating_add(1);
|
||||
}
|
||||
ReviewDecision::NetworkPolicyAmendment {
|
||||
network_policy_amendment,
|
||||
} => match network_policy_amendment.action {
|
||||
NetworkPolicyRuleAction::Allow => {
|
||||
self.approved_with_network_policy_allow_count = self
|
||||
.approved_with_network_policy_allow_count
|
||||
.saturating_add(1);
|
||||
}
|
||||
NetworkPolicyRuleAction::Deny => {
|
||||
self.denied_with_network_policy_deny_count =
|
||||
self.denied_with_network_policy_deny_count.saturating_add(1);
|
||||
}
|
||||
},
|
||||
ReviewDecision::Denied => {
|
||||
self.denied_count = self.denied_count.saturating_add(1);
|
||||
}
|
||||
ReviewDecision::Abort => {
|
||||
self.abort_count = self.abort_count.saturating_add(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
*self == Self::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema, TS)]
|
||||
pub struct PrimitiveMetadata {
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional)]
|
||||
pub approval_summary: Option<ApprovalSummary>,
|
||||
}
|
||||
|
||||
impl PrimitiveMetadata {
|
||||
pub fn with_approval_summary(approval_summary: ApprovalSummary) -> Self {
|
||||
Self {
|
||||
approval_summary: Some(approval_summary),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.approval_summary.is_none()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, JsonSchema, TS)]
|
||||
#[serde(tag = "type", rename_all = "snake_case")]
|
||||
pub enum ResponseItem {
|
||||
@@ -230,6 +307,9 @@ pub enum ResponseItem {
|
||||
call_id: Option<String>,
|
||||
status: LocalShellStatus,
|
||||
action: LocalShellAction,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional)]
|
||||
primitive_metadata: Option<PrimitiveMetadata>,
|
||||
},
|
||||
FunctionCall {
|
||||
#[serde(default, skip_serializing)]
|
||||
@@ -241,6 +321,9 @@ pub enum ResponseItem {
|
||||
// Session::handle_function_call parse it into a Value.
|
||||
arguments: String,
|
||||
call_id: String,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional)]
|
||||
primitive_metadata: Option<PrimitiveMetadata>,
|
||||
},
|
||||
// NOTE: The `output` field for `function_call_output` uses a dedicated payload type with
|
||||
// custom serialization. On the wire it is either:
|
||||
@@ -262,6 +345,9 @@ pub enum ResponseItem {
|
||||
call_id: String,
|
||||
name: String,
|
||||
input: String,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional)]
|
||||
primitive_metadata: Option<PrimitiveMetadata>,
|
||||
},
|
||||
// `custom_tool_call_output.output` uses the same wire encoding as
|
||||
// `function_call_output.output` so freeform tools can return either plain
|
||||
@@ -301,6 +387,73 @@ pub enum ResponseItem {
|
||||
Other,
|
||||
}
|
||||
|
||||
impl ResponseItem {
|
||||
pub fn work_item_call_id(&self) -> Option<&str> {
|
||||
match self {
|
||||
ResponseItem::LocalShellCall { call_id, id, .. } => {
|
||||
call_id.as_deref().or(id.as_deref())
|
||||
}
|
||||
ResponseItem::FunctionCall { call_id, .. }
|
||||
| ResponseItem::CustomToolCall { call_id, .. } => Some(call_id.as_str()),
|
||||
ResponseItem::Message { .. }
|
||||
| ResponseItem::Reasoning { .. }
|
||||
| ResponseItem::FunctionCallOutput { .. }
|
||||
| ResponseItem::CustomToolCallOutput { .. }
|
||||
| ResponseItem::WebSearchCall { .. }
|
||||
| ResponseItem::GhostSnapshot { .. }
|
||||
| ResponseItem::Compaction { .. }
|
||||
| ResponseItem::Other => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn primitive_metadata(&self) -> Option<&PrimitiveMetadata> {
|
||||
match self {
|
||||
ResponseItem::LocalShellCall {
|
||||
primitive_metadata, ..
|
||||
}
|
||||
| ResponseItem::FunctionCall {
|
||||
primitive_metadata, ..
|
||||
}
|
||||
| ResponseItem::CustomToolCall {
|
||||
primitive_metadata, ..
|
||||
} => primitive_metadata.as_ref(),
|
||||
ResponseItem::Message { .. }
|
||||
| ResponseItem::Reasoning { .. }
|
||||
| ResponseItem::FunctionCallOutput { .. }
|
||||
| ResponseItem::CustomToolCallOutput { .. }
|
||||
| ResponseItem::WebSearchCall { .. }
|
||||
| ResponseItem::GhostSnapshot { .. }
|
||||
| ResponseItem::Compaction { .. }
|
||||
| ResponseItem::Other => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_primitive_metadata(&mut self, primitive_metadata: Option<PrimitiveMetadata>) {
|
||||
match self {
|
||||
ResponseItem::LocalShellCall {
|
||||
primitive_metadata: item_primitive_metadata,
|
||||
..
|
||||
}
|
||||
| ResponseItem::FunctionCall {
|
||||
primitive_metadata: item_primitive_metadata,
|
||||
..
|
||||
}
|
||||
| ResponseItem::CustomToolCall {
|
||||
primitive_metadata: item_primitive_metadata,
|
||||
..
|
||||
} => *item_primitive_metadata = primitive_metadata.filter(|item| !item.is_empty()),
|
||||
ResponseItem::Message { .. }
|
||||
| ResponseItem::Reasoning { .. }
|
||||
| ResponseItem::FunctionCallOutput { .. }
|
||||
| ResponseItem::CustomToolCallOutput { .. }
|
||||
| ResponseItem::WebSearchCall { .. }
|
||||
| ResponseItem::GhostSnapshot { .. }
|
||||
| ResponseItem::Compaction { .. }
|
||||
| ResponseItem::Other => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub const BASE_INSTRUCTIONS_DEFAULT: &str = include_str!("prompts/base_instructions/default.md");
|
||||
|
||||
/// Base instructions for the model in a thread. Corresponds to the `instructions` field in the ResponsesAPI.
|
||||
@@ -1220,6 +1373,8 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::config_types::SandboxMode;
|
||||
use crate::protocol::AskForApproval;
|
||||
use crate::protocol::ExecPolicyAmendment;
|
||||
use crate::protocol::NetworkPolicyAmendment;
|
||||
use anyhow::Result;
|
||||
use codex_execpolicy::Policy;
|
||||
use pretty_assertions::assert_eq;
|
||||
@@ -1949,4 +2104,48 @@ mod tests {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn approval_summary_tracks_review_decisions() {
|
||||
let mut summary = ApprovalSummary::default();
|
||||
|
||||
summary.increment_request();
|
||||
summary.increment_request();
|
||||
summary.increment_decision(&ReviewDecision::Approved);
|
||||
summary.increment_decision(&ReviewDecision::ApprovedExecpolicyAmendment {
|
||||
proposed_execpolicy_amendment: ExecPolicyAmendment::from(vec![
|
||||
"git".to_string(),
|
||||
"status".to_string(),
|
||||
]),
|
||||
});
|
||||
summary.increment_decision(&ReviewDecision::ApprovedForSession);
|
||||
summary.increment_decision(&ReviewDecision::NetworkPolicyAmendment {
|
||||
network_policy_amendment: NetworkPolicyAmendment {
|
||||
host: "example.com".to_string(),
|
||||
action: NetworkPolicyRuleAction::Allow,
|
||||
},
|
||||
});
|
||||
summary.increment_decision(&ReviewDecision::NetworkPolicyAmendment {
|
||||
network_policy_amendment: NetworkPolicyAmendment {
|
||||
host: "example.com".to_string(),
|
||||
action: NetworkPolicyRuleAction::Deny,
|
||||
},
|
||||
});
|
||||
summary.increment_decision(&ReviewDecision::Denied);
|
||||
summary.increment_decision(&ReviewDecision::Abort);
|
||||
|
||||
assert_eq!(
|
||||
summary,
|
||||
ApprovalSummary {
|
||||
request_count: 2,
|
||||
approved_count: 1,
|
||||
approved_with_amendment_count: 1,
|
||||
approved_for_session_count: 1,
|
||||
approved_with_network_policy_allow_count: 1,
|
||||
denied_with_network_policy_deny_count: 1,
|
||||
denied_count: 1,
|
||||
abort_count: 1,
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ use crate::message_history::HistoryEntry;
|
||||
use crate::models::BaseInstructions;
|
||||
use crate::models::ContentItem;
|
||||
use crate::models::MessagePhase;
|
||||
use crate::models::PrimitiveMetadata;
|
||||
use crate::models::ResponseItem;
|
||||
use crate::models::WebSearchAction;
|
||||
use crate::num_format::format_with_separators;
|
||||
@@ -2097,11 +2098,18 @@ pub struct SessionMetaLine {
|
||||
pub enum RolloutItem {
|
||||
SessionMeta(SessionMetaLine),
|
||||
ResponseItem(ResponseItem),
|
||||
ResponseItemPrimitiveMetadataUpdate(ResponseItemPrimitiveMetadataUpdate),
|
||||
Compacted(CompactedItem),
|
||||
TurnContext(TurnContextItem),
|
||||
EventMsg(EventMsg),
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, JsonSchema, TS)]
|
||||
pub struct ResponseItemPrimitiveMetadataUpdate {
|
||||
pub call_id: String,
|
||||
pub primitive_metadata: PrimitiveMetadata,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, JsonSchema, TS)]
|
||||
pub struct CompactedItem {
|
||||
pub message: String,
|
||||
|
||||
@@ -22,6 +22,7 @@ pub fn apply_rollout_item(
|
||||
RolloutItem::TurnContext(turn_ctx) => apply_turn_context(metadata, turn_ctx),
|
||||
RolloutItem::EventMsg(event) => apply_event_msg(metadata, event),
|
||||
RolloutItem::ResponseItem(item) => apply_response_item(metadata, item),
|
||||
RolloutItem::ResponseItemPrimitiveMetadataUpdate(_) => {}
|
||||
RolloutItem::Compacted(_) => {}
|
||||
}
|
||||
if metadata.model_provider.is_empty() {
|
||||
|
||||
@@ -462,7 +462,8 @@ ON CONFLICT(thread_id, position) DO NOTHING
|
||||
pub(super) fn extract_dynamic_tools(items: &[RolloutItem]) -> Option<Option<Vec<DynamicToolSpec>>> {
|
||||
items.iter().find_map(|item| match item {
|
||||
RolloutItem::SessionMeta(meta_line) => Some(meta_line.meta.dynamic_tools.clone()),
|
||||
RolloutItem::ResponseItem(_)
|
||||
RolloutItem::ResponseItemPrimitiveMetadataUpdate(_)
|
||||
| RolloutItem::ResponseItem(_)
|
||||
| RolloutItem::Compacted(_)
|
||||
| RolloutItem::TurnContext(_)
|
||||
| RolloutItem::EventMsg(_) => None,
|
||||
@@ -472,7 +473,8 @@ pub(super) fn extract_dynamic_tools(items: &[RolloutItem]) -> Option<Option<Vec<
|
||||
pub(super) fn extract_memory_mode(items: &[RolloutItem]) -> Option<String> {
|
||||
items.iter().rev().find_map(|item| match item {
|
||||
RolloutItem::SessionMeta(meta_line) => meta_line.meta.memory_mode.clone(),
|
||||
RolloutItem::ResponseItem(_)
|
||||
RolloutItem::ResponseItemPrimitiveMetadataUpdate(_)
|
||||
| RolloutItem::ResponseItem(_)
|
||||
| RolloutItem::Compacted(_)
|
||||
| RolloutItem::TurnContext(_)
|
||||
| RolloutItem::EventMsg(_) => None,
|
||||
|
||||
Reference in New Issue
Block a user