feat(tui-go): workflow-propose choice panel

Render a workflow.proposed frame as a single-select picker with a manual-answer
slot: ↑↓/jk to choose, enter to launch, e for custom, esc to peek away. Picking
a candidate sends StartSession (and focuses the launched session); the custom
slot continues the conversation via ChatInput. Reuses the modal helpers from the
clarification view.
This commit is contained in:
2026-06-14 13:29:34 +04:00
parent b62b6e09a1
commit b563d9841d
9 changed files with 420 additions and 0 deletions
@@ -149,6 +149,25 @@ func TestDecodeGoldenServerFrames(t *testing.T) {
}
},
},
{
name: "workflow.proposed carries candidate workflows",
json: `{"type":"workflow.proposed","sessionId":"s1","proposalId":"prop-1","prompt":"Run one?",` +
`"candidates":[{"workflowId":"research","reason":"gather + report"},{"workflowId":"role_pipeline","reason":""}],` +
`"originalRequest":"find papers","sequence":9,"sessionSequence":4}`,
wantType: TypeWorkflowProposed,
eventBear: true,
check: func(t *testing.T, m ServerMessage) {
if m.ProposalID != "prop-1" || m.Prompt != "Run one?" || m.OriginalRequest != "find papers" {
t.Fatalf("workflow.proposed fields: %+v", m)
}
if len(m.Candidates) != 2 {
t.Fatalf("workflow.proposed candidates: %+v", m.Candidates)
}
if m.Candidates[0].WorkflowID != "research" || m.Candidates[0].Reason != "gather + report" {
t.Fatalf("workflow.proposed candidate[0]: %+v", m.Candidates[0])
}
},
},
{
name: "clarification.required carries structured questions",
json: `{"type":"clarification.required","sessionId":"s1","requestId":"req-1","stageId":"analyst",` +