use std::collections::BTreeSet;
use supercode_harness::FrontendOperationDescriptor;
use supercode_harness::FrontendOperationInvocation;
use supercode_harness::FrontendOperationKind;
use supercode_harness::FrontendRuntimeDescriptor;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ComposerCapabilities {
operations: Vec<FrontendOperationDescriptor>,
pub can_submit: bool,
pub can_steer: bool,
pub can_interrupt: bool,
pub can_respond: bool,
pub can_detach: bool,
}
impl ComposerCapabilities {
pub fn from_descriptor(descriptor: &FrontendRuntimeDescriptor) -> Self {
Self {
operations: descriptor
.operations
.iter()
.filter(|operation| {
operation.kind == FrontendOperationKind::Prompt && operation.command.is_some()
})
.cloned()
.collect(),
can_submit: descriptor.actions.submit,
can_steer: descriptor.actions.steer,
can_interrupt: descriptor.actions.interrupt,
can_respond: descriptor.actions.respond,
can_detach: descriptor.actions.detach,
}
}
pub fn operations(&self) -> &[FrontendOperationDescriptor] {
&self.operations
}
pub fn invocation_for_command(&self, input: &str) -> Option<FrontendOperationInvocation> {
let trimmed = input.trim_start();
let rest = trimmed.strip_prefix('/')?;
let (name, arguments) = rest
.split_once(char::is_whitespace)
.map_or((rest, ""), |(name, arguments)| (name, arguments.trim()));
self.operations.iter().find_map(|operation| {
if operation
.command
.as_ref()
.map(|command| command.name.as_str())
!= Some(name)
{
return None;
}
match operation.kind {
FrontendOperationKind::Prompt => Some(FrontendOperationInvocation::Prompt {
operation_id: operation.id.clone(),
arguments: arguments.to_string(),
}),
FrontendOperationKind::Model => Some(FrontendOperationInvocation::Model {
operation_id: operation.id.clone(),
model: arguments.to_string(),
}),
FrontendOperationKind::Context => Some(FrontendOperationInvocation::Context {
operation_id: operation.id.clone(),
}),
_ => None,
}
})
}
pub fn available_actions(&self) -> BTreeSet<String> {
let mut actions = self
.operations
.iter()
.map(|operation| format!("operation:{}", operation.id))
.collect::<BTreeSet<_>>();
if self.can_submit {
actions.insert("submit".into());
}
if self.can_steer {
actions.insert("steer".into());
}
if self.can_interrupt {
actions.insert("interrupt".into());
}
if self.can_respond {
actions.insert("respond".into());
}
if self.can_detach {
actions.insert("detach".into());
}
actions
}
}