Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 29 additions & 33 deletions clients/go/ahptypes/state.generated.go
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,6 @@ const (
ToolResultContentTypeResource ToolResultContentType = "resource"
ToolResultContentTypeFileEdit ToolResultContentType = "fileEdit"
ToolResultContentTypeTerminal ToolResultContentType = "terminal"
ToolResultContentTypeTerminalComplete ToolResultContentType = "terminalComplete"
ToolResultContentTypeSubagent ToolResultContentType = "subagent"
)

Expand Down Expand Up @@ -2151,37 +2150,23 @@ type ToolResultFileEditContent struct {
//
// Clients can subscribe to the terminal's URI to stream its output in real
// time, providing live feedback while a tool is executing.
//
// When the command exits, {@link result} is filled in on the completed
// result, retaining the outcome for clients that did not subscribe. This
// records the command's exit, not the terminal's — the terminal may keep
// running afterwards.
type ToolResultTerminalContent struct {
Type ToolResultContentType `json:"type"`
// Terminal URI (subscribable for full terminal state)
Resource URI `json:"resource"`
// Display title for the terminal content
Title string `json:"title"`
}

// Record of a command executed by a terminal-style tool (e.g. a shell tool),
// appended to the tool result when the command exits.
//
// This records the command's exit, not the terminal's — the terminal may
// keep running afterwards.
//
// When live output was exposed through a terminal channel (a
// {@link ToolResultTerminalContent} block in the same tool result),
// {@link resource} identifies that channel; otherwise this block stands alone
// as the retained command result.
type ToolResultTerminalCompleteContent struct {
Type ToolResultContentType `json:"type"`
// URI of the `ahp-terminal:` channel that carried live output for this
// command, if one was exposed.
Resource *URI `json:"resource,omitempty"`
// Exit code from the completed command, if reported by the runtime
ExitCode *int64 `json:"exitCode,omitempty"`
// Working directory where the command was executed
Cwd *URI `json:"cwd,omitempty"`
// Preview of the command's output, if available
Preview *string `json:"preview,omitempty"`
// Whether `preview` is known to be incomplete or truncated
Truncated *bool `json:"truncated,omitempty"`
// Whether this terminal-style resource is backed by a pseudoterminal.
// When `false`, output is plain text and clients do not need to parse
// VT sequences.
IsPty *bool `json:"isPty,omitempty"`
// Outcome of the command, present once it has exited.
Result *TerminalCommandResult `json:"result,omitempty"`
}

// A reference, embedded in a tool result, to a worker chat spawned by the tool
Expand Down Expand Up @@ -2945,6 +2930,20 @@ type FileEdit struct {
Diff *json.RawMessage `json:"diff,omitempty"`
}

// Outcome of a command run in a terminal-style tool, filled in on
// {@link ToolResultTerminalContent.result} once the command exits.
type TerminalCommandResult struct {
// Exit code from the completed command, if reported by the runtime
ExitCode *int64 `json:"exitCode,omitempty"`
// Preview of the command's output, for clients that are not subscribed
// to the terminal or that arrive after it is disposed. When `isPty` is
// `true` the preview may contain VT sequences; when `false` it is plain
// text.
Preview *string `json:"preview,omitempty"`
// Whether `preview` is known to be incomplete or truncated
Truncated *bool `json:"truncated,omitempty"`
}

// Lightweight terminal metadata exposed on the root state.
type TerminalInfo struct {
// Terminal URI (subscribable for full terminal state)
Expand Down Expand Up @@ -3005,6 +3004,10 @@ type TerminalState struct {
// Do NOT use the presence of a `command` part as a feature flag — parts
// are absent in the normal idle state.
SupportsCommandDetection *bool `json:"supportsCommandDetection,omitempty"`
// Whether this terminal-style resource is backed by a pseudoterminal.
// When `false`, output is plain text and clients do not need to parse
// VT sequences.
IsPty *bool `json:"isPty,omitempty"`
}

// Unstructured terminal output — content before, between, or after commands,
Expand Down Expand Up @@ -4010,7 +4013,6 @@ func (*ToolResultEmbeddedResourceContent) isToolResultContent() {}
func (*ToolResultResourceContent) isToolResultContent() {}
func (*ToolResultFileEditContent) isToolResultContent() {}
func (*ToolResultTerminalContent) isToolResultContent() {}
func (*ToolResultTerminalCompleteContent) isToolResultContent() {}
func (*ToolResultSubagentContent) isToolResultContent() {}

// ToolResultContentUnknown carries an unrecognized ToolResultContent variant — typically a discriminator value introduced by a newer protocol version. The original JSON object is preserved verbatim so that re-encoding round-trips faithfully.
Expand Down Expand Up @@ -4057,12 +4059,6 @@ func (u *ToolResultContent) UnmarshalJSON(data []byte) error {
return err
}
u.Value = &value
case "terminalComplete":
var value ToolResultTerminalCompleteContent
if err := json.Unmarshal(data, &value); err != nil {
return err
}
u.Value = &value
case "subagent":
var value ToolResultSubagentContent
if err := json.Unmarshal(data, &value); err != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -512,8 +512,6 @@ enum class ToolResultContentType {
FILE_EDIT,
@SerialName("terminal")
TERMINAL,
@SerialName("terminalComplete")
TERMINAL_COMPLETE,
@SerialName("subagent")
SUBAGENT
}
Expand Down Expand Up @@ -3019,33 +3017,17 @@ data class ToolResultTerminalContent(
/**
* Display title for the terminal content
*/
val title: String
)

@Serializable
data class ToolResultTerminalCompleteContent(
val type: ToolResultContentType,
/**
* URI of the `ahp-terminal:` channel that carried live output for this
* command, if one was exposed.
*/
val resource: String? = null,
/**
* Exit code from the completed command, if reported by the runtime
*/
val exitCode: Long? = null,
/**
* Working directory where the command was executed
*/
val cwd: String? = null,
val title: String,
/**
* Preview of the command's output, if available
* Whether this terminal-style resource is backed by a pseudoterminal.
* When `false`, output is plain text and clients do not need to parse
* VT sequences.
*/
val preview: String? = null,
val isPty: Boolean? = null,
/**
* Whether `preview` is known to be incomplete or truncated
* Outcome of the command, present once it has exited.
*/
val truncated: Boolean? = null
val result: TerminalCommandResult? = null
)

@Serializable
Expand Down Expand Up @@ -3940,6 +3922,25 @@ data class FileEdit(
val diff: JsonElement? = null
)

@Serializable
data class TerminalCommandResult(
/**
* Exit code from the completed command, if reported by the runtime
*/
val exitCode: Long? = null,
/**
* Preview of the command's output, for clients that are not subscribed
* to the terminal or that arrive after it is disposed. When `isPty` is
* `true` the preview may contain VT sequences; when `false` it is plain
* text.
*/
val preview: String? = null,
/**
* Whether `preview` is known to be incomplete or truncated
*/
val truncated: Boolean? = null
)

@Serializable
data class TerminalInfo(
/**
Expand Down Expand Up @@ -4035,7 +4036,13 @@ data class TerminalState(
* Do NOT use the presence of a `command` part as a feature flag — parts
* are absent in the normal idle state.
*/
val supportsCommandDetection: Boolean? = null
val supportsCommandDetection: Boolean? = null,
/**
* Whether this terminal-style resource is backed by a pseudoterminal.
* When `false`, output is plain text and clients do not need to parse
* VT sequences.
*/
val isPty: Boolean? = null
)

@Serializable
Expand Down Expand Up @@ -5465,7 +5472,6 @@ sealed interface ToolResultContent {
@JvmInline value class Resource(val value: ToolResultResourceContent) : ToolResultContent
@JvmInline value class FileEdit(val value: ToolResultFileEditContent) : ToolResultContent
@JvmInline value class Terminal(val value: ToolResultTerminalContent) : ToolResultContent
@JvmInline value class TerminalComplete(val value: ToolResultTerminalCompleteContent) : ToolResultContent
@JvmInline value class Subagent(val value: ToolResultSubagentContent) : ToolResultContent

/**
Expand Down Expand Up @@ -5495,7 +5501,6 @@ internal object ToolResultContentSerializer : KSerializer<ToolResultContent> {
"resource" -> ToolResultContent.Resource(input.json.decodeFromJsonElement(ToolResultResourceContent.serializer(), element))
"fileEdit" -> ToolResultContent.FileEdit(input.json.decodeFromJsonElement(ToolResultFileEditContent.serializer(), element))
"terminal" -> ToolResultContent.Terminal(input.json.decodeFromJsonElement(ToolResultTerminalContent.serializer(), element))
"terminalComplete" -> ToolResultContent.TerminalComplete(input.json.decodeFromJsonElement(ToolResultTerminalCompleteContent.serializer(), element))
"subagent" -> ToolResultContent.Subagent(input.json.decodeFromJsonElement(ToolResultSubagentContent.serializer(), element))
else -> ToolResultContent.Unknown(obj)
}
Expand All @@ -5510,7 +5515,6 @@ internal object ToolResultContentSerializer : KSerializer<ToolResultContent> {
is ToolResultContent.Resource -> output.json.encodeToJsonElement(ToolResultResourceContent.serializer(), value.value)
is ToolResultContent.FileEdit -> output.json.encodeToJsonElement(ToolResultFileEditContent.serializer(), value.value)
is ToolResultContent.Terminal -> output.json.encodeToJsonElement(ToolResultTerminalContent.serializer(), value.value)
is ToolResultContent.TerminalComplete -> output.json.encodeToJsonElement(ToolResultTerminalCompleteContent.serializer(), value.value)
is ToolResultContent.Subagent -> output.json.encodeToJsonElement(ToolResultSubagentContent.serializer(), value.value)
is ToolResultContent.Unknown -> value.raw
}
Expand Down
68 changes: 35 additions & 33 deletions clients/rust/crates/ahp-types/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -407,8 +407,6 @@ pub enum ToolResultContentType {
FileEdit,
#[serde(rename = "terminal")]
Terminal,
#[serde(rename = "terminalComplete")]
TerminalComplete,
#[serde(rename = "subagent")]
Subagent,
}
Expand Down Expand Up @@ -2667,44 +2665,26 @@ pub struct ToolResultFileEditContent {
///
/// Clients can subscribe to the terminal's URI to stream its output in real
/// time, providing live feedback while a tool is executing.
///
/// When the command exits, {@link result} is filled in on the completed
/// result, retaining the outcome for clients that did not subscribe. This
/// records the command's exit, not the terminal's — the terminal may keep
/// running afterwards.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ToolResultTerminalContent {
/// Terminal URI (subscribable for full terminal state)
pub resource: Uri,
/// Display title for the terminal content
pub title: String,
}

/// Record of a command executed by a terminal-style tool (e.g. a shell tool),
/// appended to the tool result when the command exits.
///
/// This records the command's exit, not the terminal's — the terminal may
/// keep running afterwards.
///
/// When live output was exposed through a terminal channel (a
/// {@link ToolResultTerminalContent} block in the same tool result),
/// {@link resource} identifies that channel; otherwise this block stands alone
/// as the retained command result.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct ToolResultTerminalCompleteContent {
/// URI of the `ahp-terminal:` channel that carried live output for this
/// command, if one was exposed.
/// Whether this terminal-style resource is backed by a pseudoterminal.
/// When `false`, output is plain text and clients do not need to parse
/// VT sequences.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub resource: Option<Uri>,
/// Exit code from the completed command, if reported by the runtime
#[serde(default, skip_serializing_if = "Option::is_none")]
pub exit_code: Option<i64>,
/// Working directory where the command was executed
#[serde(default, skip_serializing_if = "Option::is_none")]
pub cwd: Option<Uri>,
/// Preview of the command's output, if available
#[serde(default, skip_serializing_if = "Option::is_none")]
pub preview: Option<String>,
/// Whether `preview` is known to be incomplete or truncated
pub is_pty: Option<bool>,
/// Outcome of the command, present once it has exited.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub truncated: Option<bool>,
pub result: Option<TerminalCommandResult>,
}

/// A reference, embedded in a tool result, to a worker chat spawned by the tool
Expand Down Expand Up @@ -3568,6 +3548,25 @@ pub struct FileEdit {
pub diff: Option<AnyValue>,
}

/// Outcome of a command run in a terminal-style tool, filled in on
/// {@link ToolResultTerminalContent.result} once the command exits.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct TerminalCommandResult {
/// Exit code from the completed command, if reported by the runtime
#[serde(default, skip_serializing_if = "Option::is_none")]
pub exit_code: Option<i64>,
/// Preview of the command's output, for clients that are not subscribed
/// to the terminal or that arrive after it is disposed. When `isPty` is
/// `true` the preview may contain VT sequences; when `false` it is plain
/// text.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub preview: Option<String>,
/// Whether `preview` is known to be incomplete or truncated
#[serde(default, skip_serializing_if = "Option::is_none")]
pub truncated: Option<bool>,
}

/// Lightweight terminal metadata exposed on the root state.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
Expand Down Expand Up @@ -3640,6 +3639,11 @@ pub struct TerminalState {
/// are absent in the normal idle state.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub supports_command_detection: Option<bool>,
/// Whether this terminal-style resource is backed by a pseudoterminal.
/// When `false`, output is plain text and clients do not need to parse
/// VT sequences.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub is_pty: Option<bool>,
}

/// Unstructured terminal output — content before, between, or after commands,
Expand Down Expand Up @@ -4286,8 +4290,6 @@ pub enum ToolResultContent {
FileEdit(ToolResultFileEditContent),
#[serde(rename = "terminal")]
Terminal(ToolResultTerminalContent),
#[serde(rename = "terminalComplete")]
TerminalComplete(ToolResultTerminalCompleteContent),
#[serde(rename = "subagent")]
Subagent(ToolResultSubagentContent),
/// Unknown or future variant — preserved as raw JSON for round-trip fidelity.
Expand Down
1 change: 1 addition & 0 deletions clients/rust/crates/ahp/src/reducers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2117,6 +2117,7 @@ mod tests {
},
),
supports_command_detection: None,
is_pty: None,
};
let a = StateAction::TerminalData(ahp_types::actions::TerminalDataAction {
data: "hello".into(),
Expand Down
Loading
Loading