worker: separate subworkers from workspace workers
This commit is contained in:
@@ -88,9 +88,9 @@ pub enum WorkerPrompt {
|
||||
WorkerOrchestrationGuidanceSection,
|
||||
/// Weak Companion Notify payload for explicit Orchestrator Ticket events.
|
||||
TicketEventCompanionNotice,
|
||||
/// LLM-facing description for the SpawnWorker tool, including discovered
|
||||
/// LLM-facing description for the SubWorkerSpawn tool, including discovered
|
||||
/// profile selectors.
|
||||
SpawnWorkerToolDescription,
|
||||
SubWorkerSpawnToolDescription,
|
||||
}
|
||||
|
||||
impl WorkerPrompt {
|
||||
@@ -107,7 +107,7 @@ impl WorkerPrompt {
|
||||
Self::ResidentMemorySummarySection => "resident_memory_summary_section",
|
||||
Self::WorkerOrchestrationGuidanceSection => "worker_orchestration_guidance_section",
|
||||
Self::TicketEventCompanionNotice => "ticket_event_companion_notice",
|
||||
Self::SpawnWorkerToolDescription => "spawn_worker_tool_description",
|
||||
Self::SubWorkerSpawnToolDescription => "sub_worker_spawn_tool_description",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ impl WorkerPrompt {
|
||||
WorkerPrompt::ResidentMemorySummarySection,
|
||||
WorkerPrompt::WorkerOrchestrationGuidanceSection,
|
||||
WorkerPrompt::TicketEventCompanionNotice,
|
||||
WorkerPrompt::SpawnWorkerToolDescription,
|
||||
WorkerPrompt::SubWorkerSpawnToolDescription,
|
||||
];
|
||||
|
||||
pub const KEYS: &'static [&'static str] = &[
|
||||
@@ -141,7 +141,7 @@ impl WorkerPrompt {
|
||||
"resident_memory_summary_section",
|
||||
"worker_orchestration_guidance_section",
|
||||
"ticket_event_companion_notice",
|
||||
"spawn_worker_tool_description",
|
||||
"sub_worker_spawn_tool_description",
|
||||
];
|
||||
}
|
||||
|
||||
@@ -384,8 +384,8 @@ impl PromptCatalog {
|
||||
)
|
||||
}
|
||||
|
||||
/// Render `WorkerPrompt::SpawnWorkerToolDescription`.
|
||||
pub fn spawn_worker_tool_description(
|
||||
/// Render `WorkerPrompt::SubWorkerSpawnToolDescription`.
|
||||
pub fn sub_worker_spawn_tool_description(
|
||||
&self,
|
||||
available_profiles: &str,
|
||||
default_profile: &str,
|
||||
@@ -396,7 +396,7 @@ impl PromptCatalog {
|
||||
m.insert("available_profiles", Value::from(available_profiles));
|
||||
m.insert("default_profile", Value::from(default_profile));
|
||||
m.insert("profile_diagnostic", Value::from(profile_diagnostic));
|
||||
self.render(WorkerPrompt::SpawnWorkerToolDescription, Value::from(m))
|
||||
self.render(WorkerPrompt::SubWorkerSpawnToolDescription, Value::from(m))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -722,8 +722,8 @@ compact_system = "PREFIX\n{% include \"$yoi/internal/compact_system\" %}"
|
||||
fn worker_orchestration_guidance_section_renders_resource_body() {
|
||||
let cat = PromptCatalog::builtins_only().unwrap();
|
||||
let rendered = cat.worker_orchestration_guidance_section().unwrap();
|
||||
assert!(rendered.contains("## Worker orchestration"));
|
||||
assert!(rendered.contains("spawned Worker notifications are background signals"));
|
||||
assert!(rendered.contains("## SubWorker orchestration"));
|
||||
assert!(rendered.contains("SubWorker notifications are background signals"));
|
||||
assert!(rendered.contains("does not need to keep a turn open"));
|
||||
assert!(rendered.contains("Do not use `sleep` or polling loops"));
|
||||
assert!(rendered.contains("worktree state, diff, and test results"));
|
||||
@@ -732,10 +732,10 @@ compact_system = "PREFIX\n{% include \"$yoi/internal/compact_system\" %}"
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn spawn_worker_tool_description_renders_profile_block() {
|
||||
fn sub_worker_spawn_tool_description_renders_profile_block() {
|
||||
let cat = PromptCatalog::builtins_only().unwrap();
|
||||
let rendered = cat
|
||||
.spawn_worker_tool_description(
|
||||
.sub_worker_spawn_tool_description(
|
||||
"- `project:coder` — Coder\n- `project:reviewer` — Reviewer",
|
||||
"project:coder",
|
||||
"",
|
||||
|
||||
@@ -206,12 +206,12 @@ struct ToolCapabilities {
|
||||
memory_query: bool,
|
||||
memory_read_document: bool,
|
||||
memory_update_document: bool,
|
||||
worker_spawn: bool,
|
||||
worker_send: bool,
|
||||
worker_read_output: bool,
|
||||
worker_stop: bool,
|
||||
worker_list: bool,
|
||||
worker_restore: bool,
|
||||
sub_worker_spawn: bool,
|
||||
sub_worker_send: bool,
|
||||
sub_worker_read_output: bool,
|
||||
sub_worker_stop: bool,
|
||||
sub_worker_list: bool,
|
||||
sub_worker_restore: bool,
|
||||
}
|
||||
|
||||
impl ToolCapabilities {
|
||||
@@ -222,12 +222,11 @@ impl ToolCapabilities {
|
||||
"MemoryQuery" => capabilities.memory_query = true,
|
||||
"MemoryReadDocument" => capabilities.memory_read_document = true,
|
||||
"MemoryUpdateDocument" => capabilities.memory_update_document = true,
|
||||
"SpawnWorker" => capabilities.worker_spawn = true,
|
||||
"SendToWorker" => capabilities.worker_send = true,
|
||||
"ReadWorkerOutput" => capabilities.worker_read_output = true,
|
||||
"StopWorker" => capabilities.worker_stop = true,
|
||||
"ListWorkers" => capabilities.worker_list = true,
|
||||
"RestoreWorker" => capabilities.worker_restore = true,
|
||||
"SubWorkerSpawn" => capabilities.sub_worker_spawn = true,
|
||||
"SubWorkerSend" => capabilities.sub_worker_send = true,
|
||||
"SubWorkerReadOutput" => capabilities.sub_worker_read_output = true,
|
||||
"SubWorkerStop" => capabilities.sub_worker_stop = true,
|
||||
"SubWorkerList" => capabilities.sub_worker_list = true,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@@ -246,13 +245,13 @@ impl ToolCapabilities {
|
||||
self.memory_update_document
|
||||
}
|
||||
|
||||
fn worker_management(self) -> bool {
|
||||
self.worker_spawn
|
||||
|| self.worker_send
|
||||
|| self.worker_read_output
|
||||
|| self.worker_stop
|
||||
|| self.worker_list
|
||||
|| self.worker_restore
|
||||
fn sub_worker_management(self) -> bool {
|
||||
self.sub_worker_spawn
|
||||
|| self.sub_worker_send
|
||||
|| self.sub_worker_read_output
|
||||
|| self.sub_worker_stop
|
||||
|| self.sub_worker_list
|
||||
|| self.sub_worker_restore
|
||||
}
|
||||
|
||||
fn to_minijinja_value(self) -> Value {
|
||||
@@ -269,7 +268,10 @@ impl ToolCapabilities {
|
||||
Value::from(self.memory_update_document),
|
||||
);
|
||||
map.insert("memory_mutation", Value::from(self.memory_mutation()));
|
||||
map.insert("worker_management", Value::from(self.worker_management()));
|
||||
map.insert(
|
||||
"sub_worker_management",
|
||||
Value::from(self.sub_worker_management()),
|
||||
);
|
||||
Value::from(map)
|
||||
}
|
||||
}
|
||||
@@ -419,7 +421,7 @@ mod tests {
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn worker_orchestration_instruction() -> FeatureInstructionDeclaration {
|
||||
fn sub_worker_orchestration_instruction() -> FeatureInstructionDeclaration {
|
||||
FeatureInstructionDeclaration::new(
|
||||
crate::feature::FeatureInstructionId::builtin("worker.orchestration"),
|
||||
"$yoi/common/worker-orchestration",
|
||||
@@ -595,13 +597,13 @@ mod tests {
|
||||
let tmpl = SystemPromptTemplate::parse("$yoi/default", loader).unwrap();
|
||||
let dir = TempDir::new().unwrap();
|
||||
let scope = build_scope(dir.path());
|
||||
let instructions = [worker_orchestration_instruction()];
|
||||
let instructions = [sub_worker_orchestration_instruction()];
|
||||
let mut ctx = ctx(dir.path(), &scope, vec!["Read".into()], None);
|
||||
ctx.feature_instructions = &instructions;
|
||||
let rendered = tmpl.render(&ctx).unwrap();
|
||||
|
||||
assert!(rendered.contains("## Worker orchestration"));
|
||||
assert!(rendered.contains("spawned Worker notifications are background signals"));
|
||||
assert!(rendered.contains("## SubWorker orchestration"));
|
||||
assert!(rendered.contains("SubWorker notifications are background signals"));
|
||||
assert!(rendered.contains("does not need to keep a turn open"));
|
||||
assert!(rendered.contains("Do not use `sleep` or polling loops"));
|
||||
assert!(rendered.contains("worktree state, diff, and test results"));
|
||||
@@ -610,7 +612,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn worker_orchestration_guidance_is_omitted_without_worker_management_tools() {
|
||||
fn worker_orchestration_guidance_is_omitted_without_sub_worker_management_tools() {
|
||||
let loader = PromptLoader::builtins_only();
|
||||
let tmpl = SystemPromptTemplate::parse("$yoi/default", loader).unwrap();
|
||||
let dir = TempDir::new().unwrap();
|
||||
|
||||
Reference in New Issue
Block a user