Second commit of the Research + Loops arc. Builds on 0030 by lighting up
the container CRUD, the agent-slot attach/detach, the standby→processing
transition, and the wizard's one-shot LLM refine.
GET /api/research list workspace's topics
POST /api/research create (accepts wizard output)
GET /api/research/:id detail (topic + attached agents)
PATCH /api/research/:id update non-status fields
POST /api/research/:id/agents attach agent (idempotent)
DELETE /api/research/:id/agents/:agent detach
POST /api/research/:id/start standby → processing
POST /api/research/wizard/refine one-shot LLM refine
The refine endpoint accumulates the workspace's default LLM provider's
stream into a JSON object (`{title, description}`) with the tight system
prompt at the top of the module. Same provider routing as agent runs
(via runtime.provider()), so a workspace already using GLM/Kimi gets it
for free.
State machine's remaining transitions (processing → reviewing on last
run_completed; reviewing → publishing via approvals gate) land with the
orchestrator hookup + approvals extension. Publish approval and loops
are separate commits still to come.
Adds cm-llm as a direct cm-api dep (previously only pulled transitively
via cm-runtime) so the refine endpoint can build a ChatRequest. Uses
sqlx::query! for compile-time verification; .sqlx cache generated on
morpheus against a fresh migrated DB.
78 lines
1.6 KiB
JSON
78 lines
1.6 KiB
JSON
{
|
|
"db_name": "PostgreSQL",
|
|
"query": "SELECT id, workspace_id, title, description, outcome_kind, status,\n created_by, created_at, updated_at, published_at\n FROM research_topics\n WHERE id = $1 AND workspace_id = $2",
|
|
"describe": {
|
|
"columns": [
|
|
{
|
|
"ordinal": 0,
|
|
"name": "id",
|
|
"type_info": "Uuid"
|
|
},
|
|
{
|
|
"ordinal": 1,
|
|
"name": "workspace_id",
|
|
"type_info": "Uuid"
|
|
},
|
|
{
|
|
"ordinal": 2,
|
|
"name": "title",
|
|
"type_info": "Text"
|
|
},
|
|
{
|
|
"ordinal": 3,
|
|
"name": "description",
|
|
"type_info": "Text"
|
|
},
|
|
{
|
|
"ordinal": 4,
|
|
"name": "outcome_kind",
|
|
"type_info": "Text"
|
|
},
|
|
{
|
|
"ordinal": 5,
|
|
"name": "status",
|
|
"type_info": "Text"
|
|
},
|
|
{
|
|
"ordinal": 6,
|
|
"name": "created_by",
|
|
"type_info": "Uuid"
|
|
},
|
|
{
|
|
"ordinal": 7,
|
|
"name": "created_at",
|
|
"type_info": "Timestamptz"
|
|
},
|
|
{
|
|
"ordinal": 8,
|
|
"name": "updated_at",
|
|
"type_info": "Timestamptz"
|
|
},
|
|
{
|
|
"ordinal": 9,
|
|
"name": "published_at",
|
|
"type_info": "Timestamptz"
|
|
}
|
|
],
|
|
"parameters": {
|
|
"Left": [
|
|
"Uuid",
|
|
"Uuid"
|
|
]
|
|
},
|
|
"nullable": [
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
true
|
|
]
|
|
},
|
|
"hash": "eecbf1bc6a6ed59635ea26dffbba8ed014e58a6e0da19576b01912936317ed1a"
|
|
}
|