mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-10-07 03:00:29 +00:00
use Freeform question type for human gates with no fixed choices
When a human gate has only a freeform edge and no fixed choices, use QuestionType::Freeform instead of MultipleChoice. This sends the user directly to a text input prompt, skipping the unnecessary select menu. Also removes the Quit choice from the REPL workflow so it uses the new freeform-only path. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
54f3b456f0
commit
3f04e978c8
2 changed files with 58 additions and 1 deletions
13
fabro/workflows/repl/workflow.dot
Normal file
13
fabro/workflows/repl/workflow.dot
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
digraph REPL {
|
||||
graph [goal="Interactive REPL: execute user prompts in a loop"]
|
||||
rankdir=LR
|
||||
|
||||
start [shape=Mdiamond, label="Start"]
|
||||
|
||||
prompt [shape=hexagon, label="Enter prompt"]
|
||||
agent [label="Agent", fidelity="summary:high", prompt="Execute the user's request. Their prompt is in the context from the previous human gate."]
|
||||
|
||||
start -> prompt
|
||||
prompt -> agent [freeform=true]
|
||||
agent -> prompt
|
||||
}
|
||||
|
|
@ -138,7 +138,12 @@ impl Handler for HumanHandler {
|
|||
})
|
||||
.collect();
|
||||
|
||||
let mut question = Question::new(node.label(), QuestionType::MultipleChoice);
|
||||
let question_type = if choices.is_empty() {
|
||||
QuestionType::Freeform
|
||||
} else {
|
||||
QuestionType::MultipleChoice
|
||||
};
|
||||
let mut question = Question::new(node.label(), question_type);
|
||||
question.options = options;
|
||||
question.allow_freeform = freeform_target.is_some();
|
||||
question.stage.clone_from(&node.id);
|
||||
|
|
@ -284,6 +289,7 @@ mod tests {
|
|||
use crate::handler::start::StartHandler;
|
||||
use crate::handler::HandlerRegistry;
|
||||
use crate::interviewer::auto_approve::AutoApproveInterviewer;
|
||||
use crate::interviewer::recording::RecordingInterviewer;
|
||||
|
||||
fn make_services() -> EngineServices {
|
||||
EngineServices {
|
||||
|
|
@ -434,4 +440,42 @@ mod tests {
|
|||
Some(&serde_json::json!("custom input"))
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn freeform_only_gate_uses_freeform_question_type() {
|
||||
let inner = Box::new(crate::interviewer::callback::CallbackInterviewer::new(
|
||||
|_| Answer::text("hello"),
|
||||
));
|
||||
let recorder = Arc::new(RecordingInterviewer::new(inner));
|
||||
let handler = HumanHandler::new(recorder.clone());
|
||||
|
||||
let mut graph = Graph::new("test");
|
||||
let mut gate = Node::new("gate");
|
||||
gate.attrs.insert(
|
||||
"label".to_string(),
|
||||
AttrValue::String("Enter prompt".to_string()),
|
||||
);
|
||||
graph.nodes.insert("gate".to_string(), gate);
|
||||
graph
|
||||
.nodes
|
||||
.insert("target".to_string(), Node::new("target"));
|
||||
|
||||
let mut edge = Edge::new("gate", "target");
|
||||
edge.attrs
|
||||
.insert("freeform".to_string(), AttrValue::Boolean(true));
|
||||
graph.edges.push(edge);
|
||||
|
||||
let node = graph.nodes.get("gate").unwrap();
|
||||
let context = Context::new();
|
||||
let run_dir = Path::new("/tmp/test");
|
||||
|
||||
handler
|
||||
.execute(node, &context, &graph, run_dir, &make_services())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let recordings = recorder.recordings();
|
||||
assert_eq!(recordings.len(), 1);
|
||||
assert_eq!(recordings[0].0.question_type, QuestionType::Freeform);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue