mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
feat: cleaner TUI for sub-agents (#12327)
<img width="760" height="496" alt="Screenshot 2026-02-20 at 14 31 25" src="https://github.com/user-attachments/assets/1983b825-bb47-417e-9925-6f727af56765" />
This commit is contained in:
committed by
GitHub
Unverified
parent
2036a5f5e0
commit
4d60c803ba
@@ -296,6 +296,75 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"CollabAgentRef": {
|
||||
"properties": {
|
||||
"agent_nickname": {
|
||||
"description": "Optional nickname assigned to an AgentControl-spawned sub-agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"agent_role": {
|
||||
"description": "Optional role (agent_role) assigned to an AgentControl-spawned sub-agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ThreadId"
|
||||
}
|
||||
],
|
||||
"description": "Thread ID of the receiver/new agent."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"thread_id"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"CollabAgentStatusEntry": {
|
||||
"properties": {
|
||||
"agent_nickname": {
|
||||
"description": "Optional nickname assigned to an AgentControl-spawned sub-agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"agent_role": {
|
||||
"description": "Optional role (agent_role) assigned to an AgentControl-spawned sub-agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AgentStatus"
|
||||
}
|
||||
],
|
||||
"description": "Last known status of the agent."
|
||||
},
|
||||
"thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ThreadId"
|
||||
}
|
||||
],
|
||||
"description": "Thread ID of the receiver/new agent."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"status",
|
||||
"thread_id"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ContentItem": {
|
||||
"oneOf": [
|
||||
{
|
||||
@@ -2548,6 +2617,20 @@
|
||||
"description": "Identifier for the collab tool call.",
|
||||
"type": "string"
|
||||
},
|
||||
"new_agent_nickname": {
|
||||
"description": "Optional nickname assigned to the new agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"new_agent_role": {
|
||||
"description": "Optional role assigned to the new agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"new_thread_id": {
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -2653,6 +2736,20 @@
|
||||
"description": "Prompt sent from the sender to the receiver. Can be empty to prevent CoT leaking at the beginning.",
|
||||
"type": "string"
|
||||
},
|
||||
"receiver_agent_nickname": {
|
||||
"description": "Optional nickname assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_agent_role": {
|
||||
"description": "Optional role assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
@@ -2703,6 +2800,13 @@
|
||||
"description": "ID of the waiting call.",
|
||||
"type": "string"
|
||||
},
|
||||
"receiver_agents": {
|
||||
"description": "Optional nicknames/roles for receivers.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/CollabAgentRef"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"receiver_thread_ids": {
|
||||
"description": "Thread ID of the receivers.",
|
||||
"items": {
|
||||
@@ -2738,6 +2842,13 @@
|
||||
{
|
||||
"description": "Collab interaction: waiting end.",
|
||||
"properties": {
|
||||
"agent_statuses": {
|
||||
"description": "Optional receiver metadata paired with final statuses.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/CollabAgentStatusEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"call_id": {
|
||||
"description": "ID of the waiting call.",
|
||||
"type": "string"
|
||||
@@ -2821,6 +2932,20 @@
|
||||
"description": "Identifier for the collab tool call.",
|
||||
"type": "string"
|
||||
},
|
||||
"receiver_agent_nickname": {
|
||||
"description": "Optional nickname assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_agent_role": {
|
||||
"description": "Optional role assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
@@ -2870,6 +2995,20 @@
|
||||
"description": "Identifier for the collab tool call.",
|
||||
"type": "string"
|
||||
},
|
||||
"receiver_agent_nickname": {
|
||||
"description": "Optional nickname assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_agent_role": {
|
||||
"description": "Optional role assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
@@ -2910,6 +3049,20 @@
|
||||
"description": "Identifier for the collab tool call.",
|
||||
"type": "string"
|
||||
},
|
||||
"receiver_agent_nickname": {
|
||||
"description": "Optional nickname assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_agent_role": {
|
||||
"description": "Optional role assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
@@ -7528,6 +7681,20 @@
|
||||
"description": "Identifier for the collab tool call.",
|
||||
"type": "string"
|
||||
},
|
||||
"new_agent_nickname": {
|
||||
"description": "Optional nickname assigned to the new agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"new_agent_role": {
|
||||
"description": "Optional role assigned to the new agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"new_thread_id": {
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -7633,6 +7800,20 @@
|
||||
"description": "Prompt sent from the sender to the receiver. Can be empty to prevent CoT leaking at the beginning.",
|
||||
"type": "string"
|
||||
},
|
||||
"receiver_agent_nickname": {
|
||||
"description": "Optional nickname assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_agent_role": {
|
||||
"description": "Optional role assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
@@ -7683,6 +7864,13 @@
|
||||
"description": "ID of the waiting call.",
|
||||
"type": "string"
|
||||
},
|
||||
"receiver_agents": {
|
||||
"description": "Optional nicknames/roles for receivers.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/CollabAgentRef"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"receiver_thread_ids": {
|
||||
"description": "Thread ID of the receivers.",
|
||||
"items": {
|
||||
@@ -7718,6 +7906,13 @@
|
||||
{
|
||||
"description": "Collab interaction: waiting end.",
|
||||
"properties": {
|
||||
"agent_statuses": {
|
||||
"description": "Optional receiver metadata paired with final statuses.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/CollabAgentStatusEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"call_id": {
|
||||
"description": "ID of the waiting call.",
|
||||
"type": "string"
|
||||
@@ -7801,6 +7996,20 @@
|
||||
"description": "Identifier for the collab tool call.",
|
||||
"type": "string"
|
||||
},
|
||||
"receiver_agent_nickname": {
|
||||
"description": "Optional nickname assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_agent_role": {
|
||||
"description": "Optional role assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
@@ -7850,6 +8059,20 @@
|
||||
"description": "Identifier for the collab tool call.",
|
||||
"type": "string"
|
||||
},
|
||||
"receiver_agent_nickname": {
|
||||
"description": "Optional nickname assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_agent_role": {
|
||||
"description": "Optional role assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
@@ -7890,6 +8113,20 @@
|
||||
"description": "Identifier for the collab tool call.",
|
||||
"type": "string"
|
||||
},
|
||||
"receiver_agent_nickname": {
|
||||
"description": "Optional nickname assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_agent_role": {
|
||||
"description": "Optional role assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
|
||||
@@ -808,6 +808,36 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"CollabAgentRef": {
|
||||
"properties": {
|
||||
"agent_nickname": {
|
||||
"description": "Optional nickname assigned to an AgentControl-spawned sub-agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"agent_role": {
|
||||
"description": "Optional role (agent_role) assigned to an AgentControl-spawned sub-agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ThreadId"
|
||||
}
|
||||
],
|
||||
"description": "Thread ID of the receiver/new agent."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"thread_id"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"CollabAgentState": {
|
||||
"properties": {
|
||||
"message": {
|
||||
@@ -836,6 +866,45 @@
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"CollabAgentStatusEntry": {
|
||||
"properties": {
|
||||
"agent_nickname": {
|
||||
"description": "Optional nickname assigned to an AgentControl-spawned sub-agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"agent_role": {
|
||||
"description": "Optional role (agent_role) assigned to an AgentControl-spawned sub-agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AgentStatus"
|
||||
}
|
||||
],
|
||||
"description": "Last known status of the agent."
|
||||
},
|
||||
"thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ThreadId"
|
||||
}
|
||||
],
|
||||
"description": "Thread ID of the receiver/new agent."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"status",
|
||||
"thread_id"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"CollabAgentTool": {
|
||||
"enum": [
|
||||
"spawnAgent",
|
||||
@@ -3364,6 +3433,20 @@
|
||||
"description": "Identifier for the collab tool call.",
|
||||
"type": "string"
|
||||
},
|
||||
"new_agent_nickname": {
|
||||
"description": "Optional nickname assigned to the new agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"new_agent_role": {
|
||||
"description": "Optional role assigned to the new agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"new_thread_id": {
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -3469,6 +3552,20 @@
|
||||
"description": "Prompt sent from the sender to the receiver. Can be empty to prevent CoT leaking at the beginning.",
|
||||
"type": "string"
|
||||
},
|
||||
"receiver_agent_nickname": {
|
||||
"description": "Optional nickname assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_agent_role": {
|
||||
"description": "Optional role assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
@@ -3519,6 +3616,13 @@
|
||||
"description": "ID of the waiting call.",
|
||||
"type": "string"
|
||||
},
|
||||
"receiver_agents": {
|
||||
"description": "Optional nicknames/roles for receivers.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/CollabAgentRef"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"receiver_thread_ids": {
|
||||
"description": "Thread ID of the receivers.",
|
||||
"items": {
|
||||
@@ -3554,6 +3658,13 @@
|
||||
{
|
||||
"description": "Collab interaction: waiting end.",
|
||||
"properties": {
|
||||
"agent_statuses": {
|
||||
"description": "Optional receiver metadata paired with final statuses.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/CollabAgentStatusEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"call_id": {
|
||||
"description": "ID of the waiting call.",
|
||||
"type": "string"
|
||||
@@ -3637,6 +3748,20 @@
|
||||
"description": "Identifier for the collab tool call.",
|
||||
"type": "string"
|
||||
},
|
||||
"receiver_agent_nickname": {
|
||||
"description": "Optional nickname assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_agent_role": {
|
||||
"description": "Optional role assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
@@ -3686,6 +3811,20 @@
|
||||
"description": "Identifier for the collab tool call.",
|
||||
"type": "string"
|
||||
},
|
||||
"receiver_agent_nickname": {
|
||||
"description": "Optional nickname assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_agent_role": {
|
||||
"description": "Optional role assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
@@ -3726,6 +3865,20 @@
|
||||
"description": "Identifier for the collab tool call.",
|
||||
"type": "string"
|
||||
},
|
||||
"receiver_agent_nickname": {
|
||||
"description": "Optional nickname assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_agent_role": {
|
||||
"description": "Optional role assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
|
||||
@@ -2029,6 +2029,75 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"CollabAgentRef": {
|
||||
"properties": {
|
||||
"agent_nickname": {
|
||||
"description": "Optional nickname assigned to an AgentControl-spawned sub-agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"agent_role": {
|
||||
"description": "Optional role (agent_role) assigned to an AgentControl-spawned sub-agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ThreadId"
|
||||
}
|
||||
],
|
||||
"description": "Thread ID of the receiver/new agent."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"thread_id"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"CollabAgentStatusEntry": {
|
||||
"properties": {
|
||||
"agent_nickname": {
|
||||
"description": "Optional nickname assigned to an AgentControl-spawned sub-agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"agent_role": {
|
||||
"description": "Optional role (agent_role) assigned to an AgentControl-spawned sub-agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AgentStatus"
|
||||
}
|
||||
],
|
||||
"description": "Last known status of the agent."
|
||||
},
|
||||
"thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ThreadId"
|
||||
}
|
||||
],
|
||||
"description": "Thread ID of the receiver/new agent."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"status",
|
||||
"thread_id"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"CommandExecutionApprovalDecision": {
|
||||
"oneOf": [
|
||||
{
|
||||
@@ -4592,6 +4661,20 @@
|
||||
"description": "Identifier for the collab tool call.",
|
||||
"type": "string"
|
||||
},
|
||||
"new_agent_nickname": {
|
||||
"description": "Optional nickname assigned to the new agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"new_agent_role": {
|
||||
"description": "Optional role assigned to the new agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"new_thread_id": {
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -4697,6 +4780,20 @@
|
||||
"description": "Prompt sent from the sender to the receiver. Can be empty to prevent CoT leaking at the beginning.",
|
||||
"type": "string"
|
||||
},
|
||||
"receiver_agent_nickname": {
|
||||
"description": "Optional nickname assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_agent_role": {
|
||||
"description": "Optional role assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
@@ -4747,6 +4844,13 @@
|
||||
"description": "ID of the waiting call.",
|
||||
"type": "string"
|
||||
},
|
||||
"receiver_agents": {
|
||||
"description": "Optional nicknames/roles for receivers.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/CollabAgentRef"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"receiver_thread_ids": {
|
||||
"description": "Thread ID of the receivers.",
|
||||
"items": {
|
||||
@@ -4782,6 +4886,13 @@
|
||||
{
|
||||
"description": "Collab interaction: waiting end.",
|
||||
"properties": {
|
||||
"agent_statuses": {
|
||||
"description": "Optional receiver metadata paired with final statuses.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/CollabAgentStatusEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"call_id": {
|
||||
"description": "ID of the waiting call.",
|
||||
"type": "string"
|
||||
@@ -4865,6 +4976,20 @@
|
||||
"description": "Identifier for the collab tool call.",
|
||||
"type": "string"
|
||||
},
|
||||
"receiver_agent_nickname": {
|
||||
"description": "Optional nickname assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_agent_role": {
|
||||
"description": "Optional role assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
@@ -4914,6 +5039,20 @@
|
||||
"description": "Identifier for the collab tool call.",
|
||||
"type": "string"
|
||||
},
|
||||
"receiver_agent_nickname": {
|
||||
"description": "Optional nickname assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_agent_role": {
|
||||
"description": "Optional role assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
@@ -4954,6 +5093,20 @@
|
||||
"description": "Identifier for the collab tool call.",
|
||||
"type": "string"
|
||||
},
|
||||
"receiver_agent_nickname": {
|
||||
"description": "Optional nickname assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_agent_role": {
|
||||
"description": "Optional role assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
|
||||
@@ -296,6 +296,75 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"CollabAgentRef": {
|
||||
"properties": {
|
||||
"agent_nickname": {
|
||||
"description": "Optional nickname assigned to an AgentControl-spawned sub-agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"agent_role": {
|
||||
"description": "Optional role (agent_role) assigned to an AgentControl-spawned sub-agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ThreadId"
|
||||
}
|
||||
],
|
||||
"description": "Thread ID of the receiver/new agent."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"thread_id"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"CollabAgentStatusEntry": {
|
||||
"properties": {
|
||||
"agent_nickname": {
|
||||
"description": "Optional nickname assigned to an AgentControl-spawned sub-agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"agent_role": {
|
||||
"description": "Optional role (agent_role) assigned to an AgentControl-spawned sub-agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AgentStatus"
|
||||
}
|
||||
],
|
||||
"description": "Last known status of the agent."
|
||||
},
|
||||
"thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ThreadId"
|
||||
}
|
||||
],
|
||||
"description": "Thread ID of the receiver/new agent."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"status",
|
||||
"thread_id"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ContentItem": {
|
||||
"oneOf": [
|
||||
{
|
||||
@@ -2548,6 +2617,20 @@
|
||||
"description": "Identifier for the collab tool call.",
|
||||
"type": "string"
|
||||
},
|
||||
"new_agent_nickname": {
|
||||
"description": "Optional nickname assigned to the new agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"new_agent_role": {
|
||||
"description": "Optional role assigned to the new agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"new_thread_id": {
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -2653,6 +2736,20 @@
|
||||
"description": "Prompt sent from the sender to the receiver. Can be empty to prevent CoT leaking at the beginning.",
|
||||
"type": "string"
|
||||
},
|
||||
"receiver_agent_nickname": {
|
||||
"description": "Optional nickname assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_agent_role": {
|
||||
"description": "Optional role assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
@@ -2703,6 +2800,13 @@
|
||||
"description": "ID of the waiting call.",
|
||||
"type": "string"
|
||||
},
|
||||
"receiver_agents": {
|
||||
"description": "Optional nicknames/roles for receivers.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/CollabAgentRef"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"receiver_thread_ids": {
|
||||
"description": "Thread ID of the receivers.",
|
||||
"items": {
|
||||
@@ -2738,6 +2842,13 @@
|
||||
{
|
||||
"description": "Collab interaction: waiting end.",
|
||||
"properties": {
|
||||
"agent_statuses": {
|
||||
"description": "Optional receiver metadata paired with final statuses.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/CollabAgentStatusEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"call_id": {
|
||||
"description": "ID of the waiting call.",
|
||||
"type": "string"
|
||||
@@ -2821,6 +2932,20 @@
|
||||
"description": "Identifier for the collab tool call.",
|
||||
"type": "string"
|
||||
},
|
||||
"receiver_agent_nickname": {
|
||||
"description": "Optional nickname assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_agent_role": {
|
||||
"description": "Optional role assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
@@ -2870,6 +2995,20 @@
|
||||
"description": "Identifier for the collab tool call.",
|
||||
"type": "string"
|
||||
},
|
||||
"receiver_agent_nickname": {
|
||||
"description": "Optional nickname assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_agent_role": {
|
||||
"description": "Optional role assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
@@ -2910,6 +3049,20 @@
|
||||
"description": "Identifier for the collab tool call.",
|
||||
"type": "string"
|
||||
},
|
||||
"receiver_agent_nickname": {
|
||||
"description": "Optional nickname assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_agent_role": {
|
||||
"description": "Optional role assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
|
||||
@@ -296,6 +296,75 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"CollabAgentRef": {
|
||||
"properties": {
|
||||
"agent_nickname": {
|
||||
"description": "Optional nickname assigned to an AgentControl-spawned sub-agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"agent_role": {
|
||||
"description": "Optional role (agent_role) assigned to an AgentControl-spawned sub-agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ThreadId"
|
||||
}
|
||||
],
|
||||
"description": "Thread ID of the receiver/new agent."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"thread_id"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"CollabAgentStatusEntry": {
|
||||
"properties": {
|
||||
"agent_nickname": {
|
||||
"description": "Optional nickname assigned to an AgentControl-spawned sub-agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"agent_role": {
|
||||
"description": "Optional role (agent_role) assigned to an AgentControl-spawned sub-agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AgentStatus"
|
||||
}
|
||||
],
|
||||
"description": "Last known status of the agent."
|
||||
},
|
||||
"thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ThreadId"
|
||||
}
|
||||
],
|
||||
"description": "Thread ID of the receiver/new agent."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"status",
|
||||
"thread_id"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ContentItem": {
|
||||
"oneOf": [
|
||||
{
|
||||
@@ -2548,6 +2617,20 @@
|
||||
"description": "Identifier for the collab tool call.",
|
||||
"type": "string"
|
||||
},
|
||||
"new_agent_nickname": {
|
||||
"description": "Optional nickname assigned to the new agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"new_agent_role": {
|
||||
"description": "Optional role assigned to the new agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"new_thread_id": {
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -2653,6 +2736,20 @@
|
||||
"description": "Prompt sent from the sender to the receiver. Can be empty to prevent CoT leaking at the beginning.",
|
||||
"type": "string"
|
||||
},
|
||||
"receiver_agent_nickname": {
|
||||
"description": "Optional nickname assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_agent_role": {
|
||||
"description": "Optional role assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
@@ -2703,6 +2800,13 @@
|
||||
"description": "ID of the waiting call.",
|
||||
"type": "string"
|
||||
},
|
||||
"receiver_agents": {
|
||||
"description": "Optional nicknames/roles for receivers.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/CollabAgentRef"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"receiver_thread_ids": {
|
||||
"description": "Thread ID of the receivers.",
|
||||
"items": {
|
||||
@@ -2738,6 +2842,13 @@
|
||||
{
|
||||
"description": "Collab interaction: waiting end.",
|
||||
"properties": {
|
||||
"agent_statuses": {
|
||||
"description": "Optional receiver metadata paired with final statuses.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/CollabAgentStatusEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"call_id": {
|
||||
"description": "ID of the waiting call.",
|
||||
"type": "string"
|
||||
@@ -2821,6 +2932,20 @@
|
||||
"description": "Identifier for the collab tool call.",
|
||||
"type": "string"
|
||||
},
|
||||
"receiver_agent_nickname": {
|
||||
"description": "Optional nickname assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_agent_role": {
|
||||
"description": "Optional role assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
@@ -2870,6 +2995,20 @@
|
||||
"description": "Identifier for the collab tool call.",
|
||||
"type": "string"
|
||||
},
|
||||
"receiver_agent_nickname": {
|
||||
"description": "Optional nickname assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_agent_role": {
|
||||
"description": "Optional role assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
@@ -2910,6 +3049,20 @@
|
||||
"description": "Identifier for the collab tool call.",
|
||||
"type": "string"
|
||||
},
|
||||
"receiver_agent_nickname": {
|
||||
"description": "Optional nickname assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_agent_role": {
|
||||
"description": "Optional role assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
|
||||
@@ -296,6 +296,75 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"CollabAgentRef": {
|
||||
"properties": {
|
||||
"agent_nickname": {
|
||||
"description": "Optional nickname assigned to an AgentControl-spawned sub-agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"agent_role": {
|
||||
"description": "Optional role (agent_role) assigned to an AgentControl-spawned sub-agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ThreadId"
|
||||
}
|
||||
],
|
||||
"description": "Thread ID of the receiver/new agent."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"thread_id"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"CollabAgentStatusEntry": {
|
||||
"properties": {
|
||||
"agent_nickname": {
|
||||
"description": "Optional nickname assigned to an AgentControl-spawned sub-agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"agent_role": {
|
||||
"description": "Optional role (agent_role) assigned to an AgentControl-spawned sub-agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"status": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AgentStatus"
|
||||
}
|
||||
],
|
||||
"description": "Last known status of the agent."
|
||||
},
|
||||
"thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ThreadId"
|
||||
}
|
||||
],
|
||||
"description": "Thread ID of the receiver/new agent."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"status",
|
||||
"thread_id"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ContentItem": {
|
||||
"oneOf": [
|
||||
{
|
||||
@@ -2548,6 +2617,20 @@
|
||||
"description": "Identifier for the collab tool call.",
|
||||
"type": "string"
|
||||
},
|
||||
"new_agent_nickname": {
|
||||
"description": "Optional nickname assigned to the new agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"new_agent_role": {
|
||||
"description": "Optional role assigned to the new agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"new_thread_id": {
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -2653,6 +2736,20 @@
|
||||
"description": "Prompt sent from the sender to the receiver. Can be empty to prevent CoT leaking at the beginning.",
|
||||
"type": "string"
|
||||
},
|
||||
"receiver_agent_nickname": {
|
||||
"description": "Optional nickname assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_agent_role": {
|
||||
"description": "Optional role assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
@@ -2703,6 +2800,13 @@
|
||||
"description": "ID of the waiting call.",
|
||||
"type": "string"
|
||||
},
|
||||
"receiver_agents": {
|
||||
"description": "Optional nicknames/roles for receivers.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/CollabAgentRef"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"receiver_thread_ids": {
|
||||
"description": "Thread ID of the receivers.",
|
||||
"items": {
|
||||
@@ -2738,6 +2842,13 @@
|
||||
{
|
||||
"description": "Collab interaction: waiting end.",
|
||||
"properties": {
|
||||
"agent_statuses": {
|
||||
"description": "Optional receiver metadata paired with final statuses.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/CollabAgentStatusEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"call_id": {
|
||||
"description": "ID of the waiting call.",
|
||||
"type": "string"
|
||||
@@ -2821,6 +2932,20 @@
|
||||
"description": "Identifier for the collab tool call.",
|
||||
"type": "string"
|
||||
},
|
||||
"receiver_agent_nickname": {
|
||||
"description": "Optional nickname assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_agent_role": {
|
||||
"description": "Optional role assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
@@ -2870,6 +2995,20 @@
|
||||
"description": "Identifier for the collab tool call.",
|
||||
"type": "string"
|
||||
},
|
||||
"receiver_agent_nickname": {
|
||||
"description": "Optional nickname assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_agent_role": {
|
||||
"description": "Optional role assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
@@ -2910,6 +3049,20 @@
|
||||
"description": "Identifier for the collab tool call.",
|
||||
"type": "string"
|
||||
},
|
||||
"receiver_agent_nickname": {
|
||||
"description": "Optional nickname assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_agent_role": {
|
||||
"description": "Optional role assigned to the receiver agent.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"receiver_thread_id": {
|
||||
"allOf": [
|
||||
{
|
||||
|
||||
@@ -17,6 +17,14 @@ sender_thread_id: ThreadId,
|
||||
* Thread ID of the receiver.
|
||||
*/
|
||||
receiver_thread_id: ThreadId,
|
||||
/**
|
||||
* Optional nickname assigned to the receiver agent.
|
||||
*/
|
||||
receiver_agent_nickname?: string | null,
|
||||
/**
|
||||
* Optional role assigned to the receiver agent.
|
||||
*/
|
||||
receiver_agent_role?: string | null,
|
||||
/**
|
||||
* Prompt sent from the sender to the receiver. Can be empty to prevent CoT
|
||||
* leaking at the beginning.
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
// 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 { ThreadId } from "./ThreadId";
|
||||
|
||||
export type CollabAgentRef = {
|
||||
/**
|
||||
* Thread ID of the receiver/new agent.
|
||||
*/
|
||||
thread_id: ThreadId,
|
||||
/**
|
||||
* Optional nickname assigned to an AgentControl-spawned sub-agent.
|
||||
*/
|
||||
agent_nickname?: string | null,
|
||||
/**
|
||||
* Optional role (agent_role) assigned to an AgentControl-spawned sub-agent.
|
||||
*/
|
||||
agent_role?: string | null, };
|
||||
@@ -17,6 +17,14 @@ sender_thread_id: ThreadId,
|
||||
* Thread ID of the newly spawned agent, if it was created.
|
||||
*/
|
||||
new_thread_id: ThreadId | null,
|
||||
/**
|
||||
* Optional nickname assigned to the new agent.
|
||||
*/
|
||||
new_agent_nickname?: string | null,
|
||||
/**
|
||||
* Optional role assigned to the new agent.
|
||||
*/
|
||||
new_agent_role?: string | null,
|
||||
/**
|
||||
* Initial prompt sent to the agent. Can be empty to prevent CoT leaking at the
|
||||
* beginning.
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
// 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 { AgentStatus } from "./AgentStatus";
|
||||
import type { ThreadId } from "./ThreadId";
|
||||
|
||||
export type CollabAgentStatusEntry = {
|
||||
/**
|
||||
* Thread ID of the receiver/new agent.
|
||||
*/
|
||||
thread_id: ThreadId,
|
||||
/**
|
||||
* Optional nickname assigned to an AgentControl-spawned sub-agent.
|
||||
*/
|
||||
agent_nickname?: string | null,
|
||||
/**
|
||||
* Optional role (agent_role) assigned to an AgentControl-spawned sub-agent.
|
||||
*/
|
||||
agent_role?: string | null,
|
||||
/**
|
||||
* Last known status of the agent.
|
||||
*/
|
||||
status: AgentStatus, };
|
||||
@@ -17,6 +17,14 @@ sender_thread_id: ThreadId,
|
||||
* Thread ID of the receiver.
|
||||
*/
|
||||
receiver_thread_id: ThreadId,
|
||||
/**
|
||||
* Optional nickname assigned to the receiver agent.
|
||||
*/
|
||||
receiver_agent_nickname?: string | null,
|
||||
/**
|
||||
* Optional role assigned to the receiver agent.
|
||||
*/
|
||||
receiver_agent_role?: string | null,
|
||||
/**
|
||||
* Last known status of the receiver agent reported to the sender agent before
|
||||
* the close.
|
||||
|
||||
@@ -15,4 +15,12 @@ sender_thread_id: ThreadId,
|
||||
/**
|
||||
* Thread ID of the receiver.
|
||||
*/
|
||||
receiver_thread_id: ThreadId, };
|
||||
receiver_thread_id: ThreadId,
|
||||
/**
|
||||
* Optional nickname assigned to the receiver agent.
|
||||
*/
|
||||
receiver_agent_nickname?: string | null,
|
||||
/**
|
||||
* Optional role assigned to the receiver agent.
|
||||
*/
|
||||
receiver_agent_role?: string | null, };
|
||||
|
||||
@@ -17,6 +17,14 @@ sender_thread_id: ThreadId,
|
||||
* Thread ID of the receiver.
|
||||
*/
|
||||
receiver_thread_id: ThreadId,
|
||||
/**
|
||||
* Optional nickname assigned to the receiver agent.
|
||||
*/
|
||||
receiver_agent_nickname?: string | null,
|
||||
/**
|
||||
* Optional role assigned to the receiver agent.
|
||||
*/
|
||||
receiver_agent_role?: string | null,
|
||||
/**
|
||||
* Last known status of the receiver agent reported to the sender agent after
|
||||
* resume.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// 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 { CollabAgentRef } from "./CollabAgentRef";
|
||||
import type { ThreadId } from "./ThreadId";
|
||||
|
||||
export type CollabWaitingBeginEvent = {
|
||||
@@ -12,6 +13,10 @@ sender_thread_id: ThreadId,
|
||||
* Thread ID of the receivers.
|
||||
*/
|
||||
receiver_thread_ids: Array<ThreadId>,
|
||||
/**
|
||||
* Optional nicknames/roles for receivers.
|
||||
*/
|
||||
receiver_agents?: Array<CollabAgentRef>,
|
||||
/**
|
||||
* ID of the waiting call.
|
||||
*/
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { AgentStatus } from "./AgentStatus";
|
||||
import type { CollabAgentStatusEntry } from "./CollabAgentStatusEntry";
|
||||
import type { ThreadId } from "./ThreadId";
|
||||
|
||||
export type CollabWaitingEndEvent = {
|
||||
@@ -13,6 +14,10 @@ sender_thread_id: ThreadId,
|
||||
* ID of the waiting call.
|
||||
*/
|
||||
call_id: string,
|
||||
/**
|
||||
* Optional receiver metadata paired with final statuses.
|
||||
*/
|
||||
agent_statuses?: Array<CollabAgentStatusEntry>,
|
||||
/**
|
||||
* Last known status of the receiver agents reported to the sender agent.
|
||||
*/
|
||||
|
||||
@@ -33,8 +33,10 @@ export type { ClientRequest } from "./ClientRequest";
|
||||
export type { CodexErrorInfo } from "./CodexErrorInfo";
|
||||
export type { CollabAgentInteractionBeginEvent } from "./CollabAgentInteractionBeginEvent";
|
||||
export type { CollabAgentInteractionEndEvent } from "./CollabAgentInteractionEndEvent";
|
||||
export type { CollabAgentRef } from "./CollabAgentRef";
|
||||
export type { CollabAgentSpawnBeginEvent } from "./CollabAgentSpawnBeginEvent";
|
||||
export type { CollabAgentSpawnEndEvent } from "./CollabAgentSpawnEndEvent";
|
||||
export type { CollabAgentStatusEntry } from "./CollabAgentStatusEntry";
|
||||
export type { CollabCloseBeginEvent } from "./CollabCloseBeginEvent";
|
||||
export type { CollabCloseEndEvent } from "./CollabCloseEndEvent";
|
||||
export type { CollabResumeBeginEvent } from "./CollabResumeBeginEvent";
|
||||
|
||||
@@ -1475,7 +1475,18 @@ mod tests {
|
||||
.file_stem()
|
||||
.and_then(|stem| stem.to_str())
|
||||
.is_some_and(|stem| {
|
||||
stem.ends_with("Params") || stem == "InitializeCapabilities"
|
||||
stem.ends_with("Params")
|
||||
|| stem == "InitializeCapabilities"
|
||||
|| matches!(
|
||||
stem,
|
||||
"CollabAgentRef"
|
||||
| "CollabAgentStatusEntry"
|
||||
| "CollabAgentSpawnEndEvent"
|
||||
| "CollabAgentInteractionEndEvent"
|
||||
| "CollabCloseEndEvent"
|
||||
| "CollabResumeBeginEvent"
|
||||
| "CollabResumeEndEvent"
|
||||
)
|
||||
});
|
||||
|
||||
let contents = fs::read_to_string(&path)?;
|
||||
|
||||
@@ -2002,6 +2002,8 @@ mod tests {
|
||||
.expect("valid sender thread id"),
|
||||
receiver_thread_id: ThreadId::try_from("00000000-0000-0000-0000-000000000002")
|
||||
.expect("valid receiver thread id"),
|
||||
receiver_agent_nickname: None,
|
||||
receiver_agent_role: None,
|
||||
status: AgentStatus::Completed(None),
|
||||
}),
|
||||
];
|
||||
|
||||
@@ -2059,6 +2059,8 @@ mod tests {
|
||||
call_id: "call-1".to_string(),
|
||||
sender_thread_id: ThreadId::new(),
|
||||
receiver_thread_id: ThreadId::new(),
|
||||
receiver_agent_nickname: None,
|
||||
receiver_agent_role: None,
|
||||
};
|
||||
|
||||
let item = collab_resume_begin_item(event.clone());
|
||||
@@ -2080,6 +2082,8 @@ mod tests {
|
||||
call_id: "call-2".to_string(),
|
||||
sender_thread_id: ThreadId::new(),
|
||||
receiver_thread_id: ThreadId::new(),
|
||||
receiver_agent_nickname: None,
|
||||
receiver_agent_role: None,
|
||||
status: codex_protocol::protocol::AgentStatus::NotFound,
|
||||
};
|
||||
|
||||
|
||||
@@ -218,6 +218,23 @@ impl AgentControl {
|
||||
thread.agent_status().await
|
||||
}
|
||||
|
||||
pub(crate) async fn get_agent_nickname_and_role(
|
||||
&self,
|
||||
agent_id: ThreadId,
|
||||
) -> Option<(Option<String>, Option<String>)> {
|
||||
let Ok(state) = self.upgrade() else {
|
||||
return None;
|
||||
};
|
||||
let Ok(thread) = state.get_thread(agent_id).await else {
|
||||
return None;
|
||||
};
|
||||
let session_source = thread.config_snapshot().await.session_source;
|
||||
Some((
|
||||
session_source.get_nickname(),
|
||||
session_source.get_agent_role(),
|
||||
))
|
||||
}
|
||||
|
||||
/// Subscribe to status updates for `agent_id`, yielding the latest value and changes.
|
||||
pub(crate) async fn subscribe_status(
|
||||
&self,
|
||||
|
||||
@@ -20,8 +20,10 @@ use codex_protocol::models::FunctionCallOutputBody;
|
||||
use codex_protocol::protocol::AskForApproval;
|
||||
use codex_protocol::protocol::CollabAgentInteractionBeginEvent;
|
||||
use codex_protocol::protocol::CollabAgentInteractionEndEvent;
|
||||
use codex_protocol::protocol::CollabAgentRef;
|
||||
use codex_protocol::protocol::CollabAgentSpawnBeginEvent;
|
||||
use codex_protocol::protocol::CollabAgentSpawnEndEvent;
|
||||
use codex_protocol::protocol::CollabAgentStatusEntry;
|
||||
use codex_protocol::protocol::CollabCloseBeginEvent;
|
||||
use codex_protocol::protocol::CollabCloseEndEvent;
|
||||
use codex_protocol::protocol::CollabResumeBeginEvent;
|
||||
@@ -33,6 +35,7 @@ use codex_protocol::protocol::SubAgentSource;
|
||||
use codex_protocol::user_input::UserInput;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub struct MultiAgentHandler;
|
||||
|
||||
@@ -171,6 +174,15 @@ mod spawn {
|
||||
),
|
||||
Err(_) => (None, AgentStatus::NotFound),
|
||||
};
|
||||
let (new_agent_nickname, new_agent_role) = match new_thread_id {
|
||||
Some(thread_id) => session
|
||||
.services
|
||||
.agent_control
|
||||
.get_agent_nickname_and_role(thread_id)
|
||||
.await
|
||||
.unwrap_or((None, None)),
|
||||
None => (None, None),
|
||||
};
|
||||
session
|
||||
.send_event(
|
||||
&turn,
|
||||
@@ -178,6 +190,8 @@ mod spawn {
|
||||
call_id,
|
||||
sender_thread_id: session.conversation_id,
|
||||
new_thread_id,
|
||||
new_agent_nickname,
|
||||
new_agent_role,
|
||||
prompt,
|
||||
status,
|
||||
}
|
||||
@@ -228,6 +242,12 @@ mod send_input {
|
||||
let receiver_thread_id = agent_id(&args.id)?;
|
||||
let input_items = parse_collab_input(args.message, args.items)?;
|
||||
let prompt = input_preview(&input_items);
|
||||
let (receiver_agent_nickname, receiver_agent_role) = session
|
||||
.services
|
||||
.agent_control
|
||||
.get_agent_nickname_and_role(receiver_thread_id)
|
||||
.await
|
||||
.unwrap_or((None, None));
|
||||
if args.interrupt {
|
||||
session
|
||||
.services
|
||||
@@ -266,6 +286,8 @@ mod send_input {
|
||||
call_id,
|
||||
sender_thread_id: session.conversation_id,
|
||||
receiver_thread_id,
|
||||
receiver_agent_nickname,
|
||||
receiver_agent_role,
|
||||
prompt,
|
||||
status,
|
||||
}
|
||||
@@ -308,6 +330,12 @@ mod resume_agent {
|
||||
) -> Result<ToolOutput, FunctionCallError> {
|
||||
let args: ResumeAgentArgs = parse_arguments(&arguments)?;
|
||||
let receiver_thread_id = agent_id(&args.id)?;
|
||||
let (receiver_agent_nickname, receiver_agent_role) = session
|
||||
.services
|
||||
.agent_control
|
||||
.get_agent_nickname_and_role(receiver_thread_id)
|
||||
.await
|
||||
.unwrap_or((None, None));
|
||||
let child_depth = next_thread_spawn_depth(&turn.session_source);
|
||||
if exceeds_thread_spawn_depth_limit(child_depth, turn.config.agent_max_depth) {
|
||||
return Err(FunctionCallError::RespondToModel(
|
||||
@@ -322,6 +350,8 @@ mod resume_agent {
|
||||
call_id: call_id.clone(),
|
||||
sender_thread_id: session.conversation_id,
|
||||
receiver_thread_id,
|
||||
receiver_agent_nickname: receiver_agent_nickname.clone(),
|
||||
receiver_agent_role: receiver_agent_role.clone(),
|
||||
}
|
||||
.into(),
|
||||
)
|
||||
@@ -352,6 +382,12 @@ mod resume_agent {
|
||||
None
|
||||
};
|
||||
|
||||
let (receiver_agent_nickname, receiver_agent_role) = session
|
||||
.services
|
||||
.agent_control
|
||||
.get_agent_nickname_and_role(receiver_thread_id)
|
||||
.await
|
||||
.unwrap_or((receiver_agent_nickname, receiver_agent_role));
|
||||
session
|
||||
.send_event(
|
||||
&turn,
|
||||
@@ -359,6 +395,8 @@ mod resume_agent {
|
||||
call_id,
|
||||
sender_thread_id: session.conversation_id,
|
||||
receiver_thread_id,
|
||||
receiver_agent_nickname,
|
||||
receiver_agent_role,
|
||||
status: status.clone(),
|
||||
}
|
||||
.into(),
|
||||
@@ -448,6 +486,20 @@ pub(crate) mod wait {
|
||||
.iter()
|
||||
.map(|id| agent_id(id))
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
let mut receiver_agents = Vec::with_capacity(receiver_thread_ids.len());
|
||||
for receiver_thread_id in &receiver_thread_ids {
|
||||
let (agent_nickname, agent_role) = session
|
||||
.services
|
||||
.agent_control
|
||||
.get_agent_nickname_and_role(*receiver_thread_id)
|
||||
.await
|
||||
.unwrap_or((None, None));
|
||||
receiver_agents.push(CollabAgentRef {
|
||||
thread_id: *receiver_thread_id,
|
||||
agent_nickname,
|
||||
agent_role,
|
||||
});
|
||||
}
|
||||
|
||||
// Validate timeout.
|
||||
// Very short timeouts encourage busy-polling loops in the orchestrator prompt and can
|
||||
@@ -468,6 +520,7 @@ pub(crate) mod wait {
|
||||
CollabWaitingBeginEvent {
|
||||
sender_thread_id: session.conversation_id,
|
||||
receiver_thread_ids: receiver_thread_ids.clone(),
|
||||
receiver_agents: receiver_agents.clone(),
|
||||
call_id: call_id.clone(),
|
||||
}
|
||||
.into(),
|
||||
@@ -497,6 +550,10 @@ pub(crate) mod wait {
|
||||
CollabWaitingEndEvent {
|
||||
sender_thread_id: session.conversation_id,
|
||||
call_id: call_id.clone(),
|
||||
agent_statuses: build_wait_agent_statuses(
|
||||
&statuses,
|
||||
&receiver_agents,
|
||||
),
|
||||
statuses,
|
||||
}
|
||||
.into(),
|
||||
@@ -543,6 +600,7 @@ pub(crate) mod wait {
|
||||
|
||||
// Convert payload.
|
||||
let statuses_map = statuses.clone().into_iter().collect::<HashMap<_, _>>();
|
||||
let agent_statuses = build_wait_agent_statuses(&statuses_map, &receiver_agents);
|
||||
let result = WaitResult {
|
||||
status: statuses_map.clone(),
|
||||
timed_out: statuses.is_empty(),
|
||||
@@ -555,6 +613,7 @@ pub(crate) mod wait {
|
||||
CollabWaitingEndEvent {
|
||||
sender_thread_id: session.conversation_id,
|
||||
call_id,
|
||||
agent_statuses,
|
||||
statuses: statuses_map,
|
||||
}
|
||||
.into(),
|
||||
@@ -611,6 +670,12 @@ pub mod close_agent {
|
||||
) -> Result<ToolOutput, FunctionCallError> {
|
||||
let args: CloseAgentArgs = parse_arguments(&arguments)?;
|
||||
let agent_id = agent_id(&args.id)?;
|
||||
let (receiver_agent_nickname, receiver_agent_role) = session
|
||||
.services
|
||||
.agent_control
|
||||
.get_agent_nickname_and_role(agent_id)
|
||||
.await
|
||||
.unwrap_or((None, None));
|
||||
session
|
||||
.send_event(
|
||||
&turn,
|
||||
@@ -638,6 +703,8 @@ pub mod close_agent {
|
||||
call_id: call_id.clone(),
|
||||
sender_thread_id: session.conversation_id,
|
||||
receiver_thread_id: agent_id,
|
||||
receiver_agent_nickname: receiver_agent_nickname.clone(),
|
||||
receiver_agent_role: receiver_agent_role.clone(),
|
||||
status,
|
||||
}
|
||||
.into(),
|
||||
@@ -664,6 +731,8 @@ pub mod close_agent {
|
||||
call_id,
|
||||
sender_thread_id: session.conversation_id,
|
||||
receiver_thread_id: agent_id,
|
||||
receiver_agent_nickname,
|
||||
receiver_agent_role,
|
||||
status: status.clone(),
|
||||
}
|
||||
.into(),
|
||||
@@ -687,6 +756,43 @@ fn agent_id(id: &str) -> Result<ThreadId, FunctionCallError> {
|
||||
.map_err(|e| FunctionCallError::RespondToModel(format!("invalid agent id {id}: {e:?}")))
|
||||
}
|
||||
|
||||
fn build_wait_agent_statuses(
|
||||
statuses: &HashMap<ThreadId, AgentStatus>,
|
||||
receiver_agents: &[CollabAgentRef],
|
||||
) -> Vec<CollabAgentStatusEntry> {
|
||||
if statuses.is_empty() {
|
||||
return Vec::new();
|
||||
}
|
||||
|
||||
let mut entries = Vec::with_capacity(statuses.len());
|
||||
let mut seen = HashMap::with_capacity(receiver_agents.len());
|
||||
for receiver_agent in receiver_agents {
|
||||
seen.insert(receiver_agent.thread_id, ());
|
||||
if let Some(status) = statuses.get(&receiver_agent.thread_id) {
|
||||
entries.push(CollabAgentStatusEntry {
|
||||
thread_id: receiver_agent.thread_id,
|
||||
agent_nickname: receiver_agent.agent_nickname.clone(),
|
||||
agent_role: receiver_agent.agent_role.clone(),
|
||||
status: status.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let mut extras = statuses
|
||||
.iter()
|
||||
.filter(|(thread_id, _)| !seen.contains_key(thread_id))
|
||||
.map(|(thread_id, status)| CollabAgentStatusEntry {
|
||||
thread_id: *thread_id,
|
||||
agent_nickname: None,
|
||||
agent_role: None,
|
||||
status: status.clone(),
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
extras.sort_by(|left, right| left.thread_id.to_string().cmp(&right.thread_id.to_string()));
|
||||
entries.extend(extras);
|
||||
entries
|
||||
}
|
||||
|
||||
fn collab_spawn_error(err: CodexErr) -> FunctionCallError {
|
||||
match err {
|
||||
CodexErr::UnsupportedOperation(_) => {
|
||||
|
||||
@@ -632,6 +632,7 @@ impl EventProcessor for EventProcessorWithHumanOutput {
|
||||
new_thread_id,
|
||||
prompt,
|
||||
status,
|
||||
..
|
||||
}) => {
|
||||
let success = new_thread_id.is_some() && !is_collab_status_failure(&status);
|
||||
let title_style = if success { self.green } else { self.red };
|
||||
@@ -669,6 +670,7 @@ impl EventProcessor for EventProcessorWithHumanOutput {
|
||||
receiver_thread_id,
|
||||
prompt,
|
||||
status,
|
||||
..
|
||||
}) => {
|
||||
let success = !is_collab_status_failure(&status);
|
||||
let title_style = if success { self.green } else { self.red };
|
||||
@@ -687,6 +689,7 @@ impl EventProcessor for EventProcessorWithHumanOutput {
|
||||
sender_thread_id: _,
|
||||
receiver_thread_ids,
|
||||
call_id,
|
||||
..
|
||||
}) => {
|
||||
ts_msg!(
|
||||
self,
|
||||
@@ -703,6 +706,7 @@ impl EventProcessor for EventProcessorWithHumanOutput {
|
||||
sender_thread_id: _,
|
||||
call_id,
|
||||
statuses,
|
||||
..
|
||||
}) => {
|
||||
if statuses.is_empty() {
|
||||
ts_msg!(
|
||||
@@ -755,6 +759,7 @@ impl EventProcessor for EventProcessorWithHumanOutput {
|
||||
sender_thread_id: _,
|
||||
receiver_thread_id,
|
||||
status,
|
||||
..
|
||||
}) => {
|
||||
let success = !is_collab_status_failure(&status);
|
||||
let title_style = if success { self.green } else { self.red };
|
||||
|
||||
@@ -572,6 +572,8 @@ fn collab_spawn_begin_and_end_emit_item_events() {
|
||||
call_id: "call-10".to_string(),
|
||||
sender_thread_id,
|
||||
new_thread_id: Some(new_thread_id),
|
||||
new_agent_nickname: None,
|
||||
new_agent_role: None,
|
||||
prompt: prompt.clone(),
|
||||
status: AgentStatus::Running,
|
||||
}),
|
||||
@@ -623,6 +625,7 @@ fn collab_wait_end_without_begin_synthesizes_failed_item() {
|
||||
EventMsg::CollabWaitingEnd(CollabWaitingEndEvent {
|
||||
sender_thread_id,
|
||||
call_id: "call-11".to_string(),
|
||||
agent_statuses: Vec::new(),
|
||||
statuses: statuses.clone(),
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -2747,6 +2747,32 @@ pub struct CollabAgentSpawnBeginEvent {
|
||||
pub prompt: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, JsonSchema, TS)]
|
||||
pub struct CollabAgentRef {
|
||||
/// Thread ID of the receiver/new agent.
|
||||
pub thread_id: ThreadId,
|
||||
/// Optional nickname assigned to an AgentControl-spawned sub-agent.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub agent_nickname: Option<String>,
|
||||
/// Optional role (agent_role) assigned to an AgentControl-spawned sub-agent.
|
||||
#[serde(default, alias = "agent_type", skip_serializing_if = "Option::is_none")]
|
||||
pub agent_role: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, JsonSchema, TS)]
|
||||
pub struct CollabAgentStatusEntry {
|
||||
/// Thread ID of the receiver/new agent.
|
||||
pub thread_id: ThreadId,
|
||||
/// Optional nickname assigned to an AgentControl-spawned sub-agent.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub agent_nickname: Option<String>,
|
||||
/// Optional role (agent_role) assigned to an AgentControl-spawned sub-agent.
|
||||
#[serde(default, alias = "agent_type", skip_serializing_if = "Option::is_none")]
|
||||
pub agent_role: Option<String>,
|
||||
/// Last known status of the agent.
|
||||
pub status: AgentStatus,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, JsonSchema, TS)]
|
||||
pub struct CollabAgentSpawnEndEvent {
|
||||
/// Identifier for the collab tool call.
|
||||
@@ -2755,6 +2781,12 @@ pub struct CollabAgentSpawnEndEvent {
|
||||
pub sender_thread_id: ThreadId,
|
||||
/// Thread ID of the newly spawned agent, if it was created.
|
||||
pub new_thread_id: Option<ThreadId>,
|
||||
/// Optional nickname assigned to the new agent.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub new_agent_nickname: Option<String>,
|
||||
/// Optional role assigned to the new agent.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub new_agent_role: Option<String>,
|
||||
/// Initial prompt sent to the agent. Can be empty to prevent CoT leaking at the
|
||||
/// beginning.
|
||||
pub prompt: String,
|
||||
@@ -2783,6 +2815,12 @@ pub struct CollabAgentInteractionEndEvent {
|
||||
pub sender_thread_id: ThreadId,
|
||||
/// Thread ID of the receiver.
|
||||
pub receiver_thread_id: ThreadId,
|
||||
/// Optional nickname assigned to the receiver agent.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub receiver_agent_nickname: Option<String>,
|
||||
/// Optional role assigned to the receiver agent.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub receiver_agent_role: Option<String>,
|
||||
/// Prompt sent from the sender to the receiver. Can be empty to prevent CoT
|
||||
/// leaking at the beginning.
|
||||
pub prompt: String,
|
||||
@@ -2796,6 +2834,9 @@ pub struct CollabWaitingBeginEvent {
|
||||
pub sender_thread_id: ThreadId,
|
||||
/// Thread ID of the receivers.
|
||||
pub receiver_thread_ids: Vec<ThreadId>,
|
||||
/// Optional nicknames/roles for receivers.
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub receiver_agents: Vec<CollabAgentRef>,
|
||||
/// ID of the waiting call.
|
||||
pub call_id: String,
|
||||
}
|
||||
@@ -2806,6 +2847,9 @@ pub struct CollabWaitingEndEvent {
|
||||
pub sender_thread_id: ThreadId,
|
||||
/// ID of the waiting call.
|
||||
pub call_id: String,
|
||||
/// Optional receiver metadata paired with final statuses.
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub agent_statuses: Vec<CollabAgentStatusEntry>,
|
||||
/// Last known status of the receiver agents reported to the sender agent.
|
||||
pub statuses: HashMap<ThreadId, AgentStatus>,
|
||||
}
|
||||
@@ -2828,6 +2872,12 @@ pub struct CollabCloseEndEvent {
|
||||
pub sender_thread_id: ThreadId,
|
||||
/// Thread ID of the receiver.
|
||||
pub receiver_thread_id: ThreadId,
|
||||
/// Optional nickname assigned to the receiver agent.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub receiver_agent_nickname: Option<String>,
|
||||
/// Optional role assigned to the receiver agent.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub receiver_agent_role: Option<String>,
|
||||
/// Last known status of the receiver agent reported to the sender agent before
|
||||
/// the close.
|
||||
pub status: AgentStatus,
|
||||
@@ -2841,6 +2891,12 @@ pub struct CollabResumeBeginEvent {
|
||||
pub sender_thread_id: ThreadId,
|
||||
/// Thread ID of the receiver.
|
||||
pub receiver_thread_id: ThreadId,
|
||||
/// Optional nickname assigned to the receiver agent.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub receiver_agent_nickname: Option<String>,
|
||||
/// Optional role assigned to the receiver agent.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub receiver_agent_role: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, JsonSchema, TS)]
|
||||
@@ -2851,6 +2907,12 @@ pub struct CollabResumeEndEvent {
|
||||
pub sender_thread_id: ThreadId,
|
||||
/// Thread ID of the receiver.
|
||||
pub receiver_thread_id: ThreadId,
|
||||
/// Optional nickname assigned to the receiver agent.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub receiver_agent_nickname: Option<String>,
|
||||
/// Optional role assigned to the receiver agent.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub receiver_agent_role: Option<String>,
|
||||
/// Last known status of the receiver agent reported to the sender agent after
|
||||
/// resume.
|
||||
pub status: AgentStatus,
|
||||
|
||||
+411
-174
@@ -3,7 +3,9 @@ use crate::render::line_utils::prefix_lines;
|
||||
use crate::text_formatting::truncate_text;
|
||||
use codex_core::protocol::AgentStatus;
|
||||
use codex_core::protocol::CollabAgentInteractionEndEvent;
|
||||
use codex_core::protocol::CollabAgentRef;
|
||||
use codex_core::protocol::CollabAgentSpawnEndEvent;
|
||||
use codex_core::protocol::CollabAgentStatusEntry;
|
||||
use codex_core::protocol::CollabCloseEndEvent;
|
||||
use codex_core::protocol::CollabResumeBeginEvent;
|
||||
use codex_core::protocol::CollabResumeEndEvent;
|
||||
@@ -14,282 +16,517 @@ use ratatui::style::Stylize;
|
||||
use ratatui::text::Line;
|
||||
use ratatui::text::Span;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::HashSet;
|
||||
|
||||
const COLLAB_PROMPT_PREVIEW_GRAPHEMES: usize = 160;
|
||||
const COLLAB_AGENT_ERROR_PREVIEW_GRAPHEMES: usize = 160;
|
||||
const COLLAB_AGENT_RESPONSE_PREVIEW_GRAPHEMES: usize = 240;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct AgentLabel<'a> {
|
||||
thread_id: Option<ThreadId>,
|
||||
nickname: Option<&'a str>,
|
||||
role: Option<&'a str>,
|
||||
}
|
||||
|
||||
pub(crate) fn spawn_end(ev: CollabAgentSpawnEndEvent) -> PlainHistoryCell {
|
||||
let CollabAgentSpawnEndEvent {
|
||||
call_id,
|
||||
call_id: _,
|
||||
sender_thread_id: _,
|
||||
new_thread_id,
|
||||
new_agent_nickname,
|
||||
new_agent_role,
|
||||
prompt,
|
||||
status,
|
||||
status: _,
|
||||
} = ev;
|
||||
let new_agent = new_thread_id
|
||||
.map(|id| Span::from(id.to_string()))
|
||||
.unwrap_or_else(|| Span::from("not created").dim());
|
||||
let mut details = vec![
|
||||
detail_line("call", call_id),
|
||||
detail_line("agent", new_agent),
|
||||
status_line(&status),
|
||||
];
|
||||
|
||||
let title = match new_thread_id {
|
||||
Some(thread_id) => title_with_agent(
|
||||
"Spawned",
|
||||
AgentLabel {
|
||||
thread_id: Some(thread_id),
|
||||
nickname: new_agent_nickname.as_deref(),
|
||||
role: new_agent_role.as_deref(),
|
||||
},
|
||||
),
|
||||
None => title_text("Agent spawn failed"),
|
||||
};
|
||||
|
||||
let mut details = Vec::new();
|
||||
if let Some(line) = prompt_line(&prompt) {
|
||||
details.push(line);
|
||||
}
|
||||
collab_event("Agent spawned", details)
|
||||
collab_event(title, details)
|
||||
}
|
||||
|
||||
pub(crate) fn interaction_end(ev: CollabAgentInteractionEndEvent) -> PlainHistoryCell {
|
||||
let CollabAgentInteractionEndEvent {
|
||||
call_id,
|
||||
call_id: _,
|
||||
sender_thread_id: _,
|
||||
receiver_thread_id,
|
||||
receiver_agent_nickname,
|
||||
receiver_agent_role,
|
||||
prompt,
|
||||
status,
|
||||
status: _,
|
||||
} = ev;
|
||||
let mut details = vec![
|
||||
detail_line("call", call_id),
|
||||
detail_line("receiver", receiver_thread_id.to_string()),
|
||||
status_line(&status),
|
||||
];
|
||||
|
||||
let title = title_with_agent(
|
||||
"Sent input to",
|
||||
AgentLabel {
|
||||
thread_id: Some(receiver_thread_id),
|
||||
nickname: receiver_agent_nickname.as_deref(),
|
||||
role: receiver_agent_role.as_deref(),
|
||||
},
|
||||
);
|
||||
|
||||
let mut details = Vec::new();
|
||||
if let Some(line) = prompt_line(&prompt) {
|
||||
details.push(line);
|
||||
}
|
||||
collab_event("Input sent", details)
|
||||
collab_event(title, details)
|
||||
}
|
||||
|
||||
pub(crate) fn waiting_begin(ev: CollabWaitingBeginEvent) -> PlainHistoryCell {
|
||||
let CollabWaitingBeginEvent {
|
||||
call_id,
|
||||
sender_thread_id: _,
|
||||
receiver_thread_ids,
|
||||
receiver_agents,
|
||||
call_id: _,
|
||||
} = ev;
|
||||
let details = vec![
|
||||
detail_line("call", call_id),
|
||||
detail_line("receivers", format_thread_ids(&receiver_thread_ids)),
|
||||
];
|
||||
collab_event("Waiting for agents", details)
|
||||
let receiver_agents = merge_wait_receivers(&receiver_thread_ids, receiver_agents);
|
||||
|
||||
let title = match receiver_agents.as_slice() {
|
||||
[receiver] => title_with_agent("Waiting for", agent_label_from_ref(receiver)),
|
||||
[] => title_text("Waiting for agents"),
|
||||
_ => title_text(format!("Waiting for {} agents", receiver_agents.len())),
|
||||
};
|
||||
|
||||
let details = if receiver_agents.len() > 1 {
|
||||
receiver_agents
|
||||
.iter()
|
||||
.map(|receiver| agent_label_line(agent_label_from_ref(receiver)))
|
||||
.collect()
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
collab_event(title, details)
|
||||
}
|
||||
|
||||
pub(crate) fn waiting_end(ev: CollabWaitingEndEvent) -> PlainHistoryCell {
|
||||
let CollabWaitingEndEvent {
|
||||
call_id,
|
||||
call_id: _,
|
||||
sender_thread_id: _,
|
||||
agent_statuses,
|
||||
statuses,
|
||||
} = ev;
|
||||
let mut details = vec![detail_line("call", call_id)];
|
||||
details.extend(wait_complete_lines(&statuses));
|
||||
collab_event("Wait complete", details)
|
||||
let details = wait_complete_lines(&statuses, &agent_statuses);
|
||||
collab_event(title_text("Finished waiting"), details)
|
||||
}
|
||||
|
||||
pub(crate) fn close_end(ev: CollabCloseEndEvent) -> PlainHistoryCell {
|
||||
let CollabCloseEndEvent {
|
||||
call_id,
|
||||
call_id: _,
|
||||
sender_thread_id: _,
|
||||
receiver_thread_id,
|
||||
status,
|
||||
receiver_agent_nickname,
|
||||
receiver_agent_role,
|
||||
status: _,
|
||||
} = ev;
|
||||
let details = vec![
|
||||
detail_line("call", call_id),
|
||||
detail_line("receiver", receiver_thread_id.to_string()),
|
||||
status_line(&status),
|
||||
];
|
||||
collab_event("Agent closed", details)
|
||||
|
||||
collab_event(
|
||||
title_with_agent(
|
||||
"Closed",
|
||||
AgentLabel {
|
||||
thread_id: Some(receiver_thread_id),
|
||||
nickname: receiver_agent_nickname.as_deref(),
|
||||
role: receiver_agent_role.as_deref(),
|
||||
},
|
||||
),
|
||||
Vec::new(),
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn resume_begin(ev: CollabResumeBeginEvent) -> PlainHistoryCell {
|
||||
let CollabResumeBeginEvent {
|
||||
call_id,
|
||||
call_id: _,
|
||||
sender_thread_id: _,
|
||||
receiver_thread_id,
|
||||
receiver_agent_nickname,
|
||||
receiver_agent_role,
|
||||
} = ev;
|
||||
let details = vec![
|
||||
detail_line("call", call_id),
|
||||
detail_line("receiver", receiver_thread_id.to_string()),
|
||||
];
|
||||
collab_event("Resuming agent", details)
|
||||
|
||||
collab_event(
|
||||
title_with_agent(
|
||||
"Resuming",
|
||||
AgentLabel {
|
||||
thread_id: Some(receiver_thread_id),
|
||||
nickname: receiver_agent_nickname.as_deref(),
|
||||
role: receiver_agent_role.as_deref(),
|
||||
},
|
||||
),
|
||||
Vec::new(),
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn resume_end(ev: CollabResumeEndEvent) -> PlainHistoryCell {
|
||||
let CollabResumeEndEvent {
|
||||
call_id,
|
||||
call_id: _,
|
||||
sender_thread_id: _,
|
||||
receiver_thread_id,
|
||||
receiver_agent_nickname,
|
||||
receiver_agent_role,
|
||||
status,
|
||||
} = ev;
|
||||
let details = vec![
|
||||
detail_line("call", call_id),
|
||||
detail_line("receiver", receiver_thread_id.to_string()),
|
||||
status_line(&status),
|
||||
];
|
||||
collab_event("Agent resumed", details)
|
||||
|
||||
collab_event(
|
||||
title_with_agent(
|
||||
"Resumed",
|
||||
AgentLabel {
|
||||
thread_id: Some(receiver_thread_id),
|
||||
nickname: receiver_agent_nickname.as_deref(),
|
||||
role: receiver_agent_role.as_deref(),
|
||||
},
|
||||
),
|
||||
vec![status_summary_line(&status)],
|
||||
)
|
||||
}
|
||||
|
||||
fn collab_event(title: impl Into<String>, details: Vec<Line<'static>>) -> PlainHistoryCell {
|
||||
let title = title.into();
|
||||
let mut lines: Vec<Line<'static>> =
|
||||
vec![vec![Span::from("• ").dim(), Span::from(title).bold()].into()];
|
||||
fn collab_event(title: Line<'static>, details: Vec<Line<'static>>) -> PlainHistoryCell {
|
||||
let mut lines: Vec<Line<'static>> = vec![title];
|
||||
if !details.is_empty() {
|
||||
lines.extend(prefix_lines(details, " └ ".dim(), " ".into()));
|
||||
}
|
||||
PlainHistoryCell::new(lines)
|
||||
}
|
||||
|
||||
fn detail_line(label: &str, value: impl Into<Span<'static>>) -> Line<'static> {
|
||||
vec![Span::from(format!("{label}: ")).dim(), value.into()].into()
|
||||
fn title_text(title: impl Into<String>) -> Line<'static> {
|
||||
title_spans_line(vec![Span::from(title.into()).bold()])
|
||||
}
|
||||
|
||||
fn status_line(status: &AgentStatus) -> Line<'static> {
|
||||
detail_line("status", status_span(status))
|
||||
fn title_with_agent(prefix: &str, agent: AgentLabel<'_>) -> Line<'static> {
|
||||
let mut spans = vec![Span::from(format!("{prefix} ")).bold()];
|
||||
spans.extend(agent_label_spans(agent));
|
||||
title_spans_line(spans)
|
||||
}
|
||||
|
||||
fn status_span(status: &AgentStatus) -> Span<'static> {
|
||||
match status {
|
||||
AgentStatus::PendingInit => Span::from("pending init").dim(),
|
||||
AgentStatus::Running => Span::from("running").cyan().bold(),
|
||||
AgentStatus::Completed(_) => Span::from("completed").green(),
|
||||
AgentStatus::Errored(_) => Span::from("errored").red(),
|
||||
AgentStatus::Shutdown => Span::from("shutdown").dim(),
|
||||
AgentStatus::NotFound => Span::from("not found").red(),
|
||||
fn title_spans_line(mut spans: Vec<Span<'static>>) -> Line<'static> {
|
||||
let mut title = Vec::with_capacity(spans.len() + 1);
|
||||
title.push(Span::from("• ").dim());
|
||||
title.append(&mut spans);
|
||||
title.into()
|
||||
}
|
||||
|
||||
fn agent_label_from_ref(agent: &CollabAgentRef) -> AgentLabel<'_> {
|
||||
AgentLabel {
|
||||
thread_id: Some(agent.thread_id),
|
||||
nickname: agent.agent_nickname.as_deref(),
|
||||
role: agent.agent_role.as_deref(),
|
||||
}
|
||||
}
|
||||
|
||||
fn agent_label_line(agent: AgentLabel<'_>) -> Line<'static> {
|
||||
agent_label_spans(agent).into()
|
||||
}
|
||||
|
||||
fn agent_label_spans(agent: AgentLabel<'_>) -> Vec<Span<'static>> {
|
||||
let mut spans = Vec::new();
|
||||
let nickname = agent
|
||||
.nickname
|
||||
.map(str::trim)
|
||||
.filter(|nickname| !nickname.is_empty());
|
||||
let role = agent.role.map(str::trim).filter(|role| !role.is_empty());
|
||||
|
||||
if let Some(nickname) = nickname {
|
||||
spans.push(Span::from(nickname.to_string()).light_blue().bold());
|
||||
} else if let Some(thread_id) = agent.thread_id {
|
||||
spans.push(Span::from(thread_id.to_string()).dim());
|
||||
} else {
|
||||
spans.push(Span::from("agent").dim());
|
||||
}
|
||||
|
||||
if let Some(role) = role {
|
||||
spans.push(Span::from(" ").dim());
|
||||
spans.push(Span::from(format!("[{role}]")).dim());
|
||||
}
|
||||
|
||||
spans
|
||||
}
|
||||
|
||||
fn prompt_line(prompt: &str) -> Option<Line<'static>> {
|
||||
let trimmed = prompt.trim();
|
||||
if trimmed.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(detail_line(
|
||||
"prompt",
|
||||
Span::from(truncate_text(trimmed, COLLAB_PROMPT_PREVIEW_GRAPHEMES)).dim(),
|
||||
))
|
||||
Some(Line::from(Span::from(truncate_text(
|
||||
trimmed,
|
||||
COLLAB_PROMPT_PREVIEW_GRAPHEMES,
|
||||
))))
|
||||
}
|
||||
}
|
||||
|
||||
fn format_thread_ids(ids: &[ThreadId]) -> Span<'static> {
|
||||
if ids.is_empty() {
|
||||
return Span::from("none").dim();
|
||||
fn merge_wait_receivers(
|
||||
receiver_thread_ids: &[ThreadId],
|
||||
mut receiver_agents: Vec<CollabAgentRef>,
|
||||
) -> Vec<CollabAgentRef> {
|
||||
if receiver_agents.is_empty() {
|
||||
return receiver_thread_ids
|
||||
.iter()
|
||||
.map(|thread_id| CollabAgentRef {
|
||||
thread_id: *thread_id,
|
||||
agent_nickname: None,
|
||||
agent_role: None,
|
||||
})
|
||||
.collect();
|
||||
}
|
||||
let joined = ids
|
||||
|
||||
let mut seen = receiver_agents
|
||||
.iter()
|
||||
.map(ToString::to_string)
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ");
|
||||
Span::from(joined)
|
||||
}
|
||||
|
||||
fn wait_complete_lines(statuses: &HashMap<ThreadId, AgentStatus>) -> Vec<Line<'static>> {
|
||||
if statuses.is_empty() {
|
||||
return vec![detail_line("agents", Span::from("none").dim())];
|
||||
}
|
||||
|
||||
let mut pending_init = 0usize;
|
||||
let mut running = 0usize;
|
||||
let mut completed = 0usize;
|
||||
let mut errored = 0usize;
|
||||
let mut shutdown = 0usize;
|
||||
let mut not_found = 0usize;
|
||||
for status in statuses.values() {
|
||||
match status {
|
||||
AgentStatus::PendingInit => pending_init += 1,
|
||||
AgentStatus::Running => running += 1,
|
||||
AgentStatus::Completed(_) => completed += 1,
|
||||
AgentStatus::Errored(_) => errored += 1,
|
||||
AgentStatus::Shutdown => shutdown += 1,
|
||||
AgentStatus::NotFound => not_found += 1,
|
||||
.map(|agent| agent.thread_id)
|
||||
.collect::<HashSet<_>>();
|
||||
for thread_id in receiver_thread_ids {
|
||||
if seen.insert(*thread_id) {
|
||||
receiver_agents.push(CollabAgentRef {
|
||||
thread_id: *thread_id,
|
||||
agent_nickname: None,
|
||||
agent_role: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
receiver_agents
|
||||
}
|
||||
|
||||
let mut summary = vec![Span::from(format!("{} total", statuses.len())).dim()];
|
||||
push_status_count(
|
||||
&mut summary,
|
||||
pending_init,
|
||||
"pending init",
|
||||
ratatui::prelude::Stylize::dim,
|
||||
);
|
||||
push_status_count(&mut summary, running, "running", |span| span.cyan().bold());
|
||||
push_status_count(
|
||||
&mut summary,
|
||||
completed,
|
||||
"completed",
|
||||
ratatui::prelude::Stylize::green,
|
||||
);
|
||||
push_status_count(
|
||||
&mut summary,
|
||||
errored,
|
||||
"errored",
|
||||
ratatui::prelude::Stylize::red,
|
||||
);
|
||||
push_status_count(
|
||||
&mut summary,
|
||||
shutdown,
|
||||
"shutdown",
|
||||
ratatui::prelude::Stylize::dim,
|
||||
);
|
||||
push_status_count(
|
||||
&mut summary,
|
||||
not_found,
|
||||
"not found",
|
||||
ratatui::prelude::Stylize::red,
|
||||
);
|
||||
fn wait_complete_lines(
|
||||
statuses: &HashMap<ThreadId, AgentStatus>,
|
||||
agent_statuses: &[CollabAgentStatusEntry],
|
||||
) -> Vec<Line<'static>> {
|
||||
if statuses.is_empty() && agent_statuses.is_empty() {
|
||||
return vec![Line::from(Span::from("No agents completed yet").dim())];
|
||||
}
|
||||
|
||||
let mut entries: Vec<(String, &AgentStatus)> = statuses
|
||||
.iter()
|
||||
.map(|(thread_id, status)| (thread_id.to_string(), status))
|
||||
.collect();
|
||||
entries.sort_by(|(left, _), (right, _)| left.cmp(right));
|
||||
let entries = if agent_statuses.is_empty() {
|
||||
let mut entries = statuses
|
||||
.iter()
|
||||
.map(|(thread_id, status)| CollabAgentStatusEntry {
|
||||
thread_id: *thread_id,
|
||||
agent_nickname: None,
|
||||
agent_role: None,
|
||||
status: status.clone(),
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
entries.sort_by(|left, right| left.thread_id.to_string().cmp(&right.thread_id.to_string()));
|
||||
entries
|
||||
} else {
|
||||
let mut entries = agent_statuses.to_vec();
|
||||
let seen = entries
|
||||
.iter()
|
||||
.map(|entry| entry.thread_id)
|
||||
.collect::<HashSet<_>>();
|
||||
let mut extras = statuses
|
||||
.iter()
|
||||
.filter(|(thread_id, _)| !seen.contains(thread_id))
|
||||
.map(|(thread_id, status)| CollabAgentStatusEntry {
|
||||
thread_id: *thread_id,
|
||||
agent_nickname: None,
|
||||
agent_role: None,
|
||||
status: status.clone(),
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
extras.sort_by(|left, right| left.thread_id.to_string().cmp(&right.thread_id.to_string()));
|
||||
entries.extend(extras);
|
||||
entries
|
||||
};
|
||||
|
||||
let mut lines = Vec::with_capacity(entries.len() + 1);
|
||||
lines.push(detail_line_spans("agents", summary));
|
||||
lines.extend(entries.into_iter().map(|(thread_id, status)| {
|
||||
let mut spans = vec![
|
||||
Span::from(thread_id).dim(),
|
||||
Span::from(" ").dim(),
|
||||
status_span(status),
|
||||
];
|
||||
match status {
|
||||
AgentStatus::Completed(Some(message)) => {
|
||||
entries
|
||||
.into_iter()
|
||||
.map(|entry| {
|
||||
let CollabAgentStatusEntry {
|
||||
thread_id,
|
||||
agent_nickname,
|
||||
agent_role,
|
||||
status,
|
||||
} = entry;
|
||||
let mut spans = agent_label_spans(AgentLabel {
|
||||
thread_id: Some(thread_id),
|
||||
nickname: agent_nickname.as_deref(),
|
||||
role: agent_role.as_deref(),
|
||||
});
|
||||
spans.push(Span::from(": ").dim());
|
||||
spans.extend(status_summary_spans(&status));
|
||||
spans.into()
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn status_summary_line(status: &AgentStatus) -> Line<'static> {
|
||||
status_summary_spans(status).into()
|
||||
}
|
||||
|
||||
fn status_summary_spans(status: &AgentStatus) -> Vec<Span<'static>> {
|
||||
match status {
|
||||
AgentStatus::PendingInit => vec![Span::from("Pending init").dim()],
|
||||
AgentStatus::Running => vec![Span::from("Running").cyan().bold()],
|
||||
AgentStatus::Completed(message) => {
|
||||
let mut spans = vec![Span::from("Completed").green()];
|
||||
if let Some(message) = message.as_ref() {
|
||||
let message_preview = truncate_text(
|
||||
&message.split_whitespace().collect::<Vec<_>>().join(" "),
|
||||
COLLAB_AGENT_RESPONSE_PREVIEW_GRAPHEMES,
|
||||
);
|
||||
spans.push(Span::from(": ").dim());
|
||||
spans.push(Span::from(message_preview));
|
||||
if !message_preview.is_empty() {
|
||||
spans.push(Span::from(" - ").dim());
|
||||
spans.push(Span::from(message_preview));
|
||||
}
|
||||
}
|
||||
AgentStatus::Errored(error) => {
|
||||
let error_preview = truncate_text(
|
||||
&error.split_whitespace().collect::<Vec<_>>().join(" "),
|
||||
COLLAB_AGENT_ERROR_PREVIEW_GRAPHEMES,
|
||||
);
|
||||
spans.push(Span::from(": ").dim());
|
||||
spans
|
||||
}
|
||||
AgentStatus::Errored(error) => {
|
||||
let mut spans = vec![Span::from("Error").red()];
|
||||
let error_preview = truncate_text(
|
||||
&error.split_whitespace().collect::<Vec<_>>().join(" "),
|
||||
COLLAB_AGENT_ERROR_PREVIEW_GRAPHEMES,
|
||||
);
|
||||
if !error_preview.is_empty() {
|
||||
spans.push(Span::from(" - ").dim());
|
||||
spans.push(Span::from(error_preview).dim());
|
||||
}
|
||||
_ => {}
|
||||
spans
|
||||
}
|
||||
spans.into()
|
||||
}));
|
||||
lines
|
||||
AgentStatus::Shutdown => vec![Span::from("Shutdown").dim()],
|
||||
AgentStatus::NotFound => vec![Span::from("Not found").red()],
|
||||
}
|
||||
}
|
||||
|
||||
fn push_status_count(
|
||||
spans: &mut Vec<Span<'static>>,
|
||||
count: usize,
|
||||
label: &'static str,
|
||||
style: impl FnOnce(Span<'static>) -> Span<'static>,
|
||||
) {
|
||||
if count == 0 {
|
||||
return;
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::history_cell::HistoryCell;
|
||||
use insta::assert_snapshot;
|
||||
use pretty_assertions::assert_eq;
|
||||
use ratatui::style::Color;
|
||||
use ratatui::style::Modifier;
|
||||
|
||||
#[test]
|
||||
fn collab_events_snapshot() {
|
||||
let sender_thread_id = ThreadId::from_string("00000000-0000-0000-0000-000000000001")
|
||||
.expect("valid sender thread id");
|
||||
let robie_id = ThreadId::from_string("00000000-0000-0000-0000-000000000002")
|
||||
.expect("valid robie thread id");
|
||||
let bob_id = ThreadId::from_string("00000000-0000-0000-0000-000000000003")
|
||||
.expect("valid bob thread id");
|
||||
|
||||
let spawn = spawn_end(CollabAgentSpawnEndEvent {
|
||||
call_id: "call-spawn".to_string(),
|
||||
sender_thread_id,
|
||||
new_thread_id: Some(robie_id),
|
||||
new_agent_nickname: Some("Robie".to_string()),
|
||||
new_agent_role: Some("explorer".to_string()),
|
||||
prompt: "Compute 11! and reply with just the integer result.".to_string(),
|
||||
status: AgentStatus::PendingInit,
|
||||
});
|
||||
|
||||
let send = interaction_end(CollabAgentInteractionEndEvent {
|
||||
call_id: "call-send".to_string(),
|
||||
sender_thread_id,
|
||||
receiver_thread_id: robie_id,
|
||||
receiver_agent_nickname: Some("Robie".to_string()),
|
||||
receiver_agent_role: Some("explorer".to_string()),
|
||||
prompt: "Please continue and return the answer only.".to_string(),
|
||||
status: AgentStatus::Running,
|
||||
});
|
||||
|
||||
let waiting = waiting_begin(CollabWaitingBeginEvent {
|
||||
sender_thread_id,
|
||||
receiver_thread_ids: vec![robie_id],
|
||||
receiver_agents: vec![CollabAgentRef {
|
||||
thread_id: robie_id,
|
||||
agent_nickname: Some("Robie".to_string()),
|
||||
agent_role: Some("explorer".to_string()),
|
||||
}],
|
||||
call_id: "call-wait".to_string(),
|
||||
});
|
||||
|
||||
let mut statuses = HashMap::new();
|
||||
statuses.insert(
|
||||
robie_id,
|
||||
AgentStatus::Completed(Some("39916800".to_string())),
|
||||
);
|
||||
statuses.insert(bob_id, AgentStatus::Errored("tool timeout".to_string()));
|
||||
let finished = waiting_end(CollabWaitingEndEvent {
|
||||
sender_thread_id,
|
||||
call_id: "call-wait".to_string(),
|
||||
agent_statuses: vec![
|
||||
CollabAgentStatusEntry {
|
||||
thread_id: robie_id,
|
||||
agent_nickname: Some("Robie".to_string()),
|
||||
agent_role: Some("explorer".to_string()),
|
||||
status: AgentStatus::Completed(Some("39916800".to_string())),
|
||||
},
|
||||
CollabAgentStatusEntry {
|
||||
thread_id: bob_id,
|
||||
agent_nickname: Some("Bob".to_string()),
|
||||
agent_role: Some("worker".to_string()),
|
||||
status: AgentStatus::Errored("tool timeout".to_string()),
|
||||
},
|
||||
],
|
||||
statuses,
|
||||
});
|
||||
|
||||
let close = close_end(CollabCloseEndEvent {
|
||||
call_id: "call-close".to_string(),
|
||||
sender_thread_id,
|
||||
receiver_thread_id: robie_id,
|
||||
receiver_agent_nickname: Some("Robie".to_string()),
|
||||
receiver_agent_role: Some("explorer".to_string()),
|
||||
status: AgentStatus::Completed(Some("39916800".to_string())),
|
||||
});
|
||||
|
||||
let snapshot = [spawn, send, waiting, finished, close]
|
||||
.iter()
|
||||
.map(cell_to_text)
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n\n");
|
||||
assert_snapshot!("collab_agent_transcript", snapshot);
|
||||
}
|
||||
|
||||
spans.push(Span::from(" · ").dim());
|
||||
spans.push(style(Span::from(format!("{count} {label}"))));
|
||||
}
|
||||
#[test]
|
||||
fn title_styles_nickname_and_role() {
|
||||
let sender_thread_id = ThreadId::from_string("00000000-0000-0000-0000-000000000001")
|
||||
.expect("valid sender thread id");
|
||||
let robie_id = ThreadId::from_string("00000000-0000-0000-0000-000000000002")
|
||||
.expect("valid robie thread id");
|
||||
let cell = spawn_end(CollabAgentSpawnEndEvent {
|
||||
call_id: "call-spawn".to_string(),
|
||||
sender_thread_id,
|
||||
new_thread_id: Some(robie_id),
|
||||
new_agent_nickname: Some("Robie".to_string()),
|
||||
new_agent_role: Some("explorer".to_string()),
|
||||
prompt: String::new(),
|
||||
status: AgentStatus::PendingInit,
|
||||
});
|
||||
|
||||
fn detail_line_spans(label: &str, mut value: Vec<Span<'static>>) -> Line<'static> {
|
||||
let mut spans = Vec::with_capacity(value.len() + 1);
|
||||
spans.push(Span::from(format!("{label}: ")).dim());
|
||||
spans.append(&mut value);
|
||||
spans.into()
|
||||
let lines = cell.display_lines(200);
|
||||
let title = &lines[0];
|
||||
assert_eq!(title.spans[2].content.as_ref(), "Robie");
|
||||
assert_eq!(title.spans[2].style.fg, Some(Color::LightBlue));
|
||||
assert!(title.spans[2].style.add_modifier.contains(Modifier::BOLD));
|
||||
assert_eq!(title.spans[4].content.as_ref(), "[explorer]");
|
||||
assert!(title.spans[4].style.add_modifier.contains(Modifier::DIM));
|
||||
}
|
||||
|
||||
fn cell_to_text(cell: &PlainHistoryCell) -> String {
|
||||
cell.display_lines(200)
|
||||
.iter()
|
||||
.map(line_to_text)
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n")
|
||||
}
|
||||
|
||||
fn line_to_text(line: &Line<'static>) -> String {
|
||||
line.spans
|
||||
.iter()
|
||||
.map(|span| span.content.as_ref())
|
||||
.collect::<Vec<_>>()
|
||||
.join("")
|
||||
}
|
||||
}
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
---
|
||||
source: tui/src/multi_agents.rs
|
||||
expression: snapshot
|
||||
---
|
||||
• Spawned Robie [explorer]
|
||||
└ Compute 11! and reply with just the integer result.
|
||||
|
||||
• Sent input to Robie [explorer]
|
||||
└ Please continue and return the answer only.
|
||||
|
||||
• Waiting for Robie [explorer]
|
||||
|
||||
• Finished waiting
|
||||
└ Robie [explorer]: Completed - 39916800
|
||||
Bob [worker]: Error - tool timeout
|
||||
|
||||
• Closed Robie [explorer]
|
||||
Reference in New Issue
Block a user