Add initial set of doc comments to the SDK (#4513)
Also perform minor code cleanup.
This commit is contained in:
@@ -2,34 +2,45 @@ use serde::Deserialize;
|
|||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use ts_rs::TS;
|
use ts_rs::TS;
|
||||||
|
|
||||||
/// Top-level events emitted on the Codex Exec thread stream.
|
/// Top-level JSONL events emitted by codex exec
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS)]
|
||||||
#[serde(tag = "type")]
|
#[serde(tag = "type")]
|
||||||
pub enum ThreadEvent {
|
pub enum ThreadEvent {
|
||||||
|
/// Emitted when a new thread is started as the first event.
|
||||||
#[serde(rename = "thread.started")]
|
#[serde(rename = "thread.started")]
|
||||||
ThreadStarted(ThreadStartedEvent),
|
ThreadStarted(ThreadStartedEvent),
|
||||||
|
/// Emitted when a turn is started by sending a new prompt to the model.
|
||||||
|
/// A turn encompasses all events that happen while agent is processing the prompt.
|
||||||
#[serde(rename = "turn.started")]
|
#[serde(rename = "turn.started")]
|
||||||
TurnStarted(TurnStartedEvent),
|
TurnStarted(TurnStartedEvent),
|
||||||
|
/// Emitted when a turn is completed. Typically right after the assistant's response.
|
||||||
#[serde(rename = "turn.completed")]
|
#[serde(rename = "turn.completed")]
|
||||||
TurnCompleted(TurnCompletedEvent),
|
TurnCompleted(TurnCompletedEvent),
|
||||||
|
/// Indicates that a turn failed with an error.
|
||||||
#[serde(rename = "turn.failed")]
|
#[serde(rename = "turn.failed")]
|
||||||
TurnFailed(TurnFailedEvent),
|
TurnFailed(TurnFailedEvent),
|
||||||
|
/// Emitted when a new item is added to the thread. Typically the item will be in an "in progress" state.
|
||||||
#[serde(rename = "item.started")]
|
#[serde(rename = "item.started")]
|
||||||
ItemStarted(ItemStartedEvent),
|
ItemStarted(ItemStartedEvent),
|
||||||
|
/// Emitted when an item is updated.
|
||||||
#[serde(rename = "item.updated")]
|
#[serde(rename = "item.updated")]
|
||||||
ItemUpdated(ItemUpdatedEvent),
|
ItemUpdated(ItemUpdatedEvent),
|
||||||
|
/// Signals that an item has reached a terminal state—either success or failure.
|
||||||
#[serde(rename = "item.completed")]
|
#[serde(rename = "item.completed")]
|
||||||
ItemCompleted(ItemCompletedEvent),
|
ItemCompleted(ItemCompletedEvent),
|
||||||
|
/// Represents an unrecoverable error emitted directly by the event stream.
|
||||||
#[serde(rename = "error")]
|
#[serde(rename = "error")]
|
||||||
Error(ThreadErrorEvent),
|
Error(ThreadErrorEvent),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS)]
|
||||||
pub struct ThreadStartedEvent {
|
pub struct ThreadStartedEvent {
|
||||||
|
/// The identified of the new thread. Can be used to resume the thread later.
|
||||||
pub thread_id: String,
|
pub thread_id: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS, Default)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS, Default)]
|
||||||
|
|
||||||
pub struct TurnStartedEvent {}
|
pub struct TurnStartedEvent {}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS)]
|
||||||
@@ -42,11 +53,14 @@ pub struct TurnFailedEvent {
|
|||||||
pub error: ThreadErrorEvent,
|
pub error: ThreadErrorEvent,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Minimal usage summary for a turn.
|
/// Describes the usage of tokens during a turn.
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS, Default)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS, Default)]
|
||||||
pub struct Usage {
|
pub struct Usage {
|
||||||
|
/// The number of input tokens used during the turn.
|
||||||
pub input_tokens: u64,
|
pub input_tokens: u64,
|
||||||
|
/// The number of cached input tokens used during the turn.
|
||||||
pub cached_input_tokens: u64,
|
pub cached_input_tokens: u64,
|
||||||
|
/// The number of output tokens used during the turn.
|
||||||
pub output_tokens: u64,
|
pub output_tokens: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,34 +97,44 @@ pub struct ThreadItem {
|
|||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS)]
|
||||||
#[serde(tag = "item_type", rename_all = "snake_case")]
|
#[serde(tag = "item_type", rename_all = "snake_case")]
|
||||||
pub enum ThreadItemDetails {
|
pub enum ThreadItemDetails {
|
||||||
|
/// Response from the agent.
|
||||||
|
/// Either a natural-language response or a JSON string when structured output is requested.
|
||||||
AssistantMessage(AssistantMessageItem),
|
AssistantMessage(AssistantMessageItem),
|
||||||
|
/// Agent's reasoning summary.
|
||||||
Reasoning(ReasoningItem),
|
Reasoning(ReasoningItem),
|
||||||
|
/// Tracks a command executed by the agent. The item starts when the command is
|
||||||
|
/// spawned, and completes when the process exits with an exit code.
|
||||||
CommandExecution(CommandExecutionItem),
|
CommandExecution(CommandExecutionItem),
|
||||||
|
/// Represents a set of file changes by the agent. The item is emitted only as a
|
||||||
|
/// completed event once the patch succeeds or fails.
|
||||||
FileChange(FileChangeItem),
|
FileChange(FileChangeItem),
|
||||||
|
/// Represents a call to an MCP tool. The item starts when the invocation is
|
||||||
|
/// dispatched and completes when the MCP server reports success or failure.
|
||||||
McpToolCall(McpToolCallItem),
|
McpToolCall(McpToolCallItem),
|
||||||
|
/// Captures a web search request. It starts when the search is kicked off
|
||||||
|
/// and completes when results are returned to the agent.
|
||||||
WebSearch(WebSearchItem),
|
WebSearch(WebSearchItem),
|
||||||
|
/// Tracks the agent's running to-do list. It starts when the plan is first
|
||||||
|
/// issued, updates as steps change state, and completes when the turn ends.
|
||||||
TodoList(TodoListItem),
|
TodoList(TodoListItem),
|
||||||
|
/// Describes a non-fatal error surfaced as an item.
|
||||||
Error(ErrorItem),
|
Error(ErrorItem),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Session metadata.
|
/// Response from the agent.
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS)]
|
/// Either a natural-language response or a JSON string when structured output is requested.
|
||||||
pub struct SessionItem {
|
|
||||||
pub session_id: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Assistant message payload.
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS)]
|
||||||
pub struct AssistantMessageItem {
|
pub struct AssistantMessageItem {
|
||||||
pub text: String,
|
pub text: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Model reasoning summary payload.
|
/// Agent's reasoning summary.
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS)]
|
||||||
pub struct ReasoningItem {
|
pub struct ReasoningItem {
|
||||||
pub text: String,
|
pub text: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The status of a command execution.
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default, TS)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default, TS)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
pub enum CommandExecutionStatus {
|
pub enum CommandExecutionStatus {
|
||||||
@@ -120,7 +144,7 @@ pub enum CommandExecutionStatus {
|
|||||||
Failed,
|
Failed,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Local shell command execution payload.
|
/// A command executed by the agent.
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS)]
|
||||||
pub struct CommandExecutionItem {
|
pub struct CommandExecutionItem {
|
||||||
pub command: String,
|
pub command: String,
|
||||||
@@ -130,13 +154,14 @@ pub struct CommandExecutionItem {
|
|||||||
pub status: CommandExecutionStatus,
|
pub status: CommandExecutionStatus,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Single file change summary for a patch.
|
/// A set of file changes by the agent.
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS)]
|
||||||
pub struct FileUpdateChange {
|
pub struct FileUpdateChange {
|
||||||
pub path: String,
|
pub path: String,
|
||||||
pub kind: PatchChangeKind,
|
pub kind: PatchChangeKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The status of a file change.
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
pub enum PatchApplyStatus {
|
pub enum PatchApplyStatus {
|
||||||
@@ -144,14 +169,14 @@ pub enum PatchApplyStatus {
|
|||||||
Failed,
|
Failed,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Patch application payload.
|
/// A set of file changes by the agent.
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS)]
|
||||||
pub struct FileChangeItem {
|
pub struct FileChangeItem {
|
||||||
pub changes: Vec<FileUpdateChange>,
|
pub changes: Vec<FileUpdateChange>,
|
||||||
pub status: PatchApplyStatus,
|
pub status: PatchApplyStatus,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Known change kinds for a patch.
|
/// Indicates the type of the file change.
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
pub enum PatchChangeKind {
|
pub enum PatchChangeKind {
|
||||||
@@ -160,6 +185,7 @@ pub enum PatchChangeKind {
|
|||||||
Update,
|
Update,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The status of an MCP tool call.
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default, TS)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default, TS)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
pub enum McpToolCallStatus {
|
pub enum McpToolCallStatus {
|
||||||
@@ -169,6 +195,7 @@ pub enum McpToolCallStatus {
|
|||||||
Failed,
|
Failed,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A call to an MCP tool.
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS)]
|
||||||
pub struct McpToolCallItem {
|
pub struct McpToolCallItem {
|
||||||
pub server: String,
|
pub server: String,
|
||||||
@@ -176,16 +203,19 @@ pub struct McpToolCallItem {
|
|||||||
pub status: McpToolCallStatus,
|
pub status: McpToolCallStatus,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A web search request.
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS)]
|
||||||
pub struct WebSearchItem {
|
pub struct WebSearchItem {
|
||||||
pub query: String,
|
pub query: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An error notification.
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS)]
|
||||||
pub struct ErrorItem {
|
pub struct ErrorItem {
|
||||||
pub message: String,
|
pub message: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An item in agent's to-do list.
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS)]
|
||||||
pub struct TodoItem {
|
pub struct TodoItem {
|
||||||
pub text: String,
|
pub text: String,
|
||||||
|
|||||||
@@ -1 +1,53 @@
|
|||||||
# Codex SDK
|
# Codex SDK
|
||||||
|
|
||||||
|
Bring the power of the best coding agent to your application.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install @openai/codex-sdk
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Call `startThread()` and `run()` to start a thead with Codex.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { Codex } from "@openai/codex-sdk";
|
||||||
|
|
||||||
|
const codex = new Codex();
|
||||||
|
const thread = codex.startThread();
|
||||||
|
const result = await thread.run("Diagnose the test failure and propose a fix");
|
||||||
|
|
||||||
|
console.log(result);
|
||||||
|
```
|
||||||
|
|
||||||
|
You can call `run()` again to continue the same thread.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const result = await thread.run("Implement the fix");
|
||||||
|
|
||||||
|
console.log(result);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Streaming
|
||||||
|
|
||||||
|
The `await run()` method completes when a thread turn is complete and agent is prepared the final response.
|
||||||
|
|
||||||
|
You can thread items while they are being produced by calling `await runStreamed()`.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const result = thread.runStreamed("Diagnose the test failure and propose a fix");
|
||||||
|
```
|
||||||
|
|
||||||
|
### Resuming a thread
|
||||||
|
|
||||||
|
If you don't have the original `Thread` instance to continue the thread, you can resume a thread by calling `resumeThread()` and providing the thread.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const threadId = "...";
|
||||||
|
const thread = codex.resumeThread(threadId);
|
||||||
|
const result = await thread.run("Implement the fix");
|
||||||
|
|
||||||
|
console.log(result);
|
||||||
|
```
|
||||||
|
|||||||
@@ -2,6 +2,11 @@ import { CodexOptions } from "./codexOptions";
|
|||||||
import { CodexExec } from "./exec";
|
import { CodexExec } from "./exec";
|
||||||
import { Thread } from "./thread";
|
import { Thread } from "./thread";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Codex is the main class for interacting with the Codex agent.
|
||||||
|
*
|
||||||
|
* Use the `startThread()` method to start a new thread or `resumeThread()` to resume a previously started thread.
|
||||||
|
*/
|
||||||
export class Codex {
|
export class Codex {
|
||||||
private exec: CodexExec;
|
private exec: CodexExec;
|
||||||
private options: CodexOptions;
|
private options: CodexOptions;
|
||||||
@@ -11,10 +16,21 @@ export class Codex {
|
|||||||
this.options = options;
|
this.options = options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts a new conversation with an agent.
|
||||||
|
* @returns A new thread instance.
|
||||||
|
*/
|
||||||
startThread(): Thread {
|
startThread(): Thread {
|
||||||
return new Thread(this.exec, this.options);
|
return new Thread(this.exec, this.options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resumes a conversation with an agent based on the thread id.
|
||||||
|
* Threads are persisted in ~/.codex/sessions.
|
||||||
|
*
|
||||||
|
* @param id The id of the thread to resume.
|
||||||
|
* @returns A new thread instance.
|
||||||
|
*/
|
||||||
resumeThread(id: string): Thread {
|
resumeThread(id: string): Thread {
|
||||||
return new Thread(this.exec, this.options, id);
|
return new Thread(this.exec, this.options, id);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,55 +2,73 @@
|
|||||||
|
|
||||||
import type { ThreadItem } from "./items";
|
import type { ThreadItem } from "./items";
|
||||||
|
|
||||||
|
/** Emitted when a new thread is started as the first event. */
|
||||||
export type ThreadStartedEvent = {
|
export type ThreadStartedEvent = {
|
||||||
type: "thread.started";
|
type: "thread.started";
|
||||||
|
/** The identifier of the new thread. Can be used to resume the thread later. */
|
||||||
thread_id: string;
|
thread_id: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emitted when a turn is started by sending a new prompt to the model.
|
||||||
|
* A turn encompasses all events that happen while the agent is processing the prompt.
|
||||||
|
*/
|
||||||
export type TurnStartedEvent = {
|
export type TurnStartedEvent = {
|
||||||
type: "turn.started";
|
type: "turn.started";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Describes the usage of tokens during a turn. */
|
||||||
export type Usage = {
|
export type Usage = {
|
||||||
|
/** The number of input tokens used during the turn. */
|
||||||
input_tokens: number;
|
input_tokens: number;
|
||||||
|
/** The number of cached input tokens used during the turn. */
|
||||||
cached_input_tokens: number;
|
cached_input_tokens: number;
|
||||||
|
/** The number of output tokens used during the turn. */
|
||||||
output_tokens: number;
|
output_tokens: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Emitted when a turn is completed. Typically right after the assistant's response. */
|
||||||
export type TurnCompletedEvent = {
|
export type TurnCompletedEvent = {
|
||||||
type: "turn.completed";
|
type: "turn.completed";
|
||||||
usage: Usage;
|
usage: Usage;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Indicates that a turn failed with an error. */
|
||||||
export type TurnFailedEvent = {
|
export type TurnFailedEvent = {
|
||||||
type: "turn.failed";
|
type: "turn.failed";
|
||||||
error: ThreadError;
|
error: ThreadError;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Emitted when a new item is added to the thread. Typically the item is initially "in progress". */
|
||||||
export type ItemStartedEvent = {
|
export type ItemStartedEvent = {
|
||||||
type: "item.started";
|
type: "item.started";
|
||||||
item: ThreadItem;
|
item: ThreadItem;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Emitted when an item is updated. */
|
||||||
export type ItemUpdatedEvent = {
|
export type ItemUpdatedEvent = {
|
||||||
type: "item.updated";
|
type: "item.updated";
|
||||||
item: ThreadItem;
|
item: ThreadItem;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Signals that an item has reached a terminal state—either success or failure. */
|
||||||
export type ItemCompletedEvent = {
|
export type ItemCompletedEvent = {
|
||||||
type: "item.completed";
|
type: "item.completed";
|
||||||
item: ThreadItem;
|
item: ThreadItem;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Fatal error emitted by the stream. */
|
||||||
export type ThreadError = {
|
export type ThreadError = {
|
||||||
message: string;
|
message: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Represents an unrecoverable error emitted directly by the event stream. */
|
||||||
export type ThreadErrorEvent = {
|
export type ThreadErrorEvent = {
|
||||||
type: "error";
|
type: "error";
|
||||||
message: string;
|
message: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Top-level JSONL events emitted by codex exec. */
|
||||||
export type ThreadEvent =
|
export type ThreadEvent =
|
||||||
| ThreadStartedEvent
|
| ThreadStartedEvent
|
||||||
| TurnStartedEvent
|
| TurnStartedEvent
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ export type {
|
|||||||
ErrorItem,
|
ErrorItem,
|
||||||
} from "./items";
|
} from "./items";
|
||||||
|
|
||||||
export { Thread, RunResult, RunStreamedResult, Input } from "./thread";
|
export { Thread } from "./thread";
|
||||||
|
export type { RunResult, RunStreamedResult, Input } from "./thread";
|
||||||
|
|
||||||
export { Codex } from "./codex";
|
export { Codex } from "./codex";
|
||||||
|
|
||||||
|
|||||||
@@ -1,71 +1,101 @@
|
|||||||
// based on item types from codex-rs/exec/src/exec_events.rs
|
// based on item types from codex-rs/exec/src/exec_events.rs
|
||||||
|
|
||||||
|
/** The status of a command execution. */
|
||||||
export type CommandExecutionStatus = "in_progress" | "completed" | "failed";
|
export type CommandExecutionStatus = "in_progress" | "completed" | "failed";
|
||||||
|
|
||||||
|
/** A command executed by the agent. */
|
||||||
export type CommandExecutionItem = {
|
export type CommandExecutionItem = {
|
||||||
id: string;
|
id: string;
|
||||||
item_type: "command_execution";
|
item_type: "command_execution";
|
||||||
|
/** The command line executed by the agent. */
|
||||||
command: string;
|
command: string;
|
||||||
|
/** Aggregated stdout and stderr captured while the command was running. */
|
||||||
aggregated_output: string;
|
aggregated_output: string;
|
||||||
|
/** Set when the command exits; omitted while still running. */
|
||||||
exit_code?: number;
|
exit_code?: number;
|
||||||
|
/** Current status of the command execution. */
|
||||||
status: CommandExecutionStatus;
|
status: CommandExecutionStatus;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Indicates the type of the file change. */
|
||||||
export type PatchChangeKind = "add" | "delete" | "update";
|
export type PatchChangeKind = "add" | "delete" | "update";
|
||||||
|
|
||||||
|
/** A set of file changes by the agent. */
|
||||||
export type FileUpdateChange = {
|
export type FileUpdateChange = {
|
||||||
path: string;
|
path: string;
|
||||||
kind: PatchChangeKind;
|
kind: PatchChangeKind;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** The status of a file change. */
|
||||||
export type PatchApplyStatus = "completed" | "failed";
|
export type PatchApplyStatus = "completed" | "failed";
|
||||||
|
|
||||||
|
/** A set of file changes by the agent. Emitted once the patch succeeds or fails. */
|
||||||
export type FileChangeItem = {
|
export type FileChangeItem = {
|
||||||
id: string;
|
id: string;
|
||||||
item_type: "file_change";
|
item_type: "file_change";
|
||||||
|
/** Individual file changes that comprise the patch. */
|
||||||
changes: FileUpdateChange[];
|
changes: FileUpdateChange[];
|
||||||
|
/** Whether the patch ultimately succeeded or failed. */
|
||||||
status: PatchApplyStatus;
|
status: PatchApplyStatus;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** The status of an MCP tool call. */
|
||||||
export type McpToolCallStatus = "in_progress" | "completed" | "failed";
|
export type McpToolCallStatus = "in_progress" | "completed" | "failed";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a call to an MCP tool. The item starts when the invocation is dispatched
|
||||||
|
* and completes when the MCP server reports success or failure.
|
||||||
|
*/
|
||||||
export type McpToolCallItem = {
|
export type McpToolCallItem = {
|
||||||
id: string;
|
id: string;
|
||||||
item_type: "mcp_tool_call";
|
item_type: "mcp_tool_call";
|
||||||
|
/** Name of the MCP server handling the request. */
|
||||||
server: string;
|
server: string;
|
||||||
|
/** The tool invoked on the MCP server. */
|
||||||
tool: string;
|
tool: string;
|
||||||
|
/** Current status of the tool invocation. */
|
||||||
status: McpToolCallStatus;
|
status: McpToolCallStatus;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Response from the agent. Either natural-language text or JSON when structured output is requested. */
|
||||||
export type AssistantMessageItem = {
|
export type AssistantMessageItem = {
|
||||||
id: string;
|
id: string;
|
||||||
item_type: "assistant_message";
|
item_type: "assistant_message";
|
||||||
|
/** Either natural-language text or JSON when structured output is requested. */
|
||||||
text: string;
|
text: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Agent's reasoning summary. */
|
||||||
export type ReasoningItem = {
|
export type ReasoningItem = {
|
||||||
id: string;
|
id: string;
|
||||||
item_type: "reasoning";
|
item_type: "reasoning";
|
||||||
text: string;
|
text: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Captures a web search request. Completes when results are returned to the agent. */
|
||||||
export type WebSearchItem = {
|
export type WebSearchItem = {
|
||||||
id: string;
|
id: string;
|
||||||
item_type: "web_search";
|
item_type: "web_search";
|
||||||
query: string;
|
query: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Describes a non-fatal error surfaced as an item. */
|
||||||
export type ErrorItem = {
|
export type ErrorItem = {
|
||||||
id: string;
|
id: string;
|
||||||
item_type: "error";
|
item_type: "error";
|
||||||
message: string;
|
message: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** An item in the agent's to-do list. */
|
||||||
export type TodoItem = {
|
export type TodoItem = {
|
||||||
text: string;
|
text: string;
|
||||||
completed: boolean;
|
completed: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tracks the agent's running to-do list. Starts when the plan is issued, updates as steps change,
|
||||||
|
* and completes when the turn ends.
|
||||||
|
*/
|
||||||
export type TodoListItem = {
|
export type TodoListItem = {
|
||||||
id: string;
|
id: string;
|
||||||
item_type: "todo_list";
|
item_type: "todo_list";
|
||||||
@@ -78,6 +108,7 @@ export type SessionItem = {
|
|||||||
session_id: string;
|
session_id: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Canonical union of thread items and their type-specific payloads. */
|
||||||
export type ThreadItem =
|
export type ThreadItem =
|
||||||
| AssistantMessageItem
|
| AssistantMessageItem
|
||||||
| ReasoningItem
|
| ReasoningItem
|
||||||
|
|||||||
@@ -4,29 +4,45 @@ import { CodexExec } from "./exec";
|
|||||||
import { ThreadItem } from "./items";
|
import { ThreadItem } from "./items";
|
||||||
import { TurnOptions } from "./turnOptions";
|
import { TurnOptions } from "./turnOptions";
|
||||||
|
|
||||||
export type RunResult = {
|
/** Completed turn. */
|
||||||
|
export type Turn = {
|
||||||
items: ThreadItem[];
|
items: ThreadItem[];
|
||||||
finalResponse: string;
|
finalResponse: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type RunStreamedResult = {
|
/** Alias for `Turn` to describe the result of `run()`. */
|
||||||
|
export type RunResult = Turn;
|
||||||
|
|
||||||
|
/** The result of the `runStreamed` method. */
|
||||||
|
export type StreamedTurn = {
|
||||||
events: AsyncGenerator<ThreadEvent>;
|
events: AsyncGenerator<ThreadEvent>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Alias for `StreamedTurn` to describe the result of `runStreamed()`. */
|
||||||
|
export type RunStreamedResult = StreamedTurn;
|
||||||
|
|
||||||
|
/** An input to send to the agent. */
|
||||||
export type Input = string;
|
export type Input = string;
|
||||||
|
|
||||||
|
/** Respesent a thread of conversation with the agent. One thread can have multiple consecutive turns. */
|
||||||
export class Thread {
|
export class Thread {
|
||||||
private exec: CodexExec;
|
private _exec: CodexExec;
|
||||||
private options: CodexOptions;
|
private _options: CodexOptions;
|
||||||
public id: string | null;
|
private _id: string | null;
|
||||||
|
|
||||||
constructor(exec: CodexExec, options: CodexOptions, id: string | null = null) {
|
/** Returns the ID of the thread. Populated after the first turn starts. */
|
||||||
this.exec = exec;
|
public get id(): string | null {
|
||||||
this.options = options;
|
return this._id;
|
||||||
this.id = id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async runStreamed(input: string, options?: TurnOptions): Promise<RunStreamedResult> {
|
constructor(exec: CodexExec, options: CodexOptions, id: string | null = null) {
|
||||||
|
this._exec = exec;
|
||||||
|
this._options = options;
|
||||||
|
this._id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Provides the input to the agent and streams events as they are produced during the turn. */
|
||||||
|
async runStreamed(input: string, options?: TurnOptions): Promise<StreamedTurn> {
|
||||||
return { events: this.runStreamedInternal(input, options) };
|
return { events: this.runStreamedInternal(input, options) };
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,26 +50,32 @@ export class Thread {
|
|||||||
input: string,
|
input: string,
|
||||||
options?: TurnOptions,
|
options?: TurnOptions,
|
||||||
): AsyncGenerator<ThreadEvent> {
|
): AsyncGenerator<ThreadEvent> {
|
||||||
const generator = this.exec.run({
|
const generator = this._exec.run({
|
||||||
input,
|
input,
|
||||||
baseUrl: this.options.baseUrl,
|
baseUrl: this._options.baseUrl,
|
||||||
apiKey: this.options.apiKey,
|
apiKey: this._options.apiKey,
|
||||||
threadId: this.id,
|
threadId: this._id,
|
||||||
model: options?.model,
|
model: options?.model,
|
||||||
sandboxMode: options?.sandboxMode,
|
sandboxMode: options?.sandboxMode,
|
||||||
workingDirectory: options?.workingDirectory,
|
workingDirectory: options?.workingDirectory,
|
||||||
skipGitRepoCheck: options?.skipGitRepoCheck,
|
skipGitRepoCheck: options?.skipGitRepoCheck,
|
||||||
});
|
});
|
||||||
for await (const item of generator) {
|
for await (const item of generator) {
|
||||||
const parsed = JSON.parse(item) as ThreadEvent;
|
let parsed: ThreadEvent;
|
||||||
|
try {
|
||||||
|
parsed = JSON.parse(item) as ThreadEvent;
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(`Failed to parse item: ${item}`, { cause: error });
|
||||||
|
}
|
||||||
if (parsed.type === "thread.started") {
|
if (parsed.type === "thread.started") {
|
||||||
this.id = parsed.thread_id;
|
this._id = parsed.thread_id;
|
||||||
}
|
}
|
||||||
yield parsed;
|
yield parsed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async run(input: string, options?: TurnOptions): Promise<RunResult> {
|
/** Provides the input to the agent and returns the completed turn. */
|
||||||
|
async run(input: string, options?: TurnOptions): Promise<Turn> {
|
||||||
const generator = this.runStreamedInternal(input, options);
|
const generator = this.runStreamedInternal(input, options);
|
||||||
const items: ThreadItem[] = [];
|
const items: ThreadItem[] = [];
|
||||||
let finalResponse: string = "";
|
let finalResponse: string = "";
|
||||||
|
|||||||
@@ -218,7 +218,6 @@ describe("Codex", () => {
|
|||||||
await close();
|
await close();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it("runs in provided working directory", async () => {
|
it("runs in provided working directory", async () => {
|
||||||
const { url, close } = await startResponsesTestProxy({
|
const { url, close } = await startResponsesTestProxy({
|
||||||
statusCode: 200,
|
statusCode: 200,
|
||||||
@@ -286,7 +285,6 @@ describe("Codex", () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function expectPair(args: string[] | undefined, pair: [string, string]) {
|
function expectPair(args: string[] | undefined, pair: [string, string]) {
|
||||||
if (!args) {
|
if (!args) {
|
||||||
throw new Error("Args is undefined");
|
throw new Error("Args is undefined");
|
||||||
|
|||||||
Reference in New Issue
Block a user